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

Last change on this file since 436 was 426, checked in by alain, 10 years ago

Introducing fixed format (X_WIDTH / Y_WIDTH / P_WIDTH ) for processor index.

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