1 /* $NetBSD: aha.c,v 1.4 1997/03/28 23:47:08 mycroft Exp $ */ 2 3 #undef AHADIAG 4 #ifdef DDB 5 #define integrate 6 #else 7 #define integrate static inline 8 #endif 9 10 /* 11 * Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by Charles M. Hannum. 24 * 4. The name of the author may not be used to endorse or promote products 25 * derived from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Originally written by Julian Elischer (julian@tfs.com) 41 * for TRW Financial Systems for use under the MACH(2.5) operating system. 42 * 43 * TRW Financial Systems, in accordance with their agreement with Carnegie 44 * Mellon University, makes this software available to CMU to distribute 45 * or use in any manner that they see fit as long as this message is kept with 46 * the software. For this reason TFS also grants any other persons or 47 * organisations permission to use or modify this software. 48 * 49 * TFS supplies this software to be publicly redistributed 50 * on the understanding that TFS is not responsible for the correct 51 * functioning of this software in any circumstances. 52 */ 53 54 #include <sys/types.h> 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/kernel.h> 58 #include <sys/errno.h> 59 #include <sys/ioctl.h> 60 #include <sys/device.h> 61 #include <sys/malloc.h> 62 #include <sys/buf.h> 63 #include <sys/proc.h> 64 #include <sys/user.h> 65 66 #include <machine/bus.h> 67 #include <machine/intr.h> 68 69 #include <scsi/scsi_all.h> 70 #include <scsi/scsiconf.h> 71 72 #include <dev/ic/ahareg.h> 73 #include <dev/ic/ahavar.h> 74 75 #ifndef DDB 76 #define Debugger() panic("should call debugger here (aha1542.c)") 77 #endif /* ! DDB */ 78 79 #define KVTOPHYS(x) vtophys(x) 80 81 #ifdef AHADEBUG 82 int aha_debug = 1; 83 #endif /* AHADEBUG */ 84 85 int aha_cmd __P((bus_space_tag_t, bus_space_handle_t, struct aha_softc *, int, 86 u_char *, int, u_char *)); 87 integrate void aha_finish_ccbs __P((struct aha_softc *)); 88 integrate void aha_reset_ccb __P((struct aha_softc *, struct aha_ccb *)); 89 void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *)); 90 integrate void aha_init_ccb __P((struct aha_softc *, struct aha_ccb *)); 91 struct aha_ccb *aha_get_ccb __P((struct aha_softc *, int)); 92 struct aha_ccb *aha_ccb_phys_kv __P((struct aha_softc *, u_long)); 93 void aha_queue_ccb __P((struct aha_softc *, struct aha_ccb *)); 94 void aha_collect_mbo __P((struct aha_softc *)); 95 void aha_start_ccbs __P((struct aha_softc *)); 96 void aha_done __P((struct aha_softc *, struct aha_ccb *)); 97 void aha_init __P((struct aha_softc *)); 98 void aha_inquire_setup_information __P((struct aha_softc *)); 99 void ahaminphys __P((struct buf *)); 100 int aha_scsi_cmd __P((struct scsi_xfer *)); 101 int aha_poll __P((struct aha_softc *, struct scsi_xfer *, int)); 102 void aha_timeout __P((void *arg)); 103 104 struct scsi_adapter aha_switch = { 105 aha_scsi_cmd, 106 ahaminphys, 107 0, 108 0, 109 }; 110 111 /* the below structure is so we have a default dev struct for out link struct */ 112 struct scsi_device aha_dev = { 113 NULL, /* Use default error handler */ 114 NULL, /* have a queue, served by this */ 115 NULL, /* have no async handler */ 116 NULL, /* Use default 'done' routine */ 117 }; 118 119 struct cfdriver aha_cd = { 120 NULL, "aha", DV_DULL 121 }; 122 123 #define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */ 124 #define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */ 125 126 /* 127 * aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf) 128 * 129 * Activate Adapter command 130 * icnt: number of args (outbound bytes including opcode) 131 * ibuf: argument buffer 132 * ocnt: number of expected returned bytes 133 * obuf: result buffer 134 * wait: number of seconds to wait for response 135 * 136 * Performs an adapter command through the ports. Not to be confused with a 137 * scsi command, which is read in via the dma; one of the adapter commands 138 * tells it to read in a scsi command. 139 */ 140 int 141 aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf) 142 bus_space_tag_t iot; 143 bus_space_handle_t ioh; 144 struct aha_softc *sc; 145 int icnt, ocnt; 146 u_char *ibuf, *obuf; 147 { 148 const char *name; 149 register int i; 150 int wait; 151 u_char sts; 152 u_char opcode = ibuf[0]; 153 154 if (sc != NULL) 155 name = sc->sc_dev.dv_xname; 156 else 157 name = "(aha probe)"; 158 159 /* 160 * Calculate a reasonable timeout for the command. 161 */ 162 switch (opcode) { 163 case AHA_INQUIRE_DEVICES: 164 wait = 90 * 20000; 165 break; 166 default: 167 wait = 1 * 20000; 168 break; 169 } 170 171 /* 172 * Wait for the adapter to go idle, unless it's one of 173 * the commands which don't need this 174 */ 175 if (opcode != AHA_MBO_INTR_EN) { 176 for (i = 20000; i; i--) { /* 1 sec? */ 177 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 178 if (sts & AHA_STAT_IDLE) 179 break; 180 delay(50); 181 } 182 if (!i) { 183 printf("%s: aha_cmd, host not idle(0x%x)\n", 184 name, sts); 185 return (1); 186 } 187 } 188 /* 189 * Now that it is idle, if we expect output, preflush the 190 * queue feeding to us. 191 */ 192 if (ocnt) { 193 while ((bus_space_read_1(iot, ioh, AHA_STAT_PORT)) & AHA_STAT_DF) 194 bus_space_read_1(iot, ioh, AHA_DATA_PORT); 195 } 196 /* 197 * Output the command and the number of arguments given 198 * for each byte, first check the port is empty. 199 */ 200 while (icnt--) { 201 for (i = wait; i; i--) { 202 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 203 if (!(sts & AHA_STAT_CDF)) 204 break; 205 delay(50); 206 } 207 if (!i) { 208 if (opcode != AHA_INQUIRE_REVISION) 209 printf("%s: aha_cmd, cmd/data port full\n", name); 210 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_SRST); 211 return (1); 212 } 213 bus_space_write_1(iot, ioh, AHA_CMD_PORT, *ibuf++); 214 } 215 /* 216 * If we expect input, loop that many times, each time, 217 * looking for the data register to have valid data 218 */ 219 while (ocnt--) { 220 for (i = wait; i; i--) { 221 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 222 if (sts & AHA_STAT_DF) 223 break; 224 delay(50); 225 } 226 if (!i) { 227 if (opcode != AHA_INQUIRE_REVISION) 228 printf("%s: aha_cmd, cmd/data port empty %d\n", 229 name, ocnt); 230 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_SRST); 231 return (1); 232 } 233 *obuf++ = bus_space_read_1(iot, ioh, AHA_DATA_PORT); 234 } 235 /* 236 * Wait for the board to report a finished instruction. 237 * We may get an extra interrupt for the HACC signal, but this is 238 * unimportant. 239 */ 240 if (opcode != AHA_MBO_INTR_EN) { 241 for (i = 20000; i; i--) { /* 1 sec? */ 242 sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT); 243 /* XXX Need to save this in the interrupt handler? */ 244 if (sts & AHA_INTR_HACC) 245 break; 246 delay(50); 247 } 248 if (!i) { 249 printf("%s: aha_cmd, host not finished(0x%x)\n", 250 name, sts); 251 return (1); 252 } 253 } 254 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST); 255 return (0); 256 } 257 258 void 259 aha_attach(sc, apd) 260 struct aha_softc *sc; 261 struct aha_probe_data *apd; 262 { 263 264 aha_inquire_setup_information(sc); 265 aha_init(sc); 266 TAILQ_INIT(&sc->sc_free_ccb); 267 TAILQ_INIT(&sc->sc_waiting_ccb); 268 269 /* 270 * fill in the prototype scsi_link. 271 */ 272 sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; 273 sc->sc_link.adapter_softc = sc; 274 sc->sc_link.adapter_target = apd->sc_scsi_dev; 275 sc->sc_link.adapter = &aha_switch; 276 sc->sc_link.device = &aha_dev; 277 sc->sc_link.openings = 2; 278 sc->sc_link.max_target = 7; 279 280 /* 281 * ask the adapter what subunits are present 282 */ 283 config_found(&sc->sc_dev, &sc->sc_link, scsiprint); 284 } 285 286 integrate void 287 aha_finish_ccbs(sc) 288 struct aha_softc *sc; 289 { 290 struct aha_mbx_in *wmbi; 291 struct aha_ccb *ccb; 292 int i; 293 294 wmbi = wmbx->tmbi; 295 296 if (wmbi->stat == AHA_MBI_FREE) { 297 for (i = 0; i < AHA_MBX_SIZE; i++) { 298 if (wmbi->stat != AHA_MBI_FREE) { 299 printf("%s: mbi not in round-robin order\n", 300 sc->sc_dev.dv_xname); 301 goto AGAIN; 302 } 303 aha_nextmbx(wmbi, wmbx, mbi); 304 } 305 #ifdef AHADIAGnot 306 printf("%s: mbi interrupt with no full mailboxes\n", 307 sc->sc_dev.dv_xname); 308 #endif 309 return; 310 } 311 312 AGAIN: 313 do { 314 ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr)); 315 if (!ccb) { 316 printf("%s: bad mbi ccb pointer; skipping\n", 317 sc->sc_dev.dv_xname); 318 goto next; 319 } 320 321 #ifdef AHADEBUG 322 if (aha_debug) { 323 u_char *cp = &ccb->scsi_cmd; 324 printf("op=%x %x %x %x %x %x\n", 325 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 326 printf("stat %x for mbi addr = 0x%08x, ", 327 wmbi->stat, wmbi); 328 printf("ccb addr = 0x%x\n", ccb); 329 } 330 #endif /* AHADEBUG */ 331 332 switch (wmbi->stat) { 333 case AHA_MBI_OK: 334 case AHA_MBI_ERROR: 335 if ((ccb->flags & CCB_ABORT) != 0) { 336 /* 337 * If we already started an abort, wait for it 338 * to complete before clearing the CCB. We 339 * could instead just clear CCB_SENDING, but 340 * what if the mailbox was already received? 341 * The worst that happens here is that we clear 342 * the CCB a bit later than we need to. BFD. 343 */ 344 goto next; 345 } 346 break; 347 348 case AHA_MBI_ABORT: 349 case AHA_MBI_UNKNOWN: 350 /* 351 * Even if the CCB wasn't found, we clear it anyway. 352 * See preceeding comment. 353 */ 354 break; 355 356 default: 357 printf("%s: bad mbi status %02x; skipping\n", 358 sc->sc_dev.dv_xname, wmbi->stat); 359 goto next; 360 } 361 362 untimeout(aha_timeout, ccb); 363 aha_done(sc, ccb); 364 365 next: 366 wmbi->stat = AHA_MBI_FREE; 367 aha_nextmbx(wmbi, wmbx, mbi); 368 } while (wmbi->stat != AHA_MBI_FREE); 369 370 wmbx->tmbi = wmbi; 371 } 372 373 /* 374 * Catch an interrupt from the adaptor 375 */ 376 int 377 aha_intr(arg) 378 void *arg; 379 { 380 struct aha_softc *sc = arg; 381 bus_space_tag_t iot = sc->sc_iot; 382 bus_space_handle_t ioh = sc->sc_ioh; 383 u_char sts; 384 385 #ifdef AHADEBUG 386 printf("%s: aha_intr ", sc->sc_dev.dv_xname); 387 #endif /*AHADEBUG */ 388 389 /* 390 * First acknowlege the interrupt, Then if it's not telling about 391 * a completed operation just return. 392 */ 393 sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT); 394 if ((sts & AHA_INTR_ANYINTR) == 0) 395 return (0); 396 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST); 397 398 #ifdef AHADIAG 399 /* Make sure we clear CCB_SENDING before finishing a CCB. */ 400 aha_collect_mbo(sc); 401 #endif 402 403 /* Mail box out empty? */ 404 if (sts & AHA_INTR_MBOA) { 405 struct aha_toggle toggle; 406 407 toggle.cmd.opcode = AHA_MBO_INTR_EN; 408 toggle.cmd.enable = 0; 409 aha_cmd(iot, ioh, sc, 410 sizeof(toggle.cmd), (u_char *)&toggle.cmd, 411 0, (u_char *)0); 412 aha_start_ccbs(sc); 413 } 414 415 /* Mail box in full? */ 416 if (sts & AHA_INTR_MBIF) 417 aha_finish_ccbs(sc); 418 419 return (1); 420 } 421 422 integrate void 423 aha_reset_ccb(sc, ccb) 424 struct aha_softc *sc; 425 struct aha_ccb *ccb; 426 { 427 428 ccb->flags = 0; 429 } 430 431 /* 432 * A ccb is put onto the free list. 433 */ 434 void 435 aha_free_ccb(sc, ccb) 436 struct aha_softc *sc; 437 struct aha_ccb *ccb; 438 { 439 int s; 440 441 s = splbio(); 442 443 aha_reset_ccb(sc, ccb); 444 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); 445 446 /* 447 * If there were none, wake anybody waiting for one to come free, 448 * starting with queued entries. 449 */ 450 if (ccb->chain.tqe_next == 0) 451 wakeup(&sc->sc_free_ccb); 452 453 splx(s); 454 } 455 456 integrate void 457 aha_init_ccb(sc, ccb) 458 struct aha_softc *sc; 459 struct aha_ccb *ccb; 460 { 461 int hashnum; 462 463 bzero(ccb, sizeof(struct aha_ccb)); 464 /* 465 * put in the phystokv hash table 466 * Never gets taken out. 467 */ 468 ccb->hashkey = KVTOPHYS(ccb); 469 hashnum = CCB_HASH(ccb->hashkey); 470 ccb->nexthash = sc->sc_ccbhash[hashnum]; 471 sc->sc_ccbhash[hashnum] = ccb; 472 aha_reset_ccb(sc, ccb); 473 } 474 475 /* 476 * Get a free ccb 477 * 478 * If there are none, see if we can allocate a new one. If so, put it in 479 * the hash table too otherwise either return an error or sleep. 480 */ 481 struct aha_ccb * 482 aha_get_ccb(sc, flags) 483 struct aha_softc *sc; 484 int flags; 485 { 486 struct aha_ccb *ccb; 487 int s; 488 489 s = splbio(); 490 491 /* 492 * If we can and have to, sleep waiting for one to come free 493 * but only if we can't allocate a new one. 494 */ 495 for (;;) { 496 ccb = sc->sc_free_ccb.tqh_first; 497 if (ccb) { 498 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); 499 break; 500 } 501 if (sc->sc_numccbs < AHA_CCB_MAX) { 502 ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb), 503 M_TEMP, M_NOWAIT); 504 if (!ccb) { 505 printf("%s: can't malloc ccb\n", 506 sc->sc_dev.dv_xname); 507 goto out; 508 } 509 aha_init_ccb(sc, ccb); 510 sc->sc_numccbs++; 511 break; 512 } 513 if ((flags & SCSI_NOSLEEP) != 0) 514 goto out; 515 tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0); 516 } 517 518 ccb->flags |= CCB_ALLOC; 519 520 out: 521 splx(s); 522 return (ccb); 523 } 524 525 /* 526 * Given a physical address, find the ccb that it corresponds to. 527 */ 528 struct aha_ccb * 529 aha_ccb_phys_kv(sc, ccb_phys) 530 struct aha_softc *sc; 531 u_long ccb_phys; 532 { 533 int hashnum = CCB_HASH(ccb_phys); 534 struct aha_ccb *ccb = sc->sc_ccbhash[hashnum]; 535 536 while (ccb) { 537 if (ccb->hashkey == ccb_phys) 538 break; 539 ccb = ccb->nexthash; 540 } 541 return (ccb); 542 } 543 544 /* 545 * Queue a CCB to be sent to the controller, and send it if possible. 546 */ 547 void 548 aha_queue_ccb(sc, ccb) 549 struct aha_softc *sc; 550 struct aha_ccb *ccb; 551 { 552 553 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain); 554 aha_start_ccbs(sc); 555 } 556 557 /* 558 * Garbage collect mailboxes that are no longer in use. 559 */ 560 void 561 aha_collect_mbo(sc) 562 struct aha_softc *sc; 563 { 564 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */ 565 #ifdef AHADIAG 566 struct aha_ccb *ccb; 567 #endif 568 569 wmbo = wmbx->cmbo; 570 571 while (sc->sc_mbofull > 0) { 572 if (wmbo->cmd != AHA_MBO_FREE) 573 break; 574 575 #ifdef AHADIAG 576 ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr)); 577 ccb->flags &= ~CCB_SENDING; 578 #endif 579 580 --sc->sc_mbofull; 581 aha_nextmbx(wmbo, wmbx, mbo); 582 } 583 584 wmbx->cmbo = wmbo; 585 } 586 587 /* 588 * Send as many CCBs as we have empty mailboxes for. 589 */ 590 void 591 aha_start_ccbs(sc) 592 struct aha_softc *sc; 593 { 594 bus_space_tag_t iot = sc->sc_iot; 595 bus_space_handle_t ioh = sc->sc_ioh; 596 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */ 597 struct aha_ccb *ccb; 598 599 wmbo = wmbx->tmbo; 600 601 while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) { 602 if (sc->sc_mbofull >= AHA_MBX_SIZE) { 603 aha_collect_mbo(sc); 604 if (sc->sc_mbofull >= AHA_MBX_SIZE) { 605 struct aha_toggle toggle; 606 607 toggle.cmd.opcode = AHA_MBO_INTR_EN; 608 toggle.cmd.enable = 1; 609 aha_cmd(iot, ioh, sc, 610 sizeof(toggle.cmd), (u_char *)&toggle.cmd, 611 0, (u_char *)0); 612 break; 613 } 614 } 615 616 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain); 617 #ifdef AHADIAG 618 ccb->flags |= CCB_SENDING; 619 #endif 620 621 /* Link ccb to mbo. */ 622 ltophys(KVTOPHYS(ccb), wmbo->ccb_addr); 623 if (ccb->flags & CCB_ABORT) 624 wmbo->cmd = AHA_MBO_ABORT; 625 else 626 wmbo->cmd = AHA_MBO_START; 627 628 /* Tell the card to poll immediately. */ 629 bus_space_write_1(iot, ioh, AHA_CMD_PORT, AHA_START_SCSI); 630 631 if ((ccb->xs->flags & SCSI_POLL) == 0) 632 timeout(aha_timeout, ccb, (ccb->timeout * hz) / 1000); 633 634 ++sc->sc_mbofull; 635 aha_nextmbx(wmbo, wmbx, mbo); 636 } 637 638 wmbx->tmbo = wmbo; 639 } 640 641 /* 642 * We have a ccb which has been processed by the 643 * adaptor, now we look to see how the operation 644 * went. Wake up the owner if waiting 645 */ 646 void 647 aha_done(sc, ccb) 648 struct aha_softc *sc; 649 struct aha_ccb *ccb; 650 { 651 struct scsi_sense_data *s1, *s2; 652 struct scsi_xfer *xs = ccb->xs; 653 654 SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n")); 655 /* 656 * Otherwise, put the results of the operation 657 * into the xfer and call whoever started it 658 */ 659 #ifdef AHADIAG 660 if (ccb->flags & CCB_SENDING) { 661 printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname); 662 Debugger(); 663 return; 664 } 665 #endif 666 if ((ccb->flags & CCB_ALLOC) == 0) { 667 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname); 668 Debugger(); 669 return; 670 } 671 if (xs->error == XS_NOERROR) { 672 if (ccb->host_stat != AHA_OK) { 673 switch (ccb->host_stat) { 674 case AHA_SEL_TIMEOUT: /* No response */ 675 xs->error = XS_SELTIMEOUT; 676 break; 677 default: /* Other scsi protocol messes */ 678 printf("%s: host_stat %x\n", 679 sc->sc_dev.dv_xname, ccb->host_stat); 680 xs->error = XS_DRIVER_STUFFUP; 681 break; 682 } 683 } else if (ccb->target_stat != SCSI_OK) { 684 switch (ccb->target_stat) { 685 case SCSI_CHECK: 686 s1 = (struct scsi_sense_data *) (((char *) (&ccb->scsi_cmd)) + 687 ccb->scsi_cmd_length); 688 s2 = &xs->sense; 689 *s2 = *s1; 690 xs->error = XS_SENSE; 691 break; 692 case SCSI_BUSY: 693 xs->error = XS_BUSY; 694 break; 695 default: 696 printf("%s: target_stat %x\n", 697 sc->sc_dev.dv_xname, ccb->target_stat); 698 xs->error = XS_DRIVER_STUFFUP; 699 break; 700 } 701 } else 702 xs->resid = 0; 703 } 704 aha_free_ccb(sc, ccb); 705 xs->flags |= ITSDONE; 706 scsi_done(xs); 707 } 708 709 /* 710 * Find the board and find its irq/drq 711 */ 712 int 713 aha_find(iot, ioh, sc) 714 bus_space_tag_t iot; 715 bus_space_handle_t ioh; 716 struct aha_probe_data *sc; 717 { 718 int i; 719 u_char sts; 720 struct aha_config config; 721 int irq, drq; 722 723 /* 724 * reset board, If it doesn't respond, assume 725 * that it's not there.. good for the probe 726 */ 727 728 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST); 729 730 delay(100); 731 for (i = AHA_RESET_TIMEOUT; i; i--) { 732 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 733 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 734 break; 735 delay(1000); /* calibrated in msec */ 736 } 737 if (!i) { 738 #ifdef AHADEBUG 739 if (aha_debug) 740 printf("aha_find: No answer from adaptec board\n"); 741 #endif /* AHADEBUG */ 742 return (0); 743 } 744 745 /* 746 * setup dma channel from jumpers and save int 747 * level 748 */ 749 delay(1000); /* for Bustek 545 */ 750 config.cmd.opcode = AHA_INQUIRE_CONFIG; 751 aha_cmd(iot, ioh, (struct aha_softc *)0, 752 sizeof(config.cmd), (u_char *)&config.cmd, 753 sizeof(config.reply), (u_char *)&config.reply); 754 switch (config.reply.chan) { 755 case EISADMA: 756 drq = -1; 757 break; 758 case CHAN0: 759 drq = 0; 760 break; 761 case CHAN5: 762 drq = 5; 763 break; 764 case CHAN6: 765 drq = 6; 766 break; 767 case CHAN7: 768 drq = 7; 769 break; 770 default: 771 printf("aha_find: illegal drq setting %x\n", config.reply.chan); 772 return (0); 773 } 774 775 switch (config.reply.intr) { 776 case INT9: 777 irq = 9; 778 break; 779 case INT10: 780 irq = 10; 781 break; 782 case INT11: 783 irq = 11; 784 break; 785 case INT12: 786 irq = 12; 787 break; 788 case INT14: 789 irq = 14; 790 break; 791 case INT15: 792 irq = 15; 793 break; 794 default: 795 printf("aha_find: illegal irq setting %x\n", config.reply.intr); 796 return (0); 797 } 798 799 if (sc) { 800 sc->sc_irq = irq; 801 sc->sc_drq = drq; 802 sc->sc_scsi_dev = config.reply.scsi_dev; 803 } 804 805 return (1); 806 } 807 808 /* 809 * Start the board, ready for normal operation 810 */ 811 void 812 aha_init(sc) 813 struct aha_softc *sc; 814 { 815 bus_space_tag_t iot = sc->sc_iot; 816 bus_space_handle_t ioh = sc->sc_ioh; 817 struct aha_devices devices; 818 struct aha_setup setup; 819 struct aha_mailbox mailbox; 820 int i; 821 822 /* 823 * XXX 824 * If we are a 1542C or later, disable the extended BIOS so that the 825 * mailbox interface is unlocked. 826 * No need to check the extended BIOS flags as some of the 827 * extensions that cause us problems are not flagged in that byte. 828 */ 829 if (!strncmp(sc->sc_model, "1542C", 5)) { 830 struct aha_extbios extbios; 831 struct aha_unlock unlock; 832 833 printf("%s: unlocking mailbox interface\n", sc->sc_dev.dv_xname); 834 extbios.cmd.opcode = AHA_EXT_BIOS; 835 aha_cmd(iot, ioh, sc, 836 sizeof(extbios.cmd), (u_char *)&extbios.cmd, 837 sizeof(extbios.reply), (u_char *)&extbios.reply); 838 839 #ifdef AHADEBUG 840 printf("%s: flags=%02x, mailboxlock=%02x\n", 841 sc->sc_dev.dv_xname, 842 extbios.reply.flags, extbios.reply.mailboxlock); 843 #endif /* AHADEBUG */ 844 845 unlock.cmd.opcode = AHA_MBX_ENABLE; 846 unlock.cmd.junk = 0; 847 unlock.cmd.magic = extbios.reply.mailboxlock; 848 aha_cmd(iot, ioh, sc, 849 sizeof(unlock.cmd), (u_char *)&unlock.cmd, 850 0, (u_char *)0); 851 } 852 853 #if 0 854 /* 855 * Change the bus on/off times to not clash with other dma users. 856 */ 857 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7); 858 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4); 859 #endif 860 861 /* Inquire Installed Devices (to force synchronous negotiation). */ 862 devices.cmd.opcode = AHA_INQUIRE_DEVICES; 863 aha_cmd(iot, ioh, sc, 864 sizeof(devices.cmd), (u_char *)&devices.cmd, 865 sizeof(devices.reply), (u_char *)&devices.reply); 866 867 /* Obtain setup information from. */ 868 setup.cmd.opcode = AHA_INQUIRE_SETUP; 869 setup.cmd.len = sizeof(setup.reply); 870 aha_cmd(iot, ioh, sc, 871 sizeof(setup.cmd), (u_char *)&setup.cmd, 872 sizeof(setup.reply), (u_char *)&setup.reply); 873 874 printf("%s: %s, %s\n", 875 sc->sc_dev.dv_xname, 876 setup.reply.sync_neg ? "sync" : "async", 877 setup.reply.parity ? "parity" : "no parity"); 878 879 for (i = 0; i < 8; i++) { 880 if (!setup.reply.sync[i].valid || 881 (!setup.reply.sync[i].offset && !setup.reply.sync[i].period)) 882 continue; 883 printf("%s targ %d: sync, offset %d, period %dnsec\n", 884 sc->sc_dev.dv_xname, i, 885 setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200); 886 } 887 888 /* 889 * Set up initial mail box for round-robin operation. 890 */ 891 for (i = 0; i < AHA_MBX_SIZE; i++) { 892 wmbx->mbo[i].cmd = AHA_MBO_FREE; 893 wmbx->mbi[i].stat = AHA_MBI_FREE; 894 } 895 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0]; 896 wmbx->tmbi = &wmbx->mbi[0]; 897 sc->sc_mbofull = 0; 898 899 /* Initialize mail box. */ 900 mailbox.cmd.opcode = AHA_MBX_INIT; 901 mailbox.cmd.nmbx = AHA_MBX_SIZE; 902 ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr); 903 aha_cmd(iot, ioh, sc, 904 sizeof(mailbox.cmd), (u_char *)&mailbox.cmd, 905 0, (u_char *)0); 906 } 907 908 void 909 aha_inquire_setup_information(sc) 910 struct aha_softc *sc; 911 { 912 bus_space_tag_t iot = sc->sc_iot; 913 bus_space_handle_t ioh = sc->sc_ioh; 914 struct aha_revision revision; 915 u_char sts; 916 int i; 917 char *p; 918 919 strcpy(sc->sc_model, "unknown"); 920 921 /* 922 * Assume we have a board at this stage, do an adapter inquire 923 * to find out what type of controller it is. If the command 924 * fails, we assume it's either a crusty board or an old 1542 925 * clone, and skip the board-specific stuff. 926 */ 927 revision.cmd.opcode = AHA_INQUIRE_REVISION; 928 if (aha_cmd(iot, ioh, sc, 929 sizeof(revision.cmd), (u_char *)&revision.cmd, 930 sizeof(revision.reply), (u_char *)&revision.reply)) { 931 /* 932 * aha_cmd() already started the reset. It's not clear we 933 * even need to bother here. 934 */ 935 for (i = AHA_RESET_TIMEOUT; i; i--) { 936 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 937 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 938 break; 939 delay(1000); 940 } 941 if (!i) { 942 #ifdef AHADEBUG 943 printf("aha_init: soft reset failed\n"); 944 #endif /* AHADEBUG */ 945 return; 946 } 947 #ifdef AHADEBUG 948 printf("aha_init: inquire command failed\n"); 949 #endif /* AHADEBUG */ 950 goto noinquire; 951 } 952 953 #ifdef AHADEBUG 954 printf("%s: inquire %x, %x, %x, %x\n", 955 sc->sc_dev.dv_xname, 956 revision.reply.boardid, revision.reply.spec_opts, 957 revision.reply.revision_1, revision.reply.revision_2); 958 #endif /* AHADEBUG */ 959 960 switch (revision.reply.boardid) { 961 case 0x31: 962 strcpy(sc->sc_model, "1540"); 963 break; 964 case 0x41: 965 strcpy(sc->sc_model, "1540A/1542A/1542B"); 966 break; 967 case 0x42: 968 strcpy(sc->sc_model, "1640"); 969 break; 970 case 0x43: 971 strcpy(sc->sc_model, "1542C"); 972 break; 973 case 0x44: 974 case 0x45: 975 strcpy(sc->sc_model, "1542CF"); 976 break; 977 case 0x46: 978 strcpy(sc->sc_model, "1542CP"); 979 break; 980 } 981 982 p = sc->sc_firmware; 983 *p++ = revision.reply.revision_1; 984 *p++ = '.'; 985 *p++ = revision.reply.revision_2; 986 *p = '\0'; 987 988 noinquire: 989 printf("%s: model AHA-%s, firmware %s\n", 990 sc->sc_dev.dv_xname, 991 sc->sc_model, sc->sc_firmware); 992 } 993 994 void 995 ahaminphys(bp) 996 struct buf *bp; 997 { 998 999 if (bp->b_bcount > ((AHA_NSEG - 1) << PGSHIFT)) 1000 bp->b_bcount = ((AHA_NSEG - 1) << PGSHIFT); 1001 minphys(bp); 1002 } 1003 1004 /* 1005 * start a scsi operation given the command and the data address. Also needs 1006 * the unit, target and lu. 1007 */ 1008 int 1009 aha_scsi_cmd(xs) 1010 struct scsi_xfer *xs; 1011 { 1012 struct scsi_link *sc_link = xs->sc_link; 1013 struct aha_softc *sc = sc_link->adapter_softc; 1014 struct aha_ccb *ccb; 1015 struct aha_scat_gath *sg; 1016 int seg; /* scatter gather seg being worked on */ 1017 u_long thiskv, thisphys, nextphys; 1018 int bytes_this_seg, bytes_this_page, datalen, flags; 1019 #ifdef TFS 1020 struct iovec *iovp; 1021 #endif 1022 int s; 1023 1024 SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n")); 1025 /* 1026 * get a ccb to use. If the transfer 1027 * is from a buf (possibly from interrupt time) 1028 * then we can't allow it to sleep 1029 */ 1030 flags = xs->flags; 1031 if ((ccb = aha_get_ccb(sc, flags)) == NULL) { 1032 xs->error = XS_DRIVER_STUFFUP; 1033 return (TRY_AGAIN_LATER); 1034 } 1035 ccb->xs = xs; 1036 ccb->timeout = xs->timeout; 1037 1038 /* 1039 * Put all the arguments for the xfer in the ccb 1040 */ 1041 if (flags & SCSI_RESET) { 1042 ccb->opcode = AHA_RESET_CCB; 1043 ccb->scsi_cmd_length = 0; 1044 } else { 1045 /* can't use S/G if zero length */ 1046 ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB 1047 : AHA_INITIATOR_CCB); 1048 bcopy(xs->cmd, &ccb->scsi_cmd, 1049 ccb->scsi_cmd_length = xs->cmdlen); 1050 } 1051 1052 if (xs->datalen) { 1053 sg = ccb->scat_gath; 1054 seg = 0; 1055 #ifdef TFS 1056 if (flags & SCSI_DATA_UIO) { 1057 iovp = ((struct uio *)xs->data)->uio_iov; 1058 datalen = ((struct uio *)xs->data)->uio_iovcnt; 1059 xs->datalen = 0; 1060 while (datalen && seg < AHA_NSEG) { 1061 ltophys(iovp->iov_base, sg->seg_addr); 1062 ltophys(iovp->iov_len, sg->seg_len); 1063 xs->datalen += iovp->iov_len; 1064 SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)", 1065 iovp->iov_len, iovp->iov_base)); 1066 sg++; 1067 iovp++; 1068 seg++; 1069 datalen--; 1070 } 1071 } else 1072 #endif /* TFS */ 1073 { 1074 /* 1075 * Set up the scatter-gather block. 1076 */ 1077 SC_DEBUG(sc_link, SDEV_DB4, 1078 ("%d @0x%x:- ", xs->datalen, xs->data)); 1079 1080 datalen = xs->datalen; 1081 thiskv = (int)xs->data; 1082 thisphys = KVTOPHYS(thiskv); 1083 1084 while (datalen && seg < AHA_NSEG) { 1085 bytes_this_seg = 0; 1086 1087 /* put in the base address */ 1088 ltophys(thisphys, sg->seg_addr); 1089 1090 SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys)); 1091 1092 /* do it at least once */ 1093 nextphys = thisphys; 1094 while (datalen && thisphys == nextphys) { 1095 /* 1096 * This page is contiguous (physically) 1097 * with the the last, just extend the 1098 * length 1099 */ 1100 /* check it fits on the ISA bus */ 1101 if (thisphys > 0xFFFFFF) { 1102 printf("%s: DMA beyond" 1103 " end of ISA\n", 1104 sc->sc_dev.dv_xname); 1105 goto bad; 1106 } 1107 /* how far to the end of the page */ 1108 nextphys = (thisphys & ~PGOFSET) + NBPG; 1109 bytes_this_page = nextphys - thisphys; 1110 /**** or the data ****/ 1111 bytes_this_page = min(bytes_this_page, 1112 datalen); 1113 bytes_this_seg += bytes_this_page; 1114 datalen -= bytes_this_page; 1115 1116 /* get more ready for the next page */ 1117 thiskv = (thiskv & ~PGOFSET) + NBPG; 1118 if (datalen) 1119 thisphys = KVTOPHYS(thiskv); 1120 } 1121 /* 1122 * next page isn't contiguous, finish the seg 1123 */ 1124 SC_DEBUGN(sc_link, SDEV_DB4, 1125 ("(0x%x)", bytes_this_seg)); 1126 ltophys(bytes_this_seg, sg->seg_len); 1127 sg++; 1128 seg++; 1129 } 1130 } 1131 /* end of iov/kv decision */ 1132 SC_DEBUGN(sc_link, SDEV_DB4, ("\n")); 1133 if (datalen) { 1134 /* 1135 * there's still data, must have run out of segs! 1136 */ 1137 printf("%s: aha_scsi_cmd, more than %d dma segs\n", 1138 sc->sc_dev.dv_xname, AHA_NSEG); 1139 goto bad; 1140 } 1141 ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr); 1142 ltophys(seg * sizeof(struct aha_scat_gath), ccb->data_length); 1143 } else { /* No data xfer, use non S/G values */ 1144 ltophys(0, ccb->data_addr); 1145 ltophys(0, ccb->data_length); 1146 } 1147 1148 ccb->data_out = 0; 1149 ccb->data_in = 0; 1150 ccb->target = sc_link->target; 1151 ccb->lun = sc_link->lun; 1152 ccb->req_sense_length = sizeof(ccb->scsi_sense); 1153 ccb->host_stat = 0x00; 1154 ccb->target_stat = 0x00; 1155 ccb->link_id = 0; 1156 ltophys(0, ccb->link_addr); 1157 1158 s = splbio(); 1159 aha_queue_ccb(sc, ccb); 1160 splx(s); 1161 1162 /* 1163 * Usually return SUCCESSFULLY QUEUED 1164 */ 1165 SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n")); 1166 if ((flags & SCSI_POLL) == 0) 1167 return (SUCCESSFULLY_QUEUED); 1168 1169 /* 1170 * If we can't use interrupts, poll on completion 1171 */ 1172 if (aha_poll(sc, xs, ccb->timeout)) { 1173 aha_timeout(ccb); 1174 if (aha_poll(sc, xs, ccb->timeout)) 1175 aha_timeout(ccb); 1176 } 1177 return (COMPLETE); 1178 1179 bad: 1180 xs->error = XS_DRIVER_STUFFUP; 1181 aha_free_ccb(sc, ccb); 1182 return (COMPLETE); 1183 } 1184 1185 /* 1186 * Poll a particular unit, looking for a particular xs 1187 */ 1188 int 1189 aha_poll(sc, xs, count) 1190 struct aha_softc *sc; 1191 struct scsi_xfer *xs; 1192 int count; 1193 { 1194 bus_space_tag_t iot = sc->sc_iot; 1195 bus_space_handle_t ioh = sc->sc_ioh; 1196 1197 /* timeouts are in msec, so we loop in 1000 usec cycles */ 1198 while (count) { 1199 /* 1200 * If we had interrupts enabled, would we 1201 * have got an interrupt? 1202 */ 1203 if (bus_space_read_1(iot, ioh, AHA_INTR_PORT) & AHA_INTR_ANYINTR) 1204 aha_intr(sc); 1205 if (xs->flags & ITSDONE) 1206 return (0); 1207 delay(1000); /* only happens in boot so ok */ 1208 count--; 1209 } 1210 return (1); 1211 } 1212 1213 void 1214 aha_timeout(arg) 1215 void *arg; 1216 { 1217 struct aha_ccb *ccb = arg; 1218 struct scsi_xfer *xs = ccb->xs; 1219 struct scsi_link *sc_link = xs->sc_link; 1220 struct aha_softc *sc = sc_link->adapter_softc; 1221 int s; 1222 1223 sc_print_addr(sc_link); 1224 printf("timed out"); 1225 1226 s = splbio(); 1227 1228 #ifdef AHADIAG 1229 /* 1230 * If The ccb's mbx is not free, then the board has gone south? 1231 */ 1232 aha_collect_mbo(sc); 1233 if (ccb->flags & CCB_SENDING) { 1234 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname); 1235 Debugger(); 1236 } 1237 #endif 1238 1239 /* 1240 * If it has been through before, then 1241 * a previous abort has failed, don't 1242 * try abort again 1243 */ 1244 if (ccb->flags & CCB_ABORT) { 1245 /* abort timed out */ 1246 printf(" AGAIN\n"); 1247 /* XXX Must reset! */ 1248 } else { 1249 /* abort the operation that has timed out */ 1250 printf("\n"); 1251 ccb->xs->error = XS_TIMEOUT; 1252 ccb->timeout = AHA_ABORT_TIMEOUT; 1253 ccb->flags |= CCB_ABORT; 1254 aha_queue_ccb(sc, ccb); 1255 } 1256 1257 splx(s); 1258 } 1259