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