📄 tlan.c
字号:
if ((status & MII_GS_LINK) && /* We only support link info on Nat.Sem. PHY's */ (tlphy_id1 == NAT_SEM_ID1) && (tlphy_id2 == NAT_SEM_ID2)) { TLan_MiiReadReg(nic, phy, MII_AN_LPA, &partner); TLan_MiiReadReg(nic, phy, TLAN_TLPHY_PAR, &tlphy_par); printf("TLAN: %s: Link active with ", priv->nic_name); if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) { printf("forced 10%sMbps %s-Duplex\n", tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0", tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half"); } else { printf ("AutoNegotiation enabled, at 10%sMbps %s-Duplex\n", tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0", tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half"); printf("TLAN: Partner capability: "); for (i = 5; i <= 10; i++) if (partner & (1 << i)) printf("%s", media[i - 5]); printf("\n"); } TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);#ifdef MONITOR /* We have link beat..for now anyway */ priv->link = 1; /*Enabling link beat monitoring */ /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_LINK_BEAT ); */ mdelay(10000); TLan_PhyMonitor(nic);#endif } else if (status & MII_GS_LINK) { printf("TLAN: %s: Link active\n", priv->nic_name); TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK); } } if (priv->phyNum == 0) { TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tlphy_ctl); tlphy_ctl |= TLAN_TC_INTEN; TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tlphy_ctl); sio = TLan_DioRead8(BASE, TLAN_NET_SIO); sio |= TLAN_NET_SIO_MINTEN; TLan_DioWrite8(BASE, TLAN_NET_SIO, sio); } if (status & MII_GS_LINK) { TLan_SetMac(nic, 0, nic->node_addr); priv->phyOnline = 1; outb((TLAN_HC_INT_ON >> 8), BASE + TLAN_HOST_CMD + 1);/* if ( debug >= 1 && debug != TLAN_DEBUG_PROBE ) { outb( ( TLAN_HC_REQ_INT >> 8 ), BASE + TLAN_HOST_CMD + 1 ); } */ outl(virt_to_bus(&rx_ring), BASE + TLAN_CH_PARM); outl(TLAN_HC_GO | TLAN_HC_RT, BASE + TLAN_HOST_CMD); } else { printf ("TLAN: %s: Link inactive, will retry in 10 secs...\n", priv->nic_name); /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_FINISH_RESET ); */ mdelay(10000); TLan_FinishReset(nic); return; }} /* TLan_FinishReset *//**************************************************************************POLL - Wait for a frame***************************************************************************/static int tlan_poll(struct nic *nic){ /* return true if there's an ethernet packet ready to read */ /* nic->packet should contain data on return */ /* nic->packetlen should contain length of data */ u32 framesize; u32 host_cmd = 0; u32 ack = 1; int eoc = 0; int entry = priv->cur_rx % TLAN_NUM_RX_LISTS; u16 tmpCStat = le32_to_cpu(rx_ring[entry].cStat); u16 host_int = inw(BASE + TLAN_HOST_INT); outw(host_int, BASE + TLAN_HOST_INT); if (!(tmpCStat & TLAN_CSTAT_FRM_CMP)) return 0; /* printf("PI-1: 0x%hX\n", host_int); */ if (tmpCStat & TLAN_CSTAT_EOC) eoc = 1; framesize = rx_ring[entry].frameSize; nic->packetlen = framesize;#ifdef EBDEBUG printf(".%d.", framesize); #endif memcpy(nic->packet, rxb + (priv->cur_rx * TLAN_MAX_FRAME_SIZE), nic->packetlen); rx_ring[entry].cStat = 0;#ifdef EBDEBUG hex_dump(nic->packet, nic->packetlen); printf("%d", entry); #endif entry = (entry + 1) % TLAN_NUM_RX_LISTS; priv->cur_rx = entry; if (eoc) { if ((rx_ring[entry].cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) { ack |= TLAN_HC_GO | TLAN_HC_RT; host_cmd = TLAN_HC_ACK | ack | 0x001C0000; outl(host_cmd, BASE + TLAN_HOST_CMD); } } else { host_cmd = TLAN_HC_ACK | ack | (0x000C0000); outl(host_cmd, BASE + TLAN_HOST_CMD);#ifdef EBDEBUG printf("AC: 0x%hX\n", inw(BASE + TLAN_CH_PARM)); host_int = inw(BASE + TLAN_HOST_INT); printf("PI-2: 0x%hX\n", host_int); #endif } refill_rx(nic); return (1); /* initially as this is called to flush the input */}static void refill_rx(struct nic *nic __unused){ int entry = 0; for (; (priv->cur_rx - priv->dirty_rx + TLAN_NUM_RX_LISTS) % TLAN_NUM_RX_LISTS > 0; priv->dirty_rx = (priv->dirty_rx + 1) % TLAN_NUM_RX_LISTS) { entry = priv->dirty_rx % TLAN_NUM_TX_LISTS; rx_ring[entry].frameSize = TLAN_MAX_FRAME_SIZE; rx_ring[entry].cStat = TLAN_CSTAT_READY; }}/* #define EBDEBUG *//**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void tlan_transmit(struct nic *nic, const char *d, /* Destination */ unsigned int t, /* Type */ unsigned int s, /* size */ const char *p){ /* Packet */ u16 nstype; u32 to; struct TLanList *tail_list; struct TLanList *head_list; u8 *tail_buffer; u32 ack = 0; u32 host_cmd; int eoc = 0; u16 tmpCStat;#ifdef EBDEBUG u16 host_int = inw(BASE + TLAN_HOST_INT);#endif int entry = 0;#ifdef EBDEBUG printf("INT0-0x%hX\n", host_int);#endif if (!priv->phyOnline) { printf("TRANSMIT: %s PHY is not ready\n", priv->nic_name); return; } tail_list = priv->txList + priv->txTail; if (tail_list->cStat != TLAN_CSTAT_UNUSED) { printf("TRANSMIT: %s is busy (Head=%d Tail=%d)\n", priv->nic_name, priv->txList, priv->txTail); tx_ring[entry].cStat = TLAN_CSTAT_UNUSED; priv->txBusyCount++; return; } tail_list->forward = 0; tail_buffer = txb + (priv->txTail * TLAN_MAX_FRAME_SIZE); /* send the packet to destination */ memcpy(tail_buffer, d, ETH_ALEN); memcpy(tail_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN); nstype = htons((u16) t); memcpy(tail_buffer + 2 * ETH_ALEN, (u8 *) & nstype, 2); memcpy(tail_buffer + ETH_HLEN, p, s); s += ETH_HLEN; s &= 0x0FFF; while (s < ETH_ZLEN) tail_buffer[s++] = '\0'; /*=====================================================*/ /* Receive * 0000 0000 0001 1100 * 0000 0000 0000 1100 * 0000 0000 0000 0011 = 0x0003 * * 0000 0000 0000 0000 0000 0000 0000 0011 * 0000 0000 0000 1100 0000 0000 0000 0000 = 0x000C0000 * * Transmit * 0000 0000 0001 1100 * 0000 0000 0000 0100 * 0000 0000 0000 0001 = 0x0001 * * 0000 0000 0000 0000 0000 0000 0000 0001 * 0000 0000 0000 0100 0000 0000 0000 0000 = 0x00040000 * */ /* Setup the transmit descriptor */ tail_list->frameSize = (u16) s; tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) s; tail_list->buffer[1].count = 0; tail_list->buffer[1].address = 0; tail_list->cStat = TLAN_CSTAT_READY;#ifdef EBDEBUG host_int = inw(BASE + TLAN_HOST_INT); printf("INT1-0x%hX\n", host_int);#endif if (!priv->txInProgress) { priv->txInProgress = 1; outl(virt_to_le32desc(tail_list), BASE + TLAN_CH_PARM); outl(TLAN_HC_GO, BASE + TLAN_HOST_CMD); } else { if (priv->txTail == 0) {#ifdef EBDEBUG printf("Out buffer\n");#endif (priv->txList + (TLAN_NUM_TX_LISTS - 1))->forward = virt_to_le32desc(tail_list); } else {#ifdef EBDEBUG printf("Fix this \n");#endif (priv->txList + (priv->txTail - 1))->forward = virt_to_le32desc(tail_list); } } CIRC_INC(priv->txTail, TLAN_NUM_TX_LISTS);#ifdef EBDEBUG host_int = inw(BASE + TLAN_HOST_INT); printf("INT2-0x%hX\n", host_int);#endif to = currticks() + TX_TIME_OUT; while ((tail_list->cStat == TLAN_CSTAT_READY) && currticks() < to); head_list = priv->txList + priv->txHead; while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) { ack++; if(tmpCStat & TLAN_CSTAT_EOC) eoc =1; head_list->cStat = TLAN_CSTAT_UNUSED; CIRC_INC(priv->txHead, TLAN_NUM_TX_LISTS); head_list = priv->txList + priv->txHead; } if(!ack) printf("Incomplete TX Frame\n"); if(eoc) { head_list = priv->txList + priv->txHead; if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) { outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM); ack |= TLAN_HC_GO; } else { priv->txInProgress = 0; } } if(ack) { host_cmd = TLAN_HC_ACK | ack; outl(host_cmd, BASE + TLAN_HOST_CMD); } if(priv->tlanRev < 0x30 ) { ack = 1; head_list = priv->txList + priv->txHead; if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) { outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM); ack |= TLAN_HC_GO; } else { priv->txInProgress = 0; } host_cmd = TLAN_HC_ACK | ack | 0x00140000; outl(host_cmd, BASE + TLAN_HOST_CMD); } if (currticks() >= to) { printf("TX Time Out"); }}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/#ifdef EB51static void tlan_disable(struct dev *dev __unused)#elsestatic void tlan_disable(struct nic *nic __unused)#endif{ /* put the card in its initial state */ /* This function serves 3 purposes. * This disables DMA and interrupts so we don't receive * unexpected packets or interrupts from the card after * etherboot has finished. * This frees resources so etherboot may use * this driver on another interface * This allows etherboot to reinitialize the interface * if something is something goes wrong. * */ outl(TLAN_HC_AD_RST, BASE + TLAN_HOST_CMD);}static void TLan_SetMulticastList(struct nic *nic) { int i; u8 tmp; /* !IFF_PROMISC */ tmp = TLan_DioRead8(BASE, TLAN_NET_CMD); TLan_DioWrite8(BASE, TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF); /* IFF_ALLMULTI */ for(i = 0; i< 3; i++) TLan_SetMac(nic, i + 1, NULL); TLan_DioWrite32(BASE, TLAN_HASH_1, 0xFFFFFFFF); TLan_DioWrite32(BASE, TLAN_HASH_2, 0xFFFFFFFF); }/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/#define board_found 1#define valid_link 0#ifdef EB51static int tlan_probe(struct dev *dev, struct pci_device *pci){ struct nic *nic = (struct nic *) dev;#elsestruct nic *tlan_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci){#endif u16 data = 0; int err; int i; if (pci->ioaddr == 0) return 0; BASE = pci->ioaddr; printf("\n"); printf("tlan.c: %s, %s\n", drv_version, drv_date); printf("%s: Probing for Vendor 0x%hX, Device 0x%hX", pci->name, pci->vendor, pci->dev_id); /* I really must find out what this does */ adjust_pci_device(pci); /* Point to private storage */ priv = &TLanPrivateInfo; /* Figure out which chip we're dealing with */ i = 0; chip_idx = -1; while (tlan_pci_tbl[i].name) { if ((((u32) pci->dev_id << 16) | pci->vendor) == (tlan_pci_tbl[i].id.pci & 0xffffffff)) { chip_idx = i; break; } i++; } priv->vendor_id = pci->vendor; priv->dev_id = pci->dev_id; priv->nic_name = pci->name; priv->eoc = 0; err = 0; for (i = 0; i < 6; i++) err |= TLan_EeReadByte(BASE, (u8) tlan_pci_tbl[chip_idx]. addrOfs + i, (u8 *) & nic->node_addr[i]); if (err) { printf("TLAN: %s: Error reading MAC from eeprom: %d\n", pci->name, err); } else printf("\nAddress: %!\n", nic->node_addr); priv->tlanRev = TLan_DioRead8(BASE, TLAN_DEF_REVISION); printf("\nRevision = 0x%hX\n", priv->tlanRev); TLan_ResetLists(nic); TLan_ResetAdapter(nic);/* data = inl(BASE + TLAN_HOST_CMD); data |= TLAN_HC_EOC; outw(data, BASE + TLAN_HOST_CMD);*/ data = inl(BASE + TLAN_HOST_CMD); data |= TLAN_HC_INT_OFF; outw(data, BASE + TLAN_HOST_CMD); TLan_SetMulticastList(nic); udelay(100); priv->txList = tx_ring; priv->rxList = rx_ring;/* if (board_found && valid_link) {*/ /* point to NIC specific routines */#ifdef EB51 dev->disable = tlan_disable; nic->poll = tlan_poll;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -