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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [disk/] [ide/] [current/] [src/] [ide_disk.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      ide_disk.c
4
//
5
//      IDE polled mode disk driver 
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 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):    iz
43
// Contributors: 
44
// Date:         2004-10-16
45
//
46
//####DESCRIPTIONEND####
47
//
48
//==========================================================================
49
 
50
#include <pkgconf/devs_disk_ide.h>
51
#include <pkgconf/io_disk.h>
52
 
53
#include <cyg/infra/cyg_type.h>
54
#include <cyg/infra/cyg_ass.h>
55
#include <cyg/infra/diag.h>
56
#include <cyg/hal/hal_arch.h>
57
#include <cyg/hal/hal_io.h>
58
#include <cyg/hal/hal_if.h>             // delays
59
#include <cyg/hal/drv_api.h>
60
#include <cyg/io/io.h>
61
#include <cyg/io/devtab.h>
62
#include <cyg/io/disk.h>
63
 
64
#include "ide_disk.h"
65
 
66
// ----------------------------------------------------------------------------
67
 
68
#ifdef CYGDBG_IO_DISK_DEBUG
69
# define DEBUG 1
70
#endif
71
 
72
#ifdef DEBUG
73
# define D(fmt,args...) diag_printf(fmt, ## args)
74
#else
75
# define D(fmt,args...)
76
#endif
77
 
78
// ----------------------------------------------------------------------------
79
 
80
// No h/w controller structure is needed in this driver, but the address of the
81
// second argument is taken anyway.
82
DISK_CONTROLLER(ide_disk_controller, ide_disk_controller);
83
 
84
#ifdef CYGVAR_DEVS_DISK_IDE_DISK0
85
IDE_DISK_INSTANCE(0, 0, 0, true, CYGDAT_IO_DISK_IDE_DISK0_NAME);
86
#endif
87
 
88
#ifdef CYGVAR_DEVS_DISK_IDE_DISK1
89
IDE_DISK_INSTANCE(1, 0, 1, true, CYGDAT_IO_DISK_IDE_DISK1_NAME);
90
#endif
91
 
92
#ifdef CYGVAR_DEVS_DISK_IDE_DISK2
93
IDE_DISK_INSTANCE(2, 1, 0, true, CYGDAT_IO_DISK_IDE_DISK2_NAME);
94
#endif
95
 
96
#ifdef CYGVAR_DEVS_DISK_IDE_DISK3
97
IDE_DISK_INSTANCE(3, 1, 1, true, CYGDAT_IO_DISK_IDE_DISK3_NAME);
98
#endif
99
 
100
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
101
 
102
// ----------------------------------------------------------------------------
103
 
104
static void
105
id_strcpy(char *dest, cyg_uint16 *src, cyg_uint16 size)
106
{
107
    int i;
108
 
109
    for (i=0; i<size; i+=2) {
110
        *dest++ = (char)(*src >> 8);
111
        *dest++ = (char)(*src & 0x00FF);
112
        src++;
113
    }
114
    *dest = '\0';
115
}
116
 
117
// ----------------------------------------------------------------------------
118
 
119
static inline void
120
__wait_for_ready(int ctlr)
121
{
122
    cyg_uint8 status;
123
    do {
124
         HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
125
    } while (status & (IDE_STAT_BSY | IDE_STAT_DRQ));
126
}
127
 
128
// ----------------------------------------------------------------------------
129
// Wait while the device is busy with the last command
130
 
131
static inline int
132
__wait_busy(int ctlr)
133
{
134
    cyg_uint8 status;
135
    cyg_ucount32 tries;
136
 
137
    for (tries=0; tries < 1000000; tries++) {
138
         CYGACC_CALL_IF_DELAY_US(10);
139
         HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
140
         if ((status & IDE_STAT_BSY) == 0)
141
              return 1;
142
    }
143
    return 0;
144
}
145
 
146
// ----------------------------------------------------------------------------
147
 
148
static inline int
149
__wait_for_drq(int ctlr)
150
{
151
    cyg_uint8 status;
152
    cyg_ucount32 tries;
153
 
154
    for (tries=0; tries<1000000; tries++) {
155
        CYGACC_CALL_IF_DELAY_US(10);
156
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
157
        if (!(status & IDE_STAT_BSY)) {
158
            if (status & IDE_STAT_DRQ)
159
                return 1;
160
            else
161
                return 0;
162
        }
163
    }
164
    return 0;
165
}
166
 
167
// ----------------------------------------------------------------------------
168
// Return true if any devices attached to controller
169
 
170
static int
171
ide_presence_detect(int ctlr)
172
{
173
    cyg_uint8 sel, val;
174
    int i;
175
 
176
    for (i = 0; i < HAL_IDE_NUM_CONTROLLERS; i++) {
177
        sel = (i << 4) | 0xA0;
178
        CYGACC_CALL_IF_DELAY_US(50000U);
179
        HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, sel);
180
        CYGACC_CALL_IF_DELAY_US(50000U);
181
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_DEVICE, val);
182
        if (val == sel) {
183
#ifndef CYGSEM_DEVS_DISK_IDE_VMWARE
184
            if (i)
185
                HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, 0);
186
#endif
187
            return 1;
188
        }
189
    }
190
    return 0;
191
}
192
 
193
// ----------------------------------------------------------------------------
194
 
195
static int
196
ide_reset(int ctlr)
197
{
198
    cyg_uint8 status;
199
    int delay;
200
//
201
// VMware note:
202
// VMware virtual IDE device handler obviously expects that
203
// the reset and setup functions were already done
204
// by it's bios and complains if one uses reset here...
205
//
206
#ifndef CYGSEM_DEVS_DISK_IDE_VMWARE
207
    HAL_IDE_WRITE_CONTROL(ctlr, 6);    // polled mode, reset asserted
208
    CYGACC_CALL_IF_DELAY_US(5000U);
209
    HAL_IDE_WRITE_CONTROL(ctlr, 2);   // polled mode, reset cleared
210
    CYGACC_CALL_IF_DELAY_US(50000U);
211
#endif
212
 
213
    // wait 30 seconds max for not busy and drive ready
214
    for (delay=0; delay<300; ++delay) {
215
        CYGACC_CALL_IF_DELAY_US(100000U);
216
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
217
            if (!(status & IDE_STAT_BSY)) {
218
                if (status & IDE_STAT_DRDY) {
219
                    return 1;
220
                }
221
            }
222
    }
223
    return 0;
224
}
225
 
226
// ----------------------------------------------------------------------------
227
 
228
static int
229
ide_ident(int ctlr, int dev, cyg_uint16 *buf)
230
{
231
    int i;
232
 
233
    if (!__wait_busy(ctlr))
234
         return 0;
235
 
236
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
237
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0xEC);
238
    CYGACC_CALL_IF_DELAY_US(50000U);
239
 
240
    if (!__wait_for_drq(ctlr))
241
         return 0;
242
 
243
    for (i=0; i<(CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE/sizeof(cyg_uint16));
244
         i++, buf++) {
245
      HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf);
246
    }
247
    return 1;
248
}
249
 
250
// ----------------------------------------------------------------------------
251
// Requests the disk to use an 8-bit data path. This is probably ignored by
252
// most modern drives, but is supported by compact flash devices.
253
 
254
#ifdef CYGDAT_DEVS_DISK_IDE_8_BIT_DATA_PATH
255
static int
256
ide_8bit_mode(int ctlr, int dev, cyg_bool on)
257
{
258
    cyg_uint8 stat;
259
 
260
    if (!__wait_busy(ctlr))
261
         return 0;
262
 
263
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
264
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_FEATURES, 0x01);
265
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND,  0xEF);
266
 
267
    if (!__wait_busy(ctlr))
268
        return 0;
269
 
270
    HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, stat);
271
    return (stat & 1) ? 0 : 1;
272
}
273
#endif
274
 
275
// ----------------------------------------------------------------------------
276
// Reads a group of contiguous sectors from the drive.
277
// It can read up to 256 sectors.
278
 
279
static int
280
ide_read_sector(int ctlr, int dev, cyg_uint32 start,
281
                cyg_uint8 *buf, cyg_uint32 len)
282
{
283
    int i, nword;
284
    cyg_uint8 lenb;
285
    cyg_uint16 w;
286
 
287
    if (len==0 || !__wait_busy(ctlr))
288
       return 0;
289
 
290
    len = MIN(len, 256);
291
    lenb = (len == 256) ? 0 : ((cyg_uint8) len);
292
 
293
    nword = len * CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE / sizeof(cyg_uint16);
294
 
295
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, lenb);
296
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff);
297
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >>  8) & 0xff);
298
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI,  (start >> 16) & 0xff);
299
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE,
300
          ((start >> 24) & 0xf) | (dev << 4) | 0x40);
301
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x20);
302
 
303
    if (!__wait_for_drq(ctlr))
304
        return 0;
305
 
306
    if ((int) buf & 1) {
307
        // Unaligned buffer, so split each word manually
308
        for (i=0; i<nword; i++) {
309
            HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, w);
310
            *buf++ = w & 0xff;
311
            *buf++ = (w>>8) & 0xff;
312
        }
313
    }
314
    else {
315
        cyg_uint16* wbuf = (cyg_uint16*) buf;
316
        for (i=0; i<nword; i++, wbuf++)
317
            HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *wbuf);
318
    }
319
    return (int) len;
320
}
321
 
322
// ----------------------------------------------------------------------------
323
// Writes a group of contiguous sectors to the drive.
324
// It can write up to 256 sectors.
325
 
326
static int
327
ide_write_sector(int ctlr, int dev, cyg_uint32 start,
328
                 cyg_uint8 *buf, cyg_uint32 len)
329
{
330
    int i, nword;
331
    cyg_uint8 lenb;
332
    cyg_uint16 w;
333
 
334
    if (len==0 || !__wait_busy(ctlr))
335
       return 0;
336
 
337
    len = MIN(len, 256);
338
    lenb = (len == 256) ? 0 : ((cyg_uint8) len);
339
 
340
    nword = len * CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE / sizeof(cyg_uint16);
341
 
342
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, lenb);
343
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff);
344
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >>  8) & 0xff);
345
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI,  (start >> 16) & 0xff);
346
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE,
347
                            ((start >> 24) & 0xf) | (dev << 4) | 0x40);
348
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x30);
349
 
350
    if (!__wait_for_drq(ctlr))
351
        return 0;
352
 
353
    if ((int) buf & 1) {
354
        // Unaligned buffer, so assemble each word manually
355
        for (i=0; i<nword; ++i) {
356
            w  = *buf++;
357
            w |= (cyg_uint16) (*buf++) << 8;
358
            HAL_IDE_WRITE_UINT16(ctlr, IDE_REG_DATA, w);
359
        }
360
    }
361
    else {
362
        cyg_uint16* wbuf = (cyg_uint16*) buf;
363
        for (i=0; i<nword; ++i)
364
            HAL_IDE_WRITE_UINT16(ctlr, IDE_REG_DATA, *wbuf++);
365
    }
366
    return (int) len;
367
}
368
 
369
// ----------------------------------------------------------------------------
370
 
371
static cyg_bool
372
ide_disk_init(struct cyg_devtab_entry *tab)
373
{
374
    disk_channel *chan = (disk_channel *) tab->priv;
375
    ide_disk_info_t *info = (ide_disk_info_t *) chan->dev_priv;
376
    cyg_uint32 id_buf[CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE/sizeof(cyg_uint32)];
377
    static int num_controllers;
378
    static int ide_present[4], ide_reset_done[4];
379
    cyg_disk_identify_t ident;
380
    ide_identify_data_t *ide_idData=(ide_identify_data_t*)id_buf;
381
 
382
    if (chan->init)
383
        return true;
384
 
385
    D("IDE(%d:%d) hw init\n", info->port, info->chan);
386
 
387
    if (!num_controllers) num_controllers=HAL_IDE_INIT();
388
    if (info->chan>=num_controllers) {
389
        D("No IDE controller for channel %d:%d\n", info->port, info->chan);
390
        return false;
391
    }
392
 
393
#if CYGDAT_DEVS_DISK_IDE_STARTUP_DELAY
394
    CYGACC_CALL_IF_DELAY_US(CYGDAT_DEVS_DISK_IDE_STARTUP_DELAY*1000U);
395
#endif
396
 
397
    if (!ide_present[info->port]) {
398
        ide_present[info->port]=ide_presence_detect(info->port);
399
        if (!ide_present[info->port]) {
400
            diag_printf("No devices on IDE controller #%d\n",info->port);
401
            return false;
402
        }
403
    }
404
    if (!ide_reset_done[info->port]) {
405
        ide_reset_done[info->port]=ide_reset(info->port);
406
        if (!ide_reset_done[info->port]) {
407
            D("Controller #%d reset failure\n",info->port);
408
            return false;
409
        }
410
    }
411
 
412
#ifdef CYGDAT_DEVS_DISK_IDE_8_BIT_DATA_PATH
413
    if (!ide_8bit_mode(info->port, info->chan, true)) {
414
        D("IDE disk %d:%d failed to enter 8-bit mode\n",
415
          info->port, info->chan);
416
    }
417
#endif
418
 
419
    D("IDE %d:%d identify drive\n", info->port, info->chan);
420
 
421
    if (!ide_ident(info->port, info->chan, (cyg_uint16 *)id_buf)) {
422
        diag_printf("IDE %d:%d ident DRQ error\n", info->port, info->chan);
423
        return false;
424
    }
425
 
426
    id_strcpy(ident.serial, ide_idData->serial, 20);
427
    id_strcpy(ident.firmware_rev, ide_idData->firmware_rev, 8);
428
    id_strcpy(ident.model_num, ide_idData->model_num, 40);
429
 
430
    ident.cylinders_num  = ide_idData->num_cylinders;
431
    ident.heads_num = ide_idData->num_heads;
432
    ident.sectors_num = ide_idData->num_sectors;
433
    ident.lba_sectors_num = ide_idData->lba_total_sectors[1] << 16 |
434
                            ide_idData->lba_total_sectors[0];
435
    ident.phys_block_size = 1;
436
 
437
    // TODO: Should this be CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE?
438
    ident.max_transfer = 512;
439
 
440
    D("\tSerial : %s\n", ident.serial);
441
    D("\tFirmware rev. : %s\n", ident.firmware_rev);
442
    D("\tModel : %s\n", ident.model_num);
443
    D("\tC/H/S : %d/%d/%d\n", ident.cylinders_num,
444
                              ident.heads_num, ident.sectors_num);
445
 
446
    if (!(chan->callbacks->disk_init)(tab))
447
        return false;
448
 
449
    if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident))
450
        return false;
451
 
452
    return true;
453
}
454
 
455
// ----------------------------------------------------------------------------
456
 
457
static Cyg_ErrNo
458
ide_disk_lookup(struct cyg_devtab_entry **tab,
459
                struct cyg_devtab_entry  *sub_tab,
460
                const char *name)
461
{
462
    disk_channel *chan = (disk_channel *) (*tab)->priv;
463
    return (chan->callbacks->disk_lookup)(tab, sub_tab, name);
464
}
465
 
466
// ----------------------------------------------------------------------------
467
 
468
static Cyg_ErrNo
469
ide_disk_read(disk_channel *chan,
470
              void         *buf,
471
              cyg_uint32    len,
472
              cyg_uint32    block_num)
473
{
474
    ide_disk_info_t *info = (ide_disk_info_t *)chan->dev_priv;
475
 
476
    D("IDE %d:%d read block %d\n", info->port, info->chan, block_num);
477
 
478
    if (!ide_read_sector(info->port, info->chan, block_num,
479
                         (cyg_uint8 *)buf, len)) {
480
        diag_printf("IDE %d:%d read DRQ error\n", info->port, info->chan);
481
        return -EIO;
482
    }
483
 
484
    return ENOERR;
485
}
486
 
487
// ----------------------------------------------------------------------------
488
 
489
static Cyg_ErrNo
490
ide_disk_write(disk_channel *chan,
491
               const void   *buf,
492
               cyg_uint32    len,
493
               cyg_uint32    block_num)
494
{
495
    ide_disk_info_t *info = (ide_disk_info_t *)chan->dev_priv;
496
 
497
    D("IDE %d:%d write block %d\n", info->port, info->chan, block_num);
498
 
499
    if (!ide_write_sector(info->port, info->chan, block_num,
500
                         (cyg_uint8 *)buf, len)) {
501
        diag_printf("IDE %d:%d read DRQ error\n", info->port, info->chan);
502
        return -EIO;
503
    }
504
 
505
    return ENOERR;
506
}
507
 
508
// ----------------------------------------------------------------------------
509
 
510
static Cyg_ErrNo
511
ide_disk_get_config(disk_channel *chan,
512
                    cyg_uint32    key,
513
                    const void   *xbuf,
514
                    cyg_uint32   *len)
515
{
516
    return -EINVAL;
517
}
518
 
519
// ----------------------------------------------------------------------------
520
 
521
static Cyg_ErrNo
522
ide_disk_set_config(disk_channel *chan,
523
                    cyg_uint32    key,
524
                    const void   *xbuf,
525
                    cyg_uint32   *len)
526
{
527
    return -EINVAL;
528
}
529
 
530
//EOF ide_disk.c

powered by: WebSVN 2.1.0

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