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