📄 if_sm.c
字号:
} else { pEaddr = etherAddrPtr (pEh->ether_dhost); if (xs->masterAddr != 0) /* sequential addressing */ { destCPU = ((pEaddr [3] << 16)|(pEaddr [4] << 8)| pEaddr [5]) - xs->masterAddr; } else destCPU = pEaddr [5]; /* receive packets sent to self */ if (destCPU == xs->smPktDesc.smDesc.cpuNum) { smIfRecv (xs, pPkt, &retBuffer); if (retBuffer) (void) smPktFreePut (&xs->smPktDesc, (SM_PKT *)pPkt); continue; /* don't use SM to send to self */ } } if (smIfVerbose) { printf ("smIfStartOutput: [0x%x] len:%d src:%s ", pEh->ether_type, len, ether_sprintf (etherAddrPtr (pEh->ether_shost))); printf ("dst:%s cpu [%d]\n", ether_sprintf (etherAddrPtr (pEh->ether_dhost)), destCPU); } xs->xs_if.if_opackets++; if (smPktSend (&xs->smPktDesc, (SM_PKT *)pPkt, destCPU) == ERROR) { if (smIfVerbose) printf ("smIfStartOutput:smPktSend failed 0x%x\n", errno); xs->xs_if.if_oerrors++; xs->xs_if.if_opackets--; /* * need to return shared memory packet on error, * unless it's a incomplete broadcast error. */ if (errno != S_smPktLib_INCOMPLETE_BROADCAST) (void) smPktFreePut (&xs->smPktDesc, (SM_PKT *)pPkt); } } }/******************************************************************************** smIfReset - reset the backplane interface** smIfReset resets the interface. This gets called when the system* receives a reset. Basically this routine cleans up the state and marks* the interface as inactive before it goes away.** RETURNS: N/A** NOMANUAL*/LOCAL void smIfReset ( int unit /* unit number */ ) { SM_SOFTC * xs = UNIT_TO_SOFTC (unit); /* softc pointer */ int spl; /* spl level */ if (!deviceValid (unit)) return; /* detach from network */ spl = splimp (); xs->xs_if.if_flags &= ~IFF_RUNNING; if_down (&xs->xs_if); splx (spl); /* detach from shared mem */ (void) smPktDetach (&xs->smPktDesc, SM_FLUSH); }/******************************************************************************** smIfIoctl - process an ioctl request** smIfIoctl gets called to perform a control operation on the backplane network* interface. The implemented commands include: SIOCSIFADDR (set interface* address) SIOCSIFFLAGS (set interface flags), SIOCGIFADDR get (link-level)* interface address.** RETURNS: OK if successful, otherwise errno.** NOMANUAL*/LOCAL int smIfIoctl ( struct ifnet * pIf, /* interface pointer */ UINT cmd, /* ioctl command */ caddr_t data /* command data */ ) { struct ifreq * pIfr; /* if request */ int retVal = OK; /* error value */ int spl = splimp (); /* spl level */ SM_SOFTC * xs = UNIT_TO_SOFTC (pIf->if_unit); struct in_addr ipAddr; /* address passed */ struct in_addr expAddr; /* expected address */ char netString[32]; pIfr = (struct ifreq *) data; switch (cmd) { case SIOCSIFADDR: /* set interface address */ retVal = set_if_addr (pIf, data, etherAddrPtr (xs->xs_enaddr)); if ((retVal == OK) && (xs->masterAddr != 0)) { /* * We validate address after set_if_addr because * shared memory must be up (smPktAttach) before master * address can be determined. */ ipAddr = ((struct in_ifaddr *) data)->ia_addr.sin_addr; expAddr.s_addr = htonl ( ntohl (xs->smPktDesc.hdrLocalAdrs->reserved1)+ xs->smPktDesc.smDesc.cpuNum); if (expAddr.s_addr != ipAddr.s_addr) { inet_ntoa_b (expAddr, netString); printf ("Seqential addressing enabled - expected address:" "%s\n", netString); smIfReset (pIf->if_unit); retVal = ERROR; } } break; case SIOCSIFFLAGS: /* set interface flags */ if (pIf->if_flags & IFF_UP) smIfInit (pIf->if_unit); break; case SIOCGIFADDR: /* get link level address */ bcopy ((caddr_t) etherAddrPtr (xs->xs_enaddr), (caddr_t)(pIfr->ifr_addr.sa_data), sizeof (xs->xs_enaddr)); break; case SIOCADDMULTI: case SIOCDELMULTI: if (pIfr == 0) { retVal = EINVAL; /* invalid argument passed */ break; } switch (pIfr->ifr_addr.sa_family) {#ifdef INET case AF_INET: /* do nothing */ break;#endif default: retVal = EAFNOSUPPORT; break; } break; default: if (smIfVerbose) printf ("smIfIoctl: [0x%x] command not implemented\n", cmd); retVal = EINVAL; } (void) splx (spl); return (retVal); }/******************************************************************************** smIfInput - handle an input packet** smIfInput gets called from the OS specific interrupt handling routine* to process a shared memory input packet. It calls smPktRecv to obtain* the packets from shared memory and then calls smIfRecv to process the* packet and pass it up to the network modules.** RETURNS: N/A** NOMANUAL*/void smIfInput ( SM_SOFTC * xs /* softc pointer */ ) { SM_PKT * pPkt; /* shared memory packet */ int status; /* status */ BOOL retBuffer; /* return packet */ int cpuNum; /* my cpu number */ cpuNum = xs->smPktDesc.smDesc.cpuNum; do { xs->taskRecvActive = TRUE; while (((status = smPktRecv (&xs->smPktDesc, &pPkt)) == OK) && (pPkt != NULL)) { smIfRecv (xs, pPkt, &retBuffer); if (retBuffer) (void) smPktFreePut (&xs->smPktDesc, pPkt); } if (status == ERROR) { xs->xs_if.if_ierrors++; if (smIfVerbose) printf ("smIfInput:error receiving packet 0x%x\n", errno); } xs->taskRecvActive = FALSE; } while ((xs->smPktDesc.status == SM_CPU_ATTACHED) && (smIfInputCount (xs, cpuNum) > 0)); }/******************************************************************************** smIfRecv - process shared memory input packet** smIfRecv is called once per packet that arrives. It calls check_trailer* to process trailers. Copies that packet into an mbuf chain (if buffer* loaning is not set). Then passes the packet to the network layer by calling* do_protocol.** RETURNS: N/A** NOMANUAL*/LOCAL void smIfRecv ( SM_SOFTC * xs, /* softc pointer */ SM_PKT volatile * pPkt, /* packet */ BOOL * retBuffer /* kept buffer */ ) { struct ether_header * pEh; /* ethernet header */ int len; /* length */ u_char * pData; /* pointer to data */ struct mbuf * pMbuf = NULL; /* mbuf pointer */ *retBuffer = TRUE; /* return buffer by default */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ len = pPkt->header.nBytes; /* PCI bug [SPR 68844] */ len = pPkt->header.nBytes; pEh = (struct ether_header *) pPkt->data; if (inputHook (&xs->xs_if, (char *) pEh, len)) return; if (len < SIZEOF_ETHERHEADER) { if (smIfVerbose) printf ("smIfRecv:invalid packet len %d\n", len); xs->xs_if.if_ierrors++; return; /* invalid packet size */ } if (smIfVerbose) /* debugging aide */ { printf ("smIfRecv [0x%x] len: %d src:%s ", ntohs (pEh->ether_type), len, ether_sprintf (etherAddrPtr (pEh->ether_shost))); printf ("dst:%s\n", ether_sprintf (etherAddrPtr (pEh->ether_dhost))); } len -= SIZEOF_ETHERHEADER; /* adj. for enet header */ pData = ((unsigned char *) pEh) + SIZEOF_ETHERHEADER; if (len == 0) return; /* packet with no data */ /* * try to build a loaned mbuf cluster (if buffering loaning is enabled, * there are loan buffers available, the packet doesn't use * trailers, and the packet is big enough). Otherwise copy it * to an mbuf. */ if ((xs->bufFree > 0) && (USE_CLUSTER (len))) { if ((pMbuf = loanBuild (xs, pPkt, pData, len)) != NULL) { xs->bufFree--; *retBuffer = FALSE; } } if (pMbuf == NULL) { if ((pMbuf = (struct mbuf *) copyToMbufs (pData, len, 0, &xs->xs_if)) == NULL) return; } do_protocol (pEh, pMbuf, &xs->xs_ac, len); xs->xs_if.if_ipackets++; }/******************************************************************************** smIfLoanReturn - return shared memory packet to shared memory pool** smPktReturn gets called from the network modules to return the loaned* shared memory buffer once the network code has finished with it. It gets* called with the spl semaphore taken.** RETURNS: N/A** NOMANUAL*/void smIfLoanReturn ( SM_SOFTC * xs, /* softc pointer */ SM_PKT * pPkt /* shared memory packet */ ) { if (smPktFreePut (&xs->smPktDesc, pPkt) == ERROR) return; xs->bufFree++; }/******************************************************************************** smIfHwAddrSet - set hardware address** This routine sets the hardware address associated with the backplane * interface specified by <unit>.** RETURNS: N/A** NOMANUAL*/LOCAL void smIfHwAddrSet ( int unit /* unit number */ ) { u_char * pEaddr; /* ethernet address */ u_long addr; /* address */ int tmp; /* temp storage */ SM_PKT_MEM_HDR volatile * pSmPktHdr; /* packet header */ SM_SOFTC * xs = UNIT_TO_SOFTC (unit); /* softc pointer */ pEaddr = etherAddrPtr(xs->xs_enaddr); bzero ((caddr_t)pEaddr, 6); /* fill in ethernet address */ pEaddr [0] = 0x00; pEaddr [1] = 0x02; pEaddr [2] = 0xE2; pSmPktHdr = (SM_PKT_MEM_HDR volatile *)xs->smPktDesc.hdrLocalAdrs; CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pSmPktHdr->reserved1; /* PCI bug [SPR 68844] */ if (pSmPktHdr->reserved1 != 0) /* sequential addressing */ { /* * The backplane hw address consists of * { 0x00, 0x02, 0xE2, ip[1], ip[2], ip[3] }. * where ip is the lower three bytes of * the IP interface address. */ xs->masterAddr = ntohl (pSmPktHdr->reserved1) & 0x00ffffff; addr = xs->masterAddr + xs->smPktDesc.smDesc.cpuNum; pEaddr [3] = (u_char)((addr >> 16) & 0xff); pEaddr [4] = (u_char)((addr >> 8) & 0xff); pEaddr [5] = (u_char)(addr & 0xff); } else { /* * Backplane hw address consists of * { 0x00, 0x02, 0xE2, 0x00, unit, cpu }. */ pEaddr [4] = (u_char)unit; pEaddr [5] = (u_char)xs->smPktDesc.smDesc.cpuNum; } if (smIfVerbose) printf ("hw address:%s\n", ether_sprintf (pEaddr)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -