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] = (struct hd_driveid *)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 cli();
450 hd_request();
451 return;
452 ok_to_read:
453 if (msect) {
454 if ((nsect = CURRENT->current_nr_sectors) > msect)
455 nsect = msect;
456 msect -= nsect;
457 } else
458 nsect = 1;
459 insw(HD_DATA,CURRENT->buffer,nsect<<8);
460 CURRENT->sector += nsect;
461 CURRENT->buffer += nsect<<9;
462 CURRENT->errors = 0;
463 i = (CURRENT->nr_sectors -= nsect);
464
465 #ifdef DEBUG
466 printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=%08lx\n",
467 dev+'a', CURRENT->sector, CURRENT->sector+nsect,
468 CURRENT->nr_sectors, (long) CURRENT->buffer+(nsect<<9));
469 #endif
470 if ((CURRENT->current_nr_sectors -= nsect) <= 0)
471 end_request(1);
472 if (i > 0) {
473 if (msect)
474 goto ok_to_read;
475 SET_INTR(&read_intr);
476 return;
477 }
478 (void) inb_p(HD_STATUS);
479 #if (HD_DELAY > 0)
480 last_req = read_timer();
481 #endif
482 if (CURRENT)
483 hd_request();
484 return;
485 }
486
487 static inline void multwrite (unsigned int dev)
488 {
489 unsigned int mcount = mult_count[dev];
490
491 while (mcount--) {
492 outsw(HD_DATA,WCURRENT.buffer,256);
493 if (!--WCURRENT.nr_sectors)
494 return;
495 WCURRENT.buffer += 512;
496 if (!--WCURRENT.current_nr_sectors) {
497 WCURRENT.bh = WCURRENT.bh->b_reqnext;
498 if (WCURRENT.bh == NULL)
499 panic("buffer list corrupted\n");
500 WCURRENT.current_nr_sectors = WCURRENT.bh->b_size>>9;
501 WCURRENT.buffer = WCURRENT.bh->b_data;
502 }
503 }
504 }
505
506 static void multwrite_intr(void)
507 {
508 int i;
509 unsigned int dev = DEVICE_NR(WCURRENT.dev);
510
511 if (unmask_intr[dev])
512 sti();
513 if (((i = inb_p(HD_STATUS)) & STAT_MASK) == STAT_OK) {
514 if (i & DRQ_STAT) {
515 if (WCURRENT.nr_sectors) {
516 multwrite(dev);
517 SET_INTR(&multwrite_intr);
518 return;
519 }
520 } else {
521 if (!WCURRENT.nr_sectors) {
522 for (i = CURRENT->nr_sectors; i > 0;){
523 i -= CURRENT->current_nr_sectors;
524 end_request(1);
525 }
526 #if (HD_DELAY > 0)
527 last_req = read_timer();
528 #endif
529 if (CURRENT)
530 hd_request();
531 return;
532 }
533 }
534 }
535 sti();
536 printk("hd%c: multwrite_intr: status = 0x%02x\n",dev+'a',i);
537 if (i & ERR_STAT) {
538 hd_error = (unsigned) inb(HD_ERROR);
539 printk("hd:%c multwrite_intr: error = 0x%02x\n",dev+'a',hd_error);
540 }
541 bad_rw_intr();
542 cli();
543 hd_request();
544 }
545
546 static void write_intr(void)
547 {
548 int i;
549 int retries = 100000;
550
551 if (unmask_intr[DEVICE_NR(WCURRENT.dev)])
552 sti();
553 do {
554 i = (unsigned) inb_p(HD_STATUS);
555 if (i & BUSY_STAT)
556 continue;
557 if ((i & STAT_MASK) != STAT_OK)
558 break;
559 if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
560 goto ok_to_write;
561 } while (--retries > 0);
562 sti();
563 printk("HD: write_intr: status = 0x%02x\n",i);
564 if (i & ERR_STAT) {
565 hd_error = (unsigned) inb(HD_ERROR);
566 printk("HD: write_intr: error = 0x%02x\n",hd_error);
567 }
568 bad_rw_intr();
569 cli();
570 hd_request();
571 return;
572 ok_to_write:
573 CURRENT->sector++;
574 i = --CURRENT->nr_sectors;
575 --CURRENT->current_nr_sectors;
576 CURRENT->buffer += 512;
577 if (!i || (CURRENT->bh && !SUBSECTOR(i)))
578 end_request(1);
579 if (i > 0) {
580 SET_INTR(&write_intr);
581 outsw(HD_DATA,CURRENT->buffer,256);
582 sti();
583 } else {
584 #if (HD_DELAY > 0)
585 last_req = read_timer();
586 #endif
587 hd_request();
588 }
589 return;
590 }
591
592 static void recal_intr(void)
593 {
594 if (win_result())
595 bad_rw_intr();
596 #if (HD_DELAY > 0)
597 last_req = read_timer();
598 #endif
599 hd_request();
600 }
601
602
603
604
605
606 static void hd_times_out(void)
607 {
608 DEVICE_INTR = NULL;
609 sti();
610 reset = 1;
611 if (!CURRENT)
612 return;
613 special_op [DEVICE_NR(CURRENT->dev)] ++;
614 printk(KERN_DEBUG "HD timeout\n");
615 cli();
616 if (++CURRENT->errors >= MAX_ERRORS) {
617 #ifdef DEBUG
618 printk("hd : too many errors.\n");
619 #endif
620 end_request(0);
621 }
622
623 hd_request();
624 }
625
626
627
628
629
630
631
632
633 static void hd_request(void)
634 {
635 unsigned int block,dev;
636 unsigned int sec,head,cyl,track;
637 unsigned int nsect;
638
639 if (CURRENT && CURRENT->dev < 0) return;
640
641 if (DEVICE_INTR)
642 return;
643 repeat:
644 timer_active &= ~(1<<HD_TIMER);
645 sti();
646 INIT_REQUEST;
647 dev = MINOR(CURRENT->dev);
648 block = CURRENT->sector;
649 nsect = CURRENT->nr_sectors;
650 if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
651 #ifdef DEBUG
652 printk("hd : attempted read for sector %d past end of device at sector %d.\n",
653 block, hd[dev].nr_sects);
654 #endif
655 end_request(0);
656 goto repeat;
657 }
658 block += hd[dev].start_sect;
659 dev >>= 6;
660 sec = block % hd_info[dev].sect + 1;
661 track = block / hd_info[dev].sect;
662 head = track % hd_info[dev].head;
663 cyl = track / hd_info[dev].head;
664 #ifdef DEBUG
665 printk("hd%c : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
666 dev+'a', cyl, head, sec, CURRENT->buffer);
667 #endif
668 if (!unmask_intr[dev])
669 cli();
670 if (special_op[dev]) {
671 if (reset) {
672 int i;
673
674 for (i=0; i < NR_HD; i++)
675 special_op[i] = recalibrate[i] = 1;
676 cli();
677 reset_hd();
678 return;
679 }
680 if (recalibrate[dev]) {
681 recalibrate[dev] = 0;
682 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
683 if (reset)
684 goto repeat;
685 return;
686 }
687 if (!identified[dev]) {
688 identified[dev] = 1;
689 unmask_intr[dev] = DEFAULT_UNMASK_INTR;
690 mult_req[dev] = DEFAULT_MULT_COUNT;
691 hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
692 if (reset)
693 goto repeat;
694 return;
695 }
696 if (mult_req[dev] != mult_count[dev]) {
697 hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
698 if (reset)
699 goto repeat;
700 return;
701 }
702 if (hd_info[dev].head > 16) {
703 printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
704 end_request(0);
705 goto repeat;
706 }
707 --special_op[dev];
708 }
709 if (CURRENT->cmd == READ) {
710 unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ;
711 hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr);
712 if (reset)
713 goto repeat;
714 #ifdef DEBUG
715 printk("hd%c: reading %d sectors(%ld-%ld), buffer=%08lx\n",
716 dev+'a', nsect, CURRENT->sector,
717 CURRENT->sector+nsect-1, (long) CURRENT->buffer);
718 #endif
719 return;
720 }
721 if (CURRENT->cmd == WRITE) {
722 if (mult_count[dev])
723 hd_out(dev,nsect,sec,head,cyl,WIN_MULTWRITE,&multwrite_intr);
724 else
725 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
726 if (reset)
727 goto repeat;
728 #ifdef DEBUG
729 printk("hd%c: writing %d sectors(%ld-%ld), buffer=%08lx\n",
730 dev+'a', nsect, CURRENT->sector,
731 CURRENT->sector+nsect-1, (long) CURRENT->buffer);
732 #endif
733 if (wait_DRQ()) {
734 printk("hd%c: hd_request: no DRQ\n", dev+'a');
735 bad_rw_intr();
736 goto repeat;
737 }
738 if (mult_count[dev]) {
739 WCURRENT = *CURRENT;
740 multwrite(dev);
741 } else {
742 outsw(HD_DATA,CURRENT->buffer,256);
743 }
744 return;
745 }
746 panic("unknown hd-command");
747 }
748
749 static void do_hd_request (void)
750 {
751 disable_irq(HD_IRQ);
752 hd_request();
753 enable_irq(HD_IRQ);
754 }
755
756 static int hd_ioctl(struct inode * inode, struct file * file,
757 unsigned int cmd, unsigned long arg)
758 {
759 struct hd_geometry *loc = (struct hd_geometry *) arg;
760 int dev, err;
761
762 if ((!inode) || (!inode->i_rdev))
763 return -EINVAL;
764 dev = MINOR(inode->i_rdev) >> 6;
765 if (dev >= NR_HD)
766 return -EINVAL;
767 switch (cmd) {
768 case HDIO_GETGEO:
769 if (!loc) return -EINVAL;
770 err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
771 if (err)
772 return err;
773 put_fs_byte(bios_info[dev].head,
774 (char *) &loc->heads);
775 put_fs_byte(bios_info[dev].sect,
776 (char *) &loc->sectors);
777 put_fs_word(bios_info[dev].cyl,
778 (short *) &loc->cylinders);
779 put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
780 (long *) &loc->start);
781 return 0;
782 case BLKRASET:
783 if(!suser()) return -EACCES;
784 if(arg > 0xff) return -EINVAL;
785 read_ahead[MAJOR(inode->i_rdev)] = arg;
786 return 0;
787 case BLKRAGET:
788 if (!arg) return -EINVAL;
789 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
790 if (err)
791 return err;
792 put_fs_long(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
793 return 0;
794 case BLKGETSIZE:
795 if (!arg) return -EINVAL;
796 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
797 if (err)
798 return err;
799 put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
800 return 0;
801 case BLKFLSBUF:
802 if(!suser()) return -EACCES;
803 fsync_dev(inode->i_rdev);
804 invalidate_buffers(inode->i_rdev);
805 return 0;
806
807 case BLKRRPART:
808 return revalidate_hddisk(inode->i_rdev, 1);
809
810 case HDIO_SETUNMASKINTR:
811 if (!suser()) return -EACCES;
812 if (!arg) return -EINVAL;
813 if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
814 err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
815 if (err)
816 return err;
817 unmask_intr[dev] = get_fs_long((long *) arg);
818 return 0;
819
820 case HDIO_GETUNMASKINTR:
821 if (!arg) return -EINVAL;
822 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
823 if (err)
824 return err;
825 put_fs_long(unmask_intr[dev], (long *) arg);
826 return 0;
827
828 case HDIO_GETMULTCOUNT:
829 if (!arg) return -EINVAL;
830 err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
831 if (err)
832 return err;
833 put_fs_long(mult_count[dev], (long *) arg);
834 return 0;
835
836 case HDIO_SETMULTCOUNT:
837 {
838 unsigned long flags;
839 if (!suser()) return -EACCES;
840 if (!arg) return -EINVAL;
841 if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
842 err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
843 if (err)
844 return err;
845 arg = get_fs_long((long *) arg);
846 save_flags(flags);
847 cli();
848 if (arg > max_mult[dev])
849 err = -EINVAL;
850 else if (mult_req[dev] != mult_count[dev]) {
851 ++special_op[dev];
852 err = -EBUSY;
853 } else {
854 mult_req[dev] = arg;
855 ++special_op[dev];
856 err = 0;
857 }
858 restore_flags(flags);
859 return err;
860 }
861 case HDIO_GETIDENTITY:
862 if (!arg) return -EINVAL;
863 if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
864 if (hd_ident_info[dev] == NULL) return -ENOMSG;
865 err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(struct hd_driveid));
866 if (err)
867 return err;
868 memcpy_tofs((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
869
870 RO_IOCTLS(inode->i_rdev,arg);
871 default:
872 return -EINVAL;
873 }
874 }
875
876 static int hd_open(struct inode * inode, struct file * filp)
877 {
878 int target;
879 target = DEVICE_NR(MINOR(inode->i_rdev));
880
881 while (busy[target])
882 sleep_on(&busy_wait);
883 access_count[target]++;
884 return 0;
885 }
886
887
888
889
890
891 static void hd_release(struct inode * inode, struct file * file)
892 {
893 int target;
894 sync_dev(inode->i_rdev);
895
896 target = DEVICE_NR(MINOR(inode->i_rdev));
897 access_count[target]--;
898
899 }
900
901 static void hd_geninit(void);
902
903 static struct gendisk hd_gendisk = {
904 MAJOR_NR,
905 "hd",
906 6,
907 1 << 6,
908 MAX_HD,
909 hd_geninit,
910 hd,
911 hd_sizes,
912 0,
913 (void *) bios_info,
914 NULL
915 };
916
917 static void hd_interrupt(int unused)
918 {
919 void (*handler)(void) = DEVICE_INTR;
920
921 DEVICE_INTR = NULL;
922 timer_active &= ~(1<<HD_TIMER);
923 if (!handler)
924 handler = unexpected_hd_interrupt;
925 handler();
926 sti();
927 }
928
929
930
931
932
933
934
935
936
937
938 static void hd_geninit(void)
939 {
940 int drive, i;
941 extern struct drive_info drive_info;
942 unsigned char *BIOS = (unsigned char *) &drive_info;
943 int cmos_disks;
944
945 if (!NR_HD) {
946 for (drive=0 ; drive<2 ; drive++) {
947 bios_info[drive].cyl = hd_info[drive].cyl = *(unsigned short *) BIOS;
948 bios_info[drive].head = hd_info[drive].head = *(2+BIOS);
949 bios_info[drive].wpcom = hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
950 bios_info[drive].ctl = hd_info[drive].ctl = *(8+BIOS);
951 bios_info[drive].lzone = hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
952 bios_info[drive].sect = hd_info[drive].sect = *(14+BIOS);
953 #ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
954 if (hd_info[drive].cyl && NR_HD == drive)
955 NR_HD++;
956 #endif
957 BIOS += 16;
958 }
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
983 if (cmos_disks & 0x0f)
984 NR_HD = 2;
985 else
986 NR_HD = 1;
987 }
988 i = NR_HD;
989 while (i-- > 0) {
990 hd[i<<6].nr_sects = 0;
991 if (bios_info[i].head > 16) {
992
993
994
995
996
997
998
999
1000 printk("hd.c: IDE/ST-506 disk with more than 16 heads detected.\n");
1001 printk(" (hd%c: cyl=%d, sect=%d, head=%d)\n", i+'a',
1002 bios_info[i].cyl,
1003 bios_info[i].sect,
1004 bios_info[i].head);
1005 }
1006 hd[i<<6].nr_sects = bios_info[i].head *
1007 bios_info[i].sect * bios_info[i].cyl;
1008 hd_ident_info[i] = NULL;
1009 special_op[i] = 1;
1010 }
1011 if (NR_HD) {
1012 if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
1013 printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
1014 NR_HD = 0;
1015 }
1016 }
1017 hd_gendisk.nr_real = NR_HD;
1018
1019 for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
1020 blksize_size[MAJOR_NR] = hd_blocksizes;
1021 }
1022
1023 static struct file_operations hd_fops = {
1024 NULL,
1025 block_read,
1026 block_write,
1027 NULL,
1028 NULL,
1029 hd_ioctl,
1030 NULL,
1031 hd_open,
1032 hd_release,
1033 block_fsync
1034 };
1035
1036 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
1037 {
1038 if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
1039 printk("Unable to get major %d for harddisk\n",MAJOR_NR);
1040 return mem_start;
1041 }
1042 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1043 read_ahead[MAJOR_NR] = 8;
1044 hd_gendisk.next = gendisk_head;
1045 gendisk_head = &hd_gendisk;
1046 timer_table[HD_TIMER].fn = hd_times_out;
1047 return mem_start;
1048 }
1049
1050 #define DEVICE_BUSY busy[target]
1051 #define USAGE access_count[target]
1052 #define CAPACITY (bios_info[target].head*bios_info[target].sect*bios_info[target].cyl)
1053
1054
1055 #undef MAYBE_REINIT
1056 #define GENDISK_STRUCT hd_gendisk
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066 static int revalidate_hddisk(int dev, int maxusage)
1067 {
1068 int target, major;
1069 struct gendisk * gdev;
1070 int max_p;
1071 int start;
1072 int i;
1073 long flags;
1074
1075 target = DEVICE_NR(MINOR(dev));
1076 gdev = &GENDISK_STRUCT;
1077
1078 save_flags(flags);
1079 cli();
1080 if (DEVICE_BUSY || USAGE > maxusage) {
1081 restore_flags(flags);
1082 return -EBUSY;
1083 };
1084 DEVICE_BUSY = 1;
1085 restore_flags(flags);
1086
1087 max_p = gdev->max_p;
1088 start = target << gdev->minor_shift;
1089 major = MAJOR_NR << 8;
1090
1091 for (i=max_p - 1; i >=0 ; i--) {
1092 sync_dev(major | start | i);
1093 invalidate_inodes(major | start | i);
1094 invalidate_buffers(major | start | i);
1095 gdev->part[start+i].start_sect = 0;
1096 gdev->part[start+i].nr_sects = 0;
1097 };
1098
1099 #ifdef MAYBE_REINIT
1100 MAYBE_REINIT;
1101 #endif
1102
1103 gdev->part[start].nr_sects = CAPACITY;
1104 resetup_one_dev(gdev, target);
1105
1106 DEVICE_BUSY = 0;
1107 wake_up(&busy_wait);
1108 return 0;
1109 }
1110