Skip to content
Snippets Groups Projects
3c59x.c 101 KiB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
		if (enable)
			max_pkt_size += 4;	/* 802.1Q VLAN tag */

		EL3WINDOW(3);
		iowrite16(max_pkt_size, ioaddr+Wn3_MaxPktSize);
Linus Torvalds's avatar
Linus Torvalds committed

		/* set VlanEtherType to let the hardware checksumming
		   treat tagged frames correctly */
		EL3WINDOW(7);
		iowrite16(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
Linus Torvalds's avatar
Linus Torvalds committed
	} else {
		/* on older cards we have to enable large frames */

		vp->large_frames = dev->mtu > 1500 || enable;

		EL3WINDOW(3);
		mac_ctrl = ioread16(ioaddr+Wn3_MAC_Ctrl);
Linus Torvalds's avatar
Linus Torvalds committed
		if (vp->large_frames)
			mac_ctrl |= 0x40;
		else
			mac_ctrl &= ~0x40;
		iowrite16(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
Linus Torvalds's avatar
Linus Torvalds committed
	}

	EL3WINDOW(old_window);
}
#else

static void set_8021q_mode(struct net_device *dev, int enable)
{
}


#endif

/* 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 PCI I/O cycles, but we insert a delay to avoid
   "overclocking" issues. */
#define mdio_delay() ioread32(mdio_addr)
Linus Torvalds's avatar
Linus Torvalds committed

#define MDIO_SHIFT_CLK	0x01
#define MDIO_DIR_WRITE	0x04
#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
#define MDIO_DATA_READ	0x02
#define MDIO_ENB_IN		0x00

/* Generate the preamble required for initial synchronization and
   a few older transceivers. */
static void mdio_sync(void __iomem *ioaddr, int bits)
Linus Torvalds's avatar
Linus Torvalds committed
{
	void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
Linus Torvalds's avatar
Linus Torvalds committed

	/* Establish sync by sending at least 32 logic ones. */
	while (-- bits >= 0) {
		iowrite16(MDIO_DATA_WRITE1, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
		iowrite16(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
	}
}

static int mdio_read(struct net_device *dev, int phy_id, int location)
{
	int i;
	struct vortex_private *vp = netdev_priv(dev);
	void __iomem *ioaddr = vp->ioaddr;
Linus Torvalds's avatar
Linus Torvalds committed
	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
	unsigned int retval = 0;
	void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
Linus Torvalds's avatar
Linus Torvalds committed

	if (mii_preamble_required)
		mdio_sync(ioaddr, 32);

	/* Shift the read command bits out. */
	for (i = 14; i >= 0; i--) {
		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
		iowrite16(dataval, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
		iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
	}
	/* Read the two transition, 16 data, and wire-idle bits. */
	for (i = 19; i > 0; i--) {
		iowrite16(MDIO_ENB_IN, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
		retval = (retval << 1) | ((ioread16(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
		iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
	}
	return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
}

static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{
	struct vortex_private *vp = netdev_priv(dev);
	void __iomem *ioaddr = vp->ioaddr;
Linus Torvalds's avatar
Linus Torvalds committed
	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
	void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
Linus Torvalds's avatar
Linus Torvalds committed
	int i;

	if (mii_preamble_required)
		mdio_sync(ioaddr, 32);

	/* Shift the command bits out. */
	for (i = 31; i >= 0; i--) {
		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
		iowrite16(dataval, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
		iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
	}
	/* Leave the interface idle. */
	for (i = 1; i >= 0; i--) {
		iowrite16(MDIO_ENB_IN, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
		iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
Linus Torvalds's avatar
Linus Torvalds committed
		mdio_delay();
	}
	return;
}
Linus Torvalds's avatar
Linus Torvalds committed
/* ACPI: Advanced Configuration and Power Interface. */
/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */
static void acpi_set_WOL(struct net_device *dev)
{
	struct vortex_private *vp = netdev_priv(dev);
	void __iomem *ioaddr = vp->ioaddr;
Linus Torvalds's avatar
Linus Torvalds committed

	device_set_wakeup_enable(vp->gendev, vp->enable_wol);

Linus Torvalds's avatar
Linus Torvalds committed
	if (vp->enable_wol) {
		/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
		EL3WINDOW(7);
		iowrite16(2, ioaddr + 0x0c);
Linus Torvalds's avatar
Linus Torvalds committed
		/* The RxFilter must accept the WOL frames. */
		iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
		iowrite16(RxEnable, ioaddr + EL3_CMD);
Linus Torvalds's avatar
Linus Torvalds committed

Steffen Klassert's avatar
Steffen Klassert committed
		if (pci_enable_wake(VORTEX_PCI(vp), PCI_D3hot, 1)) {
			pr_info("%s: WOL not supported.\n", pci_name(VORTEX_PCI(vp)));
Steffen Klassert's avatar
Steffen Klassert committed

			vp->enable_wol = 0;
			return;
		}

		/* Change the power state to D3; RxEnable doesn't take effect. */
		pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
static void __devexit vortex_remove_one(struct pci_dev *pdev)
Linus Torvalds's avatar
Linus Torvalds committed
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct vortex_private *vp;

	if (!dev) {
		pr_err("vortex_remove_one called for Compaq device!\n");
Linus Torvalds's avatar
Linus Torvalds committed
		BUG();
	}

	vp = netdev_priv(dev);

	if (vp->cb_fn_base)
		pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base);

Linus Torvalds's avatar
Linus Torvalds committed
	unregister_netdev(dev);

	if (VORTEX_PCI(vp)) {
		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);	/* Go active */
		if (vp->pm_state_valid)
			pci_restore_state(VORTEX_PCI(vp));
		pci_disable_device(VORTEX_PCI(vp));
	}
	/* Should really use issue_and_wait() here */
	iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
	     vp->ioaddr + EL3_CMD);

	pci_iounmap(VORTEX_PCI(vp), vp->ioaddr);
Linus Torvalds's avatar
Linus Torvalds committed

	pci_free_consistent(pdev,
						sizeof(struct boom_rx_desc) * RX_RING_SIZE
							+ sizeof(struct boom_tx_desc) * TX_RING_SIZE,
						vp->rx_ring,
						vp->rx_ring_dma);
	if (vp->must_free_region)
		release_region(dev->base_addr, vp->io_size);
	free_netdev(dev);
}


static struct pci_driver vortex_driver = {
	.name		= "3c59x",
	.probe		= vortex_init_one,
	.remove		= __devexit_p(vortex_remove_one),
	.id_table	= vortex_pci_tbl,
	.driver.pm	= VORTEX_PM_OPS,
Linus Torvalds's avatar
Linus Torvalds committed
};


static int vortex_have_pci;
static int vortex_have_eisa;


static int __init vortex_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
{
	int pci_rc, eisa_rc;

	pci_rc = pci_register_driver(&vortex_driver);
Linus Torvalds's avatar
Linus Torvalds committed
	eisa_rc = vortex_eisa_init();

	if (pci_rc == 0)
		vortex_have_pci = 1;
	if (eisa_rc > 0)
		vortex_have_eisa = 1;

	return (vortex_have_pci + vortex_have_eisa) ? 0 : -ENODEV;
}


static void __exit vortex_eisa_cleanup(void)
Linus Torvalds's avatar
Linus Torvalds committed
{
	struct vortex_private *vp;
	void __iomem *ioaddr;
Linus Torvalds's avatar
Linus Torvalds committed

#ifdef CONFIG_EISA
	/* Take care of the EISA devices */
	eisa_driver_unregister(&vortex_eisa_driver);
Linus Torvalds's avatar
Linus Torvalds committed
#endif
Linus Torvalds's avatar
Linus Torvalds committed
	if (compaq_net_device) {
		vp = netdev_priv(compaq_net_device);
		ioaddr = ioport_map(compaq_net_device->base_addr,
		                    VORTEX_TOTAL_SIZE);
Linus Torvalds's avatar
Linus Torvalds committed

		unregister_netdev(compaq_net_device);
		iowrite16(TotalReset, ioaddr + EL3_CMD);
		release_region(compaq_net_device->base_addr,
		               VORTEX_TOTAL_SIZE);
Linus Torvalds's avatar
Linus Torvalds committed

		free_netdev(compaq_net_device);
static void __exit vortex_cleanup(void)
Linus Torvalds's avatar
Linus Torvalds committed
{
	if (vortex_have_pci)
		pci_unregister_driver(&vortex_driver);
Linus Torvalds's avatar
Linus Torvalds committed
	if (vortex_have_eisa)
		vortex_eisa_cleanup();
Linus Torvalds's avatar
Linus Torvalds committed
}


module_init(vortex_init);
module_exit(vortex_cleanup);