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

Last change on this file since 538 was 529, checked in by alain, 9 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.