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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      ide.c
4
//
5
//      RedBoot IDE support
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, 2003, 2004 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):    msalter
43
// Contributors: msalter
44
// Date:         2001-07-14
45
// Purpose:      
46
// Description:  
47
//              
48
// This code is part of RedBoot (tm).
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
#include <redboot.h>
55
#include <cyg/hal/hal_io.h>
56
#include <fs/disk.h>
57
#include <fs/ide.h>
58
 
59
static int ide_read(struct disk *d,
60
                    cyg_uint32 start_sector,
61
                    cyg_uint32 *buf,
62
                    cyg_uint8  nr_sectors);
63
 
64
static disk_funs_t ide_funs = { ide_read };
65
 
66
static struct ide_priv ide_privs[HAL_IDE_NUM_CONTROLLERS * 2];
67
 
68
static inline void
69
__wait_for_ready(int ctlr)
70
{
71
    cyg_uint8 status;
72
    do {
73
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
74
    } while (status & (IDE_STAT_BSY | IDE_STAT_DRQ));
75
}
76
 
77
static inline int
78
__wait_for_drq(int ctlr)
79
{
80
    cyg_uint8 status;
81
    cyg_ucount32 tries;
82
 
83
    CYGACC_CALL_IF_DELAY_US(10);
84
    for (tries=0; tries<1000000; tries++) {
85
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
86
        if (!(status & IDE_STAT_BSY)) {
87
            if (status & IDE_STAT_DRQ)
88
                return 1;
89
            else
90
                return 0;
91
        }
92
    }
93
}
94
 
95
static int
96
ide_reset(int ctlr)
97
{
98
    cyg_uint8 status;
99
    int delay;
100
//
101
// VMware note:
102
// VMware virtual IDE device handler obviously expects that
103
// the reset and setup functions were already done
104
// by it's bios and complais if one uses reset here...
105
//
106
#ifndef CYGSEM_REDBOOT_DISK_IDE_VMWARE
107
    HAL_IDE_WRITE_CONTROL(ctlr, 6);     // polled mode, reset asserted
108
    CYGACC_CALL_IF_DELAY_US(5000);
109
    HAL_IDE_WRITE_CONTROL(ctlr, 2);     // polled mode, reset cleared
110
    CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
111
#endif
112
 
113
    // wait 30 seconds max for not busy and drive ready
114
    for (delay = 0; delay < 300; ++delay) {
115
        CYGACC_CALL_IF_DELAY_US((cyg_uint32)100000);
116
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
117
          if (!(status & IDE_STAT_BSY)) {
118
                if (status & IDE_STAT_DRDY) {
119
            return 1;
120
    }
121
          }
122
    }
123
    return 0;
124
}
125
 
126
// Return true if any devices attached to controller
127
static int
128
ide_presence_detect(int ctlr)
129
{
130
    cyg_uint8 sel, val;
131
    int i;
132
 
133
    for (i = 0; i < 2; i++) {
134
        sel = (i << 4) | 0xA0;
135
        CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
136
        HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, sel);
137
        CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
138
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_DEVICE, val);
139
        if (val == sel) {
140
#ifndef CYGSEM_REDBOOT_DISK_IDE_VMWARE
141
            if (i)
142
                HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, 0);
143
#endif
144
            return 1;
145
        }
146
    }
147
    return 0;
148
}
149
 
150
static int
151
ide_ident(int ctlr, int dev, int is_packet_dev, cyg_uint16 *buf)
152
{
153
    int i;
154
 
155
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
156
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, is_packet_dev ? 0xA1 : 0xEC);
157
    CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
158
 
159
    if (!__wait_for_drq(ctlr))
160
        return 0;
161
 
162
    for (i = 0; i < (SECTOR_SIZE / sizeof(cyg_uint16)); i++, buf++)
163
        HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf);
164
 
165
    return 1;
166
}
167
 
168
static int
169
ide_read_sectors(int ctlr, int dev, cyg_uint32 start, cyg_uint8 count, cyg_uint16 *buf)
170
{
171
    int  i, j;
172
    cyg_uint16 *p;
173
 
174
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, count);
175
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff);
176
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >>  8) & 0xff);
177
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI,  (start >> 16) & 0xff);
178
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE,
179
                        ((start >> 24) & 0xf) | (dev << 4) | 0x40);
180
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x20);
181
 
182
    for(p = buf, i = 0; i < count; i++) {
183
 
184
        if (!__wait_for_drq(ctlr)) {
185
            diag_printf("%s: NO DRQ for ide%d, device %d.\n",
186
                        __FUNCTION__, ctlr, dev);
187
            return 0;
188
        }
189
 
190
        for (j = 0; j < (SECTOR_SIZE / sizeof(cyg_uint16)); j++, p++)
191
            HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *p);
192
    }
193
    return 1;
194
}
195
 
196
// max number of sectors to xfer during a single packet command
197
#define MAX_CD_XFER 16
198
 
199
static inline int
200
send_packet_command(int ctlr, int dev, cyg_uint16 len, cyg_uint16 *pkt, int pktlen)
201
{
202
    int i;
203
    cyg_uint8 status, reason;
204
 
205
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_FEATURES, 0);
206
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, 0);
207
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, 0);
208
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, len & 0xff);
209
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI,  (len >> 8) & 0xff);
210
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
211
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0xA0);
212
 
213
    if (!__wait_for_drq(ctlr)) {
214
        diag_printf("%s: NO DRQ for ide%d, device %d.\n",
215
                    __FUNCTION__, ctlr, dev);
216
        return 0;
217
    }
218
 
219
    // send packet
220
    for (i = 0; i < (pktlen/sizeof(cyg_uint16)); i++)
221
        HAL_IDE_WRITE_UINT16(ctlr, IDE_REG_DATA, pkt[i]);
222
 
223
    // wait for not busy transferring packet
224
    do {
225
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
226
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_REASON, reason);
227
 
228
        if ((status & (IDE_STAT_BSY | IDE_STAT_DRQ)) == IDE_STAT_DRQ)
229
            if (reason & IDE_REASON_COD)
230
                continue;  // still wanting packet data (should timeout here)
231
 
232
    } while (status & IDE_STAT_BSY);
233
 
234
    return 1;
235
}
236
 
237
#define READ_COUNT(x)                                    \
238
        { unsigned char tmp;                             \
239
          HAL_IDE_READ_UINT8(ctlr, IDE_REG_LBAMID, tmp); \
240
          (x) = tmp;                                     \
241
          HAL_IDE_READ_UINT8(ctlr, IDE_REG_LBAHI, tmp);  \
242
          (x) = (x) | (tmp << 8);                        \
243
        }
244
 
245
 
246
// Read the sense data
247
static int
248
request_sense(int ctlr, int dev, cyg_uint16 count, cyg_uint16 *buf)
249
{
250
    int i;
251
    cyg_uint16 cdcount, pkt[6];
252
    unsigned char status, *cpkt = (unsigned char *)pkt;
253
 
254
 
255
    // Fill in REQUEST SENSE packet command block
256
    memset(cpkt, 0, sizeof(pkt));
257
    cpkt[0] = 0x03;
258
    cpkt[4] = 254;  // allocation length
259
 
260
    if (!send_packet_command(ctlr, dev, count, pkt, sizeof(pkt)))
261
        return 0;
262
 
263
    HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
264
    if (!(status & IDE_STAT_DRQ)) {
265
        if (status & IDE_STAT_SERVICE) {
266
            unsigned char reason;
267
            HAL_IDE_READ_UINT8(ctlr, IDE_REG_REASON, reason);
268
            diag_printf("%s: SERVICE request for ide%d, device %d, status[%02x], reason[%02x].\n",
269
                        __FUNCTION__, ctlr, dev, status, reason);
270
        }
271
        return 0;
272
    }
273
 
274
    READ_COUNT(cdcount);
275
    if (cdcount != count)
276
        diag_printf("%s: ide%d, dev%d: his cnt[%d] our count[%d].\n",
277
                    __FUNCTION__, ctlr, dev, cdcount, count);
278
 
279
    for(i = 0; i < (cdcount / sizeof(*buf)); i++, buf++)
280
        HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf);
281
 
282
    // wait for not busy transferring data
283
    do {
284
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
285
    } while ((status & (IDE_STAT_BSY | IDE_STAT_DRQ)) == IDE_STAT_DRQ);
286
 
287
    return cdcount;
288
}
289
 
290
// Interpret the sense data
291
static int
292
handle_sense(int ctlr, int dev, cyg_uint8 count, cyg_uint16 *buf)
293
{
294
#if 0
295
    unsigned char *p = (char *)buf;
296
 
297
    diag_printf("%s: %d bytes:\n", __FUNCTION__, count);
298
    diag_printf("sense key[%02x] additional sense[%02x]\n",
299
                p[2], p[12]);
300
#endif
301
    return 1;
302
}
303
 
304
static int
305
do_packet_read(int ctlr, int dev, cyg_uint32 start, cyg_uint8 count, cyg_uint16 *buf)
306
{
307
    int i, retry_cnt;
308
    cyg_uint16 cdcount, pkt[6], sense[127];
309
    unsigned char status, *cpkt = (unsigned char *)pkt;
310
 
311
    // get count number of whole cdrom sectors
312
    while (count) {
313
 
314
        retry_cnt = 3;
315
 
316
        i = (count > MAX_CD_XFER) ? MAX_CD_XFER : count;
317
 
318
    retry:
319
        // Fill in READ(10) packet command block
320
        memset(cpkt, 0, sizeof(pkt));
321
        cpkt[0] = 0x28;  // READ(10)
322
        cpkt[2] = (start >> 24) & 0xff;
323
        cpkt[3] = (start >> 16) & 0xff;
324
        cpkt[4] = (start >>  8) & 0xff;
325
        cpkt[5] = (start >>  0) & 0xff;
326
        cpkt[7] = (i >> 8) & 0xff;
327
        cpkt[8] = i & 0xff;
328
 
329
        if (!send_packet_command(ctlr, dev, i * CDROM_SECTOR_SIZE,
330
                                 pkt, sizeof(pkt)))
331
            return 0;
332
 
333
        HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
334
        if (!(status & IDE_STAT_DRQ)) {
335
            if (status & IDE_STAT_SERVICE) {
336
                unsigned char reason;
337
                int sense_count;
338
                HAL_IDE_READ_UINT8(ctlr, IDE_REG_REASON, reason);
339
#if 1
340
                diag_printf("%s: SERVICE request for ide%d, device %d, status[%02x], reason[%02x].\n",
341
                            __FUNCTION__, ctlr, dev, status, reason);
342
#endif
343
                sense_count = request_sense(ctlr, dev, sizeof(sense), sense);
344
                if (sense_count) {
345
                    handle_sense(ctlr, dev, sense_count, sense);
346
                    if (retry_cnt--)
347
                        goto retry;
348
                }
349
            }
350
            return 0;
351
        }
352
 
353
        count -= i;
354
        start += i;
355
 
356
        READ_COUNT(cdcount);
357
        if (cdcount != (i * CDROM_SECTOR_SIZE))
358
            diag_printf("%s: ide%d, dev%d: his cnt[%d] our count[%d].\n",
359
                        __FUNCTION__, ctlr, dev,
360
                        cdcount, i * CDROM_SECTOR_SIZE);
361
 
362
        for(i = 0; i < (cdcount / sizeof(*buf)); i++, buf++)
363
            HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf);
364
 
365
        // wait for not busy transferring data
366
        do {
367
            HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
368
        } while ((status & (IDE_STAT_BSY | IDE_STAT_DRQ)) == IDE_STAT_DRQ);
369
    }
370
    return 1;
371
}
372
 
373
 
374
static int
375
ide_packet_read_sectors(int ctlr, int dev, cyg_uint32 start, cyg_uint8 count, cyg_uint16 *buf)
376
{
377
    int  i, extra;
378
    cyg_uint32 cdstart;
379
    static cyg_uint16 cdsec_buf[CDROM_SECTOR_SIZE/sizeof(cyg_uint16)];
380
 
381
    cdstart = (start + SECTORS_PER_CDROM_SECTOR-1) / SECTORS_PER_CDROM_SECTOR;
382
 
383
    // align to cdrom sector boundary.
384
    if (start % SECTORS_PER_CDROM_SECTOR) {
385
        if (!ide_packet_read_sectors(ctlr, dev,
386
                                     cdstart * SECTORS_PER_CDROM_SECTOR,
387
                                     SECTORS_PER_CDROM_SECTOR, cdsec_buf))
388
            return 0;
389
 
390
        i = SECTORS_PER_CDROM_SECTOR - (start % SECTORS_PER_CDROM_SECTOR);
391
        if (i > count)
392
            i = count;
393
        memcpy(buf, cdsec_buf + ((start % CDROM_SECTOR_SIZE) * SECTOR_SIZE),
394
               i * SECTOR_SIZE);
395
 
396
        count -= i;
397
        buf += (i * SECTOR_SIZE) / sizeof(*buf);
398
        ++cdstart;
399
    }
400
 
401
    extra = count % SECTORS_PER_CDROM_SECTOR;
402
    count /= SECTORS_PER_CDROM_SECTOR;
403
 
404
    if (count) {
405
        if (!do_packet_read(ctlr, dev, cdstart, count, buf))
406
            return 0;
407
        buf += count * SECTORS_PER_CDROM_SECTOR * SECTOR_SIZE;
408
    }
409
 
410
    if (extra) {
411
        // read cdrom sector 
412
        if (!ide_packet_read_sectors(ctlr, dev,
413
                                     cdstart * SECTORS_PER_CDROM_SECTOR,
414
                                     extra, cdsec_buf))
415
            return 0;
416
        memcpy(buf, cdsec_buf, extra * SECTOR_SIZE);
417
    }
418
 
419
    return 1;
420
}
421
 
422
static int
423
ide_read(struct disk *d,
424
         cyg_uint32 start_sec, cyg_uint32 *buf, cyg_uint8 nr_secs)
425
{
426
    struct ide_priv *p = (struct ide_priv *)(d->private);
427
 
428
    if (p->flags & IDE_DEV_PACKET)
429
        return ide_packet_read_sectors(p->controller, p->drive,
430
                                     start_sec, nr_secs, (cyg_uint16 *)buf);
431
 
432
    return ide_read_sectors(p->controller, p->drive,
433
                            start_sec, nr_secs, (cyg_uint16 *)buf);
434
}
435
 
436
 
437
static void
438
ide_init(void)
439
{
440
    cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)], u32;
441
    cyg_uint16 u16;
442
    cyg_uint8 u8;
443
    int i, j, num_controllers;
444
    disk_t disk;
445
    struct ide_priv *priv;
446
 
447
#define DEV_INIT_VAL ((j << 4) | 0xA0)
448
 
449
    num_controllers = HAL_IDE_INIT();
450
 
451
    CYGACC_CALL_IF_DELAY_US(5);
452
 
453
    priv = ide_privs;
454
    for (i = 0; i < num_controllers; i++) {
455
 
456
        if (!ide_presence_detect(i)) {
457
            diag_printf("No devices on IDE controller %d\n", i);
458
            continue;
459
        }
460
 
461
        // soft reset the devices on this controller
462
        if (!ide_reset(i))
463
            continue;
464
 
465
        // 2 devices per controller
466
        for (j = 0; j < 2; j++, priv++) {
467
 
468
            priv->controller = i;
469
            priv->drive = j;
470
            priv->flags = 0;
471
 
472
            // This is reminiscent of a memory test. We write a value
473
            // to a certain location (device register), then write a
474
            // different value somewhere else so that the first value
475
            // is not hanging on the bus, then we read back the first
476
            // value to see if the write was succesful.
477
            //
478
            HAL_IDE_WRITE_UINT8(i, IDE_REG_DEVICE, DEV_INIT_VAL);
479
            HAL_IDE_WRITE_UINT8(i, IDE_REG_FEATURES, 0);
480
            CYGACC_CALL_IF_DELAY_US(50000);
481
            HAL_IDE_READ_UINT8(i, IDE_REG_DEVICE, u8);
482
            if (u8 != DEV_INIT_VAL) {
483
                diag_printf("IDE failed to identify unit %d - wrote: %x, read: %x\n",
484
                            i, DEV_INIT_VAL, u8);
485
                continue;
486
            }
487
 
488
            // device present
489
            priv->flags |= IDE_DEV_PRESENT;
490
 
491
            if (ide_ident(i, j, 0, (cyg_uint16 *)buf) <= 0) {
492
                if (ide_ident(i, j, 1, (cyg_uint16 *)buf) <= 0) {
493
                    priv->flags = 0;
494
                    continue;  // can't identify device
495
                } else {
496
                    u16 = *(cyg_uint16 *)((char *)buf + IDE_DEVID_GENCONFIG);
497
                    if (((u16 >> 8) & 0x1f) != 5) {
498
                        diag_printf("Non-CDROM ATAPI device #%d - skipped\n", i);
499
                        continue;
500
                    }
501
                    priv->flags |= IDE_DEV_PACKET;
502
                }
503
            }
504
 
505
            memset(&disk, 0, sizeof(disk));
506
            disk.funs = &ide_funs;
507
            disk.private = priv;
508
 
509
            disk.kind = DISK_IDE_HD;  // until proven otherwise
510
 
511
            if (priv->flags & IDE_DEV_PACKET) {
512
                u16 = *(cyg_uint16 *)((char *)buf + IDE_DEVID_GENCONFIG);
513
                if (((u16 >> 8) & 0x1f) == 5)
514
                    disk.kind = DISK_IDE_CDROM;
515
            } else {
516
                u32 = *(cyg_uint32 *)((char *)buf + IDE_DEVID_LBA_CAPACITY);
517
                disk.nr_sectors = u32;
518
            }
519
 
520
            if (!disk_register(&disk))
521
                return;
522
        }
523
    }
524
}
525
 
526
RedBoot_init(ide_init, RedBoot_INIT_FIRST);
527
 

powered by: WebSVN 2.1.0

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