fd.c revision 1.5 1 /* $NetBSD: fd.c,v 1.5 2003/12/04 13:05:15 keihan Exp $ */
2
3 /*-
4 * Copyright (C) 1997-1998 Kazuki Sakamoto (sakamoto (at) NetBSD.org)
5 * All rights reserved.
6 *
7 * Floppy Disk Drive standalone device driver
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kazuki Sakamoto.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <stand.h>
37 #include "boot.h"
38
39 /*---------------------------------------------------------------------------*
40 * Floppy Disk Controller Define *
41 *---------------------------------------------------------------------------*/
42 /* Floppy Disk Controller Registers */
43 int FDC_PORT[] = { /* fdc base I/O port */
44 0x3f0, /* primary */
45 };
46 #define FDC_DOR(x) (FDC_PORT[x] + 0x2) /* motor drive control bits */
47 #define FDC_STATUS(x) (FDC_PORT[x] + 0x4) /* fdc main status register */
48 #define FDC_DATA(x) (FDC_PORT[x] + 0x5) /* fdc data register */
49 #define FDC_RATE(x) (FDC_PORT[x] + 0x7) /* transfer rate register */
50
51 #define FDC_IRQ 6
52 #define FD_DMA_CHAN 2
53
54 /* fdc main status register */
55 #define RQM 0x80 /* the host can transfer data if set */
56 #define DIO 0x40 /* direction of data transfer. write required if set */
57 #define NON_DMA 0x20 /* fdc have date for transfer in non dma mode */
58 #define CMD_BUSY 0x10 /* command busy if set */
59
60 /* fdc result status */
61 #define ST0_IC_MASK 0xc0 /* interrupt code 00:normal terminate */
62 #define ST1_EN 0x80 /* end of cylinder */
63
64 /* fdc digtal output register */
65 #define DOR_DMAEN 0x08 /* DRQ, nDACK, TC and FINTR output enable */
66 #define DOR_RESET 0x04 /* fdc software reset */
67
68 /* fdc command */
69 #define CMD_RECALIBRATE 0x07 /* recalibrate */
70 #define CMD_SENSE_INT 0x08 /* sense interrupt status */
71 #define CMD_DRV_SENSE 0x04 /* sense drive status */
72 #define CMD_SEEK 0x0f /* seek */
73 #define CMD_FORMAT 0x4d /* format */
74 #define CMD_READ 0x46 /* read e6 */
75 #define CMD_WRITE 0xc5 /* write */
76 #define CMD_VERIFY 0xf6 /* verify */
77 #define CMD_READID 0x4a /* readID */
78 #define CMD_SPECIFY 0x03 /* specify */
79 #define CMD_CONFIG 0x13 /* config */
80 #define CMD_VERSION 0x10 /* version */
81
82 /* command specify value */
83 #define SPECIFY1 ((0x0d<<4)|0x0f)
84 #define SPECIFY2 ((0x01<<1)|0) /* DMA MODE */
85
86 /* fdc result */
87 #define STATUS_MAX 16 /* result status max number */
88 #define RESULT_VERSION 0x90 /* enhanced controller */
89 #define RESULT_SEEK 0x20 /* seek & recalibrate complete flag on status0 */
90
91 /*---------------------------------------------------------------------------*
92 * Floppy Disk Type Define *
93 *---------------------------------------------------------------------------*/
94 struct fdd_type {
95 int seccount; /* sector per track */
96 int secsize; /* byte per sector (uPD765 paramater) */
97 int datalen; /* data length */
98 int gap; /* gap */
99 int gaplen; /* gap length */
100 int cylinder; /* track per media */
101 int maxseccount; /* media max sector count */
102 int step; /* seek step */
103 int rate; /* drive rate (250 or 500kbps) */
104 int heads; /* heads */
105 int f_gap; /* format gap */
106 int mselect; /* drive mode select */
107 char *type_name; /* media type name */
108 };
109 typedef struct fdd_type FDDTYPE;
110
111 #define FDTYPE_MAX 5
112 FDDTYPE fdd_types[FDTYPE_MAX] = {
113 { 18,2,0xff,0x1b,0x54,80,2880,1,0,2,0x6c,0,"2HQ" }, /* 2HD (PC/AT) */
114 { 8,3,0xff,0x35,0x74,77,1232,1,0,2,0x54,1,"2HD" }, /* 2HD (98) */
115 { 15,2,0xff,0x1b,0x54,80,2400,1,0,2,0x54,1,"2HC" }, /* 2HC */
116 { 9,2,0xff,0x23,0x50,80,1440,1,2,2,0x50,1,"2DD9" },/* 2DD 9 sector */
117 { 8,2,0xff,0x3a,0x50,80,1280,1,2,2,0x50,1,"2DD8" },/* 2DD 8 sector */
118 };
119
120 int fdsectors[] = {128, 256, 512, 1024, 2048, 4096};
121 #define SECTOR_MAX 4096
122 #define FDBLK (fdsectors[un->un_type->secsize])
123
124 #define START_CYL 0
125 #define START_SECTOR 1
126
127 #define DELAY(x) delay(100000 * x) /* about 100ms */
128 #define INT_TIMEOUT 3000000
129
130 /*---------------------------------------------------------------------------*
131 * FDC Device Driver Define *
132 *---------------------------------------------------------------------------*/
133 #define CTLR_MAX 1
134 #define UNIT_MAX 2
135
136 struct fd_unit {
137 int ctlr;
138 int unit;
139 int part;
140 u_int un_flags; /* unit status flag */
141 int stat[STATUS_MAX]; /* result code */
142 FDDTYPE *un_type; /* floppy type (pointer) */
143 };
144 typedef struct fd_unit FD_UNIT;
145 FD_UNIT fd_unit[CTLR_MAX][UNIT_MAX];
146
147 /*
148 * un_flags flags
149 */
150 #define INT_ALIVE 0x00000001 /* Device is Alive and Available */
151 #define INT_READY 0x00000002 /* Device is Ready */
152 #define INT_BUSY 0x00000004 /* Device is busy */
153
154 /*---------------------------------------------------------------------------*
155 * Misc define *
156 *---------------------------------------------------------------------------*/
157 #define TIMEOUT 10000000
158 #define ND_TIMEOUT 10000000
159
160 #define SUCCESS 0
161 #define FAIL -1
162
163 /*
164 * function declaration
165 */
166 int fdc_out __P((int, int));
167 int fdc_in __P((int, u_char *));
168 int fdc_intr_wait __P((void));
169 int fd_check __P((FD_UNIT *));
170 void motor_on __P((int, int));
171 void motor_off __P((int, int));
172 void fdReset __P((int));
173 void fdRecalibrate __P((int, int));
174 void fdSpecify __P((int));
175 void fdDriveStatus __P((int, int, int, int *));
176 int fdSeek __P((int, int, int));
177 int fdSenseInt __P((int, int *));
178 int fdReadWrite __P((FD_UNIT *, int, int, int, int, u_char *));
179 void irq_init __P((void));
180 int irq_polling __P((int, int));
181 void dma_setup __P((u_char *, int, int, int));
182 int dma_finished __P((int));
183
184 /*===========================================================================*
185 * fdinit *
186 *===========================================================================*/
187 int
188 fdinit(un)
189 FD_UNIT *un;
190 {
191 int ctlr = un->ctlr;
192 u_char result;
193
194 #if 0
195 irq_init();
196 #endif
197 fdReset(ctlr);
198
199 if (fdc_out(ctlr, CMD_VERSION) != SUCCESS) { /* version check */
200 printf ("fdc%d:fatal error: CMD_VERSION cmd fail\n", ctlr);
201 return (FAIL);
202 }
203 if (fdc_in(ctlr, &result) != SUCCESS) {
204 printf ("fdc%d:fatal error: CMD_VERSION exec fail\n", ctlr);
205 return (FAIL);
206 }
207 if (result != (u_char)RESULT_VERSION) {
208 printf ("fdc%d:fatal error: unknown version fdc\n", ctlr);
209 return (FAIL);
210 }
211
212 un->un_flags = INT_ALIVE;
213 return (SUCCESS);
214 }
215
216 /*===========================================================================*
217 * fdopen *
218 *===========================================================================*/
219 int
220 fdopen(f, ctlr, unit, part)
221 struct open_file *f;
222 int ctlr, unit, part;
223 {
224 FD_UNIT *un;
225 int *stat = un->stat;
226
227 if (ctlr >= CTLR_MAX)
228 return (ENXIO);
229 if (unit >= UNIT_MAX)
230 return (ENXIO);
231 un = &fd_unit[ctlr][unit];
232
233 if (!(un->un_flags & INT_ALIVE)) {
234 if (fdinit(un) != SUCCESS)
235 return (ENXIO);
236 }
237
238 motor_on(ctlr, unit);
239
240 fdRecalibrate(ctlr, unit);
241 fdSenseInt(ctlr, stat);
242 if (stat[1] != START_CYL) {
243 printf("fdc%d: unit:%d recalibrate failed. status:0x%x cyl:%d\n",
244 ctlr, unit, stat[0], stat[1]);
245 motor_off(ctlr, unit);
246 return (EIO);
247 }
248
249 if (fd_check(un) != SUCCESS) /* research disk type */
250 return (EIO);
251
252 f->f_devdata = (void *)un;
253 return (SUCCESS);
254 }
255
256 /*===========================================================================*
257 * fdclose *
258 *===========================================================================*/
259 int
260 fdclose(f)
261 struct open_file *f;
262 {
263 FD_UNIT *un = f->f_devdata;
264
265 fdRecalibrate(un->ctlr, un->unit);
266 fdSenseInt(un->ctlr, un->stat);
267 motor_off(un->ctlr, un->unit);
268 un->un_flags = 0;
269 return (SUCCESS);
270 }
271
272 /*===========================================================================*
273 * fdioctl *
274 *===========================================================================*/
275 int
276 fdioctl(f, cmd, arg)
277 struct open_file *f;
278 u_long cmd;
279 void *arg;
280 {
281 switch (cmd) {
282 default:
283 return (EIO);
284 }
285
286 return (SUCCESS);
287 }
288
289 /*===========================================================================*
290 * fdstrategy *
291 *===========================================================================*/
292 int
293 fdstrategy(devdata, func, blk, size, buf, rsize)
294 void *devdata; /* device uniq data */
295 int func; /* function (read or write) */
296 daddr_t blk; /* block number */
297 size_t size; /* request size in bytes */
298 void *buf; /* buffer */
299 size_t *rsize; /* bytes transferred */
300 {
301 int sectrac, cyl, head, sec;
302 FD_UNIT *un = devdata;
303 int ctlr = un->ctlr;
304 int unit = un->unit;
305 int *stat = un->stat;
306 long nblock, blknum;
307 int fd_skip = 0;
308 char *cbuf = (char *)buf;
309
310 if (un->un_flags & INT_BUSY) {
311 return (ENXIO);
312 }
313 fdDriveStatus(ctlr, unit, 0, stat);
314
315 nblock = un->un_type->maxseccount;
316 sectrac = un->un_type->seccount; /* sector per track */
317 *rsize = 0;
318
319 while (fd_skip < size) {
320 blknum = (u_long)blk * DEV_BSIZE/FDBLK + fd_skip/FDBLK;
321 cyl = blknum / (sectrac * 2);
322 fdSeek(ctlr, unit, cyl);
323 fdSenseInt(ctlr, stat);
324 if (!(stat[0] & RESULT_SEEK)) {
325 printf("fdc%d: unit:%d seek failed."
326 "status:0x%x cyl:%d pcyl:%d\n",
327 ctlr, unit, stat[0], cyl, stat[1]);
328 goto bad;
329 }
330
331 sec = blknum % (sectrac * 2);
332 head = sec / sectrac;
333 sec = sec % sectrac + 1;
334
335 if (fdReadWrite(un, func, cyl, head, sec, cbuf) == FAIL) {
336 printf("fdc%d: unit%d fdReadWrite error [%s]\n",
337 ctlr, unit, (func==F_READ?"READ":"WRITE"));
338 goto bad;
339 }
340
341 *rsize += FDBLK;
342 cbuf += FDBLK;
343 fd_skip += FDBLK;
344 }
345 return (SUCCESS);
346
347 bad:
348 return (FAIL);
349 }
350
351 /*===========================================================================*
352 * fd_check *
353 *===========================================================================*/
354 /*
355 * this function is Check floppy disk Type
356 */
357 int
358 fd_check(un)
359 FD_UNIT *un;
360 {
361 int ctlr = un->ctlr;
362 int unit = un->unit;
363 int *stat = un->stat;
364 int type;
365 static u_char sec_buff[SECTOR_MAX];
366
367 un->un_type = (FDDTYPE *)FAIL;
368 for (type = 0; type < FDTYPE_MAX; type++) {
369 un->un_type = &fdd_types[type];
370
371 /* try read start sector */
372 outb(FDC_RATE(ctlr), un->un_type->rate); /* rate set */
373 fdSpecify(ctlr);
374 fdSeek(ctlr, unit, START_CYL);
375 fdSenseInt(ctlr, stat);
376 if (!(stat[0] & RESULT_SEEK) || stat[1] != START_CYL) {
377 printf("fdc%d: unit:%d seek failed. status:0x%x\n",
378 ctlr, unit, stat[0]);
379 goto bad;
380 }
381 if (fdReadWrite(un, F_READ,
382 START_CYL, 0, START_SECTOR, sec_buff) == FAIL) {
383 continue; /* bad disk type */
384 }
385 break;
386 }
387 if (un->un_type == (FDDTYPE *)FAIL) {
388 printf("fdc%d: unit:%d check disk type failed.\n",
389 ctlr, unit);
390 goto bad;
391 }
392 return (SUCCESS);
393 bad:
394 return (FAIL);
395 }
396
397 /*
398 * for FDC routines.
399 */
400 /*===========================================================================*
401 * fdc_out *
402 *===========================================================================*/
403 int
404 fdc_out(ctlr, cmd)
405 int ctlr; /* controller no */
406 int cmd; /* cmd */
407 {
408 volatile int status;
409 int time_out;
410
411 time_out = TIMEOUT;
412 while (((status = inb(FDC_STATUS(ctlr))) & (RQM | DIO))
413 != (RQM | 0) && time_out-- > 0);
414 if (time_out <= 0) {
415 printf("fdc_out: timeout status = 0x%x\n", status);
416 return (FAIL);
417 }
418
419 outb(FDC_DATA(ctlr), cmd);
420
421 return (SUCCESS);
422 }
423
424 /*===========================================================================*
425 * fdc_in *
426 *===========================================================================*/
427 int
428 fdc_in(ctlr, data)
429 int ctlr; /* controller no */
430 u_char *data;
431 {
432 volatile int status;
433 int time_out;
434
435 time_out = TIMEOUT;
436 while ((status = inb(FDC_STATUS(ctlr)) & (RQM | DIO))
437 != (RQM | DIO) && time_out-- > 0) {
438 if (status == RQM) {
439 printf("fdc_in:error:ready for output\n");
440 return (FAIL);
441 }
442 }
443
444 if (time_out <= 0) {
445 printf("fdc_in:input ready timeout\n");
446 return (FAIL);
447 }
448
449 if (data) *data = (u_char)inb(FDC_DATA(ctlr));
450
451 return (SUCCESS);
452 }
453
454 /*===========================================================================*
455 * fdc_intr_wait *
456 *===========================================================================*/
457 int
458 fdc_intr_wait()
459 {
460 return (irq_polling(FDC_IRQ, INT_TIMEOUT)); /* wait interrupt */
461 }
462
463 /*===========================================================================*
464 * fdc command function *
465 *===========================================================================*/
466 void
467 motor_on(ctlr, unit)
468 int ctlr;
469 int unit;
470 {
471 outb(FDC_DOR(ctlr), DOR_RESET | DOR_DMAEN | unit
472 | (1 << (unit + 4))); /* reset & unit motor on */
473 DELAY(1); /* wait 100msec */
474 }
475
476 void
477 motor_off(ctlr, unit)
478 int ctlr;
479 int unit;
480 {
481 outb(FDC_DOR(ctlr), DOR_RESET); /* reset & motor off */
482 if (fdc_intr_wait() == FAIL) /* wait interrupt */
483 printf("fdc: motor off failed.\n");
484 }
485
486 void
487 fdReset(ctlr)
488 {
489 outb(FDC_DOR(ctlr), 0); /* fdc reset */
490 DELAY(3);
491 outb(FDC_DOR(ctlr), DOR_RESET);
492 DELAY(8);
493 }
494
495 void
496 fdRecalibrate(ctlr, unit)
497 int ctlr;
498 int unit;
499 {
500 fdc_out(ctlr, CMD_RECALIBRATE);
501 fdc_out(ctlr, unit);
502
503 if (fdc_intr_wait() == FAIL) /* wait interrupt */
504 printf("fdc: recalibrate Timeout\n");
505 }
506
507 void
508 fdSpecify(ctlr)
509 int ctlr;
510 {
511 fdc_out(ctlr, CMD_SPECIFY);
512 fdc_out(ctlr, SPECIFY1);
513 fdc_out(ctlr, SPECIFY2);
514 }
515
516 void
517 fdDriveStatus(ctlr, unit, head, stat)
518 int ctlr;
519 register int unit, head;
520 register int *stat;
521 {
522 u_char result;
523
524 fdc_out(ctlr, CMD_DRV_SENSE);
525 fdc_out(ctlr, (head << 2) | unit);
526 fdc_in(ctlr, &result);
527 *stat = (int)(result & 0xff);
528 }
529
530 int
531 fdSeek(ctlr, unit, cyl)
532 int ctlr;
533 int unit;
534 int cyl;
535 {
536 int ret_val = 0;
537
538 fdc_out(ctlr, CMD_SEEK);
539 fdc_out(ctlr, unit);
540 fdc_out(ctlr, cyl);
541
542 if (fdc_intr_wait() == FAIL) { /* wait interrupt */
543 printf("fdc: fdSeek Timeout\n");
544 ret_val = FAIL;
545 }
546
547 return(ret_val);
548 }
549
550 int
551 fdSenseInt(ctlr, stat)
552 int ctlr;
553 int *stat;
554 {
555 u_char result;
556
557 fdc_out(ctlr, CMD_SENSE_INT);
558
559 fdc_in(ctlr, &result);
560 *stat++ = (int)(result & 0xff);
561 fdc_in(ctlr, &result);
562 *stat++ = (int)(result & 0xff);
563
564 return (0);
565 }
566
567 int
568 fdReadWrite(un, func, cyl, head, sec, adrs)
569 FD_UNIT *un;
570 int func;
571 int cyl;
572 int head;
573 int sec;
574 u_char *adrs;
575 {
576 int i;
577 int ctlr = un->ctlr;
578 int unit = un->unit;
579 int *stat = un->stat;
580 u_char result;
581
582 #if 0
583 printf("%s:", (func == F_READ ? "READ" : "WRITE"));
584 printf("cyl = %d", cyl);
585 printf("head = %d", head);
586 printf("sec = %d", sec);
587 printf("secsize = %d", un->un_type->secsize);
588 printf("seccount = %d", un->un_type->seccount);
589 printf("gap = %d", un->un_type->gap);
590 printf("datalen = %d\n", un->un_type->datalen);
591 #endif
592
593 dma_setup(adrs, FDBLK, func, FD_DMA_CHAN);
594 fdc_out(ctlr, (func == F_READ ? CMD_READ : CMD_WRITE));
595 fdc_out(ctlr, (head<<2) | unit);
596 fdc_out(ctlr, cyl); /* cyl */
597 fdc_out(ctlr, head); /* head */
598 fdc_out(ctlr, sec); /* sec */
599 fdc_out(ctlr, un->un_type->secsize); /* secsize */
600 fdc_out(ctlr, un->un_type->seccount); /* EOT (end of track) */
601 fdc_out(ctlr, un->un_type->gap); /* GAP3 */
602 fdc_out(ctlr, un->un_type->datalen); /* DTL (data length) */
603
604 if (fdc_intr_wait() == FAIL) { /* wait interrupt */
605 printf("fdc: DMA transfer Timeout\n");
606 return (FAIL);
607 }
608
609 for (i = 0; i < 7; i++) {
610 fdc_in(ctlr, &result);
611 stat[i] = (int)(result & 0xff);
612 }
613 if (stat[0] & ST0_IC_MASK) { /* not normal terminate */
614 if ((stat[1] & ~ST1_EN) || stat[2])
615 goto bad;
616 }
617 if (!dma_finished(FD_DMA_CHAN)) {
618 printf("DMA not finished\n");
619 goto bad;
620 }
621 return (SUCCESS);
622
623 bad:
624 printf(" func: %s\n", (func == F_READ ? "F_READ" : "F_WRITE"));
625 printf(" st0 = 0x%x\n", stat[0]);
626 printf(" st1 = 0x%x\n", stat[1]);
627 printf(" st2 = 0x%x\n", stat[2]);
628 printf(" c = 0x%x\n", stat[3]);
629 printf(" h = 0x%x\n", stat[4]);
630 printf(" r = 0x%x\n", stat[5]);
631 printf(" n = 0x%x\n", stat[6]);
632 return (FAIL);
633 }
634
635 /*-----------------------------------------------------------------------
636 * Interrupt Controller Operation Functions
637 *-----------------------------------------------------------------------
638 */
639
640 /* 8259A interrupt controller register */
641 #define INT_CTL0 0x20
642 #define INT_CTL1 0x21
643 #define INT2_CTL0 0xA0
644 #define INT2_CTL1 0xA1
645
646 #define CASCADE_IRQ 2
647
648 #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
649 #define ICW4_AT 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
650 #define OCW3_PL 0x0e /* polling mode */
651 #define OCW2_CLEAR 0x20 /* interrupt clear */
652
653 /*
654 * IRC programing sequence
655 *
656 * after reset
657 * 1. ICW1 (write port:INT_CTL0 data:bit4=1)
658 * 2. ICW2 (write port:INT_CTL1)
659 * 3. ICW3 (write port:INT_CTL1)
660 * 4. ICW4 (write port:INT_CTL1)
661 *
662 * after ICW
663 * OCW1 (write port:INT_CTL1)
664 * OCW2 (write port:INT_CTL0 data:bit3=0,bit4=0)
665 * OCW3 (write port:INT_CTL0 data:bit3=1,bit4=0)
666 *
667 * IMR (read port:INT_CTL1)
668 * IRR (read port:INT_CTL0) OCW3(bit1=1,bit0=0)
669 * ISR (read port:INT_CTL0) OCW3(bit1=1,bit0=1)
670 * PL (read port:INT_CTL0) OCW3(bit2=1,bit1=1)
671 */
672
673 u_int INT_MASK;
674 u_int INT2_MASK;
675
676 /*===========================================================================*
677 * irq initialize *
678 *===========================================================================*/
679 void
680 irq_init()
681 {
682 outb(INT_CTL0, ICW1_AT); /* ICW1 */
683 outb(INT_CTL1, 0); /* ICW2 for master */
684 outb(INT_CTL1, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
685 outb(INT_CTL1, ICW4_AT); /* ICW4 */
686
687 outb(INT_CTL1, (INT_MASK = ~(1 << CASCADE_IRQ)));
688 /* IRQ mask(exclusive of cascade) */
689
690 outb(INT2_CTL0, ICW1_AT); /* ICW1 */
691 outb(INT2_CTL1, 8); /* ICW2 for slave */
692 outb(INT2_CTL1, CASCADE_IRQ); /* ICW3 is slave nr */
693 outb(INT2_CTL1, ICW4_AT); /* ICW4 */
694
695 outb(INT2_CTL1, (INT2_MASK = ~0)); /* IRQ 8-15 mask */
696 }
697
698 /*===========================================================================*
699 * irq polling check *
700 *===========================================================================*/
701 int
702 irq_polling(irq_no, timeout)
703 int irq_no;
704 int timeout;
705 {
706 int irc_no;
707 int data;
708 int ret;
709
710 if (irq_no > 8) irc_no = 1;
711 else irc_no = 0;
712
713 outb(irc_no ? INT2_CTL1 : INT_CTL1, ~(1 << (irq_no >> (irc_no * 3))));
714
715 while (--timeout > 0) {
716 outb(irc_no ? INT2_CTL0 : INT_CTL0, OCW3_PL);
717 /* set polling mode */
718 data = inb(irc_no ? INT2_CTL0 : INT_CTL0);
719 if (data & 0x80) { /* if interrupt request */
720 if ((irq_no >> (irc_no * 3)) == (data & 0x7)) {
721 ret = SUCCESS;
722 break;
723 }
724 }
725 }
726 if (!timeout) ret = FAIL;
727
728 if (irc_no) { /* interrupt clear */
729 outb(INT2_CTL0, OCW2_CLEAR | (irq_no >> 3));
730 outb(INT_CTL0, OCW2_CLEAR | CASCADE_IRQ);
731 } else {
732 outb(INT_CTL0, OCW2_CLEAR | irq_no);
733 }
734
735 outb(INT_CTL1, INT_MASK);
736 outb(INT2_CTL1, INT2_MASK);
737
738 return (ret);
739 }
740
741 /*---------------------------------------------------------------------------*
742 * DMA Controller Define *
743 *---------------------------------------------------------------------------*/
744 /* DMA Controller Registers */
745 #define DMA_ADDR 0x004 /* port for low 16 bits of DMA address */
746 #define DMA_LTOP 0x081 /* port for top low 8bit DMA addr(ch2) */
747 #define DMA_HTOP 0x481 /* port for top high 8bit DMA addr(ch2) */
748 #define DMA_COUNT 0x005 /* port for DMA count (count = bytes - 1) */
749 #define DMA_DEVCON 0x008 /* DMA device control register */
750 #define DMA_SR 0x008 /* DMA status register */
751 #define DMA_RESET 0x00D /* DMA software reset register */
752 #define DMA_FLIPFLOP 0x00C /* DMA byte pointer flip-flop */
753 #define DMA_MODE 0x00B /* DMA mode port */
754 #define DMA_INIT 0x00A /* DMA init port */
755
756 #define DMA_RESET_VAL 0x06
757 /* DMA channel commands. */
758 #define DMA_READ 0x46 /* DMA read opcode */
759 #define DMA_WRITE 0x4A /* DMA write opcode */
760
761 /*===========================================================================*
762 * dma_setup *
763 *===========================================================================*/
764 void
765 dma_setup(buf, size, func, chan)
766 u_char *buf;
767 int size;
768 int func;
769 int chan;
770 {
771 u_long pbuf = local_to_PCI((u_long)buf);
772
773 #if 0
774 outb(DMA_RESET, 0);
775 DELAY(1);
776 outb(DMA_DEVCON, 0x00);
777 outb(DMA_INIT, DMA_RESET_VAL); /* reset the dma controller */
778 #endif
779 outb(DMA_MODE, func == F_READ ? DMA_READ : DMA_WRITE);
780 outb(DMA_FLIPFLOP, 0); /* write anything to reset it */
781
782 outb(DMA_ADDR, (int)pbuf >> 0);
783 outb(DMA_ADDR, (int)pbuf >> 8);
784 outb(DMA_LTOP, (int)pbuf >> 16);
785 outb(DMA_HTOP, (int)pbuf >> 24);
786
787 outb(DMA_COUNT, (size - 1) >> 0);
788 outb(DMA_COUNT, (size - 1) >> 8);
789 outb(DMA_INIT, chan); /* some sort of enable */
790 }
791
792 int
793 dma_finished(chan)
794 int chan;
795 {
796 return ((inb(DMA_SR) & 0x0f) == (1 << chan));
797 }
798