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