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