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