OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [disk/] [current/] [src/] [disk.c] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      io/disk/disk.c
4
//
5
//      High level disk driver
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.      
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):     savin 
43
// Date:          2003-06-10
44
// Purpose:       Top level disk driver
45
// Description: 
46
//
47
//####DESCRIPTIONEND####
48
//
49
//==========================================================================
50
 
51
#include <pkgconf/io.h>
52
#include <pkgconf/io_disk.h>
53
 
54
#include <cyg/io/io.h>
55
#include <cyg/io/devtab.h>
56
#include <cyg/io/disk.h>
57
#include <cyg/infra/cyg_ass.h>      // assertion support
58
#include <cyg/infra/diag.h>         // diagnostic output
59
 
60
// ---------------------------------------------------------------------------
61
 
62
#ifdef CYGDBG_IO_DISK_DEBUG
63
#define DEBUG 1
64
#endif
65
 
66
#ifdef DEBUG
67
# define D(_args_) diag_printf _args_
68
#else
69
# define D(_args_)
70
#endif
71
 
72
// ---------------------------------------------------------------------------
73
 
74
// Master Boot Record defines
75
#define MBR_SIG_ADDR  0x1FE   // signature address 
76
#define MBR_SIG_BYTE0 0x55    // signature first byte value
77
#define MBR_SIG_BYTE1 0xAA    // signature second byte value
78
#define MBR_PART_ADDR 0x1BE   // first partition address
79
#define MBR_PART_SIZE 0x10    // partition size
80
#define MBR_PART_NUM  4       // number of partitions
81
 
82
// Get cylinders, heads and sectors from data (MBR partition format)
83
#define READ_CHS(_data_, _c_, _h_, _s_)                     \
84
    do {                                                    \
85
        _h_ = (*((cyg_uint8 *)_data_));                     \
86
        _s_ = (*(((cyg_uint8 *)_data_)+1) &  0x3F);         \
87
        _c_ = (*(((cyg_uint8 *)_data_)+1) & ~0x3F) << 2 |   \
88
              (*(((cyg_uint8 *)_data_)+2));                 \
89
    } while (0)
90
 
91
// Get double word from data (MBR partition format)
92
#define READ_DWORD(_data_, _val_)                           \
93
    do {                                                    \
94
        _val_ = *((cyg_uint8 *)_data_)           |          \
95
                *(((cyg_uint8 *)_data_)+1) << 8  |          \
96
                *(((cyg_uint8 *)_data_)+2) << 16 |          \
97
                *(((cyg_uint8 *)_data_)+3) << 24;           \
98
    } while (0)
99
 
100
// Convert cylinders, heads and sectors to LBA sectors 
101
#define CHS_TO_LBA(_info_, _c_, _h_, _s_, _lba_) \
102
    (_lba_=(((_c_)*(_info_)->heads_num+(_h_))*(_info_)->sectors_num)+(_s_)-1)
103
 
104
// ---------------------------------------------------------------------------
105
 
106
static Cyg_ErrNo disk_bread(cyg_io_handle_t  handle,
107
                            void            *buf,
108
                            cyg_uint32      *len,
109
                            cyg_uint32       pos);
110
 
111
static Cyg_ErrNo disk_bwrite(cyg_io_handle_t  handle,
112
                             const void      *buf,
113
                             cyg_uint32      *len,
114
                             cyg_uint32       pos);
115
 
116
static Cyg_ErrNo disk_select(cyg_io_handle_t handle,
117
                             cyg_uint32      which,
118
                             CYG_ADDRWORD    info);
119
 
120
static Cyg_ErrNo disk_get_config(cyg_io_handle_t  handle,
121
                                 cyg_uint32       key,
122
                                 void            *buf,
123
                                 cyg_uint32      *len);
124
 
125
static Cyg_ErrNo disk_set_config(cyg_io_handle_t  handle,
126
                                 cyg_uint32       key,
127
                                 const void      *buf,
128
                                 cyg_uint32      *len);
129
 
130
BLOCK_DEVIO_TABLE(cyg_io_disk_devio,
131
                  disk_bwrite,
132
                  disk_bread,
133
                  disk_select,
134
                  disk_get_config,
135
                  disk_set_config
136
);
137
 
138
static cyg_bool disk_init(struct cyg_devtab_entry *tab);
139
 
140
static Cyg_ErrNo disk_connected(struct cyg_devtab_entry *tab,
141
                                cyg_disk_identify_t     *ident);
142
 
143
static Cyg_ErrNo disk_disconnected(struct disk_channel *chan);
144
 
145
static Cyg_ErrNo disk_lookup(struct cyg_devtab_entry **tab,
146
                             struct cyg_devtab_entry  *sub_tab,
147
                             const char               *name);
148
 
149
static void disk_transfer_done(struct disk_channel *chan, Cyg_ErrNo res);
150
 
151
DISK_CALLBACKS(cyg_io_disk_callbacks,
152
               disk_init,
153
               disk_connected,
154
               disk_disconnected,
155
               disk_lookup,
156
               disk_transfer_done
157
);
158
 
159
// ---------------------------------------------------------------------------
160
//
161
// Read partition from data
162
// 
163
 
164
static void
165
read_partition(cyg_uint8            *data,
166
               cyg_disk_info_t      *info,
167
               cyg_disk_partition_t *part)
168
{
169
    cyg_disk_identify_t *ident = &info->ident;
170
    cyg_uint16 c, h, s;
171
    cyg_uint32 start, end, size;
172
 
173
#ifdef DEBUG
174
    diag_printf("Partition data:\n");
175
    diag_dump_buf( data, 16 );
176
    diag_printf("Disk geometry: %d/%d/%d\n",info->ident.cylinders_num,
177
                info->ident.heads_num, info->ident.sectors_num );
178
#endif
179
 
180
    // Retrieve basic information
181
    part->type  = data[4];
182
    part->state = data[0];
183
    READ_DWORD(&data[12], part->size);
184
 
185
    READ_DWORD(&data[8], start);
186
    READ_DWORD(&data[12], size);
187
 
188
    // Use the LBA start and size fields if they are valid. Otherwise
189
    // fall back to CHS.
190
 
191
    if( start > 0 && size > 0 )
192
    {
193
        READ_DWORD(&data[8], start);
194
        end = start + size - 1;
195
 
196
#ifdef DEBUG
197
        diag_printf("Using LBA partition parameters\n");
198
        diag_printf("      LBA start %d\n",start);
199
        diag_printf("      LBA size  %d\n",size);
200
        diag_printf("      LBA end   %d\n",end);
201
#endif
202
 
203
    }
204
    else
205
    {
206
        READ_CHS(&data[1], c, h, s);
207
        CHS_TO_LBA(ident, c, h, s, start);
208
#ifdef DEBUG
209
        diag_printf("Using CHS partition parameters\n");
210
        diag_printf("      CHS start %d/%d/%d => %d\n",c,h,s,start);
211
#endif
212
 
213
        READ_CHS(&data[5], c, h, s);
214
        CHS_TO_LBA(ident, c, h, s, end);
215
#ifdef DEBUG
216
        diag_printf("      CHS end %d/%d/%d => %d\n",c,h,s,end);
217
        diag_printf("      CHS size %d\n",size);
218
#endif
219
 
220
    }
221
 
222
    part->size = size;
223
    part->start = start;
224
    part->end = end;
225
}
226
 
227
// ---------------------------------------------------------------------------
228
//
229
// Read Master Boot Record (partitions)
230
//
231
 
232
static Cyg_ErrNo
233
read_mbr(disk_channel *chan)
234
{
235
    cyg_disk_info_t *info = chan->info;
236
    disk_funs       *funs = chan->funs;
237
    disk_controller *ctlr = chan->controller;
238
    cyg_uint8 buf[512];
239
    Cyg_ErrNo res = ENOERR;
240
    int i;
241
 
242
    D(("read MBR\n"));
243
 
244
    for (i = 0; i < info->partitions_num; i++)
245
        info->partitions[i].type = 0x00;
246
 
247
 
248
 
249
    cyg_drv_mutex_lock( &ctlr->lock );
250
 
251
    while( ctlr->busy )
252
        cyg_drv_cond_wait( &ctlr->queue );
253
 
254
    ctlr->busy = true;
255
 
256
    ctlr->result = -EWOULDBLOCK;
257
 
258
    for( i = 0; i < sizeof(buf); i++ )
259
        buf[i] = 0;
260
 
261
    res = (funs->read)(chan, (void *)buf, 1, 0);
262
 
263
    if( res == -EWOULDBLOCK )
264
    {
265
        // If the driver replys EWOULDBLOCK, then the transfer is
266
        // being handled asynchronously and when it is finished it
267
        // will call disk_transfer_done(). This will wake us up here
268
        // to continue.
269
 
270
        while( ctlr->result == -EWOULDBLOCK )
271
            cyg_drv_cond_wait( &ctlr->async );
272
 
273
        res = ctlr->result;
274
    }
275
 
276
    ctlr->busy = false;
277
 
278
    cyg_drv_mutex_unlock( &ctlr->lock );
279
 
280
    if (ENOERR != res)
281
        return res;
282
 
283
#ifdef DEBUG
284
    diag_dump_buf_with_offset( buf, 512, buf );
285
#endif
286
 
287
    if (MBR_SIG_BYTE0 == buf[MBR_SIG_ADDR+0] && MBR_SIG_BYTE1 == buf[MBR_SIG_ADDR+1])
288
    {
289
        int npart;
290
 
291
        D(("disk MBR found\n"));
292
 
293
        npart = info->partitions_num < MBR_PART_NUM ?
294
            info->partitions_num : MBR_PART_NUM;
295
 
296
        for (i = 0; i < npart; i++)
297
        {
298
            cyg_disk_partition_t *part = &info->partitions[i];
299
 
300
            read_partition(&buf[MBR_PART_ADDR+MBR_PART_SIZE*i], info, part);
301
#ifdef DEBUG
302
            if (0x00 != part->type)
303
            {
304
                D(("\ndisk MBR partition %d:\n", i));
305
                D(("      type  = %02X\n", part->type));
306
                D(("      state = %02X\n", part->state));
307
                D(("      start = %d\n",   part->start));
308
                D(("      end   = %d\n",   part->end));
309
                D(("      size  = %d\n\n", part->size));
310
            }
311
#endif
312
        }
313
    }
314
    return ENOERR;
315
}
316
 
317
// ---------------------------------------------------------------------------
318
 
319
static cyg_bool
320
disk_init(struct cyg_devtab_entry *tab)
321
{
322
    disk_channel    *chan = (disk_channel *) tab->priv;
323
    cyg_disk_info_t *info = chan->info;
324
    int i;
325
 
326
    if (!chan->init)
327
    {
328
        disk_controller *controller = chan->controller;
329
 
330
        if( !controller->init )
331
        {
332
            cyg_drv_mutex_init( &controller->lock );
333
            cyg_drv_cond_init( &controller->queue, &controller->lock );
334
            cyg_drv_cond_init( &controller->async, &controller->lock );
335
 
336
            controller->init = true;
337
        }
338
 
339
        info->connected = false;
340
 
341
        // clear partition data
342
        for (i = 0; i < info->partitions_num; i++)
343
            info->partitions[i].type = 0x00;
344
 
345
        chan->init = true;
346
    }
347
    return true;
348
}
349
 
350
// ---------------------------------------------------------------------------
351
 
352
static Cyg_ErrNo
353
disk_connected(struct cyg_devtab_entry *tab,
354
               cyg_disk_identify_t     *ident)
355
{
356
    disk_channel    *chan = (disk_channel *) tab->priv;
357
    cyg_disk_info_t *info = chan->info;
358
    Cyg_ErrNo res = ENOERR;
359
 
360
    if (!chan->init)
361
        return -EINVAL;
362
 
363
    // If the device is already connected, nothing more to do
364
    if( info->connected )
365
        return ENOERR;
366
 
367
    // If any of these assertions fire, it is probable that the
368
    // hardware driver has not been updated to match the current disk
369
    // API.
370
    CYG_ASSERT( ident->lba_sectors_num > 0, "Bad LBA sector count" );
371
    CYG_ASSERT( ident->phys_block_size > 0, "Bad physical block size");
372
    CYG_ASSERT( ident->max_transfer > 0, "Bad max transfer size");
373
 
374
    info->ident      = *ident;
375
    info->block_size = 512;
376
    info->blocks_num = ident->lba_sectors_num;
377
    info->phys_block_size = ident->phys_block_size;
378
 
379
    D(("disk connected\n"));
380
    D(("    serial            = '%s'\n", ident->serial));
381
    D(("    firmware rev      = '%s'\n", ident->firmware_rev));
382
    D(("    model num         = '%s'\n", ident->model_num));
383
    D(("    block_size        = %d\n",   info->block_size));
384
    D(("    blocks_num        = %u\n",   info->blocks_num));
385
    D(("    phys_block_size   = %d\n",   info->phys_block_size));
386
 
387
    if (chan->mbr_support)
388
    {
389
        // read disk master boot record
390
        res = read_mbr(chan);
391
    }
392
 
393
    if (ENOERR == res)
394
    {
395
        // now declare that we are connected
396
        info->connected = true;
397
        chan->valid     = true;
398
    }
399
    return res;
400
}
401
 
402
// ---------------------------------------------------------------------------
403
 
404
static Cyg_ErrNo
405
disk_disconnected(disk_channel *chan)
406
{
407
    cyg_disk_info_t *info = chan->info;
408
    int i;
409
 
410
    if (!chan->init)
411
        return -EINVAL;
412
 
413
    info->connected = false;
414
    chan->valid     = false;
415
 
416
    // clear partition data and invalidate partition devices 
417
    for (i = 0; i < info->partitions_num; i++)
418
    {
419
        info->partitions[i].type  = 0x00;
420
        chan->pdevs_chan[i].valid = false;
421
    }
422
 
423
 
424
    D(("disk disconnected\n"));
425
 
426
    return ENOERR;
427
}
428
 
429
// ---------------------------------------------------------------------------
430
 
431
static Cyg_ErrNo
432
disk_lookup(struct cyg_devtab_entry **tab,
433
            struct cyg_devtab_entry  *sub_tab,
434
            const char *name)
435
{
436
    disk_channel    *chan = (disk_channel *) (*tab)->priv;
437
    cyg_disk_info_t *info = chan->info;
438
    struct cyg_devtab_entry *new_tab;
439
    disk_channel            *new_chan;
440
    int dev_num;
441
 
442
    if (!info->connected)
443
        return -EINVAL;
444
 
445
    dev_num = 0;
446
 
447
    while ('\0' != *name)
448
    {
449
        if (*name < '0' || *name > '9')
450
            return -EINVAL;
451
 
452
        dev_num = 10 * dev_num + (*name - '0');
453
        name++;
454
    }
455
 
456
    if (dev_num > info->partitions_num)
457
        return -EINVAL;
458
 
459
    D(("disk lookup dev number = %d\n", dev_num));
460
 
461
    if (0 == dev_num)
462
    {
463
        // 0 is the root device number
464
        return ENOERR;
465
    }
466
    if (0x00 == info->partitions[dev_num-1].type)
467
    {
468
        D(("disk NO partition for dev\n"));
469
        return -EINVAL;
470
    }
471
 
472
    new_tab  = &chan->pdevs_dev[dev_num-1];
473
    new_chan = &chan->pdevs_chan[dev_num-1];
474
 
475
    // copy device data from parent
476
    *new_tab  = **tab;
477
    *new_chan = *chan;
478
 
479
    new_tab->priv = (void *)new_chan;
480
 
481
    // set partition ptr
482
    new_chan->partition = &info->partitions[dev_num-1];
483
 
484
    // return device tab 
485
    *tab = new_tab;
486
 
487
    return ENOERR;
488
}
489
 
490
// ---------------------------------------------------------------------------
491
 
492
static Cyg_ErrNo
493
disk_bread(cyg_io_handle_t  handle,
494
           void            *buf,
495
           cyg_uint32      *len,  // In blocks
496
           cyg_uint32       pos)  // In blocks
497
{
498
    cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
499
    disk_channel       *chan = (disk_channel *) t->priv;
500
    disk_controller    *ctlr = chan->controller;
501
    disk_funs          *funs = chan->funs;
502
    cyg_disk_info_t    *info = chan->info;
503
    cyg_uint32  size = *len;
504
    cyg_uint8  *bbuf = (cyg_uint8  *)buf;
505
    Cyg_ErrNo   res  = ENOERR;
506
    cyg_uint32  last;
507
 
508
    cyg_drv_mutex_lock( &ctlr->lock );
509
 
510
    while( ctlr->busy )
511
        cyg_drv_cond_wait( &ctlr->queue );
512
 
513
    if (info->connected && chan->valid)
514
    {
515
        ctlr->busy = true;
516
 
517
        if (NULL != chan->partition)
518
        {
519
            pos += chan->partition->start;
520
            last = chan->partition->end;
521
        }
522
        else
523
        {
524
            last = info->blocks_num-1;
525
        }
526
 
527
        D(("disk read block=%d len=%d buf=%p\n", pos, *len, buf));
528
 
529
        while( size > 0 )
530
        {
531
            cyg_uint32 tfr = size;
532
 
533
            if (pos > last)
534
            {
535
                res = -EIO;
536
                break;
537
            }
538
 
539
            if( tfr > info->ident.max_transfer )
540
                tfr = info->ident.max_transfer;
541
 
542
            ctlr->result = -EWOULDBLOCK;
543
 
544
            cyg_drv_dsr_lock();
545
 
546
            res = (funs->read)(chan, (void*)bbuf, tfr, pos);
547
 
548
            if( res == -EWOULDBLOCK )
549
            {
550
                // If the driver replys EWOULDBLOCK, then the transfer is
551
                // being handled asynchronously and when it is finished it
552
                // will call disk_transfer_done(). This will wake us up here
553
                // to continue.
554
 
555
                while( ctlr->result == -EWOULDBLOCK )
556
                    cyg_drv_cond_wait( &ctlr->async );
557
 
558
                res = ctlr->result;
559
            }
560
 
561
            cyg_drv_dsr_unlock();
562
 
563
            if (ENOERR != res)
564
                goto done;
565
 
566
            if (!info->connected)
567
            {
568
                res = -EINVAL;
569
                goto done;
570
            }
571
 
572
            bbuf        += tfr * info->block_size;
573
            pos         += tfr;
574
            size        -= tfr;
575
        }
576
 
577
        ctlr->busy = false;
578
        cyg_drv_cond_signal( &ctlr->queue );
579
    }
580
    else
581
        res = -EINVAL;
582
 
583
done:
584
 
585
    cyg_drv_mutex_unlock( &ctlr->lock );
586
#ifdef CYGPKG_KERNEL
587
    cyg_thread_yield();
588
#endif
589
 
590
    *len -= size;
591
    return res;
592
}
593
 
594
// ---------------------------------------------------------------------------
595
 
596
static Cyg_ErrNo
597
disk_bwrite(cyg_io_handle_t  handle,
598
            const void      *buf,
599
            cyg_uint32      *len,   // In blocks
600
            cyg_uint32       pos)   // In blocks
601
{
602
    cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
603
    disk_channel       *chan = (disk_channel *) t->priv;
604
    disk_controller    *ctlr = chan->controller;
605
    disk_funs          *funs = chan->funs;
606
    cyg_disk_info_t    *info = chan->info;
607
    cyg_uint32  size = *len;
608
    cyg_uint8  *bbuf = (cyg_uint8 * const) buf;
609
    Cyg_ErrNo   res  = ENOERR;
610
    cyg_uint32  last;
611
 
612
    cyg_drv_mutex_lock( &ctlr->lock );
613
 
614
    while( ctlr->busy )
615
        cyg_drv_cond_wait( &ctlr->queue );
616
 
617
    if (info->connected && chan->valid)
618
    {
619
        ctlr->busy = true;
620
 
621
        if (NULL != chan->partition)
622
        {
623
            pos += chan->partition->start;
624
            last = chan->partition->end;
625
        }
626
        else
627
        {
628
            last = info->blocks_num-1;
629
        }
630
 
631
        D(("disk write block=%d len=%d buf=%p\n", pos, *len, buf));
632
 
633
        while( size > 0 )
634
        {
635
            cyg_uint32 tfr = size;
636
 
637
            if (pos > last)
638
            {
639
                res = -EIO;
640
                goto done;
641
            }
642
 
643
            if( tfr > info->ident.max_transfer )
644
                tfr = info->ident.max_transfer;
645
 
646
            ctlr->result = -EWOULDBLOCK;
647
 
648
            cyg_drv_dsr_lock();
649
 
650
            res = (funs->write)(chan, (void*)bbuf, tfr, pos);
651
 
652
            if( res == -EWOULDBLOCK )
653
            {
654
                // If the driver replys EWOULDBLOCK, then the transfer is
655
                // being handled asynchronously and when it is finished it
656
                // will call disk_transfer_done(). This will wake us up here
657
                // to continue.
658
 
659
                while( ctlr->result == -EWOULDBLOCK )
660
                    cyg_drv_cond_wait( &ctlr->async );
661
 
662
                res = ctlr->result;
663
            }
664
 
665
            cyg_drv_dsr_unlock();
666
 
667
            if (ENOERR != res)
668
                goto done;
669
 
670
            if (!info->connected)
671
            {
672
                res = -EINVAL;
673
                goto done;
674
            }
675
 
676
            bbuf        += tfr * info->block_size;
677
            pos         += tfr;
678
            size        -= tfr;
679
 
680
        }
681
 
682
        ctlr->busy = false;
683
        cyg_drv_cond_signal( &ctlr->queue );
684
    }
685
    else
686
        res = -EINVAL;
687
 
688
done:
689
 
690
    cyg_drv_mutex_unlock( &ctlr->lock );
691
#ifdef CYGPKG_KERNEL    
692
    cyg_thread_yield();
693
#endif
694
 
695
    *len -= size;
696
    return res;
697
}
698
 
699
// ---------------------------------------------------------------------------
700
 
701
static void disk_transfer_done(struct disk_channel *chan, Cyg_ErrNo res)
702
{
703
    disk_controller    *ctlr = chan->controller;
704
 
705
    ctlr->result = res;
706
 
707
    cyg_drv_cond_signal( &ctlr->async );
708
}
709
 
710
// ---------------------------------------------------------------------------
711
 
712
static cyg_bool
713
disk_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
714
{
715
    cyg_devtab_entry_t *t     = (cyg_devtab_entry_t *) handle;
716
    disk_channel       *chan  = (disk_channel *) t->priv;
717
    cyg_disk_info_t    *cinfo = chan->info;
718
 
719
    if (!cinfo->connected || !chan->valid)
720
        return false;
721
    else
722
        return true;
723
}
724
 
725
// ---------------------------------------------------------------------------
726
 
727
static Cyg_ErrNo
728
disk_get_config(cyg_io_handle_t  handle,
729
                cyg_uint32       key,
730
                void            *xbuf,
731
                cyg_uint32      *len)
732
{
733
    cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
734
    disk_channel       *chan = (disk_channel *) t->priv;
735
    disk_controller    *ctlr = chan->controller;
736
    cyg_disk_info_t    *info = chan->info;
737
    cyg_disk_info_t    *buf  = (cyg_disk_info_t *) xbuf;
738
    disk_funs          *funs = chan->funs;
739
    Cyg_ErrNo res = ENOERR;
740
 
741
    cyg_drv_mutex_lock( &ctlr->lock );
742
 
743
    while( ctlr->busy )
744
        cyg_drv_cond_wait( &ctlr->queue );
745
 
746
    if (info->connected && chan->valid)
747
    {
748
        ctlr->busy = true;
749
 
750
        D(("disk get config key=%d\n", key));
751
 
752
        switch (key) {
753
        case CYG_IO_GET_CONFIG_DISK_INFO:
754
            if (*len < sizeof(cyg_disk_info_t)) {
755
                res = -EINVAL;
756
                break;
757
            }
758
            D(("chan->info->block_size %u\n", chan->info->block_size ));
759
            D(("chan->info->blocks_num %u\n", chan->info->blocks_num ));
760
            D(("chan->info->phys_block_size %u\n", chan->info->phys_block_size ));
761
            *buf = *chan->info;
762
            *len = sizeof(cyg_disk_info_t);
763
            break;
764
 
765
        default:
766
            // pass down to lower layers
767
            res = (funs->get_config)(chan, key, xbuf, len);
768
        }
769
 
770
        ctlr->busy = false;
771
        cyg_drv_cond_signal( &ctlr->queue );
772
    }
773
    else
774
        res = -EINVAL;
775
 
776
    cyg_drv_mutex_unlock( &ctlr->lock );
777
 
778
    return res;
779
}
780
 
781
// ---------------------------------------------------------------------------
782
 
783
static Cyg_ErrNo
784
disk_set_config(cyg_io_handle_t  handle,
785
                cyg_uint32       key,
786
                const void      *xbuf,
787
                cyg_uint32      *len)
788
{
789
    cyg_devtab_entry_t *t    = (cyg_devtab_entry_t *) handle;
790
    disk_channel       *chan = (disk_channel *) t->priv;
791
    disk_controller    *ctlr = chan->controller;
792
    cyg_disk_info_t    *info = chan->info;
793
    disk_funs          *funs = chan->funs;
794
    Cyg_ErrNo res = ENOERR;
795
 
796
    cyg_drv_mutex_lock( &ctlr->lock );
797
 
798
    while( ctlr->busy )
799
        cyg_drv_cond_wait( &ctlr->queue );
800
 
801
    if (info->connected && chan->valid)
802
    {
803
        ctlr->busy = true;
804
 
805
        D(("disk set config key=%d\n", key));
806
 
807
        switch ( key )
808
        {
809
        case CYG_IO_SET_CONFIG_DISK_MOUNT:
810
            chan->mounts++;
811
            info->mounts++;
812
            D(("disk mount: chan %d disk %d\n",chan->mounts, info->mounts));
813
            break;
814
 
815
        case CYG_IO_SET_CONFIG_DISK_UMOUNT:
816
            chan->mounts--;
817
            info->mounts--;
818
            D(("disk umount: chan %d disk %d\n",chan->mounts, info->mounts));
819
            break;
820
 
821
        default:
822
            break;
823
        }
824
 
825
        // pass down to lower layers
826
        res = (funs->set_config)(chan, key, xbuf, len);
827
 
828
        ctlr->busy = false;
829
        cyg_drv_cond_signal( &ctlr->queue );
830
    }
831
    else
832
        res = -EINVAL;
833
 
834
    cyg_drv_mutex_unlock( &ctlr->lock );
835
 
836
    return res;
837
 
838
}
839
 
840
// ---------------------------------------------------------------------------
841
// EOF disk.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.