uha.c revision 1.24 1 /* $NetBSD: uha.c,v 1.24 2000/11/14 18:21:02 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 (at) 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 (at) 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 <uvm/uvm_extern.h>
82
83 #include <machine/bus.h>
84 #include <machine/intr.h>
85
86 #include <dev/scsipi/scsi_all.h>
87 #include <dev/scsipi/scsipi_all.h>
88 #include <dev/scsipi/scsiconf.h>
89
90 #include <dev/ic/uhareg.h>
91 #include <dev/ic/uhavar.h>
92
93 #ifndef DDB
94 #define Debugger() panic("should call debugger here (uha.c)")
95 #endif /* ! DDB */
96
97 #define UHA_MAXXFER ((UHA_NSEG - 1) << PGSHIFT)
98
99 integrate void uha_reset_mscp __P((struct uha_softc *, struct uha_mscp *));
100 void uha_free_mscp __P((struct uha_softc *, struct uha_mscp *));
101 integrate int uha_init_mscp __P((struct uha_softc *, struct uha_mscp *));
102 struct uha_mscp *uha_get_mscp __P((struct uha_softc *, int));
103 void uhaminphys __P((struct buf *));
104 int uha_scsi_cmd __P((struct scsipi_xfer *));
105 int uha_create_mscps __P((struct uha_softc *, struct uha_mscp *, int));
106
107 /* the below structure is so we have a default dev struct for out link struct */
108 struct scsipi_device uha_dev = {
109 NULL, /* Use default error handler */
110 NULL, /* have a queue, served by this */
111 NULL, /* have no async handler */
112 NULL, /* Use default 'done' routine */
113 };
114
115 #define UHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
116
117 /*
118 * Attach all the sub-devices we can find
119 */
120 void
121 uha_attach(sc, upd)
122 struct uha_softc *sc;
123 struct uha_probe_data *upd;
124 {
125 bus_dma_segment_t seg;
126 int i, error, rseg;
127
128 TAILQ_INIT(&sc->sc_free_mscp);
129 TAILQ_INIT(&sc->sc_queue);
130
131 (sc->init)(sc);
132
133 /*
134 * Fill in the adapter.
135 */
136 sc->sc_adapter.scsipi_cmd = uha_scsi_cmd;
137 sc->sc_adapter.scsipi_minphys = uhaminphys;
138
139 /*
140 * fill in the prototype scsipi_link.
141 */
142 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
143 sc->sc_link.adapter_softc = sc;
144 sc->sc_link.scsipi_scsi.adapter_target = upd->sc_scsi_dev;
145 sc->sc_link.adapter = &sc->sc_adapter;
146 sc->sc_link.device = &uha_dev;
147 sc->sc_link.openings = 2;
148 sc->sc_link.scsipi_scsi.max_target = 7;
149 sc->sc_link.scsipi_scsi.max_lun = 7;
150 sc->sc_link.type = BUS_SCSI;
151
152 #define MSCPSIZE (UHA_MSCP_MAX * sizeof(struct uha_mscp))
153
154 /*
155 * Allocate the MSCPs.
156 */
157 if ((error = bus_dmamem_alloc(sc->sc_dmat, MSCPSIZE,
158 PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
159 printf("%s: unable to allocate mscps, error = %d\n",
160 sc->sc_dev.dv_xname, error);
161 return;
162 }
163 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
164 MSCPSIZE, (caddr_t *)&sc->sc_mscps,
165 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
166 printf("%s: unable to map mscps, error = %d\n",
167 sc->sc_dev.dv_xname, error);
168 return;
169 }
170
171 /*
172 * Create and load the DMA map used for the mscps.
173 */
174 if ((error = bus_dmamap_create(sc->sc_dmat, MSCPSIZE,
175 1, MSCPSIZE, 0, BUS_DMA_NOWAIT | sc->sc_dmaflags,
176 &sc->sc_dmamap_mscp)) != 0) {
177 printf("%s: unable to create mscp DMA map, error = %d\n",
178 sc->sc_dev.dv_xname, error);
179 return;
180 }
181 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mscp,
182 sc->sc_mscps, MSCPSIZE, NULL, BUS_DMA_NOWAIT)) != 0) {
183 printf("%s: unable to load mscp DMA map, error = %d\n",
184 sc->sc_dev.dv_xname, error);
185 return;
186 }
187
188 #undef MSCPSIZE
189
190 /*
191 * Initialize the mscps.
192 */
193 i = uha_create_mscps(sc, sc->sc_mscps, UHA_MSCP_MAX);
194 if (i == 0) {
195 printf("%s: unable to create mscps\n",
196 sc->sc_dev.dv_xname);
197 return;
198 } else if (i != UHA_MSCP_MAX) {
199 printf("%s: WARNING: only %d of %d mscps created\n",
200 sc->sc_dev.dv_xname, i, UHA_MSCP_MAX);
201 }
202
203 /*
204 * ask the adapter what subunits are present
205 */
206 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
207 }
208
209 integrate void
210 uha_reset_mscp(sc, mscp)
211 struct uha_softc *sc;
212 struct uha_mscp *mscp;
213 {
214
215 mscp->flags = 0;
216 }
217
218 /*
219 * A mscp (and hence a mbx-out) is put onto the free list.
220 */
221 void
222 uha_free_mscp(sc, mscp)
223 struct uha_softc *sc;
224 struct uha_mscp *mscp;
225 {
226 int s;
227
228 s = splbio();
229
230 uha_reset_mscp(sc, mscp);
231 TAILQ_INSERT_HEAD(&sc->sc_free_mscp, mscp, chain);
232
233 /*
234 * If there were none, wake anybody waiting for one to come free,
235 * starting with queued entries.
236 */
237 if (mscp->chain.tqe_next == 0)
238 wakeup(&sc->sc_free_mscp);
239
240 splx(s);
241 }
242
243 integrate int
244 uha_init_mscp(sc, mscp)
245 struct uha_softc *sc;
246 struct uha_mscp *mscp;
247 {
248 bus_dma_tag_t dmat = sc->sc_dmat;
249 int hashnum, error;
250
251 /*
252 * Create the DMA map for this MSCP.
253 */
254 error = bus_dmamap_create(dmat, UHA_MAXXFER, UHA_NSEG, UHA_MAXXFER,
255 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW | sc->sc_dmaflags,
256 &mscp->dmamap_xfer);
257 if (error) {
258 printf("%s: can't create mscp DMA map, error = %d\n",
259 sc->sc_dev.dv_xname, error);
260 return (error);
261 }
262
263 /*
264 * put in the phystokv hash table
265 * Never gets taken out.
266 */
267 mscp->hashkey = sc->sc_dmamap_mscp->dm_segs[0].ds_addr +
268 UHA_MSCP_OFF(mscp);
269 hashnum = MSCP_HASH(mscp->hashkey);
270 mscp->nexthash = sc->sc_mscphash[hashnum];
271 sc->sc_mscphash[hashnum] = mscp;
272 uha_reset_mscp(sc, mscp);
273 return (0);
274 }
275
276 /*
277 * Create a set of MSCPs and add them to the free list.
278 */
279 int
280 uha_create_mscps(sc, mscpstore, count)
281 struct uha_softc *sc;
282 struct uha_mscp *mscpstore;
283 int count;
284 {
285 struct uha_mscp *mscp;
286 int i, error;
287
288 bzero(mscpstore, sizeof(struct uha_mscp) * count);
289 for (i = 0; i < count; i++) {
290 mscp = &mscpstore[i];
291 if ((error = uha_init_mscp(sc, mscp)) != 0) {
292 printf("%s: unable to initialize mscp, error = %d\n",
293 sc->sc_dev.dv_xname, error);
294 goto out;
295 }
296 TAILQ_INSERT_TAIL(&sc->sc_free_mscp, mscp, chain);
297 }
298 out:
299 return (i);
300 }
301
302 /*
303 * Get a free mscp
304 *
305 * If there are none, see if we can allocate a new one. If so, put it in the
306 * hash table too otherwise either return an error or sleep.
307 */
308 struct uha_mscp *
309 uha_get_mscp(sc, flags)
310 struct uha_softc *sc;
311 int flags;
312 {
313 struct uha_mscp *mscp;
314 int s;
315
316 s = splbio();
317
318 /*
319 * If we can and have to, sleep waiting for one to come free
320 * but only if we can't allocate a new one
321 */
322 for (;;) {
323 mscp = sc->sc_free_mscp.tqh_first;
324 if (mscp) {
325 TAILQ_REMOVE(&sc->sc_free_mscp, mscp, chain);
326 break;
327 }
328 if ((flags & XS_CTL_NOSLEEP) != 0)
329 goto out;
330 tsleep(&sc->sc_free_mscp, PRIBIO, "uhamsc", 0);
331 }
332
333 mscp->flags |= MSCP_ALLOC;
334
335 out:
336 splx(s);
337 return (mscp);
338 }
339
340 /*
341 * given a physical address, find the mscp that it corresponds to.
342 */
343 struct uha_mscp *
344 uha_mscp_phys_kv(sc, mscp_phys)
345 struct uha_softc *sc;
346 u_long mscp_phys;
347 {
348 int hashnum = MSCP_HASH(mscp_phys);
349 struct uha_mscp *mscp = sc->sc_mscphash[hashnum];
350
351 while (mscp) {
352 if (mscp->hashkey == mscp_phys)
353 break;
354 mscp = mscp->nexthash;
355 }
356 return (mscp);
357 }
358
359 /*
360 * We have a mscp which has been processed by the adaptor, now we look to see
361 * how the operation went.
362 */
363 void
364 uha_done(sc, mscp)
365 struct uha_softc *sc;
366 struct uha_mscp *mscp;
367 {
368 bus_dma_tag_t dmat = sc->sc_dmat;
369 struct scsipi_sense_data *s1, *s2;
370 struct scsipi_xfer *xs = mscp->xs;
371
372 SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n"));
373
374 bus_dmamap_sync(dmat, sc->sc_dmamap_mscp,
375 UHA_MSCP_OFF(mscp), sizeof(struct uha_mscp),
376 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
377
378 /*
379 * If we were a data transfer, unload the map that described
380 * the data buffer.
381 */
382 if (xs->datalen) {
383 bus_dmamap_sync(dmat, mscp->dmamap_xfer, 0,
384 mscp->dmamap_xfer->dm_mapsize,
385 (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
386 BUS_DMASYNC_POSTWRITE);
387 bus_dmamap_unload(dmat, mscp->dmamap_xfer);
388 }
389
390 /*
391 * Otherwise, put the results of the operation
392 * into the xfer and call whoever started it
393 */
394 if ((mscp->flags & MSCP_ALLOC) == 0) {
395 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
396 Debugger();
397 return;
398 }
399 if (xs->error == XS_NOERROR) {
400 if (mscp->host_stat != UHA_NO_ERR) {
401 switch (mscp->host_stat) {
402 case UHA_SBUS_TIMEOUT: /* No response */
403 xs->error = XS_SELTIMEOUT;
404 break;
405 default: /* Other scsi protocol messes */
406 printf("%s: host_stat %x\n",
407 sc->sc_dev.dv_xname, mscp->host_stat);
408 xs->error = XS_DRIVER_STUFFUP;
409 }
410 } else if (mscp->target_stat != SCSI_OK) {
411 switch (mscp->target_stat) {
412 case SCSI_CHECK:
413 s1 = &mscp->mscp_sense;
414 s2 = &xs->sense.scsi_sense;
415 *s2 = *s1;
416 xs->error = XS_SENSE;
417 break;
418 case SCSI_BUSY:
419 xs->error = XS_BUSY;
420 break;
421 default:
422 printf("%s: target_stat %x\n",
423 sc->sc_dev.dv_xname, mscp->target_stat);
424 xs->error = XS_DRIVER_STUFFUP;
425 }
426 } else
427 xs->resid = 0;
428 }
429 uha_free_mscp(sc, mscp);
430 xs->xs_status |= XS_STS_DONE;
431 scsipi_done(xs);
432
433 /*
434 * If there are queue entries in the software queue, try to
435 * run the first one. We should be more or less guaranteed
436 * to succeed, since we just freed an MSCP.
437 *
438 * NOTE: uha_scsi_cmd() relies on our calling it with
439 * the first entry in the queue.
440 */
441 if ((xs = TAILQ_FIRST(&sc->sc_queue)) != NULL)
442 (void) uha_scsi_cmd(xs);
443 }
444
445 void
446 uhaminphys(bp)
447 struct buf *bp;
448 {
449
450 if (bp->b_bcount > UHA_MAXXFER)
451 bp->b_bcount = UHA_MAXXFER;
452 minphys(bp);
453 }
454
455 /*
456 * start a scsi operation given the command and the data address. Also
457 * needs the unit, target and lu.
458 */
459 int
460 uha_scsi_cmd(xs)
461 struct scsipi_xfer *xs;
462 {
463 struct scsipi_link *sc_link = xs->sc_link;
464 struct uha_softc *sc = sc_link->adapter_softc;
465 bus_dma_tag_t dmat = sc->sc_dmat;
466 struct uha_mscp *mscp;
467 struct uha_dma_seg *sg;
468 int error, seg, flags, s;
469 int fromqueue = 0, dontqueue = 0, nowait = 0;
470
471 SC_DEBUG(sc_link, SDEV_DB2, ("uha_scsi_cmd\n"));
472
473 s = splbio(); /* protect the queue */
474
475 /*
476 * If we're running the queue from bha_done(), we've been
477 * called with the first queue entry as our argument.
478 */
479 if (xs == TAILQ_FIRST(&sc->sc_queue)) {
480 TAILQ_REMOVE(&sc->sc_queue, xs, adapter_q);
481 fromqueue = 1;
482 nowait = 1;
483 goto get_mscp;
484 }
485
486 /* Polled requests can't be queued for later. */
487 dontqueue = xs->xs_control & XS_CTL_POLL;
488
489 /*
490 * If there are jobs in the queue, run them first.
491 */
492 if (TAILQ_FIRST(&sc->sc_queue) != NULL) {
493 /*
494 * If we can't queue, we have to abort, since
495 * we have to preserve order.
496 */
497 if (dontqueue) {
498 splx(s);
499 xs->error = XS_DRIVER_STUFFUP;
500 return (TRY_AGAIN_LATER);
501 }
502
503 /*
504 * Swap with the first queue entry.
505 */
506 TAILQ_INSERT_TAIL(&sc->sc_queue, xs, adapter_q);
507 xs = TAILQ_FIRST(&sc->sc_queue);
508 TAILQ_REMOVE(&sc->sc_queue, xs, adapter_q);
509 fromqueue = 1;
510 }
511
512 get_mscp:
513 /*
514 * get a mscp (mbox-out) to use. If the transfer
515 * is from a buf (possibly from interrupt time)
516 * then we can't allow it to sleep
517 */
518 flags = xs->xs_control;
519 if (nowait)
520 flags |= XS_CTL_NOSLEEP;
521 if ((mscp = uha_get_mscp(sc, flags)) == NULL) {
522 /*
523 * If we can't queue, we lose.
524 */
525 if (dontqueue) {
526 splx(s);
527 xs->error = XS_DRIVER_STUFFUP;
528 return (TRY_AGAIN_LATER);
529 }
530
531 /*
532 * Stuff ourselves into the queue, in front
533 * if we came off in the first place.
534 */
535 if (fromqueue)
536 TAILQ_INSERT_HEAD(&sc->sc_queue, xs, adapter_q);
537 else
538 TAILQ_INSERT_TAIL(&sc->sc_queue, xs, adapter_q);
539 splx(s);
540 return (SUCCESSFULLY_QUEUED);
541 }
542
543 splx(s); /* done playing with the queue */
544
545 mscp->xs = xs;
546 mscp->timeout = xs->timeout;
547
548 /*
549 * Put all the arguments for the xfer in the mscp
550 */
551 if (flags & XS_CTL_RESET) {
552 mscp->opcode = UHA_SDR;
553 mscp->ca = 0x01;
554 } else {
555 mscp->opcode = UHA_TSP;
556 /* XXX Not for tapes. */
557 mscp->ca = 0x01;
558 bcopy(xs->cmd, &mscp->scsi_cmd, mscp->scsi_cmd_length);
559 }
560 mscp->xdir = UHA_SDET;
561 mscp->dcn = 0x00;
562 mscp->chan = 0x00;
563 mscp->target = sc_link->scsipi_scsi.target;
564 mscp->lun = sc_link->scsipi_scsi.lun;
565 mscp->scsi_cmd_length = xs->cmdlen;
566 mscp->sense_ptr = sc->sc_dmamap_mscp->dm_segs[0].ds_addr +
567 UHA_MSCP_OFF(mscp) + offsetof(struct uha_mscp, mscp_sense);
568 mscp->req_sense_length = sizeof(mscp->mscp_sense);
569 mscp->host_stat = 0x00;
570 mscp->target_stat = 0x00;
571
572 if (xs->datalen) {
573 sg = mscp->uha_dma;
574 seg = 0;
575 #ifdef TFS
576 if (flags & SCSI_DATA_UIO) {
577 error = bus_dmamap_load_uio(dmat,
578 mscp->dmamap_xfer, (struct uio *)xs->data,
579 (flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
580 BUS_DMA_WAITOK);
581 } else
582 #endif /*TFS */
583 {
584 error = bus_dmamap_load(dmat,
585 mscp->dmamap_xfer, xs->data, xs->datalen, NULL,
586 (flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
587 BUS_DMA_WAITOK);
588 }
589
590 if (error) {
591 if (error == EFBIG) {
592 printf("%s: uha_scsi_cmd, more than %d"
593 " dma segments\n",
594 sc->sc_dev.dv_xname, UHA_NSEG);
595 } else {
596 printf("%s: uha_scsi_cmd, error %d loading"
597 " dma map\n",
598 sc->sc_dev.dv_xname, error);
599 }
600 goto bad;
601 }
602
603 bus_dmamap_sync(dmat, mscp->dmamap_xfer, 0,
604 mscp->dmamap_xfer->dm_mapsize,
605 (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
606 BUS_DMASYNC_PREWRITE);
607
608 /*
609 * Load the hardware scatter/gather map with the
610 * contents of the DMA map.
611 */
612 for (seg = 0; seg < mscp->dmamap_xfer->dm_nsegs; seg++) {
613 mscp->uha_dma[seg].seg_addr =
614 mscp->dmamap_xfer->dm_segs[seg].ds_addr;
615 mscp->uha_dma[seg].seg_len =
616 mscp->dmamap_xfer->dm_segs[seg].ds_len;
617 }
618
619 mscp->data_addr = sc->sc_dmamap_mscp->dm_segs[0].ds_addr +
620 UHA_MSCP_OFF(mscp) + offsetof(struct uha_mscp, uha_dma);
621 mscp->data_length = xs->datalen;
622 mscp->sgth = 0x01;
623 mscp->sg_num = seg;
624 } else { /* No data xfer, use non S/G values */
625 mscp->data_addr = (physaddr)0;
626 mscp->data_length = 0;
627 mscp->sgth = 0x00;
628 mscp->sg_num = 0;
629 }
630 mscp->link_id = 0;
631 mscp->link_addr = (physaddr)0;
632
633 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_mscp,
634 UHA_MSCP_OFF(mscp), sizeof(struct uha_mscp),
635 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
636
637 s = splbio();
638 (sc->start_mbox)(sc, mscp);
639 splx(s);
640
641 /*
642 * Usually return SUCCESSFULLY QUEUED
643 */
644 if ((flags & XS_CTL_POLL) == 0)
645 return (SUCCESSFULLY_QUEUED);
646
647 /*
648 * If we can't use interrupts, poll on completion
649 */
650 if ((sc->poll)(sc, xs, mscp->timeout)) {
651 uha_timeout(mscp);
652 if ((sc->poll)(sc, xs, mscp->timeout))
653 uha_timeout(mscp);
654 }
655 return (COMPLETE);
656
657 bad:
658 xs->error = XS_DRIVER_STUFFUP;
659 uha_free_mscp(sc, mscp);
660 return (COMPLETE);
661 }
662
663 void
664 uha_timeout(arg)
665 void *arg;
666 {
667 struct uha_mscp *mscp = arg;
668 struct scsipi_xfer *xs = mscp->xs;
669 struct scsipi_link *sc_link = xs->sc_link;
670 struct uha_softc *sc = sc_link->adapter_softc;
671 int s;
672
673 scsi_print_addr(sc_link);
674 printf("timed out");
675
676 s = splbio();
677
678 if (mscp->flags & MSCP_ABORT) {
679 /* abort timed out */
680 printf(" AGAIN\n");
681 /* XXX Must reset! */
682 } else {
683 /* abort the operation that has timed out */
684 printf("\n");
685 mscp->xs->error = XS_TIMEOUT;
686 mscp->timeout = UHA_ABORT_TIMEOUT;
687 mscp->flags |= MSCP_ABORT;
688 (sc->start_mbox)(sc, mscp);
689 }
690
691 splx(s);
692 }
693