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

Last change on this file since 496 was 496, checked in by alain, 9 years ago

1) Introduce access functions to MMC intrumentation registers.
2) Use _printf for error or debug messages.

File size: 8.9 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
[496]69__attribute__((section (".kdata")))
70volatile unsigned int _ioc_iommu_ix1 = 0;
[258]71
[496]72__attribute__((section (".kdata")))
73volatile unsigned int _ioc_iommu_npages; 
[258]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();
[426]96unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
97unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
98unsigned int p       = procid & ((1<<P_WIDTH)-1);
[496]99_printf("\n[IOC DEBUG] _ioc_access() : P[%d,%d,%d] enters at cycle %d\n"
100        " - channel  = %d\n"
101        " - mode     = %d\n"
102        " - vaddr    = %x\n"
103        " - sectors  = %d\n"
104        " - lba      = %x\n",
105        x, y , p, _get_proctime(), channel, mode, buf_vaddr, count, lba );
[258]106#endif
107
108    unsigned int error;            // return value
109    unsigned int pt_vbase;         // page table vbase address
[413]110    unsigned int ppn;              // user buffer first page PPN
111    unsigned int flags;            // user buffer protection flags
112    paddr_t      buf_paddr;        // user buffer physical address (if no IOMMU),
[258]113
114    // check buffer alignment
115    if ((unsigned int) buf_vaddr & 0x3)
116    {
[437]117        _puts("\n[IOC ERROR] in _ioc_access() : buffer not word aligned\n");
[295]118        _exit(); 
[258]119    }
120
[295]121    // check channel
122    if ( (USE_IOC_HBA == 0) && (channel > 0) )
123    {
[437]124        _puts("\n[IOC ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
[295]125        _exit(); 
126    }
127
[258]128    unsigned int length = count << 9;  // count * 512 bytes
129
[295]130    // computing memory buffer physical address
[496]131    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity
[258]132    {
133        buf_paddr = (paddr_t)buf_vaddr;
134    }
[496]135    else                                                 // V2P translation required
[258]136    {
137        // get page table virtual address
138        pt_vbase = _get_context_slot(CTX_PTAB_ID);
139
[413]140        // get user buffer first page ppn and flags
[481]141        _v2p_translate( (page_table_t*)pt_vbase,
142                        buf_vaddr >> 12,
143                        &ppn,
144                        &flags );
145
[413]146        // check access rights
147        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
148        {
[437]149            _puts("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
[413]150            _exit(); 
151        }
[258]152
[413]153        if ( ((flags & PTE_W) == 0 ) && to_mem )
154        {
[437]155            _puts("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
[413]156            _exit(); 
157        }
[258]158
[413]159        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
[258]160    }
161
[413]162    // cache coherence for both L1 & L2 caches
[258]163
164    if ( to_mem ) // memory write : invalidate data caches
165    {
[413]166        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
167        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
[258]168
[413]169        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]170        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
[258]171    }
172    else         // memory read : update data caches
173    {
[295]174        // L1 cache : nothing to do for L1 write-through
[258]175
[413]176        // L2 cache (only if we use an IO-Bridge component in architecture))
[297]177        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
[258]178    }
179
[295]180    // select the proper physical device
181
[413]182#if   ( USE_IOC_BDV )
[295]183        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
184        else        error = _bdv_write( mode, lba, buf_paddr, count);
185#elif ( USE_IOC_SPI )
186        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
187        else        error = _sdc_write(mode, lba, buf_paddr, count);
188#elif ( USE_IOC_HBA )
189        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
190        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
191#elif ( USE_IOC_RDK )
192        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
193        else        error = _rdk_write(lba, buf_vaddr, count);
194#endif
195
[258]196    return error;
197} // end _ioc_access()
198
[413]199//////////////////////////////////////////////
[289]200unsigned int _ioc_init( unsigned int channel )
[258]201{
[295]202
203#if   ( USE_IOC_BDV )
204
205    return _bdv_init();
206
207#elif ( USE_IOC_SPI )
208
209    return _sdc_init();
210   
211#elif ( USE_IOC_HBA )
212
[289]213    return _hba_init( channel );
[295]214   
215#elif ( USE_IOC_RDK )
216
217    return _rdk_init();
218   
[289]219#endif
[295]220   
[258]221}
222
[413]223//////////////////////////////////////////////
[295]224unsigned int _ioc_read( unsigned int channel,
225                        unsigned int mode, 
[258]226                        unsigned int lba, 
227                        void*        buffer, 
228                        unsigned int count) 
229{
230    return _ioc_access( 1,        // read access
[295]231                        channel,
[258]232                        mode, 
233                        lba,
234                        (unsigned int) buffer,
235                        count );
236}
237
[413]238//////////////////////////////////////////////
[295]239unsigned int _ioc_write( unsigned int channel,
240                         unsigned int mode, 
[258]241                         unsigned int lba, 
242                         const void*  buffer, 
243                         unsigned int count ) 
244{
245    return _ioc_access( 0,        // write access
[295]246                        channel,
[258]247                        mode, 
248                        lba,
249                        (unsigned int) buffer,
250                        count );
251}
252
[413]253/////////////////////////////////////////////////////
[295]254unsigned int _ioc_get_status( unsigned int  channel )
[258]255{
[295]256
257#if   ( USE_IOC_BDV )
258
259    return _bdv_get_status( );
260
261#elif ( USE_IOC_SPI )
262
263    return _sdc_get_status( );
264
265#elif ( USE_IOC_HBA )
266
267    return _hba_get_status( channel );
268
269#elif ( USE_IOC_RDK )
270
[496]271    return _rdk_get_status();
[295]272
[289]273#endif
[295]274
[258]275}
276
[413]277//////////////////////////////////
[258]278unsigned int _ioc_get_block_size() 
279{
[295]280
281#if   ( USE_IOC_BDV )
282
[289]283    return _bdv_get_block_size();
[295]284   
285#elif ( USE_IOC_SPI )
286
[289]287    return _sdc_get_block_size();
[295]288   
289#elif ( USE_IOC_HBA )
290
[289]291    return _hba_get_block_size();
[295]292   
293#elif ( USE_IOC_RDK )
294
295    return 512;
296
[289]297#endif
[295]298
[258]299}
300
301
302// Local Variables:
303// tab-width: 4
304// c-basic-offset: 4
305// c-file-offsets:((innamespace . 0)(inline-open . 0))
306// indent-tabs-mode: nil
307// End:
308// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
309
Note: See TracBrowser for help on using the repository browser.