123503Ssklower /* 223503Ssklower * Copyright (c) 1982 Regents of the University of California. 323503Ssklower * All rights reserved. The Berkeley software License Agreement 423503Ssklower * specifies the terms and conditions for redistribution. 523503Ssklower * 6*23672Ssklower * @(#)if_de.c 6.12 (Berkeley) 06/22/85 723503Ssklower */ 815357Skarels #include "de.h" 915357Skarels #if NDE > 0 1015357Skarels 1115357Skarels /* 1215357Skarels * DEC DEUNA interface 1315357Skarels * 1415357Skarels * Lou Salkind 1515357Skarels * New York University 1615357Skarels * 1715357Skarels * TODO: 1815357Skarels * timeout routine (get statistics) 1915357Skarels */ 2015357Skarels #include "../machine/pte.h" 2115357Skarels 2217110Sbloom #include "param.h" 2317110Sbloom #include "systm.h" 2417110Sbloom #include "mbuf.h" 2517110Sbloom #include "buf.h" 2617110Sbloom #include "protosw.h" 2717110Sbloom #include "socket.h" 2817110Sbloom #include "vmmac.h" 2917110Sbloom #include "ioctl.h" 3017110Sbloom #include "errno.h" 3115357Skarels 3215357Skarels #include "../net/if.h" 3315357Skarels #include "../net/netisr.h" 3415357Skarels #include "../net/route.h" 3523503Ssklower 3623503Ssklower #ifdef INET 3715357Skarels #include "../netinet/in.h" 3815357Skarels #include "../netinet/in_systm.h" 3919861Skarels #include "../netinet/in_var.h" 4015357Skarels #include "../netinet/ip.h" 4115357Skarels #include "../netinet/ip_var.h" 4215357Skarels #include "../netinet/if_ether.h" 4323503Ssklower #endif 4423503Ssklower 4519952Sbloom #ifdef PUP 4615357Skarels #include "../netpup/pup.h" 4719952Sbloom #endif 4815357Skarels 4923503Ssklower #ifdef NS 5023503Ssklower #include "../netns/ns.h" 5123503Ssklower #include "../netns/ns_if.h" 5223503Ssklower #endif 5323503Ssklower 5415357Skarels #include "../vax/cpu.h" 5515357Skarels #include "../vax/mtpr.h" 5617110Sbloom #include "if_dereg.h" 5717110Sbloom #include "if_uba.h" 5815357Skarels #include "../vaxuba/ubareg.h" 5915357Skarels #include "../vaxuba/ubavar.h" 6015357Skarels 6123559Ssklower #define NXMT 3 /* number of transmit buffers */ 6223559Ssklower #define NRCV 7 /* number of receive buffers (must be > 1) */ 6315357Skarels #define NTOT (NXMT + NRCV) 6415357Skarels 6516279Skarels int dedebug = 0; 6615916Skarels 6715357Skarels int deprobe(), deattach(), deintr(); 6815357Skarels struct uba_device *deinfo[NDE]; 6915357Skarels u_short destd[] = { 0 }; 7015357Skarels struct uba_driver dedriver = 7115357Skarels { deprobe, 0, deattach, 0, destd, "de", deinfo }; 7215357Skarels int deinit(),deoutput(),deioctl(),dereset(); 7315357Skarels struct mbuf *deget(); 7415357Skarels 7515357Skarels 7615357Skarels /* 7716208Skarels * The deuba structures generalizes the ifuba structure 7816208Skarels * to an arbitrary number of receive and transmit buffers. 7915357Skarels */ 8016208Skarels struct ifxmt { 8116208Skarels struct ifrw x_ifrw; /* mapping information */ 8216208Skarels struct pte x_map[IF_MAXNUBAMR]; /* output base pages */ 8316208Skarels short x_xswapd; /* mask of clusters swapped */ 8416208Skarels struct mbuf *x_xtofree; /* pages being dma'ed out */ 8516208Skarels }; 8616208Skarels 8715357Skarels struct deuba { 8815357Skarels short ifu_uban; /* uba number */ 8915357Skarels short ifu_hlen; /* local net header length */ 9015357Skarels struct uba_regs *ifu_uba; /* uba regs, in vm */ 9115357Skarels struct ifrw ifu_r[NRCV]; /* receive information */ 9216208Skarels struct ifxmt ifu_w[NXMT]; /* transmit information */ 9315357Skarels short ifu_flags; /* used during uballoc's */ 9415357Skarels }; 9515357Skarels 9615357Skarels /* 9715357Skarels * Ethernet software status per interface. 9815357Skarels * 9915357Skarels * Each interface is referenced by a network interface structure, 10015357Skarels * ds_if, which the routing code uses to locate the interface. 10115357Skarels * This structure contains the output queue for the interface, its address, ... 10215357Skarels * We also have, for each interface, a UBA interface structure, which 10315357Skarels * contains information about the UNIBUS resources held by the interface: 10415357Skarels * map registers, buffered data paths, etc. Information is cached in this 10515357Skarels * structure for use by the if_uba.c routines in running the interface 10615357Skarels * efficiently. 10715357Skarels */ 10815357Skarels struct de_softc { 10915357Skarels struct arpcom ds_ac; /* Ethernet common part */ 11015357Skarels #define ds_if ds_ac.ac_if /* network-visible interface */ 11115357Skarels #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ 11215357Skarels int ds_flags; 11315357Skarels #define DSF_LOCK 1 /* lock out destart */ 11415916Skarels #define DSF_RUNNING 2 11515357Skarels int ds_ubaddr; /* map info for incore structs */ 11615357Skarels struct deuba ds_deuba; /* unibus resource structure */ 11715357Skarels /* the following structures are always mapped in */ 11815357Skarels struct de_pcbb ds_pcbb; /* port control block */ 11915357Skarels struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ 12015357Skarels struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ 12115357Skarels struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ 12215357Skarels /* end mapped area */ 12315357Skarels #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) 12415357Skarels #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) 12515357Skarels #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) 12615357Skarels #define PCBB_OFFSET RVAL_OFF(ds_pcbb) 12715357Skarels #define XRENT_OFFSET LVAL_OFF(ds_xrent) 12815357Skarels #define RRENT_OFFSET LVAL_OFF(ds_rrent) 12915357Skarels #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) 13015357Skarels #define INCORE_SIZE RVAL_OFF(ds_xindex) 13115357Skarels int ds_xindex; /* UNA index into transmit chain */ 13215357Skarels int ds_rindex; /* UNA index into receive chain */ 13315357Skarels int ds_xfree; /* index for next transmit buffer */ 13415357Skarels int ds_nxmit; /* # of transmits in progress */ 13515357Skarels } de_softc[NDE]; 13615357Skarels 13715357Skarels deprobe(reg) 13815357Skarels caddr_t reg; 13915357Skarels { 14015357Skarels register int br, cvec; /* r11, r10 value-result */ 14115357Skarels register struct dedevice *addr = (struct dedevice *)reg; 14215357Skarels register i; 14315357Skarels 14415357Skarels #ifdef lint 14515357Skarels br = 0; cvec = br; br = cvec; 14615357Skarels i = 0; derint(i); deintr(i); 14715357Skarels #endif 14815357Skarels 14915357Skarels addr->pcsr0 = PCSR0_RSET; 15015357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 15115357Skarels ; 15215357Skarels /* make board interrupt by executing a GETPCBB command */ 15315357Skarels addr->pcsr0 = PCSR0_INTE; 15415357Skarels addr->pcsr2 = 0; 15515357Skarels addr->pcsr3 = 0; 15615357Skarels addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; 15715357Skarels DELAY(100000); 15815357Skarels return(1); 15915357Skarels } 16015357Skarels 16115357Skarels /* 16215357Skarels * Interface exists: make available by filling in network interface 16315357Skarels * record. System will initialize the interface when it is ready 16415357Skarels * to accept packets. We get the ethernet address here. 16515357Skarels */ 16615357Skarels deattach(ui) 16715357Skarels struct uba_device *ui; 16815357Skarels { 16915357Skarels register struct de_softc *ds = &de_softc[ui->ui_unit]; 17015357Skarels register struct ifnet *ifp = &ds->ds_if; 17115357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 17215357Skarels int csr0; 17315357Skarels 17415357Skarels ifp->if_unit = ui->ui_unit; 17515357Skarels ifp->if_name = "de"; 17615357Skarels ifp->if_mtu = ETHERMTU; 17719861Skarels ifp->if_flags = IFF_BROADCAST; 17815357Skarels 17915357Skarels /* 18015357Skarels * Reset the board and temporarily map 18115357Skarels * the pcbb buffer onto the Unibus. 18215357Skarels */ 18315357Skarels addr->pcsr0 = PCSR0_RSET; 18415357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 18515357Skarels ; 18615357Skarels csr0 = addr->pcsr0; 18715357Skarels addr->pchigh = csr0 >> 8; 18815357Skarels if (csr0 & PCSR0_PCEI) 18915357Skarels printf("de%d: reset failed, csr0=%b csr1=%b\n", ui->ui_unit, 19015357Skarels csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); 19115357Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, 19215357Skarels sizeof (struct de_pcbb), 0); 19315357Skarels addr->pcsr2 = ds->ds_ubaddr & 0xffff; 19415357Skarels addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; 19515357Skarels addr->pclow = CMD_GETPCBB; 19615357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 19715357Skarels ; 19815357Skarels csr0 = addr->pcsr0; 19915357Skarels addr->pchigh = csr0 >> 8; 20015357Skarels if (csr0 & PCSR0_PCEI) 20115357Skarels printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit, 20215357Skarels csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); 20315357Skarels ds->ds_pcbb.pcbb0 = FC_RDPHYAD; 20415357Skarels addr->pclow = CMD_GETCMD; 20515357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 20615357Skarels ; 20715357Skarels csr0 = addr->pcsr0; 20815357Skarels addr->pchigh = csr0 >> 8; 20915357Skarels if (csr0 & PCSR0_PCEI) 21015357Skarels printf("de%d: rdphyad failed, csr0=%b csr1=%b\n", ui->ui_unit, 21115357Skarels csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); 21215357Skarels ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); 21315916Skarels if (dedebug) 21415916Skarels printf("de%d: addr=%d:%d:%d:%d:%d:%d\n", ui->ui_unit, 21515916Skarels ds->ds_pcbb.pcbb2&0xff, (ds->ds_pcbb.pcbb2>>8)&0xff, 21615916Skarels ds->ds_pcbb.pcbb4&0xff, (ds->ds_pcbb.pcbb4>>8)&0xff, 21715916Skarels ds->ds_pcbb.pcbb6&0xff, (ds->ds_pcbb.pcbb6>>8)&0xff); 21819861Skarels bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, 21915357Skarels sizeof (ds->ds_addr)); 22015357Skarels ifp->if_init = deinit; 22115357Skarels ifp->if_output = deoutput; 22215357Skarels ifp->if_ioctl = deioctl; 22315357Skarels ifp->if_reset = dereset; 22415357Skarels ds->ds_deuba.ifu_flags = UBA_CANTWAIT; 22515357Skarels #ifdef notdef 22615357Skarels /* CAN WE USE BDP's ??? */ 22715357Skarels ds->ds_deuba.ifu_flags |= UBA_NEEDBDP; 22815357Skarels #endif 22915357Skarels if_attach(ifp); 23015357Skarels } 23115357Skarels 23215357Skarels /* 23315357Skarels * Reset of interface after UNIBUS reset. 23415357Skarels * If interface is on specified uba, reset its state. 23515357Skarels */ 23615357Skarels dereset(unit, uban) 23715357Skarels int unit, uban; 23815357Skarels { 23915357Skarels register struct uba_device *ui; 24015357Skarels 24115357Skarels if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || 24215357Skarels ui->ui_ubanum != uban) 24315357Skarels return; 24415357Skarels printf(" de%d", unit); 24519861Skarels de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; 24615357Skarels deinit(unit); 24715357Skarels } 24815357Skarels 24915357Skarels /* 25015357Skarels * Initialization of interface; clear recorded pending 25115357Skarels * operations, and reinitialize UNIBUS usage. 25215357Skarels */ 25315357Skarels deinit(unit) 25415357Skarels int unit; 25515357Skarels { 25615357Skarels register struct de_softc *ds = &de_softc[unit]; 25715357Skarels register struct uba_device *ui = deinfo[unit]; 25815357Skarels register struct dedevice *addr; 25915357Skarels register struct ifrw *ifrw; 26016208Skarels register struct ifxmt *ifxp; 26116208Skarels struct ifnet *ifp = &ds->ds_if; 26215357Skarels int s; 26315357Skarels struct de_ring *rp; 26415357Skarels int incaddr; 26515357Skarels int csr0; 26615357Skarels 26719861Skarels /* not yet, if address still unknown */ 26819861Skarels if (ifp->if_addrlist == (struct ifaddr *)0) 26915357Skarels return; 27015357Skarels 27115357Skarels if (ifp->if_flags & IFF_RUNNING) 27219861Skarels return; 27315357Skarels if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum, 27415357Skarels sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 27515357Skarels printf("de%d: can't initialize\n", unit); 27615357Skarels ds->ds_if.if_flags &= ~IFF_UP; 27715357Skarels return; 27815357Skarels } 27915357Skarels ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), INCORE_SIZE,0); 28015357Skarels addr = (struct dedevice *)ui->ui_addr; 28115357Skarels 28215357Skarels /* set the pcbb block address */ 28315357Skarels incaddr = ds->ds_ubaddr + PCBB_OFFSET; 28415357Skarels addr->pcsr2 = incaddr & 0xffff; 28515357Skarels addr->pcsr3 = (incaddr >> 16) & 0x3; 28615357Skarels addr->pclow = CMD_GETPCBB; 28715357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 28815357Skarels ; 28915357Skarels csr0 = addr->pcsr0; 29015357Skarels addr->pchigh = csr0 >> 8; 29115357Skarels if (csr0 & PCSR0_PCEI) 29215357Skarels printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit, 29315357Skarels csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); 29415357Skarels 29515357Skarels /* set the transmit and receive ring header addresses */ 29615357Skarels incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; 29715357Skarels ds->ds_pcbb.pcbb0 = FC_WTRING; 29815357Skarels ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 29915357Skarels ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 30015357Skarels 30115357Skarels incaddr = ds->ds_ubaddr + XRENT_OFFSET; 30215357Skarels ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; 30315357Skarels ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; 30415357Skarels ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); 30515357Skarels ds->ds_udbbuf.b_trlen = NXMT; 30615357Skarels incaddr = ds->ds_ubaddr + RRENT_OFFSET; 30715357Skarels ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; 30815357Skarels ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; 30915357Skarels ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); 31015357Skarels ds->ds_udbbuf.b_rrlen = NRCV; 31115357Skarels 31215357Skarels addr->pclow = CMD_GETCMD; 31315357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 31415357Skarels ; 31515357Skarels csr0 = addr->pcsr0; 31615357Skarels addr->pchigh = csr0 >> 8; 31715357Skarels if (csr0 & PCSR0_PCEI) 31815357Skarels printf("de%d: wtring failed, csr0=%b csr1=%b\n", ui->ui_unit, 31915357Skarels csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); 32015357Skarels 32115357Skarels /* initialize the mode - enable hardware padding */ 32215357Skarels ds->ds_pcbb.pcbb0 = FC_WTMODE; 32315357Skarels /* let hardware do padding - set MTCH bit on broadcast */ 32415357Skarels ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; 32515357Skarels addr->pclow = CMD_GETCMD; 32615357Skarels while ((addr->pcsr0 & PCSR0_INTR) == 0) 32715357Skarels ; 32815357Skarels csr0 = addr->pcsr0; 32915357Skarels addr->pchigh = csr0 >> 8; 33015357Skarels if (csr0 & PCSR0_PCEI) 33115357Skarels printf("de%d: wtmode failed, csr0=%b csr1=%b\n", ui->ui_unit, 33215357Skarels csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS); 33315357Skarels 33415357Skarels /* set up the receive and transmit ring entries */ 33516208Skarels ifxp = &ds->ds_deuba.ifu_w[0]; 33615357Skarels for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { 33716208Skarels rp->r_segbl = ifxp->x_ifrw.ifrw_info & 0xffff; 33816208Skarels rp->r_segbh = (ifxp->x_ifrw.ifrw_info >> 16) & 0x3; 33915357Skarels rp->r_flags = 0; 34016208Skarels ifxp++; 34115357Skarels } 34215357Skarels ifrw = &ds->ds_deuba.ifu_r[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(); 35315357Skarels ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = 0; 35419861Skarels ds->ds_if.if_flags |= IFF_RUNNING; 35515916Skarels destart(unit); /* queue output packets */ 35615357Skarels addr->pclow = PCSR0_INTE; /* avoid interlock */ 35715357Skarels addr->pclow = CMD_START | PCSR0_INTE; 35815916Skarels ds->ds_flags |= DSF_RUNNING; 35915357Skarels splx(s); 36015357Skarels } 36115357Skarels 36215357Skarels /* 36315357Skarels * Setup output on interface. 36415357Skarels * Get another datagram to send off of the interface queue, 36515357Skarels * and map it to the interface before starting the output. 36615357Skarels */ 36715357Skarels destart(unit) 36815357Skarels int unit; 36915357Skarels { 37015357Skarels int len; 37115357Skarels struct uba_device *ui = deinfo[unit]; 37215357Skarels struct dedevice *addr = (struct dedevice *)ui->ui_addr; 37315357Skarels register struct de_softc *ds = &de_softc[unit]; 37415357Skarels register struct de_ring *rp; 37515357Skarels struct mbuf *m; 37615357Skarels register int nxmit; 37715357Skarels 37815357Skarels /* 37915357Skarels * the following test is necessary, since 38015357Skarels * the code is not reentrant and we have 38115357Skarels * multiple transmission buffers. 38215357Skarels */ 38315357Skarels if (ds->ds_flags & DSF_LOCK) 38415357Skarels return; 38515357Skarels for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { 38615357Skarels IF_DEQUEUE(&ds->ds_if.if_snd, m); 38715357Skarels if (m == 0) 38815357Skarels break; 38915357Skarels rp = &ds->ds_xrent[ds->ds_xfree]; 39015357Skarels if (rp->r_flags & XFLG_OWN) 39115357Skarels panic("deuna xmit in progress"); 39216208Skarels len = deput(&ds->ds_deuba, ds->ds_xfree, m); 39315357Skarels if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP) 39415357Skarels UBAPURGE(ds->ds_deuba.ifu_uba, 39516208Skarels ds->ds_deuba.ifu_w[ds->ds_xfree].x_ifrw.ifrw_bdp); 39615357Skarels rp->r_slen = len; 39715357Skarels rp->r_tdrerr = 0; 39815357Skarels rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; 39915357Skarels 40015357Skarels ds->ds_xfree++; 40115357Skarels if (ds->ds_xfree == NXMT) 40215357Skarels ds->ds_xfree = 0; 40315357Skarels } 40415357Skarels if (ds->ds_nxmit != nxmit) { 40515357Skarels ds->ds_nxmit = nxmit; 40615916Skarels if (ds->ds_flags & DSF_RUNNING) 40715357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 40815357Skarels } 40915357Skarels } 41015357Skarels 41115357Skarels /* 41215357Skarels * Command done interrupt. 41315357Skarels */ 41415357Skarels deintr(unit) 41515357Skarels int unit; 41615357Skarels { 41715357Skarels struct uba_device *ui = deinfo[unit]; 41815357Skarels register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 41915357Skarels register struct de_softc *ds = &de_softc[unit]; 42015357Skarels register struct de_ring *rp; 42116208Skarels register struct ifxmt *ifxp; 42215357Skarels short csr0; 42315357Skarels 42415357Skarels /* save flags right away - clear out interrupt bits */ 42515357Skarels csr0 = addr->pcsr0; 42615357Skarels addr->pchigh = csr0 >> 8; 42715357Skarels 42815357Skarels 42915357Skarels ds->ds_flags |= DSF_LOCK; /* prevent entering destart */ 43015357Skarels /* 43115357Skarels * if receive, put receive buffer on mbuf 43215357Skarels * and hang the request again 43315357Skarels */ 43415357Skarels derecv(unit); 43515357Skarels 43615357Skarels /* 43715357Skarels * Poll transmit ring and check status. 43815357Skarels * Be careful about loopback requests. 43915357Skarels * Then free buffer space and check for 44015357Skarels * more transmit requests. 44115357Skarels */ 44215357Skarels for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { 44315357Skarels rp = &ds->ds_xrent[ds->ds_xindex]; 44415357Skarels if (rp->r_flags & XFLG_OWN) 44515357Skarels break; 44615357Skarels ds->ds_if.if_opackets++; 44716208Skarels ifxp = &ds->ds_deuba.ifu_w[ds->ds_xindex]; 44815357Skarels /* check for unusual conditions */ 44915357Skarels if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { 45015357Skarels if (rp->r_flags & XFLG_ERRS) { 45115357Skarels /* output error */ 45215357Skarels ds->ds_if.if_oerrors++; 45315916Skarels if (dedebug) 45415357Skarels printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", 45515357Skarels unit, rp->r_flags, XFLG_BITS, 45615357Skarels rp->r_tdrerr, XERR_BITS, rp->r_slen); 45715357Skarels } else if (rp->r_flags & XFLG_ONE) { 45815357Skarels /* one collision */ 45915357Skarels ds->ds_if.if_collisions++; 46015357Skarels } else if (rp->r_flags & XFLG_MORE) { 46115357Skarels /* more than one collision */ 46215357Skarels ds->ds_if.if_collisions += 2; /* guess */ 46315357Skarels } else if (rp->r_flags & XFLG_MTCH) { 46415357Skarels /* received our own packet */ 46515357Skarels ds->ds_if.if_ipackets++; 46616208Skarels deread(ds, &ifxp->x_ifrw, 46715357Skarels rp->r_slen - sizeof (struct ether_header)); 46815357Skarels } 46915357Skarels } 47016208Skarels if (ifxp->x_xtofree) { 47116208Skarels m_freem(ifxp->x_xtofree); 47216208Skarels ifxp->x_xtofree = 0; 47316208Skarels } 47415357Skarels /* check if next transmit buffer also finished */ 47515357Skarels ds->ds_xindex++; 47615357Skarels if (ds->ds_xindex == NXMT) 47715357Skarels ds->ds_xindex = 0; 47815357Skarels } 47915357Skarels ds->ds_flags &= ~DSF_LOCK; 48015357Skarels destart(unit); 48115357Skarels 48215357Skarels if (csr0 & PCSR0_RCBI) { 48315357Skarels printf("de%d: buffer unavailable\n", unit); 48415357Skarels addr->pclow = PCSR0_INTE|CMD_PDMD; 48515357Skarels } 48615357Skarels } 48715357Skarels 48815357Skarels /* 48915357Skarels * Ethernet interface receiver interface. 49015357Skarels * If input error just drop packet. 49115357Skarels * Otherwise purge input buffered data path and examine 49215357Skarels * packet to determine type. If can't determine length 49315357Skarels * from type, then have to drop packet. Othewise decapsulate 49415357Skarels * packet based on type and pass to type specific higher-level 49515357Skarels * input routine. 49615357Skarels */ 49715357Skarels derecv(unit) 49815357Skarels int unit; 49915357Skarels { 50015357Skarels register struct de_softc *ds = &de_softc[unit]; 50115357Skarels register struct de_ring *rp; 50215357Skarels int len; 50315357Skarels 50415357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 50515357Skarels while ((rp->r_flags & RFLG_OWN) == 0) { 50615357Skarels ds->ds_if.if_ipackets++; 50715357Skarels if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP) 50815357Skarels UBAPURGE(ds->ds_deuba.ifu_uba, 50915357Skarels ds->ds_deuba.ifu_r[ds->ds_rindex].ifrw_bdp); 51015357Skarels len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) 51115357Skarels - 4; /* don't forget checksum! */ 51215357Skarels /* check for errors */ 51315357Skarels if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || 51415357Skarels (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || 51515357Skarels (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || 51615357Skarels len < ETHERMIN || len > ETHERMTU) { 51715357Skarels ds->ds_if.if_ierrors++; 51815916Skarels if (dedebug) 51915357Skarels printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", 52015357Skarels unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, 52115357Skarels RERR_BITS, len); 52215357Skarels } else 52315357Skarels deread(ds, &ds->ds_deuba.ifu_r[ds->ds_rindex], len); 52415357Skarels 52515357Skarels /* hang the receive buffer again */ 52615357Skarels rp->r_lenerr = 0; 52715357Skarels rp->r_flags = RFLG_OWN; 52815357Skarels 52915357Skarels /* check next receive buffer */ 53015357Skarels ds->ds_rindex++; 53115357Skarels if (ds->ds_rindex == NRCV) 53215357Skarels ds->ds_rindex = 0; 53315357Skarels rp = &ds->ds_rrent[ds->ds_rindex]; 53415357Skarels } 53515357Skarels } 53615357Skarels 53715357Skarels /* 53815357Skarels * Pass a packet to the higher levels. 53915357Skarels * We deal with the trailer protocol here. 54015357Skarels */ 54115357Skarels deread(ds, ifrw, len) 54215357Skarels register struct de_softc *ds; 54315357Skarels struct ifrw *ifrw; 54415357Skarels int len; 54515357Skarels { 54615357Skarels struct ether_header *eh; 54715357Skarels struct mbuf *m; 54815357Skarels int off, resid; 54916722Sbloom int s; 55015357Skarels register struct ifqueue *inq; 55115357Skarels 55215357Skarels /* 55319861Skarels * Deal with trailer protocol: if type is trailer type 55415357Skarels * get true type from first 16-bit word past data. 55515357Skarels * Remember that type was trailer by setting off. 55615357Skarels */ 55715357Skarels eh = (struct ether_header *)ifrw->ifrw_addr; 55815357Skarels eh->ether_type = ntohs((u_short)eh->ether_type); 55915357Skarels #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 56019861Skarels if (eh->ether_type >= ETHERTYPE_TRAIL && 56119861Skarels eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 56219861Skarels off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 56315357Skarels if (off >= ETHERMTU) 56415357Skarels return; /* sanity */ 56515357Skarels eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); 56615357Skarels resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); 56715357Skarels if (off + resid > len) 56815357Skarels return; /* sanity */ 56915357Skarels len = off + resid; 57015357Skarels } else 57115357Skarels off = 0; 57215357Skarels if (len == 0) 57315357Skarels return; 57415357Skarels 57515357Skarels /* 57615357Skarels * Pull packet off interface. Off is nonzero if packet 57715357Skarels * has trailing header; deget will then force this header 57815357Skarels * information to be at the front, but we still have to drop 57915357Skarels * the type and length which are at the front of any trailer data. 58015357Skarels */ 58115357Skarels m = deget(&ds->ds_deuba, ifrw, len, off); 58215357Skarels if (m == 0) 58315357Skarels return; 58415357Skarels if (off) { 58515357Skarels m->m_off += 2 * sizeof (u_short); 58615357Skarels m->m_len -= 2 * sizeof (u_short); 58715357Skarels } 58815357Skarels switch (eh->ether_type) { 58915357Skarels 59015357Skarels #ifdef INET 59119861Skarels case ETHERTYPE_IP: 59215357Skarels schednetisr(NETISR_IP); 59315357Skarels inq = &ipintrq; 59415357Skarels break; 59515357Skarels 59619861Skarels case ETHERTYPE_ARP: 59715357Skarels arpinput(&ds->ds_ac, m); 59815357Skarels return; 59915357Skarels #endif 60023503Ssklower #ifdef NS 60123503Ssklower case ETHERTYPE_NS: 60223503Ssklower schednetisr(NETISR_NS); 60323503Ssklower inq = &nsintrq; 60423503Ssklower break; 60523503Ssklower 60623503Ssklower #endif 60715357Skarels default: 60815357Skarels m_freem(m); 60915357Skarels return; 61015357Skarels } 61115357Skarels 61216722Sbloom s = splimp(); 61315357Skarels if (IF_QFULL(inq)) { 61415357Skarels IF_DROP(inq); 61516722Sbloom splx(s); 61615357Skarels m_freem(m); 61715357Skarels return; 61815357Skarels } 61915357Skarels IF_ENQUEUE(inq, m); 62016722Sbloom splx(s); 62115357Skarels } 62215357Skarels 62315357Skarels /* 62415357Skarels * Ethernet output routine. 62515357Skarels * Encapsulate a packet of type family for the local net. 62615357Skarels * Use trailer local net encapsulation if enough data in first 62715357Skarels * packet leaves a multiple of 512 bytes of data in remainder. 62815357Skarels */ 62915357Skarels deoutput(ifp, m0, dst) 63015357Skarels struct ifnet *ifp; 63115357Skarels struct mbuf *m0; 63215357Skarels struct sockaddr *dst; 63315357Skarels { 63415357Skarels int type, s, error; 63519861Skarels u_char edst[6]; 63615357Skarels struct in_addr idst; 63715357Skarels register struct de_softc *ds = &de_softc[ifp->if_unit]; 63815357Skarels register struct mbuf *m = m0; 63915357Skarels register struct ether_header *eh; 64015357Skarels register int off; 64115357Skarels 64215357Skarels switch (dst->sa_family) { 64315357Skarels 64415357Skarels #ifdef INET 64515357Skarels case AF_INET: 64615357Skarels idst = ((struct sockaddr_in *)dst)->sin_addr; 64719861Skarels if (!arpresolve(&ds->ds_ac, m, &idst, edst)) 64815357Skarels return (0); /* if not yet resolved */ 64915357Skarels off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 65015357Skarels /* need per host negotiation */ 65115357Skarels if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 65215357Skarels if (off > 0 && (off & 0x1ff) == 0 && 65315357Skarels m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 65419861Skarels type = ETHERTYPE_TRAIL + (off>>9); 65515357Skarels m->m_off -= 2 * sizeof (u_short); 65615357Skarels m->m_len += 2 * sizeof (u_short); 65719861Skarels *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 65815357Skarels *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 65915357Skarels goto gottrailertype; 66015357Skarels } 66119861Skarels type = ETHERTYPE_IP; 66215357Skarels off = 0; 66315357Skarels goto gottype; 66415357Skarels #endif 66523503Ssklower #ifdef NS 66623503Ssklower case AF_NS: 66723503Ssklower type = ETHERTYPE_NS; 66823503Ssklower bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 66923503Ssklower (caddr_t)edst, sizeof (edst)); 67023503Ssklower off = 0; 67123503Ssklower goto gottype; 67223503Ssklower #endif 67315357Skarels 67415357Skarels case AF_UNSPEC: 67515357Skarels eh = (struct ether_header *)dst->sa_data; 67619861Skarels bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 67715357Skarels type = eh->ether_type; 67815357Skarels goto gottype; 67915357Skarels 68015357Skarels default: 68115357Skarels printf("de%d: can't handle af%d\n", ifp->if_unit, 68215357Skarels dst->sa_family); 68315357Skarels error = EAFNOSUPPORT; 68415357Skarels goto bad; 68515357Skarels } 68615357Skarels 68715357Skarels gottrailertype: 68815357Skarels /* 68915357Skarels * Packet to be sent as trailer: move first packet 69015357Skarels * (control information) to end of chain. 69115357Skarels */ 69215357Skarels while (m->m_next) 69315357Skarels m = m->m_next; 69415357Skarels m->m_next = m0; 69515357Skarels m = m0->m_next; 69615357Skarels m0->m_next = 0; 69715357Skarels m0 = m; 69815357Skarels 69915357Skarels gottype: 70015357Skarels /* 70115357Skarels * Add local net header. If no space in first mbuf, 70215357Skarels * allocate another. 70315357Skarels */ 70415357Skarels if (m->m_off > MMAXOFF || 70515357Skarels MMINOFF + sizeof (struct ether_header) > m->m_off) { 70615357Skarels m = m_get(M_DONTWAIT, MT_HEADER); 70715357Skarels if (m == 0) { 70815357Skarels error = ENOBUFS; 70915357Skarels goto bad; 71015357Skarels } 71115357Skarels m->m_next = m0; 71215357Skarels m->m_off = MMINOFF; 71315357Skarels m->m_len = sizeof (struct ether_header); 71415357Skarels } else { 71515357Skarels m->m_off -= sizeof (struct ether_header); 71615357Skarels m->m_len += sizeof (struct ether_header); 71715357Skarels } 71815357Skarels eh = mtod(m, struct ether_header *); 71915357Skarels eh->ether_type = htons((u_short)type); 72019861Skarels bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 72115357Skarels /* DEUNA fills in source address */ 72215357Skarels 72315357Skarels /* 72415357Skarels * Queue message on interface, and start output if interface 72515357Skarels * not yet active. 72615357Skarels */ 72715357Skarels s = splimp(); 72815357Skarels if (IF_QFULL(&ifp->if_snd)) { 72915357Skarels IF_DROP(&ifp->if_snd); 73015357Skarels splx(s); 73115357Skarels m_freem(m); 73215357Skarels return (ENOBUFS); 73315357Skarels } 73415357Skarels IF_ENQUEUE(&ifp->if_snd, m); 73515357Skarels destart(ifp->if_unit); 73615357Skarels splx(s); 73715357Skarels return (0); 73815357Skarels 73915357Skarels bad: 74015357Skarels m_freem(m0); 74115357Skarels return (error); 74215357Skarels } 74315357Skarels 74415357Skarels /* 74515357Skarels * Routines supporting UNIBUS network interfaces. 74615357Skarels */ 74715357Skarels 74815357Skarels /* 74915357Skarels * Init UNIBUS for interface on uban whose headers of size hlen are to 75015357Skarels * end on a page boundary. We allocate a UNIBUS map register for the page 75115357Skarels * with the header, and nmr more UNIBUS map registers for i/o on the adapter, 75215357Skarels * doing this for each receive and transmit buffer. We also 75315357Skarels * allocate page frames in the mbuffer pool for these pages. 75415357Skarels */ 75515357Skarels de_ubainit(ifu, uban, hlen, nmr) 75615357Skarels register struct deuba *ifu; 75715357Skarels int uban, hlen, nmr; 75815357Skarels { 75915357Skarels register caddr_t cp, dp; 76015357Skarels register struct ifrw *ifrw; 76116208Skarels register struct ifxmt *ifxp; 76216208Skarels int i, ncl; 76315357Skarels 76415357Skarels ncl = clrnd(nmr + CLSIZE) / CLSIZE; 76515357Skarels if (ifu->ifu_r[0].ifrw_addr) 76615357Skarels /* 76715357Skarels * If the first read buffer has a non-zero 76815357Skarels * address, it means we have already allocated core 76915357Skarels */ 77015357Skarels cp = ifu->ifu_r[0].ifrw_addr - (CLBYTES - hlen); 77115357Skarels else { 77215357Skarels cp = m_clalloc(NTOT * ncl, MPG_SPACE); 77315357Skarels if (cp == 0) 77415357Skarels return (0); 77515357Skarels ifu->ifu_hlen = hlen; 77615357Skarels ifu->ifu_uban = uban; 77715357Skarels ifu->ifu_uba = uba_hd[uban].uh_uba; 77815357Skarels dp = cp + CLBYTES - hlen; 77915357Skarels for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) { 78015357Skarels ifrw->ifrw_addr = dp; 78115357Skarels dp += ncl * CLBYTES; 78215357Skarels } 78316208Skarels for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) { 78416208Skarels ifxp->x_ifrw.ifrw_addr = dp; 78515357Skarels dp += ncl * CLBYTES; 78615357Skarels } 78715357Skarels } 78815357Skarels /* allocate for receive ring */ 78915357Skarels for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) { 79015357Skarels if (de_ubaalloc(ifu, ifrw, nmr) == 0) { 79116208Skarels struct ifrw *rw; 79215357Skarels 79316208Skarels for (rw = ifu->ifu_r; rw < ifrw; rw++) 79416208Skarels ubarelse(ifu->ifu_uban, &rw->ifrw_info); 79515357Skarels goto bad; 79615357Skarels } 79715357Skarels } 79815357Skarels /* and now transmit ring */ 79916208Skarels for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) { 80016208Skarels ifrw = &ifxp->x_ifrw; 80115357Skarels if (de_ubaalloc(ifu, ifrw, nmr) == 0) { 80216208Skarels struct ifxmt *xp; 80315357Skarels 80416208Skarels for (xp = ifu->ifu_w; xp < ifxp; xp++) 80516208Skarels ubarelse(ifu->ifu_uban, &xp->x_ifrw.ifrw_info); 80616208Skarels for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) 80716208Skarels ubarelse(ifu->ifu_uban, &ifrw->ifrw_info); 80815357Skarels goto bad; 80915357Skarels } 81016208Skarels for (i = 0; i < nmr; i++) 81116208Skarels ifxp->x_map[i] = ifrw->ifrw_mr[i]; 81216208Skarels ifxp->x_xswapd = 0; 81315357Skarels } 81415357Skarels return (1); 81515357Skarels bad: 81615357Skarels m_pgfree(cp, NTOT * ncl); 81715357Skarels ifu->ifu_r[0].ifrw_addr = 0; 81815357Skarels return(0); 81915357Skarels } 82015357Skarels 82115357Skarels /* 82215357Skarels * Setup either a ifrw structure by allocating UNIBUS map registers, 82315357Skarels * possibly a buffered data path, and initializing the fields of 82415357Skarels * the ifrw structure to minimize run-time overhead. 82515357Skarels */ 82615357Skarels static 82715357Skarels de_ubaalloc(ifu, ifrw, nmr) 82815357Skarels struct deuba *ifu; 82915357Skarels register struct ifrw *ifrw; 83015357Skarels int nmr; 83115357Skarels { 83215357Skarels register int info; 83315357Skarels 83415357Skarels info = 83515357Skarels uballoc(ifu->ifu_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->ifu_hlen, 83615357Skarels ifu->ifu_flags); 83715357Skarels if (info == 0) 83815357Skarels return (0); 83915357Skarels ifrw->ifrw_info = info; 84015357Skarels ifrw->ifrw_bdp = UBAI_BDP(info); 84115357Skarels ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT); 84215357Skarels ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[UBAI_MR(info) + 1]; 84315357Skarels return (1); 84415357Skarels } 84515357Skarels 84615357Skarels /* 84715357Skarels * Pull read data off a interface. 84815357Skarels * Len is length of data, with local net header stripped. 84915357Skarels * Off is non-zero if a trailer protocol was used, and 85015357Skarels * gives the offset of the trailer information. 85115357Skarels * We copy the trailer information and then all the normal 85215357Skarels * data into mbufs. When full cluster sized units are present 85315357Skarels * on the interface on cluster boundaries we can get them more 85415357Skarels * easily by remapping, and take advantage of this here. 85515357Skarels */ 85615357Skarels struct mbuf * 85715357Skarels deget(ifu, ifrw, totlen, off0) 85815357Skarels register struct deuba *ifu; 85915357Skarels register struct ifrw *ifrw; 86015357Skarels int totlen, off0; 86115357Skarels { 86215357Skarels struct mbuf *top, **mp, *m; 86315357Skarels int off = off0, len; 86415357Skarels register caddr_t cp = ifrw->ifrw_addr + ifu->ifu_hlen; 86515357Skarels 86615357Skarels top = 0; 86715357Skarels mp = ⊤ 86815357Skarels while (totlen > 0) { 86915357Skarels MGET(m, M_DONTWAIT, MT_DATA); 87015357Skarels if (m == 0) 87115357Skarels goto bad; 87215357Skarels if (off) { 87315357Skarels len = totlen - off; 87415357Skarels cp = ifrw->ifrw_addr + ifu->ifu_hlen + off; 87515357Skarels } else 87615357Skarels len = totlen; 87715357Skarels if (len >= CLBYTES) { 87815357Skarels struct mbuf *p; 87915357Skarels struct pte *cpte, *ppte; 88015357Skarels int x, *ip, i; 88115357Skarels 88215357Skarels MCLGET(p, 1); 88315357Skarels if (p == 0) 88415357Skarels goto nopage; 88515357Skarels len = m->m_len = CLBYTES; 88615357Skarels m->m_off = (int)p - (int)m; 88715357Skarels if (!claligned(cp)) 88815357Skarels goto copy; 88915357Skarels 89015357Skarels /* 89115357Skarels * Switch pages mapped to UNIBUS with new page p, 89215357Skarels * as quick form of copy. Remap UNIBUS and invalidate. 89315357Skarels */ 89415357Skarels cpte = &Mbmap[mtocl(cp)*CLSIZE]; 89515357Skarels ppte = &Mbmap[mtocl(p)*CLSIZE]; 89615357Skarels x = btop(cp - ifrw->ifrw_addr); 89715357Skarels ip = (int *)&ifrw->ifrw_mr[x]; 89815357Skarels for (i = 0; i < CLSIZE; i++) { 89915357Skarels struct pte t; 90015357Skarels t = *ppte; *ppte++ = *cpte; *cpte = t; 90115357Skarels *ip++ = 90215357Skarels cpte++->pg_pfnum|ifrw->ifrw_proto; 90315357Skarels mtpr(TBIS, cp); 90415357Skarels cp += NBPG; 90515357Skarels mtpr(TBIS, (caddr_t)p); 90615357Skarels p += NBPG / sizeof (*p); 90715357Skarels } 90815357Skarels goto nocopy; 90915357Skarels } 91015357Skarels nopage: 91115357Skarels m->m_len = MIN(MLEN, len); 91215357Skarels m->m_off = MMINOFF; 91315357Skarels copy: 91415357Skarels bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); 91515357Skarels cp += m->m_len; 91615357Skarels nocopy: 91715357Skarels *mp = m; 91815357Skarels mp = &m->m_next; 91915357Skarels if (off) { 92015357Skarels /* sort of an ALGOL-W style for statement... */ 92115357Skarels off += m->m_len; 92215357Skarels if (off == totlen) { 92315357Skarels cp = ifrw->ifrw_addr + ifu->ifu_hlen; 92415357Skarels off = 0; 92515357Skarels totlen = off0; 92615357Skarels } 92715357Skarels } else 92815357Skarels totlen -= m->m_len; 92915357Skarels } 93015357Skarels return (top); 93115357Skarels bad: 93215357Skarels m_freem(top); 93315357Skarels return (0); 93415357Skarels } 93515357Skarels 93615357Skarels /* 93715357Skarels * Map a chain of mbufs onto a network interface 93815357Skarels * in preparation for an i/o operation. 93915357Skarels * The argument chain of mbufs includes the local network 94015357Skarels * header which is copied to be in the mapped, aligned 94115357Skarels * i/o space. 94215357Skarels */ 94316208Skarels deput(ifu, n, m) 94416208Skarels struct deuba *ifu; 94516208Skarels int n; 94615357Skarels register struct mbuf *m; 94715357Skarels { 94815357Skarels register struct mbuf *mp; 94915357Skarels register caddr_t cp; 95016208Skarels register struct ifxmt *ifxp; 95116208Skarels register struct ifrw *ifrw; 95215357Skarels register int i; 95316208Skarels int xswapd = 0; 95416208Skarels int x, cc, t; 95516208Skarels caddr_t dp; 95615357Skarels 95716208Skarels ifxp = &ifu->ifu_w[n]; 95816208Skarels ifrw = &ifxp->x_ifrw; 95915357Skarels cp = ifrw->ifrw_addr; 96015357Skarels while (m) { 96115357Skarels dp = mtod(m, char *); 96215357Skarels if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) { 96316208Skarels struct pte *pte; int *ip; 96416208Skarels pte = &Mbmap[mtocl(dp)*CLSIZE]; 96515357Skarels x = btop(cp - ifrw->ifrw_addr); 96615357Skarels ip = (int *)&ifrw->ifrw_mr[x]; 96716208Skarels for (i = 0; i < CLSIZE; i++) 96815357Skarels *ip++ = 96916208Skarels ifrw->ifrw_proto | pte++->pg_pfnum; 97016208Skarels xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT)); 97116208Skarels mp = m->m_next; 97216208Skarels m->m_next = ifxp->x_xtofree; 97316208Skarels ifxp->x_xtofree = m; 97416208Skarels cp += m->m_len; 97515357Skarels } else { 97615357Skarels bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len); 97715357Skarels cp += m->m_len; 97816208Skarels MFREE(m, mp); 97915357Skarels } 98015357Skarels m = mp; 98115357Skarels } 98215357Skarels 98316208Skarels /* 98416208Skarels * Xswapd is the set of clusters we just mapped out. Ifxp->x_xswapd 98516208Skarels * is the set of clusters mapped out from before. We compute 98616208Skarels * the number of clusters involved in this operation in x. 98716208Skarels * Clusters mapped out before and involved in this operation 98816208Skarels * should be unmapped so original pages will be accessed by the device. 98916208Skarels */ 99015357Skarels cc = cp - ifrw->ifrw_addr; 99116208Skarels x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT; 99216208Skarels ifxp->x_xswapd &= ~xswapd; 99316208Skarels while (i = ffs(ifxp->x_xswapd)) { 99416208Skarels i--; 99516208Skarels if (i >= x) 99616208Skarels break; 99716208Skarels ifxp->x_xswapd &= ~(1<<i); 99816208Skarels i *= CLSIZE; 99916208Skarels for (t = 0; t < CLSIZE; t++) { 100016208Skarels ifrw->ifrw_mr[i] = ifxp->x_map[i]; 100116208Skarels i++; 100216208Skarels } 100316208Skarels } 100416208Skarels ifxp->x_xswapd |= xswapd; 100515357Skarels return (cc); 100615357Skarels } 100715357Skarels 100815357Skarels /* 100915357Skarels * Process an ioctl request. 101015357Skarels */ 101115357Skarels deioctl(ifp, cmd, data) 101215357Skarels register struct ifnet *ifp; 101315357Skarels int cmd; 101415357Skarels caddr_t data; 101515357Skarels { 101619861Skarels register struct ifaddr *ifa = (struct ifaddr *)data; 101715357Skarels int s = splimp(), error = 0; 101815357Skarels 101915357Skarels switch (cmd) { 102015357Skarels 102115357Skarels case SIOCSIFADDR: 102219861Skarels ifp->if_flags |= IFF_UP; 102315357Skarels deinit(ifp->if_unit); 102419861Skarels 102519861Skarels switch (ifa->ifa_addr.sa_family) { 102623503Ssklower #ifdef INET 102719861Skarels case AF_INET: 102819861Skarels ((struct arpcom *)ifp)->ac_ipaddr = 102919861Skarels IA_SIN(ifa)->sin_addr; 103019861Skarels arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 103119861Skarels break; 103223503Ssklower #endif 103323503Ssklower #ifdef NS 103423503Ssklower case AF_NS: 103523559Ssklower { 103623559Ssklower register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 103723559Ssklower 103823559Ssklower if (ns_nullhost(*ina)) { 103923559Ssklower ina->x_host = * (union ns_host *) 104023503Ssklower (de_softc[ifp->if_unit].ds_addr); 104123559Ssklower } else { 104223559Ssklower de_setaddr(ina->x_host.c_host,ifp->if_unit); 104323559Ssklower } 104423503Ssklower break; 104523559Ssklower } 104623503Ssklower #endif 104719861Skarels } 104815357Skarels break; 104915357Skarels 105015357Skarels default: 105115357Skarels error = EINVAL; 105215357Skarels } 105315357Skarels splx(s); 105415357Skarels return (error); 105515357Skarels } 105623559Ssklower 105723559Ssklower /* 105823559Ssklower * set ethernet address for unit 105923559Ssklower */ 106023559Ssklower de_setaddr(physaddr, unit) 106123559Ssklower u_char *physaddr; 106223559Ssklower int unit; 106323559Ssklower { 106423559Ssklower register struct de_softc *ds = &de_softc[unit]; 106523559Ssklower register struct uba_device *ui = deinfo[unit]; 106623559Ssklower register struct dedevice *addr= (struct dedevice *)ui->ui_addr; 106723559Ssklower int csr0; 106823559Ssklower 1069*23672Ssklower if (! (ds->ds_flags & DSF_RUNNING)) 1070*23672Ssklower return; 1071*23672Ssklower 107223559Ssklower bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6); 107323559Ssklower ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 1074*23672Ssklower addr->pclow = PCSR0_INTE|CMD_PDMD; 107523559Ssklower csr0 = addr->pcsr0; 107623559Ssklower addr->pchigh = csr0 >> 8; 107723559Ssklower if (csr0 & PCSR0_PCEI) 107823559Ssklower printf("de%d: wtphyad failed, csr0=%b csr1=%b\n", 107923559Ssklower ui->ui_unit, csr0, PCSR0_BITS, 108023559Ssklower addr->pcsr1, PCSR1_BITS); 108123559Ssklower } 108223559Ssklower 108316208Skarels #endif 108423559Ssklower 1085