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