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 = controller_busy();
144
145 if (status & BUSY_STAT)
146 return 0;
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 (DEVICE_INTR)
425 return;
426 repeat:
427 timer_active &= ~(1<<HD_TIMER);
428 sti();
429 INIT_REQUEST;
430 dev = MINOR(CURRENT->dev);
431 block = CURRENT->sector;
432 nsect = CURRENT->nr_sectors;
433 if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
434 #ifdef DEBUG
435 printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
436 block, hd[dev].nr_sects);
437 #endif
438 end_request(0);
439 goto repeat;
440 }
441 block += hd[dev].start_sect;
442 dev >>= 6;
443 sec = block % hd_info[dev].sect + 1;
444 track = block / hd_info[dev].sect;
445 head = track % hd_info[dev].head;
446 cyl = track / hd_info[dev].head;
447 #ifdef DEBUG
448 printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
449 dev, cyl, head, sec, CURRENT->buffer);
450 #endif
451 cli();
452 if (reset) {
453 int i;
454
455 for (i=0; i < NR_HD; i++)
456 recalibrate[i] = 1;
457 reset_hd();
458 sti();
459 return;
460 }
461 if (recalibrate[dev]) {
462 recalibrate[dev] = 0;
463 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
464 if (reset)
465 goto repeat;
466 sti();
467 return;
468 }
469 if (CURRENT->cmd == WRITE) {
470 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
471 if (reset)
472 goto repeat;
473 if (wait_DRQ()) {
474 printk("HD: do_hd_request: no DRQ\n");
475 bad_rw_intr();
476 goto repeat;
477 }
478 port_write(HD_DATA,CURRENT->buffer,256);
479 sti();
480 return;
481 }
482 if (CURRENT->cmd == READ) {
483 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
484 if (reset)
485 goto repeat;
486 sti();
487 return;
488 }
489 panic("unknown hd-command");
490 }
491
492 static int hd_ioctl(struct inode * inode, struct file * file,
493 unsigned int cmd, unsigned int arg)
494 {
495 struct hd_geometry *loc = (void *) arg;
496 int dev;
497
498 if (!inode)
499 return -EINVAL;
500 dev = MINOR(inode->i_rdev) >> 6;
501 if (dev >= NR_HD)
502 return -EINVAL;
503 switch (cmd) {
504 case HDIO_GETGEO:
505 if (!loc) return -EINVAL;
506 verify_area(loc, sizeof(*loc));
507 put_fs_byte(hd_info[dev].head,
508 (char *) &loc->heads);
509 put_fs_byte(hd_info[dev].sect,
510 (char *) &loc->sectors);
511 put_fs_word(hd_info[dev].cyl,
512 (short *) &loc->cylinders);
513 put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
514 (long *) &loc->start);
515 return 0;
516 case BLKRRPART:
517 return revalidate_hddisk(inode->i_rdev, 1);
518 RO_IOCTLS(inode->i_rdev,arg);
519 default:
520 return -EINVAL;
521 }
522 }
523
524 static int hd_open(struct inode * inode, struct file * filp)
525 {
526 int target;
527 target = DEVICE_NR(MINOR(inode->i_rdev));
528
529 while (busy[target])
530 sleep_on(&busy_wait);
531 access_count[target]++;
532 return 0;
533 }
534
535
536
537
538
539 static void hd_release(struct inode * inode, struct file * file)
540 {
541 int target;
542 sync_dev(inode->i_rdev);
543
544 target = DEVICE_NR(MINOR(inode->i_rdev));
545 access_count[target]--;
546
547 }
548
549 static void hd_geninit();
550
551 static struct gendisk hd_gendisk = {
552 MAJOR_NR,
553 "hd",
554 6,
555 1 << 6,
556 MAX_HD,
557 hd_geninit,
558 hd,
559 hd_sizes,
560 0,
561 (void *) hd_info,
562 NULL
563 };
564
565 static void hd_interrupt(int unused)
566 {
567 void (*handler)(void) = DEVICE_INTR;
568
569 DEVICE_INTR = NULL;
570 timer_active &= ~(1<<HD_TIMER);
571 if (!handler)
572 handler = unexpected_hd_interrupt;
573 handler();
574 sti();
575 }
576
577
578
579
580
581
582
583
584
585
586 static struct sigaction hd_sigaction = {
587 hd_interrupt,
588 0,
589 SA_INTERRUPT,
590 NULL
591 };
592
593 static void hd_geninit(void)
594 {
595 int drive, i;
596 #ifndef HD_TYPE
597 extern struct drive_info drive_info;
598 void *BIOS = (void *) &drive_info;
599 int cmos_disks;
600
601 for (drive=0 ; drive<2 ; drive++) {
602 hd_info[drive].cyl = *(unsigned short *) BIOS;
603 hd_info[drive].head = *(unsigned char *) (2+BIOS);
604 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
605 hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
606 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
607 hd_info[drive].sect = *(unsigned char *) (14+BIOS);
608 BIOS += 16;
609 }
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
634 if (cmos_disks & 0x0f)
635 NR_HD = 2;
636 else
637 NR_HD = 1;
638 else
639 NR_HD = 0;
640 #endif
641 if (NR_HD) {
642 if (irqaction(HD_IRQ,&hd_sigaction)) {
643 printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
644 NR_HD = 0;
645 }
646 }
647 for (i = 0 ; i < NR_HD ; i++)
648 hd[i<<6].nr_sects = hd_info[i].head*
649 hd_info[i].sect*hd_info[i].cyl;
650
651 hd_gendisk.nr_real = NR_HD;
652 }
653
654 static struct file_operations hd_fops = {
655 NULL,
656 block_read,
657 block_write,
658 NULL,
659 NULL,
660 hd_ioctl,
661 NULL,
662 hd_open,
663 hd_release
664 };
665
666 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
667 {
668 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
669 blkdev_fops[MAJOR_NR] = &hd_fops;
670 hd_gendisk.next = gendisk_head;
671 gendisk_head = &hd_gendisk;
672 timer_table[HD_TIMER].fn = hd_times_out;
673 return mem_start;
674 }
675
676 #define DEVICE_BUSY busy[target]
677 #define USAGE access_count[target]
678 #define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
679
680
681 #undef MAYBE_REINIT
682 #define GENDISK_STRUCT hd_gendisk
683
684
685
686
687
688
689
690
691
692 static int revalidate_hddisk(int dev, int maxusage)
693 {
694 int target, major;
695 struct gendisk * gdev;
696 int max_p;
697 int start;
698 int i;
699
700 target = DEVICE_NR(MINOR(dev));
701 gdev = &GENDISK_STRUCT;
702
703 cli();
704 if (DEVICE_BUSY || USAGE > maxusage) {
705 sti();
706 return -EBUSY;
707 };
708 DEVICE_BUSY = 1;
709 sti();
710
711 max_p = gdev->max_p;
712 start = target << gdev->minor_shift;
713 major = MAJOR_NR << 8;
714
715 for (i=max_p - 1; i >=0 ; i--) {
716 sync_dev(major | start | i);
717 invalidate_inodes(major | start | i);
718 invalidate_buffers(major | start | i);
719 gdev->part[i].start_sect = 0;
720 gdev->part[i].nr_sects = 0;
721 };
722
723 #ifdef MAYBE_REINIT
724 MAYBE_REINIT;
725 #endif
726
727 gdev->part[start].nr_sects = CAPACITY;
728 resetup_one_dev(gdev, target);
729
730 DEVICE_BUSY = 0;
731 wake_up(&busy_wait);
732 return 0;
733 }
734
735 #endif