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

Last change on this file since 481 was 481, checked in by alain, 9 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.