📄 if_gt.c
字号:
} /* Initialize Rx index */ sc->rx_next_out = 0;}intgt_ioctl(ifp, command, data) struct ifnet *ifp; u_long command; caddr_t data;{ struct gt_softc *sc = ifp->if_softc; int s, error = 0; s = splimp(); switch (command) { case SIOCPOLL: gt_intr(sc); break; case SIOCSIFADDR: error = ether_ioctl(ifp, command, data); break; case SIOCSIFFLAGS: printf("case SIOCSIFFLAGS, marking interface up/down...\n"); //sc->all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0; /* * If interface is marked up and not running, then start it. * If it is marked down and running, stop it. * XXX If it's up then re-initialize it. This is so flags * such as IFF_PROMISC are handled. */ if (ifp->if_flags & IFF_UP) { gt_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) gt_stop(sc, 1); } break;#if USE_GT_MULTICAST case SIOCADDMULTI: case SIOCDELMULTI: //sc->all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0; error = (command == SIOCADDMULTI) ? ether_addmulti(ifr, &sc->arpcom) : ether_delmulti(ifr, &sc->arpcom); if (error == ENETRESET) { /* * Multicast list has changed; set the hardware * filter accordingly. */ /*if (!sc->all_mcasts) fxp_mc_setup(sc);*/ /* * fxp_mc_setup() can turn on all_mcasts if we run * out of space, so check it again rather than else {}. */ /*if (sc->all_mcasts)*/ if (0) gt_init(sc); error = 0; } break;#endif case SIOCSIFMEDIA: case SIOCGIFMEDIA: /*error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);*/ break; default: error = EINVAL; } (void) splx(s); return (error);}voidgt_init(xsc) void *xsc;{ struct gt_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; /*s = splimp();*/ /* * Cancel any pending I/O */ ifp->if_flags |= IFF_RUNNING; /* Stop and disable port, or reset to stable state */ /*gt_stop(sc,0);*/}static intgt_ether_ioctl(ifp, cmd, data) struct ifnet *ifp; u_int32_t cmd; caddr_t data;{ struct ifaddr *ifa = (struct ifaddr *) data; struct gt_softc *sc = ifp->if_softc; switch (cmd) {#ifdef PMON case SIOCPOLL: gt_intr(sc); break;#endif case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) {#ifdef INET case AF_INET: gt_init(sc); arp_ifinit(&sc->arpcom, ifa); break;#endif#ifdef NS case AF_NS: { struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *) LLADDR(ifp->if_sadl); else bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl), ifp->if_addrlen); /* Set new address. */ gt_init(sc); break; }#endif default: gt_init(sc); break; } break; default: return (EINVAL); } return (0);}static intgt_intr(arg) void *arg;{ struct gt_softc *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; uint icr, psr; /* * Read Interrupt Cause Register and ACK interrupts */ icr = GTETH_READ(sc, ETH0_INTERRUPT_CAUSE_REG); GTETH_WRITE(sc, ETH0_INTERRUPT_CAUSE_REG, 0); /* * Process incoming packets if Rx descriptor returned to CPU ownership */ gt_rx(sc, icr); /* * Transmit more packets if queue isn't empty */ if (ifp->if_snd.ifq_head != NULL) gt_start(ifp); /* * Check for Tx errors */ if (icr & icrTxErrorLow) printf("%s: Tx resource error (low priority)\n", sc->sc_dev.dv_xname); if (icr & icrTxUdr) printf("%s: Tx underrun error\n", sc->sc_dev.dv_xname); /* * Check for Rx errors */ if (icr & icrRxError) { printf("%s: Rx resource error. Resetting Rx\n", sc->sc_dev.dv_xname); reset_rx(sc); /* Restart receive engine */ GTETH_WRITE(sc, ETH0_SDMA_COMMAND_REG, sdcmrERD); } if (icr & icrRxOVR) printf("%s: Rx overrun\n", sc->sc_dev.dv_xname); /* * Check port status errors */ psr = GTETH_READ(sc, ETH0_PORT_STATUS_REG); if (psr & psrPause) printf("%s: Pause!\n", sc->sc_dev.dv_xname); return(0);}static intgt_rx(struct gt_softc *sc, u_int32_t status){ struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m; int nextRx, cdp; RX_DESC *rd; u_int32_t cmdstat; u_int16_t total_len; /* * Determine index to current descriptor */ cdp = (GTETH_READ(sc, ETH0_CURRENT_RX_DESC_PTR0) - (u_int32_t)sc->rx_ring) / sizeof(RX_DESC); /* * Process to current descriptor */ for (nextRx = sc->rx_next_out; nextRx != cdp; nextRx = (nextRx + 1) % RX_RING_SIZE) { rd = &sc->rx_ring[nextRx]; CACHESYNC(rd, sizeof(RX_DESC), SYNC_R); cmdstat = (u_int32_t)rd->cmdstat; /* * Bail if gt owns descriptor. This is the workaround for * not relying on the icr register. */ if (cmdstat & (u_int32_t)rxOwn) { break; } /* * Must be first and last (ie only) buffer of packet */ if (!(cmdstat & (u_int32_t)rxFirst) || !(cmdstat & (u_int32_t)rxLast)) { printf("%s: descriptor not first and last!\n", sc->sc_dev.dv_xname); goto next; } /* * Drop this packet if there were any errors */ if ((cmdstat & (u_int32_t)rxErrorSummary) || (status & icrRxError)) {#ifdef DEBUG_GT printf("%s: dropped packet %p:%p\n", sc->sc_dev.dv_xname, cmdstat, status);#endif goto next; } if((total_len = (rd->byte_sz_cnt & 0xffff)) > MCLBYTES) { printf("%s: bad packet length %d\n", sc->sc_dev.dv_xname, total_len); goto next; } /* * This is where the packets start to get processed to send * to upper layers of the protocol stack. */ m = sc->rx_m[nextRx]; /* * Add a new buffer to the receive descriptor. The old * buffer is recycled if it fails to get a new buffer * and true is returned by gt_add_rfabuf. */ if (!gt_add_rfabuf(sc, &sc->rx_m[nextRx])) { struct ether_header *eh; rd->buff_ptr = VA_TO_PA(sc->rx_m[nextRx]->m_data); total_len = rd->byte_sz_cnt & 0xffff; if (total_len < sizeof(struct ether_header)) { printf("%s: buffer too small, freeing mbuf\n", sc->sc_dev.dv_xname); m_freem(m); goto next; } m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = total_len - sizeof(struct ether_header); /* * Realign data in mbuf. Discovery require receive buffer * to be 64 bit aligned so we can't do this before receive. */ bcopy(m->m_data, m->m_data + RFA_ALIGNMENT_FUDGE, total_len); m->m_data += RFA_ALIGNMENT_FUDGE; /* * Send packet to upper layer */ eh = mtod(m, struct ether_header *); m->m_data += sizeof(struct ether_header); ether_input(ifp, eh, m); } else { printf("%s: gt recycling rxbuf!\n", sc->sc_dev.dv_xname); }next: /* * Release ownership to device, set first and last, enable interrupt */ rd->cmdstat = (u_int32_t)(rxFirst | rxLast | rxOwn | rxEI); CACHESYNC(rd, sizeof(RX_DESC), SYNC_W); } sc->rx_next_out = nextRx; return 0;}/* * Get a receive buffer and return it's data address. * Return 0 if recycled. The buffer is prepares such that * the pointer to "m" is stored in front of the data. */intgt_add_rfabuf(sc, oldm) struct gt_softc *sc; struct mbuf **oldm;{ struct mbuf *m, *pm; if(oldm != NULL) { pm = *oldm; } else { pm = NULL; } MGETHDR(m, M_DONTWAIT, MT_DATA); if (m != NULL) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); if (pm == NULL) { printf("gt_add_rfabuf: error 1\n"); return -1; } /* Recycle */ m = pm; m->m_data = m->m_ext.ext_buf; } } else { /* Recycle */ if (pm == NULL) { printf("gt_add_rfabuf: error 2\n"); return 1; } m = pm; m->m_data = m->m_ext.ext_buf; } /* * Move the data pointer up so that the incoming data packet * will be 64-bit aligned as requiered by the Discovery. * The ether header is not a multiple of 4 bytes but the upper layer * assumes data to be aligned so we will have to adjust this later. */ m->m_data = (void *)ALIGN(m->m_data); CACHESYNC((void *)m->m_data, RX_BUF_SZ, SYNC_R); *oldm = m; return (m == pm);}void read_mib_counters (sc) struct gt_softc *sc;{ u_int32_t *mib_reg = (u_int32_t *)&sc->mib; int i; for (i=0; i<sizeof(mib_counters_t)/sizeof(u_int32_t); i++) { mib_reg[i] = GTETH_READ(sc, ETH0_MIB_COUNTER_BASE + i*sizeof(u_int32_t)); }}intgt_miibus_readreg(arg, phy, reg) void *arg; int phy; int reg;{ struct gt_softc *sc = (struct gt_softc *)arg; unsigned int data = 0; u_int32_t phyreg; phyreg = GT_READ(ETH_PHY_ADDR_REG); if ((sc->sc_dev.dv_unit == 0 && (phyreg & 0x1f) != phy) || (sc->sc_dev.dv_unit == 1 && (phyreg & 0x3e0) != (phy << 5)) || (sc->sc_dev.dv_unit == 2 && (phyreg & 0x7c00) != (phy << 10)) || (sc->sc_dev.dv_unit > 2)) { return (0xffff); } phyreg = ((reg << SMIR_REGADBIT) & SMIR_REGADMASK) | ((phy << SMIR_PHYADBIT) & SMIR_PHYADMASK) | SMIR_READOP; GT_WRITE(ETH_SMI_REG, phyreg); do { phyreg = GT_READ(ETH_SMI_REG); } while (phyreg & SMIR_BUSY); data = GT_READ(ETH_SMI_REG); return (data & 0xffff);}intgt_miibus_writereg(arg, phy, reg, data) void *arg; int phy; int reg; int data;{ struct gt_softc *sc = (struct gt_softc *)arg; u_int32_t phyreg; phyreg = GT_READ(ETH_PHY_ADDR_REG); if ((sc->sc_dev.dv_unit == 0 && (phyreg & 0x1f) != phy) || (sc->sc_dev.dv_unit == 1 && (phyreg & 0x3e0) != (phy << 5)) || (sc->sc_dev.dv_unit == 2 && (phyreg & 0x7c00) != (phy << 10)) || (sc->sc_dev.dv_unit > 2)) { return (0xffff); } phyreg = ((reg << SMIR_REGADBIT) & SMIR_REGADMASK) | ((phy << SMIR_PHYADBIT) & SMIR_PHYADMASK) | (data & SMIR_DATAMASK); GT_WRITE(ETH_SMI_REG, phyreg); do { phyreg = GT_READ(ETH_SMI_REG); } while (phyreg & SMIR_BUSY); return (0);}#define NUM_ETH_PORTS 3 unsigned int addressTableHashMode[NUM_ETH_PORTS]; unsigned int addressTableHashSize[NUM_ETH_PORTS]; unsigned int addressTableBase[NUM_ETH_PORTS]; /****************************************************************************** * boolean_t initAddressTable(int port,int hashMode,int hashSize,int hashDefaultMode)* * This function will initialize the address table* and will enableFiltering.* Inputs* hashMode - hash mode 0 or hash mode 1.* hashSize - the size of the hash table (0=8K ,1=1/2K)* hashDefaultMode - 0 = discard addresses not found in the address table ,* 1 = pass addresses not found in the address table.* port - ETHERNET port number.* Outputs * address table is allocated and initialized.* TRUE if success.* FALSE if fail to make the assignment.*/int initAddressTable(int port,int hashMode,int hashSize,int hashDefaultMode)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -