From: deraadt Date: Tue, 16 Jan 1996 01:22:20 +0000 (+0000) Subject: update from netbsd X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=2bae968b51d96702cdf37441668b0a7c890457e3;p=openbsd update from netbsd --- diff --git a/sys/arch/pmax/dev/if_le.c b/sys/arch/pmax/dev/if_le.c deleted file mode 100644 index 3b0b7f86cb5..00000000000 --- a/sys/arch/pmax/dev/if_le.c +++ /dev/null @@ -1,1386 +0,0 @@ -/* $NetBSD: if_le.c,v 1.17 1995/12/24 02:30:42 mycroft Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)if_le.c 8.2 (Berkeley) 11/16/93 - */ - -#include -#if NLE > 0 - -#include - -/* - * AMD 7990 LANCE - * - * This driver will generate and accept trailer encapsulated packets even - * though it buys us nothing. The motivation was to avoid incompatibilities - * with VAXen, SUNs, and others that handle and benefit from them. - * This reasoning is dubious. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#include -#endif - -#ifdef NS -#include -#include -#endif - -#if defined (CCITT) && defined (LLC) -#include -#include -extern llc_ctlinput(), cons_rtrequest(); -#endif - -#include - -#include -#include -#include -#include - -#include -#include - -#if NBPFILTER > 0 -#include -#include -#endif - -/* - * Autoconfiguration data for config.new. - * Use the statically-allocated softc until old autoconfig code and - * config.old are completely gone. - * - */ -int lematch __P((struct device * parent, void *cfdata, void *aux)); -void leattach __P((struct device *parent, struct device *self, void *aux)); -void leintr __P((int unit)); - -int le_doprobe __P((void *addr, int unit, int flags, int priority)); - -extern struct cfdriver lecd; -struct cfdriver lecd = { - NULL, "le", lematch, leattach, DV_IFNET, sizeof(struct device), 0 -}; - -int ledebug = 1; /* console error messages */ - -/* - * Ethernet software status per interface. - * - * Each interface is referenced by a network interface structure, - * le_if, which the routing code uses to locate the interface. - * This structure contains the output queue for the interface, its address, ... - */ -struct le_softc { - struct arpcom sc_ac; /* common Ethernet structures */ -#define sc_if sc_ac.ac_if /* network-visible interface */ -#define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */ - volatile struct lereg1 *sc_r1; /* LANCE registers */ - volatile void *sc_r2; /* dual-port RAM */ - int sc_ler2pad; /* Do ring descriptors require short pads? */ - void (*sc_copytobuf)(); /* Copy to buffer */ - void (*sc_copyfrombuf)(); /* Copy from buffer */ - void (*sc_zerobuf)(); /* and Zero bytes in buffer */ - int sc_rmd; /* predicted next rmd to process */ - int sc_tmd; /* last tmd processed */ - int sc_tmdnext; /* next tmd to transmit with */ - /* stats */ - int sc_runt; - int sc_merr; - int sc_babl; - int sc_cerr; - int sc_miss; - int sc_rown; - int sc_xint; - int sc_uflo; - int sc_rxlen; - int sc_rxoff; - int sc_txoff; - int sc_busy; - short sc_iflags; -} le_softc[NLE]; - -/* access LANCE registers */ -static void lewritereg(); -#define LERDWR(cntl, src, dst) { (dst) = (src); DELAY(10); } -#define LEWREG(src, dst) lewritereg(&(dst), (src)) - -#define CPU_TO_CHIP_ADDR(cpu) \ - ((unsigned)(&(((struct lereg2 *)0)->cpu))) - -#define LE_OFFSET_RAM 0x0 -#define LE_OFFSET_LANCE 0x100000 -#define LE_OFFSET_ROM 0x1c0000 - -void copytobuf_contig(), copyfrombuf_contig(), bzerobuf_contig(); -void copytobuf_gap2(), copyfrombuf_gap2(), bzerobuf_gap2(); -void copytobuf_gap16(), copyfrombuf_gap16(), bzerobuf_gap16(); - -extern int pmax_boardtype; -extern u_long le_iomem; -extern u_long asic_base; - -int leioctl __P((struct ifnet *, u_long, caddr_t)); -void lestart __P((struct ifnet *)); -void leinit __P((int)); -void lereset __P((int)); - -/* - * Match driver based on name - */ -int -lematch(parent, match, aux) - struct device *parent; - void *match; - void *aux; -{ - struct cfdata *cf = match; - struct confargs *ca = aux; - static int nunits = 0; - - if (!BUS_MATCHNAME(ca, "PMAD-BA ") && - !BUS_MATCHNAME(ca, "PMAD-AA ") && - !BUS_MATCHNAME(ca, "le") && - !BUS_MATCHNAME(ca, "lance")) - return (0); - /* - * Use statically-allocated softc and attach code until - * old config is completely gone. Don't over-run softc. - */ - if (nunits > NLE) { - printf("le: too many units for old config\n"); - return (0); - } - nunits++; - return(1); -} - -void -leattach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; -{ - register struct confargs *ca = aux; - - (void) le_doprobe((void*)MACH_PHYS_TO_UNCACHED(BUS_CVTADDR(ca)), - self->dv_unit, self->dv_cfdata->cf_flags, - ca->ca_slot); - - /* tie pseudo-slot to device */ - BUS_INTR_ESTABLISH(ca, leintr, self->dv_unit); - printf("\n"); -} - - -/* - * Test to see if device is present. - * Return true if found and initialized ok. - * If interface exists, make available by filling in network interface - * record. System will initialize the interface when it is ready - * to accept packets. - */ -le_doprobe(addr, unit, flags, priority) - void *addr; - int unit, flags, priority; -{ - volatile struct lereg1 *ler1; - struct le_softc *le = &le_softc[unit]; - struct ifnet *ifp = &le->sc_if; - u_char *cp; - int i; - - switch (pmax_boardtype) { - case DS_PMAX: - le->sc_r1 = ler1 = (volatile struct lereg1 *)addr; - le->sc_r2 = (volatile void *)MACH_PHYS_TO_UNCACHED(0x19000000); - cp = (u_char *)(MACH_PHYS_TO_UNCACHED(KN01_SYS_CLOCK) + 1); - le->sc_ler2pad = 1; - le->sc_copytobuf = copytobuf_gap2; - le->sc_copyfrombuf = copyfrombuf_gap2; - le->sc_zerobuf = bzerobuf_gap2; - break; - case DS_3MIN: - case DS_MAXINE: - case DS_3MAXPLUS: - if (unit == 0) { - volatile u_int *ssr, *ldp; - - le->sc_r1 = ler1 = (volatile struct lereg1 *) - ASIC_SYS_LANCE(asic_base); - cp = (u_char *)ASIC_SYS_ETHER_ADDRESS(asic_base); - le->sc_r2 = (volatile void *) - MACH_PHYS_TO_UNCACHED(le_iomem); - le->sc_ler2pad = 1; - le->sc_copytobuf = copytobuf_gap16; - le->sc_copyfrombuf = copyfrombuf_gap16; - le->sc_zerobuf = bzerobuf_gap16; - - /* - * And enable Lance dma through the asic. - */ - ssr = (volatile u_int *)ASIC_REG_CSR(asic_base); - ldp = (volatile u_int *) - ASIC_REG_LANCE_DMAPTR(asic_base); - *ldp = (le_iomem << 3); /* phys addr << 3 */ - *ssr |= ASIC_CSR_DMAEN_LANCE; - break; - } - /* - * Units other than 0 are turbochannel option boards and fall - * through to DS_3MAX. - */ - case DS_3MAX: - le->sc_r1 = ler1 = (volatile struct lereg1 *) - (addr + LE_OFFSET_LANCE); - le->sc_r2 = (volatile void *)(addr + LE_OFFSET_RAM); - cp = (u_char *)(addr + LE_OFFSET_ROM + 2); - le->sc_ler2pad = 0; - le->sc_copytobuf = copytobuf_contig; - le->sc_copyfrombuf = copyfrombuf_contig; - le->sc_zerobuf = bzerobuf_contig; - break; - default: - printf("Unknown CPU board type %d\n", pmax_boardtype); - return (0); - }; - - /* - * Get the ethernet address out of rom - */ - for (i = 0; i < sizeof(le->sc_addr); i++) { - le->sc_addr[i] = *cp; - cp += 4; - } - - /* make sure the chip is stopped */ - LEWREG(LE_CSR0, ler1->ler1_rap); - LEWREG(LE_STOP, ler1->ler1_rdp); - - ifp->if_unit = unit; - ifp->if_name = "le"; - ifp->if_ioctl = leioctl; - ifp->if_start = lestart; -#ifdef MULTICAST - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; -#else - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; -#endif -#if NBPFILTER > 0 - bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); -#endif - if_attach(ifp); - ether_ifattach(ifp); - - printf(": ethernet address %s", - ether_sprintf(le->sc_addr)); - return (1); -} - -#ifdef MULTICAST -/* - * Setup the logical address filter - */ -void -lesetladrf(le) - register struct le_softc *le; -{ - register volatile struct lereg2 *ler2 = le->sc_r2; - register struct ifnet *ifp = &le->sc_if; - register struct ether_multi *enm; - register u_char *cp; - register u_long crc; - register u_long c; - register int i, len; - struct ether_multistep step; - - /* - * Set up multicast address filter by passing all multicast - * addresses through a crc generator, and then using the high - * order 6 bits as a index into the 64 bit logical address - * filter. The high order two bits select the word, while the - * rest of the bits select the bit within the word. - */ - - LER2_ladrf0(ler2, 0); - LER2_ladrf1(ler2, 0); - ifp->if_flags &= ~IFF_ALLMULTI; - ETHER_FIRST_MULTI(step, &le->sc_ac, enm); - while (enm != NULL) { - if (bcmp((caddr_t)&enm->enm_addrlo, - (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) == 0) { - /* - * We must listen to a range of multicast - * addresses. For now, just accept all - * multicasts, rather than trying to set only - * those filter bits needed to match the range. - * (At this time, the only use of address - * ranges is for IP multicast routing, for - * which the range is big enough to require all - * bits set.) - */ - LER2_ladrf0(ler2, 0xff); - LER2_ladrf1(ler2, 0xff); - LER2_ladrf2(ler2, 0xff); - LER2_ladrf3(ler2, 0xff); - ifp->if_flags |= IFF_ALLMULTI; - return; - } - - cp = (unsigned char *)&enm->enm_addrlo; - c = *cp; - crc = 0xffffffff; - len = 6; - while (len-- > 0) { - c = *cp; - for (i = 0; i < 8; i++) { - if ((c & 0x01) ^ (crc & 0x01)) { - crc >>= 1; - crc = crc ^ 0xedb88320; - } - else - crc >>= 1; - c >>= 1; - } - cp++; - } - /* Just want the 6 most significant bits. */ - crc = crc >> 26; - - /* Turn on the corresponding bit in the filter. */ - switch (crc >> 5) { - case 0: - LER2_ladrf0(ler2, 1 << (crc & 0x1f)); - break; - case 1: - LER2_ladrf1(ler2, 1 << (crc & 0x1f)); - break; - case 2: - LER2_ladrf2(ler2, 1 << (crc & 0x1f)); - break; - case 3: - LER2_ladrf3(ler2, 1 << (crc & 0x1f)); - } - - ETHER_NEXT_MULTI(step, enm); - } -} -#endif - -ledrinit(le) - struct le_softc *le; -{ - register volatile void *rp; - register int i; - - for (i = 0; i < LERBUF; i++) { - rp = LER2_RMDADDR(le->sc_r2, i); - LER2_rmd0(rp, CPU_TO_CHIP_ADDR(ler2_rbuf[i][0])); - LER2_rmd1(rp, LE_OWN); - LER2_rmd2(rp, -LEMTU); - LER2_rmd3(rp, 0); - } - for (i = 0; i < LETBUF; i++) { - rp = LER2_TMDADDR(le->sc_r2, i); - LER2_tmd0(rp, CPU_TO_CHIP_ADDR(ler2_tbuf[i][0])); - LER2_tmd1(rp, 0); - LER2_tmd2(rp, 0); - LER2_tmd3(rp, 0); - } -} - -void -lereset(unit) - register int unit; -{ - register struct le_softc *le = &le_softc[unit]; - register volatile struct lereg1 *ler1 = le->sc_r1; - register volatile void *ler2 = le->sc_r2; - register int timo = 100000; - register int stat; - -#ifdef lint - stat = unit; -#endif - LEWREG(LE_CSR0, ler1->ler1_rap); - LEWREG(LE_STOP, ler1->ler1_rdp); - - /* - * Setup for transmit/receive - */ -#if NBPFILTER > 0 - if (le->sc_if.if_flags & IFF_PROMISC) - /* set the promiscuous bit */ - LER2_mode(ler2, LE_MODE | 0x8000); - else -#endif - LER2_mode(ler2, LE_MODE); - LER2_padr0(ler2, (le->sc_addr[1] << 8) | le->sc_addr[0]); - LER2_padr1(ler2, (le->sc_addr[3] << 8) | le->sc_addr[2]); - LER2_padr2(ler2, (le->sc_addr[5] << 8) | le->sc_addr[4]); - /* Setup the logical address filter */ -#ifdef MULTICAST - lesetladrf(le); -#else - LER2_ladrf0(ler2, 0); - LER2_ladrf1(ler2, 0); - LER2_ladrf2(ler2, 0); - LER2_ladrf3(ler2, 0); -#endif - LER2_rlen(ler2, LE_RLEN); - LER2_rdra(ler2, CPU_TO_CHIP_ADDR(ler2_rmd[0])); - LER2_tlen(ler2, LE_TLEN); - LER2_tdra(ler2, CPU_TO_CHIP_ADDR(ler2_tmd[0])); - ledrinit(le); - le->sc_rmd = 0; - le->sc_tmd = LETBUF - 1; - le->sc_tmdnext = 0; - - LEWREG(LE_CSR1, ler1->ler1_rap); - LEWREG(CPU_TO_CHIP_ADDR(ler2_mode), ler1->ler1_rdp); - LEWREG(LE_CSR2, ler1->ler1_rap); - LEWREG(0, ler1->ler1_rdp); - LEWREG(LE_CSR3, ler1->ler1_rap); - LEWREG(0, ler1->ler1_rdp); - LEWREG(LE_CSR0, ler1->ler1_rap); - LERDWR(ler0, LE_INIT, ler1->ler1_rdp); - do { - if (--timo == 0) { - printf("le%d: init timeout, stat = 0x%x\n", - unit, stat); - break; - } - stat = ler1->ler1_rdp; - } while ((stat & LE_IDON) == 0); - LERDWR(ler0, LE_IDON, ler1->ler1_rdp); - LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp); - le->sc_if.if_flags &= ~IFF_OACTIVE; -} - -/* - * Initialization of interface - */ -void -leinit(unit) - int unit; -{ - register struct ifnet *ifp = &le_softc[unit].sc_if; - register struct ifaddr *ifa; - int s; - - if ((ifp->if_flags & IFF_RUNNING) == 0) { - s = splnet(); - ifp->if_flags |= IFF_RUNNING; - lereset(unit); - lestart(ifp); - splx(s); - } -} - -#define LENEXTTMP \ - if (++bix == LETBUF) \ - bix = 0; \ - tmd = LER2_TMDADDR(le->sc_r2, bix) - -/* - * Start output on interface. Get another datagram to send - * off of the interface queue, and copy it to the interface - * before starting the output. - */ -void -lestart(ifp) - struct ifnet *ifp; -{ - register struct le_softc *le = &le_softc[ifp->if_unit]; - register int bix = le->sc_tmdnext; - register volatile void *tmd = LER2_TMDADDR(le->sc_r2, bix); - register struct mbuf *m; - int len = 0; - - if ((le->sc_if.if_flags & IFF_RUNNING) == 0) - return; - while (bix != le->sc_tmd) { - if (LER2V_tmd1(tmd) & LE_OWN) - panic("lestart"); - IF_DEQUEUE(&le->sc_if.if_snd, m); - if (m == 0) - break; -#if NBPFILTER > 0 - /* - * If bpf is listening on this interface, let it - * see the packet before we commit it to the wire. - */ - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m); -#endif - len = leput(le, LER2_TBUFADDR(le->sc_r2, bix), m); - LER2_tmd3(tmd, 0); - LER2_tmd2(tmd, -len); - LER2_tmd1(tmd, LE_OWN | LE_STP | LE_ENP); - LENEXTTMP; - } - if (len != 0) { - le->sc_if.if_flags |= IFF_OACTIVE; - LERDWR(ler0, LE_TDMD | LE_INEA, le->sc_r1->ler1_rdp); - } - le->sc_tmdnext = bix; -} - -/* - * Process interrupts from the 7990 chip. - */ -void -leintr(unit) - int unit; -{ - register struct le_softc *le; - register volatile struct lereg1 *ler1; - register int stat; - - le = &le_softc[unit]; - ler1 = le->sc_r1; - stat = ler1->ler1_rdp; - if (!stat || !(stat & LE_INTR)) { - printf("le%d: spurious interrupt\n", unit); - return; - } - if (stat & LE_SERR) { - leerror(unit, stat); - if (stat & LE_MERR) { - le->sc_merr++; - lereset(unit); - return; - } - if (stat & LE_BABL) - le->sc_babl++; - if (stat & LE_CERR) - le->sc_cerr++; - if (stat & LE_MISS) - le->sc_miss++; - LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp); - } - if ((stat & LE_RXON) == 0) { - le->sc_rxoff++; - lereset(unit); - return; - } - if ((stat & LE_TXON) == 0) { - le->sc_txoff++; - lereset(unit); - return; - } - if (stat & LE_RINT) { - /* interrupt is cleared in lerint */ - lerint(unit); - } - if (stat & LE_TINT) { - LERDWR(ler0, LE_TINT|LE_INEA, ler1->ler1_rdp); - lexint(unit); - } -} - -/* - * Ethernet interface transmitter interrupt. - * Start another output if more data to send. - */ -lexint(unit) - register int unit; -{ - register struct le_softc *le = &le_softc[unit]; - register int bix = le->sc_tmd; - register volatile void *tmd; - - if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) { - le->sc_xint++; - return; - } - LENEXTTMP; - while (bix != le->sc_tmdnext && (LER2V_tmd1(tmd) & LE_OWN) == 0) { - le->sc_tmd = bix; - if ((LER2V_tmd1(tmd) & LE_ERR) || (LER2V_tmd3(tmd) & LE_TBUFF)) { - lexerror(unit); - le->sc_if.if_oerrors++; - if (LER2V_tmd3(tmd) & (LE_TBUFF|LE_UFLO)) { - le->sc_uflo++; - lereset(unit); - break; - } - else if (LER2V_tmd3(tmd) & LE_LCOL) - le->sc_if.if_collisions++; - else if (LER2V_tmd3(tmd) & LE_RTRY) - le->sc_if.if_collisions += 16; - } - else if (LER2V_tmd1(tmd) & LE_ONE) - le->sc_if.if_collisions++; - else if (LER2V_tmd1(tmd) & LE_MORE) - /* what is the real number? */ - le->sc_if.if_collisions += 2; - else - le->sc_if.if_opackets++; - LENEXTTMP; - } - if (bix == le->sc_tmdnext) - le->sc_if.if_flags &= ~IFF_OACTIVE; - lestart(&le->sc_if); -} - -#define LENEXTRMP \ - if (++bix == LERBUF) \ - bix = 0; \ - rmd = LER2_RMDADDR(le->sc_r2, bix) - -/* - * Ethernet interface receiver interrupt. - * If input error just drop packet. - * Decapsulate packet based on type and pass to type specific - * higher-level input routine. - */ -lerint(unit) - int unit; -{ - register struct le_softc *le = &le_softc[unit]; - register int bix = le->sc_rmd; - register volatile void *rmd = LER2_RMDADDR(le->sc_r2, bix); - - /* - * Out of sync with hardware, should never happen? - */ - if (LER2V_rmd1(rmd) & LE_OWN) { - le->sc_rown++; - LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); - return; - } - - /* - * Process all buffers with valid data - */ - while ((LER2V_rmd1(rmd) & LE_OWN) == 0) { - int len = LER2V_rmd3(rmd); - - /* Clear interrupt to avoid race condition */ - LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); - - if (LER2V_rmd1(rmd) & LE_ERR) { - le->sc_rmd = bix; - lererror(unit, "bad packet"); - le->sc_if.if_ierrors++; - } else if ((LER2V_rmd1(rmd) & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { - /* - * Find the end of the packet so we can see how long - * it was. We still throw it away. - */ - do { - LERDWR(le->sc_r0, LE_RINT|LE_INEA, - le->sc_r1->ler1_rdp); - LER2_rmd3(rmd, 0); - LER2_rmd1(rmd, LE_OWN); - LENEXTRMP; - } while (!(LER2V_rmd1(rmd) & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); - le->sc_rmd = bix; - lererror(unit, "chained buffer"); - le->sc_rxlen++; - /* - * If search terminated without successful completion - * we reset the hardware (conservative). - */ - if ((LER2V_rmd1(rmd) & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != - LE_ENP) { - lereset(unit); - return; - } - } else - leread(unit, LER2_RBUFADDR(le->sc_r2, bix), len); - LER2_rmd3(rmd, 0); - LER2_rmd1(rmd, LE_OWN); - LENEXTRMP; - } - MachEmptyWriteBuffer(); /* Paranoia */ - le->sc_rmd = bix; -} - -/* - * Look at the packet in network buffer memory so we can be smart about how - * we copy the data into mbufs. - * This needs work since we can't just read network buffer memory like - * regular memory. - */ -leread(unit, buf, len) - int unit; - volatile void *buf; - int len; -{ - register struct le_softc *le = &le_softc[unit]; - struct ether_header et; - struct mbuf *m; - int off, resid, flags; - u_short sbuf[2], eth_type; - extern struct mbuf *leget(); - - le->sc_if.if_ipackets++; - (*le->sc_copyfrombuf)(buf, 0, (char *)&et, sizeof (et)); - eth_type = ntohs(et.ether_type); - /* adjust input length to account for header and CRC */ - len = len - sizeof(struct ether_header) - 4; - - if (eth_type >= ETHERTYPE_TRAIL && - eth_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { - off = (eth_type - ETHERTYPE_TRAIL) * 512; - if (off >= ETHERMTU) - return; /* sanity */ - (*le->sc_copyfrombuf)(buf, sizeof (et) + off, (char *)sbuf, - sizeof (sbuf)); - eth_type = ntohs(sbuf[0]); - resid = ntohs(sbuf[1]); - if (off + resid > len) - return; /* sanity */ - len = off + resid; - } else - off = 0; - - if (len <= 0) { - if (ledebug) - log(LOG_WARNING, - "le%d: ierror(runt packet): from %s: len=%d\n", - unit, ether_sprintf(et.ether_shost), len); - le->sc_runt++; - le->sc_if.if_ierrors++; - return; - } - flags = 0; - if (bcmp((caddr_t)etherbroadcastaddr, - (caddr_t)et.ether_dhost, sizeof(etherbroadcastaddr)) == 0) - flags |= M_BCAST; - if (et.ether_dhost[0] & 1) - flags |= M_MCAST; - - /* - * Pull packet off interface. Off is nonzero if packet - * has trailing header; leget will then force this header - * information to be at the front, but we still have to drop - * the type and length which are at the front of any trailer data. - */ - m = leget(le, buf, len, off, &le->sc_if); - if (m == 0) - return; -#if NBPFILTER > 0 - /* - * Check if there's a bpf filter listening on this interface. - * If so, hand off the raw packet to enet. - */ - if (le->sc_if.if_bpf) { - M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT); - if (m == 0) - return; - bcopy(&et, mtod(m, void *), sizeof(struct ether_header)); - - bpf_mtap(le->sc_if.if_bpf, m); - - m_adj(m, sizeof(struct ether_header)); - - /* - * Keep the packet if it's a broadcast or has our - * physical ethernet address (or if we support - * multicast and it's one). - */ - if ( -#ifdef MULTICAST - (flags & (M_BCAST | M_MCAST)) == 0 && -#else - (flags & M_BCAST) == 0 && -#endif - bcmp(et.ether_dhost, le->sc_addr, - sizeof(et.ether_dhost)) != 0) { - m_freem(m); - return; - } - } -#endif - m->m_flags |= flags; - ether_input(&le->sc_if, &et, m); -} - -/* - * Routine to copy from mbuf chain to transmit buffer in - * network buffer memory. - */ -leput(le, lebuf, m) - struct le_softc *le; - register volatile void *lebuf; - register struct mbuf *m; -{ - register struct mbuf *mp; - register int len, tlen = 0; - register int boff = 0; - - for (mp = m; mp; mp = mp->m_next) { - len = mp->m_len; - if (len == 0) - continue; - (*le->sc_copytobuf)(mtod(mp, char *), lebuf, boff, len); - tlen += len; - boff += len; - } - m_freem(m); - if (tlen < LEMINSIZE) { - (*le->sc_zerobuf)(lebuf, boff, LEMINSIZE - tlen); - tlen = LEMINSIZE; - } - return(tlen); -} - -/* - * Routine to copy from network buffer memory into mbufs. - */ -struct mbuf * -leget(le, lebuf, totlen, off, ifp) - struct le_softc *le; - volatile void *lebuf; - int totlen, off; - struct ifnet *ifp; -{ - register struct mbuf *m; - struct mbuf *top = 0, **mp = ⊤ - register int len, resid, boff; - - /* NOTE: sizeof(struct ether_header) should be even */ - boff = sizeof(struct ether_header); - if (off) { - /* NOTE: off should be even */ - boff += off + 2 * sizeof(u_short); - totlen -= 2 * sizeof(u_short); - resid = totlen - off; - } else - resid = totlen; - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == 0) - return (0); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = totlen; - m->m_len = MHLEN; - - while (totlen > 0) { - if (top) { - MGET(m, M_DONTWAIT, MT_DATA); - if (m == 0) { - m_freem(top); - return (0); - } - m->m_len = MLEN; - } - - if (resid >= MINCLSIZE) - MCLGET(m, M_DONTWAIT); - if (m->m_flags & M_EXT) - m->m_len = min(resid, MCLBYTES); - else if (resid < m->m_len) { - /* - * Place initial small packet/header at end of mbuf. - */ - if (top == 0 && resid + max_linkhdr <= m->m_len) - m->m_data += max_linkhdr; - m->m_len = resid; - } - len = m->m_len; - (*le->sc_copyfrombuf)(lebuf, boff, mtod(m, char *), len); - boff += len; - *mp = m; - mp = &m->m_next; - totlen -= len; - resid -= len; - if (resid == 0) { - boff = sizeof (struct ether_header); - resid = totlen; - } - } - return (top); -} - -/* - * Process an ioctl request. - */ -leioctl(ifp, cmd, data) - register struct ifnet *ifp; - u_long cmd; - caddr_t data; -{ - register struct ifaddr *ifa = (struct ifaddr *)data; - struct le_softc *le = &le_softc[ifp->if_unit]; - volatile struct lereg1 *ler1 = le->sc_r1; - int s, error = 0; - - s = splnet(); - switch (cmd) { - - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - leinit(ifp->if_unit); - arp_ifinit(&le->sc_ac, ifa); - break; -#endif -#ifdef NS - case AF_NS: - { - register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); - - if (ns_nullhost(*ina)) - ina->x_host = *(union ns_host *)(le->sc_addr); - else { - /* - * The manual says we can't change the address - * while the receiver is armed, - * so reset everything - */ - ifp->if_flags &= ~IFF_RUNNING; - LEWREG(LE_STOP, ler1->ler1_rdp); - bcopy((caddr_t)ina->x_host.c_host, - (caddr_t)le->sc_addr, sizeof(le->sc_addr)); - } - leinit(ifp->if_unit); /* does le_setaddr() */ - break; - } -#endif - default: - leinit(ifp->if_unit); - break; - } - break; - -#if defined (CCITT) && defined (LLC) - case SIOCSIFCONF_X25: - ifp->if_flags |= IFF_UP; - ifa->ifa_rtrequest = cons_rtrequest; - error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); - if (error == 0) - leinit(ifp->if_unit); - break; -#endif /* CCITT && LLC */ - - case SIOCSIFFLAGS: - if ((ifp->if_flags & IFF_UP) == 0 && - ifp->if_flags & IFF_RUNNING) { - LEWREG(LE_STOP, ler1->ler1_rdp); - ifp->if_flags &= ~IFF_RUNNING; - } else if (ifp->if_flags & IFF_UP && - (ifp->if_flags & IFF_RUNNING) == 0) - leinit(ifp->if_unit); - /* - * If the state of the promiscuous bit changes, the interface - * must be reset to effect the change. - */ - if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && - (ifp->if_flags & IFF_RUNNING)) { - le->sc_iflags = ifp->if_flags; - lereset(ifp->if_unit); - lestart(ifp); - } - break; - -#ifdef MULTICAST - case SIOCADDMULTI: - case SIOCDELMULTI: - /* Update our multicast list */ - error = (cmd == SIOCADDMULTI) ? - ether_addmulti((struct ifreq *)data, &le->sc_ac) : - ether_delmulti((struct ifreq *)data, &le->sc_ac); - - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware - * filter accordingly. - */ - lereset(ifp->if_unit); - error = 0; - } - break; -#endif - - default: - error = EINVAL; - } - splx(s); - return (error); -} - -leerror(unit, stat) - int unit; - int stat; -{ - if (!ledebug) - return; - - /* - * Not all transceivers implement heartbeat - * so we only log CERR once. - */ - if ((stat & LE_CERR) && le_softc[unit].sc_cerr) - return; - log(LOG_WARNING, - "le%d: error: stat=%b\n", unit, - stat, - "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"); -} - -lererror(unit, msg) - int unit; - char *msg; -{ - register struct le_softc *le = &le_softc[unit]; - register volatile void *rmd; - u_char eaddr[6]; - int len; - - if (!ledebug) - return; - - rmd = LER2_RMDADDR(le->sc_r2, le->sc_rmd); - len = LER2V_rmd3(rmd); - if (len > 11) - (*le->sc_copyfrombuf)(LER2_RBUFADDR(le->sc_r2, le->sc_rmd), - 6, eaddr, 6); - log(LOG_WARNING, - "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", - unit, msg, - len > 11 ? ether_sprintf(eaddr) : "unknown", - le->sc_rmd, len, - LER2V_rmd1(rmd), - "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP"); -} - -lexerror(unit) - int unit; -{ - register struct le_softc *le = &le_softc[unit]; - register volatile void *tmd; - u_char eaddr[6]; - int len; - - if (!ledebug) - return; - - tmd = LER2_TMDADDR(le->sc_r2, 0); - len = -LER2V_tmd2(tmd); - if (len > 5) - (*le->sc_copyfrombuf)(LER2_TBUFADDR(le->sc_r2, 0), 0, eaddr, 6); - log(LOG_WARNING, - "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n", - unit, - len > 5 ? ether_sprintf(eaddr) : "unknown", - 0, len, - LER2V_tmd1(tmd), - "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP", - LER2V_tmd3(tmd), - "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); -} - -/* - * Write a lance register port, reading it back to ensure success. This seems - * to be necessary during initialization, since the chip appears to be a bit - * pokey sometimes. - */ -static void -lewritereg(regptr, val) - register volatile u_short *regptr; - register u_short val; -{ - register int i = 0; - - while (*regptr != val) { - *regptr = val; - MachEmptyWriteBuffer(); - if (++i > 10000) { - printf("le: Reg did not settle (to x%x): x%x\n", - val, *regptr); - return; - } - DELAY(100); - } -} - -/* - * Routines for accessing the transmit and receive buffers. Unfortunately, - * CPU addressing of these buffers is done in one of 3 ways: - * - contiguous (for the 3max and turbochannel option card) - * - gap2, which means shorts (2 bytes) interspersed with short (2 byte) - * spaces (for the pmax) - * - gap16, which means 16bytes interspersed with 16byte spaces - * for buffers which must begin on a 32byte boundary (for 3min and maxine) - * The buffer offset is the logical byte offset, assuming contiguous storage. - */ -void -copytobuf_contig(from, lebuf, boff, len) - char *from; - volatile void *lebuf; - int boff; - int len; -{ - - /* - * Just call bcopy() to do the work. - */ - bcopy(from, ((char *)lebuf) + boff, len); -} - -void -copyfrombuf_contig(lebuf, boff, to, len) - volatile void *lebuf; - int boff; - char *to; - int len; -{ - - /* - * Just call bcopy() to do the work. - */ - bcopy(((char *)lebuf) + boff, to, len); -} - -void -bzerobuf_contig(lebuf, boff, len) - volatile void *lebuf; - int boff; - int len; -{ - - /* - * Just let bzero() do the work - */ - bzero(((char *)lebuf) + boff, len); -} - -/* - * For the pmax the buffer consists of shorts (2 bytes) interspersed with - * short (2 byte) spaces and must be accessed with halfword load/stores. - * (don't worry about doing an extra byte) - */ -void -copytobuf_gap2(from, lebuf, boff, len) - register char *from; - volatile void *lebuf; - int boff; - register int len; -{ - register volatile u_short *bptr; - register int xfer; - - if (boff & 0x1) { - /* handle unaligned first byte */ - bptr = ((volatile u_short *)lebuf) + (boff - 1); - *bptr = (*from++ << 8) | (*bptr & 0xff); - bptr += 2; - len--; - } else - bptr = ((volatile u_short *)lebuf) + boff; - if ((unsigned)from & 0x1) { - while (len > 1) { - *bptr = (from[1] << 8) | (from[0] & 0xff); - bptr += 2; - from += 2; - len -= 2; - } - } else { - /* optimize for aligned transfers */ - xfer = (int)((unsigned)len & ~0x1); - CopyToBuffer((u_short *)from, bptr, xfer); - bptr += xfer; - from += xfer; - len -= xfer; - } - if (len == 1) - *bptr = (u_short)*from; -} - -void -copyfrombuf_gap2(lebuf, boff, to, len) - volatile void *lebuf; - int boff; - register char *to; - register int len; -{ - register volatile u_short *bptr; - register u_short tmp; - register int xfer; - - if (boff & 0x1) { - /* handle unaligned first byte */ - bptr = ((volatile u_short *)lebuf) + (boff - 1); - *to++ = (*bptr >> 8) & 0xff; - bptr += 2; - len--; - } else - bptr = ((volatile u_short *)lebuf) + boff; - if ((unsigned)to & 0x1) { - while (len > 1) { - tmp = *bptr; - *to++ = tmp & 0xff; - *to++ = (tmp >> 8) & 0xff; - bptr += 2; - len -= 2; - } - } else { - /* optimize for aligned transfers */ - xfer = (int)((unsigned)len & ~0x1); - CopyFromBuffer(bptr, to, xfer); - bptr += xfer; - to += xfer; - len -= xfer; - } - if (len == 1) - *to = *bptr & 0xff; -} - -void -bzerobuf_gap2(lebuf, boff, len) - volatile void *lebuf; - int boff; - int len; -{ - register volatile u_short *bptr; - - if ((unsigned)boff & 0x1) { - bptr = ((volatile u_short *)lebuf) + (boff - 1); - *bptr &= 0xff; - bptr += 2; - len--; - } else - bptr = ((volatile u_short *)lebuf) + boff; - while (len > 0) { - *bptr = 0; - bptr += 2; - len -= 2; - } -} - -/* - * For the 3min and maxine, the buffers are in main memory filled in with - * 16byte blocks interspersed with 16byte spaces. - */ -void -copytobuf_gap16(from, lebuf, boff, len) - register char *from; - volatile void *lebuf; - int boff; - register int len; -{ - register char *bptr; - register int xfer; - - bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f); - boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { - bcopy(from, ((char *)bptr) + boff, xfer); - from += xfer; - bptr += 32; - boff = 0; - len -= xfer; - xfer = min(len, 16); - } -} - -void -copyfrombuf_gap16(lebuf, boff, to, len) - volatile void *lebuf; - int boff; - register char *to; - register int len; -{ - register char *bptr; - register int xfer; - - bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f); - boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { - bcopy(((char *)bptr) + boff, to, xfer); - to += xfer; - bptr += 32; - boff = 0; - len -= xfer; - xfer = min(len, 16); - } -} - -void -bzerobuf_gap16(lebuf, boff, len) - volatile void *lebuf; - int boff; - register int len; -{ - register char *bptr; - register int xfer; - - bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f); - boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { - bzero(((char *)bptr) + boff, xfer); - bptr += 32; - boff = 0; - len -= xfer; - xfer = min(len, 16); - } -} -#endif /* NLE */ diff --git a/sys/arch/pmax/dev/scc.c b/sys/arch/pmax/dev/scc.c deleted file mode 100644 index 99aa08869b5..00000000000 --- a/sys/arch/pmax/dev/scc.c +++ /dev/null @@ -1,1393 +0,0 @@ -/* $NetBSD: scc.c,v 1.11 1995/08/21 21:42:10 jonathan Exp $ */ - -/* - * Copyright (c) 1991,1990,1989,1994,1995 Carnegie Mellon University - * All rights reserved. - * - * Author: Chris G. Demetriou and Jonathan Stone - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)scc.c 8.2 (Berkeley) 11/30/93 - */ - -/* - * Old, non-rcons Pmax console-redirection won't compile on Alphas. - */ -#ifdef pmax -#define TK_NOTYET -#endif - -#include -#if NSCC > 0 -/* - * Intel 82530 dual usart chip driver. Supports the serial port(s) on the - * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard - * and mouse on the 5000/1xx. (Don't ask me where the A channel signals - * are on the 5000/xx.) - * - * See: Intel MicroCommunications Handbook, Section 2, pg. 155-173, 1992. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef alpha -#include -#endif - -#include - -#include -#include -#include -#include - -#include - -#ifdef pmax -#include -#include -#include -#include -#include -#include -#include /* XXX */ -#endif - - -#ifdef alpha -#include -#include -#include -#include -#include -#endif - - -extern struct consdev cn_tab; -extern void ttrstrt __P((void *)); - -#ifdef alpha -#undef SCCDEV -#define SCCDEV 15 /* XXX */ -#endif - -/* - * Support old-style pmax console redirection, with - * macros that also work on Alphas with serial consoles. - * (Should be replaced with rcons?) - */ -#ifdef pmax -#define CONSOLE_ON_FRAMEBUFFER() (cn_tab.cn_screen) -#endif - -#ifdef alpha -#define CONSOLE_ON_FRAMEBUFFER() 1 /* Treat test for cn_screen as true */ -#endif - - -#define NSCCLINE (NSCC*2) -#define SCCUNIT(dev) (minor(dev) >> 1) -#define SCCLINE(dev) (minor(dev) & 0x1) - -struct tty *scc_tty[NSCCLINE]; -void (*sccDivertXInput)(); /* X windows keyboard input routine */ -void (*sccMouseEvent)(); /* X windows mouse motion event routine */ -void (*sccMouseButtons)(); /* X windows mouse buttons event routine */ -#ifdef DEBUG -int debugChar; -#endif - -struct scc_softc { - struct device sc_dv; - struct pdma scc_pdma[2]; - struct { - u_char wr1; - u_char wr3; - u_char wr4; - u_char wr5; - u_char wr14; - } scc_wreg[2]; - int scc_softCAR; -}; - -/* - * BRG formula is: - * ClockFrequency - * BRGconstant = --------------------------- - 2 - * 2 * BaudRate * ClockDivider - * - * Speed selections with Pclk=7.3728Mhz, clock x16 - */ -struct speedtab sccspeedtab[] = { - { 0, 0, }, - { 50, 4606, }, - { 75, 3070, }, - { 110, 2093, }, - { 134.5, 1711, }, - { 150, 1534, }, - { 200, 1150, }, - { 300, 766, }, - { 600, 382, }, - { 1200, 190, }, - { 1800, 126, }, - { 2400, 94, }, - { 4800, 46, }, - { 9600, 22, }, - { 19200, 10, }, - { 38400, 4, }, - { -1, -1, }, -}; - -#ifndef PORTSELECTOR -#define ISPEED TTYDEF_SPEED -#define LFLAG TTYDEF_LFLAG -#else -#define ISPEED B4800 -#define LFLAG (TTYDEF_LFLAG & ~ECHO) -#endif - -/* Definition of the driver for autoconfig. */ -int sccmatch __P((struct device * parent, void *cfdata, void *aux)); -void sccattach __P((struct device *parent, struct device *self, void *aux)); -extern struct cfdriver scccd; -struct cfdriver scccd = { - NULL, "scc", sccmatch, sccattach, DV_TTY, sizeof (struct scc_softc) -}; - -int sccGetc __P((dev_t)); -void sccPutc __P((dev_t, int)); -void sccPollc __P((dev_t, int)); -int sccparam __P((struct tty *, struct termios *)); -void sccstart __P((struct tty *)); -int sccmctl __P((dev_t, int, int)); - - -static void scc_modem_intr __P((dev_t)); -static void sccreset __P((struct scc_softc *)); - -void sccintr __P((void *)); -#ifdef alpha -void scc_alphaintr __P((int)); -#endif - -/* - * Test to see if device is present. - * Return true if found. - */ -int -sccmatch(parent, match, aux) - struct device *parent; - void *match; - void *aux; -{ - struct cfdata *cf = match; - struct confargs *ca = aux; - void *sccaddr; - - extern struct cfdriver ioasiccd; - - - if (parent->dv_cfdata->cf_driver == &ioasiccd) { - /* Make sure that we're looking for this type of device. */ - if (!BUS_MATCHNAME(ca, "scc")) - return (0); - } - else { -#ifdef DIAGNOSTIC - printf("Cannot attach scc on %s\n", parent->dv_xname); -#endif - return 0; - } - - - /* Don't over-run softc. */ - if (cf->cf_unit >= NSCC) - return (0); - - /* Get the address, and check it for validity. */ - sccaddr = BUS_CVTADDR(ca); -#ifdef alpha - sccaddr = TC_DENSE_TO_SPARSE(sccaddr); -#endif /*alpha*/ - - if (badaddr(sccaddr, 2)) - return (0); - - return (1); -} - -#ifdef alpha -void -scc_alphaintr(onoff) - int onoff; -{ - if (onoff) { - *(volatile u_int *)ASIC_REG_IMSK(asic_base) |= - ASIC_INTR_SCC_1 | ASIC_INTR_SCC_0; -#if !defined(DEC_3000_300) && defined(SCC_DMA) - *(volatile u_int *)ASIC_REG_CSR(asic_base) |= - ASIC_CSR_DMAEN_T1 | ASIC_CSR_DMAEN_R1 | - ASIC_CSR_DMAEN_T2 | ASIC_CSR_DMAEN_R2; -#endif - } else { - *(volatile u_int *)ASIC_REG_IMSK(asic_base) &= - ~(ASIC_INTR_SCC_1 | ASIC_INTR_SCC_0); -#if !defined(DEC_3000_300) && defined(SCC_DMA) - *(volatile u_int *)ASIC_REG_CSR(asic_base) &= - ~(ASIC_CSR_DMAEN_T1 | ASIC_CSR_DMAEN_R1 | - ASIC_CSR_DMAEN_T2 | ASIC_CSR_DMAEN_R2); -#endif - } - wbflush(); -} -#endif /*alpha*/ - -void -sccattach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; -{ - struct scc_softc *sc = (struct scc_softc *)self; - struct confargs *ca = aux; - struct pdma *pdp; - struct tty *tp; - void *sccaddr; - int cntr; - struct termios cterm; - struct tty ctty; - int s; -#ifdef alpha - extern int cputype; -#endif - int unit, flags; - - unit = sc->sc_dv.dv_unit; - flags = sc->sc_dv.dv_cfdata->cf_flags; - - sccaddr = MACH_PHYS_TO_UNCACHED(BUS_CVTADDR(ca)); -#ifdef alpha - sccaddr = TC_DENSE_TO_SPARSE(sccaddr); -#endif /*alpha*/ - - /* Register the interrupt handler. */ - BUS_INTR_ESTABLISH(ca, sccintr, (void *)(long)sc->sc_dv.dv_unit); - - /* - * For a remote console, wait a while for previous output to - * complete. - */ -#ifdef TK_NOTYET - if (major(cn_tab.cn_dev) == SCCDEV && cn_tab.cn_screen == 0 && - SCCUNIT(cn_tab.cn_dev) == unit) - DELAY(10000); -#else - if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) || - (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0)) - DELAY(10000); -#endif - - pdp = &sc->scc_pdma[0]; - - /* init pseudo DMA structures */ - for (cntr = 0; cntr < 2; cntr++) { - pdp->p_addr = (void *)sccaddr; - tp = scc_tty[unit * 2 + cntr] = ttymalloc(); - pdp->p_arg = (long)tp; - pdp->p_fcn = (void (*)())0; - tp->t_dev = (dev_t)((unit << 1) | cntr); - pdp++; - } - /* What's the warning here? Defaulting to softCAR on line 2? */ - sc->scc_softCAR = flags | 0x2; /* XXX */ - - /* reset chip */ - sccreset(sc); - - /* - * Special handling for consoles. - */ -#ifdef TK_NOTYET - if (cn_tab.cn_screen) { - if (cn_tab.cn_kbdgetc == sccGetc) { - if (unit == 1) { - s = spltty(); - ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); - cterm.c_cflag = CS8; -#ifdef pmax - /* XXX -- why on pmax, not on Alpha? */ - cterm.c_cflag |= CLOCAL; -#endif - cterm.c_ospeed = cterm.c_ispeed = 4800; - (void) sccparam(&ctty, &cterm); - DELAY(10000); -#ifdef notyet - /* - * For some reason doing this hangs the 3min - * during booting. Fortunately the keyboard - * works ok without it. - */ - KBDReset(ctty.t_dev, sccPutc); -#endif - DELAY(10000); - splx(s); - } else if (unit == 0) { - s = spltty(); - ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); - cterm.c_cflag = CS8 | PARENB | PARODD; - cterm.c_ospeed = cterm.c_ispeed = 4800; - (void) sccparam(&ctty, &cterm); -#ifdef TK_NOTYET - DELAY(10000); - MouseInit(ctty.t_dev, sccPutc, sccGetc); - DELAY(10000); -#endif - splx(s); - } - } - } else if (SCCUNIT(cn_tab.cn_dev) == unit) -#endif /* TK_NOTYET */ - { - s = spltty(); -#ifdef pmax - ctty.t_dev = cn_tab.cn_dev; -#else - ctty.t_dev = makedev(SCCDEV, - sc->sc_dv.dv_unit == 0 ? SCCCOMM2_PORT : SCCCOMM3_PORT); -#endif - cterm.c_cflag = CS8; -#ifdef pmax - /* XXX -- why on pmax, not on Alpha? */ - cterm.c_cflag |= CLOCAL; -#endif - cterm.c_ospeed = cterm.c_ispeed = 9600; - (void) sccparam(&ctty, &cterm); - DELAY(1000); -#ifdef TK_NOTYET - cn_tab.cn_disabled = 0; -#endif - splx(s); - } - -#ifdef alpha - /* - * XXX - * Unit 1 is the remote console, wire it up now. - */ - if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) || - (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0)) { - static struct consdev scccons = { - NULL, NULL, sccGetc, sccPutc, sccPollc, NODEV, 0 - }; - cn_tab = &scccons; - cn_tab->cn_dev = makedev(SCCDEV, sc->sc_dv.dv_unit * 2); - - printf(": console\n"); - - /* wire carrier for console. */ - sc->scc_softCAR |= SCCLINE(cn_tab->cn_dev); - } else -#endif - printf("\n"); -} - -/* - * Reset the chip. - */ -static void -sccreset(sc) - register struct scc_softc *sc; -{ - register scc_regmap_t *regs; - register u_char val; - - regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; - /* - * Chip once-only initialization - * - * NOTE: The wiring we assume is the one on the 3min: - * - * out A-TxD --> TxD keybd or mouse - * in A-RxD --> RxD keybd or mouse - * out A-DTR~ --> DTR comm - * out A-RTS~ --> RTS comm - * in A-CTS~ --> SI comm - * in A-DCD~ --> RI comm - * in A-SYNCH~--> DSR comm - * out B-TxD --> TxD comm - * in B-RxD --> RxD comm - * in B-RxC --> TRxCB comm - * in B-TxC --> RTxCB comm - * out B-RTS~ --> SS comm - * in B-CTS~ --> CTS comm - * in B-DCD~ --> CD comm - */ - SCC_INIT_REG(regs, SCC_CHANNEL_A); - SCC_INIT_REG(regs, SCC_CHANNEL_B); - - SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, ZSWR9_HARD_RESET); - DELAY(50000); /*enough ? */ - SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0); - - /* program the interrupt vector */ - SCC_WRITE_REG(regs, SCC_CHANNEL_A, ZSWR_IVEC, 0xf0); - SCC_WRITE_REG(regs, SCC_CHANNEL_B, ZSWR_IVEC, 0xf0); - SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, ZSWR9_VECTOR_INCL_STAT); - - /* receive parameters and control */ - sc->scc_wreg[SCC_CHANNEL_A].wr3 = 0; - sc->scc_wreg[SCC_CHANNEL_B].wr3 = 0; - - /* timing base defaults */ - sc->scc_wreg[SCC_CHANNEL_A].wr4 = ZSWR4_CLK_X16; - sc->scc_wreg[SCC_CHANNEL_B].wr4 = ZSWR4_CLK_X16 ; - - /* enable DTR, RTS and SS */ -#ifdef alpha - /* XXX -- who changed the alpha driver to do this, and why? */ - sc->scc_wreg[SCC_CHANNEL_B].wr5 = 0; -#else - sc->scc_wreg[SCC_CHANNEL_B].wr5 = ZSWR5_RTS; -#endif - sc->scc_wreg[SCC_CHANNEL_A].wr5 = ZSWR5_RTS | ZSWR5_DTR; - - /* baud rates */ - val = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK; - sc->scc_wreg[SCC_CHANNEL_B].wr14 = val; - sc->scc_wreg[SCC_CHANNEL_A].wr14 = val; - - /* interrupt conditions */ - val = ZSWR1_RIE | ZSWR1_PE_SC | ZSWR1_SIE | ZSWR1_TIE; - sc->scc_wreg[SCC_CHANNEL_A].wr1 = val; - sc->scc_wreg[SCC_CHANNEL_B].wr1 = val; -} - -int -sccopen(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - register struct scc_softc *sc; - register struct tty *tp; - register int unit, line; - int s, error = 0; - - unit = SCCUNIT(dev); - if (unit >= scccd.cd_ndevs) - return (ENXIO); - sc = scccd.cd_devs[unit]; - if (!sc) - return (ENXIO); - - line = SCCLINE(dev); - if (sc->scc_pdma[line].p_addr == NULL) - return (ENXIO); - - tp = scc_tty[minor(dev)]; - if (tp == NULL) - tp = scc_tty[minor(dev)] = ttymalloc(); - tp->t_oproc = sccstart; - tp->t_param = sccparam; - tp->t_dev = dev; - if ((tp->t_state & TS_ISOPEN) == 0) { - tp->t_state |= TS_WOPEN; - ttychars(tp); -#ifndef PORTSELECTOR - if (tp->t_ispeed == 0) { -#endif - tp->t_iflag = TTYDEF_IFLAG; - tp->t_oflag = TTYDEF_OFLAG; - tp->t_cflag = TTYDEF_CFLAG; - tp->t_lflag = LFLAG; - tp->t_ispeed = tp->t_ospeed = ISPEED; -#ifdef PORTSELECTOR - tp->t_cflag |= HUPCL; -#else - } -#endif - (void) sccparam(tp, &tp->t_termios); - ttsetwater(tp); - } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) - return (EBUSY); - (void) sccmctl(dev, DML_DTR, DMSET); - s = spltty(); - while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && - !(tp->t_state & TS_CARR_ON)) { - tp->t_state |= TS_WOPEN; - if ((error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, - ttopen, 0)) != 0) - break; - } - splx(s); - if (error) - return (error); - return ((*linesw[tp->t_line].l_open)(dev, tp)); -} - -/*ARGSUSED*/ -int -sccclose(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - register struct scc_softc *sc = scccd.cd_devs[SCCUNIT(dev)]; - register struct tty *tp; - register int bit, line; - - tp = scc_tty[minor(dev)]; - line = SCCLINE(dev); - if (sc->scc_wreg[line].wr5 & ZSWR5_BREAK) { - sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK; - ttyoutput(0, tp); - } - (*linesw[tp->t_line].l_close)(tp, flag); - if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || - !(tp->t_state & TS_ISOPEN)) - (void) sccmctl(dev, 0, DMSET); - return (ttyclose(tp)); -} - -int -sccread(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - register struct tty *tp; - - tp = scc_tty[minor(dev)]; - return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); -} - -int -sccwrite(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - register struct tty *tp; - - tp = scc_tty[minor(dev)]; - return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); -} - -struct tty * -scctty(dev) - dev_t dev; -{ - /* What's the warning here? */ - struct tty *tp = scc_tty[minor(dev)]; /* XXX */ - - return (tp); -} - -/*ARGSUSED*/ -int -sccioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - register struct scc_softc *sc; - register struct tty *tp; - int error, line; - - tp = scc_tty[minor(dev)]; - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); - if (error >= 0) - return (error); - error = ttioctl(tp, cmd, data, flag, p); - if (error >= 0) - return (error); - - line = SCCLINE(dev); - sc = scccd.cd_devs[SCCUNIT(dev)]; - switch (cmd) { - - case TIOCSBRK: - sc->scc_wreg[line].wr5 |= ZSWR5_BREAK; - ttyoutput(0, tp); - break; - - case TIOCCBRK: - sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK; - ttyoutput(0, tp); - break; - - case TIOCSDTR: - (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS); - break; - - case TIOCCDTR: - (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC); - break; - - case TIOCMSET: - (void) sccmctl(dev, *(int *)data, DMSET); - break; - - case TIOCMBIS: - (void) sccmctl(dev, *(int *)data, DMBIS); - break; - - case TIOCMBIC: - (void) sccmctl(dev, *(int *)data, DMBIC); - break; - - case TIOCMGET: - *(int *)data = sccmctl(dev, 0, DMGET); - break; - - default: - return (ENOTTY); - } - return (0); -} - -int -sccparam(tp, t) - register struct tty *tp; - register struct termios *t; -{ - register struct scc_softc *sc; - register scc_regmap_t *regs; - register int line; - register u_char value, wvalue; - register int cflag = t->c_cflag; - int ospeed; - - if (t->c_ispeed && t->c_ispeed != t->c_ospeed) - return (EINVAL); - ospeed = ttspeedtab(t->c_ospeed, sccspeedtab); - if (ospeed < 0) - return (EINVAL); - /* and copy to tty */ - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = cflag; - - /* - * Handle console specially. - */ -#ifdef TK_NOTYET - if (cn_tab.cn_screen) { - if (minor(tp->t_dev) == SCCKBD_PORT) { - cflag = CS8; - ospeed = ttspeedtab(4800, sccspeedtab); - } else if (minor(tp->t_dev) == SCCMOUSE_PORT) { - cflag = CS8 | PARENB | PARODD; - ospeed = ttspeedtab(4800, sccspeedtab); - } - } else if (tp->t_dev == cn_tab.cn_dev) -#endif /*TK_NOTYET*/ - { - cflag = CS8; - ospeed = ttspeedtab(9600, sccspeedtab); - } - if (ospeed == 0) { - (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */ - return (0); - } - - sc = scccd.cd_devs[SCCUNIT(tp->t_dev)]; - line = SCCLINE(tp->t_dev); - regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; - - /* - * pmax driver used to reset the SCC here. That reset causes the - * other channel on the SCC to drop outpur chars: at least that's - * what CGD reports for the Alpha. It's a bug. - */ -#if 0 - /* reset line */ - if (line == SCC_CHANNEL_A) - value = ZSWR9_A_RESET; - else - value = ZSWR9_B_RESET; - SCC_WRITE_REG(regs, line, SCC_WR9, value); - DELAY(25); -#endif - - /* stop bits, normally 1 */ - value = sc->scc_wreg[line].wr4 & 0xf0; - if (cflag & CSTOPB) - value |= ZSWR4_TWOSB; - else - value |= ZSWR4_ONESB; - if ((cflag & PARODD) == 0) - value |= ZSWR4_EVENP; - if (cflag & PARENB) - value |= ZSWR4_PARENB; - - /* set it now, remember it must be first after reset */ - sc->scc_wreg[line].wr4 = value; - SCC_WRITE_REG(regs, line, SCC_WR4, value); - - /* vector again */ - SCC_WRITE_REG(regs, line, ZSWR_IVEC, 0xf0); - - /* clear break, keep rts dtr */ - wvalue = sc->scc_wreg[line].wr5 & (ZSWR5_DTR|ZSWR5_RTS); - switch (cflag & CSIZE) { - case CS5: - value = ZSWR3_RX_5; - wvalue |= ZSWR5_TX_5; - break; - case CS6: - value = ZSWR3_RX_6; - wvalue |= ZSWR5_TX_6; - break; - case CS7: - value = ZSWR3_RX_7; - wvalue |= ZSWR5_TX_7; - break; - case CS8: - default: - value = ZSWR3_RX_8; - wvalue |= ZSWR5_TX_8; - }; - sc->scc_wreg[line].wr3 = value; - SCC_WRITE_REG(regs, line, SCC_WR3, value); - - sc->scc_wreg[line].wr5 = wvalue; - SCC_WRITE_REG(regs, line, SCC_WR5, wvalue); - - /* - * XXX Does the SCC chip require us to refresh the WR5 register - * for the other channel after writing the other, or not? - */ -#ifdef notdef - /* XXX */ - { - int otherline = (line + 1) & 1; - SCC_WRITE_REG(regs, otherline, SCC_WR5, sc->scc_wreg[otherline].wr5); - } -#endif - - SCC_WRITE_REG(regs, line, ZSWR_SYNCLO, 0); - SCC_WRITE_REG(regs, line, ZSWR_SYNCHI, 0); - SCC_WRITE_REG(regs, line, SCC_WR9, ZSWR9_VECTOR_INCL_STAT); - SCC_WRITE_REG(regs, line, SCC_WR10, 0); - value = ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD | - ZSWR11_TRXC_OUT_ENA | ZSWR11_TRXC_BAUD; - SCC_WRITE_REG(regs, line, SCC_WR11, value); - SCC_SET_TIMING_BASE(regs, line, ospeed); - value = sc->scc_wreg[line].wr14; - SCC_WRITE_REG(regs, line, SCC_WR14, value); - -#ifdef alpha - if (SCCUNIT(tp->t_dev) == 1) { - /* On unit one, on the flamingo, modem control is floating! */ - value = ZSWR15_BREAK_IE; - } else -#endif - { - value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE; - } - SCC_WRITE_REG(regs, line, SCC_WR15, value); - - /* and now the enables */ - value = sc->scc_wreg[line].wr3 | ZSWR3_RX_ENABLE; - SCC_WRITE_REG(regs, line, SCC_WR3, value); - value = sc->scc_wreg[line].wr5 | ZSWR5_TX_ENABLE; - sc->scc_wreg[line].wr5 = value; - SCC_WRITE_REG(regs, line, SCC_WR5, value); - - /* master inter enable */ - value = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT; - SCC_WRITE_REG(regs, line, SCC_WR9, value); - SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); - wbflush(); - -#ifdef alpha - scc_alphaintr(1); -#endif /*alpha*/ - - return (0); -} - -/* - * Check for interrupts from all devices. - */ -void -sccintr(xxxunit) - void * xxxunit; -{ - register int unit = (long)xxxunit; - register scc_regmap_t *regs; - register struct tty *tp; - register struct pdma *dp; - register struct scc_softc *sc; - register int cc, chan, rr1, rr2, rr3; - int overrun = 0; - - sc = scccd.cd_devs[unit]; - regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; - unit <<= 1; - for (;;) { - SCC_READ_REG(regs, SCC_CHANNEL_B, ZSRR_IVEC, rr2); - rr2 = SCC_RR2_STATUS(rr2); - /* are we done yet ? */ - if (rr2 == 6) { /* strange, distinguished value */ - SCC_READ_REG(regs, SCC_CHANNEL_A, ZSRR_IPEND, rr3); - if (rr3 == 0) - return; - } - - SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, ZSWR0_CLR_INTR); - if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { - chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? - SCC_CHANNEL_A : SCC_CHANNEL_B; - tp = scc_tty[unit | chan]; - dp = &sc->scc_pdma[chan]; - if (dp->p_mem < dp->p_end) { - SCC_WRITE_DATA(regs, chan, *dp->p_mem++); - wbflush(); - } else { - tp->t_state &= ~TS_BUSY; - if (tp->t_state & TS_FLUSH) - tp->t_state &= ~TS_FLUSH; - else { - ndflush(&tp->t_outq, dp->p_mem - - (caddr_t) tp->t_outq.c_cf); - dp->p_end = dp->p_mem = tp->t_outq.c_cf; - } - if (tp->t_line) - (*linesw[tp->t_line].l_start)(tp); - else - sccstart(tp); - if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { - SCC_READ_REG(regs, chan, SCC_RR15, cc); - cc &= ~ZSWR15_TXUEOM_IE; - SCC_WRITE_REG(regs, chan, SCC_WR15, cc); - cc = sc->scc_wreg[chan].wr1 & ~ZSWR1_TIE; - SCC_WRITE_REG(regs, chan, SCC_WR1, cc); - sc->scc_wreg[chan].wr1 = cc; - wbflush(); - } - } - } else if (rr2 == SCC_RR2_A_RECV_DONE || - rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL || - rr2 == SCC_RR2_B_RECV_SPECIAL) { - if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL) - chan = SCC_CHANNEL_A; - else - chan = SCC_CHANNEL_B; - tp = scc_tty[unit | chan]; - SCC_READ_DATA(regs, chan, cc); - if (rr2 == SCC_RR2_A_RECV_SPECIAL || - rr2 == SCC_RR2_B_RECV_SPECIAL) { - SCC_READ_REG(regs, chan, SCC_RR1, rr1); - SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_ERRORS); - if ((rr1 & ZSRR1_DO) && overrun == 0) { - log(LOG_WARNING, "scc%d,%d: silo overflow\n", - unit >> 1, chan); - overrun = 1; - } - } - - /* - * Keyboard needs special treatment. - */ - if (tp == scc_tty[SCCKBD_PORT] && CONSOLE_ON_FRAMEBUFFER()) { -#ifdef KADB - if (cc == LK_DO) { - spl0(); - kdbpanic(); - return; - } -#endif -#ifdef DEBUG - debugChar = cc; -#endif - if (sccDivertXInput) { - (*sccDivertXInput)(cc); - continue; - } -#ifdef TK_NOTYET - if ((cc = kbdMapChar(cc)) < 0) - continue; -#endif - /* - * Now for mousey - */ - } else if (tp == scc_tty[SCCMOUSE_PORT] && sccMouseButtons) { - register MouseReport *mrp; - static MouseReport currentRep; - - mrp = ¤tRep; - mrp->byteCount++; - if (cc & MOUSE_START_FRAME) { - /* - * The first mouse report byte (button state). - */ - mrp->state = cc; - if (mrp->byteCount > 1) - mrp->byteCount = 1; - } else if (mrp->byteCount == 2) { - /* - * The second mouse report byte (delta x). - */ - mrp->dx = cc; - } else if (mrp->byteCount == 3) { - /* - * The final mouse report byte (delta y). - */ - mrp->dy = cc; - mrp->byteCount = 0; - if (mrp->dx != 0 || mrp->dy != 0) { - /* - * If the mouse moved, - * post a motion event. - */ - (*sccMouseEvent)(mrp); - } - (*sccMouseButtons)(mrp); - } - continue; - } - if (!(tp->t_state & TS_ISOPEN)) { - wakeup((caddr_t)&tp->t_rawq); -#ifdef PORTSELECTOR - if (!(tp->t_state & TS_WOPEN)) -#endif - continue; - } - if (rr2 == SCC_RR2_A_RECV_SPECIAL || - rr2 == SCC_RR2_B_RECV_SPECIAL) { - if (rr1 & ZSRR1_PE) - cc |= TTY_PE; - if (rr1 & ZSRR1_FE) - cc |= TTY_FE; - } - (*linesw[tp->t_line].l_rint)(cc, tp); - } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { - chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? - SCC_CHANNEL_A : SCC_CHANNEL_B; - SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_STATUS); - scc_modem_intr(unit | chan); - } - } -} - -void -sccstart(tp) - register struct tty *tp; -{ - register struct pdma *dp; - register scc_regmap_t *regs; - register struct scc_softc *sc; - register int cc, chan; - u_char temp; - int s, sendone; - - sc = scccd.cd_devs[SCCUNIT(tp->t_dev)]; - dp = &sc->scc_pdma[SCCLINE(tp->t_dev)]; - regs = (scc_regmap_t *)dp->p_addr; - s = spltty(); - if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) - goto out; - if (tp->t_outq.c_cc <= tp->t_lowat) { - if (tp->t_state & TS_ASLEEP) { - tp->t_state &= ~TS_ASLEEP; - wakeup((caddr_t)&tp->t_outq); - } - selwakeup(&tp->t_wsel); - } - if (tp->t_outq.c_cc == 0) - goto out; - /* handle console specially */ - if (tp == scc_tty[SCCKBD_PORT] && CONSOLE_ON_FRAMEBUFFER()) { - while (tp->t_outq.c_cc > 0) { - cc = getc(&tp->t_outq) & 0x7f; - cnputc(cc); - } - /* - * After we flush the output queue we may need to wake - * up the process that made the output. - */ - if (tp->t_outq.c_cc <= tp->t_lowat) { - if (tp->t_state & TS_ASLEEP) { - tp->t_state &= ~TS_ASLEEP; - wakeup((caddr_t)&tp->t_outq); - } - selwakeup(&tp->t_wsel); - } - goto out; - } - if (tp->t_flags & (RAW|LITOUT)) - cc = ndqb(&tp->t_outq, 0); - else { - cc = ndqb(&tp->t_outq, 0200); - if (cc == 0) { - cc = getc(&tp->t_outq); - timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); - tp->t_state |= TS_TIMEOUT; - goto out; - } - } - tp->t_state |= TS_BUSY; - dp->p_end = dp->p_mem = tp->t_outq.c_cf; - dp->p_end += cc; - - /* - * Enable transmission and send the first char, as required. - */ - chan = SCCLINE(tp->t_dev); - SCC_READ_REG(regs, chan, SCC_RR0, temp); - sendone = (temp & ZSRR0_TX_READY); - SCC_READ_REG(regs, chan, SCC_RR15, temp); - temp |= ZSWR15_TXUEOM_IE; - SCC_WRITE_REG(regs, chan, SCC_WR15, temp); - temp = sc->scc_wreg[chan].wr1 | ZSWR1_TIE; - SCC_WRITE_REG(regs, chan, SCC_WR1, temp); - sc->scc_wreg[chan].wr1 = temp; - if (sendone) { -#ifdef DIAGNOSTIC - if (cc == 0) - panic("sccstart: No chars"); -#endif - SCC_WRITE_DATA(regs, chan, *dp->p_mem++); - } - wbflush(); -out: - splx(s); -} - -/* - * Stop output on a line. - */ -/*ARGSUSED*/ -int -sccstop(tp, flag) - register struct tty *tp; - int flag; -{ - register struct pdma *dp; - register struct scc_softc *sc; - register int s; - - sc = scccd.cd_devs[SCCUNIT(tp->t_dev)]; - dp = &sc->scc_pdma[SCCLINE(tp->t_dev)]; - s = spltty(); - if (tp->t_state & TS_BUSY) { - dp->p_end = dp->p_mem; - if (!(tp->t_state & TS_TTSTOP)) - tp->t_state |= TS_FLUSH; - } - splx(s); - - return 0; /* XXX should be void */ -} - -int -sccmctl(dev, bits, how) - dev_t dev; - int bits, how; -{ - register struct scc_softc *sc; - register scc_regmap_t *regs; - register int line, mbits; - register u_char value; - int s; - - sc = scccd.cd_devs[SCCUNIT(dev)]; - line = SCCLINE(dev); - regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; - s = spltty(); - /* - * only channel B has modem control, however the DTR and RTS - * pins on the comm port are wired to the DTR and RTS A channel - * signals. - */ - mbits = DML_DTR | DML_DSR | DML_CAR; - if (line == SCC_CHANNEL_B) { - if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & ZSWR5_DTR) - mbits = DML_DTR | DML_DSR; - else - mbits = 0; - SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value); - if (value & ZSRR0_DCD) - mbits |= DML_CAR; - } - switch (how) { - case DMSET: - mbits = bits; - break; - - case DMBIS: - mbits |= bits; - break; - - case DMBIC: - mbits &= ~bits; - break; - - case DMGET: - (void) splx(s); - return (mbits); - } - if (line == SCC_CHANNEL_B) { - if (mbits & DML_DTR) - sc->scc_wreg[SCC_CHANNEL_A].wr5 |= ZSWR5_DTR; - else - sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~ZSWR5_DTR; - SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5, - sc->scc_wreg[SCC_CHANNEL_A].wr5); - } - if ((mbits & DML_DTR) || (sc->scc_softCAR & (1 << line))) - scc_tty[minor(dev)]->t_state |= TS_CARR_ON; - (void) splx(s); - return (mbits); -} - -/* - * Check for carrier transition. - */ -static void -scc_modem_intr(dev) - dev_t dev; -{ - register scc_regmap_t *regs; - register struct scc_softc *sc; - register struct tty *tp; - register int car, chan; - register u_char value; - int s; - - sc = scccd.cd_devs[SCCUNIT(dev)]; - tp = scc_tty[minor(dev)]; - chan = SCCLINE(dev); - regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr; - if (chan == SCC_CHANNEL_A) - return; - s = spltty(); - if (sc->scc_softCAR & (1 << chan)) - car = 1; - else { - SCC_READ_REG_ZERO(regs, chan, value); - car = value & ZSRR0_DCD; - } - - /* - * XXX Why doesn't the Alpha driver follow carrier-detect? - * (in the Alpha driver, this is an "#ifdef notdef"). - * Is it related to console handling? - */ -#ifndef alpha -#ifdef notyet /*XXX -does this help pmax console? */ - if (car) { - /* carrier present */ - if (!(tp->t_state & TS_CARR_ON)) - (void)(*linesw[tp->t_line].l_modem)(tp, 1); - } else if (tp->t_state & TS_CARR_ON) - (void)(*linesw[tp->t_line].l_modem)(tp, 0); -#endif /*notyet*/ -#endif - splx(s); -} - -/* - * Get a char off the appropriate line via. a busy wait loop. - */ -int -sccGetc(dev) - dev_t dev; -{ - register scc_regmap_t *regs; - register int c, line; - register u_char value; - struct scc_softc *sc; - int s; - - line = SCCLINE(dev); - sc = scccd.cd_devs[SCCUNIT(dev)]; - regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; - if (!regs) - return (0); -#ifdef pmax - s = spltty(); /* XXX why different spls? */ -#else - s = splhigh(); -#endif - for (;;) { - SCC_READ_REG(regs, line, SCC_RR0, value); - if (value & ZSRR0_RX_READY) { - SCC_READ_REG(regs, line, SCC_RR1, value); - SCC_READ_DATA(regs, line, c); - if (value & (ZSRR1_PE | ZSRR1_DO | ZSRR1_FE)) { - SCC_WRITE_REG(regs, line, SCC_WR0, - ZSWR0_RESET_ERRORS); - SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, - ZSWR0_CLR_INTR); - } else { - SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, - ZSWR0_CLR_INTR); - splx(s); - return (c & 0xff); - } - } else - DELAY(10); - } -} - -/* - * Send a char on a port, via a busy wait loop. - */ -void -sccPutc(dev, c) - dev_t dev; - int c; -{ - register scc_regmap_t *regs; - register int line; - register u_char value; - struct scc_softc *sc; - int s; - -#ifdef pmax - s = spltty(); /* XXX why different spls? */ -#else - s = splhigh(); -#endif - line = SCCLINE(dev); - sc = scccd.cd_devs[SCCUNIT(dev)]; - regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; - - /* - * Wait for transmitter to be not busy. - */ - do { - SCC_READ_REG(regs, line, SCC_RR0, value); - if (value & ZSRR0_TX_READY) - break; - DELAY(100); - } while (1); - - /* - * Send the char. - */ - SCC_WRITE_DATA(regs, line, c); - wbflush(); - splx(s); - - return; -} - -/* - * Enable/disable polling mode - */ -void -sccPollc(dev, on) - dev_t dev; - int on; -{ -} - -#ifdef SCC_DEBUG -static void -rr(msg, regs) - char *msg; - scc_regmap_t *regs; -{ - u_char value; - int r0, r1, r2, r3, r10, r15; - - printf("%s: register: %lx\n", msg, regs); -#define L(reg, r) { \ - SCC_READ_REG(regs, SCC_CHANNEL_A, reg, value); \ - r = value; \ -} - L(SCC_RR0, r0); - L(SCC_RR1, r1); - L(ZSRR_IVEC, r2); - L(ZSRR_IPEND, r3); - L(SCC_RR10, r10); - L(SCC_RR15, r15); - printf("A: 0: %x 1: %x 2(vec): %x 3: %x 10: %x 15: %x\n", - r0, r1, r2, r3, r10, r15); -#undef L -#define L(reg, r) { \ - SCC_READ_REG(regs, SCC_CHANNEL_B, reg, value); \ - r = value; \ -} - L(SCC_RR0, r0); - L(SCC_RR1, r1); - L(ZSRR_IVEC, r2); - L(SCC_RR10, r10); - L(SCC_RR15, r15); - printf("B: 0: %x 1: %x 2(state): %x 10: %x 15: %x\n", - r0, r1, r2, r10, r15); -} -#endif -#endif /* NSCC */ diff --git a/sys/arch/pmax/include/autoconf.h b/sys/arch/pmax/include/autoconf.h index c21cba396eb..7f5c589393e 100644 --- a/sys/arch/pmax/include/autoconf.h +++ b/sys/arch/pmax/include/autoconf.h @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.h,v 1.2 1995/09/20 04:33:00 jonathan Exp $ */ +/* $NetBSD: autoconf.h,v 1.3 1996/01/11 05:57:04 jonathan Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -70,8 +70,8 @@ struct abus { struct confargs { char *ca_name; /* Device name. */ int ca_slot; /* Device slot (table entry). */ - int ca_slotpri; /* Device interrupt "priority" */ int ca_offset; /* Offset into slot. */ + int ca_slotpri; /* Device interrupt "priority" */ struct abus *ca_bus; /* bus device resides on. */ }; diff --git a/sys/arch/pmax/stand/Makefile b/sys/arch/pmax/stand/Makefile index ab2fc0e36bc..8870fa3f7e1 100644 --- a/sys/arch/pmax/stand/Makefile +++ b/sys/arch/pmax/stand/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.5 1995/01/18 06:53:36 mellon Exp $ +# $NetBSD: Makefile,v 1.6 1996/01/15 01:44:52 thorpej Exp $ # @(#)Makefile 8.3 (Berkeley) 2/16/94 DESTDIR= @@ -98,8 +98,8 @@ clean cleandir: install: ./mkboot boot rzboot bootrz - install -o bin -g bin -m 444 rzboot ${DESTDIR}/usr/mdec - install -o bin -g bin -m 444 bootrz ${DESTDIR}/usr/mdec + install -o ${BINOWN} -g ${BINGRP} -m 444 rzboot ${DESTDIR}/usr/mdec + install -o ${BINOWN} -g ${BINGRP} -m 444 bootrz ${DESTDIR}/usr/mdec depend: ${SRCS} mkdep ${INCPATH} ${DEFS} ${SRCS} diff --git a/sys/arch/pmax/tc/ds-tc-conf.c b/sys/arch/pmax/tc/ds-tc-conf.c index 316554ecdf1..c3418d6d071 100644 --- a/sys/arch/pmax/tc/ds-tc-conf.c +++ b/sys/arch/pmax/tc/ds-tc-conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: ds-tc-conf.c,v 1.5 1996/01/03 20:39:16 jonathan Exp $ */ +/* $NetBSD: ds-tc-conf.c,v 1.6 1996/01/11 05:59:23 jonathan Exp $ */ /* * Copyright (c) 1995 Jonathan Stone @@ -11,21 +11,38 @@ * We can share one configuration-struct table and use two slot-address * tables to handle the fact that the turbochannel slot size and base * addresses are different on the two machines. - * (thankfully the IOASIC subslots are all the same size.) + * (thankfully, the IOCTL ASIC subslots are all the same size on all + * DECstations with IOASICs.) The devices are listed in the order in which + * we should probe and attach them. */ #define C(x) ((void *)(u_long)x) +#if 0 +#define TC_SCSI "PMAZ-AA " +#define TC_ETHER "PMAD-AA " +#else +#define TC_SCSI NULL +#define TC_ETHER NULL +#endif struct confargs tc3_devs[4] = { /* name slot offset intpri */ - { "IOCTL ", 3, 0x0, -1, }, /* offset 0x040000 ?*/ - { NULL, 2, 0x0, 2, }, - { NULL, 1, 0x0, 1, }, - { NULL, 0, 0x0, 0, } + { "IOCTL ", 3, 0x0, -1, }, /* IOCTL asic, builtin */ + { NULL, 2, 0x0, 2, }, /* option slot 2 */ + { NULL, 1, 0x0, 1, }, /* option slot 1 */ + { NULL, 0, 0x0, 0, } /* option slot 0 */ }; -/* 3MAXPLUS slot addreseses */ +/* + * The only builtin Turbonchannel device on the kn03 and kmin + * is the IOCTL asic, which is mapped into TC slot 3. + */ +struct tc_builtin tc_kn03_builtins[] = { + { "IOCTL ", 3, 0x0, C(3), /*C(3)*/ } +}; + +/* 3MAXPLUS TC slot addresses */ static struct tc_slotdesc tc_kn03_slots [4] = { { KV(KN03_PHYS_TC_0_START), C(0) }, /* slot0 - tc option slot 0 */ { KV(KN03_PHYS_TC_1_START), C(1) }, /* slot1 - tc option slot 1 */ @@ -53,8 +70,8 @@ struct tc_cpu_desc kn03_tc_desc = static struct tc_slotdesc tc_kmin_slots [] = { { KV(KMIN_PHYS_TC_0_START), C(0) }, /* slot0 - tc option slot 0 */ { KV(KMIN_PHYS_TC_1_START), C(1) }, /* slot1 - tc option slot 1 */ - { KV(KMIN_PHYS_TC_2_START), C(3) }, /* slot2 - tc option slot 2 */ - { KV(KMIN_PHYS_TC_3_START), C(4) } /* slot3 - IO asic on b'board */ + { KV(KMIN_PHYS_TC_2_START), C(2) }, /* slot2 - tc option slot 2 */ + { KV(KMIN_PHYS_TC_3_START), C(3) } /* slot3 - IO asic on b'board */ }; int tc_kmin_nslots = @@ -107,14 +124,6 @@ struct tc_cpu_desc xine_tc_desc = /************************************************************************/ -#if 0 -#define TC_SCSI "PMAZ-AA " -#define TC_ETHER "PMAD-AA " -#else -#define TC_SCSI NULL -#define TC_ETHER NULL -#endif - /* 3MAX (kn02) turbochannel slots */ struct confargs kn02_devs[8] = { /* The 3max supposedly has "KN02 " at 0xbffc0410 */ @@ -123,7 +132,7 @@ struct confargs kn02_devs[8] = { { KN02_ASIC_NAME, 7, 0x0, -1, }, /* System CSR and subslots */ { TC_ETHER, 6, 0x0, 6, }, /* slot 6: Ether on cpu board*/ { TC_SCSI, 5, 0x0, 5, }, /* slot 5: SCSI on cpu board */ -/*XXX*/ { NULL, 4, -1, 0, }, /* slot 3 reserved */ +/*XXX*/ { NULL, 4, -1, 0, }, /* slot 4 reserved */ /*XXX*/ { NULL, 3, -1, 0, }, /* slot 3 reserved */ { NULL, 2, 0x0, 2, }, /* slot 2 - TC option slot 2 */ { NULL, 1, 0x0, 1, }, /* slot 1 - TC option slot 1 */ @@ -132,14 +141,14 @@ struct confargs kn02_devs[8] = { /* slot addreseses */ static struct tc_slotdesc tc_kn02_slots [8] = { - { KV(KN02_PHYS_TC_0_START), }, /* slot 0 - tc option slot 0 */ - { KV(KN02_PHYS_TC_1_START), }, /* slot 1 - tc option slot 1 */ - { KV(KN02_PHYS_TC_2_START), }, /* slot 2 - tc option slot 2 */ - { KV(KN02_PHYS_TC_3_START), }, /* slot 3 - reserved */ - { KV(KN02_PHYS_TC_4_START), }, /* slot 4 - reserved */ - { KV(KN02_PHYS_TC_5_START), }, /* slot 5 - SCSI on cpu board */ - { KV(KN02_PHYS_TC_6_START), }, /* slot 6 - Ether on cpu board */ - { KV(KN02_PHYS_TC_7_START), } /* slot 7 - system devices */ + { KV(KN02_PHYS_TC_0_START), C(0)}, /* slot 0 - tc option slot 0 */ + { KV(KN02_PHYS_TC_1_START), C(1), }, /* slot 1 - tc option slot 1 */ + { KV(KN02_PHYS_TC_2_START), C(2), }, /* slot 2 - tc option slot 2 */ + { KV(KN02_PHYS_TC_3_START), C(3), }, /* slot 3 - reserved */ + { KV(KN02_PHYS_TC_4_START), C(4), }, /* slot 4 - reserved */ + { KV(KN02_PHYS_TC_5_START), C(5), }, /* slot 5 - SCSI on b`board */ + { KV(KN02_PHYS_TC_6_START), C(6), }, /* slot 6 - b'board Ether */ + { KV(KN02_PHYS_TC_7_START), C(7), } /* slot 7 - system devices */ }; @@ -153,9 +162,9 @@ int tc_kn02_nslots = #define TC_KN02_DEV_SCSI 5 struct tc_builtin tc_kn02_builtins[] = { - { KN02_ROM_NAME,7, 0x00000000, C(TC_KN02_DEV_IOASIC), }, - { TC_ETHER, 6, 0x00000000, C(TC_KN02_DEV_ETHER), }, - { TC_SCSI, 5, 0x00000000, C(TC_KN02_DEV_SCSI), }, + { KN02_ROM_NAME,7, 0x0, C(TC_KN02_DEV_IOASIC) /* C(7)*/ }, + { TC_ETHER, 6, 0x0, C(TC_KN02_DEV_ETHER) /* C(6)*/ }, + { TC_SCSI, 5, 0x0, C(TC_KN02_DEV_SCSI) /* C(5)*/ }, };