X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a0b7c7fb19b3c0f54cdd3c30d33b8c0c2348dfbe..667b32867c6dffc35ca4222282de798640f1aaf2:/usr/src/sys/vax/if/if_acc.c diff --git a/usr/src/sys/vax/if/if_acc.c b/usr/src/sys/vax/if/if_acc.c index 836c1d4631..8adb258cd6 100644 --- a/usr/src/sys/vax/if/if_acc.c +++ b/usr/src/sys/vax/if/if_acc.c @@ -1,30 +1,36 @@ -/* if_acc.c 4.2 82/02/01 */ +/* + * Copyright (c) 1982 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)if_acc.c 6.5 (Berkeley) %G% + */ #include "acc.h" -#ifdef NACC > 0 +#if NACC > 0 /* * ACC LH/DH ARPAnet IMP interface driver. */ +#include "../machine/pte.h" + +#include "param.h" +#include "systm.h" +#include "mbuf.h" +#include "buf.h" +#include "protosw.h" +#include "socket.h" +#include "vmmac.h" -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/mbuf.h" -#include "../h/pte.h" -#include "../h/buf.h" -#include "../h/protosw.h" -#include "../h/socket.h" -#include "../h/ubareg.h" -#include "../h/ubavar.h" -#include "../h/accreg.h" -#include "../h/cpu.h" -#include "../h/mtpr.h" -#include "../h/vmmac.h" -#include "../net/in.h" -#include "../net/in_systm.h" #include "../net/if.h" -#include "../net/if_imp.h" -#include "../net/if_uba.h" +#include "../netimp/if_imp.h" + +#include "../vax/cpu.h" +#include "../vax/mtpr.h" +#include "if_accreg.h" +#include "if_uba.h" +#include "../vaxuba/ubareg.h" +#include "../vaxuba/ubavar.h" int accprobe(), accattach(), accrint(), accxint(); struct uba_device *accinfo[NACC]; @@ -71,24 +77,17 @@ accprobe(reg) register int br, cvec; /* r11, r10 value-result */ register struct accdevice *addr = (struct accdevice *)reg; -COUNT(ACCPROBE); #ifdef lint br = 0; cvec = br; br = cvec; accrint(0); accxint(0); #endif - addr->acc_icsr = ACC_RESET; - DELAY(500000); - addr->acc_ocsr = ACC_RESET; - DELAY(500000); - - addr->acc_ocsr = OUT_BBACK; - DELAY(500000); - addr->acc_owc = 0; - addr->acc_ocsr = ACC_IE | ACC_GO; - DELAY(500000); - addr->acc_ocsr = 0; - /* interrupt was for transmit, push back to receive vector */ - if (cvec && cvec != 0x200) + addr->icsr = ACC_RESET; DELAY(5000); + addr->ocsr = ACC_RESET; DELAY(5000); + addr->ocsr = OUT_BBACK; DELAY(5000); + addr->owc = 0; + addr->ocsr = ACC_IE | ACC_GO; DELAY(5000); + addr->ocsr = 0; + if (cvec && cvec != 0x200) /* transmit -> receive */ cvec -= 4; return (1); } @@ -108,14 +107,17 @@ accattach(ui) struct impcb ifimp_impcb; } *ifimp; -COUNT(ACCATTACH); - if ((ifimp = (struct ifimpcb *)impattach(ui)) == 0) - panic("accattach"); /* XXX */ + if ((ifimp = (struct ifimpcb *)impattach(ui, accreset)) == 0) + panic("accattach"); sc->acc_if = &ifimp->ifimp_if; ip = &ifimp->ifimp_impcb; sc->acc_ic = ip; ip->ic_init = accinit; ip->ic_start = accstart; + sc->acc_ifuba.ifu_flags = UBA_CANTWAIT; +#ifdef notdef + sc->acc_ifuba.ifu_flags |= UBA_NEEDBDP; +#endif } /* @@ -128,71 +130,100 @@ accreset(unit, uban) register struct uba_device *ui; struct acc_softc *sc; -COUNT(ACCRESET); if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" acc%d", unit); sc = &acc_softc[unit]; + sc->acc_if->if_flags &= ~IFF_RUNNING; /* must go through IMP to allow it to set state */ (*sc->acc_if->if_init)(unit); } /* * Initialize interface: clear recorded pending operations, - * and retrieve, and reinitialize UNIBUS resources. + * and retrieve, and initialize UNIBUS resources. Note + * return value is used by IMP init routine to mark IMP + * unavailable for outgoing traffic. */ accinit(unit) int unit; { - register struct acc_softc *sc = &acc_softc[unit]; - register struct uba_device *ui = accinfo[unit]; + register struct acc_softc *sc; + register struct uba_device *ui; register struct accdevice *addr; - int x, info; + int info; -COUNT(ACCINIT); - if (if_ubainit(&sc->acc_ifuba, ui->ui_ubanum, - sizeof(struct imp_leader), (int)btop(IMP_MTU)) == 0) { + if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0) { + printf("acc%d: not alive\n", unit); + return (0); + } + sc = &acc_softc[unit]; + /* + * Header length is 0 since we have to passs + * the IMP leader up to the protocol interpretation + * routines. If we had the header length as + * sizeof(struct imp_leader), then the if_ routines + * would asssume we handle it on input and output. + */ + if (if_ubainit(&sc->acc_ifuba, ui->ui_ubanum, 0, + (int)btoc(IMPMTU)) == 0) { printf("acc%d: can't initialize\n", unit); - return; + ui->ui_alive = 0; + return (0); } + sc->acc_if->if_flags |= IFF_RUNNING; addr = (struct accdevice *)ui->ui_addr; /* - * Reset the imp interface. - * the delays are totally guesses + * Reset the imp interface; + * the delays are pure guesswork. */ - x = spl5(); - addr->acc_icsr = ACC_RESET; - DELAY(100); - addr->acc_ocsr = ACC_RESET; - DELAY(1000); - addr->acc_ocsr = OUT_BBACK; /* reset host master ready */ - DELAY(1000); - addr->acc_ocsr = 0; - addr->acc_icsr = IN_MRDY; /* close the relay */ - splx(x); - - /* YECH!!! */ - while ((addr->acc_icsr & IN_HRDY) == 0 || - (addr->acc_icsr & (IN_RMR | IN_IMPBSY))) { - /* keep turning IN_RMR off */ - addr->acc_icsr = IN_MRDY; - sleep((caddr_t)&lbolt, PZERO); /* ??? */ + addr->ocsr = ACC_RESET; DELAY(5000); + addr->ocsr = OUT_BBACK; DELAY(5000); /* reset host master ready */ + addr->ocsr = 0; + if (accinputreset(addr, unit) == 0) { + ui->ui_alive = 0; + return (0); } /* * Put up a read. We can't restart any outstanding writes * until we're back in synch with the IMP (i.e. we've flushed * the NOOPs it throws at us). + * Note: IMPMTU includes the leader. */ - x = spl5(); info = sc->acc_ifuba.ifu_r.ifrw_info; - addr->acc_iba = (u_short)info; - addr->acc_iwc = -(sizeof(struct imp_leader) + IMP_MTU) >> 1; - addr->acc_icsr = + addr->iba = (u_short)info; + addr->iwc = -(IMPMTU >> 1); +#ifdef LOOPBACK + addr->ocsr |= OUT_BBACK; +#endif + addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; - splx(x); + return (1); +} + +accinputreset(addr, unit) + register struct accdevice *addr; + register int unit; +{ + register int i; + + addr->icsr = ACC_RESET; DELAY(5000); + addr->icsr = IN_MRDY | IN_WEN; /* close the relay */ + DELAY(10000); + /* YECH!!! */ + for (i = 0; i < 500; i++) { + if ((addr->icsr & IN_HRDY) || + (addr->icsr & (IN_RMR | IN_IMPBSY)) == 0) + return (1); + addr->icsr = IN_MRDY | IN_WEN; DELAY(10000); + /* keep turning IN_RMR off */ + } + printf("acc%d: imp doesn't respond, icsr=%b\n", unit, + addr->icsr, ACC_INBITS); + return (0); } /* @@ -202,13 +233,11 @@ accstart(dev) dev_t dev; { int unit = ACCUNIT(dev), info; - struct uba_device *ui = accinfo[unit]; register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; struct mbuf *m; u_short cmd; -COUNT(ACCSTART); if (sc->acc_ic->ic_oactive) goto restart; @@ -226,16 +255,20 @@ COUNT(ACCSTART); restart: /* - * Have request mapped to UNIBUS for transmission. - * Purge any stale data from the BDP, and start the output. + * Have request mapped to UNIBUS for + * transmission; start the output. */ - UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_w.ifrw_bdp); - addr = (struct accdevice *)ui->ui_addr; + if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP) + UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_w.ifrw_bdp); + addr = (struct accdevice *)accinfo[unit]->ui_addr; info = sc->acc_ifuba.ifu_w.ifrw_info; - addr->acc_oba = (u_short)info; - addr->acc_owc = -((sc->acc_olen + 1) >> 1); + addr->oba = (u_short)info; + addr->owc = -((sc->acc_olen + 1) >> 1); cmd = ACC_IE | OUT_ENLB | ((info & 0x30000) >> 12) | ACC_GO; - addr->acc_ocsr = cmd; +#ifdef LOOPBACK + cmd |= OUT_BBACK; +#endif + addr->ocsr = cmd; sc->acc_ic->ic_oactive = 1; } @@ -243,66 +276,69 @@ restart: * Output interrupt handler. */ accxint(unit) + int unit; { - register struct uba_device *ui = accinfo[unit]; register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; -COUNT(ACCXINT); + addr = (struct accdevice *)accinfo[unit]->ui_addr; if (sc->acc_ic->ic_oactive == 0) { - printf("acc%d: stray send interrupt\n", unit); + printf("acc%d: stray xmit interrupt, csr=%b\n", unit, + addr->ocsr, ACC_OUTBITS); return; } - addr = (struct accdevice *)ui->ui_addr; sc->acc_if->if_opackets++; sc->acc_ic->ic_oactive = 0; - if (addr->acc_ocsr & ACC_ERR) { - printf("acc%d: send error, csr=%b\n", unit, - addr->acc_ocsr, ACC_OUTBITS); + if (addr->ocsr & ACC_ERR) { + printf("acc%d: output error, ocsr=%b, icsr=%b\n", unit, + addr->ocsr, ACC_OUTBITS, addr->icsr, ACC_INBITS); sc->acc_if->if_oerrors++; } - if (sc->acc_if->if_snd.ifq_head == 0) { - if (sc->acc_ifuba.ifu_xtofree) { - m_freem(sc->acc_ifuba.ifu_xtofree); - sc->acc_ifuba.ifu_xtofree = 0; - } - return; + if (sc->acc_ifuba.ifu_xtofree) { + m_freem(sc->acc_ifuba.ifu_xtofree); + sc->acc_ifuba.ifu_xtofree = 0; } - accstart(unit); + if (sc->acc_if->if_snd.ifq_head) + accstart(unit); } /* * Input interrupt handler */ accrint(unit) + int unit; { register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; - register struct ifqueue *inq; struct mbuf *m; int len, info; -COUNT(ACCRINT); + addr = (struct accdevice *)accinfo[unit]->ui_addr; sc->acc_if->if_ipackets++; /* * Purge BDP; flush message if error indicated. */ - UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_r.ifrw_bdp); - addr = (struct accdevice *)accinfo[unit]->ui_addr; - if (addr->acc_icsr & ACC_ERR) { - printf("acc%d: recv error, csr=%b\n", unit, - addr->acc_icsr, ACC_INBITS); + if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP) + UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_r.ifrw_bdp); + if (addr->icsr & ACC_ERR) { + printf("acc%d: input error, csr=%b\n", unit, + addr->icsr, ACC_INBITS); sc->acc_if->if_ierrors++; sc->acc_flush = 1; } if (sc->acc_flush) { - if (addr->acc_icsr & IN_EOM) + if (addr->icsr & IN_EOM) sc->acc_flush = 0; goto setup; } - len = sizeof(struct imp_leader) + (addr->acc_iwc << 1); + len = IMPMTU + (addr->iwc << 1); + if (len < 0 || len > IMPMTU) { + printf("acc%d: bad length=%d\n", len); + sc->acc_if->if_ierrors++; + goto setup; + } /* * The last parameter is always 0 since using @@ -311,15 +347,13 @@ COUNT(ACCRINT); m = if_rubaget(&sc->acc_ifuba, len, 0); if (m == 0) goto setup; - if ((addr->acc_icsr & IN_EOM) == 0) { + if ((addr->icsr & IN_EOM) == 0) { if (sc->acc_iq) m_cat(sc->acc_iq, m); else sc->acc_iq = m; goto setup; } - /* adjust message length for padding. */ - m->m_len -= 2; if (sc->acc_iq) { m_cat(sc->acc_iq, m); m = sc->acc_iq; @@ -332,9 +366,9 @@ setup: * Setup for next message. */ info = sc->acc_ifuba.ifu_r.ifrw_info; - addr->acc_iba = (u_short)info; - addr->acc_iwc = - (sizeof(struct imp_leader) + IMP_MTU) >> 1; - addr->acc_icsr = + addr->iba = (u_short)info; + addr->iwc = -(IMPMTU >> 1); + addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; } #endif