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

Last change on this file since 295 was 295, checked in by alain, 11 years ago

Introducing a major release, to suppoort the tsar_generic_leti platform
and the various (external or internal) peripherals configurations.
The map.xml format has been modified, in order to support the new
vci_iopic componentand a new policy for peripherals initialisation.
The IRQs are nom described in the XICU and IOPIC components
(and not anymore in the processors).
To enforce this major change, the map.xml file signature changed:
The signature value must be: 0xDACE2014

This new release has been tested on the tsar_generic_leti platform
for the following mappings:

  • 4c_4p_sort_leti
  • 4c_4p_sort_leti_ext
  • 4c_4p_transpose_leti
  • 4c_4p_transpose_leti_ext
  • 4c_1p_four_leti_ext
File size: 16.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// The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel.
9//
10// This abstact driver define a generic API, supporting various physical
11// block device controlers, including:
12// - vci_block_device : single channel)                    => bdv_driver
13// - vci_ahci         : multi channels                     => hba_driver
14// - sd_card          : single channel                     => sdc_driver
15// - ramdisk (single channel meory mapped virtual disk)    => rdk_driver
16//
17// It can exist only one block-device type in the architecture, that must be
18// defined by one of the following configuration variables in hard_config.h file:
19// USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK.
20//
21// Any physical driver xxx must provide the following API:
22// - _xxx_init()
23// - _xxx_read()
24// - _xxx_write()
25// - _xxx_get_status()
26// - _xxx_get_block_size()
27// The "channel" parameter is no transmited to single channel devices.
28//
29// The _ioc_read() and _ioc_write() functions are always blocking for
30// the calling user program.
31//
32// These functions compute the physical address of the memory buffer before
33// calling the proper physical device. They can be called in 3 modes:
34//
35// - In BOOT mode, these functions use the buffer virtual address
36//   as a physical address if the MMU is not activated.
37//   They make a V2P translation if the MMU is activated.
38//   This mode is used to load the map.bin file (before memory activation),
39//   or to load the various .elf files (after MMU activation).
40//
41// - In KERNEL mode, these functions make a V2P translation to
42//   compute the buffer physical address.
43//   There is no checking of user access right to the memory buffer. 
44//   This mode must be used for an "open" system call.
45//
46// - In USER mode, these functions make a V2P translation to
47//   compute the buffer physical address.
48//   The user access right to the memory buffer are checked. 
49//   This mode must be used for a "read" or "write" system call.
50//
51// The IOMMU can be activated or not:
52//
53// 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to
54// the IOC peripheral, in the I/O virtual space, and the user buffer is
55// dynamically remapped in the IOMMU page table. The corresponding entry
56// in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable.
57// The number of pages to be unmapped is stored in the _ioc_npages variable.
58// The number of PT2 entries is dynamically computed and stored in the
59// kernel _ioc_iommu_npages variable. It cannot be larger than 512.
60// The user buffer is unmapped by the _ioc_completed() function when
61// the transfer is completed.
62//
63// 2/ If the IOMMU is not used, we check that  the user buffer is mapped to a
64// contiguous physical buffer (this is generally true because the user space
65// page tables are statically constructed to use contiguous physical memory).
66//
67// Finally, the memory buffer must fulfill the following conditions:
68// - The buffer must be word aligned,
69// - The buffer must be mapped in user space for an user access,
70// - The buffer must be writable in case of (to_mem) access,
71// - The total number of physical pages occupied by the user buffer cannot
72//   be larger than 512 pages if the IOMMU is activated,
73// - All physical pages occupied by the user buffer must be contiguous
74//   if the IOMMU is not activated.
75// An error code is returned if these conditions are not verified.
76//
77// The "seg_ioc_base" virtual base address of the segment containing the
78// memory-mapped registers of the device must be defined in the giet_vsegs.ld file.
79// If the RAMDISK is used, an extra memory segment with virtual base address
80// "seg_ramdisk_base" must be defined in the giet_vsegs.ld file.
81///////////////////////////////////////////////////////////////////////////////////
82// Implementation note:
83// In order to share the code, the two _ioc_read() and _ioc_write() functions
84// call the same _ioc_access() function.
85///////////////////////////////////////////////////////////////////////////////////
86
87#include <giet_config.h>
88#include <ioc_driver.h>
89#include <bdv_driver.h>
90#include <hba_driver.h>
91#include <sdc_driver.h>
92#include <rdk_driver.h>
93#include <utils.h>
94#include <tty_driver.h>
95#include <iob_driver.h>
96#include <ctx_handler.h>
97#include <mmc_driver.h>
98#include <vmem.h>
99
100#if !defined( USE_IOB )
101# error: You must define USE_IOB in the hard_config.h file
102#endif
103
104#if !defined(GIET_USE_IOMMU)
105# error: You must define GIET_USE_IOMMU in the giet_config.h file
106#endif
107
108#if (USE_IOC_BDV + USE_IOC_SPI + USE_IOC_HBA + USE_IOC_RDK) != 1
109# error: You must use only one IOC controller type (BDV or SPI or HBA or RDK)
110#endif
111
112#if USE_IOC_BDV
113# include <bdv_driver.h>
114#endif
115
116#if USE_IOC_SPI
117# include <sdc_driver.h>
118#endif
119
120#if USE_IOC_HBA
121# include <hba_driver.h>
122#endif
123
124#if USE_IOC_RDK
125# include <rdk_driver.h>
126#endif
127
128///////////////////////////////////////////////////////////////////////////////
129// IOC global variables
130///////////////////////////////////////////////////////////////////////////////
131
132#define in_unckdata __attribute__((section (".unckdata")))
133
134in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0;
135in_unckdata volatile unsigned int _ioc_iommu_npages; 
136
137///////////////////////////////////////////////////////////////////////////////
138// This function transfer data between a memory buffer and the block device.
139// The buffer lentgth is (count*block_size) bytes.
140// Arguments are:
141// - to_mem     : from external storage to memory when non 0.
142// - mode       : BOOT_PA / BOOT_VA / KERNEL / USER
143// - lba        : first block index on the external storage.
144// - buf_vaddr  : virtual base address of the memory buffer.
145// - count      : number of blocks to be transfered.
146// Returns 0 if success, > 0 if error.
147///////////////////////////////////////////////////////////////////////////////
148static unsigned int _ioc_access( unsigned int to_mem,
149                                 unsigned int channel,
150                                 unsigned int mode,
151                                 unsigned int lba,
152                                 unsigned int buf_vaddr,
153                                 unsigned int count) 
154{
155
156#if GIET_DEBUG_IOC_DRIVER
157unsigned int procid  = _get_procid();
158unsigned int cid     = procid / NB_PROCS_MAX;
159unsigned int lpid    = procid % NB_PROCS_MAX;
160unsigned int x       = cid >> Y_WIDTH;
161unsigned int y       = cid & ((1<<Y_WIDTH) - 1);
162
163_printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _ioc_access() at cycle %d\n"
164        " - channel  = %d\n"
165        " - mode     = %d\n"
166        " - vaddr    = %d\n"
167        " - sectors  = %d\n"
168        " - lba      = %d\n",
169        x, y, lpid, _get_proctime(), channel, mode, buf_vaddr, count, lba );
170#endif
171
172    unsigned int error;            // return value
173    unsigned int pt_vbase;         // page table vbase address
174    unsigned int vpn_min;          // first virtuel page index covering buffer
175    unsigned int vpn_max;          // last virtual page index covering buffer
176    unsigned int vpn;              // current virtual page index
177    unsigned int ppn;              // physical page number
178    unsigned int flags;            // page protection flags
179    unsigned int ix2;              // page index in IOMMU PT1 page table
180    unsigned int ppn_first;        // first physical page number for user buffer
181    unsigned int buf_xaddr = 0;    // user buffer virtual address in IO space (if IOMMU)
182    paddr_t      buf_paddr = 0;    // user buffer physical address (if no IOMMU),
183
184    // check buffer alignment
185    if ((unsigned int) buf_vaddr & 0x3)
186    {
187        _printf("\n[GIET ERROR] in _ioc_access() : buffer not word aligned\n");
188        _exit(); 
189    }
190
191    // check channel
192    if ( (USE_IOC_HBA == 0) && (channel > 0) )
193    {
194        _printf("\n[GIET ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
195        _exit(); 
196    }
197
198    unsigned int length = count << 9;  // count * 512 bytes
199
200    // computing memory buffer physical address
201    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity mapping
202    {
203        buf_paddr = (paddr_t)buf_vaddr;
204    }
205    else                                                    // V2P translation required
206    {
207        // get page table virtual address
208        pt_vbase = _get_context_slot(CTX_PTAB_ID);
209        vpn_min  = buf_vaddr >> 12;
210        vpn_max  = (buf_vaddr + length - 1) >> 12;
211
212        // loop on all virtual pages covering the user buffer
213        for (vpn = vpn_min, ix2 = 0 ; vpn <= vpn_max ; vpn++, ix2++ ) 
214        {
215            // get ppn and flags for each vpn
216            unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase,
217                                              vpn,
218                                              &ppn,
219                                              &flags);
220            // check access rights
221            if ( ko )
222            {
223                _printf("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n");
224                return 1; 
225            }
226
227            if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
228            {
229                _printf("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n");
230                return 1; 
231            }
232
233            if ( ((flags & PTE_W) == 0 ) && to_mem )
234            {
235                _printf("\n[GIET ERROR] in _ioc_access() : buffer not writable\n");
236                return 1; 
237            }
238
239            // save first ppn value
240            if (ix2 == 0) ppn_first = ppn;
241
242#if GIET_USE_IOMMU
243 
244            // check buffer length < 2 Mbytes
245            if (ix2 > 511) // check buffer length < 2 Mbytes
246            {
247                _printf("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n");
248                return 1; 
249            }
250            // map the physical page in IOMMU page table
251            _iommu_add_pte2( _ioc_iommu_ix1,    // PT1 index
252                             ix2,               // PT2 index
253                             ppn,               // Physical page number   
254                             flags );           // Protection flags
255
256            // compute user buffer virtual adress in IO space
257            buf_xaddr = (_ioc_iommu_ix1) << 21 | (buf_vaddr & 0xFFF);
258
259#else
260
261            // check that physical pages are contiguous
262            if ((ppn - ppn_first) != ix2) 
263            {
264                _printf("[GIET ERROR] in _ioc_access() : split physical buffer\n");
265                return 1; 
266            }
267
268            // compute user buffer physical adress
269            buf_paddr = (((paddr_t)ppn_first) << 12) | (buf_vaddr & 0xFFF);
270#endif           
271
272        } // end for vpn
273    }
274
275#if GIET_USE_IOMMU
276
277    // register the number of pages to be unmapped in IOMMU
278    _ioc_iommu_npages = (vpn_max - vpn_min) + 1;
279
280#endif
281
282    if ( to_mem ) // memory write : invalidate data caches
283    {
284        // L1 cache
285        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate((void *) buf_vaddr, length);
286
287        // L2 cache (only if IOB used)
288        if ( USE_IOB ) _memc_inval( buf_paddr, length );
289    }
290    else         // memory read : update data caches
291    {
292        // L1 cache : nothing to do for L1 write-through
293
294        // L2 cache (only if IOB used)
295        if ( USE_IOB ) _memc_sync( buf_paddr, length );
296    }
297
298    if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr;
299
300    ///////////////////////////////////////////
301    // select the proper physical device
302    ///////////////////////////////////////////
303
304#if       ( USE_IOC_BDV )
305
306#if GIET_DEBUG_IOC_DRIVER
307_printf("\n[IOC DEBUG] Calling BDV driver\n");
308#endif
309        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
310        else        error = _bdv_write( mode, lba, buf_paddr, count);
311
312#elif ( USE_IOC_SPI )
313
314#if GIET_DEBUG_IOC_DRIVER
315_printf("\n[IOC DEBUG] Calling SPI driver\n");
316#endif
317        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
318        else        error = _sdc_write(mode, lba, buf_paddr, count);
319
320#elif ( USE_IOC_HBA )
321
322#if GIET_DEBUG_IOC_DRIVER
323_printf("\n[IOC DEBUG] Calling HBA driver\n");
324#endif
325        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
326        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
327
328#elif ( USE_IOC_RDK )
329
330#if GIET_DEBUG_IOC_DRIVER
331_printf("\n[IOC DEBUG] Calling RDK driver\n");
332#endif
333        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
334        else        error = _rdk_write(lba, buf_vaddr, count);
335
336#endif
337
338    return error;
339} // end _ioc_access()
340
341///////////////////////////////////////////////////////////////////////////////
342// This function cheks block size, and activates the IOC interrupts.
343// Return 0 for success.
344///////////////////////////////////////////////////////////////////////////////
345unsigned int _ioc_init( unsigned int channel )
346{
347
348#if   ( USE_IOC_BDV )
349
350    return _bdv_init();
351
352#elif ( USE_IOC_SPI )
353
354    return _sdc_init();
355   
356#elif ( USE_IOC_HBA )
357
358    return _hba_init( channel );
359   
360#elif ( USE_IOC_RDK )
361
362    return _rdk_init();
363   
364#endif
365   
366}
367
368///////////////////////////////////////////////////////////////////////////////
369// Transfer data from the block device to a memory buffer.
370// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER
371// - lba      : first block index on the block device
372// - buffer   : base address of the memory buffer (must be word aligned)
373// - count    : number of blocks to be transfered.
374// Returns 0 if success, > 0 if error.
375///////////////////////////////////////////////////////////////////////////////
376unsigned int _ioc_read( unsigned int channel,
377                        unsigned int mode, 
378                        unsigned int lba, 
379                        void*        buffer, 
380                        unsigned int count) 
381{
382    return _ioc_access( 1,        // read access
383                        channel,
384                        mode, 
385                        lba,
386                        (unsigned int) buffer,
387                        count );
388}
389
390///////////////////////////////////////////////////////////////////////////////
391// Transfer data from a memory buffer to the block device.
392// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER
393// - lba      : first block index on the block device
394// - buffer   : base address of the memory buffer (must be word aligned)
395// - count    : number of blocks to be transfered.
396// Returns 0 if success, > 0 if error.
397///////////////////////////////////////////////////////////////////////////////
398unsigned int _ioc_write( unsigned int channel,
399                         unsigned int mode, 
400                         unsigned int lba, 
401                         const void*  buffer, 
402                         unsigned int count ) 
403{
404    return _ioc_access( 0,        // write access
405                        channel,
406                        mode, 
407                        lba,
408                        (unsigned int) buffer,
409                        count );
410}
411
412///////////////////////////////////////////////////////////////////////////////
413// This function returns in the status variable, the transfert status, and
414// acknowledge the IRQ if the IOC controler is not busy.
415// Returns 0 if success, > 0 if error
416///////////////////////////////////////////////////////////////////////////////
417unsigned int _ioc_get_status( unsigned int  channel )
418{
419
420#if   ( USE_IOC_BDV )
421
422    return _bdv_get_status( );
423
424#elif ( USE_IOC_SPI )
425
426    return _sdc_get_status( );
427
428#elif ( USE_IOC_HBA )
429
430    return _hba_get_status( channel );
431
432#elif ( USE_IOC_RDK )
433
434    _printf("[GIET ERROR] _ioc_get_status() should not be called");
435    _printf(" when RAMDISK  is used...\n");
436    _exit();
437
438    return 0;
439
440#endif
441
442}
443
444///////////////////////////////////////////////////////////////////////////////
445// This function returns the block_size with which the IOC has been configured.
446///////////////////////////////////////////////////////////////////////////////
447unsigned int _ioc_get_block_size() 
448{
449
450#if   ( USE_IOC_BDV )
451
452    return _bdv_get_block_size();
453   
454#elif ( USE_IOC_SPI )
455
456    return _sdc_get_block_size();
457   
458#elif ( USE_IOC_HBA )
459
460    return _hba_get_block_size();
461   
462#elif ( USE_IOC_RDK )
463
464    return 512;
465
466#endif
467
468}
469
470
471// Local Variables:
472// tab-width: 4
473// c-basic-offset: 4
474// c-file-offsets:((innamespace . 0)(inline-open . 0))
475// indent-tabs-mode: nil
476// End:
477// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
478
Note: See TracBrowser for help on using the repository browser.