📄 if_hy.c
字号:
#ifndef lintstatic char *sccsid = "@(#)if_hy.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * * * 05-Feb-89 -- R. Bhanukitsiri * * Reflect V3.2 source pool changes. Also, include * * Lea's changes from 27-Jul-88 (added & typo). * * * * 12-Apr-88 -- lea 43.5bsd fixes * * * * 13-Jun-86 -- jaw fix to uba reset and drivers. * * * 18-mar-86 -- jaw br/cvec changed to NOT use registers. * * Larry Cohen - 09/16/85 * * Add 43bsd alpha tape changes for subnet routing * * * ************************************************************************//* * Copyright (c) 1982 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)if_hy.c 7.1 (Berkeley) 6/5/86 *//* * 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 || defined(BINARY)#include "../data/if_hy_data.c"/* * configuration specific paramters * - change as appropriate for particular installaions */#define HYELOG#define HYLOG#define HYMTU 1100#ifdef HYELOGu_long hy_elog[HYE_SIZE];#endif#ifdef HYLOGstruct hy_log hy_log;#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) */int hyprobe(), hyattach(), hyinit(), hyioctl();int hyoutput(), hyreset(), hywatch();u_short hystd[] = { 0772410, 0 };struct uba_driver hydriver = { hyprobe, 0, hyattach, 0, hystd, "hy", hyinfo };char *hy_state_names[] = { "Startup", "Idle", "Status Sent", "End op Sent", "Recieve Message Proper Sent", "Recieve Data Sent", "Transmit Message Proper Sent", "Transmit Data Sent", "Wait for Message Sent", "Clear Wait for Message Sent", "Mark Port Down Sent", "Read Statistics Sent"};/* * Network Systems Copropration Hyperchanel interface *//* * 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 struct hydevice *addr = (struct hydevice *) reg;#ifdef lint 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 >= nNHY || (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 { printf("hy%d: BAR overflow\n", unit); hycancel(ui); } } else if (HYS_NORMAL(addr)) { /* * Normal interrupt, bump state machine unless in state * waiting and no data present (assumed to be word count * zero interrupt or other hardware botch). */ if (is->hy_state != WAITING || HYS_RECVDATA(addr)) hyact(ui); } else if (HYS_ABNORMAL(addr)) { /* * Abnormal termination. * bump error counts, retry the last function * 'MAXRETRY' times before kicking the bucket. * * Don't reissue the cmd if in certain states, abnormal * on a reissued cmd or max retry exceeded. */#ifdef HYLOG if (hy_log.hyl_enable != hy_log.hyl_onerr) { hy_log.hyl_enable = hy_log.hyl_onerr; goto logit; }#endif#ifdef DEBUG if (hy_nodebug & 4) hy_debug_flag = 1; printD("hy%d: abnormal interrupt, driver state \"%s\" (%d)\n", unit, hy_state_names[is->hy_state], is->hy_state);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -