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