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

Last change on this file since 478 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
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///////////////////////////////////////////////////////////////////////////////////
[437]8// Implementation notes:
[413]9// 1) In order to share the code, the two _ioc_read() and _ioc_write() functions
[437]10// call the same _ioc_access() function, and this function call the selected
11// physical driver (BDV / HBA / SPI / RDK).
[413]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.
[258]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>
[295]22#include <bdv_driver.h>
23#include <hba_driver.h>
24#include <sdc_driver.h>
25#include <rdk_driver.h>
[258]26#include <utils.h>
[456]27#include <tty0.h>
[258]28#include <iob_driver.h>
29#include <ctx_handler.h>
30#include <mmc_driver.h>
31#include <vmem.h>
32
[320]33#if !defined( SEG_IOC_BASE )
34# error: You must define SEG_IOC_BASE in the hard_config.h file
35#endif
36
[258]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
[295]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)
[289]47#endif
48
[295]49#if USE_IOC_BDV
[289]50# include <bdv_driver.h>
51#endif
52
[295]53#if USE_IOC_SPI
[289]54# include <sdc_driver.h>
55#endif
56
[295]57#if USE_IOC_HBA
[289]58# include <hba_driver.h>
59#endif
60
[295]61#if USE_IOC_RDK
62# include <rdk_driver.h>
63#endif
[289]64
[295]65///////////////////////////////////////////////////////////////////////////////
66// IOC global variables
67///////////////////////////////////////////////////////////////////////////////
68
[258]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.
[295]79// - mode       : BOOT_PA / BOOT_VA / KERNEL / USER
[258]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,
[295]86                                 unsigned int channel,
[258]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
[295]94unsigned int procid  = _get_procid();
[426]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);
[437]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");
[258]117#endif
118
119    unsigned int error;            // return value
120    unsigned int pt_vbase;         // page table vbase address
[413]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),
[258]124
125    // check buffer alignment
126    if ((unsigned int) buf_vaddr & 0x3)
127    {
[437]128        _puts("\n[IOC ERROR] in _ioc_access() : buffer not word aligned\n");
[295]129        _exit(); 
[258]130    }
131
[295]132    // check channel
133    if ( (USE_IOC_HBA == 0) && (channel > 0) )
134    {
[437]135        _puts("\n[IOC ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
[295]136        _exit(); 
137    }
138
[258]139    unsigned int length = count << 9;  // count * 512 bytes
140
[295]141    // computing memory buffer physical address
142    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity mapping
[258]143    {
144        buf_paddr = (paddr_t)buf_vaddr;
145    }
[295]146    else                                                    // V2P translation required
[258]147    {
148        // get page table virtual address
149        pt_vbase = _get_context_slot(CTX_PTAB_ID);
150
[413]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 )
[258]158        {
[437]159            _puts("\n[IOC ERROR] in _ioc_access() : buffer unmapped\n");
[413]160            _exit(); 
161        }
[258]162
[413]163        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
164        {
[437]165            _puts("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
[413]166            _exit(); 
167        }
[258]168
[413]169        if ( ((flags & PTE_W) == 0 ) && to_mem )
170        {
[437]171            _puts("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
[413]172            _exit(); 
173        }
[258]174
[413]175        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
[258]176    }
177
[413]178    // cache coherence for both L1 & L2 caches
[258]179
180    if ( to_mem ) // memory write : invalidate data caches
181    {
[413]182        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
183        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
[258]184
[413]185        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]186        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
[258]187    }
188    else         // memory read : update data caches
189    {
[295]190        // L1 cache : nothing to do for L1 write-through
[258]191
[413]192        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]193        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
[258]194    }
195
[295]196    // select the proper physical device
197
[413]198#if   ( USE_IOC_BDV )
[295]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
[258]212    return error;
213} // end _ioc_access()
214
[413]215//////////////////////////////////////////////
[289]216unsigned int _ioc_init( unsigned int channel )
[258]217{
[295]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
[289]229    return _hba_init( channel );
[295]230   
231#elif ( USE_IOC_RDK )
232
233    return _rdk_init();
234   
[289]235#endif
[295]236   
[258]237}
238
[413]239//////////////////////////////////////////////
[295]240unsigned int _ioc_read( unsigned int channel,
241                        unsigned int mode, 
[258]242                        unsigned int lba, 
243                        void*        buffer, 
244                        unsigned int count) 
245{
246    return _ioc_access( 1,        // read access
[295]247                        channel,
[258]248                        mode, 
249                        lba,
250                        (unsigned int) buffer,
251                        count );
252}
253
[413]254//////////////////////////////////////////////
[295]255unsigned int _ioc_write( unsigned int channel,
256                         unsigned int mode, 
[258]257                         unsigned int lba, 
258                         const void*  buffer, 
259                         unsigned int count ) 
260{
261    return _ioc_access( 0,        // write access
[295]262                        channel,
[258]263                        mode, 
264                        lba,
265                        (unsigned int) buffer,
266                        count );
267}
268
[413]269/////////////////////////////////////////////////////
[295]270unsigned int _ioc_get_status( unsigned int  channel )
[258]271{
[295]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
[437]287    return rdk_get_status();
[295]288
[289]289#endif
[295]290
[258]291}
292
[413]293//////////////////////////////////
[258]294unsigned int _ioc_get_block_size() 
295{
[295]296
297#if   ( USE_IOC_BDV )
298
[289]299    return _bdv_get_block_size();
[295]300   
301#elif ( USE_IOC_SPI )
302
[289]303    return _sdc_get_block_size();
[295]304   
305#elif ( USE_IOC_HBA )
306
[289]307    return _hba_get_block_size();
[295]308   
309#elif ( USE_IOC_RDK )
310
311    return 512;
312
[289]313#endif
[295]314
[258]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.