📄 rtk8189c.c
字号:
printk(KERN_INFO "%s: %s at 0x%lx, ",
dev->name, pci_id_tbl[chip_idx].name, ioaddr);
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] = le16_to_cpu(eeprom_read(ioaddr, i + 8));
if (memcmp(dev->dev_addr, "\0\0\0\0\0", 6) == 0) {
printk(" (MISSING EEPROM ADDRESS)");
memcpy(dev->dev_addr, "\0Linux", 6);
}
for (i = 0; i < 5; i++)
printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
#if ! defined(final_version) /* Dump the EEPROM contents during development. */
if (debug > 4)
for (i = 0; i < 0x40; i++)
printk("%4.4x%s",
eeprom_read(ioaddr, i), i % 16 != 15 ? " " : "\n");
#endif
/* Make certain elements e.g. descriptor lists are aligned. */
priv_mem = kmalloc(sizeof(*np) + PRIV_ALIGN, GFP_KERNEL);
/* Check for the very unlikely case of no memory. */
if (priv_mem == NULL)
return NULL;
/* Do bogusness checks before this point.
We do a request_region() only to register /proc/ioports info. */
#ifdef USE_IO_OPS
request_region(ioaddr, pci_id_tbl[chip_idx].io_size, dev->name);
#endif
/* Reset the chip to erase previous misconfiguration. */
writel(BCR_Reset, ioaddr + PCIBusCfg);
dev->base_addr = ioaddr;
dev->irq = irq;
dev->priv = np = (void *)(((long)priv_mem + PRIV_ALIGN) & ~PRIV_ALIGN);
memset(np, 0, sizeof(*np));
np->priv_addr = priv_mem;
np->next_module = root_net_dev;
root_net_dev = dev;
np->pci_dev = pdev;
np->chip_id = chip_idx;
np->drv_flags = pci_id_tbl[chip_idx].drv_flags;
if (dev->mem_start)
option = dev->mem_start;
/* The lower four bits are the media type. */
if (option > 0) {
if (option & 0x220)
np->full_duplex = 1;
np->default_port = option & 0x3ff;
if (np->default_port)
np->medialock = 1;
}
if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
np->full_duplex = 1;
if (np->full_duplex) {
printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
" disabled.\n", dev->name);
np->duplex_lock = 1;
}
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
dev->hard_start_xmit = &start_tx;
dev->stop = &netdev_close;
dev->get_stats = &get_stats;
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &mii_ioctl;
if (mtu)
dev->mtu = mtu;
if (np->drv_flags & HasMIIXcvr) {
int phy, phy_idx = 0;
for (phy = 0; phy < 32 && phy_idx < 4; phy++) {
int mii_status = mdio_read(dev, phy, 1);
if (mii_status != 0xffff && mii_status != 0x0000) {
np->phys[phy_idx++] = phy;
np->advertising = mdio_read(dev, phy, 4);
printk(KERN_INFO "%s: MII PHY found at address %d, status "
"0x%4.4x advertising %4.4x.\n",
dev->name, phy, mii_status, np->advertising);
}
}
np->mii_cnt = phy_idx;
}
if (np->drv_flags & HasChipXcvr) {
np->phys[np->mii_cnt++] = 32;
printk(KERN_INFO "%s: Internal PHY status 0x%4.4x"
" advertising %4.4x.\n",
dev->name, mdio_read(dev, 32, 1), mdio_read(dev, 32, 4));
}
if (np->default_port & 0x330) {
np->medialock = 1;
printk(KERN_INFO " Forcing %dMbs %s-duplex operation.\n",
(option & 0x300 ? 100 : 10),
(option & 0x220 ? "full" : "half"));
if (np->mii_cnt)
mdio_write(dev, np->phys[0], 0,
((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */
((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */
}
return dev;
}
/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are
often serial bit streams generated by the host processor.
The example below is for the common 93c46 EEPROM, 64 16 bit words. */
/* This "delay" forces out buffered PCI writes. */
#define eeprom_delay(ee_addr) readl(ee_addr); udelay(2); readl(ee_addr)
enum EEPROM_Ctrl_Bits {
EE_ShiftClk=0x04<<16, EE_ChipSelect=0x88<<16,
EE_DataOut=0x02<<16, EE_DataIn=0x01<<16,
EE_Write0=0x88<<16, EE_Write1=0x8a<<16,
};
/* The EEPROM commands always start with 01.. preamble bits.
Commands are prepended to the variable-length address. */
enum EEPROM_Cmds { EE_WriteCmd=5, EE_ReadCmd=6, EE_EraseCmd=7, };
static int eeprom_read(long addr, int location)
{
int i;
int retval = 0;
long ee_addr = addr + EECtrl;
int read_cmd = location | (EE_ReadCmd<<6);
writel(EE_ChipSelect, ee_addr);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
int dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
writel(dataval, ee_addr);
eeprom_delay(ee_addr);
writel(dataval | EE_ShiftClk, ee_addr);
eeprom_delay(ee_addr);
}
writel(EE_ChipSelect, ee_addr);
eeprom_delay(ee_addr);
for (i = 16; i > 0; i--) {
writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
eeprom_delay(ee_addr);
retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0);
writel(EE_ChipSelect, ee_addr);
eeprom_delay(ee_addr);
}
/* Terminate the EEPROM access. */
writel(EE_ChipSelect, ee_addr);
writel(0, ee_addr);
return retval;
}
/* MII transceiver control section.
Read and write the MII registers using software-generated serial
MDIO protocol. See the MII specifications or DP83840A data sheet
for details.
The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
met by back-to-back 33Mhz PCI cycles. */
#define mdio_delay(mdio_addr) readl(mdio_addr)
/* Set iff a MII transceiver on any interface requires mdio preamble.
This only set with older tranceivers, so the extra
code size of a per-interface flag is not worthwhile. */
static char mii_preamble_required = 0;
enum mii_reg_bits {
MDIO_ShiftClk=0x0001, MDIO_Data=0x0002, MDIO_EnbOutput=0x0004,
};
#define MDIO_EnbIn (0)
#define MDIO_WRITE0 (MDIO_EnbOutput)
#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput)
/* Generate the preamble required for initial synchronization and
a few older transceivers. */
static void mdio_sync(long mdio_addr)
{
int bits = 32;
/* Establish sync by sending at least 32 logic ones. */
while (--bits >= 0) {
writel(MDIO_WRITE1, mdio_addr);
mdio_delay(mdio_addr);
writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
}
static int mdio_read(struct net_device *dev, int phy_id, unsigned int location)
{
long ioaddr = dev->base_addr;
long mdio_addr = ioaddr + MIICtrl;
int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int i, retval = 0;
if (location >= 32)
return 0xffff;
if (phy_id >= 32) {
if (location < 6)
return readw(ioaddr + PHYMgmt + location*2);
else if (location == 16)
return readw(ioaddr + PHYMgmt + 6*2);
else if (location == 17)
return readw(ioaddr + PHYMgmt + 7*2);
else if (location == 18)
return readw(ioaddr + PHYMgmt + 10*2);
else
return 0;
}
if (mii_preamble_required)
mdio_sync(mdio_addr);
/* Shift the read command bits out. */
for (i = 15; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
writel(dataval, mdio_addr);
mdio_delay(mdio_addr);
writel(dataval | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
/* Read the two transition, 16 data, and wire-idle bits. */
for (i = 19; i > 0; i--) {
writel(MDIO_EnbIn, mdio_addr);
mdio_delay(mdio_addr);
retval = (retval << 1) | ((readl(mdio_addr) & MDIO_Data) ? 1 : 0);
writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
return (retval>>1) & 0xffff;
}
static void mdio_write(struct net_device *dev, int phy_id,
unsigned int location, int value)
{
struct netdev_private *np = (struct netdev_private *)dev->priv;
long ioaddr = dev->base_addr;
long mdio_addr = ioaddr + MIICtrl;
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
int i;
if (location == 4 && phy_id == np->phys[0])
np->advertising = value;
else if (location >= 32)
return;
if (phy_id == 32) {
if (location < 6)
writew(value, ioaddr + PHYMgmt + location*2);
else if (location == 16)
writew(value, ioaddr + PHYMgmt + 6*2);
else if (location == 17)
writew(value, ioaddr + PHYMgmt + 7*2);
return;
}
if (mii_preamble_required)
mdio_sync(mdio_addr);
/* Shift the command bits out. */
for (i = 31; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
writel(dataval, mdio_addr);
mdio_delay(mdio_addr);
writel(dataval | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
/* Clear out extra bits. */
for (i = 2; i > 0; i--) {
writel(MDIO_EnbIn, mdio_addr);
mdio_delay(mdio_addr);
writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
return;
}
static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = (struct netdev_private *)dev->priv;
long ioaddr = dev->base_addr;
/* Some chips may need to be reset. */
MOD_INC_USE_COUNT;
writel(~0, ioaddr + IntrStatus);
/* Note that both request_irq() and init_ring() call kmalloc(), which
break the global kernel lock protecting this routine. */
if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) {
MOD_DEC_USE_COUNT;
return -EAGAIN;
}
if (debug > 1)
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
dev->name, dev->irq);
init_ring(dev);
writel(virt_to_bus(np->rx_ring), ioaddr + RxRingPtr);
writel(virt_to_bus(np->tx_ring), ioaddr + TxRingPtr);
/* Address register must be written as words. */
writel(cpu_to_le32(cpu_to_le32(get_unaligned((u32 *)dev->dev_addr))),
ioaddr + StationAddr);
writel(cpu_to_le16(cpu_to_le16(get_unaligned((u16 *)(dev->dev_addr+4)))),
ioaddr + StationAddr + 4);
/* Set the flow control address, 01:80:c2:00:00:01. */
// writel(0x00c28001, ioaddr + FlowCtrlAddr);
// writel(0x00000100, ioaddr + FlowCtrlAddr + 4);
/* Initialize other registers. */
/* Configure the PCI bus bursts and FIFO thresholds. */
// writel(0x01f8, ioaddr + PCIBusCfg);
writel(0x038, ioaddr + PCIBusCfg);
if (dev->if_port == 0)
dev->if_port = np->default_port;
// np->txrx_config = TxEnable | RxEnable | RxFlowCtrl | 0x00600000;
np->txrx_config = TxEnable | RxEnable | TxThreshold | 0x0f00;
np->mcast_filter[0] = np->mcast_filter[1] = 0;
set_rx_mode(dev);
netif_start_tx_queue(dev);
/* Enable interrupts by setting the interrupt mask. */
writel(IntrRxDone | IntrRxErr | IntrRxEmpty | IntrTxDone | IntrTxEmpty
| StatsMax | RxOverflow | TxUnderrun | IntrPCIErr | NWayDone
| LinkChange,
ioaddr + IntrEnable);
if (debug > 2)
printk(KERN_DEBUG "%s: Done netdev_open(), PHY status: %x %x.\n",
dev->name, (int)readw(ioaddr + PHYMgmt),
(int)readw(ioaddr + PHYMgmt + 2));
/* Set the timer to check for link beat. */
init_timer(&np->timer);
np->timer.expires = jiffies + 3*HZ;
np->timer.data = (unsigned long)dev;
np->timer.function = &netdev_timer; /* timer handler */
add_timer(&np->timer);
return 0;
}
static void check_duplex(struct net_device *dev)
{
struct netdev_private *np = (struct netdev_private *)dev->priv;
long ioaddr = dev->base_addr;
int new_tx_mode = np->txrx_config;
if (np->medialock) {
} else {
int mii_reg5 = mdio_read(dev, np->phys[0], 5);
int negotiated = mii_reg5 & np->advertising;
int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
if (np->duplex_lock || mii_reg5 == 0xffff)
return;
if (duplex)
new_tx_mode |= TxModeFDX;
if (np->full_duplex != duplex) {
np->full_duplex = duplex;
if (debug)
printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d"
" negotiated capability %4.4x.\n", dev->name,
duplex ? "full" : "half", np->phys[0], negotiated);
}
}
if (np->txrx_config != new_tx_mode)
writel(new_tx_mode, ioaddr + RxConfig);
}
static void resetnic(struct net_device *dev)
{
struct netdev_private *np = (struct netdev_private *)dev->priv;
int i;
long ioaddr = dev->base_addr;
struct sk_buff *skb;
/* Perhaps we should reinitialize the hardware here. */
dev->if_port = 0;
/* Stop Tx and Rx */
i=0;
while (i<10)
{
++i;
writel(0, ioaddr + RxConfig);
if (readl(ioaddr + RxConfig)&TxEnable)
continue;
if (readl(ioaddr + RxConfig)&RxEnable)
continue;
break;
}
/* reset the nic */
writel(1, ioaddr + PCIBusCfg);
do
{
if (!(readl(ioaddr + PCIBusCfg)&0x01))
break;
} while (1);
/* Initialize all Rx descriptors. */
for (i = 0; i < RX_RING_SIZE; i++) {
if (np->rx_ring[i].rxbuffer)
np->rx_ring[i].status = cpu_to_le32(DescOwn);
}
/* Refill the Rx ring buffers. */
while (np->lackrxcount) {
skb = dev_alloc_skb(np->rx_buf_sz);
if (skb == NULL)
break; /* Better luck next round. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -