This source file includes following definitions.
- CMOS_READ
- read_timer
- hd_setup
- win_result
- controller_ready
- status_ok
- controller_busy
- hd_out
- rawstring
- identify_intr
- set_multmode_intr
- drive_busy
- reset_controller
- reset_hd
- unexpected_hd_interrupt
- bad_rw_intr
- wait_DRQ
- read_intr
- multwrite
- multwrite_intr
- write_intr
- recal_intr
- hd_times_out
- hd_request
- 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
21
22
23
24 #define DEFAULT_MULT_COUNT 0
25 #define DEFAULT_UNMASK_INTR 0
26
27 #include <asm/irq.h>
28 #include <linux/errno.h>
29 #include <linux/signal.h>
30 #include <linux/sched.h>
31 #include <linux/timer.h>
32 #include <linux/fs.h>
33 #include <linux/kernel.h>
34 #include <linux/hdreg.h>
35 #include <linux/genhd.h>
36 #include <linux/config.h>
37 #include <linux/malloc.h>
38
39 #define REALLY_SLOW_IO
40 #include <asm/system.h>
41 #include <asm/io.h>
42 #include <asm/segment.h>
43
44 #define MAJOR_NR HD_MAJOR
45 #include "blk.h"
46
47 #define HD_IRQ 14
48
49 static int revalidate_hddisk(int, int);
50
51 static inline unsigned char CMOS_READ(unsigned char addr)
52 {
53 outb_p(addr,0x70);
54 return inb_p(0x71);
55 }
56
57 #define HD_DELAY 0
58
59 #define MAX_ERRORS 16
60 #define RESET_FREQ 8
61 #define RECAL_FREQ 4
62 #define MAX_HD 2
63
64 static void recal_intr(void);
65 static void bad_rw_intr(void);
66
67 static char recalibrate[MAX_HD] = { 0, };
68 static char special_op[MAX_HD] = { 0, };
69 static int access_count[MAX_HD] = {0, };
70 static char busy[MAX_HD] = {0, };
71 static struct wait_queue * busy_wait = NULL;
72
73 static int reset = 0;
74 static int hd_error = 0;
75
76
77
78
79 struct hd_i_struct {
80 unsigned int head,sect,cyl,wpcom,lzone,ctl;
81 };
82 static struct hd_driveid *hd_ident_info[MAX_HD];
83
84 #ifdef HD_TYPE
85 static struct hd_i_struct hd_info[] = { HD_TYPE };
86 struct hd_i_struct bios_info[] = { HD_TYPE };
87 static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
88 #else
89 static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
90 struct hd_i_struct bios_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
91 static int NR_HD = 0;
92 #endif
93
94 static struct hd_struct hd[MAX_HD<<6]={{0,0},};
95 static int hd_sizes[MAX_HD<<6] = {0, };
96 static int hd_blocksizes[MAX_HD<<6] = {0, };
97
98 #if (HD_DELAY > 0)
99 unsigned long last_req;
100
101 unsigned long read_timer(void)
102 {
103 unsigned long t, flags;
104 int i;
105
106 save_flags(flags);
107 cli();
108 t = jiffies * 11932;
109 outb_p(0, 0x43);
110 i = inb_p(0x40);
111 i |= inb(0x40) << 8;
112 restore_flags(flags);
113 return(t - i);
114 }
115 #endif
116
117 void hd_setup(char *str, int *ints)
118 {
119 int hdind = 0;
120
121 if (ints[0] != 3)
122 return;
123 if (bios_info[0].head != 0)
124 hdind=1;
125 bios_info[hdind].head = hd_info[hdind].head = ints[2];
126 bios_info[hdind].sect = hd_info[hdind].sect = ints[3];
127 bios_info[hdind].cyl = hd_info[hdind].cyl = ints[1];
128 bios_info[hdind].wpcom = hd_info[hdind].wpcom = 0;
129 bios_info[hdind].lzone = hd_info[hdind].lzone = ints[1];
130 bios_info[hdind].ctl = hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
131 NR_HD = hdind+1;
132 }
133
134 static int win_result(void)
135 {
136 int i=inb_p(HD_STATUS);
137
138 if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
139 == (READY_STAT | SEEK_STAT)) {
140 hd_error = 0;
141 return 0;
142 }
143 printk("HD: win_result: status = 0x%02x\n",i);
144 if (i&1) {
145 hd_error = inb(HD_ERROR);
146 printk("HD: win_result: error = 0x%02x\n",hd_error);
147 }
148 return 1;
149 }
150
151 static int controller_busy(void);
152 static int status_ok(void);
153
154 static int controller_ready(unsigned int drive, unsigned int head)
155 {
156 int retry = 100;
157
158 do {
159 if (controller_busy() & BUSY_STAT)
160 return 0;
161 outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
162 if (status_ok())
163 return 1;
164 } while (--retry);
165 return 0;
166 }
167
168 static int status_ok(void)
169 {
170 unsigned char status = inb_p(HD_STATUS);
171
172 if (status & BUSY_STAT)
173 return 1;
174 if (status & WRERR_STAT)
175 return 0;
176 if (!(status & READY_STAT))
177 return 0;
178 if (!(status & SEEK_STAT))
179 return 0;
180 return 1;
181 }
182
183 static int controller_busy(void)
184 {
185 int retries = 100000;
186 unsigned char status;
187
188 do {
189 status = inb_p(HD_STATUS);
190 } while ((status & BUSY_STAT) && --retries);
191 return status;
192 }
193
194 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
195 unsigned int head,unsigned int cyl,unsigned int cmd,
196 void (*intr_addr)(void))
197 {
198 unsigned short port;
199
200 #ifdef DEBUG
201 if (drive>1 || head>15) {
202 printk("bad drive mapping, trying to access drive=%d, cyl=%d, head=%d, sect=%d\n",
203 drive, cyl, head, sect);
204 panic("harddisk driver problem");
205 }
206 #endif
207 #if (HD_DELAY > 0)
208 while (read_timer() - last_req < HD_DELAY)
209 ;
210 #endif
211 if (reset)
212 return;
213 if (!controller_ready(drive, head)) {
214 special_op[drive] += reset = 1;
215 return;
216 }
217 SET_INTR(intr_addr);
218 outb_p(hd_info[drive].ctl,HD_CMD);
219 port=HD_DATA;
220 outb_p(hd_info[drive].wpcom>>2,++port);
221 outb_p(nsect,++port);
222 outb_p(sect,++port);
223 outb_p(cyl,++port);
224 outb_p(cyl>>8,++port);
225 outb_p(0xA0|(drive<<4)|head,++port);
226 outb_p(cmd,++port);
227 }
228
229 static void hd_request (void);
230 static unsigned int identified [MAX_HD] = {0,};
231 static unsigned int unmask_intr [MAX_HD] = {0,};
232 static unsigned int max_mult [MAX_HD] = {0,};
233 static unsigned int mult_req [MAX_HD] = {0,};
234 static unsigned int mult_count [MAX_HD] = {0,};
235 static struct request WCURRENT;
236
237 static void rawstring (char *prefix, unsigned char *s, int n)
238 {
239 if (prefix)
240 printk(prefix);
241 if (s && *s) {
242 int i;
243 for (i=0; i < n && s[i^1] == ' '; ++i);
244 for (; i < n && s[i^1]; ++i)
245 if (s[i^1] != ' ' || ((i+1) < n && s[(i+1)^1] != ' '))
246 printk("%c",s[i^1]);
247 }
248 }
249
250 static void identify_intr(void)
251 {
252 unsigned int dev = DEVICE_NR(CURRENT->dev);
253 unsigned short stat = inb_p(HD_STATUS);
254 struct hd_driveid id;
255
256 if (unmask_intr[dev])
257 sti();
258 if (stat & (BUSY_STAT|ERR_STAT))
259 printk (" hd%c: identity unknown\n", dev+'a');
260 else {
261 insw(HD_DATA, (char *)&id, sizeof(id)/2);
262 max_mult[dev] = id.max_multsect;
263 if ((id.cur_valid&1) && id.cur_cyls && id.cur_heads && (id.cur_heads <= 16) && id.cur_sectors) {
264
265
266
267
268
269
270
271 hd_info[dev].cyl = id.cur_cyls;
272 hd_info[dev].head = id.cur_heads;
273 hd_info[dev].sect = id.cur_sectors;
274 }
275 printk (" hd%c: ", dev+'a');
276 rawstring(NULL, id.model, sizeof(id.model));
277 printk (", %dMB w/%dKB Cache, CHS=%d/%d/%d, MaxMult=%d\n",
278 id.cyls*id.heads*id.sectors/2048, id.buf_size/2,
279 hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect, id.max_multsect);
280
281 if (NULL != (hd_ident_info[dev] = kmalloc(sizeof(id),GFP_ATOMIC)))
282 *hd_ident_info[dev] = id;
283
284
285 insw(HD_DATA,(char *)&id,sizeof(id)/2);
286 insw(HD_DATA,(char *)&id,sizeof(id)/2);
287 insw(HD_DATA,(char *)&id,sizeof(id)/2);
288 }
289 #if (HD_DELAY > 0)
290 last_req = read_timer();
291 #endif
292 hd_request();
293 return;
294 }
295
296 static void set_multmode_intr(void)
297 {
298 unsigned int dev = DEVICE_NR(CURRENT->dev), stat = inb_p(HD_STATUS);
299
300 if (unmask_intr[dev])
301 sti();
302 if (stat & (BUSY_STAT|ERR_STAT)) {
303 mult_req[dev] = mult_count[dev] = 0;
304 printk (" hd%c: set multiple mode failed\n", dev+'a');
305 } else {
306 if ((mult_count[dev] = mult_req[dev]))
307 printk (" hd%c: enabled %d-sector multiple mode\n",
308 dev+'a', mult_count[dev]);
309 else
310 printk (" hd%c: disabled multiple mode\n", dev+'a');
311 }
312 #if (HD_DELAY > 0)
313 last_req = read_timer();
314 #endif
315 hd_request();
316 return;
317 }
318
319 static int drive_busy(void)
320 {
321 unsigned int i;
322 unsigned char c;
323
324 for (i = 0; i < 500000 ; i++) {
325 c = inb_p(HD_STATUS);
326 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
327 if (c == (READY_STAT | SEEK_STAT))
328 return 0;
329 }
330 printk("HD controller times out, status = 0x%02x\n",c);
331 return 1;
332 }
333
334 static void reset_controller(void)
335 {
336 int i;
337
338 printk(KERN_DEBUG "HD-controller reset\n");
339 outb_p(4,HD_CMD);
340 for(i = 0; i < 1000; i++) nop();
341 outb(hd_info[0].ctl & 0x0f ,HD_CMD);
342 if (drive_busy())
343 printk("HD-controller still busy\n");
344 if ((hd_error = inb(HD_ERROR)) != 1)
345 printk("HD-controller reset failed: %02x\n",hd_error);
346 }
347
348 static void reset_hd(void)
349 {
350 static int i;
351
352 repeat:
353 if (reset) {
354 reset = 0;
355 i = -1;
356 reset_controller();
357 } else if (win_result()) {
358 bad_rw_intr();
359 if (reset)
360 goto repeat;
361 }
362 if (++i < NR_HD) {
363 if (unmask_intr[i]) {
364 printk("hd%c: disabled irq-unmasking\n",i+'a');
365 unmask_intr[i] = 0;
366 }
367 if (mult_req[i] || mult_count[i]) {
368 printk("hd%c: disabled multiple mode\n",i+'a');
369 mult_req[i] = mult_count[i] = 0;
370 }
371 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
372 hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
373 if (reset)
374 goto repeat;
375 } else
376 hd_request();
377 }
378
379
380
381
382
383
384 void unexpected_hd_interrupt(void)
385 {
386 sti();
387 printk(KERN_DEBUG "Unexpected HD interrupt\n");
388 SET_TIMER;
389 }
390
391
392
393
394
395
396 static void bad_rw_intr(void)
397 {
398 int dev;
399
400 if (!CURRENT)
401 return;
402 dev = MINOR(CURRENT->dev) >> 6;
403 if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
404 end_request(0);
405 special_op[dev] += recalibrate[dev] = 1;
406 } else if (CURRENT->errors % RESET_FREQ == 0)
407 special_op[dev] += reset = 1;
408 else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
409 special_op[dev] += recalibrate[dev] = 1;
410
411 }
412
413 static inline int wait_DRQ(void)
414 {
415 int retries = 100000;
416
417 while (--retries > 0)
418 if (inb_p(HD_STATUS) & DRQ_STAT)
419 return 0;
420 return -1;
421 }
422
423 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
424 #define STAT_OK (READY_STAT | SEEK_STAT)
425
426 static void read_intr(void)
427 {
428 unsigned int dev = DEVICE_NR(CURRENT->dev);
429 int i, retries = 100000, msect = mult_count[dev], nsect;
430
431 if (unmask_intr[dev])
432 sti();
433 do {
434 i = (unsigned) inb_p(HD_STATUS);
435 if (i & BUSY_STAT)
436 continue;
437 if ((i & STAT_MASK) != STAT_OK)
438 break;
439 if (i & DRQ_STAT)
440 goto ok_to_read;
441 } while (--retries > 0);
442 sti();
443 printk("hd%c: read_intr: status = 0x%02x\n",dev+'a',i);
444 if (i & ERR_STAT) {
445 hd_error = (unsigned) inb(HD_ERROR);
446 printk("hd%c: read_intr: error = 0x%02x\n",dev+'a',hd_error);
447 }
448 bad_rw_intr();
449 hd_request();
450 return;
451 ok_to_read:
452 if (msect) {
453 if ((nsect = CURRENT->current_nr_sectors) > msect)
454 nsect = msect;
455 msect -= nsect;
456 } else
457 nsect = 1;
458 insw(HD_DATA,CURRENT->buffer,nsect<<8);
459 CURRENT->sector += nsect;
460 CURRENT->buffer += nsect<<9;
461 CURRENT->errors = 0;
462 i = (CURRENT->nr_sectors -= nsect);
463
464 #ifdef DEBUG
465 printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=%08lx\n",
466 dev+'a', CURRENT->sector, CURRENT->sector+nsect,
467 CURRENT->nr_sectors, (long) CURRENT->buffer+(nsect<<9));
468 #endif
469 if ((CURRENT->current_nr_sectors -= nsect) <= 0)
470 end_request(1);
471 if (i > 0) {
472 if (msect)
473 goto ok_to_read;
474 SET_INTR(&read_intr);
475 return;
476 }
477 (void) inb_p(HD_STATUS);
478 #if (HD_DELAY > 0)
479 last_req = read_timer();
480 #endif
481 if (CURRENT)
482 hd_request();
483 return;
484 }
485
486 static inline void multwrite (unsigned int dev)
487 {
488 unsigned int mcount = mult_count[dev];
489
490 while (mcount--) {
491 outsw(HD_DATA,WCURRENT.buffer,256);
492 if (!--WCURRENT.nr_sectors)
493 return;
494 WCURRENT.buffer += 512;
495 if (!--WCURRENT.current_nr_sectors) {
496 WCURRENT.bh = WCURRENT.bh->b_reqnext;
497 if (WCURRENT.bh == NULL)
498 panic("buffer list corrupted\n");
499 WCURRENT.current_nr_sectors = WCURRENT.bh->b_size>>9;
500 WCURRENT.buffer = WCURRENT.bh->b_data;
501 }
502 }
503 }
504
505 static void multwrite_intr(void)
506 {
507 int i;
508 unsigned int dev = DEVICE_NR(WCURRENT.dev);
509
510 if (unmask_intr[dev])
511 sti();
512 if (((i = inb_p(HD_STATUS)) & STAT_MASK) == STAT_OK) {
513 if (i & DRQ_STAT) {
514 if (WCURRENT.nr_sectors) {
515 multwrite(dev);
516 SET_INTR(&multwrite_intr);
517 return;
518 }
519 } else {
520 if (!WCURRENT.nr_sectors) {
521 for (i = CURRENT->nr_sectors; i > 0;){
522 i -= CURRENT->current_nr_sectors;
523 end_request(1);
524 }
525 #if (HD_DELAY > 0)
526 last_req = read_timer();
527 #endif
528 if (CURRENT)
529 hd_request();
530 return;
531 }
532 }
533 }
534 sti();
535 printk("hd%c: multwrite_intr: status = 0x%02x\n",dev+'a',i);
536 if (i & ERR_STAT) {
537 hd_error = (unsigned) inb(HD_ERROR);
538 printk("hd:%c multwrite_intr: error = 0x%02x\n",dev+'a',hd_error);
539 }
540 bad_rw_intr();
541 hd_request();
542 }
543
544 static void write_intr(void)
545 {
546 int i;
547 int retries = 100000;
548
549 if (unmask_intr[DEVICE_NR(WCURRENT.dev)])
550 sti();
551 do {
552 i = (unsigned) inb_p(HD_STATUS);
553 if (i & BUSY_STAT)
554 continue;
555 if ((i & STAT_MASK) != STAT_OK)
556 break;
557 if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
558 goto ok_to_write;
559 } while (--retries > 0);
560 sti();
561 printk("HD: write_intr: status = 0x%02x\n",i);
562 if (i & ERR_STAT) {
563 hd_error = (unsigned) inb(HD_ERROR);
564 printk("HD: write_intr: error = 0x%02x\n",hd_error);
565 }
566 bad_rw_intr();
567 hd_request();
568 return;
569 ok_to_write:
570 CURRENT->sector++;
571 i = --CURRENT->nr_sectors;
572 --CURRENT->current_nr_sectors;
573 CURRENT->buffer += 512;
574 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
575 end_request(1);
576 if (i > 0) {
577 SET_INTR(&write_intr);
578 outsw(HD_DATA,CURRENT->buffer,256);
579 sti();
580 } else {
581 #if (HD_DELAY > 0)
582 last_req = read_timer();
583 #endif
584 hd_request();
585 }
586 return;
587 }
588
589 static void recal_intr(void)
590 {
591 if (win_result())
592 bad_rw_intr();
593 #if (HD_DELAY > 0)
594 last_req = read_timer();
595 #endif
596 hd_request();
597 }
598
599
600
601
602
603 static void hd_times_out(void)
604 {
605 DEVICE_INTR = NULL;
606 sti();
607 special_op [DEVICE_NR(CURRENT->dev)] += reset = 1;
608 if (!CURRENT)
609 return;
610 printk(KERN_DEBUG "HD timeout\n");
611 cli();
612 if (++CURRENT->errors >= MAX_ERRORS) {
613 #ifdef DEBUG
614 printk("hd : too many errors.\n");
615 #endif
616 end_request(0);
617 }
618
619 hd_request();
620 }
621
622
623
624
625
626
627
628
629 static void hd_request(void)
630 {
631 unsigned int block,dev;
632 unsigned int sec,head,cyl,track;
633 unsigned int nsect;
634
635 if (CURRENT && CURRENT->dev < 0) return;
636
637 if (DEVICE_INTR)
638 return;
639 repeat:
640 timer_active &= ~(1<<HD_TIMER);
641 sti();
642 INIT_REQUEST;
643 dev = MINOR(CURRENT->dev);
644 block = CURRENT->sector;
645 nsect = CURRENT->nr_sectors;
646 if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
647 #ifdef DEBUG
648 printk("hd : attempted read for sector %d past end of device at sector %d.\n",
649 block, hd[dev].nr_sects);
650 #endif
651 end_request(0);
652 goto repeat;
653 }
654 block += hd[dev].start_sect;
655 dev >>= 6;
656 sec = block % hd_info[dev].sect + 1;
657 track = block / hd_info[dev].sect;
658 head = track % hd_info[dev].head;
659 cyl = track / hd_info[dev].head;
660 #ifdef DEBUG
661 printk("hd%c : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
662 dev+'a', cyl, head, sec, CURRENT->buffer);
663 #endif
664 if (!unmask_intr[dev])
665 cli();
666 if (special_op[dev]) {
667 if (reset) {
668 int i;
669
670 for (i=0; i < NR_HD; i++)
671 special_op[i] = recalibrate[i] = 1;
672 cli();
673 reset_hd();
674 return;
675 }
676 if (recalibrate[dev]) {
677 recalibrate[dev] = 0;
678 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
679 if (reset)
680 goto repeat;
681 return;
682 }
683 if (!identified[dev]) {
684 identified[dev] = 1;
685 unmask_intr[dev] = DEFAULT_UNMASK_INTR;
686 mult_req[dev] = DEFAULT_MULT_COUNT;
687 hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
688 if (reset)
689 goto repeat;
690 return;
691 }
692 if (mult_req[dev] != mult_count[dev]) {
693 hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
694 if (reset)
695 goto repeat;
696 return;
697 }
698 if (hd_info[dev].head > 16) {
699 printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
700 end_request(0);
701 goto repeat;
702 }
703 --special_op[dev];
704 }
705 if (CURRENT->cmd == READ) {
706 unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ;
707 hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr);
708 if (reset)
709 goto repeat;
710 #ifdef DEBUG
711 printk("hd%c: reading %d sectors(%ld-%ld), buffer=%08lx\n",
712 dev+'a', nsect, CURRENT->sector,
713 CURRENT->sector+nsect-1, (long) CURRENT->buffer);
714 #endif
715 return;
716 }
717 if (CURRENT->cmd == WRITE) {
718 if (mult_count[dev])
719 hd_out(dev,nsect,sec,head,cyl,WIN_MULTWRITE,&multwrite_intr);
720 else
721 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
722 if (reset)
723 goto repeat;
724 #ifdef DEBUG
725 printk("hd%c: writing %d sectors(%ld-%ld), buffer=%08lx\n",
726 dev+'a', nsect, CURRENT->sector,
727 CURRENT->sector+nsect-1, (long) CURRENT->buffer);
728 #endif
729 if (wait_DRQ()) {
730 printk("hd%c: hd_request: no DRQ\n", dev+'a');
731 bad_rw_intr();
732 goto repeat;
733 }
734 if (mult_count[dev]) {
735 WCURRENT = *CURRENT;
736 multwrite(dev);
737 } else {
738 outsw(HD_DATA,CURRENT->buffer,256);
739 }
740 return;
741 }
742 panic("unknown hd-command");
743 }
744
745 static void do_hd_request (void)
746 {
747 disable_irq(HD_IRQ);
748 hd_request();
749 enable_irq(HD_IRQ);
750 }
751
752 static int hd_ioctl(struct inode * inode, struct file * file,
753 unsigned int cmd, unsigned long arg)
754 {
755 struct hd_geometry *loc = (struct hd_geometry *) arg;
756 int dev, err;
757
758 if ((!inode) || (!inode->i_rdev))
759 return -EINVAL;
760 dev = MINOR(inode->i_rdev) >> 6;
761 if (dev >= NR_HD)
762 return -EINVAL;
763 switch (cmd) {
764 case HDIO_GETGEO:
765 if (!loc) return -EINVAL;
766 err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
767 if (err)
768 return err;
769 put_fs_byte(bios_info[dev].head,
770 (char *) &loc->heads);
771 put_fs_byte(bios_info[dev].sect,
772 (char *) &loc->sectors);
773 put_fs_word(bios_info[dev].cyl,
774 (short *) &loc->cylinders);
775 put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
776 (long *) &loc->start);
777 return 0;
778 case BLKRASET:
779 if(!suser()) return -EACCES;
780 if(arg > 0xff) return -EINVAL;
781 read_ahead[MAJOR(inode->i_rdev)] = arg;
782 return 0;
783 case BLKRAGET:
784 if (!arg) return -EINVAL;
785 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
786 if (err)
787 return err;
788 put_fs_long(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
789 return 0;
790 case BLKGETSIZE:
791 if (!arg) return -EINVAL;
792 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
793 if (err)
794 return err;
795 put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
796 return 0;
797 case BLKFLSBUF:
798 if(!suser()) return -EACCES;
799 fsync_dev(inode->i_rdev);
800 invalidate_buffers(inode->i_rdev);
801 return 0;
802
803 case BLKRRPART:
804 return revalidate_hddisk(inode->i_rdev, 1);
805
806 case HDIO_SETUNMASKINTR:
807 if (!suser()) return -EACCES;
808 if (!arg) return -EINVAL;
809 if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
810 err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
811 if (err)
812 return err;
813 unmask_intr[dev] = get_fs_long((long *) arg);
814 return 0;
815
816 case HDIO_GETUNMASKINTR:
817 if (!arg) return -EINVAL;
818 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
819 if (err)
820 return err;
821 put_fs_long(unmask_intr[dev], (long *) arg);
822 return 0;
823
824 case HDIO_GETMULTCOUNT:
825 if (!arg) return -EINVAL;
826 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
827 if (err)
828 return err;
829 put_fs_long(mult_count[dev], (long *) arg);
830 return 0;
831
832 case HDIO_SETMULTCOUNT:
833 {
834 unsigned long flags;
835 if (!suser()) return -EACCES;
836 if (!arg) return -EINVAL;
837 if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
838 err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
839 if (err)
840 return err;
841 arg = get_fs_long((long *) arg);
842 save_flags(flags);
843 cli();
844 if (arg > max_mult[dev])
845 err = -EINVAL;
846 else if (mult_req[dev] != mult_count[dev]) {
847 ++special_op[dev];
848 err = -EBUSY;
849 } else {
850 mult_req[dev] = arg;
851 ++special_op[dev];
852 err = 0;
853 }
854 restore_flags(flags);
855 return err;
856 }
857 case HDIO_GETIDENTITY:
858 if (!arg) return -EINVAL;
859 if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
860 if (hd_ident_info[dev] == NULL) return -ENOMSG;
861 err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(struct hd_driveid));
862 if (err)
863 return err;
864 memcpy_tofs((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
865
866 RO_IOCTLS(inode->i_rdev,arg);
867 default:
868 return -EINVAL;
869 }
870 }
871
872 static int hd_open(struct inode * inode, struct file * filp)
873 {
874 int target;
875 target = DEVICE_NR(MINOR(inode->i_rdev));
876
877 while (busy[target])
878 sleep_on(&busy_wait);
879 access_count[target]++;
880 return 0;
881 }
882
883
884
885
886
887 static void hd_release(struct inode * inode, struct file * file)
888 {
889 int target;
890 sync_dev(inode->i_rdev);
891
892 target = DEVICE_NR(MINOR(inode->i_rdev));
893 access_count[target]--;
894
895 }
896
897 static void hd_geninit(void);
898
899 static struct gendisk hd_gendisk = {
900 MAJOR_NR,
901 "hd",
902 6,
903 1 << 6,
904 MAX_HD,
905 hd_geninit,
906 hd,
907 hd_sizes,
908 0,
909 (void *) bios_info,
910 NULL
911 };
912
913 static void hd_interrupt(int unused)
914 {
915 void (*handler)(void) = DEVICE_INTR;
916
917 DEVICE_INTR = NULL;
918 timer_active &= ~(1<<HD_TIMER);
919 if (!handler)
920 handler = unexpected_hd_interrupt;
921 handler();
922 sti();
923 }
924
925
926
927
928
929
930
931
932
933
934 static struct sigaction hd_sigaction = {
935 hd_interrupt,
936 0,
937 SA_INTERRUPT,
938 NULL
939 };
940
941 static void hd_geninit(void)
942 {
943 int drive, i;
944 extern struct drive_info drive_info;
945 unsigned char *BIOS = (unsigned char *) &drive_info;
946 int cmos_disks;
947
948 if (!NR_HD) {
949 for (drive=0 ; drive<2 ; drive++) {
950 bios_info[drive].cyl = hd_info[drive].cyl = *(unsigned short *) BIOS;
951 bios_info[drive].head = hd_info[drive].head = *(2+BIOS);
952 bios_info[drive].wpcom = hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
953 bios_info[drive].ctl = hd_info[drive].ctl = *(8+BIOS);
954 bios_info[drive].lzone = hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
955 bios_info[drive].sect = hd_info[drive].sect = *(14+BIOS);
956 #ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
957 if (hd_info[drive].cyl && NR_HD == drive)
958 NR_HD++;
959 #endif
960 BIOS += 16;
961 }
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
986 if (cmos_disks & 0x0f)
987 NR_HD = 2;
988 else
989 NR_HD = 1;
990 }
991 i = NR_HD;
992 while (i-- > 0) {
993 hd[i<<6].nr_sects = 0;
994 if (bios_info[i].head > 16) {
995
996
997
998
999
1000
1001
1002
1003 printk("hd.c: IDE/ST-506 disk with more than 16 heads detected.\n");
1004 printk(" (hd%c: cyl=%d, sect=%d, head=%d)\n", i+'a',
1005 bios_info[i].cyl,
1006 bios_info[i].sect,
1007 bios_info[i].head);
1008 }
1009 hd[i<<6].nr_sects = bios_info[i].head *
1010 bios_info[i].sect * bios_info[i].cyl;
1011 hd_ident_info[i] = NULL;
1012 special_op[i] = 1;
1013 }
1014 if (NR_HD) {
1015 if (irqaction(HD_IRQ,&hd_sigaction)) {
1016 printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
1017 NR_HD = 0;
1018 }
1019 }
1020 hd_gendisk.nr_real = NR_HD;
1021
1022 for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
1023 blksize_size[MAJOR_NR] = hd_blocksizes;
1024 }
1025
1026 static struct file_operations hd_fops = {
1027 NULL,
1028 block_read,
1029 block_write,
1030 NULL,
1031 NULL,
1032 hd_ioctl,
1033 NULL,
1034 hd_open,
1035 hd_release,
1036 block_fsync
1037 };
1038
1039 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
1040 {
1041 if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
1042 printk("Unable to get major %d for harddisk\n",MAJOR_NR);
1043 return mem_start;
1044 }
1045 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1046 read_ahead[MAJOR_NR] = 8;
1047 hd_gendisk.next = gendisk_head;
1048 gendisk_head = &hd_gendisk;
1049 timer_table[HD_TIMER].fn = hd_times_out;
1050 return mem_start;
1051 }
1052
1053 #define DEVICE_BUSY busy[target]
1054 #define USAGE access_count[target]
1055 #define CAPACITY (bios_info[target].head*bios_info[target].sect*bios_info[target].cyl)
1056
1057
1058 #undef MAYBE_REINIT
1059 #define GENDISK_STRUCT hd_gendisk
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 static int revalidate_hddisk(int dev, int maxusage)
1070 {
1071 int target, major;
1072 struct gendisk * gdev;
1073 int max_p;
1074 int start;
1075 int i;
1076 long flags;
1077
1078 target = DEVICE_NR(MINOR(dev));
1079 gdev = &GENDISK_STRUCT;
1080
1081 save_flags(flags);
1082 cli();
1083 if (DEVICE_BUSY || USAGE > maxusage) {
1084 restore_flags(flags);
1085 return -EBUSY;
1086 };
1087 DEVICE_BUSY = 1;
1088 restore_flags(flags);
1089
1090 max_p = gdev->max_p;
1091 start = target << gdev->minor_shift;
1092 major = MAJOR_NR << 8;
1093
1094 for (i=max_p - 1; i >=0 ; i--) {
1095 sync_dev(major | start | i);
1096 invalidate_inodes(major | start | i);
1097 invalidate_buffers(major | start | i);
1098 gdev->part[start+i].start_sect = 0;
1099 gdev->part[start+i].nr_sects = 0;
1100 };
1101
1102 #ifdef MAYBE_REINIT
1103 MAYBE_REINIT;
1104 #endif
1105
1106 gdev->part[start].nr_sects = CAPACITY;
1107 resetup_one_dev(gdev, target);
1108
1109 DEVICE_BUSY = 0;
1110 wake_up(&busy_wait);
1111 return 0;
1112 }
1113