1 /* $NetBSD: fd.c,v 1.11 2014/12/12 15:57:30 phx 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 761 dma_finished(int chan) 762 { 763 764 return ((inb(DMA_SR) & 0x0f) == (1 << chan)); 765 } 766