1 /* $NetBSD: fd.c,v 1.4 2001/08/31 04:44:58 simonb 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 <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