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