📄 if_hy.c
字号:
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); 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 cmd 0x%x ptr 0x%x\n", is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr, is->hy_savedcmd);#endif#ifdef PI13 addr->hyd_csr &= ~S_C; /* clear the damned PI-13 */#endif if (is->hy_state == XMITSENT || is->hy_state == XMITDATASENT) is->hy_if.if_oerrors++; else if (is->hy_state == RECVSENT || is->hy_state == RECVDATASENT) is->hy_if.if_ierrors++; else is->hy_if.if_collisions++; /* other errors */ if (is->hy_state == XMITDATASENT || is->hy_state == RECVSENT || is->hy_state == RECVDATASENT || (is->hy_flags & RQ_REISSUE) != 0 || is->hy_retry > MAXRETRY) hycancel(ui); else {#ifdef DEBUG if (hy_nodebug & 2) hy_debug_flag = 1;#endif is->hy_retry++; is->hy_flags |= RQ_ENDOP | RQ_STATUS | RQ_REISSUE; is->hy_state = IDLE; hyact(ui); } } else { /* * Interrupt is neither normal, abnormal, or interface error. * Ignore it. It's either stacked or a word count 0. */#ifdef HYLOG if (hy_log.hyl_enable != hy_log.hyl_onerr) { hy_log.hyl_enable = hy_log.hyl_onerr; goto logit; }#endif#ifdef DEBUG printD("hy%d: possible stacked interrupt ignored\n", unit);#endif }#ifdef DEBUG printD("hy%d: hyint exit\n\n", unit);#endif hyint_active = 0;}int hyoutprint = 0;/* * Encapsulate a packet of type family for the local net. */hyoutput(ifp, m0, dst) struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst;{ register struct hym_hdr *hym; register struct mbuf *m; register char *mp; int dlen; /* packet size, incl hardware header, but not sw header */ int error = 0; int s; /* * Calculate packet length for later deciding whether it will fit * in a message proper or we also need associated data. */ dlen = 0; for (m = m0; m; m = m->m_next) dlen += m->m_len; m = m0; if (dst->sa_family == AF_HYLINK) { /* don't add header */ dlen -= HYM_SWLEN; goto headerexists; } /* * Add the software and hardware hyperchannel headers. * If there's not enough space in the first mbuf, allocate another. * If that should fail, drop this sucker. * No extra space for headers is allocated. */ mp = mtod(m, char *); /* save pointer to real message */ M_PREPEND(m, sizeof(struct hym_hdr), M_DONTWAIT); if (m == 0) { error = ENOBUFS; goto bad; } dlen += sizeof(struct hym_hdr) - HYM_SWLEN; hym = mtod(m, struct hym_hdr *); bzero((caddr_t)hym, sizeof(struct hym_hdr)); switch(dst->sa_family) {#ifdef INET case AF_INET: { int i; /* * if loopback address, swizzle ip header so when * it comes back it looks like it was addressed to us */ i = hyroute(ifp, (u_long)in_lnaof(((struct sockaddr_in *)dst)->sin_addr), hym); if (i < 0) goto notfound; if (i > 0) { struct in_addr temp; temp.s_addr = ((struct ip *)mp)->ip_dst.s_addr; ((struct ip *)mp)->ip_dst.s_addr = ((struct ip *)mp)->ip_src.s_addr; ((struct ip *)mp)->ip_src.s_addr = temp.s_addr; } /* * If entire packet won't fit in message proper, just * send hyperchannel hardware header and ip header in * message proper. * * This insures that the associated data is at least a * TCP/UDP header in length and thus prevents potential * problems with very short word counts. */ if (dlen > MPSIZE) hym->hym_mplen = sizeof(struct hy_hdr) + (((struct ip *)mp)->ip_hl << 2); hym->hym_type = HYLINK_IP; break; }#endif default: printf("hy%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto drop; }headerexists: /* * insure message proper is below the maximum */ if (hym->hym_mplen > MPSIZE || (dlen > MPSIZE && hym->hym_mplen == 0)) hym->hym_mplen = MPSIZE; hym->hym_from = htons(hy_softc[ifp->if_unit].hy_host); if (hym->hym_mplen) hym->hym_ctl |= H_ASSOC; else hym->hym_ctl &= ~H_ASSOC; if (hyoutprint) printf("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n", ifp->if_unit, hym->hym_mplen, hym->hym_ctl, hym->hym_access, hym->hym_to, hym->hym_from, hym->hym_param, hym->hym_type);#ifdef DEBUG printD("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n", ifp->if_unit, hym->hym_mplen, hym->hym_ctl, hym->hym_access, hym->hym_to, hym->hym_from, hym->hym_param, hym->hym_type);#endif s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); error = ENOBUFS; splx(s); goto drop; } IF_ENQUEUE(&ifp->if_snd, m); if (hy_softc[ifp->if_unit].hy_state == WAITING) hyact(hyinfo[ifp->if_unit]); splx(s); return (0);notfound: error = EHOSTUNREACH;drop: m_freem(m); return (error);}inthyroute(ifp, dest, hym) register struct ifnet *ifp; u_long dest; register struct hym_hdr *hym;{#ifdef HYROUTE register struct hy_route *rt = &hy_route[ifp->if_unit]; register struct hyr_hash *rhash; register int i;#endif hym->hym_param = 0;#ifdef HYROUTE if (rt->hyr_lasttime != 0) { i = HYRHASH(dest); rhash = &rt->hyr_hash[i]; i = 0; while (rhash->hyr_key != dest) { if (rhash->hyr_flags == 0 || i > HYRSIZE) return(-1); rhash++; i++; if (rhash >= &rt->hyr_hash[HYRSIZE]) rhash = &rt->hyr_hash[0]; } if (rhash->hyr_flags & HYR_GATE) { i = rhash->hyr_nextgate; if (i >= rhash->hyr_egate) rhash->hyr_nextgate = rhash->hyr_pgate; else rhash->hyr_nextgate++; rhash = &rt->hyr_hash[rt->hyr_gateway[i]]; if ((rhash->hyr_flags & HYR_DIR) == 0) return(-1); } else if (rhash->hyr_flags & HYR_LOOP) { hym->hym_param = H_LOOPBK; /* adapter loopback */ } else if (rhash->hyr_flags & HYR_RLOOP) { hym->hym_param = H_RLOOPBK; /* A710 remote loopback */ } hym->hym_ctl = rhash->hyr_ctl; hym->hym_access = rhash->hyr_access; hym->hym_to = rhash->hyr_dst; } else {#endif hym->hym_ctl = H_XTRUNKS | H_RTRUNKS; hym->hym_access = 0; hym->hym_to = htons((u_short)dest); if (dest & 0x010000) hym->hym_param = H_LOOPBK; /* adapter loopback */ else if (dest & 0x020000) hym->hym_param = H_RLOOPBK; /* A710 remote loopback */#ifdef HYROUTE }#endif if (hym->hym_param == 0) return(0); else return(1);}hyact(ui) register struct uba_device *ui;{ register struct hy_softc *is = &hy_softc[ui->ui_unit]; register struct hydevice *addr = (struct hydevice *)ui->ui_addr;actloop:#ifdef DEBUG printD("hy%d: hyact, enter state \"%s\"\n", ui->ui_unit, hy_state_names[is->hy_state]);#endif switch (is->hy_state) { case STARTUP: goto endintr; case IDLE: { register rq = is->hy_flags; if (rq & RQ_STATUS) { is->hy_flags &= ~RQ_STATUS; is->hy_state = STATSENT; hystart(ui, HYF_STATUS, sizeof (is->hy_status), is->hy_ifuba.ifu_r.ifrw_info); } else if (rq & RQ_ENDOP) { is->hy_flags &= ~RQ_ENDOP; is->hy_state = ENDOPSENT; hystart(ui, HYF_END_OP, 0, 0); } else if (rq & RQ_STATISTICS) { is->hy_flags &= ~RQ_STATISTICS; is->hy_state = RSTATSENT; hystart(ui, HYF_RSTATS, sizeof (is->hy_stat), is->hy_ifuba.ifu_r.ifrw_info); } else if (HYS_RECVDATA(addr)) { is->hy_state = RECVSENT; is->hy_retry = 0; hystart(ui, HYF_INPUTMSG, MPSIZE, is->hy_ifuba.ifu_r.ifrw_info + HYM_SWLEN); } else if (rq & RQ_REISSUE) { is->hy_flags &= ~RQ_REISSUE; is->hy_state = is->hy_savedstate;#ifdef DEBUG printD("hy%d: reissue cmd=0x%x count=%d", ui->ui_unit, is->hy_savedcmd, is->hy_savedcount); printD(" ubaddr=0x%x retry=%d\n", is->hy_savedaddr, is->hy_retry);#endif hystart(ui, is->hy_savedcmd, is->hy_savedcount, is->hy_savedaddr); } else { register struct mbuf *m; IF_DEQUEUE(&is->hy_if.if_snd, m); if (m != NULL) { register struct hym_hdr *hym; register int mplen; register int cmd; is->hy_state = XMITSENT; is->hy_retry = 0; hym = mtod(m, struct hym_hdr *);#ifdef HYLOG hylog(HYL_XMIT, sizeof(struct hym_hdr), (char *)hym);#endif mplen = hym->hym_mplen; if (hym->hym_to_adapter == hym->hym_from_adapter) cmd = HYF_XMITLOCMSG; else cmd = HYF_XMITMSG;#ifdef DEBUG printD("hy%d: hym_hdr = ", ui->ui_unit); if (hy_debug_flag) hyprintdata((char *)hym, sizeof (struct hym_hdr));#endif is->hy_olen = if_wubaput(&is->hy_ifuba, m) - HYM_SWLEN; if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) UBAPURGE(is->hy_ifuba.ifu_uba, is->hy_ifuba.ifu_w.ifrw_bdp);#ifdef DEBUG printD( "hy%d: sending packet (mplen = %d, hy_olen = %d) data = ", ui->ui_unit, mplen, is->hy_olen); if (hy_debug_flag) hyprintdata( is->hy_ifuba.ifu_w.ifrw_addr, is->hy_olen + HYM_SWLEN);#endif if (mplen == 0) { is->hy_flags &= ~RQ_XASSOC; mplen = is->hy_olen; } else { is->hy_flags |= RQ_XASSOC; } hystart(ui, cmd, mplen, is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN); } else if (rq & RQ_MARKDOWN) { is->hy_flags &= ~(RQ_MARKUP | RQ_MARKDOWN); is->hy_state = MARKPORT; is->hy_retry = 0; /* * Port number is taken from status data */ hystart(ui, (int)(HYF_MARKP0|(PORTNUM(&is->hy_status)<<2)), 0, 0); } else if (rq & RQ_MARKUP) { register struct ifnet *ifp = &is->hy_if; is->hy_flags &= ~RQ_MARKUP; is->hy_retry = 0; /* * Fill in the host number * from the status buffer */ printf( "hy%d: unit number 0x%x port %d type %x microcode level 0x%x\n", ui->ui_unit, is->hy_stat.hyc_uaddr, PORTNUM(&is->hy_status), (is->hy_stat.hyc_atype[0]<<8) | is->hy_stat.hyc_atype[1], is->hy_stat.hyc_atype[2]); is->hy_host = (is->hy_stat.hyc_uaddr << 8) | PORTNUM(&is->hy_status); ifp->if_flags |= IFF_UP;#ifdef HYLOG hylog(HYL_UP, 0, (char *)0);#endif } else { is->hy_state = WAITING; is->hy_retry = 0; hystart(ui, HYF_WAITFORMSG, 0, 0); } } break; } case STATSENT: bcopy(is->hy_ifuba.ifu_r.ifrw_addr, (caddr_t)&is->hy_status, sizeof (struct hy_status));#ifdef DEBUG printD("hy%d: status - %x %x %x %x %x %x %x %x\n", ui->ui_unit, is->hy_status.hys_gen_status, is->hy_status.hys_last_fcn, is->hy_status.hys_resp_trunk, is->hy_status.hys_status_trunk, is->hy_status.hys_recd_resp, is->hy_status.hys_error, is->hy_status.hys_caddr, is->hy_status.hys_pad);#endif is->hy_state = IDLE;#ifdef HYLOG hylog(HYL_STATUS, sizeof (struct hy_status), (char *)&is->hy_status);#endif#ifdef HYELOG { register int i; i = is->hy_status.hys_error; if (i > HYE_MAX) i = HYE_MAX; switch (is->hy_status.hys_last_fcn) { case HYF_XMITLOCMSG: i += HYE_MAX+1; /* fall through */ case HYF_XMITLSTDATA: i += HYE_MAX+1; /* fall through */ case HYF_XMITMSG: i += HYE_MAX+1; } hy_elog[i]++; }#endif break; case RSTATSENT: { register struct hy_stat *p = (struct hy_stat *)is->hy_ifuba.ifu_r.ifrw_addr; bcopy((caddr_t)p, (caddr_t)&is->hy_stat, sizeof(struct hy_stat));#ifdef DEBUG printD("hy%d: statistics - df0 %d df1 %d df2 %d df3 %d\n", ui->ui_unit, (is->hy_stat.hyc_df0[0]<<16) | (is->hy_stat.hyc_df0[1]<<8) | is->hy_stat.hyc_df0[2], (is->hy_stat.hyc_df1[0]<<16) | (is->hy_stat.hyc_df1[1]<<8) | is->hy_stat.hyc_df1[2], (is->hy_stat.hyc_df2[0]<<16) | (is->hy_stat.hyc_df2[1]<<8) | is->hy_stat.hyc_df2[2], (is->hy_stat.hyc_df3[0]<<16) | (is->hy_stat.hyc_df3[1]<<8) | is->hy_stat.hyc_df3[2]); printD(" ret0 %d ret1 %d ret2 %d ret3 %d\n", (is->hy_stat.hyc_ret0[0]<<16) | (is->hy_stat.hyc_ret0[1]<<8) | is->hy_stat.hyc_ret0[2], (is->hy_stat.hyc_ret1[0]<<16) | (is->hy_stat.hyc_ret1[1]<<8) | is->hy_stat.hyc_ret1[2], (is->hy_stat.hyc_ret2[0]<<16) | (is->hy_stat.hyc_ret2[1]<<8) | is->hy_stat.hyc_ret2[2], (is->hy_stat.hyc_ret3[0]<<16) | (is->hy_stat.hyc_ret3[1]<<8) | is->hy_stat.hyc_ret3[2]); printD(" cancel %d abort %d atype %x %x %x uaddr %x\n", (is->hy_stat.hyc_cancel[0]<<8) | is->hy_stat.hyc_cancel[1], (is->hy_stat.hyc_abort[0]<<8) | is->hy_stat.hyc_abort[1], is->hy_stat.hyc_atype[0], is->hy_stat.hyc_atype[1], is->hy_stat.hyc_atype[2], is->hy_stat.hyc_uaddr);#endif is->hy_state = IDLE;#ifdef HYLOG hylog(HYL_STATISTICS, sizeof (struct hy_stat), (char *)&is->hy_stat);#endif break; } case CLEARSENT: is->hy_state = IDLE; break; case ENDOPSENT: is->hy_state = IDLE; break; case RECVSENT: { register struct hym_hdr *hym; register unsigned len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -