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