wiki:ioc_driver

Version 3 (modified by alain, 10 years ago) (diff)

--

GIET-VM / IOC Driver

The ioc_driver.c and ioc_driver.h files define an abstract, block oriented, mass storage peripheral driver.

This abstact driver define a generic API, supporting various physical disks or virtual disks controlers:

  • vci_block_device : single channel physical disk with DMA capacity => bdv_driver
  • vci_ahci : multi channels physical disk => hba_driver
  • sd_card : single channel physical SD card => sdc_driver
  • ramdisk : single channel memory mapped virtual disk => rdk_driver

It can exist only one block-device type in the architecture, that must be defined by one of the following configuration variables in hard_config.h file: USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK.

Any physical block device driver xxx must provide the following API:

  • _xxx_init()
  • _xxx_read()
  • _xxx_write()
  • _xxx_get_status()
  • _xxx_get_block_size()

The _ioc_read() and _ioc_write() functions are always blocking for the calling user program. These functions compute the physical address of the memory buffer before calling the proper physical device. This drivers makes the assumption that the user buffer is mapped to a contiguous physical buffer because, this is granted by the GIET-VM physical memory allocator.

These functions can be called in 3 modes:

  • In BOOT mode, these functions use the buffer virtual address as a physical address if the MMU is not activated. They make a V2P translation if the MMU is activated. This mode is used to load the map.bin file (before memory activation), or to load the various .elf files (after MMU activation).
  • In KERNEL mode, these functions make a V2P translation to compute the buffer physical address. There is no checking of user access right to the memory buffer. This mode must be used for an open system call.
  • In USER mode, these functions make a V2P translation to compute the buffer physical address. The user access right to the memory buffer are checked. This mode must be used for a read or write system call.

The memory buffer must fulfill the following conditions:

  • The buffer must be word aligned,
  • The buffer must be mapped in user space for an user access,
  • The buffer must be writable in case of (to_mem) access,
  • All physical pages occupied by the user buffer must be contiguous

Exit if these conditions are not verified.

The SEG_IOC_BASE virtual base address must be defined in hard_config.h, as it is used by the BDV, HBA and SPI drivers. If the RAMDISK is used, an extra memory segment with virtual base address SEG_RDK_BASE, used by RDK driver, must be defined in hard_config.h.

The IOMMU is not supported yet, but the method is the following: A fixed size 2 Mbytes vseg is allocated to the IOC peripheral, in the I/O virtual space, and the user buffer is dynamically remapped to one single big page in the IOMMU page table. The user buffer is unmapped by the _ioc_completed() function when the transfer is completed.

unsigned int _ioc_init( unsigned int channel )

This function cheks block size, and desactivates interrupts. Return 0 for success, non zero if error.

unsigned int _ioc_write( unsigned int channel, unsigned int mode, unsigned int lba, const void* buffer, unsigned int count )

Transfer data from a memory buffer to the disk.

  • channel : channel index (for multi-channels peripherals)
  • mode : BOOT / KERNEL / USER
  • lba : first block index on the block device
  • buffer : base address of the memory buffer (must be word aligned)
  • count : number of blocks to be transfered.

Returns 0 if success, > 0 if error.

unsigned int _ioc_read( unsigned int channel, unsigned int mode, unsigned int lba, void* buffer, unsigned int count )

Transfer data from the disk to a memory buffer.

  • channel : channel index (for multi-channels peripherals)
  • mode : BOOT / KERNEL / USER
  • lba : first block index on the block device
  • buffer : base address of the memory buffer (must be word aligned)
  • count : number of blocks to be transfered.

Returns 0 if success, > 0 if error.

unsigned int _ioc_get_status( unsigned int channel )

This function returns in the status variable, the transfert status, and acknowledge the IRQ if required. Returns 0 if success, > 0 if error

unsigned int _ioc_get_block_size()

This function returns the block_size for the block device.