wds.c revision 1.26 1 /* $NetBSD: wds.c,v 1.26 1997/11/30 15:24:00 drochner Exp $ */
2
3 #undef WDSDIAG
4 #ifdef DDB
5 #define integrate
6 #else
7 #define integrate static inline
8 #endif
9
10 /*
11 * XXX
12 * sense data
13 * aborts
14 * resets
15 */
16
17 /*-
18 * Copyright (c) 1997 The NetBSD Foundation, Inc.
19 * All rights reserved.
20 *
21 * This code is derived from software contributed to The NetBSD Foundation
22 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
23 * NASA Ames Research Center.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
28 * 1. Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
33 * 3. All advertising materials mentioning features or use of this software
34 * must display the following acknowledgement:
35 * This product includes software developed by the NetBSD
36 * Foundation, Inc. and its contributors.
37 * 4. Neither the name of The NetBSD Foundation nor the names of its
38 * contributors may be used to endorse or promote products derived
39 * from this software without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
42 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
43 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
45 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51 * POSSIBILITY OF SUCH DAMAGE.
52 */
53
54 /*
55 * Copyright (c) 1994, 1995 Julian Highfield. All rights reserved.
56 * Portions copyright (c) 1994, 1996, 1997
57 * Charles M. Hannum. All rights reserved.
58 *
59 * Redistribution and use in source and binary forms, with or without
60 * modification, are permitted provided that the following conditions
61 * are met:
62 * 1. Redistributions of source code must retain the above copyright
63 * notice, this list of conditions and the following disclaimer.
64 * 2. Redistributions in binary form must reproduce the above copyright
65 * notice, this list of conditions and the following disclaimer in the
66 * documentation and/or other materials provided with the distribution.
67 * 3. All advertising materials mentioning features or use of this software
68 * must display the following acknowledgement:
69 * This product includes software developed by Julian Highfield.
70 * 4. The name of the author may not be used to endorse or promote products
71 * derived from this software without specific prior written permission.
72 *
73 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
74 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
75 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
76 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
77 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
78 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
79 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
80 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
81 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
82 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
83 */
84
85 /*
86 * This driver is for the WD7000 family of SCSI controllers:
87 * the WD7000-ASC, a bus-mastering DMA controller,
88 * the WD7000-FASST2, an -ASC with new firmware and scatter-gather,
89 * and the WD7000-ASE, which was custom manufactured for Apollo
90 * workstations and seems to include an -ASC as well as floppy
91 * and ESDI interfaces.
92 *
93 * Loosely based on Theo Deraadt's unfinished attempt.
94 */
95
96 #include <sys/types.h>
97 #include <sys/param.h>
98 #include <sys/systm.h>
99 #include <sys/kernel.h>
100 #include <sys/errno.h>
101 #include <sys/ioctl.h>
102 #include <sys/device.h>
103 #include <sys/malloc.h>
104 #include <sys/buf.h>
105 #include <sys/proc.h>
106 #include <sys/user.h>
107
108 #include <machine/bus.h>
109 #include <machine/intr.h>
110
111 #include <dev/scsipi/scsi_all.h>
112 #include <dev/scsipi/scsipi_all.h>
113 #include <dev/scsipi/scsiconf.h>
114
115 #include <dev/isa/isavar.h>
116 #include <dev/isa/isadmavar.h>
117
118 #include <dev/isa/wdsreg.h>
119
120 #define WDS_ISA_IOSIZE 8
121
122 #ifndef DDB
123 #define Debugger() panic("should call debugger here (wds.c)")
124 #endif /* ! DDB */
125
126 #define WDS_MAXXFER ((WDS_NSEG - 1) << PGSHIFT)
127
128 #define WDS_MBX_SIZE 16
129
130 #define WDS_SCB_MAX 32
131 #define SCB_HASH_SIZE 32 /* hash table size for phystokv */
132 #define SCB_HASH_SHIFT 9
133 #define SCB_HASH(x) ((((long)(x))>>SCB_HASH_SHIFT) & (SCB_HASH_SIZE - 1))
134
135 #define wds_nextmbx(wmb, mbx, mbio) \
136 if ((wmb) == &(mbx)->mbio[WDS_MBX_SIZE - 1]) \
137 (wmb) = &(mbx)->mbio[0]; \
138 else \
139 (wmb)++;
140
141 struct wds_mbx {
142 struct wds_mbx_out mbo[WDS_MBX_SIZE];
143 struct wds_mbx_in mbi[WDS_MBX_SIZE];
144 struct wds_mbx_out *cmbo; /* Collection Mail Box out */
145 struct wds_mbx_out *tmbo; /* Target Mail Box out */
146 struct wds_mbx_in *tmbi; /* Target Mail Box in */
147 };
148
149 struct wds_softc {
150 struct device sc_dev;
151
152 bus_space_tag_t sc_iot;
153 bus_space_handle_t sc_ioh;
154 bus_dma_tag_t sc_dmat;
155 bus_dmamap_t sc_dmamap_mbox; /* maps the mailbox */
156 void *sc_ih;
157
158 struct wds_mbx *sc_mbx;
159 #define wmbx (sc->sc_mbx)
160 struct wds_scb *sc_scbhash[SCB_HASH_SIZE];
161 TAILQ_HEAD(, wds_scb) sc_free_scb, sc_waiting_scb;
162 int sc_numscbs, sc_mbofull;
163 struct scsipi_link sc_link; /* prototype for subdevs */
164
165 LIST_HEAD(, scsipi_xfer) sc_queue;
166 struct scsipi_xfer *sc_queuelast;
167
168 int sc_revision;
169 int sc_maxsegs;
170 };
171
172 struct wds_probe_data {
173 #ifdef notyet
174 int sc_irq, sc_drq;
175 #endif
176 int sc_scsi_dev;
177 };
178
179 integrate void
180 wds_wait __P((bus_space_tag_t, bus_space_handle_t, int, int, int));
181 int wds_cmd __P((bus_space_tag_t, bus_space_handle_t, u_char *, int));
182 integrate void wds_finish_scbs __P((struct wds_softc *));
183 int wdsintr __P((void *));
184 integrate void wds_reset_scb __P((struct wds_softc *, struct wds_scb *));
185 void wds_free_scb __P((struct wds_softc *, struct wds_scb *));
186 integrate int wds_init_scb __P((struct wds_softc *, struct wds_scb *));
187 struct wds_scb *wds_get_scb __P((struct wds_softc *, int));
188 struct wds_scb *wds_scb_phys_kv __P((struct wds_softc *, u_long));
189 void wds_queue_scb __P((struct wds_softc *, struct wds_scb *));
190 void wds_collect_mbo __P((struct wds_softc *));
191 void wds_start_scbs __P((struct wds_softc *));
192 void wds_done __P((struct wds_softc *, struct wds_scb *, u_char));
193 int wds_find __P((bus_space_tag_t, bus_space_handle_t, struct wds_probe_data *));
194 void wds_attach __P((struct wds_softc *, struct wds_probe_data *));
195 void wds_init __P((struct wds_softc *, int));
196 void wds_inquire_setup_information __P((struct wds_softc *));
197 void wdsminphys __P((struct buf *));
198 int wds_scsi_cmd __P((struct scsipi_xfer *));
199 void wds_sense __P((struct wds_softc *, struct wds_scb *));
200 int wds_poll __P((struct wds_softc *, struct scsipi_xfer *, int));
201 int wds_ipoll __P((struct wds_softc *, struct wds_scb *, int));
202 void wds_timeout __P((void *));
203 int wds_create_scbs __P((struct wds_softc *, void *, size_t));
204 void wds_enqueue __P((struct wds_softc *, struct scsipi_xfer *, int));
205 struct scsipi_xfer *wds_dequeue __P((struct wds_softc *));
206
207 struct scsipi_adapter wds_switch = {
208 wds_scsi_cmd,
209 wdsminphys,
210 0,
211 0,
212 };
213
214 /* the below structure is so we have a default dev struct for our link struct */
215 struct scsipi_device wds_dev = {
216 NULL, /* Use default error handler */
217 NULL, /* have a queue, served by this */
218 NULL, /* have no async handler */
219 NULL, /* Use default 'done' routine */
220 };
221
222 #ifdef __BROKEN_INDIRECT_CONFIG
223 int wdsprobe __P((struct device *, void *, void *));
224 #else
225 int wdsprobe __P((struct device *, struct cfdata *, void *));
226 #endif
227 void wdsattach __P((struct device *, struct device *, void *));
228
229 struct cfattach wds_ca = {
230 sizeof(struct wds_softc), wdsprobe, wdsattach
231 };
232
233 struct cfdriver wds_cd = {
234 NULL, "wds", DV_DULL
235 };
236
237 #define WDS_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
238
239 /* XXX Should put this in a better place. */
240 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
241
242 /*
243 * Insert a scsipi_xfer into the software queue. We overload xs->free_list
244 * to avoid having to allocate additional resources (since we're used
245 * only during resource shortages anyhow.
246 */
247 void
248 wds_enqueue(sc, xs, infront)
249 struct wds_softc *sc;
250 struct scsipi_xfer *xs;
251 int infront;
252 {
253
254 if (infront || sc->sc_queue.lh_first == NULL) {
255 if (sc->sc_queue.lh_first == NULL)
256 sc->sc_queuelast = xs;
257 LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
258 return;
259 }
260
261 LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
262 sc->sc_queuelast = xs;
263 }
264
265 /*
266 * Pull a scsipi_xfer off the front of the software queue.
267 */
268 struct scsipi_xfer *
269 wds_dequeue(sc)
270 struct wds_softc *sc;
271 {
272 struct scsipi_xfer *xs;
273
274 xs = sc->sc_queue.lh_first;
275 LIST_REMOVE(xs, free_list);
276
277 if (sc->sc_queue.lh_first == NULL)
278 sc->sc_queuelast = NULL;
279
280 return (xs);
281 }
282
283 integrate void
284 wds_wait(iot, ioh, port, mask, val)
285 bus_space_tag_t iot;
286 bus_space_handle_t ioh;
287 int port;
288 int mask, val;
289 {
290
291 while ((bus_space_read_1(iot, ioh, port) & mask) != val)
292 ;
293 }
294
295 /*
296 * Write a command to the board's I/O ports.
297 */
298 int
299 wds_cmd(iot, ioh, ibuf, icnt)
300 bus_space_tag_t iot;
301 bus_space_handle_t ioh;
302 u_char *ibuf;
303 int icnt;
304 {
305 u_char c;
306
307 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
308
309 while (icnt--) {
310 bus_space_write_1(iot, ioh, WDS_CMD, *ibuf++);
311 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
312 c = bus_space_read_1(iot, ioh, WDS_STAT);
313 if (c & WDSS_REJ)
314 return 1;
315 }
316
317 return 0;
318 }
319
320 /*
321 * Check for the presence of a WD7000 SCSI controller.
322 */
323 int
324 wdsprobe(parent, match, aux)
325 struct device *parent;
326 #ifdef __BROKEN_INDIRECT_CONFIG
327 void *match;
328 #else
329 struct cfdata *match;
330 #endif
331 void *aux;
332 {
333 struct isa_attach_args *ia = aux;
334 bus_space_tag_t iot = ia->ia_iot;
335 bus_space_handle_t ioh;
336 struct wds_probe_data wpd;
337 int rv;
338
339 /* Disallow wildcarded i/o address. */
340 if (ia->ia_iobase == ISACF_PORT_DEFAULT)
341 return (0);
342
343 if (bus_space_map(iot, ia->ia_iobase, WDS_ISA_IOSIZE, 0, &ioh))
344 return (0);
345
346 rv = wds_find(iot, ioh, &wpd);
347
348 bus_space_unmap(iot, ioh, WDS_ISA_IOSIZE);
349
350 if (rv) {
351 #ifdef notyet
352 if (ia->ia_irq != -1 && ia->ia_irq != wpd.sc_irq)
353 return (0);
354 if (ia->ia_drq != -1 && ia->ia_drq != wpd.sc_drq)
355 return (0);
356 ia->ia_irq = wpd.sc_irq;
357 ia->ia_drq = wpd.sc_drq;
358 #else
359 if (ia->ia_irq == -1)
360 return (0);
361 if (ia->ia_drq == -1)
362 return (0);
363 #endif
364 ia->ia_msize = 0;
365 ia->ia_iosize = WDS_ISA_IOSIZE;
366 }
367 return (rv);
368 }
369
370 /*
371 * Attach all available units.
372 */
373 void
374 wdsattach(parent, self, aux)
375 struct device *parent, *self;
376 void *aux;
377 {
378 struct isa_attach_args *ia = aux;
379 struct wds_softc *sc = (void *)self;
380 bus_space_tag_t iot = ia->ia_iot;
381 bus_space_handle_t ioh;
382 struct wds_probe_data wpd;
383 isa_chipset_tag_t ic = ia->ia_ic;
384
385 printf("\n");
386
387 if (bus_space_map(iot, ia->ia_iobase, WDS_ISA_IOSIZE, 0, &ioh)) {
388 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
389 return;
390 }
391
392 sc->sc_iot = iot;
393 sc->sc_ioh = ioh;
394 sc->sc_dmat = ia->ia_dmat;
395 if (!wds_find(iot, ioh, &wpd)) {
396 printf("%s: wds_find failed\n", sc->sc_dev.dv_xname);
397 return;
398 }
399
400 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN);
401 #ifdef notyet
402 if (wpd.sc_drq != -1)
403 isa_dmacascade(parent, wpd.sc_drq);
404
405 sc->sc_ih = isa_intr_establish(ic, wpd.sc_irq, IST_EDGE, IPL_BIO,
406 wdsintr, sc);
407 #else
408 if (ia->ia_drq != -1)
409 isa_dmacascade(parent, ia->ia_drq);
410
411 sc->sc_ih = isa_intr_establish(ic, ia->ia_irq, IST_EDGE, IPL_BIO,
412 wdsintr, sc);
413 #endif
414 if (sc->sc_ih == NULL) {
415 printf("%s: couldn't establish interrupt\n",
416 sc->sc_dev.dv_xname);
417 return;
418 }
419
420 wds_attach(sc, &wpd);
421 }
422
423 void
424 wds_attach(sc, wpd)
425 struct wds_softc *sc;
426 struct wds_probe_data *wpd;
427 {
428
429 TAILQ_INIT(&sc->sc_free_scb);
430 TAILQ_INIT(&sc->sc_waiting_scb);
431 LIST_INIT(&sc->sc_queue);
432
433 wds_init(sc, 0);
434 wds_inquire_setup_information(sc);
435
436 /*
437 * fill in the prototype scsipi_link.
438 */
439 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
440 sc->sc_link.adapter_softc = sc;
441 sc->sc_link.scsipi_scsi.adapter_target = wpd->sc_scsi_dev;
442 sc->sc_link.adapter = &wds_switch;
443 sc->sc_link.device = &wds_dev;
444 /* XXX */
445 /* I don't think the -ASE can handle openings > 1. */
446 /* It gives Vendor Error 26 whenever I try it. */
447 sc->sc_link.openings = 1;
448 sc->sc_link.scsipi_scsi.max_target = 7;
449 sc->sc_link.type = BUS_SCSI;
450
451 /*
452 * ask the adapter what subunits are present
453 */
454 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
455 }
456
457 integrate void
458 wds_finish_scbs(sc)
459 struct wds_softc *sc;
460 {
461 struct wds_mbx_in *wmbi;
462 struct wds_scb *scb;
463 int i;
464
465 wmbi = wmbx->tmbi;
466
467 if (wmbi->stat == WDS_MBI_FREE) {
468 for (i = 0; i < WDS_MBX_SIZE; i++) {
469 if (wmbi->stat != WDS_MBI_FREE) {
470 printf("%s: mbi not in round-robin order\n",
471 sc->sc_dev.dv_xname);
472 goto AGAIN;
473 }
474 wds_nextmbx(wmbi, wmbx, mbi);
475 }
476 #ifdef WDSDIAGnot
477 printf("%s: mbi interrupt with no full mailboxes\n",
478 sc->sc_dev.dv_xname);
479 #endif
480 return;
481 }
482
483 AGAIN:
484 do {
485 scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr));
486 if (!scb) {
487 printf("%s: bad mbi scb pointer; skipping\n",
488 sc->sc_dev.dv_xname);
489 goto next;
490 }
491
492 #ifdef WDSDEBUG
493 if (wds_debug) {
494 u_char *cp = &scb->scsipi_cmd;
495 printf("op=%x %x %x %x %x %x\n",
496 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
497 printf("stat %x for mbi addr = 0x%08x, ",
498 wmbi->stat, wmbi);
499 printf("scb addr = 0x%x\n", scb);
500 }
501 #endif /* WDSDEBUG */
502
503 untimeout(wds_timeout, scb);
504 wds_done(sc, scb, wmbi->stat);
505
506 next:
507 wmbi->stat = WDS_MBI_FREE;
508 wds_nextmbx(wmbi, wmbx, mbi);
509 } while (wmbi->stat != WDS_MBI_FREE);
510
511 wmbx->tmbi = wmbi;
512 }
513
514 /*
515 * Process an interrupt.
516 */
517 int
518 wdsintr(arg)
519 void *arg;
520 {
521 struct wds_softc *sc = arg;
522 bus_space_tag_t iot = sc->sc_iot;
523 bus_space_handle_t ioh = sc->sc_ioh;
524 u_char c;
525
526 /* Was it really an interrupt from the board? */
527 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ) == 0)
528 return 0;
529
530 /* Get the interrupt status byte. */
531 c = bus_space_read_1(iot, ioh, WDS_IRQSTAT) & WDSI_MASK;
532
533 /* Acknowledge (which resets) the interrupt. */
534 bus_space_write_1(iot, ioh, WDS_IRQACK, 0x00);
535
536 switch (c) {
537 case WDSI_MSVC:
538 wds_finish_scbs(sc);
539 break;
540
541 case WDSI_MFREE:
542 wds_start_scbs(sc);
543 break;
544
545 default:
546 printf("%s: unrecognized interrupt type %02x",
547 sc->sc_dev.dv_xname, c);
548 break;
549 }
550
551 return 1;
552 }
553
554 integrate void
555 wds_reset_scb(sc, scb)
556 struct wds_softc *sc;
557 struct wds_scb *scb;
558 {
559
560 scb->flags = 0;
561 }
562
563 /*
564 * Free the command structure, the outgoing mailbox and the data buffer.
565 */
566 void
567 wds_free_scb(sc, scb)
568 struct wds_softc *sc;
569 struct wds_scb *scb;
570 {
571 int s;
572
573 s = splbio();
574
575 wds_reset_scb(sc, scb);
576 TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain);
577
578 /*
579 * If there were none, wake anybody waiting for one to come free,
580 * starting with queued entries.
581 */
582 if (scb->chain.tqe_next == 0)
583 wakeup(&sc->sc_free_scb);
584
585 splx(s);
586 }
587
588 integrate int
589 wds_init_scb(sc, scb)
590 struct wds_softc *sc;
591 struct wds_scb *scb;
592 {
593 bus_dma_tag_t dmat = sc->sc_dmat;
594 int hashnum, error;
595
596 /*
597 * XXX Should we put a DIAGNOSTIC check for multiple
598 * XXX SCB inits here?
599 */
600
601 bzero(scb, sizeof(struct wds_scb));
602
603 /*
604 * Create DMA maps for this SCB.
605 */
606 error = bus_dmamap_create(dmat, sizeof(struct wds_scb), 1,
607 sizeof(struct wds_scb), 0, BUS_DMA_NOWAIT, &scb->dmamap_self);
608 if (error) {
609 printf("%s: can't create scb dmamap_self\n",
610 sc->sc_dev.dv_xname);
611 return (error);
612 }
613
614 error = bus_dmamap_create(dmat, WDS_MAXXFER, WDS_NSEG, WDS_MAXXFER,
615 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &scb->dmamap_xfer);
616 if (error) {
617 printf("%s: can't create scb dmamap_xfer\n",
618 sc->sc_dev.dv_xname);
619 bus_dmamap_destroy(dmat, scb->dmamap_self);
620 return (error);
621 }
622
623 /*
624 * Load the permanent DMA maps.
625 */
626 error = bus_dmamap_load(dmat, scb->dmamap_self, scb,
627 sizeof(struct wds_scb), NULL, BUS_DMA_NOWAIT);
628 if (error) {
629 printf("%s: can't load scb dmamap_self\n",
630 sc->sc_dev.dv_xname);
631 bus_dmamap_destroy(dmat, scb->dmamap_self);
632 bus_dmamap_destroy(dmat, scb->dmamap_xfer);
633 return (error);
634 }
635
636 /*
637 * put in the phystokv hash table
638 * Never gets taken out.
639 */
640 scb->hashkey = scb->dmamap_self->dm_segs[0].ds_addr;
641 hashnum = SCB_HASH(scb->hashkey);
642 scb->nexthash = sc->sc_scbhash[hashnum];
643 sc->sc_scbhash[hashnum] = scb;
644 wds_reset_scb(sc, scb);
645 return (0);
646 }
647
648 /*
649 * Create a set of scbs and add them to the free list.
650 */
651 int
652 wds_create_scbs(sc, mem, size)
653 struct wds_softc *sc;
654 void *mem;
655 size_t size;
656 {
657 bus_dma_segment_t seg;
658 struct wds_scb *scb;
659 int rseg, error;
660
661 if (sc->sc_numscbs >= WDS_SCB_MAX)
662 return (0);
663
664 if ((scb = mem) != NULL)
665 goto have_mem;
666
667 size = NBPG;
668 error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
669 BUS_DMA_NOWAIT);
670 if (error) {
671 printf("%s: can't allocate memory for scbs\n",
672 sc->sc_dev.dv_xname);
673 return (error);
674 }
675
676 error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
677 (caddr_t *)&scb, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC);
678 if (error) {
679 printf("%s: can't map memory for scbs\n",
680 sc->sc_dev.dv_xname);
681 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
682 return (error);
683 }
684
685 have_mem:
686 bzero(scb, size);
687 while (size > sizeof(struct wds_scb) && sc->sc_numscbs < WDS_SCB_MAX) {
688 error = wds_init_scb(sc, scb);
689 if (error) {
690 printf("%s: can't initialize scb\n",
691 sc->sc_dev.dv_xname);
692 return (error);
693 }
694 TAILQ_INSERT_TAIL(&sc->sc_free_scb, scb, chain);
695 (caddr_t)scb += ALIGN(sizeof(struct wds_scb));
696 size -= ALIGN(sizeof(struct wds_scb));
697 sc->sc_numscbs++;
698 }
699
700 return (0);
701 }
702
703 /*
704 * Get a free scb
705 *
706 * If there are none, see if we can allocate a new one. If so, put it in
707 * the hash table too otherwise either return an error or sleep.
708 */
709 struct wds_scb *
710 wds_get_scb(sc, flags)
711 struct wds_softc *sc;
712 int flags;
713 {
714 struct wds_scb *scb;
715 int s;
716
717 s = splbio();
718
719 /*
720 * If we can and have to, sleep waiting for one to come free
721 * but only if we can't allocate a new one.
722 */
723 for (;;) {
724 scb = sc->sc_free_scb.tqh_first;
725 if (scb) {
726 TAILQ_REMOVE(&sc->sc_free_scb, scb, chain);
727 break;
728 }
729 if (sc->sc_numscbs < WDS_SCB_MAX) {
730 /*
731 * wds_create_scbs() might have managed to create
732 * one before it failed. If so, don't abort,
733 * just grab it and continue to hobble along.
734 */
735 if (wds_create_scbs(sc, NULL, 0) != 0 &&
736 sc->sc_free_scb.tqh_first == NULL) {
737 printf("%s: can't allocate scbs\n",
738 sc->sc_dev.dv_xname);
739 goto out;
740 }
741 continue;
742 }
743 if ((flags & SCSI_NOSLEEP) != 0)
744 goto out;
745 tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0);
746 }
747
748 scb->flags |= SCB_ALLOC;
749
750 out:
751 splx(s);
752 return (scb);
753 }
754
755 struct wds_scb *
756 wds_scb_phys_kv(sc, scb_phys)
757 struct wds_softc *sc;
758 u_long scb_phys;
759 {
760 int hashnum = SCB_HASH(scb_phys);
761 struct wds_scb *scb = sc->sc_scbhash[hashnum];
762
763 while (scb) {
764 if (scb->hashkey == scb_phys)
765 break;
766 /* XXX Check to see if it matches the sense command block. */
767 if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd)))
768 break;
769 scb = scb->nexthash;
770 }
771 return (scb);
772 }
773
774 /*
775 * Queue a SCB to be sent to the controller, and send it if possible.
776 */
777 void
778 wds_queue_scb(sc, scb)
779 struct wds_softc *sc;
780 struct wds_scb *scb;
781 {
782
783 TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain);
784 wds_start_scbs(sc);
785 }
786
787 /*
788 * Garbage collect mailboxes that are no longer in use.
789 */
790 void
791 wds_collect_mbo(sc)
792 struct wds_softc *sc;
793 {
794 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
795 #ifdef WDSDIAG
796 struct wds_scb *scb;
797 #endif
798
799 wmbo = wmbx->cmbo;
800
801 while (sc->sc_mbofull > 0) {
802 if (wmbo->cmd != WDS_MBO_FREE)
803 break;
804
805 #ifdef WDSDIAG
806 scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr));
807 scb->flags &= ~SCB_SENDING;
808 #endif
809
810 --sc->sc_mbofull;
811 wds_nextmbx(wmbo, wmbx, mbo);
812 }
813
814 wmbx->cmbo = wmbo;
815 }
816
817 /*
818 * Send as many SCBs as we have empty mailboxes for.
819 */
820 void
821 wds_start_scbs(sc)
822 struct wds_softc *sc;
823 {
824 bus_space_tag_t iot = sc->sc_iot;
825 bus_space_handle_t ioh = sc->sc_ioh;
826 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
827 struct wds_scb *scb;
828 u_char c;
829
830 wmbo = wmbx->tmbo;
831
832 while ((scb = sc->sc_waiting_scb.tqh_first) != NULL) {
833 if (sc->sc_mbofull >= WDS_MBX_SIZE) {
834 wds_collect_mbo(sc);
835 if (sc->sc_mbofull >= WDS_MBX_SIZE) {
836 c = WDSC_IRQMFREE;
837 wds_cmd(iot, ioh, &c, sizeof c);
838 break;
839 }
840 }
841
842 TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain);
843 #ifdef WDSDIAG
844 scb->flags |= SCB_SENDING;
845 #endif
846
847 /* Link scb to mbo. */
848 if (scb->flags & SCB_SENSE)
849 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
850 offsetof(struct wds_scb, sense), wmbo->scb_addr);
851 else
852 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
853 offsetof(struct wds_scb, cmd), wmbo->scb_addr);
854 /* XXX What about aborts? */
855 wmbo->cmd = WDS_MBO_START;
856
857 /* Tell the card to poll immediately. */
858 c = WDSC_MSTART(wmbo - wmbx->mbo);
859 wds_cmd(sc->sc_iot, sc->sc_ioh, &c, sizeof c);
860
861 if ((scb->flags & SCB_POLLED) == 0)
862 timeout(wds_timeout, scb, (scb->timeout * hz) / 1000);
863
864 ++sc->sc_mbofull;
865 wds_nextmbx(wmbo, wmbx, mbo);
866 }
867
868 wmbx->tmbo = wmbo;
869 }
870
871 /*
872 * Process the result of a SCSI command.
873 */
874 void
875 wds_done(sc, scb, stat)
876 struct wds_softc *sc;
877 struct wds_scb *scb;
878 u_char stat;
879 {
880 bus_dma_tag_t dmat = sc->sc_dmat;
881 struct scsipi_xfer *xs = scb->xs;
882
883 /* XXXXX */
884
885 /* Don't release the SCB if it was an internal command. */
886 if (xs == 0) {
887 scb->flags |= SCB_DONE;
888 return;
889 }
890
891 /* Sense handling. */
892 if (xs->error == XS_SENSE) {
893 bcopy(&scb->sense_data, &xs->sense.scsi_sense,
894 sizeof (struct scsipi_sense_data));
895 } else {
896 /*
897 * If we were a data transfer, unload the map that described
898 * the data buffer.
899 */
900 if (xs->datalen) {
901 bus_dmamap_sync(dmat, scb->dmamap_xfer,
902 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
903 BUS_DMASYNC_POSTWRITE);
904 bus_dmamap_unload(dmat, scb->dmamap_xfer);
905 }
906 if (xs->error == XS_NOERROR) {
907 /* If all went well, or an error is acceptable. */
908 if (stat == WDS_MBI_OK) {
909 /* OK, set the result */
910 xs->resid = 0;
911 } else {
912 /* Check the mailbox status. */
913 switch (stat) {
914 case WDS_MBI_OKERR:
915 /*
916 * SCSI error recorded in scb,
917 * counts as WDS_MBI_OK
918 */
919 switch (scb->cmd.venderr) {
920 case 0x00:
921 printf("%s: Is this "
922 "an error?\n",
923 sc->sc_dev.dv_xname);
924 /* Experiment. */
925 xs->error = XS_DRIVER_STUFFUP;
926 break;
927 case 0x01:
928 #if 0
929 printf("%s: OK, see SCSI "
930 "error field.\n",
931 sc->sc_dev.dv_xname);
932 #endif
933 if (scb->cmd.stat ==
934 SCSI_CHECK) {
935 /* Do sense. */
936 wds_sense(sc, scb);
937 return;
938 } else if (scb->cmd.stat ==
939 SCSI_BUSY) {
940 xs->error = XS_BUSY;
941 }
942 break;
943 case 0x40:
944 #if 0
945 printf("%s: DMA underrun!\n",
946 sc->sc_dev.dv_xname);
947 #endif
948 /*
949 * Hits this if the target
950 * returns fewer that datalen
951 * bytes (eg my CD-ROM, which
952 * returns a short version
953 * string, or if DMA is
954 * turned off etc.
955 */
956 xs->resid = 0;
957 break;
958 default:
959 printf("%s: VENDOR ERROR "
960 "%02x, scsi %02x\n",
961 sc->sc_dev.dv_xname,
962 scb->cmd.venderr,
963 scb->cmd.stat);
964 /* Experiment. */
965 xs->error = XS_DRIVER_STUFFUP;
966 break;
967 }
968 break;
969 case WDS_MBI_ETIME:
970 /*
971 * The documentation isn't clear on
972 * what conditions might generate this,
973 * but selection timeouts are the only
974 * one I can think of.
975 */
976 xs->error = XS_SELTIMEOUT;
977 break;
978 case WDS_MBI_ERESET:
979 case WDS_MBI_ETARCMD:
980 case WDS_MBI_ERESEL:
981 case WDS_MBI_ESEL:
982 case WDS_MBI_EABORT:
983 case WDS_MBI_ESRESET:
984 case WDS_MBI_EHRESET:
985 xs->error = XS_DRIVER_STUFFUP;
986 break;
987 }
988 }
989 } /* else sense */
990 } /* XS_NOERROR */
991
992 wds_free_scb(sc, scb);
993 xs->flags |= ITSDONE;
994 scsipi_done(xs);
995
996 /*
997 * If there are queue entries in the software queue, try to
998 * run the first one. We should be more or less guaranteed
999 * to succeed, since we just freed a CCB.
1000 *
1001 * NOTE: wds_scsi_cmd() relies on our calling it with
1002 * the first entry in the queue.
1003 */
1004 if ((xs = sc->sc_queue.lh_first) != NULL)
1005 (void) wds_scsi_cmd(xs);
1006 }
1007
1008 int
1009 wds_find(iot, ioh, sc)
1010 bus_space_tag_t iot;
1011 bus_space_handle_t ioh;
1012 struct wds_probe_data *sc;
1013 {
1014 int i;
1015
1016 /* XXXXX */
1017
1018 /*
1019 * Sending a command causes the CMDRDY bit to clear.
1020 */
1021 for (i = 5; i; i--) {
1022 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY) != 0)
1023 break;
1024 delay(100);
1025 }
1026 if (!i)
1027 return 0;
1028
1029 bus_space_write_1(iot, ioh, WDS_CMD, WDSC_NOOP);
1030 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY) != 0)
1031 return 0;
1032
1033 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
1034 delay(10000);
1035 bus_space_write_1(iot, ioh, WDS_HCR, 0x00);
1036 delay(500000);
1037 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
1038 if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 1)
1039 if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 7)
1040 return 0;
1041
1042 for (i = 2000; i; i--) {
1043 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY) != 0)
1044 break;
1045 delay(100);
1046 }
1047 if (!i)
1048 return 0;
1049
1050 if (sc) {
1051 #ifdef notyet
1052 sc->sc_irq = ...;
1053 sc->sc_drq = ...;
1054 #endif
1055 /* XXX Can we do this better? */
1056 sc->sc_scsi_dev = 7;
1057 }
1058
1059 return 1;
1060 }
1061
1062 /*
1063 * Initialise the board and driver.
1064 */
1065 void
1066 wds_init(sc, isreset)
1067 struct wds_softc *sc;
1068 int isreset;
1069 {
1070 bus_space_tag_t iot = sc->sc_iot;
1071 bus_space_handle_t ioh = sc->sc_ioh;
1072 bus_dma_segment_t seg;
1073 struct wds_setup init;
1074 u_char c;
1075 int i, rseg;
1076
1077 if (isreset)
1078 goto doinit;
1079
1080 /*
1081 * Allocate the mailbox.
1082 */
1083 if (bus_dmamem_alloc(sc->sc_dmat, NBPG, NBPG, 0, &seg, 1,
1084 &rseg, BUS_DMA_NOWAIT) ||
1085 bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
1086 (caddr_t *)&wmbx, BUS_DMA_NOWAIT|BUS_DMAMEM_NOSYNC))
1087 panic("wds_init: can't create or map mailbox");
1088
1089 /*
1090 * Since DMA memory allocation is always rounded up to a
1091 * page size, create some scbs from the leftovers.
1092 */
1093 if (wds_create_scbs(sc, ((caddr_t)wmbx) +
1094 ALIGN(sizeof(struct wds_mbx)),
1095 NBPG - ALIGN(sizeof(struct wds_mbx))))
1096 panic("wds_init: can't create scbs");
1097
1098 /*
1099 * Create and load the mailbox DMA map.
1100 */
1101 if (bus_dmamap_create(sc->sc_dmat, sizeof(struct wds_mbx), 1,
1102 sizeof(struct wds_mbx), 0, BUS_DMA_NOWAIT, &sc->sc_dmamap_mbox) ||
1103 bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mbox, wmbx,
1104 sizeof(struct wds_mbx), NULL, BUS_DMA_NOWAIT))
1105 panic("wds_ionit: can't craete or load mailbox dma map");
1106
1107 doinit:
1108 /*
1109 * Set up initial mail box for round-robin operation.
1110 */
1111 for (i = 0; i < WDS_MBX_SIZE; i++) {
1112 wmbx->mbo[i].cmd = WDS_MBO_FREE;
1113 wmbx->mbi[i].stat = WDS_MBI_FREE;
1114 }
1115 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
1116 wmbx->tmbi = &wmbx->mbi[0];
1117 sc->sc_mbofull = 0;
1118
1119 init.opcode = WDSC_INIT;
1120 init.scsi_id = sc->sc_link.scsipi_scsi.adapter_target;
1121 init.buson_t = 48;
1122 init.busoff_t = 24;
1123 init.xx = 0;
1124 ltophys(sc->sc_dmamap_mbox->dm_segs[0].ds_addr, init.mbaddr);
1125 init.nomb = init.nimb = WDS_MBX_SIZE;
1126 wds_cmd(iot, ioh, (u_char *)&init, sizeof init);
1127
1128 wds_wait(iot, ioh, WDS_STAT, WDSS_INIT, WDSS_INIT);
1129
1130 c = WDSC_DISUNSOL;
1131 wds_cmd(iot, ioh, &c, sizeof c);
1132 }
1133
1134 /*
1135 * Read the board's firmware revision information.
1136 */
1137 void
1138 wds_inquire_setup_information(sc)
1139 struct wds_softc *sc;
1140 {
1141 bus_space_tag_t iot = sc->sc_iot;
1142 bus_space_handle_t ioh = sc->sc_ioh;
1143 struct wds_scb *scb;
1144 u_char *j;
1145 int s;
1146
1147 sc->sc_maxsegs = 1;
1148
1149 scb = wds_get_scb(sc, SCSI_NOSLEEP);
1150 if (scb == 0)
1151 panic("wds_inquire_setup_information: no scb available");
1152
1153 scb->xs = NULL;
1154 scb->timeout = 40;
1155
1156 bzero(&scb->cmd, sizeof scb->cmd);
1157 scb->cmd.write = 0x80;
1158 scb->cmd.opcode = WDSX_GETFIRMREV;
1159
1160 /* Will poll card, await result. */
1161 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN);
1162 scb->flags |= SCB_POLLED;
1163
1164 s = splbio();
1165 wds_queue_scb(sc, scb);
1166 splx(s);
1167
1168 if (wds_ipoll(sc, scb, scb->timeout))
1169 goto out;
1170
1171 /* Print the version number. */
1172 printf("%s: version %x.%02x ", sc->sc_dev.dv_xname,
1173 scb->cmd.targ, scb->cmd.scb.opcode);
1174 sc->sc_revision = (scb->cmd.targ << 8) | scb->cmd.scb.opcode;
1175 /* Print out the version string. */
1176 j = 2 + &(scb->cmd.targ);
1177 while ((*j >= 32) && (*j < 128)) {
1178 printf("%c", *j);
1179 j++;
1180 }
1181
1182 /*
1183 * Determine if we can use scatter/gather.
1184 */
1185 if (sc->sc_revision >= 0x800)
1186 sc->sc_maxsegs = WDS_NSEG;
1187
1188 out:
1189 printf("\n");
1190
1191 /*
1192 * Free up the resources used by this scb.
1193 */
1194 wds_free_scb(sc, scb);
1195 }
1196
1197 void
1198 wdsminphys(bp)
1199 struct buf *bp;
1200 {
1201
1202 if (bp->b_bcount > WDS_MAXXFER)
1203 bp->b_bcount = WDS_MAXXFER;
1204 minphys(bp);
1205 }
1206
1207 /*
1208 * Send a SCSI command.
1209 */
1210 int
1211 wds_scsi_cmd(xs)
1212 struct scsipi_xfer *xs;
1213 {
1214 struct scsipi_link *sc_link = xs->sc_link;
1215 struct wds_softc *sc = sc_link->adapter_softc;
1216 bus_dma_tag_t dmat = sc->sc_dmat;
1217 struct wds_scb *scb;
1218 struct wds_scat_gath *sg;
1219 int error, seg, flags, s;
1220 int fromqueue = 0, dontqueue = 0;
1221 #ifdef TFS
1222 struct iovec *iovp;
1223 #endif
1224
1225 if (xs->flags & SCSI_RESET) {
1226 /* XXX Fix me! */
1227 printf("%s: reset!\n", sc->sc_dev.dv_xname);
1228 wds_init(sc, 1);
1229 return COMPLETE;
1230 }
1231
1232 s = splbio(); /* protect the queue */
1233
1234 /*
1235 * If we're running the queue from wds_done(), we've been
1236 * called with the first queue entry as our argument.
1237 */
1238 if (xs == sc->sc_queue.lh_first) {
1239 xs = wds_dequeue(sc);
1240 fromqueue = 1;
1241 goto get_scb;
1242 }
1243
1244 /* Polled requests can't be queued for later. */
1245 dontqueue = xs->flags & SCSI_POLL;
1246
1247 /*
1248 * If there are jobs in the queue, run them first.
1249 */
1250 if (sc->sc_queue.lh_first != NULL) {
1251 /*
1252 * If we can't queue, we have to abort, since
1253 * we have to preserve order.
1254 */
1255 if (dontqueue) {
1256 splx(s);
1257 xs->error = XS_DRIVER_STUFFUP;
1258 return (TRY_AGAIN_LATER);
1259 }
1260
1261 /*
1262 * Swap with the first queue entry.
1263 */
1264 wds_enqueue(sc, xs, 0);
1265 xs = wds_dequeue(sc);
1266 fromqueue = 1;
1267 }
1268
1269 get_scb:
1270 flags = xs->flags;
1271 if ((scb = wds_get_scb(sc, flags)) == NULL) {
1272 /*
1273 * If we can't queue, we lose.
1274 */
1275 if (dontqueue) {
1276 splx(s);
1277 xs->error = XS_DRIVER_STUFFUP;
1278 return (TRY_AGAIN_LATER);
1279 }
1280
1281 /*
1282 * Stuff ourselves into the queue, in front
1283 * if we came off in the first place.
1284 */
1285 wds_enqueue(sc, xs, fromqueue);
1286 splx(s);
1287 return (SUCCESSFULLY_QUEUED);
1288 }
1289
1290 splx(s); /* done playing with the queue */
1291
1292 scb->xs = xs;
1293 scb->timeout = xs->timeout;
1294
1295 if (xs->flags & SCSI_DATA_UIO) {
1296 /* XXX Fix me! */
1297 /* Let's not worry about UIO. There isn't any code for the *
1298 * non-SG boards anyway! */
1299 printf("%s: UIO is untested and disabled!\n",
1300 sc->sc_dev.dv_xname);
1301 goto bad;
1302 }
1303
1304 /* Zero out the command structure. */
1305 bzero(&scb->cmd, sizeof scb->cmd);
1306 bcopy(xs->cmd, &scb->cmd.scb, xs->cmdlen < 12 ? xs->cmdlen : 12);
1307
1308 /* Set up some of the command fields. */
1309 scb->cmd.targ = (xs->sc_link->scsipi_scsi.target << 5) |
1310 xs->sc_link->scsipi_scsi.lun;
1311
1312 /* NOTE: cmd.write may be OK as 0x40 (disable direction checking)
1313 * on boards other than the WD-7000V-ASE. Need this for the ASE:
1314 */
1315 scb->cmd.write = (xs->flags & SCSI_DATA_IN) ? 0x80 : 0x00;
1316
1317 if (xs->datalen) {
1318 sg = scb->scat_gath;
1319 seg = 0;
1320 #ifdef TFS
1321 if (flags & SCSI_DATA_UIO) {
1322 error = bus_Dmamap_load_uio(dmat,
1323 scb->dmamap_xfer, (struct uio *)xs->data,
1324 (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1325 BUS_DMA_WAITOK);
1326 } else
1327 #endif /* TFS */
1328 {
1329 error = bus_dmamap_load(dmat,
1330 scb->dmamap_xfer, xs->data, xs->datalen, NULL,
1331 (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1332 BUS_DMA_WAITOK);
1333 }
1334
1335 if (error) {
1336 if (error == EFBIG) {
1337 printf("%s: wds_scsi_cmd, more than %d"
1338 " dma segments\n",
1339 sc->sc_dev.dv_xname, sc->sc_maxsegs);
1340 } else {
1341 printf("%s: wds_scsi_cmd, error %d loading"
1342 " dma map\n",
1343 sc->sc_dev.dv_xname, error);
1344 }
1345 goto bad;
1346 }
1347
1348 bus_dmamap_sync(dmat, scb->dmamap_xfer,
1349 (flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1350 BUS_DMASYNC_PREWRITE);
1351
1352 if (sc->sc_maxsegs > 1) {
1353 /*
1354 * Load the hardware scatter/gather map with the
1355 * contents of the DMA map.
1356 */
1357 for (seg = 0; seg < scb->dmamap_xfer->dm_nsegs;
1358 seg++) {
1359 ltophys(scb->dmamap_xfer->dm_segs[seg].ds_addr,
1360 scb->scat_gath[seg].seg_addr);
1361 ltophys(scb->dmamap_xfer->dm_segs[seg].ds_len,
1362 scb->scat_gath[seg].seg_len);
1363 }
1364
1365 /*
1366 * Set up for scatter/gather transfer.
1367 */
1368 scb->cmd.opcode = WDSX_SCSISG;
1369 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
1370 offsetof(struct wds_scb, scat_gath),
1371 scb->cmd.data);
1372 ltophys(scb->dmamap_self->dm_nsegs *
1373 sizeof(struct wds_scat_gath), scb->cmd.len);
1374 } else {
1375 /*
1376 * This board is an ASC or an ASE, and the
1377 * transfer has been mapped contig for us.
1378 */
1379 scb->cmd.opcode = WDSX_SCSICMD;
1380 ltophys(scb->dmamap_xfer->dm_segs[0].ds_addr,
1381 scb->cmd.data);
1382 ltophys(scb->dmamap_xfer->dm_segs[0].ds_len,
1383 scb->cmd.len);
1384 }
1385 } else {
1386 scb->cmd.opcode = WDSX_SCSICMD;
1387 ltophys(0, scb->cmd.data);
1388 ltophys(0, scb->cmd.len);
1389 }
1390
1391 scb->cmd.stat = 0x00;
1392 scb->cmd.venderr = 0x00;
1393 ltophys(0, scb->cmd.link);
1394
1395 /* XXX Do we really want to do this? */
1396 if (flags & SCSI_POLL) {
1397 /* Will poll card, await result. */
1398 bus_space_write_1(sc->sc_iot, sc->sc_ioh, WDS_HCR, WDSH_DRQEN);
1399 scb->flags |= SCB_POLLED;
1400 } else {
1401 /* Will send command, let interrupt routine handle result. */
1402 bus_space_write_1(sc->sc_iot, sc->sc_ioh, WDS_HCR,
1403 WDSH_IRQEN | WDSH_DRQEN);
1404 }
1405
1406 s = splbio();
1407 wds_queue_scb(sc, scb);
1408 splx(s);
1409
1410 if ((flags & SCSI_POLL) == 0)
1411 return SUCCESSFULLY_QUEUED;
1412
1413 if (wds_poll(sc, xs, scb->timeout)) {
1414 wds_timeout(scb);
1415 if (wds_poll(sc, xs, scb->timeout))
1416 wds_timeout(scb);
1417 }
1418 return COMPLETE;
1419
1420 bad:
1421 xs->error = XS_DRIVER_STUFFUP;
1422 wds_free_scb(sc, scb);
1423 return COMPLETE;
1424 }
1425
1426 /*
1427 * Send a sense request.
1428 */
1429 void
1430 wds_sense(sc, scb)
1431 struct wds_softc *sc;
1432 struct wds_scb *scb;
1433 {
1434 struct scsipi_xfer *xs = scb->xs;
1435 struct scsipi_sense *ss = (void *)&scb->sense.scb;
1436 int s;
1437
1438 /* XXXXX */
1439
1440 /* Send sense request SCSI command. */
1441 xs->error = XS_SENSE;
1442 scb->flags |= SCB_SENSE;
1443
1444 /* Next, setup a request sense command block */
1445 bzero(ss, sizeof(*ss));
1446 ss->opcode = REQUEST_SENSE;
1447 ss->byte2 = xs->sc_link->scsipi_scsi.lun << 5;
1448 ss->length = sizeof(struct scsipi_sense_data);
1449
1450 /* Set up some of the command fields. */
1451 scb->sense.targ = scb->cmd.targ;
1452 scb->sense.write = 0x80;
1453 scb->sense.opcode = WDSX_SCSICMD;
1454 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
1455 offsetof(struct wds_scb, sense_data), scb->sense.data);
1456 ltophys(sizeof(struct scsipi_sense_data), scb->sense.len);
1457
1458 s = splbio();
1459 wds_queue_scb(sc, scb);
1460 splx(s);
1461
1462 /*
1463 * There's no reason for us to poll here. There are two cases:
1464 * 1) If it's a polling operation, then we're called from the interrupt
1465 * handler, and we return and continue polling.
1466 * 2) If it's an interrupt-driven operation, then it gets completed
1467 * later on when the REQUEST SENSE finishes.
1468 */
1469 }
1470
1471 /*
1472 * Poll a particular unit, looking for a particular scb
1473 */
1474 int
1475 wds_poll(sc, xs, count)
1476 struct wds_softc *sc;
1477 struct scsipi_xfer *xs;
1478 int count;
1479 {
1480 bus_space_tag_t iot = sc->sc_iot;
1481 bus_space_handle_t ioh = sc->sc_ioh;
1482
1483 /* timeouts are in msec, so we loop in 1000 usec cycles */
1484 while (count) {
1485 /*
1486 * If we had interrupts enabled, would we
1487 * have got an interrupt?
1488 */
1489 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
1490 wdsintr(sc);
1491 if (xs->flags & ITSDONE)
1492 return 0;
1493 delay(1000); /* only happens in boot so ok */
1494 count--;
1495 }
1496 return 1;
1497 }
1498
1499 /*
1500 * Poll a particular unit, looking for a particular scb
1501 */
1502 int
1503 wds_ipoll(sc, scb, count)
1504 struct wds_softc *sc;
1505 struct wds_scb *scb;
1506 int count;
1507 {
1508 bus_space_tag_t iot = sc->sc_iot;
1509 bus_space_handle_t ioh = sc->sc_ioh;
1510
1511 /* timeouts are in msec, so we loop in 1000 usec cycles */
1512 while (count) {
1513 /*
1514 * If we had interrupts enabled, would we
1515 * have got an interrupt?
1516 */
1517 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
1518 wdsintr(sc);
1519 if (scb->flags & SCB_DONE)
1520 return 0;
1521 delay(1000); /* only happens in boot so ok */
1522 count--;
1523 }
1524 return 1;
1525 }
1526
1527 void
1528 wds_timeout(arg)
1529 void *arg;
1530 {
1531 struct wds_scb *scb = arg;
1532 struct scsipi_xfer *xs = scb->xs;
1533 struct scsipi_link *sc_link = xs->sc_link;
1534 struct wds_softc *sc = sc_link->adapter_softc;
1535 int s;
1536
1537 scsi_print_addr(sc_link);
1538 printf("timed out");
1539
1540 s = splbio();
1541
1542 #ifdef WDSDIAG
1543 /*
1544 * If The scb's mbx is not free, then the board has gone south?
1545 */
1546 wds_collect_mbo(sc);
1547 if (scb->flags & SCB_SENDING) {
1548 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1549 Debugger();
1550 }
1551 #endif
1552
1553 /*
1554 * If it has been through before, then
1555 * a previous abort has failed, don't
1556 * try abort again
1557 */
1558 if (scb->flags & SCB_ABORT) {
1559 /* abort timed out */
1560 printf(" AGAIN\n");
1561 /* XXX Must reset! */
1562 } else {
1563 /* abort the operation that has timed out */
1564 printf("\n");
1565 scb->xs->error = XS_TIMEOUT;
1566 scb->timeout = WDS_ABORT_TIMEOUT;
1567 scb->flags |= SCB_ABORT;
1568 wds_queue_scb(sc, scb);
1569 }
1570
1571 splx(s);
1572 }
1573