This source file includes following definitions.
- CMOS_READ
- read_timer
- hd_setup
- win_result
- controller_ready
- status_ok
- controller_busy
- hd_out
- drive_busy
- reset_controller
- reset_hd
- unexpected_hd_interrupt
- bad_rw_intr
- wait_DRQ
- read_intr
- write_intr
- recal_intr
- hd_times_out
- do_hd_request
- hd_ioctl
- hd_open
- hd_release
- hd_interrupt
- hd_geninit
- hd_init
- revalidate_hddisk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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>
29
30 #define REALLY_SLOW_IO
31 #include <asm/system.h>
32 #include <asm/io.h>
33 #include <asm/segment.h>
34
35 #define MAJOR_NR HD_MAJOR
36 #include "blk.h"
37
38 #define HD_IRQ 14
39
40 static int revalidate_hddisk(int, int);
41
42 static inline unsigned char CMOS_READ(unsigned char addr)
43 {
44 outb_p(addr,0x70);
45 return inb_p(0x71);
46 }
47
48 #define HD_DELAY 0
49
50 #define MAX_ERRORS 16
51 #define RESET_FREQ 8
52 #define RECAL_FREQ 4
53 #define MAX_HD 2
54
55 static void recal_intr(void);
56 static void bad_rw_intr(void);
57
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;
62
63 static int reset = 0;
64 static int hd_error = 0;
65
66 #if (HD_DELAY > 0)
67 unsigned long last_req, read_timer();
68 #endif
69
70
71
72
73 struct hd_i_struct {
74 unsigned int head,sect,cyl,wpcom,lzone,ctl;
75 };
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
83
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, };
87
88 #if (HD_DELAY > 0)
89 unsigned long read_timer(void)
90 {
91 unsigned long t;
92 int i;
93
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);
101 }
102 #endif
103
104 void hd_setup(char *str, int *ints)
105 {
106 int hdind = 0;
107
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;
119 }
120
121 static int win_result(void)
122 {
123 int i=inb_p(HD_STATUS);
124
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;
129 }
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);
134 }
135 return 1;
136 }
137
138 static int controller_busy(void);
139 static int status_ok(void);
140
141 static int controller_ready(unsigned int drive, unsigned int head)
142 {
143 int retry = 100;
144
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;
153 }
154
155 static int status_ok(void)
156 {
157 unsigned char status = inb_p(HD_STATUS);
158
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;
168 }
169
170 static int controller_busy(void)
171 {
172 int retries = 100000;
173 unsigned char status;
174
175 do {
176 status = inb_p(HD_STATUS);
177 } while ((status & BUSY_STAT) && --retries);
178 return status;
179 }
180
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))
184 {
185 unsigned short port;
186
187 if (drive>1 || head>15) {
188 printk("bad drive mapping, trying to access drive=%d, cyl=%d, head=%d, sect=%d\n",
189 drive, cyl, head, sect);
190 panic("harddisk driver problem");
191 }
192 #if (HD_DELAY > 0)
193 while (read_timer() - last_req < HD_DELAY)
194 ;
195 #endif
196 if (reset)
197 return;
198 if (!controller_ready(drive, head)) {
199 reset = 1;
200 return;
201 }
202 SET_INTR(intr_addr);
203 outb_p(hd_info[drive].ctl,HD_CMD);
204 port=HD_DATA;
205 outb_p(hd_info[drive].wpcom>>2,++port);
206 outb_p(nsect,++port);
207 outb_p(sect,++port);
208 outb_p(cyl,++port);
209 outb_p(cyl>>8,++port);
210 outb_p(0xA0|(drive<<4)|head,++port);
211 outb_p(cmd,++port);
212 }
213
214 static int drive_busy(void)
215 {
216 unsigned int i;
217 unsigned char c;
218
219 for (i = 0; i < 500000 ; i++) {
220 c = inb_p(HD_STATUS);
221 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
222 if (c == (READY_STAT | SEEK_STAT))
223 return 0;
224 }
225 printk("HD controller times out, status = 0x%02x\n",c);
226 return 1;
227 }
228
229 static void reset_controller(void)
230 {
231 int i;
232
233 printk(KERN_DEBUG "HD-controller reset\n");
234 outb_p(4,HD_CMD);
235 for(i = 0; i < 1000; i++) nop();
236 outb(hd_info[0].ctl & 0x0f ,HD_CMD);
237 if (drive_busy())
238 printk("HD-controller still busy\n");
239 if ((hd_error = inb(HD_ERROR)) != 1)
240 printk("HD-controller reset failed: %02x\n",hd_error);
241 }
242
243 static void reset_hd(void)
244 {
245 static int i;
246
247 repeat:
248 if (reset) {
249 reset = 0;
250 i = -1;
251 reset_controller();
252 } else if (win_result()) {
253 bad_rw_intr();
254 if (reset)
255 goto repeat;
256 }
257 i++;
258 if (i < NR_HD) {
259 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
260 hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
261 if (reset)
262 goto repeat;
263 } else
264 do_hd_request();
265 }
266
267
268
269
270
271
272 void unexpected_hd_interrupt(void)
273 {
274 sti();
275 printk(KERN_DEBUG "Unexpected HD interrupt\n");
276 SET_TIMER;
277 }
278
279
280
281
282
283
284 static void bad_rw_intr(void)
285 {
286 int dev;
287
288 if (!CURRENT)
289 return;
290 dev = MINOR(CURRENT->dev) >> 6;
291 if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
292 end_request(0);
293 recalibrate[dev] = 1;
294 } else if (CURRENT->errors % RESET_FREQ == 0)
295 reset = 1;
296 else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
297 recalibrate[dev] = 1;
298
299 }
300
301 static inline int wait_DRQ(void)
302 {
303 int retries = 100000;
304
305 while (--retries > 0)
306 if (inb_p(HD_STATUS) & DRQ_STAT)
307 return 0;
308 return -1;
309 }
310
311 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
312 #define STAT_OK (READY_STAT | SEEK_STAT)
313
314 static void read_intr(void)
315 {
316 int i;
317 int retries = 100000;
318
319 do {
320 i = (unsigned) inb_p(HD_STATUS);
321 if (i & BUSY_STAT)
322 continue;
323 if ((i & STAT_MASK) != STAT_OK)
324 break;
325 if (i & DRQ_STAT)
326 goto ok_to_read;
327 } while (--retries > 0);
328 sti();
329 printk("HD: read_intr: status = 0x%02x\n",i);
330 if (i & ERR_STAT) {
331 hd_error = (unsigned) inb(HD_ERROR);
332 printk("HD: read_intr: error = 0x%02x\n",hd_error);
333 }
334 bad_rw_intr();
335 cli();
336 do_hd_request();
337 return;
338 ok_to_read:
339 insw(HD_DATA,CURRENT->buffer,256);
340 CURRENT->errors = 0;
341 CURRENT->buffer += 512;
342 CURRENT->sector++;
343 i = --CURRENT->nr_sectors;
344 --CURRENT->current_nr_sectors;
345 #ifdef DEBUG
346 printk("hd%d : sector = %d, %d remaining to buffer = %08x\n",
347 MINOR(CURRENT->dev), CURRENT->sector, i, CURRENT->
348 buffer);
349 #endif
350 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
351 end_request(1);
352 if (i > 0) {
353 SET_INTR(&read_intr);
354 sti();
355 return;
356 }
357 (void) inb_p(HD_STATUS);
358 #if (HD_DELAY > 0)
359 last_req = read_timer();
360 #endif
361 do_hd_request();
362 return;
363 }
364
365 static void write_intr(void)
366 {
367 int i;
368 int retries = 100000;
369
370 do {
371 i = (unsigned) inb_p(HD_STATUS);
372 if (i & BUSY_STAT)
373 continue;
374 if ((i & STAT_MASK) != STAT_OK)
375 break;
376 if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
377 goto ok_to_write;
378 } while (--retries > 0);
379 sti();
380 printk("HD: write_intr: status = 0x%02x\n",i);
381 if (i & ERR_STAT) {
382 hd_error = (unsigned) inb(HD_ERROR);
383 printk("HD: write_intr: error = 0x%02x\n",hd_error);
384 }
385 bad_rw_intr();
386 cli();
387 do_hd_request();
388 return;
389 ok_to_write:
390 CURRENT->sector++;
391 i = --CURRENT->nr_sectors;
392 --CURRENT->current_nr_sectors;
393 CURRENT->buffer += 512;
394 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
395 end_request(1);
396 if (i > 0) {
397 SET_INTR(&write_intr);
398 outsw(HD_DATA,CURRENT->buffer,256);
399 sti();
400 } else {
401 #if (HD_DELAY > 0)
402 last_req = read_timer();
403 #endif
404 do_hd_request();
405 }
406 return;
407 }
408
409 static void recal_intr(void)
410 {
411 if (win_result())
412 bad_rw_intr();
413 do_hd_request();
414 }
415
416
417
418
419
420 static void hd_times_out(void)
421 {
422 DEVICE_INTR = NULL;
423 sti();
424 reset = 1;
425 if (!CURRENT)
426 return;
427 printk(KERN_DEBUG "HD timeout\n");
428 cli();
429 if (++CURRENT->errors >= MAX_ERRORS) {
430 #ifdef DEBUG
431 printk("hd : too many errors.\n");
432 #endif
433 end_request(0);
434 }
435
436 do_hd_request();
437 }
438
439
440
441
442
443
444
445
446 static void do_hd_request(void)
447 {
448 unsigned int block,dev;
449 unsigned int sec,head,cyl,track;
450 unsigned int nsect;
451
452 if (CURRENT && CURRENT->dev < 0) return;
453
454 if (DEVICE_INTR)
455 return;
456 repeat:
457 timer_active &= ~(1<<HD_TIMER);
458 sti();
459 INIT_REQUEST;
460 dev = MINOR(CURRENT->dev);
461 block = CURRENT->sector;
462 nsect = CURRENT->nr_sectors;
463 if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
464 #ifdef DEBUG
465 printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
466 block, hd[dev].nr_sects);
467 #endif
468 end_request(0);
469 goto repeat;
470 }
471 block += hd[dev].start_sect;
472 dev >>= 6;
473 sec = block % hd_info[dev].sect + 1;
474 track = block / hd_info[dev].sect;
475 head = track % hd_info[dev].head;
476 cyl = track / hd_info[dev].head;
477 #ifdef DEBUG
478 printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
479 dev, cyl, head, sec, CURRENT->buffer);
480 #endif
481 cli();
482 if (reset) {
483 int i;
484
485 for (i=0; i < NR_HD; i++)
486 recalibrate[i] = 1;
487 reset_hd();
488 sti();
489 return;
490 }
491 if (recalibrate[dev]) {
492 recalibrate[dev] = 0;
493 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
494 if (reset)
495 goto repeat;
496 sti();
497 return;
498 }
499 if (CURRENT->cmd == WRITE) {
500 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
501 if (reset)
502 goto repeat;
503 if (wait_DRQ()) {
504 printk("HD: do_hd_request: no DRQ\n");
505 bad_rw_intr();
506 goto repeat;
507 }
508 outsw(HD_DATA,CURRENT->buffer,256);
509 sti();
510 return;
511 }
512 if (CURRENT->cmd == READ) {
513 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
514 if (reset)
515 goto repeat;
516 sti();
517 return;
518 }
519 panic("unknown hd-command");
520 }
521
522 static int hd_ioctl(struct inode * inode, struct file * file,
523 unsigned int cmd, unsigned long arg)
524 {
525 struct hd_geometry *loc = (struct hd_geometry *) arg;
526 int dev, err;
527
528 if (!inode)
529 return -EINVAL;
530 dev = MINOR(inode->i_rdev) >> 6;
531 if (dev >= NR_HD)
532 return -EINVAL;
533 switch (cmd) {
534 case HDIO_GETGEO:
535 if (!loc) return -EINVAL;
536 err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
537 if (err)
538 return err;
539 put_fs_byte(hd_info[dev].head,
540 (char *) &loc->heads);
541 put_fs_byte(hd_info[dev].sect,
542 (char *) &loc->sectors);
543 put_fs_word(hd_info[dev].cyl,
544 (short *) &loc->cylinders);
545 put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
546 (long *) &loc->start);
547 return 0;
548 case BLKRASET:
549 if(!suser()) return -EACCES;
550 if(!inode->i_rdev) return -EINVAL;
551 if(arg > 0xff) return -EINVAL;
552 read_ahead[MAJOR(inode->i_rdev)] = arg;
553 return 0;
554 case BLKGETSIZE:
555 if (!arg) return -EINVAL;
556 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
557 if (err)
558 return err;
559 put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects,
560 (long *) arg);
561 return 0;
562 case BLKFLSBUF:
563 if(!suser()) return -EACCES;
564 if(!inode->i_rdev) return -EINVAL;
565 fsync_dev(inode->i_rdev);
566 invalidate_buffers(inode->i_rdev);
567 return 0;
568
569 case BLKRRPART:
570 return revalidate_hddisk(inode->i_rdev, 1);
571 RO_IOCTLS(inode->i_rdev,arg);
572 default:
573 return -EINVAL;
574 }
575 }
576
577 static int hd_open(struct inode * inode, struct file * filp)
578 {
579 int target;
580 target = DEVICE_NR(MINOR(inode->i_rdev));
581
582 while (busy[target])
583 sleep_on(&busy_wait);
584 access_count[target]++;
585 return 0;
586 }
587
588
589
590
591
592 static void hd_release(struct inode * inode, struct file * file)
593 {
594 int target;
595 sync_dev(inode->i_rdev);
596
597 target = DEVICE_NR(MINOR(inode->i_rdev));
598 access_count[target]--;
599
600 }
601
602 static void hd_geninit(void);
603
604 static struct gendisk hd_gendisk = {
605 MAJOR_NR,
606 "hd",
607 6,
608 1 << 6,
609 MAX_HD,
610 hd_geninit,
611 hd,
612 hd_sizes,
613 0,
614 (void *) hd_info,
615 NULL
616 };
617
618 static void hd_interrupt(int unused)
619 {
620 void (*handler)(void) = DEVICE_INTR;
621
622 DEVICE_INTR = NULL;
623 timer_active &= ~(1<<HD_TIMER);
624 if (!handler)
625 handler = unexpected_hd_interrupt;
626 handler();
627 sti();
628 }
629
630
631
632
633
634
635
636
637
638
639 static struct sigaction hd_sigaction = {
640 hd_interrupt,
641 0,
642 SA_INTERRUPT,
643 NULL
644 };
645
646 static void hd_geninit(void)
647 {
648 int drive, i;
649 extern struct drive_info drive_info;
650 unsigned char *BIOS = (unsigned char *) &drive_info;
651 int cmos_disks;
652
653 if (!NR_HD) {
654 for (drive=0 ; drive<2 ; drive++) {
655 hd_info[drive].cyl = *(unsigned short *) BIOS;
656 hd_info[drive].head = *(2+BIOS);
657 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
658 hd_info[drive].ctl = *(8+BIOS);
659 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
660 hd_info[drive].sect = *(14+BIOS);
661 #ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
662 if (hd_info[drive].cyl && NR_HD == drive)
663 NR_HD++;
664 #endif
665 BIOS += 16;
666 }
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
691 if (cmos_disks & 0x0f)
692 NR_HD = 2;
693 else
694 NR_HD = 1;
695 }
696 i = NR_HD;
697 while (i-- > 0) {
698 hd[i<<6].nr_sects = 0;
699 if (hd_info[i].head > 16) {
700 printk("hd.c: ST-506 interface disk with more than 16 heads detected,\n");
701 printk(" probably due to non-standard sector translation. Giving up.\n");
702 printk(" (disk %d: cyl=%d, sect=%d, head=%d)\n", i,
703 hd_info[i].cyl,
704 hd_info[i].sect,
705 hd_info[i].head);
706 if (i+1 == NR_HD)
707 NR_HD--;
708 continue;
709 }
710 hd[i<<6].nr_sects = hd_info[i].head*
711 hd_info[i].sect*hd_info[i].cyl;
712 }
713 if (NR_HD) {
714 if (irqaction(HD_IRQ,&hd_sigaction)) {
715 printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
716 NR_HD = 0;
717 }
718 }
719 hd_gendisk.nr_real = NR_HD;
720
721 for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
722 blksize_size[MAJOR_NR] = hd_blocksizes;
723 }
724
725 static struct file_operations hd_fops = {
726 NULL,
727 block_read,
728 block_write,
729 NULL,
730 NULL,
731 hd_ioctl,
732 NULL,
733 hd_open,
734 hd_release,
735 block_fsync
736 };
737
738 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
739 {
740 if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
741 printk("Unable to get major %d for harddisk\n",MAJOR_NR);
742 return mem_start;
743 }
744 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
745 read_ahead[MAJOR_NR] = 8;
746 hd_gendisk.next = gendisk_head;
747 gendisk_head = &hd_gendisk;
748 timer_table[HD_TIMER].fn = hd_times_out;
749 return mem_start;
750 }
751
752 #define DEVICE_BUSY busy[target]
753 #define USAGE access_count[target]
754 #define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
755
756
757 #undef MAYBE_REINIT
758 #define GENDISK_STRUCT hd_gendisk
759
760
761
762
763
764
765
766
767
768 static int revalidate_hddisk(int dev, int maxusage)
769 {
770 int target, major;
771 struct gendisk * gdev;
772 int max_p;
773 int start;
774 int i;
775
776 target = DEVICE_NR(MINOR(dev));
777 gdev = &GENDISK_STRUCT;
778
779 cli();
780 if (DEVICE_BUSY || USAGE > maxusage) {
781 sti();
782 return -EBUSY;
783 };
784 DEVICE_BUSY = 1;
785 sti();
786
787 max_p = gdev->max_p;
788 start = target << gdev->minor_shift;
789 major = MAJOR_NR << 8;
790
791 for (i=max_p - 1; i >=0 ; i--) {
792 sync_dev(major | start | i);
793 invalidate_inodes(major | start | i);
794 invalidate_buffers(major | start | i);
795 gdev->part[start+i].start_sect = 0;
796 gdev->part[start+i].nr_sects = 0;
797 };
798
799 #ifdef MAYBE_REINIT
800 MAYBE_REINIT;
801 #endif
802
803 gdev->part[start].nr_sects = CAPACITY;
804 resetup_one_dev(gdev, target);
805
806 DEVICE_BUSY = 0;
807 wake_up(&busy_wait);
808 return 0;
809 }
810