123503Ssklower /* 229359Smckusick * Copyright (c) 1982, 1986 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*37187Ssklower * @(#)if_de.c 7.6 (Berkeley) 03/15/89 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 */ 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 }; 79*37187Ssklower int deinit(),ether_output(),deioctl(),dereset(),destart(); 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; 223*37187Ssklower ifp->if_output = ether_output; 22415357Skarels ifp->if_ioctl = deioctl; 22515357Skarels ifp->if_reset = dereset; 226*37187Ssklower ifp->if_start = destart; 22724795Skarels ds->ds_deuba.iff_flags = UBA_CANTWAIT; 22815357Skarels #ifdef notdef 22915357Skarels /* CAN WE USE BDP's ??? */ 23024795Skarels ds->ds_deuba.iff_flags |= UBA_NEEDBDP; 23115357Skarels #endif 23215357Skarels if_attach(ifp); 23315357Skarels } 23415357Skarels 23515357Skarels /* 23615357Skarels * Reset of interface after UNIBUS reset. 23715357Skarels * If interface is on specified uba, reset its state. 23815357Skarels */ 23915357Skarels dereset(unit, uban) 24015357Skarels int unit, uban; 24115357Skarels { 24215357Skarels register struct uba_device *ui; 24315357Skarels 24415357Skarels if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || 24515357Skarels ui->ui_ubanum != uban) 24615357Skarels return; 24715357Skarels printf(" de%d", unit); 248*37187Ssklower de_softc[unit].ds_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 249*37187Ssklower de_softc[unit].ds_flags &= ~DSF_RUNNING; 25032660Skarels ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET; 25132660Skarels (void)dewait(ui, "reset"); 25215357Skarels deinit(unit); 25315357Skarels } 25415357Skarels 25515357Skarels /* 25615357Skarels * Initialization of interface; clear recorded pending 25715357Skarels * operations, and reinitialize UNIBUS usage. 25815357Skarels */ 25915357Skarels deinit(unit) 26015357Skarels int unit; 26115357Skarels { 26215357Skarels register struct de_softc *ds = &de_softc[unit]; 26315357Skarels register struct uba_device *ui = deinfo[unit]; 26415357Skarels register struct dedevice *addr; 26515357Skarels register struct ifrw *ifrw; 26616208Skarels register struct ifxmt *ifxp; 26716208Skarels struct ifnet *ifp = &ds->ds_if; 26815357Skarels int s; 26915357Skarels struct de_ring *rp; 27015357Skarels int incaddr; 27115357Skarels 27219861Skarels /* not yet, if address still unknown */ 27319861Skarels if (ifp->if_addrlist == (struct ifaddr *)0) 27415357Skarels return; 27515357Skarels 27625448Skarels if (ds->ds_flags & DSF_RUNNING) 27719861Skarels return; 27825448Skarels if ((ifp->if_flags & IFF_RUNNING) == 0) { 27925448Skarels if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, 28025448Skarels sizeof (struct ether_header), (int)btoc(ETHERMTU), 28125448Skarels ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { 28225448Skarels printf("de%d: can't initialize\n", unit); 28325448Skarels ds->ds_if.if_flags &= ~IFF_UP; 28425448Skarels return; 28525448Skarels } 28625448Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), 28725448Skarels INCORE_SIZE, 0); 28815357Skarels } 28915357Skarels addr = (struct dedevice *)ui->ui_addr; 29015357Skarels 29115357Skarels /* set the pcbb block address */ 29215357Skarels incaddr = ds->ds_ubaddr + PCBB_OFFSET; 29315357Skarels addr->pcsr2 = incaddr & 0xffff; 29415357Skarels addr->pcsr3 = (incaddr >> 16) & 0x3; 29529572Skarels addr->pclow = 0; /* reset INTE */ 29629572Skarels DELAY(100); 29715357Skarels addr->pclow = CMD_GETPCBB; 29825633Skarels (void)dewait(ui, "pcbb"); 29915357Skarels 30015357Skarels /* set the transmit and receive ring header addresses */ 30115357Skarels incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; 30215357Skarels ds->ds_pcbb.pcbb0 = FC_WTRING; 30315357Skarels ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 30415357Skarels ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 30515357Skarels 30615357Skarels incaddr = ds->ds_ubaddr + XRENT_OFFSET; 30715357Skarels ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; 30815357Skarels ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; 30915357Skarels ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); 31015357Skarels ds->ds_udbbuf.b_trlen = NXMT; 31115357Skarels incaddr = ds->ds_ubaddr + RRENT_OFFSET; 31215357Skarels ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; 31315357Skarels ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; 31415357Skarels ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); 31515357Skarels ds->ds_udbbuf.b_rrlen = NRCV; 31615357Skarels 31715357Skarels addr->pclow = CMD_GETCMD; 31825633Skarels (void)dewait(ui, "wtring"); 31915357Skarels 32015357Skarels /* initialize the mode - enable hardware padding */ 32115357Skarels ds->ds_pcbb.pcbb0 = FC_WTMODE; 32215357Skarels /* let hardware do padding - set MTCH bit on broadcast */ 32315357Skarels ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; 32415357Skarels addr->pclow = CMD_GETCMD; 32525633Skarels (void)dewait(ui, "wtmode"); 32615357Skarels 32715357Skarels /* set up the receive and transmit ring entries */ 32824795Skarels ifxp = &ds->ds_ifw[0]; 32915357Skarels for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { 33024795Skarels rp->r_segbl = ifxp->ifw_info & 0xffff; 33124795Skarels rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; 33215357Skarels rp->r_flags = 0; 33316208Skarels ifxp++; 33415357Skarels } 33524795Skarels ifrw = &ds->ds_ifr[0]; 33615357Skarels for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { 33715357Skarels rp->r_slen = sizeof (struct de_buf); 33815357Skarels rp->r_segbl = ifrw->ifrw_info & 0xffff; 33915357Skarels rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; 34015357Skarels rp->r_flags = RFLG_OWN; /* hang receive */ 34115357Skarels ifrw++; 34215357Skarels } 34315357Skarels 34415357Skarels /* start up the board (rah rah) */ 34515357Skarels s = splimp(); 34625448Skarels ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; 34719861Skarels ds->ds_if.if_flags |= IFF_RUNNING; 34829572Skarels addr->pclow = PCSR0_INTE; /* avoid interlock */ 349*37187Ssklower (void) destart(&ds->ds_if); /* queue output packets */ 35025633Skarels ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ 35125448Skarels if (ds->ds_flags & DSF_SETADDR) 35225448Skarels de_setaddr(ds->ds_addr, unit); 35325633Skarels addr->pclow = CMD_START | PCSR0_INTE; 35415357Skarels splx(s); 35515357Skarels } 35615357Skarels 35715357Skarels /* 35815357Skarels * Setup output on interface. 35915357Skarels * Get another datagram to send off of the interface queue, 36015357Skarels * and map it to the interface before starting the output. 36115357Skarels */ 362*37187Ssklower destart(ifp) 363*37187Ssklower struct ifnet *ifp; 36415357Skarels { 36515357Skarels int len; 366*37187Ssklower int unit = ifp->if_unit; 36715357Skarels struct uba_device *ui = deinfo[unit]; 36815357Skarels struct dedevice *addr = (struct dedevice *)ui->ui_addr; 36915357Skarels register struct de_softc *ds = &de_softc[unit]; 37015357Skarels register struct de_ring *rp; 37115357Skarels struct mbuf *m; 37215357Skarels register int nxmit; 37315357Skarels 37415357Skarels /* 37515357Skarels * the following test is necessary, since 37615357Skarels * the code is not reentrant and we have 37715357Skarels * multiple transmission buffers. 37815357Skarels */ 379*37187Ssklower if (ds->ds_if.if_flags & IFF_OACTIVE) 380*37187Ssklower return (0); 38115357Skarels for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { 38215357Skarels IF_DEQUEUE(&ds->ds_if.if_snd, m); 38315357Skarels if (m == 0) 38415357Skarels break; 38515357Skarels rp = &ds->ds_xrent[ds->ds_xfree]; 38615357Skarels if (rp->r_flags & XFLG_OWN) 38715357Skarels panic("deuna xmit in progress"); 38824795Skarels len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); 38924795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 39024795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 39124795Skarels ds->ds_ifw[ds->ds_xfree].ifw_bdp); 39215357Skarels rp->r_slen = len; 39315357Skarels rp->r_tdrerr = 0; 39415357Skarels rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; 39515357Skarels 39615357Skarels ds->ds_xfree++; 39715357Skarels if (ds->ds_xfree == NXMT) 39815357Skarels ds->ds_xfree = 0; 39915357Skarels } 40015357Skarels if (ds->ds_nxmit != nxmit) { 40115357Skarels ds->ds_nxmit = nxmit; 40215916Skarels if (ds->ds_flags & DSF_RUNNING) 40315357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 40415357Skarels } 405*37187Ssklower return (0); 40615357Skarels } 40715357Skarels 40815357Skarels /* 40915357Skarels * Command done interrupt. 41015357Skarels */ 41115357Skarels deintr(unit) 41215357Skarels int unit; 41315357Skarels { 41415357Skarels struct uba_device *ui = deinfo[unit]; 41515357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 41615357Skarels register struct de_softc *ds = &de_softc[unit]; 41715357Skarels register struct de_ring *rp; 41816208Skarels register struct ifxmt *ifxp; 41915357Skarels short csr0; 42015357Skarels 42115357Skarels /* save flags right away - clear out interrupt bits */ 42215357Skarels csr0 = addr->pcsr0; 42315357Skarels addr->pchigh = csr0 >> 8; 42415357Skarels 42515357Skarels 426*37187Ssklower ds->ds_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */ 42715357Skarels /* 42815357Skarels * if receive, put receive buffer on mbuf 42915357Skarels * and hang the request again 43015357Skarels */ 43115357Skarels derecv(unit); 43215357Skarels 43315357Skarels /* 43415357Skarels * Poll transmit ring and check status. 43515357Skarels * Be careful about loopback requests. 43615357Skarels * Then free buffer space and check for 43715357Skarels * more transmit requests. 43815357Skarels */ 43915357Skarels for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { 44015357Skarels rp = &ds->ds_xrent[ds->ds_xindex]; 44115357Skarels if (rp->r_flags & XFLG_OWN) 44215357Skarels break; 44315357Skarels ds->ds_if.if_opackets++; 44424795Skarels ifxp = &ds->ds_ifw[ds->ds_xindex]; 44515357Skarels /* check for unusual conditions */ 44615357Skarels if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { 44715357Skarels if (rp->r_flags & XFLG_ERRS) { 44815357Skarels /* output error */ 44915357Skarels ds->ds_if.if_oerrors++; 45015916Skarels if (dedebug) 45115357Skarels printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", 45215357Skarels unit, rp->r_flags, XFLG_BITS, 45315357Skarels rp->r_tdrerr, XERR_BITS, rp->r_slen); 45415357Skarels } else if (rp->r_flags & XFLG_ONE) { 45515357Skarels /* one collision */ 45615357Skarels ds->ds_if.if_collisions++; 45715357Skarels } else if (rp->r_flags & XFLG_MORE) { 45815357Skarels /* more than one collision */ 45915357Skarels ds->ds_if.if_collisions += 2; /* guess */ 46015357Skarels } else if (rp->r_flags & XFLG_MTCH) { 46115357Skarels /* received our own packet */ 46215357Skarels ds->ds_if.if_ipackets++; 46324795Skarels deread(ds, &ifxp->ifrw, 46415357Skarels rp->r_slen - sizeof (struct ether_header)); 46515357Skarels } 46615357Skarels } 46724795Skarels if (ifxp->ifw_xtofree) { 46824795Skarels m_freem(ifxp->ifw_xtofree); 46924795Skarels ifxp->ifw_xtofree = 0; 47016208Skarels } 47115357Skarels /* check if next transmit buffer also finished */ 47215357Skarels ds->ds_xindex++; 47315357Skarels if (ds->ds_xindex == NXMT) 47415357Skarels ds->ds_xindex = 0; 47515357Skarels } 476*37187Ssklower ds->ds_if.if_flags &= ~IFF_OACTIVE; 477*37187Ssklower (void) destart(&ds->ds_if); 47815357Skarels 47915357Skarels if (csr0 & PCSR0_RCBI) { 48025633Skarels if (dedebug) 48125633Skarels log(LOG_WARNING, "de%d: buffer unavailable\n", unit); 48215357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 48315357Skarels } 48415357Skarels } 48515357Skarels 48615357Skarels /* 48715357Skarels * Ethernet interface receiver interface. 48815357Skarels * If input error just drop packet. 48915357Skarels * Otherwise purge input buffered data path and examine 49015357Skarels * packet to determine type. If can't determine length 49115357Skarels * from type, then have to drop packet. Othewise decapsulate 49215357Skarels * packet based on type and pass to type specific higher-level 49315357Skarels * input routine. 49415357Skarels */ 49515357Skarels derecv(unit) 49615357Skarels int unit; 49715357Skarels { 49815357Skarels register struct de_softc *ds = &de_softc[unit]; 49915357Skarels register struct de_ring *rp; 50015357Skarels int len; 50115357Skarels 50215357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 50315357Skarels while ((rp->r_flags & RFLG_OWN) == 0) { 50415357Skarels ds->ds_if.if_ipackets++; 50524795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 50624795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 50724795Skarels ds->ds_ifr[ds->ds_rindex].ifrw_bdp); 50815357Skarels len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) 50915357Skarels - 4; /* don't forget checksum! */ 51015357Skarels /* check for errors */ 51115357Skarels if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || 51215357Skarels (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || 51315357Skarels (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || 51415357Skarels len < ETHERMIN || len > ETHERMTU) { 51515357Skarels ds->ds_if.if_ierrors++; 51615916Skarels if (dedebug) 51715357Skarels printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", 51815357Skarels unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, 51915357Skarels RERR_BITS, len); 52015357Skarels } else 52124795Skarels deread(ds, &ds->ds_ifr[ds->ds_rindex], len); 52215357Skarels 52315357Skarels /* hang the receive buffer again */ 52415357Skarels rp->r_lenerr = 0; 52515357Skarels rp->r_flags = RFLG_OWN; 52615357Skarels 52715357Skarels /* check next receive buffer */ 52815357Skarels ds->ds_rindex++; 52915357Skarels if (ds->ds_rindex == NRCV) 53015357Skarels ds->ds_rindex = 0; 53115357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 53215357Skarels } 53315357Skarels } 53415357Skarels 53515357Skarels /* 53615357Skarels * Pass a packet to the higher levels. 53715357Skarels * We deal with the trailer protocol here. 53815357Skarels */ 53915357Skarels deread(ds, ifrw, len) 54015357Skarels register struct de_softc *ds; 54115357Skarels struct ifrw *ifrw; 54215357Skarels int len; 54315357Skarels { 54415357Skarels struct ether_header *eh; 54515357Skarels struct mbuf *m; 54615357Skarels int off, resid; 54716722Sbloom int s; 54815357Skarels register struct ifqueue *inq; 54915357Skarels 55015357Skarels /* 55119861Skarels * Deal with trailer protocol: if type is trailer type 55215357Skarels * get true type from first 16-bit word past data. 55315357Skarels * Remember that type was trailer by setting off. 55415357Skarels */ 55515357Skarels eh = (struct ether_header *)ifrw->ifrw_addr; 55615357Skarels eh->ether_type = ntohs((u_short)eh->ether_type); 55715357Skarels #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 55819861Skarels if (eh->ether_type >= ETHERTYPE_TRAIL && 55919861Skarels eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 56019861Skarels off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 56115357Skarels if (off >= ETHERMTU) 56215357Skarels return; /* sanity */ 56315357Skarels eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); 56415357Skarels resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); 56515357Skarels if (off + resid > len) 56615357Skarels return; /* sanity */ 56715357Skarels len = off + resid; 56815357Skarels } else 56915357Skarels off = 0; 57015357Skarels if (len == 0) 57115357Skarels return; 57215357Skarels 57315357Skarels /* 57415357Skarels * Pull packet off interface. Off is nonzero if packet 57524795Skarels * has trailing header; if_ubaget will then force this header 57615357Skarels * information to be at the front, but we still have to drop 57715357Skarels * the type and length which are at the front of any trailer data. 57815357Skarels */ 57924795Skarels m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); 58015357Skarels if (m == 0) 58115357Skarels return; 582*37187Ssklower ether_input(&ds->ds_if, eh, m); 58324795Skarels 58416722Sbloom s = splimp(); 58515357Skarels if (IF_QFULL(inq)) { 58615357Skarels IF_DROP(inq); 58715357Skarels m_freem(m); 588*37187Ssklower } else 589*37187Ssklower IF_ENQUEUE(inq, m); 59016722Sbloom splx(s); 59115357Skarels } 59215357Skarels /* 59315357Skarels * Process an ioctl request. 59415357Skarels */ 59515357Skarels deioctl(ifp, cmd, data) 59615357Skarels register struct ifnet *ifp; 59715357Skarels int cmd; 59815357Skarels caddr_t data; 59915357Skarels { 60019861Skarels register struct ifaddr *ifa = (struct ifaddr *)data; 60125448Skarels register struct de_softc *ds = &de_softc[ifp->if_unit]; 60215357Skarels int s = splimp(), error = 0; 60315357Skarels 60415357Skarels switch (cmd) { 60515357Skarels 60615357Skarels case SIOCSIFADDR: 60719861Skarels ifp->if_flags |= IFF_UP; 60815357Skarels deinit(ifp->if_unit); 60919861Skarels 610*37187Ssklower switch (ifa->ifa_addr->sa_family) { 61123503Ssklower #ifdef INET 61219861Skarels case AF_INET: 61319861Skarels ((struct arpcom *)ifp)->ac_ipaddr = 61419861Skarels IA_SIN(ifa)->sin_addr; 61519861Skarels arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 61619861Skarels break; 61723503Ssklower #endif 61823503Ssklower #ifdef NS 61923503Ssklower case AF_NS: 62023559Ssklower { 62123559Ssklower register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 62223559Ssklower 62325448Skarels if (ns_nullhost(*ina)) 62425448Skarels ina->x_host = *(union ns_host *)(ds->ds_addr); 62525448Skarels else 62623559Ssklower de_setaddr(ina->x_host.c_host,ifp->if_unit); 62723503Ssklower break; 62823559Ssklower } 62923503Ssklower #endif 63019861Skarels } 63115357Skarels break; 63215357Skarels 63325448Skarels case SIOCSIFFLAGS: 63425448Skarels if ((ifp->if_flags & IFF_UP) == 0 && 63525448Skarels ds->ds_flags & DSF_RUNNING) { 63625448Skarels ((struct dedevice *) 63729572Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = 0; 63829572Skarels DELAY(100); 63929572Skarels ((struct dedevice *) 64025448Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; 641*37187Ssklower ds->ds_flags &= ~DSF_RUNNING; 642*37187Ssklower ds->ds_if.if_flags &= ~IFF_OACTIVE; 64325448Skarels } else if (ifp->if_flags & IFF_UP && 64425448Skarels (ds->ds_flags & DSF_RUNNING) == 0) 64525448Skarels deinit(ifp->if_unit); 64625448Skarels break; 64725448Skarels 64815357Skarels default: 64915357Skarels error = EINVAL; 65015357Skarels } 65115357Skarels splx(s); 65215357Skarels return (error); 65315357Skarels } 65423559Ssklower 65523559Ssklower /* 65623559Ssklower * set ethernet address for unit 65723559Ssklower */ 65823559Ssklower de_setaddr(physaddr, unit) 65925448Skarels u_char *physaddr; 66025448Skarels int unit; 66123559Ssklower { 66223559Ssklower register struct de_softc *ds = &de_softc[unit]; 66325633Skarels struct uba_device *ui = deinfo[unit]; 66423559Ssklower register struct dedevice *addr= (struct dedevice *)ui->ui_addr; 66523559Ssklower 66623672Ssklower if (! (ds->ds_flags & DSF_RUNNING)) 66723672Ssklower return; 66823672Ssklower 66934502Skarels bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6); 67023559Ssklower ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 67125448Skarels addr->pclow = PCSR0_INTE|CMD_GETCMD; 67225633Skarels if (dewait(ui, "address change") == 0) { 67325633Skarels ds->ds_flags |= DSF_SETADDR; 67434502Skarels bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6); 67525633Skarels } 67625633Skarels } 67725633Skarels 67825633Skarels /* 67925633Skarels * Await completion of the named function 68025633Skarels * and check for errors. 68125633Skarels */ 68225633Skarels dewait(ui, fn) 68325633Skarels register struct uba_device *ui; 68425633Skarels char *fn; 68525633Skarels { 68625633Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 68725633Skarels register csr0; 68825633Skarels 68925448Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 69025448Skarels ; 69123559Ssklower csr0 = addr->pcsr0; 69223559Ssklower addr->pchigh = csr0 >> 8; 69323559Ssklower if (csr0 & PCSR0_PCEI) 69425633Skarels printf("de%d: %s failed, csr0=%b csr1=%b\n", 69525633Skarels ui->ui_unit, fn, csr0, PCSR0_BITS, 69623559Ssklower addr->pcsr1, PCSR1_BITS); 69725633Skarels return (csr0 & PCSR0_PCEI); 69823559Ssklower } 69916208Skarels #endif 700