Ignore:
Timestamp:
Feb 4, 2014, 2:16:37 AM (10 years ago)
Author:
cfuguet
Message:

Modifications on GIET-VM IOC driver:

  • Introducing new layer on the IOC driver. Every call to ioc_read, ioc_write, ioc_get_block_size or ioc_init

functions will call the specific driver of the used IOC
controller. Supported IOC controllers are (for now) :

  1. BDV (Soclib Block Device)
  2. HBA
  3. SPI (SDCARD - SPI controller)
  • All functions of IOC controllers drivers respect the same interface.
  • To specify the used IOC controller of the platform, a subtype field has been introduced on the map.xml file. This subtype field must be declared on the IOC periph instantiation. Available subtypes (for now) : BDV, HBA or SPI.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_drivers/ioc_driver.c

    r279 r289  
    11///////////////////////////////////////////////////////////////////////////////////
    2 // File     : ioc_driver.c
    3 // Date     : 23/05/2013
    4 // Author   : alain greiner
     2// File       : ioc_driver.c
     3// Date       : 23/05/2013
     4// Author     : alain greiner
     5// Maintainer : cesar fuguet
    56// Copyright (c) UPMC-LIP6
    67///////////////////////////////////////////////////////////////////////////////////
     
    1213//
    1314// The _ioc_read() and _ioc_write() functions use the _ioc_access() function,
    14 // that is always blocking, but can be called in 4 modes:
    15 //
    16 // - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address
    17 //   as a physical address (as the page tables are not build) and use a polling
    18 //   policy on the IOC_STATUS register to detect transfer completion, as
    19 //   hardware interrupts are not activated. This mode is used by the
    20 //   boot code to load the map.bin file into memory.
     15// that is always blocking. The _ioc_access function will call the read or
     16// write function in the driver of the choosen IOC peripheral, which can be for
     17// now: BDV, HBA and SPI. This function can be called in 4 modes:
     18//
     19// - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address
     20//   as a physical address (as the page tables are not build). This mode is
     21//   used by the boot code to load the map.bin file into memory.
    2122//
    2223// - In BOOT_VA mode, the _ioc_access() function makes a V2P translation to
    23 //   compute the buffer physical address, and use a polling policy on IOC_STATUS
    24 //   register to detect transfer completion. This mode is used by the boot code
    25 //   to load the various .elf files into memory.
     24//   compute the buffer physical address. This mode is used by the boot code to
     25//   load the various .elf files into memory.
    2626//
    2727// - In KERNEL mode, the _ioc_access() function makes a V2P translation to
    28 //   compute the buffer physical address, and use a descheduling strategy:
    29 //   The ISR executed when transfer completes should restart the calling task.
    30 //   There is no checking of user access right to the memory buffer.
    31 //   This mode must be used to access IOC, for an "open" system call.
     28//   compute the buffer physical address. There is no checking of user access
     29//   right to the memory buffer.  This mode must be used to access IOC, for an
     30//   "open" system call.
    3231//
    3332// - In USER mode, the _ioc_access() function makes a V2P translation to
    34 //   compute the buffer physical address, and use a descheduling strategy:
    35 //   The ISR executed when transfer completes should restart the calling task,
    36 //   The user access right to the memory buffer must be checked.
    37 //   This mode must be used to access IOC, for a "read/write" system call.
    38 //
    39 // As the IOC component can be used by several programs running in parallel,
    40 // the _ioc_lock variable guaranties exclusive access to the device.  The
    41 // _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock.
     33//   compute the buffer physical address. The user access right to the memory
     34//   buffer must be checked.  This mode must be used to access IOC, for a
     35//   "read/write" system call.
    4236//
    4337// The IOMMU can be activated or not:
     
    8781#endif
    8882
     83#if (USE_BDV + USE_SPI + USE_HBA) != 1
     84# error: You must use only one IOC controller (BDV or SPI or HBA)
     85#endif
     86
     87#if USE_BDV
     88# include <bdv_driver.h>
     89#endif
     90
     91#if USE_SPI
     92# include <sdc_driver.h>
     93#endif
     94
     95#if USE_HBA
     96# include <hba_driver.h>
     97#endif
     98
     99
    89100#define in_unckdata __attribute__((section (".unckdata")))
    90101
    91102///////////////////// IOC global variables
    92103
    93 in_unckdata unsigned int          _ioc_lock = 0;
    94 in_unckdata volatile unsigned int _ioc_status = 0;
     104in_unckdata unsigned int _ioc_lock = 0;
     105in_unckdata unsigned int _ioc_status = 0;
    95106in_unckdata volatile unsigned int _ioc_gtid;
    96107in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0;
     
    155166    }
    156167
    157     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;
    158 
    159168    unsigned int length = count << 9;  // count * 512 bytes
    160169
     
    269278    }
    270279
    271     // get the lock protecting IOC
    272     _get_lock(&_ioc_lock);
    273 
    274     // set the _ioc_status polling variable
    275     _ioc_status = BLOCK_DEVICE_BUSY;
    276 
    277 #if GIET_DEBUG_IOC_DRIVER
    278 _tty_get_lock( 0 );
    279 _puts("\n[IOC DEBUG] _ioc_access() : configure IOC\n");
    280 _puts(" - buf_paddr = ");
    281 _putl( buf_paddr );
    282 _puts("\n");
    283 _puts(" - count     = ");
    284 _putd( count );
    285 _puts("\n");
    286 _puts(" - lba       = ");
    287 _putx( lba );
    288 _puts("\n");
    289 _tty_release_lock( 0 );
    290 #endif
    291 
    292     // send command to IOC   
    293     if ( GIET_USE_IOMMU )
    294     {
    295         ioc_address[BLOCK_DEVICE_BUFFER] = buf_xaddr;
    296         ioc_address[BLOCK_DEVICE_COUNT]  = count;
    297         ioc_address[BLOCK_DEVICE_LBA]    = lba;
    298     }
    299     else
    300     {
    301         ioc_address[BLOCK_DEVICE_BUFFER]     = (unsigned int)buf_paddr;
    302         ioc_address[BLOCK_DEVICE_BUFFER_EXT] = (unsigned int)(buf_paddr>>32);
    303         ioc_address[BLOCK_DEVICE_COUNT]      = count;
    304         ioc_address[BLOCK_DEVICE_LBA]        = lba;
    305     }
    306 
    307     // There is two policies for transfer completion
    308         // detection, depending on the mode argument:
    309 
    310     if ( (mode == IOC_BOOT_PA_MODE) ||    // We poll directly the IOC_STATUS register
    311          (mode == IOC_BOOT_VA_MODE) )     // as IRQs are masked.
    312     {
    313         // Launch transfert
    314         if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
    315         else             ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
    316 
    317         unsigned int status;
    318         if ( _ioc_get_status(0, &status) ) return 1;
    319 
    320         while( (status != BLOCK_DEVICE_READ_SUCCESS)  &&
    321                (status != BLOCK_DEVICE_READ_ERROR)    &&
    322                (status != BLOCK_DEVICE_WRITE_SUCCESS) &&
    323                (status != BLOCK_DEVICE_WRITE_ERROR) )
    324         {
    325             if ( _ioc_get_status(0, &status) ) return 1;
    326 
    327 #if GIET_DEBUG_IOC_DRIVER
    328 _tty_get_lock( 0 );
    329 _puts("\n[IOC DEBUG] _ioc_access() : ... waiting on IOC_STATUS register ...\n");
    330 _tty_release_lock( 0 );
    331 #endif
    332 
    333         }
    334         // analyse status
    335         error = ( (status == BLOCK_DEVICE_READ_ERROR) ||
    336                   (status == BLOCK_DEVICE_WRITE_ERROR) );
    337 
    338         // release lock
    339         _release_lock(&_ioc_lock);     
    340     }
    341     else                           // in USER or KERNEL mode, we deschedule the task.
    342                                    // When the task is rescheduled by the ISR, we reset
    343                                    // the _ioc_status variable, and release the lock
    344     {
    345         // We need a critical section, because we must reset the RUN bit
    346                 // before to launch the transfer, and we want to avoid to be descheduled
    347                 // between these two operations.
    348 
    349         // Enter critical section
    350         _it_disable();
    351        
    352         // set _ioc_gtid and reset runnable
    353         unsigned int ltid = _get_proc_task_id();
    354         unsigned int pid = _get_procid();
    355         _ioc_gtid = (pid<<16) + ltid;
    356         _set_task_slot( pid, ltid, CTX_RUN_ID, 0 ); 
    357        
    358         // Launch transfert
    359         if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
    360         else             ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
    361 
    362         // deschedule task
    363         _ctx_switch();                     
    364 
    365         // analyse status
    366         error = ( (_ioc_status == BLOCK_DEVICE_READ_ERROR) ||
    367                   (_ioc_status == BLOCK_DEVICE_WRITE_ERROR) );
    368 
    369         // reset _ioc_status and release lock
    370         _ioc_status = BLOCK_DEVICE_IDLE;
    371         _release_lock(&_ioc_lock);     
    372     }
    373 
    374 #if GIET_DEBUG_IOC_DRIVER
    375 _tty_get_lock( 0 );
    376 _puts("\n[IOC DEBUG] _ioc_access completed at cycle ");
    377 _putd( _get_proctime() );
    378 _puts(" for processor ");
    379 _putd( _get_procid() );
    380 _puts(" : error = ");
    381 _putd( (unsigned int)error );
    382 _puts("\n");
    383 _tty_release_lock( 0 );
     280    if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr;
     281
     282#if   USE_BDV
     283    if (to_mem) error = _bdv_read (mode, lba, buf_paddr, count);
     284    else        error = _bdv_write(mode, lba, buf_paddr, count);
     285#elif USE_SPI
     286    if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
     287    else        error = _sdc_write(mode, lba, buf_paddr, count);
     288#elif USE_HBA
     289    if (to_mem) error = _hba_read (mode, lba, buf_paddr, count);
     290    else        error = _hba_write(mode, lba, buf_paddr, count);
    384291#endif
    385292
     
    392299// Return 0 for success.
    393300///////////////////////////////////////////////////////////////////////////////
    394 unsigned int _ioc_init()
    395 {
    396     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;
    397    
    398     if ( ioc_address[BLOCK_DEVICE_BLOCK_SIZE] != 512 )
    399     {
    400         _puts("\n[GIET ERROR] in _ioc_init() : block size must be 512 bytes\n");
    401         _exit();
    402     }
    403 
    404     ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
    405     return 0;
     301unsigned int _ioc_init( unsigned int channel )
     302{
     303#if   USE_BDV
     304    return _bdv_init( channel );
     305#elif USE_SPI
     306    return _sdc_init( channel );
     307#elif USE_HBA
     308    return _hba_init( channel );
     309#endif
    406310}
    407311
     
    457361                              unsigned int* status )
    458362{
    459     if ( channel != 0 )
    460     {
    461         _tty_get_lock( 0 );
    462         _puts("\n[GIET ERROR] in _ioc_get_status : illegal channel\n");
    463         _tty_release_lock( 0 );
    464 
    465         return 1;
    466     }
    467 
    468     // get IOC base address
    469     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
    470     *status = ioc_address[BLOCK_DEVICE_STATUS];
    471 
    472     return 0;
     363#if   USE_BDV
     364    return _bdv_get_status(channel, status);
     365#elif USE_SPI
     366    return _sdc_get_status(channel, status);
     367#elif USE_HBA
     368    return _hba_get_status(channel, status);
     369#endif
    473370}
    474371
     
    479376unsigned int _ioc_get_block_size()
    480377{
    481     // get IOC base address
    482     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
    483    
    484     return  ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
     378#if   USE_BDV
     379    return _bdv_get_block_size();
     380#elif USE_SPI
     381    return _sdc_get_block_size();
     382#elif USE_HBA
     383    return _hba_get_block_size();
     384#endif
    485385}
    486386
Note: See TracChangeset for help on using the changeset viewer.