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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [block/] [hd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 *  linux/drivers/block/hd.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
/*
8
 * This is the low-level hd interrupt support. It traverses the
9
 * request-list, using interrupts to jump between functions. As
10
 * all the functions are called within interrupts, we may not
11
 * sleep. Special care is recommended.
12
 *
13
 *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
14
 *
15
 *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
16
 *  in the early extended-partition checks and added DM partitions
17
 *
18
 *  IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
19
 *  and general streamlining by Mark Lord.
20
 */
21
 
22
#define DEFAULT_MULT_COUNT  0   /* set to 0 to disable multiple mode at boot */
23
#define DEFAULT_UNMASK_INTR 0   /* set to 0 to *NOT* unmask irq's more often */
24
 
25
#include <asm/irq.h>
26
#include <linux/errno.h>
27
#include <linux/signal.h>
28
#include <linux/sched.h>
29
#include <linux/timer.h>
30
#include <linux/fs.h>
31
#include <linux/kernel.h>
32
#include <linux/hdreg.h>
33
#include <linux/genhd.h>
34
#include <linux/malloc.h>
35
#include <linux/string.h>
36
#include <linux/ioport.h>
37
#include <linux/mc146818rtc.h> /* CMOS defines */
38
 
39
#define REALLY_SLOW_IO
40
#include <asm/system.h>
41
#include <asm/io.h>
42
#include <asm/segment.h>
43
 
44
#define MAJOR_NR HD_MAJOR
45
#include <linux/blk.h>
46
 
47
static int revalidate_hddisk(kdev_t, int);
48
 
49
#define HD_DELAY        0
50
 
51
#define MAX_ERRORS     16       /* Max read/write errors/sector */
52
#define RESET_FREQ      8       /* Reset controller every 8th retry */
53
#define RECAL_FREQ      4       /* Recalibrate every 4th retry */
54
#define MAX_HD          2
55
 
56
#define STAT_OK         (READY_STAT|SEEK_STAT)
57
#define OK_STATUS(s)    (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
58
 
59
static void recal_intr(void);
60
static void bad_rw_intr(void);
61
 
62
static char recalibrate[MAX_HD] = { 0, };
63
static char special_op[MAX_HD] = { 0, };
64
static int access_count[MAX_HD] = {0, };
65
static char busy[MAX_HD] = {0, };
66
static struct wait_queue * busy_wait = NULL;
67
 
68
static int reset = 0;
69
static int hd_error = 0;
70
 
71
/*
72
 *  This struct defines the HD's and their types.
73
 */
74
struct hd_i_struct {
75
        unsigned int head,sect,cyl,wpcom,lzone,ctl;
76
        };
77
static struct hd_driveid *hd_ident_info[MAX_HD] = {0, };
78
 
79
#ifdef HD_TYPE
80
static struct hd_i_struct hd_info[] = { HD_TYPE };
81
struct hd_i_struct bios_info[] = { HD_TYPE };
82
static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
83
#else
84
static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
85
struct hd_i_struct bios_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
86
static int NR_HD = 0;
87
#endif
88
 
89
static struct hd_struct hd[MAX_HD<<6]={{0,0},};
90
static int hd_sizes[MAX_HD<<6] = {0, };
91
static int hd_blocksizes[MAX_HD<<6] = {0, };
92
 
93
#if (HD_DELAY > 0)
94
unsigned long last_req;
95
 
96
unsigned long read_timer(void)
97
{
98
        unsigned long t, flags;
99
        int i;
100
 
101
        save_flags(flags);
102
        cli();
103
        t = jiffies * 11932;
104
        outb_p(0, 0x43);
105
        i = inb_p(0x40);
106
        i |= inb(0x40) << 8;
107
        restore_flags(flags);
108
        return(t - i);
109
}
110
#endif
111
 
112
void hd_setup(char *str, int *ints)
113
{
114
        int hdind = 0;
115
 
116
        if (ints[0] != 3)
117
                return;
118
        if (bios_info[0].head != 0)
119
                hdind=1;
120
        bios_info[hdind].head  = hd_info[hdind].head = ints[2];
121
        bios_info[hdind].sect  = hd_info[hdind].sect = ints[3];
122
        bios_info[hdind].cyl   = hd_info[hdind].cyl = ints[1];
123
        bios_info[hdind].wpcom = hd_info[hdind].wpcom = 0;
124
        bios_info[hdind].lzone = hd_info[hdind].lzone = ints[1];
125
        bios_info[hdind].ctl   = hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
126
        NR_HD = hdind+1;
127
}
128
 
129
static void dump_status (const char *msg, unsigned int stat)
130
{
131
        unsigned long flags;
132
        char devc;
133
 
134
        devc = CURRENT ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
135
        save_flags (flags);
136
        sti();
137
        printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
138
        if (stat & BUSY_STAT)   printk("Busy ");
139
        if (stat & READY_STAT)  printk("DriveReady ");
140
        if (stat & WRERR_STAT)  printk("WriteFault ");
141
        if (stat & SEEK_STAT)   printk("SeekComplete ");
142
        if (stat & DRQ_STAT)    printk("DataRequest ");
143
        if (stat & ECC_STAT)    printk("CorrectedError ");
144
        if (stat & INDEX_STAT)  printk("Index ");
145
        if (stat & ERR_STAT)    printk("Error ");
146
        printk("}\n");
147
        if ((stat & ERR_STAT) == 0) {
148
                hd_error = 0;
149
        } else {
150
                hd_error = inb(HD_ERROR);
151
                printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff);
152
                if (hd_error & BBD_ERR)         printk("BadSector ");
153
                if (hd_error & ECC_ERR)         printk("UncorrectableError ");
154
                if (hd_error & ID_ERR)          printk("SectorIdNotFound ");
155
                if (hd_error & ABRT_ERR)        printk("DriveStatusError ");
156
                if (hd_error & TRK0_ERR)        printk("TrackZeroNotFound ");
157
                if (hd_error & MARK_ERR)        printk("AddrMarkNotFound ");
158
                printk("}");
159
                if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
160
                        printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
161
                                inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
162
                        if (CURRENT)
163
                                printk(", sector=%ld", CURRENT->sector);
164
                }
165
                printk("\n");
166
        }
167
        restore_flags (flags);
168
}
169
 
170
void check_status(void)
171
{
172
        int i = inb_p(HD_STATUS);
173
 
174
        if (!OK_STATUS(i)) {
175
                dump_status("check_status", i);
176
                bad_rw_intr();
177
        }
178
}
179
 
180
static int controller_busy(void)
181
{
182
        int retries = 100000;
183
        unsigned char status;
184
 
185
        do {
186
                status = inb_p(HD_STATUS);
187
        } while ((status & BUSY_STAT) && --retries);
188
        return status;
189
}
190
 
191
static int status_ok(void)
192
{
193
        unsigned char status = inb_p(HD_STATUS);
194
 
195
        if (status & BUSY_STAT)
196
                return 1;       /* Ancient, but does it make sense??? */
197
        if (status & WRERR_STAT)
198
                return 0;
199
        if (!(status & READY_STAT))
200
                return 0;
201
        if (!(status & SEEK_STAT))
202
                return 0;
203
        return 1;
204
}
205
 
206
static int controller_ready(unsigned int drive, unsigned int head)
207
{
208
        int retry = 100;
209
 
210
        do {
211
                if (controller_busy() & BUSY_STAT)
212
                        return 0;
213
                outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
214
                if (status_ok())
215
                        return 1;
216
        } while (--retry);
217
        return 0;
218
}
219
 
220
static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
221
                unsigned int head,unsigned int cyl,unsigned int cmd,
222
                void (*intr_addr)(void))
223
{
224
        unsigned short port;
225
 
226
#if (HD_DELAY > 0)
227
        while (read_timer() - last_req < HD_DELAY)
228
                /* nothing */;
229
#endif
230
        if (reset)
231
                return;
232
        if (!controller_ready(drive, head)) {
233
                reset = 1;
234
                return;
235
        }
236
        SET_INTR(intr_addr);
237
        outb_p(hd_info[drive].ctl,HD_CMD);
238
        port=HD_DATA;
239
        outb_p(hd_info[drive].wpcom>>2,++port);
240
        outb_p(nsect,++port);
241
        outb_p(sect,++port);
242
        outb_p(cyl,++port);
243
        outb_p(cyl>>8,++port);
244
        outb_p(0xA0|(drive<<4)|head,++port);
245
        outb_p(cmd,++port);
246
}
247
 
248
static void hd_request (void);
249
static unsigned int identified  [MAX_HD] = {0,}; /* 1 = drive ID already displayed   */
250
static unsigned int unmask_intr [MAX_HD] = {0,}; /* 1 = unmask IRQs during I/O       */
251
static unsigned int max_mult    [MAX_HD] = {0,}; /* max sectors for MultMode         */
252
static unsigned int mult_req    [MAX_HD] = {0,}; /* requested MultMode count         */
253
static unsigned int mult_count  [MAX_HD] = {0,}; /* currently enabled MultMode count */
254
static struct request WCURRENT;
255
 
256
static void fixstring (unsigned char *s, int bytecount)
257
{
258
        unsigned char *p, *end = &s[bytecount &= ~1];   /* bytecount must be even */
259
 
260
        /* convert from big-endian to little-endian */
261
        for (p = end ; p != s;) {
262
                unsigned short *pp = (unsigned short *) (p -= 2);
263
                *pp = (*pp >> 8) | (*pp << 8);
264
        }
265
 
266
        /* strip leading blanks */
267
        while (s != end && *s == ' ')
268
                ++s;
269
 
270
        /* compress internal blanks and strip trailing blanks */
271
        while (s != end && *s) {
272
                if (*s++ != ' ' || (s != end && *s && *s != ' '))
273
                        *p++ = *(s-1);
274
        }
275
 
276
        /* wipe out trailing garbage */
277
        while (p != end)
278
                *p++ = '\0';
279
}
280
 
281
static void identify_intr(void)
282
{
283
        unsigned int dev = DEVICE_NR(CURRENT->rq_dev);
284
        unsigned short stat = inb_p(HD_STATUS);
285
        struct hd_driveid *id = hd_ident_info[dev];
286
 
287
        if (unmask_intr[dev])
288
                sti();
289
        if (stat & (BUSY_STAT|ERR_STAT)) {
290
                printk ("  hd%c: non-IDE device, %dMB, CHS=%d/%d/%d\n", dev+'a',
291
                        hd_info[dev].cyl*hd_info[dev].head*hd_info[dev].sect / 2048,
292
                        hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect);
293
                if (id != NULL) {
294
                        hd_ident_info[dev] = NULL;
295
                        kfree_s (id, 512);
296
                }
297
        } else {
298
                insw(HD_DATA, id, 256); /* get ID info */
299
                max_mult[dev] = id->max_multsect;
300
                if ((id->field_valid&1) && id->cur_cyls && id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
301
                        /*
302
                         * Extract the physical drive geometry for our use.
303
                         * Note that we purposely do *not* update the bios_info.
304
                         * This way, programs that use it (like fdisk) will
305
                         * still have the same logical view as the BIOS does,
306
                         * which keeps the partition table from being screwed.
307
                         */
308
                        hd_info[dev].cyl  = id->cur_cyls;
309
                        hd_info[dev].head = id->cur_heads;
310
                        hd_info[dev].sect = id->cur_sectors;
311
                }
312
                fixstring (id->serial_no, sizeof(id->serial_no));
313
                fixstring (id->fw_rev, sizeof(id->fw_rev));
314
                fixstring (id->model, sizeof(id->model));
315
                printk ("  hd%c: %.40s, %dMB w/%dKB Cache, CHS=%d/%d/%d, MaxMult=%d\n",
316
                        dev+'a', id->model, id->cyls*id->heads*id->sectors/2048,
317
                        id->buf_size/2, bios_info[dev].cyl, bios_info[dev].head,
318
                        bios_info[dev].sect, id->max_multsect);
319
                /*
320
                 * Early model Quantum drives go weird at this point,
321
                 *   but doing a recalibrate seems to "fix" them.
322
                 * (Doing a full reset confuses some other model Quantums)
323
                 */
324
                if (!strncmp(id->model, "QUANTUM", 7))
325
                        special_op[dev] = recalibrate[dev] = 1;
326
        }
327
#if (HD_DELAY > 0)
328
        last_req = read_timer();
329
#endif
330
        hd_request();
331
        return;
332
}
333
 
334
static void set_multmode_intr(void)
335
{
336
        unsigned int dev = DEVICE_NR(CURRENT->rq_dev), stat = inb_p(HD_STATUS);
337
 
338
        if (unmask_intr[dev])
339
                sti();
340
        if (stat & (BUSY_STAT|ERR_STAT)) {
341
                mult_req[dev] = mult_count[dev] = 0;
342
                dump_status("set multmode failed", stat);
343
        } else {
344
                if ((mult_count[dev] = mult_req[dev]))
345
                        printk ("  hd%c: enabled %d-sector multiple mode\n",
346
                                dev+'a', mult_count[dev]);
347
                else
348
                        printk ("  hd%c: disabled multiple mode\n", dev+'a');
349
        }
350
#if (HD_DELAY > 0)
351
        last_req = read_timer();
352
#endif
353
        hd_request();
354
        return;
355
}
356
 
357
static int drive_busy(void)
358
{
359
        unsigned int i;
360
        unsigned char c;
361
 
362
        for (i = 0; i < 500000 ; i++) {
363
                c = inb_p(HD_STATUS);
364
                if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
365
                        return 0;
366
        }
367
        dump_status("reset timed out", c);
368
        return 1;
369
}
370
 
371
static void reset_controller(void)
372
{
373
        int     i;
374
 
375
        outb_p(4,HD_CMD);
376
        for(i = 0; i < 1000; i++) barrier();
377
        outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
378
        for(i = 0; i < 1000; i++) barrier();
379
        if (drive_busy())
380
                printk("hd: controller still busy\n");
381
        else if ((hd_error = inb(HD_ERROR)) != 1)
382
                printk("hd: controller reset failed: %02x\n",hd_error);
383
}
384
 
385
static void reset_hd(void)
386
{
387
        static int i;
388
 
389
repeat:
390
        if (reset) {
391
                reset = 0;
392
                i = -1;
393
                reset_controller();
394
        } else {
395
                check_status();
396
                if (reset)
397
                        goto repeat;
398
        }
399
        if (++i < NR_HD) {
400
                special_op[i] = recalibrate[i] = 1;
401
                if (unmask_intr[i]) {
402
                        unmask_intr[i] = DEFAULT_UNMASK_INTR;
403
                        printk("hd%c: reset irq-unmasking to %d\n",i+'a',
404
                                DEFAULT_UNMASK_INTR);
405
                }
406
                if (mult_req[i] || mult_count[i]) {
407
                        mult_count[i] = 0;
408
                        mult_req[i] = DEFAULT_MULT_COUNT;
409
                        printk("hd%c: reset multiple mode to %d\n",i+'a',
410
                                DEFAULT_MULT_COUNT);
411
                }
412
                hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
413
                        hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
414
                if (reset)
415
                        goto repeat;
416
        } else
417
                hd_request();
418
}
419
 
420
/*
421
 * Ok, don't know what to do with the unexpected interrupts: on some machines
422
 * doing a reset and a retry seems to result in an eternal loop. Right now I
423
 * ignore it, and just set the timeout.
424
 *
425
 * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
426
 * drive enters "idle", "standby", or "sleep" mode, so if the status looks
427
 * "good", we just ignore the interrupt completely.
428
 */
429
void unexpected_hd_interrupt(void)
430
{
431
        unsigned int stat = inb_p(HD_STATUS);
432
 
433
        if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
434
                dump_status ("unexpected interrupt", stat);
435
                SET_TIMER;
436
        }
437
}
438
 
439
/*
440
 * bad_rw_intr() now tries to be a bit smarter and does things
441
 * according to the error returned by the controller.
442
 * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
443
 */
444
static void bad_rw_intr(void)
445
{
446
        int dev;
447
 
448
        if (!CURRENT)
449
                return;
450
        dev = DEVICE_NR(CURRENT->rq_dev);
451
        if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
452
                end_request(0);
453
                special_op[dev] = recalibrate[dev] = 1;
454
        } else if (CURRENT->errors % RESET_FREQ == 0)
455
                reset = 1;
456
        else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
457
                special_op[dev] = recalibrate[dev] = 1;
458
        /* Otherwise just retry */
459
}
460
 
461
static inline int wait_DRQ(void)
462
{
463
        int retries = 100000, stat;
464
 
465
        while (--retries > 0)
466
                if ((stat = inb_p(HD_STATUS)) & DRQ_STAT)
467
                        return 0;
468
        dump_status("wait_DRQ", stat);
469
        return -1;
470
}
471
 
472
static void read_intr(void)
473
{
474
        unsigned int dev = DEVICE_NR(CURRENT->rq_dev);
475
        int i, retries = 100000, msect = mult_count[dev], nsect;
476
 
477
        if (unmask_intr[dev])
478
                sti();                  /* permit other IRQs during xfer */
479
        do {
480
                i = (unsigned) inb_p(HD_STATUS);
481
                if (i & BUSY_STAT)
482
                        continue;
483
                if (!OK_STATUS(i))
484
                        break;
485
                if (i & DRQ_STAT)
486
                        goto ok_to_read;
487
        } while (--retries > 0);
488
        dump_status("read_intr", i);
489
        bad_rw_intr();
490
        hd_request();
491
        return;
492
ok_to_read:
493
        if (msect) {
494
                if ((nsect = CURRENT->current_nr_sectors) > msect)
495
                        nsect = msect;
496
                msect -= nsect;
497
        } else
498
                nsect = 1;
499
        insw(HD_DATA,CURRENT->buffer,nsect<<8);
500
        CURRENT->sector += nsect;
501
        CURRENT->buffer += nsect<<9;
502
        CURRENT->errors = 0;
503
        i = (CURRENT->nr_sectors -= nsect);
504
 
505
#ifdef DEBUG
506
        printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=0x%08lx\n",
507
                dev+'a', CURRENT->sector, CURRENT->sector+nsect,
508
                CURRENT->nr_sectors, (unsigned long) CURRENT->buffer+(nsect<<9));
509
#endif
510
        if ((CURRENT->current_nr_sectors -= nsect) <= 0)
511
                end_request(1);
512
        if (i > 0) {
513
                if (msect)
514
                        goto ok_to_read;
515
                SET_INTR(&read_intr);
516
                return;
517
        }
518
        (void) inb_p(HD_STATUS);
519
#if (HD_DELAY > 0)
520
        last_req = read_timer();
521
#endif
522
        if (CURRENT)
523
                hd_request();
524
        return;
525
}
526
 
527
static inline void multwrite (unsigned int dev)
528
{
529
        unsigned int mcount = mult_count[dev];
530
 
531
        while (mcount--) {
532
                outsw(HD_DATA,WCURRENT.buffer,256);
533
                if (!--WCURRENT.nr_sectors)
534
                        return;
535
                WCURRENT.buffer += 512;
536
                if (!--WCURRENT.current_nr_sectors) {
537
                        WCURRENT.bh = WCURRENT.bh->b_reqnext;
538
                        if (WCURRENT.bh == NULL)
539
                                panic("buffer list corrupted\n");
540
                        WCURRENT.current_nr_sectors = WCURRENT.bh->b_size>>9;
541
                        WCURRENT.buffer             = WCURRENT.bh->b_data;
542
                }
543
        }
544
}
545
 
546
static void multwrite_intr(void)
547
{
548
        int i;
549
        unsigned int dev = DEVICE_NR(WCURRENT.rq_dev);
550
 
551
        if (unmask_intr[dev])
552
                sti();
553
        if (OK_STATUS(i=inb_p(HD_STATUS))) {
554
                if (i & DRQ_STAT) {
555
                        if (WCURRENT.nr_sectors) {
556
                                multwrite(dev);
557
                                SET_INTR(&multwrite_intr);
558
                                return;
559
                        }
560
                } else {
561
                        if (!WCURRENT.nr_sectors) {     /* all done? */
562
                                for (i = CURRENT->nr_sectors; i > 0;){
563
                                        i -= CURRENT->current_nr_sectors;
564
                                        end_request(1);
565
                                }
566
#if (HD_DELAY > 0)
567
                                last_req = read_timer();
568
#endif
569
                                if (CURRENT)
570
                                        hd_request();
571
                                return;
572
                        }
573
                }
574
        }
575
        dump_status("multwrite_intr", i);
576
        bad_rw_intr();
577
        hd_request();
578
}
579
 
580
static void write_intr(void)
581
{
582
        int i;
583
        int retries = 100000;
584
 
585
        if (unmask_intr[DEVICE_NR(WCURRENT.rq_dev)])
586
                sti();
587
        do {
588
                i = (unsigned) inb_p(HD_STATUS);
589
                if (i & BUSY_STAT)
590
                        continue;
591
                if (!OK_STATUS(i))
592
                        break;
593
                if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
594
                        goto ok_to_write;
595
        } while (--retries > 0);
596
        dump_status("write_intr", i);
597
        bad_rw_intr();
598
        hd_request();
599
        return;
600
ok_to_write:
601
        CURRENT->sector++;
602
        i = --CURRENT->nr_sectors;
603
        --CURRENT->current_nr_sectors;
604
        CURRENT->buffer += 512;
605
        if (!i || (CURRENT->bh && !SUBSECTOR(i)))
606
                end_request(1);
607
        if (i > 0) {
608
                SET_INTR(&write_intr);
609
                outsw(HD_DATA,CURRENT->buffer,256);
610
                sti();
611
        } else {
612
#if (HD_DELAY > 0)
613
                last_req = read_timer();
614
#endif
615
                hd_request();
616
        }
617
        return;
618
}
619
 
620
static void recal_intr(void)
621
{
622
        check_status();
623
#if (HD_DELAY > 0)
624
        last_req = read_timer();
625
#endif
626
        hd_request();
627
}
628
 
629
/*
630
 * This is another of the error-routines I don't know what to do with. The
631
 * best idea seems to just set reset, and start all over again.
632
 */
633
static void hd_times_out(void)
634
{
635
        unsigned int dev;
636
 
637
        DEVICE_INTR = NULL;
638
        if (!CURRENT)
639
                return;
640
        disable_irq(HD_IRQ);
641
        sti();
642
        reset = 1;
643
        dev = DEVICE_NR(CURRENT->rq_dev);
644
        printk("hd%c: timeout\n", dev+'a');
645
        if (++CURRENT->errors >= MAX_ERRORS) {
646
#ifdef DEBUG
647
                printk("hd%c: too many errors\n", dev+'a');
648
#endif
649
                end_request(0);
650
        }
651
        cli();
652
        hd_request();
653
        enable_irq(HD_IRQ);
654
}
655
 
656
int do_special_op (unsigned int dev)
657
{
658
        if (recalibrate[dev]) {
659
                recalibrate[dev] = 0;
660
                hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
661
                return reset;
662
        }
663
        if (!identified[dev]) {
664
                identified[dev]  = 1;
665
                unmask_intr[dev] = DEFAULT_UNMASK_INTR;
666
                mult_req[dev]    = DEFAULT_MULT_COUNT;
667
                hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
668
                return reset;
669
        }
670
        if (mult_req[dev] != mult_count[dev]) {
671
                hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
672
                return reset;
673
        }
674
        if (hd_info[dev].head > 16) {
675
                printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
676
                end_request(0);
677
        }
678
        special_op[dev] = 0;
679
        return 1;
680
}
681
 
682
/*
683
 * The driver enables interrupts as much as possible.  In order to do this,
684
 * (a) the device-interrupt is disabled before entering hd_request(),
685
 * and (b) the timeout-interrupt is disabled before the sti().
686
 *
687
 * Interrupts are still masked (by default) whenever we are exchanging
688
 * data/cmds with a drive, because some drives seem to have very poor
689
 * tolerance for latency during I/O.  For devices which don't suffer from
690
 * that problem (most don't), the unmask_intr[] flag can be set to unmask
691
 * other interrupts during data/cmd transfers (by defining DEFAULT_UNMASK_INTR
692
 * to 1, or by using "hdparm -u1 /dev/hd?" from the shell).
693
 */
694
static void hd_request(void)
695
{
696
        unsigned int dev, block, nsect, sec, track, head, cyl;
697
 
698
        if (CURRENT && CURRENT->rq_status == RQ_INACTIVE) return;
699
        if (DEVICE_INTR)
700
                return;
701
repeat:
702
        timer_active &= ~(1<<HD_TIMER);
703
        sti();
704
        INIT_REQUEST;
705
        if (reset) {
706
                cli();
707
                reset_hd();
708
                return;
709
        }
710
        dev = MINOR(CURRENT->rq_dev);
711
        block = CURRENT->sector;
712
        nsect = CURRENT->nr_sectors;
713
        if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
714
#ifdef DEBUG
715
                if (dev >= (NR_HD<<6))
716
                        printk("hd: bad minor number: device=%s\n",
717
                               kdevname(CURRENT->rq_dev));
718
                else
719
                        printk("hd%c: bad access: block=%d, count=%d\n",
720
                                (MINOR(CURRENT->rq_dev)>>6)+'a', block, nsect);
721
#endif
722
                end_request(0);
723
                goto repeat;
724
        }
725
        block += hd[dev].start_sect;
726
        dev >>= 6;
727
        if (special_op[dev]) {
728
                if (do_special_op(dev))
729
                        goto repeat;
730
                return;
731
        }
732
        sec   = block % hd_info[dev].sect + 1;
733
        track = block / hd_info[dev].sect;
734
        head  = track % hd_info[dev].head;
735
        cyl   = track / hd_info[dev].head;
736
#ifdef DEBUG
737
        printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n",
738
                dev+'a', (CURRENT->cmd == READ)?"read":"writ",
739
                cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
740
#endif
741
        if (!unmask_intr[dev])
742
                cli();
743
        if (CURRENT->cmd == READ) {
744
                unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ;
745
                hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr);
746
                if (reset)
747
                        goto repeat;
748
                return;
749
        }
750
        if (CURRENT->cmd == WRITE) {
751
                if (mult_count[dev])
752
                        hd_out(dev,nsect,sec,head,cyl,WIN_MULTWRITE,&multwrite_intr);
753
                else
754
                        hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
755
                if (reset)
756
                        goto repeat;
757
                if (wait_DRQ()) {
758
                        bad_rw_intr();
759
                        goto repeat;
760
                }
761
                if (mult_count[dev]) {
762
                        WCURRENT = *CURRENT;
763
                        multwrite(dev);
764
                } else
765
                        outsw(HD_DATA,CURRENT->buffer,256);
766
                return;
767
        }
768
        panic("unknown hd-command");
769
}
770
 
771
static void do_hd_request (void)
772
{
773
        disable_irq(HD_IRQ);
774
        hd_request();
775
        enable_irq(HD_IRQ);
776
}
777
 
778
static int hd_ioctl(struct inode * inode, struct file * file,
779
        unsigned int cmd, unsigned long arg)
780
{
781
        struct hd_geometry *loc = (struct hd_geometry *) arg;
782
        int dev, err;
783
        unsigned long flags;
784
 
785
        if ((!inode) || !(inode->i_rdev))
786
                return -EINVAL;
787
        dev = DEVICE_NR(inode->i_rdev);
788
        if (dev >= NR_HD)
789
                return -EINVAL;
790
        switch (cmd) {
791
                case HDIO_GETGEO:
792
                        if (!loc)  return -EINVAL;
793
                        err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
794
                        if (err)
795
                                return err;
796
                        put_user(bios_info[dev].head,
797
                                (char *) &loc->heads);
798
                        put_user(bios_info[dev].sect,
799
                                (char *) &loc->sectors);
800
                        put_user(bios_info[dev].cyl,
801
                                (short *) &loc->cylinders);
802
                        put_user(hd[MINOR(inode->i_rdev)].start_sect,
803
                                (long *) &loc->start);
804
                        return 0;
805
                case BLKRASET:
806
                        if(!suser())  return -EACCES;
807
                        if(arg > 0xff) return -EINVAL;
808
                        read_ahead[MAJOR(inode->i_rdev)] = arg;
809
                        return 0;
810
                case BLKRAGET:
811
                        if (!arg)  return -EINVAL;
812
                        err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
813
                        if (err)
814
                                return err;
815
                        put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
816
                        return 0;
817
                case BLKGETSIZE:   /* Return device size */
818
                        if (!arg)  return -EINVAL;
819
                        err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
820
                        if (err)
821
                                return err;
822
                        put_user(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
823
                        return 0;
824
                case BLKFLSBUF:
825
                        if(!suser())  return -EACCES;
826
                        fsync_dev(inode->i_rdev);
827
                        invalidate_buffers(inode->i_rdev);
828
                        return 0;
829
 
830
                case BLKRRPART: /* Re-read partition tables */
831
                        return revalidate_hddisk(inode->i_rdev, 1);
832
 
833
                case HDIO_SET_UNMASKINTR:
834
                        if (!suser()) return -EACCES;
835
                        if ((arg > 1) || (MINOR(inode->i_rdev) & 0x3F))
836
                                return -EINVAL;
837
                        unmask_intr[dev] = arg;
838
                        return 0;
839
 
840
                case HDIO_GET_UNMASKINTR:
841
                        if (!arg)  return -EINVAL;
842
                        err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
843
                        if (err)
844
                                return err;
845
                        put_user(unmask_intr[dev], (long *) arg);
846
                        return 0;
847
 
848
                case HDIO_GET_MULTCOUNT:
849
                        if (!arg)  return -EINVAL;
850
                        err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
851
                        if (err)
852
                                return err;
853
                        put_user(mult_count[dev], (long *) arg);
854
                        return 0;
855
 
856
                case HDIO_SET_MULTCOUNT:
857
                        if (!suser()) return -EACCES;
858
                        if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
859
                        save_flags(flags);
860
                        cli();  /* a prior request might still be in progress */
861
                        if (arg > max_mult[dev])
862
                                err = -EINVAL;  /* out of range for device */
863
                        else if (mult_req[dev] != mult_count[dev]) {
864
                                special_op[dev] = 1;
865
                                err = -EBUSY;   /* busy, try again */
866
                        } else {
867
                                mult_req[dev] = arg;
868
                                special_op[dev] = 1;
869
                                err = 0;
870
                        }
871
                        restore_flags(flags);
872
                        return err;
873
 
874
                case HDIO_OBSOLETE_IDENTITY:
875
                case HDIO_GET_IDENTITY:
876
                        if (!arg)  return -EINVAL;
877
                        if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
878
                        if (hd_ident_info[dev] == NULL)  return -ENOMSG;
879
                        err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(struct hd_driveid));
880
                        if (err)
881
                                return err;
882
                        memcpy_tofs((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
883
                        return 0;
884
 
885
                RO_IOCTLS(inode->i_rdev,arg);
886
                default:
887
                        return -EINVAL;
888
        }
889
}
890
 
891
static int hd_open(struct inode * inode, struct file * filp)
892
{
893
        int target;
894
        target =  DEVICE_NR(inode->i_rdev);
895
 
896
        if (target >= NR_HD)
897
                return -ENODEV;
898
        while (busy[target])
899
                sleep_on(&busy_wait);
900
        access_count[target]++;
901
        return 0;
902
}
903
 
904
/*
905
 * Releasing a block device means we sync() it, so that it can safely
906
 * be forgotten about...
907
 */
908
static void hd_release(struct inode * inode, struct file * file)
909
{
910
        int target;
911
        sync_dev(inode->i_rdev);
912
 
913
        target =  DEVICE_NR(inode->i_rdev);
914
        access_count[target]--;
915
 
916
}
917
 
918
static void hd_geninit(struct gendisk *);
919
 
920
static struct gendisk hd_gendisk = {
921
        MAJOR_NR,       /* Major number */
922
        "hd",           /* Major name */
923
        6,              /* Bits to shift to get real from partition */
924
        1 << 6,         /* Number of partitions per real */
925
        MAX_HD,         /* maximum number of real */
926
        hd_geninit,     /* init function */
927
        hd,             /* hd struct */
928
        hd_sizes,       /* block sizes */
929
        0,               /* number */
930
        (void *) bios_info,     /* internal */
931
        NULL            /* next */
932
};
933
 
934
static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
935
{
936
        void (*handler)(void) = DEVICE_INTR;
937
 
938
        DEVICE_INTR = NULL;
939
        timer_active &= ~(1<<HD_TIMER);
940
        if (!handler)
941
                handler = unexpected_hd_interrupt;
942
        handler();
943
        sti();
944
}
945
 
946
/*
947
 * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags
948
 * means we run the IRQ-handler with interrupts disabled: this is bad for
949
 * interrupt latency, but anything else has led to problems on some
950
 * machines...
951
 *
952
 * We enable interrupts in some of the routines after making sure it's
953
 * safe.
954
 */
955
static void hd_geninit(struct gendisk *ignored)
956
{
957
        int i;
958
 
959
#ifdef __i386__
960
        if (!NR_HD) {
961
                extern struct drive_info drive_info;
962
                unsigned char *BIOS = (unsigned char *) &drive_info;
963
                int cmos_disks, drive;
964
 
965
                for (drive=0 ; drive<2 ; drive++) {
966
                        bios_info[drive].cyl   = hd_info[drive].cyl = *(unsigned short *) BIOS;
967
                        bios_info[drive].head  = hd_info[drive].head = *(2+BIOS);
968
                        bios_info[drive].wpcom = hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
969
                        bios_info[drive].ctl   = hd_info[drive].ctl = *(8+BIOS);
970
                        bios_info[drive].lzone = hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
971
                        bios_info[drive].sect  = hd_info[drive].sect = *(14+BIOS);
972
#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
973
                        if (hd_info[drive].cyl && NR_HD == drive)
974
                                NR_HD++;
975
#endif
976
                        BIOS += 16;
977
                }
978
 
979
        /*
980
                We query CMOS about hard disks : it could be that
981
                we have a SCSI/ESDI/etc controller that is BIOS
982
                compatible with ST-506, and thus showing up in our
983
                BIOS table, but not register compatible, and therefore
984
                not present in CMOS.
985
 
986
                Furthermore, we will assume that our ST-506 drives
987
                <if any> are the primary drives in the system, and
988
                the ones reflected as drive 1 or 2.
989
 
990
                The first drive is stored in the high nibble of CMOS
991
                byte 0x12, the second in the low nibble.  This will be
992
                either a 4 bit drive type or 0xf indicating use byte 0x19
993
                for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
994
 
995
                Needless to say, a non-zero value means we have
996
                an AT controller hard disk for that drive.
997
 
998
 
999
        */
1000
 
1001
                if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
1002
                        if (cmos_disks & 0x0f)
1003
                                NR_HD = 2;
1004
                        else
1005
                                NR_HD = 1;
1006
        }
1007
#endif /* __i386__ */
1008
        i = NR_HD;
1009
        while (i-- > 0) {
1010
                /*
1011
                 * The newer E-IDE BIOSs handle drives larger than 1024
1012
                 * cylinders by increasing the number of logical heads
1013
                 * to keep the number of logical cylinders below the
1014
                 * sacred INT13 limit of 1024 (10 bits).  If that is
1015
                 * what's happening here, we'll find out and correct
1016
                 * it later when "identifying" the drive.
1017
                 */
1018
                hd[i<<6].nr_sects = bios_info[i].head *
1019
                                bios_info[i].sect * bios_info[i].cyl;
1020
                hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
1021
                special_op[i] = 1;
1022
        }
1023
        if (NR_HD) {
1024
                if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
1025
                        printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
1026
                        NR_HD = 0;
1027
                } else {
1028
                        request_region(HD_DATA, 8, "hd");
1029
                        request_region(HD_CMD, 1, "hd(cmd)");
1030
                }
1031
        }
1032
        hd_gendisk.nr_real = NR_HD;
1033
 
1034
        for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
1035
        blksize_size[MAJOR_NR] = hd_blocksizes;
1036
}
1037
 
1038
static struct file_operations hd_fops = {
1039
        NULL,                   /* lseek - default */
1040
        block_read,             /* read - general block-dev read */
1041
        block_write,            /* write - general block-dev write */
1042
        NULL,                   /* readdir - bad */
1043
        NULL,                   /* select */
1044
        hd_ioctl,               /* ioctl */
1045
        NULL,                   /* mmap */
1046
        hd_open,                /* open */
1047
        hd_release,             /* release */
1048
        block_fsync             /* fsync */
1049
};
1050
 
1051
int hd_init(void)
1052
{
1053
        if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
1054
                printk("hd: unable to get major %d for harddisk\n",MAJOR_NR);
1055
                return -1;
1056
        }
1057
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1058
        read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
1059
        hd_gendisk.next = gendisk_head;
1060
        gendisk_head = &hd_gendisk;
1061
        timer_table[HD_TIMER].fn = hd_times_out;
1062
        return 0;
1063
}
1064
 
1065
#define DEVICE_BUSY busy[target]
1066
#define USAGE access_count[target]
1067
#define CAPACITY (bios_info[target].head*bios_info[target].sect*bios_info[target].cyl)
1068
/* We assume that the BIOS parameters do not change, so the disk capacity
1069
   will not change */
1070
#undef MAYBE_REINIT
1071
#define GENDISK_STRUCT hd_gendisk
1072
 
1073
/*
1074
 * This routine is called to flush all partitions and partition tables
1075
 * for a changed scsi disk, and then re-read the new partition table.
1076
 * If we are revalidating a disk because of a media change, then we
1077
 * enter with usage == 0.  If we are using an ioctl, we automatically have
1078
 * usage == 1 (we need an open channel to use an ioctl :-), so this
1079
 * is our limit.
1080
 */
1081
static int revalidate_hddisk(kdev_t dev, int maxusage)
1082
{
1083
        int target;
1084
        struct gendisk * gdev;
1085
        int max_p;
1086
        int start;
1087
        int i;
1088
        long flags;
1089
 
1090
        target = DEVICE_NR(dev);
1091
        gdev = &GENDISK_STRUCT;
1092
 
1093
        save_flags(flags);
1094
        cli();
1095
        if (DEVICE_BUSY || USAGE > maxusage) {
1096
                restore_flags(flags);
1097
                return -EBUSY;
1098
        };
1099
        DEVICE_BUSY = 1;
1100
        restore_flags(flags);
1101
 
1102
        max_p = gdev->max_p;
1103
        start = target << gdev->minor_shift;
1104
 
1105
        for (i=max_p - 1; i >=0 ; i--) {
1106
                int minor = start + i;
1107
                kdev_t devi = MKDEV(MAJOR_NR, minor);
1108
                sync_dev(devi);
1109
                invalidate_inodes(devi);
1110
                invalidate_buffers(devi);
1111
                gdev->part[minor].start_sect = 0;
1112
                gdev->part[minor].nr_sects = 0;
1113
        };
1114
 
1115
#ifdef MAYBE_REINIT
1116
        MAYBE_REINIT;
1117
#endif
1118
 
1119
        gdev->part[start].nr_sects = CAPACITY;
1120
        resetup_one_dev(gdev, target);
1121
 
1122
        DEVICE_BUSY = 0;
1123
        wake_up(&busy_wait);
1124
        return 0;
1125
}
1126
 

powered by: WebSVN 2.1.0

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