* add p cc
[mascara-docs.git] / i386 / linux / linux-0.99 / drivers / block / hd.c
blobc26348f0e37b2d6c3c421b06f8067ae921c2cd85
1 /*
2 * linux/kernel/hd.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
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.
13 * modified by Drew Eckhardt to check nr of hd's from the CMOS.
15 * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
16 * in the early extended-partition checks and added DM partitions
20 #include <linux/errno.h>
21 #include <linux/signal.h>
22 #include <linux/sched.h>
23 #include <linux/timer.h>
24 #include <linux/fs.h>
25 #include <linux/kernel.h>
26 #include <linux/hdreg.h>
27 #include <linux/genhd.h>
28 #include <linux/config.h>
30 #define REALLY_SLOW_IO
31 #include <asm/system.h>
32 #include <asm/io.h>
33 #include <asm/segment.h>
35 #define MAJOR_NR HD_MAJOR
36 #include "blk.h"
38 #define HD_IRQ 14
40 static int revalidate_hddisk(int, int);
42 static inline unsigned char CMOS_READ(unsigned char addr)
44 outb_p(addr,0x70);
45 return inb_p(0x71);
48 #define HD_DELAY 0
50 #define MAX_ERRORS 16 /* Max read/write errors/sector */
51 #define RESET_FREQ 8 /* Reset controller every 8th retry */
52 #define RECAL_FREQ 4 /* Recalibrate every 4th retry */
53 #define MAX_HD 2
55 static void recal_intr(void);
56 static void bad_rw_intr(void);
58 static char recalibrate[ MAX_HD ] = { 0, };
59 static int access_count[MAX_HD] = {0, };
60 static char busy[MAX_HD] = {0, };
61 static struct wait_queue * busy_wait = NULL;
63 static int reset = 0;
64 static int hd_error = 0;
66 #if (HD_DELAY > 0)
67 unsigned long last_req, read_timer();
68 #endif
71 * This struct defines the HD's and their types.
73 struct hd_i_struct {
74 unsigned int head,sect,cyl,wpcom,lzone,ctl;
76 #ifdef HD_TYPE
77 struct hd_i_struct hd_info[] = { HD_TYPE };
78 static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
79 #else
80 struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
81 static int NR_HD = 0;
82 #endif
84 static struct hd_struct hd[MAX_HD<<6]={{0,0},};
85 static int hd_sizes[MAX_HD<<6] = {0, };
86 static int hd_blocksizes[MAX_HD<<6] = {0, };
88 #if (HD_DELAY > 0)
89 unsigned long read_timer(void)
91 unsigned long t;
92 int i;
94 cli();
95 t = jiffies * 11932;
96 outb_p(0, 0x43);
97 i = inb_p(0x40);
98 i |= inb(0x40) << 8;
99 sti();
100 return(t - i);
102 #endif
104 void hd_setup(char *str, int *ints)
106 int hdind = 0;
108 if (ints[0] != 3)
109 return;
110 if (hd_info[0].head != 0)
111 hdind=1;
112 hd_info[hdind].head = ints[2];
113 hd_info[hdind].sect = ints[3];
114 hd_info[hdind].cyl = ints[1];
115 hd_info[hdind].wpcom = 0;
116 hd_info[hdind].lzone = ints[1];
117 hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
118 NR_HD = hdind+1;
121 static int win_result(void)
123 int i=inb_p(HD_STATUS);
125 if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
126 == (READY_STAT | SEEK_STAT)) {
127 hd_error = 0;
128 return 0; /* ok */
130 printk("HD: win_result: status = 0x%02x\n",i);
131 if (i&1) {
132 hd_error = inb(HD_ERROR);
133 printk("HD: win_result: error = 0x%02x\n",hd_error);
135 return 1;
138 static int controller_busy(void);
139 static int status_ok(void);
141 static int controller_ready(unsigned int drive, unsigned int head)
143 int retry = 100;
145 do {
146 if (controller_busy() & BUSY_STAT)
147 return 0;
148 outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
149 if (status_ok())
150 return 1;
151 } while (--retry);
152 return 0;
155 static int status_ok(void)
157 unsigned char status = inb_p(HD_STATUS);
159 if (status & BUSY_STAT)
160 return 1;
161 if (status & WRERR_STAT)
162 return 0;
163 if (!(status & READY_STAT))
164 return 0;
165 if (!(status & SEEK_STAT))
166 return 0;
167 return 1;
170 static int controller_busy(void)
172 int retries = 100000;
173 unsigned char status;
175 do {
176 status = inb_p(HD_STATUS);
177 } while ((status & BUSY_STAT) && --retries);
178 return status;
181 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
182 unsigned int head,unsigned int cyl,unsigned int cmd,
183 void (*intr_addr)(void))
185 unsigned short port;
187 if (drive>1 || head>15)
188 panic("Trying to write bad sector");
189 #if (HD_DELAY > 0)
190 while (read_timer() - last_req < HD_DELAY)
191 /* nothing */;
192 #endif
193 if (reset)
194 return;
195 if (!controller_ready(drive, head)) {
196 reset = 1;
197 return;
199 SET_INTR(intr_addr);
200 outb_p(hd_info[drive].ctl,HD_CMD);
201 port=HD_DATA;
202 outb_p(hd_info[drive].wpcom>>2,++port);
203 outb_p(nsect,++port);
204 outb_p(sect,++port);
205 outb_p(cyl,++port);
206 outb_p(cyl>>8,++port);
207 outb_p(0xA0|(drive<<4)|head,++port);
208 outb_p(cmd,++port);
211 static int drive_busy(void)
213 unsigned int i;
214 unsigned char c;
216 for (i = 0; i < 500000 ; i++) {
217 c = inb_p(HD_STATUS);
218 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
219 if (c == (READY_STAT | SEEK_STAT))
220 return 0;
222 printk("HD controller times out, status = 0x%02x\n",c);
223 return 1;
226 static void reset_controller(void)
228 int i;
230 printk(KERN_DEBUG "HD-controller reset\n");
231 outb_p(4,HD_CMD);
232 for(i = 0; i < 1000; i++) nop();
233 outb(hd_info[0].ctl & 0x0f ,HD_CMD);
234 if (drive_busy())
235 printk("HD-controller still busy\n");
236 if ((hd_error = inb(HD_ERROR)) != 1)
237 printk("HD-controller reset failed: %02x\n",hd_error);
240 static void reset_hd(void)
242 static int i;
244 repeat:
245 if (reset) {
246 reset = 0;
247 i = -1;
248 reset_controller();
249 } else if (win_result()) {
250 bad_rw_intr();
251 if (reset)
252 goto repeat;
254 i++;
255 if (i < NR_HD) {
256 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
257 hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
258 if (reset)
259 goto repeat;
260 } else
261 do_hd_request();
265 * Ok, don't know what to do with the unexpected interrupts: on some machines
266 * doing a reset and a retry seems to result in an eternal loop. Right now I
267 * ignore it, and just set the timeout.
269 void unexpected_hd_interrupt(void)
271 sti();
272 printk(KERN_DEBUG "Unexpected HD interrupt\n");
273 SET_TIMER;
277 * bad_rw_intr() now tries to be a bit smarter and does things
278 * according to the error returned by the controller.
279 * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
281 static void bad_rw_intr(void)
283 int dev;
285 if (!CURRENT)
286 return;
287 dev = MINOR(CURRENT->dev) >> 6;
288 if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
289 end_request(0);
290 recalibrate[dev] = 1;
291 } else if (CURRENT->errors % RESET_FREQ == 0)
292 reset = 1;
293 else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
294 recalibrate[dev] = 1;
295 /* Otherwise just retry */
298 static inline int wait_DRQ(void)
300 int retries = 100000;
302 while (--retries > 0)
303 if (inb_p(HD_STATUS) & DRQ_STAT)
304 return 0;
305 return -1;
308 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
309 #define STAT_OK (READY_STAT | SEEK_STAT)
311 static void read_intr(void)
313 int i;
314 int retries = 100000;
316 do {
317 i = (unsigned) inb_p(HD_STATUS);
318 if (i & BUSY_STAT)
319 continue;
320 if ((i & STAT_MASK) != STAT_OK)
321 break;
322 if (i & DRQ_STAT)
323 goto ok_to_read;
324 } while (--retries > 0);
325 sti();
326 printk("HD: read_intr: status = 0x%02x\n",i);
327 if (i & ERR_STAT) {
328 hd_error = (unsigned) inb(HD_ERROR);
329 printk("HD: read_intr: error = 0x%02x\n",hd_error);
331 bad_rw_intr();
332 cli();
333 do_hd_request();
334 return;
335 ok_to_read:
336 insw(HD_DATA,CURRENT->buffer,256);
337 CURRENT->errors = 0;
338 CURRENT->buffer += 512;
339 CURRENT->sector++;
340 i = --CURRENT->nr_sectors;
341 --CURRENT->current_nr_sectors;
342 #ifdef DEBUG
343 printk("hd%d : sector = %d, %d remaining to buffer = %08x\n",
344 MINOR(CURRENT->dev), CURRENT->sector, i, CURRENT->
345 buffer);
346 #endif
347 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
348 end_request(1);
349 if (i > 0) {
350 SET_INTR(&read_intr);
351 sti();
352 return;
354 (void) inb_p(HD_STATUS);
355 #if (HD_DELAY > 0)
356 last_req = read_timer();
357 #endif
358 do_hd_request();
359 return;
362 static void write_intr(void)
364 int i;
365 int retries = 100000;
367 do {
368 i = (unsigned) inb_p(HD_STATUS);
369 if (i & BUSY_STAT)
370 continue;
371 if ((i & STAT_MASK) != STAT_OK)
372 break;
373 if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
374 goto ok_to_write;
375 } while (--retries > 0);
376 sti();
377 printk("HD: write_intr: status = 0x%02x\n",i);
378 if (i & ERR_STAT) {
379 hd_error = (unsigned) inb(HD_ERROR);
380 printk("HD: write_intr: error = 0x%02x\n",hd_error);
382 bad_rw_intr();
383 cli();
384 do_hd_request();
385 return;
386 ok_to_write:
387 CURRENT->sector++;
388 i = --CURRENT->nr_sectors;
389 --CURRENT->current_nr_sectors;
390 CURRENT->buffer += 512;
391 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
392 end_request(1);
393 if (i > 0) {
394 SET_INTR(&write_intr);
395 outsw(HD_DATA,CURRENT->buffer,256);
396 sti();
397 } else {
398 #if (HD_DELAY > 0)
399 last_req = read_timer();
400 #endif
401 do_hd_request();
403 return;
406 static void recal_intr(void)
408 if (win_result())
409 bad_rw_intr();
410 do_hd_request();
414 * This is another of the error-routines I don't know what to do with. The
415 * best idea seems to just set reset, and start all over again.
417 static void hd_times_out(void)
419 DEVICE_INTR = NULL;
420 sti();
421 reset = 1;
422 if (!CURRENT)
423 return;
424 printk(KERN_DEBUG "HD timeout\n");
425 cli();
426 if (++CURRENT->errors >= MAX_ERRORS) {
427 #ifdef DEBUG
428 printk("hd : too many errors.\n");
429 #endif
430 end_request(0);
433 do_hd_request();
437 * The driver has been modified to enable interrupts a bit more: in order to
438 * do this we first (a) disable the timeout-interrupt and (b) clear the
439 * device-interrupt. This way the interrupts won't mess with out code (the
440 * worst that can happen is that an unexpected HD-interrupt comes in and
441 * sets the "reset" variable and starts the timer)
443 static void do_hd_request(void)
445 unsigned int block,dev;
446 unsigned int sec,head,cyl,track;
447 unsigned int nsect;
449 if (CURRENT && CURRENT->dev < 0) return;
451 if (DEVICE_INTR)
452 return;
453 repeat:
454 timer_active &= ~(1<<HD_TIMER);
455 sti();
456 INIT_REQUEST;
457 dev = MINOR(CURRENT->dev);
458 block = CURRENT->sector;
459 nsect = CURRENT->nr_sectors;
460 if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
461 #ifdef DEBUG
462 printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
463 block, hd[dev].nr_sects);
464 #endif
465 end_request(0);
466 goto repeat;
468 block += hd[dev].start_sect;
469 dev >>= 6;
470 sec = block % hd_info[dev].sect + 1;
471 track = block / hd_info[dev].sect;
472 head = track % hd_info[dev].head;
473 cyl = track / hd_info[dev].head;
474 #ifdef DEBUG
475 printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
476 dev, cyl, head, sec, CURRENT->buffer);
477 #endif
478 cli();
479 if (reset) {
480 int i;
482 for (i=0; i < NR_HD; i++)
483 recalibrate[i] = 1;
484 reset_hd();
485 sti();
486 return;
488 if (recalibrate[dev]) {
489 recalibrate[dev] = 0;
490 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
491 if (reset)
492 goto repeat;
493 sti();
494 return;
496 if (CURRENT->cmd == WRITE) {
497 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
498 if (reset)
499 goto repeat;
500 if (wait_DRQ()) {
501 printk("HD: do_hd_request: no DRQ\n");
502 bad_rw_intr();
503 goto repeat;
505 outsw(HD_DATA,CURRENT->buffer,256);
506 sti();
507 return;
509 if (CURRENT->cmd == READ) {
510 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
511 if (reset)
512 goto repeat;
513 sti();
514 return;
516 panic("unknown hd-command");
519 static int hd_ioctl(struct inode * inode, struct file * file,
520 unsigned int cmd, unsigned long arg)
522 struct hd_geometry *loc = (struct hd_geometry *) arg;
523 int dev, err;
525 if (!inode)
526 return -EINVAL;
527 dev = MINOR(inode->i_rdev) >> 6;
528 if (dev >= NR_HD)
529 return -EINVAL;
530 switch (cmd) {
531 case HDIO_GETGEO:
532 if (!loc) return -EINVAL;
533 err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
534 if (err)
535 return err;
536 put_fs_byte(hd_info[dev].head,
537 (char *) &loc->heads);
538 put_fs_byte(hd_info[dev].sect,
539 (char *) &loc->sectors);
540 put_fs_word(hd_info[dev].cyl,
541 (short *) &loc->cylinders);
542 put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
543 (long *) &loc->start);
544 return 0;
545 case BLKGETSIZE: /* Return device size */
546 if (!arg) return -EINVAL;
547 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
548 if (err)
549 return err;
550 put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects,
551 (long *) arg);
552 return 0;
553 case BLKFLSBUF:
554 if(!suser()) return -EACCES;
555 if(!inode->i_rdev) return -EINVAL;
556 fsync_dev(inode->i_rdev);
557 invalidate_buffers(inode->i_rdev);
558 return 0;
560 case BLKRRPART: /* Re-read partition tables */
561 return revalidate_hddisk(inode->i_rdev, 1);
562 RO_IOCTLS(inode->i_rdev,arg);
563 default:
564 return -EINVAL;
568 static int hd_open(struct inode * inode, struct file * filp)
570 int target;
571 target = DEVICE_NR(MINOR(inode->i_rdev));
573 while (busy[target])
574 sleep_on(&busy_wait);
575 access_count[target]++;
576 return 0;
580 * Releasing a block device means we sync() it, so that it can safely
581 * be forgotten about...
583 static void hd_release(struct inode * inode, struct file * file)
585 int target;
586 sync_dev(inode->i_rdev);
588 target = DEVICE_NR(MINOR(inode->i_rdev));
589 access_count[target]--;
593 static void hd_geninit(void);
595 static struct gendisk hd_gendisk = {
596 MAJOR_NR, /* Major number */
597 "hd", /* Major name */
598 6, /* Bits to shift to get real from partition */
599 1 << 6, /* Number of partitions per real */
600 MAX_HD, /* maximum number of real */
601 hd_geninit, /* init function */
602 hd, /* hd struct */
603 hd_sizes, /* block sizes */
604 0, /* number */
605 (void *) hd_info, /* internal */
606 NULL /* next */
609 static void hd_interrupt(int unused)
611 void (*handler)(void) = DEVICE_INTR;
613 DEVICE_INTR = NULL;
614 timer_active &= ~(1<<HD_TIMER);
615 if (!handler)
616 handler = unexpected_hd_interrupt;
617 handler();
618 sti();
622 * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags
623 * means we run the IRQ-handler with interrupts disabled: this is bad for
624 * interrupt latency, but anything else has led to problems on some
625 * machines...
627 * We enable interrupts in some of the routines after making sure it's
628 * safe.
630 static struct sigaction hd_sigaction = {
631 hd_interrupt,
633 SA_INTERRUPT,
634 NULL
637 static void hd_geninit(void)
639 int drive, i;
640 extern struct drive_info drive_info;
641 unsigned char *BIOS = (unsigned char *) &drive_info;
642 int cmos_disks;
644 if (!NR_HD) {
645 for (drive=0 ; drive<2 ; drive++) {
646 hd_info[drive].cyl = *(unsigned short *) BIOS;
647 hd_info[drive].head = *(2+BIOS);
648 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
649 hd_info[drive].ctl = *(8+BIOS);
650 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
651 hd_info[drive].sect = *(14+BIOS);
652 BIOS += 16;
656 We querry CMOS about hard disks : it could be that
657 we have a SCSI/ESDI/etc controller that is BIOS
658 compatable with ST-506, and thus showing up in our
659 BIOS table, but not register compatable, and therefore
660 not present in CMOS.
662 Furthurmore, we will assume that our ST-506 drives
663 <if any> are the primary drives in the system, and
664 the ones reflected as drive 1 or 2.
666 The first drive is stored in the high nibble of CMOS
667 byte 0x12, the second in the low nibble. This will be
668 either a 4 bit drive type or 0xf indicating use byte 0x19
669 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
671 Needless to say, a non-zero value means we have
672 an AT controller hard disk for that drive.
677 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
678 if (cmos_disks & 0x0f)
679 NR_HD = 2;
680 else
681 NR_HD = 1;
683 i = NR_HD;
684 while (i-- > 0) {
685 hd[i<<6].nr_sects = 0;
686 if (hd_info[i].head > 16) {
687 printk("hd.c: ST-506 interface disk with more than 16 heads detected,\n");
688 printk(" probably due to non-standard sector translation. Giving up.\n");
689 printk(" (disk %d: cyl=%d, sect=%d, head=%d)\n", i,
690 hd_info[i].cyl,
691 hd_info[i].sect,
692 hd_info[i].head);
693 if (i+1 == NR_HD)
694 NR_HD--;
695 continue;
697 hd[i<<6].nr_sects = hd_info[i].head*
698 hd_info[i].sect*hd_info[i].cyl;
700 if (NR_HD) {
701 if (irqaction(HD_IRQ,&hd_sigaction)) {
702 printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
703 NR_HD = 0;
706 hd_gendisk.nr_real = NR_HD;
708 for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
709 blksize_size[MAJOR_NR] = hd_blocksizes;
712 static struct file_operations hd_fops = {
713 NULL, /* lseek - default */
714 block_read, /* read - general block-dev read */
715 block_write, /* write - general block-dev write */
716 NULL, /* readdir - bad */
717 NULL, /* select */
718 hd_ioctl, /* ioctl */
719 NULL, /* mmap */
720 hd_open, /* open */
721 hd_release, /* release */
722 block_fsync /* fsync */
725 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
727 if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
728 printk("Unable to get major %d for harddisk\n",MAJOR_NR);
729 return mem_start;
731 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
732 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
733 hd_gendisk.next = gendisk_head;
734 gendisk_head = &hd_gendisk;
735 timer_table[HD_TIMER].fn = hd_times_out;
736 return mem_start;
739 #define DEVICE_BUSY busy[target]
740 #define USAGE access_count[target]
741 #define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
742 /* We assume that the the bios parameters do not change, so the disk capacity
743 will not change */
744 #undef MAYBE_REINIT
745 #define GENDISK_STRUCT hd_gendisk
748 * This routine is called to flush all partitions and partition tables
749 * for a changed scsi disk, and then re-read the new partition table.
750 * If we are revalidating a disk because of a media change, then we
751 * enter with usage == 0. If we are using an ioctl, we automatically have
752 * usage == 1 (we need an open channel to use an ioctl :-), so this
753 * is our limit.
755 static int revalidate_hddisk(int dev, int maxusage)
757 int target, major;
758 struct gendisk * gdev;
759 int max_p;
760 int start;
761 int i;
763 target = DEVICE_NR(MINOR(dev));
764 gdev = &GENDISK_STRUCT;
766 cli();
767 if (DEVICE_BUSY || USAGE > maxusage) {
768 sti();
769 return -EBUSY;
771 DEVICE_BUSY = 1;
772 sti();
774 max_p = gdev->max_p;
775 start = target << gdev->minor_shift;
776 major = MAJOR_NR << 8;
778 for (i=max_p - 1; i >=0 ; i--) {
779 sync_dev(major | start | i);
780 invalidate_inodes(major | start | i);
781 invalidate_buffers(major | start | i);
782 gdev->part[start+i].start_sect = 0;
783 gdev->part[start+i].nr_sects = 0;
786 #ifdef MAYBE_REINIT
787 MAYBE_REINIT;
788 #endif
790 gdev->part[start].nr_sects = CAPACITY;
791 resetup_one_dev(gdev, target);
793 DEVICE_BUSY = 0;
794 wake_up(&busy_wait);
795 return 0;