📄 if_hy.c
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Tektronix 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_hy.c 7.7 (Berkeley) 12/16/90 *//* * 4.2 BSD Unix Kernel - Vax Network Interface Support * * $Header: if_hy.c,v 10.1 84/07/22 21:02:56 steveg Exp $ * $Locker: $ * * Modifications from Berkeley 4.2 BSD * Copyright (c) 1983, Tektronix Inc. * All Rights Reserved * * $Log: if_hy.c,v $ * Revision 10.1 84/07/22 21:02:56 steveg * define PI13 (moved from if_hyreg.h, somehow got dropped in the process) * rework hywatch to check for power fails first * * Revision 10.0 84/06/30 19:54:27 steveg * Big Build * * Revision 3.17 84/06/20 19:20:28 steveg * increment hy_ntime in hywatch * print out state name, csr, last command, and hy_flags when watchdog timer * expires * * Revision 3.16 84/06/20 19:09:34 steveg * turn on continuous logging by default * * Revision 3.15 84/05/30 22:19:09 steveg * changes to reflect new layout ot statistics data * * Revision 3.14 84/05/30 19:25:15 steveg * move driver states to if_hy.h so log printing programs can use them * * Revision 3.13 84/05/30 17:13:26 steveg * make it compile * * Revision 3.12 84/05/30 13:46:16 steveg * rework logging * * Revision 3.11 84/05/18 19:35:02 steveg * clear IFF_RUNNING and IFF_UP on unibus reset to force resource allocation * by the init routine * * Revision 3.10 84/05/04 12:14:44 steveg * more rework to make it actually work under 4.2 * * Revision 3.9 84/05/01 23:34:52 steveg * fix typo so it compiles (unit -> ui->ui_unit) * * Revision 3.8 84/05/01 23:18:30 steveg * changes after talking with rickk * - check power off more closely * - support remote loopback through A710 adapters * - IMPLINK -> HYLINK * - return EHOSTUNREACH on hyroute failure * - bump if_collisions on abnormal interrupts that aren't input or output * * */#include "hy.h"#if NHY > 0/* * Network Systems Copropration Hyperchanel 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/errno.h"#include "sys/time.h"#include "sys/kernel.h"#include "sys/ioctl.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"#endif#include "../include/cpu.h"#include "../include/mtpr.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"/* * configuration specific paramters * - change as appropriate for particular installaions */#define HYROUTE#define HYELOG#define HYLOG#define HYMTU 1100#define PI13#ifdef DEBUG#define HYLOG#endif#include "if_hy.h"#include "if_hyreg.h"#include "if_uba.h"int hyprobe(), hyattach(), hyinit(), hyioctl();int hyoutput(), hyreset(), hywatch();struct uba_device *hyinfo[NHY];u_short hystd[] = { 0772410, 0 };struct uba_driver hydriver = { hyprobe, 0, hyattach, 0, hystd, "hy", hyinfo };/* * Hyperchannel software status per interface. * * Each interface is referenced by a network interface structure, * hy_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 hy_softc { struct ifnet hy_if; /* network-visible interface */ struct ifuba hy_ifuba; /* UNIBUS resources */ short hy_flags; /* flags */ short hy_state; /* driver state */ u_short hy_host; /* local host number */ struct in_addr hy_addr; /* internet address */ int hy_olen; /* packet length on output */ int hy_lastwcr; /* last command's word count */ short hy_savedstate; /* saved for reissue after status */ short hy_savedcmd; /* saved command for reissue */ int hy_savedcount; /* saved byte count for reissue */ int hy_savedaddr; /* saved unibus address for reissue */ int hy_ntime; /* number of timeouts since last cmd */ int hy_retry; /* retry counter */ struct hy_stat hy_stat; /* statistics */ struct hy_status hy_status; /* status */} hy_softc[NHY];#ifdef HYELOGu_long hy_elog[HYE_SIZE];#endif#ifdef HYLOGstruct hy_log hy_log;#endif#ifdef HYROUTEstruct hy_route hy_route[NHY];#endif#ifdef DEBUG#define printL printf#define printD if (hy_debug_flag) printfint hy_debug_flag = 0;/* * hy_nodebug bit 0x01 set hy_debug_flag on hycancel * hy_nodebug bit 0x02 set hy_debug_flag on command reissue * hy_nodebug bit 0x04 set hy_debug_flag on abnormal interrupt */int hy_nodebug = 0x0;#endif#define SCANINTERVAL 10 /* seconds */#define MAXINTERVAL 20 /* seconds (max action) *//* * Cause a device interrupt. This code uses a buffer starting at * location zero on the unibus (which is already mapped by the * autoconfigure code in the kernel). */hyprobe(reg) caddr_t reg;{ register int br, cvec; /* r11, r10 value-result */ register struct hydevice *addr = (struct hydevice *) reg;#ifdef lint br = 0; cvec = br; br = cvec; hyint(0);#endif /* * request adapter status to a buffer starting at unibus location 0 */ addr->hyd_bar = 0; addr->hyd_wcr = -((sizeof(struct hy_status) + 1) >> 1); addr->hyd_dbuf = HYF_STATUS;#ifdef PI13 addr->hyd_csr |= S_GO | S_IE | S_IATTN;#else addr->hyd_csr |= S_GO | S_IE;#endif DELAY(10000);#ifdef PI13 addr->hyd_csr |= S_CLRINT; /* clear any stacked interrupts */#endif addr->hyd_csr &= ~(S_IE | S_CLRINT); /* disable further interrupts */ return(sizeof(struct hydevice));}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */hyattach(ui) struct uba_device *ui;{ register struct hy_softc *is = &hy_softc[ui->ui_unit]; register struct ifnet *ifp = &is->hy_if; ifp->if_unit = ui->ui_unit; ifp->if_name = "hy"; ifp->if_mtu = HYMTU; is->hy_state = STARTUP; /* don't allow state transitions yet */ ifp->if_init = hyinit; ifp->if_ioctl = hyioctl; ifp->if_output = hyoutput; ifp->if_reset = hyreset; ifp->if_watchdog = hywatch; ifp->if_timer = SCANINTERVAL; is->hy_ifuba.ifu_flags = UBA_CANTWAIT;#ifdef notdef is->hy_ifuba.ifu_flags |= UBA_NEEDBDP;#endif if_attach(ifp);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */hyreset(unit, uban) int unit, uban;{ register struct uba_device *ui; register struct hy_softc *is; if (unit >= NHY || (ui = hyinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) return; printf(" hy%d", unit); is = &hy_softc[unit]; /* force unibus resource allocation */ is->hy_if.if_flags &= ~(IFF_UP|IFF_RUNNING); hyinit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */hyinit(unit) int unit;{ register struct hy_softc *is = &hy_softc[unit]; register struct uba_device *ui = hyinfo[unit]; register struct mbuf *m; int s; if (is->hy_if.if_addrlist == 0) /* address still unknown */ return; if (is->hy_if.if_flags & IFF_RUNNING) /* just reset the device */ goto justreset; if (if_ubainit(&is->hy_ifuba, ui->ui_ubanum, sizeof (struct hym_hdr), (int)btoc(HYMTU)) == 0) { #ifdef DEBUG if (hy_nodebug & 4) hy_debug_flag = 1;#endif printf("hy%d: can't initialize\n", unit); is->hy_if.if_flags &= ~IFF_UP; return; } is->hy_if.if_flags |= IFF_RUNNING;justreset: /* * remove any left over outgoing messages, reset the hardware and * start the state machine */ s = splimp();#ifdef HYLOG hylog(HYL_RESET, 0, (char *)0);#endif is->hy_state = IDLE; is->hy_flags = RQ_STATUS | RQ_STATISTICS | RQ_MARKUP; is->hy_retry = 0; for(;;) { IF_DEQUEUE(&is->hy_if.if_snd, m); if (m != NULL) m_freem(m); else break; } hycancel(ui); /* also bumps the state machine */ splx(s);}/* * Issue a command to the adapter */hystart(ui, cmd, count, ubaddr) struct uba_device *ui; int cmd, count, ubaddr;{ register struct hy_softc *is = &hy_softc[ui->ui_unit]; register struct hydevice *addr = (struct hydevice *)ui->ui_addr;#ifdef DEBUG printD("hy%d: hystart cmd = 0x%x count=%d ubaddr=0x%x\n", ui->ui_unit, cmd, count, ubaddr); printD("hy%d: - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr);#endif if (((is->hy_flags & RQ_REISSUE) == 0) && (cmd != HYF_STATUS) && (cmd != HYF_END_OP) && (cmd != HYF_RSTATS)) { is->hy_savedstate = is->hy_state; is->hy_savedcmd = cmd; is->hy_savedcount = count; is->hy_savedaddr = ubaddr; }#ifdef PI13 if (addr->hyd_csr & S_POWEROFF) { printf("hy%d: \"Soft\" Adapter Power Failure (hystart)\n", ui->ui_unit); addr->hyd_csr |= S_POWEROFF; DELAY(100); if (addr->hyd_csr & S_POWEROFF) { printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hystart)\n", ui->ui_unit); if_down(&is->hy_if); is->hy_if.if_flags &= ~IFF_UP; is->hy_state = STARTUP; } else { printf("hy%d: Adapter Power Restored (hystart)\n", ui->ui_unit); } return; }#endif addr->hyd_bar = ubaddr & 0xffff; addr->hyd_wcr = is->hy_lastwcr = -((count+1) >> 1); addr->hyd_dbuf = cmd;#ifdef PI13 addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE | S_IATTN;#else addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE;#endif#ifdef DEBUG printD("hy%d: exit hystart - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr);#endif#ifdef HYLOG { struct { u_char hcmd; u_char hstate; short hcount; } hcl; hcl.hcmd = cmd; hcl.hstate = is->hy_state; hcl.hcount = count; hylog(HYL_CMD, sizeof(hcl), (char *)&hcl); }#endif is->hy_ntime = 0;}int hyint_active = 0; /* set during hy interrupt *//* * Hyperchannel interface interrupt. * * An interrupt can occur for many reasons. Examine the status of * the hyperchannel status bits to determine what to do next. * * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */hyint(unit) int unit;{ register struct hy_softc *is = &hy_softc[unit]; register struct uba_device *ui = hyinfo[unit]; register struct hydevice *addr = (struct hydevice *)ui->ui_addr; if (hyint_active) panic("RECURSIVE HYPERCHANNEL INTERRUPT"); hyint_active++;#ifdef DEBUG printD("hy%d: hyint enter - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr);#endif#ifdef HYLOGlogit: { struct { u_char hstate; u_char hflags; short hcsr; short hwcr; } hil; hil.hstate = is->hy_state; hil.hflags = is->hy_flags; hil.hcsr = addr->hyd_csr; hil.hwcr = addr->hyd_wcr; hylog(HYL_INT, sizeof(hil), (char *)&hil); }#endif if (HYS_ERROR(addr) && ((addr->hyd_csr & S_ATTN) == 0)) { /* * Error bit set, some sort of error in the interface. * * The adapter sets attn on command completion so that's not * a real error even though the interface considers it one. */#ifdef DEBUG if (hy_nodebug & 4) hy_debug_flag = 1;#endif printf("csr = 0x%b\nbar = 0x%x\nwcr = 0x%x\n", addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr); if (addr->hyd_csr & S_NEX) { printf("hy%d: NEX - Non Existant Memory\n", unit);#ifdef PI13 addr->hyd_csr |= S_NEX; /* as per PI13 manual */#else addr->hyd_csr &= ~S_NEX;#endif hycancel(ui);#ifdef PI13 } else if (addr->hyd_csr & S_POWEROFF) { printf("hy%d: \"Soft\" Adapter Power Failure (hyint)\n", unit); addr->hyd_csr |= S_POWEROFF; DELAY(100); if (addr->hyd_csr & S_POWEROFF) { printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hyint)\n", unit); if_down(&is->hy_if); is->hy_if.if_flags &= ~IFF_UP; is->hy_state = STARTUP; } else { printf("hy%d: Adapter Power Restored (hyint)\n", unit); }#endif } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -