source: trunk/softs/tsar_boot/drivers/reset_hba.c @ 966

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

Introducing HBA driver in the tsar boot-loader.

File size: 4.7 KB
RevLine 
[964]1/**
2 * \File     : reset_hba.c
3 * \Date     : 23/11/2013
4 * \Author   : alain greiner
5 * \Copyright (c) UPMC-LIP6
6 */
7
8#include <reset_hba.h>
9#include <reset_tty.h>
10#include <reset_inval.h>
11#include <io.h>
12#include <defs.h>
13
14///////////////////////////////////////////////////////////////////////////////
15//               Global variables
16///////////////////////////////////////////////////////////////////////////////
17
18// command descriptor (one single command)
19static hba_cmd_desc_t  hba_cmd_desc  __attribute__((aligned(64)));
20
21// command table (one single command)
22static hba_cmd_table_t  hba_cmd_table __attribute__((aligned(64)));
23
24// IOC/HBA device base address
25static int* const ioc_address = (int* const)SEG_IOC_BASE;
26
27///////////////////////////////////////////////////////////////////////////////
28//      Extern functions
29///////////////////////////////////////////////////////////////////////////////
30
31///////////////////////////////////////////////////////////////////////////////
32// This function register one command in both the command descriptor
33// and the command data, and updates the HBA_PXCI register.
34// The all addresses are supposed to be identity mapping (vaddr == paddr).
35// return 0 if success, -1 if error
36///////////////////////////////////////////////////////////////////////////////
37int reset_hba_read( unsigned int lba, 
38                    void*        buffer,
39                    unsigned int count )   
40{
41    unsigned int       pxci;           // HBA_PXCI register value
42    unsigned int       pxis;           // HBA_PXIS register value
43
44    // check buffer alignment
45    if( (unsigned int)buffer & 0x3F )
46    {
47        reset_puts("\n[RESET ERROR] in reset_hba_read() ");
48        reset_puts("buffer not aligned on 64 bytes: base = "); 
49        reset_putx( (unsigned int)buffer );
50        reset_puts("\n"); 
51        return -1;
52    }
53
54    // set command data header: lba value
55    hba_cmd_table.header.lba0 = (char)lba;
56    hba_cmd_table.header.lba1 = (char)(lba>>8);
57    hba_cmd_table.header.lba2 = (char)(lba>>16);
58    hba_cmd_table.header.lba3 = (char)(lba>>24);
59    hba_cmd_table.header.lba4 = 0;
60    hba_cmd_table.header.lba5 = 0;
61
62    // set command data buffer: address and size)
63    hba_cmd_table.buffer.dba  = (unsigned int)(buffer);
64    hba_cmd_table.buffer.dbau = 0;
65    hba_cmd_table.buffer.dbc  = count*512;
66
67    // set command descriptor: one single buffer / read access
68    hba_cmd_desc.prdtl[0] = 1;
69    hba_cmd_desc.prdtl[1] = 0;
70    hba_cmd_desc.flag[0]  = 0;  // read
71   
72#if USE_IOB
73    // update external memory for command table
74    reset_L2_sync( &hba_cmd_table , 32 );
75
76    // update external memory for command descriptor
77    reset_L2_sync( &hba_cmd_desc , 16 );
78#endif
79
80    // start transfer
81    iowrite32( &ioc_address[HBA_PXCI] , 1 );
82
83#if (RESET_HARD_CC == 0) || USE_IOB
84    // inval buffer in L1 cache
85    reset_L1_inval( buffer , count * 512 );
86#endif
87
88#if USE_IOB
89    // inval buffer in  L2 cache
90    reset_L2_inval( buffer , count * 512 );
91#endif
92
93    // poll PXCI until command completed by HBA
94    do
95    {
96        pxci = ioread32( &ioc_address[HBA_PXCI] );
97    }
98    while( pxci ); 
99             
100    // get PXIS register
101    pxis = ioread32( &ioc_address[HBA_PXIS] );
102
103    // reset PXIS register
104    iowrite32( &ioc_address[HBA_PXIS] , 0 );
105
106    // reset PXCI register : we use only command slot[0] in PXCI
107    iowrite32( &ioc_address[HBA_PXCI] , 0 );
108
109    // check error status
110    if ( pxis & 0x40000000 ) 
111    {
112        reset_puts("[RESET ERROR] in reset_hba_read() : "
113                   " status error returned by HBA\n");
114        return 1;
115    }
116
117    return 0;
118} // end reset_hba_read()
119
120
121///////////////////////////////////////////////////////////////////////////////
122// This function initialises both the HBA registers and the
123// memory structures used by the AHCI peripheral (one single command).
124///////////////////////////////////////////////////////////////////////////////
125int reset_hba_init()
126{
127    // initialise the command descriptor
128    hba_cmd_desc.ctba  = (unsigned int)&hba_cmd_table;
129    hba_cmd_desc.ctbau = 0;
130
131#if USE_IOB
132    // update external memory for the commande descriptor
133    reset_L2_sync( &hba_cmd_desc , sizeof( hba_cmd_desc_t ) );
134#endif
135    // initialise HBA registers
136    iowrite32( &ioc_address[HBA_PXCLB]  , (unsigned int)&hba_cmd_desc );
137    iowrite32( &ioc_address[HBA_PXCLBU] , 0 );
138    iowrite32( &ioc_address[HBA_PXIE]   , 0 );
139    iowrite32( &ioc_address[HBA_PXIS]   , 0 );
140    iowrite32( &ioc_address[HBA_PXCI]   , 0 );
141    iowrite32( &ioc_address[HBA_PXCMD]  , 1 );
142
143    return 0;
144}
145
146
147// Local Variables:
148// tab-width: 4
149// c-basic-offset: 4
150// c-file-offsets:((innamespace . 0)(inline-open . 0))
151// indent-tabs-mode: nil
152// End:
153// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
154
Note: See TracBrowser for help on using the repository browser.