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

Last change on this file since 553 was 545, checked in by alain, 10 years ago

Cosmetic

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