Ignore:
Timestamp:
Mar 26, 2014, 6:44:44 PM (11 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
Location:
soft/giet_vm/giet_drivers
Files:
22 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
  • soft/giet_vm/giet_drivers/bdv_driver.h

    r289 r295  
    77///////////////////////////////////////////////////////////////////////////////////
    88
    9 #ifndef _GIET_BDV_DRIVERS_H_
    10 #define _GIET_BDV_DRIVERS_H_
    11 
    12 #include <mapping_info.h>
     9#ifndef _GIET_BDV_DRIVER_H_
     10#define _GIET_BDV_DRIVER_H_
    1311
    1412///////////////////////////////////////////////////////////////////////////////////
    15 // BDV access functions and variables (vci_block_device)
     13// BDV global variables
    1614///////////////////////////////////////////////////////////////////////////////////
    1715
    18 extern unsigned int _bdv_init( unsigned int channel );
     16extern unsigned int          _bdv_lock;    // BDV is a shared ressource
     17extern volatile unsigned int _bdv_status;  // required for IRQ signaling
     18extern volatile unsigned int _bdv_gtid;    // descheduled task id = gpid<<16 + ltid
    1919
    20 extern unsigned int _bdv_write( unsigned int mode,
    21                                 unsigned int lba,
    22                                 paddr_t      buffer,
    23                                 unsigned int count );
     20///////////////////////////////////////////////////////////////////////////////////
     21// BDV registers, operations and status values
     22///////////////////////////////////////////////////////////////////////////////////
    2423
    25 extern unsigned int _bdv_read(  unsigned int mode,
    26                                 unsigned int lba,
    27                                 paddr_t      buffer,
    28                                 unsigned int count );
     24enum BDV_registers
     25{
     26    BLOCK_DEVICE_BUFFER,
     27    BLOCK_DEVICE_LBA,
     28    BLOCK_DEVICE_COUNT,
     29    BLOCK_DEVICE_OP,
     30    BLOCK_DEVICE_STATUS,
     31    BLOCK_DEVICE_IRQ_ENABLE,
     32    BLOCK_DEVICE_SIZE,
     33    BLOCK_DEVICE_BLOCK_SIZE,
     34    BLOCK_DEVICE_BUFFER_EXT,
     35};
    2936
    30 extern unsigned int _bdv_get_status( unsigned int  channel,
    31                                      unsigned int* status );
     37enum BDV_operations
     38{
     39    BLOCK_DEVICE_NOOP,
     40    BLOCK_DEVICE_READ,
     41    BLOCK_DEVICE_WRITE,
     42};
     43
     44enum BDV_status
     45{
     46    BLOCK_DEVICE_IDLE,
     47    BLOCK_DEVICE_BUSY,
     48    BLOCK_DEVICE_READ_SUCCESS,
     49    BLOCK_DEVICE_WRITE_SUCCESS,
     50    BLOCK_DEVICE_READ_ERROR,
     51    BLOCK_DEVICE_WRITE_ERROR,
     52    BLOCK_DEVICE_ERROR,
     53};
     54
     55///////////////////////////////////////////////////////////////////////////////////
     56// BDV access functions (vci_block_device)
     57///////////////////////////////////////////////////////////////////////////////////
     58
     59extern unsigned int _bdv_init();
     60
     61extern unsigned int _bdv_write( unsigned int       mode,
     62                                unsigned int       lba,
     63                                unsigned long long buffer,
     64                                unsigned int       count );
     65
     66extern unsigned int _bdv_read(  unsigned int       mode,
     67                                unsigned int       lba,
     68                                unsigned long long buffer,
     69                                unsigned int       count );
     70
     71extern unsigned int _bdv_get_status();
    3272
    3373extern unsigned int _bdv_get_block_size();
     74
     75extern void _bdv_isr( unsigned irq_type,
     76                      unsigned irq_id,
     77                      unsigned channel );
    3478
    3579///////////////////////////////////////////////////////////////////////////////////
  • soft/giet_vm/giet_drivers/cma_driver.h

    r258 r295  
    2929};
    3030
     31///////////////////////////////////////////////////////////////////////////////////
     32// CMA (vci_chbuf_dma) low-level access functions
     33///////////////////////////////////////////////////////////////////////////////////
     34
     35extern unsigned int _cma_get_register( unsigned int channel,
     36                                       unsigned int index );
     37
     38extern void _cma_set_register( unsigned int channel,
     39                               unsigned int index,
     40                               unsigned int value );
     41
     42extern void _cma_isr( unsigned int irq_type,
     43                      unsigned int irq_id,
     44                      unsigned int channel );
     45
     46///////////////////////////////////////////////////////////////////////////////////
     47
    3148#endif
    3249
  • soft/giet_vm/giet_drivers/dma_driver.c

    r267 r295  
    196196    unsigned int procid    = _get_procid();
    197197    unsigned int cluster_xy = procid/NB_PROCS_MAX;
     198    unsigned int x          = cluster_xy >> Y_WIDTH;
     199    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
    198200    unsigned int channel_id = procid%NB_PROCS_MAX;
    199201
     
    203205
    204206#if GIET_DEBUG_DMA_DRIVER
    205 _tty_get_lock( 0 );
    206 _puts("\n[DMA DEBUG] Enter _dma_copy() at cycle ");
    207 _putd( _get_proctime() );
    208 _puts("\n - vspace_id  = ");
    209 _putx( vspace_id );
    210 _puts("\n - cluster_xy = ");
    211 _putx( cluster_xy );
    212 _puts("\n - channel_id = ");
    213 _putx( channel_id );
    214 _puts("\n - dest       = ");
    215 _putx( (unsigned int)dest );
    216 _puts("\n - source     = ");
    217 _putx( (unsigned int)source );
    218 _puts("\n - bytes      = ");
    219 _putd( size );
    220 _tty_release_lock( 0 );
     207unsigned int x          = cluster_xy >> Y_WIDTH;
     208unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     209
     210_printf("\n[DMA DEBUG] Processor[%d,%d,%d] enters _dma_copy() at cycle %d\n"
     211        " - vspace_id  = %d\n"
     212        " - cluster_xy = %x\n"
     213        " - channel_id = %d\n"
     214        " - dest       = %x\n"
     215        " - source     = %x\n"
     216        " - bytes      = %x\n",
     217        x, y, channel_id, _get_proctime(), vspace_id, cluster_xy,
     218        (unsigned int)dest, (unsigned int)source, size );
    221219#endif
    222220
     
    226224         (size & 0x3) )
    227225    {
    228         _tty_get_lock( 0 );
    229         _puts("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n");
    230         _tty_release_lock( 0 );
     226        _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n");
    231227        _exit();
    232228    }
     
    242238    if ( ko )
    243239    {
    244         _tty_get_lock( 0 );
    245         _puts("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n");
    246         _tty_release_lock( 0 );
     240        _printf("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n");
    247241        _exit();
    248242    }
     
    257251    if ( ko )
    258252    {
    259         _tty_get_lock( 0 );
    260         _puts("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n");
    261         _tty_release_lock( 0 );
     253        _printf("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n");
    262254        _exit();
    263255    }
     
    266258
    267259#if GIET_DEBUG_DMA_DRIVER
    268 _tty_get_lock( 0 );
    269 _puts("\n - src_paddr  = ");
    270 _putl( src_paddr );
    271 _puts("\n - dst_paddr  = ");
    272 _putl( dst_paddr );
    273 _puts("\n");
    274 _tty_release_lock( 0 );
     260_printf(" - src_paddr  = %llx\n"
     261        " - dst_paddr  = %llx\n",
     262        src_paddr, dst_paddr );
    275263#endif
    276264
     
    282270    if ( ko )
    283271    {
    284         _tty_get_lock( 0 );
    285         _puts("\n[GIET ERROR] in _dma_copy() : cannot start transfer\n");
    286         _tty_release_lock( 0 );
     272        _printf("\n[GIET ERROR] in _dma_copy() : cannot start transfer\n");
    287273        _exit();
    288274    }
     
    297283
    298284#if GIET_DEBUG_DMA_DRIVER
    299 _tty_get_lock( 0 );
    300 _puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register ...\n");
    301 _tty_release_lock( 0 );
     285_printf("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register ...\n");
    302286#endif
    303287
     
    307291    if( status != DMA_SUCCESS )
    308292    {
    309         _tty_get_lock( 0 );
    310         _puts("\n[GIET ERROR] in _dma_copy() : DMA_STATUS error = ");
    311         _putd( status );
    312         _puts("\n");
    313         _tty_release_lock( 0 );
     293        _printf("\n[GIET ERROR] in _dma_copy() : DMA_STATUS = %x\n", status );
    314294        _exit();
    315295    }
     
    318298
    319299#if GIET_DEBUG_DMA_DRIVER
    320 _tty_get_lock( 0 );
    321 _puts("\n[DMA DEBUG] _dma_copy() completed at cycle ");
    322 _putd( _get_proctime() );
    323 _puts("\n");
    324 _tty_release_lock( 0 );
     300_printf("\n[DMA DEBUG] _dma_copy() completed at cycle %d\n", _get_proctime() );
    325301#endif
    326302
    327303#else // NB_DMA_CHANNELS == 0
    328     _tty_get_lock( 0 );
    329     _puts("\n[GIET ERROR] in _dma_copy() : NB_DMA_CHANNELS = 0 !\n");
    330     _tty_release_lock( 0 );
     304    _printf("\n[GIET ERROR] in _dma_copy() : NB_DMA_CHANNELS = 0 !\n");
    331305    _exit();
    332306#endif
  • soft/giet_vm/giet_drivers/fbf_driver.c

    r275 r295  
    77// The fbf_driver.c and fbf_driver.h files are part ot the GIET-VM kernel.
    88// This driver supports the SoCLib vci_framebuffer component.
    9 //
    10 // It can exist only one frame buffer in the architecture.
    119//
    1210// There exist two methods to access the VciFrameBuffer device:
     
    5957                            unsigned int length)
    6058{
    61     char* fb_address = (char *)&seg_fbf_base + offset;
    62     _memcpy( fb_address, buffer, length);
     59    char* fbf_address = (char *)&seg_fbf_base + offset;
     60
     61    _memcpy( fbf_address, buffer, length);
     62
    6363    return 0;
    6464}
     
    7474                            unsigned int   length)
    7575{
    76     char* fb_address = (char *)&seg_fbf_base + offset;
    77     _memcpy( buffer, fb_address, length);
     76    char* fbf_address = (char *)&seg_fbf_base + offset;
     77
     78    _memcpy( buffer, fbf_address, length);
     79
    7880    return 0;
    7981}
     
    145147    if ( channel_id >= NB_CMA_CHANNELS )
    146148    {
    147         _tty_get_lock( 0 );
    148         _puts("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n");
    149         _tty_release_lock( 0 );
     149        _printf("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n");
    150150        return 1;
    151151    }
     
    154154    if ( sizeof(fb_cma_channel_t) != 32 )
    155155    {
    156         _tty_get_lock( 0 );
    157         _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n");
    158         _tty_release_lock( 0 );
     156        _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n");
    159157        return 1;
    160158    }
     
    163161    if ( (unsigned int)(&_fb_cma_channel[channel_id]) & 0x1F )
    164162    {
    165         _tty_get_lock( 0 );
    166         _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n");
    167         _tty_release_lock( 0 );
     163        _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n");
    168164        return 1;
    169165    }
     
    172168    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) )
    173169    {
    174         _tty_get_lock( 0 );
    175         _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n");
    176         _tty_release_lock( 0 );
     170        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n");
    177171        return 1;
    178172    }
     
    189183    if (ko)
    190184    {
    191         _tty_get_lock( 0 );
    192         _puts("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n");
    193         _tty_release_lock( 0 );
     185        _printf("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n");
    194186        return 1;
    195187    }
     
    204196    if (ko)
    205197    {
    206         _tty_get_lock( 0 );
    207         _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n");
    208         _tty_release_lock( 0 );
     198        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n");
    209199        return 1;
    210200    }
    211201    if ((flags & PTE_U) == 0)
    212202    {
    213         _tty_get_lock( 0 );
    214         _puts("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n");
    215         _tty_release_lock( 0 );
     203        _printf("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n");
    216204        return 1;
    217205    }
     
    226214    if (ko)
    227215    {
    228         _tty_get_lock( 0 );
    229         _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n");
    230         _tty_release_lock( 0 );
     216        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n");
    231217        return 1;
    232218    }
    233219    if ((flags & PTE_U) == 0)
    234220    {
    235         _tty_get_lock( 0 );
    236         _puts("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n");
    237         _tty_release_lock( 0 );
     221        _printf("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n");
    238222        return 1;
    239223    }
     
    251235    if (ko)
    252236    {
    253         _tty_get_lock( 0 );
    254         _puts("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n");
    255         _tty_release_lock( 0 );
     237        _printf("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n");
    256238        return 1;
    257239    }
     
    262244
    263245#if GIET_DEBUG_FBF_DRIVER
    264 _tty_get_lock( 0 );
    265 _puts("\n[CMA DEBUG] fb_cma_init()");
    266 _puts("\n - fbf       pbase = ");
    267 _putl( _fb_cma_channel[channel_id].fbf );
    268 _puts("\n - buf0      pbase = ");
    269 _putl( _fb_cma_channel[channel_id].buf0 );
    270 _puts("\n - buf1      pbase = ");
    271 _putl( _fb_cma_channel[channel_id].buf1 );
    272 _puts("\n - channel   pbase = ");
    273 _putl( _fb_cma_desc_paddr[channel_id] );
    274 _puts("\n");
    275 _tty_release_lock( 0 );
     246_printf("\n[CMA DEBUG] enters _fb_cma_init()\n"
     247        " - fbf       pbase = %l\n"
     248        " - buf0      pbase = %l\n"
     249        " - buf1      pbase = %l\n"
     250        " - channel   pbase = %l\n"
     251        _fb_cma_channel[channel_id].fbf,
     252        _fb_cma_channel[channel_id].buf0,
     253        _fb_cma_channel[channel_id].buf1,
     254        _fb_cma_desc_paddr[channel_id] );
    276255#endif
    277256
     
    283262
    284263    // CMA channel activation
    285     unsigned int* cma_vbase = (unsigned int *)&seg_cma_base;
    286     unsigned int  offset    = channel_id * CHBUF_CHANNEL_SPAN;
    287 
    288     cma_vbase[offset + CHBUF_SRC_DESC]  = (unsigned int)(desc_paddr & 0xFFFFFFFF);
    289     cma_vbase[offset + CHBUF_SRC_EXT]   = (unsigned int)(desc_paddr >> 32);
    290     cma_vbase[offset + CHBUF_SRC_NBUFS] = 2;
    291     cma_vbase[offset + CHBUF_DST_DESC]  = (unsigned int)(desc_paddr & 0xFFFFFFFF) + 16;
    292     cma_vbase[offset + CHBUF_DST_EXT]   = (unsigned int)(desc_paddr >> 32);
    293     cma_vbase[offset + CHBUF_DST_NBUFS] = 1;
    294     cma_vbase[offset + CHBUF_BUF_SIZE]  = length;
    295     cma_vbase[offset + CHBUF_PERIOD]    = 300;
    296     cma_vbase[offset + CHBUF_RUN]       = 1;
    297 
     264    _cma_set_register( channel_id, CHBUF_SRC_DESC , (unsigned int)(desc_paddr & 0xFFFFFFFF) );
     265    _cma_set_register( channel_id, CHBUF_SRC_EXT  , (unsigned int)(desc_paddr >> 32) );
     266    _cma_set_register( channel_id, CHBUF_SRC_NBUFS, 2 );
     267    _cma_set_register( channel_id, CHBUF_DST_DESC , (unsigned int)(desc_paddr & 0xFFFFFFFF) + 16 );
     268    _cma_set_register( channel_id, CHBUF_DST_EXT  , (unsigned int)(desc_paddr >> 32) );
     269    _cma_set_register( channel_id, CHBUF_DST_NBUFS, 1 );
     270    _cma_set_register( channel_id, CHBUF_BUF_SIZE , length );
     271    _cma_set_register( channel_id, CHBUF_PERIOD   , 300 );
     272    _cma_set_register( channel_id, CHBUF_RUN      , 1 );
    298273    return 0;
    299274
    300275#else
    301 
    302     _tty_get_lock( 0 );
    303     _puts("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n");
    304     _tty_release_lock( 0 );
    305 
     276    _printf("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n");
    306277    return 1;
    307278#endif
    308279}
     280
    309281////////////////////////////////////////////////////////////////////////////////////
    310282// _fb_cma_write()
     
    330302
    331303    volatile paddr_t buf_paddr;
    332     unsigned int     buf_length;
    333304    unsigned int     full = 1;
    334305
     
    339310
    340311#if GIET_DEBUG_FBF_DRIVER
    341 _tty_get_lock( 0 );
    342 _puts("\n[CMA DEBUG] fb_cma_write() for CMA channel ");
    343 _putd( channel_id );
    344 _puts(" / buf_id = ");
    345 _putd( buffer_id );
    346 _puts("\n");
    347 _tty_release_lock( 0 );
     312_printf("\n[CMA DEBUG] _fb_cma_write() for CMA channel %d / bufid = %d at cycle %d\n",
     313        channel_id, buffer_id, _get_proctime() );
    348314#endif
    349315
     
    357323
    358324            // INVAL L1 cache for the channel descriptor,
    359             _dcache_buf_invalidate( &_fb_cma_channel[channel_id], 32 );
     325            _dcache_buf_invalidate( (void*)&_fb_cma_channel[channel_id], 32 );
    360326        }
    361327
     
    367333        count++;
    368334        if ( count == 10 ) _exit();
    369 
    370 #if GIET_DEBUG_FBF_DRIVER
    371 _tty_get_lock( 0 );
    372 _puts(" - buffer descriptor = ");
    373 _putl( buf_paddr );
    374 _puts(" at cycle ");
    375 _putd( _get_proctime() );
    376 _puts("\n");
    377 _tty_release_lock( 0 );
    378 #endif
    379 
    380335    }
    381336
     
    408363#else
    409364
    410     _tty_get_lock( 0 );
    411     _puts("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n");
    412     _tty_release_lock( 0 );
     365    _printf("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n");
    413366    return 1;
    414367
     
    427380    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
    428381
     382#if GIET_DEBUG_FBF_DRIVER
     383_printf("\n[CMA DEBUG] _fb_cma_stop() for CMA channel %d at cycle %d\n",
     384        channel_id, _get_proctime() );
     385#endif
     386
    429387    // CMA channel desactivation
    430     unsigned int* cma_vbase = (unsigned int *)&seg_cma_base;
    431     unsigned int  offset     = channel_id * CHBUF_CHANNEL_SPAN;
    432     cma_vbase[offset + CHBUF_RUN] = 0;
     388    _cma_set_register( channel_id, CHBUF_RUN, 0 );
     389
    433390    return 0;
    434391
    435392#else
    436393
    437     _tty_get_lock( 0 );
    438     _puts("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n");
    439     _tty_release_lock( 0 );
     394    _printf("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n");
    440395    return 1;
    441396
  • soft/giet_vm/giet_drivers/hba_driver.c

    r289 r295  
    22// File     : hba_driver.c
    33// Date     : 23/11/2013
    4 // Author   : alain greiner and zhang
     4// Author   : alain greiner
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
     
    99// block oriented, external storage contrÃŽler, respecting the AHCI standard.
    1010//
    11 // It can exist only one ahci-device controler in the architecture.
     11// The seg_ioc_base (standard HBA virtual base address) and seg_ioc_base_bis
     12// (backup HBA virtual base address) must be defined in giet_vsegs.ld file.
     13//////////////////////////////////////////////////////////////////////////////////
     14// Implementation notes:
    1215//
    13 // The _ioc_read() and _ioc_write() functions use the _ioc_access() function,
    14 // that is always blocking, but can be called in 4 modes:
     16// 1. In order to share code, the two _hba_read() and _hba_write() functions
     17//    call the same _hba_set_cmd() function.
    1518//
    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.
    21 //
    22 // - 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.
    26 //
    27 // - 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.
    32 //
    33 // - 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.
    42 //
    43 // The IOMMU can be activated or not:
    44 //
    45 // 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to
    46 // the IOC peripheral, in the I/O virtual space, and the user buffer is
    47 // dynamically remapped in the IOMMU page table. The corresponding entry
    48 // in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable.
    49 // The number of pages to be unmapped is stored in the _ioc_npages variable.
    50 // The number of PT2 entries is dynamically computed and stored in the
    51 // kernel _ioc_iommu_npages variable. It cannot be larger than 512.
    52 // The user buffer is unmapped by the _ioc_completed() function when
    53 // the transfer is completed.
    54 //
    55 // 2/ If the IOMMU is not used, we check that  the user buffer is mapped to a
    56 // contiguous physical buffer (this is generally true because the user space
    57 // page tables are statically constructed to use contiguous physical memory).
    58 //
    59 // Finally, the memory buffer must fulfill the following conditions:
    60 // - The buffer must be word aligned,
    61 // - The buffer must be mapped in user space for an user access,
    62 // - The buffer must be writable in case of (to_mem) access,
    63 // - The total number of physical pages occupied by the user buffer cannot
    64 //   be larger than 512 pages if the IOMMU is activated,
    65 // - All physical pages occupied by the user buffer must be contiguous
    66 //   if the IOMMU is not activated.
    67 // An error code is returned if these conditions are not verified.
    68 ///////////////////////////////////////////////////////////////////////////////////
    69 // The seg_ioc_base virtual base addresses must be defined in giet_vsegs.ld file.
     19// 2. All accesses to HBA registers are done by the two
     20//    _hba_set_register() and _hba_get_register() low-level functions,
     21//    that are handling virtual / physical extended addressing.
    7022///////////////////////////////////////////////////////////////////////////////////
    7123
     
    8032#include <vmem.h>
    8133
    82 #if !defined( NB_HBA_CHANNELS )
    83 # error: You must define NB_HBA_CHANNELS in the hard_config.h file
    84 #endif
    85 
    86 #if ( NB_HBA_CHANNELS > 8 )
    87 # error: NB_HBA_CHANNELS cannot be larger than 8
    88 #endif
    89 
    90 #if !defined( USE_IOB )
    91 # error: You must define USE_IOB in the hard_config.h file
    92 #endif
    93 
    94 #if !defined(GIET_USE_IOMMU)
    95 # error: You must define GIET_USE_IOMMU in the giet_config.h file
     34#if !defined( NB_IOC_CHANNELS )
     35# error: You must define NB_IOC_CHANNELS in the hard_config.h file
     36#endif
     37
     38#if ( NB_IOC_CHANNELS > 8 )
     39# error: NB_IOC_CHANNELS cannot be larger than 8
    9640#endif
    9741
     
    10347
    10448// command list array (one per channel)
    105 hba_cmd_list_t   hba_cmd_list[NB_HBA_CHANNELS] __attribute__((aligned(0x1000)));   
     49hba_cmd_list_t   hba_cmd_list[NB_IOC_CHANNELS] __attribute__((aligned(0x1000)));   
    10650
    10751// command tables array (32 command tables per channel)
    108 hba_cmd_table_t  hba_cmd_table[NB_HBA_CHANNELS][32] __attribute__((aligned(0x1000)));
     52hba_cmd_table_t  hba_cmd_table[NB_IOC_CHANNELS][32] __attribute__((aligned(0x1000)));
    10953
    11054// command list physical addresses array (one per channel)
    111 paddr_t          hba_cmd_list_paddr[NB_HBA_CHANNELS];
     55paddr_t          hba_cmd_list_paddr[NB_IOC_CHANNELS];
    11256
    11357// command tables physical addresses array (32 command tables per channel)
    114 paddr_t          hba_cmd_table_paddr[NB_HBA_CHANNELS][32];
     58paddr_t          hba_cmd_table_paddr[NB_IOC_CHANNELS][32];
    11559
    11660// command list pointer array (one per channel)
    117 unsigned int     hba_cmd_slot[NB_HBA_CHANNELS];
    118 
    119 //////////////////////////////////////////////////////////////////
    120 // This function returns the status of a given channel.
    121 // return 0 if success, >0 if error
    122 //////////////////////////////////////////////////////////////////
    123 unsigned int _hba_get_status( unsigned int   channel,
    124                               unsigned int*  status )
    125 {
    126     volatile unsigned int* hba_address;
    127     hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel);
    128 
    129     if( channel >= NB_HBA_CHANNELS )
    130     {
    131         _tty_get_lock( 0 );
    132         _puts("\n[GIET ERROR] in _hba_get_status() : illegal channel\n");
    133         _tty_release_lock( 0 );
    134         return 1;
    135     }
    136     else
    137     {
    138         *status = hba_address[HBA_PXIS];
    139         return 0;
    140     }
    141 }
    142 //////////////////////////////////////////////////////////////////
    143 // This function reset the status resgister for a given channel.
    144 // return 0 if success, >0 if error
    145 //////////////////////////////////////////////////////////////////
    146 unsigned int _hba_reset_status( unsigned int channel )
    147 {
    148     volatile unsigned int* hba_address;
    149     hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel);
    150 
    151     if( channel >= NB_HBA_CHANNELS )
    152     {   
    153         _tty_get_lock( 0 );
    154         _puts("\n[GIET ERROR] in _hba_reset_status() : illegal channel\n");
    155         _tty_release_lock( 0 );
    156         return 1;
    157     }
    158     else
    159     {
    160         hba_address[HBA_PXIS] = 0;
    161         return 0;
    162     }
    163 }
     61unsigned int     hba_cmd_slot[NB_IOC_CHANNELS];
     62
     63//////////////////////////////////////////////////////////////////////////////
     64// This low level function returns the value of register (channel / index)
     65//////////////////////////////////////////////////////////////////////////////
     66unsigned int _hba_get_register( unsigned int channel,
     67                                unsigned int index )
     68{
     69    unsigned int* vaddr = (unsigned int*)&seg_ioc_base + channel*HBA_SPAN + index;
     70    return _io_extended_read( vaddr );
     71}
     72
     73//////////////////////////////////////////////////////////////////////////////
     74// This low level function set a new value in register (channel / index) 
     75//////////////////////////////////////////////////////////////////////////////
     76void _hba_set_register( unsigned int channel,
     77                        unsigned int index,
     78                        unsigned int value )
     79{
     80    unsigned int* vaddr = (unsigned int*)&seg_ioc_base + channel*HBA_SPAN + index;
     81    _io_extended_write( vaddr, value );
     82}
     83
     84
    16485///////////////////////////////////////////////////////////////////////////////
    16586// This function register a command in both the command list
     
    17192// return 0 if success, > 0 if error
    17293///////////////////////////////////////////////////////////////////////////////
    173 unsigned int _hba_cmd_set( unsigned int  is_read,     // to memory
     94unsigned int _hba_cmd_set( unsigned int  channel,     // channel index
     95                           unsigned int  is_read,     // to memory
    17496                           unsigned int  lba,         // logic block address
    175                            unsigned int  buf_vaddr,   // buffer virtual address
     97                           paddr_t       buffer,      // buffer physical address
    17698                           unsigned int  count )      // number of blocks
    17799{
    178     volatile unsigned int *hba_address;
    179 
    180100    unsigned int       block_size;     // defined by the block device (bytes)
    181     unsigned int       channel_id;     // channel index
    182101    unsigned int       pxci;           // command list status
    183102    unsigned int       cmd_id;         // command index in command list
    184     unsigned int       buf_id;         // for physical buffers covering user buffer
    185     unsigned int       user_pt_vbase;  // user page table virtual base address
    186     unsigned int       vpn;            // for all pages covering the userbuffer
    187     unsigned int       vpn_min;        // first virtual page index for user buffer
    188     unsigned int       vpn_max;        // last  virtual page index for user buffer
    189     unsigned int       offset;         // unaligned bytes in page frame: buf_vaddr & 0xFFF
    190     unsigned int       offset_last;    // unaligned bytes in last frame
     103
    191104    hba_cmd_desc_t*    cmd_desc;       // command descriptor pointer   
    192105    hba_cmd_table_t*   cmd_table;      // command table pointer
     
    195108
    196109    // check buffer alignment
    197     if( buf_vaddr & (block_size-1) )
    198     {
    199         _tty_get_lock( 0 );
    200         _puts("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n");
    201         _tty_release_lock( 0 );
     110    if( buffer & (block_size-1) )
     111    {
     112        _printf("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n");
    202113        return 1;
    203114    }
    204115
    205     // get channel index
    206     channel_id = _get_context_slot(CTX_HBA_ID);
    207     if ( channel_id == 0xFFFFFFFF )
    208     {
    209         _tty_get_lock( 0 );
    210         _puts("\n[GIET ERROR] in _hba_set_cmd() : no HBA channel allocated\n");
    211         _tty_release_lock( 0 );
     116    // get command list status from PXCI register
     117    pxci = _hba_get_register( channel, HBA_PXCI );
     118
     119    // get command index and return error if command list full
     120    cmd_id = hba_cmd_slot[channel];
     121    if( pxci & (1<<cmd_id ) )
     122    {
     123        _printf("\n[GIET ERROR] in _hba_set_cmd() : command list full for channel %d\n",
     124                channel );
    212125        return 1;
    213126    }
    214127
    215     // get hba device address
    216     hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN * channel_id);
    217 
    218     // get command list status
    219     pxci = hba_address[HBA_PXCI];
    220 
    221     // get command index and return error if command list full
    222     cmd_id = hba_cmd_slot[channel_id];
    223     if( pxci & (1<<cmd_id ) )
    224     {
    225         _tty_get_lock( 0 );
    226         _puts("\n[GIET ERROR] in _hba_set_cmd() : command list full in channel \n");
    227         _putd( channel_id );
    228         _puts("\n");
    229         _tty_release_lock( 0 );
    230         return 1;
    231     }
    232 
    233128    // compute pointers on command descriptor and command table   
    234     cmd_desc  = (hba_cmd_desc_t*)(&(hba_cmd_list[channel_id].desc[cmd_id]));
    235     cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel_id][cmd_id]));
     129    cmd_desc  = (hba_cmd_desc_t*)(&(hba_cmd_list[channel].desc[cmd_id]));
     130    cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel][cmd_id]));
     131
     132    // set  buffer descriptor in command table
     133    cmd_table->entry[0].dba  = (unsigned int)(buffer);
     134    cmd_table->entry[0].dbau = (unsigned int)(buffer >> 32);
     135    cmd_table->entry[0].dbc  = count * block_size;
     136
     137    // initialize command table header
     138    cmd_table->header.lba0 = (char)lba;
     139    cmd_table->header.lba1 = (char)(lba>>8);
     140    cmd_table->header.lba2 = (char)(lba>>16);
     141    cmd_table->header.lba3 = (char)(lba>>24);
     142    cmd_table->header.lba4 = 0;
     143    cmd_table->header.lba5 = 0;
     144
     145    // initialise command descriptor
     146    cmd_desc->prdtl[0] = 1;
     147    cmd_desc->prdtl[1] = 0;
     148    cmd_desc->ctba     = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]);
     149    cmd_desc->ctbau    = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]>>32);
     150    if( is_read ) cmd_desc->flag[0] = 0x00;
     151    else          cmd_desc->flag[0] = 0x40;     
     152   
     153    // update PXCI register
     154    _hba_set_register( channel, HBA_PXCI, (1<<cmd_id) );
     155
     156    // update command pointer
     157    hba_cmd_slot[channel] = (cmd_id + 1)%32;
     158
     159    return  0;
     160}
     161
     162/* This can be used for a future use with buffer in virtual space
    236163
    237164    // get user space page table virtual address
     
    262189        if ( ko )
    263190        {
    264             _tty_get_lock( 0 );
    265             _puts("[GIET ERROR] in _hba_set_cmd() : user buffer unmapped\n");
    266             _tty_release_lock( 0 );
     191            _printf("[GIET ERROR] in _hba_set_cmd() : user buffer unmapped\n");
    267192            return 1;
    268193        }
    269194        if ((flags & PTE_U) == 0)
    270195        {
    271             _tty_get_lock( 0 );
    272             _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n");
    273             _tty_release_lock( 0 );
     196            _printf("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n");
    274197            return 1;
    275198        }
    276199        if (((flags & PTE_W) == 0 ) && (is_read == 0) )
    277200        {
    278             _tty_get_lock( 0 );
    279             _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n");
    280             _tty_release_lock( 0 );
     201            _printf("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n");
    281202            return 1;
    282203        }
     
    285206        if( buf_id > 245 )
    286207        {
    287             _tty_get_lock( 0 );
    288             _puts("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n");
    289             _tty_release_lock( 0 );
     208            _printf("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n");
    290209            return 1;
    291210        }
     
    301220
    302221#if GIET_DEBUG_HBA_DRIVER
    303 _puts("\n- buf_index = ");
     222_printf("\n- buf_index = ");
    304223_putd( buf_id );
    305 _puts(" / paddr = ");
     224_printf(" / paddr = ");
    306225_putl( paddr );
    307 _puts(" / count = ");
     226_printf(" / count = ");
    308227_putd( count );
    309 _puts("\n");
     228_printf("\n");
    310229#endif
    311230            buf_id++;
     
    320239
    321240#if GIET_DEBUG_HBA_DRIVER
    322 _puts("\n- buf_index = ");
     241_printf("\n- buf_index = ");
    323242_putd( buf_id );
    324 _puts(" / paddr = ");
     243_printf(" / paddr = ");
    325244_putl( paddr );
    326 _puts(" / count = ");
     245_printf(" / count = ");
    327246_putd( count );
    328 _puts("\n");
     247_printf("\n");
    329248#endif
    330249            buf_id++;
     
    340259
    341260#if GIET_DEBUG_HBA_DRIVER
    342 _puts("\n- buf_index = ");
     261_printf("\n- buf_index = ");
    343262_putd( buf_id );
    344 _puts(" / paddr = ");
     263_printf(" / paddr = ");
    345264_putl( paddr );
    346 _puts(" / count = ");
     265_printf(" / count = ");
    347266_putd( count );
    348 _puts("\n");
     267_printf("\n");
    349268#endif
    350269            buf_id++;
     
    357276
    358277#if GIET_DEBUG_HBA_DRIVER
    359 _puts("\n- buf_index = ");
     278_printf("\n- buf_index = ");
    360279_putd( buf_id );
    361 _puts(" / paddr = ");
     280_printf(" / paddr = ");
    362281_putl( paddr );
    363 _puts(" / count = ");
     282_printf(" / count = ");
    364283_putd( count );
    365 _puts("\n");
     284_printf("\n");
    366285#endif
    367286            buf_id++;
     
    376295
    377296#if GIET_DEBUG_HBA_DRIVER
    378 _puts("\n- buf_index = ");
     297_printf("\n- buf_index = ");
    379298_putd( buf_id );
    380 _puts(" / paddr = ");
     299_printf(" / paddr = ");
    381300_putl( paddr );
    382 _puts(" / count = ");
     301_printf(" / count = ");
    383302_putd( count );
    384 _puts("\n");
     303_printf("\n");
    385304#endif
    386305            buf_id++;
    387306        }
    388307    }
    389 
    390     // initialize command table header
    391     cmd_table->header.lba0 = (char)lba;
    392     cmd_table->header.lba1 = (char)(lba>>8);
    393     cmd_table->header.lba2 = (char)(lba>>16);
    394     cmd_table->header.lba3 = (char)(lba>>24);
    395 
    396     // initialise command descriptor
    397     cmd_desc->prdtl[0] = (unsigned char)(buf_id);
    398     cmd_desc->prdtl[1] = (unsigned char)(buf_id>>8);
    399     cmd_desc->ctba     = (unsigned int)(hba_cmd_table_paddr[channel_id][cmd_id]);
    400     cmd_desc->ctbau    = (unsigned int)(hba_cmd_table_paddr[channel_id][cmd_id]>>32);
    401     if( is_read ) cmd_desc->flag[0] = 0x00;
    402     else          cmd_desc->flag[0] = 0x40;     
    403    
    404     // update PXCI register
    405     hba_address[HBA_PXCI] = (1<<cmd_id);
    406 
    407     // update command pointer
    408     hba_cmd_slot[channel_id] = (cmd_id + 1)%32;
    409 
    410     return  0;
    411 }
     308*/
     309
     310
    412311///////////////////////////////////////////////////////////////////
    413312// Register a write command in Command List and Command Table
    414 // for a single buffer.
     313// for a single physical buffer.
    415314// Returns 0 if success, > 0 if error.
    416315///////////////////////////////////////////////////////////////////
    417 unsigned int _hba_write( unsigned int  mode,
     316unsigned int _hba_write( unsigned int  channel,
     317                         unsigned int  mode,
    418318                         unsigned int  lba,
    419                          void*         buffer,
     319                         paddr_t       buffer,
    420320                         unsigned int  count )
    421321{
    422     return _hba_cmd_set( 0, lba, (unsigned int)buffer, count );
     322    return _hba_cmd_set( channel,
     323                         0,         // write
     324                         lba,
     325                         buffer,
     326                         count );
    423327}
    424328
    425329///////////////////////////////////////////////////////////////////
    426330// Register a read command in Command List and Command Table
    427 // for a single buffer.
     331// for a single physical buffer.
    428332// Returns 0 if success, > 0 if error.
    429333///////////////////////////////////////////////////////////////////
    430 unsigned int _hba_read( unsigned int  mode,
     334unsigned int _hba_read( unsigned int  channel,
     335                        unsigned int  mode,
    431336                        unsigned int  lba,
    432                         void*         buffer,
     337                        paddr_t       buffer,
    433338                        unsigned int  count )
    434339{
    435     return _hba_cmd_set( 1, lba, (unsigned int)buffer, count );
    436 }
     340    return _hba_cmd_set( channel,
     341                         1,          // read
     342                         lba,
     343                         buffer,
     344                         count );
     345}
     346
    437347//////////////////////////////////////////////////////////////////
    438348// This function initializes for a given channel
     
    453363    unsigned int pt = _get_context_slot(CTX_PTAB_ID);
    454364
    455     // HBA registers
    456     unsigned int*  hba_address;
    457     hba_address = (unsigned int*)&seg_ioc_base + HBA_SPAN * channel;
    458 
    459     hba_address[HBA_PXCLB]  = (unsigned int)(&hba_cmd_list[channel]);
    460     hba_address[HBA_PXCLBU] = 0;
    461     hba_address[HBA_PXIE]   = 0x40000001;
    462     hba_address[HBA_PXIS]   = 0;
    463     hba_address[HBA_PXCI]   = 0;
    464     hba_address[HBA_PXCMD]  = 1;
     365    // HBA registers TODO: ne faut_il pas un V2P pour PXCLB/PXCLBU ? (AG)
     366    _hba_set_register( channel, HBA_PXCLB , (unsigned int)&hba_cmd_list[channel] );
     367    _hba_set_register( channel, HBA_PXCLBU, 0 );
     368    _hba_set_register( channel, HBA_PXIE  , 0x40000001 );
     369    _hba_set_register( channel, HBA_PXIS  , 0 );
     370    _hba_set_register( channel, HBA_PXCI  , 0 );
     371    _hba_set_register( channel, HBA_PXCMD , 1 );
    465372
    466373    // command list pointer       
     
    475382    if ( fail )
    476383    {
    477         _tty_get_lock( 0 );
    478         _puts("[GIET ERROR] in _hba_init() : command list unmapped\n");
    479         _tty_release_lock( 0 );
     384        _printf("[GIET ERROR] in _hba_init() : command list unmapped\n");
    480385        return 1;
    481386    }
     
    492397        if ( fail )
    493398        {
    494             _tty_get_lock( 0 );
    495             _puts("[GIET ERROR] in _hba_init() : command table unmapped\n");
    496             _tty_release_lock( 0 );
     399            _printf("[GIET ERROR] in _hba_init() : command table unmapped\n");
    497400            return 1;
    498401        }
     
    513416}
    514417
     418/////////////////////////////////////////////////////////////////////////////////////
     419// This function returns the content of the HBA_PXIS register for a given channel,
     420// and reset this register to acknoledge IRQ.
     421// return 0 if success, > 0 if error
     422/////////////////////////////////////////////////////////////////////////////////////
     423unsigned int _hba_get_status( unsigned int channel )
     424{
     425
     426    if( channel >= NB_IOC_CHANNELS )
     427    {
     428        _printf("\n[GIET ERROR] in _hba_get_status() : illegal channel\n");
     429        _exit();
     430    }
     431
     432    // get HBA_PXIS value
     433    unsigned int status = _hba_get_register( channel, HBA_PXIS );
     434
     435    // reset HBA_PXIS
     436    _hba_set_register( channel, HBA_PXIS, 0 );
     437
     438    return status;
     439}
    515440
    516441// Local Variables:
  • soft/giet_vm/giet_drivers/hba_driver.h

    r289 r295  
    5959} hba_cmd_entry_t;
    6060
    61 typedef struct hba_cmd_table_s  // size = 256 bytes
     61typedef struct hba_cmd_table_s  // size = 4096 bytes
    6262{
    6363
     
    9797///////////////////////////////////////////////////////////////////////////////////
    9898
    99 unsigned int _hba_write( unsigned int mode,
    100                          unsigned int lba,       // logic bloc address on device
    101                          void*        buffer,    // memory buffer base address
    102                          unsigned int count );   // number of blocs
     99extern unsigned int _hba_init ( unsigned int channel );
    103100
    104 unsigned int _hba_read ( unsigned int mode,
    105                          unsigned int lba,       // logic bloc address on device
    106                          void*        buffer,    // memory buffer base address
    107                          unsigned int count );   // number of blocks
     101extern unsigned int _hba_write( unsigned int channel,     // channel index
     102                                unsigned int mode,        // BOOT / KERNEL / USER
     103                                unsigned int lba,         // logic bloc address on device
     104                                unsigned long long paddr, // memory buffer base address
     105                                unsigned int count );     // number of blocs
    108106
    109 unsigned int _hba_init ( unsigned int channel );
     107extern unsigned int _hba_read ( unsigned int channel,     // channel index
     108                                unsigned int mode,        // BOOT / KERNEL / USER
     109                                unsigned int lba,         // logic bloc address on device
     110                                unsigned long long paddr, // memory buffer base address
     111                                unsigned int count );     // number of blocks
    110112
    111 unsigned int _hba_get_status( unsigned int   channel,
    112                               unsigned int*  status );
     113extern unsigned int _hba_get_status( unsigned int   channel );
    113114
    114 unsigned int _hba_reset_status( unsigned int channel );
    115 
    116 unsigned int _hba_get_block_size ();
     115extern unsigned int _hba_get_block_size ();
    117116
    118117
  • soft/giet_vm/giet_drivers/icu_driver.c

    r263 r295  
    7070
    7171#if USE_XICU
    72     _puts("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n");
     72    _printf("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n");
    7373    return 1;
    7474#else
     
    9898
    9999#if USE_XICU
    100     _puts("[GIET ERROR] _icu_get_index() should not be used if USE_XICU is set\n");
     100    _printf("[GIET ERROR] _icu_set_mask() should not be used if USE_XICU is set\n");
    101101    return 1;
    102102#else
  • soft/giet_vm/giet_drivers/ioc_driver.c

    r289 r295  
    77///////////////////////////////////////////////////////////////////////////////////
    88// The ioc_driver.c and ioc_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 // It can exist only one block-device controler in the architecture.
    13 //
    14 // The _ioc_read() and _ioc_write() functions use the _ioc_access() function,
    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.
    22 //
    23 // - In BOOT_VA mode, the _ioc_access() function makes a V2P translation to
    24 //   compute the buffer physical address. This mode is used by the boot code to
    25 //   load the various .elf files into memory.
    26 //
    27 // - In KERNEL mode, the _ioc_access() function makes a V2P translation to
    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.
    31 //
    32 // - In USER mode, the _ioc_access() function makes a V2P translation to
    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.
     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
     16//
     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.
    3650//
    3751// The IOMMU can be activated or not:
     
    6074//   if the IOMMU is not activated.
    6175// An error code is returned if these conditions are not verified.
     76//
     77// The "seg_ioc_base" virtual base address of the segment containing the
     78// memory-mapped registers of the device must be defined in the giet_vsegs.ld file.
     79// If the RAMDISK is used, an extra memory segment with virtual base address
     80// "seg_ramdisk_base" must be defined in the giet_vsegs.ld file.
    6281///////////////////////////////////////////////////////////////////////////////////
    63 // The seg_ioc_base virtual base addresses must be defined in giet_vsegs.ld file.
     82// Implementation note:
     83// In order to share the code, the two _ioc_read() and _ioc_write() functions
     84// call the same _ioc_access() function.
    6485///////////////////////////////////////////////////////////////////////////////////
    6586
    6687#include <giet_config.h>
    6788#include <ioc_driver.h>
     89#include <bdv_driver.h>
     90#include <hba_driver.h>
     91#include <sdc_driver.h>
     92#include <rdk_driver.h>
    6893#include <utils.h>
    6994#include <tty_driver.h>
     
    81106#endif
    82107
    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
     108#if (USE_IOC_BDV + USE_IOC_SPI + USE_IOC_HBA + USE_IOC_RDK) != 1
     109# error: You must use only one IOC controller type (BDV or SPI or HBA or RDK)
     110#endif
     111
     112#if USE_IOC_BDV
    88113# include <bdv_driver.h>
    89114#endif
    90115
    91 #if USE_SPI
     116#if USE_IOC_SPI
    92117# include <sdc_driver.h>
    93118#endif
    94119
    95 #if USE_HBA
     120#if USE_IOC_HBA
    96121# include <hba_driver.h>
    97122#endif
    98123
     124#if USE_IOC_RDK
     125# include <rdk_driver.h>
     126#endif
     127
     128///////////////////////////////////////////////////////////////////////////////
     129// IOC global variables
     130///////////////////////////////////////////////////////////////////////////////
    99131
    100132#define in_unckdata __attribute__((section (".unckdata")))
    101133
    102 ///////////////////// IOC global variables
    103 
    104 in_unckdata unsigned int _ioc_lock = 0;
    105 in_unckdata unsigned int _ioc_status = 0;
    106 in_unckdata volatile unsigned int _ioc_gtid;
    107134in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0;
    108135in_unckdata volatile unsigned int _ioc_iommu_npages;
    109136
    110137///////////////////////////////////////////////////////////////////////////////
    111 //      _ioc_access()
    112138// This function transfer data between a memory buffer and the block device.
    113139// The buffer lentgth is (count*block_size) bytes.
    114140// Arguments are:
    115141// - to_mem     : from external storage to memory when non 0.
    116 // - kernel     : kernel buffer with identity mapping when non 0.
     142// - mode       : BOOT_PA / BOOT_VA / KERNEL / USER
    117143// - lba        : first block index on the external storage.
    118144// - buf_vaddr  : virtual base address of the memory buffer.
     
    121147///////////////////////////////////////////////////////////////////////////////
    122148static unsigned int _ioc_access( unsigned int to_mem,
     149                                 unsigned int channel,
    123150                                 unsigned int mode,
    124151                                 unsigned int lba,
     
    128155
    129156#if GIET_DEBUG_IOC_DRIVER
    130 _tty_get_lock( 0 );
    131 _puts("\n[IOC DEBUG] Enter _ioc_access() at cycle ");
    132 _putd( _get_proctime() );
    133 _puts(" for processor ");
    134 _putd( _get_procid() );
    135 _puts("\n - mode    = ");
    136 _putd( mode );
    137 _puts("\n - vaddr   = ");
    138 _putx( buf_vaddr );
    139 _puts("\n - sectors = ");
    140 _putd( count );
    141 _puts("\n - lba     = ");
    142 _putx( lba );
    143 _puts("\n");
    144 _tty_release_lock( 0 );
     157unsigned int procid  = _get_procid();
     158unsigned int cid     = procid / NB_PROCS_MAX;
     159unsigned int lpid    = procid % NB_PROCS_MAX;
     160unsigned int x       = cid >> Y_WIDTH;
     161unsigned int y       = cid & ((1<<Y_WIDTH) - 1);
     162
     163_printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _ioc_access() at cycle %d\n"
     164        " - channel  = %d\n"
     165        " - mode     = %d\n"
     166        " - vaddr    = %d\n"
     167        " - sectors  = %d\n"
     168        " - lba      = %d\n",
     169        x, y, lpid, _get_proctime(), channel, mode, buf_vaddr, count, lba );
    145170#endif
    146171
     
    160185    if ((unsigned int) buf_vaddr & 0x3)
    161186    {
    162         _tty_get_lock( 0 );
    163         _puts("\n[GIET ERROR] in _ioc_access() : buffer not word aligned\n");
    164         _tty_release_lock( 0 );
    165         return 1;
     187        _printf("\n[GIET ERROR] in _ioc_access() : buffer not word aligned\n");
     188        _exit();
     189    }
     190
     191    // check channel
     192    if ( (USE_IOC_HBA == 0) && (channel > 0) )
     193    {
     194        _printf("\n[GIET ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
     195        _exit();
    166196    }
    167197
    168198    unsigned int length = count << 9;  // count * 512 bytes
    169199
    170     // computing target buffer physical address
    171     if ( mode == IOC_BOOT_PA_MODE )                // identity mapping
     200    // computing memory buffer physical address
     201    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity mapping
    172202    {
    173203        buf_paddr = (paddr_t)buf_vaddr;
    174204    }
    175     else                                           // V2P translation
     205    else                                                    // V2P translation required
    176206    {
    177207        // get page table virtual address
    178208        pt_vbase = _get_context_slot(CTX_PTAB_ID);
    179         vpn_min = buf_vaddr >> 12;
    180         vpn_max = (buf_vaddr + length - 1) >> 12;
     209        vpn_min  = buf_vaddr >> 12;
     210        vpn_max  = (buf_vaddr + length - 1) >> 12;
    181211
    182212        // loop on all virtual pages covering the user buffer
    183         for (vpn = vpn_min, ix2 = 0 ;
    184              vpn <= vpn_max ;
    185              vpn++, ix2++ )
     213        for (vpn = vpn_min, ix2 = 0 ; vpn <= vpn_max ; vpn++, ix2++ )
    186214        {
    187215            // get ppn and flags for each vpn
     
    193221            if ( ko )
    194222            {
    195                 _tty_get_lock( 0 );
    196                 _puts("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n");
    197                 _tty_release_lock( 0 );
     223                _printf("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n");
    198224                return 1;
    199225            }
     
    201227            if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
    202228            {
    203                 _tty_get_lock( 0 );
    204                 _puts("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n");
    205                 _tty_release_lock( 0 );
     229                _printf("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n");
    206230                return 1;
    207231            }
     
    209233            if ( ((flags & PTE_W) == 0 ) && to_mem )
    210234            {
    211                 _tty_get_lock( 0 );
    212                 _puts("\n[GIET ERROR] in _ioc_access() : buffer not writable\n");
    213                 _tty_release_lock( 0 );
     235                _printf("\n[GIET ERROR] in _ioc_access() : buffer not writable\n");
    214236                return 1;
    215237            }
     
    223245            if (ix2 > 511) // check buffer length < 2 Mbytes
    224246            {
    225                 _tty_get_lock( 0 );
    226                 _puts("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n");
    227                 _tty_release_lock( 0 );
     247                _printf("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n");
    228248                return 1;
    229249            }
     
    242262            if ((ppn - ppn_first) != ix2)
    243263            {
    244                 _tty_get_lock( 0 );
    245                 _puts("[GIET ERROR] in _ioc_access() : split physical buffer\n");
    246                 _tty_release_lock( 0 );
     264                _printf("[GIET ERROR] in _ioc_access() : split physical buffer\n");
    247265                return 1;
    248266            }
     
    272290    else         // memory read : update data caches
    273291    {
    274         // L1 cache : nothing to do if L1 write-through
     292        // L1 cache : nothing to do for L1 write-through
    275293
    276294        // L2 cache (only if IOB used)
     
    280298    if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr;
    281299
    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);
     300    ///////////////////////////////////////////
     301    // select the proper physical device
     302    ///////////////////////////////////////////
     303
     304#if       ( USE_IOC_BDV )
     305
     306#if GIET_DEBUG_IOC_DRIVER
     307_printf("\n[IOC DEBUG] Calling BDV driver\n");
     308#endif
     309        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
     310        else        error = _bdv_write( mode, lba, buf_paddr, count);
     311
     312#elif ( USE_IOC_SPI )
     313
     314#if GIET_DEBUG_IOC_DRIVER
     315_printf("\n[IOC DEBUG] Calling SPI driver\n");
     316#endif
     317        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
     318        else        error = _sdc_write(mode, lba, buf_paddr, count);
     319
     320#elif ( USE_IOC_HBA )
     321
     322#if GIET_DEBUG_IOC_DRIVER
     323_printf("\n[IOC DEBUG] Calling HBA driver\n");
     324#endif
     325        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
     326        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
     327
     328#elif ( USE_IOC_RDK )
     329
     330#if GIET_DEBUG_IOC_DRIVER
     331_printf("\n[IOC DEBUG] Calling RDK driver\n");
     332#endif
     333        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
     334        else        error = _rdk_write(lba, buf_vaddr, count);
     335
    291336#endif
    292337
     
    295340
    296341///////////////////////////////////////////////////////////////////////////////
    297 //       _ioc_init()
    298342// This function cheks block size, and activates the IOC interrupts.
    299343// Return 0 for success.
     
    301345unsigned int _ioc_init( unsigned int channel )
    302346{
    303 #if   USE_BDV
    304     return _bdv_init( channel );
    305 #elif USE_SPI
    306     return _sdc_init( channel );
    307 #elif USE_HBA
     347
     348#if   ( USE_IOC_BDV )
     349
     350    return _bdv_init();
     351
     352#elif ( USE_IOC_SPI )
     353
     354    return _sdc_init();
     355   
     356#elif ( USE_IOC_HBA )
     357
    308358    return _hba_init( channel );
    309 #endif
     359   
     360#elif ( USE_IOC_RDK )
     361
     362    return _rdk_init();
     363   
     364#endif
     365   
    310366}
    311367
    312368///////////////////////////////////////////////////////////////////////////////
    313 //     _ioc_read()
    314369// Transfer data from the block device to a memory buffer.
    315 // - mode     : BOOT / KERNEL / USER
     370// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER
    316371// - lba      : first block index on the block device
    317372// - buffer   : base address of the memory buffer (must be word aligned)
     
    319374// Returns 0 if success, > 0 if error.
    320375///////////////////////////////////////////////////////////////////////////////
    321 unsigned int _ioc_read( unsigned int mode, 
     376unsigned int _ioc_read( unsigned int channel,
     377                        unsigned int mode, 
    322378                        unsigned int lba,
    323379                        void*        buffer,
     
    325381{
    326382    return _ioc_access( 1,        // read access
     383                        channel,
    327384                        mode, 
    328385                        lba,
     
    332389
    333390///////////////////////////////////////////////////////////////////////////////
    334 //     _ioc_write()
    335391// Transfer data from a memory buffer to the block device.
    336 // - mode     : BOOT / KERNEL / USER
     392// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER
    337393// - lba      : first block index on the block device
    338394// - buffer   : base address of the memory buffer (must be word aligned)
     
    340396// Returns 0 if success, > 0 if error.
    341397///////////////////////////////////////////////////////////////////////////////
    342 unsigned int _ioc_write( unsigned int mode, 
     398unsigned int _ioc_write( unsigned int channel,
     399                         unsigned int mode, 
    343400                         unsigned int lba,
    344401                         const void*  buffer,
     
    346403{
    347404    return _ioc_access( 0,        // write access
     405                        channel,
    348406                        mode, 
    349407                        lba,
     
    353411
    354412///////////////////////////////////////////////////////////////////////////////
    355 //     _ioc_get_status()
    356413// This function returns in the status variable, the transfert status, and
    357414// acknowledge the IRQ if the IOC controler is not busy.
    358415// Returns 0 if success, > 0 if error
    359416///////////////////////////////////////////////////////////////////////////////
    360 unsigned int _ioc_get_status( unsigned int  channel,
    361                               unsigned int* status )
    362 {
    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
     417unsigned int _ioc_get_status( unsigned int  channel )
     418{
     419
     420#if   ( USE_IOC_BDV )
     421
     422    return _bdv_get_status( );
     423
     424#elif ( USE_IOC_SPI )
     425
     426    return _sdc_get_status( );
     427
     428#elif ( USE_IOC_HBA )
     429
     430    return _hba_get_status( channel );
     431
     432#elif ( USE_IOC_RDK )
     433
     434    _printf("[GIET ERROR] _ioc_get_status() should not be called");
     435    _printf(" when RAMDISK  is used...\n");
     436    _exit();
     437
     438    return 0;
     439
     440#endif
     441
    370442}
    371443
    372444///////////////////////////////////////////////////////////////////////////////
    373 //     _ioc_get_block_size()
    374445// This function returns the block_size with which the IOC has been configured.
    375446///////////////////////////////////////////////////////////////////////////////
    376447unsigned int _ioc_get_block_size()
    377448{
    378 #if   USE_BDV
     449
     450#if   ( USE_IOC_BDV )
     451
    379452    return _bdv_get_block_size();
    380 #elif USE_SPI
     453   
     454#elif ( USE_IOC_SPI )
     455
    381456    return _sdc_get_block_size();
    382 #elif USE_HBA
     457   
     458#elif ( USE_IOC_HBA )
     459
    383460    return _hba_get_block_size();
    384 #endif
     461   
     462#elif ( USE_IOC_RDK )
     463
     464    return 512;
     465
     466#endif
     467
    385468}
    386469
  • soft/giet_vm/giet_drivers/ioc_driver.h

    r289 r295  
    1313///////////////////////////////////////////////////////////////////////////////////
    1414
    15 enum IOC_registers
    16 {
    17     BLOCK_DEVICE_BUFFER,
    18     BLOCK_DEVICE_LBA,
    19     BLOCK_DEVICE_COUNT,
    20     BLOCK_DEVICE_OP,
    21     BLOCK_DEVICE_STATUS,
    22     BLOCK_DEVICE_IRQ_ENABLE,
    23     BLOCK_DEVICE_SIZE,
    24     BLOCK_DEVICE_BLOCK_SIZE,
    25     BLOCK_DEVICE_BUFFER_EXT,
    26 };
    27 enum IOC_operations
    28 {
    29     BLOCK_DEVICE_NOOP,
    30     BLOCK_DEVICE_READ,
    31     BLOCK_DEVICE_WRITE,
    32 };
    33 enum IOC_status
    34 {
    35     BLOCK_DEVICE_IDLE,
    36     BLOCK_DEVICE_BUSY,
    37     BLOCK_DEVICE_READ_SUCCESS,
    38     BLOCK_DEVICE_WRITE_SUCCESS,
    39     BLOCK_DEVICE_READ_ERROR,
    40     BLOCK_DEVICE_WRITE_ERROR,
    41     BLOCK_DEVICE_ERROR,
    42 };
    4315enum IOC_driver_modes
    4416{
    45     IOC_BOOT_PA_MODE,  // No V2P translation / Polling IOC_STATUS / no access checking
    46     IOC_BOOT_VA_MODE,  // V2P translation    / Polling IOC_STATUS / no access checking
    47     IOC_KERNEL_MODE,   // V2P translation    / Descheduling + IRQ / no access checking
    48     IOC_USER_MODE,     // V2P translation    / Descheduling + IRQ / access checking
     17    IOC_BOOT_MODE   = 0,     //  Polling IOC_STATUS / no access right checking
     18    IOC_KERNEL_MODE = 1,     //  Descheduling + IRQ / no access right checking
     19    IOC_USER_MODE   = 2,     //  Descheduling + IRQ / access right checking
    4920};
    5021
    5122///////////////////////////////////////////////////////////////////////////////////
    52 // IOC access functions and variables (vci_block_device)
     23// IOC global variables (generic disk controller)
    5324///////////////////////////////////////////////////////////////////////////////////
    5425
    55 extern unsigned int _ioc_lock;
    56 extern unsigned int _ioc_status;
    57 extern volatile unsigned int _ioc_gtid;
    5826extern volatile unsigned int _ioc_iommu_ix1;
    5927extern volatile unsigned int _ioc_iommu_npages;
    6028
     29///////////////////////////////////////////////////////////////////////////////////
     30// IOC access functions  (generic disk controller)
     31///////////////////////////////////////////////////////////////////////////////////
     32
    6133extern unsigned int _ioc_init( unsigned int channel );
    6234
    63 extern unsigned int _ioc_write( unsigned int mode,
     35extern unsigned int _ioc_write( unsigned int channel,
     36                                unsigned int mode,
    6437                                unsigned int lba,
    6538                                const void*  buffer,
    6639                                unsigned int count );
    6740
    68 extern unsigned int _ioc_read(  unsigned int mode,
     41extern unsigned int _ioc_read(  unsigned int channel,
     42                                unsigned int mode,
    6943                                unsigned int lba,
    7044                                void*        buffer,
    7145                                unsigned int count );
    7246
    73 extern unsigned int _ioc_get_status( unsigned int  channel,
    74                                      unsigned int* status );
     47extern unsigned int _ioc_get_status( unsigned int channel );
    7548
    7649extern unsigned int _ioc_get_block_size();
  • soft/giet_vm/giet_drivers/mmc_driver.c

    r263 r295  
    5757    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
    5858    {
    59         _puts("\n[GIET ERROR] in _memc_inval() : illegal cluster index[");
    60         _putd( x );
    61         _puts(",");
    62         _putd( y );
    63         _puts("]\n");
    64         _puts("   - paddr      = ");
    65         _putl( buf_paddr );
    66         _puts("\n   - cluster_xy = ");
    67         _putx( cluster_xy );
    68         _puts("\n");
     59        _printf("\n[GIET ERROR] in _memc_inval() : illegal cluster_xy for paddr %l\n",
     60                 buf_paddr );
    6961        _exit();
    7062    }
     
    10294    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
    10395    {
    104         _puts("\n[GIET ERROR] in _memc_sync() : illegal cluster index[");
    105         _putd( x );
    106         _puts(",");
    107         _putd( y );
    108         _puts("]\n");
    109         _puts("   - paddr      = ");
    110         _putl( buf_paddr );
    111         _puts("\n   - cluster_xy = ");
    112         _putx( cluster_xy );
    113         _puts("\n");
     96        _printf( "\n[GIET ERROR] in _memc_sync() : illegal cluster_xy for paddr %l\n",
     97                 buf_paddr );
    11498        _exit();
    11599    }
  • soft/giet_vm/giet_drivers/mwr_driver.c

    r263 r295  
    5656                           paddr_t                channel_pbase )
    5757{
    58     _puts(" [GIET_ERROR] _mwr_hw_init() function not supported yet\n");
     58    _printf(" [GIET_ERROR] _mwr_hw_init() function not supported yet\n");
    5959    _exit();
    6060
  • soft/giet_vm/giet_drivers/nic_driver.c

    r258 r295  
    5656#define in_unckdata __attribute__((section (".unckdata")))
    5757
     58///////////////////////////////////////////////////////////////////////////////
     59// This low_level function returns the value contained in register (index).
     60///////////////////////////////////////////////////////////////////////////////
     61unsigned int _nic_get_register( unsigned int channel,
     62                                unsigned int index )
     63{
     64    unsigned int* vaddr = (unsigned int*)&seg_nic_base +
     65                           NIC_CHANNEL_SPAN*channel + index;
     66    return _io_extended_read( vaddr );
     67}
     68
     69///////////////////////////////////////////////////////////////////////////////
     70// This low-level function set a new value in register (index).
     71///////////////////////////////////////////////////////////////////////////////
     72void _nic_set_register( unsigned int channel,
     73                        unsigned int index,
     74                        unsigned int value )
     75{
     76    unsigned int* vaddr = (unsigned int*)&seg_nic_base +
     77                           NIC_CHANNEL_SPAN*channel + index;
     78    _io_extended_write( vaddr, value );
     79}
     80
    5881//////////////////////////////////////////////////////////////////////////////////
    59 // _nic_sync_write()
    6082// Transfer data from an memory buffer to the NIC device using a memcpy.
    6183// - buffer : base address of the memory buffer.
     
    6587                              unsigned int   length )
    6688{
    67     _puts("[GIET ERROR] _nic_sync_write function not implemented\n");
     89    _printf("[GIET ERROR] _nic_sync_write function not implemented\n");
    6890    _exit();
    6991
     
    7395}
    7496//////////////////////////////////////////////////////////////////////////////////
    75 // _nic_sync_read()
    7697// Transfer data from the NIC device to a memory buffer using a memcpy.
    7798// - buffer : base address of the memory buffer.
     
    81102                             unsigned int   length )
    82103{
    83     _puts("[GIET ERROR] _nic_sync_read function not implemented\n");
     104    _printf("[GIET ERROR] _nic_sync_read function not implemented\n");
    84105    _exit();
    85106
     
    89110}
    90111//////////////////////////////////////////////////////////////////////////////////
    91 // _nic_cma_start()
    92112// Returns 0 if success, > 0 if error.
    93113//////////////////////////////////////////////////////////////////////////////////
    94114unsigned int _nic_cma_start( )
    95115{
    96     _puts("[GIET ERROR] _nic_cma_start function not implemented\n");
     116    _printf("[GIET ERROR] _nic_cma_start() not implemented\n");
    97117    _exit();
    98118
     
    101121}
    102122//////////////////////////////////////////////////////////////////////////////////
    103 // _nic_cma_stop()
    104123// Returns 0 if success, > 0 if error.
    105124//////////////////////////////////////////////////////////////////////////////////
    106125unsigned int _nic_cma_stop()
    107126{
    108     _puts("[GIET ERROR] _nic_cma_stop function not implemented\n");
     127    _printf("[GIET ERROR] _nic_cma_stop() not implemented\n");
    109128    _exit();
    110129
     
    113132}
    114133
     134//////////////////////////////////////////////////////////////////////////////////
     135// This ISR handles IRQx from a NIC RX channeL
     136//////////////////////////////////////////////////////////////////////////////////
     137void _nic_rx_isr( unsigned int irq_type,
     138                  unsigned int irq_id,
     139                  unsigned int channel )
     140{
     141    _printf("[GIET ERROR] _nic_rx_isr() not implemented\n");
     142    _exit();
     143}
     144
     145//////////////////////////////////////////////////////////////////////////////////
     146// This ISR handles IRQx from a NIC RX channeL
     147//////////////////////////////////////////////////////////////////////////////////
     148void _nic_tx_isr( unsigned int irq_type,
     149                  unsigned int irq_id,
     150                  unsigned int channel )
     151{
     152    _printf("[GIET ERROR] _nic_tx_isr() not implemented\n");
     153    _exit();
     154}
    115155
    116156// Local Variables:
  • soft/giet_vm/giet_drivers/nic_driver.h

    r258 r295  
    88#ifndef _GIET_NIC_DRIVERS_H_
    99#define _GIET_NIC_DRIVERS_H_
     10
     11///////////////////////////////////////////////////////////////////////////////////
     12// NIC Registers  (vci_multi_nic)
     13///////////////////////////////////////////////////////////////////////////////////
     14
     15enum SoclibMultiNicHyperviseurRegisters {
     16    NIC_G_VIS                        = 0,   // bitfield : bit N = 0 -> channel N disabled
     17    NIC_G_ON                         = 1,   // boolean : NIC component activated
     18    NIC_G_NB_CHAN                    = 2,   // Number of channels present in this NIC (read only)
     19    NIC_G_BC_ENABLE                  = 3,   // boolean : Enable Broadcast if non zero
     20    NIC_G_TDM_ENABLE                 = 4,   // boolean : TDM Scheduler if non zero
     21    NIC_G_TDM_PERIOD                 = 5,   // TDM time slot value
     22    NIC_G_BYPASS_ENABLE              = 6,   // boolean : Enable bypass for TX packets
     23    // alignment
     24    NIC_G_MAC_4                      = 8,   // channel mac address 32 LSB bits array[8]
     25    NIC_G_MAC_2                      = 16,  // channel mac address 16 MSB bits array[8]
     26    // alignment
     27    NIC_G_NPKT_RX_G2S_RECEIVED       = 32,  // number of packets received on GMII RX port
     28    NIC_G_NPKT_RX_G2S_DISCARDED      = 33,  // number of RX packets discarded by RX_G2S FSM
     29
     30    NIC_G_NPKT_RX_DES_SUCCESS        = 34,  // number of RX packets transmited by RX_DES FSM
     31    NIC_G_NPKT_RX_DES_TOO_SMALL      = 35,  // number of discarded too small RX packets (<60B)
     32    NIC_G_NPKT_RX_DES_TOO_BIG        = 36,  // number of discarded too big RX packets (>1514B)
     33    NIC_G_NPKT_RX_DES_MFIFO_FULL     = 37,  // number of discarded RX packets because fifo full
     34    NIC_G_NPKT_RX_DES_CRC_FAIL       = 38,  // number of discarded RX packets because CRC32 failure
     35
     36    NIC_G_NPKT_RX_DISPATCH_RECEIVED  = 39,  // number of packets received by RX_DISPATCH FSM
     37    NIC_G_NPKT_RX_DISPATCH_BROADCAST = 40,  // number of broadcast RX packets received
     38    NIC_G_NPKT_RX_DISPATCH_DST_FAIL  = 41,  // number of discarded RX packets for DST MAC not found
     39    NIC_G_NPKT_RX_DISPATCH_CH_FULL   = 42,  // number of discarded RX packets for channel full
     40
     41    NIC_G_NPKT_TX_DISPATCH_RECEIVED  = 43,  // number of packets received by TX_DISPATCH FSM
     42    NIC_G_NPKT_TX_DISPATCH_TOO_SMALL = 44,  // number of discarded too small TX packets (<60B)
     43    NIC_G_NPKT_TX_DISPATCH_TOO_BIG   = 45,  // number of discarded too big TX packets (>1514B)
     44    NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  = 46,  // number of discarded TX packets for SRC MAC failed
     45    NIC_G_NPKT_TX_DISPATCH_BROADCAST = 47,  // number of broadcast TX packets received
     46    NIC_G_NPKT_TX_DISPATCH_BYPASS    = 48,  // number of bypassed TX->RX packets
     47    NIC_G_NPKT_TX_DISPATCH_TRANSMIT  = 49,  // number of transmit TX packets
     48
     49    NIC_CHANNEL_SPAN                 = 0x2000,
     50};
     51
     52/////////////////////////////////////////////////////////////////////
     53// A container descriptor has the following form:
     54// LOW WORD : Container LSB base address     
     55// HIGH WORD: Container status (leftmost bit), '1' means full
     56//            Base address MSB extension, if needed (right aligned)
     57//////////////////////////////////////////////////////////////////////
     58enum SoclibMultiNicChannelRegisters
     59{
     60    NIC_RX_DESC_LO_0          = 0,   // RX_0 descriptor low word         (Read/Write)
     61    NIC_RX_DESC_HI_0          = 1,   // RX_0 descriptor high word        (Read/Write)
     62    NIC_RX_DESC_LO_1          = 2,   // RX_1 descriptor low word         (Read/Write)
     63    NIC_RX_DESC_HI_1          = 3,   // RX_1 descriptor high word        (Read/Write)
     64    NIC_TX_DESC_LO_0          = 4,   // TX_0 descriptor low word         (Read/Write)
     65    NIC_TX_DESC_HI_0          = 5,   // TX_0 descriptor high word        (Read/Write)
     66    NIC_TX_DESC_LO_1          = 6,   // TX_1 descriptor low word         (Read/Write)
     67    NIC_TX_DESC_HI_1          = 7,   // TX_1 descriptor high word        (Read/Write)
     68    NIC_MAC_4                 = 8,   // channel mac address 32 LSB bits  (Read Only)
     69    NIC_MAC_2                 = 9,   // channel mac address 16 LSB bits  (Read Only)
     70    NIC_RX_RUN                = 10,  // RX packets can be received       (write_only)
     71    NIC_TX_RUN                = 11,  // TX packets can be transmitted    (write_only)
     72};
    1073
    1174///////////////////////////////////////////////////////////////////////////////////
     
    2386extern unsigned int _nic_cma_stop();
    2487
     88extern void _nic_rx_isr( unsigned int irq_type,
     89                         unsigned int irq_id,
     90                         unsigned int channel );
     91
     92extern void _nic_tx_isr( unsigned int irq_type,
     93                         unsigned int irq_id,
     94                         unsigned int channel );
     95
    2596///////////////////////////////////////////////////////////////////////////////////
    2697
  • soft/giet_vm/giet_drivers/sdc_driver.c

    r289 r295  
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
     7
    78#include <sdc_driver.h>
     9#include <tty_driver.h>
    810#include <utils.h>
    911
     
    179181        if ( sdcard_rsp != 0x01 )
    180182        {
    181 
    182                 _puts("card CMD0 failed ");
     183                _printf("[SDC ERROR] card CMD0 failed\n");
    183184                return sdcard_rsp;
    184185        }
     
    196197        if (!SDCARD_CHECK_R1_VALID(sdcard_rsp))
    197198    {
    198                 _puts("card CMD8 failed ");
     199                _printf("[SDC ERROR] card CMD8 failed\n");
    199200                return sdcard_rsp;
    200201        }
     
    206207                ersp = (ersp << 8) | _sdc_receive_char();
    207208                ersp = (ersp << 8) | _sdc_receive_char();
    208                 if ((ersp & 0xffff) != 0x0101) {
     209                if ((ersp & 0xffff) != 0x0101)
     210        {
    209211                        // voltage mismatch
    210                         _puts("card CMD8 mismatch: ");
    211                         _putx(ersp);
     212                        _printf("[SDC ERROR] card CMD8 mismatch : ersp = %x\n");
    212213                        return sdcard_rsp;
    213214                }
    214                 _puts("v2 or later ");
     215                _printf("[SDC WARNING] v2 or later ");
    215216                sdcard.sdhc = 1;
    216217        }
     
    218219    {
    219220                // other error
    220                 _puts("card CMD8 error ");
     221                _printf("[SDC ERROR] card CMD8 error\n");
    221222                return sdcard_rsp;
    222223        }
     
    249250        if (sdcard_rsp)
    250251    {
    251                 _puts("SD ACMD41 failed ");
     252                _printf("[SDC ERROR] ACMD41 failed\n");
    252253                return sdcard_rsp;
    253254        }
     
    263264                if (sdcard_rsp)
    264265        {
    265                         _puts("SD CMD58 failed ");
     266                        _printf("[SDC ERROR] CMD58 failed\n");
    266267                        return sdcard_rsp;
    267268                }
     
    272273                if (ersp & 0x40000000)
    273274        {
    274                         _puts("SDHC ");
    275                 } else
     275                        _printf(" SDHC ");
     276                }
     277        else
    276278        {
    277279                        sdcard.sdhc = 0;
     
    279281                _sdc_disable();
    280282        }
    281         _puts("card detected ");
     283        _printf("card detected\n");
    282284        return 0;
    283285}
     
    334336// Returns 0 if success, other value if failure
    335337///////////////////////////////////////////////////////////////////////////////
    336 unsigned int _sdc_init( unsigned int channel )
     338unsigned int _sdc_init()
    337339{
    338340    spi = (struct spi_dev*) &seg_ioc_base;
     
    355357    while(1)
    356358    {
    357         _puts("Trying to initialize SD card... ");
    358 
    359         sdcard_rsp = _sdc_open( channel );
     359        _printf("[SDC WARNING] Trying to initialize SD card...\n");
     360
     361        sdcard_rsp = _sdc_open( 0 );  // only channel 0
    360362        if (sdcard_rsp == 0)
    361363        {
    362             _puts("OK\n");
     364            _printf("OK\n");
    363365            break;
    364366        }
    365367
    366         _puts("KO\n");
     368        _printf("KO\n");
    367369
    368370        for (i = 0; i < 1000; i++);
     
    370372        if (++iter >= SDCARD_RESET_ITER_MAX)
    371373        {
    372             _puts("\nERROR: During SD card reset to IDLE state\n"
    373                  "/ card response = ");
    374             _putx(sdcard_rsp);
    375             _puts("\n");
     374            _printf("\n[SDC ERROR] During SD card reset to IDLE state "
     375                    "/ card response = %x\n", sdcard_rsp );
    376376            _exit();
    377377        }
     
    382382    if (sdcard_rsp)
    383383    {
    384         _puts("ERROR: During SD card blocklen initialization\n");
     384        _printf("[SDC ERROR] During SD card blocklen initialization\n");
    385385        _exit();
    386386    }
     
    396396    );
    397397
    398     _puts("Finish block device initialization\n\r");
     398    _printf("[SDC WARNING] Finish SD card initialization\n\r");
    399399
    400400    return 0;
     
    478478
    479479///////////////////////////////////////////////////////////////////////////////
    480 //     _sdc_get_status()
    481480// Transfer data from memory buffer to SD card device.
    482481// - channel: channel index
     
    484483// Returns 0 if success, > 0 if error.
    485484///////////////////////////////////////////////////////////////////////////////
    486 unsigned int _sdc_get_status( unsigned int channel ,
    487                               unsigned int* status )
    488 {
    489     *status = BLOCK_DEVICE_IDLE;
    490 
    491     return 0;
    492 }
    493 
    494 ///////////////////////////////////////////////////////////////////////////////
    495 //     _sdc_get_block_size()
     485unsigned int _sdc_get_status()
     486{
     487    _printf("[SDC ERROR] function _sdc_get_status() should not be called\n");
     488    _exit();
     489
     490    return 0;  // to avoid a warning
     491}
     492
     493///////////////////////////////////////////////////////////////////////////////
    496494// Returns the block size in bytes of the SD card
    497495///////////////////////////////////////////////////////////////////////////////
  • soft/giet_vm/giet_drivers/sdc_driver.h

    r289 r295  
    3636};
    3737
    38 unsigned int _sdc_init( unsigned int channel );
    39 
     38unsigned int _sdc_init();
    4039
    4140unsigned int _sdc_read( unsigned int mode,
     
    5049                         unsigned int count);
    5150
     51unsigned int _sdc_get_status();
     52
    5253unsigned int _sdc_get_block_size();
    53 
    54 unsigned int _sdc_get_status( unsigned int channel ,
    55                               unsigned int* status );
    5654
    5755
  • soft/giet_vm/giet_drivers/tim_driver.c

    r263 r295  
    1818// The global index is cluster_xy * (NB_PROCS_MAX + NB_TIM_CHANNELS) + local_id
    1919//
    20 // The NB_PROCS_MAX and NB_TIM_CHANNELS values must be defined in the
    21 // hard_config.h file.
    22 //
    23 // The register offsets must be defined in the hwr_mapping.h file.
     20// The NB_PROCS_MAX and NB_TIM_CHANNELS values must be defined in hard_config.h file.
    2421/////////////////////////////////////////////////////////////////////////////////////
    2522// The virtual base address of the segment associated to a channel is:
     
    3330#include <giet_config.h>
    3431#include <tim_driver.h>
     32#include <xcu_driver.h>
     33#include <tty_driver.h>
    3534#include <utils.h>
    3635
     
    6867
    6968#if (NB_TIM_CHANNELS > 0)
    70 in_unckdata volatile unsigned char _user_timer_event[X_SIZE*Y_SIZE*NB_TIM_CHANNELS]
    71                             = { [0 ... ((X_SIZE*Y_SIZE*NB_TIM_CHANNELS) - 1)] = 0 };
     69in_unckdata volatile unsigned char _user_timer_event[(1<<X_WIDTH)*(1<<Y_WIDTH)*NB_TIM_CHANNELS]
     70                        = { [0 ... (((1<<X_WIDTH)*(1<<Y_WIDTH)*NB_TIM_CHANNELS) - 1)] = 0 };
    7271#endif
    7372
    7473////////////////////////////////////////////////////////////////////////////////////
    75 //     _timer_start()
    7674// This function activates a timer in the vci_timer component
    7775// by writing in the proper register the period value.
    7876// It can be used by both the kernel to initialise a "system" timer,
    7977// or by a task (through a system call) to configure an "user" timer.
    80 // Returns 0 if success, > 0 if error.
    81 //////////////////////////////////////////////////////////////////////////////
    82 unsigned int _timer_start( unsigned int cluster_xy,
    83                            unsigned int local_id,
    84                            unsigned int period)
    85 {
    86     // parameters checking
    87     unsigned int x = cluster_xy >> Y_WIDTH;
    88     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    89     if (x >= X_SIZE)                  return 1;
    90     if (y >= Y_SIZE)                  return 1;
    91     if (local_id >= NB_TIM_CHANNELS)  return 1;
     78///////////////////////////////////////////////////////////////////////////////////
     79void _timer_start( unsigned int cluster_xy,
     80                   unsigned int local_id,
     81                   unsigned int period)
     82{
     83#if NB_TIM_CHANNELS
     84
     85    // parameters checking
     86    unsigned int x = cluster_xy >> Y_WIDTH;
     87    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     88    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
     89    {
     90        _printf("[GIET ERROR] in _timer_start()\n");
     91        _exit();
     92    }
    9293
    9394    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base +
     
    9697    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
    9798    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0x3;
    98     return 0;
    99 }
    100 
    101 //////////////////////////////////////////////////////////////////////////////
    102 //     _timer_stop()
     99
     100#else
     101    _printf("[GIET ERROR] _timer_start() should not be called when NB_TIM_CHANNELS is 0\n");
     102    _exit();
     103#endif
     104}
     105
     106//////////////////////////////////////////////////////////////////////////////
    103107// This function desactivates a timer in the vci_timer component
    104108// by writing in the proper register.
    105109// Returns 0 if success, > 0 if error.
    106110//////////////////////////////////////////////////////////////////////////////
    107 unsigned int _timer_stop( unsigned int cluster_xy,
    108                           unsigned int local_id)
    109 {
    110     // parameters checking
    111     unsigned int x = cluster_xy >> Y_WIDTH;
    112     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    113     if (x >= X_SIZE)                  return 1;
    114     if (y >= Y_SIZE)                  return 1;
    115     if (local_id >= NB_TIM_CHANNELS)  return 1;
     111void _timer_stop( unsigned int cluster_xy,
     112                  unsigned int local_id)
     113{
     114#if NB_TIM_CHANNELS
     115
     116    // parameters checking
     117    unsigned int x = cluster_xy >> Y_WIDTH;
     118    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     119    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
     120    {
     121        _printf("[GIET ERROR] in _timer_stop()\n");
     122        _exit();
     123    }
    116124
    117125    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base +
     
    119127
    120128    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
    121     return 0;
    122 }
    123 
    124 //////////////////////////////////////////////////////////////////////////////
    125 //     _timer_reset_irq()
     129
     130#else
     131    _printf("[GIET ERROR] _timer_stop() should not be called when NB_TIM_CHANNELS is 0\n");
     132    _exit();
     133#endif
     134}
     135
     136//////////////////////////////////////////////////////////////////////////////
    126137// This function acknowlegge a timer interrupt in the vci_timer 
    127138// component by writing in the proper register.
     
    130141// Returns 0 if success, > 0 if error.
    131142//////////////////////////////////////////////////////////////////////////////
    132 unsigned int _timer_reset_irq( unsigned int cluster_xy,
    133                                unsigned int local_id )
    134 {
    135     // parameters checking
    136     unsigned int x = cluster_xy >> Y_WIDTH;
    137     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    138     if (x >= X_SIZE)                  return 1;
    139     if (y >= Y_SIZE)                  return 1;
    140     if (local_id >= NB_TIM_CHANNELS)  return 1;
     143void _timer_reset_irq( unsigned int cluster_xy,
     144                       unsigned int local_id )
     145{
     146#if NB_TIM_CHANNELS
     147
     148    // parameters checking
     149    unsigned int x = cluster_xy >> Y_WIDTH;
     150    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     151    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
     152    {
     153        _printf("[GIET ERROR] in _timer_reset_irq()\n");
     154        _exit();
     155    }
    141156
    142157    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base +
     
    144159
    145160    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
    146     return 0;
     161
     162#else
     163    _printf("[GIET ERROR] _timer_reset_irq() should not be called when NB_TIM_CHANNELS is 0\n");
     164    _exit();
     165#endif
    147166}
    148167
    149168/////////////////////////////////////////////////////////////////////////////
    150 //     _timer_reset_cpt()
    151169// This function resets the timer counter. To do so, we re-write the period
    152170// in the proper register, what causes the count to restart.
     
    156174// This function is called during a context switch (user or preemptive)
    157175//////////////////////////////////////////////////////////////////////i//////
    158 unsigned int _timer_reset_cpt( unsigned int cluster_xy,
    159                                unsigned int local_id)
    160 {
    161     // parameters checking
    162     unsigned int x = cluster_xy >> Y_WIDTH;
    163     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    164     if (x >= X_SIZE)                  return 1;
    165     if (y >= Y_SIZE)                  return 1;
    166     if (local_id >= NB_TIM_CHANNELS)  return 1;
     176void _timer_reset_cpt( unsigned int cluster_xy,
     177                       unsigned int local_id)
     178{
     179#if NB_TIM_CHANNELS
     180
     181    // parameters checking
     182    unsigned int x = cluster_xy >> Y_WIDTH;
     183    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     184    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
     185    {
     186        _printf("[GIET ERROR in _timer_reset_cpt()\n");
     187        _exit();
     188    }
    167189
    168190    // We suppose that the TIMER_MODE register value is 0x3
     
    172194    unsigned int period = timer_address[local_id * TIMER_SPAN + TIMER_PERIOD];
    173195    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
    174     return 0;
    175 }
     196
     197#else
     198    _printf("[GIET ERROR] _timer_reset_cpt should not be called when NB_TIM_CHANNELS is 0\n");
     199    _exit();
     200#endif
     201}
     202
     203///////////////////////////////////////////////////////////////////////////////////
     204// This ISR handles the IRQs generated by the "user" timers that are
     205// replicated in all clusters.
     206// The IRQs generated by the "system" timers should be handled by _isr_switch().
     207// It can be a HWI or a PTI.
     208// The channel argument is the user timer local index.
     209//     timer_global_id = cluster_id*(NB_TIM_CHANNELS) + channel
     210// The ISR acknowledges the IRQ and registers the event in the proper entry
     211// of the _user_timer_event[] array, and a log message is displayed on TTY0.
     212///////////////////////////////////////////////////////////////////////////////////
     213void _timer_isr( unsigned int irq_type,   // HWI / PTI
     214                 unsigned int irq_id,     // index returned by XCU
     215                 unsigned int channel )   // user timer index
     216{
     217#if NB_TIM_CHANNELS
     218
     219    unsigned int cluster_xy = _get_procid() / NB_PROCS_MAX;
     220
     221    // acknowledge IRQ depending on type
     222    if   ( irq_type == IRQ_TYPE_HWI )  _timer_reset_irq( cluster_xy, channel );
     223    else                               _xcu_timer_reset_irq( cluster_xy, irq_id );
     224
     225    // register the event
     226    _user_timer_event[cluster_xy * NB_TIM_CHANNELS + channel] = 1;
     227
     228    // display a message on TTY 0
     229    _printf("\n[GIET WARNING] User Timer IRQ at cycle %d / cluster = %x / channel = %d\n",
     230            _get_proctime(), cluster_xy, channel );
     231
     232#else
     233    _printf("[GIET ERROR] _timer_isr() should not be called when NB_TIM_CHANNELS == 0\n");
     234    _exit();
     235#endif
     236}
     237
    176238
    177239
  • soft/giet_vm/giet_drivers/tim_driver.h

    r263 r295  
    66///////////////////////////////////////////////////////////////////////////////////
    77
    8 #ifndef _GIET_TIM_DRIVERS_H_
    9 #define _GIET_TIM_DRIVERS_H_
     8#ifndef _GIET_TIM_DRIVER_H_
     9#define _GIET_TIM_DRIVER_H_
    1010
    1111///////////////////////////////////////////////////////////////////////////////////
     
    2727///////////////////////////////////////////////////////////////////////////////////
    2828
    29 extern volatile unsigned char _timer_event[];
     29extern void _timer_start( unsigned int cluster_xy,
     30                          unsigned int local_id,
     31                          unsigned int period );
    3032
    31 extern unsigned int _timer_start( unsigned int cluster_xy,
    32                                   unsigned int local_id,
    33                                   unsigned int period );
     33extern void _timer_stop( unsigned int cluster_xy,
     34                         unsigned int local_id );
    3435
    35 extern unsigned int _timer_stop( unsigned int cluster_xy,
    36                                  unsigned int local_id );
     36extern void _timer_reset_irq( unsigned int cluster_xy,
     37                              unsigned int local_id );
    3738
    38 extern unsigned int _timer_reset_irq( unsigned int cluster_xy,
    39                                       unsigned int local_id );
     39extern void _timer_reset_cpt( unsigned int cluster_xy,
     40                              unsigned int local_id);
    4041
    41 extern unsigned int _timer_reset_cpt( unsigned int cluster_xy,
    42                                       unsigned int local_id);
     42extern void _timer_isr( unsigned int irq_type,
     43                        unsigned int irq_id,
     44                        unsigned int channel );
    4345
    4446///////////////////////////////////////////////////////////////////////////////////
  • soft/giet_vm/giet_drivers/tty_driver.c

    r258 r295  
    88// This driver supports the SocLib vci_multi_tty component.
    99//
    10 // It can exist only one multi_tty controler in the architecture.
    11 //
    1210// The total number of TTY terminals must be defined by the configuration
    1311// parameter NB_TTY_CHANNELS in the hard_config.h file.
    14 //
    15 // The register offsets must be defined in the hwr_mapping.h file.
    1612//
    1713// The "system" terminal is TTY[0].
     
    1915// as defined in the mapping_info data structure. The corresponding tty_id must
    2016// be stored in the context of the task by the boot code.
    21 ///////////////////////////////////////////////////////////////////////////////////
    22 // The virtual base address of the segment associated to a channel is:
    2317//
    24 //                  seg_tty_base  + TTY_SPAN * channel_id
    25 //
    26 // The seg_tty_base virtual base addresses must be defined in giet_vsegs.ld file.
     18// The seg_tty_base must be defined in giet_vsegs.ld file.
     19///////////////////////////////////////////////////////////////////////////////////
     20// Implementation note:
     21//
     22// All physical accesses to device registers are done by the two
     23// _tty_get_register(), _tty_set_register() low-level functions,
     24// that are handling virtual / physical addressing.
    2725///////////////////////////////////////////////////////////////////////////////////
    2826
    2927#include <giet_config.h>
    3028#include <tty_driver.h>
     29#include <xcu_driver.h>
    3130#include <ctx_handler.h>
    3231#include <utils.h>
     
    4241#define in_unckdata __attribute__((section (".unckdata")))
    4342
    44 /////////////////   TTY global variables
    45 in_unckdata volatile unsigned char _tty_get_buf[NB_TTY_CHANNELS];
    46 in_unckdata volatile unsigned char _tty_get_full[NB_TTY_CHANNELS]
     43//////////////////////////////////////////////////////////////////////////////
     44//   TTY global variables
     45//////////////////////////////////////////////////////////////////////////////
     46
     47in_unckdata volatile unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
     48in_unckdata volatile unsigned int _tty_rx_full[NB_TTY_CHANNELS]
    4749                                     = { [0 ... NB_TTY_CHANNELS - 1] = 0 };
     50
     51//////////////////////////////////////////////////////////////////////////////
     52// This low level function returns the value of register (channel / index)
     53//////////////////////////////////////////////////////////////////////////////
     54unsigned int _tty_get_register( unsigned int channel,
     55                                unsigned int index )
     56{
     57    unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index;
     58    return _io_extended_read( vaddr );
     59}
     60
     61//////////////////////////////////////////////////////////////////////////////
     62// This low level function set a new value in register (channel / index) 
     63//////////////////////////////////////////////////////////////////////////////
     64void _tty_set_register( unsigned int channel,
     65                        unsigned int index,
     66                        unsigned int value )
     67{
     68    unsigned int* vaddr = (unsigned int*)&seg_tty_base + channel*TTY_SPAN + index;
     69    _io_extended_write( vaddr, value );
     70}
    4871
    4972/////////////////////////////////////////////////////////////////////////////////
    5073// This non-blocking function writes a character string from a fixed-length
    51 // buffer to the TTY_WRITE register of a TTY terminal identified by the
    52 // channel argument. If the channel argument is 0xFFFFFFFF, the channel
    53 // index is obtained from the current taxk context.
    54 // It doesn't use any interrupt.
     74// buffer to a TTY terminal identified by the channel argument.
     75// This function is intended to be used to handle a system call, and should
     76// not be used by the kernel for log messages on TTY 0.
     77// protecting exclusive access to the selected terminal.
     78// If channel argument is 0xFFFFFFFF, the TTY index is found in the task context.
    5579// This is a non blocking call: it tests the TTY_STATUS register, and stops
    5680// the transfer as soon as the TTY_STATUS[WRITE] bit is set.
     
    6286                         unsigned int channel)   // channel index
    6387{
    64     unsigned int nwritten;
    65     unsigned int tty_id;
    66     unsigned int* tty_address = (unsigned int *) &seg_tty_base;
    67 
    68     // compute tty channel
    69     if( channel == 0xFFFFFFFF )
    70     {
    71         tty_id = _get_context_slot(CTX_TTY_ID);
    72     }
    73     else
    74     {
    75         tty_id = (unsigned int)channel;
    76     }
     88    unsigned int  nwritten;
     89
     90    // compute and check tty channel
     91    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
     92    if( channel >= NB_TTY_CHANNELS ) return -1;
    7793
    7894    // write string to TTY channel
     
    8096    {
    8197        // check tty's status
    82         if ((tty_address[tty_id * TTY_SPAN + TTY_STATUS] & 0x2) == 0x2) break;
    83         _tty_write_data( tty_id, buffer[nwritten] );
    84     }
     98        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
     99
     100        // write one byte
     101        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
     102    }
     103   
    85104    return nwritten;
    86105}
     
    92111// It uses the TTY_GET_IRQ[tty_id] interrupt and the buffer must have been
    93112// filled by the TTY_ISR.
    94 // It test the _tty_get_full[tty_id] register, read the _tty_get_buf[tty_id]
     113// It test the _tty_rx_full[tty_id] variable, read the _tty_rx_buf[tty_id]
    95114// buffer, writes this character to the target buffer, and resets the
    96 // _tty_get_full[tty_id] register.
     115// _tty_rx_full[tty_id] register.
    97116// The length argument is not used.
    98117//////////////////////////////////////////////////////////////////////////////
     
    103122                        unsigned int channel)   // channel index
    104123{
    105    
    106     unsigned int tty_id;
    107 
    108     // compute tty channel
    109     if( channel == 0xFFFFFFFF )
    110     {
    111         tty_id = _get_context_slot(CTX_TTY_ID);
    112     }
    113     else
    114     {
    115         tty_id = (unsigned int)channel;
    116     }
     124    // compute and check tty channel
     125    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
     126    if( channel >= NB_TTY_CHANNELS ) return -1;
    117127
    118128    // read one character from TTY channel
    119     if (_tty_get_full[tty_id] == 0)
     129    if (_tty_rx_full[channel] == 0)
    120130    {
    121131        return 0;
     
    123133    else
    124134    {
    125         *buffer = _tty_get_buf[tty_id];
    126         _tty_get_full[tty_id] = 0;
     135        *buffer = _tty_rx_buf[channel];
     136        _tty_rx_full[channel] = 0;
    127137        return 1;
    128138    }
    129139}
    130 //////////////////////////////////////////////////////////////////////////////
    131 
    132 //////////////////////////////////////////////////////////////////////////////
    133 // This function try to take the hardwired lock protecting exclusive access
    134 // to TTY terminal identified by the channel argument.
     140
     141//////////////////////////////////////////////////////////////////////////////
     142// This function try to take the hardwired lock protecting
     143// exclusive access to TTY terminal identified by the "channel" argument.
     144// It enters a critical section before taking the lock, and save the SR value
     145// at address defined by the "save_sr_ptr" argument.
    135146// It returns only when the lock has been successfully taken.
    136147//////////////////////////////////////////////////////////////////////////////
    137 void _tty_get_lock( unsigned int channel )
    138 {
    139     unsigned int* tty_address = (unsigned int *) &seg_tty_base;
    140 
    141     if( channel >= NB_TTY_CHANNELS )
    142     {
    143         _puts("[GIET ERROR] in _tty_get_lock() : illegal TTY index\n");
    144         _exit();       
    145     }
    146 
    147     while ( tty_address[channel * TTY_SPAN + TTY_CONFIG] );
    148 }
    149 
    150 //////////////////////////////////////////////////////////////////////////////
    151 // This function releases the hardwired lock protecting exclusive access
    152 // to TTY terminal identified by the channel argument.
    153 //////////////////////////////////////////////////////////////////////////////
    154 void _tty_release_lock( unsigned int channel )
    155 {
    156     unsigned int* tty_address = (unsigned int *) &seg_tty_base;
    157 
    158     if( channel >= NB_TTY_CHANNELS )
    159     {
    160         _puts("[GIET ERROR] in _tty_release_lock() : illegal TTY index\n");
    161         _exit();       
    162     }
    163 
    164     tty_address[channel * TTY_SPAN + TTY_CONFIG] = 0;
    165 }
    166 
    167 //////////////////////////////////////////////////////////////////////////////
    168 // This function returns the content of the TTY_READ register in the
    169 // TTY terminal identified by the channel argument.
    170 //////////////////////////////////////////////////////////////////////////////
    171 unsigned int _tty_read_data( unsigned int channel )
    172 {
    173     unsigned int* tty_address = (unsigned int *) &seg_tty_base;
    174 
    175     if( channel >= NB_TTY_CHANNELS )
    176     {
    177         _puts("[GIET ERROR] in _tty_read_data() : illegal TTY index\n");
    178         _exit();       
    179     }
    180 
    181     return tty_address[channel * TTY_SPAN + TTY_READ];
    182 }
    183 
    184 //////////////////////////////////////////////////////////////////////////////
    185 // This function returns the content of the TTY_STATUS register in the
    186 // TTY terminal identified by the channel argument.
    187 //////////////////////////////////////////////////////////////////////////////
    188 unsigned int _tty_get_status( unsigned int channel )
    189 {
    190     unsigned int* tty_address = (unsigned int *) &seg_tty_base;
    191 
    192     if( channel >= NB_TTY_CHANNELS )
    193     {
    194         _puts("[GIET ERROR] in _tty_get_status() : illegal TTY index\n");
    195         _exit();       
    196     }
    197 
    198     return tty_address[channel * TTY_SPAN + TTY_STATUS];
    199 }
    200 
    201 //////////////////////////////////////////////////////////////////////////////
    202 // This function writes one character in the TTY_WRITE register in the
    203 // TTY terminal identified by the channel argument.
    204 //////////////////////////////////////////////////////////////////////////////
    205 void _tty_write_data( unsigned int channel,
    206                       char         byte )
    207 {
    208     unsigned int* tty_address = (unsigned int *) &seg_tty_base;
    209 
    210     if( channel >= NB_TTY_CHANNELS )
    211     {
    212         _puts("[GIET ERROR] in _tty_write_data() : illegal TTY index\n");
    213         _exit();       
    214     }
    215 
    216     tty_address[channel * TTY_SPAN + TTY_WRITE] = (unsigned int) byte;
    217 }
    218 
     148void _tty_get_lock( unsigned int   channel,
     149                    unsigned int * save_sr_ptr )
     150{
     151    if( channel >= NB_TTY_CHANNELS ) _exit();
     152    _it_disable( save_sr_ptr );
     153    while ( _tty_get_register( channel, TTY_CONFIG ) ); // busy waiting
     154}
     155
     156//////////////////////////////////////////////////////////////////////////////
     157// This function releases the hardwired lock protecting
     158// exclusive access to TTY terminal identified by the channel argument.
     159// It exit the critical section after lock release, and restore SR value
     160// from address defined by the "save_sr_ptr" argument.
     161//////////////////////////////////////////////////////////////////////////////
     162void _tty_release_lock( unsigned int   channel,
     163                        unsigned int * save_sr_ptr )
     164{
     165    if( channel >= NB_TTY_CHANNELS ) _exit();
     166
     167    _tty_set_register( channel, TTY_CONFIG, 0 );
     168    _it_restore( save_sr_ptr );
     169}
     170
     171///////////////////////////////////////////////////////////////////////////////////
     172// This ISR handles the IRQ signaling that the RX buffer is full.
     173// IT can be an HWI or an SWI.
     174// There is one single multi_tty component controling all channels.
     175// There is one communication buffer _tty_rx_buf[i] and one synchronisation
     176// variable _tty_rx_full[i] per channel.
     177// A character is lost if the buffer is full when the ISR is executed.
     178///////////////////////////////////////////////////////////////////////////////////
     179void _tty_rx_isr( unsigned int irq_type,   // HWI / WTI
     180                  unsigned int irq_id,     // index returned by XCU
     181                  unsigned int channel )   // TTY channel
     182{
     183    unsigned int cluster_xy = _get_procid() / NB_PROCS_MAX;
     184
     185    if ( irq_type == IRQ_TYPE_WTI )   // reset SWI in XCU if required
     186    {
     187        unsigned int value;
     188        _xcu_get_wti_value( cluster_xy, irq_id, &value );
     189    }
     190     
     191    // get character and reset TTY IRQ
     192    _tty_rx_buf[channel] = _tty_get_register( channel, TTY_READ );
     193
     194#if GIET_DEBUG_IRQS  // we don't take the TTY lock to avoid deadlock
     195unsigned int x              = cluster_xy >> Y_WIDTH;
     196unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
     197unsigned int lpid           = _get_procid() % NB_PROCS_MAX;
     198_puts("\n[IRQS DEBUG] Processor[");
     199_putd(x );
     200_puts(",");
     201_putd(y );
     202_puts(",");
     203_putd(lpid );
     204_puts("] enters _tty_rx_isr() at cycle ");
     205_putd(_get_proctime() );
     206_puts("\n  read byte = ");
     207_putx(_tty_rx_buf[channel] );
     208_puts("\n");
     209#endif
     210
     211    // signals character available
     212    _tty_rx_full[channel] = 1;
     213}
     214
     215///////////////////////////////////////////////////////////////////////////////////
     216// This ISR handles the IRQ signaling that the TX buffer is empty.
     217// IT can be an HWI or an SWI.
     218// There is one single multi_tty component controling all channels.
     219// There is one communication buffer _tty_rx_buf[i] and one synchronisation
     220// variable _tty_rx_full[i] per channel.
     221// A character is lost if the buffer is full when the ISR is executed.
     222///////////////////////////////////////////////////////////////////////////////////
     223void _tty_tx_isr( unsigned int irq_type,   // HWI / WTI
     224                  unsigned int irq_id,     // index returned by XCU
     225                  unsigned int channel )   // TTY channel
     226{
     227    _puts("\n[GIET ERROR] the _tty_tx_isr() is not implemented\n");
     228    _exit();
     229}
    219230
    220231// Local Variables:
  • soft/giet_vm/giet_drivers/tty_driver.h

    r258 r295  
    2424
    2525///////////////////////////////////////////////////////////////////////////////////
    26 // TTY access functions and variables
     26// TTY variables
    2727///////////////////////////////////////////////////////////////////////////////////
    2828
     
    3131extern volatile unsigned char _tty_get_full[];
    3232
    33 /////// rather high level access functions ///////////////////////////////////////
     33//////////////////////////////////////////////////////////////////////////////////
     34// TTY access functions
     35//////////////////////////////////////////////////////////////////////////////////
    3436
    3537extern unsigned int _tty_write( const char*  buffer,
    36                                 unsigned int length,     // number of characters
    37                                 unsigned int channel );  // channel index
     38                                unsigned int length,     
     39                                unsigned int channel ); 
    3840
    3941extern unsigned int _tty_read(  char*        buffer,
    40                                 unsigned int length,     // unused
    41                                 unsigned int channel );  // channel index
     42                                unsigned int length, 
     43                                unsigned int channel );
    4244
    43 /////// very low level access functions //////////////////////////////////////////
     45extern void _tty_get_lock( unsigned int  channel,
     46                           unsigned int* save_sr_ptr );
    4447
    45 extern void _tty_write_data( unsigned int channel, char byte );
     48extern void _tty_release_lock( unsigned int  channel,
     49                               unsigned int* save_sr_ptr );
    4650
    47 extern unsigned int _tty_read_data( unsigned int channel );
     51extern void _tty_rx_isr( unsigned int irq_type,
     52                         unsigned int irq_id,
     53                         unsigned int channel );
    4854
    49 extern unsigned int _tty_get_status( unsigned int channel );
    50 
    51 extern void _tty_get_lock( unsigned int channel );
    52 
    53 extern void _tty_release_lock( unsigned int channel );
     55extern void _tty_tx_isr( unsigned int irq_type,
     56                         unsigned int irq_id,
     57                         unsigned int channel );
    5458
    5559///////////////////////////////////////////////////////////////////////////////////
     60// low-level access functions
     61///////////////////////////////////////////////////////////////////////////////////
    5662
     63extern unsigned int _tty_get_register( unsigned int channel,
     64                                       unsigned int index );
     65
     66extern void _tty_set_register( unsigned int channel,
     67                               unsigned int index,
     68                               unsigned int value );
    5769
    5870#endif
  • soft/giet_vm/giet_drivers/xcu_driver.c

    r281 r295  
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
    7 // The xcu_driver.c and xcu_driver.h files are part ot the GIET-VM nano-kernel.
    8 // This driver supports the SoCLib vci_xicu, that is a vectorised interrupt
    9 // controler supporting IPI (Inter Processor Interrupts) and integrated timers.
    10 //
    11 // It can exist several interrupt controller unit in the architecture
    12 // (one per cluster), and each one can contain several channels.
    13 // The number of XICU channels is equal to NB_PROCS_MAX, because there is
    14 // one private XICU channel per processor in a cluster.
    15 ////////////////////////////////////////////////////////////////////////////////
    16 // The virtual base address of the segment associated to the component is:
    17 //
    18 //      seg_xcu_base + cluster_xy * vseg_cluster_increment
    19 //
    20 // The seg_xcu_base and vseg_cluster_increment values must be defined
    21 // in giet_vsegs.ld file.
    22 ////////////////////////////////////////////////////////////////////////////////
    237
    248#include <giet_config.h>
     
    5236#endif
    5337
    54 ////////////////////////////////////////////////////////////////////////////////
    55 //     _xcu_set_mask()
    56 // This function set the mask register for the XICU channel identified by the
    57 // cluster index and the processor index multiplied by the number of IRQ per
    58 // processor.
     38
     39////////////////////////////////////////////////////////////////////////////////
     40// This function set the mask register for the IRQ type defined by "irq_type",
     41// and for the channel identified by the "cluster_xy" and "channel" arguments.
    5942// All '1' bits are set / all '0' bits are not modified.
    60 // Returns 0 if success, > 0 if error.
    61 ////////////////////////////////////////////////////////////////////////////////
    62 unsigned int _xcu_set_mask( unsigned int cluster_xy,
    63                             unsigned int irq_index,
    64                             unsigned int value,
    65                             unsigned int irq_type )
    66 {
    67     // parameters checking
    68     unsigned int x = cluster_xy >> Y_WIDTH;
    69     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    70     if (x >= X_SIZE)                                     return 1;
    71     if (y >= Y_SIZE)                                     return 1;
    72     if (irq_index >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) return 1;
    73 
    74 #if USE_XICU
     43////////////////////////////////////////////////////////////////////////////////
     44void _xcu_set_mask( unsigned int cluster_xy,
     45                    unsigned int channel, 
     46                    unsigned int value,
     47                    unsigned int irq_type )
     48{
     49#if USE_XICU
     50    // parameters checking
     51    unsigned int x = cluster_xy >> Y_WIDTH;
     52    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     53    if (x >= X_SIZE)                                   _exit();
     54    if (y >= Y_SIZE)                                   _exit();
     55    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit();
     56
    7557    volatile unsigned int* xcu_address =
    7658        (unsigned int *) ((unsigned int)&seg_xcu_base +
     
    7961    unsigned int func;
    8062    if      (irq_type == IRQ_TYPE_PTI) func = XICU_MSK_PTI_ENABLE;
    81     else if (irq_type == IRQ_TYPE_SWI) func = XICU_MSK_WTI_ENABLE;
    82     else                               func = XICU_MSK_HWI_ENABLE;
    83     xcu_address[XICU_REG(func,irq_index)] = value;
    84     return 0;
    85 #else
    86     _tty_get_lock( 0 );
    87     _puts("[GIET ERROR] _xcu_set_mask should not be used if USE_XICU is not set\n");
    88     _tty_release_lock( 0 );
    89     return 1;
    90 #endif
    91 }
    92 
    93 ////////////////////////////////////////////////////////////////////////////////
    94 //     _xcu_get_index()
    95 // This function returns the index of the highest priority (smaller index)
    96 // - active HWI (Hardware Interrupt), or
    97 // - active PTI (Timer Interrupt), or
    98 // - active SWI (Software Interrupt).
    99 // The ICU channel is identified by the cluster index and the processor index
    100 // multiplied by the number of IRQ per processor.
    101 // Returns 0 if success, > 0 if error.
    102 ////////////////////////////////////////////////////////////////////////////////
    103 unsigned int _xcu_get_index( unsigned int cluster_xy,
    104                              unsigned int irq_index,
    105                              unsigned int * buffer)
    106 {
    107     // parameters checking
    108     unsigned int x = cluster_xy >> Y_WIDTH;
    109     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    110     if (x >= X_SIZE)                                     return 1;
    111     if (y >= Y_SIZE)                                     return 1;
    112     if (irq_index >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) return 1;
    113 
    114 #if USE_XICU
    115     volatile unsigned int* xcu_address =
    116         (unsigned int *) ((unsigned int)&seg_xcu_base +
    117         (cluster_xy * (unsigned int)&vseg_cluster_increment));
    118 
    119     unsigned int prio = xcu_address[XICU_REG(XICU_PRIO,irq_index)];
     63    else if (irq_type == IRQ_TYPE_WTI) func = XICU_MSK_WTI_ENABLE;
     64    else if (irq_type == IRQ_TYPE_HWI) func = XICU_MSK_HWI_ENABLE;
     65    else
     66    {
     67        _printf("[GIET ERROR] _xcu_set_mask() receives illegal IRQ type\n");
     68        _exit();
     69    }
     70
     71    xcu_address[XICU_REG(func,channel)] = value;
     72
     73#else
     74    _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XICU not set\n");
     75    _exit();
     76#endif
     77}
     78
     79////////////////////////////////////////////////////////////////////////////////
     80// This function returns the index and the type of the highest priority
     81// - active PTI (Timer Interrupt), then
     82// - active HWI (Hardware Interrupt), then
     83// - active WTI (Software Interrupt)
     84// As the hardware can define more than one IRQ per processor, but the GIET
     85// use only one, channel = lpid * IRQ_PER_PROCESSOR.
     86////////////////////////////////////////////////////////////////////////////////
     87void _xcu_get_index( unsigned int cluster_xy,
     88                     unsigned int channel,   
     89                     unsigned int * index,
     90                     unsigned int * irq_type )
     91{
     92#if USE_XICU
     93    // parameters checking
     94    unsigned int x = cluster_xy >> Y_WIDTH;
     95    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     96    if (x >= X_SIZE)                                   _exit();
     97    if (y >= Y_SIZE)                                   _exit();
     98    if (channel >= (NB_PROCS_MAX * IRQ_PER_PROCESSOR)) _exit();
     99
     100    volatile unsigned int* xcu_address =
     101        (unsigned int *) ((unsigned int)&seg_xcu_base +
     102        (cluster_xy * (unsigned int)&vseg_cluster_increment));
     103
     104    unsigned int prio = xcu_address[XICU_REG(XICU_PRIO,channel)];
    120105    unsigned int pti_ok = (prio & 0x00000001);
    121106    unsigned int hwi_ok = (prio & 0x00000002);
    122     unsigned int swi_ok = (prio & 0x00000004);
     107    unsigned int wti_ok = (prio & 0x00000004);
    123108    unsigned int pti_id = (prio & 0x00001F00) >> 8;
    124109    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
    125     unsigned int swi_id = (prio & 0x1F000000) >> 24;
    126     if      (pti_ok)  *buffer = pti_id;
    127     else if (hwi_ok)  *buffer = hwi_id;
    128     else if (swi_ok)  *buffer = swi_id;
    129     else              *buffer = 32;
    130     return 0;
    131 #else
    132     _tty_get_lock( 0 );
    133     _puts("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n");
    134     _tty_release_lock( 0 );
    135     return 1;
    136 #endif
    137 }
    138 
    139 ////////////////////////////////////////////////////////////////////////////////
    140 //     _xcu_send_ipi()
    141 // This function can be used only in an architecture using  XICU components.
    142 // It writes the "wdata" value in the mailbox defined by the cluster index
    143 // and the processor index.
    144 // Giet-VM supports at most NB_PROCS_MAX mailboxes:
    145 // (0 <= wti_index <= NB_PROCS_MAX-1)
    146 // Returns 0 if success, > 0 if error.
    147 ////////////////////////////////////////////////////////////////////////////////
    148 unsigned int _xcu_send_ipi( unsigned int cluster_xy,
    149                             unsigned int wti_index,
    150                             unsigned int wdata )
     110    unsigned int wti_id = (prio & 0x1F000000) >> 24;
     111    if      (pti_ok)
     112    {
     113        *index    = pti_id;
     114        *irq_type = IRQ_TYPE_PTI;
     115    }
     116    else if (hwi_ok)
     117    {
     118        *index    = hwi_id;
     119        *irq_type = IRQ_TYPE_HWI;
     120    }
     121    else if (wti_ok)
     122    {
     123        *index    = wti_id;
     124        *irq_type = IRQ_TYPE_WTI;
     125    }
     126    else
     127    {
     128        *index = 32;
     129    }
     130 
     131#else
     132    _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n");
     133    _exit();
     134#endif
     135}
     136
     137////////////////////////////////////////////////////////////////////////////////
     138// This function writes the "wdata" value in the mailbox defined
     139// by the "cluster_xy" and "wti_index" arguments.
     140////////////////////////////////////////////////////////////////////////////////
     141void _xcu_send_wti( unsigned int cluster_xy,
     142                    unsigned int wti_index,
     143                    unsigned int wdata )
    151144{
    152     // parameters checking
    153     unsigned int x = cluster_xy >> Y_WIDTH;
    154     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    155     if (x >= X_SIZE)               return 1;
    156     if (y >= Y_SIZE)               return 1;
    157     if (wti_index >= NB_PROCS_MAX) return 1;
    158 
    159 #if USE_XICU
     145#if USE_XICU
     146    // parameters checking
     147    unsigned int x = cluster_xy >> Y_WIDTH;
     148    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     149    if (x >= X_SIZE)               _exit();
     150    if (y >= Y_SIZE)               _exit();
     151    if (wti_index >= 32)           _exit();
     152
    160153    volatile unsigned int* xcu_address =
    161154        (unsigned int *) ((unsigned int)&seg_xcu_base +
     
    163156
    164157    xcu_address[XICU_REG(XICU_WTI_REG,wti_index)] = wdata;
    165     return 0;
    166 #else
    167     _tty_get_lock( 0 );
    168     _puts("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n");
    169     _tty_release_lock( 0 );
    170     return 1;
     158
     159#else
     160    _printf("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n");
     161    _exit();
    171162#endif
    172163}
    173164
    174165////////////////////////////////////////////////////////////////////////////////
    175 //    _xcu_timer_start()
     166// This function returns the value contained in a WTI mailbox defined by
     167// the cluster_xy and "wti_index" arguments. This value is written in
     168// the "value" argument, and the corresponding WTI is acknowledged.
     169// returns 0 if success, > 0 if error.
     170////////////////////////////////////////////////////////////////////////////////
     171void _xcu_get_wti_value( unsigned int   cluster_xy,
     172                         unsigned int   wti_index,
     173                         unsigned int * value )
     174{
     175#if USE_XICU
     176    // parameters checking
     177    unsigned int x = cluster_xy >> Y_WIDTH;
     178    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     179    if (x >= X_SIZE)               _exit();
     180    if (y >= Y_SIZE)               _exit();
     181    if (wti_index >= 32)           _exit();
     182 
     183    volatile unsigned int* xcu_address =
     184        (unsigned int *) ((unsigned int)&seg_xcu_base +
     185        (cluster_xy * (unsigned int)&vseg_cluster_increment));
     186
     187    *value = xcu_address[XICU_REG(XICU_WTI_REG, wti_index)];
     188
     189#else
     190    _printf("[GIET ERROR] in _xcu_get_wti_value() USE_XICU is not set\n");
     191    _exit();
     192#endif
     193}
     194
     195////////////////////////////////////////////////////////////////////////////////
     196// This function returns the address of a WTI mailbox defined by
     197// the "wti_index" argument, in the unsigned int "address" argument.
     198// It is used by the GIET to configurate the IOPIC component.
     199// There is no access to a specific XCU component in a specific cluster.
     200// returns 0 if success, > 0 if error.
     201////////////////////////////////////////////////////////////////////////////////
     202void _xcu_get_wti_address( unsigned int   wti_index,
     203                           unsigned int * address )
     204{
     205#if USE_XICU
     206    if (wti_index >= 32)           _exit();
     207 
     208    unsigned int xcu_address = (unsigned int)&seg_xcu_base;
     209    *address = xcu_address + (XICU_REG(XICU_WTI_REG, wti_index)<<2);
     210
     211#else
     212    _printf("[GIET ERROR] in _xcu_get_wti_address() USE_XICU is not set\n");
     213    _exit();
     214#endif
     215}
     216
     217////////////////////////////////////////////////////////////////////////////////
    176218// This function activates a timer contained in XICU by writing in the
    177219// proper register the period value.
    178 // Returns 0 if success, > 0 if error.
    179 ////////////////////////////////////////////////////////////////////////////////
    180 unsigned int _xcu_timer_start( unsigned int cluster_xy,
    181                                unsigned int pti_index,
    182                                unsigned int period )
    183 {
    184     // parameters checking
    185     unsigned int x = cluster_xy >> Y_WIDTH;
    186     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    187     if (x >= X_SIZE)             return 1;
    188     if (y >= Y_SIZE)             return 1;
    189 
    190 #if USE_XICU
     220////////////////////////////////////////////////////////////////////////////////
     221void _xcu_timer_start( unsigned int cluster_xy,
     222                       unsigned int pti_index,
     223                       unsigned int period )
     224{
     225#if USE_XICU
     226    // parameters checking
     227    unsigned int x = cluster_xy >> Y_WIDTH;
     228    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     229    if (x >= X_SIZE)             _exit();
     230    if (y >= Y_SIZE)             _exit();
     231
    191232    volatile unsigned int* xcu_address =
    192233        (unsigned int *) ((unsigned int)&seg_xcu_base +
     
    194235
    195236    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period;
    196     return 0;
    197 #else
    198     _tty_get_lock( 0 );
    199     _puts("[GIET ERROR] _xcu_timer_start should not be used if USE_XICU is not set\n");
    200     _tty_release_lock( 0 );
    201     return 1;
    202 #endif
    203 }
    204 
    205 //////////////////////////////////////////////////////////////////////////////
    206 //     _xcu_timer_stop()
     237
     238#else
     239    _printf("[GIET ERROR] in _xcu_timer_start() USE_XICU is not set\n");
     240    _exit();
     241#endif
     242}
     243
     244//////////////////////////////////////////////////////////////////////////////
    207245// This function desactivates a timer in XICU component
    208246// by writing in the proper register.
    209 // Returns 0 if success, > 0 if error.
    210 //////////////////////////////////////////////////////////////////////////////
    211 unsigned int _xcu_timer_stop( unsigned int cluster_xy,
    212                               unsigned int pti_index)
    213 {
    214     // parameters checking
    215     unsigned int x = cluster_xy >> Y_WIDTH;
    216     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    217     if (x >= X_SIZE)             return 1;
    218     if (y >= Y_SIZE)             return 1;
    219 
    220 #if USE_XICU
     247//////////////////////////////////////////////////////////////////////////////
     248void _xcu_timer_stop( unsigned int cluster_xy,
     249                      unsigned int pti_index)
     250{
     251#if USE_XICU
     252    // parameters checking
     253    unsigned int x = cluster_xy >> Y_WIDTH;
     254    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     255    if (x >= X_SIZE)             _exit();
     256    if (y >= Y_SIZE)             _exit();
     257
    221258    volatile unsigned int * xcu_address =
    222259        (unsigned int *) ((unsigned int)&seg_xcu_base +
     
    224261
    225262    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0;
    226     return 0;
    227 #else
    228     _tty_get_lock( 0 );
    229     _puts("[GIET ERROR] _xcu_timer_stop should not be used if USE_XICU is not set\n");
    230     _tty_release_lock( 0 );
    231     return 1;
    232 #endif
    233 }
    234 
    235 //////////////////////////////////////////////////////////////////////////////
    236 //     _xcu_timer_reset_irq()
     263
     264#else
     265    _printf("[GIET ERROR] in _xcu_timer_stop() USE_XICU is not set\n");
     266    _exit();
     267#endif
     268}
     269
     270//////////////////////////////////////////////////////////////////////////////
    237271// This function acknowlegge a timer interrupt in XICU
    238272// component by reading in the proper register.
    239273// It can be used by both the isr_switch() for a "system" timer,
    240274// or by the _isr_timer() for an "user" timer.
    241 // Returns 0 if success, > 0 if error.
    242 //////////////////////////////////////////////////////////////////////////////
    243 unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy,
    244                                    unsigned int pti_index )
    245 {
    246     // parameters checking
    247     unsigned int x = cluster_xy >> Y_WIDTH;
    248     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    249     if (x >= X_SIZE)             return 1;
    250     if (y >= Y_SIZE)             return 1;
    251 
    252 #if USE_XICU
     275//////////////////////////////////////////////////////////////////////////////
     276void _xcu_timer_reset_irq( unsigned int cluster_xy,
     277                           unsigned int pti_index )
     278{
     279#if USE_XICU
     280    // parameters checking
     281    unsigned int x = cluster_xy >> Y_WIDTH;
     282    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     283    if (x >= X_SIZE)             _exit();
     284    if (y >= Y_SIZE)             _exit();
     285
    253286    volatile unsigned int * xcu_address =
    254287        (unsigned int *) ((unsigned int)&seg_xcu_base +
     
    256289
    257290    xcu_address[XICU_REG(XICU_PTI_ACK, pti_index)];
    258     return 0;
    259 #else
    260     _tty_get_lock( 0 );
    261     _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n");
    262     _tty_release_lock( 0 );
    263     return 1;
    264 #endif
    265 }
    266 
    267 //////////////////////////////////////////////////////////////////////////////
    268 //     _xcu_timer_reset_cpt()
     291
     292#else
     293    _printf("[GIET ERROR] in _xcu_timer_reset_irq() USE_XICU is not set\n");
     294    _exit();
     295#endif
     296}
     297
     298//////////////////////////////////////////////////////////////////////////////
    269299// This function resets a timer counter. To do so, we re-write the period
    270300// in the proper register, what causes the count to restart.
    271301// The period value is read from the same (TIMER_PERIOD) register,
    272302// this is why in appearance we do nothing useful (read a value
    273 // from a register and write this value in the same register)
     303// from a register and write this value in the same register).
    274304// This function is called during a context switch (user or preemptive)
    275305/////////////////////////////////////////////////////////////////////////////
    276 unsigned int _xcu_timer_reset_cpt( unsigned int cluster_xy,
    277                                    unsigned int pti_index )
    278 {
    279     // parameters checking
    280     unsigned int x = cluster_xy >> Y_WIDTH;
    281     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    282     if (x >= X_SIZE)             return 1;
    283     if (y >= Y_SIZE)             return 1;
    284 
    285 #if USE_XICU
     306void _xcu_timer_reset_cpt( unsigned int cluster_xy,
     307                           unsigned int pti_index )
     308{
     309#if USE_XICU
     310    // parameters checking
     311    unsigned int x = cluster_xy >> Y_WIDTH;
     312    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     313    if (x >= X_SIZE)             _exit();
     314    if (y >= Y_SIZE)             _exit();
     315
    286316    volatile unsigned int * xcu_address =
    287317        (unsigned int *) ((unsigned int) &seg_xcu_base +
     
    294324    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0;
    295325    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period;
    296     return 0;
    297 #else
    298     _tty_get_lock( 0 );
    299     _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n");
    300     _tty_release_lock( 0 );
    301     return 1;
     326
     327#else
     328    _printf("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XICU is not set\n");
     329    _exit();
    302330#endif
    303331}
  • soft/giet_vm/giet_drivers/xcu_driver.h

    r281 r295  
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
     7// The xcu_driver.c and xcu_driver.h files are part ot the GIET-VM nano-kernel.
     8// This driver supports the SoCLib vci_xicu, that is a vectorised interrupt
     9// controler supporting IPI (Inter Processor Interrupts) and integrated timers.
     10//
     11// It can exist several interrupt controller unit in the architecture
     12// (one per cluster), and each one can contain several channels.
     13// The number of XICU channels is equal to NB_PROCS_MAX, because there is
     14// one private XICU channel per processor in a cluster.
     15////////////////////////////////////////////////////////////////////////////////
     16// The virtual base address of the segment associated to the component is:
     17//
     18//      seg_xcu_base + cluster_xy * vseg_cluster_increment
     19//
     20// The seg_xcu_base and vseg_cluster_increment values must be defined
     21// in giet_vsegs.ld file.
     22////////////////////////////////////////////////////////////////////////////////
    723
    824#ifndef _GIET_XCU_DRIVER_H_
     
    4460///////////////////////////////////////////////////////////////////////////////////
    4561
    46 extern unsigned int _xcu_get_index( unsigned int cluster_xy,
    47                                     unsigned int irq_index,
    48                                     unsigned int * buffer );
     62extern void _xcu_set_mask( unsigned int cluster_xy,
     63                           unsigned int channel, 
     64                           unsigned int mask,
     65                           unsigned int irq_type );
    4966
    50 extern unsigned int _xcu_set_mask( unsigned int cluster_xy,
    51                                    unsigned int irq_index,
    52                                    unsigned int mask,
    53                                    unsigned int is_timer );
     67extern void _xcu_get_index( unsigned int   cluster_xy,
     68                            unsigned int   channel,   
     69                            unsigned int * index,
     70                            unsigned int * irq_type );
    5471
    55 extern unsigned int _xcu_send_ipi( unsigned int cluster_xy,
    56                                    unsigned int wti_index,
    57                                    unsigned int wdata );
     72extern void _xcu_send_wti( unsigned int cluster_xy,
     73                           unsigned int wti_index,
     74                           unsigned int wdata );
    5875
    59 extern unsigned int _xcu_timer_start( unsigned int cluster_xy,
    60                                       unsigned int pti_index,
    61                                       unsigned int period );
     76extern void _xcu_get_wti_value( unsigned int   cluster_xy,
     77                                unsigned int   wti_index,
     78                                unsigned int * value );
    6279
    63 extern unsigned int _xcu_timer_stop( unsigned int cluster_xy,
    64                                      unsigned int pti_index );
     80extern void _xcu_get_wti_address( unsigned int   wti_index,
     81                                  unsigned int * address );
    6582
    66 extern unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy,
    67                                           unsigned int pti_index );
     83extern void _xcu_timer_start( unsigned int cluster_xy,
     84                              unsigned int pti_index,
     85                              unsigned int period );
    6886
    69 extern unsigned int _xcu_timer_reset_cpt( unsigned int cluster_xy,
    70                                           unsigned int pti_index );
     87extern void _xcu_timer_stop( unsigned int cluster_xy,
     88                             unsigned int pti_index );
     89
     90extern void _xcu_timer_reset_irq( unsigned int cluster_xy,
     91                                  unsigned int pti_index );
     92
     93extern void _xcu_timer_reset_cpt( unsigned int cluster_xy,
     94                                  unsigned int pti_index );
    7195
    7296///////////////////////////////////////////////////////////////////////////////////
Note: See TracChangeset for help on using the changeset viewer.