📄 if_ulip.c
字号:
#endif /* SIMSPARCSOLARIS */ close (sc->ulipFd); free ((char *) sc); ul_softc [unit] = (UL_SOFTC *) NULL; return (OK); }/********************************************************************************* ulinit - initialize ULIP interface** RETURNS: 0*/LOCAL int ulinit ( int unit ) { UL_SOFTC *sc = ul_softc [unit]; sc->sc_if.if_flags |= IFF_UP | IFF_RUNNING; /* open for business */ return (0); }/********************************************************************************* ulStartOutput - push packets onto "interface"*/#ifdef BSD43_DRIVERLOCAL STATUS ulStartOutput ( int unit ) { UL_SOFTC *sc = ul_softc [unit];#elseLOCAL STATUS ulStartOutput ( UL_SOFTC *sc ) { int unit = sc->sc_if.if_unit;#endif char data [ULIP_MTU + SIZEOF_ETHERHEADER]; char *pBuf; int len; struct mbuf *m; int s = splnet (); while (sc->sc_if.if_snd.ifq_head != NULL) { IF_DEQUEUE (&sc->sc_if.if_snd, m); /* get head of next mbuf chain */ copy_from_mbufs (data, m, len); if (uldebug) u_printf ("OUTPUT: unit=%d, data=%#x, len=%#x\n", unit, data, len);#ifdef BSD43_DRIVER pBuf = data + SIZEOF_ETHERHEADER; /* don't want eh */#else pBuf = data;#endif#if 0 /* call output hook if any */ if ((etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&sc->sc_if, data, len)) continue;#endif#ifdef BSD43_DRIVER len -= SIZEOF_ETHERHEADER;#endif#if ( CPU==SIMSPARCSOLARIS ) if ((WriteUlip (sc->ulipFd, pBuf, len)) != len)#else /* ( CPU==SIMSPARCSOLARIS ) */ if (u_write (sc->ulipFd, pBuf, len) != len)#endif /* ( CPU==SIMSPARCSOLARIS ) */ { sc->sc_if.if_oerrors++; u_printf ("ul%d: write failed %d\n", unit, len); } else sc->sc_if.if_opackets++; } splx (s); return (0); }/********************************************************************************* uloutput - output a packet over the ULIP line** RETURNS: 0 or errno.*/LOCAL STATUS uloutput ( struct ifnet *ifp, /* ULIP interface pointer */ struct mbuf *m, /* packet to be sent out */ struct sockaddr *dst /* address of the destination */ ) {#ifdef BSD43_DRIVER return (ether_output (ifp, m, dst, ulStartOutput, &ul_softc [ifp->if_unit]->sc_ac));#else FAST UL_SOFTC *sc; FAST int s; FAST int unit; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { m_freem (m); return (ENETDOWN); } /* * Check and see if destination socket uses AF_INET protocol family. * Currently only AF_INET is supported by the ulip driver. */ if (dst->sa_family != AF_INET) { m_freem (m); return (EAFNOSUPPORT); } unit = ifp->if_unit; sc = ul_softc [unit]; s = splimp (); /* * If send queue is full drop the packet. */ if (IF_QFULL (&ifp->if_snd)) { IF_DROP (&ifp->if_snd); m_freem (m); ++sc->sc_if.if_oerrors; splx (s); return (ENOBUFS); } /* enqueue the packet and call the output routine */ IF_ENQUEUE (&ifp->if_snd, m); ifp->if_lastchange = tickGet (); if ((ifp->if_flags & IFF_OACTIVE) == 0) (*ifp->if_start)(ifp); splx (s); return (OK);#endif }/********************************************************************************* ulread - hand packet up to higher level** RETURNS: N/A*/LOCAL void ulread ( int unit ) { UL_SOFTC *sc = ul_softc [unit]; char data [ULIP_MTU + SIZEOF_ETHERHEADER]; struct mbuf *m; int lvl; int len;#ifndef BSD43_DRIVER int s;#endif for (;;) { lvl = intLock (); len = u_read (sc->ulipFd, data, ULIP_MTU); if (len <= 0) { sc->ulReadLoop = 0; intUnlock (lvl); return; } intUnlock (lvl); if (uldebug) u_printf ("INPUT: unit=%d, data=%#x, len=%#x, ifp=%#x\n", unit, data, len, &ul_softc[unit]->sc_if); m = copy_to_mbufs (data, len, 0, (struct ifnet *) &ul_softc[unit]->sc_if); if (m != NULL) {#ifdef BSD43_DRIVER do_protocol_with_type (ETHERTYPE_IP, m, &sc->sc_ac, NONE/* len? */);#else /* send up to protocol */ sc->sc_if.if_ipackets++; sc->sc_if.if_lastchange = tickGet(); s = splimp(); if (IF_QFULL(&ipintrq)) { IF_DROP(&ipintrq); sc->sc_if.if_ierrors++; sc->sc_if.if_iqdrops++; m_freem(m); } else { IF_ENQUEUE(&ipintrq, m); schednetisr(NETISR_IP); } splx(s);#endif } else sc->sc_if.if_ierrors++; } }/********************************************************************************* ulioctl - process an ioctl request** RETURNS: 0 or errno.*/LOCAL int ulioctl ( struct ifnet *ifp, /* pointer to ULIP interface */ int cmd, /* command */ caddr_t data /* data */ ) { struct ifaddr *ifa = (struct ifaddr *)data; int error = 0; int s; s = splimp (); switch (cmd) { case SIOCGIFFLAGS: *(short *)data = ifp->if_flags; break; case SIOCSIFADDR:#ifdef BSD43_DRIVER if (ifa->ifa_addr.sa_family == AF_INET)#else if (ifa->ifa_addr->sa_family == AF_INET)#endif ulinit (ifp->if_unit); else error = EAFNOSUPPORT; break; case SIOCSIFDSTADDR:#ifdef BSD43_DRIVER if (ifa->ifa_addr.sa_family != AF_INET)#else if (ifa->ifa_addr->sa_family != AF_INET)#endif error = EAFNOSUPPORT; break; default: error = EINVAL; break; } splx (s); return (error); }/********************************************************************************* ulget - handle interrupt to get 'packet'*/LOCAL void ulget ( int unit ) { UL_SOFTC *sc = ul_softc [unit]; if (ul_softc [unit] == (UL_SOFTC *) NULL) { if (uldebug) u_printf ("ulget: INT 0\n"); return; } if (sc->ulReadLoop == 0) { sc->ulReadLoop = 1; if (uldebug) u_printf ("ulget: INT (netjob)\n"); netJobAdd ((FUNCPTR)ulread, unit, 0, 0, 0, 0); } else if (uldebug) u_printf ("ulget: INT (already processing)\n"); }/********************************************************************************* ulipconnect - open UNIX fd for unit** RETURNS: 0 on success or -1 if error.*/LOCAL int ulconnect ( int unit ) { int fd; UL_SOFTC *sc = ul_softc [unit];#if CPU==SIMSPARCSOLARIS int isUsed;#endif /* SIMSPARCSOLARIS */#if CPU==SIMHPPA int lvl; lvl = intLock();#endif /* CPU=SIMHPPA */ if ((fd = u_open (sc->devUlip, O_RDWR, 0)) < 0) { errno = u_errno (); /* XXX was S_if_ul_NO_UNIX_DEVICE */#if CPU==SIMHPPA intUnlock(lvl);#endif /* CPU=SIMHPPA */ return (-1); } s_fdint (fd, 1); if (intConnect ((VOIDFUNCPTR*) FD_TO_IVEC(fd), ulget, unit) == ERROR) { u_printf ("ul%d: intConnect failed\n", unit);#if CPU==SIMHPPA intUnlock(lvl);#endif /* CPU=SIMHPPA */ return (-1); }#if CPU==SIMSPARCSOLARIS /* Send ioctl to UNIX ulip driver to mark this processor number used. This * is marked as unused in ulipconnect. s_ulipIoctl is called because the * FIOSETUSED ioctl requires special bundling of its user data. */ isUsed = 1; if (s_ulipIoctl (fd, FIOSETUSED, (char *)&isUsed, sizeof (isUsed)) != 0) { errno = u_errno (); u_printf ("ul%d: set Used failed\n", unit); return (-1); }#endif /* SIMSPARCSOLARIS */ /* get ifnet address */ if (u_ioctl (fd, SIOCGIFADDR, (char*)&sc->ipaddr) != 0) sc->ipaddr = -1; sc->ulReadLoop = 0; sc->ulipFd = fd;#if CPU==SIMHPPA intUnlock(lvl);#endif /* CPU=SIMHPPA */ return (0); }#if CPU==SIMSPARCSOLARIS/******************************************************************************** ulipDebugSet - Set debug flag in UNIX's ULIP driver** This function uses an ioctl call to UNIX's (Solaris's) ULIP driver to set * that driver's debugging flag to the value in debugFlag. Because there is no * simple way for the caller to assertain the unit number of the interface in * use, all unit numbers are looped over and each receives the ioctl. Possible * values for the debug flag are discussed above in this file, although all the* levels have not been implemented.** This is not the right place to put this function (user callable routines* would be more appropriately placed in simLib.h). Because of the requirement * to use both Sun structures (to bundle ioctl data) and VxWorks structures * (ul_softc), and given the same requirements when calling the FIOSETUSED * ioctl, this seems the best place to put it.** RETURNS: OK or ERROR if the ioctl fails */STATUS ulipDebugSet ( int debugFlag ) { int i; /* s_ulipIoctl is called because the FIOSETD ioctl requires special * bundling of its user data. */ for (i=0; i < NULIP; i++) if (ul_softc [i] != NULL) if (s_ulipIoctl (ul_softc [i]->ulipFd, FIOSETD, (char *)&debugFlag, sizeof (debugFlag)) != 0) return (ERROR); return (OK); }#endif /* SIMSPARCSOLARIS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -