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

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

Cosmetic

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