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 #define port_read(port,buf,nr) \
89 __asm__("cld;rep;insw": :"d" (port),"D" (buf),"c" (nr):"cx","di")
90
91 #define port_write(port,buf,nr) \
92 __asm__("cld;rep;outsw": :"d" (port),"S" (buf),"c" (nr):"cx","si")
93
94 #if (HD_DELAY > 0)
95 unsigned long read_timer(void)
96 {
97 unsigned long t;
98 int i;
99
100 cli();
101 t = jiffies * 11932;
102 outb_p(0, 0x43);
103 i = inb_p(0x40);
104 i |= inb(0x40) << 8;
105 sti();
106 return(t - i);
107 }
108 #endif
109
110 void hd_setup(char *str, int *ints)
111 {
112 int hdind = 0;
113
114 if (ints[0] != 3)
115 return;
116 if (hd_info[0].head != 0)
117 hdind=1;
118 hd_info[hdind].head = ints[2];
119 hd_info[hdind].sect = ints[3];
120 hd_info[hdind].cyl = ints[1];
121 hd_info[hdind].wpcom = 0;
122 hd_info[hdind].lzone = ints[1];
123 hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
124 NR_HD = hdind+1;
125 }
126
127 static int win_result(void)
128 {
129 int i=inb_p(HD_STATUS);
130
131 if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
132 == (READY_STAT | SEEK_STAT)) {
133 hd_error = 0;
134 return 0;
135 }
136 printk("HD: win_result: status = 0x%02x\n",i);
137 if (i&1) {
138 hd_error = inb(HD_ERROR);
139 printk("HD: win_result: error = 0x%02x\n",hd_error);
140 }
141 return 1;
142 }
143
144 static int controller_busy(void);
145 static int status_ok(void);
146
147 static int controller_ready(unsigned int drive, unsigned int head)
148 {
149 int retry = 100;
150
151 do {
152 if (controller_busy() & BUSY_STAT)
153 return 0;
154 outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
155 if (status_ok())
156 return 1;
157 } while (--retry);
158 return 0;
159 }
160
161 static int status_ok(void)
162 {
163 unsigned char status = inb_p(HD_STATUS);
164
165 if (status & BUSY_STAT)
166 return 1;
167 if (status & WRERR_STAT)
168 return 0;
169 if (!(status & READY_STAT))
170 return 0;
171 if (!(status & SEEK_STAT))
172 return 0;
173 return 1;
174 }
175
176 static int controller_busy(void)
177 {
178 int retries = 100000;
179 unsigned char status;
180
181 do {
182 status = inb_p(HD_STATUS);
183 } while ((status & BUSY_STAT) && --retries);
184 return status;
185 }
186
187 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
188 unsigned int head,unsigned int cyl,unsigned int cmd,
189 void (*intr_addr)(void))
190 {
191 unsigned short port;
192
193 if (drive>1 || head>15)
194 panic("Trying to write bad sector");
195 #if (HD_DELAY > 0)
196 while (read_timer() - last_req < HD_DELAY)
197 ;
198 #endif
199 if (reset)
200 return;
201 if (!controller_ready(drive, head)) {
202 reset = 1;
203 return;
204 }
205 SET_INTR(intr_addr);
206 outb_p(hd_info[drive].ctl,HD_CMD);
207 port=HD_DATA;
208 outb_p(hd_info[drive].wpcom>>2,++port);
209 outb_p(nsect,++port);
210 outb_p(sect,++port);
211 outb_p(cyl,++port);
212 outb_p(cyl>>8,++port);
213 outb_p(0xA0|(drive<<4)|head,++port);
214 outb_p(cmd,++port);
215 }
216
217 static int drive_busy(void)
218 {
219 unsigned int i;
220 unsigned char c;
221
222 for (i = 0; i < 500000 ; i++) {
223 c = inb_p(HD_STATUS);
224 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
225 if (c == (READY_STAT | SEEK_STAT))
226 return 0;
227 }
228 printk("HD controller times out, status = 0x%02x\n",c);
229 return 1;
230 }
231
232 static void reset_controller(void)
233 {
234 int i;
235
236 printk("HD-controller reset\n");
237 outb(4,HD_CMD);
238 for(i = 0; i < 1000; i++) nop();
239 outb(hd_info[0].ctl & 0x0f ,HD_CMD);
240 if (drive_busy())
241 printk("HD-controller still busy\n");
242 if ((hd_error = inb(HD_ERROR)) != 1)
243 printk("HD-controller reset failed: %02x\n",hd_error);
244 }
245
246 static void reset_hd(void)
247 {
248 static int i;
249
250 repeat:
251 if (reset) {
252 reset = 0;
253 i = -1;
254 reset_controller();
255 } else if (win_result()) {
256 bad_rw_intr();
257 if (reset)
258 goto repeat;
259 }
260 i++;
261 if (i < NR_HD) {
262 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
263 hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
264 if (reset)
265 goto repeat;
266 } else
267 do_hd_request();
268 }
269
270
271
272
273
274
275 void unexpected_hd_interrupt(void)
276 {
277 sti();
278 printk("Unexpected HD interrupt\n");
279 SET_TIMER;
280 }
281
282
283
284
285
286
287 static void bad_rw_intr(void)
288 {
289 int dev;
290
291 if (!CURRENT)
292 return;
293 dev = MINOR(CURRENT->dev) >> 6;
294 if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
295 end_request(0);
296 recalibrate[dev] = 1;
297 } else if (CURRENT->errors % RESET_FREQ == 0)
298 reset = 1;
299 else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
300 recalibrate[dev] = 1;
301
302 }
303
304 static inline int wait_DRQ(void)
305 {
306 int retries = 100000;
307
308 while (--retries > 0)
309 if (inb_p(HD_STATUS) & DRQ_STAT)
310 return 0;
311 return -1;
312 }
313
314 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
315 #define STAT_OK (READY_STAT | SEEK_STAT)
316
317 static void read_intr(void)
318 {
319 int i;
320 int retries = 100000;
321
322 do {
323 i = (unsigned) inb_p(HD_STATUS);
324 if (i & BUSY_STAT)
325 continue;
326 if ((i & STAT_MASK) != STAT_OK)
327 break;
328 if (i & DRQ_STAT)
329 goto ok_to_read;
330 } while (--retries > 0);
331 sti();
332 printk("HD: read_intr: status = 0x%02x\n",i);
333 if (i & ERR_STAT) {
334 hd_error = (unsigned) inb(HD_ERROR);
335 printk("HD: read_intr: error = 0x%02x\n",hd_error);
336 }
337 bad_rw_intr();
338 cli();
339 do_hd_request();
340 return;
341 ok_to_read:
342 port_read(HD_DATA,CURRENT->buffer,256);
343 CURRENT->errors = 0;
344 CURRENT->buffer += 512;
345 CURRENT->sector++;
346 i = --CURRENT->nr_sectors;
347 --CURRENT->current_nr_sectors;
348 #ifdef DEBUG
349 printk("hd%d : sector = %d, %d remaining to buffer = %08x\n",
350 MINOR(CURRENT->dev), CURRENT->sector, i, CURRENT->
351 buffer);
352 #endif
353 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
354 end_request(1);
355 if (i > 0) {
356 SET_INTR(&read_intr);
357 sti();
358 return;
359 }
360 (void) inb_p(HD_STATUS);
361 #if (HD_DELAY > 0)
362 last_req = read_timer();
363 #endif
364 do_hd_request();
365 return;
366 }
367
368 static void write_intr(void)
369 {
370 int i;
371 int retries = 100000;
372
373 do {
374 i = (unsigned) inb_p(HD_STATUS);
375 if (i & BUSY_STAT)
376 continue;
377 if ((i & STAT_MASK) != STAT_OK)
378 break;
379 if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
380 goto ok_to_write;
381 } while (--retries > 0);
382 sti();
383 printk("HD: write_intr: status = 0x%02x\n",i);
384 if (i & ERR_STAT) {
385 hd_error = (unsigned) inb(HD_ERROR);
386 printk("HD: write_intr: error = 0x%02x\n",hd_error);
387 }
388 bad_rw_intr();
389 cli();
390 do_hd_request();
391 return;
392 ok_to_write:
393 CURRENT->sector++;
394 i = --CURRENT->nr_sectors;
395 --CURRENT->current_nr_sectors;
396 CURRENT->buffer += 512;
397 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
398 end_request(1);
399 if (i > 0) {
400 SET_INTR(&write_intr);
401 port_write(HD_DATA,CURRENT->buffer,256);
402 sti();
403 } else {
404 #if (HD_DELAY > 0)
405 last_req = read_timer();
406 #endif
407 do_hd_request();
408 }
409 return;
410 }
411
412 static void recal_intr(void)
413 {
414 if (win_result())
415 bad_rw_intr();
416 do_hd_request();
417 }
418
419
420
421
422
423 static void hd_times_out(void)
424 {
425 DEVICE_INTR = NULL;
426 sti();
427 reset = 1;
428 if (!CURRENT)
429 return;
430 printk("HD timeout\n");
431 cli();
432 if (++CURRENT->errors >= MAX_ERRORS) {
433 #ifdef DEBUG
434 printk("hd : too many errors.\n");
435 #endif
436 end_request(0);
437 }
438
439 do_hd_request();
440 }
441
442
443
444
445
446
447
448
449 static void do_hd_request(void)
450 {
451 unsigned int block,dev;
452 unsigned int sec,head,cyl,track;
453 unsigned int nsect;
454
455 if (CURRENT && CURRENT->dev < 0) return;
456
457 if (DEVICE_INTR)
458 return;
459 repeat:
460 timer_active &= ~(1<<HD_TIMER);
461 sti();
462 INIT_REQUEST;
463 dev = MINOR(CURRENT->dev);
464 block = CURRENT->sector;
465 nsect = CURRENT->nr_sectors;
466 if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
467 #ifdef DEBUG
468 printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
469 block, hd[dev].nr_sects);
470 #endif
471 end_request(0);
472 goto repeat;
473 }
474 block += hd[dev].start_sect;
475 dev >>= 6;
476 sec = block % hd_info[dev].sect + 1;
477 track = block / hd_info[dev].sect;
478 head = track % hd_info[dev].head;
479 cyl = track / hd_info[dev].head;
480 #ifdef DEBUG
481 printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
482 dev, cyl, head, sec, CURRENT->buffer);
483 #endif
484 cli();
485 if (reset) {
486 int i;
487
488 for (i=0; i < NR_HD; i++)
489 recalibrate[i] = 1;
490 reset_hd();
491 sti();
492 return;
493 }
494 if (recalibrate[dev]) {
495 recalibrate[dev] = 0;
496 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
497 if (reset)
498 goto repeat;
499 sti();
500 return;
501 }
502 if (CURRENT->cmd == WRITE) {
503 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
504 if (reset)
505 goto repeat;
506 if (wait_DRQ()) {
507 printk("HD: do_hd_request: no DRQ\n");
508 bad_rw_intr();
509 goto repeat;
510 }
511 port_write(HD_DATA,CURRENT->buffer,256);
512 sti();
513 return;
514 }
515 if (CURRENT->cmd == READ) {
516 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
517 if (reset)
518 goto repeat;
519 sti();
520 return;
521 }
522 panic("unknown hd-command");
523 }
524
525 static int hd_ioctl(struct inode * inode, struct file * file,
526 unsigned int cmd, unsigned long arg)
527 {
528 struct hd_geometry *loc = (struct hd_geometry *) arg;
529 int dev, err;
530
531 if (!inode)
532 return -EINVAL;
533 dev = MINOR(inode->i_rdev) >> 6;
534 if (dev >= NR_HD)
535 return -EINVAL;
536 switch (cmd) {
537 case HDIO_GETGEO:
538 if (!loc) return -EINVAL;
539 err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
540 if (err)
541 return err;
542 put_fs_byte(hd_info[dev].head,
543 (char *) &loc->heads);
544 put_fs_byte(hd_info[dev].sect,
545 (char *) &loc->sectors);
546 put_fs_word(hd_info[dev].cyl,
547 (short *) &loc->cylinders);
548 put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
549 (long *) &loc->start);
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