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