?? if_il.c
字號:
/* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * 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_il.c 7.8 (Berkeley) 12/16/90 */#include "il.h"#if NIL > 0/* * Interlan Ethernet Communications Controller interface */#include "../include/pte.h"#include "sys/param.h"#include "sys/systm.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/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/if_ether.h"#endif#ifdef NS#include "netns/ns.h"#include "netns/ns_if.h"#endif#include "../include/cpu.h"#include "../include/mtpr.h"#include "if_il.h"#include "if_ilreg.h"#include "if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"int ilprobe(), ilattach(), ilrint(), ilcint();struct uba_device *ilinfo[NIL];u_short ilstd[] = { 0 };struct uba_driver ildriver = { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };#define ILUNIT(x) minor(x)int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(),ilstart();int ildebug = 0;/* * 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, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc. Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */struct ether_addr { u_char addr[6];};struct il_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 */ struct ifuba is_ifuba; /* UNIBUS resources */ int is_flags;#define ILF_RCVPENDING 0x2 /* start rcv in ilcint */#define ILF_STATPENDING 0x4 /* stat cmd pending */#define ILF_RUNNING 0x8 /* board is running */#define ILF_SETADDR 0x10 /* physical address is changed */ short is_lastcmd; /* can't read csr, so must save it */ short is_scaninterval; /* interval of stat collection */#define ILWATCHINTERVAL 60 /* once every 60 seconds */ union { struct il_stats isu_stats; /* holds on-board statistics */ struct ether_addr isu_maddrs[63]; /* multicast addrs */ } is_isu;#define is_stats is_isu.isu_stats#define is_maddrs is_isu.isu_maddrs struct il_stats is_sum; /* summation over time */ int is_ubaddr; /* mapping registers of is_stats */} il_softc[NIL];ilprobe(reg) caddr_t reg;{ register int br, cvec; /* r11, r10 value-result */ register struct ildevice *addr = (struct ildevice *)reg; register i;#ifdef lint br = 0; cvec = br; br = cvec; i = 0; ilrint(i); ilcint(i); ilwatch(i);#endif addr->il_csr = ILC_OFFLINE|IL_CIE; DELAY(100000); i = addr->il_csr; /* clear CDONE */ if (cvec > 0 && cvec != 0x200) cvec -= 4; return (1);}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. A STATUS command is done to get the ethernet * address and other interesting data. */ilattach(ui) struct uba_device *ui;{ register struct il_softc *is = &il_softc[ui->ui_unit]; register struct ifnet *ifp = &is->is_if; register struct ildevice *addr = (struct ildevice *)ui->ui_addr; ifp->if_unit = ui->ui_unit; ifp->if_name = "il"; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST; /* * Reset the board and map the statistics * buffer onto the Unibus. */ addr->il_csr = ILC_RESET; (void)ilwait(ui, "reset"); is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, sizeof (struct il_stats), 0); addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof (struct il_stats); addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; (void)ilwait(ui, "status"); ubarelse(ui->ui_ubanum, &is->is_ubaddr); if (ildebug) printf("il%d: module=%s firmware=%s\n", ui->ui_unit, is->is_stats.ils_module, is->is_stats.ils_firmware); bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, sizeof (is->is_addr)); printf("il%d: hardware address %s\n", ui->ui_unit, ether_sprintf(is->is_addr)); ifp->if_init = ilinit; ifp->if_output = ether_output; ifp->if_ioctl = ilioctl; ifp->if_reset = ilreset; ifp->if_start = ilstart; is->is_ifuba.ifu_flags = UBA_CANTWAIT; if_attach(ifp);}ilwait(ui, op) struct uba_device *ui; char *op;{ register struct ildevice *addr = (struct ildevice *)ui->ui_addr; while ((addr->il_csr&IL_CDONE) == 0) ; if (addr->il_csr&IL_STATUS) { printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op, addr->il_csr, IL_BITS); return (-1); } return (0);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ilreset(unit, uban) int unit, uban;{ register struct uba_device *ui; if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" il%d", unit); il_softc[unit].is_if.if_flags &= ~IFF_RUNNING; il_softc[unit].is_flags &= ~ILF_RUNNING; ilinit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ilinit(unit) int unit;{ register struct il_softc *is = &il_softc[unit]; register struct uba_device *ui = ilinfo[unit]; register struct ildevice *addr; register struct ifnet *ifp = &is->is_if; int s; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (is->is_flags & ILF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_ubainit(&is->is_ifuba, ui->ui_ubanum, sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { printf("il%d: can't initialize\n", unit); is->is_if.if_flags &= ~IFF_UP; return; } is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_isu, sizeof (is->is_isu), 0); } ifp->if_watchdog = ilwatch; is->is_scaninterval = ILWATCHINTERVAL; ifp->if_timer = is->is_scaninterval; addr = (struct ildevice *)ui->ui_addr; /* * Turn off source address insertion (it's faster this way), * and set board online. Former doesn't work if board is * already online (happens on ubareset), so we put it offline * first. */ s = splimp(); addr->il_csr = ILC_RESET; if (ilwait(ui, "hardware diag")) { is->is_if.if_flags &= ~IFF_UP; splx(s); return; } addr->il_csr = ILC_CISA; while ((addr->il_csr & IL_CDONE) == 0) ; /* * If we must reprogram this board's physical ethernet * address (as for secondary XNS interfaces), we do so * before putting it on line, and starting receive requests. * If you try this on an older 1010 board, it will total * wedge the board. */ if (is->is_flags & ILF_SETADDR) { bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_isu, sizeof is->is_addr); addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof is->is_addr; addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA; if (ilwait(ui, "setaddr")) return; addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = sizeof (struct il_stats); addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; if (ilwait(ui, "verifying setaddr")) return; if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, sizeof (is->is_addr)) != 0) { printf("il%d: setaddr didn't work\n", ui->ui_unit); return; } }#ifdef MULTICAST if (is->is_if.if_flags & IFF_PROMISC) { addr->il_csr = ILC_PRMSC; if (ilwait(ui, "all multi")) return; } else if (is->is_if.if_flags & IFF_ALLMULTI) { too_many_multis: addr->il_csr = ILC_ALLMC; if (ilwait(ui, "all multi")) return; else { int i; register struct ether_addr *ep = is->is_maddrs; struct ether_multi *enm; struct ether_multistep step; /* * Step through our list of multicast addresses. If we have * too many multicast addresses, or if we have to listen to * a range of multicast addresses, turn on reception of all * multicasts. */ i = 0; ETHER_FIRST_MULTI(step, &is->is_ac, enm); while (enm != NULL) { if (++i > 63 && k != 0) { break; } *ep++ = *(struct ether_addr *)enm->enm_addrlo; ETHER_NEXT_MULTI(step, enm); } if (i = 0) { /* no multicasts! */ } else if (i <= 63) { addr->il_bar = is->is_ubaddr & 0xffff; addr->il_bcr = i * sizeof (struct ether_addr); addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)| LC_LDGRPS; if (ilwait(ui, "load multi")) return; } else {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -