1 /* $NetBSD: edc_mca.c,v 1.6 2001/04/23 06:10:08 jdolecek Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Jaromir Dolecek. 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 the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /* 37 * Driver for MCA ESDI controllers and disks conforming to IBM DASD 38 * spec. 39 * 40 * The driver was written with DASD Storage Interface Specification 41 * for MCA rev. 2.2 in hands, thanks to Scott Telford <st@epcc.ed.ac.uk>. 42 * 43 * TODO: 44 * - finish support for kernel memory crash dump 45 * - move the MCA DMA controller (edc_setup_dma()) goo to device driver 46 * independant location 47 * - improve error recovery 48 * add any soft resets when anything gets stuck? 49 * - test with > 1 disk (this is supported by some controllers), eliminate 50 * any remaining devno=0 assumptions if there are any still 51 * - test with > 1 ESDI controller in machine; shared interrupts 52 * necessary for this to work should be supported - edc_intr() specifically 53 * checks if the interrupt is for this controller 54 */ 55 56 #include "rnd.h" 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/errno.h> 61 #include <sys/device.h> 62 #include <sys/malloc.h> 63 #include <sys/endian.h> 64 #include <sys/disklabel.h> 65 #include <sys/disk.h> 66 #include <sys/syslog.h> 67 #include <sys/proc.h> 68 #include <sys/vnode.h> 69 #include <sys/kernel.h> 70 #if NRND > 0 71 #include <sys/rnd.h> 72 #endif 73 74 #include <machine/bus.h> 75 #include <machine/intr.h> 76 77 #include <dev/mca/mcareg.h> 78 #include <dev/mca/mcavar.h> 79 #include <dev/mca/mcadevs.h> 80 81 #include <dev/mca/edcreg.h> 82 #include <dev/mca/edvar.h> 83 #include <dev/mca/edcvar.h> 84 85 #define DASD_MAXDEVS 7 86 struct edc_mca_softc { 87 struct device sc_dev; 88 89 bus_space_tag_t sc_iot; 90 bus_space_handle_t sc_ioh; 91 92 bus_dma_tag_t sc_dmat; /* DMA tag as passed by parent */ 93 bus_space_handle_t sc_dmaextcmdh; 94 bus_space_handle_t sc_dmaexech; 95 96 void *sc_ih; /* interrupt handle */ 97 int sc_drq; /* DRQ number */ 98 int sc_cmd_async; /* asynchronous cmd pending */ 99 100 int sc_flags; 101 #define DASD_QUIET 0x01 /* don't dump cmd error info */ 102 struct ed_softc *sc_ed[DASD_MAXDEVS]; 103 104 int sc_maxdevs; /* maximum # of devs supported by 105 * controller */ 106 }; 107 108 int edc_mca_probe __P((struct device *, struct cfdata *, void *)); 109 void edc_mca_attach __P((struct device *, struct device *, void *)); 110 111 struct cfattach edc_mca_ca = { 112 sizeof(struct edc_mca_softc), edc_mca_probe, edc_mca_attach 113 }; 114 115 #define DMA_EXTCMD 0x18 116 #define DMA_EXEC 0x1A 117 118 static int edc_intr __P((void *)); 119 static void edc_attach_ed __P((struct device *)); 120 static void edc_dump_status_block __P((struct edc_mca_softc *, int, int)); 121 static int edc_setup_dma __P((struct edc_mca_softc *, struct buf *, 122 bus_addr_t, bus_size_t)); 123 static int edc_do_attn __P((struct edc_mca_softc *, int, int, int)); 124 125 int 126 edc_mca_probe(parent, match, aux) 127 struct device *parent; 128 struct cfdata *match; 129 void *aux; 130 { 131 struct mca_attach_args *ma = aux; 132 133 switch (ma->ma_id) { 134 case MCA_PRODUCT_IBM_ESDIC: 135 case MCA_PRODUCT_IBM_ESDIC_IG: 136 return (1); 137 default: 138 return (0); 139 } 140 } 141 142 void 143 edc_mca_attach(parent, self, aux) 144 struct device *parent, *self; 145 void *aux; 146 { 147 struct edc_mca_softc *sc = (void *) self; 148 struct mca_attach_args *ma = aux; 149 int pos2, pos3, pos4; 150 int irq, drq, iobase; 151 const char *typestr; 152 153 pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2); 154 pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3); 155 pos4 = mca_conf_read(ma->ma_mc, ma->ma_slot, 4); 156 157 /* 158 * POS register 2: (adf pos0) 159 * 160 * 7 6 5 4 3 2 1 0 161 * \ \____/ \ \__ enable: 0=adapter disabled, 1=adapter enabled 162 * \ \ \___ Primary/Alternate Port Adresses: 163 * \ \ 0=0x3510-3517 1=0x3518-0x351f 164 * \ \_____ DMA Arbitration Level: 0101=5 0110=6 0111=7 165 * \ 0000=0 0001=1 0011=3 0100=4 166 * \_________ Fairness On/Off: 1=On 0=Off 167 * 168 * POS register 3: (adf pos1) 169 * 170 * 7 6 5 4 3 2 1 0 171 * 0 0 \_/ 172 * \__________ DMA Burst Pacing Interval: 10=24ms 11=31ms 173 * 01=16ms 00=Burst Disabled 174 * 175 * POS register 4: (adf pos2) 176 * 177 * 7 6 5 4 3 2 1 0 178 * \_/ \__ DMA Pacing Control: 1=Disabled 0=Enabled 179 * \____ Time to Release: 1X=6ms 01=3ms 00=Immediate 180 * 181 * IRQ is fixed to 14 (0x0e). 182 */ 183 184 switch (ma->ma_id) { 185 case MCA_PRODUCT_IBM_ESDIC: 186 typestr = "IBM ESDI Fixed Disk Controller"; 187 break; 188 case MCA_PRODUCT_IBM_ESDIC_IG: 189 typestr = "IBM Integ. ESDI Fixed Disk & Controller"; 190 break; 191 default: 192 /* never reached */ 193 } 194 195 irq = ESDIC_IRQ; 196 iobase = (pos2 & IO_IS_ALT) ? ESDIC_IOALT : ESDIC_IOPRM; 197 drq = (pos2 & DRQ_MASK) >> 2; 198 199 printf(" slot %d irq %d: %s\n", ma->ma_slot+1, irq, typestr); 200 201 #ifdef DIAGNOSTIC 202 /* 203 * It's not strictly necessary to check this, machine configuration 204 * utility uses only valid adresses. 205 */ 206 if (drq == 2 || drq >= 8) { 207 printf("%s: invalid DMA Arbitration Level %d\n", 208 sc->sc_dev.dv_xname, drq); 209 return; 210 } 211 #endif 212 213 printf("%s: Fairness %s, Release %s, DRQ %d, ", 214 sc->sc_dev.dv_xname, 215 (pos2 & FAIRNESS_ENABLE) ? "On" : "Off", 216 (pos4 & RELEASE_1) ? "6ms" 217 : ((pos4 & RELEASE_2) ? "3ms" : "Immediate"), 218 drq); 219 if ((pos4 & PACING_CTRL_DISABLE) == 0) { 220 static const char * const pacint[] = 221 { "disabled", "16ms", "24ms", "31ms"}; 222 printf("DMA burst pacing interval %s\n", 223 pacint[(pos3 & PACING_INT_MASK) >> 4]); 224 } else 225 printf("DMA pacing control disabled\n"); 226 227 sc->sc_iot = ma->ma_iot; 228 sc->sc_drq = drq; 229 230 if (bus_space_map(sc->sc_iot, iobase, 231 ESDIC_REG_NPORTS, 0, &sc->sc_ioh)) { 232 printf("%s: couldn't map registers\n", 233 sc->sc_dev.dv_xname); 234 return; 235 } 236 237 if (bus_space_map(sc->sc_iot, DMA_EXTCMD, 1, 0, &sc->sc_dmaextcmdh)) { 238 printf("%s: couldn't map registers\n", 239 sc->sc_dev.dv_xname); 240 return; 241 } 242 if (bus_space_map(sc->sc_iot, DMA_EXEC, 1, 0, &sc->sc_dmaexech)) { 243 printf("%s: couldn't map registers\n", 244 sc->sc_dev.dv_xname); 245 return; 246 } 247 248 sc->sc_dmat = ma->ma_dmat; 249 250 sc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_BIO, edc_intr, sc); 251 if (sc->sc_ih == NULL) { 252 printf("%s: couldn't establish interrupt handler\n", 253 sc->sc_dev.dv_xname); 254 return; 255 } 256 257 /* 258 * Integrated ESDI controller supports only one disk, other 259 * controllers support two disks. 260 */ 261 if (ma->ma_id == MCA_PRODUCT_IBM_ESDIC_IG) 262 sc->sc_maxdevs = 1; 263 else 264 sc->sc_maxdevs = 2; 265 266 /* Defer probe for individual disks until interrupts are enabled. */ 267 config_interrupts(self, edc_attach_ed); 268 } 269 270 /* 271 * Try to attach ed* at edc? if any configured and installed now 272 * that interrupts are enabled. 273 */ 274 static void 275 edc_attach_ed(self) 276 struct device *self; 277 { 278 struct edc_mca_softc *sc = (void *) self; 279 struct ed_softc *ed; 280 struct ed_attach_args eda; 281 int devno; 282 283 /* Do a reset to ensure sane state after warm boot. */ 284 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY) { 285 /* hard reset */ 286 printf("%s: controller busy, performing hardware reset ...\n", 287 sc->sc_dev.dv_xname); 288 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, 289 BCR_INT_ENABLE|BCR_RESET); 290 } else { 291 /* "SOFT" reset */ 292 edc_do_attn(sc, ATN_RESET_ATTACHMENT, DASD_DEVNO_CONTROLLER,0); 293 } 294 295 /* Wait until the reset completes. */ 296 while(bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY) 297 delay(1); 298 299 /* 300 * Get dummy ed_softc to be used during probe. Once a disk is 301 * found, ed_mca_attach() calls edc_add_disk() to insert the 302 * right pointer into sc->sc_ed[] array. 303 */ 304 MALLOC(ed, struct ed_softc *, sizeof(struct ed_softc), 305 M_TEMP, M_WAITOK); 306 307 /* be quiet duting probes */ 308 sc->sc_flags |= DASD_QUIET; 309 310 /* check for attached disks */ 311 for(devno=0; devno < sc->sc_maxdevs; devno++) { 312 eda.sc_devno = devno; 313 eda.sc_dmat = sc->sc_dmat; 314 sc->sc_ed[devno] = ed; 315 sc->sc_ed[devno] = 316 (void *) config_found_sm(self, &eda, NULL, NULL); 317 } 318 319 /* enable full error dumps again */ 320 sc->sc_flags &= ~DASD_QUIET; 321 322 /* cleanup */ 323 FREE(ed, M_TEMP); 324 325 /* XXX disestablish interrupt if no disks found ? */ 326 } 327 328 void 329 edc_add_disk(sc, ed, devno) 330 struct edc_mca_softc *sc; 331 struct ed_softc *ed; 332 int devno; 333 { 334 sc->sc_ed[devno] = ed; 335 } 336 337 static int 338 edc_intr(arg) 339 void *arg; 340 { 341 struct edc_mca_softc *sc = arg; 342 u_int8_t isr, intr_id; 343 u_int16_t sifr; 344 int cmd=-1, devno, bioerror=0; 345 struct ed_softc *ed=NULL; 346 347 /* 348 * Check if the interrupt was for us. 349 */ 350 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_INTR) == 0) 351 return (0); 352 353 /* 354 * Read ISR to find out interrupt type. This also clears the interrupt 355 * condition and BSR_INTR flag. Accordings to docs interrupt ID of 0, 2 356 * and 4 are reserved and not used. 357 */ 358 isr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ISR); 359 intr_id = isr & ISR_INTR_ID_MASK; 360 361 #ifdef DEBUG 362 if (intr_id == 0 || intr_id == 2 || intr_id == 4) { 363 printf("%s: bogus interrupt id %d\n", sc->sc_dev.dv_xname, 364 (int) intr_id); 365 return (0); 366 } 367 #endif 368 369 /* Get number of device whose intr this was */ 370 devno = (isr & 0xe0) >> 5; 371 372 /* 373 * Get Status block. Higher byte always says how long the status 374 * block is, rest is device number and command code. 375 * Check the status block length against our supported maximum length 376 * and fetch the data. 377 */ 378 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh,BSR) & BSR_SIFR_FULL 379 && intr_id != ISR_RESET_COMPLETED) { 380 size_t len; 381 int i; 382 383 sifr = le16toh(bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR)); 384 len = (sifr & 0xff00) >> 8; 385 if (len > DASD_MAX_CMD_RES_LEN) { 386 printf("%s: maximum Status Length exceeded: %d > %d\n", 387 sc->sc_dev.dv_xname, 388 len, DASD_MAX_CMD_RES_LEN); 389 goto attn_eoi; 390 } 391 392 /* Get command code */ 393 cmd = sifr & SIFR_CMD_MASK; 394 395 /* Read whole status block */ 396 ed = sc->sc_ed[devno]; 397 ed->sc_status_block[0] = sifr; 398 for(i=1; i < len; i++) { 399 while((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) 400 & BSR_SIFR_FULL) == 0) 401 delay(1); 402 403 ed->sc_status_block[i] = le16toh( 404 bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR)); 405 } 406 } 407 408 switch (intr_id) { 409 case ISR_DATA_TRANSFER_RDY: 410 /* 411 * Ready to do DMA, setup DMA controller and kick DASD 412 * controller to do the transfer. 413 */ 414 ed = sc->sc_ed[devno]; 415 if (!edc_setup_dma(sc, ed->sc_bp, 416 ed->dmamap_xfer->dm_segs[0].ds_addr, 417 ed->dmamap_xfer->dm_segs[0].ds_len)) { 418 /* XXX bail out? */ 419 printf("%s: edc_setup_dma() failed\n", 420 ed->sc_dev.dv_xname); 421 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, 422 BCR_INT_ENABLE); 423 } else { 424 /* OK, proceed with DMA */ 425 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, 426 BCR_INT_ENABLE|BCR_DMA_ENABLE); 427 } 428 break; 429 case ISR_COMPLETED: 430 case ISR_COMPLETED_WITH_ECC: 431 case ISR_COMPLETED_RETRIES: 432 case ISR_COMPLETED_WARNING: 433 bioerror = 0; 434 break; 435 case ISR_RESET_COMPLETED: 436 case ISR_ABORT_COMPLETED: 437 /* nothing to do */ 438 break; 439 default: 440 if ((sc->sc_flags & DASD_QUIET) == 0) 441 edc_dump_status_block(sc, devno, intr_id); 442 443 bioerror = EIO; 444 break; 445 } 446 447 attn_eoi: 448 /* 449 * Unless the interrupt is for Data Transfer Ready or 450 * Attention Error, finish by assertion EOI. This makes 451 * attachment aware the interrupt is processed and system 452 * is ready to accept another one. 453 */ 454 if (intr_id != ISR_DATA_TRANSFER_RDY && intr_id != ISR_ATTN_ERROR) 455 edc_do_attn(sc, ATN_END_INT, devno, intr_id); 456 457 /* If Read or Write Data, wakeup worker thread to finish it */ 458 if (intr_id != ISR_DATA_TRANSFER_RDY 459 && (cmd == CMD_READ_DATA || cmd == CMD_WRITE_DATA)) { 460 sc->sc_ed[devno]->sc_error = bioerror; 461 sc->sc_ed[devno]->sc_flags |= EDF_IODONE; 462 wakeup_one(&sc->sc_ed[devno]->edc_softc); 463 } 464 465 return (1); 466 } 467 468 /* 469 * This follows the exact order for Attention Request as 470 * written in DASD Storage Interface Specification MC (Rev 2.2). 471 */ 472 static int 473 edc_do_attn(sc, attn_type, devno, intr_id) 474 struct edc_mca_softc *sc; 475 int attn_type, devno, intr_id; 476 { 477 int tries; 478 479 /* 1. Disable interrupts in BCR. */ 480 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, 0); 481 482 /* 2. Assure NOT BUSY and NO INTERRUPT PENDING, unless acknowledging 483 * a RESET COMPLETED interrupt. */ 484 if (intr_id != ISR_RESET_COMPLETED) { 485 for(tries=0; tries < 1000; tries++) { 486 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) 487 & (BSR_INT_PENDING|BSR_BUSY)) == 0) 488 break; 489 } 490 491 if (tries == 1000) { 492 printf("%s: edc_do_attn: timeout waiting for attachment to become available\n", 493 (devno == DASD_DEVNO_CONTROLLER) 494 ? sc->sc_dev.dv_xname 495 : sc->sc_ed[devno]->sc_dev.dv_xname); 496 return (EAGAIN); 497 } 498 } 499 500 /* 501 * 3. Write proper DEVICE NUMBER and Attention number to ATN. 502 */ 503 bus_space_write_1(sc->sc_iot, sc->sc_ioh, ATN, 504 attn_type | (devno << 5)); 505 506 /* 507 * 4. Enable interrupts via BCR. 508 */ 509 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, BCR_INT_ENABLE); 510 511 return (0); 512 } 513 514 /* 515 * Wait until command is processed, timeout after 'secs' seconds. 516 * We use mono_time, since we don't need actual RTC, just time 517 * interval. 518 */ 519 int 520 edc_cmd_wait(sc, devno, secs) 521 struct edc_mca_softc *sc; 522 int devno, secs; 523 { 524 struct timeval start, now; 525 int s; 526 527 s = splclock(); 528 start = mono_time; 529 splx(s); 530 531 while((bus_space_read_1(sc->sc_iot,sc->sc_ioh,BSR)&BSR_CMD_INPROGRESS)){ 532 s = splclock(); 533 now = mono_time; 534 splx(s); 535 if (now.tv_sec - start.tv_sec > secs) 536 break; 537 538 delay(1); 539 } 540 541 if (now.tv_sec - start.tv_sec >= secs && 542 bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_CMD_INPROGRESS){ 543 printf("%s: timed out waiting for previous cmd to finish\n", 544 sc->sc_ed[devno]->sc_dev.dv_xname); 545 return (EAGAIN); 546 } 547 548 return (0); 549 } 550 551 int 552 edc_run_cmd(sc, cmd, devno, cmd_args, cmd_len, async) 553 struct edc_mca_softc *sc; 554 int cmd; 555 int devno; 556 u_int16_t cmd_args[]; 557 int cmd_len; 558 int async; 559 { 560 int i, error; 561 u_int16_t cmd0; 562 563 /* 564 * If there has been an asynchronous command executed, first wait for it 565 * to finish. 566 */ 567 if (sc->sc_cmd_async) { 568 /* Wait maximum 15s */ 569 if (edc_cmd_wait(sc, devno, 15)) 570 return (EAGAIN); /* Busy */ 571 572 sc->sc_cmd_async = 0; 573 } 574 575 /* Do Attention Request for Command Request. */ 576 if ((error = edc_do_attn(sc, ATN_CMD_REQ, devno, 0))) 577 return (error); 578 579 /* 580 * Construct the command. The bits are like this: 581 * 582 * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 583 * \_/ 0 0 1 0 \__/ \_____/ 584 * \ \__________/ \ \_ Command Code (see CMD_*) 585 * \ \ \__ Device: 0 common, 7 controller 586 * \ \__ Options: reserved, bit 10=cache bypass bit 587 * \_ Type: 00=2B, 01=4B, 10 and 11 reserved 588 * 589 * We always use device 0 or 1, so difference is made only by Command 590 * Code, Command Options and command length. 591 */ 592 cmd0 = ((cmd_len == 4) ? (CIFR_LONG_CMD) : 0) 593 | (devno << 5) 594 | (cmd_args[0] << 8) | cmd; 595 cmd_args[0] = cmd0; 596 597 /* 598 * Write word of CMD to the CIFR. This sets "Command 599 * Interface Register Full (CMD IN)" in BSR. Once the attachment 600 * detects it, it reads the word and clears CMD IN. 601 */ 602 for(i=0; i < cmd_len; i++) { 603 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CIFR, 604 htole16(cmd_args[i])); 605 606 /* wait until CMD IN is cleared */ 607 while(bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_CIFR_FULL) 608 delay(1); 609 } 610 611 /* 612 * Attachment is now executing the command. Unless we are executing 613 * command asynchronously, wait until it finishes. 614 */ 615 if (async) { 616 sc->sc_cmd_async = 1; 617 return (0); 618 } 619 620 /* Wait for command to complete, but maximum 15 seconds. */ 621 if (edc_cmd_wait(sc, devno, 15)) 622 return (EAGAIN); 623 624 /* Check if the command completed successfully; if not, return error */ 625 switch(SB_GET_CMD_STATUS(sc->sc_ed[devno]->sc_status_block)) { 626 case ISR_COMPLETED: 627 case ISR_COMPLETED_WITH_ECC: 628 case ISR_COMPLETED_RETRIES: 629 case ISR_COMPLETED_WARNING: 630 return (0); 631 default: 632 return (EIO); 633 } 634 } 635 636 static int 637 edc_setup_dma(sc, bp, phys, cnt) 638 struct edc_mca_softc *sc; 639 struct buf *bp; 640 bus_addr_t phys; 641 bus_size_t cnt; 642 { 643 /* XXX magic constants, should be moved to device-independant location*/ 644 /* The exact sequence to setup MCA DMA controller is taken from Minix */ 645 646 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0, 647 0x90 + sc->sc_drq); 648 /* Disable access to dma channel */ 649 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0, 650 0x20 + sc->sc_drq); 651 /* Clear the address byte pointer */ 652 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0, 653 (phys >> 0) & 0xff); /* address bits 0..7 */ 654 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0, 655 (phys >> 8) & 0xff); /* address bits 8..15 */ 656 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0, 657 (phys >> 16) & 0xff); /* address bits 16..23 */ 658 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0, 659 0x40 + sc->sc_drq); 660 /* Clear the count byte pointer */ 661 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0, 662 ((cnt - 1) >> 0) & 0xff); /* count bits 0..7 */ 663 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0, 664 ((cnt - 1) >> 8) & 0xff); /* count bits 8..15 */ 665 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0, 666 0x70 + sc->sc_drq); 667 /* Set the transfer mode */ 668 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0, 669 (bp->b_flags & B_READ) ? 0x4C : 0x44); 670 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0, 671 0xA0 + sc->sc_drq); 672 /* Enable access to dma channel */ 673 674 return (1); 675 } 676 677 static const char * const edc_commands[] = { 678 "Invalid Command", 679 "Read Data", 680 "Write Data", 681 "Read Verify", 682 "Write with Verify", 683 "Seek", 684 "Park Head", 685 "Get Command Complete Status", 686 "Get Device Status", 687 "Get Device Configuration", 688 "Get POS Information", 689 "Translate RBA", 690 "Write Attachment Buffer", 691 "Read Attachment Buffer", 692 "Run Diagnostic Test", 693 "Get Diagnostic Status Block", 694 "Get MFG Header", 695 "Format Unit", 696 "Format Prepare", 697 "Set MAX RBA", 698 "Set Power Saving Mode", 699 "Power Conservation Command", 700 }; 701 702 static const char * const edc_cmd_status[256] = { 703 "Reserved", 704 "Command completed successfully", 705 "Reserved", 706 "Command completed successfully with ECC applied", 707 "Reserved", 708 "Command completed successfully with retries", 709 "Format Command partially completed", /* Status available */ 710 "Command completed successfully with ECC and retries", 711 "Command completed with Warning", /* Command Error is available */ 712 "Aborted", 713 "Reset completed", 714 "Data Transfer Ready", /* No Status Block available */ 715 "Command terminated with failure", /* Device Error is available */ 716 "DMA Error", /* Retry entire command as recovery */ 717 "Command Block Error", 718 "Attention Error (Illegal Attention Code)", 719 /* 0x14 - 0xff reserved */ 720 }; 721 722 static const char * const edc_cmd_error[256] = { 723 "No Error", 724 "Invalid parameter in the command block", 725 "Reserved", 726 "Command not supported", 727 "Command Aborted per request", 728 "Reserved", 729 "Command rejected", /* Attachment diagnostic failure */ 730 "Format Rejected", /* Prepare Format command is required */ 731 "Format Error (Primary Map is not readable)", 732 "Format Error (Secondary map is not readable)", 733 "Format Error (Diagnostic Failure)", 734 "Format Warning (Secondary Map Overflow)", 735 "Reserved" 736 "Format Error (Host Checksum Error)", 737 "Reserved", 738 "Format Warning (Push table overflow)", 739 "Format Warning (More pushes than allowed)", 740 "Reserved", 741 "Format Warning (Error during verifying)", 742 "Invalid device number for the command", 743 /* 0x14-0xff reserved */ 744 }; 745 746 static const char * const edc_dev_errors[] = { 747 "No Error", 748 "Seek Fault", /* Device report */ 749 "Interface Fault (Parity, Attn, or Cmd Complete Error)", 750 "Block not found (ID not found)", 751 "Block not found (AM not found)", 752 "Data ECC Error (hard error)", 753 "ID CRC Error", 754 "RBA Out of Range", 755 "Reserved", 756 "Defective Block", 757 "Reserved", 758 "Selection Error", 759 "Reserved", 760 "Write Fault", 761 "No index or sector pulse", 762 "Device Not Ready", 763 "Seek Error", /* Attachment report */ 764 "Bad Format", 765 "Volume Overflow", 766 "No Data AM Found", 767 "Block not found (No ID AM or ID CRC error occured)", 768 "Reserved", 769 "Reserved", 770 "No ID found on track (ID search)", 771 /* 0x19 - 0xff reserved */ 772 }; 773 774 static void 775 edc_dump_status_block(sc, devno, intr_id) 776 struct edc_mca_softc *sc; 777 int devno, intr_id; 778 { 779 struct ed_softc *ed = sc->sc_ed[devno]; 780 printf("%s: Command: %s, Status: %s\n", 781 ed->sc_dev.dv_xname, 782 edc_commands[ed->sc_status_block[0] & 0x1f], 783 edc_cmd_status[SB_GET_CMD_STATUS(ed->sc_status_block)] 784 ); 785 printf("%s: # left blocks: %u, last processed RBA: %u\n", 786 ed->sc_dev.dv_xname, 787 ed->sc_status_block[SB_RESBLKCNT_IDX], 788 (ed->sc_status_block[5] << 16) | ed->sc_status_block[4]); 789 790 if (intr_id == ISR_COMPLETED_WARNING) { 791 printf("%s: Command Error Code: %s\n", 792 ed->sc_dev.dv_xname, 793 edc_cmd_error[ed->sc_status_block[1] & 0xff]); 794 } 795 796 if (intr_id == ISR_CMD_FAILED) { 797 char buf[100]; 798 799 printf("%s: Device Error Code: %s\n", 800 ed->sc_dev.dv_xname, 801 edc_dev_errors[ed->sc_status_block[2] & 0xff]); 802 bitmask_snprintf((ed->sc_status_block[2] & 0xff00) >> 8, 803 "\20" 804 "\01SeekOrCmdComplete" 805 "\02Track0Flag" 806 "\03WriteFault" 807 "\04Selected" 808 "\05Ready" 809 "\06Reserved0" 810 "\07STANDBY" 811 "\010Reserved0", 812 buf, sizeof(buf)); 813 printf("%s: Device Status: %s\n", 814 ed->sc_dev.dv_xname, buf); 815 } 816 } 817