source: soft/giet_vm/giet_drivers/hba_driver.c @ 539

Last change on this file since 539 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: 11.9 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : hba_driver.c
3// Date     : 23/11/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// Implementation notes:
8// All accesses to HBA registers are done by the two
9// _hba_set_register() and _hba_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 <hba_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#include <vmem.h>
23
24///////////////////////////////////////////////////////////////////////////////////
25//               Global variables
26///////////////////////////////////////////////////////////////////////////////////
27
28// global index ot the task, for each entry in the command list
29__attribute__((section(".kdata")))
30unsigned int _hba_gtid[32];
31
32// status of the command, for each entry in the command list
33__attribute__((section(".kdata")))
34unsigned int _hba_status[32];
35
36// command list : up to 32 commands
37__attribute__((section(".kdata")))
38hba_cmd_desc_t  _hba_cmd_list[32] __attribute__((aligned(0x1000)));   
39
40// command tables array : one command table per entry in command list
41__attribute__((section(".kdata")))
42hba_cmd_table_t _hba_cmd_table[32] __attribute__((aligned(0x1000))); 
43
44// command list write index : next slot to register a command
45__attribute__((section(".kdata")))
46unsigned int     _hba_cmd_ptw;
47
48// command list read index : next slot to poll a completed command
49__attribute__((section(".kdata")))
50unsigned int     _hba_cmd_ptr;
51
52//////////////////////////////////////////////////////////////////////////////
53// This low level function returns the value of register (index)
54//////////////////////////////////////////////////////////////////////////////
55unsigned int _hba_get_register( unsigned int index )
56{
57    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
58    return _io_extended_read( vaddr );
59}
60
61//////////////////////////////////////////////////////////////////////////////
62// This low level function set a new value in register (index) 
63//////////////////////////////////////////////////////////////////////////////
64void _hba_set_register( unsigned int index,
65                        unsigned int value )
66{
67    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
68    _io_extended_write( vaddr, value );
69}
70
71///////////////////////////////////////////////////////////////////////////////
72//      Extern functions
73///////////////////////////////////////////////////////////////////////////////
74
75///////////////////////////////////////////////////////////////////////////////
76// This function register a command in both the command list
77// and the command table, and updates the HBA_PXCI register.
78// return 0 if success, -1 if error
79///////////////////////////////////////////////////////////////////////////////
80unsigned int _hba_access( unsigned int       use_irq,
81                          unsigned int       to_mem,
82                          unsigned int       lba, 
83                          unsigned long long buf_paddr,
84                          unsigned int       count )   
85{
86    unsigned int procid  = _get_procid();
87    unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
88    unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1);
89    unsigned int p       = procid & ((1<<P_WIDTH)-1);
90
91#if GIET_DEBUG_IOC_DRIVER
92_printf("\n[HBA DEBUG] P[%d,%d,%d] enters _hba_access at cycle %d\n"
93        "  use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n",
94        x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count );
95#endif
96
97    unsigned int       pxci;           // HBA_PXCI register value
98    unsigned int       ptw;            // command list write pointer
99    unsigned int       pxis;           // HBA_PXIS register value
100    hba_cmd_desc_t*    cmd_desc;       // command descriptor pointer   
101    hba_cmd_table_t*   cmd_table;      // command table pointer
102
103    // check buffer alignment
104    if( buf_paddr & 0x1FF )
105    {
106        _printf("\n[HBA ERROR] in _hba_access() : buffer not block aligned\n");
107        return -1;
108    }
109
110    // get pointer on the next possible entry in command list
111    ptw = _atomic_increment( &_hba_cmd_ptw , 1 );
112
113    // poll PXCI register until pointed entry empty
114    do
115    {
116        // get PXCI register
117        pxci = _hba_get_register( HBA_PXCI );
118    } 
119    while ( pxci & (1<<ptw) );
120   
121    // compute pointers on command descriptor and command table   
122    cmd_desc  = &_hba_cmd_list[ptw];
123    cmd_table = &_hba_cmd_table[ptw];
124
125    // set  buffer descriptor in command table
126    cmd_table->entry[0].dba  = (unsigned int)(buf_paddr);
127    cmd_table->entry[0].dbau = (unsigned int)(buf_paddr >> 32);
128    cmd_table->entry[0].dbc  = count * 512;
129
130    // initialize command table header
131    cmd_table->header.lba0 = (char)lba;
132    cmd_table->header.lba1 = (char)(lba>>8);
133    cmd_table->header.lba2 = (char)(lba>>16);
134    cmd_table->header.lba3 = (char)(lba>>24);
135    cmd_table->header.lba4 = 0;
136    cmd_table->header.lba5 = 0;
137
138    // initialise command descriptor
139    cmd_desc->prdtl[0] = 1;
140    cmd_desc->prdtl[1] = 0;
141    if( to_mem ) cmd_desc->flag[0] = 0x00;
142    else         cmd_desc->flag[0] = 0x40;     
143   
144    // set command in PXCI[ptw]
145    _hba_set_register( HBA_PXCI, pxci + (1<<ptw) );
146
147
148    /////////////////////////////////////////////////////////////////////
149    // In synchronous mode, we poll the PXCI register until completion
150    /////////////////////////////////////////////////////////////////////
151    if ( use_irq == 0 ) 
152    {
153
154#if GIET_DEBUG_IOC_DRIVER
155_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer"
156        " in polling mode at cycle %d\n",
157        x , y , p , _get_proctime() );
158#endif
159        // disable IRQs in PXIE register
160        _hba_set_register( HBA_PXIE , 0 );
161
162        // poll PXCI[ptw] until command completed by HBA
163        do
164        {
165            pxci = _hba_get_register( HBA_PXCI ) & (1<<ptw);
166
167#if GIET_DEBUG_IOC_DRIVER
168_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] wait on HBA_STATUS ...\n",
169        x , y , p );
170#endif
171        }
172        while( pxci & (1<<ptw) ); 
173             
174        // get PXIS register
175        pxis = _hba_get_register( HBA_PXIS );
176
177        // reset PXIS register
178        _hba_set_register( HBA_PXIS , 0 );
179    }
180
181    /////////////////////////////////////////////////////////////////
182    // in descheduling mode, we deschedule the task
183    // and use an interrupt to reschedule the task.
184    // We need a critical section, because we must reset the RUN bit
185        // before to launch the transfer, and we don't want to be
186    // descheduled between these two operations.
187    /////////////////////////////////////////////////////////////////
188    else
189    {
190
191#if GIET_DEBUG_IOC_DRIVER
192_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer"
193        " in descheduling mode at cycle %d\n",
194        x , y , p , _get_proctime() );
195#endif
196        unsigned int save_sr;
197        unsigned int ltid = _get_current_task_id();
198
199        // activates HBA interrupts
200        _hba_set_register( HBA_PXIE , 0x00000001 ); 
201
202        // set _hba_gtid[ptw]
203        _hba_gtid[ptw] = (procid<<16) + ltid;
204
205        // enters critical section
206        _it_disable( &save_sr ); 
207
208        // reset runnable
209        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
210
211        // deschedule task
212        _ctx_switch();                     
213
214#if GIET_DEBUG_IOC_DRIVER
215_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] resume execution at cycle %d\n",
216        x , y , p , _get_proctime() );
217#endif
218
219        // restore SR
220        _it_restore( &save_sr );
221
222        // get command status
223        pxis = _hba_status[ptw];
224    }   
225
226#if GIET_DEBUG_IOC_DRIVER
227_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] exit at cycle %d\n",
228        x , y , p , _get_proctime() );
229#endif
230
231    if ( pxis & 0x40000000 ) return pxis;
232    else                     return 0;
233
234} // end _hba_access()
235
236
237////////////////////////
238unsigned int _hba_init()
239{
240    unsigned int       flags;
241    unsigned int       vaddr;
242    unsigned long long paddr;
243    unsigned int       c;     
244    unsigned int       pxclb;
245    unsigned int       pxclbu;
246
247    // command list pointers
248    _hba_cmd_ptw = 0;
249    _hba_cmd_ptr = 0;
250
251    // Command list physical addresse
252    vaddr  = (unsigned int)(_hba_cmd_list);
253    paddr  = _v2p_translate( vaddr , &flags );
254    pxclb  = (unsigned int)paddr;
255    pxclbu = (unsigned int)(paddr>>32);
256
257    // Command tables physical addresses
258    for( c=0 ; c<32 ; c++ )
259    {
260        // compute command table physical address
261        // for one entry in the command list
262        vaddr = (unsigned int)(&_hba_cmd_table[c]);
263        paddr = _v2p_translate( vaddr , &flags );
264
265        // initialise the corresponding command descriptor
266        _hba_cmd_list[c].ctba  = (unsigned int)paddr;
267        _hba_cmd_list[c].ctbau = (unsigned int)(paddr>>32);
268    }
269
270    // set HBA registers
271    _hba_set_register( HBA_PXCLB , pxclb  );
272    _hba_set_register( HBA_PXCLBU, pxclbu );
273    _hba_set_register( HBA_PXIE  , 0      );
274    _hba_set_register( HBA_PXIS  , 0      );
275    _hba_set_register( HBA_PXCI  , 0      );
276    _hba_set_register( HBA_PXCMD , 1      );
277
278    return 0;
279}
280
281
282/////////////////////////////////////
283void _hba_isr( unsigned int irq_type,   // HWI / WTI
284               unsigned int irq_id,     // index returned by ICU
285               unsigned int channel )   // unused
286{
287    // get HBA_PXCI containing commands status
288    unsigned int pxci = _hba_get_register( HBA_PXCI );
289
290    // scan active commands from (_hba_cmd_ptr) to (_hba_cmd_ptw-1)
291    unsigned int c;
292    for ( c = _hba_cmd_ptr ; 
293          c != _hba_cmd_ptw ; 
294          c = (c + 1) % 32 )
295    {
296        if ( (pxci & (1<<c)) == 0 )    // command completed
297        {
298            // increment read pointer;
299            _hba_cmd_ptr++;
300
301            // save PXIS register
302            _hba_status[c] = _hba_get_register( HBA_PXIS );
303
304            // reset PXIS register
305            _hba_set_register( HBA_PXIS , 0 );
306 
307            // identify waiting task
308            unsigned int remote_procid  = _hba_gtid[c]>>16;
309            unsigned int ltid           = _hba_gtid[c] & 0xFFFF;
310            unsigned int remote_cluster = remote_procid >> P_WIDTH;
311            unsigned int remote_x       = remote_cluster >> Y_WIDTH;
312            unsigned int remote_y       = remote_cluster & ((1<<Y_WIDTH)-1);
313            unsigned int remote_p       = remote_procid & ((1<<P_WIDTH)-1);
314 
315            // re-activates waiting task
316            _set_task_slot( remote_x,
317                            remote_y,
318                            remote_p,
319                            ltid,
320                            CTX_RUN_ID,
321                            1 );
322
323            // send a WAKUP WTI to processor running the waiting task
324            _xcu_send_wti( remote_cluster , 
325                           remote_p , 
326                           0 );          // don't force context switch
327
328#if GIET_DEBUG_IOC_DRIVER 
329unsigned int procid  = _get_procid();
330unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
331unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
332unsigned int p       = procid & ((1<<P_WIDTH)-1);
333_printf("\n[HBA DEBUG] Processor[%d,%d,%d] executes _hba_isr() :\n"
334        "  resume task %d running on P[%d,%d,%d] / status = %x at cyle %d\n",
335        x , y , p , 
336        ltid , remote_x , remote_y , remote_p , _hba_status[c] , _get_proctime() );
337#endif
338        }
339        else                         // command non completed
340        {
341            break;
342        }
343    }
344} // end _hba_isr()
345
346// Local Variables:
347// tab-width: 4
348// c-basic-offset: 4
349// c-file-offsets:((innamespace . 0)(inline-open . 0))
350// indent-tabs-mode: nil
351// End:
352// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
353
Note: See TracBrowser for help on using the repository browser.