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