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

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

All drivers have been modified to use only the information
contained in the hard_config.h file

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