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