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