1 /* $NetBSD: aha.c,v 1.59 2009/09/21 08:12:47 tsutsui 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.59 2009/09/21 08:12:47 tsutsui 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/malloc.h> 63 #include <sys/buf.h> 64 #include <sys/proc.h> 65 #include <sys/user.h> 66 67 #include <uvm/uvm_extern.h> 68 69 #include <sys/bus.h> 70 #include <sys/intr.h> 71 72 #include <dev/scsipi/scsi_all.h> 73 #include <dev/scsipi/scsipi_all.h> 74 #include <dev/scsipi/scsiconf.h> 75 76 #include <dev/ic/ahareg.h> 77 #include <dev/ic/ahavar.h> 78 79 #ifndef DDB 80 #define Debugger() panic("should call debugger here (aha1542.c)") 81 #endif /* ! DDB */ 82 83 #define AHA_MAXXFER ((AHA_NSEG - 1) << PGSHIFT) 84 85 #ifdef AHADEBUG 86 int aha_debug = 1; 87 #endif /* AHADEBUG */ 88 89 static int aha_cmd(bus_space_tag_t, bus_space_handle_t, 90 struct aha_softc *, int, u_char *, int, u_char *); 91 static void aha_finish_ccbs(struct aha_softc *); 92 static void aha_free_ccb(struct aha_softc *, struct aha_ccb *); 93 static int aha_init_ccb(struct aha_softc *, struct aha_ccb *); 94 static struct aha_ccb *aha_get_ccb(struct aha_softc *); 95 static struct aha_ccb *aha_ccb_phys_kv(struct aha_softc *, u_long); 96 static void aha_queue_ccb(struct aha_softc *, struct aha_ccb *); 97 static void aha_collect_mbo(struct aha_softc *); 98 static void aha_start_ccbs(struct aha_softc *); 99 static void aha_done(struct aha_softc *, struct aha_ccb *); 100 static int aha_init(struct aha_softc *); 101 static void aha_inquire_setup_information(struct aha_softc *); 102 static void ahaminphys(struct buf *); 103 static void aha_scsipi_request(struct scsipi_channel *, 104 scsipi_adapter_req_t, void *); 105 static int aha_poll(struct aha_softc *, struct scsipi_xfer *, int); 106 static void aha_timeout(void *arg); 107 static int aha_create_ccbs(struct aha_softc *, struct aha_ccb *, int); 108 109 #define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */ 110 #define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */ 111 112 /* 113 * aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf) 114 * 115 * Activate Adapter command 116 * icnt: number of args (outbound bytes including opcode) 117 * ibuf: argument buffer 118 * ocnt: number of expected returned bytes 119 * obuf: result buffer 120 * wait: number of seconds to wait for response 121 * 122 * Performs an adapter command through the ports. Not to be confused with a 123 * scsi command, which is read in via the DMA; one of the adapter commands 124 * tells it to read in a scsi command. 125 */ 126 static int 127 aha_cmd(bus_space_tag_t iot, bus_space_handle_t ioh, struct aha_softc *sc, 128 int icnt, u_char *ibuf, int ocnt, u_char *obuf) 129 { 130 const char *name; 131 int i; 132 int wait; 133 u_char sts; 134 u_char opcode = ibuf[0]; 135 136 if (sc != NULL) 137 name = device_xname(sc->sc_dev); 138 else 139 name = "(aha probe)"; 140 141 /* 142 * Calculate a reasonable timeout for the command. 143 */ 144 switch (opcode) { 145 case AHA_INQUIRE_DEVICES: 146 wait = 90 * 20000; 147 break; 148 default: 149 wait = 1 * 20000; 150 break; 151 } 152 153 /* 154 * Wait for the adapter to go idle, unless it's one of 155 * the commands which don't need this 156 */ 157 if (opcode != AHA_MBO_INTR_EN) { 158 for (i = 20000; i; i--) { /* 1 sec? */ 159 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 160 if (sts & AHA_STAT_IDLE) 161 break; 162 delay(50); 163 } 164 if (!i) { 165 printf("%s: aha_cmd, host not idle(0x%x)\n", 166 name, sts); 167 return (1); 168 } 169 } 170 /* 171 * Now that it is idle, if we expect output, preflush the 172 * queue feeding to us. 173 */ 174 if (ocnt) { 175 while ((bus_space_read_1(iot, ioh, AHA_STAT_PORT)) & AHA_STAT_DF) 176 bus_space_read_1(iot, ioh, AHA_DATA_PORT); 177 } 178 /* 179 * Output the command and the number of arguments given 180 * for each byte, first check the port is empty. 181 */ 182 while (icnt--) { 183 for (i = wait; i; i--) { 184 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 185 if (!(sts & AHA_STAT_CDF)) 186 break; 187 delay(50); 188 } 189 if (!i) { 190 if (opcode != AHA_INQUIRE_REVISION) 191 printf("%s: aha_cmd, cmd/data port full\n", name); 192 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_SRST); 193 return (1); 194 } 195 bus_space_write_1(iot, ioh, AHA_CMD_PORT, *ibuf++); 196 } 197 /* 198 * If we expect input, loop that many times, each time, 199 * looking for the data register to have valid data 200 */ 201 while (ocnt--) { 202 for (i = wait; i; i--) { 203 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 204 if (sts & AHA_STAT_DF) 205 break; 206 delay(50); 207 } 208 if (!i) { 209 if (opcode != AHA_INQUIRE_REVISION) 210 printf("%s: aha_cmd, cmd/data port empty %d\n", 211 name, ocnt); 212 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, 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); 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 *) (((char *) (&ccb->scsi_cmd)) + 712 ccb->scsi_cmd_length); 713 s2 = &xs->sense.scsi_sense; 714 *s2 = *s1; 715 xs->error = XS_SENSE; 716 break; 717 case SCSI_BUSY: 718 xs->error = XS_BUSY; 719 break; 720 default: 721 printf("%s: target_stat %x\n", 722 device_xname(sc->sc_dev), ccb->target_stat); 723 xs->error = XS_DRIVER_STUFFUP; 724 break; 725 } 726 } else 727 xs->resid = 0; 728 } 729 aha_free_ccb(sc, ccb); 730 scsipi_done(xs); 731 } 732 733 /* 734 * Find the board and find its irq/drq 735 */ 736 int 737 aha_find(bus_space_tag_t iot, bus_space_handle_t ioh, struct aha_probe_data *sc) 738 { 739 int i; 740 u_char sts; 741 struct aha_config config; 742 int irq, drq; 743 744 /* 745 * assume invalid status means the board is not present. 746 */ 747 748 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 749 if (sts == 0) 750 return (0); 751 if ((sts & (AHA_STAT_STST|AHA_STAT_RSVD|AHA_STAT_CDF)) != 0) 752 return (0); 753 sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT); 754 if ((sts & AHA_INTR_RSVD) != 0) 755 return (0); 756 757 /* 758 * reset board, If it doesn't respond, assume 759 * that it's not there.. good for the probe 760 */ 761 762 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST); 763 764 delay(100); 765 for (i = AHA_RESET_TIMEOUT; i; i--) { 766 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 767 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 768 break; 769 delay(1000); /* calibrated in msec */ 770 } 771 if (!i) { 772 #ifdef AHADEBUG 773 if (aha_debug) 774 printf("aha_find: No answer from adaptec board\n"); 775 #endif /* AHADEBUG */ 776 return (0); 777 } 778 779 /* 780 * setup DMA channel from jumpers and save int 781 * level 782 */ 783 delay(1000); /* for Bustek 545 */ 784 config.cmd.opcode = AHA_INQUIRE_CONFIG; 785 aha_cmd(iot, ioh, (struct aha_softc *)0, 786 sizeof(config.cmd), (u_char *)&config.cmd, 787 sizeof(config.reply), (u_char *)&config.reply); 788 switch (config.reply.chan) { 789 case EISADMA: 790 drq = -1; 791 break; 792 case CHAN0: 793 drq = 0; 794 break; 795 case CHAN5: 796 drq = 5; 797 break; 798 case CHAN6: 799 drq = 6; 800 break; 801 case CHAN7: 802 drq = 7; 803 break; 804 default: 805 printf("aha_find: illegal drq setting %x\n", config.reply.chan); 806 return (0); 807 } 808 809 switch (config.reply.intr) { 810 case INT9: 811 irq = 9; 812 break; 813 case INT10: 814 irq = 10; 815 break; 816 case INT11: 817 irq = 11; 818 break; 819 case INT12: 820 irq = 12; 821 break; 822 case INT14: 823 irq = 14; 824 break; 825 case INT15: 826 irq = 15; 827 break; 828 default: 829 printf("aha_find: illegal irq setting %x\n", config.reply.intr); 830 return (0); 831 } 832 833 if (sc) { 834 sc->sc_irq = irq; 835 sc->sc_drq = drq; 836 sc->sc_scsi_dev = config.reply.scsi_dev; 837 } 838 839 return (1); 840 } 841 842 /* 843 * Start the board, ready for normal operation 844 */ 845 static int 846 aha_init(struct aha_softc *sc) 847 { 848 bus_space_tag_t iot = sc->sc_iot; 849 bus_space_handle_t ioh = sc->sc_ioh; 850 bus_dma_segment_t seg; 851 struct aha_devices devices; 852 struct aha_setup setup; 853 struct aha_mailbox mailbox; 854 int error, i, j, initial_ccbs, rseg; 855 856 /* 857 * XXX 858 * If we are a 1542C or later, disable the extended BIOS so that the 859 * mailbox interface is unlocked. 860 * No need to check the extended BIOS flags as some of the 861 * extensions that cause us problems are not flagged in that byte. 862 */ 863 if (!strncmp(sc->sc_model, "1542C", 5)) { 864 struct aha_extbios extbios; 865 struct aha_unlock unlock; 866 867 printf("%s: unlocking mailbox interface\n", 868 device_xname(sc->sc_dev)); 869 extbios.cmd.opcode = AHA_EXT_BIOS; 870 aha_cmd(iot, ioh, sc, 871 sizeof(extbios.cmd), (u_char *)&extbios.cmd, 872 sizeof(extbios.reply), (u_char *)&extbios.reply); 873 874 #ifdef AHADEBUG 875 printf("%s: flags=%02x, mailboxlock=%02x\n", 876 device_xname(sc->sc_dev), 877 extbios.reply.flags, extbios.reply.mailboxlock); 878 #endif /* AHADEBUG */ 879 880 unlock.cmd.opcode = AHA_MBX_ENABLE; 881 unlock.cmd.junk = 0; 882 unlock.cmd.magic = extbios.reply.mailboxlock; 883 aha_cmd(iot, ioh, sc, 884 sizeof(unlock.cmd), (u_char *)&unlock.cmd, 885 0, (u_char *)0); 886 } 887 888 #if 0 889 /* 890 * Change the bus on/off times to not clash with other DMA users. 891 */ 892 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7); 893 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4); 894 #endif 895 896 /* Inquire Installed Devices (to force synchronous negotiation). */ 897 devices.cmd.opcode = AHA_INQUIRE_DEVICES; 898 aha_cmd(iot, ioh, sc, 899 sizeof(devices.cmd), (u_char *)&devices.cmd, 900 sizeof(devices.reply), (u_char *)&devices.reply); 901 902 /* Count installed units */ 903 initial_ccbs = 0; 904 for (i = 0; i < 8; i++) { 905 for (j = 0; j < 8; j++) { 906 if (((devices.reply.lun_map[i] >> j) & 1) == 1) 907 initial_ccbs += 1; 908 } 909 } 910 initial_ccbs *= 2; 911 if (initial_ccbs > AHA_CCB_MAX) 912 initial_ccbs = AHA_CCB_MAX; 913 if (initial_ccbs == 0) /* yes, this can happen */ 914 initial_ccbs = 2; 915 916 /* Obtain setup information from. */ 917 setup.cmd.opcode = AHA_INQUIRE_SETUP; 918 setup.cmd.len = sizeof(setup.reply); 919 aha_cmd(iot, ioh, sc, 920 sizeof(setup.cmd), (u_char *)&setup.cmd, 921 sizeof(setup.reply), (u_char *)&setup.reply); 922 923 printf("%s: %s, %s\n", 924 device_xname(sc->sc_dev), 925 setup.reply.sync_neg ? "sync" : "async", 926 setup.reply.parity ? "parity" : "no parity"); 927 928 for (i = 0; i < 8; i++) { 929 if (!setup.reply.sync[i].valid || 930 (!setup.reply.sync[i].offset && !setup.reply.sync[i].period)) 931 continue; 932 printf("%s targ %d: sync, offset %d, period %dnsec\n", 933 device_xname(sc->sc_dev), i, 934 setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200); 935 } 936 937 /* 938 * Allocate the mailbox and control blocks. 939 */ 940 if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct aha_control), 941 PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 942 aprint_error_dev(sc->sc_dev, 943 "unable to allocate control structures, " 944 "error = %d\n", error); 945 return (error); 946 } 947 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 948 sizeof(struct aha_control), (void **)&sc->sc_control, 949 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { 950 aprint_error_dev(sc->sc_dev, 951 "unable to map control structures, error = %d\n", error); 952 return (error); 953 } 954 955 /* 956 * Create and load the DMA map used for the mailbox and 957 * control blocks. 958 */ 959 if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct aha_control), 960 1, sizeof(struct aha_control), 0, BUS_DMA_NOWAIT, 961 &sc->sc_dmamap_control)) != 0) { 962 aprint_error_dev(sc->sc_dev, 963 "unable to create control DMA map, error = %d\n", 964 error); 965 return (error); 966 } 967 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control, 968 sc->sc_control, sizeof(struct aha_control), NULL, 969 BUS_DMA_NOWAIT)) != 0) { 970 aprint_error_dev(sc->sc_dev, 971 "unable to load control DMA map, error = %d\n", 972 error); 973 return (error); 974 } 975 976 /* 977 * Initialize the control blocks. 978 */ 979 i = aha_create_ccbs(sc, sc->sc_control->ac_ccbs, initial_ccbs); 980 if (i == 0) { 981 aprint_error_dev(sc->sc_dev, 982 "unable to create control blocks\n"); 983 return (ENOMEM); 984 } else if (i != initial_ccbs) { 985 printf("%s: WARNING: only %d of %d control blocks created\n", 986 device_xname(sc->sc_dev), i, initial_ccbs); 987 } 988 989 sc->sc_adapter.adapt_openings = i; 990 sc->sc_adapter.adapt_max_periph = sc->sc_adapter.adapt_openings; 991 992 /* 993 * Set up initial mail box for round-robin operation. 994 */ 995 for (i = 0; i < AHA_MBX_SIZE; i++) { 996 wmbx->mbo[i].cmd = AHA_MBO_FREE; 997 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 998 AHA_MBO_OFF(&wmbx->mbo[i]), sizeof(struct aha_mbx_out), 999 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1000 wmbx->mbi[i].stat = AHA_MBI_FREE; 1001 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 1002 AHA_MBI_OFF(&wmbx->mbi[i]), sizeof(struct aha_mbx_in), 1003 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1004 } 1005 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0]; 1006 wmbx->tmbi = &wmbx->mbi[0]; 1007 sc->sc_mbofull = 0; 1008 1009 /* Initialize mail box. */ 1010 mailbox.cmd.opcode = AHA_MBX_INIT; 1011 mailbox.cmd.nmbx = AHA_MBX_SIZE; 1012 ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 1013 offsetof(struct aha_control, ac_mbx), mailbox.cmd.addr); 1014 aha_cmd(iot, ioh, sc, 1015 sizeof(mailbox.cmd), (u_char *)&mailbox.cmd, 1016 0, (u_char *)0); 1017 return (0); 1018 } 1019 1020 static void 1021 aha_inquire_setup_information(struct aha_softc *sc) 1022 { 1023 bus_space_tag_t iot = sc->sc_iot; 1024 bus_space_handle_t ioh = sc->sc_ioh; 1025 struct aha_revision revision; 1026 u_char sts; 1027 int i; 1028 char *p; 1029 1030 strcpy(sc->sc_model, "unknown"); 1031 1032 /* 1033 * Assume we have a board at this stage, do an adapter inquire 1034 * to find out what type of controller it is. If the command 1035 * fails, we assume it's either a crusty board or an old 1542 1036 * clone, and skip the board-specific stuff. 1037 */ 1038 revision.cmd.opcode = AHA_INQUIRE_REVISION; 1039 if (aha_cmd(iot, ioh, sc, 1040 sizeof(revision.cmd), (u_char *)&revision.cmd, 1041 sizeof(revision.reply), (u_char *)&revision.reply)) { 1042 /* 1043 * aha_cmd() already started the reset. It's not clear we 1044 * even need to bother here. 1045 */ 1046 for (i = AHA_RESET_TIMEOUT; i; i--) { 1047 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 1048 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 1049 break; 1050 delay(1000); 1051 } 1052 if (!i) { 1053 #ifdef AHADEBUG 1054 printf("aha_init: soft reset failed\n"); 1055 #endif /* AHADEBUG */ 1056 return; 1057 } 1058 #ifdef AHADEBUG 1059 printf("aha_init: inquire command failed\n"); 1060 #endif /* AHADEBUG */ 1061 goto noinquire; 1062 } 1063 1064 #ifdef AHADEBUG 1065 printf("%s: inquire %x, %x, %x, %x\n", 1066 device_xname(sc->sc_dev), 1067 revision.reply.boardid, revision.reply.spec_opts, 1068 revision.reply.revision_1, revision.reply.revision_2); 1069 #endif /* AHADEBUG */ 1070 1071 switch (revision.reply.boardid) { 1072 case BOARD_1540_16HEAD_BIOS: 1073 case BOARD_1540_64HEAD_BIOS: 1074 case BOARD_1540: 1075 strcpy(sc->sc_model, "1540"); 1076 break; 1077 case BOARD_1542: 1078 strcpy(sc->sc_model, "1540A/1542A/1542B"); 1079 break; 1080 case BOARD_1640: 1081 strcpy(sc->sc_model, "1640"); 1082 break; 1083 case BOARD_1740: 1084 strcpy(sc->sc_model, "1740"); 1085 break; 1086 case BOARD_1542C: 1087 strcpy(sc->sc_model, "1542C"); 1088 break; 1089 case BOARD_1542CF: 1090 strcpy(sc->sc_model, "1542CF"); 1091 break; 1092 case BOARD_1542CP: 1093 strcpy(sc->sc_model, "1542CP"); 1094 break; 1095 } 1096 1097 p = sc->sc_firmware; 1098 *p++ = revision.reply.revision_1; 1099 *p++ = '.'; 1100 *p++ = revision.reply.revision_2; 1101 *p = '\0'; 1102 1103 noinquire: 1104 printf("%s: model AHA-%s, firmware %s\n", 1105 device_xname(sc->sc_dev), 1106 sc->sc_model, sc->sc_firmware); 1107 } 1108 1109 static void 1110 ahaminphys(struct buf *bp) 1111 { 1112 1113 if (bp->b_bcount > AHA_MAXXFER) 1114 bp->b_bcount = AHA_MAXXFER; 1115 minphys(bp); 1116 } 1117 1118 /* 1119 * start a scsi operation given the command and the data address. Also needs 1120 * the unit, target and lu. 1121 */ 1122 1123 static void 1124 aha_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 1125 void *arg) 1126 { 1127 struct scsipi_xfer *xs; 1128 struct scsipi_periph *periph; 1129 struct aha_softc *sc = device_private(chan->chan_adapter->adapt_dev); 1130 bus_dma_tag_t dmat = sc->sc_dmat; 1131 struct aha_ccb *ccb; 1132 int error, seg, flags, s; 1133 1134 1135 switch (req) { 1136 case ADAPTER_REQ_RUN_XFER: 1137 xs = arg; 1138 periph = xs->xs_periph; 1139 flags = xs->xs_control; 1140 1141 SC_DEBUG(periph, SCSIPI_DB2, ("aha_scsipi_request\n")); 1142 1143 /* Get a CCB to use. */ 1144 ccb = aha_get_ccb(sc); 1145 #ifdef DIAGNOSTIC 1146 /* 1147 * This should never happen as we track the resources 1148 * in the mid-layer. 1149 */ 1150 if (ccb == NULL) { 1151 scsipi_printaddr(periph); 1152 printf("unable to allocate ccb\n"); 1153 panic("aha_scsipi_request"); 1154 } 1155 #endif 1156 1157 ccb->xs = xs; 1158 ccb->timeout = xs->timeout; 1159 1160 /* 1161 * Put all the arguments for the xfer in the ccb 1162 */ 1163 if (flags & XS_CTL_RESET) { 1164 ccb->opcode = AHA_RESET_CCB; 1165 ccb->scsi_cmd_length = 0; 1166 } else { 1167 /* can't use S/G if zero length */ 1168 if (xs->cmdlen > sizeof(ccb->scsi_cmd)) { 1169 printf("%s: cmdlen %d too large for CCB\n", 1170 device_xname(sc->sc_dev), xs->cmdlen); 1171 xs->error = XS_DRIVER_STUFFUP; 1172 goto out_bad; 1173 } 1174 ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB 1175 : AHA_INITIATOR_CCB); 1176 memcpy(&ccb->scsi_cmd, xs->cmd, 1177 ccb->scsi_cmd_length = xs->cmdlen); 1178 } 1179 1180 if (xs->datalen) { 1181 /* 1182 * Map the DMA transfer. 1183 */ 1184 #ifdef TFS 1185 if (flags & XS_CTL_DATA_UIO) { 1186 error = bus_dmamap_load_uio(dmat, 1187 ccb->dmamap_xfer, (struct uio *)xs->data, 1188 ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : 1189 BUS_DMA_WAITOK) | BUS_DMA_STREAMING | 1190 ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ : 1191 BUS_DMA_WRITE)); 1192 } else 1193 #endif 1194 { 1195 error = bus_dmamap_load(dmat, 1196 ccb->dmamap_xfer, xs->data, xs->datalen, 1197 NULL, 1198 ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : 1199 BUS_DMA_WAITOK) | BUS_DMA_STREAMING | 1200 ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ : 1201 BUS_DMA_WRITE)); 1202 } 1203 1204 switch (error) { 1205 case 0: 1206 break; 1207 1208 case ENOMEM: 1209 case EAGAIN: 1210 xs->error = XS_RESOURCE_SHORTAGE; 1211 goto out_bad; 1212 1213 default: 1214 xs->error = XS_DRIVER_STUFFUP; 1215 if (error == EFBIG) { 1216 printf("%s: aha_scsi_cmd, more than %d" 1217 " DMA segments\n", 1218 device_xname(sc->sc_dev), AHA_NSEG); 1219 } else { 1220 aprint_error_dev(sc->sc_dev, 1221 "error %d loading DMA map\n", 1222 error); 1223 } 1224 out_bad: 1225 aha_free_ccb(sc, ccb); 1226 scsipi_done(xs); 1227 return; 1228 } 1229 1230 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0, 1231 ccb->dmamap_xfer->dm_mapsize, 1232 (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : 1233 BUS_DMASYNC_PREWRITE); 1234 1235 /* 1236 * Load the hardware scatter/gather map with the 1237 * contents of the DMA map. 1238 */ 1239 for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) { 1240 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr, 1241 ccb->scat_gath[seg].seg_addr); 1242 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len, 1243 ccb->scat_gath[seg].seg_len); 1244 } 1245 1246 ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 1247 AHA_CCB_OFF(ccb) + 1248 offsetof(struct aha_ccb, scat_gath), 1249 ccb->data_addr); 1250 ltophys(ccb->dmamap_xfer->dm_nsegs * 1251 sizeof(struct aha_scat_gath), ccb->data_length); 1252 } else { 1253 /* 1254 * No data xfer, use non S/G values. 1255 */ 1256 ltophys(0, ccb->data_addr); 1257 ltophys(0, ccb->data_length); 1258 } 1259 1260 ccb->data_out = 0; 1261 ccb->data_in = 0; 1262 ccb->target = periph->periph_target; 1263 ccb->lun = periph->periph_lun; 1264 ccb->req_sense_length = sizeof(ccb->scsi_sense); 1265 ccb->host_stat = 0x00; 1266 ccb->target_stat = 0x00; 1267 ccb->link_id = 0; 1268 ltophys(0, ccb->link_addr); 1269 1270 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 1271 AHA_CCB_OFF(ccb), sizeof(struct aha_ccb), 1272 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1273 1274 s = splbio(); 1275 aha_queue_ccb(sc, ccb); 1276 splx(s); 1277 1278 SC_DEBUG(periph, SCSIPI_DB3, ("cmd_sent\n")); 1279 if ((flags & XS_CTL_POLL) == 0) 1280 return; 1281 1282 /* Not allowed to use interrupts, poll for completion. */ 1283 if (aha_poll(sc, xs, ccb->timeout)) { 1284 aha_timeout(ccb); 1285 if (aha_poll(sc, xs, ccb->timeout)) 1286 aha_timeout(ccb); 1287 } 1288 return; 1289 1290 case ADAPTER_REQ_GROW_RESOURCES: 1291 /* XXX Not supported. */ 1292 return; 1293 1294 case ADAPTER_REQ_SET_XFER_MODE: 1295 /* 1296 * Can't really do this on the Adaptec; it has 1297 * its own config mechanism, but we do know how 1298 * to query what the firmware negotiated. 1299 */ 1300 /* XXX XXX XXX */ 1301 return; 1302 } 1303 } 1304 1305 /* 1306 * Poll a particular unit, looking for a particular xs 1307 */ 1308 static int 1309 aha_poll(struct aha_softc *sc, struct scsipi_xfer *xs, int count) 1310 { 1311 bus_space_tag_t iot = sc->sc_iot; 1312 bus_space_handle_t ioh = sc->sc_ioh; 1313 1314 /* timeouts are in msec, so we loop in 1000 usec cycles */ 1315 while (count) { 1316 /* 1317 * If we had interrupts enabled, would we 1318 * have got an interrupt? 1319 */ 1320 if (bus_space_read_1(iot, ioh, AHA_INTR_PORT) & AHA_INTR_ANYINTR) 1321 aha_intr(sc); 1322 if (xs->xs_status & XS_STS_DONE) 1323 return (0); 1324 delay(1000); /* only happens in boot so ok */ 1325 count--; 1326 } 1327 return (1); 1328 } 1329 1330 static void 1331 aha_timeout(void *arg) 1332 { 1333 struct aha_ccb *ccb = arg; 1334 struct scsipi_xfer *xs = ccb->xs; 1335 struct scsipi_periph *periph = xs->xs_periph; 1336 struct aha_softc *sc = 1337 device_private(periph->periph_channel->chan_adapter->adapt_dev); 1338 int s; 1339 1340 scsipi_printaddr(periph); 1341 printf("timed out"); 1342 1343 s = splbio(); 1344 1345 #ifdef AHADIAG 1346 /* 1347 * If The ccb's mbx is not free, then the board has gone south? 1348 */ 1349 aha_collect_mbo(sc); 1350 if (ccb->flags & CCB_SENDING) { 1351 aprint_error_dev(sc->sc_dev, "not taking commands!\n"); 1352 Debugger(); 1353 } 1354 #endif 1355 1356 /* 1357 * If it has been through before, then 1358 * a previous abort has failed, don't 1359 * try abort again 1360 */ 1361 if (ccb->flags & CCB_ABORT) { 1362 /* abort timed out */ 1363 printf(" AGAIN\n"); 1364 /* XXX Must reset! */ 1365 } else { 1366 /* abort the operation that has timed out */ 1367 printf("\n"); 1368 ccb->xs->error = XS_TIMEOUT; 1369 ccb->timeout = AHA_ABORT_TIMEOUT; 1370 ccb->flags |= CCB_ABORT; 1371 aha_queue_ccb(sc, ccb); 1372 } 1373 1374 splx(s); 1375 } 1376