📄 if_hy.c
字号:
if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->hy_ifuba.ifu_uba, is->hy_ifuba.ifu_r.ifrw_bdp); hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr); len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; if (len > MPSIZE) { printf("hy%d: RECVD MP > MPSIZE (%d)\n", ui->ui_unit, len); is->hy_state = IDLE;#ifdef DEBUG hy_debug_flag = 1; 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 } hym->hym_mplen = len;#ifdef DEBUG printD("hy%d: recvd mp, len = %d, data = ", ui->ui_unit, len); if (hy_debug_flag) hyprintdata((char *)hym, len + HYM_SWLEN);#endif if (hym->hym_ctl & H_ASSOC) { is->hy_state = RECVDATASENT; is->hy_retry = 0; hystart(ui, HYF_INPUTDATA, (int)(HYMTU + sizeof (struct hy_hdr) - len), (int)(HYM_SWLEN + is->hy_ifuba.ifu_r.ifrw_info + len)); } else { hyrecvdata(ui, hym, (int)len + HYM_SWLEN); is->hy_state = IDLE; } break; } case RECVDATASENT: { register struct hym_hdr *hym; register unsigned len; if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->hy_ifuba.ifu_uba, is->hy_ifuba.ifu_r.ifrw_bdp); hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr); len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;#ifdef DEBUG printD("hy%d: recvd assoc data, len = %d, data = ", ui->ui_unit, len); if (hy_debug_flag) hyprintdata((char *)hym + hym->hym_mplen, len);#endif hyrecvdata(ui, hym, (int)(len + hym->hym_mplen + HYM_SWLEN)); is->hy_state = IDLE; break; } case XMITSENT: if (is->hy_flags & RQ_XASSOC) { register int len; is->hy_flags &= ~RQ_XASSOC; is->hy_state = XMITDATASENT; is->hy_retry = 0; len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; if (len > is->hy_olen) { printf( "hy%d: xmit error - len > hy_olen [%d > %d]\n", ui->ui_unit, len, is->hy_olen);#ifdef DEBUG hy_debug_flag = 1;#endif } hystart(ui, HYF_XMITLSTDATA, is->hy_olen - len, is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN + len); break; } /* fall through to ... */ case XMITDATASENT: hyxmitdata(ui); is->hy_state = IDLE; break; case WAITING: /* wait for message complete or output requested */ if (HYS_RECVDATA(addr)) is->hy_state = IDLE; else { is->hy_state = CLEARSENT; is->hy_retry = 0; hystart(ui, HYF_CLRWFMSG, 0, 0); } break; case MARKPORT: is->hy_state = STARTUP; if_down(&is->hy_if); is->hy_if.if_flags &= ~IFF_UP; goto endintr; default: printf("hy%d: DRIVER BUG - INVALID STATE %d\n", ui->ui_unit, is->hy_state); panic("HYPERCHANNEL IN INVALID STATE"); /*NOTREACHED*/ } if (is->hy_state == IDLE) goto actloop;endintr: ;#ifdef DEBUG printD("hy%d: hyact, exit at \"%s\"\n", ui->ui_unit, hy_state_names[is->hy_state]);#endif}struct sockproto hypproto = { PF_HYLINK };struct sockaddr_in hypdst = { sizeof(hypdst), AF_HYLINK };struct sockaddr_in hypsrc = { sizeof(hypsrc), AF_HYLINK };/* * Called from device interrupt when receiving data. * Examine packet to determine type. Decapsulate packet * based on type and pass to type specific higher-level * input routine. */hyrecvdata(ui, hym, len) struct uba_device *ui; register struct hym_hdr *hym; int len;{ register struct hy_softc *is = &hy_softc[ui->ui_unit]; struct mbuf *m; register struct ifqueue *inq; is->hy_if.if_ipackets++;#ifdef DEBUG printD("hy%d: recieved packet, len = %d\n", ui->ui_unit, len);#endif#ifdef HYLOG { struct { short hlen; struct hym_hdr hhdr; } hh; hh.hlen = len; hh.hhdr = *hym; hylog(HYL_RECV, sizeof(hh), (char *)&hh); }#endif if (len > HYMTU + MPSIZE || len == 0) return; /* sanity */ /* * Pull packet off interface. */ m = if_rubaget(&is->hy_ifuba, len, 0, &is->hy_if); if (m == NULL) return; /* * if normal or adapter loopback response packet believe hym_type, * otherwise, use the raw input queue cause it's a response from an * adapter command. */ if (hym->hym_param != 0 && (u_short)hym->hym_param != 0x80ff) goto rawlinkin; switch (hym->hym_type) {#ifdef INET case HYLINK_IP: schednetisr(NETISR_IP); inq = &ipintrq; break;#endif default: rawlinkin: { M_PREPEND(m, sizeof(struct hym_hdr), M_DONTWAIT); if (m == 0) { m_freem(m); return; } bcopy((caddr_t)hym, mtod(m, caddr_t), sizeof(struct hym_hdr)); hypproto.sp_protocol = 0; hypdst.sin_addr = is->hy_addr; hypsrc.sin_addr = is->hy_addr; raw_input(m, &hypproto, (struct sockaddr *)&hypsrc, (struct sockaddr *)&hypdst); return; } } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m);}/* * Transmit done, release resources, bump counters. */hyxmitdata(ui) struct uba_device *ui;{ register struct hy_softc *is = &hy_softc[ui->ui_unit]; is->hy_if.if_opackets++; if (is->hy_ifuba.ifu_xtofree) { m_freem(is->hy_ifuba.ifu_xtofree); is->hy_ifuba.ifu_xtofree = 0; }}hycancel(ui) register struct uba_device *ui;{ register struct hy_softc *is = &hy_softc[ui->ui_unit]; if (is->hy_ifuba.ifu_xtofree) { m_freem(is->hy_ifuba.ifu_xtofree); is->hy_ifuba.ifu_xtofree = 0; }#ifdef HYLOG hylog(HYL_CANCEL, 0, (char *)0);#endif#ifdef DEBUG if (hy_nodebug & 1) hy_debug_flag = 1;#endif#ifdef DEBUG printD("hy%d: cancel from state \"%s\" cmd=0x%x count=%d ptr=0x%x\n", ui->ui_unit, hy_state_names[is->hy_state], is->hy_savedcmd, is->hy_savedcount, is->hy_savedaddr); printD("\tflags 0x%x olen %d lastwcr %d retry %d\n", is->hy_flags, is->hy_olen, is->hy_lastwcr, is->hy_retry); printD("\tsaved: state %d count %d ptr 0x%x cmd 0x%x\n", is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr, is->hy_savedcmd);#endif is->hy_state = IDLE; is->hy_flags |= (RQ_ENDOP | RQ_STATUS); hyact(ui);}#ifdef DEBUGhyprintdata(cp, len) register char *cp; register int len;{ register int count = 16; register char *fmt; static char regfmt[] = "\n\t %x"; fmt = ®fmt[2]; while (--len >= 0) { printL(fmt, *cp++ & 0xff); fmt = ®fmt[2]; if (--count <= 0) { fmt = ®fmt[0]; count = 16; } } printL("\n");}#endifhywatch(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; int s; s = splimp();#ifdef PI13 if ((addr->hyd_csr & S_POWEROFF) != 0) { addr->hyd_csr |= S_POWEROFF; DELAY(100); if ((addr->hyd_csr & S_POWEROFF) == 0) { printf("hy%d: Adapter Power Restored (hywatch)\n", unit); is->hy_state = IDLE; is->hy_flags |= (RQ_MARKUP | RQ_STATISTICS | RQ_ENDOP | RQ_STATUS); hyact(ui); } }#endif if (++is->hy_ntime >= 2 && is->hy_state != WAITING && is->hy_state != STARTUP && is->hy_state != IDLE) {#ifdef HYLOG printf("hy%d: watchdog timer expired in state \"%s\"\n", unit, hy_state_names[is->hy_state]);#else printf("hy%d: watchdog timer expired in state %d\n", unit, is->hy_state);#endif printf("hy%d: last command 0x%x, flags 0x%x, csr 0x%b\n", unit, is->hy_savedcmd, is->hy_flags, addr->hyd_csr, HY_CSR_BITS); hycancel(ui); } splx(s); is->hy_if.if_timer = SCANINTERVAL;}#ifdef HYLOGhylog(code, len, ptr) int code, len; char *ptr;{ register unsigned char *p; int s; s = splimp(); if (hy_log.hyl_self != &hy_log) { hy_log.hyl_eptr = &hy_log.hyl_buf[HYL_SIZE]; hy_log.hyl_ptr = &hy_log.hyl_buf[0]; hy_log.hyl_self = &hy_log; hy_log.hyl_enable = HYL_CONTINUOUS; hy_log.hyl_onerr = HYL_CONTINUOUS; hy_log.hyl_count = 0; hy_log.hyl_icount = 16; hy_log.hyl_filter = 0xffff; /* enable all */ } if (hy_log.hyl_enable == HYL_DISABLED || ((1 << code) & hy_log.hyl_filter) == 0) goto out; p = hy_log.hyl_ptr; if (p + len + 3 >= hy_log.hyl_eptr) { bzero((caddr_t)p, (unsigned)(hy_log.hyl_eptr - p)); p = &hy_log.hyl_buf[0]; if (hy_log.hyl_enable != HYL_CONTINUOUS) { hy_log.hyl_enable = HYL_DISABLED; goto out; } } *p++ = code; *p++ = len; bcopy((caddr_t)ptr, (caddr_t)p, (unsigned)len); if (hy_log.hyl_count != 0 && --hy_log.hyl_count == 0) { *p++ = '\0'; hy_log.hyl_enable = HYL_DISABLED; hy_log.hyl_count = hy_log.hyl_icount; } p += len; if (hy_log.hyl_wait != 0) { /* wakeup HYGETLOG if wanted */ if (hy_log.hyl_wait <= p - hy_log.hyl_ptr) { wakeup((caddr_t)&hy_log); hy_log.hyl_wait = 0; } else hy_log.hyl_wait -= p - hy_log.hyl_ptr; } hy_log.hyl_ptr = p;out: splx(s);}#endif/*ARGSUSED*/hyioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ struct ifaddr *ifa = (struct ifaddr *) data; struct hyrsetget *sg = (struct hyrsetget *)data;#if defined(HYLOG) || defined(HYELOG) struct hylsetget *sgl = (struct hylsetget *)data;#endif struct hy_route *r = (struct hy_route *)&hy_route[ifp->if_unit]; int s = splimp(), error = 0;#ifdef HYLOG struct hy_softc *is = &hy_softc[ifp->if_unit]; struct { u_char hstate; u_char hflags; u_short iflags; int hcmd; int herror; u_long haddr; u_long hmisc; } hil; hil.hmisc = -1; hil.hstate = is->hy_state; hil.hflags = is->hy_flags; hil.hcmd = cmd;#endif switch(cmd) { case SIOCSIFADDR: if (ifa->ifa_addr->sa_family != AF_INET) return(EINVAL); if ((ifp->if_flags & IFF_RUNNING) == 0) hyinit(ifp->if_unit); hy_softc[ifp->if_unit].hy_addr = IA_SIN(ifa)->sin_addr;#ifdef HYLOG hil.haddr = is->hy_addr.s_addr;#endif break; case HYSETROUTE: if (error = suser(u.u_cred, &u.u_acflag)) goto out; if (sg->hyrsg_len != sizeof(struct hy_route)) { error = EINVAL; goto out; } if (copyin((caddr_t)(sg->hyrsg_ptr), (caddr_t)r, sg->hyrsg_len)) { r->hyr_lasttime = 0; /* disable further routing if trouble */ error = EFAULT; goto out; } r->hyr_lasttime = time.tv_sec;#ifdef HYLOG hil.hmisc = r->hyr_lasttime;#endif break; case HYGETROUTE: if (sg->hyrsg_len < sizeof(struct hy_route)) { error = EINVAL; goto out; } if (copyout((caddr_t)r, (caddr_t) (sg->hyrsg_ptr), sizeof(struct hy_route))) { error = EFAULT; goto out; } break;#ifdef HYELOG case HYGETELOG: if (sgl->hylsg_len < sizeof(hy_elog)) { error = EINVAL; goto out; } if (copyout((caddr_t)hy_elog, sgl->hylsg_ptr, sizeof(hy_elog))) { error = EFAULT; goto out; } if (sgl->hylsg_cmd) { if (error = suser(u.u_cred, &u.u_acflag)) goto out; bzero((caddr_t)hy_elog, sizeof(hy_elog)); } break;#endif#ifdef HYLOG case HYSETLOG: if (error = suser(u.u_cred, &u.u_acflag)) goto out; hy_log.hyl_enable = HYL_DISABLED; hylog(HYL_NOP, 0, (char *)0); /* force log init */ hy_log.hyl_enable = sgl->hylsg_cmd & 0x0f; hy_log.hyl_onerr = (sgl->hylsg_cmd >> 4) & 0x0f; hy_log.hyl_filter = (sgl->hylsg_cmd >> 8) & 0xffffff; hy_log.hyl_count = hy_log.hyl_icount = sgl->hylsg_len; wakeup((caddr_t)&hy_log); /* wakeup sleeping HYGETLOG */ break; case HYGETLOG: if (sgl->hylsg_len < sizeof(hy_log)) { error = EINVAL; goto out; } if (sgl->hylsg_cmd != 0) { if (hy_log.hyl_wait) { error = EBUSY; goto out; } hy_log.hyl_wait = sgl->hylsg_cmd; sleep((caddr_t)&hy_log, PZERO - 1); } if (copyout((caddr_t)&hy_log, sgl->hylsg_ptr, sizeof(hy_log))) { error = EFAULT; goto out; } break;#endif default: error = EINVAL; break; }out:#ifdef HYLOG hil.herror = error; hil.iflags = ifp->if_flags; hil.haddr = is->hy_addr.s_addr; hylog(HYL_IOCTL, sizeof(hil), (char *)&hil);#endif splx(s); return (error);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -