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