| [283] | 1 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2 | // File      : bdv_driver.h | 
|---|
|  | 3 | // Date      : 01/11/2013 | 
|---|
|  | 4 | // Author    : alain greiner | 
|---|
|  | 5 | // Maintainer: cesar fuguet | 
|---|
|  | 6 | // Copyright (c) UPMC-LIP6 | 
|---|
|  | 7 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [437] | 8 | // The bdv_driver.c and bdv_driver.h files are part ot the GIET-VM kernel. | 
|---|
|  | 9 | // This driver supports the SocLib vci_block_device component, that is | 
|---|
|  | 10 | // a single channel, block oriented, external storage contrÃŽler. | 
|---|
|  | 11 | // | 
|---|
|  | 12 | // The _bdv_read() and _bdv_write() functions are always blocking. | 
|---|
|  | 13 | // They can be called in 3 modes: | 
|---|
|  | 14 | // | 
|---|
|  | 15 | // - In BOOT mode, these functions use a polling policy on the BDV STATUS | 
|---|
|  | 16 | //   register to detect transfer completion, as interrupts are not activated. | 
|---|
|  | 17 | //   This mode is used by the boot code to load the map.bin file into memory | 
|---|
|  | 18 | //   (before MMU activation), or to load the .elf files (after MMU activation). | 
|---|
|  | 19 | // | 
|---|
|  | 20 | // - In KERNEL mode, these functions use a descheduling strategy: | 
|---|
|  | 21 | //   The ISR executed when transfer completes should restart the calling task. | 
|---|
|  | 22 | //   There is no checking of user access right to the memory buffer. | 
|---|
|  | 23 | //   This mode must be used, for an "open" system call. | 
|---|
|  | 24 | // | 
|---|
|  | 25 | // - In USER mode, these functions use a descheduling strategy: | 
|---|
|  | 26 | //   The ISR executed when transfer completes should restart the calling task, | 
|---|
|  | 27 | //   The user access right to the memory buffer must be checked. | 
|---|
|  | 28 | //   This mode must be used for a "read/write" system call. | 
|---|
|  | 29 | // | 
|---|
|  | 30 | // As the BDV component can be used by several programs running in parallel, | 
|---|
|  | 31 | // the _bdv_lock variable guaranties exclusive access to the device.  The | 
|---|
|  | 32 | // _bdv_read() and _bdv_write() functions use atomic LL/SC to get the lock. | 
|---|
|  | 33 | // | 
|---|
|  | 34 | // Finally, the memory buffer must fulfill the following conditions: | 
|---|
|  | 35 | // - The buffer must be word aligned, | 
|---|
|  | 36 | // - The buffer must be mapped in user space for an user access, | 
|---|
|  | 37 | // - The buffer must be writable in case of (to_mem) access, | 
|---|
|  | 38 | // - The total number of physical pages occupied by the user buffer cannot | 
|---|
|  | 39 | //   be larger than 512 pages if the IOMMU is activated, | 
|---|
|  | 40 | // - All physical pages occupied by the user buffer must be contiguous | 
|---|
|  | 41 | //   if the IOMMU is not activated. | 
|---|
|  | 42 | // An error code is returned if these conditions are not verified. | 
|---|
|  | 43 | // | 
|---|
|  | 44 | // The SEG_IOC_BASE address must be defined in the hard_config.h file. | 
|---|
|  | 45 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [283] | 46 |  | 
|---|
| [295] | 47 | #ifndef _GIET_BDV_DRIVER_H_ | 
|---|
|  | 48 | #define _GIET_BDV_DRIVER_H_ | 
|---|
| [283] | 49 |  | 
|---|
| [350] | 50 | #include "utils.h" | 
|---|
|  | 51 |  | 
|---|
| [295] | 52 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 53 | // BDV global variables | 
|---|
|  | 54 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [283] | 55 |  | 
|---|
| [350] | 56 | extern giet_lock_t           _bdv_lock;    // BDV is a shared ressource | 
|---|
| [295] | 57 | extern volatile unsigned int _bdv_status;  // required for IRQ signaling | 
|---|
|  | 58 | extern volatile unsigned int _bdv_gtid;    // descheduled task id = gpid<<16 + ltid | 
|---|
|  | 59 |  | 
|---|
| [283] | 60 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [295] | 61 | // BDV registers, operations and status values | 
|---|
| [283] | 62 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 63 |  | 
|---|
| [295] | 64 | enum BDV_registers | 
|---|
|  | 65 | { | 
|---|
|  | 66 | BLOCK_DEVICE_BUFFER, | 
|---|
|  | 67 | BLOCK_DEVICE_LBA, | 
|---|
|  | 68 | BLOCK_DEVICE_COUNT, | 
|---|
|  | 69 | BLOCK_DEVICE_OP, | 
|---|
|  | 70 | BLOCK_DEVICE_STATUS, | 
|---|
|  | 71 | BLOCK_DEVICE_IRQ_ENABLE, | 
|---|
|  | 72 | BLOCK_DEVICE_SIZE, | 
|---|
|  | 73 | BLOCK_DEVICE_BLOCK_SIZE, | 
|---|
|  | 74 | BLOCK_DEVICE_BUFFER_EXT, | 
|---|
|  | 75 | }; | 
|---|
| [283] | 76 |  | 
|---|
| [295] | 77 | enum BDV_operations | 
|---|
|  | 78 | { | 
|---|
|  | 79 | BLOCK_DEVICE_NOOP, | 
|---|
|  | 80 | BLOCK_DEVICE_READ, | 
|---|
|  | 81 | BLOCK_DEVICE_WRITE, | 
|---|
|  | 82 | }; | 
|---|
| [283] | 83 |  | 
|---|
| [295] | 84 | enum BDV_status | 
|---|
|  | 85 | { | 
|---|
|  | 86 | BLOCK_DEVICE_IDLE, | 
|---|
|  | 87 | BLOCK_DEVICE_BUSY, | 
|---|
|  | 88 | BLOCK_DEVICE_READ_SUCCESS, | 
|---|
|  | 89 | BLOCK_DEVICE_WRITE_SUCCESS, | 
|---|
|  | 90 | BLOCK_DEVICE_READ_ERROR, | 
|---|
|  | 91 | BLOCK_DEVICE_WRITE_ERROR, | 
|---|
|  | 92 | BLOCK_DEVICE_ERROR, | 
|---|
|  | 93 | }; | 
|---|
| [283] | 94 |  | 
|---|
| [295] | 95 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [437] | 96 | //            Access functions | 
|---|
| [295] | 97 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [283] | 98 |  | 
|---|
| [437] | 99 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 100 | // This function cheks block size == 512, and desactivates the interrupts. | 
|---|
|  | 101 | // Return 0 for success, > 0 if error | 
|---|
|  | 102 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [295] | 103 | extern unsigned int _bdv_init(); | 
|---|
|  | 104 |  | 
|---|
| [437] | 105 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 106 | // Transfer data from the block device to a memory buffer. | 
|---|
|  | 107 | // - mode     : BOOT / KERNEL / USER | 
|---|
|  | 108 | // - lba      : first block index on the block device | 
|---|
|  | 109 | // - buffer   : base address of the memory buffer (must be word aligned) | 
|---|
|  | 110 | // - count    : number of blocks to be transfered. | 
|---|
|  | 111 | // Returns 0 if success, > 0 if error. | 
|---|
|  | 112 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 113 | extern unsigned int _bdv_read(  unsigned int       mode, | 
|---|
| [295] | 114 | unsigned int       lba, | 
|---|
| [437] | 115 | unsigned long long buffer, | 
|---|
| [295] | 116 | unsigned int       count ); | 
|---|
|  | 117 |  | 
|---|
| [437] | 118 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 119 | // Transfer data from a memory buffer to the block device. | 
|---|
|  | 120 | // - mode     : BOOT / KERNEL / USER | 
|---|
|  | 121 | // - lba      : first block index on the block device | 
|---|
|  | 122 | // - buffer   : base address of the memory buffer (must be word aligned) | 
|---|
|  | 123 | // - count    : number of blocks to be transfered. | 
|---|
|  | 124 | // Returns 0 if success, > 0 if error. | 
|---|
|  | 125 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 126 | extern unsigned int _bdv_write( unsigned int       mode, | 
|---|
| [295] | 127 | unsigned int       lba, | 
|---|
| [437] | 128 | unsigned long long buffer, | 
|---|
| [295] | 129 | unsigned int       count ); | 
|---|
|  | 130 |  | 
|---|
| [437] | 131 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 132 | // Returns device status. | 
|---|
|  | 133 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [295] | 134 | extern unsigned int _bdv_get_status(); | 
|---|
|  | 135 |  | 
|---|
| [437] | 136 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 137 | // Returns block size. | 
|---|
|  | 138 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [283] | 139 | extern unsigned int _bdv_get_block_size(); | 
|---|
|  | 140 |  | 
|---|
| [437] | 141 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 142 | // This ISR save the status, acknowledge the IRQ, and activates the task | 
|---|
|  | 143 | // waiting on IO transfer. It can be an HWI or a SWI. | 
|---|
|  | 144 | // | 
|---|
|  | 145 | // TODO the _set_task_slot access should be replaced by an atomic LL/SC | 
|---|
|  | 146 | //      when the CTX_RUN bool will be replaced by a bit_vector. | 
|---|
|  | 147 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [295] | 148 | extern void _bdv_isr( unsigned irq_type, | 
|---|
|  | 149 | unsigned irq_id, | 
|---|
|  | 150 | unsigned channel ); | 
|---|
|  | 151 |  | 
|---|
| [283] | 152 |  | 
|---|
|  | 153 | #endif | 
|---|
|  | 154 |  | 
|---|
|  | 155 | // Local Variables: | 
|---|
|  | 156 | // tab-width: 4 | 
|---|
|  | 157 | // c-basic-offset: 4 | 
|---|
|  | 158 | // c-file-offsets:((innamespace . 0)(inline-open . 0)) | 
|---|
|  | 159 | // indent-tabs-mode: nil | 
|---|
|  | 160 | // End: | 
|---|
|  | 161 | // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 | 
|---|
|  | 162 |  | 
|---|