source: soft/giet_vm/giet_drivers/ioc_driver.c @ 487

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

1) The NIC, IOC, DMA and HBA drivers have been adapted to support the new _v2p_translate() function prototype (returns void).
2) The _mmc_inval() and _mmc_sync() functions does not use anymore the hard lock in the MMC, but use a soft spin_lock.
3) The NIC driver does not use anymore the GIET_NIC_BUFSIZE, GIET_NIC_NBUFS, and GIET_NIC_TIMEOUT parameters (removed from giet_config.h file).
4) The NIC driver registers map has been modified to support 64 bytes buffer descriptors for chained buffers.

File size: 9.1 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File       : ioc_driver.c
3// Date       : 23/05/2013
4// Author     : alain greiner
5// Maintainer : cesar fuguet
6// Copyright (c) UPMC-LIP6
7///////////////////////////////////////////////////////////////////////////////////
8// Implementation notes:
9// 1) In order to share the code, the two _ioc_read() and _ioc_write() functions
10// call the same _ioc_access() function, and this function call the selected
11// physical driver (BDV / HBA / SPI / RDK).
12// 2) The IOMMU is not supported yet, but the method is the following:
13// A fixed size 2 Mbytes vseg is allocated to the IOC peripheral, in the I/O
14// virtual space, and the user buffer is dynamically remapped to one single
15// big page in the IOMMU page table.
16// The user buffer is unmapped by the _ioc_completed() function when
17// the transfer is completed.
18///////////////////////////////////////////////////////////////////////////////////
19
20#include <giet_config.h>
21#include <ioc_driver.h>
22#include <bdv_driver.h>
23#include <hba_driver.h>
24#include <sdc_driver.h>
25#include <rdk_driver.h>
26#include <utils.h>
27#include <tty0.h>
28#include <iob_driver.h>
29#include <ctx_handler.h>
30#include <mmc_driver.h>
31#include <vmem.h>
32
33#if !defined( SEG_IOC_BASE )
34# error: You must define SEG_IOC_BASE in the hard_config.h file
35#endif
36
37#if !defined( USE_IOB )
38# error: You must define USE_IOB in the hard_config.h file
39#endif
40
41#if !defined(GIET_USE_IOMMU)
42# error: You must define GIET_USE_IOMMU in the giet_config.h file
43#endif
44
45#if (USE_IOC_BDV + USE_IOC_SPI + USE_IOC_HBA + USE_IOC_RDK) != 1
46# error: You must use only one IOC controller type (BDV or SPI or HBA or RDK)
47#endif
48
49#if USE_IOC_BDV
50# include <bdv_driver.h>
51#endif
52
53#if USE_IOC_SPI
54# include <sdc_driver.h>
55#endif
56
57#if USE_IOC_HBA
58# include <hba_driver.h>
59#endif
60
61#if USE_IOC_RDK
62# include <rdk_driver.h>
63#endif
64
65///////////////////////////////////////////////////////////////////////////////
66// IOC global variables
67///////////////////////////////////////////////////////////////////////////////
68
69#define in_unckdata __attribute__((section (".unckdata")))
70
71in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0;
72in_unckdata volatile unsigned int _ioc_iommu_npages; 
73
74///////////////////////////////////////////////////////////////////////////////
75// This function transfer data between a memory buffer and the block device.
76// The buffer lentgth is (count*block_size) bytes.
77// Arguments are:
78// - to_mem     : from external storage to memory when non 0.
79// - mode       : BOOT_PA / BOOT_VA / KERNEL / USER
80// - lba        : first block index on the external storage.
81// - buf_vaddr  : virtual base address of the memory buffer.
82// - count      : number of blocks to be transfered.
83// Returns 0 if success, > 0 if error.
84///////////////////////////////////////////////////////////////////////////////
85static unsigned int _ioc_access( unsigned int to_mem,
86                                 unsigned int channel,
87                                 unsigned int mode,
88                                 unsigned int lba,
89                                 unsigned int buf_vaddr,
90                                 unsigned int count) 
91{
92
93#if GIET_DEBUG_IOC_DRIVER
94unsigned int procid  = _get_procid();
95unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
96unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
97unsigned int p       = procid & ((1<<P_WIDTH)-1);
98_puts("\n[IOC DEBUG] _ioc_access() : P[");
99_putd( x );
100_puts(",");
101_putd( y );
102_puts(",");
103_putd( p );
104_puts("] enters at cycle ");
105_putd( _get_proctime() );
106_puts("\n - channel  = ");
107_putd( channel );
108_puts("\n - mode     = ");
109_putd( mode );
110_puts("\n - vaddr    = ");
111_putx( buf_vaddr );
112_puts("\n - sectors  = ");
113_putd( count );
114_puts("\n - lba      = ");
115_putx( lba );
116_puts("\n");
117#endif
118
119    unsigned int error;            // return value
120    unsigned int pt_vbase;         // page table vbase address
121    unsigned int ppn;              // user buffer first page PPN
122    unsigned int flags;            // user buffer protection flags
123    paddr_t      buf_paddr;        // user buffer physical address (if no IOMMU),
124
125    // check buffer alignment
126    if ((unsigned int) buf_vaddr & 0x3)
127    {
128        _puts("\n[IOC ERROR] in _ioc_access() : buffer not word aligned\n");
129        _exit(); 
130    }
131
132    // check channel
133    if ( (USE_IOC_HBA == 0) && (channel > 0) )
134    {
135        _puts("\n[IOC ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
136        _exit(); 
137    }
138
139    unsigned int length = count << 9;  // count * 512 bytes
140
141    // computing memory buffer physical address
142    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity mapping
143    {
144        buf_paddr = (paddr_t)buf_vaddr;
145    }
146    else                                                    // V2P translation required
147    {
148        // get page table virtual address
149        pt_vbase = _get_context_slot(CTX_PTAB_ID);
150
151        // get user buffer first page ppn and flags
152        _v2p_translate( (page_table_t*)pt_vbase,
153                        buf_vaddr >> 12,
154                        &ppn,
155                        &flags );
156
157        // check access rights
158        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
159        {
160            _puts("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
161            _exit(); 
162        }
163
164        if ( ((flags & PTE_W) == 0 ) && to_mem )
165        {
166            _puts("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
167            _exit(); 
168        }
169
170        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
171    }
172
173    // cache coherence for both L1 & L2 caches
174
175    if ( to_mem ) // memory write : invalidate data caches
176    {
177        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
178        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
179
180        // L2 cache (only if we use an IO-Bridge component in architecture))
181        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
182    }
183    else         // memory read : update data caches
184    {
185        // L1 cache : nothing to do for L1 write-through
186
187        // L2 cache (only if we use an IO-Bridge component in architecture))
188        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
189    }
190
191    // select the proper physical device
192
193#if   ( USE_IOC_BDV )
194        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
195        else        error = _bdv_write( mode, lba, buf_paddr, count);
196#elif ( USE_IOC_SPI )
197        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
198        else        error = _sdc_write(mode, lba, buf_paddr, count);
199#elif ( USE_IOC_HBA )
200        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
201        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
202#elif ( USE_IOC_RDK )
203        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
204        else        error = _rdk_write(lba, buf_vaddr, count);
205#endif
206
207    return error;
208} // end _ioc_access()
209
210//////////////////////////////////////////////
211unsigned int _ioc_init( unsigned int channel )
212{
213
214#if   ( USE_IOC_BDV )
215
216    return _bdv_init();
217
218#elif ( USE_IOC_SPI )
219
220    return _sdc_init();
221   
222#elif ( USE_IOC_HBA )
223
224    return _hba_init( channel );
225   
226#elif ( USE_IOC_RDK )
227
228    return _rdk_init();
229   
230#endif
231   
232}
233
234//////////////////////////////////////////////
235unsigned int _ioc_read( unsigned int channel,
236                        unsigned int mode, 
237                        unsigned int lba, 
238                        void*        buffer, 
239                        unsigned int count) 
240{
241    return _ioc_access( 1,        // read access
242                        channel,
243                        mode, 
244                        lba,
245                        (unsigned int) buffer,
246                        count );
247}
248
249//////////////////////////////////////////////
250unsigned int _ioc_write( unsigned int channel,
251                         unsigned int mode, 
252                         unsigned int lba, 
253                         const void*  buffer, 
254                         unsigned int count ) 
255{
256    return _ioc_access( 0,        // write access
257                        channel,
258                        mode, 
259                        lba,
260                        (unsigned int) buffer,
261                        count );
262}
263
264/////////////////////////////////////////////////////
265unsigned int _ioc_get_status( unsigned int  channel )
266{
267
268#if   ( USE_IOC_BDV )
269
270    return _bdv_get_status( );
271
272#elif ( USE_IOC_SPI )
273
274    return _sdc_get_status( );
275
276#elif ( USE_IOC_HBA )
277
278    return _hba_get_status( channel );
279
280#elif ( USE_IOC_RDK )
281
282    return rdk_get_status();
283
284#endif
285
286}
287
288//////////////////////////////////
289unsigned int _ioc_get_block_size() 
290{
291
292#if   ( USE_IOC_BDV )
293
294    return _bdv_get_block_size();
295   
296#elif ( USE_IOC_SPI )
297
298    return _sdc_get_block_size();
299   
300#elif ( USE_IOC_HBA )
301
302    return _hba_get_block_size();
303   
304#elif ( USE_IOC_RDK )
305
306    return 512;
307
308#endif
309
310}
311
312
313// Local Variables:
314// tab-width: 4
315// c-basic-offset: 4
316// c-file-offsets:((innamespace . 0)(inline-open . 0))
317// indent-tabs-mode: nil
318// End:
319// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
320
Note: See TracBrowser for help on using the repository browser.