source: soft/giet_vm/giet_drivers/bdv_driver.c @ 605

Last change on this file since 605 was 593, checked in by alain, 9 years ago

Bloup

File size: 9.6 KB
RevLine 
[283]1///////////////////////////////////////////////////////////////////////////////////
[284]2// File      : bdv_driver.c
3// Date      : 23/05/2013
[529]4// Author    : alain greiner cesar fuguet
[283]5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[295]7// Implementation notes:
[529]8// All accesses to BDV registers are done by the two
9// _bdv_set_register() and _bdv_get_register() low-level functions,
10// that are handling virtual / physical extended addressing.
[283]11///////////////////////////////////////////////////////////////////////////////////
12
13#include <giet_config.h>
[320]14#include <hard_config.h>
[295]15#include <bdv_driver.h>
16#include <xcu_driver.h>
[545]17#include <mmc_driver.h>
[529]18#include <kernel_locks.h>
[283]19#include <utils.h>
[456]20#include <tty0.h>
[283]21#include <ctx_handler.h>
[529]22#include <irq_handler.h>
[283]23
24///////////////////////////////////////////////////////////////////////////////
[529]25//      Global variables
[295]26///////////////////////////////////////////////////////////////////////////////
27
[529]28// lock protecting single channel BDV peripheral
[496]29__attribute__((section(".kdata")))
[456]30spin_lock_t  _bdv_lock __attribute__((aligned(64)));
[496]31
[529]32// global index of the waiting task (only used in descheduling mode)
[496]33__attribute__((section(".kdata")))
[529]34unsigned int _bdv_gtid;
[496]35
[529]36// BDV peripheral status (only used in descheduling mode)
[496]37__attribute__((section(".kdata")))
[529]38unsigned int _bdv_status;
[295]39
40///////////////////////////////////////////////////////////////////////////////
41// This low_level function returns the value contained in register (index).
42///////////////////////////////////////////////////////////////////////////////
43unsigned int _bdv_get_register( unsigned int index )
44{
[320]45    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
[295]46    return _io_extended_read( vaddr );
47}
48
49///////////////////////////////////////////////////////////////////////////////
50// This low-level function set a new value in register (index).
51///////////////////////////////////////////////////////////////////////////////
52void _bdv_set_register( unsigned int index,
53                        unsigned int value ) 
54{
[320]55    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
[295]56    _io_extended_write( vaddr, value );
57}
58
59///////////////////////////////////////////////////////////////////////////////
[529]60//      Extern functions
[283]61///////////////////////////////////////////////////////////////////////////////
[529]62
63/////////////////////////////////////////////////////
64unsigned int _bdv_access( unsigned int       use_irq,
65                          unsigned int       to_mem,
66                          unsigned int       lba,
67                          unsigned long long buf_paddr,
68                          unsigned int       count) 
[283]69{
[426]70    unsigned int procid  = _get_procid();
71    unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
72    unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1);
73    unsigned int p       = procid & ((1<<P_WIDTH)-1);
[283]74
[593]75#if GIET_DEBUG_IOC
76if ( _get_proctime() > GIET_DEBUG_IOC )
[529]77_printf("\n[BDV DEBUG] P[%d,%d,%d] enters _bdv_access at cycle %d\n"
78        "  use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n",
79        x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count );
[283]80#endif
81
[529]82    // check buffer alignment
[593]83    if( buf_paddr & 0x3F )
[529]84    {
[593]85        _printf("\n[BDV ERROR] in _bdv_access() : buffer not cache ligne aligned\n");
[529]86        return -1;
87    }
[283]88
[529]89    unsigned int error;
90    unsigned int status;
91
[295]92    // get the lock protecting BDV
[469]93    _spin_lock_acquire( &_bdv_lock );
[283]94
[295]95    // set device registers
96    _bdv_set_register( BLOCK_DEVICE_BUFFER    , (unsigned int)buf_paddr );
97    _bdv_set_register( BLOCK_DEVICE_BUFFER_EXT, (unsigned int)(buf_paddr>>32) );
98    _bdv_set_register( BLOCK_DEVICE_COUNT     , count );
99    _bdv_set_register( BLOCK_DEVICE_LBA       , lba );
[283]100
[545]101#if USE_IOB    // software L2/L3 cache coherence
102    if ( to_mem )  _mmc_inval( buf_paddr, count<<9 );
103    else           _mmc_sync( buf_paddr, count<<9 );
104#endif     // end software L2/L3 cache coherence
105
[529]106    /////////////////////////////////////////////////////////////////////
107    // In synchronous mode, we launch transfer,
108    // and poll the BDV_STATUS register until completion.
109    /////////////////////////////////////////////////////////////////////
110    if ( use_irq == 0 ) 
[283]111    {
112        // Launch transfert
[295]113        if (to_mem == 0) _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_WRITE );
114        else             _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_READ );
[283]115
[593]116#if GIET_DEBUG_IOC
117if ( _get_proctime() > GIET_DEBUG_IOC )
[529]118_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] launch transfer"
119        " in polling mode at cycle %d\n",
120        x , y , p , _get_proctime() );
[333]121#endif
[529]122
[289]123        do
[283]124        {
[295]125            status = _bdv_get_register( BLOCK_DEVICE_STATUS );
[283]126
[593]127#if GIET_DEBUG_IOC
128if ( _get_proctime() > GIET_DEBUG_IOC )
[529]129_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] wait on BDV_STATUS ...\n",
130        x , y , p );
[283]131#endif
[289]132        }
133        while( (status != BLOCK_DEVICE_READ_SUCCESS)  &&
134               (status != BLOCK_DEVICE_READ_ERROR)    &&
135               (status != BLOCK_DEVICE_WRITE_SUCCESS) &&
[295]136               (status != BLOCK_DEVICE_WRITE_ERROR)   );      // busy waiting
[283]137
138        // analyse status
139        error = ( (status == BLOCK_DEVICE_READ_ERROR) ||
140                  (status == BLOCK_DEVICE_WRITE_ERROR) );
[529]141    }
[283]142
[529]143    /////////////////////////////////////////////////////////////////
144    // in descheduling mode, we deschedule the task
145    // and use an interrupt to reschedule the task.
[295]146    // We need a critical section, because we must reset the RUN bit
[529]147        // before to launch the transfer, and we don't want to be
148    // descheduled between these two operations.
149    /////////////////////////////////////////////////////////////////
[295]150    else
[283]151    {
[295]152        unsigned int save_sr;
153        unsigned int ltid = _get_current_task_id();
[283]154
[529]155        // activates BDV interrupt
[295]156        _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 1 );
157
[545]158        // set _bdv_gtid
159        _bdv_gtid = (procid<<16) + ltid;
160
[295]161        // enters critical section
162        _it_disable( &save_sr ); 
[320]163
[545]164        // reset runnable
[426]165        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
[283]166       
[295]167        // launch transfer
168        if (to_mem == 0) _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_WRITE );
169        else             _bdv_set_register( BLOCK_DEVICE_OP, BLOCK_DEVICE_READ  );
[283]170
[593]171#if GIET_DEBUG_IOC
172if ( _get_proctime() > GIET_DEBUG_IOC )
[529]173_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] launch transfer"
174        " in descheduling mode at cycle %d\n",
175        x , y , p , _get_proctime() );
[333]176#endif
[437]177
[283]178        // deschedule task
179        _ctx_switch();                     
180
[593]181#if GIET_DEBUG_IOC
182if ( _get_proctime() > GIET_DEBUG_IOC )
[529]183_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] resume execution at cycle %d\n",
184        x , y , p , _get_proctime() );
[426]185#endif
[529]186
[295]187        // restore SR
188        _it_restore( &save_sr );
189
[283]190        // analyse status
[295]191        error = ( (_bdv_status == BLOCK_DEVICE_READ_ERROR) ||
192                  (_bdv_status == BLOCK_DEVICE_WRITE_ERROR) );
[283]193    }
194
[529]195    // release lock
196    _spin_lock_release( &_bdv_lock );     
197
[593]198#if GIET_DEBUG_IOC
199if ( _get_proctime() > GIET_DEBUG_IOC )
[529]200_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] exit at cycle %d\n",
201        x , y , p , _get_proctime() );
[283]202#endif
203
204    return error;
205} // end _bdv_access()
206
[437]207////////////////////////
[295]208unsigned int _bdv_init()
[283]209{
[295]210    if ( _bdv_get_register( BLOCK_DEVICE_BLOCK_SIZE ) != 512 )
[283]211    {
[437]212        _puts("\n[GIET ERROR] in _bdv_init() : block size must be 512 bytes\n");
[283]213        return 1; 
214    }
215
[295]216    _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 0 );
[283]217    return 0;
218}
219
[437]220/////////////////////////////////////
[295]221void _bdv_isr( unsigned int irq_type,   // HWI / WTI
222               unsigned int irq_id,     // index returned by ICU
223               unsigned int channel )   // unused
224{
[529]225    // get BDV status and reset BDV_IRQ
[297]226    unsigned int status =  _bdv_get_register( BLOCK_DEVICE_STATUS ); 
[295]227
[297]228    // check status: does nothing if IDLE or BUSY
229    if ( (status == BLOCK_DEVICE_IDLE) ||
230         (status == BLOCK_DEVICE_BUSY) )   return;
231 
[529]232    // register status in global variable
233    _bdv_status = status;
[295]234
235    // identify task waiting on BDV
[426]236    unsigned int remote_procid  = _bdv_gtid>>16;
237    unsigned int ltid           = _bdv_gtid & 0xFFFF;
238    unsigned int remote_cluster = remote_procid >> P_WIDTH;
239    unsigned int remote_x       = remote_cluster >> Y_WIDTH;
240    unsigned int remote_y       = remote_cluster & ((1<<Y_WIDTH)-1);
241    unsigned int remote_p       = remote_procid & ((1<<P_WIDTH)-1);
[295]242
[297]243    // re-activates sleeping task
[426]244    _set_task_slot( remote_x,
245                    remote_y,
246                    remote_p,
247                    ltid,       
[297]248                    CTX_RUN_ID,  // CTX_RUN slot
[529]249                    1 );         // running value
[297]250
[529]251    // send a WAKUP WTI to processor running the sleeping task
[426]252    _xcu_send_wti( remote_cluster,   
253                   remote_p, 
[529]254                   0 );          // don't force context switch
[297]255
[593]256#if GIET_DEBUG_IOC 
[426]257unsigned int procid  = _get_procid();
258unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
259unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
260unsigned int p       = procid & ((1<<P_WIDTH)-1);
[593]261if ( _get_proctime() > GIET_DEBUG_IOC )
[563]262_printf("\n[BDV DEBUG] Processor[%d,%d,%d] enters _bdv_isr() at cycle %d\n"
[529]263        "  for task %d running on P[%d,%d,%d] / bdv_status = %x\n",
264        x , y , p , _get_proctime() ,
265        ltid , remote_x , remote_y , remote_p , status );
[295]266#endif
267
[529]268} // end bdv_isr()
[295]269
270
[283]271// Local Variables:
272// tab-width: 4
273// c-basic-offset: 4
274// c-file-offsets:((innamespace . 0)(inline-open . 0))
275// indent-tabs-mode: nil
276// End:
277// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
278
Note: See TracBrowser for help on using the repository browser.