📄 if_fn.c
字号:
sysEnetIntDisable (unit); /* The secondary DLC register group is mapped in. Set the node ID. */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_ADDR1, ((u_short *) pDrvCtrl->fn_enaddr) [0]); sysAsiSeth (pDev + NICE_ADDR2, ((u_short *) pDrvCtrl->fn_enaddr) [1]); sysAsiSeth (pDev + NICE_ADDR3, ((u_short *) pDrvCtrl->fn_enaddr) [2]);#endif /* Change register map. Select buffer memory register group. */#if (CPU_FAMILY == SPARC) temp = sysAsiGeth (pDev + NICE_CONFIG);#endif temp &= ~DLCR7_REG_BNK; /* clear bank select bits */ temp |= DLCR7_REG_BNK_BMR; /* add desired bits */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_CONFIG, temp);#endif /* Setup the receiver and transmitter modes. */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_MODE, DLCR4_LBC | DLCR5_BIT_2 | DLCR5_AF0);#endif /* Do the board specific interrupt enable for the device. */ sysEnetIntEnable (unit); /* Enable specific interrupts. */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_INTRMASK, NORM_INTRMASK);#endif /* Enable the DLC. */#if (CPU_FAMILY == SPARC) temp = sysAsiGeth (pDev + NICE_CONFIG); /* get config reg */#endif temp &= ~DLCR6_DISABLE_DLC; /* clear the disable bit */#if (CPU_FAMILY == SPARC) sysAsiSeth (pDev + NICE_CONFIG, temp); /* update config reg */ /* set collision control drop packet after 16 collisions */ sysAsiSeth (pDev + NICE_TRANSMIT, (BMR11_MASK16 | BMR11_RST_TX16 | BMR11_OPT_16_COLL));#endif } /* End block */ /* Set our interface flags. */ pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); /* That's all */ pDrvCtrl->attached = TRUE; return (OK); } /* End of fnattach() *//********************************************************************************* fnIoctl - the driver I/O control routine** This routine will process an ioctl request ** RETURNS: 0 or errno*/LOCAL int fnIoctl ( struct ifnet * pIfnet, /* ptr to our interface struct */ int cmd, /* the command code */ char * pArgs /* ptr to the command arguments */ ) { int errno; /* hold error value or zero */ int unit = pIfnet->if_unit; DRV_CTRL * pDrvCtrl = &drvCtrl[unit];#ifdef FN_DEBUG if (DEBUG_SPEC) printf ( "fn: ioctl: pIfnet=%x cmd=%x pArgs=%x\n", pIfnet, cmd, pArgs );#endif /* FN_DEBUG */ errno = 0; /* assume no error */ switch (cmd) { case SIOCSIFADDR: /* set i/f address */#ifdef FN_DEBUG if (DEBUG_SPEC) printf ("fn: ioctl: set addr\n");#endif /* FN_DEBUG */ /* copy the INET address into our arpcom structure */ pDrvCtrl->idr.ac_ipaddr = IA_SIN (pArgs)->sin_addr; arpwhohas (pIfnet, &IA_SIN (pArgs)->sin_addr); break; case SIOCGIFADDR: /* get i/f address */#ifdef FN_DEBUG if (DEBUG_SPEC) printf ("fn: ioctl: get addr\n");#endif /* FN_DEBUG */ bcopy ( (caddr_t) pDrvCtrl->fn_enaddr, (caddr_t) ((struct ifreq *)pArgs)->ifr_addr.sa_data, 6 ); break; case SIOCSIFFLAGS: /* set i/f flags */#ifdef FN_DEBUG if (DEBUG_SPEC) printf ("fn: ioctl: set flags\n");#endif /* FN_DEBUG */ break; case SIOCGIFFLAGS: /* get i/f flags */#ifdef FN_DEBUG if (DEBUG_SPEC) printf ("fn: ioctl: get flags\n");#endif /* FN_DEBUG */ *(short *)pArgs = pIfnet->if_flags; break; default : errno = EINVAL; } return (errno); } /* End of fnIoctl() *//********************************************************************************* fnReset - the driver reset routine** This routine resets the device** RETURNS: OK.*/LOCAL int fnReset ( int unit ) {#ifdef FN_DEBUG if (DEBUG_SPEC) printf ("fnReset\n");#endif /* FN_DEBUG */ return (OK); } /* End of fnReset() */#ifdef BSD43_DRIVER/********************************************************************************* fnOutput - The driver's output routine** This routine is responsible for tranmitting packets over physical media.* The destination address is passed to this function as a pointer to a* generic socket address structure. This address information is first* converted to the six byte destination address and type field that we* need to build a proper Ethernet frame.** The data to be sent out is held in a chain of mbufs. This function is* passed a pointer to the head mbuf. The data in each mbuf fragment must* be copied to the device's packet buffer.** RETURNS: OK, or ERROR*/LOCAL int fnOutput ( struct arpcom * pIDR, /* ptr to our interface struct */ struct mbuf * pMbuf, /* ptr to the mbufs to send */ struct sockaddr * pDest /* ptr to dest socket addr */ ) { char destEnetAddr [6]; /* space for enet addr */ u_short packetType; /* type field for the packet */ int pktLen; /* total length of packet */ int dataLen; /* real length of data portion */ int loopy; /* loop counter */ char *nicePort; /* ptr to the nice buffer port */ u_short *pSource; /* ptr to source of data byte */ DRV_CTRL * pDrvCtrl; /* ptr to driver control structure */ static char privateBuf [ETHERMTU + ENET_HDR_REAL_SIZ];#ifdef FN_DEBUG if (DEBUG_TX) printf ( "fn: Tx: pIfnet=%x pMbuf=%x pDest=%x\n", pIfnet, pMbuf, pDest );#endif /* FN_DEBUG */ /* Check ifnet flags. Return error if incorrect. */ if ( (pIfnet->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) { m_freem (pMbuf); return (ENETDOWN); } /* Attempt to convert socket addr into enet addr and packet type. * Note that if ARP resolution of the address is required, the ARP * module will call our routine again to transmit the ARP request * packet. This means we may actually call ourselves recursively! */ if (convertDestAddr (pIDR, pDest, destEnetAddr, &packetType, pMbuf) == FALSE) return (OK); /* I KNOW returning OK is stupid, but it is correct */ /* Get driver control pointer */ pDrvCtrl = &drvCtrl [pIDR->ac_if.if_unit]; /* get ptr to the buffer port */ nicePort = pDrvCtrl->pDev + NICE_PORT; semTake (pDrvCtrl->TxSem, WAIT_FOREVER); /* take the xmit semaphore */ bcopy (destEnetAddr, privateBuf, 6); bcopy ( (char *) pDrvCtrl->fn_enaddr, (privateBuf + 6), 6); ((struct ether_header *)privateBuf)->ether_type = packetType; dataLen = 0; copy_from_mbufs ((privateBuf + ENET_HDR_REAL_SIZ), pMbuf, dataLen); /* stuffed by macro */#ifdef FN_DEBUG if (DEBUG_TX) printf ("fn: Tx: dataLen=%d\n", dataLen);#endif /* FN_DEBUG */ /* Ensure we send a legal size frame. */ dataLen += ENET_HDR_REAL_SIZ; 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)) goto outputDone; /* goto the end */ /* 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++; /* That's all. */ outputDone: semGive (pDrvCtrl->TxSem); return (0); } /* End of fnOutput() */#else/********************************************************************************* fnTxStartup - kick start the transmitter after generic ether_output** This routine is responsible for tranmitting packets over physical media.* The data to be sent out is held in a chain of mbufs. The data in each mbuf * fragment must be copied to the device's packet buffer.** RETURNS: OK, or ERROR*/LOCAL int fnTxStartup ( DRV_CTRL * pDrvCtrl /* pointer to driver control structure */ ) { struct mbuf * pMbuf; /* ptr to the mbufs to send */ int pktLen; /* total length of packet */ int dataLen; /* real length of data portion */ int loopy; /* loop counter */ char *nicePort; /* ptr to the nice buffer port */ u_short *pSource; /* ptr to source of data byte */ static char privateBuf [ETHERMTU]; /* get ptr to the buffer port */ nicePort = pDrvCtrl->pDev + NICE_PORT; while (pDrvCtrl->idr.ac_if.if_snd.ifq_head) { /* Dequeue a packet from the send queue. */ IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf); /* * This driver maintains transmit resources internally. The * CPU cannot retrieve or examine them. */ copy_from_mbufs (privateBuf, pMbuf, dataLen);#ifdef FN_DEBUG if (DEBUG_TX) printf ("fn: Tx: dataLen=%d\n", dataLen);#endif /* FN_DEBUG */ /* Ensure we send a legal size frame. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -