141480Smckusick /* 241480Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 341480Smckusick * All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*45788Sbostic * @(#)nhpib.c 7.3 (Berkeley) 12/16/90 841480Smckusick */ 941480Smckusick 1041480Smckusick /* 1141480Smckusick * Internal/98624 HPIB driver 1241480Smckusick */ 1341480Smckusick #include "hpib.h" 1441480Smckusick #if NHPIB > 0 1541480Smckusick 16*45788Sbostic #include "sys/param.h" 17*45788Sbostic #include "sys/systm.h" 18*45788Sbostic #include "sys/buf.h" 19*45788Sbostic 2041480Smckusick #include "device.h" 2141480Smckusick #include "nhpibreg.h" 2241480Smckusick #include "hpibvar.h" 2341480Smckusick #include "dmavar.h" 2441480Smckusick 2541480Smckusick nhpibtype(hc) 2641480Smckusick register struct hp_ctlr *hc; 2741480Smckusick { 2841480Smckusick register struct hpib_softc *hs = &hpib_softc[hc->hp_unit]; 2941480Smckusick register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr; 3041480Smckusick 3141480Smckusick if ((int)hc->hp_addr == internalhpib) { 3241480Smckusick hs->sc_type = HPIBA; 3341480Smckusick hs->sc_ba = HPIBA_BA; 3441480Smckusick hc->hp_ipl = HPIBA_IPL; 3541480Smckusick } 3641480Smckusick else if (hd->hpib_cid == HPIBB) { 3741480Smckusick hs->sc_type = HPIBB; 3841480Smckusick hs->sc_ba = hd->hpib_csa & CSA_BA; 3941480Smckusick hc->hp_ipl = HPIB_IPL(hd->hpib_ids); 4041480Smckusick } 4141480Smckusick else 4241480Smckusick return(0); 4341480Smckusick return(1); 4441480Smckusick } 4541480Smckusick 4641480Smckusick nhpibreset(unit) 4741480Smckusick { 4841480Smckusick register struct hpib_softc *hs = &hpib_softc[unit]; 4941480Smckusick register struct nhpibdevice *hd; 5041480Smckusick 5141480Smckusick hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 5241480Smckusick hd->hpib_acr = AUX_SSWRST; 5341480Smckusick hd->hpib_ar = hs->sc_ba; 5441480Smckusick hd->hpib_lim = LIS_ERR; 5541480Smckusick hd->hpib_mim = 0; 5641480Smckusick hd->hpib_acr = AUX_CDAI; 5741480Smckusick hd->hpib_acr = AUX_CSHDW; 5841480Smckusick hd->hpib_acr = AUX_SSTD1; 5941480Smckusick hd->hpib_acr = AUX_SVSTD1; 6041480Smckusick hd->hpib_acr = AUX_CPP; 6141480Smckusick hd->hpib_acr = AUX_CHDFA; 6241480Smckusick hd->hpib_acr = AUX_CHDFE; 6341480Smckusick hd->hpib_acr = AUX_RHDF; 6441480Smckusick hd->hpib_acr = AUX_CSWRST; 6541480Smckusick nhpibifc(hd); 6641480Smckusick hd->hpib_ie = IDS_IE; 6741480Smckusick hd->hpib_data = C_DCL; 6841480Smckusick DELAY(100000); 6941480Smckusick } 7041480Smckusick 7141480Smckusick nhpibifc(hd) 7241480Smckusick register struct nhpibdevice *hd; 7341480Smckusick { 7441480Smckusick hd->hpib_acr = AUX_TCA; 7541480Smckusick hd->hpib_acr = AUX_CSRE; 7641480Smckusick hd->hpib_acr = AUX_SSIC; 7741480Smckusick DELAY(100); 7841480Smckusick hd->hpib_acr = AUX_CSIC; 7941480Smckusick hd->hpib_acr = AUX_SSRE; 8041480Smckusick } 8141480Smckusick 8245511Smckusick nhpibsend(unit, slave, sec, addr, origcnt) 8341480Smckusick register char *addr; 8441480Smckusick { 8541480Smckusick register struct hpib_softc *hs = &hpib_softc[unit]; 8641480Smckusick register struct nhpibdevice *hd; 8745511Smckusick register int cnt = origcnt; 8841480Smckusick 8941480Smckusick hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 9041480Smckusick hd->hpib_acr = AUX_TCA; 9141480Smckusick hd->hpib_data = C_UNL; 9245511Smckusick if (nhpibwait(hd, MIS_BO)) 9345511Smckusick goto senderror; 9441480Smckusick hd->hpib_data = C_TAG + hs->sc_ba; 9541480Smckusick hd->hpib_acr = AUX_STON; 9645511Smckusick if (nhpibwait(hd, MIS_BO)) 9745511Smckusick goto senderror; 9841480Smckusick hd->hpib_data = C_LAG + slave; 9945511Smckusick if (nhpibwait(hd, MIS_BO)) 10045511Smckusick goto senderror; 10141480Smckusick if (sec != -1) { 10241480Smckusick hd->hpib_data = C_SCG + sec; 10345511Smckusick if (nhpibwait(hd, MIS_BO)) 10445511Smckusick goto senderror; 10541480Smckusick } 10641480Smckusick hd->hpib_acr = AUX_GTS; 10741480Smckusick if (cnt) { 10845511Smckusick while (--cnt > 0) { 10941480Smckusick hd->hpib_data = *addr++; 11045511Smckusick if (nhpibwait(hd, MIS_BO)) 11145511Smckusick goto senderror; 11241480Smckusick } 11341480Smckusick hd->hpib_acr = AUX_EOI; 11441480Smckusick hd->hpib_data = *addr; 11545511Smckusick if (nhpibwait(hd, MIS_BO)) 11645511Smckusick goto senderror; 11745511Smckusick hd->hpib_acr = AUX_TCA; 11845511Smckusick #if 0 11945511Smckusick /* 12045511Smckusick * May be causing 345 disks to hang due to interference 12145511Smckusick * with PPOLL mechanism. 12245511Smckusick */ 12345511Smckusick hd->hpib_data = C_UNL; 12445511Smckusick (void) nhpibwait(hd, MIS_BO); 12545511Smckusick #endif 12641480Smckusick } 12745511Smckusick return(origcnt); 12845511Smckusick senderror: 12945511Smckusick nhpibifc(hd); 13045511Smckusick return(origcnt - cnt - 1); 13141480Smckusick } 13241480Smckusick 13345511Smckusick nhpibrecv(unit, slave, sec, addr, origcnt) 13441480Smckusick register char *addr; 13541480Smckusick { 13641480Smckusick register struct hpib_softc *hs = &hpib_softc[unit]; 13741480Smckusick register struct nhpibdevice *hd; 13845511Smckusick register int cnt = origcnt; 13941480Smckusick 14041480Smckusick hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 14141480Smckusick hd->hpib_acr = AUX_TCA; 14241480Smckusick hd->hpib_data = C_UNL; 14345511Smckusick if (nhpibwait(hd, MIS_BO)) 14445511Smckusick goto recverror; 14541480Smckusick hd->hpib_data = C_LAG + hs->sc_ba; 14641480Smckusick hd->hpib_acr = AUX_SLON; 14745511Smckusick if (nhpibwait(hd, MIS_BO)) 14845511Smckusick goto recverror; 14941480Smckusick hd->hpib_data = C_TAG + slave; 15045511Smckusick if (nhpibwait(hd, MIS_BO)) 15145511Smckusick goto recverror; 15241480Smckusick if (sec != -1) { 15341480Smckusick hd->hpib_data = C_SCG + sec; 15445511Smckusick if (nhpibwait(hd, MIS_BO)) 15545511Smckusick goto recverror; 15641480Smckusick } 15741480Smckusick hd->hpib_acr = AUX_RHDF; 15841480Smckusick hd->hpib_acr = AUX_GTS; 15941480Smckusick if (cnt) { 16041480Smckusick while (--cnt >= 0) { 16145511Smckusick if (nhpibwait(hd, MIS_BI)) 16245511Smckusick goto recvbyteserror; 16341480Smckusick *addr++ = hd->hpib_data; 16441480Smckusick } 16541480Smckusick hd->hpib_acr = AUX_TCA; 16645511Smckusick hd->hpib_data = (slave == 31) ? C_UNA : C_UNT; 16745511Smckusick (void) nhpibwait(hd, MIS_BO); 16841480Smckusick } 16945511Smckusick return(origcnt); 17045511Smckusick recverror: 17145511Smckusick nhpibifc(hd); 17245511Smckusick recvbyteserror: 17345511Smckusick return(origcnt - cnt - 1); 17441480Smckusick } 17541480Smckusick 17641480Smckusick nhpibgo(unit, slave, sec, addr, count, rw) 17741480Smckusick register int unit, slave; 17841480Smckusick char *addr; 17941480Smckusick { 18041480Smckusick register struct hpib_softc *hs = &hpib_softc[unit]; 18141480Smckusick register struct nhpibdevice *hd; 18241480Smckusick 18341480Smckusick hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 18441480Smckusick hs->sc_flags |= HPIBF_IO; 18541480Smckusick if (rw == B_READ) 18641480Smckusick hs->sc_flags |= HPIBF_READ; 18741480Smckusick #ifdef DEBUG 18841480Smckusick else if (hs->sc_flags & HPIBF_READ) { 18941480Smckusick printf("nhpibgo: HPIBF_READ still set\n"); 19041480Smckusick hs->sc_flags &= ~HPIBF_READ; 19141480Smckusick } 19241480Smckusick #endif 19341480Smckusick hs->sc_count = count; 19441480Smckusick hs->sc_addr = addr; 19541480Smckusick if (hs->sc_flags & HPIBF_READ) { 19641480Smckusick hs->sc_curcnt = count; 19741480Smckusick dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ); 19841480Smckusick nhpibrecv(unit, slave, sec, 0, 0); 19941480Smckusick hd->hpib_mim = MIS_END; 20045511Smckusick } else { 20145511Smckusick hd->hpib_mim = 0; 20245511Smckusick if (count < hpibdmathresh) { 20345511Smckusick hs->sc_curcnt = count; 20445511Smckusick nhpibsend(unit, slave, sec, addr, count); 20545511Smckusick nhpibdone(unit); 20645511Smckusick return; 20741480Smckusick } 20845511Smckusick hs->sc_curcnt = --count; 20945511Smckusick dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE); 21045511Smckusick nhpibsend(unit, slave, sec, 0, 0); 21141480Smckusick } 21241480Smckusick hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr); 21341480Smckusick } 21441480Smckusick 21541480Smckusick nhpibdone(unit) 21641480Smckusick register int unit; 21741480Smckusick { 21841480Smckusick register struct hpib_softc *hs = &hpib_softc[unit]; 21941480Smckusick register struct nhpibdevice *hd; 22041480Smckusick register int cnt; 22141480Smckusick 22241480Smckusick hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 22341480Smckusick cnt = hs->sc_curcnt; 22441480Smckusick hs->sc_addr += cnt; 22541480Smckusick hs->sc_count -= cnt; 22645511Smckusick hs->sc_flags |= HPIBF_DONE; 22745511Smckusick hd->hpib_ie = IDS_IE; 22845511Smckusick if ((hs->sc_flags & HPIBF_READ) == 0) { 22941480Smckusick if (hs->sc_count == 1) { 23045511Smckusick (void) nhpibwait(hd, MIS_BO); 23141480Smckusick hd->hpib_acr = AUX_EOI; 23245511Smckusick hd->hpib_data = *hs->sc_addr; 23345511Smckusick hd->hpib_mim = MIS_BO; 23441480Smckusick } 23545511Smckusick #ifdef DEBUG 23645511Smckusick else if (hs->sc_count) 23745511Smckusick panic("nhpibdone"); 23845511Smckusick #endif 23941480Smckusick } 24041480Smckusick } 24141480Smckusick 24241480Smckusick nhpibintr(unit) 24341480Smckusick register int unit; 24441480Smckusick { 24541480Smckusick register struct hpib_softc *hs = &hpib_softc[unit]; 24641480Smckusick register struct nhpibdevice *hd; 24745511Smckusick register struct devqueue *dq; 24841480Smckusick register int stat0; 24941480Smckusick int stat1; 25041480Smckusick 25141480Smckusick #ifdef lint 25241480Smckusick if (stat1 = unit) return(1); 25341480Smckusick #endif 25441480Smckusick hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 25541480Smckusick if ((hd->hpib_ids & IDS_IR) == 0) 25641480Smckusick return(0); 25741480Smckusick stat0 = hd->hpib_mis; 25841480Smckusick stat1 = hd->hpib_lis; 25945511Smckusick dq = hs->sc_sq.dq_forw; 26041480Smckusick if (hs->sc_flags & HPIBF_IO) { 26141480Smckusick hd->hpib_mim = 0; 26241480Smckusick if ((hs->sc_flags & HPIBF_DONE) == 0) 26341480Smckusick dmastop(hs->sc_dq.dq_ctlr); 26441480Smckusick hd->hpib_acr = AUX_TCA; 26541480Smckusick hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ); 26641480Smckusick dmafree(&hs->sc_dq); 26741480Smckusick (dq->dq_driver->d_intr)(dq->dq_unit); 26845511Smckusick } else if (hs->sc_flags & HPIBF_PPOLL) { 26941480Smckusick hd->hpib_mim = 0; 27041480Smckusick stat0 = nhpibppoll(unit); 27141480Smckusick if (stat0 & (0x80 >> dq->dq_slave)) { 27241480Smckusick hs->sc_flags &= ~HPIBF_PPOLL; 27341480Smckusick (dq->dq_driver->d_intr)(dq->dq_unit); 27441480Smckusick } 27545511Smckusick #ifdef DEBUG 27645511Smckusick else 27745511Smckusick printf("hpib%d: PPOLL intr bad status %x\n", 27845511Smckusick unit, stat0); 27945511Smckusick #endif 28041480Smckusick } 28141480Smckusick return(1); 28241480Smckusick } 28341480Smckusick 28441480Smckusick nhpibppoll(unit) 28545511Smckusick int unit; 28641480Smckusick { 28741480Smckusick register struct nhpibdevice *hd; 28841480Smckusick register int ppoll; 28941480Smckusick 29045511Smckusick hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr; 29141480Smckusick hd->hpib_acr = AUX_SPP; 29241480Smckusick DELAY(25); 29341480Smckusick ppoll = hd->hpib_cpt; 29441480Smckusick hd->hpib_acr = AUX_CPP; 29541480Smckusick return(ppoll); 29641480Smckusick } 29741480Smckusick 29845511Smckusick nhpibwait(hd, x) 29941480Smckusick register struct nhpibdevice *hd; 30041480Smckusick { 30141480Smckusick register int timo = hpibtimeout; 30241480Smckusick 30345511Smckusick while ((hd->hpib_mis & x) == 0 && --timo) 30445511Smckusick DELAY(1); 30541480Smckusick if (timo == 0) 30641480Smckusick return(-1); 30741480Smckusick return(0); 30841480Smckusick } 30941480Smckusick 31041480Smckusick nhpibppwatch(unit) 31141480Smckusick register int unit; 31241480Smckusick { 31341480Smckusick register struct hpib_softc *hs = &hpib_softc[unit]; 31441480Smckusick 31541480Smckusick if ((hs->sc_flags & HPIBF_PPOLL) == 0) 31641480Smckusick return; 31745511Smckusick if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave)) 31841480Smckusick ((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO; 31941480Smckusick else 32041480Smckusick timeout(nhpibppwatch, unit, 1); 32141480Smckusick } 32241480Smckusick #endif 323