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