Home | History | Annotate | Line # | Download | only in dev
fhpib.c revision 1.14
      1  1.14   thorpej /*	$NetBSD: fhpib.c,v 1.14 1997/01/30 09:06:53 thorpej Exp $	*/
      2   1.5       cgd 
      3   1.1       cgd /*
      4  1.14   thorpej  * Copyright (c) 1996, 1997 Jason R. Thorpe.  All rights reserved.
      5   1.4   mycroft  * Copyright (c) 1982, 1990, 1993
      6   1.4   mycroft  *	The Regents of the University of California.  All rights reserved.
      7   1.1       cgd  *
      8   1.1       cgd  * Redistribution and use in source and binary forms, with or without
      9   1.1       cgd  * modification, are permitted provided that the following conditions
     10   1.1       cgd  * are met:
     11   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     12   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     13   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     15   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     16   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     17   1.1       cgd  *    must display the following acknowledgement:
     18   1.1       cgd  *	This product includes software developed by the University of
     19   1.1       cgd  *	California, Berkeley and its contributors.
     20   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     21   1.1       cgd  *    may be used to endorse or promote products derived from this software
     22   1.1       cgd  *    without specific prior written permission.
     23   1.1       cgd  *
     24   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34   1.1       cgd  * SUCH DAMAGE.
     35   1.1       cgd  *
     36   1.5       cgd  *	@(#)fhpib.c	8.2 (Berkeley) 1/12/94
     37   1.1       cgd  */
     38   1.1       cgd 
     39   1.1       cgd /*
     40   1.1       cgd  * 98625A/B HPIB driver
     41   1.1       cgd  */
     42   1.1       cgd 
     43   1.4   mycroft #include <sys/param.h>
     44   1.4   mycroft #include <sys/systm.h>
     45   1.6   mycroft #include <sys/kernel.h>
     46   1.4   mycroft #include <sys/buf.h>
     47  1.14   thorpej #include <sys/device.h>
     48  1.14   thorpej 
     49  1.14   thorpej #include <machine/autoconf.h>
     50  1.14   thorpej 
     51  1.14   thorpej #include <hp300/hp300/isr.h>
     52  1.14   thorpej 
     53  1.14   thorpej #include <hp300/dev/dioreg.h>
     54  1.14   thorpej #include <hp300/dev/diovar.h>
     55  1.14   thorpej #include <hp300/dev/diodevs.h>
     56  1.14   thorpej 
     57  1.14   thorpej #include <hp300/dev/dmavar.h>
     58   1.4   mycroft 
     59   1.4   mycroft #include <hp300/dev/fhpibreg.h>
     60   1.4   mycroft #include <hp300/dev/hpibvar.h>
     61   1.1       cgd 
     62   1.1       cgd /*
     63   1.1       cgd  * Inline version of fhpibwait to be used in places where
     64   1.1       cgd  * we don't worry about getting hung.
     65   1.1       cgd  */
     66  1.11   thorpej #define	FHPIBWAIT(hd, m)	while (((hd)->hpib_intr & (m)) == 0) DELAY(1)
     67   1.1       cgd 
     68   1.1       cgd #ifdef DEBUG
     69   1.1       cgd int	fhpibdebugunit = -1;
     70   1.1       cgd int	fhpibdebug = 0;
     71   1.1       cgd #define FDB_FAIL	0x01
     72   1.1       cgd #define FDB_DMA		0x02
     73   1.1       cgd #define FDB_WAIT	0x04
     74   1.1       cgd #define FDB_PPOLL	0x08
     75   1.1       cgd 
     76   1.1       cgd int	dopriodma = 0;	/* use high priority DMA */
     77   1.1       cgd int	doworddma = 1;	/* non-zero if we should attempt word dma */
     78   1.1       cgd int	doppollint = 1;	/* use ppoll interrupts instead of watchdog */
     79   1.4   mycroft int	fhpibppolldelay = 50;
     80   1.1       cgd #endif
     81   1.1       cgd 
     82  1.14   thorpej void	fhpibifc __P((struct fhpibdevice *));
     83  1.14   thorpej void	fhpibdmadone __P((void *));
     84  1.14   thorpej int	fhpibwait __P((struct fhpibdevice *, int));
     85  1.14   thorpej 
     86  1.14   thorpej void	fhpibreset __P((struct hpibbus_softc *));
     87  1.14   thorpej int	fhpibsend __P((struct hpibbus_softc *, int, int, void *, int));
     88  1.14   thorpej int	fhpibrecv __P((struct hpibbus_softc *, int, int, void *, int));
     89  1.14   thorpej int	fhpibppoll __P((struct hpibbus_softc *));
     90   1.7   thorpej void	fhpibppwatch __P((void *));
     91  1.14   thorpej void	fhpibgo __P((struct hpibbus_softc *, int, int, void *, int, int, int));
     92  1.14   thorpej void	fhpibdone __P((struct hpibbus_softc *));
     93   1.9   thorpej int	fhpibintr __P((void *));
     94   1.7   thorpej 
     95   1.7   thorpej /*
     96   1.7   thorpej  * Our controller ops structure.
     97   1.7   thorpej  */
     98   1.7   thorpej struct	hpib_controller fhpib_controller = {
     99   1.7   thorpej 	fhpibreset,
    100   1.7   thorpej 	fhpibsend,
    101   1.7   thorpej 	fhpibrecv,
    102   1.7   thorpej 	fhpibppoll,
    103   1.7   thorpej 	fhpibppwatch,
    104   1.7   thorpej 	fhpibgo,
    105   1.7   thorpej 	fhpibdone,
    106   1.7   thorpej 	fhpibintr
    107   1.7   thorpej };
    108   1.7   thorpej 
    109  1.14   thorpej struct fhpib_softc {
    110  1.14   thorpej 	struct device sc_dev;		/* generic device glue */
    111  1.14   thorpej 	struct fhpibdevice *sc_regs;	/* device registers */
    112  1.14   thorpej 	int	sc_cmd;
    113  1.14   thorpej 	struct hpibbus_softc *sc_hpibbus; /* XXX */
    114  1.14   thorpej };
    115  1.14   thorpej 
    116  1.14   thorpej int	fhpibmatch __P((struct device *, struct cfdata *, void *));
    117  1.14   thorpej void	fhpibattach __P((struct device *, struct device *, void *));
    118  1.14   thorpej 
    119  1.14   thorpej struct cfattach fhpib_ca = {
    120  1.14   thorpej 	sizeof(struct fhpib_softc), fhpibmatch, fhpibattach
    121  1.14   thorpej };
    122  1.14   thorpej 
    123  1.14   thorpej struct cfdriver fhpib_cd = {
    124  1.14   thorpej 	NULL, "fhpib", DV_DULL
    125  1.14   thorpej };
    126  1.14   thorpej 
    127   1.7   thorpej int
    128  1.14   thorpej fhpibmatch(parent, match, aux)
    129  1.14   thorpej 	struct device *parent;
    130  1.14   thorpej 	struct cfdata *match;
    131  1.14   thorpej 	void *aux;
    132   1.1       cgd {
    133  1.14   thorpej 	struct dio_attach_args *da = aux;
    134   1.7   thorpej 
    135  1.14   thorpej 	if (da->da_id == DIO_DEVICE_ID_FHPIB)
    136  1.14   thorpej 		return (1);
    137   1.7   thorpej 
    138  1.14   thorpej 	return (0);
    139   1.8   thorpej }
    140   1.8   thorpej 
    141   1.8   thorpej void
    142  1.14   thorpej fhpibattach(parent, self, aux)
    143  1.14   thorpej 	struct device *parent, *self;
    144  1.14   thorpej 	void *aux;
    145  1.14   thorpej {
    146  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)self;
    147  1.14   thorpej 	struct dio_attach_args *da = aux;
    148  1.14   thorpej 	struct hpibdev_attach_args ha;
    149  1.14   thorpej 	int ipl;
    150  1.14   thorpej 
    151  1.14   thorpej 	sc->sc_regs = (struct fhpibdevice *)iomap(dio_scodetopa(da->da_scode),
    152  1.14   thorpej 	    da->da_size);
    153  1.14   thorpej 	if (sc->sc_regs == NULL) {
    154  1.14   thorpej 		printf("\n%s: can't map registers\n", self->dv_xname);
    155  1.14   thorpej 		return;
    156  1.14   thorpej 	}
    157  1.14   thorpej 
    158  1.14   thorpej 	ipl = DIO_IPL(sc->sc_regs);
    159  1.14   thorpej 	printf(" ipl %d: %s\n", ipl, DIO_DEVICE_DESC_FHPIB);
    160   1.8   thorpej 
    161  1.14   thorpej 	/* Establish the interrupt handler. */
    162  1.14   thorpej 	(void) isrlink(fhpibintr, sc, ipl, ISRPRI_BIO);
    163  1.14   thorpej 	dmacomputeipl();
    164  1.14   thorpej 
    165  1.14   thorpej 	ha.ha_ops = &fhpib_controller;
    166  1.14   thorpej 	ha.ha_type = HPIBC;			/* XXX */
    167  1.14   thorpej 	ha.ha_ba = HPIBC_BA;
    168  1.14   thorpej 	ha.ha_softcpp = &sc->sc_hpibbus;	/* XXX */
    169  1.14   thorpej 	(void)config_found(self, &ha, hpibdevprint);
    170   1.1       cgd }
    171   1.1       cgd 
    172   1.7   thorpej void
    173  1.14   thorpej fhpibreset(hs)
    174  1.14   thorpej 	struct hpibbus_softc *hs;
    175   1.1       cgd {
    176  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    177  1.14   thorpej 	struct fhpibdevice *hd = sc->sc_regs;
    178   1.1       cgd 
    179   1.1       cgd 	hd->hpib_cid = 0xFF;
    180   1.1       cgd 	DELAY(100);
    181   1.1       cgd 	hd->hpib_cmd = CT_8BIT;
    182   1.1       cgd 	hd->hpib_ar = AR_ARONC;
    183   1.1       cgd 	fhpibifc(hd);
    184   1.1       cgd 	hd->hpib_ie = IDS_IE;
    185   1.1       cgd 	hd->hpib_data = C_DCL;
    186   1.1       cgd 	DELAY(100000);
    187   1.1       cgd 	/*
    188   1.1       cgd 	 * See if we can do word dma.
    189   1.1       cgd 	 * If so, we should be able to write and read back the appropos bit.
    190   1.1       cgd 	 */
    191   1.1       cgd 	hd->hpib_ie |= IDS_WDMA;
    192   1.1       cgd 	if (hd->hpib_ie & IDS_WDMA) {
    193   1.1       cgd 		hd->hpib_ie &= ~IDS_WDMA;
    194   1.1       cgd 		hs->sc_flags |= HPIBF_DMA16;
    195   1.1       cgd #ifdef DEBUG
    196   1.1       cgd 		if (fhpibdebug & FDB_DMA)
    197  1.14   thorpej 			printf("fhpibtype: %s has word dma\n",
    198  1.14   thorpej 			    sc->sc_dev.dv_xname);
    199   1.1       cgd 
    200   1.1       cgd #endif
    201   1.1       cgd 	}
    202   1.1       cgd }
    203   1.1       cgd 
    204  1.14   thorpej void
    205   1.1       cgd fhpibifc(hd)
    206   1.1       cgd 	register struct fhpibdevice *hd;
    207   1.1       cgd {
    208   1.1       cgd 	hd->hpib_cmd |= CT_IFC;
    209   1.1       cgd 	hd->hpib_cmd |= CT_INITFIFO;
    210   1.1       cgd 	DELAY(100);
    211   1.1       cgd 	hd->hpib_cmd &= ~CT_IFC;
    212   1.1       cgd 	hd->hpib_cmd |= CT_REN;
    213   1.1       cgd 	hd->hpib_stat = ST_ATN;
    214   1.1       cgd }
    215   1.1       cgd 
    216   1.7   thorpej int
    217  1.14   thorpej fhpibsend(hs, slave, sec, ptr, origcnt)
    218  1.14   thorpej 	struct hpibbus_softc *hs;
    219  1.14   thorpej 	int slave, sec, origcnt;
    220   1.7   thorpej 	void *ptr;
    221   1.1       cgd {
    222  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    223  1.14   thorpej 	struct fhpibdevice *hd = sc->sc_regs;
    224   1.1       cgd 	register int cnt = origcnt;
    225   1.1       cgd 	register int timo;
    226   1.7   thorpej 	char *addr = ptr;
    227   1.1       cgd 
    228   1.1       cgd 	hd->hpib_stat = 0;
    229   1.1       cgd 	hd->hpib_imask = IM_IDLE | IM_ROOM;
    230   1.1       cgd 	if (fhpibwait(hd, IM_IDLE) < 0)
    231   1.1       cgd 		goto senderr;
    232   1.1       cgd 	hd->hpib_stat = ST_ATN;
    233   1.1       cgd 	hd->hpib_data = C_UNL;
    234   1.1       cgd 	hd->hpib_data = C_TAG + hs->sc_ba;
    235   1.1       cgd 	hd->hpib_data = C_LAG + slave;
    236   1.6   mycroft 	if (sec < 0) {
    237   1.6   mycroft 		if (sec == -2)		/* selected device clear KLUDGE */
    238   1.6   mycroft 			hd->hpib_data = C_SDC;
    239   1.6   mycroft 	} else
    240   1.1       cgd 		hd->hpib_data = C_SCG + sec;
    241   1.1       cgd 	if (fhpibwait(hd, IM_IDLE) < 0)
    242   1.1       cgd 		goto senderr;
    243   1.1       cgd 	if (cnt) {
    244   1.1       cgd 		hd->hpib_stat = ST_WRITE;
    245   1.1       cgd 		while (--cnt) {
    246   1.1       cgd 			hd->hpib_data = *addr++;
    247   1.1       cgd 			timo = hpibtimeout;
    248   1.1       cgd 			while ((hd->hpib_intr & IM_ROOM) == 0) {
    249   1.1       cgd 				if (--timo <= 0)
    250   1.1       cgd 					goto senderr;
    251  1.11   thorpej 				DELAY(1);
    252   1.1       cgd 			}
    253   1.1       cgd 		}
    254   1.1       cgd 		hd->hpib_stat = ST_EOI;
    255   1.1       cgd 		hd->hpib_data = *addr;
    256   1.1       cgd 		FHPIBWAIT(hd, IM_ROOM);
    257   1.1       cgd 		hd->hpib_stat = ST_ATN;
    258   1.1       cgd 		/* XXX: HP-UX claims bug with CS80 transparent messages */
    259   1.1       cgd 		if (sec == 0x12)
    260   1.1       cgd 			DELAY(150);
    261   1.1       cgd 		hd->hpib_data = C_UNL;
    262   1.1       cgd 		(void) fhpibwait(hd, IM_IDLE);
    263   1.1       cgd 	}
    264   1.1       cgd 	hd->hpib_imask = 0;
    265   1.1       cgd 	return (origcnt);
    266   1.6   mycroft 
    267   1.1       cgd senderr:
    268   1.1       cgd 	hd->hpib_imask = 0;
    269   1.1       cgd 	fhpibifc(hd);
    270   1.1       cgd #ifdef DEBUG
    271   1.1       cgd 	if (fhpibdebug & FDB_FAIL) {
    272  1.13  christos 		printf("%s: fhpibsend failed: slave %d, sec %x, ",
    273  1.14   thorpej 		    sc->sc_dev.dv_xname, slave, sec);
    274  1.13  christos 		printf("sent %d of %d bytes\n", origcnt-cnt-1, origcnt);
    275   1.1       cgd 	}
    276   1.1       cgd #endif
    277   1.6   mycroft 	return (origcnt - cnt - 1);
    278   1.1       cgd }
    279   1.1       cgd 
    280   1.7   thorpej int
    281  1.14   thorpej fhpibrecv(hs, slave, sec, ptr, origcnt)
    282  1.14   thorpej 	struct hpibbus_softc *hs;
    283  1.14   thorpej 	int slave, sec, origcnt;
    284   1.7   thorpej 	void *ptr;
    285   1.1       cgd {
    286  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    287  1.14   thorpej 	struct fhpibdevice *hd = sc->sc_regs;
    288   1.1       cgd 	register int cnt = origcnt;
    289   1.1       cgd 	register int timo;
    290   1.7   thorpej 	char *addr = ptr;
    291   1.1       cgd 
    292   1.6   mycroft 	/*
    293   1.6   mycroft 	 * Slave < 0 implies continuation of a previous receive
    294   1.6   mycroft 	 * that probably timed out.
    295   1.6   mycroft 	 */
    296   1.6   mycroft 	if (slave >= 0) {
    297   1.6   mycroft 		hd->hpib_stat = 0;
    298   1.6   mycroft 		hd->hpib_imask = IM_IDLE | IM_ROOM | IM_BYTE;
    299   1.6   mycroft 		if (fhpibwait(hd, IM_IDLE) < 0)
    300   1.6   mycroft 			goto recverror;
    301   1.6   mycroft 		hd->hpib_stat = ST_ATN;
    302   1.6   mycroft 		hd->hpib_data = C_UNL;
    303   1.6   mycroft 		hd->hpib_data = C_LAG + hs->sc_ba;
    304   1.6   mycroft 		hd->hpib_data = C_TAG + slave;
    305   1.6   mycroft 		if (sec != -1)
    306   1.6   mycroft 			hd->hpib_data = C_SCG + sec;
    307   1.6   mycroft 		if (fhpibwait(hd, IM_IDLE) < 0)
    308   1.6   mycroft 			goto recverror;
    309   1.6   mycroft 		hd->hpib_stat = ST_READ0;
    310   1.6   mycroft 		hd->hpib_data = 0;
    311   1.6   mycroft 	}
    312   1.1       cgd 	if (cnt) {
    313   1.1       cgd 		while (--cnt >= 0) {
    314   1.1       cgd 			timo = hpibtimeout;
    315   1.1       cgd 			while ((hd->hpib_intr & IM_BYTE) == 0) {
    316   1.1       cgd 				if (--timo == 0)
    317   1.1       cgd 					goto recvbyteserror;
    318  1.11   thorpej 				DELAY(1);
    319   1.1       cgd 			}
    320   1.1       cgd 			*addr++ = hd->hpib_data;
    321   1.1       cgd 		}
    322   1.1       cgd 		FHPIBWAIT(hd, IM_ROOM);
    323   1.1       cgd 		hd->hpib_stat = ST_ATN;
    324   1.1       cgd 		hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
    325   1.1       cgd 		(void) fhpibwait(hd, IM_IDLE);
    326   1.1       cgd 	}
    327   1.1       cgd 	hd->hpib_imask = 0;
    328   1.1       cgd 	return (origcnt);
    329   1.1       cgd 
    330   1.1       cgd recverror:
    331   1.1       cgd 	fhpibifc(hd);
    332   1.1       cgd recvbyteserror:
    333   1.1       cgd 	hd->hpib_imask = 0;
    334   1.1       cgd #ifdef DEBUG
    335   1.1       cgd 	if (fhpibdebug & FDB_FAIL) {
    336  1.13  christos 		printf("%s: fhpibrecv failed: slave %d, sec %x, ",
    337  1.14   thorpej 		    sc->sc_dev.dv_xname, slave, sec);
    338  1.13  christos 		printf("got %d of %d bytes\n", origcnt-cnt-1, origcnt);
    339   1.1       cgd 	}
    340   1.1       cgd #endif
    341   1.6   mycroft 	return (origcnt - cnt - 1);
    342   1.1       cgd }
    343   1.1       cgd 
    344   1.7   thorpej void
    345  1.14   thorpej fhpibgo(hs, slave, sec, ptr, count, rw, timo)
    346  1.14   thorpej 	struct hpibbus_softc *hs;
    347  1.14   thorpej 	int slave, sec, count, rw, timo;
    348   1.7   thorpej 	void *ptr;
    349   1.1       cgd {
    350  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    351  1.14   thorpej 	register struct fhpibdevice *hd = sc->sc_regs;
    352   1.1       cgd 	register int i;
    353   1.7   thorpej 	char *addr = ptr;
    354   1.1       cgd 	int flags = 0;
    355   1.1       cgd 
    356   1.1       cgd 	hs->sc_flags |= HPIBF_IO;
    357   1.6   mycroft 	if (timo)
    358   1.6   mycroft 		hs->sc_flags |= HPIBF_TIMO;
    359   1.1       cgd 	if (rw == B_READ)
    360   1.1       cgd 		hs->sc_flags |= HPIBF_READ;
    361   1.1       cgd #ifdef DEBUG
    362   1.1       cgd 	else if (hs->sc_flags & HPIBF_READ) {
    363  1.13  christos 		printf("fhpibgo: HPIBF_READ still set\n");
    364   1.1       cgd 		hs->sc_flags &= ~HPIBF_READ;
    365   1.1       cgd 	}
    366   1.1       cgd #endif
    367   1.1       cgd 	hs->sc_count = count;
    368   1.1       cgd 	hs->sc_addr = addr;
    369   1.1       cgd #ifdef DEBUG
    370  1.14   thorpej 	/* fhpibtransfer[unit]++;			XXX */
    371   1.1       cgd #endif
    372   1.1       cgd 	if ((hs->sc_flags & HPIBF_DMA16) &&
    373   1.1       cgd 	    ((int)addr & 1) == 0 && count && (count & 1) == 0
    374   1.1       cgd #ifdef DEBUG
    375   1.1       cgd 	    && doworddma
    376   1.1       cgd #endif
    377   1.1       cgd 	    ) {
    378   1.1       cgd #ifdef DEBUG
    379  1.14   thorpej 		/* fhpibworddma[unit]++;		XXX */
    380   1.1       cgd #endif
    381   1.1       cgd 		flags |= DMAGO_WORD;
    382   1.1       cgd 		hd->hpib_latch = 0;
    383   1.1       cgd 	}
    384   1.1       cgd #ifdef DEBUG
    385   1.1       cgd 	if (dopriodma)
    386   1.1       cgd 		flags |= DMAGO_PRI;
    387   1.1       cgd #endif
    388   1.1       cgd 	if (hs->sc_flags & HPIBF_READ) {
    389  1.14   thorpej 		sc->sc_cmd = CT_REN | CT_8BIT;
    390   1.1       cgd 		hs->sc_curcnt = count;
    391  1.14   thorpej 		dmago(hs->sc_dq->dq_chan, addr, count, flags|DMAGO_READ);
    392  1.14   thorpej 		if (fhpibrecv(hs, slave, sec, 0, 0) < 0) {
    393   1.1       cgd #ifdef DEBUG
    394  1.13  christos 			printf("fhpibgo: recv failed, retrying...\n");
    395   1.1       cgd #endif
    396  1.14   thorpej 			(void) fhpibrecv(hs, slave, sec, 0, 0);
    397   1.1       cgd 		}
    398   1.1       cgd 		i = hd->hpib_cmd;
    399  1.14   thorpej 		hd->hpib_cmd = sc->sc_cmd;
    400  1.14   thorpej 		hd->hpib_ie = IDS_DMA(hs->sc_dq->dq_chan) |
    401   1.1       cgd 			((flags & DMAGO_WORD) ? IDS_WDMA : 0);
    402   1.1       cgd 		return;
    403   1.1       cgd 	}
    404  1.14   thorpej 	sc->sc_cmd = CT_REN | CT_8BIT | CT_FIFOSEL;
    405   1.1       cgd 	if (count < hpibdmathresh) {
    406   1.1       cgd #ifdef DEBUG
    407  1.14   thorpej 		/* fhpibnondma[unit]++;			XXX */
    408   1.1       cgd 		if (flags & DMAGO_WORD)
    409  1.14   thorpej 			/* fhpibworddma[unit]--;	XXX */ ;
    410   1.1       cgd #endif
    411   1.1       cgd 		hs->sc_curcnt = count;
    412  1.14   thorpej 		(void) fhpibsend(hs, slave, sec, addr, count);
    413  1.14   thorpej 		fhpibdone(hs);
    414   1.1       cgd 		return;
    415   1.1       cgd 	}
    416   1.1       cgd 	count -= (flags & DMAGO_WORD) ? 2 : 1;
    417   1.1       cgd 	hs->sc_curcnt = count;
    418  1.14   thorpej 	dmago(hs->sc_dq->dq_chan, addr, count, flags);
    419  1.14   thorpej 	if (fhpibsend(hs, slave, sec, 0, 0) < 0) {
    420   1.1       cgd #ifdef DEBUG
    421  1.13  christos 		printf("fhpibgo: send failed, retrying...\n");
    422   1.1       cgd #endif
    423  1.14   thorpej 		(void) fhpibsend(hs, slave, sec, 0, 0);
    424   1.1       cgd 	}
    425   1.1       cgd 	i = hd->hpib_cmd;
    426  1.14   thorpej 	hd->hpib_cmd = sc->sc_cmd;
    427  1.14   thorpej 	hd->hpib_ie = IDS_DMA(hs->sc_dq->dq_chan) | IDS_WRITE |
    428   1.1       cgd 		((flags & DMAGO_WORD) ? IDS_WDMA : 0);
    429   1.1       cgd }
    430   1.1       cgd 
    431   1.6   mycroft /*
    432   1.6   mycroft  * A DMA read can finish but the device can still be waiting (MAG-tape
    433   1.6   mycroft  * with more data than we're waiting for).  This timeout routine
    434   1.6   mycroft  * takes care of that.  Somehow, the thing gets hosed.  For now, since
    435   1.6   mycroft  * this should be a very rare occurence, we RESET it.
    436   1.6   mycroft  */
    437   1.6   mycroft void
    438   1.6   mycroft fhpibdmadone(arg)
    439   1.6   mycroft 	void *arg;
    440   1.6   mycroft {
    441  1.14   thorpej 	register struct hpibbus_softc *hs = arg;
    442  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    443   1.6   mycroft 	int s = splbio();
    444   1.6   mycroft 
    445   1.6   mycroft 	if (hs->sc_flags & HPIBF_IO) {
    446  1.14   thorpej 		register struct fhpibdevice *hd = sc->sc_regs;
    447  1.14   thorpej 		register struct hpibqueue *hq;
    448   1.6   mycroft 
    449   1.6   mycroft 		hd->hpib_imask = 0;
    450   1.6   mycroft 		hd->hpib_cid = 0xFF;
    451   1.6   mycroft 		DELAY(100);
    452   1.6   mycroft 		hd->hpib_cmd = CT_8BIT;
    453   1.6   mycroft 		hd->hpib_ar = AR_ARONC;
    454   1.6   mycroft 		fhpibifc(hd);
    455   1.6   mycroft 		hd->hpib_ie = IDS_IE;
    456   1.6   mycroft 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
    457  1.14   thorpej 		dmafree(hs->sc_dq);
    458  1.14   thorpej 
    459  1.14   thorpej 		hq = hs->sc_queue.tqh_first;
    460  1.14   thorpej 		(hq->hq_intr)(hq->hq_softc);
    461   1.6   mycroft 	}
    462  1.14   thorpej 	splx(s);
    463   1.6   mycroft }
    464   1.6   mycroft 
    465   1.7   thorpej void
    466  1.14   thorpej fhpibdone(hs)
    467  1.14   thorpej 	struct hpibbus_softc *hs;
    468   1.1       cgd {
    469  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    470  1.14   thorpej 	register struct fhpibdevice *hd = sc->sc_regs;
    471   1.1       cgd 	register char *addr;
    472   1.1       cgd 	register int cnt;
    473   1.1       cgd 
    474   1.1       cgd 	cnt = hs->sc_curcnt;
    475   1.1       cgd 	hs->sc_addr += cnt;
    476   1.1       cgd 	hs->sc_count -= cnt;
    477   1.1       cgd #ifdef DEBUG
    478   1.1       cgd 	if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit)
    479  1.13  christos 		printf("fhpibdone: addr %x cnt %d\n",
    480   1.1       cgd 		       hs->sc_addr, hs->sc_count);
    481   1.1       cgd #endif
    482   1.6   mycroft 	if (hs->sc_flags & HPIBF_READ) {
    483   1.1       cgd 		hd->hpib_imask = IM_IDLE | IM_BYTE;
    484   1.6   mycroft 		if (hs->sc_flags & HPIBF_TIMO)
    485  1.14   thorpej 			timeout(fhpibdmadone, hs, hz >> 2);
    486   1.6   mycroft 	} else {
    487   1.1       cgd 		cnt = hs->sc_count;
    488   1.1       cgd 		if (cnt) {
    489   1.1       cgd 			addr = hs->sc_addr;
    490   1.1       cgd 			hd->hpib_imask = IM_IDLE | IM_ROOM;
    491   1.1       cgd 			FHPIBWAIT(hd, IM_IDLE);
    492   1.1       cgd 			hd->hpib_stat = ST_WRITE;
    493   1.1       cgd 			while (--cnt) {
    494   1.1       cgd 				hd->hpib_data = *addr++;
    495   1.1       cgd 				FHPIBWAIT(hd, IM_ROOM);
    496   1.1       cgd 			}
    497   1.1       cgd 			hd->hpib_stat = ST_EOI;
    498   1.1       cgd 			hd->hpib_data = *addr;
    499   1.1       cgd 		}
    500   1.1       cgd 		hd->hpib_imask = IM_IDLE;
    501   1.1       cgd 	}
    502   1.1       cgd 	hs->sc_flags |= HPIBF_DONE;
    503   1.1       cgd 	hd->hpib_stat = ST_IENAB;
    504   1.1       cgd 	hd->hpib_ie = IDS_IE;
    505   1.1       cgd }
    506   1.1       cgd 
    507   1.7   thorpej int
    508   1.9   thorpej fhpibintr(arg)
    509   1.9   thorpej 	void *arg;
    510   1.1       cgd {
    511  1.14   thorpej 	struct fhpib_softc *sc = arg;
    512  1.14   thorpej 	register struct hpibbus_softc *hs = sc->sc_hpibbus;
    513  1.14   thorpej 	register struct fhpibdevice *hd = sc->sc_regs;
    514  1.14   thorpej 	register struct hpibqueue *hq;
    515  1.14   thorpej 	register int stat0, unit = sc->sc_dev.dv_unit;
    516   1.1       cgd 
    517   1.1       cgd 	stat0 = hd->hpib_ids;
    518   1.1       cgd 	if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) {
    519   1.1       cgd #ifdef DEBUG
    520   1.1       cgd 		if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) &&
    521   1.1       cgd 		    (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO)
    522  1.13  christos 			printf("%s: fhpibintr: bad status %x\n",
    523  1.14   thorpej 			sc->sc_dev.dv_xname, stat0);
    524  1.14   thorpej 		/* fhpibbadint[0]++;			XXX */
    525   1.1       cgd #endif
    526   1.1       cgd 		return(0);
    527   1.1       cgd 	}
    528   1.1       cgd 	if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) {
    529   1.1       cgd #ifdef DEBUG
    530  1.14   thorpej 		/* fhpibbadint[1]++;			XXX */
    531   1.1       cgd #endif
    532   1.1       cgd 		return(0);
    533   1.1       cgd 	}
    534   1.1       cgd #ifdef DEBUG
    535   1.1       cgd 	if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit)
    536  1.13  christos 		printf("fhpibintr: flags %x\n", hs->sc_flags);
    537   1.1       cgd #endif
    538  1.14   thorpej 	hq = hs->sc_queue.tqh_first;
    539   1.1       cgd 	if (hs->sc_flags & HPIBF_IO) {
    540   1.6   mycroft 		if (hs->sc_flags & HPIBF_TIMO)
    541  1.14   thorpej 			untimeout(fhpibdmadone, hs);
    542   1.1       cgd 		stat0 = hd->hpib_cmd;
    543  1.14   thorpej 		hd->hpib_cmd = sc->sc_cmd & ~CT_8BIT;
    544   1.1       cgd 		hd->hpib_stat = 0;
    545   1.1       cgd 		hd->hpib_cmd = CT_REN | CT_8BIT;
    546   1.1       cgd 		stat0 = hd->hpib_intr;
    547   1.1       cgd 		hd->hpib_imask = 0;
    548   1.6   mycroft 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
    549  1.14   thorpej 		dmafree(hs->sc_dq);
    550  1.14   thorpej 		(hq->hq_intr)(hq->hq_softc);
    551   1.1       cgd 	} else if (hs->sc_flags & HPIBF_PPOLL) {
    552   1.1       cgd 		stat0 = hd->hpib_intr;
    553   1.1       cgd #ifdef DEBUG
    554   1.1       cgd 		if ((fhpibdebug & FDB_FAIL) &&
    555   1.1       cgd 		    doppollint && (stat0 & IM_PPRESP) == 0)
    556  1.13  christos 			printf("%s: fhpibintr: bad intr reg %x\n",
    557  1.14   thorpej 			    sc->sc_dev.dv_xname, stat0);
    558   1.1       cgd #endif
    559   1.1       cgd 		hd->hpib_stat = 0;
    560   1.1       cgd 		hd->hpib_imask = 0;
    561   1.1       cgd #ifdef DEBUG
    562  1.14   thorpej 		stat0 = fhpibppoll(hs);
    563   1.1       cgd 		if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit)
    564  1.13  christos 			printf("fhpibintr: got PPOLL status %x\n", stat0);
    565  1.14   thorpej 		if ((stat0 & (0x80 >> hq->hq_slave)) == 0) {
    566   1.4   mycroft 			/*
    567   1.4   mycroft 			 * XXX give it another shot (68040)
    568   1.4   mycroft 			 */
    569  1.14   thorpej 			/* fhpibppollfail[unit]++;	XXX */
    570   1.4   mycroft 			DELAY(fhpibppolldelay);
    571  1.14   thorpej 			stat0 = fhpibppoll(hs);
    572  1.14   thorpej 			if ((stat0 & (0x80 >> hq->hq_slave)) == 0 &&
    573   1.4   mycroft 			    (fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit)
    574  1.13  christos 				printf("fhpibintr: PPOLL: unit %d slave %d stat %x\n",
    575   1.4   mycroft 				       unit, dq->dq_slave, stat0);
    576   1.1       cgd 		}
    577   1.1       cgd #endif
    578   1.1       cgd 		hs->sc_flags &= ~HPIBF_PPOLL;
    579  1.14   thorpej 		(hq->hq_intr)(hq->hq_softc);
    580   1.1       cgd 	}
    581   1.1       cgd 	return(1);
    582   1.1       cgd }
    583   1.1       cgd 
    584   1.7   thorpej int
    585  1.14   thorpej fhpibppoll(hs)
    586  1.14   thorpej 	struct hpibbus_softc *hs;
    587   1.1       cgd {
    588  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    589  1.14   thorpej 	register struct fhpibdevice *hd = sc->sc_regs;
    590   1.1       cgd 	register int ppoll;
    591   1.1       cgd 
    592   1.1       cgd 	hd->hpib_stat = 0;
    593   1.1       cgd 	hd->hpib_psense = 0;
    594   1.1       cgd 	hd->hpib_pmask = 0xFF;
    595   1.1       cgd 	hd->hpib_imask = IM_PPRESP | IM_PABORT;
    596   1.1       cgd 	DELAY(25);
    597   1.1       cgd 	hd->hpib_intr = IM_PABORT;
    598   1.1       cgd 	ppoll = hd->hpib_data;
    599   1.1       cgd 	if (hd->hpib_intr & IM_PABORT)
    600   1.1       cgd 		ppoll = 0;
    601   1.1       cgd 	hd->hpib_imask = 0;
    602   1.1       cgd 	hd->hpib_pmask = 0;
    603   1.1       cgd 	hd->hpib_stat = ST_IENAB;
    604   1.1       cgd 	return(ppoll);
    605   1.1       cgd }
    606   1.1       cgd 
    607   1.7   thorpej int
    608   1.1       cgd fhpibwait(hd, x)
    609   1.1       cgd 	register struct fhpibdevice *hd;
    610   1.4   mycroft 	int x;
    611   1.1       cgd {
    612   1.1       cgd 	register int timo = hpibtimeout;
    613   1.1       cgd 
    614   1.1       cgd 	while ((hd->hpib_intr & x) == 0 && --timo)
    615  1.11   thorpej 		DELAY(1);
    616   1.1       cgd 	if (timo == 0) {
    617   1.1       cgd #ifdef DEBUG
    618   1.1       cgd 		if (fhpibdebug & FDB_FAIL)
    619  1.13  christos 			printf("fhpibwait(%x, %x) timeout\n", hd, x);
    620   1.1       cgd #endif
    621   1.1       cgd 		return(-1);
    622   1.1       cgd 	}
    623   1.1       cgd 	return(0);
    624   1.1       cgd }
    625   1.1       cgd 
    626   1.1       cgd /*
    627   1.4   mycroft  * XXX: this will have to change if we ever allow more than one
    628   1.1       cgd  * pending operation per HP-IB.
    629   1.1       cgd  */
    630   1.4   mycroft void
    631   1.3   mycroft fhpibppwatch(arg)
    632   1.3   mycroft 	void *arg;
    633   1.1       cgd {
    634  1.14   thorpej 	register struct hpibbus_softc *hs = arg;
    635  1.14   thorpej 	struct fhpib_softc *sc = (struct fhpib_softc *)hs->sc_dev.dv_parent;
    636  1.14   thorpej 	register struct fhpibdevice *hd = sc->sc_regs;
    637   1.1       cgd 	register int slave;
    638   1.1       cgd 
    639   1.1       cgd 	if ((hs->sc_flags & HPIBF_PPOLL) == 0)
    640   1.1       cgd 		return;
    641  1.14   thorpej 	slave = (0x80 >> hs->sc_queue.tqh_first->hq_slave);
    642   1.1       cgd #ifdef DEBUG
    643   1.1       cgd 	if (!doppollint) {
    644  1.14   thorpej 		if (fhpibppoll(hs) & slave) {
    645   1.1       cgd 			hd->hpib_stat = ST_IENAB;
    646   1.1       cgd 			hd->hpib_imask = IM_IDLE | IM_ROOM;
    647   1.1       cgd 		} else
    648  1.14   thorpej 			timeout(fhpibppwatch, sc, 1);
    649   1.1       cgd 		return;
    650   1.1       cgd 	}
    651  1.14   thorpej 	if ((fhpibdebug & FDB_PPOLL) && sc->sc_dev.dv_unit == fhpibdebugunit)
    652  1.14   thorpej 		printf("fhpibppwatch: sense request on %s\n",
    653  1.14   thorpej 		    sc->sc_dev.dv_xname);
    654   1.1       cgd #endif
    655   1.1       cgd 	hd->hpib_psense = ~slave;
    656   1.1       cgd 	hd->hpib_pmask = slave;
    657   1.1       cgd 	hd->hpib_stat = ST_IENAB;
    658   1.1       cgd 	hd->hpib_imask = IM_PPRESP | IM_PABORT;
    659   1.1       cgd 	hd->hpib_ie = IDS_IE;
    660   1.1       cgd }
    661