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