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