Home | History | Annotate | Line # | Download | only in dev
nhpib.c revision 1.27
      1  1.27  gmcgarry /*	$NetBSD: nhpib.c,v 1.27 2003/05/24 06:21:22 gmcgarry Exp $	*/
      2  1.18   thorpej 
      3  1.18   thorpej /*-
      4  1.18   thorpej  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
      5  1.18   thorpej  * All rights reserved.
      6  1.18   thorpej  *
      7  1.18   thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8  1.18   thorpej  * by Jason R. Thorpe.
      9  1.18   thorpej  *
     10  1.18   thorpej  * Redistribution and use in source and binary forms, with or without
     11  1.18   thorpej  * modification, are permitted provided that the following conditions
     12  1.18   thorpej  * are met:
     13  1.18   thorpej  * 1. Redistributions of source code must retain the above copyright
     14  1.18   thorpej  *    notice, this list of conditions and the following disclaimer.
     15  1.18   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.18   thorpej  *    notice, this list of conditions and the following disclaimer in the
     17  1.18   thorpej  *    documentation and/or other materials provided with the distribution.
     18  1.18   thorpej  * 3. All advertising materials mentioning features or use of this software
     19  1.18   thorpej  *    must display the following acknowledgement:
     20  1.18   thorpej  *	This product includes software developed by the NetBSD
     21  1.18   thorpej  *	Foundation, Inc. and its contributors.
     22  1.18   thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.18   thorpej  *    contributors may be used to endorse or promote products derived
     24  1.18   thorpej  *    from this software without specific prior written permission.
     25  1.18   thorpej  *
     26  1.18   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.18   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.18   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.18   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.18   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.18   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.18   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.18   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.18   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.18   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.18   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     37  1.18   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  *	@(#)nhpib.c	8.2 (Berkeley) 1/12/94
     72   1.1       cgd  */
     73   1.1       cgd 
     74   1.1       cgd /*
     75   1.1       cgd  * Internal/98624 HPIB driver
     76   1.1       cgd  */
     77  1.24  gmcgarry 
     78  1.24  gmcgarry #include <sys/cdefs.h>
     79  1.27  gmcgarry __KERNEL_RCSID(0, "$NetBSD: nhpib.c,v 1.27 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.22   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.27  gmcgarry #include <machine/bus.h>
     89  1.14   thorpej 
     90  1.27  gmcgarry #include <hp300/dev/intiovar.h>
     91  1.14   thorpej #include <hp300/dev/diovar.h>
     92  1.14   thorpej #include <hp300/dev/diodevs.h>
     93  1.14   thorpej #include <hp300/dev/dmavar.h>
     94   1.4   mycroft 
     95   1.4   mycroft #include <hp300/dev/nhpibreg.h>
     96   1.4   mycroft #include <hp300/dev/hpibvar.h>
     97   1.1       cgd 
     98   1.6   mycroft /*
     99   1.6   mycroft  * ODD parity table for listen and talk addresses and secondary commands.
    100   1.6   mycroft  * The TI9914A doesn't produce the parity bit.
    101   1.6   mycroft  */
    102   1.6   mycroft static u_char listnr_par[] = {
    103   1.6   mycroft 	0040,0241,0242,0043,0244,0045,0046,0247,
    104   1.6   mycroft 	0250,0051,0052,0253,0054,0255,0256,0057,
    105   1.6   mycroft 	0260,0061,0062,0263,0064,0265,0266,0067,
    106   1.6   mycroft 	0070,0271,0272,0073,0274,0075,0076,0277,
    107   1.6   mycroft };
    108   1.6   mycroft static u_char talker_par[] = {
    109   1.6   mycroft 	0100,0301,0302,0103,0304,0105,0106,0307,
    110   1.6   mycroft 	0310,0111,0112,0313,0114,0315,0316,0117,
    111   1.6   mycroft 	0320,0121,0122,0323,0124,0325,0326,0127,
    112   1.6   mycroft 	0130,0331,0332,0133,0334,0135,0136,0337,
    113   1.6   mycroft };
    114   1.6   mycroft static u_char sec_par[] = {
    115   1.6   mycroft 	0340,0141,0142,0343,0144,0345,0346,0147,
    116   1.6   mycroft 	0150,0351,0352,0153,0354,0155,0156,0357,
    117   1.6   mycroft 	0160,0361,0362,0163,0364,0165,0166,0367,
    118   1.6   mycroft 	0370,0171,0172,0373,0174,0375,0376,0177
    119   1.6   mycroft };
    120   1.6   mycroft 
    121  1.14   thorpej void	nhpibifc __P((struct nhpibdevice *));
    122  1.14   thorpej void	nhpibreadtimo __P((void *));
    123  1.14   thorpej int	nhpibwait __P((struct nhpibdevice *, int));
    124  1.14   thorpej 
    125  1.14   thorpej void	nhpibreset __P((struct hpibbus_softc *));
    126  1.14   thorpej int	nhpibsend __P((struct hpibbus_softc *, int, int, void *, int));
    127  1.14   thorpej int	nhpibrecv __P((struct hpibbus_softc *, int, int, void *, int));
    128  1.14   thorpej int	nhpibppoll __P((struct hpibbus_softc *));
    129   1.7   thorpej void	nhpibppwatch __P((void *));
    130  1.14   thorpej void	nhpibgo __P((struct hpibbus_softc *, int, int, void *, int, int, int));
    131  1.14   thorpej void	nhpibdone __P((struct hpibbus_softc *));
    132   1.9   thorpej int	nhpibintr __P((void *));
    133   1.7   thorpej 
    134   1.7   thorpej /*
    135   1.7   thorpej  * Our controller ops structure.
    136   1.7   thorpej  */
    137   1.7   thorpej struct	hpib_controller nhpib_controller = {
    138   1.7   thorpej 	nhpibreset,
    139   1.7   thorpej 	nhpibsend,
    140   1.7   thorpej 	nhpibrecv,
    141   1.7   thorpej 	nhpibppoll,
    142   1.7   thorpej 	nhpibppwatch,
    143   1.7   thorpej 	nhpibgo,
    144   1.7   thorpej 	nhpibdone,
    145   1.7   thorpej 	nhpibintr
    146   1.7   thorpej };
    147   1.7   thorpej 
    148  1.14   thorpej struct nhpib_softc {
    149  1.14   thorpej 	struct device sc_dev;		/* generic device glue */
    150  1.27  gmcgarry 
    151  1.27  gmcgarry 	bus_space_tag_t sc_bst;
    152  1.27  gmcgarry 	bus_space_handle_t sc_bsh;
    153  1.27  gmcgarry 
    154  1.14   thorpej 	struct nhpibdevice *sc_regs;	/* device registers */
    155  1.14   thorpej 	struct hpibbus_softc *sc_hpibbus; /* XXX */
    156  1.27  gmcgarry 
    157  1.27  gmcgarry 	int sc_myaddr;
    158  1.27  gmcgarry 	int sc_type;
    159  1.27  gmcgarry 
    160  1.22   thorpej 	struct callout sc_read_ch;
    161  1.22   thorpej 	struct callout sc_ppwatch_ch;
    162  1.14   thorpej };
    163  1.14   thorpej 
    164  1.27  gmcgarry int	nhpib_dio_match __P((struct device *, struct cfdata *, void *));
    165  1.27  gmcgarry void	nhpib_dio_attach __P((struct device *, struct device *, void *));
    166  1.27  gmcgarry int	nhpib_intio_match __P((struct device *, struct cfdata *, void *));
    167  1.27  gmcgarry void	nhpib_intio_attach __P((struct device *, struct device *, void *));
    168  1.27  gmcgarry 
    169  1.27  gmcgarry void	nhpib_common_attach(struct nhpib_softc *, const char *);
    170  1.27  gmcgarry 
    171  1.27  gmcgarry CFATTACH_DECL(nhpib_dio, sizeof(struct nhpib_softc),
    172  1.27  gmcgarry     nhpib_dio_match, nhpib_dio_attach, NULL, NULL);
    173  1.27  gmcgarry 
    174  1.27  gmcgarry CFATTACH_DECL(nhpib_intio, sizeof(struct nhpib_softc),
    175  1.27  gmcgarry     nhpib_intio_match, nhpib_intio_attach, NULL, NULL);
    176  1.27  gmcgarry 
    177  1.27  gmcgarry int
    178  1.27  gmcgarry nhpib_intio_match(parent, match, aux)
    179  1.27  gmcgarry 	struct device *parent;
    180  1.27  gmcgarry 	struct cfdata *match;
    181  1.27  gmcgarry 	void *aux;
    182  1.27  gmcgarry {
    183  1.27  gmcgarry 	struct intio_attach_args *ia = aux;
    184  1.27  gmcgarry 
    185  1.27  gmcgarry 	if (strcmp("hpib", ia->ia_modname) == 0)
    186  1.27  gmcgarry 		return (1);
    187  1.14   thorpej 
    188  1.27  gmcgarry 	return (0);
    189  1.27  gmcgarry }
    190  1.14   thorpej 
    191   1.7   thorpej int
    192  1.27  gmcgarry nhpib_dio_match(parent, match, aux)
    193  1.14   thorpej 	struct device *parent;
    194  1.14   thorpej 	struct cfdata *match;
    195  1.14   thorpej 	void *aux;
    196   1.1       cgd {
    197  1.14   thorpej 	struct dio_attach_args *da = aux;
    198   1.1       cgd 
    199  1.27  gmcgarry 	if (da->da_id == DIO_DEVICE_ID_NHPIB)
    200   1.8   thorpej 		return (1);
    201   1.8   thorpej 
    202  1.14   thorpej 	return (0);
    203   1.8   thorpej }
    204   1.8   thorpej 
    205   1.8   thorpej void
    206  1.27  gmcgarry nhpib_intio_attach(parent, self, aux)
    207  1.27  gmcgarry 	struct device *parent, *self;
    208  1.27  gmcgarry 	void *aux;
    209  1.27  gmcgarry {
    210  1.27  gmcgarry 	struct nhpib_softc *sc = (struct nhpib_softc *)self;
    211  1.27  gmcgarry 	struct intio_attach_args *ia = aux;
    212  1.27  gmcgarry 	const char *desc = "internal HP-IB";
    213  1.27  gmcgarry 
    214  1.27  gmcgarry 	sc->sc_bst = ia->ia_bst;
    215  1.27  gmcgarry 	if (bus_space_map(ia->ia_bst, ia->ia_iobase, INTIO_DEVSIZE, 0,
    216  1.27  gmcgarry 	    &sc->sc_bsh)) {
    217  1.27  gmcgarry 		printf(": can't map registers\n");
    218  1.27  gmcgarry 		return;
    219  1.27  gmcgarry 	}
    220  1.27  gmcgarry 
    221  1.27  gmcgarry 	sc->sc_myaddr = HPIBA_BA;
    222  1.27  gmcgarry 	sc->sc_type = HPIBA;
    223  1.27  gmcgarry 
    224  1.27  gmcgarry 	nhpib_common_attach(sc, desc);
    225  1.27  gmcgarry 
    226  1.27  gmcgarry 	/* establish the interrupt handler */
    227  1.27  gmcgarry 	(void) intio_intr_establish(nhpibintr, sc, ia->ia_ipl, IPL_BIO);
    228  1.27  gmcgarry }
    229  1.27  gmcgarry 
    230  1.27  gmcgarry void
    231  1.27  gmcgarry nhpib_dio_attach(parent, self, aux)
    232  1.14   thorpej 	struct device *parent, *self;
    233  1.14   thorpej 	void *aux;
    234  1.14   thorpej {
    235  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)self;
    236  1.14   thorpej 	struct dio_attach_args *da = aux;
    237  1.27  gmcgarry 	const char *desc = DIO_DEVICE_DESC_NHPIB;
    238  1.14   thorpej 
    239  1.27  gmcgarry 	sc->sc_bst = da->da_bst;
    240  1.27  gmcgarry 	if (bus_space_map(sc->sc_bst, da->da_addr, da->da_size, 0,
    241  1.27  gmcgarry 	    &sc->sc_bsh)) {
    242  1.27  gmcgarry 		printf(": can't map registers\n");
    243  1.14   thorpej 		return;
    244  1.14   thorpej 	}
    245   1.8   thorpej 
    246  1.27  gmcgarry 	/* read address off switches */
    247  1.27  gmcgarry 	sc->sc_myaddr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 5);
    248  1.27  gmcgarry 	sc->sc_type = HPIBB;
    249  1.27  gmcgarry 
    250  1.27  gmcgarry 	nhpib_common_attach(sc, desc);
    251  1.27  gmcgarry 
    252  1.27  gmcgarry 	/* establish the interrupt handler */
    253  1.27  gmcgarry 	(void)dio_intr_establish(nhpibintr, sc, da->da_ipl, IPL_BIO);
    254  1.27  gmcgarry }
    255   1.8   thorpej 
    256  1.27  gmcgarry void
    257  1.27  gmcgarry nhpib_common_attach(sc, desc)
    258  1.27  gmcgarry 	struct nhpib_softc *sc;
    259  1.27  gmcgarry 	const char *desc;
    260  1.27  gmcgarry {
    261  1.27  gmcgarry 	struct hpibdev_attach_args ha;
    262  1.14   thorpej 
    263  1.27  gmcgarry 	printf(": %s\n", desc);
    264  1.14   thorpej 
    265  1.27  gmcgarry 	sc->sc_regs = (struct nhpibdevice *)bus_space_vaddr(sc->sc_bst,
    266  1.27  gmcgarry 	    sc->sc_bsh);
    267  1.14   thorpej 
    268  1.22   thorpej 	callout_init(&sc->sc_read_ch);
    269  1.22   thorpej 	callout_init(&sc->sc_ppwatch_ch);
    270  1.22   thorpej 
    271  1.14   thorpej 	ha.ha_ops = &nhpib_controller;
    272  1.27  gmcgarry 	ha.ha_type = sc->sc_type;			/* XXX */
    273  1.27  gmcgarry 	ha.ha_ba = sc->sc_myaddr;
    274  1.27  gmcgarry 	ha.ha_softcpp = &sc->sc_hpibbus;		/* XXX */
    275  1.27  gmcgarry 	(void)config_found((void *)sc, &ha, hpibdevprint);
    276   1.1       cgd }
    277   1.1       cgd 
    278   1.7   thorpej void
    279  1.14   thorpej nhpibreset(hs)
    280  1.14   thorpej 	struct hpibbus_softc *hs;
    281   1.1       cgd {
    282  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    283  1.14   thorpej 	struct nhpibdevice *hd = sc->sc_regs;
    284   1.1       cgd 
    285   1.1       cgd 	hd->hpib_acr = AUX_SSWRST;
    286   1.1       cgd 	hd->hpib_ar = hs->sc_ba;
    287   1.1       cgd 	hd->hpib_lim = LIS_ERR;
    288   1.1       cgd 	hd->hpib_mim = 0;
    289   1.1       cgd 	hd->hpib_acr = AUX_CDAI;
    290   1.1       cgd 	hd->hpib_acr = AUX_CSHDW;
    291   1.1       cgd 	hd->hpib_acr = AUX_SSTD1;
    292   1.1       cgd 	hd->hpib_acr = AUX_SVSTD1;
    293   1.1       cgd 	hd->hpib_acr = AUX_CPP;
    294   1.1       cgd 	hd->hpib_acr = AUX_CHDFA;
    295   1.1       cgd 	hd->hpib_acr = AUX_CHDFE;
    296   1.1       cgd 	hd->hpib_acr = AUX_RHDF;
    297   1.1       cgd 	hd->hpib_acr = AUX_CSWRST;
    298   1.1       cgd 	nhpibifc(hd);
    299   1.1       cgd 	hd->hpib_ie = IDS_IE;
    300   1.6   mycroft 	hd->hpib_data = C_DCL_P;
    301   1.1       cgd 	DELAY(100000);
    302   1.1       cgd }
    303   1.1       cgd 
    304  1.14   thorpej void
    305   1.1       cgd nhpibifc(hd)
    306  1.15    scottr 	struct nhpibdevice *hd;
    307   1.1       cgd {
    308   1.1       cgd 	hd->hpib_acr = AUX_TCA;
    309   1.1       cgd 	hd->hpib_acr = AUX_CSRE;
    310   1.1       cgd 	hd->hpib_acr = AUX_SSIC;
    311   1.1       cgd 	DELAY(100);
    312   1.1       cgd 	hd->hpib_acr = AUX_CSIC;
    313   1.1       cgd 	hd->hpib_acr = AUX_SSRE;
    314   1.1       cgd }
    315   1.1       cgd 
    316   1.7   thorpej int
    317  1.14   thorpej nhpibsend(hs, slave, sec, ptr, origcnt)
    318  1.14   thorpej 	struct hpibbus_softc *hs;
    319  1.14   thorpej 	int slave, sec, origcnt;
    320   1.7   thorpej 	void *ptr;
    321   1.1       cgd {
    322  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    323  1.14   thorpej 	struct nhpibdevice *hd = sc->sc_regs;
    324  1.14   thorpej 	int cnt = origcnt;
    325   1.7   thorpej 	char *addr = ptr;
    326   1.1       cgd 
    327   1.1       cgd 	hd->hpib_acr = AUX_TCA;
    328   1.6   mycroft 	hd->hpib_data = C_UNL_P;
    329   1.1       cgd 	if (nhpibwait(hd, MIS_BO))
    330   1.1       cgd 		goto senderror;
    331   1.6   mycroft 	hd->hpib_data = talker_par[hs->sc_ba];
    332   1.1       cgd 	hd->hpib_acr = AUX_STON;
    333   1.1       cgd 	if (nhpibwait(hd, MIS_BO))
    334   1.1       cgd 		goto senderror;
    335   1.6   mycroft 	hd->hpib_data = listnr_par[slave];
    336   1.1       cgd 	if (nhpibwait(hd, MIS_BO))
    337   1.1       cgd 		goto senderror;
    338   1.6   mycroft 	if (sec >= 0 || sec == -2) {
    339   1.6   mycroft 		if (sec == -2)		/* selected device clear KLUDGE */
    340   1.6   mycroft 			hd->hpib_data = C_SDC_P;
    341   1.6   mycroft 		else
    342   1.6   mycroft 			hd->hpib_data = sec_par[sec];
    343   1.1       cgd 		if (nhpibwait(hd, MIS_BO))
    344   1.1       cgd 			goto senderror;
    345   1.1       cgd 	}
    346   1.1       cgd 	hd->hpib_acr = AUX_GTS;
    347   1.1       cgd 	if (cnt) {
    348   1.1       cgd 		while (--cnt > 0) {
    349   1.1       cgd 			hd->hpib_data = *addr++;
    350   1.1       cgd 			if (nhpibwait(hd, MIS_BO))
    351   1.1       cgd 				goto senderror;
    352   1.1       cgd 		}
    353   1.1       cgd 		hd->hpib_acr = AUX_EOI;
    354   1.1       cgd 		hd->hpib_data = *addr;
    355   1.1       cgd 		if (nhpibwait(hd, MIS_BO))
    356   1.1       cgd 			goto senderror;
    357   1.1       cgd 		hd->hpib_acr = AUX_TCA;
    358   1.1       cgd #if 0
    359   1.1       cgd 		/*
    360   1.1       cgd 		 * May be causing 345 disks to hang due to interference
    361   1.1       cgd 		 * with PPOLL mechanism.
    362   1.1       cgd 		 */
    363   1.6   mycroft 		hd->hpib_data = C_UNL_P;
    364   1.1       cgd 		(void) nhpibwait(hd, MIS_BO);
    365   1.1       cgd #endif
    366   1.1       cgd 	}
    367   1.1       cgd 	return(origcnt);
    368   1.6   mycroft 
    369   1.1       cgd senderror:
    370   1.1       cgd 	nhpibifc(hd);
    371   1.1       cgd 	return(origcnt - cnt - 1);
    372   1.1       cgd }
    373   1.1       cgd 
    374   1.7   thorpej int
    375  1.14   thorpej nhpibrecv(hs, slave, sec, ptr, origcnt)
    376  1.14   thorpej 	struct hpibbus_softc *hs;
    377  1.14   thorpej 	int slave, sec, origcnt;
    378   1.7   thorpej 	void *ptr;
    379   1.1       cgd {
    380  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    381  1.14   thorpej 	struct nhpibdevice *hd = sc->sc_regs;
    382  1.14   thorpej 	int cnt = origcnt;
    383   1.7   thorpej 	char *addr = ptr;
    384   1.1       cgd 
    385   1.6   mycroft 	/*
    386   1.6   mycroft 	 * Slave < 0 implies continuation of a previous receive
    387   1.6   mycroft 	 * that probably timed out.
    388   1.6   mycroft 	 */
    389   1.6   mycroft 	if (slave >= 0) {
    390   1.6   mycroft 		hd->hpib_acr = AUX_TCA;
    391   1.6   mycroft 		hd->hpib_data = C_UNL_P;
    392   1.6   mycroft 		if (nhpibwait(hd, MIS_BO))
    393   1.6   mycroft 			goto recverror;
    394   1.6   mycroft 		hd->hpib_data = listnr_par[hs->sc_ba];
    395   1.6   mycroft 		hd->hpib_acr = AUX_SLON;
    396   1.6   mycroft 		if (nhpibwait(hd, MIS_BO))
    397   1.6   mycroft 			goto recverror;
    398   1.6   mycroft 		hd->hpib_data = talker_par[slave];
    399   1.1       cgd 		if (nhpibwait(hd, MIS_BO))
    400   1.1       cgd 			goto recverror;
    401   1.6   mycroft 		if (sec >= 0) {
    402   1.6   mycroft 			hd->hpib_data = sec_par[sec];
    403   1.6   mycroft 			if (nhpibwait(hd, MIS_BO))
    404   1.6   mycroft 				goto recverror;
    405   1.6   mycroft 		}
    406   1.6   mycroft 		hd->hpib_acr = AUX_RHDF;
    407   1.6   mycroft 		hd->hpib_acr = AUX_GTS;
    408   1.1       cgd 	}
    409   1.1       cgd 	if (cnt) {
    410   1.1       cgd 		while (--cnt >= 0) {
    411   1.1       cgd 			if (nhpibwait(hd, MIS_BI))
    412   1.1       cgd 				goto recvbyteserror;
    413   1.1       cgd 			*addr++ = hd->hpib_data;
    414   1.1       cgd 		}
    415   1.1       cgd 		hd->hpib_acr = AUX_TCA;
    416   1.6   mycroft 		hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P;
    417   1.1       cgd 		(void) nhpibwait(hd, MIS_BO);
    418   1.1       cgd 	}
    419   1.1       cgd 	return(origcnt);
    420   1.6   mycroft 
    421   1.1       cgd recverror:
    422   1.1       cgd 	nhpibifc(hd);
    423   1.1       cgd recvbyteserror:
    424   1.1       cgd 	return(origcnt - cnt - 1);
    425   1.1       cgd }
    426   1.1       cgd 
    427   1.7   thorpej void
    428  1.14   thorpej nhpibgo(hs, slave, sec, ptr, count, rw, timo)
    429  1.14   thorpej 	struct hpibbus_softc *hs;
    430  1.14   thorpej 	int slave, sec, count, rw, timo;
    431   1.7   thorpej 	void *ptr;
    432   1.1       cgd {
    433  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    434  1.14   thorpej 	struct nhpibdevice *hd = sc->sc_regs;
    435   1.7   thorpej 	char *addr = ptr;
    436   1.1       cgd 
    437   1.1       cgd 	hs->sc_flags |= HPIBF_IO;
    438   1.6   mycroft 	if (timo)
    439   1.6   mycroft 		hs->sc_flags |= HPIBF_TIMO;
    440   1.1       cgd 	if (rw == B_READ)
    441   1.1       cgd 		hs->sc_flags |= HPIBF_READ;
    442   1.1       cgd #ifdef DEBUG
    443   1.1       cgd 	else if (hs->sc_flags & HPIBF_READ) {
    444  1.13  christos 		printf("nhpibgo: HPIBF_READ still set\n");
    445   1.1       cgd 		hs->sc_flags &= ~HPIBF_READ;
    446   1.1       cgd 	}
    447   1.1       cgd #endif
    448   1.1       cgd 	hs->sc_count = count;
    449   1.1       cgd 	hs->sc_addr = addr;
    450   1.1       cgd 	if (hs->sc_flags & HPIBF_READ) {
    451   1.1       cgd 		hs->sc_curcnt = count;
    452  1.14   thorpej 		dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE|DMAGO_READ);
    453  1.14   thorpej 		nhpibrecv(hs, slave, sec, 0, 0);
    454   1.1       cgd 		hd->hpib_mim = MIS_END;
    455   1.1       cgd 	} else {
    456   1.1       cgd 		hd->hpib_mim = 0;
    457   1.1       cgd 		if (count < hpibdmathresh) {
    458   1.1       cgd 			hs->sc_curcnt = count;
    459  1.14   thorpej 			nhpibsend(hs, slave, sec, addr, count);
    460  1.14   thorpej 			nhpibdone(hs);
    461   1.1       cgd 			return;
    462   1.1       cgd 		}
    463   1.1       cgd 		hs->sc_curcnt = --count;
    464  1.14   thorpej 		dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE);
    465  1.14   thorpej 		nhpibsend(hs, slave, sec, 0, 0);
    466   1.1       cgd 	}
    467  1.14   thorpej 	hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq->dq_chan);
    468   1.1       cgd }
    469   1.1       cgd 
    470   1.6   mycroft /*
    471   1.6   mycroft  * This timeout can only happen if a DMA read finishes DMAing with the read
    472   1.6   mycroft  * still pending (more data in read transaction than the driver was prepared
    473   1.6   mycroft  * to accept).  At the moment, variable-record tape drives are the only things
    474   1.6   mycroft  * capabale of doing this.  We repeat the necessary code from nhpibintr() -
    475   1.6   mycroft  * easier and quicker than calling nhpibintr() for this special case.
    476   1.6   mycroft  */
    477   1.6   mycroft void
    478   1.6   mycroft nhpibreadtimo(arg)
    479   1.6   mycroft 	void *arg;
    480   1.6   mycroft {
    481  1.14   thorpej 	struct hpibbus_softc *hs = arg;
    482  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    483   1.6   mycroft 	int s = splbio();
    484   1.6   mycroft 
    485   1.6   mycroft 	if (hs->sc_flags & HPIBF_IO) {
    486  1.15    scottr 		struct nhpibdevice *hd = sc->sc_regs;
    487  1.15    scottr 		struct hpibqueue *hq;
    488   1.6   mycroft 
    489   1.6   mycroft 		hd->hpib_mim = 0;
    490   1.6   mycroft 		hd->hpib_acr = AUX_TCA;
    491   1.6   mycroft 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
    492  1.14   thorpej 		dmafree(hs->sc_dq);
    493  1.14   thorpej 
    494  1.14   thorpej 		hq = hs->sc_queue.tqh_first;
    495  1.14   thorpej 		(hq->hq_intr)(hq->hq_softc);
    496   1.6   mycroft 	}
    497  1.14   thorpej 	splx(s);
    498   1.6   mycroft }
    499   1.6   mycroft 
    500   1.7   thorpej void
    501  1.14   thorpej nhpibdone(hs)
    502  1.14   thorpej 	struct hpibbus_softc *hs;
    503   1.1       cgd {
    504  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    505  1.14   thorpej 	struct nhpibdevice *hd = sc->sc_regs;
    506  1.14   thorpej 	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 	hs->sc_flags |= HPIBF_DONE;
    512   1.1       cgd 	hd->hpib_ie = IDS_IE;
    513   1.6   mycroft 	if (hs->sc_flags & HPIBF_READ) {
    514   1.6   mycroft 		if ((hs->sc_flags & HPIBF_TIMO) &&
    515   1.6   mycroft 		    (hd->hpib_ids & IDS_IR) == 0)
    516  1.23   frueauf 			callout_reset(&sc->sc_read_ch, hz >> 2,
    517  1.22   thorpej 			    nhpibreadtimo, hs);
    518   1.6   mycroft 	} else {
    519   1.1       cgd 		if (hs->sc_count == 1) {
    520   1.1       cgd 			(void) nhpibwait(hd, MIS_BO);
    521   1.1       cgd 			hd->hpib_acr = AUX_EOI;
    522   1.1       cgd 			hd->hpib_data = *hs->sc_addr;
    523   1.1       cgd 			hd->hpib_mim = MIS_BO;
    524   1.1       cgd 		}
    525   1.1       cgd #ifdef DEBUG
    526   1.1       cgd 		else if (hs->sc_count)
    527   1.1       cgd 			panic("nhpibdone");
    528   1.1       cgd #endif
    529   1.1       cgd 	}
    530   1.1       cgd }
    531   1.1       cgd 
    532   1.7   thorpej int
    533   1.9   thorpej nhpibintr(arg)
    534   1.9   thorpej 	void *arg;
    535   1.1       cgd {
    536  1.14   thorpej 	struct nhpib_softc *sc = arg;
    537  1.14   thorpej 	struct hpibbus_softc *hs = sc->sc_hpibbus;
    538  1.14   thorpej 	struct nhpibdevice *hd = sc->sc_regs;
    539  1.14   thorpej 	struct hpibqueue *hq;
    540  1.14   thorpej 	int stat0;
    541  1.14   thorpej 	int stat1;
    542   1.1       cgd 
    543   1.1       cgd #ifdef lint
    544   1.1       cgd 	if (stat1 = unit) return(1);
    545   1.1       cgd #endif
    546   1.1       cgd 	if ((hd->hpib_ids & IDS_IR) == 0)
    547   1.1       cgd 		return(0);
    548   1.1       cgd 	stat0 = hd->hpib_mis;
    549   1.1       cgd 	stat1 = hd->hpib_lis;
    550  1.14   thorpej 
    551  1.14   thorpej 	hq = hs->sc_queue.tqh_first;
    552  1.14   thorpej 
    553   1.1       cgd 	if (hs->sc_flags & HPIBF_IO) {
    554   1.1       cgd 		hd->hpib_mim = 0;
    555   1.6   mycroft 		if ((hs->sc_flags & HPIBF_DONE) == 0) {
    556   1.6   mycroft 			hs->sc_flags &= ~HPIBF_TIMO;
    557  1.14   thorpej 			dmastop(hs->sc_dq->dq_chan);
    558   1.6   mycroft 		} else if (hs->sc_flags & HPIBF_TIMO)
    559  1.22   thorpej 			callout_stop(&sc->sc_read_ch);
    560   1.1       cgd 		hd->hpib_acr = AUX_TCA;
    561   1.6   mycroft 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
    562  1.14   thorpej 
    563  1.14   thorpej 		dmafree(hs->sc_dq);
    564  1.14   thorpej 		(hq->hq_intr)(hq->hq_softc);
    565   1.1       cgd 	} else if (hs->sc_flags & HPIBF_PPOLL) {
    566   1.1       cgd 		hd->hpib_mim = 0;
    567  1.14   thorpej 		stat0 = nhpibppoll(hs);
    568  1.14   thorpej 		if (stat0 & (0x80 >> hq->hq_slave)) {
    569   1.1       cgd 			hs->sc_flags &= ~HPIBF_PPOLL;
    570  1.14   thorpej 			(hq->hq_intr)(hq->hq_softc);
    571   1.1       cgd 		}
    572   1.1       cgd #ifdef DEBUG
    573   1.1       cgd 		else
    574  1.13  christos 			printf("%s: PPOLL intr bad status %x\n",
    575  1.14   thorpej 			       hs->sc_dev.dv_xname, stat0);
    576   1.1       cgd #endif
    577   1.1       cgd 	}
    578   1.1       cgd 	return(1);
    579   1.1       cgd }
    580   1.1       cgd 
    581   1.7   thorpej int
    582  1.14   thorpej nhpibppoll(hs)
    583  1.14   thorpej 	struct hpibbus_softc *hs;
    584   1.1       cgd {
    585  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    586  1.14   thorpej 	struct nhpibdevice *hd = sc->sc_regs;
    587  1.14   thorpej 	int ppoll;
    588   1.1       cgd 
    589   1.1       cgd 	hd->hpib_acr = AUX_SPP;
    590   1.1       cgd 	DELAY(25);
    591   1.1       cgd 	ppoll = hd->hpib_cpt;
    592   1.1       cgd 	hd->hpib_acr = AUX_CPP;
    593   1.1       cgd 	return(ppoll);
    594   1.1       cgd }
    595   1.1       cgd 
    596   1.6   mycroft #ifdef DEBUG
    597   1.6   mycroft int nhpibreporttimo = 0;
    598   1.6   mycroft #endif
    599   1.6   mycroft 
    600   1.7   thorpej int
    601   1.1       cgd nhpibwait(hd, x)
    602  1.15    scottr 	struct nhpibdevice *hd;
    603   1.4   mycroft 	int x;
    604   1.1       cgd {
    605  1.15    scottr 	int timo = hpibtimeout;
    606   1.1       cgd 
    607   1.1       cgd 	while ((hd->hpib_mis & x) == 0 && --timo)
    608  1.11   thorpej 		DELAY(1);
    609   1.6   mycroft 	if (timo == 0) {
    610   1.6   mycroft #ifdef DEBUG
    611   1.6   mycroft 		if (nhpibreporttimo)
    612  1.13  christos 			printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN");
    613   1.6   mycroft #endif
    614   1.1       cgd 		return(-1);
    615   1.6   mycroft 	}
    616   1.1       cgd 	return(0);
    617   1.1       cgd }
    618   1.1       cgd 
    619   1.4   mycroft void
    620   1.3   mycroft nhpibppwatch(arg)
    621   1.3   mycroft 	void *arg;
    622   1.1       cgd {
    623  1.14   thorpej 	struct hpibbus_softc *hs = arg;
    624  1.14   thorpej 	struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
    625   1.1       cgd 
    626   1.1       cgd 	if ((hs->sc_flags & HPIBF_PPOLL) == 0)
    627   1.1       cgd 		return;
    628   1.4   mycroft again:
    629  1.14   thorpej 	if (nhpibppoll(hs) & (0x80 >> hs->sc_queue.tqh_first->hq_slave))
    630  1.14   thorpej        		sc->sc_regs->hpib_mim = MIS_BO;
    631   1.4   mycroft 	else if (cold)
    632   1.4   mycroft 		/* timeouts not working yet */
    633   1.4   mycroft 		goto again;
    634   1.1       cgd 	else
    635  1.22   thorpej 		callout_reset(&sc->sc_ppwatch_ch, 1, nhpibppwatch, hs);
    636   1.1       cgd }
    637