1 /* $NetBSD: aha.c,v 1.58 2009/03/14 15:36:17 dsl 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.58 2009/03/14 15:36:17 dsl 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, "unable to create ccb DMA map, error = %d\n", 468 error); 469 return (error); 470 } 471 472 /* 473 * put in the phystokv hash table 474 * Never gets taken out. 475 */ 476 ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr + 477 AHA_CCB_OFF(ccb); 478 hashnum = CCB_HASH(ccb->hashkey); 479 ccb->nexthash = sc->sc_ccbhash[hashnum]; 480 sc->sc_ccbhash[hashnum] = ccb; 481 aha_reset_ccb(sc, ccb); 482 return (0); 483 } 484 485 /* 486 * Create a set of ccbs and add them to the free list. Called once 487 * by aha_init(). We return the number of CCBs successfully created. 488 */ 489 static int 490 aha_create_ccbs(struct aha_softc *sc, struct aha_ccb *ccbstore, int count) 491 { 492 struct aha_ccb *ccb; 493 int i, error; 494 495 memset(ccbstore, 0, sizeof(struct aha_ccb) * count); 496 for (i = 0; i < count; i++) { 497 ccb = &ccbstore[i]; 498 if ((error = aha_init_ccb(sc, ccb)) != 0) { 499 aprint_error_dev(&sc->sc_dev, "unable to initialize ccb, error = %d\n", 500 error); 501 goto out; 502 } 503 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain); 504 } 505 out: 506 return (i); 507 } 508 509 /* 510 * Get a free ccb 511 * 512 * If there are none, see if we can allocate a new one. If so, put it in 513 * the hash table too otherwise either return an error or sleep. 514 */ 515 struct aha_ccb * 516 aha_get_ccb(struct aha_softc *sc) 517 { 518 struct aha_ccb *ccb; 519 int s; 520 521 s = splbio(); 522 ccb = TAILQ_FIRST(&sc->sc_free_ccb); 523 if (ccb != NULL) { 524 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); 525 ccb->flags |= CCB_ALLOC; 526 } 527 splx(s); 528 return (ccb); 529 } 530 531 /* 532 * Given a physical address, find the ccb that it corresponds to. 533 */ 534 static struct aha_ccb * 535 aha_ccb_phys_kv(struct aha_softc *sc, u_long ccb_phys) 536 { 537 int hashnum = CCB_HASH(ccb_phys); 538 struct aha_ccb *ccb = sc->sc_ccbhash[hashnum]; 539 540 while (ccb) { 541 if (ccb->hashkey == ccb_phys) 542 break; 543 ccb = ccb->nexthash; 544 } 545 return (ccb); 546 } 547 548 /* 549 * Queue a CCB to be sent to the controller, and send it if possible. 550 */ 551 static void 552 aha_queue_ccb(struct aha_softc *sc, struct aha_ccb *ccb) 553 { 554 555 TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain); 556 aha_start_ccbs(sc); 557 } 558 559 /* 560 * Garbage collect mailboxes that are no longer in use. 561 */ 562 static void 563 aha_collect_mbo(struct aha_softc *sc) 564 { 565 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */ 566 #ifdef AHADIAG 567 struct aha_ccb *ccb; 568 #endif 569 570 wmbo = wmbx->cmbo; 571 572 while (sc->sc_mbofull > 0) { 573 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 574 AHA_MBO_OFF(wmbo), sizeof(struct aha_mbx_out), 575 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 576 if (wmbo->cmd != AHA_MBO_FREE) 577 break; 578 579 #ifdef AHADIAG 580 ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr)); 581 ccb->flags &= ~CCB_SENDING; 582 #endif 583 584 --sc->sc_mbofull; 585 aha_nextmbx(wmbo, wmbx, mbo); 586 } 587 588 wmbx->cmbo = wmbo; 589 } 590 591 /* 592 * Send as many CCBs as we have empty mailboxes for. 593 */ 594 static void 595 aha_start_ccbs(struct aha_softc *sc) 596 { 597 bus_space_tag_t iot = sc->sc_iot; 598 bus_space_handle_t ioh = sc->sc_ioh; 599 struct aha_mbx_out *wmbo; /* Mail Box Out pointer */ 600 struct aha_ccb *ccb; 601 602 wmbo = wmbx->tmbo; 603 604 while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) { 605 if (sc->sc_mbofull >= AHA_MBX_SIZE) { 606 aha_collect_mbo(sc); 607 if (sc->sc_mbofull >= AHA_MBX_SIZE) { 608 struct aha_toggle toggle; 609 610 toggle.cmd.opcode = AHA_MBO_INTR_EN; 611 toggle.cmd.enable = 1; 612 aha_cmd(iot, ioh, sc, 613 sizeof(toggle.cmd), (u_char *)&toggle.cmd, 614 0, (u_char *)0); 615 break; 616 } 617 } 618 619 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain); 620 #ifdef AHADIAG 621 ccb->flags |= CCB_SENDING; 622 #endif 623 624 /* Link ccb to mbo. */ 625 ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 626 AHA_CCB_OFF(ccb), wmbo->ccb_addr); 627 if (ccb->flags & CCB_ABORT) 628 wmbo->cmd = AHA_MBO_ABORT; 629 else 630 wmbo->cmd = AHA_MBO_START; 631 632 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 633 AHA_MBO_OFF(wmbo), sizeof(struct aha_mbx_out), 634 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 635 636 /* Tell the card to poll immediately. */ 637 bus_space_write_1(iot, ioh, AHA_CMD_PORT, AHA_START_SCSI); 638 639 if ((ccb->xs->xs_control & XS_CTL_POLL) == 0) 640 callout_reset(&ccb->xs->xs_callout, 641 mstohz(ccb->timeout), aha_timeout, ccb); 642 643 ++sc->sc_mbofull; 644 aha_nextmbx(wmbo, wmbx, mbo); 645 } 646 647 wmbx->tmbo = wmbo; 648 } 649 650 /* 651 * We have a ccb which has been processed by the 652 * adaptor, now we look to see how the operation 653 * went. Wake up the owner if waiting 654 */ 655 static void 656 aha_done(struct aha_softc *sc, struct aha_ccb *ccb) 657 { 658 bus_dma_tag_t dmat = sc->sc_dmat; 659 struct scsi_sense_data *s1, *s2; 660 struct scsipi_xfer *xs = ccb->xs; 661 662 SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("aha_done\n")); 663 664 /* 665 * If we were a data transfer, unload the map that described 666 * the data buffer. 667 */ 668 if (xs->datalen) { 669 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0, 670 ccb->dmamap_xfer->dm_mapsize, 671 (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD : 672 BUS_DMASYNC_POSTWRITE); 673 bus_dmamap_unload(dmat, ccb->dmamap_xfer); 674 } 675 676 /* 677 * Otherwise, put the results of the operation 678 * into the xfer and call whoever started it 679 */ 680 #ifdef AHADIAG 681 if (ccb->flags & CCB_SENDING) { 682 printf("%s: exiting ccb still in transit!\n", device_xname(&sc->sc_dev)); 683 Debugger(); 684 return; 685 } 686 #endif 687 if ((ccb->flags & CCB_ALLOC) == 0) { 688 printf("%s: exiting ccb not allocated!\n", device_xname(&sc->sc_dev)); 689 Debugger(); 690 return; 691 } 692 if (xs->error == XS_NOERROR) { 693 if (ccb->host_stat != AHA_OK) { 694 switch (ccb->host_stat) { 695 case AHA_SEL_TIMEOUT: /* No response */ 696 xs->error = XS_SELTIMEOUT; 697 break; 698 default: /* Other scsi protocol messes */ 699 printf("%s: host_stat %x\n", 700 device_xname(&sc->sc_dev), ccb->host_stat); 701 xs->error = XS_DRIVER_STUFFUP; 702 break; 703 } 704 } else if (ccb->target_stat != SCSI_OK) { 705 switch (ccb->target_stat) { 706 case SCSI_CHECK: 707 s1 = (struct scsi_sense_data *) (((char *) (&ccb->scsi_cmd)) + 708 ccb->scsi_cmd_length); 709 s2 = &xs->sense.scsi_sense; 710 *s2 = *s1; 711 xs->error = XS_SENSE; 712 break; 713 case SCSI_BUSY: 714 xs->error = XS_BUSY; 715 break; 716 default: 717 printf("%s: target_stat %x\n", 718 device_xname(&sc->sc_dev), ccb->target_stat); 719 xs->error = XS_DRIVER_STUFFUP; 720 break; 721 } 722 } else 723 xs->resid = 0; 724 } 725 aha_free_ccb(sc, ccb); 726 scsipi_done(xs); 727 } 728 729 /* 730 * Find the board and find its irq/drq 731 */ 732 int 733 aha_find(bus_space_tag_t iot, bus_space_handle_t ioh, struct aha_probe_data *sc) 734 { 735 int i; 736 u_char sts; 737 struct aha_config config; 738 int irq, drq; 739 740 /* 741 * assume invalid status means the board is not present. 742 */ 743 744 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 745 if (sts == 0) 746 return (0); 747 if ((sts & (AHA_STAT_STST|AHA_STAT_RSVD|AHA_STAT_CDF)) != 0) 748 return (0); 749 sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT); 750 if ((sts & AHA_INTR_RSVD) != 0) 751 return (0); 752 753 /* 754 * reset board, If it doesn't respond, assume 755 * that it's not there.. good for the probe 756 */ 757 758 bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST); 759 760 delay(100); 761 for (i = AHA_RESET_TIMEOUT; i; i--) { 762 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 763 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 764 break; 765 delay(1000); /* calibrated in msec */ 766 } 767 if (!i) { 768 #ifdef AHADEBUG 769 if (aha_debug) 770 printf("aha_find: No answer from adaptec board\n"); 771 #endif /* AHADEBUG */ 772 return (0); 773 } 774 775 /* 776 * setup DMA channel from jumpers and save int 777 * level 778 */ 779 delay(1000); /* for Bustek 545 */ 780 config.cmd.opcode = AHA_INQUIRE_CONFIG; 781 aha_cmd(iot, ioh, (struct aha_softc *)0, 782 sizeof(config.cmd), (u_char *)&config.cmd, 783 sizeof(config.reply), (u_char *)&config.reply); 784 switch (config.reply.chan) { 785 case EISADMA: 786 drq = -1; 787 break; 788 case CHAN0: 789 drq = 0; 790 break; 791 case CHAN5: 792 drq = 5; 793 break; 794 case CHAN6: 795 drq = 6; 796 break; 797 case CHAN7: 798 drq = 7; 799 break; 800 default: 801 printf("aha_find: illegal drq setting %x\n", config.reply.chan); 802 return (0); 803 } 804 805 switch (config.reply.intr) { 806 case INT9: 807 irq = 9; 808 break; 809 case INT10: 810 irq = 10; 811 break; 812 case INT11: 813 irq = 11; 814 break; 815 case INT12: 816 irq = 12; 817 break; 818 case INT14: 819 irq = 14; 820 break; 821 case INT15: 822 irq = 15; 823 break; 824 default: 825 printf("aha_find: illegal irq setting %x\n", config.reply.intr); 826 return (0); 827 } 828 829 if (sc) { 830 sc->sc_irq = irq; 831 sc->sc_drq = drq; 832 sc->sc_scsi_dev = config.reply.scsi_dev; 833 } 834 835 return (1); 836 } 837 838 /* 839 * Start the board, ready for normal operation 840 */ 841 static int 842 aha_init(struct aha_softc *sc) 843 { 844 bus_space_tag_t iot = sc->sc_iot; 845 bus_space_handle_t ioh = sc->sc_ioh; 846 bus_dma_segment_t seg; 847 struct aha_devices devices; 848 struct aha_setup setup; 849 struct aha_mailbox mailbox; 850 int error, i, j, initial_ccbs, rseg; 851 852 /* 853 * XXX 854 * If we are a 1542C or later, disable the extended BIOS so that the 855 * mailbox interface is unlocked. 856 * No need to check the extended BIOS flags as some of the 857 * extensions that cause us problems are not flagged in that byte. 858 */ 859 if (!strncmp(sc->sc_model, "1542C", 5)) { 860 struct aha_extbios extbios; 861 struct aha_unlock unlock; 862 863 printf("%s: unlocking mailbox interface\n", device_xname(&sc->sc_dev)); 864 extbios.cmd.opcode = AHA_EXT_BIOS; 865 aha_cmd(iot, ioh, sc, 866 sizeof(extbios.cmd), (u_char *)&extbios.cmd, 867 sizeof(extbios.reply), (u_char *)&extbios.reply); 868 869 #ifdef AHADEBUG 870 printf("%s: flags=%02x, mailboxlock=%02x\n", 871 device_xname(&sc->sc_dev), 872 extbios.reply.flags, extbios.reply.mailboxlock); 873 #endif /* AHADEBUG */ 874 875 unlock.cmd.opcode = AHA_MBX_ENABLE; 876 unlock.cmd.junk = 0; 877 unlock.cmd.magic = extbios.reply.mailboxlock; 878 aha_cmd(iot, ioh, sc, 879 sizeof(unlock.cmd), (u_char *)&unlock.cmd, 880 0, (u_char *)0); 881 } 882 883 #if 0 884 /* 885 * Change the bus on/off times to not clash with other DMA users. 886 */ 887 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7); 888 aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4); 889 #endif 890 891 /* Inquire Installed Devices (to force synchronous negotiation). */ 892 devices.cmd.opcode = AHA_INQUIRE_DEVICES; 893 aha_cmd(iot, ioh, sc, 894 sizeof(devices.cmd), (u_char *)&devices.cmd, 895 sizeof(devices.reply), (u_char *)&devices.reply); 896 897 /* Count installed units */ 898 initial_ccbs = 0; 899 for (i = 0; i < 8; i++) { 900 for (j = 0; j < 8; j++) { 901 if (((devices.reply.lun_map[i] >> j) & 1) == 1) 902 initial_ccbs += 1; 903 } 904 } 905 initial_ccbs *= 2; 906 if (initial_ccbs > AHA_CCB_MAX) 907 initial_ccbs = AHA_CCB_MAX; 908 if (initial_ccbs == 0) /* yes, this can happen */ 909 initial_ccbs = 2; 910 911 /* Obtain setup information from. */ 912 setup.cmd.opcode = AHA_INQUIRE_SETUP; 913 setup.cmd.len = sizeof(setup.reply); 914 aha_cmd(iot, ioh, sc, 915 sizeof(setup.cmd), (u_char *)&setup.cmd, 916 sizeof(setup.reply), (u_char *)&setup.reply); 917 918 printf("%s: %s, %s\n", 919 device_xname(&sc->sc_dev), 920 setup.reply.sync_neg ? "sync" : "async", 921 setup.reply.parity ? "parity" : "no parity"); 922 923 for (i = 0; i < 8; i++) { 924 if (!setup.reply.sync[i].valid || 925 (!setup.reply.sync[i].offset && !setup.reply.sync[i].period)) 926 continue; 927 printf("%s targ %d: sync, offset %d, period %dnsec\n", 928 device_xname(&sc->sc_dev), i, 929 setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200); 930 } 931 932 /* 933 * Allocate the mailbox and control blocks. 934 */ 935 if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct aha_control), 936 PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 937 aprint_error_dev(&sc->sc_dev, "unable to allocate control structures, " 938 "error = %d\n", error); 939 return (error); 940 } 941 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 942 sizeof(struct aha_control), (void **)&sc->sc_control, 943 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { 944 aprint_error_dev(&sc->sc_dev, "unable to map control structures, error = %d\n", error); 945 return (error); 946 } 947 948 /* 949 * Create and load the DMA map used for the mailbox and 950 * control blocks. 951 */ 952 if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct aha_control), 953 1, sizeof(struct aha_control), 0, BUS_DMA_NOWAIT, 954 &sc->sc_dmamap_control)) != 0) { 955 aprint_error_dev(&sc->sc_dev, "unable to create control DMA map, error = %d\n", 956 error); 957 return (error); 958 } 959 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control, 960 sc->sc_control, sizeof(struct aha_control), NULL, 961 BUS_DMA_NOWAIT)) != 0) { 962 aprint_error_dev(&sc->sc_dev, "unable to load control DMA map, error = %d\n", 963 error); 964 return (error); 965 } 966 967 /* 968 * Initialize the control blocks. 969 */ 970 i = aha_create_ccbs(sc, sc->sc_control->ac_ccbs, initial_ccbs); 971 if (i == 0) { 972 aprint_error_dev(&sc->sc_dev, "unable to create control blocks\n"); 973 return (ENOMEM); 974 } else if (i != initial_ccbs) { 975 printf("%s: WARNING: only %d of %d control blocks created\n", 976 device_xname(&sc->sc_dev), i, initial_ccbs); 977 } 978 979 sc->sc_adapter.adapt_openings = i; 980 sc->sc_adapter.adapt_max_periph = sc->sc_adapter.adapt_openings; 981 982 /* 983 * Set up initial mail box for round-robin operation. 984 */ 985 for (i = 0; i < AHA_MBX_SIZE; i++) { 986 wmbx->mbo[i].cmd = AHA_MBO_FREE; 987 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 988 AHA_MBO_OFF(&wmbx->mbo[i]), sizeof(struct aha_mbx_out), 989 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 990 wmbx->mbi[i].stat = AHA_MBI_FREE; 991 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 992 AHA_MBI_OFF(&wmbx->mbi[i]), sizeof(struct aha_mbx_in), 993 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 994 } 995 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0]; 996 wmbx->tmbi = &wmbx->mbi[0]; 997 sc->sc_mbofull = 0; 998 999 /* Initialize mail box. */ 1000 mailbox.cmd.opcode = AHA_MBX_INIT; 1001 mailbox.cmd.nmbx = AHA_MBX_SIZE; 1002 ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 1003 offsetof(struct aha_control, ac_mbx), mailbox.cmd.addr); 1004 aha_cmd(iot, ioh, sc, 1005 sizeof(mailbox.cmd), (u_char *)&mailbox.cmd, 1006 0, (u_char *)0); 1007 return (0); 1008 } 1009 1010 static void 1011 aha_inquire_setup_information(struct aha_softc *sc) 1012 { 1013 bus_space_tag_t iot = sc->sc_iot; 1014 bus_space_handle_t ioh = sc->sc_ioh; 1015 struct aha_revision revision; 1016 u_char sts; 1017 int i; 1018 char *p; 1019 1020 strcpy(sc->sc_model, "unknown"); 1021 1022 /* 1023 * Assume we have a board at this stage, do an adapter inquire 1024 * to find out what type of controller it is. If the command 1025 * fails, we assume it's either a crusty board or an old 1542 1026 * clone, and skip the board-specific stuff. 1027 */ 1028 revision.cmd.opcode = AHA_INQUIRE_REVISION; 1029 if (aha_cmd(iot, ioh, sc, 1030 sizeof(revision.cmd), (u_char *)&revision.cmd, 1031 sizeof(revision.reply), (u_char *)&revision.reply)) { 1032 /* 1033 * aha_cmd() already started the reset. It's not clear we 1034 * even need to bother here. 1035 */ 1036 for (i = AHA_RESET_TIMEOUT; i; i--) { 1037 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 1038 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 1039 break; 1040 delay(1000); 1041 } 1042 if (!i) { 1043 #ifdef AHADEBUG 1044 printf("aha_init: soft reset failed\n"); 1045 #endif /* AHADEBUG */ 1046 return; 1047 } 1048 #ifdef AHADEBUG 1049 printf("aha_init: inquire command failed\n"); 1050 #endif /* AHADEBUG */ 1051 goto noinquire; 1052 } 1053 1054 #ifdef AHADEBUG 1055 printf("%s: inquire %x, %x, %x, %x\n", 1056 device_xname(&sc->sc_dev), 1057 revision.reply.boardid, revision.reply.spec_opts, 1058 revision.reply.revision_1, revision.reply.revision_2); 1059 #endif /* AHADEBUG */ 1060 1061 switch (revision.reply.boardid) { 1062 case BOARD_1540_16HEAD_BIOS: 1063 case BOARD_1540_64HEAD_BIOS: 1064 case BOARD_1540: 1065 strcpy(sc->sc_model, "1540"); 1066 break; 1067 case BOARD_1542: 1068 strcpy(sc->sc_model, "1540A/1542A/1542B"); 1069 break; 1070 case BOARD_1640: 1071 strcpy(sc->sc_model, "1640"); 1072 break; 1073 case BOARD_1740: 1074 strcpy(sc->sc_model, "1740"); 1075 break; 1076 case BOARD_1542C: 1077 strcpy(sc->sc_model, "1542C"); 1078 break; 1079 case BOARD_1542CF: 1080 strcpy(sc->sc_model, "1542CF"); 1081 break; 1082 case BOARD_1542CP: 1083 strcpy(sc->sc_model, "1542CP"); 1084 break; 1085 } 1086 1087 p = sc->sc_firmware; 1088 *p++ = revision.reply.revision_1; 1089 *p++ = '.'; 1090 *p++ = revision.reply.revision_2; 1091 *p = '\0'; 1092 1093 noinquire: 1094 printf("%s: model AHA-%s, firmware %s\n", 1095 device_xname(&sc->sc_dev), 1096 sc->sc_model, sc->sc_firmware); 1097 } 1098 1099 static void 1100 ahaminphys(struct buf *bp) 1101 { 1102 1103 if (bp->b_bcount > AHA_MAXXFER) 1104 bp->b_bcount = AHA_MAXXFER; 1105 minphys(bp); 1106 } 1107 1108 /* 1109 * start a scsi operation given the command and the data address. Also needs 1110 * the unit, target and lu. 1111 */ 1112 1113 static void 1114 aha_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 1115 void *arg) 1116 { 1117 struct scsipi_xfer *xs; 1118 struct scsipi_periph *periph; 1119 struct aha_softc *sc = (void *)chan->chan_adapter->adapt_dev; 1120 bus_dma_tag_t dmat = sc->sc_dmat; 1121 struct aha_ccb *ccb; 1122 int error, seg, flags, s; 1123 1124 1125 switch (req) { 1126 case ADAPTER_REQ_RUN_XFER: 1127 xs = arg; 1128 periph = xs->xs_periph; 1129 flags = xs->xs_control; 1130 1131 SC_DEBUG(periph, SCSIPI_DB2, ("aha_scsipi_request\n")); 1132 1133 /* Get a CCB to use. */ 1134 ccb = aha_get_ccb(sc); 1135 #ifdef DIAGNOSTIC 1136 /* 1137 * This should never happen as we track the resources 1138 * in the mid-layer. 1139 */ 1140 if (ccb == NULL) { 1141 scsipi_printaddr(periph); 1142 printf("unable to allocate ccb\n"); 1143 panic("aha_scsipi_request"); 1144 } 1145 #endif 1146 1147 ccb->xs = xs; 1148 ccb->timeout = xs->timeout; 1149 1150 /* 1151 * Put all the arguments for the xfer in the ccb 1152 */ 1153 if (flags & XS_CTL_RESET) { 1154 ccb->opcode = AHA_RESET_CCB; 1155 ccb->scsi_cmd_length = 0; 1156 } else { 1157 /* can't use S/G if zero length */ 1158 if (xs->cmdlen > sizeof(ccb->scsi_cmd)) { 1159 printf("%s: cmdlen %d too large for CCB\n", 1160 device_xname(&sc->sc_dev), xs->cmdlen); 1161 xs->error = XS_DRIVER_STUFFUP; 1162 goto out_bad; 1163 } 1164 ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB 1165 : AHA_INITIATOR_CCB); 1166 memcpy(&ccb->scsi_cmd, xs->cmd, 1167 ccb->scsi_cmd_length = xs->cmdlen); 1168 } 1169 1170 if (xs->datalen) { 1171 /* 1172 * Map the DMA transfer. 1173 */ 1174 #ifdef TFS 1175 if (flags & XS_CTL_DATA_UIO) { 1176 error = bus_dmamap_load_uio(dmat, 1177 ccb->dmamap_xfer, (struct uio *)xs->data, 1178 ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : 1179 BUS_DMA_WAITOK) | BUS_DMA_STREAMING | 1180 ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ : 1181 BUS_DMA_WRITE)); 1182 } else 1183 #endif 1184 { 1185 error = bus_dmamap_load(dmat, 1186 ccb->dmamap_xfer, xs->data, xs->datalen, 1187 NULL, 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 } 1193 1194 switch (error) { 1195 case 0: 1196 break; 1197 1198 case ENOMEM: 1199 case EAGAIN: 1200 xs->error = XS_RESOURCE_SHORTAGE; 1201 goto out_bad; 1202 1203 default: 1204 xs->error = XS_DRIVER_STUFFUP; 1205 if (error == EFBIG) { 1206 printf("%s: aha_scsi_cmd, more than %d" 1207 " DMA segments\n", 1208 device_xname(&sc->sc_dev), AHA_NSEG); 1209 } else { 1210 aprint_error_dev(&sc->sc_dev, "error %d loading DMA map\n", 1211 error); 1212 } 1213 out_bad: 1214 aha_free_ccb(sc, ccb); 1215 scsipi_done(xs); 1216 return; 1217 } 1218 1219 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0, 1220 ccb->dmamap_xfer->dm_mapsize, 1221 (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : 1222 BUS_DMASYNC_PREWRITE); 1223 1224 /* 1225 * Load the hardware scatter/gather map with the 1226 * contents of the DMA map. 1227 */ 1228 for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) { 1229 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr, 1230 ccb->scat_gath[seg].seg_addr); 1231 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len, 1232 ccb->scat_gath[seg].seg_len); 1233 } 1234 1235 ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 1236 AHA_CCB_OFF(ccb) + 1237 offsetof(struct aha_ccb, scat_gath), 1238 ccb->data_addr); 1239 ltophys(ccb->dmamap_xfer->dm_nsegs * 1240 sizeof(struct aha_scat_gath), ccb->data_length); 1241 } else { 1242 /* 1243 * No data xfer, use non S/G values. 1244 */ 1245 ltophys(0, ccb->data_addr); 1246 ltophys(0, ccb->data_length); 1247 } 1248 1249 ccb->data_out = 0; 1250 ccb->data_in = 0; 1251 ccb->target = periph->periph_target; 1252 ccb->lun = periph->periph_lun; 1253 ccb->req_sense_length = sizeof(ccb->scsi_sense); 1254 ccb->host_stat = 0x00; 1255 ccb->target_stat = 0x00; 1256 ccb->link_id = 0; 1257 ltophys(0, ccb->link_addr); 1258 1259 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 1260 AHA_CCB_OFF(ccb), sizeof(struct aha_ccb), 1261 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1262 1263 s = splbio(); 1264 aha_queue_ccb(sc, ccb); 1265 splx(s); 1266 1267 SC_DEBUG(periph, SCSIPI_DB3, ("cmd_sent\n")); 1268 if ((flags & XS_CTL_POLL) == 0) 1269 return; 1270 1271 /* Not allowed to use interrupts, poll for completion. */ 1272 if (aha_poll(sc, xs, ccb->timeout)) { 1273 aha_timeout(ccb); 1274 if (aha_poll(sc, xs, ccb->timeout)) 1275 aha_timeout(ccb); 1276 } 1277 return; 1278 1279 case ADAPTER_REQ_GROW_RESOURCES: 1280 /* XXX Not supported. */ 1281 return; 1282 1283 case ADAPTER_REQ_SET_XFER_MODE: 1284 /* 1285 * Can't really do this on the Adaptec; it has 1286 * its own config mechanism, but we do know how 1287 * to query what the firmware negotiated. 1288 */ 1289 /* XXX XXX XXX */ 1290 return; 1291 } 1292 } 1293 1294 /* 1295 * Poll a particular unit, looking for a particular xs 1296 */ 1297 static int 1298 aha_poll(struct aha_softc *sc, struct scsipi_xfer *xs, int count) 1299 { 1300 bus_space_tag_t iot = sc->sc_iot; 1301 bus_space_handle_t ioh = sc->sc_ioh; 1302 1303 /* timeouts are in msec, so we loop in 1000 usec cycles */ 1304 while (count) { 1305 /* 1306 * If we had interrupts enabled, would we 1307 * have got an interrupt? 1308 */ 1309 if (bus_space_read_1(iot, ioh, AHA_INTR_PORT) & AHA_INTR_ANYINTR) 1310 aha_intr(sc); 1311 if (xs->xs_status & XS_STS_DONE) 1312 return (0); 1313 delay(1000); /* only happens in boot so ok */ 1314 count--; 1315 } 1316 return (1); 1317 } 1318 1319 static void 1320 aha_timeout(void *arg) 1321 { 1322 struct aha_ccb *ccb = arg; 1323 struct scsipi_xfer *xs = ccb->xs; 1324 struct scsipi_periph *periph = xs->xs_periph; 1325 struct aha_softc *sc = 1326 (void *)periph->periph_channel->chan_adapter->adapt_dev; 1327 int s; 1328 1329 scsipi_printaddr(periph); 1330 printf("timed out"); 1331 1332 s = splbio(); 1333 1334 #ifdef AHADIAG 1335 /* 1336 * If The ccb's mbx is not free, then the board has gone south? 1337 */ 1338 aha_collect_mbo(sc); 1339 if (ccb->flags & CCB_SENDING) { 1340 aprint_error_dev(&sc->sc_dev, "not taking commands!\n"); 1341 Debugger(); 1342 } 1343 #endif 1344 1345 /* 1346 * If it has been through before, then 1347 * a previous abort has failed, don't 1348 * try abort again 1349 */ 1350 if (ccb->flags & CCB_ABORT) { 1351 /* abort timed out */ 1352 printf(" AGAIN\n"); 1353 /* XXX Must reset! */ 1354 } else { 1355 /* abort the operation that has timed out */ 1356 printf("\n"); 1357 ccb->xs->error = XS_TIMEOUT; 1358 ccb->timeout = AHA_ABORT_TIMEOUT; 1359 ccb->flags |= CCB_ABORT; 1360 aha_queue_ccb(sc, ccb); 1361 } 1362 1363 splx(s); 1364 } 1365