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

Last change on this file since 416 was 413, checked in by alain, 10 years ago

Introducing support for the PIC_MASK register in pic_driver.

File size: 9.2 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///////////////////////////////////////////////////////////////////////////////////
[413]8// Implementation note:
[258]9//
[413]10// 1) In order to share the code, the two _ioc_read() and _ioc_write() functions
11// call the same _ioc_access() function.
[258]12//
[413]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.
[258]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>
[295]23#include <bdv_driver.h>
24#include <hba_driver.h>
25#include <sdc_driver.h>
26#include <rdk_driver.h>
[258]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
[320]34#if !defined( SEG_IOC_BASE )
35# error: You must define SEG_IOC_BASE in the hard_config.h file
36#endif
37
[258]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
[295]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)
[289]48#endif
49
[295]50#if USE_IOC_BDV
[289]51# include <bdv_driver.h>
52#endif
53
[295]54#if USE_IOC_SPI
[289]55# include <sdc_driver.h>
56#endif
57
[295]58#if USE_IOC_HBA
[289]59# include <hba_driver.h>
60#endif
61
[295]62#if USE_IOC_RDK
63# include <rdk_driver.h>
64#endif
[289]65
[295]66///////////////////////////////////////////////////////////////////////////////
67// IOC global variables
68///////////////////////////////////////////////////////////////////////////////
69
[258]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.
[295]80// - mode       : BOOT_PA / BOOT_VA / KERNEL / USER
[258]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,
[295]87                                 unsigned int channel,
[258]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
[295]95unsigned int procid  = _get_procid();
96unsigned int cid     = procid / NB_PROCS_MAX;
97unsigned int lpid    = procid % NB_PROCS_MAX;
98unsigned int x       = cid >> Y_WIDTH;
99unsigned int y       = cid & ((1<<Y_WIDTH) - 1);
100
[413]101_printf("\n[IOC DEBUG] _ioc_access() : P[%d,%d,%d] enters at cycle %d\n"
[295]102        " - channel  = %d\n"
103        " - mode     = %d\n"
[313]104        " - vaddr    = %x\n"
[295]105        " - sectors  = %d\n"
[313]106        " - lba      = %x\n",
[295]107        x, y, lpid, _get_proctime(), channel, mode, buf_vaddr, count, lba );
[258]108#endif
109
110    unsigned int error;            // return value
111    unsigned int pt_vbase;         // page table vbase address
[413]112    unsigned int ppn;              // user buffer first page PPN
113    unsigned int flags;            // user buffer protection flags
114    paddr_t      buf_paddr;        // user buffer physical address (if no IOMMU),
[258]115
116    // check buffer alignment
117    if ((unsigned int) buf_vaddr & 0x3)
118    {
[413]119        _printf("\n[IOC ERROR] in _ioc_access() : buffer not word aligned\n");
[295]120        _exit(); 
[258]121    }
122
[295]123    // check channel
124    if ( (USE_IOC_HBA == 0) && (channel > 0) )
125    {
[413]126        _printf("\n[IOC ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
[295]127        _exit(); 
128    }
129
[258]130    unsigned int length = count << 9;  // count * 512 bytes
131
[295]132    // computing memory buffer physical address
133    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity mapping
[258]134    {
135        buf_paddr = (paddr_t)buf_vaddr;
136    }
[295]137    else                                                    // V2P translation required
[258]138    {
139        // get page table virtual address
140        pt_vbase = _get_context_slot(CTX_PTAB_ID);
141
[413]142        // get user buffer first page ppn and flags
143        unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase,
144                                           buf_vaddr >> 12,
145                                           &ppn,
146                                           &flags );
147        // check access rights
148        if ( ko )
[258]149        {
[413]150            _printf("\n[IOC ERROR] in _ioc_access() : buffer unmapped\n");
151            _exit(); 
152        }
[258]153
[413]154        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
155        {
156            _printf("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
157            _exit(); 
158        }
[258]159
[413]160        if ( ((flags & PTE_W) == 0 ) && to_mem )
161        {
162            _printf("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
163            _exit(); 
164        }
[258]165
[413]166        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
[258]167    }
168
[413]169    // cache coherence for both L1 & L2 caches
[258]170
171    if ( to_mem ) // memory write : invalidate data caches
172    {
[413]173        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
174        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
[258]175
[413]176        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]177        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
[258]178    }
179    else         // memory read : update data caches
180    {
[295]181        // L1 cache : nothing to do for L1 write-through
[258]182
[413]183        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]184        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
[258]185    }
186
[295]187    // select the proper physical device
188
[413]189#if   ( USE_IOC_BDV )
[295]190        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
191        else        error = _bdv_write( mode, lba, buf_paddr, count);
192#elif ( USE_IOC_SPI )
193        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
194        else        error = _sdc_write(mode, lba, buf_paddr, count);
195#elif ( USE_IOC_HBA )
196        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
197        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
198#elif ( USE_IOC_RDK )
199        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
200        else        error = _rdk_write(lba, buf_vaddr, count);
201#endif
202
[258]203    return error;
204} // end _ioc_access()
205
[413]206//////////////////////////////////////////////
[289]207unsigned int _ioc_init( unsigned int channel )
[258]208{
[295]209
210#if   ( USE_IOC_BDV )
211
212    return _bdv_init();
213
214#elif ( USE_IOC_SPI )
215
216    return _sdc_init();
217   
218#elif ( USE_IOC_HBA )
219
[289]220    return _hba_init( channel );
[295]221   
222#elif ( USE_IOC_RDK )
223
224    return _rdk_init();
225   
[289]226#endif
[295]227   
[258]228}
229
[413]230//////////////////////////////////////////////
[295]231unsigned int _ioc_read( unsigned int channel,
232                        unsigned int mode, 
[258]233                        unsigned int lba, 
234                        void*        buffer, 
235                        unsigned int count) 
236{
237    return _ioc_access( 1,        // read access
[295]238                        channel,
[258]239                        mode, 
240                        lba,
241                        (unsigned int) buffer,
242                        count );
243}
244
[413]245//////////////////////////////////////////////
[295]246unsigned int _ioc_write( unsigned int channel,
247                         unsigned int mode, 
[258]248                         unsigned int lba, 
249                         const void*  buffer, 
250                         unsigned int count ) 
251{
252    return _ioc_access( 0,        // write access
[295]253                        channel,
[258]254                        mode, 
255                        lba,
256                        (unsigned int) buffer,
257                        count );
258}
259
[413]260/////////////////////////////////////////////////////
[295]261unsigned int _ioc_get_status( unsigned int  channel )
[258]262{
[295]263
264#if   ( USE_IOC_BDV )
265
266    return _bdv_get_status( );
267
268#elif ( USE_IOC_SPI )
269
270    return _sdc_get_status( );
271
272#elif ( USE_IOC_HBA )
273
274    return _hba_get_status( channel );
275
276#elif ( USE_IOC_RDK )
277
278    _printf("[GIET ERROR] _ioc_get_status() should not be called");
279    _printf(" when RAMDISK  is used...\n");
280    _exit();
281
282    return 0;
283
[289]284#endif
[295]285
[258]286}
287
[413]288//////////////////////////////////
[258]289unsigned int _ioc_get_block_size() 
290{
[295]291
292#if   ( USE_IOC_BDV )
293
[289]294    return _bdv_get_block_size();
[295]295   
296#elif ( USE_IOC_SPI )
297
[289]298    return _sdc_get_block_size();
[295]299   
300#elif ( USE_IOC_HBA )
301
[289]302    return _hba_get_block_size();
[295]303   
304#elif ( USE_IOC_RDK )
305
306    return 512;
307
[289]308#endif
[295]309
[258]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.