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*37508Smckusick * @(#)if_de.c 7.8 (Berkeley) 04/25/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 */ 32*37508Smckusick #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" 6537476Ssklower #include "../netiso/iso_snpac.h" 6637476Ssklower extern struct snpa_cache all_es, all_is; 6737476Ssklower #endif 6837476Ssklower 6915357Skarels #include "../vax/cpu.h" 7015357Skarels #include "../vax/mtpr.h" 7117110Sbloom #include "if_dereg.h" 7217110Sbloom #include "if_uba.h" 7315357Skarels #include "../vaxuba/ubareg.h" 7415357Skarels #include "../vaxuba/ubavar.h" 7515357Skarels 7623559Ssklower #define NXMT 3 /* number of transmit buffers */ 7723559Ssklower #define NRCV 7 /* number of receive buffers (must be > 1) */ 7815357Skarels 7916279Skarels int dedebug = 0; 8015916Skarels 8115357Skarels int deprobe(), deattach(), deintr(); 8215357Skarels struct uba_device *deinfo[NDE]; 8315357Skarels u_short destd[] = { 0 }; 8415357Skarels struct uba_driver dedriver = 8515357Skarels { deprobe, 0, deattach, 0, destd, "de", deinfo }; 8637187Ssklower int deinit(),ether_output(),deioctl(),dereset(),destart(); 8715357Skarels 8815357Skarels 8915357Skarels /* 9015357Skarels * Ethernet software status per interface. 9115357Skarels * 9215357Skarels * Each interface is referenced by a network interface structure, 9315357Skarels * ds_if, which the routing code uses to locate the interface. 9415357Skarels * This structure contains the output queue for the interface, its address, ... 9515357Skarels * We also have, for each interface, a UBA interface structure, which 9615357Skarels * contains information about the UNIBUS resources held by the interface: 9715357Skarels * map registers, buffered data paths, etc. Information is cached in this 9815357Skarels * structure for use by the if_uba.c routines in running the interface 9915357Skarels * efficiently. 10015357Skarels */ 10115357Skarels struct de_softc { 10215357Skarels struct arpcom ds_ac; /* Ethernet common part */ 10315357Skarels #define ds_if ds_ac.ac_if /* network-visible interface */ 10415357Skarels #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ 10515357Skarels int ds_flags; 10615357Skarels #define DSF_LOCK 1 /* lock out destart */ 10725448Skarels #define DSF_RUNNING 2 /* board is enabled */ 10825448Skarels #define DSF_SETADDR 4 /* physical address is changed */ 10915357Skarels int ds_ubaddr; /* map info for incore structs */ 11024795Skarels struct ifubinfo ds_deuba; /* unibus resource structure */ 11124795Skarels struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ 11224795Skarels struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ 11315357Skarels /* the following structures are always mapped in */ 11415357Skarels struct de_pcbb ds_pcbb; /* port control block */ 11515357Skarels struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ 11615357Skarels struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ 11715357Skarels struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ 11815357Skarels /* end mapped area */ 11915357Skarels #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) 12015357Skarels #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) 12115357Skarels #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) 12215357Skarels #define PCBB_OFFSET RVAL_OFF(ds_pcbb) 12315357Skarels #define XRENT_OFFSET LVAL_OFF(ds_xrent) 12415357Skarels #define RRENT_OFFSET LVAL_OFF(ds_rrent) 12515357Skarels #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) 12615357Skarels #define INCORE_SIZE RVAL_OFF(ds_xindex) 12715357Skarels int ds_xindex; /* UNA index into transmit chain */ 12815357Skarels int ds_rindex; /* UNA index into receive chain */ 12915357Skarels int ds_xfree; /* index for next transmit buffer */ 13015357Skarels int ds_nxmit; /* # of transmits in progress */ 13115357Skarels } de_softc[NDE]; 13215357Skarels 13315357Skarels deprobe(reg) 13415357Skarels caddr_t reg; 13515357Skarels { 13615357Skarels register int br, cvec; /* r11, r10 value-result */ 13715357Skarels register struct dedevice *addr = (struct dedevice *)reg; 13815357Skarels register i; 13915357Skarels 14015357Skarels #ifdef lint 14115357Skarels br = 0; cvec = br; br = cvec; 14215357Skarels i = 0; derint(i); deintr(i); 14315357Skarels #endif 14415357Skarels 14529572Skarels /* 14629572Skarels * Make sure self-test is finished before we screw with the board. 14729572Skarels * Self-test on a DELUA can take 15 seconds (argh). 14829572Skarels */ 14929572Skarels for (i = 0; 15029572Skarels i < 160 && 15129572Skarels (addr->pcsr0 & PCSR0_FATI) == 0 && 15229572Skarels (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; 15329572Skarels ++i) 15429572Skarels DELAY(100000); 15529572Skarels if ((addr->pcsr0 & PCSR0_FATI) != 0 || 15629572Skarels (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) 15729572Skarels return(0); 15829572Skarels 15929572Skarels addr->pcsr0 = 0; 16029572Skarels DELAY(100); 16115357Skarels addr->pcsr0 = PCSR0_RSET; 16215357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 16315357Skarels ; 16415357Skarels /* make board interrupt by executing a GETPCBB command */ 16515357Skarels addr->pcsr0 = PCSR0_INTE; 16615357Skarels addr->pcsr2 = 0; 16715357Skarels addr->pcsr3 = 0; 16815357Skarels addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; 16915357Skarels DELAY(100000); 17015357Skarels return(1); 17115357Skarels } 17215357Skarels 17315357Skarels /* 17415357Skarels * Interface exists: make available by filling in network interface 17515357Skarels * record. System will initialize the interface when it is ready 17615357Skarels * to accept packets. We get the ethernet address here. 17715357Skarels */ 17815357Skarels deattach(ui) 17915357Skarels struct uba_device *ui; 18015357Skarels { 18115357Skarels register struct de_softc *ds = &de_softc[ui->ui_unit]; 18215357Skarels register struct ifnet *ifp = &ds->ds_if; 18315357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 18429572Skarels int csr1; 18515357Skarels 18615357Skarels ifp->if_unit = ui->ui_unit; 18715357Skarels ifp->if_name = "de"; 18815357Skarels ifp->if_mtu = ETHERMTU; 18919861Skarels ifp->if_flags = IFF_BROADCAST; 19015357Skarels 19115357Skarels /* 19229572Skarels * What kind of a board is this? 19329572Skarels * The error bits 4-6 in pcsr1 are a device id as long as 19429572Skarels * the high byte is zero. 19529572Skarels */ 19629572Skarels csr1 = addr->pcsr1; 19729572Skarels if (csr1 & 0xff60) 19829572Skarels printf("de%d: broken\n", ui->ui_unit); 19929572Skarels else if (csr1 & 0x10) 20029572Skarels printf("de%d: delua\n", ui->ui_unit); 20129572Skarels else 20229572Skarels printf("de%d: deuna\n", ui->ui_unit); 20329572Skarels 20429572Skarels /* 20515357Skarels * Reset the board and temporarily map 20615357Skarels * the pcbb buffer onto the Unibus. 20715357Skarels */ 20829572Skarels addr->pcsr0 = 0; /* reset INTE */ 20929572Skarels DELAY(100); 21015357Skarels addr->pcsr0 = PCSR0_RSET; 21125633Skarels (void)dewait(ui, "reset"); 21225633Skarels 21315357Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, 21415357Skarels sizeof (struct de_pcbb), 0); 21515357Skarels addr->pcsr2 = ds->ds_ubaddr & 0xffff; 21615357Skarels addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; 21715357Skarels addr->pclow = CMD_GETPCBB; 21825633Skarels (void)dewait(ui, "pcbb"); 21925633Skarels 22015357Skarels ds->ds_pcbb.pcbb0 = FC_RDPHYAD; 22115357Skarels addr->pclow = CMD_GETCMD; 22225633Skarels (void)dewait(ui, "read addr "); 22325633Skarels 22415357Skarels ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); 22519861Skarels bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, 22615357Skarels sizeof (ds->ds_addr)); 22725974Skarels printf("de%d: hardware address %s\n", ui->ui_unit, 22825974Skarels ether_sprintf(ds->ds_addr)); 22915357Skarels ifp->if_init = deinit; 23037187Ssklower ifp->if_output = ether_output; 23115357Skarels ifp->if_ioctl = deioctl; 23215357Skarels ifp->if_reset = dereset; 23337187Ssklower ifp->if_start = destart; 23424795Skarels ds->ds_deuba.iff_flags = UBA_CANTWAIT; 23515357Skarels #ifdef notdef 23615357Skarels /* CAN WE USE BDP's ??? */ 23724795Skarels ds->ds_deuba.iff_flags |= UBA_NEEDBDP; 23815357Skarels #endif 23915357Skarels if_attach(ifp); 24015357Skarels } 24115357Skarels 24215357Skarels /* 24315357Skarels * Reset of interface after UNIBUS reset. 24415357Skarels * If interface is on specified uba, reset its state. 24515357Skarels */ 24615357Skarels dereset(unit, uban) 24715357Skarels int unit, uban; 24815357Skarels { 24915357Skarels register struct uba_device *ui; 25015357Skarels 25115357Skarels if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || 25215357Skarels ui->ui_ubanum != uban) 25315357Skarels return; 25415357Skarels printf(" de%d", unit); 25537187Ssklower de_softc[unit].ds_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 25637187Ssklower de_softc[unit].ds_flags &= ~DSF_RUNNING; 25732660Skarels ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET; 25832660Skarels (void)dewait(ui, "reset"); 25915357Skarels deinit(unit); 26015357Skarels } 26115357Skarels 26215357Skarels /* 26315357Skarels * Initialization of interface; clear recorded pending 26415357Skarels * operations, and reinitialize UNIBUS usage. 26515357Skarels */ 26615357Skarels deinit(unit) 26715357Skarels int unit; 26815357Skarels { 26915357Skarels register struct de_softc *ds = &de_softc[unit]; 27015357Skarels register struct uba_device *ui = deinfo[unit]; 27115357Skarels register struct dedevice *addr; 27215357Skarels register struct ifrw *ifrw; 27316208Skarels register struct ifxmt *ifxp; 27416208Skarels struct ifnet *ifp = &ds->ds_if; 27515357Skarels int s; 27615357Skarels struct de_ring *rp; 27715357Skarels int incaddr; 27815357Skarels 27919861Skarels /* not yet, if address still unknown */ 28019861Skarels if (ifp->if_addrlist == (struct ifaddr *)0) 28115357Skarels return; 28215357Skarels 28325448Skarels if (ds->ds_flags & DSF_RUNNING) 28419861Skarels return; 28525448Skarels if ((ifp->if_flags & IFF_RUNNING) == 0) { 28625448Skarels if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, 28725448Skarels sizeof (struct ether_header), (int)btoc(ETHERMTU), 28825448Skarels ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { 28925448Skarels printf("de%d: can't initialize\n", unit); 29025448Skarels ds->ds_if.if_flags &= ~IFF_UP; 29125448Skarels return; 29225448Skarels } 29325448Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), 29425448Skarels INCORE_SIZE, 0); 29515357Skarels } 29615357Skarels addr = (struct dedevice *)ui->ui_addr; 29715357Skarels 29815357Skarels /* set the pcbb block address */ 29915357Skarels incaddr = ds->ds_ubaddr + PCBB_OFFSET; 30015357Skarels addr->pcsr2 = incaddr & 0xffff; 30115357Skarels addr->pcsr3 = (incaddr >> 16) & 0x3; 30229572Skarels addr->pclow = 0; /* reset INTE */ 30329572Skarels DELAY(100); 30415357Skarels addr->pclow = CMD_GETPCBB; 30525633Skarels (void)dewait(ui, "pcbb"); 30615357Skarels 30715357Skarels /* set the transmit and receive ring header addresses */ 30815357Skarels incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; 30915357Skarels ds->ds_pcbb.pcbb0 = FC_WTRING; 31015357Skarels ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 31115357Skarels ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 31215357Skarels 31315357Skarels incaddr = ds->ds_ubaddr + XRENT_OFFSET; 31415357Skarels ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; 31515357Skarels ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; 31615357Skarels ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); 31715357Skarels ds->ds_udbbuf.b_trlen = NXMT; 31815357Skarels incaddr = ds->ds_ubaddr + RRENT_OFFSET; 31915357Skarels ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; 32015357Skarels ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; 32115357Skarels ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); 32215357Skarels ds->ds_udbbuf.b_rrlen = NRCV; 32315357Skarels 32415357Skarels addr->pclow = CMD_GETCMD; 32525633Skarels (void)dewait(ui, "wtring"); 32615357Skarels 32715357Skarels /* initialize the mode - enable hardware padding */ 32815357Skarels ds->ds_pcbb.pcbb0 = FC_WTMODE; 32915357Skarels /* let hardware do padding - set MTCH bit on broadcast */ 33015357Skarels ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; 33115357Skarels addr->pclow = CMD_GETCMD; 33225633Skarels (void)dewait(ui, "wtmode"); 33315357Skarels 33415357Skarels /* set up the receive and transmit ring entries */ 33524795Skarels ifxp = &ds->ds_ifw[0]; 33615357Skarels for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { 33724795Skarels rp->r_segbl = ifxp->ifw_info & 0xffff; 33824795Skarels rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; 33915357Skarels rp->r_flags = 0; 34016208Skarels ifxp++; 34115357Skarels } 34224795Skarels ifrw = &ds->ds_ifr[0]; 34315357Skarels for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { 34415357Skarels rp->r_slen = sizeof (struct de_buf); 34515357Skarels rp->r_segbl = ifrw->ifrw_info & 0xffff; 34615357Skarels rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; 34715357Skarels rp->r_flags = RFLG_OWN; /* hang receive */ 34815357Skarels ifrw++; 34915357Skarels } 35015357Skarels 35115357Skarels /* start up the board (rah rah) */ 35215357Skarels s = splimp(); 35325448Skarels ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; 35419861Skarels ds->ds_if.if_flags |= IFF_RUNNING; 35529572Skarels addr->pclow = PCSR0_INTE; /* avoid interlock */ 35637187Ssklower (void) destart(&ds->ds_if); /* queue output packets */ 35725633Skarels ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ 35825448Skarels if (ds->ds_flags & DSF_SETADDR) 35925448Skarels de_setaddr(ds->ds_addr, unit); 36025633Skarels addr->pclow = CMD_START | PCSR0_INTE; 36115357Skarels splx(s); 36215357Skarels } 36315357Skarels 36415357Skarels /* 36515357Skarels * Setup output on interface. 36615357Skarels * Get another datagram to send off of the interface queue, 36715357Skarels * and map it to the interface before starting the output. 36815357Skarels */ 36937187Ssklower destart(ifp) 37037187Ssklower struct ifnet *ifp; 37115357Skarels { 37215357Skarels int len; 37337187Ssklower int unit = ifp->if_unit; 37415357Skarels struct uba_device *ui = deinfo[unit]; 37515357Skarels struct dedevice *addr = (struct dedevice *)ui->ui_addr; 37615357Skarels register struct de_softc *ds = &de_softc[unit]; 37715357Skarels register struct de_ring *rp; 37815357Skarels struct mbuf *m; 37915357Skarels register int nxmit; 38015357Skarels 38115357Skarels /* 38215357Skarels * the following test is necessary, since 38315357Skarels * the code is not reentrant and we have 38415357Skarels * multiple transmission buffers. 38515357Skarels */ 38637187Ssklower if (ds->ds_if.if_flags & IFF_OACTIVE) 38737187Ssklower return (0); 38815357Skarels for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { 38915357Skarels IF_DEQUEUE(&ds->ds_if.if_snd, m); 39015357Skarels if (m == 0) 39115357Skarels break; 39215357Skarels rp = &ds->ds_xrent[ds->ds_xfree]; 39315357Skarels if (rp->r_flags & XFLG_OWN) 39415357Skarels panic("deuna xmit in progress"); 39524795Skarels len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); 39624795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 39724795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 39824795Skarels ds->ds_ifw[ds->ds_xfree].ifw_bdp); 39915357Skarels rp->r_slen = len; 40015357Skarels rp->r_tdrerr = 0; 40115357Skarels rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; 40215357Skarels 40315357Skarels ds->ds_xfree++; 40415357Skarels if (ds->ds_xfree == NXMT) 40515357Skarels ds->ds_xfree = 0; 40615357Skarels } 40715357Skarels if (ds->ds_nxmit != nxmit) { 40815357Skarels ds->ds_nxmit = nxmit; 40915916Skarels if (ds->ds_flags & DSF_RUNNING) 41015357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 41115357Skarels } 41237187Ssklower return (0); 41315357Skarels } 41415357Skarels 41515357Skarels /* 41615357Skarels * Command done interrupt. 41715357Skarels */ 41815357Skarels deintr(unit) 41915357Skarels int unit; 42015357Skarels { 42115357Skarels struct uba_device *ui = deinfo[unit]; 42215357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 42315357Skarels register struct de_softc *ds = &de_softc[unit]; 42415357Skarels register struct de_ring *rp; 42516208Skarels register struct ifxmt *ifxp; 42615357Skarels short csr0; 42715357Skarels 42815357Skarels /* save flags right away - clear out interrupt bits */ 42915357Skarels csr0 = addr->pcsr0; 43015357Skarels addr->pchigh = csr0 >> 8; 43115357Skarels 43215357Skarels 43337187Ssklower ds->ds_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */ 43415357Skarels /* 43515357Skarels * if receive, put receive buffer on mbuf 43615357Skarels * and hang the request again 43715357Skarels */ 43815357Skarels derecv(unit); 43915357Skarels 44015357Skarels /* 44115357Skarels * Poll transmit ring and check status. 44215357Skarels * Be careful about loopback requests. 44315357Skarels * Then free buffer space and check for 44415357Skarels * more transmit requests. 44515357Skarels */ 44615357Skarels for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { 44715357Skarels rp = &ds->ds_xrent[ds->ds_xindex]; 44815357Skarels if (rp->r_flags & XFLG_OWN) 44915357Skarels break; 45015357Skarels ds->ds_if.if_opackets++; 45124795Skarels ifxp = &ds->ds_ifw[ds->ds_xindex]; 45215357Skarels /* check for unusual conditions */ 45315357Skarels if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { 45415357Skarels if (rp->r_flags & XFLG_ERRS) { 45515357Skarels /* output error */ 45615357Skarels ds->ds_if.if_oerrors++; 45715916Skarels if (dedebug) 45815357Skarels printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", 45915357Skarels unit, rp->r_flags, XFLG_BITS, 46015357Skarels rp->r_tdrerr, XERR_BITS, rp->r_slen); 46115357Skarels } else if (rp->r_flags & XFLG_ONE) { 46215357Skarels /* one collision */ 46315357Skarels ds->ds_if.if_collisions++; 46415357Skarels } else if (rp->r_flags & XFLG_MORE) { 46515357Skarels /* more than one collision */ 46615357Skarels ds->ds_if.if_collisions += 2; /* guess */ 46715357Skarels } else if (rp->r_flags & XFLG_MTCH) { 46815357Skarels /* received our own packet */ 46915357Skarels ds->ds_if.if_ipackets++; 47024795Skarels deread(ds, &ifxp->ifrw, 47115357Skarels rp->r_slen - sizeof (struct ether_header)); 47215357Skarels } 47315357Skarels } 47424795Skarels if (ifxp->ifw_xtofree) { 47524795Skarels m_freem(ifxp->ifw_xtofree); 47624795Skarels ifxp->ifw_xtofree = 0; 47716208Skarels } 47815357Skarels /* check if next transmit buffer also finished */ 47915357Skarels ds->ds_xindex++; 48015357Skarels if (ds->ds_xindex == NXMT) 48115357Skarels ds->ds_xindex = 0; 48215357Skarels } 48337187Ssklower ds->ds_if.if_flags &= ~IFF_OACTIVE; 48437187Ssklower (void) destart(&ds->ds_if); 48515357Skarels 48615357Skarels if (csr0 & PCSR0_RCBI) { 48725633Skarels if (dedebug) 48825633Skarels log(LOG_WARNING, "de%d: buffer unavailable\n", unit); 48915357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 49015357Skarels } 49115357Skarels } 49215357Skarels 49315357Skarels /* 49415357Skarels * Ethernet interface receiver interface. 49515357Skarels * If input error just drop packet. 49615357Skarels * Otherwise purge input buffered data path and examine 49715357Skarels * packet to determine type. If can't determine length 49815357Skarels * from type, then have to drop packet. Othewise decapsulate 49915357Skarels * packet based on type and pass to type specific higher-level 50015357Skarels * input routine. 50115357Skarels */ 50215357Skarels derecv(unit) 50315357Skarels int unit; 50415357Skarels { 50515357Skarels register struct de_softc *ds = &de_softc[unit]; 50615357Skarels register struct de_ring *rp; 50715357Skarels int len; 50815357Skarels 50915357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 51015357Skarels while ((rp->r_flags & RFLG_OWN) == 0) { 51115357Skarels ds->ds_if.if_ipackets++; 51224795Skarels if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 51324795Skarels UBAPURGE(ds->ds_deuba.iff_uba, 51424795Skarels ds->ds_ifr[ds->ds_rindex].ifrw_bdp); 51515357Skarels len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) 51615357Skarels - 4; /* don't forget checksum! */ 51715357Skarels /* check for errors */ 51815357Skarels if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || 51915357Skarels (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || 52015357Skarels (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || 52115357Skarels len < ETHERMIN || len > ETHERMTU) { 52215357Skarels ds->ds_if.if_ierrors++; 52315916Skarels if (dedebug) 52415357Skarels printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", 52515357Skarels unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, 52615357Skarels RERR_BITS, len); 52715357Skarels } else 52824795Skarels deread(ds, &ds->ds_ifr[ds->ds_rindex], len); 52915357Skarels 53015357Skarels /* hang the receive buffer again */ 53115357Skarels rp->r_lenerr = 0; 53215357Skarels rp->r_flags = RFLG_OWN; 53315357Skarels 53415357Skarels /* check next receive buffer */ 53515357Skarels ds->ds_rindex++; 53615357Skarels if (ds->ds_rindex == NRCV) 53715357Skarels ds->ds_rindex = 0; 53815357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 53915357Skarels } 54015357Skarels } 54115357Skarels 54215357Skarels /* 54315357Skarels * Pass a packet to the higher levels. 54415357Skarels * We deal with the trailer protocol here. 54515357Skarels */ 54615357Skarels deread(ds, ifrw, len) 54715357Skarels register struct de_softc *ds; 54815357Skarels struct ifrw *ifrw; 54915357Skarels int len; 55015357Skarels { 55115357Skarels struct ether_header *eh; 55215357Skarels struct mbuf *m; 55315357Skarels int off, resid; 55416722Sbloom int s; 55515357Skarels register struct ifqueue *inq; 55615357Skarels 55715357Skarels /* 55819861Skarels * Deal with trailer protocol: if type is trailer type 55915357Skarels * get true type from first 16-bit word past data. 56015357Skarels * Remember that type was trailer by setting off. 56115357Skarels */ 56215357Skarels eh = (struct ether_header *)ifrw->ifrw_addr; 56315357Skarels eh->ether_type = ntohs((u_short)eh->ether_type); 56415357Skarels #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 56519861Skarels if (eh->ether_type >= ETHERTYPE_TRAIL && 56619861Skarels eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 56719861Skarels off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 56815357Skarels if (off >= ETHERMTU) 56915357Skarels return; /* sanity */ 57015357Skarels eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); 57115357Skarels resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); 57215357Skarels if (off + resid > len) 57315357Skarels return; /* sanity */ 57415357Skarels len = off + resid; 57515357Skarels } else 57615357Skarels off = 0; 57715357Skarels if (len == 0) 57815357Skarels return; 57915357Skarels 58015357Skarels /* 58115357Skarels * Pull packet off interface. Off is nonzero if packet 58224795Skarels * has trailing header; if_ubaget will then force this header 58315357Skarels * information to be at the front, but we still have to drop 58415357Skarels * the type and length which are at the front of any trailer data. 58515357Skarels */ 58624795Skarels m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); 58715357Skarels if (m == 0) 58815357Skarels return; 58937187Ssklower ether_input(&ds->ds_if, eh, m); 59024795Skarels 59116722Sbloom s = splimp(); 59215357Skarels if (IF_QFULL(inq)) { 59315357Skarels IF_DROP(inq); 59415357Skarels m_freem(m); 59537187Ssklower } else 59637187Ssklower IF_ENQUEUE(inq, m); 59716722Sbloom splx(s); 59815357Skarels } 59915357Skarels /* 60015357Skarels * Process an ioctl request. 60115357Skarels */ 60215357Skarels deioctl(ifp, cmd, data) 60315357Skarels register struct ifnet *ifp; 60415357Skarels int cmd; 60515357Skarels caddr_t data; 60615357Skarels { 60719861Skarels register struct ifaddr *ifa = (struct ifaddr *)data; 60825448Skarels register struct de_softc *ds = &de_softc[ifp->if_unit]; 60915357Skarels int s = splimp(), error = 0; 61015357Skarels 61115357Skarels switch (cmd) { 61215357Skarels 61315357Skarels case SIOCSIFADDR: 61419861Skarels ifp->if_flags |= IFF_UP; 61515357Skarels deinit(ifp->if_unit); 61619861Skarels 61737187Ssklower switch (ifa->ifa_addr->sa_family) { 61823503Ssklower #ifdef INET 61919861Skarels case AF_INET: 62019861Skarels ((struct arpcom *)ifp)->ac_ipaddr = 62119861Skarels IA_SIN(ifa)->sin_addr; 62219861Skarels arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 62319861Skarels break; 62423503Ssklower #endif 62523503Ssklower #ifdef NS 62623503Ssklower case AF_NS: 62723559Ssklower { 62823559Ssklower register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 62923559Ssklower 63025448Skarels if (ns_nullhost(*ina)) 63125448Skarels ina->x_host = *(union ns_host *)(ds->ds_addr); 63225448Skarels else 63323559Ssklower de_setaddr(ina->x_host.c_host,ifp->if_unit); 63423503Ssklower break; 63523559Ssklower } 63623503Ssklower #endif 63719861Skarels } 63815357Skarels break; 63915357Skarels 64025448Skarels case SIOCSIFFLAGS: 64125448Skarels if ((ifp->if_flags & IFF_UP) == 0 && 64225448Skarels ds->ds_flags & DSF_RUNNING) { 64325448Skarels ((struct dedevice *) 64429572Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = 0; 64529572Skarels DELAY(100); 64629572Skarels ((struct dedevice *) 64725448Skarels (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; 64837187Ssklower ds->ds_flags &= ~DSF_RUNNING; 64937187Ssklower ds->ds_if.if_flags &= ~IFF_OACTIVE; 65025448Skarels } else if (ifp->if_flags & IFF_UP && 65125448Skarels (ds->ds_flags & DSF_RUNNING) == 0) 65225448Skarels deinit(ifp->if_unit); 65325448Skarels break; 65425448Skarels 65515357Skarels default: 65615357Skarels error = EINVAL; 65715357Skarels } 65815357Skarels splx(s); 65915357Skarels return (error); 66015357Skarels } 66123559Ssklower 66223559Ssklower /* 66323559Ssklower * set ethernet address for unit 66423559Ssklower */ 66523559Ssklower de_setaddr(physaddr, unit) 66625448Skarels u_char *physaddr; 66725448Skarels int unit; 66823559Ssklower { 66923559Ssklower register struct de_softc *ds = &de_softc[unit]; 67025633Skarels struct uba_device *ui = deinfo[unit]; 67123559Ssklower register struct dedevice *addr= (struct dedevice *)ui->ui_addr; 67223559Ssklower 67323672Ssklower if (! (ds->ds_flags & DSF_RUNNING)) 67423672Ssklower return; 67523672Ssklower 67634502Skarels bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6); 67723559Ssklower ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 67825448Skarels addr->pclow = PCSR0_INTE|CMD_GETCMD; 67925633Skarels if (dewait(ui, "address change") == 0) { 68025633Skarels ds->ds_flags |= DSF_SETADDR; 68134502Skarels bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6); 68225633Skarels } 68325633Skarels } 68425633Skarels 68525633Skarels /* 68625633Skarels * Await completion of the named function 68725633Skarels * and check for errors. 68825633Skarels */ 68925633Skarels dewait(ui, fn) 69025633Skarels register struct uba_device *ui; 69125633Skarels char *fn; 69225633Skarels { 69325633Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 69425633Skarels register csr0; 69525633Skarels 69625448Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 69725448Skarels ; 69823559Ssklower csr0 = addr->pcsr0; 69923559Ssklower addr->pchigh = csr0 >> 8; 70023559Ssklower if (csr0 & PCSR0_PCEI) 70125633Skarels printf("de%d: %s failed, csr0=%b csr1=%b\n", 70225633Skarels ui->ui_unit, fn, csr0, PCSR0_BITS, 70323559Ssklower addr->pcsr1, PCSR1_BITS); 70425633Skarels return (csr0 & PCSR0_PCEI); 70523559Ssklower } 70616208Skarels #endif 707