source: trunk/softs/tsar_boot/io_drivers/ioc.c @ 286

Last change on this file since 286 was 286, checked in by cfuguet, 12 years ago

Fixing bug in boot_tty.c:

Use address of tty status when reading with the ioread32 function.

Makefile and ioc.c:
Introducing SYSCLK_FREQ environment variable to choose a clock frequency when
using FPGA platform. 50000000 Hz by default.

File size: 10.1 KB
Line 
1#include <ioc.h>
2#include <defs.h>
3
4#define in_reset        __attribute__((section (".reset")))
5#define in_reset_data   __attribute__((section (".reset_data")))
6#define in_unckdata     __attribute__((section (".unckdata")))
7
8in_unckdata   int volatile _ioc_lock    = 0;
9in_reset_data int volatile _ioc_done    = 0;
10in_reset_data int volatile _ioc_status;
11
12#ifndef SOCLIB_IOC
13/*in_reset_data volatile unsigned int _ioc_init_ok = 0;*/
14
15static in_reset_data struct sdcard_dev  _sdcard_device;
16static in_reset_data struct spi_dev   * _spi_device   = ( struct spi_dev * )IOC_BASE;
17#endif
18
19//////////////////////////////////////////////////////////////////////////////////////////
20//  I/O BLOCK_DEVICE
21// The three functions below use the three variables _ioc_lock _ioc_done,
22// and _ioc_status for synchronsation.
23// - As the IOC component can be used by several programs running in parallel,
24// the _ioc_lock variable guaranties exclusive access to the device.
25// The _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock.
26// and set _ioc_lock to a non zero value.
27// The _ioc_write() and _ioc_read() functions are blocking, polling the _ioc_lock
28// variable until the device is available.
29// - When the tranfer is completed, the ISR routine activated by the IOC IRQ
30// set the _ioc_done variable to a non-zero value. Possible address errors detected
31// by the IOC peripheral are reported by the ISR in the _ioc_status variable.
32// The _ioc_completed() function is polling the _ioc_done variable, waiting for
33// tranfer conpletion. When the completion is signaled, the _ioc_completed() function
34// reset the _ioc_done variable to zero, and releases the _ioc_lock variable.
35//
36// In a multi-tasks environment, this polling policy must be replaced by a
37// descheduling policy for the requesting process.
38//////////////////////////////////////////////////////////////////////
39
40//////////////////////////////////////////////////////////////////////
41//  _dcache_buf_invalidate()
42// Invalidate all cache lines corresponding to a memory buffer.
43// This is used by the block_device driver.
44/////////////////////////////////////////////////////////////////////////
45//in_reset static void _dcache_buf_invalidate(const void * buffer, size_t size)
46//{
47//    size_t i;
48//    size_t dcache_line_size;
49//
50//    // retrieve dcache line size from config register (bits 12:10)
51//    asm volatile("mfc0 %0, $16, 1" : "=r" (dcache_line_size));
52//
53//    dcache_line_size = 2 << ((dcache_line_size>>10) & 0x7);
54//
55//    // iterate on lines to invalidate each one of them
56//    for ( i=0; i<size; i+=dcache_line_size )
57//        asm volatile
58//            (" mtc2 %0,     $7\n"
59//             :
60//             : "r" (*((char*)buffer+i))
61//             );
62//}
63
64///////////////////////////////////////////////////////////////////////////////////////
65//  _ioc_get_lock()
66// This blocking function is used by the _ioc_read() and _ioc_write() functions
67// to get _ioc_lock using LL/SC.
68///////////////////////////////////////////////////////////////////////////////////////
69in_reset void _ioc_get_lock()
70{
71    register unsigned int   proctime;
72    register unsigned int   delay;
73    register unsigned int*  plock = (unsigned int*)&_ioc_lock;         
74
75    asm volatile(
76        "mfc0 %0, $9    \n"
77        : "=r"(proctime)
78        : /* No inputs */
79    );
80
81    delay = (proctime & 0xF) << 4;
82
83    asm volatile ("_ioc_llsc:                   \n"
84                  "ll   $2,    0(%0)            \n" // $2 <= _ioc_lock
85                  "bnez $2,    _ioc_delay       \n" // random delay if busy
86                  "li   $3,    1                \n" // prepare argument for sc 
87                  "sc   $3,    0(%0)            \n" // try to set _ioc_busy
88                  "bnez $3,    _ioc_ok          \n" // exit if atomic
89                  "_ioc_delay:                  \n"
90                  "move $4,    %1               \n" // $4 <= delay
91                  "_ioc_loop:                   \n"
92                  "addi $4,    $4,    -1        \n" // $4 <= $4 - 1
93                  "beqz $4,    _ioc_loop        \n" // test end delay
94                  "j           _ioc_llsc        \n" // retry
95                  "_ioc_ok:                     \n"
96                  ::"r"(plock),"r"(delay):"$2","$3","$4");
97}
98
99in_reset int _ioc_init()
100{
101#ifndef SOCLIB_IOC
102    in_reset_data static char init_begin[] = "Initializing block device\n\r";
103    in_reset_data static char init_end[]   = "Finish block device initialization\n\r";
104
105    unsigned char sdcard_rsp;
106
107    boot_puts(init_begin);
108
109#ifndef SYSCLK_FREQ
110#warning "Using default value for SYSCLK_FREQ = 50000000"
111#define SYSCLK_FREQ 50000000U
112#endif
113
114    /**
115     * Initializing the SPI controller
116     */
117    spi_dev_config (
118      _spi_device   ,
119      200000        , /**< SPI_clk: 200 Khz */
120      SYSCLK_FREQ   , /**< Sys_clk          */
121      8             , /**< Charlen: 8       */
122      SPI_TX_NEGEDGE,
123      SPI_RX_POSEDGE
124    ); 
125
126    /**
127     * Initializing the SD Card
128     */
129    if ( (sdcard_rsp = sdcard_dev_open(&_sdcard_device, _spi_device, 0)) )
130        return sdcard_rsp;
131
132    if ( (sdcard_rsp = sdcard_dev_set_blocklen(&_sdcard_device, 512)) )
133        return sdcard_rsp;
134
135    /**
136     * Incrementing SDCARD clock frequency for normal function
137     */
138    spi_dev_config (
139        _spi_device ,
140        10000000    , /**< SPI_clkL 10 Mhz */
141        SYSCLK_FREQ , /**< Sys_clk         */
142        -1          , /**< Charlen: 8      */
143        -1          ,
144        -1
145    );
146
147    boot_puts(init_end);
148#endif
149
150    return 0;
151}
152
153///////////////////////////////////////////////////////////////////////////////////////
154//  _ioc_completed()
155// This blocking function cheks completion of an I/O transfer and reports errors.
156// It returns 0 if the transfer is successfully completed.
157// It returns -1 if an error has been reported.
158///////////////////////////////////////////////////////////////////////////////////////
159in_reset int _ioc_completed()
160{
161    unsigned int status = 0;
162
163#ifdef SOCLIB_IOC
164
165    unsigned int * ioc_address = ( unsigned int * )VCIBD_BASE;
166 
167    while ( 1 )
168    { 
169        status = ioread32(&ioc_address[BLOCK_DEVICE_STATUS]);
170
171        if (( status == BLOCK_DEVICE_READ_SUCCESS ) ||
172            ( status == BLOCK_DEVICE_READ_ERROR  ))
173        break;
174    }
175   
176#endif
177
178    return status;
179}
180
181//////////////////////////////////////////////////////////////////////////////////////
182//  _ioc_write()
183// Transfer data from a memory buffer to a file on the block_device.
184// - lba    : first block index on the disk
185// - buffer : base address of the memory buffer
186// - count  : number of blocks to be transfered
187// The source buffer must be in user address space.
188///////////////////////////////////////////////////////////////////////////////////////
189in_reset int _ioc_write(size_t lba, void* buffer, size_t count)
190{
191    // get the lock
192    // _ioc_get_lock();
193
194#ifdef SOCLIB_IOC
195
196    unsigned int * ioc_address = ( unsigned int * )VCIBD_BASE;
197
198    // block_device configuration
199    iowrite32( &ioc_address[BLOCK_DEVICE_BUFFER],
200            ( unsigned int ) buffer );
201
202    iowrite32( &ioc_address[BLOCK_DEVICE_COUNT],
203            ( unsigned int ) count );
204
205    iowrite32( &ioc_address[BLOCK_DEVICE_LBA],
206            ( unsigned int ) lba );
207
208    iowrite32( &ioc_address[BLOCK_DEVICE_IRQ_ENABLE],
209            ( unsigned int ) 0 );
210
211    iowrite32( &ioc_address[BLOCK_DEVICE_OP],
212            ( unsigned int ) BLOCK_DEVICE_WRITE);
213
214    _ioc_completed();
215
216#else   
217/*
218in_reset_data static char end_line[] =
219    "\n\r";
220in_reset_data static char error_init[] =
221    "ERROR during initialization of block device. Code: ";
222
223unsigned int sdcard_rsp;
224
225if ( _ioc_init_ok == 0 )
226{
227    if (( sdcard_rsp = _ioc_init(&_sdcard_device, 0) ))
228    {
229        boot_puts(error_init);
230        boot_putx(sdcard_rsp);
231        boot_puts(end_line);
232    }   
233
234    _ioc_init_ok = 1;
235}
236*/
237       
238    sdcard_dev_lseek(&_sdcard_device, lba);
239    sdcard_dev_write(&_sdcard_device, buffer, count*512);
240
241#endif
242
243// _ioc_lock = 0;
244
245    return 0;
246}
247
248/**
249 *  _ioc_read()
250 *
251 * Transfer data from a file on the block device to a memory buffer.
252 *
253 * \param lba    : first block index on the disk
254 * \param buffer : base address of the memory buffer
255 * \param count  : number of blocks to be transfered
256 *
257 * \note This is a blocking function. The function returns once the transfer
258 *       has finished
259 */
260in_reset int _ioc_read(size_t lba, void* buffer, size_t count)
261{
262    // get the lock
263    // _ioc_get_lock();
264
265#ifdef SOCLIB_IOC
266
267    unsigned int * ioc_address  = (unsigned int*)VCIBD_BASE;
268
269    // block_device configuration
270    iowrite32( &ioc_address[BLOCK_DEVICE_BUFFER],
271            ( unsigned int ) buffer );
272
273    iowrite32( &ioc_address[BLOCK_DEVICE_COUNT],
274            ( unsigned int ) count );
275
276    iowrite32( &ioc_address[BLOCK_DEVICE_LBA],
277            ( unsigned int ) lba );
278
279    iowrite32( &ioc_address[BLOCK_DEVICE_IRQ_ENABLE],
280            ( unsigned int ) 0 );
281
282    iowrite32( &ioc_address[BLOCK_DEVICE_OP],
283            ( unsigned int ) BLOCK_DEVICE_READ );
284
285    _ioc_completed();
286
287#else
288    in_reset_data static char error_read[] =
289        "ERROR during read on the SDCARD device. Code: ";
290    in_reset_data static char end_line[] =
291        "\n\r";
292/*
293in_reset_data static char error_init[] =
294    "ERROR during initialization of block device. Code: ";
295*/
296
297    unsigned int sdcard_rsp;
298
299/*
300if ( _ioc_init_ok == 0 )
301{
302    if (( sdcard_rsp = _ioc_init(&_sdcard_device, 0) ))
303    {
304        boot_puts(error_init);
305        boot_putx(sdcard_rsp);
306        boot_puts(end_line);
307    }   
308   
309    _ioc_init_ok = 1;
310}
311*/
312
313    sdcard_dev_lseek(&_sdcard_device, lba);
314
315    unsigned int i;
316    for(i = 0; i < count; i++)
317    {
318        if (( sdcard_rsp = sdcard_dev_read (
319                        &_sdcard_device,
320                        (unsigned char *) buffer + (512 * i),
321                        512
322                        ) 
323            ))
324        {
325            boot_puts(error_read); 
326            boot_putx(sdcard_rsp);
327            boot_puts(end_line);
328
329            return 1;
330        }   
331    }
332   
333#endif
334
335    //_ioc_lock = 0;
336
337    return 0;
338}
339#undef in_reset
340#undef in_reset_data
341#undef in_unckdata
342
343/*
344 * vim: tabstop=4 : shiftwidth=4 : expandtab
345 */
Note: See TracBrowser for help on using the repository browser.