See the file COPYING in this distribution for more information.
Contributors:
-
+
Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
PCI suspend/resume - Felipe Damasio <felipewd@terra.com.br>
LinkChg interrupt - Felipe Damasio <felipewd@terra.com.br>
-
+
TODO:
* Test Tx checksumming thoroughly
* Implement dev->tx_timeout
#define DRV_RELDATE "Mar 22, 2004"
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#ifdef CONFIG_NET_POLL_CONTROLLER
static void cp_poll_controller(struct net_device *dev);
#endif
-static int cp_get_eeprom_len(struct net_device *dev);
-static int cp_get_eeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data);
-static int cp_set_eeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data);
static struct pci_device_id cp_pci_tbl[] = {
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
static inline void cp_set_rxbufsize (struct cp_private *cp)
{
unsigned int mtu = cp->dev->mtu;
-
+
if (mtu > ETH_DATA_LEN)
/* MTU + ethernet header + FCS + optional VLAN tag */
cp->rx_buf_sz = mtu + ETH_HLEN + 8;
static inline unsigned int cp_rx_csum_ok (u32 status)
{
unsigned int protocol = (status >> 16) & 0x3;
-
+
if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
return 1;
else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
cpw8(Config3, PARMEnable);
cp->wol_enabled = 0;
- cpw8(Config5, cpr8(Config5) & PMEStatus);
+ cpw8(Config5, cpr8(Config5) & PMEStatus);
cpw32_f(HiTxRingAddr, 0);
cpw32_f(HiTxRingAddr + 4, 0);
cp_init_hw(cp);
- rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
+ rc = request_irq(dev->irq, cp_interrupt, SA_SHIRQ, dev->name, dev);
if (rc)
goto err_out_hw;
WAKE_MCAST | WAKE_UCAST;
/* We don't need to go on if WOL is disabled */
if (!cp->wol_enabled) return;
-
+
options = cpr8 (Config3);
if (options & LinkUp) wol->wolopts |= WAKE_PHY;
if (options & MagicPacket) wol->wolopts |= WAKE_MAGIC;
.get_strings = cp_get_strings,
.get_ethtool_stats = cp_get_ethtool_stats,
.get_perm_addr = ethtool_op_get_perm_addr,
- .get_eeprom_len = cp_get_eeprom_len,
- .get_eeprom = cp_get_eeprom,
- .set_eeprom = cp_set_eeprom,
};
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
#define eeprom_delay() readl(ee_addr)
/* The EEPROM commands include the alway-set leading bit. */
-#define EE_EXTEND_CMD (4)
#define EE_WRITE_CMD (5)
#define EE_READ_CMD (6)
#define EE_ERASE_CMD (7)
-#define EE_EWDS_ADDR (0)
-#define EE_WRAL_ADDR (1)
-#define EE_ERAL_ADDR (2)
-#define EE_EWEN_ADDR (3)
-
-#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139
-
-static void eeprom_cmd_start(void __iomem *ee_addr)
+static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
{
+ int i;
+ unsigned retval = 0;
+ void __iomem *ee_addr = ioaddr + Cfg9346;
+ int read_cmd = location | (EE_READ_CMD << addr_len);
+
writeb (EE_ENB & ~EE_CS, ee_addr);
writeb (EE_ENB, ee_addr);
eeprom_delay ();
-}
-
-static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len)
-{
- int i;
- /* Shift the command bits out. */
- for (i = cmd_len - 1; i >= 0; i--) {
- int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
writeb (EE_ENB | dataval, ee_addr);
eeprom_delay ();
writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
}
writeb (EE_ENB, ee_addr);
eeprom_delay ();
-}
-
-static void eeprom_cmd_end(void __iomem *ee_addr)
-{
- writeb (~EE_CS, ee_addr);
- eeprom_delay ();
-}
-
-static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd,
- int addr_len)
-{
- int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2));
-
- eeprom_cmd_start(ee_addr);
- eeprom_cmd(ee_addr, cmd, 3 + addr_len);
- eeprom_cmd_end(ee_addr);
-}
-
-static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len)
-{
- int i;
- u16 retval = 0;
- void __iomem *ee_addr = ioaddr + Cfg9346;
- int read_cmd = location | (EE_READ_CMD << addr_len);
-
- eeprom_cmd_start(ee_addr);
- eeprom_cmd(ee_addr, read_cmd, 3 + addr_len);
for (i = 16; i > 0; i--) {
writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay ();
}
- eeprom_cmd_end(ee_addr);
+ /* Terminate the EEPROM access. */
+ writeb (~EE_CS, ee_addr);
+ eeprom_delay ();
return retval;
}
-static void write_eeprom(void __iomem *ioaddr, int location, u16 val,
- int addr_len)
-{
- int i;
- void __iomem *ee_addr = ioaddr + Cfg9346;
- int write_cmd = location | (EE_WRITE_CMD << addr_len);
-
- eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len);
-
- eeprom_cmd_start(ee_addr);
- eeprom_cmd(ee_addr, write_cmd, 3 + addr_len);
- eeprom_cmd(ee_addr, val, 16);
- eeprom_cmd_end(ee_addr);
-
- eeprom_cmd_start(ee_addr);
- for (i = 0; i < 20000; i++)
- if (readb(ee_addr) & EE_DATA_READ)
- break;
- eeprom_cmd_end(ee_addr);
-
- eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len);
-}
-
-static int cp_get_eeprom_len(struct net_device *dev)
-{
- struct cp_private *cp = netdev_priv(dev);
- int size;
-
- spin_lock_irq(&cp->lock);
- size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128;
- spin_unlock_irq(&cp->lock);
-
- return size;
-}
-
-static int cp_get_eeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- struct cp_private *cp = netdev_priv(dev);
- unsigned int addr_len;
- u16 val;
- u32 offset = eeprom->offset >> 1;
- u32 len = eeprom->len;
- u32 i = 0;
-
- eeprom->magic = CP_EEPROM_MAGIC;
-
- spin_lock_irq(&cp->lock);
-
- addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
-
- if (eeprom->offset & 1) {
- val = read_eeprom(cp->regs, offset, addr_len);
- data[i++] = (u8)(val >> 8);
- offset++;
- }
-
- while (i < len - 1) {
- val = read_eeprom(cp->regs, offset, addr_len);
- data[i++] = (u8)val;
- data[i++] = (u8)(val >> 8);
- offset++;
- }
-
- if (i < len) {
- val = read_eeprom(cp->regs, offset, addr_len);
- data[i] = (u8)val;
- }
-
- spin_unlock_irq(&cp->lock);
- return 0;
-}
-
-static int cp_set_eeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- struct cp_private *cp = netdev_priv(dev);
- unsigned int addr_len;
- u16 val;
- u32 offset = eeprom->offset >> 1;
- u32 len = eeprom->len;
- u32 i = 0;
-
- if (eeprom->magic != CP_EEPROM_MAGIC)
- return -EINVAL;
-
- spin_lock_irq(&cp->lock);
-
- addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
-
- if (eeprom->offset & 1) {
- val = read_eeprom(cp->regs, offset, addr_len) & 0xff;
- val |= (u16)data[i++] << 8;
- write_eeprom(cp->regs, offset, val, addr_len);
- offset++;
- }
-
- while (i < len - 1) {
- val = (u16)data[i++];
- val |= (u16)data[i++] << 8;
- write_eeprom(cp->regs, offset, val, addr_len);
- offset++;
- }
-
- if (i < len) {
- val = read_eeprom(cp->regs, offset, addr_len) & 0xff00;
- val |= (u16)data[i];
- write_eeprom(cp->regs, offset, val, addr_len);
- }
-
- spin_unlock_irq(&cp->lock);
- return 0;
-}
-
/* Put the board into D3cold state and wait for WakeUp signal */
static void cp_set_d3_state (struct cp_private *cp)
{
struct cp_private *cp;
int rc;
void __iomem *regs;
- resource_size_t pciaddr;
+ long pciaddr;
unsigned int addr_len, i, pci_using_dac;
u8 pci_rev;
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) {
- dev_err(&pdev->dev,
- "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
- pdev->vendor, pdev->device, pci_rev);
- dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
+ printk(KERN_ERR PFX "pci dev %s (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
+ pci_name(pdev), pdev->vendor, pdev->device, pci_rev);
+ printk(KERN_ERR PFX "Try the \"8139too\" driver instead.\n");
return -ENODEV;
}
pciaddr = pci_resource_start(pdev, 1);
if (!pciaddr) {
rc = -EIO;
- dev_err(&pdev->dev, "no MMIO resource\n");
+ printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n",
+ pci_name(pdev));
goto err_out_res;
}
if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) {
rc = -EIO;
- dev_err(&pdev->dev, "MMIO resource (%llx) too small\n",
- (unsigned long long)pci_resource_len(pdev, 1));
+ printk(KERN_ERR PFX "MMIO resource (%lx) too small on pci dev %s\n",
+ pci_resource_len(pdev, 1), pci_name(pdev));
goto err_out_res;
}
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- dev_err(&pdev->dev,
- "No usable DMA configuration, aborting.\n");
+ printk(KERN_ERR PFX "No usable DMA configuration, "
+ "aborting.\n");
goto err_out_res;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- dev_err(&pdev->dev,
- "No usable consistent DMA configuration, "
- "aborting.\n");
+ printk(KERN_ERR PFX "No usable consistent DMA configuration, "
+ "aborting.\n");
goto err_out_res;
}
}
regs = ioremap(pciaddr, CP_REGS_SIZE);
if (!regs) {
rc = -EIO;
- dev_err(&pdev->dev, "Cannot map PCI MMIO (%Lx@%Lx)\n",
- (unsigned long long)pci_resource_len(pdev, 1),
- (unsigned long long)pciaddr);
+ printk(KERN_ERR PFX "Cannot map PCI MMIO (%lx@%lx) on pci dev %s\n",
+ pci_resource_len(pdev, 1), pciaddr, pci_name(pdev));
goto err_out_res;
}
dev->base_addr = (unsigned long) regs;
/* enable busmastering and memory-write-invalidate */
pci_set_master(pdev);
- if (cp->wol_enabled)
- cp_set_d3_state (cp);
+ if (cp->wol_enabled) cp_set_d3_state (cp);
return 0;
BUG_ON(!dev);
unregister_netdev(dev);
iounmap(cp->regs);
- if (cp->wol_enabled)
- pci_set_power_state (pdev, PCI_D0);
+ if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
pci_release_regions(pdev);
pci_clear_mwi(pdev);
pci_disable_device(pdev);
mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
spin_unlock_irqrestore (&cp->lock, flags);
-
+
return 0;
}
#endif /* CONFIG_PM */