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