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

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

Defining the NIC and CMA drivers (validated by the classif application).
Updating other drivers to comply with the new tty0 common file.

File size: 9.3 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        unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase,
153                                           buf_vaddr >> 12,
154                                           &ppn,
155                                           &flags );
156        // check access rights
157        if ( ko )
158        {
159            _puts("\n[IOC ERROR] in _ioc_access() : buffer unmapped\n");
160            _exit(); 
161        }
162
163        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
164        {
165            _puts("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
166            _exit(); 
167        }
168
169        if ( ((flags & PTE_W) == 0 ) && to_mem )
170        {
171            _puts("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
172            _exit(); 
173        }
174
175        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
176    }
177
178    // cache coherence for both L1 & L2 caches
179
180    if ( to_mem ) // memory write : invalidate data caches
181    {
182        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
183        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
184
185        // L2 cache (only if we use an IO-Bridge component in architecture))
186        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
187    }
188    else         // memory read : update data caches
189    {
190        // L1 cache : nothing to do for L1 write-through
191
192        // L2 cache (only if we use an IO-Bridge component in architecture))
193        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
194    }
195
196    // select the proper physical device
197
198#if   ( USE_IOC_BDV )
199        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
200        else        error = _bdv_write( mode, lba, buf_paddr, count);
201#elif ( USE_IOC_SPI )
202        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
203        else        error = _sdc_write(mode, lba, buf_paddr, count);
204#elif ( USE_IOC_HBA )
205        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
206        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
207#elif ( USE_IOC_RDK )
208        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
209        else        error = _rdk_write(lba, buf_vaddr, count);
210#endif
211
212    return error;
213} // end _ioc_access()
214
215//////////////////////////////////////////////
216unsigned int _ioc_init( unsigned int channel )
217{
218
219#if   ( USE_IOC_BDV )
220
221    return _bdv_init();
222
223#elif ( USE_IOC_SPI )
224
225    return _sdc_init();
226   
227#elif ( USE_IOC_HBA )
228
229    return _hba_init( channel );
230   
231#elif ( USE_IOC_RDK )
232
233    return _rdk_init();
234   
235#endif
236   
237}
238
239//////////////////////////////////////////////
240unsigned int _ioc_read( unsigned int channel,
241                        unsigned int mode, 
242                        unsigned int lba, 
243                        void*        buffer, 
244                        unsigned int count) 
245{
246    return _ioc_access( 1,        // read access
247                        channel,
248                        mode, 
249                        lba,
250                        (unsigned int) buffer,
251                        count );
252}
253
254//////////////////////////////////////////////
255unsigned int _ioc_write( unsigned int channel,
256                         unsigned int mode, 
257                         unsigned int lba, 
258                         const void*  buffer, 
259                         unsigned int count ) 
260{
261    return _ioc_access( 0,        // write access
262                        channel,
263                        mode, 
264                        lba,
265                        (unsigned int) buffer,
266                        count );
267}
268
269/////////////////////////////////////////////////////
270unsigned int _ioc_get_status( unsigned int  channel )
271{
272
273#if   ( USE_IOC_BDV )
274
275    return _bdv_get_status( );
276
277#elif ( USE_IOC_SPI )
278
279    return _sdc_get_status( );
280
281#elif ( USE_IOC_HBA )
282
283    return _hba_get_status( channel );
284
285#elif ( USE_IOC_RDK )
286
287    return rdk_get_status();
288
289#endif
290
291}
292
293//////////////////////////////////
294unsigned int _ioc_get_block_size() 
295{
296
297#if   ( USE_IOC_BDV )
298
299    return _bdv_get_block_size();
300   
301#elif ( USE_IOC_SPI )
302
303    return _sdc_get_block_size();
304   
305#elif ( USE_IOC_HBA )
306
307    return _hba_get_block_size();
308   
309#elif ( USE_IOC_RDK )
310
311    return 512;
312
313#endif
314
315}
316
317
318// Local Variables:
319// tab-width: 4
320// c-basic-offset: 4
321// c-file-offsets:((innamespace . 0)(inline-open . 0))
322// indent-tabs-mode: nil
323// End:
324// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
325
Note: See TracBrowser for help on using the repository browser.