📄 if_ni.c
字号:
} /* header + space for DGRLEN buffer names */ ni_data->dg_len = NI_DGRLEN; ni_data->opcode = DGREC; ni_data->dg_ptdb_index = 2; for(j=0; j<NI_RBUF; j++) { bde = (struct _bd *) ni->ni_pqb->ni.bdt_base; bde += i+j;/* Need to have 1st buffer be ether_header */ if(j == 0) { KM_ALLOC(buffer, char *, sizeof(struct ether_header), KM_DEVBUF, KM_NOWAIT); if (buffer == 0){ printf("ni%d Init out of memory - buffer\n",ni->unit); return; } bde->buf_len = sizeof(struct ether_header); bde->pt_addr = svtopte(buffer); bde->offset = (unsigned)buffer&PGOFSET; } else if ( j == 1) { KM_ALLOC(buffer, char *,M_CLUSTERSZ,KM_CLUSTER, KM_NOWAIT); if (buffer == 0){ printf("ni%d Init out of memory - buffer\n",ni->unit); return; } bde->pt_addr = svtopte(buffer); bde->offset = (unsigned)buffer&PGOFSET; bde->buf_len = NI_MAXPACKETSZ; } else { cprintf("Too many recv desc"); } bde->key = 1; bde->valid = 1; ni_data->cbufs[j].offset = 0; ni_data->cbufs[j].s_len = bde->buf_len; ni_data->cbufs[j].bdt_index = i+j; ni_data->cbufs[j].buffer_key = 1; } if((empty=insqti(ni_data, &ni->freeq2, NI_MAXITRY)) > 0) printf("recv insqti failed %d\n", i); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_RFREEQ|PC_OWN; while((addr->pc&PC_OWN)) ; } } splx(s); while((addr->ps&PS_OWN)) ; /* Write Parameters */ { struct ni_msg *ni_msg; KM_ALLOC(ni_msg, struct ni_msg *, sizeof(struct ni_msg), KM_DEVBUF, KM_NOW_CL); if (ni_msg == 0){ printf("ni%d Init out of memory - ni_msg\n",ni->unit); return; } ni_msg->opcode = SNDMSG; ni_msg->status = 0; ni_msg->msg_len = sizeof(struct ni_param) + 6; ni_msg->ni_opcode = NIOP_WPARAM; /* Someone has set the apa at least once */ if((bcmp(ds->ds_addr, ni_notset, 6) != 0)) bcopy(ds->ds_addr,((struct ni_param *)&ni_msg->text[0])->apa, 6); ((struct ni_param *)&ni_msg->text[0])->flags = NI_PAD; if((empty=insqti(ni_msg, &ni->comq0, NI_MAXITRY)) > 0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN; while((addr->pc&PC_OWN)) ; } } { struct ni_msg *ni_msg; KM_ALLOC(ni_msg, struct ni_msg *, sizeof(struct ni_msg), KM_DEVBUF, KM_NOW_CL); if (ni_msg == 0){ printf("ni%d Init out of memory - ni_msg\n",ni->unit); return; } ni_msg->opcode = SNDMSG; ni_msg->status = 0; ni_msg->msg_len = sizeof(struct ni_param) + 6; ni_msg->ni_opcode = NIOP_RCCNTR; if((empty=insqti(ni_msg, &ni->comq0, NI_MAXITRY)) > 0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN; while((addr->pc&PC_OWN)) ; } } /* Let all these commands complete */ while((addr->ps & PS_OWN)) ; /* Hardware address not set yet */ while((bcmp(ds->ds_addr, ni_notset, 6) == 0)) ; /* Set up PTDB's */ ni_sptdb(ni,0,1,1,0,1); /* #1 for send queue returns */ ni_sptdb(ni,ETHERTYPE_IP,2,2,PTDB_UNK|PTDB_BDC,1); /* #2 all incoming */ ds->nxmit = 0; ifp->if_flags &= ~IFF_OACTIVE; /* The board is up (ooo rah) */ s = splimp(); smp_lock(&ds->lk_ni_softc, LK_RETRY); ds->ds_if.if_flags |= IFF_UP|IFF_RUNNING; nistart(unit); /* queue output packets */ smp_unlock(&ds->lk_ni_softc); splx(s);}/* * Setup output on interface. */nistart(unit) int unit;{ register struct ni *ni = &niinfo[unit]; register struct mbuf *m, *m0; register struct _bd *bde; register struct ni_data *nid; register int len, curindex; struct mbuf *mprev; struct ni_softc *ds = &ni_softc[unit]; struct nidevice *addr = (struct nidevice *)ni->ni_regs; int empty; if((addr->ps&PS_STATEMASK) != PS_ENABLED) { cprintf("ni%d state(nistart) %x %x %x %x\n", unit, addr->ps, addr->pe, addr->pc, addr->pd); if((addr->ps&PS_STATEMASK) == PS_UNDEFINED || (addr->ps&PS_STATEMASK) == PS_STOPPED) nireset(unit); } /* * Check the queues BEFORE dequeueing an entry */ while (ds->ds_if.if_snd.ifq_head && ni->freeq1.flink) { if((nid = (struct ni_data *)remqhi(&ni->freeq1, NI_MAXITRY)) == (struct ni_data *)QEMPTY) goto done; IF_DEQUEUE(&ds->ds_if.if_snd, m0); m = m0; bde = (struct _bd *) ni->ni_pqb->ni.bdt_base; bde += nid->cbufs[0].bdt_index; mprev = 0; for (len = 0, curindex = 0; m; curindex++, bde++) { if ((curindex == (NI_NUMBUF - 2)) && (m->m_next && m->m_next->m_next)) { int off = 0; struct mbuf *n, *p = 0; MGET(n, M_DONTWAIT, MT_DATA); if (n) { MCLGET(n, p); if (p == 0) m_freem(n); } if (!p) { if((empty=insqti(nid, &ni->freeq1, NI_MAXITRY)) > 0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_DFREEQ|PC_OWN; } m_freem(m0); goto done; } while (m->m_next) { bcopy(mtod(m, caddr_t), mtod(n, caddr_t)+off, (unsigned)m->m_len); off += m->m_len; m = m_free(m); } n->m_len = off; n->m_next = m; m = n; if (mprev) mprev->m_next = n; } bde->offset = mtod(m, unsigned)&PGOFSET; bde->pt_addr = svtopte(mtod(m, char *)); bde->buf_len = m->m_len; bde->valid = 1; nid->cbufs[curindex].offset = 0; nid->cbufs[curindex].s_len = bde->buf_len; nid->cbufs[curindex].chain = 1; len += m->m_len; mprev = m; m = m->m_next; } if(len < 64) { /* Last buffer may get something tacked on */ (--bde)->buf_len += 64 - len; nid->cbufs[curindex-1].s_len += 64 - len; } nid->opcode = SNDDG; nid->R = 1; nid->status = 0; nid->dg_ptdb_index = 1; nid->dg_len = 10 + curindex*8; nid->cbufs[--curindex].chain = 0; nid->mbuf_tofree = (unsigned long)m0; ds->nxmit++; ds->ds_if.if_flags |= IFF_OACTIVE; ds->ds_if.if_opackets++; if((empty=insqti(nid, &ni->comq0, NI_MAXITRY)) > 0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN; } }done: return;}/* * Command done interrupt. */bvpniintr(unit) register int unit;{ register struct ni *ni = &niinfo[unit]; register struct nidevice *addr = (struct nidevice *)ni->ni_regs; register struct ni_softc *ds = &ni_softc[unit]; int s;retry: if((addr->ps&PS_STATEMASK) != PS_ENABLED) { if((addr->ps&PS_STATEMASK) == PS_UNDEFINED || (addr->ps&PS_STATEMASK) == PS_STOPPED) nireset(unit); addr->ps &= ~PS_SUME; goto done; } /* * Check for incoming packets. */ s = splimp(); smp_lock(&ds->lk_ni_softc, LK_RETRY); if(addr->ps&PS_RSQ) { nirecv(unit); } /* * Check for outgoing packets. */ if (!(ds->ds_if.if_flags & IFF_OACTIVE)) nistart(unit); smp_unlock(&ds->lk_ni_softc); splx(s);done: if(addr->ps & PS_SUME) { register struct el_rec *elrp; if ((addr->ps & PS_FQE) && (addr->pd != 0)) /* * PS_FQE for other than free queue 0 NOT an * error condition. */ ni_fqe++; else { if((elrp = ealloc(sizeof(struct el_bvp), EL_PRILOW))) { register struct el_bvp *elbod; struct biic_regs *nxv; elbod = &elrp->el_body.elbvp; nxv = (struct biic_regs *) ((char *)(ni->ni_regs) - NI_NI_ADDR); elbod->bvp_biic_typ = nxv->biic_typ; elbod->bvp_biic_csr = nxv->biic_ctrl; elbod->bvp_pcntl = addr->pc; elbod->bvp_pstatus = addr->ps; elbod->bvp_perr = addr->pe; elbod->bvp_pdata = addr->pd; LSUBID(elrp,ELCT_DCNTL,ELBI_BVP,ELBVP_AIE, ni->ni_pqb->ni.piv.bi_node,unit,addr->pe); EVALID(elrp); } } if((addr->ps&PS_STATEMASK) == PS_UNDEFINED || (addr->ps&PS_STATEMASK) == PS_STOPPED) goto retry; } addr->ps &= ~(PS_OWN|PS_SUME|PS_RSQ);}/* * Ethernet interface receiver interface. */nirecv(unit) int unit;{ register struct ni *ni = &niinfo[unit]; register struct ni_data *nid; register struct nidevice *addr = (struct nidevice *)ni->ni_regs; register struct ni_softc *ds = &ni_softc[unit]; int len, empty; struct _bd *bde; /* First guess is that its a data gram recieve */ for(;;) { if((nid = (struct ni_data *)remqhi(&ni->respq, NI_MAXITRY)) >= (struct ni_data *)QEMPTY) break; if(nid->status&PCK_FAIL) { register struct el_rec *elrp; if((elrp = ealloc(sizeof(struct el_bvp), EL_PRILOW))) { register struct el_bvp *elbod; struct biic_regs *nxv; elbod = &elrp->el_body.elbvp; nxv = (struct biic_regs *) ((char *)(ni->ni_regs) - NI_NI_ADDR); elbod->bvp_biic_typ = nxv->biic_typ; elbod->bvp_biic_csr = nxv->biic_ctrl; elbod->bvp_pcntl = addr->pc; elbod->bvp_pstatus = addr->ps; elbod->bvp_perr = addr->pe; elbod->bvp_pdata = addr->pd; LSUBID(elrp,ELCT_DCNTL,ELBI_BVP,ELBVP_AIE, ni->ni_pqb->ni.piv.bi_node,unit,nid->status); EVALID(elrp); } } switch(nid->opcode) { case DGIREC: case DGISNT: break; case DGREC: ds->ds_if.if_ipackets++; bde = (struct _bd *) ni->ni_pqb->ni.bdt_base; bde += nid->cbufs[0].bdt_index; if(nid->status&PCK_FAIL) ds->ds_if.if_ierrors++; len = 0; /* Walk buffers & add length */ { register int curindex = 0; register struct _bd *pbde = bde; while(curindex < NI_RBUF ) { len += nid->cbufs[curindex].s_len; nid->cbufs[curindex].s_len = pbde++->buf_len; if(nid->cbufs[curindex].chain == 0) break; curindex++; } } niread(ni, ds, bde, len, 0); nid->opcode=DGREC; nid->dg_len = NI_DGRLEN; nid->status=0; /* DGREC must end up on freeq2 */ if((empty=insqti(nid, &ni->freeq2, NI_MAXITRY)) > 0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_RFREEQ|PC_OWN; } break; case DGSNT: /* DGSNT must end up on freeq1 */ { struct mbuf *m = (struct mbuf *)nid->mbuf_tofree; if (!(--ds->nxmit)) ds->ds_if.if_flags &= ~IFF_OACTIVE; if(nid->status&PCK_FAIL) { ds->ds_if.if_oerrors++; m_freem(m); } else { if(((bcmp(mtod(m, struct ether_header *), ni_multi, 6) == 0)) || (ds->ds_if.if_flags & IFF_PFCOPYALL)) niread(ni, ds, 0, 64, m); else m_freem(m); } nid->mbuf_tofree = 0; if((empty=insqti(nid, &ni->freeq1, NI_MAXITRY)) > 0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_DFREEQ|PC_OWN; } } break; case MSGSNT: case MSGREC: { struct ni_msg *ni_msg; ni_msg = (struct ni_msg *)nid; switch(ni_msg->ni_opcode) { case NIOP_WPARAM: case NIOP_RPARAM: bcopy(((struct ni_param *)&ni_msg->text[0])->apa, ds->ds_addr, 6); bcopy(((struct ni_param *)&ni_msg->text[0])->dpa, ds->ds_dpaddr, 6);#if NPACKETFILTER > 0 /* tell packet filter about new address */ pfilt_newaddress(ds->ds_ed.ess_enetunit, ds->ds_addr);#endif NPACKETFILTER > 0 break; case NIOP_RCCNTR: case NIOP_RDCNTR: /* User may be waiting for info to come back */ wakeup((caddr_t)ni_msg); break; case NIOP_STPTDB: case NIOP_CLPTDB: default: break; } /* MSGSNT must end up on freeq0 */ if((empty=insqti(ni_msg, &ni->freeq0, NI_MAXITRY))>0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_MFREEQ|PC_OWN; } } break; default: cprintf("ni%d unknown respq opcode\n", unit); if((empty=insqti(nid, &ni->freeq0, NI_MAXITRY))>0) printf("insqti failed\n"); else if(empty == QEMPTY) { while((addr->pc&PC_OWN)) ; addr->pc = PC_FREEQNE|PC_MFREEQ|PC_OWN; } break; } } }/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */niread(ni, ds, bde, len, swloop) struct ni *ni; register struct ni_softc *ds; register struct _bd *bde; int len; struct mbuf *swloop; { register struct mbuf *m, *swloop_tmp1; struct ether_header *eh, swloop_eh; struct protosw *pr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -