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

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

Simplify the Command Table C structure: only one physical buffer per command.

File size: 11.9 KB
RevLine 
[529]1//////////////////////////////////////////////////////////////////////////////////
[258]2// File     : hba_driver.c
3// Date     : 23/11/2013
[295]4// Author   : alain greiner
[258]5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[295]7// Implementation notes:
[529]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.
[258]11///////////////////////////////////////////////////////////////////////////////////
12
13#include <giet_config.h>
[529]14#include <hard_config.h>
15#include <hba_driver.h>
16#include <xcu_driver.h>
17#include <kernel_locks.h>
[258]18#include <utils.h>
[456]19#include <tty0.h>
[258]20#include <ctx_handler.h>
[529]21#include <irq_handler.h>
[258]22#include <vmem.h>
23
[529]24///////////////////////////////////////////////////////////////////////////////////
25//               Global variables
26///////////////////////////////////////////////////////////////////////////////////
[258]27
[529]28// global index ot the task, for each entry in the command list
29__attribute__((section(".kdata")))
30unsigned int _hba_gtid[32];
[258]31
[529]32// status of the command, for each entry in the command list
33__attribute__((section(".kdata")))
34unsigned int _hba_status[32];
[258]35
[529]36// command list : up to 32 commands
37__attribute__((section(".kdata")))
[540]38hba_cmd_desc_t  _hba_cmd_list[32] __attribute__((aligned(0x10)));   
[258]39
[529]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))); 
[258]43
[529]44// command list write index : next slot to register a command
45__attribute__((section(".kdata")))
46unsigned int     _hba_cmd_ptw;
[258]47
[529]48// command list read index : next slot to poll a completed command
49__attribute__((section(".kdata")))
50unsigned int     _hba_cmd_ptr;
[258]51
[295]52//////////////////////////////////////////////////////////////////////////////
[529]53// This low level function returns the value of register (index)
[295]54//////////////////////////////////////////////////////////////////////////////
[529]55unsigned int _hba_get_register( unsigned int index )
[258]56{
[529]57    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
[295]58    return _io_extended_read( vaddr );
59}
[258]60
[295]61//////////////////////////////////////////////////////////////////////////////
[529]62// This low level function set a new value in register (index) 
[295]63//////////////////////////////////////////////////////////////////////////////
[529]64void _hba_set_register( unsigned int index,
[295]65                        unsigned int value )
66{
[529]67    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
[295]68    _io_extended_write( vaddr, value );
[258]69}
70
[529]71///////////////////////////////////////////////////////////////////////////////
72//      Extern functions
73///////////////////////////////////////////////////////////////////////////////
[295]74
[258]75///////////////////////////////////////////////////////////////////////////////
76// This function register a command in both the command list
77// and the command table, and updates the HBA_PXCI register.
[437]78// return 0 if success, -1 if error
[258]79///////////////////////////////////////////////////////////////////////////////
[529]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 )   
[258]85{
[529]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);
[295]90
[529]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
[258]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
[529]104    if( buf_paddr & 0x1FF )
[258]105    {
[529]106        _printf("\n[HBA ERROR] in _hba_access() : buffer not block aligned\n");
[437]107        return -1;
[258]108    }
109
[529]110    // get pointer on the next possible entry in command list
111    ptw = _atomic_increment( &_hba_cmd_ptw , 1 );
[258]112
[529]113    // poll PXCI register until pointed entry empty
114    do
[258]115    {
[529]116        // get PXCI register
117        pxci = _hba_get_register( HBA_PXCI );
118    } 
119    while ( pxci & (1<<ptw) );
120   
[258]121    // compute pointers on command descriptor and command table   
[529]122    cmd_desc  = &_hba_cmd_list[ptw];
123    cmd_table = &_hba_cmd_table[ptw];
[258]124
[295]125    // set  buffer descriptor in command table
[540]126    cmd_table->buffer.dba  = (unsigned int)(buf_paddr);
127    cmd_table->buffer.dbau = (unsigned int)(buf_paddr >> 32);
128    cmd_table->buffer.dbc  = count * 512;
[295]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;
[529]141    if( to_mem ) cmd_desc->flag[0] = 0x00;
142    else         cmd_desc->flag[0] = 0x40;     
[295]143   
[529]144    // set command in PXCI[ptw]
145    _hba_set_register( HBA_PXCI, pxci + (1<<ptw) );
[295]146
147
[529]148    /////////////////////////////////////////////////////////////////////
149    // In synchronous mode, we poll the PXCI register until completion
150    /////////////////////////////////////////////////////////////////////
151    if ( use_irq == 0 ) 
152    {
[295]153
[529]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 );
[295]161
[529]162        // poll PXCI[ptw] until command completed by HBA
163        do
164        {
165            pxci = _hba_get_register( HBA_PXCI ) & (1<<ptw);
[258]166
[529]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
[258]189    {
190
[529]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();
[258]198
[529]199        // activates HBA interrupts
200        _hba_set_register( HBA_PXIE , 0x00000001 ); 
[258]201
[529]202        // set _hba_gtid[ptw]
203        _hba_gtid[ptw] = (procid<<16) + ltid;
[258]204
[529]205        // enters critical section
206        _it_disable( &save_sr ); 
[258]207
[529]208        // reset runnable
209        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
[258]210
[529]211        // deschedule task
212        _ctx_switch();                     
[258]213
[529]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
[258]218
[529]219        // restore SR
220        _it_restore( &save_sr );
[258]221
[529]222        // get command status
223        pxis = _hba_status[ptw];
224    }   
[258]225
[529]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
[258]230
[529]231    if ( pxis & 0x40000000 ) return pxis;
232    else                     return 0;
[258]233
[529]234} // end _hba_access()
[258]235
236
[529]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;
[258]246
[529]247    // command list pointers
248    _hba_cmd_ptw = 0;
249    _hba_cmd_ptr = 0;
[258]250
251    // Command list physical addresse
[529]252    vaddr  = (unsigned int)(_hba_cmd_list);
253    paddr  = _v2p_translate( vaddr , &flags );
254    pxclb  = (unsigned int)paddr;
255    pxclbu = (unsigned int)(paddr>>32);
[258]256
257    // Command tables physical addresses
258    for( c=0 ; c<32 ; c++ )
259    {
[529]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);
[258]268    }
[289]269
[529]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
[289]278    return 0;
[258]279}
280
[437]281
[529]282/////////////////////////////////////
283void _hba_isr( unsigned int irq_type,   // HWI / WTI
284               unsigned int irq_id,     // index returned by ICU
285               unsigned int channel )   // unused
[437]286{
[529]287    // get HBA_PXCI containing commands status
288    unsigned int pxci = _hba_get_register( HBA_PXCI );
[437]289
[529]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++;
[258]300
[529]301            // save PXIS register
302            _hba_status[c] = _hba_get_register( HBA_PXIS );
[258]303
[529]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 );
[295]322
[529]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
[295]327
[529]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()
[295]345
[258]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.