📄 if_ace.c
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Computer Consoles Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_ace.c 7.8 (Berkeley) 12/16/90 *//* * ACC VERSAbus Ethernet controller */#include "ace.h"#if NACE > 0#include "sys/param.h"#include "sys/systm.h"#include "sys/malloc.h"#include "sys/mbuf.h"#include "sys/buf.h"#include "sys/protosw.h"#include "sys/socket.h"#include "sys/vmmac.h"#include "sys/ioctl.h"#include "sys/errno.h"#include "sys/vmparam.h"#include "sys/syslog.h"#include "net/if.h"#include "net/netisr.h"#include "net/route.h"#ifdef INET#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/if_ether.h"#endif#ifdef NS#include "netns/ns.h"#include "netns/ns_if.h"#endif#include "../include/cpu.h"#include "../include/pte.h"#include "../include/mtpr.h"#include "../if/if_acereg.h"#include "../vba/vbavar.h"int aceprobe(), aceattach(), acerint(), acecint(), acestart();struct vba_device *aceinfo[NACE];long acestd[] = { 0 };struct vba_driver acedriver = { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };int aceinit(), aceoutput(), aceioctl(), acereset();struct mbuf *aceget();/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * is_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct ace_softc { struct arpcom is_ac; /* Ethernet common part */#define is_if is_ac.ac_if /* network-visible interface */#define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ short is_flags;#define ACEF_OACTIVE 0x1 /* output is active */#define ACEF_RCVPENDING 0x2 /* start rcv in acecint */ short is_promiscuous; /* true is enabled */ short is_segboundry; /* first TX Seg in dpm */ short is_eictr; /* Rx segment tracking ctr */ short is_eoctr; /* Tx segment tracking ctr */ short is_txnext; /* Next available Tx segment */ short is_currnd; /* current random backoff */ struct ace_stats is_stats; /* holds board statistics */ short is_xcnt; /* count xmitted segments to be acked by the controller */ long is_ivec; /* autoconfig interrupt vector base */ struct pte *is_map; /* pte map for dual ported memory */ caddr_t is_dpm; /* address of mapped memory */} ace_softc[NACE];extern struct ifnet loif;aceprobe(reg, vi) caddr_t reg; struct vba_device *vi;{ register br, cvec; /* must be r12, r11 */ struct acedevice *ap = (struct acedevice *)reg; struct ace_softc *is = &ace_softc[vi->ui_unit];#ifdef lint br = 0; cvec = br; br = cvec; acerint(0); acecint(0);#endif if (badaddr(reg, 2)) return (0); movow(&ap->csr, CSR_RESET); DELAY(10000);#ifdef notdef /* * Select two spaces for the interrupts aligned to an * eight vector boundary and fitting in 8 bits (as * required by the controller) -- YECH. The controller * will be notified later at initialization time. */ if ((vi->ui_hd->vh_lastiv -= 2) > 0xff) vi->ui_hd->vh_lastiv = 0x200; is->is_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x7;#else is->is_ivec = 0x90+vi->ui_unit*8;#endif br = 0x14, cvec = is->is_ivec; /* XXX */ return (sizeof (*ap));}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */aceattach(ui) struct vba_device *ui;{ register short unit = ui->ui_unit; register struct ace_softc *is = &ace_softc[unit]; register struct ifnet *ifp = &is->is_if; register struct acedevice *addr = (struct acedevice *)ui->ui_addr; register short *wp, i; ifp->if_unit = unit; ifp->if_name = "ace"; ifp->if_mtu = ETHERMTU; /* * Get station's addresses and set multicast hash table. */ for (wp = (short *)addr->station, i = 0; i < 6; i++) is->is_addr[i] = ~*wp++; printf("ace%d: hardware address %s\n", unit, ether_sprintf(is->is_addr)); is->is_promiscuous = 0; for (wp = (short *)addr->hash, i = 0; i < 8; i++) movow(wp++, ~0xf); movow(&addr->bcastena[0], ~0xffff); movow(&addr->bcastena[1], ~0xffff); /* * Allocate and map dual ported VERSAbus memory. */ if (vbmemalloc(32, (caddr_t)ui->ui_flags, &is->is_map, &is->is_dpm) == 0) { printf("ace%d: can't allocate VERSAbus memory map\n", unit); return; } ifp->if_init = aceinit; ifp->if_output = ether_output; ifp->if_start = acestart; ifp->if_ioctl = aceioctl; ifp->if_reset = acereset; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; if_attach(ifp);}/* * Reset of interface after "system" reset. */acereset(unit, vban) int unit, vban;{ register struct vba_device *ui; if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_vbanum != vban) return; printf(" ace%d", unit); aceinit(unit);}/* * Initialization of interface; clear recorded pending operations */aceinit(unit) int unit;{ register struct ace_softc *is = &ace_softc[unit]; register struct vba_device *ui = aceinfo[unit]; register struct acedevice *addr; register short Csr; register int s; if (is->is_if.if_addrlist == (struct ifaddr *)0) return; if ((is->is_if.if_flags & IFF_RUNNING) == 0) { /* * Reset the controller, initialize the recieve buffers, * and turn the controller on again and set board online. */ addr = (struct acedevice *)ui->ui_addr; s = splimp(); movow(&addr->csr, CSR_RESET); DELAY(10000); /* * Clean up dpm since the controller might * jumble dpm after reset. */ acesetup(unit); movow(&addr->csr, CSR_GO); Csr = addr->csr; if (Csr & CSR_ACTIVE) { movow(&addr->ivct, is->is_ivec); Csr |= CSR_IENA | is->is_promiscuous; movow(&addr->csr, Csr); is->is_flags = 0; is->is_xcnt = 0; is->is_if.if_flags |= IFF_RUNNING; } splx(s); } if (is->is_if.if_snd.ifq_head) acestart(&is->is_if);}/* * Start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */acestart(ifp) register struct ifnet *ifp;{ register struct tx_segment *txs; register long len; register int s; struct mbuf *m; short retries;#define is ((struct ace_softc *)ifp)again: txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11)); if (txs->tx_csr & TCS_TBFULL) { is->is_stats.tx_busy++; ifp->if_flags |= IFF_OACTIVE; return (0); } s = splimp(); IF_DEQUEUE(&ifp->if_snd, m); splx(s); if (m == 0) { ifp->if_flags &= ~IFF_OACTIVE; return (0); } len = aceput(txs->tx_data, m); retries = txs->tx_csr & TCS_RTC; if (retries > 0) acebakoff(is, txs, retries); /* * Ensure minimum packet length. * This makes the safe assumtion that there are no virtual holes * after the data. * For security, it might be wise to zero out the added bytes, * but we're mainly interested in speed at the moment. */ if (len - sizeof (struct ether_header) < ETHERMIN) len = ETHERMIN + sizeof (struct ether_header); if (++is->is_txnext > SEG_MAX) is->is_txnext = is->is_segboundry; ifp->if_opackets++; is->is_xcnt++; len = (len & 0x7fff) | TCS_TBFULL; movow(txs, len); goto again;#undef is}/* * Transmit done interrupt. */acecint(unit) int unit;{ register struct ace_softc *is = &ace_softc[unit]; register struct tx_segment *txseg; short eostat; if (is->is_xcnt <= 0) { log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n", unit, is->is_xcnt); is->is_xcnt = 0; if (is->is_if.if_snd.ifq_head) acestart(&is->is_if); return; } is->is_xcnt--; txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm); eostat = txseg->tx_csr; if ((eostat & TCS_TBFULL) == 0) { is->is_stats.tx_retries += eostat & TCS_RTC; if (eostat & TCS_RTFAIL) { is->is_stats.tx_discarded++; is->is_if.if_oerrors++; } else is->is_stats.tx_datagrams++; if (++is->is_eoctr >= 16) is->is_eoctr = is->is_segboundry; } if (is->is_if.if_snd.ifq_head) acestart(&is->is_if);}/* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */acerint(unit) int unit;{ register struct ace_softc *is = &ace_softc[unit]; register struct ifqueue *inq; register struct ether_header *ace; register struct rx_segment *rxseg; int len, s, off, resid; struct mbuf *m; short eistat; if ((is->is_if.if_flags&IFF_RUNNING) == 0) return;again: rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm); eistat = rxseg->rx_csr; if ((eistat & RCS_RBFULL) == 0) return; is->is_if.if_ipackets++; if (++is->is_eictr >= is->is_segboundry) is->is_eictr = 0; len = eistat & RCS_RBC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -