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 panic("Trying to write bad sector");
189 #if (HD_DELAY > 0)
190 while (read_timer() - last_req < HD_DELAY)
191 ;
192 #endif
193 if (reset)
194 return;
195 if (!controller_ready(drive, head)) {
196 reset = 1;
197 return;
198 }
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);
209 }
210
211 static int drive_busy(void)
212 {
213 unsigned int i;
214 unsigned char c;
215
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;
221 }
222 printk("HD controller times out, status = 0x%02x\n",c);
223 return 1;
224 }
225
226 static void reset_controller(void)
227 {
228 int i;
229
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);
238 }
239
240 static void reset_hd(void)
241 {
242 static int i;
243
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;
253 }
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();
262 }
263
264
265
266
267
268
269 void unexpected_hd_interrupt(void)
270 {
271 sti();
272 printk(KERN_DEBUG "Unexpected HD interrupt\n");
273 SET_TIMER;
274 }
275
276
277
278
279
280
281 static void bad_rw_intr(void)
282 {
283 int dev;
284
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
296 }
297
298 static inline int wait_DRQ(void)
299 {
300 int retries = 100000;
301
302 while (--retries > 0)
303 if (inb_p(HD_STATUS) & DRQ_STAT)
304 return 0;
305 return -1;
306 }
307
308 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
309 #define STAT_OK (READY_STAT | SEEK_STAT)
310
311 static void read_intr(void)
312 {
313 int i;
314 int retries = 100000;
315
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);
330 }
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;
353 }
354 (void) inb_p(HD_STATUS);
355 #if (HD_DELAY > 0)
356 last_req = read_timer();
357 #endif
358 do_hd_request();
359 return;
360 }
361
362 static void write_intr(void)
363 {
364 int i;
365 int retries = 100000;
366
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);
381 }
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();
402 }
403 return;
404 }
405
406 static void recal_intr(void)
407 {
408 if (win_result())
409 bad_rw_intr();
410 do_hd_request();
411 }
412
413
414
415
416
417 static void hd_times_out(void)
418 {
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);
431 }
432
433 do_hd_request();
434 }
435
436
437
438
439
440
441
442
443 static void do_hd_request(void)
444 {
445 unsigned int block,dev;
446 unsigned int sec,head,cyl,track;
447 unsigned int nsect;
448
449 if (CURRENT && CURRENT->dev < 0) return;
450
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;
467 }
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;
481
482 for (i=0; i < NR_HD; i++)
483 recalibrate[i] = 1;
484 reset_hd();
485 sti();
486 return;
487 }
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;
495 }
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;
504 }
505 outsw(HD_DATA,CURRENT->buffer,256);
506 sti();
507 return;
508 }
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;
515 }
516 panic("unknown hd-command");
517 }
518
519 static int hd_ioctl(struct inode * inode, struct file * file,
520 unsigned int cmd, unsigned long arg)
521 {
522 struct hd_geometry *loc = (struct hd_geometry *) arg;
523 int dev, err;
524
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 BLKRASET:
546 if(!suser()) return -EACCES;
547 if(!inode->i_rdev) return -EINVAL;
548 if(arg > 0xff) return -EINVAL;
549 read_ahead[MAJOR(inode->i_rdev)] = arg;
550 return 0;
551 case BLKGETSIZE:
552 if (!arg) return -EINVAL;
553 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
554 if (err)
555 return err;
556 put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects,
557 (long *) arg);
558 return 0;
559 case BLKFLSBUF:
560 if(!suser()) return -EACCES;
561 if(!inode->i_rdev) return -EINVAL;
562 fsync_dev(inode->i_rdev);
563 invalidate_buffers(inode->i_rdev);
564 return 0;
565
566 case BLKRRPART:
567 return revalidate_hddisk(inode->i_rdev, 1);
568 RO_IOCTLS(inode->i_rdev,arg);
569 default:
570 return -EINVAL;
571 }
572 }
573
574 static int hd_open(struct inode * inode, struct file * filp)
575 {
576 int target;
577 target = DEVICE_NR(MINOR(inode->i_rdev));
578
579 while (busy[target])
580 sleep_on(&busy_wait);
581 access_count[target]++;
582 return 0;
583 }
584
585
586
587
588
589 static void hd_release(struct inode * inode, struct file * file)
590 {
591 int target;
592 sync_dev(inode->i_rdev);
593
594 target = DEVICE_NR(MINOR(inode->i_rdev));
595 access_count[target]--;
596
597 }
598
599 static void hd_geninit(void);
600
601 static struct gendisk hd_gendisk = {
602 MAJOR_NR,
603 "hd",
604 6,
605 1 << 6,
606 MAX_HD,
607 hd_geninit,
608 hd,
609 hd_sizes,
610 0,
611 (void *) hd_info,
612 NULL
613 };
614
615 static void hd_interrupt(int unused)
616 {
617 void (*handler)(void) = DEVICE_INTR;
618
619 DEVICE_INTR = NULL;
620 timer_active &= ~(1<<HD_TIMER);
621 if (!handler)
622 handler = unexpected_hd_interrupt;
623 handler();
624 sti();
625 }
626
627
628
629
630
631
632
633
634
635
636 static struct sigaction hd_sigaction = {
637 hd_interrupt,
638 0,
639 SA_INTERRUPT,
640 NULL
641 };
642
643 static void hd_geninit(void)
644 {
645 int drive, i;
646 extern struct drive_info drive_info;
647 unsigned char *BIOS = (unsigned char *) &drive_info;
648 int cmos_disks;
649
650 if (!NR_HD) {
651 for (drive=0 ; drive<2 ; drive++) {
652 hd_info[drive].cyl = *(unsigned short *) BIOS;
653 hd_info[drive].head = *(2+BIOS);
654 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
655 hd_info[drive].ctl = *(8+BIOS);
656 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
657 hd_info[drive].sect = *(14+BIOS);
658 BIOS += 16;
659 }
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
684 if (cmos_disks & 0x0f)
685 NR_HD = 2;
686 else
687 NR_HD = 1;
688 }
689 i = NR_HD;
690 while (i-- > 0) {
691 hd[i<<6].nr_sects = 0;
692 if (hd_info[i].head > 16) {
693 printk("hd.c: ST-506 interface disk with more than 16 heads detected,\n");
694 printk(" probably due to non-standard sector translation. Giving up.\n");
695 printk(" (disk %d: cyl=%d, sect=%d, head=%d)\n", i,
696 hd_info[i].cyl,
697 hd_info[i].sect,
698 hd_info[i].head);
699 if (i+1 == NR_HD)
700 NR_HD--;
701 continue;
702 }
703 hd[i<<6].nr_sects = hd_info[i].head*
704 hd_info[i].sect*hd_info[i].cyl;
705 }
706 if (NR_HD) {
707 if (irqaction(HD_IRQ,&hd_sigaction)) {
708 printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
709 NR_HD = 0;
710 }
711 }
712 hd_gendisk.nr_real = NR_HD;
713
714 for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
715 blksize_size[MAJOR_NR] = hd_blocksizes;
716 }
717
718 static struct file_operations hd_fops = {
719 NULL,
720 block_read,
721 block_write,
722 NULL,
723 NULL,
724 hd_ioctl,
725 NULL,
726 hd_open,
727 hd_release,
728 block_fsync
729 };
730
731 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
732 {
733 if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
734 printk("Unable to get major %d for harddisk\n",MAJOR_NR);
735 return mem_start;
736 }
737 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
738 read_ahead[MAJOR_NR] = 8;
739 hd_gendisk.next = gendisk_head;
740 gendisk_head = &hd_gendisk;
741 timer_table[HD_TIMER].fn = hd_times_out;
742 return mem_start;
743 }
744
745 #define DEVICE_BUSY busy[target]
746 #define USAGE access_count[target]
747 #define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
748
749
750 #undef MAYBE_REINIT
751 #define GENDISK_STRUCT hd_gendisk
752
753
754
755
756
757
758
759
760
761 static int revalidate_hddisk(int dev, int maxusage)
762 {
763 int target, major;
764 struct gendisk * gdev;
765 int max_p;
766 int start;
767 int i;
768
769 target = DEVICE_NR(MINOR(dev));
770 gdev = &GENDISK_STRUCT;
771
772 cli();
773 if (DEVICE_BUSY || USAGE > maxusage) {
774 sti();
775 return -EBUSY;
776 };
777 DEVICE_BUSY = 1;
778 sti();
779
780 max_p = gdev->max_p;
781 start = target << gdev->minor_shift;
782 major = MAJOR_NR << 8;
783
784 for (i=max_p - 1; i >=0 ; i--) {
785 sync_dev(major | start | i);
786 invalidate_inodes(major | start | i);
787 invalidate_buffers(major | start | i);
788 gdev->part[start+i].start_sect = 0;
789 gdev->part[start+i].nr_sects = 0;
790 };
791
792 #ifdef MAYBE_REINIT
793 MAYBE_REINIT;
794 #endif
795
796 gdev->part[start].nr_sects = CAPACITY;
797 resetup_one_dev(gdev, target);
798
799 DEVICE_BUSY = 0;
800 wake_up(&busy_wait);
801 return 0;
802 }
803