Ignore:
Timestamp:
Mar 26, 2014, 6:44:44 PM (10 years ago)
Author:
alain
Message:

Introducing a major release, to suppoort the tsar_generic_leti platform
and the various (external or internal) peripherals configurations.
The map.xml format has been modified, in order to support the new
vci_iopic componentand a new policy for peripherals initialisation.
The IRQs are nom described in the XICU and IOPIC components
(and not anymore in the processors).
To enforce this major change, the map.xml file signature changed:
The signature value must be: 0xDACE2014

This new release has been tested on the tsar_generic_leti platform
for the following mappings:

  • 4c_4p_sort_leti
  • 4c_4p_sort_leti_ext
  • 4c_4p_transpose_leti
  • 4c_4p_transpose_leti_ext
  • 4c_1p_four_leti_ext
File:
1 edited

Legend:

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

    r289 r295  
    1010// a single channel, block oriented, external storage contrÃŽler.
    1111//
    12 // It can exist only one block-device controler in the architecture.
    13 //
    14 // The _bdv_read() and _bdv_write() functions use the _bdv_access() function,
    15 // that is always blocking, but can be called in 4 modes:
    16 //
    17 // - In BOOT_PA mode, the _bdv_access() function uses a polling policy on the
    18 //   IOC_STATUS register to detect transfer completion, as hardware interrupts
    19 //   are not activated. This mode is used by the boot code to load the map.bin
    20 //   file into memory.
    21 //
    22 // - In BOOT_VA mode, the _bdv_access() function uses a polling policy on
    23 //   IOC_STATUS register to detect transfer completion. This mode is used by
    24 //   the boot code to load the various .elf files into memory.
    25 //
    26 // - In KERNEL mode, the _bdv_access() function uses a descheduling strategy:
     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:
    2721//   The ISR executed when transfer completes should restart the calling task.
    28 //   There is no checking of user access right to the memory buffer. This mode
    29 //   must be used to access IOC, for an "open" system call.
    30 //
    31 // - In USER mode, the _bdv_access() function uses a descheduling strategy:
     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:
    3226//   The ISR executed when transfer completes should restart the calling task,
    3327//   The user access right to the memory buffer must be checked.
    34 //   This mode must be used to access IOC, for a "read/write" system call.
     28//   This mode must be used for a "read/write" system call.
    3529//
    3630// As the BDV component can be used by several programs running in parallel,
    37 // the _ioc_lock variable guaranties exclusive access to the device.  The
     31// the _bdv_lock variable guaranties exclusive access to the device.  The
    3832// _bdv_read() and _bdv_write() functions use atomic LL/SC to get the lock.
    3933//
     
    4741//   if the IOMMU is not activated.
    4842// An error code is returned if these conditions are not verified.
    49 ///////////////////////////////////////////////////////////////////////////////////
    50 // The seg_ioc_base virtual base addresses must be defined in giet_vsegs.ld file.
     43//
     44// The "seg_ioc_base" must be defined in giet_vsegs.ld file.
     45///////////////////////////////////////////////////////////////////////////////////
     46// Implementation notes:
     47//
     48// 1. In order to share code, the two _bdv_read() and _bdv_write() functions
     49//    call the same _bdv_access() function.
     50//
     51// 2. All accesses to BDV registers are done by the two
     52//    _bdv_set_register() and _bdv_get_register() low-level functions,
     53//    that are handling virtual / physical extended addressing.
    5154///////////////////////////////////////////////////////////////////////////////////
    5255
    5356#include <giet_config.h>
     57#include <bdv_driver.h>
     58#include <xcu_driver.h>
    5459#include <ioc_driver.h>
    55 #include <bdv_driver.h>
    5660#include <utils.h>
    5761#include <tty_driver.h>
     
    5963
    6064///////////////////////////////////////////////////////////////////////////////
    61 //      _bdv_access()
     65// BDV global variables
     66///////////////////////////////////////////////////////////////////////////////
     67
     68#define in_unckdata __attribute__((section (".unckdata")))
     69
     70in_unckdata unsigned int          _bdv_lock = 0;
     71in_unckdata volatile unsigned int _bdv_status = 0;
     72in_unckdata volatile unsigned int _bdv_gtid;
     73
     74///////////////////////////////////////////////////////////////////////////////
     75// This low_level function returns the value contained in register (index).
     76///////////////////////////////////////////////////////////////////////////////
     77unsigned int _bdv_get_register( unsigned int index )
     78{
     79    unsigned int* vaddr = (unsigned int*)&seg_ioc_base + index;
     80    return _io_extended_read( vaddr );
     81}
     82
     83///////////////////////////////////////////////////////////////////////////////
     84// This low-level function set a new value in register (index).
     85///////////////////////////////////////////////////////////////////////////////
     86void _bdv_set_register( unsigned int index,
     87                        unsigned int value )
     88{
     89    unsigned int* vaddr = (unsigned int*)&seg_ioc_base + index;
     90    _io_extended_write( vaddr, value );
     91}
     92
     93///////////////////////////////////////////////////////////////////////////////
    6294// This function transfer data between a memory buffer and the block device.
    6395// The buffer lentgth is (count*block_size) bytes.
     
    70102// Returns 0 if success, > 0 if error.
    71103///////////////////////////////////////////////////////////////////////////////
    72 static unsigned int _bdv_access( unsigned int to_mem,
    73                                  unsigned int mode,
    74                                  unsigned int lba,
    75                                  paddr_t buf_paddr,
    76                                  unsigned int count)
    77 {
    78 
    79 #if GIET_DEBUG_IOC_DRIVER
    80 _tty_get_lock( 0 );
    81 _puts("\n[IOC DEBUG] Enter _bdv_access() at cycle ");
    82 _putd( _get_proctime() );
    83 _puts(" for processor ");
    84 _putd( _get_procid() );
    85 _puts("\n - mode    = ");
    86 _putd( mode );
    87 _puts("\n - paddr   = ");
    88 _putx( buf_paddr );
    89 _puts("\n - sectors = ");
    90 _putd( count );
    91 _puts("\n - lba     = ");
    92 _putx( lba );
    93 _puts("\n");
    94 _tty_release_lock( 0 );
     104static unsigned int _bdv_access( unsigned int       to_mem,
     105                                 unsigned int       mode,
     106                                 unsigned int       lba,
     107                                 unsigned long long buf_paddr,
     108                                 unsigned int       count)
     109{
     110
     111#if GIET_DEBUG_BDV_DRIVER
     112unsigned int procid  = _get_procid();
     113unsigned int cxy     = procid / NB_PROCS_MAX;
     114unsigned int lpid    = procid % NB_PROCS_MAX;
     115unsigned int x       = cxy >> Y_WIDTH;
     116unsigned int y       = cxy & ((1<<Y_WIDTH) - 1);
     117
     118_printf("\n[BDV DEBUG] Processor[%d,%d,%d] enters _bdv_access() at cycle %d\n"
     119        " - mode    = %d\n"
     120        " - paddr   = %l\n"
     121        " - sectors = %x\n"
     122        " - lba     = %x\n",
     123        x, y, lpid, _get_proctime(), mode, buf_paddr, count, lba );
    95124#endif
    96125
    97     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;
    98     unsigned int error = 0;
    99 
    100     // get the lock protecting IOC
    101     _get_lock(&_ioc_lock);
    102 
    103     // set the _ioc_status polling variable
    104     _ioc_status = BLOCK_DEVICE_BUSY;
    105 
    106     ioc_address[BLOCK_DEVICE_BUFFER]     = (unsigned int)buf_paddr;
    107     ioc_address[BLOCK_DEVICE_BUFFER_EXT] = (unsigned int)(buf_paddr>>32);
    108     ioc_address[BLOCK_DEVICE_COUNT]      = count;
    109     ioc_address[BLOCK_DEVICE_LBA]        = lba;
    110 
    111     // There are two policies for transfer completion
    112         // detection, depending on the mode argument:
    113 
    114     if ( (mode == IOC_BOOT_PA_MODE) ||    // We poll directly the IOC_STATUS register
    115          (mode == IOC_BOOT_VA_MODE) )     // as IRQs are masked.
     126    unsigned int       error = 0;
     127
     128    // get the lock protecting BDV
     129    _get_lock(&_bdv_lock);
     130
     131    // set device registers
     132    _bdv_set_register( BLOCK_DEVICE_BUFFER    , (unsigned int)buf_paddr );
     133    _bdv_set_register( BLOCK_DEVICE_BUFFER_EXT, (unsigned int)(buf_paddr>>32) );
     134    _bdv_set_register( BLOCK_DEVICE_COUNT     , count );
     135    _bdv_set_register( BLOCK_DEVICE_LBA       , lba );
     136
     137    // In BOOT mode, we launch transfer, and poll the BDV_STATUS
     138    // register because IRQs are masked.
     139    if ( mode == IOC_BOOT_MODE )
    116140    {
    117141        // Launch transfert
    118         if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
    119         else             ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
     142        if (to_mem == 0) _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_WRITE );
     143        else             _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_READ );
    120144
    121145        unsigned int status;
    122146        do
    123147        {
    124             if ( _bdv_get_status( 0, &status ) ) return 1;
    125 
    126 #if GIET_DEBUG_IOC_DRIVER
    127 _tty_get_lock( 0 );
    128 _puts("\n[IOC DEBUG] _bdv_access() : ... waiting on IOC_STATUS register ...\n");
    129 _tty_release_lock( 0 );
     148            status = _bdv_get_register( BLOCK_DEVICE_STATUS );
     149
     150#if GIET_DEBUG_BDV_DRIVER
     151_printf("\n[BDV DEBUG] _bdv_access() : ... waiting on BDV_STATUS register ...\n");
    130152#endif
    131153        }
     
    133155               (status != BLOCK_DEVICE_READ_ERROR)    &&
    134156               (status != BLOCK_DEVICE_WRITE_SUCCESS) &&
    135                (status != BLOCK_DEVICE_WRITE_ERROR)   );
     157               (status != BLOCK_DEVICE_WRITE_ERROR)   );      // busy waiting
    136158
    137159        // analyse status
     
    140162
    141163        // release lock
    142         _release_lock(&_ioc_lock);     
     164        _release_lock(&_bdv_lock);     
    143165    }
    144     else                           // in USER or KERNEL mode, we deschedule the task.
    145                                    // When the task is rescheduled by the ISR, we reset
    146                                    // the _ioc_status variable, and release the lock
     166    // in USER or KERNEL mode, we deschedule the task.
     167    // When the task is rescheduled, we check the _bdv_status variable,
     168    // and release the lock.
     169    // We need a critical section, because we must reset the RUN bit
     170        // before to launch the transfer, and we don't want to be descheduled
     171        // between these two operations.
     172    else
    147173    {
    148         // We need a critical section, because we must reset the RUN bit
    149                 // before to launch the transfer, and we want to avoid to be descheduled
    150                 // between these two operations.
    151 
    152         // Enter critical section
    153         _it_disable();
     174        unsigned int save_sr;
     175        unsigned int ltid = _get_current_task_id();
     176        unsigned int gpid = _get_procid();
     177
     178        // activates BDV interrupts
     179        _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 1 );
     180
     181        // set the _bdv_status variable
     182        _bdv_status = BLOCK_DEVICE_BUSY;
     183
     184        // enters critical section
     185        _it_disable( &save_sr );
    154186       
    155         // set _ioc_gtid and reset runnable
    156         unsigned int ltid = _get_proc_task_id();
    157         unsigned int pid = _get_procid();
    158         _ioc_gtid = (pid<<16) + ltid;
    159         _set_task_slot( pid, ltid, CTX_RUN_ID, 0 ); 
     187        // set _bdv_gtid and reset runnable
     188        _bdv_gtid = (gpid<<16) + ltid;
     189        _set_task_slot( gpid, ltid, CTX_RUN_ID, 0 ); 
    160190       
    161         // Launch transfert
    162         if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
    163         else             ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
     191        // launch transfer
     192        if (to_mem == 0) _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_WRITE );
     193        else             _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_READ  );
    164194
    165195        // deschedule task
    166196        _ctx_switch();                     
    167197
     198        // restore SR
     199        _it_restore( &save_sr );
     200
    168201        // analyse status
    169         error = ( (_ioc_status == BLOCK_DEVICE_READ_ERROR) ||
    170                   (_ioc_status == BLOCK_DEVICE_WRITE_ERROR) );
    171 
    172         // reset _ioc_status and release lock
    173         _ioc_status = BLOCK_DEVICE_IDLE;
    174         _release_lock(&_ioc_lock);     
     202        error = ( (_bdv_status == BLOCK_DEVICE_READ_ERROR) ||
     203                  (_bdv_status == BLOCK_DEVICE_WRITE_ERROR) );
     204
     205        // reset _bdv_status and release lock
     206        _bdv_status = BLOCK_DEVICE_IDLE;
     207        _release_lock(&_bdv_lock);     
    175208    }
    176209
    177 #if GIET_DEBUG_IOC_DRIVER
    178 _tty_get_lock( 0 );
    179 _puts("\n[IOC DEBUG] _bdv_access completed at cycle ");
    180 _putd( _get_proctime() );
    181 _puts(" for processor ");
    182 _putd( _get_procid() );
    183 _puts(" : error = ");
    184 _putd( (unsigned int)error );
    185 _puts("\n");
    186 _tty_release_lock( 0 );
     210#if GIET_DEBUG_BDV_DRIVER
     211_printf("\n[BDV DEBUG] Processor[%d,%d,%d] exit _bdv_access() at cycle %d\n",
     212        x, y, lpid, _get_proctime() );
    187213#endif
    188214
     
    191217
    192218///////////////////////////////////////////////////////////////////////////////
    193 //       _bdv_init()
    194 // This function cheks block size, and activates the IOC interrupts.
     219// This function cheks block size, and desactivates the interrupts.
    195220// Return 0 for success, > 0 if error
    196221///////////////////////////////////////////////////////////////////////////////
    197 unsigned int _bdv_init( unsigned int channel )
    198 {
    199     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;
    200    
    201     if ( ioc_address[BLOCK_DEVICE_BLOCK_SIZE] != 512 )
     222unsigned int _bdv_init()
     223{
     224    if ( _bdv_get_register( BLOCK_DEVICE_BLOCK_SIZE ) != 512 )
    202225    {
    203         _tty_get_lock( 0 );
    204         _puts("\n[GIET ERROR] in _bdv_init() : block size must be 512 bytes\n");
    205         _tty_release_lock( 0 );
     226        _printf("\n[GIET ERROR] in _bdv_init() : block size must be 512 bytes\n");
    206227        return 1;
    207228    }
    208229
    209     if ( channel != 0 )
    210     {
    211         _tty_get_lock( 0 );
    212         _puts("\n[GIET ERROR] in _bdv_init() : illegal channel\n");
    213         _tty_release_lock( 0 );
    214 
    215         return 1;
    216     }
    217 
    218     ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
     230    _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 0 );
    219231    return 0;
    220232}
    221233
    222234///////////////////////////////////////////////////////////////////////////////
    223 //     _bdv_read()
    224235// Transfer data from the block device to a memory buffer.
    225236// - mode     : BOOT / KERNEL / USER
     
    229240// Returns 0 if success, > 0 if error.
    230241///////////////////////////////////////////////////////////////////////////////
    231 unsigned int _bdv_read( unsigned int mode, 
    232                         unsigned int lba,
    233                         paddr_t      buffer,
    234                         unsigned int count)
     242unsigned int _bdv_read( unsigned int       mode, 
     243                        unsigned int       lba,
     244                        unsigned long long buffer,
     245                        unsigned int       count)
    235246{
    236247    return _bdv_access( 1,        // read access
     
    242253
    243254///////////////////////////////////////////////////////////////////////////////
    244 //     _bdv_write()
    245255// Transfer data from a memory buffer to the block device.
    246256// - mode     : BOOT / KERNEL / USER
     
    250260// Returns 0 if success, > 0 if error.
    251261///////////////////////////////////////////////////////////////////////////////
    252 unsigned int _bdv_write( unsigned int mode, 
    253                          unsigned int lba,
    254                          paddr_t buffer,
    255                          unsigned int count )
     262unsigned int _bdv_write( unsigned int       mode, 
     263                         unsigned int       lba,
     264                         unsigned long long buffer,
     265                         unsigned int       count )
    256266{
    257267    return _bdv_access( 0,        // write access
     
    263273
    264274///////////////////////////////////////////////////////////////////////////////
    265 //     _bdv_get_status()
    266 // This function returns in the status variable, the transfert status, and
    267 // acknowledge the IRQ if the IOC controler is not busy.
    268 // Returns 0 if success, > 0 if error
    269 ///////////////////////////////////////////////////////////////////////////////
    270 unsigned int _bdv_get_status( unsigned int  channel,
    271                               unsigned int* status )
    272 {
    273     if ( channel != 0 )
    274     {
    275         _tty_get_lock( 0 );
    276         _puts("\n[GIET ERROR] in _bdv_get_status() : illegal channel\n");
    277         _tty_release_lock( 0 );
    278 
    279         return 1;
    280     }
    281 
    282     // get IOC base address
    283     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
    284     *status = ioc_address[BLOCK_DEVICE_STATUS];
    285 
    286     return 0;
    287 }
    288 
    289 ///////////////////////////////////////////////////////////////////////////////
    290 //     _bdv_get_block_size()
    291 // This function returns the block_size with which the IOC has been configured.
    292 ///////////////////////////////////////////////////////////////////////////////
    293 unsigned int _bdv_get_block_size()
    294 {
    295     // get IOC base address
    296     volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
    297    
    298     return  ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
     275// Returns device status.
     276///////////////////////////////////////////////////////////////////////////////
     277unsigned int _bdv_get_status()
     278{
     279    return _bdv_get_register( BLOCK_DEVICE_STATUS );
     280}
     281
     282///////////////////////////////////////////////////////////////////////////////
     283// Returns block size.
     284///////////////////////////////////////////////////////////////////////////////
     285unsigned int _bdv_get_block_size()
     286{
     287    return _bdv_get_register( BLOCK_DEVICE_BLOCK_SIZE );
     288}
     289
     290///////////////////////////////////////////////////////////////////////////////////
     291// This ISR save the status, acknowledge the IRQ,
     292// and activates the task waiting on IO transfer.
     293// It can be an HWI or a SWI.
     294//
     295// TODO the _set_task_slot access should be replaced by an atomic LL/SC
     296//      when the CTX_RUN bool will be replaced by a bit_vector.
     297///////////////////////////////////////////////////////////////////////////////////
     298void _bdv_isr( unsigned int irq_type,   // HWI / WTI
     299               unsigned int irq_id,     // index returned by ICU
     300               unsigned int channel )   // unused
     301{
     302    unsigned int procid     = _get_procid();
     303    unsigned int cluster_xy = procid / NB_PROCS_MAX;
     304    unsigned int lpid       = procid % NB_PROCS_MAX;
     305
     306    // acknowledge WTI in local XCU if required
     307    unsigned int value;
     308    if ( irq_type == IRQ_TYPE_WTI ) _xcu_get_wti_value( cluster_xy, irq_id, &value );
     309
     310    // save status in _bdv_status variable and reset IRQ
     311    _bdv_status = _bdv_get_register( BLOCK_DEVICE_STATUS );
     312
     313    // identify task waiting on BDV
     314    unsigned int rprocid    = _bdv_gtid>>16;
     315    unsigned int ltid       = _bdv_gtid & 0xFFFF;
     316    unsigned int remote_xy  = rprocid / NB_PROCS_MAX;
     317
     318#if GIET_DEBUG_IRQS  // we don't take the TTY lock to avoid deadlock
     319unsigned int x              = cluster_xy >> Y_WIDTH;
     320unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
     321unsigned int rx             = remote_xy >> Y_WIDTH;
     322unsigned int ry             = remote_xy & ((1<<Y_WIDTH)-1);
     323unsigned int rlpid          = rprocid % NB_PROCS_MAX;
     324_puts("\n[IRQS DEBUG] Processor[");
     325_putd(x );
     326_puts(",");
     327_putd(y );
     328_puts(",");
     329_putd(lpid );
     330_puts("] enters _bdv_isr() at cycle ");
     331_putd(_get_proctime() );
     332_puts("\n  for task ");
     333_putd(ltid );
     334_puts(" running on processor[");
     335_putd(rx );
     336_puts(",");
     337_putd(ry );
     338_puts(",");
     339_putd(rlpid );
     340_puts(" / bdv status = ");
     341_putx(_bdv_status );
     342_puts("\n");
     343#endif
     344
     345    // re-activates sleeping task
     346    _set_task_slot( rprocid,     // global processor index
     347                    ltid,        // local task index on processor
     348                    CTX_RUN_ID,  // CTX_RUN slot
     349                    1 );         // running
     350
     351    // requires a context switch for remote processor running the waiting task
     352    _xcu_send_wti( remote_xy,    // cluster index
     353                   lpid,         // local processor index
     354                   0 );          // don't force context switch if not idle
    299355}
    300356
Note: See TracChangeset for help on using the changeset viewer.