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

Last change on this file since 542 was 529, checked in by alain, 10 years ago

1) Removing the IOC driver (integrated in the FAT library).
2) Simplifying the BDV, HBA, SDC, RDK drivers: they support
only two modes (synchronous => polling / descheduling => IRQ),
and only one access function (for both read/write).

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