wds.c revision 1.37 1 /* $NetBSD: wds.c,v 1.37 1998/12/05 19:43:55 mjacob Exp $ */
2
3 #include "opt_ddb.h"
4
5 #undef WDSDIAG
6 #ifdef DDB
7 #define integrate
8 #else
9 #define integrate static inline
10 #endif
11
12 /*
13 * XXX
14 * sense data
15 * aborts
16 * resets
17 */
18
19 /*-
20 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
21 * All rights reserved.
22 *
23 * This code is derived from software contributed to The NetBSD Foundation
24 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
25 * NASA Ames Research Center.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the NetBSD
38 * Foundation, Inc. and its contributors.
39 * 4. Neither the name of The NetBSD Foundation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
44 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
45 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
46 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
47 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
53 * POSSIBILITY OF SUCH DAMAGE.
54 */
55
56 /*
57 * Copyright (c) 1994, 1995 Julian Highfield. All rights reserved.
58 * Portions copyright (c) 1994, 1996, 1997
59 * Charles M. Hannum. All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 * 2. Redistributions in binary form must reproduce the above copyright
67 * notice, this list of conditions and the following disclaimer in the
68 * documentation and/or other materials provided with the distribution.
69 * 3. All advertising materials mentioning features or use of this software
70 * must display the following acknowledgement:
71 * This product includes software developed by Julian Highfield.
72 * 4. The name of the author may not be used to endorse or promote products
73 * derived from this software without specific prior written permission.
74 *
75 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
76 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
77 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
78 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
79 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
80 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
81 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
82 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
83 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
84 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
85 */
86
87 /*
88 * This driver is for the WD7000 family of SCSI controllers:
89 * the WD7000-ASC, a bus-mastering DMA controller,
90 * the WD7000-FASST2, an -ASC with new firmware and scatter-gather,
91 * and the WD7000-ASE, which was custom manufactured for Apollo
92 * workstations and seems to include an -ASC as well as floppy
93 * and ESDI interfaces.
94 *
95 * Loosely based on Theo Deraadt's unfinished attempt.
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/isa/isavar.h>
118 #include <dev/isa/isadmavar.h>
119
120 #include <dev/isa/wdsreg.h>
121
122 #define WDS_ISA_IOSIZE 8
123
124 #ifndef DDB
125 #define Debugger() panic("should call debugger here (wds.c)")
126 #endif /* ! DDB */
127
128 #define WDS_MAXXFER ((WDS_NSEG - 1) << PGSHIFT)
129
130 #define WDS_MBX_SIZE 16
131
132 #define WDS_SCB_MAX 32
133 #define SCB_HASH_SIZE 32 /* hash table size for phystokv */
134 #define SCB_HASH_SHIFT 9
135 #define SCB_HASH(x) ((((long)(x))>>SCB_HASH_SHIFT) & (SCB_HASH_SIZE - 1))
136
137 #define wds_nextmbx(wmb, mbx, mbio) \
138 if ((wmb) == &(mbx)->mbio[WDS_MBX_SIZE - 1]) \
139 (wmb) = &(mbx)->mbio[0]; \
140 else \
141 (wmb)++;
142
143 struct wds_mbx {
144 struct wds_mbx_out mbo[WDS_MBX_SIZE];
145 struct wds_mbx_in mbi[WDS_MBX_SIZE];
146 struct wds_mbx_out *cmbo; /* Collection Mail Box out */
147 struct wds_mbx_out *tmbo; /* Target Mail Box out */
148 struct wds_mbx_in *tmbi; /* Target Mail Box in */
149 };
150
151 struct wds_softc {
152 struct device sc_dev;
153
154 bus_space_tag_t sc_iot;
155 bus_space_handle_t sc_ioh;
156 bus_dma_tag_t sc_dmat;
157 bus_dmamap_t sc_dmamap_mbox; /* maps the mailbox */
158 void *sc_ih;
159
160 struct wds_mbx *sc_mbx;
161 #define wmbx (sc->sc_mbx)
162 struct wds_scb *sc_scbhash[SCB_HASH_SIZE];
163 TAILQ_HEAD(, wds_scb) sc_free_scb, sc_waiting_scb;
164 int sc_numscbs, sc_mbofull;
165 struct scsipi_link sc_link; /* prototype for subdevs */
166 struct scsipi_adapter sc_adapter;
167
168 LIST_HEAD(, scsipi_xfer) sc_queue;
169 struct scsipi_xfer *sc_queuelast;
170
171 int sc_revision;
172 int sc_maxsegs;
173 };
174
175 struct wds_probe_data {
176 #ifdef notyet
177 int sc_irq, sc_drq;
178 #endif
179 int sc_scsi_dev;
180 };
181
182 integrate void
183 wds_wait __P((bus_space_tag_t, bus_space_handle_t, int, int, int));
184 int wds_cmd __P((bus_space_tag_t, bus_space_handle_t, u_char *, int));
185 integrate void wds_finish_scbs __P((struct wds_softc *));
186 int wdsintr __P((void *));
187 integrate void wds_reset_scb __P((struct wds_softc *, struct wds_scb *));
188 void wds_free_scb __P((struct wds_softc *, struct wds_scb *));
189 integrate int wds_init_scb __P((struct wds_softc *, struct wds_scb *));
190 struct wds_scb *wds_get_scb __P((struct wds_softc *, int));
191 struct wds_scb *wds_scb_phys_kv __P((struct wds_softc *, u_long));
192 void wds_queue_scb __P((struct wds_softc *, struct wds_scb *));
193 void wds_collect_mbo __P((struct wds_softc *));
194 void wds_start_scbs __P((struct wds_softc *));
195 void wds_done __P((struct wds_softc *, struct wds_scb *, u_char));
196 int wds_find __P((bus_space_tag_t, bus_space_handle_t, struct wds_probe_data *));
197 void wds_attach __P((struct wds_softc *, struct wds_probe_data *));
198 void wds_init __P((struct wds_softc *, int));
199 void wds_inquire_setup_information __P((struct wds_softc *));
200 void wdsminphys __P((struct buf *));
201 int wds_scsi_cmd __P((struct scsipi_xfer *));
202 void wds_sense __P((struct wds_softc *, struct wds_scb *));
203 int wds_poll __P((struct wds_softc *, struct scsipi_xfer *, int));
204 int wds_ipoll __P((struct wds_softc *, struct wds_scb *, int));
205 void wds_timeout __P((void *));
206 int wds_create_scbs __P((struct wds_softc *, void *, size_t));
207 void wds_enqueue __P((struct wds_softc *, struct scsipi_xfer *, int));
208 struct scsipi_xfer *wds_dequeue __P((struct wds_softc *));
209
210 /* the below structure is so we have a default dev struct for our link struct */
211 struct scsipi_device wds_dev = {
212 NULL, /* Use default error handler */
213 NULL, /* have a queue, served by this */
214 NULL, /* have no async handler */
215 NULL, /* Use default 'done' routine */
216 };
217
218 int wdsprobe __P((struct device *, struct cfdata *, void *));
219 void wdsattach __P((struct device *, struct device *, void *));
220
221 struct cfattach wds_ca = {
222 sizeof(struct wds_softc), wdsprobe, wdsattach
223 };
224
225 #define WDS_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
226
227 /*
228 * Insert a scsipi_xfer into the software queue. We overload xs->free_list
229 * to avoid having to allocate additional resources (since we're used
230 * only during resource shortages anyhow.
231 */
232 void
233 wds_enqueue(sc, xs, infront)
234 struct wds_softc *sc;
235 struct scsipi_xfer *xs;
236 int infront;
237 {
238
239 if (infront || sc->sc_queue.lh_first == NULL) {
240 if (sc->sc_queue.lh_first == NULL)
241 sc->sc_queuelast = xs;
242 LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
243 return;
244 }
245
246 LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
247 sc->sc_queuelast = xs;
248 }
249
250 /*
251 * Pull a scsipi_xfer off the front of the software queue.
252 */
253 struct scsipi_xfer *
254 wds_dequeue(sc)
255 struct wds_softc *sc;
256 {
257 struct scsipi_xfer *xs;
258
259 xs = sc->sc_queue.lh_first;
260 LIST_REMOVE(xs, free_list);
261
262 if (sc->sc_queue.lh_first == NULL)
263 sc->sc_queuelast = NULL;
264
265 return (xs);
266 }
267
268 integrate void
269 wds_wait(iot, ioh, port, mask, val)
270 bus_space_tag_t iot;
271 bus_space_handle_t ioh;
272 int port;
273 int mask, val;
274 {
275
276 while ((bus_space_read_1(iot, ioh, port) & mask) != val)
277 ;
278 }
279
280 /*
281 * Write a command to the board's I/O ports.
282 */
283 int
284 wds_cmd(iot, ioh, ibuf, icnt)
285 bus_space_tag_t iot;
286 bus_space_handle_t ioh;
287 u_char *ibuf;
288 int icnt;
289 {
290 u_char c;
291
292 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
293
294 while (icnt--) {
295 bus_space_write_1(iot, ioh, WDS_CMD, *ibuf++);
296 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
297 c = bus_space_read_1(iot, ioh, WDS_STAT);
298 if (c & WDSS_REJ)
299 return 1;
300 }
301
302 return 0;
303 }
304
305 /*
306 * Check for the presence of a WD7000 SCSI controller.
307 */
308 int
309 wdsprobe(parent, match, aux)
310 struct device *parent;
311 struct cfdata *match;
312 void *aux;
313 {
314 struct isa_attach_args *ia = aux;
315 bus_space_tag_t iot = ia->ia_iot;
316 bus_space_handle_t ioh;
317 struct wds_probe_data wpd;
318 int rv;
319
320 /* Disallow wildcarded i/o address. */
321 if (ia->ia_iobase == ISACF_PORT_DEFAULT)
322 return (0);
323
324 if (bus_space_map(iot, ia->ia_iobase, WDS_ISA_IOSIZE, 0, &ioh))
325 return (0);
326
327 rv = wds_find(iot, ioh, &wpd);
328
329 bus_space_unmap(iot, ioh, WDS_ISA_IOSIZE);
330
331 if (rv) {
332 #ifdef notyet
333 if (ia->ia_irq != -1 && ia->ia_irq != wpd.sc_irq)
334 return (0);
335 if (ia->ia_drq != -1 && ia->ia_drq != wpd.sc_drq)
336 return (0);
337 ia->ia_irq = wpd.sc_irq;
338 ia->ia_drq = wpd.sc_drq;
339 #else
340 if (ia->ia_irq == -1)
341 return (0);
342 if (ia->ia_drq == -1)
343 return (0);
344 #endif
345 ia->ia_msize = 0;
346 ia->ia_iosize = WDS_ISA_IOSIZE;
347 }
348 return (rv);
349 }
350
351 /*
352 * Attach all available units.
353 */
354 void
355 wdsattach(parent, self, aux)
356 struct device *parent, *self;
357 void *aux;
358 {
359 struct isa_attach_args *ia = aux;
360 struct wds_softc *sc = (void *)self;
361 bus_space_tag_t iot = ia->ia_iot;
362 bus_space_handle_t ioh;
363 struct wds_probe_data wpd;
364 isa_chipset_tag_t ic = ia->ia_ic;
365 int error;
366
367 printf("\n");
368
369 if (bus_space_map(iot, ia->ia_iobase, WDS_ISA_IOSIZE, 0, &ioh)) {
370 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
371 return;
372 }
373
374 sc->sc_iot = iot;
375 sc->sc_ioh = ioh;
376 sc->sc_dmat = ia->ia_dmat;
377 if (!wds_find(iot, ioh, &wpd)) {
378 printf("%s: wds_find failed\n", sc->sc_dev.dv_xname);
379 return;
380 }
381
382 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN);
383 #ifdef notyet
384 if (wpd.sc_drq != -1) {
385 if ((error = isa_dmacascade(ic, wpd.sc_drq)) != 0) {
386 printf("%s: unable to cascade DRQ, error = %d\n",
387 sc->sc_dev.dv_xname, error);
388 return;
389 }
390 }
391
392 sc->sc_ih = isa_intr_establish(ic, wpd.sc_irq, IST_EDGE, IPL_BIO,
393 wdsintr, sc);
394 #else
395 if (ia->ia_drq != -1) {
396 if ((error = isa_dmacascade(ic, ia->ia_drq)) != 0) {
397 printf("%s: unable to cascade DRQ, error = %d\n",
398 sc->sc_dev.dv_xname, error);
399 return;
400 }
401 }
402
403 sc->sc_ih = isa_intr_establish(ic, ia->ia_irq, IST_EDGE, IPL_BIO,
404 wdsintr, sc);
405 #endif
406 if (sc->sc_ih == NULL) {
407 printf("%s: couldn't establish interrupt\n",
408 sc->sc_dev.dv_xname);
409 return;
410 }
411
412 wds_attach(sc, &wpd);
413 }
414
415 void
416 wds_attach(sc, wpd)
417 struct wds_softc *sc;
418 struct wds_probe_data *wpd;
419 {
420
421 TAILQ_INIT(&sc->sc_free_scb);
422 TAILQ_INIT(&sc->sc_waiting_scb);
423 LIST_INIT(&sc->sc_queue);
424
425 wds_init(sc, 0);
426 wds_inquire_setup_information(sc);
427
428 /*
429 * Fill in the adapter.
430 */
431 sc->sc_adapter.scsipi_cmd = wds_scsi_cmd;
432 sc->sc_adapter.scsipi_minphys = minphys;
433
434 /*
435 * fill in the prototype scsipi_link.
436 */
437 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
438 sc->sc_link.adapter_softc = sc;
439 sc->sc_link.scsipi_scsi.adapter_target = wpd->sc_scsi_dev;
440 sc->sc_link.adapter = &sc->sc_adapter;
441 sc->sc_link.device = &wds_dev;
442 /* XXX */
443 /* I don't think the -ASE can handle openings > 1. */
444 /* It gives Vendor Error 26 whenever I try it. */
445 sc->sc_link.openings = 1;
446 sc->sc_link.scsipi_scsi.max_target = 7;
447 sc->sc_link.scsipi_scsi.max_lun = 7;
448 sc->sc_link.type = BUS_SCSI;
449
450 /*
451 * ask the adapter what subunits are present
452 */
453 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
454 }
455
456 integrate void
457 wds_finish_scbs(sc)
458 struct wds_softc *sc;
459 {
460 struct wds_mbx_in *wmbi;
461 struct wds_scb *scb;
462 int i;
463
464 wmbi = wmbx->tmbi;
465
466 if (wmbi->stat == WDS_MBI_FREE) {
467 for (i = 0; i < WDS_MBX_SIZE; i++) {
468 if (wmbi->stat != WDS_MBI_FREE) {
469 printf("%s: mbi not in round-robin order\n",
470 sc->sc_dev.dv_xname);
471 goto AGAIN;
472 }
473 wds_nextmbx(wmbi, wmbx, mbi);
474 }
475 #ifdef WDSDIAGnot
476 printf("%s: mbi interrupt with no full mailboxes\n",
477 sc->sc_dev.dv_xname);
478 #endif
479 return;
480 }
481
482 AGAIN:
483 do {
484 scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr));
485 if (!scb) {
486 printf("%s: bad mbi scb pointer; skipping\n",
487 sc->sc_dev.dv_xname);
488 goto next;
489 }
490
491 #ifdef WDSDEBUG
492 if (wds_debug) {
493 u_char *cp = &scb->scsipi_cmd;
494 printf("op=%x %x %x %x %x %x\n",
495 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
496 printf("stat %x for mbi addr = 0x%08x, ",
497 wmbi->stat, wmbi);
498 printf("scb addr = 0x%x\n", scb);
499 }
500 #endif /* WDSDEBUG */
501
502 untimeout(wds_timeout, scb);
503 wds_done(sc, scb, wmbi->stat);
504
505 next:
506 wmbi->stat = WDS_MBI_FREE;
507 wds_nextmbx(wmbi, wmbx, mbi);
508 } while (wmbi->stat != WDS_MBI_FREE);
509
510 wmbx->tmbi = wmbi;
511 }
512
513 /*
514 * Process an interrupt.
515 */
516 int
517 wdsintr(arg)
518 void *arg;
519 {
520 struct wds_softc *sc = arg;
521 bus_space_tag_t iot = sc->sc_iot;
522 bus_space_handle_t ioh = sc->sc_ioh;
523 u_char c;
524
525 /* Was it really an interrupt from the board? */
526 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ) == 0)
527 return 0;
528
529 /* Get the interrupt status byte. */
530 c = bus_space_read_1(iot, ioh, WDS_IRQSTAT) & WDSI_MASK;
531
532 /* Acknowledge (which resets) the interrupt. */
533 bus_space_write_1(iot, ioh, WDS_IRQACK, 0x00);
534
535 switch (c) {
536 case WDSI_MSVC:
537 wds_finish_scbs(sc);
538 break;
539
540 case WDSI_MFREE:
541 wds_start_scbs(sc);
542 break;
543
544 default:
545 printf("%s: unrecognized interrupt type %02x",
546 sc->sc_dev.dv_xname, c);
547 break;
548 }
549
550 return 1;
551 }
552
553 integrate void
554 wds_reset_scb(sc, scb)
555 struct wds_softc *sc;
556 struct wds_scb *scb;
557 {
558
559 scb->flags = 0;
560 }
561
562 /*
563 * Free the command structure, the outgoing mailbox and the data buffer.
564 */
565 void
566 wds_free_scb(sc, scb)
567 struct wds_softc *sc;
568 struct wds_scb *scb;
569 {
570 int s;
571
572 s = splbio();
573
574 wds_reset_scb(sc, scb);
575 TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain);
576
577 /*
578 * If there were none, wake anybody waiting for one to come free,
579 * starting with queued entries.
580 */
581 if (scb->chain.tqe_next == 0)
582 wakeup(&sc->sc_free_scb);
583
584 splx(s);
585 }
586
587 integrate int
588 wds_init_scb(sc, scb)
589 struct wds_softc *sc;
590 struct wds_scb *scb;
591 {
592 bus_dma_tag_t dmat = sc->sc_dmat;
593 int hashnum, error;
594
595 /*
596 * XXX Should we put a DIAGNOSTIC check for multiple
597 * XXX SCB inits here?
598 */
599
600 bzero(scb, sizeof(struct wds_scb));
601
602 /*
603 * Create DMA maps for this SCB.
604 */
605 error = bus_dmamap_create(dmat, sizeof(struct wds_scb), 1,
606 sizeof(struct wds_scb), 0, BUS_DMA_NOWAIT, &scb->dmamap_self);
607 if (error) {
608 printf("%s: can't create scb dmamap_self\n",
609 sc->sc_dev.dv_xname);
610 return (error);
611 }
612
613 error = bus_dmamap_create(dmat, WDS_MAXXFER, WDS_NSEG, WDS_MAXXFER,
614 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &scb->dmamap_xfer);
615 if (error) {
616 printf("%s: can't create scb dmamap_xfer\n",
617 sc->sc_dev.dv_xname);
618 bus_dmamap_destroy(dmat, scb->dmamap_self);
619 return (error);
620 }
621
622 /*
623 * Load the permanent DMA maps.
624 */
625 error = bus_dmamap_load(dmat, scb->dmamap_self, scb,
626 sizeof(struct wds_scb), NULL, BUS_DMA_NOWAIT);
627 if (error) {
628 printf("%s: can't load scb dmamap_self\n",
629 sc->sc_dev.dv_xname);
630 bus_dmamap_destroy(dmat, scb->dmamap_self);
631 bus_dmamap_destroy(dmat, scb->dmamap_xfer);
632 return (error);
633 }
634
635 /*
636 * put in the phystokv hash table
637 * Never gets taken out.
638 */
639 scb->hashkey = scb->dmamap_self->dm_segs[0].ds_addr;
640 hashnum = SCB_HASH(scb->hashkey);
641 scb->nexthash = sc->sc_scbhash[hashnum];
642 sc->sc_scbhash[hashnum] = scb;
643 wds_reset_scb(sc, scb);
644 return (0);
645 }
646
647 /*
648 * Create a set of scbs and add them to the free list.
649 */
650 int
651 wds_create_scbs(sc, mem, size)
652 struct wds_softc *sc;
653 void *mem;
654 size_t size;
655 {
656 bus_dma_segment_t seg;
657 struct wds_scb *scb;
658 int rseg, error;
659
660 if (sc->sc_numscbs >= WDS_SCB_MAX)
661 return (0);
662
663 if ((scb = mem) != NULL)
664 goto have_mem;
665
666 size = NBPG;
667 error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1, &rseg,
668 BUS_DMA_NOWAIT);
669 if (error) {
670 printf("%s: can't allocate memory for scbs\n",
671 sc->sc_dev.dv_xname);
672 return (error);
673 }
674
675 error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
676 (caddr_t *)&scb, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
677 if (error) {
678 printf("%s: can't map memory for scbs\n",
679 sc->sc_dev.dv_xname);
680 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
681 return (error);
682 }
683
684 have_mem:
685 bzero(scb, size);
686 while (size > sizeof(struct wds_scb) && sc->sc_numscbs < WDS_SCB_MAX) {
687 error = wds_init_scb(sc, scb);
688 if (error) {
689 printf("%s: can't initialize scb\n",
690 sc->sc_dev.dv_xname);
691 return (error);
692 }
693 TAILQ_INSERT_TAIL(&sc->sc_free_scb, scb, chain);
694 (caddr_t)scb += ALIGN(sizeof(struct wds_scb));
695 size -= ALIGN(sizeof(struct wds_scb));
696 sc->sc_numscbs++;
697 }
698
699 return (0);
700 }
701
702 /*
703 * Get a free scb
704 *
705 * If there are none, see if we can allocate a new one. If so, put it in
706 * the hash table too otherwise either return an error or sleep.
707 */
708 struct wds_scb *
709 wds_get_scb(sc, flags)
710 struct wds_softc *sc;
711 int flags;
712 {
713 struct wds_scb *scb;
714 int s;
715
716 s = splbio();
717
718 /*
719 * If we can and have to, sleep waiting for one to come free
720 * but only if we can't allocate a new one.
721 */
722 for (;;) {
723 scb = sc->sc_free_scb.tqh_first;
724 if (scb) {
725 TAILQ_REMOVE(&sc->sc_free_scb, scb, chain);
726 break;
727 }
728 if (sc->sc_numscbs < WDS_SCB_MAX) {
729 /*
730 * wds_create_scbs() might have managed to create
731 * one before it failed. If so, don't abort,
732 * just grab it and continue to hobble along.
733 */
734 if (wds_create_scbs(sc, NULL, 0) != 0 &&
735 sc->sc_free_scb.tqh_first == NULL) {
736 printf("%s: can't allocate scbs\n",
737 sc->sc_dev.dv_xname);
738 goto out;
739 }
740 continue;
741 }
742 if ((flags & SCSI_NOSLEEP) != 0)
743 goto out;
744 tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0);
745 }
746
747 scb->flags |= SCB_ALLOC;
748
749 out:
750 splx(s);
751 return (scb);
752 }
753
754 struct wds_scb *
755 wds_scb_phys_kv(sc, scb_phys)
756 struct wds_softc *sc;
757 u_long scb_phys;
758 {
759 int hashnum = SCB_HASH(scb_phys);
760 struct wds_scb *scb = sc->sc_scbhash[hashnum];
761
762 while (scb) {
763 if (scb->hashkey == scb_phys)
764 break;
765 /* XXX Check to see if it matches the sense command block. */
766 if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd)))
767 break;
768 scb = scb->nexthash;
769 }
770 return (scb);
771 }
772
773 /*
774 * Queue a SCB to be sent to the controller, and send it if possible.
775 */
776 void
777 wds_queue_scb(sc, scb)
778 struct wds_softc *sc;
779 struct wds_scb *scb;
780 {
781
782 TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain);
783 wds_start_scbs(sc);
784 }
785
786 /*
787 * Garbage collect mailboxes that are no longer in use.
788 */
789 void
790 wds_collect_mbo(sc)
791 struct wds_softc *sc;
792 {
793 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
794 #ifdef WDSDIAG
795 struct wds_scb *scb;
796 #endif
797
798 wmbo = wmbx->cmbo;
799
800 while (sc->sc_mbofull > 0) {
801 if (wmbo->cmd != WDS_MBO_FREE)
802 break;
803
804 #ifdef WDSDIAG
805 scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr));
806 scb->flags &= ~SCB_SENDING;
807 #endif
808
809 --sc->sc_mbofull;
810 wds_nextmbx(wmbo, wmbx, mbo);
811 }
812
813 wmbx->cmbo = wmbo;
814 }
815
816 /*
817 * Send as many SCBs as we have empty mailboxes for.
818 */
819 void
820 wds_start_scbs(sc)
821 struct wds_softc *sc;
822 {
823 bus_space_tag_t iot = sc->sc_iot;
824 bus_space_handle_t ioh = sc->sc_ioh;
825 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
826 struct wds_scb *scb;
827 u_char c;
828
829 wmbo = wmbx->tmbo;
830
831 while ((scb = sc->sc_waiting_scb.tqh_first) != NULL) {
832 if (sc->sc_mbofull >= WDS_MBX_SIZE) {
833 wds_collect_mbo(sc);
834 if (sc->sc_mbofull >= WDS_MBX_SIZE) {
835 c = WDSC_IRQMFREE;
836 wds_cmd(iot, ioh, &c, sizeof c);
837 break;
838 }
839 }
840
841 TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain);
842 #ifdef WDSDIAG
843 scb->flags |= SCB_SENDING;
844 #endif
845
846 /* Link scb to mbo. */
847 if (scb->flags & SCB_SENSE)
848 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
849 offsetof(struct wds_scb, sense), wmbo->scb_addr);
850 else
851 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
852 offsetof(struct wds_scb, cmd), wmbo->scb_addr);
853 /* XXX What about aborts? */
854 wmbo->cmd = WDS_MBO_START;
855
856 /* Tell the card to poll immediately. */
857 c = WDSC_MSTART(wmbo - wmbx->mbo);
858 wds_cmd(sc->sc_iot, sc->sc_ioh, &c, sizeof c);
859
860 if ((scb->flags & SCB_POLLED) == 0)
861 timeout(wds_timeout, scb, (scb->timeout * hz) / 1000);
862
863 ++sc->sc_mbofull;
864 wds_nextmbx(wmbo, wmbx, mbo);
865 }
866
867 wmbx->tmbo = wmbo;
868 }
869
870 /*
871 * Process the result of a SCSI command.
872 */
873 void
874 wds_done(sc, scb, stat)
875 struct wds_softc *sc;
876 struct wds_scb *scb;
877 u_char stat;
878 {
879 bus_dma_tag_t dmat = sc->sc_dmat;
880 struct scsipi_xfer *xs = scb->xs;
881
882 /* XXXXX */
883
884 /* Don't release the SCB if it was an internal command. */
885 if (xs == 0) {
886 scb->flags |= SCB_DONE;
887 return;
888 }
889
890 /* Sense handling. */
891 if (xs->error == XS_SENSE) {
892 bcopy(&scb->sense_data, &xs->sense.scsi_sense,
893 sizeof (struct scsipi_sense_data));
894 } else {
895 /*
896 * If we were a data transfer, unload the map that described
897 * the data buffer.
898 */
899 if (xs->datalen) {
900 bus_dmamap_sync(dmat, scb->dmamap_xfer, 0,
901 scb->dmamap_xfer->dm_mapsize,
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_DMA_COHERENT))
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, 0,
1349 scb->dmamap_xfer->dm_mapsize,
1350 (flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1351 BUS_DMASYNC_PREWRITE);
1352
1353 if (sc->sc_maxsegs > 1) {
1354 /*
1355 * Load the hardware scatter/gather map with the
1356 * contents of the DMA map.
1357 */
1358 for (seg = 0; seg < scb->dmamap_xfer->dm_nsegs;
1359 seg++) {
1360 ltophys(scb->dmamap_xfer->dm_segs[seg].ds_addr,
1361 scb->scat_gath[seg].seg_addr);
1362 ltophys(scb->dmamap_xfer->dm_segs[seg].ds_len,
1363 scb->scat_gath[seg].seg_len);
1364 }
1365
1366 /*
1367 * Set up for scatter/gather transfer.
1368 */
1369 scb->cmd.opcode = WDSX_SCSISG;
1370 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
1371 offsetof(struct wds_scb, scat_gath),
1372 scb->cmd.data);
1373 ltophys(scb->dmamap_self->dm_nsegs *
1374 sizeof(struct wds_scat_gath), scb->cmd.len);
1375 } else {
1376 /*
1377 * This board is an ASC or an ASE, and the
1378 * transfer has been mapped contig for us.
1379 */
1380 scb->cmd.opcode = WDSX_SCSICMD;
1381 ltophys(scb->dmamap_xfer->dm_segs[0].ds_addr,
1382 scb->cmd.data);
1383 ltophys(scb->dmamap_xfer->dm_segs[0].ds_len,
1384 scb->cmd.len);
1385 }
1386 } else {
1387 scb->cmd.opcode = WDSX_SCSICMD;
1388 ltophys(0, scb->cmd.data);
1389 ltophys(0, scb->cmd.len);
1390 }
1391
1392 scb->cmd.stat = 0x00;
1393 scb->cmd.venderr = 0x00;
1394 ltophys(0, scb->cmd.link);
1395
1396 /* XXX Do we really want to do this? */
1397 if (flags & SCSI_POLL) {
1398 /* Will poll card, await result. */
1399 bus_space_write_1(sc->sc_iot, sc->sc_ioh, WDS_HCR, WDSH_DRQEN);
1400 scb->flags |= SCB_POLLED;
1401 } else {
1402 /* Will send command, let interrupt routine handle result. */
1403 bus_space_write_1(sc->sc_iot, sc->sc_ioh, WDS_HCR,
1404 WDSH_IRQEN | WDSH_DRQEN);
1405 }
1406
1407 s = splbio();
1408 wds_queue_scb(sc, scb);
1409 splx(s);
1410
1411 if ((flags & SCSI_POLL) == 0)
1412 return SUCCESSFULLY_QUEUED;
1413
1414 if (wds_poll(sc, xs, scb->timeout)) {
1415 wds_timeout(scb);
1416 if (wds_poll(sc, xs, scb->timeout))
1417 wds_timeout(scb);
1418 }
1419 return COMPLETE;
1420
1421 bad:
1422 xs->error = XS_DRIVER_STUFFUP;
1423 wds_free_scb(sc, scb);
1424 return COMPLETE;
1425 }
1426
1427 /*
1428 * Send a sense request.
1429 */
1430 void
1431 wds_sense(sc, scb)
1432 struct wds_softc *sc;
1433 struct wds_scb *scb;
1434 {
1435 struct scsipi_xfer *xs = scb->xs;
1436 struct scsipi_sense *ss = (void *)&scb->sense.scb;
1437 int s;
1438
1439 /* XXXXX */
1440
1441 /* Send sense request SCSI command. */
1442 xs->error = XS_SENSE;
1443 scb->flags |= SCB_SENSE;
1444
1445 /* Next, setup a request sense command block */
1446 bzero(ss, sizeof(*ss));
1447 ss->opcode = REQUEST_SENSE;
1448 ss->byte2 = xs->sc_link->scsipi_scsi.lun << 5;
1449 ss->length = sizeof(struct scsipi_sense_data);
1450
1451 /* Set up some of the command fields. */
1452 scb->sense.targ = scb->cmd.targ;
1453 scb->sense.write = 0x80;
1454 scb->sense.opcode = WDSX_SCSICMD;
1455 ltophys(scb->dmamap_self->dm_segs[0].ds_addr +
1456 offsetof(struct wds_scb, sense_data), scb->sense.data);
1457 ltophys(sizeof(struct scsipi_sense_data), scb->sense.len);
1458
1459 s = splbio();
1460 wds_queue_scb(sc, scb);
1461 splx(s);
1462
1463 /*
1464 * There's no reason for us to poll here. There are two cases:
1465 * 1) If it's a polling operation, then we're called from the interrupt
1466 * handler, and we return and continue polling.
1467 * 2) If it's an interrupt-driven operation, then it gets completed
1468 * later on when the REQUEST SENSE finishes.
1469 */
1470 }
1471
1472 /*
1473 * Poll a particular unit, looking for a particular scb
1474 */
1475 int
1476 wds_poll(sc, xs, count)
1477 struct wds_softc *sc;
1478 struct scsipi_xfer *xs;
1479 int count;
1480 {
1481 bus_space_tag_t iot = sc->sc_iot;
1482 bus_space_handle_t ioh = sc->sc_ioh;
1483
1484 /* timeouts are in msec, so we loop in 1000 usec cycles */
1485 while (count) {
1486 /*
1487 * If we had interrupts enabled, would we
1488 * have got an interrupt?
1489 */
1490 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
1491 wdsintr(sc);
1492 if (xs->flags & ITSDONE)
1493 return 0;
1494 delay(1000); /* only happens in boot so ok */
1495 count--;
1496 }
1497 return 1;
1498 }
1499
1500 /*
1501 * Poll a particular unit, looking for a particular scb
1502 */
1503 int
1504 wds_ipoll(sc, scb, count)
1505 struct wds_softc *sc;
1506 struct wds_scb *scb;
1507 int count;
1508 {
1509 bus_space_tag_t iot = sc->sc_iot;
1510 bus_space_handle_t ioh = sc->sc_ioh;
1511
1512 /* timeouts are in msec, so we loop in 1000 usec cycles */
1513 while (count) {
1514 /*
1515 * If we had interrupts enabled, would we
1516 * have got an interrupt?
1517 */
1518 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
1519 wdsintr(sc);
1520 if (scb->flags & SCB_DONE)
1521 return 0;
1522 delay(1000); /* only happens in boot so ok */
1523 count--;
1524 }
1525 return 1;
1526 }
1527
1528 void
1529 wds_timeout(arg)
1530 void *arg;
1531 {
1532 struct wds_scb *scb = arg;
1533 struct scsipi_xfer *xs = scb->xs;
1534 struct scsipi_link *sc_link = xs->sc_link;
1535 struct wds_softc *sc = sc_link->adapter_softc;
1536 int s;
1537
1538 scsi_print_addr(sc_link);
1539 printf("timed out");
1540
1541 s = splbio();
1542
1543 #ifdef WDSDIAG
1544 /*
1545 * If The scb's mbx is not free, then the board has gone south?
1546 */
1547 wds_collect_mbo(sc);
1548 if (scb->flags & SCB_SENDING) {
1549 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
1550 Debugger();
1551 }
1552 #endif
1553
1554 /*
1555 * If it has been through before, then
1556 * a previous abort has failed, don't
1557 * try abort again
1558 */
1559 if (scb->flags & SCB_ABORT) {
1560 /* abort timed out */
1561 printf(" AGAIN\n");
1562 /* XXX Must reset! */
1563 } else {
1564 /* abort the operation that has timed out */
1565 printf("\n");
1566 scb->xs->error = XS_TIMEOUT;
1567 scb->timeout = WDS_ABORT_TIMEOUT;
1568 scb->flags |= SCB_ABORT;
1569 wds_queue_scb(sc, scb);
1570 }
1571
1572 splx(s);
1573 }
1574