123503Ssklower /* 240842Ssklower * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 335316Sbostic * All rights reserved. 423503Ssklower * 535316Sbostic * Redistribution and use in source and binary forms are permitted 635316Sbostic * provided that the above copyright notice and this paragraph are 735316Sbostic * duplicated in all such forms and that any documentation, 835316Sbostic * advertising materials, and other materials related to such 935316Sbostic * distribution and use acknowledge that the software was developed 1035316Sbostic * by the University of California, Berkeley. The name of the 1135316Sbostic * University may not be used to endorse or promote products derived 1235316Sbostic * from this software without specific prior written permission. 1335316Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435316Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535316Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1635316Sbostic * 17*43337Ssklower * @(#)if_de.c 7.10 (Berkeley) 06/20/90 1823503Ssklower */ 1935316Sbostic 2015357Skarels #include "de.h" 2115357Skarels #if NDE > 0 2215357Skarels 2315357Skarels /* 2415357Skarels * DEC DEUNA interface 2515357Skarels * 2615357Skarels * Lou Salkind 2715357Skarels * New York University 2815357Skarels * 2915357Skarels * TODO: 3015357Skarels * timeout routine (get statistics) 3115357Skarels */ 3237508Smckusick #include "machine/pte.h" 3315357Skarels 3417110Sbloom #include "param.h" 3517110Sbloom #include "systm.h" 3617110Sbloom #include "mbuf.h" 3717110Sbloom #include "buf.h" 3817110Sbloom #include "protosw.h" 3917110Sbloom #include "socket.h" 4017110Sbloom #include "vmmac.h" 4117110Sbloom #include "ioctl.h" 4217110Sbloom #include "errno.h" 4325448Skarels #include "syslog.h" 4415357Skarels 4515357Skarels #include "../net/if.h" 4615357Skarels #include "../net/netisr.h" 4715357Skarels #include "../net/route.h" 4823503Ssklower 4923503Ssklower #ifdef INET 5015357Skarels #include "../netinet/in.h" 5115357Skarels #include "../netinet/in_systm.h" 5219861Skarels #include "../netinet/in_var.h" 5315357Skarels #include "../netinet/ip.h" 5415357Skarels #include "../netinet/if_ether.h" 5523503Ssklower #endif 5623503Ssklower 5723503Ssklower #ifdef NS 5823503Ssklower #include "../netns/ns.h" 5923503Ssklower #include "../netns/ns_if.h" 6023503Ssklower #endif 6123503Ssklower 6237476Ssklower #ifdef ISO 6337476Ssklower #include "../netiso/iso.h" 6437476Ssklower #include "../netiso/iso_var.h" 65*43337Ssklower extern char all_es_snpa[], all_is_snpa[]; 6637476Ssklower #endif 6737476Ssklower 6815357Skarels #include "../vax/cpu.h" 6915357Skarels #include "../vax/mtpr.h" 7017110Sbloom #include "if_dereg.h" 7117110Sbloom #include "if_uba.h" 7215357Skarels #include "../vaxuba/ubareg.h" 7315357Skarels #include "../vaxuba/ubavar.h" 7415357Skarels 7523559Ssklower #define NXMT 3 /* number of transmit buffers */ 7623559Ssklower #define NRCV 7 /* number of receive buffers (must be > 1) */ 7715357Skarels 7816279Skarels int dedebug = 0; 7915916Skarels 8015357Skarels int deprobe(), deattach(), deintr(); 8115357Skarels struct uba_device *deinfo[NDE]; 8215357Skarels u_short destd[] = { 0 }; 8315357Skarels struct uba_driver dedriver = 8415357Skarels { deprobe, 0, deattach, 0, destd, "de", deinfo }; 8537187Ssklower int deinit(),ether_output(),deioctl(),dereset(),destart(); 8615357Skarels 8715357Skarels 8815357Skarels /* 8915357Skarels * Ethernet software status per interface. 9015357Skarels * 9115357Skarels * Each interface is referenced by a network interface structure, 9215357Skarels * ds_if, which the routing code uses to locate the interface. 9315357Skarels * This structure contains the output queue for the interface, its address, ... 9415357Skarels * We also have, for each interface, a UBA interface structure, which 9515357Skarels * contains information about the UNIBUS resources held by the interface: 9615357Skarels * map registers, buffered data paths, etc. Information is cached in this 9715357Skarels * structure for use by the if_uba.c routines in running the interface 9815357Skarels * efficiently. 9915357Skarels */ 10015357Skarels struct de_softc { 10115357Skarels struct arpcom ds_ac; /* Ethernet common part */ 10215357Skarels #define ds_if ds_ac.ac_if /* network-visible interface */ 10315357Skarels #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ 10415357Skarels int ds_flags; 10525448Skarels #define DSF_RUNNING 2 /* board is enabled */ 10625448Skarels #define DSF_SETADDR 4 /* physical address is changed */ 10715357Skarels int ds_ubaddr; /* map info for incore structs */ 10824795Skarels struct ifubinfo ds_deuba; /* unibus resource structure */ 10924795Skarels struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ 11024795Skarels struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ 11115357Skarels /* the following structures are always mapped in */ 11215357Skarels struct de_pcbb ds_pcbb; /* port control block */ 11315357Skarels struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ 11415357Skarels struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ 11515357Skarels struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ 11615357Skarels /* end mapped area */ 11715357Skarels #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) 11815357Skarels #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) 11915357Skarels #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) 12015357Skarels #define PCBB_OFFSET RVAL_OFF(ds_pcbb) 12115357Skarels #define XRENT_OFFSET LVAL_OFF(ds_xrent) 12215357Skarels #define RRENT_OFFSET LVAL_OFF(ds_rrent) 12315357Skarels #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) 12415357Skarels #define INCORE_SIZE RVAL_OFF(ds_xindex) 12515357Skarels int ds_xindex; /* UNA index into transmit chain */ 12615357Skarels int ds_rindex; /* UNA index into receive chain */ 12715357Skarels int ds_xfree; /* index for next transmit buffer */ 12815357Skarels int ds_nxmit; /* # of transmits in progress */ 12915357Skarels } de_softc[NDE]; 13015357Skarels 13115357Skarels deprobe(reg) 13215357Skarels caddr_t reg; 13315357Skarels { 13415357Skarels register int br, cvec; /* r11, r10 value-result */ 13515357Skarels register struct dedevice *addr = (struct dedevice *)reg; 13615357Skarels register i; 13715357Skarels 13815357Skarels #ifdef lint 13915357Skarels br = 0; cvec = br; br = cvec; 14015357Skarels i = 0; derint(i); deintr(i); 14115357Skarels #endif 14215357Skarels 14329572Skarels /* 14429572Skarels * Make sure self-test is finished before we screw with the board. 14529572Skarels * Self-test on a DELUA can take 15 seconds (argh). 14629572Skarels */ 14729572Skarels for (i = 0; 14829572Skarels i < 160 && 14929572Skarels (addr->pcsr0 & PCSR0_FATI) == 0 && 15029572Skarels (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; 15129572Skarels ++i) 15229572Skarels DELAY(100000); 15329572Skarels if ((addr->pcsr0 & PCSR0_FATI) != 0 || 15429572Skarels (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) 15529572Skarels return(0); 15629572Skarels 15729572Skarels addr->pcsr0 = 0; 15829572Skarels DELAY(100); 15915357Skarels addr->pcsr0 = PCSR0_RSET; 16015357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 16115357Skarels ; 16215357Skarels /* make board interrupt by executing a GETPCBB command */ 16315357Skarels addr->pcsr0 = PCSR0_INTE; 16415357Skarels addr->pcsr2 = 0; 16515357Skarels addr->pcsr3 = 0; 16615357Skarels addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; 16715357Skarels DELAY(100000); 16815357Skarels return(1); 16915357Skarels } 17015357Skarels 17115357Skarels /* 17215357Skarels * Interface exists: make available by filling in network interface 17315357Skarels * record. System will initialize the interface when it is ready 17415357Skarels * to accept packets. We get the ethernet address here. 17515357Skarels */ 17615357Skarels deattach(ui) 17715357Skarels struct uba_device *ui; 17815357Skarels { 17915357Skarels register struct de_softc *ds = &de_softc[ui->ui_unit]; 18015357Skarels register struct ifnet *ifp = &ds->ds_if; 18115357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 18229572Skarels int csr1; 18315357Skarels 18415357Skarels ifp->if_unit = ui->ui_unit; 18515357Skarels ifp->if_name = "de"; 18615357Skarels ifp->if_mtu = ETHERMTU; 18719861Skarels ifp->if_flags = IFF_BROADCAST; 18815357Skarels 18915357Skarels /* 19029572Skarels * What kind of a board is this? 19129572Skarels * The error bits 4-6 in pcsr1 are a device id as long as 19229572Skarels * the high byte is zero. 19329572Skarels */ 19429572Skarels csr1 = addr->pcsr1; 19529572Skarels if (csr1 & 0xff60) 19629572Skarels printf("de%d: broken\n", ui->ui_unit); 19729572Skarels else if (csr1 & 0x10) 19829572Skarels printf("de%d: delua\n", ui->ui_unit); 19929572Skarels else 20029572Skarels printf("de%d: deuna\n", ui->ui_unit); 20129572Skarels 20229572Skarels /* 20315357Skarels * Reset the board and temporarily map 20415357Skarels * the pcbb buffer onto the Unibus. 20515357Skarels */ 20629572Skarels addr->pcsr0 = 0; /* reset INTE */ 20729572Skarels DELAY(100); 20815357Skarels addr->pcsr0 = PCSR0_RSET; 20925633Skarels (void)dewait(ui, "reset"); 21025633Skarels 21115357Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, 21215357Skarels sizeof (struct de_pcbb), 0); 21315357Skarels addr->pcsr2 = ds->ds_ubaddr & 0xffff; 21415357Skarels addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; 21515357Skarels addr->pclow = CMD_GETPCBB; 21625633Skarels (void)dewait(ui, "pcbb"); 21725633Skarels 21815357Skarels ds->ds_pcbb.pcbb0 = FC_RDPHYAD; 21915357Skarels addr->pclow = CMD_GETCMD; 22025633Skarels (void)dewait(ui, "read addr "); 22125633Skarels 22215357Skarels ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); 22319861Skarels bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, 22415357Skarels sizeof (ds->ds_addr)); 22525974Skarels printf("de%d: hardware address %s\n", ui->ui_unit, 22625974Skarels ether_sprintf(ds->ds_addr)); 22715357Skarels ifp->if_init = deinit; 22837187Ssklower ifp->if_output = ether_output; 22915357Skarels ifp->if_ioctl = deioctl; 23015357Skarels ifp->if_reset = dereset; 23137187Ssklower ifp->if_start = destart; 23224795Skarels ds->ds_deuba.iff_flags = UBA_CANTWAIT; 23315357Skarels #ifdef notdef 23415357Skarels /* CAN WE USE BDP's ??? */ 23524795Skarels ds->ds_deuba.iff_flags |= UBA_NEEDBDP; 23615357Skarels #endif 23715357Skarels if_attach(ifp); 23815357Skarels } 23915357Skarels 24015357Skarels /* 24115357Skarels * Reset of interface after UNIBUS reset. 24215357Skarels * If interface is on specified uba, reset its state. 24315357Skarels */ 24415357Skarels dereset(unit, uban) 24515357Skarels int unit, uban; 24615357Skarels { 24715357Skarels register struct uba_device *ui; 24815357Skarels 24915357Skarels if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || 25015357Skarels ui->ui_ubanum != uban) 25115357Skarels return; 25215357Skarels printf(" de%d", unit); 25337187Ssklower de_softc[unit].ds_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 25437187Ssklower de_softc[unit].ds_flags &= ~DSF_RUNNING; 25532660Skarels ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET; 25632660Skarels (void)dewait(ui, "reset"); 25715357Skarels deinit(unit); 25815357Skarels } 25915357Skarels 26015357Skarels /* 26115357Skarels * Initialization of interface; clear recorded pending 26215357Skarels * operations, and reinitialize UNIBUS usage. 26315357Skarels */ 26415357Skarels deinit(unit) 26515357Skarels int unit; 26615357Skarels { 26715357Skarels register struct de_softc *ds = &de_softc[unit]; 26815357Skarels register struct uba_device *ui = deinfo[unit]; 26915357Skarels register struct dedevice *addr; 27015357Skarels register struct ifrw *ifrw; 27116208Skarels register struct ifxmt *ifxp; 27216208Skarels struct ifnet *ifp = &ds->ds_if; 27315357Skarels int s; 27415357Skarels struct de_ring *rp; 27515357Skarels int incaddr; 27615357Skarels 27719861Skarels /* not yet, if address still unknown */ 27819861Skarels if (ifp->if_addrlist == (struct ifaddr *)0) 27915357Skarels return; 28015357Skarels 28125448Skarels if (ds->ds_flags & DSF_RUNNING) 28219861Skarels return; 28325448Skarels if ((ifp->if_flags & IFF_RUNNING) == 0) { 28425448Skarels if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, 28525448Skarels sizeof (struct ether_header), (int)btoc(ETHERMTU), 28625448Skarels ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { 28725448Skarels printf("de%d: can't initialize\n", unit); 28825448Skarels ds->ds_if.if_flags &= ~IFF_UP; 28925448Skarels return; 29025448Skarels } 29125448Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), 29225448Skarels INCORE_SIZE, 0); 29315357Skarels } 29415357Skarels addr = (struct dedevice *)ui->ui_addr; 29515357Skarels 29615357Skarels /* set the pcbb block address */ 29715357Skarels incaddr = ds->ds_ubaddr + PCBB_OFFSET; 29815357Skarels addr->pcsr2 = incaddr & 0xffff; 29915357Skarels addr->pcsr3 = (incaddr >> 16) & 0x3; 30029572Skarels addr->pclow = 0; /* reset INTE */ 30129572Skarels DELAY(100); 30215357Skarels addr->pclow = CMD_GETPCBB; 30325633Skarels (void)dewait(ui, "pcbb"); 30415357Skarels 30515357Skarels /* set the transmit and receive ring header addresses */ 30615357Skarels incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; 30715357Skarels ds->ds_pcbb.pcbb0 = FC_WTRING; 30815357Skarels ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 30915357Skarels ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 31015357Skarels 31115357Skarels incaddr = ds->ds_ubaddr + XRENT_OFFSET; 31215357Skarels ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; 31315357Skarels ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; 31415357Skarels ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); 31515357Skarels ds->ds_udbbuf.b_trlen = NXMT; 31615357Skarels incaddr = ds->ds_ubaddr + RRENT_OFFSET; 31715357Skarels ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; 31815357Skarels ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; 31915357Skarels ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); 32015357Skarels ds->ds_udbbuf.b_rrlen = NRCV; 32115357Skarels 32215357Skarels addr->pclow = CMD_GETCMD; 32325633Skarels (void)dewait(ui, "wtring"); 32415357Skarels 32515357Skarels /* initialize the mode - enable hardware padding */ 32615357Skarels ds->ds_pcbb.pcbb0 = FC_WTMODE; 32715357Skarels /* let hardware do padding - set MTCH bit on broadcast */ 32815357Skarels ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; 32915357Skarels addr->pclow = CMD_GETCMD; 33025633Skarels (void)dewait(ui, "wtmode"); 33115357Skarels 33215357Skarels /* set up the receive and transmit ring entries */ 33324795Skarels ifxp = &ds->ds_ifw[0]; 33415357Skarels for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { 33524795Skarels rp->r_segbl = ifxp->ifw_info & 0xffff; 33624795Skarels rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; 33715357Skarels rp->r_flags = 0; 33816208Skarels ifxp++; 33915357Skarels } 34024795Skarels ifrw = &ds->ds_ifr[0]; 34115357Skarels for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { 34215357Skarels rp->r_slen = sizeof (struct de_buf); 34315357Skarels rp->r_segbl = ifrw->ifrw_info & 0xffff; 34415357Skarels rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; 34515357Skarels rp->r_flags = RFLG_OWN; /* hang receive */ 34615357Skarels ifrw++; 34715357Skarels } 34815357Skarels 34915357Skarels /* start up the board (rah rah) */ 35015357Skarels s = splimp(); 35125448Skarels ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; 35219861Skarels ds->ds_if.if_flags |= IFF_RUNNING; 35329572Skarels addr->pclow = PCSR0_INTE; /* avoid interlock */ 35440842Ssklower destart(&ds->ds_if); /* queue output packets */ 35525633Skarels ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ 35625448Skarels if (ds->ds_flags & DSF_SETADDR) 35725448Skarels de_setaddr(ds->ds_addr, unit); 35825633Skarels addr->pclow = CMD_START | PCSR0_INTE; 35915357Skarels splx(s); 36015357Skarels } 36115357Skarels 36215357Skarels /* 36315357Skarels * Setup output on interface. 36415357Skarels * Get another datagram to send off of the interface queue, 36515357Skarels * and map it to the interface before starting the output. 36640842Ssklower * Must be called from ipl >= our interrupt level. 36715357Skarels */ 36837187Ssklower destart(ifp) 36937187Ssklower struct ifnet *ifp; 37015357Skarels { 37115357Skarels int len; 37237187Ssklower int unit = ifp->if_unit; 37315357Skarels struct uba_device *ui = deinfo[unit]; 37415357Skarels struct dedevice *addr = (struct dedevice *)ui->ui_addr; 37515357Skarels register struct de_softc *ds = &de_softc[unit]; 37615357Skarels register struct de_ring *rp; 37715357Skarels struct mbuf *m; 37815357Skarels register int nxmit; 37915357Skarels 38015357Skarels /* 38115357Skarels * the following test is necessary, since 38215357Skarels * the code is not reentrant and we have 38315357Skarels * multiple transmission buffers. 38415357Skarels */ 38537187Ssklower if (ds->ds_if.if_flags & IFF_OACTIVE) 38640842Ssklower return; 38715357Skarels for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { 38815357Skarels IF_DEQUEUE(&ds->ds_if.if_snd, m); 38915357Skarels if (m == 0) 39015357Skarels break; 39115357Skarels rp = &ds->ds_xrent[ds->ds_xfree]; 39215357Skarels if (rp->r_flags & XFLG_OWN) 39315357Skarels panic("deuna xmit in progress"); 39424795Skarels len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); 39524795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 39624795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 39724795Skarels ds->ds_ifw[ds->ds_xfree].ifw_bdp); 39815357Skarels rp->r_slen = len; 39915357Skarels rp->r_tdrerr = 0; 40015357Skarels rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; 40115357Skarels 40215357Skarels ds->ds_xfree++; 40315357Skarels if (ds->ds_xfree == NXMT) 40415357Skarels ds->ds_xfree = 0; 40515357Skarels } 40615357Skarels if (ds->ds_nxmit != nxmit) { 40715357Skarels ds->ds_nxmit = nxmit; 40815916Skarels if (ds->ds_flags & DSF_RUNNING) 40915357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 41015357Skarels } 41115357Skarels } 41215357Skarels 41315357Skarels /* 41415357Skarels * Command done interrupt. 41515357Skarels */ 41615357Skarels deintr(unit) 41715357Skarels int unit; 41815357Skarels { 41915357Skarels struct uba_device *ui = deinfo[unit]; 42015357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 42115357Skarels register struct de_softc *ds = &de_softc[unit]; 42215357Skarels register struct de_ring *rp; 42316208Skarels register struct ifxmt *ifxp; 42415357Skarels short csr0; 42515357Skarels 42615357Skarels /* save flags right away - clear out interrupt bits */ 42715357Skarels csr0 = addr->pcsr0; 42815357Skarels addr->pchigh = csr0 >> 8; 42915357Skarels 43015357Skarels 43137187Ssklower ds->ds_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */ 43215357Skarels /* 43315357Skarels * if receive, put receive buffer on mbuf 43415357Skarels * and hang the request again 43515357Skarels */ 43615357Skarels derecv(unit); 43715357Skarels 43815357Skarels /* 43915357Skarels * Poll transmit ring and check status. 44015357Skarels * Be careful about loopback requests. 44115357Skarels * Then free buffer space and check for 44215357Skarels * more transmit requests. 44315357Skarels */ 44415357Skarels for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { 44515357Skarels rp = &ds->ds_xrent[ds->ds_xindex]; 44615357Skarels if (rp->r_flags & XFLG_OWN) 44715357Skarels break; 44815357Skarels ds->ds_if.if_opackets++; 44924795Skarels ifxp = &ds->ds_ifw[ds->ds_xindex]; 45015357Skarels /* check for unusual conditions */ 45115357Skarels if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { 45215357Skarels if (rp->r_flags & XFLG_ERRS) { 45315357Skarels /* output error */ 45415357Skarels ds->ds_if.if_oerrors++; 45515916Skarels if (dedebug) 45615357Skarels printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", 45715357Skarels unit, rp->r_flags, XFLG_BITS, 45815357Skarels rp->r_tdrerr, XERR_BITS, rp->r_slen); 45915357Skarels } else if (rp->r_flags & XFLG_ONE) { 46015357Skarels /* one collision */ 46115357Skarels ds->ds_if.if_collisions++; 46215357Skarels } else if (rp->r_flags & XFLG_MORE) { 46315357Skarels /* more than one collision */ 46415357Skarels ds->ds_if.if_collisions += 2; /* guess */ 46515357Skarels } else if (rp->r_flags & XFLG_MTCH) { 46615357Skarels /* received our own packet */ 46715357Skarels ds->ds_if.if_ipackets++; 46824795Skarels deread(ds, &ifxp->ifrw, 46915357Skarels rp->r_slen - sizeof (struct ether_header)); 47015357Skarels } 47115357Skarels } 47224795Skarels if (ifxp->ifw_xtofree) { 47324795Skarels m_freem(ifxp->ifw_xtofree); 47424795Skarels ifxp->ifw_xtofree = 0; 47516208Skarels } 47615357Skarels /* check if next transmit buffer also finished */ 47715357Skarels ds->ds_xindex++; 47815357Skarels if (ds->ds_xindex == NXMT) 47915357Skarels ds->ds_xindex = 0; 48015357Skarels } 48137187Ssklower ds->ds_if.if_flags &= ~IFF_OACTIVE; 48240842Ssklower destart(&ds->ds_if); 48315357Skarels 48415357Skarels if (csr0 & PCSR0_RCBI) { 48525633Skarels if (dedebug) 48625633Skarels log(LOG_WARNING, "de%d: buffer unavailable\n", unit); 48715357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 48815357Skarels } 48915357Skarels } 49015357Skarels 49115357Skarels /* 49215357Skarels * Ethernet interface receiver interface. 49315357Skarels * If input error just drop packet. 49415357Skarels * Otherwise purge input buffered data path and examine 49515357Skarels * packet to determine type. If can't determine length 49615357Skarels * from type, then have to drop packet. Othewise decapsulate 49715357Skarels * packet based on type and pass to type specific higher-level 49815357Skarels * input routine. 49915357Skarels */ 50015357Skarels derecv(unit) 50115357Skarels int unit; 50215357Skarels { 50315357Skarels register struct de_softc *ds = &de_softc[unit]; 50415357Skarels register struct de_ring *rp; 50515357Skarels int len; 50615357Skarels 50715357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 50815357Skarels while ((rp->r_flags & RFLG_OWN) == 0) { 50915357Skarels ds->ds_if.if_ipackets++; 51024795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 51124795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 51224795Skarels ds->ds_ifr[ds->ds_rindex].ifrw_bdp); 51315357Skarels len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) 51415357Skarels - 4; /* don't forget checksum! */ 51515357Skarels /* check for errors */ 51615357Skarels if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || 51715357Skarels (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || 51815357Skarels (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || 51915357Skarels len < ETHERMIN || len > ETHERMTU) { 52015357Skarels ds->ds_if.if_ierrors++; 52115916Skarels if (dedebug) 52215357Skarels printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", 52315357Skarels unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, 52415357Skarels RERR_BITS, len); 52515357Skarels } else 52624795Skarels deread(ds, &ds->ds_ifr[ds->ds_rindex], len); 52715357Skarels 52815357Skarels /* hang the receive buffer again */ 52915357Skarels rp->r_lenerr = 0; 53015357Skarels rp->r_flags = RFLG_OWN; 53115357Skarels 53215357Skarels /* check next receive buffer */ 53315357Skarels ds->ds_rindex++; 53415357Skarels if (ds->ds_rindex == NRCV) 53515357Skarels ds->ds_rindex = 0; 53615357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 53715357Skarels } 53815357Skarels } 53915357Skarels 54015357Skarels /* 54115357Skarels * Pass a packet to the higher levels. 54215357Skarels * We deal with the trailer protocol here. 54315357Skarels */ 54415357Skarels deread(ds, ifrw, len) 54515357Skarels register struct de_softc *ds; 54615357Skarels struct ifrw *ifrw; 54715357Skarels int len; 54815357Skarels { 54915357Skarels struct ether_header *eh; 55015357Skarels struct mbuf *m; 55115357Skarels int off, resid; 55216722Sbloom int s; 55315357Skarels register struct ifqueue *inq; 55415357Skarels 55515357Skarels /* 55619861Skarels * Deal with trailer protocol: if type is trailer type 55715357Skarels * get true type from first 16-bit word past data. 55815357Skarels * Remember that type was trailer by setting off. 55915357Skarels */ 56015357Skarels eh = (struct ether_header *)ifrw->ifrw_addr; 56115357Skarels eh->ether_type = ntohs((u_short)eh->ether_type); 56215357Skarels #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 56319861Skarels if (eh->ether_type >= ETHERTYPE_TRAIL && 56419861Skarels eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 56519861Skarels off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 56615357Skarels if (off >= ETHERMTU) 56715357Skarels return; /* sanity */ 56815357Skarels eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); 56915357Skarels resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); 57015357Skarels if (off + resid > len) 57115357Skarels return; /* sanity */ 57215357Skarels len = off + resid; 57315357Skarels } else 57415357Skarels off = 0; 57515357Skarels if (len == 0) 57615357Skarels return; 57715357Skarels 57815357Skarels /* 57915357Skarels * Pull packet off interface. Off is nonzero if packet 58024795Skarels * has trailing header; if_ubaget will then force this header 58140842Ssklower * information to be at the front. 58215357Skarels */ 58324795Skarels m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); 58440842Ssklower if (m) 58540842Ssklower ether_input(&ds->ds_if, eh, m); 58615357Skarels } 58715357Skarels /* 58815357Skarels * Process an ioctl request. 58915357Skarels */ 59015357Skarels deioctl(ifp, cmd, data) 59115357Skarels register struct ifnet *ifp; 59215357Skarels int cmd; 59315357Skarels caddr_t data; 59415357Skarels { 59519861Skarels register struct ifaddr *ifa = (struct ifaddr *)data; 59625448Skarels register struct de_softc *ds = &de_softc[ifp->if_unit]; 59715357Skarels int s = splimp(), error = 0; 59815357Skarels 59915357Skarels switch (cmd) { 60015357Skarels 60115357Skarels case SIOCSIFADDR: 60219861Skarels ifp->if_flags |= IFF_UP; 60315357Skarels deinit(ifp->if_unit); 60419861Skarels 60537187Ssklower switch (ifa->ifa_addr->sa_family) { 60623503Ssklower #ifdef INET 60719861Skarels case AF_INET: 60819861Skarels ((struct arpcom *)ifp)->ac_ipaddr = 60919861Skarels IA_SIN(ifa)->sin_addr; 61019861Skarels arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 61119861Skarels break; 61223503Ssklower #endif 61323503Ssklower #ifdef NS 61423503Ssklower case AF_NS: 61523559Ssklower { 61623559Ssklower register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 61723559Ssklower 61825448Skarels if (ns_nullhost(*ina)) 61925448Skarels ina->x_host = *(union ns_host *)(ds->ds_addr); 62025448Skarels else 62123559Ssklower de_setaddr(ina->x_host.c_host,ifp->if_unit); 62223503Ssklower break; 62323559Ssklower } 62423503Ssklower #endif 62519861Skarels } 62615357Skarels break; 62715357Skarels 62825448Skarels case SIOCSIFFLAGS: 62925448Skarels if ((ifp->if_flags & IFF_UP) == 0 && 63025448Skarels ds->ds_flags & DSF_RUNNING) { 63125448Skarels ((struct dedevice *) 63229572Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = 0; 63329572Skarels DELAY(100); 63429572Skarels ((struct dedevice *) 63525448Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; 63637187Ssklower ds->ds_flags &= ~DSF_RUNNING; 63737187Ssklower ds->ds_if.if_flags &= ~IFF_OACTIVE; 63825448Skarels } else if (ifp->if_flags & IFF_UP && 63925448Skarels (ds->ds_flags & DSF_RUNNING) == 0) 64025448Skarels deinit(ifp->if_unit); 64125448Skarels break; 64225448Skarels 64315357Skarels default: 64415357Skarels error = EINVAL; 64515357Skarels } 64615357Skarels splx(s); 64715357Skarels return (error); 64815357Skarels } 64923559Ssklower 65023559Ssklower /* 65123559Ssklower * set ethernet address for unit 65223559Ssklower */ 65323559Ssklower de_setaddr(physaddr, unit) 65425448Skarels u_char *physaddr; 65525448Skarels int unit; 65623559Ssklower { 65723559Ssklower register struct de_softc *ds = &de_softc[unit]; 65825633Skarels struct uba_device *ui = deinfo[unit]; 65923559Ssklower register struct dedevice *addr= (struct dedevice *)ui->ui_addr; 66023559Ssklower 66123672Ssklower if (! (ds->ds_flags & DSF_RUNNING)) 66223672Ssklower return; 66323672Ssklower 66434502Skarels bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6); 66523559Ssklower ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 66625448Skarels addr->pclow = PCSR0_INTE|CMD_GETCMD; 66725633Skarels if (dewait(ui, "address change") == 0) { 66825633Skarels ds->ds_flags |= DSF_SETADDR; 66934502Skarels bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6); 67025633Skarels } 67125633Skarels } 67225633Skarels 67325633Skarels /* 67425633Skarels * Await completion of the named function 67525633Skarels * and check for errors. 67625633Skarels */ 67725633Skarels dewait(ui, fn) 67825633Skarels register struct uba_device *ui; 67925633Skarels char *fn; 68025633Skarels { 68125633Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 68225633Skarels register csr0; 68325633Skarels 68425448Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 68525448Skarels ; 68623559Ssklower csr0 = addr->pcsr0; 68723559Ssklower addr->pchigh = csr0 >> 8; 68823559Ssklower if (csr0 & PCSR0_PCEI) 68925633Skarels printf("de%d: %s failed, csr0=%b csr1=%b\n", 69025633Skarels ui->ui_unit, fn, csr0, PCSR0_BITS, 69123559Ssklower addr->pcsr1, PCSR1_BITS); 69225633Skarels return (csr0 & PCSR0_PCEI); 69323559Ssklower } 69416208Skarels #endif 695