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