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

Last change on this file since 488 was 481, checked in by alain, 10 years ago

1) The NIC, IOC, DMA and HBA drivers have been adapted to support the new _v2p_translate() function prototype (returns void).
2) The _mmc_inval() and _mmc_sync() functions does not use anymore the hard lock in the MMC, but use a soft spin_lock.
3) The NIC driver does not use anymore the GIET_NIC_BUFSIZE, GIET_NIC_NBUFS, and GIET_NIC_TIMEOUT parameters (removed from giet_config.h file).
4) The NIC driver registers map has been modified to support 64 bytes buffer descriptors for chained buffers.

File size: 9.1 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
[481]152        _v2p_translate( (page_table_t*)pt_vbase,
153                        buf_vaddr >> 12,
154                        &ppn,
155                        &flags );
156
[413]157        // check access rights
158        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
159        {
[437]160            _puts("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
[413]161            _exit(); 
162        }
[258]163
[413]164        if ( ((flags & PTE_W) == 0 ) && to_mem )
165        {
[437]166            _puts("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
[413]167            _exit(); 
168        }
[258]169
[413]170        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
[258]171    }
172
[413]173    // cache coherence for both L1 & L2 caches
[258]174
175    if ( to_mem ) // memory write : invalidate data caches
176    {
[413]177        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
178        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
[258]179
[413]180        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]181        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
[258]182    }
183    else         // memory read : update data caches
184    {
[295]185        // L1 cache : nothing to do for L1 write-through
[258]186
[413]187        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]188        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
[258]189    }
190
[295]191    // select the proper physical device
192
[413]193#if   ( USE_IOC_BDV )
[295]194        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
195        else        error = _bdv_write( mode, lba, buf_paddr, count);
196#elif ( USE_IOC_SPI )
197        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
198        else        error = _sdc_write(mode, lba, buf_paddr, count);
199#elif ( USE_IOC_HBA )
200        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
201        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
202#elif ( USE_IOC_RDK )
203        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
204        else        error = _rdk_write(lba, buf_vaddr, count);
205#endif
206
[258]207    return error;
208} // end _ioc_access()
209
[413]210//////////////////////////////////////////////
[289]211unsigned int _ioc_init( unsigned int channel )
[258]212{
[295]213
214#if   ( USE_IOC_BDV )
215
216    return _bdv_init();
217
218#elif ( USE_IOC_SPI )
219
220    return _sdc_init();
221   
222#elif ( USE_IOC_HBA )
223
[289]224    return _hba_init( channel );
[295]225   
226#elif ( USE_IOC_RDK )
227
228    return _rdk_init();
229   
[289]230#endif
[295]231   
[258]232}
233
[413]234//////////////////////////////////////////////
[295]235unsigned int _ioc_read( unsigned int channel,
236                        unsigned int mode, 
[258]237                        unsigned int lba, 
238                        void*        buffer, 
239                        unsigned int count) 
240{
241    return _ioc_access( 1,        // read access
[295]242                        channel,
[258]243                        mode, 
244                        lba,
245                        (unsigned int) buffer,
246                        count );
247}
248
[413]249//////////////////////////////////////////////
[295]250unsigned int _ioc_write( unsigned int channel,
251                         unsigned int mode, 
[258]252                         unsigned int lba, 
253                         const void*  buffer, 
254                         unsigned int count ) 
255{
256    return _ioc_access( 0,        // write access
[295]257                        channel,
[258]258                        mode, 
259                        lba,
260                        (unsigned int) buffer,
261                        count );
262}
263
[413]264/////////////////////////////////////////////////////
[295]265unsigned int _ioc_get_status( unsigned int  channel )
[258]266{
[295]267
268#if   ( USE_IOC_BDV )
269
270    return _bdv_get_status( );
271
272#elif ( USE_IOC_SPI )
273
274    return _sdc_get_status( );
275
276#elif ( USE_IOC_HBA )
277
278    return _hba_get_status( channel );
279
280#elif ( USE_IOC_RDK )
281
[437]282    return rdk_get_status();
[295]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.