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