This source file includes following definitions.
- CMOS_READ
- read_timer
- controller_ready
- win_result
- 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_release
- hd_geninit
- hd_interrupt
- hd_init
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 static inline unsigned char CMOS_READ(unsigned char addr)
42 {
43 outb_p(0x80|addr,0x70);
44 return inb_p(0x71);
45 }
46
47 #define HD_DELAY 0
48
49
50 #define MAX_ERRORS 7
51 #define MAX_HD 2
52
53 static void recal_intr(void);
54 static void bad_rw_intr(void);
55
56 static int recalibrate = 0;
57 static int reset = 0;
58
59 #if (HD_DELAY > 0)
60 unsigned long last_req, read_timer();
61 #endif
62
63
64
65
66 struct hd_i_struct {
67 unsigned int head,sect,cyl,wpcom,lzone,ctl;
68 };
69 #ifdef HD_TYPE
70 struct hd_i_struct hd_info[] = { HD_TYPE };
71 #define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))
72 #else
73 struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
74 static int NR_HD = 0;
75 #endif
76
77 static struct hd_struct hd[MAX_HD<<6]={{0,0},};
78 static int hd_sizes[MAX_HD<<6] = {0, };
79
80 #define port_read(port,buf,nr) \
81 __asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")
82
83 #define port_write(port,buf,nr) \
84 __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
85
86 #if (HD_DELAY > 0)
87 unsigned long read_timer(void)
88 {
89 unsigned long t;
90 int i;
91
92 cli();
93 outb_p(0xc2, 0x43);
94 t = jiffies * 11931 + (inb_p(0x40) & 0x80 ? 5966 : 11932);
95 i = inb_p(0x40);
96 i |= inb(0x40) << 8;
97 sti();
98 return(t - i / 2);
99 }
100 #endif
101
102 static int controller_ready(void)
103 {
104 int retries = 100000;
105
106 while (--retries && (inb_p(HD_STATUS)&0x80))
107 ;
108 if (!retries)
109 printk("controller_ready: status = %02x\n\r",
110 (unsigned char) inb_p(HD_STATUS));
111 return (retries);
112 }
113
114 static int win_result(void)
115 {
116 int i=inb_p(HD_STATUS);
117
118 if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
119 == (READY_STAT | SEEK_STAT))
120 return 0;
121 printk("HD: win_result: status = 0x%02x\n",i);
122 if (i&1) {
123 i=inb(HD_ERROR);
124 printk("HD: win_result: error = 0x%02x\n",i);
125 }
126 return 1;
127 }
128
129 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
130 unsigned int head,unsigned int cyl,unsigned int cmd,
131 void (*intr_addr)(void))
132 {
133 unsigned short port;
134
135 if (drive>1 || head>15)
136 panic("Trying to write bad sector");
137 #if (HD_DELAY > 0)
138 while (read_timer() - last_req < HD_DELAY)
139 ;
140 #endif
141 if (reset || !controller_ready()) {
142 reset = 1;
143 return;
144 }
145 SET_INTR(intr_addr);
146 outb_p(hd_info[drive].ctl,HD_CMD);
147 port=HD_DATA;
148 outb_p(hd_info[drive].wpcom>>2,++port);
149 outb_p(nsect,++port);
150 outb_p(sect,++port);
151 outb_p(cyl,++port);
152 outb_p(cyl>>8,++port);
153 outb_p(0xA0|(drive<<4)|head,++port);
154 outb_p(cmd,++port);
155 }
156
157 static int drive_busy(void)
158 {
159 unsigned int i;
160 unsigned char c;
161
162 for (i = 0; i < 500000 ; i++) {
163 c = inb_p(HD_STATUS);
164 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
165 if (c == (READY_STAT | SEEK_STAT))
166 return 0;
167 }
168 printk("HD controller times out, status = 0x%02x\n\r",c);
169 return(1);
170 }
171
172 static void reset_controller(void)
173 {
174 int i;
175
176 printk("HD-controller reset\r\n");
177 outb(4,HD_CMD);
178 for(i = 0; i < 1000; i++) nop();
179 outb(hd_info[0].ctl & 0x0f ,HD_CMD);
180 if (drive_busy())
181 printk("HD-controller still busy\n\r");
182 if ((i = inb(HD_ERROR)) != 1)
183 printk("HD-controller reset failed: %02x\n\r",i);
184 }
185
186 static void reset_hd(void)
187 {
188 static int i;
189
190 repeat:
191 if (reset) {
192 reset = 0;
193 i = -1;
194 reset_controller();
195 } else if (win_result()) {
196 bad_rw_intr();
197 if (reset)
198 goto repeat;
199 }
200 i++;
201 if (i < NR_HD) {
202 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
203 hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
204 if (reset)
205 goto repeat;
206 } else
207 do_hd_request();
208 }
209
210
211
212
213
214
215 void unexpected_hd_interrupt(void)
216 {
217 sti();
218 printk("Unexpected HD interrupt\n\r");
219 SET_TIMER;
220 }
221
222 static void bad_rw_intr(void)
223 {
224 if (!CURRENT)
225 return;
226 if (++CURRENT->errors >= MAX_ERRORS)
227 end_request(0);
228 else if (CURRENT->errors > MAX_ERRORS/2)
229 reset = 1;
230 else
231 recalibrate = 1;
232 }
233
234 static inline int wait_DRQ(void)
235 {
236 int retries = 100000;
237
238 while (--retries > 0)
239 if (inb_p(HD_STATUS) & DRQ_STAT)
240 return 0;
241 return -1;
242 }
243
244 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
245 #define STAT_OK (READY_STAT | SEEK_STAT)
246
247 static void read_intr(void)
248 {
249 int i;
250
251 i = (unsigned) inb_p(HD_STATUS);
252 if ((i & STAT_MASK) != STAT_OK) {
253 printk("HD: read_intr: status = 0x%02x\n",i);
254 goto bad_read;
255 }
256 if (wait_DRQ()) {
257 printk("HD: read_intr: no DRQ\n");
258 goto bad_read;
259 }
260 port_read(HD_DATA,CURRENT->buffer,256);
261 i = (unsigned) inb_p(HD_STATUS);
262 if (!(i & BUSY_STAT))
263 if ((i & STAT_MASK) != STAT_OK) {
264 printk("HD: read_intr: second status = 0x%02x\n",i);
265 goto bad_read;
266 }
267 CURRENT->errors = 0;
268 CURRENT->buffer += 512;
269 CURRENT->sector++;
270 i = --CURRENT->nr_sectors;
271 --CURRENT->current_nr_sectors;
272 #ifdef DEBUG
273 printk("hd%d : sector = %d, %d remaining to buffer = %08x\n",
274 MINOR(CURRENT->dev), CURRENT->sector, i, CURRENT->
275 buffer);
276 #endif
277 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
278 end_request(1);
279 if (i > 0) {
280 SET_INTR(&read_intr);
281 sti();
282 return;
283 }
284 #if (HD_DELAY > 0)
285 last_req = read_timer();
286 #endif
287 do_hd_request();
288 return;
289 bad_read:
290 if (i & ERR_STAT) {
291 i = (unsigned) inb(HD_ERROR);
292 printk("HD: read_intr: error = 0x%02x\n",i);
293 }
294 bad_rw_intr();
295 do_hd_request();
296 return;
297 }
298
299 static void write_intr(void)
300 {
301 int i;
302
303 i = (unsigned) inb_p(HD_STATUS);
304 if ((i & STAT_MASK) != STAT_OK) {
305 printk("HD: write_intr: status = 0x%02x\n",i);
306 goto bad_write;
307 }
308 if (CURRENT->nr_sectors > 1 && wait_DRQ()) {
309 printk("HD: write_intr: no DRQ\n");
310 goto bad_write;
311 }
312 CURRENT->sector++;
313 i = --CURRENT->nr_sectors;
314 --CURRENT->current_nr_sectors;
315 CURRENT->buffer += 512;
316 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
317 end_request(1);
318 if (i > 0) {
319 SET_INTR(&write_intr);
320 port_write(HD_DATA,CURRENT->buffer,256);
321 sti();
322 } else {
323 #if (HD_DELAY > 0)
324 last_req = read_timer();
325 #endif
326 do_hd_request();
327 }
328 return;
329 bad_write:
330 sti();
331 if (i & ERR_STAT) {
332 i = (unsigned) inb(HD_ERROR);
333 printk("HD: write_intr: error = 0x%02x\n",i);
334 }
335 bad_rw_intr();
336 cli();
337 do_hd_request();
338 return;
339 }
340
341 static void recal_intr(void)
342 {
343 if (win_result())
344 bad_rw_intr();
345 do_hd_request();
346 }
347
348
349
350
351
352 static void hd_times_out(void)
353 {
354 sti();
355 DEVICE_INTR = NULL;
356 reset = 1;
357 if (!CURRENT)
358 return;
359 printk("HD timeout\n\r");
360 cli();
361 if (++CURRENT->errors >= MAX_ERRORS) {
362 #ifdef DEBUG
363 printk("hd : too many errors.\n");
364 #endif
365 end_request(0);
366 }
367
368 do_hd_request();
369 }
370
371
372
373
374
375
376
377
378 static void do_hd_request(void)
379 {
380 unsigned int block,dev;
381 unsigned int sec,head,cyl;
382 unsigned int nsect;
383
384 repeat:
385 DEVICE_INTR = NULL;
386 timer_active &= ~(1<<HD_TIMER);
387 sti();
388 INIT_REQUEST;
389 dev = MINOR(CURRENT->dev);
390 block = CURRENT->sector;
391 nsect = CURRENT->nr_sectors;
392 if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
393 #ifdef DEBUG
394 printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
395 block, hd[dev].nr_sects);
396 #endif
397 end_request(0);
398 goto repeat;
399 }
400 block += hd[dev].start_sect;
401 dev >>= 6;
402 sec = block % hd_info[dev].sect;
403 block /= hd_info[dev].sect;
404 head = block % hd_info[dev].head;
405 cyl = block / hd_info[dev].head;
406 sec++;
407 #ifdef DEBUG
408 printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
409 dev, cyl, head, sec, CURRENT->buffer);
410 #endif
411 cli();
412 if (reset) {
413 recalibrate = 1;
414 reset_hd();
415 sti();
416 return;
417 }
418 if (recalibrate) {
419 recalibrate = 0;
420 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
421 if (reset)
422 goto repeat;
423 sti();
424 return;
425 }
426 if (CURRENT->cmd == WRITE) {
427 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
428 if (reset)
429 goto repeat;
430 if (wait_DRQ()) {
431 printk("HD: do_hd_request: no DRQ\n");
432 bad_rw_intr();
433 goto repeat;
434 }
435 port_write(HD_DATA,CURRENT->buffer,256);
436 sti();
437 } else if (CURRENT->cmd == READ) {
438 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
439 if (reset)
440 goto repeat;
441 sti();
442 } else
443 panic("unknown hd-command");
444 }
445
446 static int hd_ioctl(struct inode * inode, struct file * file,
447 unsigned int cmd, unsigned int arg)
448 {
449 struct hd_geometry *loc = (void *) arg;
450 int dev;
451
452 if (!loc || !inode)
453 return -EINVAL;
454 dev = MINOR(inode->i_rdev) >> 6;
455 if (dev >= NR_HD)
456 return -EINVAL;
457 switch (cmd) {
458 case HDIO_REQ:
459 verify_area(loc, sizeof(*loc));
460 put_fs_byte(hd_info[dev].head,
461 (char *) &loc->heads);
462 put_fs_byte(hd_info[dev].sect,
463 (char *) &loc->sectors);
464 put_fs_word(hd_info[dev].cyl,
465 (short *) &loc->cylinders);
466 put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
467 (long *) &loc->start);
468 return 0;
469 RO_IOCTLS(inode->i_rdev,arg);
470 default:
471 return -EINVAL;
472 }
473 }
474
475
476
477
478
479 static void hd_release(struct inode * inode, struct file * file)
480 {
481 sync_dev(inode->i_rdev);
482 }
483
484
485 static void hd_geninit();
486
487 static struct gendisk hd_gendisk = {
488 MAJOR_NR,
489 "hd",
490 6,
491 1 << 6,
492 MAX_HD,
493 hd_geninit,
494 hd,
495 hd_sizes,
496 0,
497 (void *) hd_info,
498 NULL
499 };
500
501 static void hd_geninit(void)
502 {
503 int drive;
504 #ifndef HD_TYPE
505 extern struct drive_info drive_info;
506 void *BIOS = (void *) &drive_info;
507 int cmos_disks, i;
508
509 for (drive=0 ; drive<2 ; drive++) {
510 hd_info[drive].cyl = *(unsigned short *) BIOS;
511 hd_info[drive].head = *(unsigned char *) (2+BIOS);
512 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
513 hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
514 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
515 hd_info[drive].sect = *(unsigned char *) (14+BIOS);
516 BIOS += 16;
517 }
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
542 if (cmos_disks & 0x0f)
543 NR_HD = 2;
544 else
545 NR_HD = 1;
546 else
547 NR_HD = 0;
548 #endif
549
550 for (i = 0 ; i < NR_HD ; i++)
551 hd[i<<6].nr_sects = hd_info[i].head*
552 hd_info[i].sect*hd_info[i].cyl;
553
554 hd_gendisk.nr_real = NR_HD;
555 }
556
557 static struct file_operations hd_fops = {
558 NULL,
559 block_read,
560 block_write,
561 NULL,
562 NULL,
563 hd_ioctl,
564 NULL,
565 hd_release
566 };
567
568 static void hd_interrupt(int unused)
569 {
570 void (*handler)(void) = DEVICE_INTR;
571
572 DEVICE_INTR = NULL;
573 timer_active &= ~(1<<HD_TIMER);
574 if (!handler)
575 handler = unexpected_hd_interrupt;
576 handler();
577 sti();
578 }
579
580
581
582
583
584
585
586
587
588
589 static struct sigaction hd_sigaction = {
590 hd_interrupt,
591 0,
592 SA_INTERRUPT,
593 NULL
594 };
595
596 void hd_init(void)
597 {
598 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
599 blkdev_fops[MAJOR_NR] = &hd_fops;
600 hd_gendisk.next = gendisk_head;
601 gendisk_head = &hd_gendisk;
602 if (irqaction(HD_IRQ,&hd_sigaction))
603 printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
604 timer_table[HD_TIMER].fn = hd_times_out;
605 }
606
607 #endif