- Timestamp:
- Sep 29, 2014, 12:02:13 PM (10 years ago)
- Location:
- soft/giet_vm/giet_drivers
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/bdv_driver.c
r357 r413 128 128 unsigned int y = cxy & ((1<<Y_WIDTH) - 1); 129 129 130 _printf("\n[BDV DEBUG] Processor[%d,%d,%d] enters _bdv_access()at cycle %d\n"130 _printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] enters at cycle %d\n" 131 131 " - mode = %d\n" 132 132 " - paddr = %l\n" … … 160 160 161 161 #if GIET_DEBUG_IOC_DRIVER 162 _printf("\n[BDV DEBUG] _bdv_access() : transfer tlaunched in polling mode\n");162 _printf("\n[BDV DEBUG] _bdv_access() : transfer launched in polling mode\n"); 163 163 #endif 164 164 unsigned int status; … … 231 231 232 232 #if GIET_DEBUG_IOC_DRIVER 233 _printf("\n[BDV DEBUG] Processor[%d,%d,%d] exit _bdv_access() at cycle%d\n",234 x, y, lpid, _get_proctime() );233 _printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] exit at cycle %d / error = %d\n", 234 x, y, lpid, _get_proctime(), error ); 235 235 #endif 236 236 -
soft/giet_vm/giet_drivers/fbf_driver.c
r345 r413 328 328 329 329 // INVAL L1 cache for the channel descriptor, 330 _dcache_buf_invalidate( ( void*)&_fb_cma_channel[channel_id], 32 );330 _dcache_buf_invalidate( (unsigned int)&_fb_cma_channel[channel_id], 32 ); 331 331 } 332 332 -
soft/giet_vm/giet_drivers/ioc_driver.c
r350 r413 6 6 // Copyright (c) UPMC-LIP6 7 7 /////////////////////////////////////////////////////////////////////////////////// 8 // The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel.8 // Implementation note: 9 9 // 10 // This abstact driver define a generic API, supporting various physical 11 // block device controlers, including: 12 // - vci_block_device : single channel) => bdv_driver 13 // - vci_ahci : multi channels => hba_driver 14 // - sd_card : single channel => sdc_driver 15 // - ramdisk (single channel meory mapped virtual disk) => rdk_driver 10 // 1) In order to share the code, the two _ioc_read() and _ioc_write() functions 11 // call the same _ioc_access() function. 16 12 // 17 // It can exist only one block-device type in the architecture, that must be 18 // defined by one of the following configuration variables in hard_config.h file: 19 // USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK. 20 // 21 // Any physical driver xxx must provide the following API: 22 // - _xxx_init() 23 // - _xxx_read() 24 // - _xxx_write() 25 // - _xxx_get_status() 26 // - _xxx_get_block_size() 27 // The "channel" parameter is no transmited to single channel devices. 28 // 29 // The _ioc_read() and _ioc_write() functions are always blocking for 30 // the calling user program. 31 // 32 // These functions compute the physical address of the memory buffer before 33 // calling the proper physical device. They can be called in 3 modes: 34 // 35 // - In BOOT mode, these functions use the buffer virtual address 36 // as a physical address if the MMU is not activated. 37 // They make a V2P translation if the MMU is activated. 38 // This mode is used to load the map.bin file (before memory activation), 39 // or to load the various .elf files (after MMU activation). 40 // 41 // - In KERNEL mode, these functions make a V2P translation to 42 // compute the buffer physical address. 43 // There is no checking of user access right to the memory buffer. 44 // This mode must be used for an "open" system call. 45 // 46 // - In USER mode, these functions make a V2P translation to 47 // compute the buffer physical address. 48 // The user access right to the memory buffer are checked. 49 // This mode must be used for a "read" or "write" system call. 50 // 51 // The IOMMU can be activated or not: 52 // 53 // 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to 54 // the IOC peripheral, in the I/O virtual space, and the user buffer is 55 // dynamically remapped in the IOMMU page table. The corresponding entry 56 // in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable. 57 // The number of pages to be unmapped is stored in the _ioc_npages variable. 58 // The number of PT2 entries is dynamically computed and stored in the 59 // kernel _ioc_iommu_npages variable. It cannot be larger than 512. 13 // 2) The IOMMU is not supported yet, but the method is the following: 14 // A fixed size 2 Mbytes vseg is allocated to the IOC peripheral, in the I/O 15 // virtual space, and the user buffer is dynamically remapped to one single 16 // big page in the IOMMU page table. 60 17 // The user buffer is unmapped by the _ioc_completed() function when 61 18 // the transfer is completed. 62 //63 // 2/ If the IOMMU is not used, we check that the user buffer is mapped to a64 // contiguous physical buffer (this is generally true because the user space65 // page tables are statically constructed to use contiguous physical memory).66 //67 // Finally, the memory buffer must fulfill the following conditions:68 // - The buffer must be word aligned,69 // - The buffer must be mapped in user space for an user access,70 // - The buffer must be writable in case of (to_mem) access,71 // - The total number of physical pages occupied by the user buffer cannot72 // be larger than 512 pages if the IOMMU is activated,73 // - All physical pages occupied by the user buffer must be contiguous74 // if the IOMMU is not activated.75 // An error code is returned if these conditions are not verified.76 //77 // The SEG_IOC_BASE virtual base address must be defined in hard_config.h,78 // as it is used by the BDV, HBA and SPI drivers.79 //80 // If the RAMDISK is used, an extra memory segment with virtual base address81 // SEG_RDK_BASE, used by RDK driver, must be defined in hard_config.h.82 ///////////////////////////////////////////////////////////////////////////////////83 // Implementation note:84 // In order to share the code, the two _ioc_read() and _ioc_write() functions85 // call the same _ioc_access() function.86 19 /////////////////////////////////////////////////////////////////////////////////// 87 20 … … 166 99 unsigned int y = cid & ((1<<Y_WIDTH) - 1); 167 100 168 _printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _ioc_access()at cycle %d\n"101 _printf("\n[IOC DEBUG] _ioc_access() : P[%d,%d,%d] enters at cycle %d\n" 169 102 " - channel = %d\n" 170 103 " - mode = %d\n" … … 177 110 unsigned int error; // return value 178 111 unsigned int pt_vbase; // page table vbase address 179 unsigned int vpn_min; // first virtuel page index covering buffer 180 unsigned int vpn_max; // last virtual page index covering buffer 181 unsigned int vpn; // current virtual page index 182 unsigned int ppn; // physical page number 183 unsigned int flags; // page protection flags 184 unsigned int ix2; // page index in IOMMU PT1 page table 185 unsigned int ppn_first = 0; // first physical page number for user buffer 186 unsigned int buf_xaddr = 0; // user buffer virtual address in IO space (if IOMMU) 187 paddr_t buf_paddr = 0; // user buffer physical address (if no IOMMU), 112 unsigned int ppn; // user buffer first page PPN 113 unsigned int flags; // user buffer protection flags 114 paddr_t buf_paddr; // user buffer physical address (if no IOMMU), 188 115 189 116 // check buffer alignment 190 117 if ((unsigned int) buf_vaddr & 0x3) 191 118 { 192 _printf("\n[ GIETERROR] in _ioc_access() : buffer not word aligned\n");119 _printf("\n[IOC ERROR] in _ioc_access() : buffer not word aligned\n"); 193 120 _exit(); 194 121 } … … 197 124 if ( (USE_IOC_HBA == 0) && (channel > 0) ) 198 125 { 199 _printf("\n[ GIETERROR] in _ioc_access() : channel must be 0 when HBA not used\n");126 _printf("\n[IOC ERROR] in _ioc_access() : channel must be 0 when HBA not used\n"); 200 127 _exit(); 201 128 } … … 212 139 // get page table virtual address 213 140 pt_vbase = _get_context_slot(CTX_PTAB_ID); 214 vpn_min = buf_vaddr >> 12; 215 vpn_max = (buf_vaddr + length - 1) >> 12; 216 217 // loop on all virtual pages covering the user buffer 218 for (vpn = vpn_min, ix2 = 0 ; vpn <= vpn_max ; vpn++, ix2++ ) 141 142 // get user buffer first page ppn and flags 143 unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase, 144 buf_vaddr >> 12, 145 &ppn, 146 &flags ); 147 // check access rights 148 if ( ko ) 219 149 { 220 // get ppn and flags for each vpn 221 unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase, 222 vpn, 223 &ppn, 224 &flags); 225 // check access rights 226 if ( ko ) 227 { 228 _printf("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n"); 229 return 1; 230 } 231 232 if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) ) 233 { 234 _printf("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n"); 235 return 1; 236 } 237 238 if ( ((flags & PTE_W) == 0 ) && to_mem ) 239 { 240 _printf("\n[GIET ERROR] in _ioc_access() : buffer not writable\n"); 241 return 1; 242 } 243 244 // save first ppn value 245 if (ix2 == 0) ppn_first = ppn; 246 247 #if GIET_USE_IOMMU 248 249 // check buffer length < 2 Mbytes 250 if (ix2 > 511) // check buffer length < 2 Mbytes 251 { 252 _printf("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n"); 253 return 1; 254 } 255 // map the physical page in IOMMU page table 256 _iommu_add_pte2( _ioc_iommu_ix1, // PT1 index 257 ix2, // PT2 index 258 ppn, // Physical page number 259 flags ); // Protection flags 260 261 // compute user buffer virtual adress in IO space 262 buf_xaddr = (_ioc_iommu_ix1) << 21 | (buf_vaddr & 0xFFF); 263 264 #else 265 266 // check that physical pages are contiguous 267 if ((ppn - ppn_first) != ix2) 268 { 269 _printf("[GIET ERROR] in _ioc_access() : split physical buffer\n"); 270 return 1; 271 } 272 273 // compute user buffer physical adress 274 buf_paddr = (((paddr_t)ppn_first) << 12) | (buf_vaddr & 0xFFF); 275 #endif 276 277 } // end for vpn 278 } 279 280 #if GIET_USE_IOMMU 281 282 // register the number of pages to be unmapped in IOMMU 283 _ioc_iommu_npages = (vpn_max - vpn_min) + 1; 284 285 #endif 150 _printf("\n[IOC ERROR] in _ioc_access() : buffer unmapped\n"); 151 _exit(); 152 } 153 154 if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) ) 155 { 156 _printf("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n"); 157 _exit(); 158 } 159 160 if ( ((flags & PTE_W) == 0 ) && to_mem ) 161 { 162 _printf("\n[IOC ERROR] in _ioc_access() : buffer not writable\n"); 163 _exit(); 164 } 165 166 buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF); 167 } 168 169 // cache coherence for both L1 & L2 caches 286 170 287 171 if ( to_mem ) // memory write : invalidate data caches 288 172 { 289 // L1 cache 290 if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( (void *) buf_vaddr, length);291 292 // L2 cache (only if IOB used)173 // L1 cache (only if L1 cache coherence not guaranteed by hardware) 174 if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length ); 175 176 // L2 cache (only if we use an IO-Bridge component in architecture)) 293 177 if ( USE_IOB ) _mmc_inval( buf_paddr, length ); 294 178 } … … 297 181 // L1 cache : nothing to do for L1 write-through 298 182 299 // L2 cache (only if IOB used)183 // L2 cache (only if we use an IO-Bridge component in architecture)) 300 184 if ( USE_IOB ) _mmc_sync( buf_paddr, length ); 301 185 } 302 186 303 if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr;304 305 ///////////////////////////////////////////306 187 // select the proper physical device 307 /////////////////////////////////////////// 308 309 #if ( USE_IOC_BDV ) 188 189 #if ( USE_IOC_BDV ) 310 190 if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count); 311 191 else error = _bdv_write( mode, lba, buf_paddr, count); … … 324 204 } // end _ioc_access() 325 205 326 /////////////////////////////////////////////////////////////////////////////// 327 // This function cheks block size, and desactivates the IOC interrupts. 328 // Return 0 for success. 329 /////////////////////////////////////////////////////////////////////////////// 206 ////////////////////////////////////////////// 330 207 unsigned int _ioc_init( unsigned int channel ) 331 208 { … … 351 228 } 352 229 353 /////////////////////////////////////////////////////////////////////////////// 354 // Transfer data from the block device to a memory buffer. 355 // - mode : BOOT_PA / BOOT_VA / KERNEL / USER 356 // - lba : first block index on the block device 357 // - buffer : base address of the memory buffer (must be word aligned) 358 // - count : number of blocks to be transfered. 359 // Returns 0 if success, > 0 if error. 360 /////////////////////////////////////////////////////////////////////////////// 230 ////////////////////////////////////////////// 361 231 unsigned int _ioc_read( unsigned int channel, 362 232 unsigned int mode, … … 373 243 } 374 244 375 /////////////////////////////////////////////////////////////////////////////// 376 // Transfer data from a memory buffer to the block device. 377 // - mode : BOOT_PA / BOOT_VA / KERNEL / USER 378 // - lba : first block index on the block device 379 // - buffer : base address of the memory buffer (must be word aligned) 380 // - count : number of blocks to be transfered. 381 // Returns 0 if success, > 0 if error. 382 /////////////////////////////////////////////////////////////////////////////// 245 ////////////////////////////////////////////// 383 246 unsigned int _ioc_write( unsigned int channel, 384 247 unsigned int mode, … … 395 258 } 396 259 397 /////////////////////////////////////////////////////////////////////////////// 398 // This function returns in the status variable, the transfert status, and 399 // acknowledge the IRQ if the IOC controler is not busy. 400 // Returns 0 if success, > 0 if error 401 /////////////////////////////////////////////////////////////////////////////// 260 ///////////////////////////////////////////////////// 402 261 unsigned int _ioc_get_status( unsigned int channel ) 403 262 { … … 427 286 } 428 287 429 /////////////////////////////////////////////////////////////////////////////// 430 // This function returns the block_size with which the IOC has been configured. 431 /////////////////////////////////////////////////////////////////////////////// 288 ////////////////////////////////// 432 289 unsigned int _ioc_get_block_size() 433 290 { -
soft/giet_vm/giet_drivers/ioc_driver.h
r295 r413 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel. 8 // 9 // This abstact driver define a generic API, supporting various physical 10 // block device controlers, including: 11 // - vci_block_device : single channel => bdv_driver 12 // - vci_ahci : multi channels => hba_driver 13 // - sd_card : single channel => sdc_driver 14 // - ramdisk (single channel meory mapped virtual disk) => rdk_driver 15 // 16 // It can exist only one block-device type in the architecture, that must be 17 // defined by one of the following configuration variables in hard_config.h file: 18 // USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK. 19 // 20 // Any physical block device driver xxx must provide the following API: 21 // - _xxx_init() 22 // - _xxx_read() 23 // - _xxx_write() 24 // - _xxx_get_status() 25 // - _xxx_get_block_size() 26 // The "channel" parameter is no transmited to single channel devices. 27 // 28 // The _ioc_read() and _ioc_write() functions are always blocking for 29 // the calling user program. 30 // 31 // These functions compute the physical address of the memory buffer before 32 // calling the proper physical device. We know that the user buffer is mapped 33 // to a contiguous physical buffer because, for each vseg, the page tables 34 // are statically constructed to use contiguous physical memory. 35 // 36 // These functions can be called in 3 modes: 37 // 38 // - In BOOT mode, these functions use the buffer virtual address 39 // as a physical address if the MMU is not activated. 40 // They make a V2P translation if the MMU is activated. 41 // This mode is used to load the map.bin file (before memory activation), 42 // or to load the various .elf files (after MMU activation). 43 // 44 // - In KERNEL mode, these functions make a V2P translation to 45 // compute the buffer physical address. 46 // There is no checking of user access right to the memory buffer. 47 // This mode must be used for an "open" system call. 48 // 49 // - In USER mode, these functions make a V2P translation to 50 // compute the buffer physical address. 51 // The user access right to the memory buffer are checked. 52 // This mode must be used for a "read" or "write" system call. 53 // 54 // Finally, the memory buffer must fulfill the following conditions: 55 // - The buffer must be word aligned, 56 // - The buffer must be mapped in user space for an user access, 57 // - The buffer must be writable in case of (to_mem) access, 58 // - The total number of physical pages occupied by the user buffer cannot 59 // be larger than 512 pages if the IOMMU is activated, 60 // - All physical pages occupied by the user buffer must be contiguous 61 // if the IOMMU is not activated. 62 // Exit if these conditions are not verified. 63 // 64 // The SEG_IOC_BASE virtual base address must be defined in hard_config.h, 65 // as it is used by the BDV, HBA and SPI drivers. 66 // 67 // If the RAMDISK is used, an extra memory segment with virtual base address 68 // SEG_RDK_BASE, used by RDK driver, must be defined in hard_config.h. 69 /////////////////////////////////////////////////////////////////////////////////// 70 // Implementation note: 71 // 72 // 1) In order to share the code, the two _ioc_read() and _ioc_write() functions 73 // call the same _ioc_access() function. 74 // 75 // 2) The IOMMU is not supported yet, but the method is the following: 76 // A fixed size 2 Mbytes vseg is allocated to the IOC peripheral, in the I/O 77 // virtual space, and the user buffer is dynamically remapped to one single 78 // big page in the IOMMU page table. 79 // The user buffer is unmapped by the _ioc_completed() function when 80 // the transfer is completed. 6 81 /////////////////////////////////////////////////////////////////////////////////// 7 82 … … 31 106 /////////////////////////////////////////////////////////////////////////////////// 32 107 108 /////////////////////////////////////////////////////////////////////////////// 109 // This function cheks block size, and desactivates the IOC interrupts. 110 // Return 0 for success, non zero if error. 111 /////////////////////////////////////////////////////////////////////////////// 33 112 extern unsigned int _ioc_init( unsigned int channel ); 34 113 114 /////////////////////////////////////////////////////////////////////////////// 115 // Transfer data from a memory buffer to the block device. 116 // - mode : BOOT_PA / BOOT_VA / KERNEL / USER 117 // - lba : first block index on the block device 118 // - buffer : base address of the memory buffer (must be word aligned) 119 // - count : number of blocks to be transfered. 120 // Returns 0 if success, > 0 if error. 121 /////////////////////////////////////////////////////////////////////////////// 35 122 extern unsigned int _ioc_write( unsigned int channel, 36 123 unsigned int mode, … … 39 126 unsigned int count ); 40 127 128 /////////////////////////////////////////////////////////////////////////////// 129 // Transfer data from the block device to a memory buffer. 130 // - mode : BOOT_PA / BOOT_VA / KERNEL / USER 131 // - lba : first block index on the block device 132 // - buffer : base address of the memory buffer (must be word aligned) 133 // - count : number of blocks to be transfered. 134 // Returns 0 if success, > 0 if error. 135 /////////////////////////////////////////////////////////////////////////////// 41 136 extern unsigned int _ioc_read( unsigned int channel, 42 137 unsigned int mode, … … 45 140 unsigned int count ); 46 141 142 /////////////////////////////////////////////////////////////////////////////// 143 // This function returns in the status variable, the transfert status, and 144 // acknowledge the IRQ if the IOC controler is not busy. 145 // Returns 0 if success, > 0 if error 146 /////////////////////////////////////////////////////////////////////////////// 47 147 extern unsigned int _ioc_get_status( unsigned int channel ); 48 148 149 /////////////////////////////////////////////////////////////////////////////// 150 // This function returns the block_size for the block device. 151 /////////////////////////////////////////////////////////////////////////////// 49 152 extern unsigned int _ioc_get_block_size(); 50 51 ///////////////////////////////////////////////////////////////////////////////////52 153 53 154 -
soft/giet_vm/giet_drivers/pic_driver.c
r320 r413 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The pic_driver.c and pic_drivers.h files are part ot the GIET-VM kernel.8 // This driver supports the SocLib vci_iopic component.9 //10 // The SEG_PIC_BASE address must be defined in hard_config.h file.11 ///////////////////////////////////////////////////////////////////////////////////12 7 // Implementation note: 13 //14 8 // All physical accesses to device registers are done by the two 15 9 // _pic_get_register(), _pic_set_register() low-level functions, … … 25 19 26 20 ///////////////////////////////////////////////////////////////////////////////// 27 // This low level function returns the value of register (channel / index)28 /////////////////////////////////////////////////////////////////////////////////29 21 unsigned int _pic_get_register( unsigned int channel, 30 22 unsigned int index ) … … 34 26 } 35 27 36 /////////////////////////////////////////////////////////////////////////////////37 // This low level function set a new value in register (channel / index)38 28 ///////////////////////////////////////////////////////////////////////////////// 39 29 void _pic_set_register( unsigned int channel, … … 45 35 } 46 36 47 ///////////////////////////////////////////////////////////////////////////////// 48 // This function initializes the XICU target physical address (vaddr + extend) 49 // corresponding to a given HWI channel. 37 50 38 ///////////////////////////////////////////////////////////////////////////////// 51 39 void _pic_init( unsigned int channel, // source PIC HWI channel … … 55 43 _pic_set_register( channel, IOPIC_ADDRESS, vaddr ); 56 44 _pic_set_register( channel, IOPIC_EXTEND, extend ); 45 _pic_set_register( channel, IOPIC_MASK, 1 ); 57 46 } 58 47 59 /////////////////////////////////////////////////////////////////////////////////60 // This function returns the status of a given HWI channel.61 48 ///////////////////////////////////////////////////////////////////////////////// 62 49 unsigned int _pic_get_status( unsigned int channel ) -
soft/giet_vm/giet_drivers/pic_driver.h
r298 r413 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The pic_driver.c and pic_drivers.h files are part ot the GIET-VM kernel. 8 // This driver supports the SocLib vci_iopic component. 9 // 10 // The SEG_PIC_BASE address must be defined in hard_config.h file. 6 11 /////////////////////////////////////////////////////////////////////////////////// 7 12 … … 18 23 IOPIC_EXTEND = 1, 19 24 IOPIC_STATUS = 2, 25 IOPIC_MASK = 3, 20 26 /**/ 21 27 IOPIC_SPAN = 4, … … 26 32 ////////////////////////////////////////////////////////////////////////////////// 27 33 34 ///////////////////////////////////////////////////////////////////////////////// 35 // This function initializes the XICU target physical address (vaddr + extend) 36 // corresponding to a given HWI channel. 37 ///////////////////////////////////////////////////////////////////////////////// 28 38 extern void _pic_init( unsigned int channel, // source PIC HWI channel 29 39 unsigned int vaddr, // dest XCU WTI address 30 40 unsigned int extend ); // dest XCU cluster_xy 31 41 42 ///////////////////////////////////////////////////////////////////////////////// 43 // This function returns the status of a given HWI channel. 44 ///////////////////////////////////////////////////////////////////////////////// 32 45 extern unsigned int _pic_get_status( unsigned int channel ); 33 46 … … 36 49 /////////////////////////////////////////////////////////////////////////////////// 37 50 51 ///////////////////////////////////////////////////////////////////////////////// 52 // This low level function returns the value of register (channel / index) 53 ///////////////////////////////////////////////////////////////////////////////// 38 54 extern unsigned int _pic_get_register( unsigned int channel, 39 55 unsigned int index ); 40 56 57 ///////////////////////////////////////////////////////////////////////////////// 58 // This low level function set a new value in register (channel / index) 59 ///////////////////////////////////////////////////////////////////////////////// 41 60 extern void _pic_set_register( unsigned int channel, 42 61 unsigned int index,
Note: See TracChangeset
for help on using the changeset viewer.