📄 if_fza.c
字号:
if(fzadebug) printf("fza%d: size too long %d",unit,totlen); m_freem(m0); goto next_m; } /* * the last descriptor not own by host * put the mbuf back to the queue */ last = index + totlen/XMTSEGSIZE - (((totlen % XMTSEGSIZE) != 0)? 0 : 1 ); if ( sc->tring[last % sc->nrmcxmt].own == FZA_RMC_OWN ) { IF_PREPEND(&sc->is_if.if_snd, m0); sc->tindex = index; return; } /* * String the mbuf chain onto the transmit ring entry's * buffer segment addresses. * Architectures which need to use program I/O to data copy * mbuf chain into one or several ( maximum 9 ) RMC transimit * rings which are 512 bytes segments */ if(fzadebug > 1 ) printf("fzastart: ready to copy data len %d \n",totlen); tpstart = tp; { register int tleft = 512 , mleft; register caddr_t mptr, tptr; int space; int oindex, nring = 1; u_long rmc; /* * rleft : space left for current RMC XMT ring * mleft : bytes left for copying in current mbuf */ m = m0; tptr = (caddr_t)FZAXMTADDR(tp,sc->basereg); oindex = index ; while (m) { mleft = m->m_len ; mptr = mtod(m, caddr_t); while (mleft) { space = MIN(tleft,mleft); fzacpy(mptr, tptr , space ); tptr += space ; mptr += space ; mleft -= space ; tleft -= space ; if (tleft == 0 && mleft > 0 ) { index = ++index % sc->nrmcxmt ; sc->tring[index].own = FZA_RMC_OWN; sc->tring[index].rmc = 0; if(index == 0 ) tptr = (caddr_t)FZAXMTADDR(&sc->tring[index],sc->basereg); tleft = 512; nring++; } } m = m->m_next; } /* * need more than one XMT rings */ if( nring > 1 ) { sc->tring[index].rmc = FZA_EOP ; tpstart->rmc = FZA_SOP | FZA_XMT_VBC | totlen ; } else tpstart->rmc = FZA_SOP | FZA_EOP | FZA_XMT_VBC | totlen ; /* * save the mbuf chain */ tpstart->xmt_mbuf = m0; tpstart->own = FZA_RMC_OWN; /* * this is try to slove the RMC pipe line problem */ tmp = tpstart->own ; if(fzadebug > 1) printf("fzastart index %d rmc 0x%x \n",index,tpstart->own); } sc->nxmit++; ifp->if_flags |= IFF_OACTIVE ; /* * Advise the port that a new transmit packet is pending */ sc->reg_ctla |= XMT_POLL ; wbflush(); } sc->tindex = index;}/* * FZA device interrupt handler */fzaintr(unit) int unit;{ register struct fza_softc *sc = &fza_softc[unit]; register FZASMTRING *smttp; register FZAXMTRING *tp; register int index; struct mbuf *m0; struct ifnet *ifp = &sc->is_if; u_short csr ; int s = splimp(); csr = sc->reg_intr; /* clear the interrupt event register */ sc->reg_intr = csr; /* * Lock softc, since we will be updating the per-unit ring pointers * and active ring entry counts frequently. */ smp_lock(&sc->lk_fza_softc, LK_RETRY); /* * See if we got here due to a port state change interrupt. */ if (csr & STATE_CHG ) { switch ((sc->reg_status & ADAPTER_STATE)) { case STATE_HALTED : printf("fza%d: port in the Halt State -> ",unit); switch(sc->reg_status & ID_FIELD ) { case HALT_UNKNOWN: printf("Unknown reason\n"); break; case HALT_HOST_DIRECTED: printf("Host request to halt \n"); break; case HALT_HBUS_PARITY: printf("Host Maxbus parity errors \n"); break; case HALT_HNXM: printf("Host Non-exist Memory \n"); break; case HALT_ADAP_SW_FAULT: printf("Adapter software fault\n"); break; case HALT_ADAP_HW_FAULT: printf("Adapter hardware fault\n"); break; case HALT_CNS_PC_TEST: printf("CNS PC trace path test\n"); sc->flag = FZA_PC_TRACED ; break; case HALT_CNS_SW_FAULT: printf("CNS software fault\n"); break; case HALT_CNS_HW_FAULT: printf("CNS hardware fault\n"); break; default: printf("unknown halt id %d\n",sc->reg_status & ADAPTER_STATE); break; } { struct el_rec *elrp; if((elrp = ealloc(sizeof(struct el_fza), EL_PRILOW))) { struct el_fza *elbod = &elrp->el_body.el_fza; bcopy(((char *)(sc->basereg + FZA_DLU_ADDR )),elbod,sizeof(structel_fza)); LSUBID(elrp,ELCT_DCNTL,ELFZA,0,0,unit,(sc->reg_status & ID_FIELD)); } EVALID(elrp); } /* * This is used for HALT recovrey. * It will bring back the * RUNNING state that help the * link unavilable before the * adapter change to HALT state * case. */ if (!(ifp->if_flags & IFF_RUNNING)) ifp->if_flags |= IFF_RUNNING ; fzareset(unit); break; case STATE_RESET: if(fzadebug) cprintf("fza%d: port in the Resetting State \n",unit); break; case STATE_UNINITIALIZED: if(fzadebug) cprintf("fza%d: port in the UninitialiedState \n",unit); break; case STATE_INITIALIZED: if(fzadebug) cprintf("fza%d: port in the Initialized State \n",unit); break; case STATE_RUNNING: if(fzadebug) cprintf("fza%d: port in the Running State \n",unit); break; case STATE_MAINTENANCE: if(fzadebug) cprintf("fza%d: port in the Maintenance State \n",unit); break; default: printf("fza%d: Undefined state id %d \n", unit, sc->reg_status & ADAPTER_STATE ); break; } /* * turn off the interface because of unrecovery errors */ smp_unlock(&sc->lk_fza_softc); splx(s); return; } /* * See if we get the FLUSH_TX interrupt. If so, the driver * will return the ownership of all pending SMT XMT buffer back * to the adapter and turn on the DTP bit in all the Tx descriptors * which is owned by the RMC */ if(csr & FLUSH_TX) { if(fzadebug) printf("fza%d: flush the XMT buffer \n",unit); for ( index = sc->tsmtindex, smttp = &sc->smttring[index] ; (smttp->own & FZA_HOST_OWN); index = index++ % sc->nsmtxmt,smttp = &sc->smttring[index] ) smttp->own &= ~(FZA_HOST_OWN); sc->tsmtindex = index; /* * Clean up the Tx ring */ for ( index = sc->tindex - 1 , tp = &sc->tring[index] ; (index != sc->tindex) && (tp->own & FZA_RMC_OWN) ;) { tp->rmc |= FZA_XMT_DTP ; if(--index < 0 ) index = sc->nrmcxmt-1; tp = &sc->tring[index]; } sc->ltindex = sc->tindex - 1 ; sc->nxmit = 0; /* * notice adapter the flush was done */ sc->reg_ctla |= FLUSH_DONE; wbflush(); smp_unlock(&sc->lk_fza_softc); splx(s); return; } /* * See if we get the LINK STATUS CHANGE interrupt. If so, * we need to turn off or turn on the interface */ if (csr & LINK_STATUS_CHG) { if(fzadebug) printf("fza%d: LINK STATE CHANGE \n",unit); if (sc->reg_status & LINK_AVAILABLE ) { if (!(ifp->if_flags & IFF_RUNNING)) { ifp->if_flags |= IFF_RUNNING ; cprintf("fza%d: LINK available \n",unit); } } else { if (ifp->if_flags & IFF_RUNNING ) { ifp->if_flags &= ~IFF_RUNNING; cprintf("fza%d: LINK unavailable \n",unit); /* * drop packets on the transmit queue */ while(sc->is_if.if_snd.ifq_head) { IF_DEQUEUE(&sc->is_if.if_snd, m0); m_freem(m0); } } } } if (csr & RCV_POLL) /* receive interrupt */ fzarint(unit); if (csr & XMT_PKT_DONE) /* transmit done interrupt */ fzatint(unit); if (csr & CMD_DONE ) /* command done interrupt */ fzacmdint(unit); if (csr & SMT_XMT_POLL) /* SMT transmit done interrupt */ fzasmtint(unit); if (csr & UNS_POLL ) { /* unsolicited event interrupt */ register int index; register FZAUNSRING *up; for(index = sc->unsindex, up= &sc->unsring[index]; (up->own) ; index = ++index % NFZAUNS, up = &sc->unsring[index] ) { /* * process the unsolicited ring */ if(fzadebug) printf("fza%d: Unsolicited Event -> ",unit); else mprintf("fza%d: Unsolicited Event -> ",unit); switch(up->status_id) { case UNS_UNDEFINED: if(fzadebug) printf(" Undefined \n"); else mprintf(" Undefined \n"); break; case UNS_RINGINIT: if(fzadebug) printf(" Ring Init Initiated \n"); else mprintf(" Ring Init Initiated \n"); break; case UNS_RINGINITRCV: if(fzadebug) printf(" Ring Init Received \n"); else mprintf(" Ring Init Received \n"); break; case UNS_RINGBEACONINIT: if(fzadebug) printf(" Ring Beaconing Initiated \n"); else mprintf(" Ring Beaconing Initiated \n"); break; case UNS_DUPADDR: if(fzadebug) printf(" Duplicate Address Detected \n"); else mprintf(" Duplicate Address Detected \n"); break; case UNS_DUPTOKEN: if(fzadebug) printf(" Duplicated Token Detected \n"); else mprintf(" Duplicated Token Detected \n"); break; case UNS_RINGPURGEERR: if(fzadebug) printf(" Ring Purge Error \n"); else mprintf(" Ring Purge Error \n"); break; case UNS_BRIDGESTRIPERR: if(fzadebug) printf(" Bridge Strip Error \n"); else mprintf(" Bridge Strip Error \n"); break; case UNS_RINGOPOSC: if(fzadebug) printf(" Ring Op Oscillation \n"); else mprintf(" Ring Op Oscillation \n"); break; case UNS_DIRECTEDBEACON: if(fzadebug) printf(" Directed Beacon Received \n"); else mprintf(" Directed Beacon Received \n"); break; case UNS_PCINIT: if(fzadebug) printf("PC Trace Initiated \n"); else mprintf("PC Trace Initiated \n"); break; case UNS_PCRCV: if(fzadebug) printf("PC Trace Received \n"); else mprintf("PC Trace Received \n"); break; case UNS_XMT_UNDERRUN: if(fzadebug) printf("Transmit Underrun \n"); else mprintf("Transmit Underrun \n"); break; case UNS_XMT_FAILURE: if(fzadebug) printf("Transmit Failure \n"); else mprintf("Transmit Failure \n"); break; case UNS_RCV_OVERRUN: if(fzadebug) printf("Receive Overrun \n"); else mprintf("Receive Overrun \n"); break; default: if(fzadebug) printf("Unknown event %d \n",up->status_id); else mprintf("Unknown event %d \n",up->status_id); break; } up->own = 0 ; /* turn back the ownership to RMC */ } sc->unsindex = index; } /* * Dequeue next SMT received packet from queue and copy to SMT RCV ring */ { FZASMTRING *sp = &sc->smtrring[sc->rsmtindex]; register struct mbuf *m; register caddr_t bp; int len; /* * check for something need to be send to the SMT RCV ring */ while ( sc->is_smt.ifq_head && (sp->own & FZA_HOST_OWN) ) { IF_DEQUEUE(&sc->is_smt, m0); bp = (caddr_t)(sc->basereg + sp->buf_addr); len = 0; m = m0; while(m) { fzacpy(mtod(m,caddr_t),bp,m->m_len); bp += m->m_len; len += m->m_len; m = m->m_next; } /* * use the original RMC descriptor */ sp->rmc = FZA_SOP | FZA_EOP | sc->smt_rmc[sc->lsmtrmcindex]; sp->own &= ~FZA_HOST_OWN; sc->lsmtrmcindex = ++sc->lsmtrmcindex % IFQ_MAXLEN; m_freem(m0); sc->rsmtindex = ++sc->rsmtindex % sc->nsmtrcv; sp = &sc->smtrring[sc->rsmtindex]; } /* * ask adapter to process this smt frame */ sc->reg_ctla |= SMT_RCV_POLL ; } /* * Dequeue next transmit request if interface is no longer busy. */ if (sc->nxmit <= 0) { sc->is_if.if_flags &= ~IFF_OACTIVE; fzastart( unit ); } /* * Drop softc lock and return . */ smp_unlock(&sc->lk_fza_softc); splx(s);}/* * FZA smt interrupt routine */fzasmtint(unit)int unit;{ register struct fza_softc *sc = &fza_softc[unit]; register FZASMTRING *sp; register FZAXMTRING *tp; register int index; FZAXMTRING *tpstart; caddr_t smtbp,tbp; int len,last,nring,tlen; u_long tmp; /* * process SMT XMT frame */ for(index = sc->tsmtindex , sp = &sc->smttring[index]; (sp->own & FZA_HOST_OWN); index = ++index % sc->nsmtxmt, sp= &sc->smttring[index]) { tpstart = &sc->tring[sc->tindex];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -