1 /* $NetBSD: fd.c,v 1.12 2022/08/07 11:06:18 andvar Exp $ */
2
3 /*-
4 * Copyright (C) 1997-1998 Kazuki Sakamoto (sakamoto@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 <lib/libsa/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 parameter) */
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 u_int un_flags; /* unit status flag */
140 int stat[STATUS_MAX]; /* result code */
141 FDDTYPE *un_type; /* floppy type (pointer) */
142 };
143 typedef struct fd_unit FD_UNIT;
144 FD_UNIT fd_unit[CTLR_MAX][UNIT_MAX];
145
146 /*
147 * un_flags flags
148 */
149 #define INT_ALIVE 0x00000001 /* Device is Alive and Available */
150 #define INT_READY 0x00000002 /* Device is Ready */
151 #define INT_BUSY 0x00000004 /* Device is busy */
152
153 /*---------------------------------------------------------------------------*
154 * Misc define *
155 *---------------------------------------------------------------------------*/
156 #define TIMEOUT 10000000
157 #define ND_TIMEOUT 10000000
158
159 #define SUCCESS 0
160 #define FAIL -1
161
162 /*
163 * function declaration
164 */
165 int fdinit(FD_UNIT *);
166 int fdopen(struct open_file *, int, int);
167 int fdclose(struct open_file *);
168 int fdioctl(struct open_file *, u_long, void *);
169 int fdstrategy(void *, int, daddr_t, size_t, void *, size_t *);
170 int fdc_out(int, int);
171 int fdc_in(int, u_char *);
172 int fdc_intr_wait(void);
173 int fd_check(FD_UNIT *);
174 void motor_on(int, int);
175 void motor_off(int, int);
176 void fdReset(int);
177 void fdRecalibrate(int, int);
178 void fdSpecify(int);
179 void fdDriveStatus(int, int, int, int *);
180 int fdSeek(int, int, int);
181 int fdSenseInt(int, int *);
182 int fdReadWrite(FD_UNIT *, int, int, int, int, u_char *);
183 void irq_init(void);
184 int irq_polling(int, int);
185 void dma_setup(u_char *, int, int, int);
186 int dma_finished(int);
187
188 /*===========================================================================*
189 * fdinit *
190 *===========================================================================*/
191 int
fdinit(FD_UNIT * un)192 fdinit(FD_UNIT *un)
193 {
194 int ctlr = un->ctlr;
195 u_char result;
196
197 #if 0
198 irq_init();
199 #endif
200 fdReset(ctlr);
201
202 if (fdc_out(ctlr, CMD_VERSION) != SUCCESS) { /* version check */
203 printf ("fdc%d:fatal error: CMD_VERSION cmd fail\n", ctlr);
204 return (FAIL);
205 }
206 if (fdc_in(ctlr, &result) != SUCCESS) {
207 printf ("fdc%d:fatal error: CMD_VERSION exec fail\n", ctlr);
208 return (FAIL);
209 }
210 if (result != (u_char)RESULT_VERSION) {
211 printf ("fdc%d:fatal error: unknown version fdc\n", ctlr);
212 return (FAIL);
213 }
214
215 un->un_flags = INT_ALIVE;
216 return (SUCCESS);
217 }
218
219 /*===========================================================================*
220 * fdopen *
221 *===========================================================================*/
222 int
fdopen(struct open_file * f,int ctlr,int unit)223 fdopen(struct open_file *f, int ctlr, int unit)
224 {
225 FD_UNIT *un;
226 int *stat;
227
228 if (ctlr >= CTLR_MAX)
229 return (ENXIO);
230 if (unit >= UNIT_MAX)
231 return (ENXIO);
232 un = &fd_unit[ctlr][unit];
233 stat = un->stat;
234
235 if (!(un->un_flags & INT_ALIVE)) {
236 if (fdinit(un) != SUCCESS)
237 return (ENXIO);
238 }
239
240 motor_on(ctlr, unit);
241
242 fdRecalibrate(ctlr, unit);
243 fdSenseInt(ctlr, stat);
244 if (stat[1] != START_CYL) {
245 printf("fdc%d: unit:%d recalibrate failed. status:0x%x cyl:%d\n",
246 ctlr, unit, stat[0], stat[1]);
247 motor_off(ctlr, unit);
248 return (EIO);
249 }
250
251 if (fd_check(un) != SUCCESS) /* research disk type */
252 return (EIO);
253
254 f->f_devdata = (void *)un;
255 return (SUCCESS);
256 }
257
258 /*===========================================================================*
259 * fdclose *
260 *===========================================================================*/
261 int
fdclose(struct open_file * f)262 fdclose(struct open_file *f)
263 {
264 FD_UNIT *un = f->f_devdata;
265
266 fdRecalibrate(un->ctlr, un->unit);
267 fdSenseInt(un->ctlr, un->stat);
268 motor_off(un->ctlr, un->unit);
269 un->un_flags = 0;
270 return (SUCCESS);
271 }
272
273 /*===========================================================================*
274 * fdioctl *
275 *===========================================================================*/
276 int
fdioctl(struct open_file * f,u_long cmd,void * arg)277 fdioctl(struct open_file *f, u_long cmd, void *arg)
278 {
279
280 switch (cmd) {
281 default:
282 return (EIO);
283 }
284
285 return (SUCCESS);
286 }
287
288 /*===========================================================================*
289 * fdstrategy *
290 *===========================================================================*/
291 int
fdstrategy(void * devdata,int func,daddr_t blk,size_t size,void * buf,size_t * rsize)292 fdstrategy(void *devdata, int func, daddr_t blk, size_t size, void *buf,
293 size_t *rsize)
294 {
295 int sectrac, cyl, head, sec;
296 FD_UNIT *un = devdata;
297 int ctlr = un->ctlr;
298 int unit = un->unit;
299 int *stat = un->stat;
300 long blknum;
301 int fd_skip = 0;
302 u_char *cbuf = (u_char *)buf;
303
304 if (un->un_flags & INT_BUSY) {
305 return (ENXIO);
306 }
307 fdDriveStatus(ctlr, unit, 0, stat);
308
309 sectrac = un->un_type->seccount; /* sector per track */
310 *rsize = 0;
311
312 while (fd_skip < size) {
313 blknum = (u_long)blk * DEV_BSIZE/FDBLK + fd_skip/FDBLK;
314 cyl = blknum / (sectrac * 2);
315 fdSeek(ctlr, unit, cyl);
316 fdSenseInt(ctlr, stat);
317 if (!(stat[0] & RESULT_SEEK)) {
318 printf("fdc%d: unit:%d seek failed."
319 "status:0x%x cyl:%d pcyl:%d\n",
320 ctlr, unit, stat[0], cyl, stat[1]);
321 goto bad;
322 }
323
324 sec = blknum % (sectrac * 2);
325 head = sec / sectrac;
326 sec = sec % sectrac + 1;
327
328 if (fdReadWrite(un, func, cyl, head, sec, cbuf) == FAIL) {
329 printf("fdc%d: unit%d fdReadWrite error [%s]\n",
330 ctlr, unit, (func==F_READ?"READ":"WRITE"));
331 goto bad;
332 }
333
334 *rsize += FDBLK;
335 cbuf += FDBLK;
336 fd_skip += FDBLK;
337 }
338 return (SUCCESS);
339
340 bad:
341 return (FAIL);
342 }
343
344 /*===========================================================================*
345 * fd_check *
346 *===========================================================================*/
347 /*
348 * this function is Check floppy disk Type
349 */
350 int
fd_check(FD_UNIT * un)351 fd_check(FD_UNIT *un)
352 {
353 int ctlr = un->ctlr;
354 int unit = un->unit;
355 int *stat = un->stat;
356 int type;
357 static u_char sec_buff[SECTOR_MAX];
358
359 un->un_type = (FDDTYPE *)FAIL;
360 for (type = 0; type < FDTYPE_MAX; type++) {
361 un->un_type = &fdd_types[type];
362
363 /* try read start sector */
364 outb(FDC_RATE(ctlr), un->un_type->rate); /* rate set */
365 fdSpecify(ctlr);
366 fdSeek(ctlr, unit, START_CYL);
367 fdSenseInt(ctlr, stat);
368 if (!(stat[0] & RESULT_SEEK) || stat[1] != START_CYL) {
369 printf("fdc%d: unit:%d seek failed. status:0x%x\n",
370 ctlr, unit, stat[0]);
371 goto bad;
372 }
373 if (fdReadWrite(un, F_READ,
374 START_CYL, 0, START_SECTOR, sec_buff) == FAIL) {
375 continue; /* bad disk type */
376 }
377 break;
378 }
379 if (un->un_type == (FDDTYPE *)FAIL) {
380 printf("fdc%d: unit:%d check disk type failed.\n",
381 ctlr, unit);
382 goto bad;
383 }
384 return (SUCCESS);
385 bad:
386 return (FAIL);
387 }
388
389 /*
390 * for FDC routines.
391 */
392 /*===========================================================================*
393 * fdc_out *
394 *===========================================================================*/
395 int
fdc_out(int ctlr,int cmd)396 fdc_out(int ctlr, int cmd)
397 {
398 volatile int status;
399 int time_out;
400
401 time_out = TIMEOUT;
402 while (((status = inb(FDC_STATUS(ctlr))) & (RQM | DIO))
403 != (RQM | 0) && time_out-- > 0);
404 if (time_out <= 0) {
405 printf("fdc_out: timeout status = 0x%x\n", status);
406 return (FAIL);
407 }
408
409 outb(FDC_DATA(ctlr), cmd);
410
411 return (SUCCESS);
412 }
413
414 /*===========================================================================*
415 * fdc_in *
416 *===========================================================================*/
417 int
fdc_in(int ctlr,u_char * data)418 fdc_in(int ctlr, u_char *data)
419 {
420 volatile int status;
421 int time_out;
422
423 time_out = TIMEOUT;
424 while ((status = inb(FDC_STATUS(ctlr)) & (RQM | DIO))
425 != (RQM | DIO) && time_out-- > 0) {
426 if (status == RQM) {
427 printf("fdc_in:error:ready for output\n");
428 return (FAIL);
429 }
430 }
431
432 if (time_out <= 0) {
433 printf("fdc_in:input ready timeout\n");
434 return (FAIL);
435 }
436
437 if (data) *data = (u_char)inb(FDC_DATA(ctlr));
438
439 return (SUCCESS);
440 }
441
442 /*===========================================================================*
443 * fdc_intr_wait *
444 *===========================================================================*/
445 int
fdc_intr_wait(void)446 fdc_intr_wait(void)
447 {
448
449 return (irq_polling(FDC_IRQ, INT_TIMEOUT)); /* wait interrupt */
450 }
451
452 /*===========================================================================*
453 * fdc command function *
454 *===========================================================================*/
455 void
motor_on(int ctlr,int unit)456 motor_on(int ctlr, int unit)
457 {
458
459 outb(FDC_DOR(ctlr), DOR_RESET | DOR_DMAEN | unit
460 | (1 << (unit + 4))); /* reset & unit motor on */
461 DELAY(1); /* wait 100msec */
462 }
463
464 void
motor_off(int ctlr,int unit)465 motor_off(int ctlr, int unit)
466 {
467
468 outb(FDC_DOR(ctlr), DOR_RESET); /* reset & motor off */
469 if (fdc_intr_wait() == FAIL) /* wait interrupt */
470 printf("fdc: motor off failed.\n");
471 }
472
473 void
fdReset(int ctlr)474 fdReset(int ctlr)
475 {
476
477 outb(FDC_DOR(ctlr), 0); /* fdc reset */
478 DELAY(3);
479 outb(FDC_DOR(ctlr), DOR_RESET);
480 DELAY(8);
481 }
482
483 void
fdRecalibrate(int ctlr,int unit)484 fdRecalibrate(int ctlr, int unit)
485 {
486
487 fdc_out(ctlr, CMD_RECALIBRATE);
488 fdc_out(ctlr, unit);
489
490 if (fdc_intr_wait() == FAIL) /* wait interrupt */
491 printf("fdc: recalibrate Timeout\n");
492 }
493
494 void
fdSpecify(int ctlr)495 fdSpecify(int ctlr)
496 {
497
498 fdc_out(ctlr, CMD_SPECIFY);
499 fdc_out(ctlr, SPECIFY1);
500 fdc_out(ctlr, SPECIFY2);
501 }
502
503 void
fdDriveStatus(int ctlr,register int unit,register int head,register int * stat)504 fdDriveStatus(int ctlr, register int unit, register int head,
505 register int *stat)
506 {
507 u_char result;
508
509 fdc_out(ctlr, CMD_DRV_SENSE);
510 fdc_out(ctlr, (head << 2) | unit);
511 fdc_in(ctlr, &result);
512 *stat = (int)(result & 0xff);
513 }
514
515 int
fdSeek(int ctlr,int unit,int cyl)516 fdSeek(int ctlr, int unit, int cyl)
517 {
518 int ret_val = 0;
519
520 fdc_out(ctlr, CMD_SEEK);
521 fdc_out(ctlr, unit);
522 fdc_out(ctlr, cyl);
523
524 if (fdc_intr_wait() == FAIL) { /* wait interrupt */
525 printf("fdc: fdSeek Timeout\n");
526 ret_val = FAIL;
527 }
528
529 return(ret_val);
530 }
531
532 int
fdSenseInt(int ctlr,int * stat)533 fdSenseInt(int ctlr, int *stat)
534 {
535 u_char result;
536
537 fdc_out(ctlr, CMD_SENSE_INT);
538
539 fdc_in(ctlr, &result);
540 *stat++ = (int)(result & 0xff);
541 fdc_in(ctlr, &result);
542 *stat++ = (int)(result & 0xff);
543
544 return (0);
545 }
546
547 int
fdReadWrite(FD_UNIT * un,int func,int cyl,int head,int sec,u_char * adrs)548 fdReadWrite(FD_UNIT *un, int func, int cyl, int head, int sec, u_char *adrs)
549 {
550 int i;
551 int ctlr = un->ctlr;
552 int unit = un->unit;
553 int *stat = un->stat;
554 u_char result;
555
556 #if 0
557 printf("%s:", (func == F_READ ? "READ" : "WRITE"));
558 printf("cyl = %d", cyl);
559 printf("head = %d", head);
560 printf("sec = %d", sec);
561 printf("secsize = %d", un->un_type->secsize);
562 printf("seccount = %d", un->un_type->seccount);
563 printf("gap = %d", un->un_type->gap);
564 printf("datalen = %d\n", un->un_type->datalen);
565 #endif
566
567 dma_setup(adrs, FDBLK, func, FD_DMA_CHAN);
568 fdc_out(ctlr, (func == F_READ ? CMD_READ : CMD_WRITE));
569 fdc_out(ctlr, (head<<2) | unit);
570 fdc_out(ctlr, cyl); /* cyl */
571 fdc_out(ctlr, head); /* head */
572 fdc_out(ctlr, sec); /* sec */
573 fdc_out(ctlr, un->un_type->secsize); /* secsize */
574 fdc_out(ctlr, un->un_type->seccount); /* EOT (end of track) */
575 fdc_out(ctlr, un->un_type->gap); /* GAP3 */
576 fdc_out(ctlr, un->un_type->datalen); /* DTL (data length) */
577
578 if (fdc_intr_wait() == FAIL) { /* wait interrupt */
579 printf("fdc: DMA transfer Timeout\n");
580 return (FAIL);
581 }
582
583 for (i = 0; i < 7; i++) {
584 fdc_in(ctlr, &result);
585 stat[i] = (int)(result & 0xff);
586 }
587 if (stat[0] & ST0_IC_MASK) { /* not normal terminate */
588 if ((stat[1] & ~ST1_EN) || stat[2])
589 goto bad;
590 }
591 if (!dma_finished(FD_DMA_CHAN)) {
592 printf("DMA not finished\n");
593 goto bad;
594 }
595 return (SUCCESS);
596
597 bad:
598 printf(" func: %s\n", (func == F_READ ? "F_READ" : "F_WRITE"));
599 printf(" st0 = 0x%x\n", stat[0]);
600 printf(" st1 = 0x%x\n", stat[1]);
601 printf(" st2 = 0x%x\n", stat[2]);
602 printf(" c = 0x%x\n", stat[3]);
603 printf(" h = 0x%x\n", stat[4]);
604 printf(" r = 0x%x\n", stat[5]);
605 printf(" n = 0x%x\n", stat[6]);
606 return (FAIL);
607 }
608
609 /*-----------------------------------------------------------------------
610 * Interrupt Controller Operation Functions
611 *-----------------------------------------------------------------------
612 */
613
614 /* 8259A interrupt controller register */
615 #define INT_CTL0 0x20
616 #define INT_CTL1 0x21
617 #define INT2_CTL0 0xA0
618 #define INT2_CTL1 0xA1
619
620 #define CASCADE_IRQ 2
621
622 #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
623 #define ICW4_AT 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
624 #define OCW3_PL 0x0e /* polling mode */
625 #define OCW2_CLEAR 0x20 /* interrupt clear */
626
627 /*
628 * IRC programing sequence
629 *
630 * after reset
631 * 1. ICW1 (write port:INT_CTL0 data:bit4=1)
632 * 2. ICW2 (write port:INT_CTL1)
633 * 3. ICW3 (write port:INT_CTL1)
634 * 4. ICW4 (write port:INT_CTL1)
635 *
636 * after ICW
637 * OCW1 (write port:INT_CTL1)
638 * OCW2 (write port:INT_CTL0 data:bit3=0,bit4=0)
639 * OCW3 (write port:INT_CTL0 data:bit3=1,bit4=0)
640 *
641 * IMR (read port:INT_CTL1)
642 * IRR (read port:INT_CTL0) OCW3(bit1=1,bit0=0)
643 * ISR (read port:INT_CTL0) OCW3(bit1=1,bit0=1)
644 * PL (read port:INT_CTL0) OCW3(bit2=1,bit1=1)
645 */
646
647 u_int INT_MASK;
648 u_int INT2_MASK;
649
650 /*===========================================================================*
651 * irq initialize *
652 *===========================================================================*/
653 void
irq_init(void)654 irq_init(void)
655 {
656 outb(INT_CTL0, ICW1_AT); /* ICW1 */
657 outb(INT_CTL1, 0); /* ICW2 for master */
658 outb(INT_CTL1, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
659 outb(INT_CTL1, ICW4_AT); /* ICW4 */
660
661 outb(INT_CTL1, (INT_MASK = ~(1 << CASCADE_IRQ)));
662 /* IRQ mask(exclusive of cascade) */
663
664 outb(INT2_CTL0, ICW1_AT); /* ICW1 */
665 outb(INT2_CTL1, 8); /* ICW2 for slave */
666 outb(INT2_CTL1, CASCADE_IRQ); /* ICW3 is slave nr */
667 outb(INT2_CTL1, ICW4_AT); /* ICW4 */
668
669 outb(INT2_CTL1, (INT2_MASK = ~0)); /* IRQ 8-15 mask */
670 }
671
672 /*===========================================================================*
673 * irq polling check *
674 *===========================================================================*/
675 int
irq_polling(int irq_no,int timeout)676 irq_polling(int irq_no, int timeout)
677 {
678 int irc_no;
679 int data;
680 int ret;
681
682 if (irq_no > 8) irc_no = 1;
683 else irc_no = 0;
684
685 outb(irc_no ? INT2_CTL1 : INT_CTL1, ~(1 << (irq_no >> (irc_no * 3))));
686
687 while (--timeout > 0) {
688 outb(irc_no ? INT2_CTL0 : INT_CTL0, OCW3_PL);
689 /* set polling mode */
690 data = inb(irc_no ? INT2_CTL0 : INT_CTL0);
691 if (data & 0x80) { /* if interrupt request */
692 if ((irq_no >> (irc_no * 3)) == (data & 0x7)) {
693 ret = SUCCESS;
694 break;
695 }
696 }
697 }
698 if (!timeout) ret = FAIL;
699
700 if (irc_no) { /* interrupt clear */
701 outb(INT2_CTL0, OCW2_CLEAR | (irq_no >> 3));
702 outb(INT_CTL0, OCW2_CLEAR | CASCADE_IRQ);
703 } else {
704 outb(INT_CTL0, OCW2_CLEAR | irq_no);
705 }
706
707 outb(INT_CTL1, INT_MASK);
708 outb(INT2_CTL1, INT2_MASK);
709
710 return (ret);
711 }
712
713 /*---------------------------------------------------------------------------*
714 * DMA Controller Define *
715 *---------------------------------------------------------------------------*/
716 /* DMA Controller Registers */
717 #define DMA_ADDR 0x004 /* port for low 16 bits of DMA address */
718 #define DMA_LTOP 0x081 /* port for top low 8bit DMA addr(ch2) */
719 #define DMA_HTOP 0x481 /* port for top high 8bit DMA addr(ch2) */
720 #define DMA_COUNT 0x005 /* port for DMA count (count = bytes - 1) */
721 #define DMA_DEVCON 0x008 /* DMA device control register */
722 #define DMA_SR 0x008 /* DMA status register */
723 #define DMA_RESET 0x00D /* DMA software reset register */
724 #define DMA_FLIPFLOP 0x00C /* DMA byte pointer flip-flop */
725 #define DMA_MODE 0x00B /* DMA mode port */
726 #define DMA_INIT 0x00A /* DMA init port */
727
728 #define DMA_RESET_VAL 0x06
729 /* DMA channel commands. */
730 #define DMA_READ 0x46 /* DMA read opcode */
731 #define DMA_WRITE 0x4A /* DMA write opcode */
732
733 /*===========================================================================*
734 * dma_setup *
735 *===========================================================================*/
736 void
dma_setup(u_char * buf,int size,int func,int chan)737 dma_setup(u_char *buf, int size, int func, int chan)
738 {
739 u_long pbuf = local_to_PCI((u_long)buf);
740
741 #if 0
742 outb(DMA_RESET, 0);
743 DELAY(1);
744 outb(DMA_DEVCON, 0x00);
745 outb(DMA_INIT, DMA_RESET_VAL); /* reset the dma controller */
746 #endif
747 outb(DMA_MODE, func == F_READ ? DMA_READ : DMA_WRITE);
748 outb(DMA_FLIPFLOP, 0); /* write anything to reset it */
749
750 outb(DMA_ADDR, (int)pbuf >> 0);
751 outb(DMA_ADDR, (int)pbuf >> 8);
752 outb(DMA_LTOP, (int)pbuf >> 16);
753 outb(DMA_HTOP, (int)pbuf >> 24);
754
755 outb(DMA_COUNT, (size - 1) >> 0);
756 outb(DMA_COUNT, (size - 1) >> 8);
757 outb(DMA_INIT, chan); /* some sort of enable */
758 }
759
760 int
dma_finished(int chan)761 dma_finished(int chan)
762 {
763
764 return ((inb(DMA_SR) & 0x0f) == (1 << chan));
765 }
766