aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-18 16:00:54 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-18 16:00:54 -0400
commitbb2c018b09b681d43f5e08124b83e362647ea82b (patch)
treed794902c78f9fdd04ed88a4b8d451ed6f9292ec0 /drivers/block
parent82638844d9a8581bbf33201cc209a14876eca167 (diff)
parent5b664cb235e97afbf34db9c4d77f08ebd725335e (diff)
Merge branch 'linus' into cpus4096
Conflicts: drivers/acpi/processor_throttling.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Kconfig12
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/hd.c814
3 files changed, 827 insertions, 0 deletions
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 0d1d2133d9bc..61ad8d639ba3 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -433,4 +433,16 @@ config VIRTIO_BLK
433 This is the virtual block driver for virtio. It can be used with 433 This is the virtual block driver for virtio. It can be used with
434 lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. 434 lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
435 435
436config BLK_DEV_HD
437 bool "Very old hard disk (MFM/RLL/IDE) driver"
438 depends on HAVE_IDE
439 depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN
440 help
441 This is a very old hard disk driver that lacks the enhanced
442 functionality of the newer ones.
443
444 It is required for systems with ancient MFM/RLL/ESDI drives.
445
446 If unsure, say N.
447
436endif # BLK_DEV 448endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 5e584306be99..204332b29578 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -29,5 +29,6 @@ obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
29obj-$(CONFIG_VIODASD) += viodasd.o 29obj-$(CONFIG_VIODASD) += viodasd.o
30obj-$(CONFIG_BLK_DEV_SX8) += sx8.o 30obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
31obj-$(CONFIG_BLK_DEV_UB) += ub.o 31obj-$(CONFIG_BLK_DEV_UB) += ub.o
32obj-$(CONFIG_BLK_DEV_HD) += hd.o
32 33
33obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o 34obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
new file mode 100644
index 000000000000..682243bf2e46
--- /dev/null
+++ b/drivers/block/hd.c
@@ -0,0 +1,814 @@
1/*
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 *
4 * This is the low-level hd interrupt support. It traverses the
5 * request-list, using interrupts to jump between functions. As
6 * all the functions are called within interrupts, we may not
7 * sleep. Special care is recommended.
8 *
9 * modified by Drew Eckhardt to check nr of hd's from the CMOS.
10 *
11 * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
12 * in the early extended-partition checks and added DM partitions
13 *
14 * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
15 * and general streamlining by Mark Lord.
16 *
17 * Removed 99% of above. Use Mark's ide driver for those options.
18 * This is now a lightweight ST-506 driver. (Paul Gortmaker)
19 *
20 * Modified 1995 Russell King for ARM processor.
21 *
22 * Bugfix: max_sectors must be <= 255 or the wheels tend to come
23 * off in a hurry once you queue things up - Paul G. 02/2001
24 */
25
26/* Uncomment the following if you want verbose error reports. */
27/* #define VERBOSE_ERRORS */
28
29#include <linux/blkdev.h>
30#include <linux/errno.h>
31#include <linux/signal.h>
32#include <linux/interrupt.h>
33#include <linux/timer.h>
34#include <linux/fs.h>
35#include <linux/kernel.h>
36#include <linux/genhd.h>
37#include <linux/slab.h>
38#include <linux/string.h>
39#include <linux/ioport.h>
40#include <linux/init.h>
41#include <linux/blkpg.h>
42#include <linux/hdreg.h>
43
44#define REALLY_SLOW_IO
45#include <asm/system.h>
46#include <asm/io.h>
47#include <asm/uaccess.h>
48
49#ifdef __arm__
50#undef HD_IRQ
51#endif
52#include <asm/irq.h>
53#ifdef __arm__
54#define HD_IRQ IRQ_HARDDISK
55#endif
56
57/* Hd controller regster ports */
58
59#define HD_DATA 0x1f0 /* _CTL when writing */
60#define HD_ERROR 0x1f1 /* see err-bits */
61#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
62#define HD_SECTOR 0x1f3 /* starting sector */
63#define HD_LCYL 0x1f4 /* starting cylinder */
64#define HD_HCYL 0x1f5 /* high byte of starting cyl */
65#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
66#define HD_STATUS 0x1f7 /* see status-bits */
67#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
68#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
69#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
70
71#define HD_CMD 0x3f6 /* used for resets */
72#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
73
74/* Bits of HD_STATUS */
75#define ERR_STAT 0x01
76#define INDEX_STAT 0x02
77#define ECC_STAT 0x04 /* Corrected error */
78#define DRQ_STAT 0x08
79#define SEEK_STAT 0x10
80#define SERVICE_STAT SEEK_STAT
81#define WRERR_STAT 0x20
82#define READY_STAT 0x40
83#define BUSY_STAT 0x80
84
85/* Bits for HD_ERROR */
86#define MARK_ERR 0x01 /* Bad address mark */
87#define TRK0_ERR 0x02 /* couldn't find track 0 */
88#define ABRT_ERR 0x04 /* Command aborted */
89#define MCR_ERR 0x08 /* media change request */
90#define ID_ERR 0x10 /* ID field not found */
91#define MC_ERR 0x20 /* media changed */
92#define ECC_ERR 0x40 /* Uncorrectable ECC error */
93#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
94#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
95
96static DEFINE_SPINLOCK(hd_lock);
97static struct request_queue *hd_queue;
98
99#define MAJOR_NR HD_MAJOR
100#define QUEUE (hd_queue)
101#define CURRENT elv_next_request(hd_queue)
102
103#define TIMEOUT_VALUE (6*HZ)
104#define HD_DELAY 0
105
106#define MAX_ERRORS 16 /* Max read/write errors/sector */
107#define RESET_FREQ 8 /* Reset controller every 8th retry */
108#define RECAL_FREQ 4 /* Recalibrate every 4th retry */
109#define MAX_HD 2
110
111#define STAT_OK (READY_STAT|SEEK_STAT)
112#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
113
114static void recal_intr(void);
115static void bad_rw_intr(void);
116
117static int reset;
118static int hd_error;
119
120/*
121 * This struct defines the HD's and their types.
122 */
123struct hd_i_struct {
124 unsigned int head, sect, cyl, wpcom, lzone, ctl;
125 int unit;
126 int recalibrate;
127 int special_op;
128};
129
130#ifdef HD_TYPE
131static struct hd_i_struct hd_info[] = { HD_TYPE };
132static int NR_HD = ARRAY_SIZE(hd_info);
133#else
134static struct hd_i_struct hd_info[MAX_HD];
135static int NR_HD;
136#endif
137
138static struct gendisk *hd_gendisk[MAX_HD];
139
140static struct timer_list device_timer;
141
142#define TIMEOUT_VALUE (6*HZ)
143
144#define SET_TIMER \
145 do { \
146 mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \
147 } while (0)
148
149static void (*do_hd)(void) = NULL;
150#define SET_HANDLER(x) \
151if ((do_hd = (x)) != NULL) \
152 SET_TIMER; \
153else \
154 del_timer(&device_timer);
155
156
157#if (HD_DELAY > 0)
158
159#include <asm/i8253.h>
160
161unsigned long last_req;
162
163unsigned long read_timer(void)
164{
165 unsigned long t, flags;
166 int i;
167
168 spin_lock_irqsave(&i8253_lock, flags);
169 t = jiffies * 11932;
170 outb_p(0, 0x43);
171 i = inb_p(0x40);
172 i |= inb(0x40) << 8;
173 spin_unlock_irqrestore(&i8253_lock, flags);
174 return(t - i);
175}
176#endif
177
178static void __init hd_setup(char *str, int *ints)
179{
180 int hdind = 0;
181
182 if (ints[0] != 3)
183 return;
184 if (hd_info[0].head != 0)
185 hdind = 1;
186 hd_info[hdind].head = ints[2];
187 hd_info[hdind].sect = ints[3];
188 hd_info[hdind].cyl = ints[1];
189 hd_info[hdind].wpcom = 0;
190 hd_info[hdind].lzone = ints[1];
191 hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
192 NR_HD = hdind+1;
193}
194
195static void dump_status(const char *msg, unsigned int stat)
196{
197 char *name = "hd?";
198 if (CURRENT)
199 name = CURRENT->rq_disk->disk_name;
200
201#ifdef VERBOSE_ERRORS
202 printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
203 if (stat & BUSY_STAT) printk("Busy ");
204 if (stat & READY_STAT) printk("DriveReady ");
205 if (stat & WRERR_STAT) printk("WriteFault ");
206 if (stat & SEEK_STAT) printk("SeekComplete ");
207 if (stat & DRQ_STAT) printk("DataRequest ");
208 if (stat & ECC_STAT) printk("CorrectedError ");
209 if (stat & INDEX_STAT) printk("Index ");
210 if (stat & ERR_STAT) printk("Error ");
211 printk("}\n");
212 if ((stat & ERR_STAT) == 0) {
213 hd_error = 0;
214 } else {
215 hd_error = inb(HD_ERROR);
216 printk("%s: %s: error=0x%02x { ", name, msg, hd_error & 0xff);
217 if (hd_error & BBD_ERR) printk("BadSector ");
218 if (hd_error & ECC_ERR) printk("UncorrectableError ");
219 if (hd_error & ID_ERR) printk("SectorIdNotFound ");
220 if (hd_error & ABRT_ERR) printk("DriveStatusError ");
221 if (hd_error & TRK0_ERR) printk("TrackZeroNotFound ");
222 if (hd_error & MARK_ERR) printk("AddrMarkNotFound ");
223 printk("}");
224 if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
225 printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
226 inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
227 if (CURRENT)
228 printk(", sector=%ld", CURRENT->sector);
229 }
230 printk("\n");
231 }
232#else
233 printk("%s: %s: status=0x%02x.\n", name, msg, stat & 0xff);
234 if ((stat & ERR_STAT) == 0) {
235 hd_error = 0;
236 } else {
237 hd_error = inb(HD_ERROR);
238 printk("%s: %s: error=0x%02x.\n", name, msg, hd_error & 0xff);
239 }
240#endif
241}
242
243static void check_status(void)
244{
245 int i = inb_p(HD_STATUS);
246
247 if (!OK_STATUS(i)) {
248 dump_status("check_status", i);
249 bad_rw_intr();
250 }
251}
252
253static int controller_busy(void)
254{
255 int retries = 100000;
256 unsigned char status;
257
258 do {
259 status = inb_p(HD_STATUS);
260 } while ((status & BUSY_STAT) && --retries);
261 return status;
262}
263
264static int status_ok(void)
265{
266 unsigned char status = inb_p(HD_STATUS);
267
268 if (status & BUSY_STAT)
269 return 1; /* Ancient, but does it make sense??? */
270 if (status & WRERR_STAT)
271 return 0;
272 if (!(status & READY_STAT))
273 return 0;
274 if (!(status & SEEK_STAT))
275 return 0;
276 return 1;
277}
278
279static int controller_ready(unsigned int drive, unsigned int head)
280{
281 int retry = 100;
282
283 do {
284 if (controller_busy() & BUSY_STAT)
285 return 0;
286 outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
287 if (status_ok())
288 return 1;
289 } while (--retry);
290 return 0;
291}
292
293static void hd_out(struct hd_i_struct *disk,
294 unsigned int nsect,
295 unsigned int sect,
296 unsigned int head,
297 unsigned int cyl,
298 unsigned int cmd,
299 void (*intr_addr)(void))
300{
301 unsigned short port;
302
303#if (HD_DELAY > 0)
304 while (read_timer() - last_req < HD_DELAY)
305 /* nothing */;
306#endif
307 if (reset)
308 return;
309 if (!controller_ready(disk->unit, head)) {
310 reset = 1;
311 return;
312 }
313 SET_HANDLER(intr_addr);
314 outb_p(disk->ctl, HD_CMD);
315 port = HD_DATA;
316 outb_p(disk->wpcom >> 2, ++port);
317 outb_p(nsect, ++port);
318 outb_p(sect, ++port);
319 outb_p(cyl, ++port);
320 outb_p(cyl >> 8, ++port);
321 outb_p(0xA0 | (disk->unit << 4) | head, ++port);
322 outb_p(cmd, ++port);
323}
324
325static void hd_request (void);
326
327static int drive_busy(void)
328{
329 unsigned int i;
330 unsigned char c;
331
332 for (i = 0; i < 500000 ; i++) {
333 c = inb_p(HD_STATUS);
334 if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
335 return 0;
336 }
337 dump_status("reset timed out", c);
338 return 1;
339}
340
341static void reset_controller(void)
342{
343 int i;
344
345 outb_p(4, HD_CMD);
346 for (i = 0; i < 1000; i++) barrier();
347 outb_p(hd_info[0].ctl & 0x0f, HD_CMD);
348 for (i = 0; i < 1000; i++) barrier();
349 if (drive_busy())
350 printk("hd: controller still busy\n");
351 else if ((hd_error = inb(HD_ERROR)) != 1)
352 printk("hd: controller reset failed: %02x\n", hd_error);
353}
354
355static void reset_hd(void)
356{
357 static int i;
358
359repeat:
360 if (reset) {
361 reset = 0;
362 i = -1;
363 reset_controller();
364 } else {
365 check_status();
366 if (reset)
367 goto repeat;
368 }
369 if (++i < NR_HD) {
370 struct hd_i_struct *disk = &hd_info[i];
371 disk->special_op = disk->recalibrate = 1;
372 hd_out(disk, disk->sect, disk->sect, disk->head-1,
373 disk->cyl, WIN_SPECIFY, &reset_hd);
374 if (reset)
375 goto repeat;
376 } else
377 hd_request();
378}
379
380/*
381 * Ok, don't know what to do with the unexpected interrupts: on some machines
382 * doing a reset and a retry seems to result in an eternal loop. Right now I
383 * ignore it, and just set the timeout.
384 *
385 * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
386 * drive enters "idle", "standby", or "sleep" mode, so if the status looks
387 * "good", we just ignore the interrupt completely.
388 */
389static void unexpected_hd_interrupt(void)
390{
391 unsigned int stat = inb_p(HD_STATUS);
392
393 if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
394 dump_status("unexpected interrupt", stat);
395 SET_TIMER;
396 }
397}
398
399/*
400 * bad_rw_intr() now tries to be a bit smarter and does things
401 * according to the error returned by the controller.
402 * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
403 */
404static void bad_rw_intr(void)
405{
406 struct request *req = CURRENT;
407 if (req != NULL) {
408 struct hd_i_struct *disk = req->rq_disk->private_data;
409 if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
410 end_request(req, 0);
411 disk->special_op = disk->recalibrate = 1;
412 } else if (req->errors % RESET_FREQ == 0)
413 reset = 1;
414 else if ((hd_error & TRK0_ERR) || req->errors % RECAL_FREQ == 0)
415 disk->special_op = disk->recalibrate = 1;
416 /* Otherwise just retry */
417 }
418}
419
420static inline int wait_DRQ(void)
421{
422 int retries;
423 int stat;
424
425 for (retries = 0; retries < 100000; retries++) {
426 stat = inb_p(HD_STATUS);
427 if (stat & DRQ_STAT)
428 return 0;
429 }
430 dump_status("wait_DRQ", stat);
431 return -1;
432}
433
434static void read_intr(void)
435{
436 struct request *req;
437 int i, retries = 100000;
438
439 do {
440 i = (unsigned) inb_p(HD_STATUS);
441 if (i & BUSY_STAT)
442 continue;
443 if (!OK_STATUS(i))
444 break;
445 if (i & DRQ_STAT)
446 goto ok_to_read;
447 } while (--retries > 0);
448 dump_status("read_intr", i);
449 bad_rw_intr();
450 hd_request();
451 return;
452ok_to_read:
453 req = CURRENT;
454 insw(HD_DATA, req->buffer, 256);
455 req->sector++;
456 req->buffer += 512;
457 req->errors = 0;
458 i = --req->nr_sectors;
459 --req->current_nr_sectors;
460#ifdef DEBUG
461 printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
462 req->rq_disk->disk_name, req->sector, req->nr_sectors,
463 req->buffer+512);
464#endif
465 if (req->current_nr_sectors <= 0)
466 end_request(req, 1);
467 if (i > 0) {
468 SET_HANDLER(&read_intr);
469 return;
470 }
471 (void) inb_p(HD_STATUS);
472#if (HD_DELAY > 0)
473 last_req = read_timer();
474#endif
475 if (elv_next_request(QUEUE))
476 hd_request();
477 return;
478}
479
480static void write_intr(void)
481{
482 struct request *req = CURRENT;
483 int i;
484 int retries = 100000;
485
486 do {
487 i = (unsigned) inb_p(HD_STATUS);
488 if (i & BUSY_STAT)
489 continue;
490 if (!OK_STATUS(i))
491 break;
492 if ((req->nr_sectors <= 1) || (i & DRQ_STAT))
493 goto ok_to_write;
494 } while (--retries > 0);
495 dump_status("write_intr", i);
496 bad_rw_intr();
497 hd_request();
498 return;
499ok_to_write:
500 req->sector++;
501 i = --req->nr_sectors;
502 --req->current_nr_sectors;
503 req->buffer += 512;
504 if (!i || (req->bio && req->current_nr_sectors <= 0))
505 end_request(req, 1);
506 if (i > 0) {
507 SET_HANDLER(&write_intr);
508 outsw(HD_DATA, req->buffer, 256);
509 local_irq_enable();
510 } else {
511#if (HD_DELAY > 0)
512 last_req = read_timer();
513#endif
514 hd_request();
515 }
516 return;
517}
518
519static void recal_intr(void)
520{
521 check_status();
522#if (HD_DELAY > 0)
523 last_req = read_timer();
524#endif
525 hd_request();
526}
527
528/*
529 * This is another of the error-routines I don't know what to do with. The
530 * best idea seems to just set reset, and start all over again.
531 */
532static void hd_times_out(unsigned long dummy)
533{
534 char *name;
535
536 do_hd = NULL;
537
538 if (!CURRENT)
539 return;
540
541 disable_irq(HD_IRQ);
542 local_irq_enable();
543 reset = 1;
544 name = CURRENT->rq_disk->disk_name;
545 printk("%s: timeout\n", name);
546 if (++CURRENT->errors >= MAX_ERRORS) {
547#ifdef DEBUG
548 printk("%s: too many errors\n", name);
549#endif
550 end_request(CURRENT, 0);
551 }
552 local_irq_disable();
553 hd_request();
554 enable_irq(HD_IRQ);
555}
556
557static int do_special_op(struct hd_i_struct *disk, struct request *req)
558{
559 if (disk->recalibrate) {
560 disk->recalibrate = 0;
561 hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr);
562 return reset;
563 }
564 if (disk->head > 16) {
565 printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
566 end_request(req, 0);
567 }
568 disk->special_op = 0;
569 return 1;
570}
571
572/*
573 * The driver enables interrupts as much as possible. In order to do this,
574 * (a) the device-interrupt is disabled before entering hd_request(),
575 * and (b) the timeout-interrupt is disabled before the sti().
576 *
577 * Interrupts are still masked (by default) whenever we are exchanging
578 * data/cmds with a drive, because some drives seem to have very poor
579 * tolerance for latency during I/O. The IDE driver has support to unmask
580 * interrupts for non-broken hardware, so use that driver if required.
581 */
582static void hd_request(void)
583{
584 unsigned int block, nsect, sec, track, head, cyl;
585 struct hd_i_struct *disk;
586 struct request *req;
587
588 if (do_hd)
589 return;
590repeat:
591 del_timer(&device_timer);
592 local_irq_enable();
593
594 req = CURRENT;
595 if (!req) {
596 do_hd = NULL;
597 return;
598 }
599
600 if (reset) {
601 local_irq_disable();
602 reset_hd();
603 return;
604 }
605 disk = req->rq_disk->private_data;
606 block = req->sector;
607 nsect = req->nr_sectors;
608 if (block >= get_capacity(req->rq_disk) ||
609 ((block+nsect) > get_capacity(req->rq_disk))) {
610 printk("%s: bad access: block=%d, count=%d\n",
611 req->rq_disk->disk_name, block, nsect);
612 end_request(req, 0);
613 goto repeat;
614 }
615
616 if (disk->special_op) {
617 if (do_special_op(disk, req))
618 goto repeat;
619 return;
620 }
621 sec = block % disk->sect + 1;
622 track = block / disk->sect;
623 head = track % disk->head;
624 cyl = track / disk->head;
625#ifdef DEBUG
626 printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
627 req->rq_disk->disk_name,
628 req_data_dir(req) == READ ? "read" : "writ",
629 cyl, head, sec, nsect, req->buffer);
630#endif
631 if (blk_fs_request(req)) {
632 switch (rq_data_dir(req)) {
633 case READ:
634 hd_out(disk, nsect, sec, head, cyl, WIN_READ,
635 &read_intr);
636 if (reset)
637 goto repeat;
638 break;
639 case WRITE:
640 hd_out(disk, nsect, sec, head, cyl, WIN_WRITE,
641 &write_intr);
642 if (reset)
643 goto repeat;
644 if (wait_DRQ()) {
645 bad_rw_intr();
646 goto repeat;
647 }
648 outsw(HD_DATA, req->buffer, 256);
649 break;
650 default:
651 printk("unknown hd-command\n");
652 end_request(req, 0);
653 break;
654 }
655 }
656}
657
658static void do_hd_request(struct request_queue *q)
659{
660 disable_irq(HD_IRQ);
661 hd_request();
662 enable_irq(HD_IRQ);
663}
664
665static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
666{
667 struct hd_i_struct *disk = bdev->bd_disk->private_data;
668
669 geo->heads = disk->head;
670 geo->sectors = disk->sect;
671 geo->cylinders = disk->cyl;
672 return 0;
673}
674
675/*
676 * Releasing a block device means we sync() it, so that it can safely
677 * be forgotten about...
678 */
679
680static irqreturn_t hd_interrupt(int irq, void *dev_id)
681{
682 void (*handler)(void) = do_hd;
683
684 do_hd = NULL;
685 del_timer(&device_timer);
686 if (!handler)
687 handler = unexpected_hd_interrupt;
688 handler();
689 local_irq_enable();
690 return IRQ_HANDLED;
691}
692
693static struct block_device_operations hd_fops = {
694 .getgeo = hd_getgeo,
695};
696
697/*
698 * This is the hard disk IRQ description. The IRQF_DISABLED in sa_flags
699 * means we run the IRQ-handler with interrupts disabled: this is bad for
700 * interrupt latency, but anything else has led to problems on some
701 * machines.
702 *
703 * We enable interrupts in some of the routines after making sure it's
704 * safe.
705 */
706
707static int __init hd_init(void)
708{
709 int drive;
710
711 if (register_blkdev(MAJOR_NR, "hd"))
712 return -1;
713
714 hd_queue = blk_init_queue(do_hd_request, &hd_lock);
715 if (!hd_queue) {
716 unregister_blkdev(MAJOR_NR, "hd");
717 return -ENOMEM;
718 }
719
720 blk_queue_max_sectors(hd_queue, 255);
721 init_timer(&device_timer);
722 device_timer.function = hd_times_out;
723 blk_queue_hardsect_size(hd_queue, 512);
724
725 if (!NR_HD) {
726 /*
727 * We don't know anything about the drive. This means
728 * that you *MUST* specify the drive parameters to the
729 * kernel yourself.
730 *
731 * If we were on an i386, we used to read this info from
732 * the BIOS or CMOS. This doesn't work all that well,
733 * since this assumes that this is a primary or secondary
734 * drive, and if we're using this legacy driver, it's
735 * probably an auxilliary controller added to recover
736 * legacy data off an ST-506 drive. Either way, it's
737 * definitely safest to have the user explicitly specify
738 * the information.
739 */
740 printk("hd: no drives specified - use hd=cyl,head,sectors"
741 " on kernel command line\n");
742 goto out;
743 }
744
745 for (drive = 0 ; drive < NR_HD ; drive++) {
746 struct gendisk *disk = alloc_disk(64);
747 struct hd_i_struct *p = &hd_info[drive];
748 if (!disk)
749 goto Enomem;
750 disk->major = MAJOR_NR;
751 disk->first_minor = drive << 6;
752 disk->fops = &hd_fops;
753 sprintf(disk->disk_name, "hd%c", 'a'+drive);
754 disk->private_data = p;
755 set_capacity(disk, p->head * p->sect * p->cyl);
756 disk->queue = hd_queue;
757 p->unit = drive;
758 hd_gendisk[drive] = disk;
759 printk("%s: %luMB, CHS=%d/%d/%d\n",
760 disk->disk_name, (unsigned long)get_capacity(disk)/2048,
761 p->cyl, p->head, p->sect);
762 }
763
764 if (request_irq(HD_IRQ, hd_interrupt, IRQF_DISABLED, "hd", NULL)) {
765 printk("hd: unable to get IRQ%d for the hard disk driver\n",
766 HD_IRQ);
767 goto out1;
768 }
769 if (!request_region(HD_DATA, 8, "hd")) {
770 printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
771 goto out2;
772 }
773 if (!request_region(HD_CMD, 1, "hd(cmd)")) {
774 printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
775 goto out3;
776 }
777
778 /* Let them fly */
779 for (drive = 0; drive < NR_HD; drive++)
780 add_disk(hd_gendisk[drive]);
781
782 return 0;
783
784out3:
785 release_region(HD_DATA, 8);
786out2:
787 free_irq(HD_IRQ, NULL);
788out1:
789 for (drive = 0; drive < NR_HD; drive++)
790 put_disk(hd_gendisk[drive]);
791 NR_HD = 0;
792out:
793 del_timer(&device_timer);
794 unregister_blkdev(MAJOR_NR, "hd");
795 blk_cleanup_queue(hd_queue);
796 return -1;
797Enomem:
798 while (drive--)
799 put_disk(hd_gendisk[drive]);
800 goto out;
801}
802
803static int __init parse_hd_setup(char *line)
804{
805 int ints[6];
806
807 (void) get_options(line, ARRAY_SIZE(ints), ints);
808 hd_setup(NULL, ints);
809
810 return 1;
811}
812__setup("hd=", parse_hd_setup);
813
814late_initcall(hd_init);