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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ide/] [legacy/] [hd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/ide/legacy/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
 *  Removed 99% of above. Use Mark's ide driver for those options.
22
 *  This is now a lightweight ST-506 driver. (Paul Gortmaker)
23
 *
24
 *  Modified 1995 Russell King for ARM processor.
25
 *
26
 *  Bugfix: max_sectors must be <= 255 or the wheels tend to come
27
 *  off in a hurry once you queue things up - Paul G. 02/2001
28
 */
29
 
30
/* Uncomment the following if you want verbose error reports. */
31
/* #define VERBOSE_ERRORS */
32
 
33
#include <linux/errno.h>
34
#include <linux/signal.h>
35
#include <linux/sched.h>
36
#include <linux/timer.h>
37
#include <linux/fs.h>
38
#include <linux/devfs_fs_kernel.h>
39
#include <linux/kernel.h>
40
#include <linux/hdreg.h>
41
#include <linux/genhd.h>
42
#include <linux/slab.h>
43
#include <linux/string.h>
44
#include <linux/ioport.h>
45
#include <linux/mc146818rtc.h> /* CMOS defines */
46
#include <linux/init.h>
47
#include <linux/blkpg.h>
48
 
49
#define REALLY_SLOW_IO
50
#include <asm/system.h>
51
#include <asm/io.h>
52
#include <asm/uaccess.h>
53
 
54
#define MAJOR_NR HD_MAJOR
55
#include <linux/blk.h>
56
 
57
#ifdef __arm__
58
#undef  HD_IRQ
59
#endif
60
#include <asm/irq.h>
61
#ifdef __arm__
62
#define HD_IRQ IRQ_HARDDISK
63
#endif
64
 
65
static int revalidate_hddisk(kdev_t, int);
66
 
67
#define HD_DELAY        0
68
 
69
#define MAX_ERRORS     16       /* Max read/write errors/sector */
70
#define RESET_FREQ      8       /* Reset controller every 8th retry */
71
#define RECAL_FREQ      4       /* Recalibrate every 4th retry */
72
#define MAX_HD          2
73
 
74
#define STAT_OK         (READY_STAT|SEEK_STAT)
75
#define OK_STATUS(s)    (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
76
 
77
static void recal_intr(void);
78
static void bad_rw_intr(void);
79
 
80
static char recalibrate[MAX_HD];
81
static char special_op[MAX_HD];
82
static int access_count[MAX_HD];
83
static char busy[MAX_HD];
84
static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
85
 
86
static int reset;
87
static int hd_error;
88
 
89
#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
90
 
91
/*
92
 *  This struct defines the HD's and their types.
93
 */
94
struct hd_i_struct {
95
        unsigned int head,sect,cyl,wpcom,lzone,ctl;
96
};
97
 
98
#ifdef HD_TYPE
99
static struct hd_i_struct hd_info[] = { HD_TYPE };
100
static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
101
#else
102
static struct hd_i_struct hd_info[MAX_HD];
103
static int NR_HD;
104
#endif
105
 
106
static struct hd_struct hd[MAX_HD<<6];
107
static int hd_sizes[MAX_HD<<6];
108
static int hd_blocksizes[MAX_HD<<6];
109
static int hd_hardsectsizes[MAX_HD<<6];
110
static int hd_maxsect[MAX_HD<<6];
111
 
112
static struct timer_list device_timer;
113
 
114
#define SET_TIMER                                                       \
115
        do {                                                            \
116
                mod_timer(&device_timer, jiffies + TIMEOUT_VALUE);      \
117
        } while (0)
118
 
119
#define CLEAR_TIMER del_timer(&device_timer);
120
 
121
#undef SET_INTR
122
 
123
#define SET_INTR(x) \
124
if ((DEVICE_INTR = (x)) != NULL) \
125
        SET_TIMER; \
126
else \
127
        CLEAR_TIMER;
128
 
129
 
130
#if (HD_DELAY > 0)
131
unsigned long last_req;
132
 
133
unsigned long read_timer(void)
134
{
135
        unsigned long t, flags;
136
        int i;
137
 
138
        spin_lock_irqsave(&io_request_lock, flags);
139
        t = jiffies * 11932;
140
        outb_p(0, 0x43);
141
        i = inb_p(0x40);
142
        i |= inb(0x40) << 8;
143
        spin_unlock_irqrestore(&io_request_lock, flags);
144
        return(t - i);
145
}
146
#endif
147
 
148
void __init hd_setup(char *str, int *ints)
149
{
150
        int hdind = 0;
151
 
152
        if (ints[0] != 3)
153
                return;
154
        if (hd_info[0].head != 0)
155
                hdind=1;
156
        hd_info[hdind].head = ints[2];
157
        hd_info[hdind].sect = ints[3];
158
        hd_info[hdind].cyl = ints[1];
159
        hd_info[hdind].wpcom = 0;
160
        hd_info[hdind].lzone = ints[1];
161
        hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
162
        NR_HD = hdind+1;
163
}
164
 
165
static void dump_status (const char *msg, unsigned int stat)
166
{
167
        unsigned long flags;
168
        char devc;
169
 
170
        devc = !QUEUE_EMPTY ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
171
        save_flags (flags);
172
        sti();
173
#ifdef VERBOSE_ERRORS
174
        printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
175
        if (stat & BUSY_STAT)   printk("Busy ");
176
        if (stat & READY_STAT)  printk("DriveReady ");
177
        if (stat & WRERR_STAT)  printk("WriteFault ");
178
        if (stat & SEEK_STAT)   printk("SeekComplete ");
179
        if (stat & DRQ_STAT)    printk("DataRequest ");
180
        if (stat & ECC_STAT)    printk("CorrectedError ");
181
        if (stat & INDEX_STAT)  printk("Index ");
182
        if (stat & ERR_STAT)    printk("Error ");
183
        printk("}\n");
184
        if ((stat & ERR_STAT) == 0) {
185
                hd_error = 0;
186
        } else {
187
                hd_error = inb(HD_ERROR);
188
                printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff);
189
                if (hd_error & BBD_ERR)         printk("BadSector ");
190
                if (hd_error & ECC_ERR)         printk("UncorrectableError ");
191
                if (hd_error & ID_ERR)          printk("SectorIdNotFound ");
192
                if (hd_error & ABRT_ERR)        printk("DriveStatusError ");
193
                if (hd_error & TRK0_ERR)        printk("TrackZeroNotFound ");
194
                if (hd_error & MARK_ERR)        printk("AddrMarkNotFound ");
195
                printk("}");
196
                if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
197
                        printk(", CHS=%d/%d/%d",
198
                                (inb(HD_HCYL)<<8) + inb(HD_LCYL),
199
                                inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
200
                        if (!QUEUE_EMPTY)
201
                                printk(", sector=%ld", CURRENT->sector);
202
                }
203
                printk("\n");
204
        }
205
#else
206
        printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff);
207
        if ((stat & ERR_STAT) == 0) {
208
                hd_error = 0;
209
        } else {
210
                hd_error = inb(HD_ERROR);
211
                printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
212
        }
213
#endif  /* verbose errors */
214
        restore_flags (flags);
215
}
216
 
217
void check_status(void)
218
{
219
        int i = inb_p(HD_STATUS);
220
 
221
        if (!OK_STATUS(i)) {
222
                dump_status("check_status", i);
223
                bad_rw_intr();
224
        }
225
}
226
 
227
static int controller_busy(void)
228
{
229
        int retries = 100000;
230
        unsigned char status;
231
 
232
        do {
233
                status = inb_p(HD_STATUS);
234
        } while ((status & BUSY_STAT) && --retries);
235
        return status;
236
}
237
 
238
static int status_ok(void)
239
{
240
        unsigned char status = inb_p(HD_STATUS);
241
 
242
        if (status & BUSY_STAT)
243
                return 1;       /* Ancient, but does it make sense??? */
244
        if (status & WRERR_STAT)
245
                return 0;
246
        if (!(status & READY_STAT))
247
                return 0;
248
        if (!(status & SEEK_STAT))
249
                return 0;
250
        return 1;
251
}
252
 
253
static int controller_ready(unsigned int drive, unsigned int head)
254
{
255
        int retry = 100;
256
 
257
        do {
258
                if (controller_busy() & BUSY_STAT)
259
                        return 0;
260
                outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
261
                if (status_ok())
262
                        return 1;
263
        } while (--retry);
264
        return 0;
265
}
266
 
267
static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
268
                unsigned int head,unsigned int cyl,unsigned int cmd,
269
                void (*intr_addr)(void))
270
{
271
        unsigned short port;
272
 
273
#if (HD_DELAY > 0)
274
        while (read_timer() - last_req < HD_DELAY)
275
                /* nothing */;
276
#endif
277
        if (reset)
278
                return;
279
        if (!controller_ready(drive, head)) {
280
                reset = 1;
281
                return;
282
        }
283
        SET_INTR(intr_addr);
284
        outb_p(hd_info[drive].ctl,HD_CMD);
285
        port=HD_DATA;
286
        outb_p(hd_info[drive].wpcom>>2,++port);
287
        outb_p(nsect,++port);
288
        outb_p(sect,++port);
289
        outb_p(cyl,++port);
290
        outb_p(cyl>>8,++port);
291
        outb_p(0xA0|(drive<<4)|head,++port);
292
        outb_p(cmd,++port);
293
}
294
 
295
static void hd_request (void);
296
 
297
static int drive_busy(void)
298
{
299
        unsigned int i;
300
        unsigned char c;
301
 
302
        for (i = 0; i < 500000 ; i++) {
303
                c = inb_p(HD_STATUS);
304
                if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
305
                        return 0;
306
        }
307
        dump_status("reset timed out", c);
308
        return 1;
309
}
310
 
311
static void reset_controller(void)
312
{
313
        int     i;
314
 
315
        outb_p(4,HD_CMD);
316
        for(i = 0; i < 1000; i++) barrier();
317
        outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
318
        for(i = 0; i < 1000; i++) barrier();
319
        if (drive_busy())
320
                printk("hd: controller still busy\n");
321
        else if ((hd_error = inb(HD_ERROR)) != 1)
322
                printk("hd: controller reset failed: %02x\n",hd_error);
323
}
324
 
325
static void reset_hd(void)
326
{
327
        static int i;
328
 
329
repeat:
330
        if (reset) {
331
                reset = 0;
332
                i = -1;
333
                reset_controller();
334
        } else {
335
                check_status();
336
                if (reset)
337
                        goto repeat;
338
        }
339
        if (++i < NR_HD) {
340
                special_op[i] = recalibrate[i] = 1;
341
                hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
342
                        hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
343
                if (reset)
344
                        goto repeat;
345
        } else
346
                hd_request();
347
}
348
 
349
void do_reset_hd(void)
350
{
351
        DEVICE_INTR = NULL;
352
        reset = 1;
353
        reset_hd();
354
}
355
 
356
/*
357
 * Ok, don't know what to do with the unexpected interrupts: on some machines
358
 * doing a reset and a retry seems to result in an eternal loop. Right now I
359
 * ignore it, and just set the timeout.
360
 *
361
 * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
362
 * drive enters "idle", "standby", or "sleep" mode, so if the status looks
363
 * "good", we just ignore the interrupt completely.
364
 */
365
void unexpected_hd_interrupt(void)
366
{
367
        unsigned int stat = inb_p(HD_STATUS);
368
 
369
        if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
370
                dump_status ("unexpected interrupt", stat);
371
                SET_TIMER;
372
        }
373
}
374
 
375
/*
376
 * bad_rw_intr() now tries to be a bit smarter and does things
377
 * according to the error returned by the controller.
378
 * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
379
 */
380
static void bad_rw_intr(void)
381
{
382
        int dev;
383
 
384
        if (QUEUE_EMPTY)
385
                return;
386
        dev = DEVICE_NR(CURRENT->rq_dev);
387
        if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
388
                end_request(0);
389
                special_op[dev] = recalibrate[dev] = 1;
390
        } else if (CURRENT->errors % RESET_FREQ == 0)
391
                reset = 1;
392
        else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
393
                special_op[dev] = recalibrate[dev] = 1;
394
        /* Otherwise just retry */
395
}
396
 
397
static inline int wait_DRQ(void)
398
{
399
        int retries = 100000, stat;
400
 
401
        while (--retries > 0)
402
                if ((stat = inb_p(HD_STATUS)) & DRQ_STAT)
403
                        return 0;
404
        dump_status("wait_DRQ", stat);
405
        return -1;
406
}
407
 
408
static void read_intr(void)
409
{
410
        int i, retries = 100000;
411
 
412
        do {
413
                i = (unsigned) inb_p(HD_STATUS);
414
                if (i & BUSY_STAT)
415
                        continue;
416
                if (!OK_STATUS(i))
417
                        break;
418
                if (i & DRQ_STAT)
419
                        goto ok_to_read;
420
        } while (--retries > 0);
421
        dump_status("read_intr", i);
422
        bad_rw_intr();
423
        hd_request();
424
        return;
425
ok_to_read:
426
        insw(HD_DATA,CURRENT->buffer,256);
427
        CURRENT->sector++;
428
        CURRENT->buffer += 512;
429
        CURRENT->errors = 0;
430
        i = --CURRENT->nr_sectors;
431
        --CURRENT->current_nr_sectors;
432
#ifdef DEBUG
433
        printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n",
434
                dev+'a', CURRENT->sector, CURRENT->nr_sectors,
435
                (unsigned long) CURRENT->buffer+512));
436
#endif
437
        if (CURRENT->current_nr_sectors <= 0)
438
                end_request(1);
439
        if (i > 0) {
440
                SET_INTR(&read_intr);
441
                return;
442
        }
443
        (void) inb_p(HD_STATUS);
444
#if (HD_DELAY > 0)
445
        last_req = read_timer();
446
#endif
447
        if (!QUEUE_EMPTY)
448
                hd_request();
449
        return;
450
}
451
 
452
static void write_intr(void)
453
{
454
        int i;
455
        int retries = 100000;
456
 
457
        do {
458
                i = (unsigned) inb_p(HD_STATUS);
459
                if (i & BUSY_STAT)
460
                        continue;
461
                if (!OK_STATUS(i))
462
                        break;
463
                if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
464
                        goto ok_to_write;
465
        } while (--retries > 0);
466
        dump_status("write_intr", i);
467
        bad_rw_intr();
468
        hd_request();
469
        return;
470
ok_to_write:
471
        CURRENT->sector++;
472
        i = --CURRENT->nr_sectors;
473
        --CURRENT->current_nr_sectors;
474
        CURRENT->buffer += 512;
475
        if (!i || (CURRENT->bh && !SUBSECTOR(i)))
476
                end_request(1);
477
        if (i > 0) {
478
                SET_INTR(&write_intr);
479
                outsw(HD_DATA,CURRENT->buffer,256);
480
                sti();
481
        } else {
482
#if (HD_DELAY > 0)
483
                last_req = read_timer();
484
#endif
485
                hd_request();
486
        }
487
        return;
488
}
489
 
490
static void recal_intr(void)
491
{
492
        check_status();
493
#if (HD_DELAY > 0)
494
        last_req = read_timer();
495
#endif
496
        hd_request();
497
}
498
 
499
/*
500
 * This is another of the error-routines I don't know what to do with. The
501
 * best idea seems to just set reset, and start all over again.
502
 */
503
static void hd_times_out(unsigned long dummy)
504
{
505
        unsigned int dev;
506
 
507
        DEVICE_INTR = NULL;
508
        if (QUEUE_EMPTY)
509
                return;
510
        disable_irq(HD_IRQ);
511
        sti();
512
        reset = 1;
513
        dev = DEVICE_NR(CURRENT->rq_dev);
514
        printk("hd%c: timeout\n", dev+'a');
515
        if (++CURRENT->errors >= MAX_ERRORS) {
516
#ifdef DEBUG
517
                printk("hd%c: too many errors\n", dev+'a');
518
#endif
519
                end_request(0);
520
        }
521
        cli();
522
        hd_request();
523
        enable_irq(HD_IRQ);
524
}
525
 
526
int do_special_op (unsigned int dev)
527
{
528
        if (recalibrate[dev]) {
529
                recalibrate[dev] = 0;
530
                hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
531
                return reset;
532
        }
533
        if (hd_info[dev].head > 16) {
534
                printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
535
                end_request(0);
536
        }
537
        special_op[dev] = 0;
538
        return 1;
539
}
540
 
541
/*
542
 * The driver enables interrupts as much as possible.  In order to do this,
543
 * (a) the device-interrupt is disabled before entering hd_request(),
544
 * and (b) the timeout-interrupt is disabled before the sti().
545
 *
546
 * Interrupts are still masked (by default) whenever we are exchanging
547
 * data/cmds with a drive, because some drives seem to have very poor
548
 * tolerance for latency during I/O. The IDE driver has support to unmask
549
 * interrupts for non-broken hardware, so use that driver if required.
550
 */
551
static void hd_request(void)
552
{
553
        unsigned int dev, block, nsect, sec, track, head, cyl;
554
 
555
        if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE) return;
556
        if (DEVICE_INTR)
557
                return;
558
repeat:
559
        del_timer(&device_timer);
560
        sti();
561
        INIT_REQUEST;
562
        if (reset) {
563
                cli();
564
                reset_hd();
565
                return;
566
        }
567
        dev = MINOR(CURRENT->rq_dev);
568
        block = CURRENT->sector;
569
        nsect = CURRENT->nr_sectors;
570
        if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
571
#ifdef DEBUG
572
                if (dev >= (NR_HD<<6))
573
                        printk("hd: bad minor number: device=%s\n",
574
                               kdevname(CURRENT->rq_dev));
575
                else
576
                        printk("hd%c: bad access: block=%d, count=%d\n",
577
                                (MINOR(CURRENT->rq_dev)>>6)+'a', block, nsect);
578
#endif
579
                end_request(0);
580
                goto repeat;
581
        }
582
        block += hd[dev].start_sect;
583
        dev >>= 6;
584
        if (special_op[dev]) {
585
                if (do_special_op(dev))
586
                        goto repeat;
587
                return;
588
        }
589
        sec   = block % hd_info[dev].sect + 1;
590
        track = block / hd_info[dev].sect;
591
        head  = track % hd_info[dev].head;
592
        cyl   = track / hd_info[dev].head;
593
#ifdef DEBUG
594
        printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n",
595
                dev+'a', (CURRENT->cmd == READ)?"read":"writ",
596
                cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
597
#endif
598
        if (CURRENT->cmd == READ) {
599
                hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
600
                if (reset)
601
                        goto repeat;
602
                return;
603
        }
604
        if (CURRENT->cmd == WRITE) {
605
                hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
606
                if (reset)
607
                        goto repeat;
608
                if (wait_DRQ()) {
609
                        bad_rw_intr();
610
                        goto repeat;
611
                }
612
                outsw(HD_DATA,CURRENT->buffer,256);
613
                return;
614
        }
615
        panic("unknown hd-command");
616
}
617
 
618
static void do_hd_request (request_queue_t * q)
619
{
620
        disable_irq(HD_IRQ);
621
        hd_request();
622
        enable_irq(HD_IRQ);
623
}
624
 
625
static int hd_ioctl(struct inode * inode, struct file * file,
626
        unsigned int cmd, unsigned long arg)
627
{
628
        struct hd_geometry *loc = (struct hd_geometry *) arg;
629
        int dev;
630
 
631
        if ((!inode) || !(inode->i_rdev))
632
                return -EINVAL;
633
        dev = DEVICE_NR(inode->i_rdev);
634
        if (dev >= NR_HD)
635
                return -EINVAL;
636
        switch (cmd) {
637
                case HDIO_GETGEO:
638
                {
639
                        struct hd_geometry g;
640
                        if (!loc)  return -EINVAL;
641
                        g.heads = hd_info[dev].head;
642
                        g.sectors = hd_info[dev].sect;
643
                        g.cylinders = hd_info[dev].cyl;
644
                        g.start = hd[MINOR(inode->i_rdev)].start_sect;
645
                        return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
646
                }
647
 
648
                case BLKGETSIZE:   /* Return device size */
649
                        return put_user(hd[MINOR(inode->i_rdev)].nr_sects,
650
                                        (unsigned long *) arg);
651
                case BLKGETSIZE64:
652
                        return put_user((u64)hd[MINOR(inode->i_rdev)].nr_sects << 9,
653
                                        (u64 *) arg);
654
 
655
                case BLKRRPART: /* Re-read partition tables */
656
                        if (!capable(CAP_SYS_ADMIN))
657
                                return -EACCES;
658
                        return revalidate_hddisk(inode->i_rdev, 1);
659
 
660
                case BLKROSET:
661
                case BLKROGET:
662
                case BLKRASET:
663
                case BLKRAGET:
664
                case BLKFLSBUF:
665
                case BLKPG:
666
                        return blk_ioctl(inode->i_rdev, cmd, arg);
667
 
668
                default:
669
                        return -EINVAL;
670
        }
671
}
672
 
673
static int hd_open(struct inode * inode, struct file * filp)
674
{
675
        int target;
676
        target =  DEVICE_NR(inode->i_rdev);
677
 
678
        if (target >= NR_HD)
679
                return -ENODEV;
680
        while (busy[target])
681
                sleep_on(&busy_wait);
682
        access_count[target]++;
683
        return 0;
684
}
685
 
686
/*
687
 * Releasing a block device means we sync() it, so that it can safely
688
 * be forgotten about...
689
 */
690
static int hd_release(struct inode * inode, struct file * file)
691
{
692
        int target =  DEVICE_NR(inode->i_rdev);
693
        access_count[target]--;
694
        return 0;
695
}
696
 
697
extern struct block_device_operations hd_fops;
698
 
699
static struct gendisk hd_gendisk = {
700
        major:          MAJOR_NR,
701
        major_name:     "hd",
702
        minor_shift:    6,
703
        max_p:          1 << 6,
704
        part:           hd,
705
        sizes:          hd_sizes,
706
        fops:           &hd_fops,
707
};
708
 
709
static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
710
{
711
        void (*handler)(void) = DEVICE_INTR;
712
 
713
        DEVICE_INTR = NULL;
714
        del_timer(&device_timer);
715
        if (!handler)
716
                handler = unexpected_hd_interrupt;
717
        handler();
718
        sti();
719
}
720
 
721
static struct block_device_operations hd_fops = {
722
        open:           hd_open,
723
        release:        hd_release,
724
        ioctl:          hd_ioctl,
725
};
726
 
727
/*
728
 * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
729
 * means we run the IRQ-handler with interrupts disabled:  this is bad for
730
 * interrupt latency, but anything else has led to problems on some
731
 * machines.
732
 *
733
 * We enable interrupts in some of the routines after making sure it's
734
 * safe.
735
 */
736
static void __init hd_geninit(void)
737
{
738
        int drive;
739
 
740
        for(drive=0; drive < (MAX_HD << 6); drive++) {
741
                hd_blocksizes[drive] = 1024;
742
                hd_hardsectsizes[drive] = 512;
743
                hd_maxsect[drive]=255;
744
        }
745
        blksize_size[MAJOR_NR] = hd_blocksizes;
746
        hardsect_size[MAJOR_NR] = hd_hardsectsizes;
747
        max_sectors[MAJOR_NR] = hd_maxsect;
748
 
749
#ifdef __i386__
750
        if (!NR_HD) {
751
                extern struct drive_info drive_info;
752
                unsigned char *BIOS = (unsigned char *) &drive_info;
753
                unsigned long flags;
754
                int cmos_disks;
755
 
756
                for (drive=0 ; drive<2 ; drive++) {
757
                        hd_info[drive].cyl = *(unsigned short *) BIOS;
758
                        hd_info[drive].head = *(2+BIOS);
759
                        hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
760
                        hd_info[drive].ctl = *(8+BIOS);
761
                        hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
762
                        hd_info[drive].sect = *(14+BIOS);
763
#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
764
                        if (hd_info[drive].cyl && NR_HD == drive)
765
                                NR_HD++;
766
#endif
767
                        BIOS += 16;
768
                }
769
 
770
        /*
771
                We query CMOS about hard disks : it could be that
772
                we have a SCSI/ESDI/etc controller that is BIOS
773
                compatible with ST-506, and thus showing up in our
774
                BIOS table, but not register compatible, and therefore
775
                not present in CMOS.
776
 
777
                Furthermore, we will assume that our ST-506 drives
778
                <if any> are the primary drives in the system, and
779
                the ones reflected as drive 1 or 2.
780
 
781
                The first drive is stored in the high nibble of CMOS
782
                byte 0x12, the second in the low nibble.  This will be
783
                either a 4 bit drive type or 0xf indicating use byte 0x19
784
                for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
785
 
786
                Needless to say, a non-zero value means we have
787
                an AT controller hard disk for that drive.
788
 
789
                Currently the rtc_lock is a bit academic since this
790
                driver is non-modular, but someday... ?         Paul G.
791
        */
792
 
793
                spin_lock_irqsave(&rtc_lock, flags);
794
                cmos_disks = CMOS_READ(0x12);
795
                spin_unlock_irqrestore(&rtc_lock, flags);
796
 
797
                if (cmos_disks & 0xf0) {
798
                        if (cmos_disks & 0x0f)
799
                                NR_HD = 2;
800
                        else
801
                                NR_HD = 1;
802
                }
803
        }
804
#endif /* __i386__ */
805
#ifdef __arm__
806
        if (!NR_HD) {
807
                /* We don't know anything about the drive.  This means
808
                 * that you *MUST* specify the drive parameters to the
809
                 * kernel yourself.
810
                 */
811
                printk("hd: no drives specified - use hd=cyl,head,sectors"
812
                        " on kernel command line\n");
813
        }
814
#endif
815
 
816
        for (drive=0 ; drive < NR_HD ; drive++) {
817
                hd[drive<<6].nr_sects = hd_info[drive].head *
818
                        hd_info[drive].sect * hd_info[drive].cyl;
819
                printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a',
820
                        hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl,
821
                        hd_info[drive].head, hd_info[drive].sect);
822
        }
823
        if (!NR_HD)
824
                return;
825
 
826
        if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
827
                printk("hd: unable to get IRQ%d for the hard disk driver\n",
828
                        HD_IRQ);
829
                NR_HD = 0;
830
                return;
831
        }
832
        request_region(HD_DATA, 8, "hd");
833
        request_region(HD_CMD, 1, "hd(cmd)");
834
 
835
        hd_gendisk.nr_real = NR_HD;
836
 
837
        for(drive=0; drive < NR_HD; drive++)
838
                register_disk(&hd_gendisk, MKDEV(MAJOR_NR,drive<<6), 1<<6,
839
                        &hd_fops, hd_info[drive].head * hd_info[drive].sect *
840
                        hd_info[drive].cyl);
841
}
842
 
843
int __init hd_init(void)
844
{
845
        if (devfs_register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
846
                printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
847
                return -1;
848
        }
849
        blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
850
        read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
851
        add_gendisk(&hd_gendisk);
852
        init_timer(&device_timer);
853
        device_timer.function = hd_times_out;
854
        hd_geninit();
855
        return 0;
856
}
857
 
858
#define DEVICE_BUSY busy[target]
859
#define USAGE access_count[target]
860
#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
861
/* We assume that the BIOS parameters do not change, so the disk capacity
862
   will not change */
863
#undef MAYBE_REINIT
864
#define GENDISK_STRUCT hd_gendisk
865
 
866
/*
867
 * This routine is called to flush all partitions and partition tables
868
 * for a changed disk, and then re-read the new partition table.
869
 * If we are revalidating a disk because of a media change, then we
870
 * enter with usage == 0.  If we are using an ioctl, we automatically have
871
 * usage == 1 (we need an open channel to use an ioctl :-), so this
872
 * is our limit.
873
 */
874
static int revalidate_hddisk(kdev_t dev, int maxusage)
875
{
876
        int target;
877
        struct gendisk * gdev;
878
        int max_p;
879
        int start;
880
        int i;
881
        long flags;
882
 
883
        target = DEVICE_NR(dev);
884
        gdev = &GENDISK_STRUCT;
885
 
886
        spin_lock_irqsave(&io_request_lock, flags);
887
        if (DEVICE_BUSY || USAGE > maxusage) {
888
                spin_unlock_irqrestore(&io_request_lock, flags);
889
                return -EBUSY;
890
        }
891
        DEVICE_BUSY = 1;
892
        spin_unlock_irqrestore(&io_request_lock, flags);
893
 
894
        max_p = gdev->max_p;
895
        start = target << gdev->minor_shift;
896
 
897
        for (i=max_p - 1; i >=0 ; i--) {
898
                int minor = start + i;
899
                invalidate_device(MKDEV(MAJOR_NR, minor), 1);
900
                gdev->part[minor].start_sect = 0;
901
                gdev->part[minor].nr_sects = 0;
902
        }
903
 
904
#ifdef MAYBE_REINIT
905
        MAYBE_REINIT;
906
#endif
907
 
908
        grok_partitions(gdev, target, 1<<6, CAPACITY);
909
 
910
        DEVICE_BUSY = 0;
911
        wake_up(&busy_wait);
912
        return 0;
913
}
914
 
915
static int parse_hd_setup (char *line) {
916
        int ints[6];
917
 
918
        (void) get_options(line, ARRAY_SIZE(ints), ints);
919
        hd_setup(NULL, ints);
920
 
921
        return 1;
922
}
923
__setup("hd=", parse_hd_setup);
924
 
925
module_init(hd_init);

powered by: WebSVN 2.1.0

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