📄 if_fn.c
字号:
pktLen = max (ETHERSMALL, dataLen); /* taking care of short packets, pad with 0s */ if (dataLen < ETHERSMALL) for (loopy = dataLen; loopy < pktLen; loopy++) privateBuf [loopy] = 0; /* * Support for network interface hooks. Call output hook * if any specified. If the routine returns non-zero, * assume the hook has taken care of the frame (don't send * on interface). See etherLib for more information */ if ( (etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&pDrvCtrl->fn_if, privateBuf, pktLen)) continue; /* Tell the device the length; in little endian order */#if (CPU_FAMILY == SPARC) sysAsiSeth (nicePort, ( (pktLen & 0xff00) >> 8) | ( (pktLen & 0x00ff) << 8));#endif pSource = (u_short *)privateBuf; for (loopy = pktLen; loopy > 0 ; loopy -= sizeof (u_short)) {#if (CPU_FAMILY == SPARC) sysAsiSeth (nicePort, *pSource);#endif pSource++; } if (pktLen % sizeof (u_short)) /* packet size is odd */ { unsigned short lastByte; lastByte = 0; ( (char *) (&lastByte))[0] = ((char *) (pSource))[0];#if (CPU_FAMILY == SPARC) sysAsiSeth (nicePort, lastByte);#endif } /* See if transmitter is free and start it orelse wait. */#if (CPU_FAMILY == SPARC) while ( (sysAsiGeth (pDrvCtrl->pDev + NICE_TRANSMIT)) & (0x7f << 8)) ; /* loop until transmit count is 0 */ sysAsiSeth (pDrvCtrl->pDev + NICE_TRANSMIT, KICK_TRANSMIT);#endif /* Bump the statistic counter. */ pDrvCtrl->fn_if.if_opackets++; } return (0); }#endif/********************************************************************************* fnRxEvent - process the receiver event from the device** This routine is the top level receiver handler. Runs as long as packets * left in the buffer.** RETURNS: N/A*/LOCAL void fnRxEvent ( DRV_CTRL * pDrvCtrl /* pointer to driver control structure */ ) { char * pDev; /* ptr to the device regs */ /* Check ifnet flags. Return if we're down, leaving interrupt disabled. */ if ( (pDrvCtrl->fn_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) return; pDev = pDrvCtrl->pDev; /* get ptr to device */ /* While more packets, process the packet. */ while ( fnRxMore (pDrvCtrl) ) { if (fnRxProcessPkt (pDrvCtrl) == ERROR) { rcvPktError++; /* bump the recieve packet error counter */ break; } } /* Turn the receive interrupts on again. */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_INTRMASK, NORM_INTRMASK);#endif } /* End of fnRxEvent() *//********************************************************************************* fnRxMore - indicates more packets in the buffer** This routine indicates that there are more packets left in the buffer** RETURNS: TRUE or FALSE*/LOCAL BOOL fnRxMore ( DRV_CTRL * pDrvCtrl /* pointer to driver control structure */ ) { u_short mode; char * pDev; /* ptr to the device regs */ pDev = pDrvCtrl->pDev; /* get ptr to device */#if (CPU_FAMILY == SPARC) mode = sysAsiGeth (pDev + NICE_MODE);#endif if (mode & DLCR5_BUF_EMPTY) return (FALSE); else return (TRUE); } /* End of fnRxMore() *//********************************************************************************* fnRxProcessPkt - process the next available packet** RETURNS: OK, or ERROR.*/LOCAL STATUS fnRxProcessPkt ( DRV_CTRL * pDrvCtrl /* pointer to driver control structure */ ) { int loopy; /* loop counter */ int dataLen; /* length of packet data */ char * pDev; /* ptr to the device regs */ u_short * pDest; /* ptr to destination */ struct mbuf * pMbuf; /* ptr to mbufs */ RX_HDR rxHdr; /* an Rx pkt header */ /* allocate space for one received frame */ static struct rx_frame { struct ether_header enetHdr; /* the Ethernet header */ char data [1500]; /* the data field */ } rxFrame; pDev = pDrvCtrl->pDev; /* get ptr to device */ /* Fill our local copy of the Rx header from the device's buffer. */#if (CPU_FAMILY == SPARC) rxHdr.status = sysAsiGeth (pDev + NICE_PORT); rxHdr.len = sysAsiGeth (pDev + NICE_PORT);#endif rxHdr.len = ((rxHdr.len & 0xff00) >> 8) | /* swap bytes */ ((rxHdr.len & 0x00ff) << 8); /* Clear the status bit for packet ready. */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_STATUS, DLCR1_RX_PKT);#endif#ifdef FN_DEBUG if (DEBUG_RX) printf ( "fn: Rx: status=%04x len=%d\n", rxHdr.status & 0xff00, rxHdr.len );#endif /* FN_DEBUG */ /* Sanity check the packet info. */ if ( (!(rxHdr.status & RX_HDR_STAT_GOOD)) || (rxHdr.len < 60) || (rxHdr.len > 1514) ) { printf ("fn: Fatal error, invalid receiver header %04x %04x\n", rxHdr.status, rxHdr.len); pDrvCtrl->fn_if.if_ierrors++; /* bump errors */ pDrvCtrl->fn_if.if_flags &= ~(IFF_UP | IFF_RUNNING); /* flags down */ return (ERROR); } /* Bump the statistic counter */ pDrvCtrl->fn_if.if_ipackets++; /* Fill our frame buffer from the device's buffer. */ pDest = (u_short *) &rxFrame; /* stuff ptr */ for (loopy = rxHdr.len; loopy > 0; loopy -= sizeof (u_short))#if (CPU_FAMILY == SPARC) *pDest++ = sysAsiGeth (pDev + NICE_PORT);#else ;#endif /* * Support for network interface hooks. Call input hook if any * specified. If the routine returns non-zero, assume the * hook has taken care of the frame. See etherLib in the Vxworks * Reference Manual for more information. */ if ((etherInputHookRtn != NULL) && ((*etherInputHookRtn) (&pDrvCtrl->fn_if, (char *) &rxFrame , rxHdr.len) != 0)) return (OK); /* Copy our frame buffer into mbufs. */ dataLen = rxHdr.len - ENET_HDR_REAL_SIZ; /* obtain data length */ pMbuf = copy_to_mbufs (rxFrame.data, dataLen, 0, &pDrvCtrl->fn_if); /* Give the mbufs to the upper layers */ if (pMbuf != NULL)#ifdef BSD43_DRIVER do_protocol_with_type ( rxFrame.enetHdr.type, /* packet type */ pMbuf, /* the mbufs */ &pDrvCtrl->idr, /* interface data record */ dataLen /* length of data */ );#else do_protocol (&rxFrame.enetHdr, pMbuf, &pDrvCtrl->idr, dataLen);#endif else pDrvCtrl->idr.ac_if.if_ierrors++;#ifdef FN_DEBUG logMsg ("fn: Sent packet up.\n", 0, 0, 0, 0, 0, 0);#endif return (OK); } /* End of fnRxProcessPkt() *//********************************************************************************* fnIntr - the driver interrupt handler routine** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A*/LOCAL void fnIntr ( int unit /* unit number to service */ ) { char *pDev; /* ptr to the device regs */ u_short event; u_short reg; DRV_CTRL * pDrvCtrl; /* ptr to driver control structure */ pDrvCtrl = &drvCtrl [unit]; pDev = pDrvCtrl->pDev;#if (CPU_FAMILY == SPARC) event = sysAsiGeth (pDev + NICE_STATUS); /* get intr status */ reg = sysAsiGeth (pDev + NICE_INTRMASK); /* get current mask */#endif#ifdef FN_DEBUG if (DEBUG_INTR) logMsg ("fn: Intr: event=%04x\n", event, 0, 0, 0, 0, 0);#endif /* FN_DEBUG */ /* Handle receiver overflow event. */ if (event & DLCR1_OVR_FLO) { overFlowCnt++; /* bump the counter */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_STATUS, DLCR1_OVR_FLO); #endif return; } /* Handle the receiver event, only if it was enabled. */ if ((reg & DLCR3_RX_PKT) && (event & DLCR1_RX_PKT)) {#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_INTRMASK, NO_RX_INTRMASK); /* disable */#endif netJobAdd ((FUNCPTR)fnRxEvent, (int)pDrvCtrl, 0,0,0,0); } /* ACK the interrupts */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_STATUS, event);#endif } /* End of fnIntr() */#ifdef BSD43_DRIVER/********************************************************************************* convertDestAddr - converts socket addr into enet addr and packet type** RETURNS: TRUE or FALSE*/LOCAL BOOL convertDestAddr ( IDR * pIDR, /* ptr to interface data record */ struct sockaddr * pDestSktAddr, /* ptr to a generic sock addr */ char * pDestEnetAddr, /* where to write enet addr */ u_short * pPacketType, /* where to write packet type */ struct mbuf * pMbuf /* ptr to mbuf data */ ) { /***** 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 *****/ { struct ether_header * pEnetHdr; if (pDestSktAddr->sa_family == AF_UNSPEC) { pEnetHdr = (struct ether_header *) pDestSktAddr->sa_data; bcopy ( (char *)pEnetHdr->ether_dhost, pDestEnetAddr, 6); *pPacketType = pEnetHdr->ether_type; return (TRUE); } } /* Unsupported family */ return (FALSE); }#endif /* BSD43_DRIVER *//* END OF FILE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -