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