📄 via-rhine.c
字号:
byMIIAdrbak = inb (byMIIAD); byMIICRbak = inb (byMIICR); outb (byMIICRbak & 0x7f, byMIICR); MIIDelay (); outb (byMIISetByte, byMIIAD); MIIDelay (); outb (inb (byMIICR) | 0x40, byMIICR); byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x40; while (byMIItemp != 0) { byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x40; } MIIDelay (); ReadMIItmp = inw (wMIIDATA); MIIMask = 0x0001; MIIMask = MIIMask << byMIISetBit; if (byMIIOP == 0) { MIIMask = ~MIIMask; ReadMIItmp = ReadMIItmp & MIIMask; } else { ReadMIItmp = ReadMIItmp | MIIMask; } outw (ReadMIItmp, wMIIDATA); MIIDelay (); outb (inb (byMIICR) | 0x20, byMIICR); byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x20; while (byMIItemp != 0) { byMIItemp = inb (byMIICR); byMIItemp = byMIItemp & 0x20; } MIIDelay (); outb (byMIIAdrbak & 0x7f, byMIIAD); outb (byMIICRbak, byMIICR); MIIDelay ();}voidMIIDelay (void){ int i; for (i = 0; i < 0x7fff; i++) { inb (0x61); inb (0x61); inb (0x61); inb (0x61); }}struct nic *rhine_probe (struct nic *nic, unsigned short *probeaddrs, struct pci_device *pci){ if (!pci->ioaddr) return NULL; nic = rhine_probe1 (nic, pci->ioaddr, 0, -1); if (nic) adjust_pci_device(pci); nic->poll = rhine_poll; nic->transmit = rhine_transmit; nic->reset = rhine_reset; nic->disable = rhine_disable; rhine_reset (nic); return nic;}static struct nic *rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options){ struct rhine_private *tp; static int did_version = 0; /* Already printed version info. */ int i; unsigned int timeout; int FDXFlag; int byMIIvalue, LineSpeed, MIICRbak; if (rhine_debug > 0 && did_version++ == 0) printf (version); /* Perhaps this should be read from the EEPROM? */ for (i = 0; i < ETH_ALEN; i++) nic->node_addr[i] = inb (byPAR0 + i); printf ("IO address %hX Ethernet Address: %!\n", ioaddr, nic->node_addr); /* restart MII auto-negotiation */ WriteMII (0, 9, 1, ioaddr); printf ("Analyzing Media type,this will take several seconds........"); for (i = 0; i < 5; i++) { /* need to wait 1 millisecond - we will round it up to 50-100ms */ timeout = currticks() + 2; for (timeout = currticks() + 2; currticks() < timeout;) /* nothing */; if (ReadMII (1, ioaddr) & 0x0020) break; } printf ("OK\n");#if 0 /* JJM : for Debug */ printf("MII : Address %hhX ",inb(ioaddr+0x6c)); { unsigned char st1,st2,adv1,adv2,l1,l2; st1=ReadMII(1,ioaddr)>>8; st2=ReadMII(1,ioaddr)&0xFF; adv1=ReadMII(4,ioaddr)>>8; adv2=ReadMII(4,ioaddr)&0xFF; l1=ReadMII(5,ioaddr)>>8; l2=ReadMII(5,ioaddr)&0xFF; printf(" status 0x%hhX%hhX, advertising 0x%hhX%hhX, link 0x%hhX%hhX\n", st1,st2,adv1,adv2,l1,l2); }#endif /* query MII to know LineSpeed,duplex mode */ byMIIvalue = inb (ioaddr + 0x6d); LineSpeed = byMIIvalue & MIISR_SPEED; if (LineSpeed != 0) //JJM { printf ("Linespeed=10Mbs"); } else { printf ("Linespeed=100Mbs"); } FDXFlag = QueryAuto (ioaddr); if (FDXFlag == 1) { printf (" Fullduplex\n"); outw (CR_FDX, byCR0); } else { printf (" Halfduplex\n"); } /* set MII 10 FULL ON */ WriteMII (17, 1, 1, ioaddr); /* turn on MII link change */ MIICRbak = inb (byMIICR); outb (MIICRbak & 0x7F, byMIICR); MIIDelay (); outb (0x41, byMIIAD); MIIDelay (); /* while((inb(byMIIAD)&0x20)==0) ; */ outb (MIICRbak | 0x80, byMIICR); nic->priv_data = &rhine; tp = &rhine; tp->chip_id = chip_id; tp->ioaddr = ioaddr; tp->phys[0] = -1; /* The lower four bits are the media type. */ if (options > 0) { tp->full_duplex = (options & 16) ? 1 : 0; tp->default_port = options & 15; if (tp->default_port) tp->medialock = 1; } return nic;}static voidrhine_disable (struct nic *nic){ struct rhine_private *tp = (struct rhine_private *) nic->priv_data; int ioaddr = tp->ioaddr; printf ("rhine disable\n"); /* Switch to loopback mode to avoid hardware races. */ writeb(0x60 | 0x01, byTCR); /* Stop the chip's Tx and Rx processes. */ writew(CR_STOP, byCR0);}/**************************************************************************ETH_RESET - Reset adapter***************************************************************************/static voidrhine_reset (struct nic *nic){ struct rhine_private *tp = (struct rhine_private *) nic->priv_data; int ioaddr = tp->ioaddr; int i, j; int FDXFlag, CRbak; int rx_ring_tmp, rx_ring_tmp1; int tx_ring_tmp, tx_ring_tmp1; int rx_bufs_tmp, rx_bufs_tmp1; int tx_bufs_tmp, tx_bufs_tmp1;#ifdef USE_LOWMEM_BUFFER#define buf1 (0x10000 - (RX_RING_SIZE * PKT_BUF_SZ + 32))#define buf2 (buf1 - (RX_RING_SIZE * PKT_BUF_SZ + 32))#define desc1 (buf2 - (TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32))#define desc2 (desc1 - (TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32))#else static char buf1[RX_RING_SIZE * PKT_BUF_SZ + 32]; static char buf2[RX_RING_SIZE * PKT_BUF_SZ + 32]; static char desc1[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32]; static char desc2[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32];#endif /* printf ("rhine_reset\n"); */ /* Soft reset the chip. */ /*outb(CmdReset, ioaddr + ChipCmd); */ tx_bufs_tmp = (int) buf1; tx_ring_tmp = (int) desc1; rx_bufs_tmp = (int) buf2; rx_ring_tmp = (int) desc2; /* tune RD TD 32 byte alignment */ rx_ring_tmp1 = (int) virt_to_bus ((char *) rx_ring_tmp); j = (rx_ring_tmp1 + 32) & (~0x1f); /* printf ("txring[%d]", j); */ tp->rx_ring = (struct rhine_rx_desc *) bus_to_virt (j); tx_ring_tmp1 = (int) virt_to_bus ((char *) tx_ring_tmp); j = (tx_ring_tmp1 + 32) & (~0x1f); tp->tx_ring = (struct rhine_tx_desc *) bus_to_virt (j); /* printf ("rxring[%X]", j); */ tx_bufs_tmp1 = (int) virt_to_bus ((char *) tx_bufs_tmp); j = (int) (tx_bufs_tmp1 + 32) & (~0x1f); tx_bufs_tmp = (int) bus_to_virt (j); /* printf ("txb[%X]", j); */ rx_bufs_tmp1 = (int) virt_to_bus ((char *) rx_bufs_tmp); j = (int) (rx_bufs_tmp1 + 32) & (~0x1f); rx_bufs_tmp = (int) bus_to_virt (j); /* printf ("rxb[%X][%X]", rx_bufs_tmp1, j); */ for (i = 0; i < RX_RING_SIZE; i++) { tp->rx_buffs[i] = (char *) rx_bufs_tmp; /* printf("r[%X]",tp->rx_buffs[i]); */ rx_bufs_tmp += 1536; } for (i = 0; i < TX_RING_SIZE; i++) { tp->tx_buffs[i] = (char *) tx_bufs_tmp; /* printf("t[%X]",tp->tx_buffs[i]); */ tx_bufs_tmp += 1536; } /* software reset */ outb (CR1_SFRST, byCR1); MIIDelay (); /* printf ("init ring"); */ rhine_init_ring (nic); /*write TD RD Descriptor to MAC */ outl (virt_to_bus (tp->rx_ring), dwCurrentRxDescAddr); outl (virt_to_bus (tp->tx_ring), dwCurrentTxDescAddr); /* close IMR */ outw (0x0000, byIMR0); /* set TCR RCR threshold */ outb (0x06, byBCR0); outb (0x00, byBCR1); outb (0x2c, byRCR); outb (0x60, byTCR); /* Set Fulldupex */ FDXFlag = QueryAuto (ioaddr); if (FDXFlag == 1) { outb (CFGD_CFDX, byCFGD); outw (CR_FDX, byCR0); } /* KICK NIC to WORK */ CRbak = inw (byCR0); CRbak = CRbak & 0xFFFB; /* not CR_STOP */ outw ((CRbak | CR_STRT | CR_TXON | CR_RXON | CR_DPOLL), byCR0); /*set IMR to work */ outw (IMRShadow, byIMR0);}static intrhine_poll (struct nic *nic){ struct rhine_private *tp = (struct rhine_private *) nic->priv_data; int rxstatus, good = 0;; if (tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit == 0) { rxstatus = tp->rx_ring[tp->cur_rx].rx_status.lw; if ((rxstatus & 0x0300) != 0x0300) { printf("rhine_poll: bad status\n"); } else if (rxstatus & (RSR_ABNORMAL)) { printf ("rxerr[%X]\n", rxstatus); } else good = 1; if (good) { nic->packetlen = tp->rx_ring[tp->cur_rx].rx_status.bits.frame_length; memcpy (nic->packet, tp->rx_buffs[tp->cur_rx], nic->packetlen); /* printf ("Packet RXed\n"); */ } tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit = 1; tp->cur_rx++; tp->cur_rx = tp->cur_rx % RX_RING_SIZE; } return good;}static voidrhine_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p){ struct rhine_private *tp = (struct rhine_private *) nic->priv_data; int ioaddr = tp->ioaddr; int entry; unsigned char CR1bak; /*printf ("rhine_transmit\n"); */ /* setup ethernet header */ /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % TX_RING_SIZE; memcpy (tp->tx_buffs[entry], d, ETH_ALEN); /* dst */ memcpy (tp->tx_buffs[entry] + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ *((char *) tp->tx_buffs[entry] + 12) = t >> 8; /* type */ *((char *) tp->tx_buffs[entry] + 13) = t; memcpy (tp->tx_buffs[entry] + ETH_HLEN, p, s); s += ETH_HLEN; while (s < ETH_ZLEN) *((char *) tp->tx_buffs[entry] + ETH_HLEN + (s++)) = 0; tp->tx_ring[entry].tx_ctrl.bits.tx_buf_size = ETH_HLEN + s; tp->tx_ring[entry].tx_status.bits.own_bit = 1; CR1bak = inb (byCR1); CR1bak = CR1bak | CR1_TDMD1; /*printf("tdsw=[%X]",tp->tx_ring[entry].tx_status.lw); */ /*printf("tdcw=[%X]",tp->tx_ring[entry].tx_ctrl.lw); */ /*printf("tdbuf1=[%X]",tp->tx_ring[entry].buf_addr_1); */ /*printf("tdbuf2=[%X]",tp->tx_ring[entry].buf_addr_2); */ /*printf("td1=[%X]",inl(dwCurrentTDSE0)); */ /*printf("td2=[%X]",inl(dwCurrentTDSE1)); */ /*printf("td3=[%X]",inl(dwCurrentTDSE2)); */ /*printf("td4=[%X]",inl(dwCurrentTDSE3)); */ outb (CR1bak, byCR1); tp->cur_tx++; /*outw(IMRShadow,byIMR0); */ /*dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE); */ /*tp->tx_skbuff[entry] = 0; */}/* EOF via-rhine.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -