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