/////////////////////////////////////////////////////////////////////////////////// // File : ioc_driver.h // Date : 01/11/2013 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// // The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel. // // This abstact driver define a generic API, supporting various physical // block device controlers, including: // - vci_block_device : single channel => bdv_driver // - vci_ahci : multi channels => hba_driver // - sd_card : single channel => sdc_driver // - ramdisk (single channel meory 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 must provide the 5 five functions defined // by this generic driver. // // 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. We know that the user buffer is mapped // to a contiguous physical buffer because, for each vseg, the page tables // are statically constructed to use contiguous physical memory. // // 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. // // Finally, 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, // - The total number of physical pages occupied by the user buffer cannot // be larger than 512 pages if the IOMMU is activated, // - All physical pages occupied by the user buffer must be contiguous // if the IOMMU is not activated. // 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. /////////////////////////////////////////////////////////////////////////////////// #ifndef _GIET_IOC_DRIVER_H_ #define _GIET_IOC_DRIVER_H_ /////////////////////////////////////////////////////////////////////////////////// // IOC (vci_block device) registers offsets /////////////////////////////////////////////////////////////////////////////////// enum IOC_driver_modes { IOC_BOOT_MODE = 0, // Polling IOC_STATUS / no access right checking IOC_KERNEL_MODE = 1, // Descheduling + IRQ / no access right checking IOC_USER_MODE = 2, // Descheduling + IRQ / access right checking }; /////////////////////////////////////////////////////////////////////////////////// // IOC global variables (generic disk controller) /////////////////////////////////////////////////////////////////////////////////// extern volatile unsigned int _ioc_iommu_ix1; extern volatile unsigned int _ioc_iommu_npages; /////////////////////////////////////////////////////////////////////////////////// // External functions /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // This function cheks block size, and desactivates interrupts. // Return 0 for success, non zero if error. /////////////////////////////////////////////////////////////////////////////// extern unsigned int _ioc_init( unsigned int channel ); /////////////////////////////////////////////////////////////////////////////// // Transfer data from a memory buffer to the disk. // - 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. /////////////////////////////////////////////////////////////////////////////// extern unsigned int _ioc_write( unsigned int channel, unsigned int mode, unsigned int lba, const void* buffer, unsigned int count ); /////////////////////////////////////////////////////////////////////////////// // Transfer data from the disk to a memory buffer. // - 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. /////////////////////////////////////////////////////////////////////////////// extern unsigned int _ioc_read( unsigned int channel, unsigned int mode, unsigned int lba, void* buffer, unsigned int count ); /////////////////////////////////////////////////////////////////////////////// // This function returns in the status variable, the transfert status, and // acknowledge the IRQ if required. // Returns 0 if success, > 0 if error /////////////////////////////////////////////////////////////////////////////// extern unsigned int _ioc_get_status( unsigned int channel ); /////////////////////////////////////////////////////////////////////////////// // This function returns the block_size for the block device. /////////////////////////////////////////////////////////////////////////////// extern unsigned int _ioc_get_block_size(); #endif // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4