1 /* $NetBSD: uha.c,v 1.23 2000/02/12 19:12:54 thorpej Exp $ */ 2 3 #undef UHADEBUG 4 #ifdef DDB 5 #define integrate 6 #else 7 #define integrate static inline 8 #endif 9 10 /*- 11 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 12 * All rights reserved. 13 * 14 * This code is derived from software contributed to The NetBSD Foundation 15 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 16 * Simulation Facility, NASA Ames Research Center. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 3. All advertising materials mentioning features or use of this software 27 * must display the following acknowledgement: 28 * This product includes software developed by the NetBSD 29 * Foundation, Inc. and its contributors. 30 * 4. Neither the name of The NetBSD Foundation nor the names of its 31 * contributors may be used to endorse or promote products derived 32 * from this software without specific prior written permission. 33 * 34 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 35 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 37 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 44 * POSSIBILITY OF SUCH DAMAGE. 45 */ 46 47 /* 48 * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu) 49 * Slight fixes to timeouts to run with the 34F 50 * Thanks to Julian Elischer for advice and help with this port. 51 * 52 * Originally written by Julian Elischer (julian@tfs.com) 53 * for TRW Financial Systems for use under the MACH(2.5) operating system. 54 * 55 * TRW Financial Systems, in accordance with their agreement with Carnegie 56 * Mellon University, makes this software available to CMU to distribute 57 * or use in any manner that they see fit as long as this message is kept with 58 * the software. For this reason TFS also grants any other persons or 59 * organisations permission to use or modify this software. 60 * 61 * TFS supplies this software to be publicly redistributed 62 * on the understanding that TFS is not responsible for the correct 63 * functioning of this software in any circumstances. 64 * 65 * commenced: Sun Sep 27 18:14:01 PDT 1992 66 * slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993 67 */ 68 69 #include <sys/types.h> 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/kernel.h> 73 #include <sys/errno.h> 74 #include <sys/ioctl.h> 75 #include <sys/device.h> 76 #include <sys/malloc.h> 77 #include <sys/buf.h> 78 #include <sys/proc.h> 79 #include <sys/user.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/uhareg.h> 89 #include <dev/ic/uhavar.h> 90 91 #ifndef DDB 92 #define Debugger() panic("should call debugger here (uha.c)") 93 #endif /* ! DDB */ 94 95 #define UHA_MAXXFER ((UHA_NSEG - 1) << PGSHIFT) 96 97 integrate void uha_reset_mscp __P((struct uha_softc *, struct uha_mscp *)); 98 void uha_free_mscp __P((struct uha_softc *, struct uha_mscp *)); 99 integrate int uha_init_mscp __P((struct uha_softc *, struct uha_mscp *)); 100 struct uha_mscp *uha_get_mscp __P((struct uha_softc *, int)); 101 void uhaminphys __P((struct buf *)); 102 int uha_scsi_cmd __P((struct scsipi_xfer *)); 103 int uha_create_mscps __P((struct uha_softc *, struct uha_mscp *, int)); 104 105 /* the below structure is so we have a default dev struct for out link struct */ 106 struct scsipi_device uha_dev = { 107 NULL, /* Use default error handler */ 108 NULL, /* have a queue, served by this */ 109 NULL, /* have no async handler */ 110 NULL, /* Use default 'done' routine */ 111 }; 112 113 #define UHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */ 114 115 /* 116 * Attach all the sub-devices we can find 117 */ 118 void 119 uha_attach(sc, upd) 120 struct uha_softc *sc; 121 struct uha_probe_data *upd; 122 { 123 bus_dma_segment_t seg; 124 int i, error, rseg; 125 126 TAILQ_INIT(&sc->sc_free_mscp); 127 TAILQ_INIT(&sc->sc_queue); 128 129 (sc->init)(sc); 130 131 /* 132 * Fill in the adapter. 133 */ 134 sc->sc_adapter.scsipi_cmd = uha_scsi_cmd; 135 sc->sc_adapter.scsipi_minphys = uhaminphys; 136 137 /* 138 * fill in the prototype scsipi_link. 139 */ 140 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE; 141 sc->sc_link.adapter_softc = sc; 142 sc->sc_link.scsipi_scsi.adapter_target = upd->sc_scsi_dev; 143 sc->sc_link.adapter = &sc->sc_adapter; 144 sc->sc_link.device = &uha_dev; 145 sc->sc_link.openings = 2; 146 sc->sc_link.scsipi_scsi.max_target = 7; 147 sc->sc_link.scsipi_scsi.max_lun = 7; 148 sc->sc_link.type = BUS_SCSI; 149 150 #define MSCPSIZE (UHA_MSCP_MAX * sizeof(struct uha_mscp)) 151 152 /* 153 * Allocate the MSCPs. 154 */ 155 if ((error = bus_dmamem_alloc(sc->sc_dmat, MSCPSIZE, 156 NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 157 printf("%s: unable to allocate mscps, error = %d\n", 158 sc->sc_dev.dv_xname, error); 159 return; 160 } 161 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 162 MSCPSIZE, (caddr_t *)&sc->sc_mscps, 163 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { 164 printf("%s: unable to map mscps, error = %d\n", 165 sc->sc_dev.dv_xname, error); 166 return; 167 } 168 169 /* 170 * Create and load the DMA map used for the mscps. 171 */ 172 if ((error = bus_dmamap_create(sc->sc_dmat, MSCPSIZE, 173 1, MSCPSIZE, 0, BUS_DMA_NOWAIT | sc->sc_dmaflags, 174 &sc->sc_dmamap_mscp)) != 0) { 175 printf("%s: unable to create mscp DMA map, error = %d\n", 176 sc->sc_dev.dv_xname, error); 177 return; 178 } 179 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mscp, 180 sc->sc_mscps, MSCPSIZE, NULL, BUS_DMA_NOWAIT)) != 0) { 181 printf("%s: unable to load mscp DMA map, error = %d\n", 182 sc->sc_dev.dv_xname, error); 183 return; 184 } 185 186 #undef MSCPSIZE 187 188 /* 189 * Initialize the mscps. 190 */ 191 i = uha_create_mscps(sc, sc->sc_mscps, UHA_MSCP_MAX); 192 if (i == 0) { 193 printf("%s: unable to create mscps\n", 194 sc->sc_dev.dv_xname); 195 return; 196 } else if (i != UHA_MSCP_MAX) { 197 printf("%s: WARNING: only %d of %d mscps created\n", 198 sc->sc_dev.dv_xname, i, UHA_MSCP_MAX); 199 } 200 201 /* 202 * ask the adapter what subunits are present 203 */ 204 config_found(&sc->sc_dev, &sc->sc_link, scsiprint); 205 } 206 207 integrate void 208 uha_reset_mscp(sc, mscp) 209 struct uha_softc *sc; 210 struct uha_mscp *mscp; 211 { 212 213 mscp->flags = 0; 214 } 215 216 /* 217 * A mscp (and hence a mbx-out) is put onto the free list. 218 */ 219 void 220 uha_free_mscp(sc, mscp) 221 struct uha_softc *sc; 222 struct uha_mscp *mscp; 223 { 224 int s; 225 226 s = splbio(); 227 228 uha_reset_mscp(sc, mscp); 229 TAILQ_INSERT_HEAD(&sc->sc_free_mscp, mscp, chain); 230 231 /* 232 * If there were none, wake anybody waiting for one to come free, 233 * starting with queued entries. 234 */ 235 if (mscp->chain.tqe_next == 0) 236 wakeup(&sc->sc_free_mscp); 237 238 splx(s); 239 } 240 241 integrate int 242 uha_init_mscp(sc, mscp) 243 struct uha_softc *sc; 244 struct uha_mscp *mscp; 245 { 246 bus_dma_tag_t dmat = sc->sc_dmat; 247 int hashnum, error; 248 249 /* 250 * Create the DMA map for this MSCP. 251 */ 252 error = bus_dmamap_create(dmat, UHA_MAXXFER, UHA_NSEG, UHA_MAXXFER, 253 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW | sc->sc_dmaflags, 254 &mscp->dmamap_xfer); 255 if (error) { 256 printf("%s: can't create mscp DMA map, error = %d\n", 257 sc->sc_dev.dv_xname, error); 258 return (error); 259 } 260 261 /* 262 * put in the phystokv hash table 263 * Never gets taken out. 264 */ 265 mscp->hashkey = sc->sc_dmamap_mscp->dm_segs[0].ds_addr + 266 UHA_MSCP_OFF(mscp); 267 hashnum = MSCP_HASH(mscp->hashkey); 268 mscp->nexthash = sc->sc_mscphash[hashnum]; 269 sc->sc_mscphash[hashnum] = mscp; 270 uha_reset_mscp(sc, mscp); 271 return (0); 272 } 273 274 /* 275 * Create a set of MSCPs and add them to the free list. 276 */ 277 int 278 uha_create_mscps(sc, mscpstore, count) 279 struct uha_softc *sc; 280 struct uha_mscp *mscpstore; 281 int count; 282 { 283 struct uha_mscp *mscp; 284 int i, error; 285 286 bzero(mscpstore, sizeof(struct uha_mscp) * count); 287 for (i = 0; i < count; i++) { 288 mscp = &mscpstore[i]; 289 if ((error = uha_init_mscp(sc, mscp)) != 0) { 290 printf("%s: unable to initialize mscp, error = %d\n", 291 sc->sc_dev.dv_xname, error); 292 goto out; 293 } 294 TAILQ_INSERT_TAIL(&sc->sc_free_mscp, mscp, chain); 295 } 296 out: 297 return (i); 298 } 299 300 /* 301 * Get a free mscp 302 * 303 * If there are none, see if we can allocate a new one. If so, put it in the 304 * hash table too otherwise either return an error or sleep. 305 */ 306 struct uha_mscp * 307 uha_get_mscp(sc, flags) 308 struct uha_softc *sc; 309 int flags; 310 { 311 struct uha_mscp *mscp; 312 int s; 313 314 s = splbio(); 315 316 /* 317 * If we can and have to, sleep waiting for one to come free 318 * but only if we can't allocate a new one 319 */ 320 for (;;) { 321 mscp = sc->sc_free_mscp.tqh_first; 322 if (mscp) { 323 TAILQ_REMOVE(&sc->sc_free_mscp, mscp, chain); 324 break; 325 } 326 if ((flags & XS_CTL_NOSLEEP) != 0) 327 goto out; 328 tsleep(&sc->sc_free_mscp, PRIBIO, "uhamsc", 0); 329 } 330 331 mscp->flags |= MSCP_ALLOC; 332 333 out: 334 splx(s); 335 return (mscp); 336 } 337 338 /* 339 * given a physical address, find the mscp that it corresponds to. 340 */ 341 struct uha_mscp * 342 uha_mscp_phys_kv(sc, mscp_phys) 343 struct uha_softc *sc; 344 u_long mscp_phys; 345 { 346 int hashnum = MSCP_HASH(mscp_phys); 347 struct uha_mscp *mscp = sc->sc_mscphash[hashnum]; 348 349 while (mscp) { 350 if (mscp->hashkey == mscp_phys) 351 break; 352 mscp = mscp->nexthash; 353 } 354 return (mscp); 355 } 356 357 /* 358 * We have a mscp which has been processed by the adaptor, now we look to see 359 * how the operation went. 360 */ 361 void 362 uha_done(sc, mscp) 363 struct uha_softc *sc; 364 struct uha_mscp *mscp; 365 { 366 bus_dma_tag_t dmat = sc->sc_dmat; 367 struct scsipi_sense_data *s1, *s2; 368 struct scsipi_xfer *xs = mscp->xs; 369 370 SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n")); 371 372 bus_dmamap_sync(dmat, sc->sc_dmamap_mscp, 373 UHA_MSCP_OFF(mscp), sizeof(struct uha_mscp), 374 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 375 376 /* 377 * If we were a data transfer, unload the map that described 378 * the data buffer. 379 */ 380 if (xs->datalen) { 381 bus_dmamap_sync(dmat, mscp->dmamap_xfer, 0, 382 mscp->dmamap_xfer->dm_mapsize, 383 (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD : 384 BUS_DMASYNC_POSTWRITE); 385 bus_dmamap_unload(dmat, mscp->dmamap_xfer); 386 } 387 388 /* 389 * Otherwise, put the results of the operation 390 * into the xfer and call whoever started it 391 */ 392 if ((mscp->flags & MSCP_ALLOC) == 0) { 393 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname); 394 Debugger(); 395 return; 396 } 397 if (xs->error == XS_NOERROR) { 398 if (mscp->host_stat != UHA_NO_ERR) { 399 switch (mscp->host_stat) { 400 case UHA_SBUS_TIMEOUT: /* No response */ 401 xs->error = XS_SELTIMEOUT; 402 break; 403 default: /* Other scsi protocol messes */ 404 printf("%s: host_stat %x\n", 405 sc->sc_dev.dv_xname, mscp->host_stat); 406 xs->error = XS_DRIVER_STUFFUP; 407 } 408 } else if (mscp->target_stat != SCSI_OK) { 409 switch (mscp->target_stat) { 410 case SCSI_CHECK: 411 s1 = &mscp->mscp_sense; 412 s2 = &xs->sense.scsi_sense; 413 *s2 = *s1; 414 xs->error = XS_SENSE; 415 break; 416 case SCSI_BUSY: 417 xs->error = XS_BUSY; 418 break; 419 default: 420 printf("%s: target_stat %x\n", 421 sc->sc_dev.dv_xname, mscp->target_stat); 422 xs->error = XS_DRIVER_STUFFUP; 423 } 424 } else 425 xs->resid = 0; 426 } 427 uha_free_mscp(sc, mscp); 428 xs->xs_status |= XS_STS_DONE; 429 scsipi_done(xs); 430 431 /* 432 * If there are queue entries in the software queue, try to 433 * run the first one. We should be more or less guaranteed 434 * to succeed, since we just freed an MSCP. 435 * 436 * NOTE: uha_scsi_cmd() relies on our calling it with 437 * the first entry in the queue. 438 */ 439 if ((xs = TAILQ_FIRST(&sc->sc_queue)) != NULL) 440 (void) uha_scsi_cmd(xs); 441 } 442 443 void 444 uhaminphys(bp) 445 struct buf *bp; 446 { 447 448 if (bp->b_bcount > UHA_MAXXFER) 449 bp->b_bcount = UHA_MAXXFER; 450 minphys(bp); 451 } 452 453 /* 454 * start a scsi operation given the command and the data address. Also 455 * needs the unit, target and lu. 456 */ 457 int 458 uha_scsi_cmd(xs) 459 struct scsipi_xfer *xs; 460 { 461 struct scsipi_link *sc_link = xs->sc_link; 462 struct uha_softc *sc = sc_link->adapter_softc; 463 bus_dma_tag_t dmat = sc->sc_dmat; 464 struct uha_mscp *mscp; 465 struct uha_dma_seg *sg; 466 int error, seg, flags, s; 467 int fromqueue = 0, dontqueue = 0, nowait = 0; 468 469 SC_DEBUG(sc_link, SDEV_DB2, ("uha_scsi_cmd\n")); 470 471 s = splbio(); /* protect the queue */ 472 473 /* 474 * If we're running the queue from bha_done(), we've been 475 * called with the first queue entry as our argument. 476 */ 477 if (xs == TAILQ_FIRST(&sc->sc_queue)) { 478 TAILQ_REMOVE(&sc->sc_queue, xs, adapter_q); 479 fromqueue = 1; 480 nowait = 1; 481 goto get_mscp; 482 } 483 484 /* Polled requests can't be queued for later. */ 485 dontqueue = xs->xs_control & XS_CTL_POLL; 486 487 /* 488 * If there are jobs in the queue, run them first. 489 */ 490 if (TAILQ_FIRST(&sc->sc_queue) != NULL) { 491 /* 492 * If we can't queue, we have to abort, since 493 * we have to preserve order. 494 */ 495 if (dontqueue) { 496 splx(s); 497 xs->error = XS_DRIVER_STUFFUP; 498 return (TRY_AGAIN_LATER); 499 } 500 501 /* 502 * Swap with the first queue entry. 503 */ 504 TAILQ_INSERT_TAIL(&sc->sc_queue, xs, adapter_q); 505 xs = TAILQ_FIRST(&sc->sc_queue); 506 TAILQ_REMOVE(&sc->sc_queue, xs, adapter_q); 507 fromqueue = 1; 508 } 509 510 get_mscp: 511 /* 512 * get a mscp (mbox-out) to use. If the transfer 513 * is from a buf (possibly from interrupt time) 514 * then we can't allow it to sleep 515 */ 516 flags = xs->xs_control; 517 if (nowait) 518 flags |= XS_CTL_NOSLEEP; 519 if ((mscp = uha_get_mscp(sc, flags)) == NULL) { 520 /* 521 * If we can't queue, we lose. 522 */ 523 if (dontqueue) { 524 splx(s); 525 xs->error = XS_DRIVER_STUFFUP; 526 return (TRY_AGAIN_LATER); 527 } 528 529 /* 530 * Stuff ourselves into the queue, in front 531 * if we came off in the first place. 532 */ 533 if (fromqueue) 534 TAILQ_INSERT_HEAD(&sc->sc_queue, xs, adapter_q); 535 else 536 TAILQ_INSERT_TAIL(&sc->sc_queue, xs, adapter_q); 537 splx(s); 538 return (SUCCESSFULLY_QUEUED); 539 } 540 541 splx(s); /* done playing with the queue */ 542 543 mscp->xs = xs; 544 mscp->timeout = xs->timeout; 545 546 /* 547 * Put all the arguments for the xfer in the mscp 548 */ 549 if (flags & XS_CTL_RESET) { 550 mscp->opcode = UHA_SDR; 551 mscp->ca = 0x01; 552 } else { 553 mscp->opcode = UHA_TSP; 554 /* XXX Not for tapes. */ 555 mscp->ca = 0x01; 556 bcopy(xs->cmd, &mscp->scsi_cmd, mscp->scsi_cmd_length); 557 } 558 mscp->xdir = UHA_SDET; 559 mscp->dcn = 0x00; 560 mscp->chan = 0x00; 561 mscp->target = sc_link->scsipi_scsi.target; 562 mscp->lun = sc_link->scsipi_scsi.lun; 563 mscp->scsi_cmd_length = xs->cmdlen; 564 mscp->sense_ptr = sc->sc_dmamap_mscp->dm_segs[0].ds_addr + 565 UHA_MSCP_OFF(mscp) + offsetof(struct uha_mscp, mscp_sense); 566 mscp->req_sense_length = sizeof(mscp->mscp_sense); 567 mscp->host_stat = 0x00; 568 mscp->target_stat = 0x00; 569 570 if (xs->datalen) { 571 sg = mscp->uha_dma; 572 seg = 0; 573 #ifdef TFS 574 if (flags & SCSI_DATA_UIO) { 575 error = bus_dmamap_load_uio(dmat, 576 mscp->dmamap_xfer, (struct uio *)xs->data, 577 (flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : 578 BUS_DMA_WAITOK); 579 } else 580 #endif /*TFS */ 581 { 582 error = bus_dmamap_load(dmat, 583 mscp->dmamap_xfer, xs->data, xs->datalen, NULL, 584 (flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : 585 BUS_DMA_WAITOK); 586 } 587 588 if (error) { 589 if (error == EFBIG) { 590 printf("%s: uha_scsi_cmd, more than %d" 591 " dma segments\n", 592 sc->sc_dev.dv_xname, UHA_NSEG); 593 } else { 594 printf("%s: uha_scsi_cmd, error %d loading" 595 " dma map\n", 596 sc->sc_dev.dv_xname, error); 597 } 598 goto bad; 599 } 600 601 bus_dmamap_sync(dmat, mscp->dmamap_xfer, 0, 602 mscp->dmamap_xfer->dm_mapsize, 603 (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : 604 BUS_DMASYNC_PREWRITE); 605 606 /* 607 * Load the hardware scatter/gather map with the 608 * contents of the DMA map. 609 */ 610 for (seg = 0; seg < mscp->dmamap_xfer->dm_nsegs; seg++) { 611 mscp->uha_dma[seg].seg_addr = 612 mscp->dmamap_xfer->dm_segs[seg].ds_addr; 613 mscp->uha_dma[seg].seg_len = 614 mscp->dmamap_xfer->dm_segs[seg].ds_len; 615 } 616 617 mscp->data_addr = sc->sc_dmamap_mscp->dm_segs[0].ds_addr + 618 UHA_MSCP_OFF(mscp) + offsetof(struct uha_mscp, uha_dma); 619 mscp->data_length = xs->datalen; 620 mscp->sgth = 0x01; 621 mscp->sg_num = seg; 622 } else { /* No data xfer, use non S/G values */ 623 mscp->data_addr = (physaddr)0; 624 mscp->data_length = 0; 625 mscp->sgth = 0x00; 626 mscp->sg_num = 0; 627 } 628 mscp->link_id = 0; 629 mscp->link_addr = (physaddr)0; 630 631 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_mscp, 632 UHA_MSCP_OFF(mscp), sizeof(struct uha_mscp), 633 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 634 635 s = splbio(); 636 (sc->start_mbox)(sc, mscp); 637 splx(s); 638 639 /* 640 * Usually return SUCCESSFULLY QUEUED 641 */ 642 if ((flags & XS_CTL_POLL) == 0) 643 return (SUCCESSFULLY_QUEUED); 644 645 /* 646 * If we can't use interrupts, poll on completion 647 */ 648 if ((sc->poll)(sc, xs, mscp->timeout)) { 649 uha_timeout(mscp); 650 if ((sc->poll)(sc, xs, mscp->timeout)) 651 uha_timeout(mscp); 652 } 653 return (COMPLETE); 654 655 bad: 656 xs->error = XS_DRIVER_STUFFUP; 657 uha_free_mscp(sc, mscp); 658 return (COMPLETE); 659 } 660 661 void 662 uha_timeout(arg) 663 void *arg; 664 { 665 struct uha_mscp *mscp = arg; 666 struct scsipi_xfer *xs = mscp->xs; 667 struct scsipi_link *sc_link = xs->sc_link; 668 struct uha_softc *sc = sc_link->adapter_softc; 669 int s; 670 671 scsi_print_addr(sc_link); 672 printf("timed out"); 673 674 s = splbio(); 675 676 if (mscp->flags & MSCP_ABORT) { 677 /* abort timed out */ 678 printf(" AGAIN\n"); 679 /* XXX Must reset! */ 680 } else { 681 /* abort the operation that has timed out */ 682 printf("\n"); 683 mscp->xs->error = XS_TIMEOUT; 684 mscp->timeout = UHA_ABORT_TIMEOUT; 685 mscp->flags |= MSCP_ABORT; 686 (sc->start_mbox)(sc, mscp); 687 } 688 689 splx(s); 690 } 691