📄 if_nic.c
字号:
* that NIC transmits from. If successful, and the NIC is not currently busy* transmitting, it then attempts to start the NIC transmitting.*/LOCAL int nicTxStartup ( DRV_CTRL * pDrvCtrl /* pointer to driver control structure */ ) { MBUF * pMbuf; int oldLevel; u_long nicBufAddr; MBUF *pTempMbuf; NIC_DEVICE *pNic; TX_DESC *pTxNext; /* ptr to next desc to use */ pNic = pDrvCtrl->nicAddr; /* copy it, due to frequent use */ /* Get next transmit resource */ while (pDrvCtrl->idr.ac_if.if_snd.ifq_head) { /* Dequeue a packet from the transmit queue. */ IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf); pTxNext = pDrvCtrl->pTxNext; /* copy it, due to frequent use */ if (pTxNext->ready) /* if still in use */ { m_freem (pMbuf); /* release MBUFs */ pDrvCtrl->idr.ac_if.if_oerrors++; break; } /* copy mbufs to NIC buffer */ pTempMbuf = pMbuf; /* copy head of MBUF chain */ nicBufAddr = pTxNext->addr; while (pTempMbuf != NULL) { while (pktBufWrite (pDrvCtrl, nicBufAddr, pTempMbuf->m_len, mtod (pTempMbuf, caddr_t)) == ERROR) ; nicBufAddr += (u_long) pTempMbuf->m_len; pTempMbuf = pTempMbuf->m_next; } pTxNext->len = max (MINPKTSIZE, (nicBufAddr - pTxNext->addr)); m_freem (pMbuf); /* free the mbufs */ oldLevel = intLock (); /* keep our int handler out */ pTxNext->ready = TRUE; /* mark packet as "ready" */ if (pDrvCtrl->pTxActive == NULL) /* if transmitter not active */ { pDrvCtrl->pTxActive = pTxNext; /* set active ptr */ pNic->Tpsr = pTxNext->addr >> 8; pNic->Tbcr0 = pTxNext->len & 0xff; pNic->Tbcr1 = pTxNext->len >> 8; pNic->Cr = TXP; /* start NIC transmitting */ } pDrvCtrl->pTxNext = pTxNext->next; /* move ptr to next desc */ intUnlock (oldLevel); /* allow interrupts again */ /* Bump packet counter */ pDrvCtrl->idr.ac_if.if_opackets++; } return (0); }#endif/********************************************************************************* nicIoctl - the driver's I/O control routine**/LOCAL int nicIoctl ( IDR *pIDR, int cmd, caddr_t data ) { int error; error = 0; switch (cmd) { case SIOCSIFADDR: ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr; arpwhohas (pIDR, &IA_SIN (data)->sin_addr); break; case SIOCSIFFLAGS: /* Flags are set outside this module. No additional work to do. */ break; default: error = EINVAL; } return (error); }/********************************************************************************* nicEnetAddrGet - get hardwired Ethernet address.** Read the Ethernet address out of the ROM*/LOCAL void nicEnetAddrGet ( int unit ) { DRV_CTRL *pDrvCtrl = & drvCtrl [unit]; NIC_DEVICE *pNic = pDrvCtrl->nicAddr; int i; pNic->Rsar0 = 0; /* ID ROM starts at 0 */ pNic->Rsar1 = 0; pNic->Rbcr0 = 6; /* length of enet addr */ pNic->Rbcr1 = 0; pNic->Cr = RREAD; /* Start NIC Remote DMA */ for (i = 0; i < 6; i++) { while (pNic->Rsar0 == i) /* wait for byte available */ ; pDrvCtrl->idr.ac_enaddr [i] = *NIC_BUF_PORT; /* read byte from port */ } }/********************************************************************************* nicConfig - configure the NIC chip for Ethernet and program address*/LOCAL void nicConfig ( int unit ) { DRV_CTRL *pDrvCtrl = & drvCtrl [unit]; NIC_DEVICE *pNic = pDrvCtrl->nicAddr; pNic->Cr = RPAGE0 | STP; /* select page 0 and stop */ pNic->Dcr = NOTLS | FIFO8; pNic->Rbcr0 = 0; /* clear remote DMA byte count registers */ pNic->Rbcr1 = 0; pNic->Rcr = AB; /* accept broadcast, but not runt or multicast */ pNic->Tcr = MODE1; /* internal loopback mode */ pNic->Pstart = PSTART; pNic->Pstop = PSTOP; pNic->Bnry = BNRY; nicEnetAddrGet (unit); /* Get Ethernet address */ /* set up page 1 registers */ pNic->Cr = RPAGE1; pNic->Par0 = pDrvCtrl->idr.ac_enaddr [0]; pNic->Par1 = pDrvCtrl->idr.ac_enaddr [1]; pNic->Par2 = pDrvCtrl->idr.ac_enaddr [2]; pNic->Par3 = pDrvCtrl->idr.ac_enaddr [3]; pNic->Par4 = pDrvCtrl->idr.ac_enaddr [4]; pNic->Par5 = pDrvCtrl->idr.ac_enaddr [5]; pNic->nic_pg1.mar0 = 0xff; pNic->nic_pg1.mar1 = 0xff; pNic->nic_pg1.mar2 = 0xff; pNic->nic_pg1.mar3 = 0xff; pNic->nic_pg1.mar4 = 0xff; pNic->nic_pg1.mar5 = 0xff; pNic->nic_pg1.mar6 = 0xff; pNic->nic_pg1.mar7 = 0xff; pNic->Curr = CURR; pNic->Cr = RPAGE0; /* back to page 0 */ pNic->Tcr = MODE0; /* put Tx into normal mode */ pNic->Cr = STA; /* start the beast running */ pNic->Isr = 0xff; /* clr any pending ints */ pNic->Imr = PRXE|PTXE|TXEE|OVWE|RDCE; /* enable these ints */ }/********************************************************************************* pktBufWrite - write data to NIC buffer*/LOCAL STATUS pktBufWrite ( DRV_CTRL *pDrvCtrl, unsigned long nicBufAddr, unsigned long len, char *pData ) { NIC_DEVICE *pNic; WE32104 *pDmac; STATUS status; if (len == 0) /* nothing to do */ return (OK); pNic = pDrvCtrl->nicAddr; pDmac = (WE32104 *) DMA_BASE; semTake(pDrvCtrl->dmaSem, WAIT_FOREVER); /* obtain semaphore */ pDrvCtrl->dmaWait = TRUE; /* set our flag */ /* set up NIC remote DMA transfer */ pNic->Rsar0 = nicBufAddr; pNic->Rsar1 = nicBufAddr >> 8; pNic->Rbcr0 = len; pNic->Rbcr1 = len >> 8; /* set up main DMAC transfer */ cacheFlush (DATA_CACHE, pData, len); /* ensure coherency */ pDmac->Ch2.SourceAdd = (unsigned long) pData; pDmac->Ch2.TranCount = len; pDmac->Ch2.Mode = MODE_TT_MP | MODE_DS_LONG | MODE_BR; /* start both devices doing the transfer */ pDmac->Ch2.StatCont = SCR_STR; pNic->Cr = RWRITE; /* wait for interrupt handler to clear our flag */ while (pDrvCtrl->dmaWait) { if ( (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) { pDrvCtrl->dmaWait = FALSE; pDmac->Ch2.StatCont = SCR_SA; /* abort */ semGive(pDrvCtrl->dmaSem); /* release the sem */ return (OK); /* this is correct */ } } /* check for DMAC error */ if(pDmac->Ch2.StatCont & SCR_ACT) { pDmac->Ch2.StatCont = SCR_SA; /* abort */ status = ERROR; } else status = OK; semGive(pDrvCtrl->dmaSem); return (status); }/********************************************************************************* pktBufRead - read data from NIC buffer*/LOCAL STATUS pktBufRead ( DRV_CTRL *pDrvCtrl, unsigned long nicBufAddr, unsigned long len, char *pData ) { NIC_DEVICE *pNic; WE32104 *pDmac; STATUS status; if (len == 0) /* nothing to do */ return (OK); /* Avoid starting DMA if device is down to to fatal error */ if ( (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) return (OK); pNic = pDrvCtrl->nicAddr; pDmac = (WE32104 *) DMA_BASE; semTake(pDrvCtrl->dmaSem, WAIT_FOREVER); /* obtain semaphore */ pDrvCtrl->dmaWait = TRUE; /* set our flag */ /* set up NIC remote DMA transfer */ pNic->Rsar0 = nicBufAddr; pNic->Rsar1 = nicBufAddr >> 8; pNic->Rbcr0 = len; pNic->Rbcr1 = len >> 8; /* set up main DMAC transfer */ pDmac->Ch2.DestAdd = (unsigned long) pData; pDmac->Ch2.TranCount = len; pDmac->Ch2.Mode = MODE_TT_PM | MODE_DS_LONG | MODE_BR; /* start both devices doing the transfer */ pDmac->Ch2.StatCont = SCR_STR; pNic->Cr = RREAD; /* wait for interrupt handler to clear our flag */ while (pDrvCtrl->dmaWait) { if ( (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) { pDrvCtrl->dmaWait = FALSE; pDmac->Ch2.StatCont = SCR_SA; /* abort */ semGive(pDrvCtrl->dmaSem); /* release the sem */ return (OK); /* this is correct */ } } /* check for DMAC error */ if(pDmac->Ch2.StatCont & SCR_ACT) { pDmac->Ch2.StatCont = SCR_SA; /* abort */ status = ERROR; } else { cacheInvalidate (DATA_CACHE, pData, len); /* ensure coherency */ status = OK; } semGive(pDrvCtrl->dmaSem); return (status); }#ifdef BSD43_DRIVER#include "sys/socket.h"/********************************************************************************* convertDestAddr - converts socket addr into enet addr and packet type**/static BOOL convertDestAddr ( IDR *pIDR, /* ptr to i/f data record */ SOCK *pDestSktAddr, /* ptr to a generic sock addr */ char *pDestEnetAddr, /* where to write enet addr */ u_short *pPacketType, /* where to write packet type */ MBUF *pMbuf /* ptr to mbuf data */ ) {#ifdef __STDC__ extern arpresolve ( /* we call this */ IDR *, MBUF *, struct in_addr *, char *, int * );#else /* __STDC__ */ extern arpresolve ();#endif /* __STDC__ */ /***** Internet family *****/ { struct in_addr destIPAddr; /* not used */ int trailers; /* not supported */ if (pDestSktAddr->sa_family == AF_INET) { *pPacketType = ETHERTYPE_IP; /* stuff packet type */ destIPAddr = ((struct sockaddr_in *) pDestSktAddr)->sin_addr; if (!arpresolve (pIDR, pMbuf, &destIPAddr, pDestEnetAddr, &trailers)) return (FALSE); /* if not yet resolved */ return (TRUE); } } /***** Generic family *****/ { ETH_HDR *pEnetHdr; if (pDestSktAddr->sa_family == AF_UNSPEC) { pEnetHdr = (ETH_HDR *) pDestSktAddr->sa_data; /* ptr to hdr */ bcopy (pEnetHdr->dst, pDestEnetAddr, 6); /* copy dst addr */ *pPacketType = pEnetHdr->ether_type; /* copy type */ return (TRUE); } } /* Unsupported family */ return (FALSE); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -