123503Ssklower /* 229359Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 3*35316Sbostic * All rights reserved. 423503Ssklower * 5*35316Sbostic * Redistribution and use in source and binary forms are permitted 6*35316Sbostic * provided that the above copyright notice and this paragraph are 7*35316Sbostic * duplicated in all such forms and that any documentation, 8*35316Sbostic * advertising materials, and other materials related to such 9*35316Sbostic * distribution and use acknowledge that the software was developed 10*35316Sbostic * by the University of California, Berkeley. The name of the 11*35316Sbostic * University may not be used to endorse or promote products derived 12*35316Sbostic * from this software without specific prior written permission. 13*35316Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*35316Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*35316Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*35316Sbostic * 17*35316Sbostic * @(#)if_de.c 7.5 (Berkeley) 08/04/88 1823503Ssklower */ 19*35316Sbostic 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 */ 3215357Skarels #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 6215357Skarels #include "../vax/cpu.h" 6315357Skarels #include "../vax/mtpr.h" 6417110Sbloom #include "if_dereg.h" 6517110Sbloom #include "if_uba.h" 6615357Skarels #include "../vaxuba/ubareg.h" 6715357Skarels #include "../vaxuba/ubavar.h" 6815357Skarels 6923559Ssklower #define NXMT 3 /* number of transmit buffers */ 7023559Ssklower #define NRCV 7 /* number of receive buffers (must be > 1) */ 7115357Skarels 7216279Skarels int dedebug = 0; 7315916Skarels 7415357Skarels int deprobe(), deattach(), deintr(); 7515357Skarels struct uba_device *deinfo[NDE]; 7615357Skarels u_short destd[] = { 0 }; 7715357Skarels struct uba_driver dedriver = 7815357Skarels { deprobe, 0, deattach, 0, destd, "de", deinfo }; 7915357Skarels int deinit(),deoutput(),deioctl(),dereset(); 8015357Skarels 8115357Skarels 8215357Skarels /* 8315357Skarels * Ethernet software status per interface. 8415357Skarels * 8515357Skarels * Each interface is referenced by a network interface structure, 8615357Skarels * ds_if, which the routing code uses to locate the interface. 8715357Skarels * This structure contains the output queue for the interface, its address, ... 8815357Skarels * We also have, for each interface, a UBA interface structure, which 8915357Skarels * contains information about the UNIBUS resources held by the interface: 9015357Skarels * map registers, buffered data paths, etc. Information is cached in this 9115357Skarels * structure for use by the if_uba.c routines in running the interface 9215357Skarels * efficiently. 9315357Skarels */ 9415357Skarels struct de_softc { 9515357Skarels struct arpcom ds_ac; /* Ethernet common part */ 9615357Skarels #define ds_if ds_ac.ac_if /* network-visible interface */ 9715357Skarels #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ 9815357Skarels int ds_flags; 9915357Skarels #define DSF_LOCK 1 /* lock out destart */ 10025448Skarels #define DSF_RUNNING 2 /* board is enabled */ 10125448Skarels #define DSF_SETADDR 4 /* physical address is changed */ 10215357Skarels int ds_ubaddr; /* map info for incore structs */ 10324795Skarels struct ifubinfo ds_deuba; /* unibus resource structure */ 10424795Skarels struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ 10524795Skarels struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ 10615357Skarels /* the following structures are always mapped in */ 10715357Skarels struct de_pcbb ds_pcbb; /* port control block */ 10815357Skarels struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ 10915357Skarels struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ 11015357Skarels struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ 11115357Skarels /* end mapped area */ 11215357Skarels #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) 11315357Skarels #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) 11415357Skarels #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) 11515357Skarels #define PCBB_OFFSET RVAL_OFF(ds_pcbb) 11615357Skarels #define XRENT_OFFSET LVAL_OFF(ds_xrent) 11715357Skarels #define RRENT_OFFSET LVAL_OFF(ds_rrent) 11815357Skarels #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) 11915357Skarels #define INCORE_SIZE RVAL_OFF(ds_xindex) 12015357Skarels int ds_xindex; /* UNA index into transmit chain */ 12115357Skarels int ds_rindex; /* UNA index into receive chain */ 12215357Skarels int ds_xfree; /* index for next transmit buffer */ 12315357Skarels int ds_nxmit; /* # of transmits in progress */ 12415357Skarels } de_softc[NDE]; 12515357Skarels 12615357Skarels deprobe(reg) 12715357Skarels caddr_t reg; 12815357Skarels { 12915357Skarels register int br, cvec; /* r11, r10 value-result */ 13015357Skarels register struct dedevice *addr = (struct dedevice *)reg; 13115357Skarels register i; 13215357Skarels 13315357Skarels #ifdef lint 13415357Skarels br = 0; cvec = br; br = cvec; 13515357Skarels i = 0; derint(i); deintr(i); 13615357Skarels #endif 13715357Skarels 13829572Skarels /* 13929572Skarels * Make sure self-test is finished before we screw with the board. 14029572Skarels * Self-test on a DELUA can take 15 seconds (argh). 14129572Skarels */ 14229572Skarels for (i = 0; 14329572Skarels i < 160 && 14429572Skarels (addr->pcsr0 & PCSR0_FATI) == 0 && 14529572Skarels (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; 14629572Skarels ++i) 14729572Skarels DELAY(100000); 14829572Skarels if ((addr->pcsr0 & PCSR0_FATI) != 0 || 14929572Skarels (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) 15029572Skarels return(0); 15129572Skarels 15229572Skarels addr->pcsr0 = 0; 15329572Skarels DELAY(100); 15415357Skarels addr->pcsr0 = PCSR0_RSET; 15515357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 15615357Skarels ; 15715357Skarels /* make board interrupt by executing a GETPCBB command */ 15815357Skarels addr->pcsr0 = PCSR0_INTE; 15915357Skarels addr->pcsr2 = 0; 16015357Skarels addr->pcsr3 = 0; 16115357Skarels addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; 16215357Skarels DELAY(100000); 16315357Skarels return(1); 16415357Skarels } 16515357Skarels 16615357Skarels /* 16715357Skarels * Interface exists: make available by filling in network interface 16815357Skarels * record. System will initialize the interface when it is ready 16915357Skarels * to accept packets. We get the ethernet address here. 17015357Skarels */ 17115357Skarels deattach(ui) 17215357Skarels struct uba_device *ui; 17315357Skarels { 17415357Skarels register struct de_softc *ds = &de_softc[ui->ui_unit]; 17515357Skarels register struct ifnet *ifp = &ds->ds_if; 17615357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 17729572Skarels int csr1; 17815357Skarels 17915357Skarels ifp->if_unit = ui->ui_unit; 18015357Skarels ifp->if_name = "de"; 18115357Skarels ifp->if_mtu = ETHERMTU; 18219861Skarels ifp->if_flags = IFF_BROADCAST; 18315357Skarels 18415357Skarels /* 18529572Skarels * What kind of a board is this? 18629572Skarels * The error bits 4-6 in pcsr1 are a device id as long as 18729572Skarels * the high byte is zero. 18829572Skarels */ 18929572Skarels csr1 = addr->pcsr1; 19029572Skarels if (csr1 & 0xff60) 19129572Skarels printf("de%d: broken\n", ui->ui_unit); 19229572Skarels else if (csr1 & 0x10) 19329572Skarels printf("de%d: delua\n", ui->ui_unit); 19429572Skarels else 19529572Skarels printf("de%d: deuna\n", ui->ui_unit); 19629572Skarels 19729572Skarels /* 19815357Skarels * Reset the board and temporarily map 19915357Skarels * the pcbb buffer onto the Unibus. 20015357Skarels */ 20129572Skarels addr->pcsr0 = 0; /* reset INTE */ 20229572Skarels DELAY(100); 20315357Skarels addr->pcsr0 = PCSR0_RSET; 20425633Skarels (void)dewait(ui, "reset"); 20525633Skarels 20615357Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, 20715357Skarels sizeof (struct de_pcbb), 0); 20815357Skarels addr->pcsr2 = ds->ds_ubaddr & 0xffff; 20915357Skarels addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; 21015357Skarels addr->pclow = CMD_GETPCBB; 21125633Skarels (void)dewait(ui, "pcbb"); 21225633Skarels 21315357Skarels ds->ds_pcbb.pcbb0 = FC_RDPHYAD; 21415357Skarels addr->pclow = CMD_GETCMD; 21525633Skarels (void)dewait(ui, "read addr "); 21625633Skarels 21715357Skarels ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); 21819861Skarels bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, 21915357Skarels sizeof (ds->ds_addr)); 22025974Skarels printf("de%d: hardware address %s\n", ui->ui_unit, 22125974Skarels ether_sprintf(ds->ds_addr)); 22215357Skarels ifp->if_init = deinit; 22315357Skarels ifp->if_output = deoutput; 22415357Skarels ifp->if_ioctl = deioctl; 22515357Skarels ifp->if_reset = dereset; 22624795Skarels ds->ds_deuba.iff_flags = UBA_CANTWAIT; 22715357Skarels #ifdef notdef 22815357Skarels /* CAN WE USE BDP's ??? */ 22924795Skarels ds->ds_deuba.iff_flags |= UBA_NEEDBDP; 23015357Skarels #endif 23115357Skarels if_attach(ifp); 23215357Skarels } 23315357Skarels 23415357Skarels /* 23515357Skarels * Reset of interface after UNIBUS reset. 23615357Skarels * If interface is on specified uba, reset its state. 23715357Skarels */ 23815357Skarels dereset(unit, uban) 23915357Skarels int unit, uban; 24015357Skarels { 24115357Skarels register struct uba_device *ui; 24215357Skarels 24315357Skarels if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || 24415357Skarels ui->ui_ubanum != uban) 24515357Skarels return; 24615357Skarels printf(" de%d", unit); 24719861Skarels de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; 24825448Skarels de_softc[unit].ds_flags &= ~(DSF_LOCK | DSF_RUNNING); 24932660Skarels ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET; 25032660Skarels (void)dewait(ui, "reset"); 25115357Skarels deinit(unit); 25215357Skarels } 25315357Skarels 25415357Skarels /* 25515357Skarels * Initialization of interface; clear recorded pending 25615357Skarels * operations, and reinitialize UNIBUS usage. 25715357Skarels */ 25815357Skarels deinit(unit) 25915357Skarels int unit; 26015357Skarels { 26115357Skarels register struct de_softc *ds = &de_softc[unit]; 26215357Skarels register struct uba_device *ui = deinfo[unit]; 26315357Skarels register struct dedevice *addr; 26415357Skarels register struct ifrw *ifrw; 26516208Skarels register struct ifxmt *ifxp; 26616208Skarels struct ifnet *ifp = &ds->ds_if; 26715357Skarels int s; 26815357Skarels struct de_ring *rp; 26915357Skarels int incaddr; 27015357Skarels 27119861Skarels /* not yet, if address still unknown */ 27219861Skarels if (ifp->if_addrlist == (struct ifaddr *)0) 27315357Skarels return; 27415357Skarels 27525448Skarels if (ds->ds_flags & DSF_RUNNING) 27619861Skarels return; 27725448Skarels if ((ifp->if_flags & IFF_RUNNING) == 0) { 27825448Skarels if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, 27925448Skarels sizeof (struct ether_header), (int)btoc(ETHERMTU), 28025448Skarels ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { 28125448Skarels printf("de%d: can't initialize\n", unit); 28225448Skarels ds->ds_if.if_flags &= ~IFF_UP; 28325448Skarels return; 28425448Skarels } 28525448Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), 28625448Skarels INCORE_SIZE, 0); 28715357Skarels } 28815357Skarels addr = (struct dedevice *)ui->ui_addr; 28915357Skarels 29015357Skarels /* set the pcbb block address */ 29115357Skarels incaddr = ds->ds_ubaddr + PCBB_OFFSET; 29215357Skarels addr->pcsr2 = incaddr & 0xffff; 29315357Skarels addr->pcsr3 = (incaddr >> 16) & 0x3; 29429572Skarels addr->pclow = 0; /* reset INTE */ 29529572Skarels DELAY(100); 29615357Skarels addr->pclow = CMD_GETPCBB; 29725633Skarels (void)dewait(ui, "pcbb"); 29815357Skarels 29915357Skarels /* set the transmit and receive ring header addresses */ 30015357Skarels incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; 30115357Skarels ds->ds_pcbb.pcbb0 = FC_WTRING; 30215357Skarels ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 30315357Skarels ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 30415357Skarels 30515357Skarels incaddr = ds->ds_ubaddr + XRENT_OFFSET; 30615357Skarels ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; 30715357Skarels ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; 30815357Skarels ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); 30915357Skarels ds->ds_udbbuf.b_trlen = NXMT; 31015357Skarels incaddr = ds->ds_ubaddr + RRENT_OFFSET; 31115357Skarels ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; 31215357Skarels ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; 31315357Skarels ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); 31415357Skarels ds->ds_udbbuf.b_rrlen = NRCV; 31515357Skarels 31615357Skarels addr->pclow = CMD_GETCMD; 31725633Skarels (void)dewait(ui, "wtring"); 31815357Skarels 31915357Skarels /* initialize the mode - enable hardware padding */ 32015357Skarels ds->ds_pcbb.pcbb0 = FC_WTMODE; 32115357Skarels /* let hardware do padding - set MTCH bit on broadcast */ 32215357Skarels ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; 32315357Skarels addr->pclow = CMD_GETCMD; 32425633Skarels (void)dewait(ui, "wtmode"); 32515357Skarels 32615357Skarels /* set up the receive and transmit ring entries */ 32724795Skarels ifxp = &ds->ds_ifw[0]; 32815357Skarels for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { 32924795Skarels rp->r_segbl = ifxp->ifw_info & 0xffff; 33024795Skarels rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; 33115357Skarels rp->r_flags = 0; 33216208Skarels ifxp++; 33315357Skarels } 33424795Skarels ifrw = &ds->ds_ifr[0]; 33515357Skarels for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { 33615357Skarels rp->r_slen = sizeof (struct de_buf); 33715357Skarels rp->r_segbl = ifrw->ifrw_info & 0xffff; 33815357Skarels rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; 33915357Skarels rp->r_flags = RFLG_OWN; /* hang receive */ 34015357Skarels ifrw++; 34115357Skarels } 34215357Skarels 34315357Skarels /* start up the board (rah rah) */ 34415357Skarels s = splimp(); 34525448Skarels ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; 34619861Skarels ds->ds_if.if_flags |= IFF_RUNNING; 34729572Skarels addr->pclow = PCSR0_INTE; /* avoid interlock */ 34825633Skarels destart(unit); /* queue output packets */ 34925633Skarels ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ 35025448Skarels if (ds->ds_flags & DSF_SETADDR) 35125448Skarels de_setaddr(ds->ds_addr, unit); 35225633Skarels addr->pclow = CMD_START | PCSR0_INTE; 35315357Skarels splx(s); 35415357Skarels } 35515357Skarels 35615357Skarels /* 35715357Skarels * Setup output on interface. 35815357Skarels * Get another datagram to send off of the interface queue, 35915357Skarels * and map it to the interface before starting the output. 36015357Skarels */ 36115357Skarels destart(unit) 36215357Skarels int unit; 36315357Skarels { 36415357Skarels int len; 36515357Skarels struct uba_device *ui = deinfo[unit]; 36615357Skarels struct dedevice *addr = (struct dedevice *)ui->ui_addr; 36715357Skarels register struct de_softc *ds = &de_softc[unit]; 36815357Skarels register struct de_ring *rp; 36915357Skarels struct mbuf *m; 37015357Skarels register int nxmit; 37115357Skarels 37215357Skarels /* 37315357Skarels * the following test is necessary, since 37415357Skarels * the code is not reentrant and we have 37515357Skarels * multiple transmission buffers. 37615357Skarels */ 37715357Skarels if (ds->ds_flags & DSF_LOCK) 37815357Skarels return; 37915357Skarels for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { 38015357Skarels IF_DEQUEUE(&ds->ds_if.if_snd, m); 38115357Skarels if (m == 0) 38215357Skarels break; 38315357Skarels rp = &ds->ds_xrent[ds->ds_xfree]; 38415357Skarels if (rp->r_flags & XFLG_OWN) 38515357Skarels panic("deuna xmit in progress"); 38624795Skarels len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); 38724795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 38824795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 38924795Skarels ds->ds_ifw[ds->ds_xfree].ifw_bdp); 39015357Skarels rp->r_slen = len; 39115357Skarels rp->r_tdrerr = 0; 39215357Skarels rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; 39315357Skarels 39415357Skarels ds->ds_xfree++; 39515357Skarels if (ds->ds_xfree == NXMT) 39615357Skarels ds->ds_xfree = 0; 39715357Skarels } 39815357Skarels if (ds->ds_nxmit != nxmit) { 39915357Skarels ds->ds_nxmit = nxmit; 40015916Skarels if (ds->ds_flags & DSF_RUNNING) 40115357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 40215357Skarels } 40315357Skarels } 40415357Skarels 40515357Skarels /* 40615357Skarels * Command done interrupt. 40715357Skarels */ 40815357Skarels deintr(unit) 40915357Skarels int unit; 41015357Skarels { 41115357Skarels struct uba_device *ui = deinfo[unit]; 41215357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 41315357Skarels register struct de_softc *ds = &de_softc[unit]; 41415357Skarels register struct de_ring *rp; 41516208Skarels register struct ifxmt *ifxp; 41615357Skarels short csr0; 41715357Skarels 41815357Skarels /* save flags right away - clear out interrupt bits */ 41915357Skarels csr0 = addr->pcsr0; 42015357Skarels addr->pchigh = csr0 >> 8; 42115357Skarels 42215357Skarels 42315357Skarels ds->ds_flags |= DSF_LOCK; /* prevent entering destart */ 42415357Skarels /* 42515357Skarels * if receive, put receive buffer on mbuf 42615357Skarels * and hang the request again 42715357Skarels */ 42815357Skarels derecv(unit); 42915357Skarels 43015357Skarels /* 43115357Skarels * Poll transmit ring and check status. 43215357Skarels * Be careful about loopback requests. 43315357Skarels * Then free buffer space and check for 43415357Skarels * more transmit requests. 43515357Skarels */ 43615357Skarels for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { 43715357Skarels rp = &ds->ds_xrent[ds->ds_xindex]; 43815357Skarels if (rp->r_flags & XFLG_OWN) 43915357Skarels break; 44015357Skarels ds->ds_if.if_opackets++; 44124795Skarels ifxp = &ds->ds_ifw[ds->ds_xindex]; 44215357Skarels /* check for unusual conditions */ 44315357Skarels if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { 44415357Skarels if (rp->r_flags & XFLG_ERRS) { 44515357Skarels /* output error */ 44615357Skarels ds->ds_if.if_oerrors++; 44715916Skarels if (dedebug) 44815357Skarels printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", 44915357Skarels unit, rp->r_flags, XFLG_BITS, 45015357Skarels rp->r_tdrerr, XERR_BITS, rp->r_slen); 45115357Skarels } else if (rp->r_flags & XFLG_ONE) { 45215357Skarels /* one collision */ 45315357Skarels ds->ds_if.if_collisions++; 45415357Skarels } else if (rp->r_flags & XFLG_MORE) { 45515357Skarels /* more than one collision */ 45615357Skarels ds->ds_if.if_collisions += 2; /* guess */ 45715357Skarels } else if (rp->r_flags & XFLG_MTCH) { 45815357Skarels /* received our own packet */ 45915357Skarels ds->ds_if.if_ipackets++; 46024795Skarels deread(ds, &ifxp->ifrw, 46115357Skarels rp->r_slen - sizeof (struct ether_header)); 46215357Skarels } 46315357Skarels } 46424795Skarels if (ifxp->ifw_xtofree) { 46524795Skarels m_freem(ifxp->ifw_xtofree); 46624795Skarels ifxp->ifw_xtofree = 0; 46716208Skarels } 46815357Skarels /* check if next transmit buffer also finished */ 46915357Skarels ds->ds_xindex++; 47015357Skarels if (ds->ds_xindex == NXMT) 47115357Skarels ds->ds_xindex = 0; 47215357Skarels } 47315357Skarels ds->ds_flags &= ~DSF_LOCK; 47415357Skarels destart(unit); 47515357Skarels 47615357Skarels if (csr0 & PCSR0_RCBI) { 47725633Skarels if (dedebug) 47825633Skarels log(LOG_WARNING, "de%d: buffer unavailable\n", unit); 47915357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 48015357Skarels } 48115357Skarels } 48215357Skarels 48315357Skarels /* 48415357Skarels * Ethernet interface receiver interface. 48515357Skarels * If input error just drop packet. 48615357Skarels * Otherwise purge input buffered data path and examine 48715357Skarels * packet to determine type. If can't determine length 48815357Skarels * from type, then have to drop packet. Othewise decapsulate 48915357Skarels * packet based on type and pass to type specific higher-level 49015357Skarels * input routine. 49115357Skarels */ 49215357Skarels derecv(unit) 49315357Skarels int unit; 49415357Skarels { 49515357Skarels register struct de_softc *ds = &de_softc[unit]; 49615357Skarels register struct de_ring *rp; 49715357Skarels int len; 49815357Skarels 49915357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 50015357Skarels while ((rp->r_flags & RFLG_OWN) == 0) { 50115357Skarels ds->ds_if.if_ipackets++; 50224795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 50324795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 50424795Skarels ds->ds_ifr[ds->ds_rindex].ifrw_bdp); 50515357Skarels len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) 50615357Skarels - 4; /* don't forget checksum! */ 50715357Skarels /* check for errors */ 50815357Skarels if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || 50915357Skarels (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || 51015357Skarels (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || 51115357Skarels len < ETHERMIN || len > ETHERMTU) { 51215357Skarels ds->ds_if.if_ierrors++; 51315916Skarels if (dedebug) 51415357Skarels printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", 51515357Skarels unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, 51615357Skarels RERR_BITS, len); 51715357Skarels } else 51824795Skarels deread(ds, &ds->ds_ifr[ds->ds_rindex], len); 51915357Skarels 52015357Skarels /* hang the receive buffer again */ 52115357Skarels rp->r_lenerr = 0; 52215357Skarels rp->r_flags = RFLG_OWN; 52315357Skarels 52415357Skarels /* check next receive buffer */ 52515357Skarels ds->ds_rindex++; 52615357Skarels if (ds->ds_rindex == NRCV) 52715357Skarels ds->ds_rindex = 0; 52815357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 52915357Skarels } 53015357Skarels } 53115357Skarels 53215357Skarels /* 53315357Skarels * Pass a packet to the higher levels. 53415357Skarels * We deal with the trailer protocol here. 53515357Skarels */ 53615357Skarels deread(ds, ifrw, len) 53715357Skarels register struct de_softc *ds; 53815357Skarels struct ifrw *ifrw; 53915357Skarels int len; 54015357Skarels { 54115357Skarels struct ether_header *eh; 54215357Skarels struct mbuf *m; 54315357Skarels int off, resid; 54416722Sbloom int s; 54515357Skarels register struct ifqueue *inq; 54615357Skarels 54715357Skarels /* 54819861Skarels * Deal with trailer protocol: if type is trailer type 54915357Skarels * get true type from first 16-bit word past data. 55015357Skarels * Remember that type was trailer by setting off. 55115357Skarels */ 55215357Skarels eh = (struct ether_header *)ifrw->ifrw_addr; 55315357Skarels eh->ether_type = ntohs((u_short)eh->ether_type); 55415357Skarels #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 55519861Skarels if (eh->ether_type >= ETHERTYPE_TRAIL && 55619861Skarels eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 55719861Skarels off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 55815357Skarels if (off >= ETHERMTU) 55915357Skarels return; /* sanity */ 56015357Skarels eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); 56115357Skarels resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); 56215357Skarels if (off + resid > len) 56315357Skarels return; /* sanity */ 56415357Skarels len = off + resid; 56515357Skarels } else 56615357Skarels off = 0; 56715357Skarels if (len == 0) 56815357Skarels return; 56915357Skarels 57015357Skarels /* 57115357Skarels * Pull packet off interface. Off is nonzero if packet 57224795Skarels * has trailing header; if_ubaget will then force this header 57315357Skarels * information to be at the front, but we still have to drop 57415357Skarels * the type and length which are at the front of any trailer data. 57515357Skarels */ 57624795Skarels m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); 57715357Skarels if (m == 0) 57815357Skarels return; 57915357Skarels if (off) { 58024795Skarels struct ifnet *ifp; 58124795Skarels 58224795Skarels ifp = *(mtod(m, struct ifnet **)); 58315357Skarels m->m_off += 2 * sizeof (u_short); 58415357Skarels m->m_len -= 2 * sizeof (u_short); 58524795Skarels *(mtod(m, struct ifnet **)) = ifp; 58615357Skarels } 58715357Skarels switch (eh->ether_type) { 58815357Skarels 58915357Skarels #ifdef INET 59019861Skarels case ETHERTYPE_IP: 59115357Skarels schednetisr(NETISR_IP); 59215357Skarels inq = &ipintrq; 59315357Skarels break; 59415357Skarels 59519861Skarels case ETHERTYPE_ARP: 59615357Skarels arpinput(&ds->ds_ac, m); 59715357Skarels return; 59815357Skarels #endif 59923503Ssklower #ifdef NS 60023503Ssklower case ETHERTYPE_NS: 60123503Ssklower schednetisr(NETISR_NS); 60223503Ssklower inq = &nsintrq; 60323503Ssklower break; 60423503Ssklower 60523503Ssklower #endif 60615357Skarels default: 60715357Skarels m_freem(m); 60815357Skarels return; 60915357Skarels } 61015357Skarels 61116722Sbloom s = splimp(); 61215357Skarels if (IF_QFULL(inq)) { 61315357Skarels IF_DROP(inq); 61416722Sbloom splx(s); 61515357Skarels m_freem(m); 61615357Skarels return; 61715357Skarels } 61815357Skarels IF_ENQUEUE(inq, m); 61916722Sbloom splx(s); 62015357Skarels } 62115357Skarels 62215357Skarels /* 62315357Skarels * Ethernet output routine. 62415357Skarels * Encapsulate a packet of type family for the local net. 62515357Skarels * Use trailer local net encapsulation if enough data in first 62615357Skarels * packet leaves a multiple of 512 bytes of data in remainder. 62715357Skarels */ 62815357Skarels deoutput(ifp, m0, dst) 62915357Skarels struct ifnet *ifp; 63015357Skarels struct mbuf *m0; 63115357Skarels struct sockaddr *dst; 63215357Skarels { 63315357Skarels int type, s, error; 63419861Skarels u_char edst[6]; 63515357Skarels struct in_addr idst; 63615357Skarels register struct de_softc *ds = &de_softc[ifp->if_unit]; 63715357Skarels register struct mbuf *m = m0; 63815357Skarels register struct ether_header *eh; 63915357Skarels register int off; 64025974Skarels int usetrailers; 64115357Skarels 64225448Skarels if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 64325448Skarels error = ENETDOWN; 64425448Skarels goto bad; 64525448Skarels } 64615357Skarels switch (dst->sa_family) { 64715357Skarels 64815357Skarels #ifdef INET 64915357Skarels case AF_INET: 65015357Skarels idst = ((struct sockaddr_in *)dst)->sin_addr; 65125974Skarels if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers)) 65215357Skarels return (0); /* if not yet resolved */ 65315357Skarels off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 65425974Skarels if (usetrailers && off > 0 && (off & 0x1ff) == 0 && 65515357Skarels m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 65619861Skarels type = ETHERTYPE_TRAIL + (off>>9); 65715357Skarels m->m_off -= 2 * sizeof (u_short); 65815357Skarels m->m_len += 2 * sizeof (u_short); 65919861Skarels *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 66015357Skarels *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 66115357Skarels goto gottrailertype; 66215357Skarels } 66319861Skarels type = ETHERTYPE_IP; 66415357Skarels off = 0; 66515357Skarels goto gottype; 66615357Skarels #endif 66723503Ssklower #ifdef NS 66823503Ssklower case AF_NS: 66923503Ssklower type = ETHERTYPE_NS; 67023503Ssklower bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 67123503Ssklower (caddr_t)edst, sizeof (edst)); 67223503Ssklower off = 0; 67323503Ssklower goto gottype; 67423503Ssklower #endif 67515357Skarels 67615357Skarels case AF_UNSPEC: 67715357Skarels eh = (struct ether_header *)dst->sa_data; 67819861Skarels bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 67915357Skarels type = eh->ether_type; 68015357Skarels goto gottype; 68115357Skarels 68215357Skarels default: 68315357Skarels printf("de%d: can't handle af%d\n", ifp->if_unit, 68415357Skarels dst->sa_family); 68515357Skarels error = EAFNOSUPPORT; 68615357Skarels goto bad; 68715357Skarels } 68815357Skarels 68915357Skarels gottrailertype: 69015357Skarels /* 69115357Skarels * Packet to be sent as trailer: move first packet 69215357Skarels * (control information) to end of chain. 69315357Skarels */ 69415357Skarels while (m->m_next) 69515357Skarels m = m->m_next; 69615357Skarels m->m_next = m0; 69715357Skarels m = m0->m_next; 69815357Skarels m0->m_next = 0; 69915357Skarels m0 = m; 70015357Skarels 70115357Skarels gottype: 70215357Skarels /* 70315357Skarels * Add local net header. If no space in first mbuf, 70415357Skarels * allocate another. 70515357Skarels */ 70615357Skarels if (m->m_off > MMAXOFF || 70715357Skarels MMINOFF + sizeof (struct ether_header) > m->m_off) { 70815357Skarels m = m_get(M_DONTWAIT, MT_HEADER); 70915357Skarels if (m == 0) { 71015357Skarels error = ENOBUFS; 71115357Skarels goto bad; 71215357Skarels } 71315357Skarels m->m_next = m0; 71415357Skarels m->m_off = MMINOFF; 71515357Skarels m->m_len = sizeof (struct ether_header); 71615357Skarels } else { 71715357Skarels m->m_off -= sizeof (struct ether_header); 71815357Skarels m->m_len += sizeof (struct ether_header); 71915357Skarels } 72015357Skarels eh = mtod(m, struct ether_header *); 72115357Skarels eh->ether_type = htons((u_short)type); 72219861Skarels bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 72315357Skarels /* DEUNA fills in source address */ 72415357Skarels 72515357Skarels /* 72615357Skarels * Queue message on interface, and start output if interface 72715357Skarels * not yet active. 72815357Skarels */ 72915357Skarels s = splimp(); 73015357Skarels if (IF_QFULL(&ifp->if_snd)) { 73115357Skarels IF_DROP(&ifp->if_snd); 73215357Skarels splx(s); 73315357Skarels m_freem(m); 73415357Skarels return (ENOBUFS); 73515357Skarels } 73615357Skarels IF_ENQUEUE(&ifp->if_snd, m); 73715357Skarels destart(ifp->if_unit); 73815357Skarels splx(s); 73915357Skarels return (0); 74015357Skarels 74115357Skarels bad: 74215357Skarels m_freem(m0); 74315357Skarels return (error); 74415357Skarels } 74515357Skarels 74615357Skarels /* 74715357Skarels * Process an ioctl request. 74815357Skarels */ 74915357Skarels deioctl(ifp, cmd, data) 75015357Skarels register struct ifnet *ifp; 75115357Skarels int cmd; 75215357Skarels caddr_t data; 75315357Skarels { 75419861Skarels register struct ifaddr *ifa = (struct ifaddr *)data; 75525448Skarels register struct de_softc *ds = &de_softc[ifp->if_unit]; 75615357Skarels int s = splimp(), error = 0; 75715357Skarels 75815357Skarels switch (cmd) { 75915357Skarels 76015357Skarels case SIOCSIFADDR: 76119861Skarels ifp->if_flags |= IFF_UP; 76215357Skarels deinit(ifp->if_unit); 76319861Skarels 76419861Skarels switch (ifa->ifa_addr.sa_family) { 76523503Ssklower #ifdef INET 76619861Skarels case AF_INET: 76719861Skarels ((struct arpcom *)ifp)->ac_ipaddr = 76819861Skarels IA_SIN(ifa)->sin_addr; 76919861Skarels arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 77019861Skarels break; 77123503Ssklower #endif 77223503Ssklower #ifdef NS 77323503Ssklower case AF_NS: 77423559Ssklower { 77523559Ssklower register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 77623559Ssklower 77725448Skarels if (ns_nullhost(*ina)) 77825448Skarels ina->x_host = *(union ns_host *)(ds->ds_addr); 77925448Skarels else 78023559Ssklower de_setaddr(ina->x_host.c_host,ifp->if_unit); 78123503Ssklower break; 78223559Ssklower } 78323503Ssklower #endif 78419861Skarels } 78515357Skarels break; 78615357Skarels 78725448Skarels case SIOCSIFFLAGS: 78825448Skarels if ((ifp->if_flags & IFF_UP) == 0 && 78925448Skarels ds->ds_flags & DSF_RUNNING) { 79025448Skarels ((struct dedevice *) 79129572Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = 0; 79229572Skarels DELAY(100); 79329572Skarels ((struct dedevice *) 79425448Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; 79525448Skarels ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING); 79625448Skarels } else if (ifp->if_flags & IFF_UP && 79725448Skarels (ds->ds_flags & DSF_RUNNING) == 0) 79825448Skarels deinit(ifp->if_unit); 79925448Skarels break; 80025448Skarels 80115357Skarels default: 80215357Skarels error = EINVAL; 80315357Skarels } 80415357Skarels splx(s); 80515357Skarels return (error); 80615357Skarels } 80723559Ssklower 80823559Ssklower /* 80923559Ssklower * set ethernet address for unit 81023559Ssklower */ 81123559Ssklower de_setaddr(physaddr, unit) 81225448Skarels u_char *physaddr; 81325448Skarels int unit; 81423559Ssklower { 81523559Ssklower register struct de_softc *ds = &de_softc[unit]; 81625633Skarels struct uba_device *ui = deinfo[unit]; 81723559Ssklower register struct dedevice *addr= (struct dedevice *)ui->ui_addr; 81823559Ssklower 81923672Ssklower if (! (ds->ds_flags & DSF_RUNNING)) 82023672Ssklower return; 82123672Ssklower 82234502Skarels bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6); 82323559Ssklower ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 82425448Skarels addr->pclow = PCSR0_INTE|CMD_GETCMD; 82525633Skarels if (dewait(ui, "address change") == 0) { 82625633Skarels ds->ds_flags |= DSF_SETADDR; 82734502Skarels bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6); 82825633Skarels } 82925633Skarels } 83025633Skarels 83125633Skarels /* 83225633Skarels * Await completion of the named function 83325633Skarels * and check for errors. 83425633Skarels */ 83525633Skarels dewait(ui, fn) 83625633Skarels register struct uba_device *ui; 83725633Skarels char *fn; 83825633Skarels { 83925633Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 84025633Skarels register csr0; 84125633Skarels 84225448Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 84325448Skarels ; 84423559Ssklower csr0 = addr->pcsr0; 84523559Ssklower addr->pchigh = csr0 >> 8; 84623559Ssklower if (csr0 & PCSR0_PCEI) 84725633Skarels printf("de%d: %s failed, csr0=%b csr1=%b\n", 84825633Skarels ui->ui_unit, fn, csr0, PCSR0_BITS, 84923559Ssklower addr->pcsr1, PCSR1_BITS); 85025633Skarels return (csr0 & PCSR0_PCEI); 85123559Ssklower } 85216208Skarels #endif 853