+++ /dev/null
-/* $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 <le.h>
-#if NLE > 0
-
-#include <bpfilter.h>
-
-/*
- * 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 <sys/param.h>
-#include <sys/proc.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/buf.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/syslog.h>
-#include <sys/ioctl.h>
-#include <sys/errno.h>
-
-#include <sys/device.h>
-#include <machine/autoconf.h>
-#include <machine/machConst.h>
-
-#include <net/if.h>
-#include <net/netisr.h>
-#include <net/route.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/if_ether.h>
-#endif
-
-#ifdef NS
-#include <netns/ns.h>
-#include <netns/ns_if.h>
-#endif
-
-#if defined (CCITT) && defined (LLC)
-#include <sys/socketvar.h>
-#include <netccitt/x25.h>
-extern llc_ctlinput(), cons_rtrequest();
-#endif
-
-#include <machine/machConst.h>
-
-#include <pmax/pmax/pmaxtype.h>
-#include <pmax/pmax/kn01.h>
-#include <pmax/pmax/kmin.h>
-#include <pmax/pmax/asic.h>
-
-#include <pmax/dev/device.h>
-#include <pmax/dev/if_lereg.h>
-
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#include <net/bpfdesc.h>
-#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 */
+++ /dev/null
-/* $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 <scc.h>
-#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 <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/map.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/kernel.h>
-#include <sys/syslog.h>
-#include <sys/device.h>
-
-#ifdef alpha
-#include <dev/cons.h>
-#endif
-
-#include <pmax/include/pmioctl.h>
-
-#include <pmax/dev/device.h>
-#include <pmax/dev/pdma.h>
-#include <dev/ic/z8530reg.h>
-#include <pmax/dev/fbreg.h>
-
-#include <machine/autoconf.h>
-
-#ifdef pmax
-#include <machine/machConst.h>
-#include <pmax/pmax/cons.h>
-#include <pmax/pmax/pmaxtype.h>
-#include <pmax/pmax/maxine.h>
-#include <pmax/pmax/asic.h>
-#include <pmax/dev/sccreg.h>
-#include <pmax/dev/sccvar.h> /* XXX */
-#endif
-
-
-#ifdef alpha
-#include <alpha/tc/sccreg.h>
-#include <alpha/tc/sccvar.h>
-#include <machine/rpb.h>
-#include <alpha/tc/asic.h>
-#include <alpha/tc/tc.h>
-#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 */
-/* $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.
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. */
};
-# $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=
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}
-/* $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
* 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 */
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 =
/************************************************************************/
-#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 */
{ 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 */
/* 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 */
};
#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)*/ },
};