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

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

1) Introduce a new driver "sdc_driver" for SD Card uding directly the 4 bits SD bus.
2) Improve the debug for all IOC drivers (debug activated only if _get_time() > GIET_DEBUG_IOC_DRIVER).

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