#define IOC3_NAME "ioc3-eth"
#define IOC3_VERSION "2.6.3-3"
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <linux/dma-mapping.h>
#ifdef CONFIG_SERIAL_8250
-#include <linux/serial.h>
-#include <asm/serial.h>
-#define IOC3_BAUD (22000000 / (3*16))
-#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
#endif
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/skbuff.h>
-#include <linux/dp83840.h>
#include <net/ip.h>
#include <asm/byteorder.h>
static inline unsigned long ioc3_map(void *ptr, unsigned long vdev)
{
#ifdef CONFIG_SGI_IP27
- vdev <<= 58; /* Shift to PCI64_ATTR_VIRTUAL */
+ vdev <<= 57; /* Shift to PCI64_ATTR_VIRTUAL */
return vdev | (0xaUL << PCI64_ATTR_TARG_SHFT) | PCI64_ATTR_PREF |
((unsigned long)ptr & TO_PHYS_MASK);
printk(".\n");
}
+static void __ioc3_set_mac_address(struct net_device *dev)
+{
+ struct ioc3_private *ip = netdev_priv(dev);
+ struct ioc3 *ioc3 = ip->regs;
+
+ ioc3_w_emar_h((dev->dev_addr[5] << 8) | dev->dev_addr[4]);
+ ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
+ (dev->dev_addr[1] << 8) | dev->dev_addr[0]);
+}
+
+static int ioc3_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct ioc3_private *ip = netdev_priv(dev);
+ struct sockaddr *sa = addr;
+
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+ spin_lock_irq(&ip->ioc3_lock);
+ __ioc3_set_mac_address(dev);
+ spin_unlock_irq(&ip->ioc3_lock);
+
+ return 0;
+}
/*
* Caller must hold the ioc3_lock ever for MII readers. This is also
ioc3_w_micr((phy << MICR_PHYADDR_SHIFT) | reg | MICR_READTRIG);
while (ioc3_r_micr() & MICR_BUSY);
- return ioc3_r_micr() & MIDR_DATA_MASK;
+ return ioc3_r_midr_r() & MIDR_DATA_MASK;
}
static void ioc3_mdio_write(struct net_device *dev, int phy, int reg, int data)
static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len)
{
- struct ethhdr *eh = skb->mac.ethernet;
+ struct ethhdr *eh = eth_hdr(skb);
uint32_t csum, ehsum;
unsigned int proto;
struct iphdr *ih;
(void) ioc3_r_etcdc(); /* Clear on read */
ioc3_w_ercsr(15); /* RX low watermark */
ioc3_w_ertr(0); /* Interrupt immediately */
- ioc3_w_emar_h((dev->dev_addr[5] << 8) | dev->dev_addr[4]);
- ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
- (dev->dev_addr[1] << 8) | dev->dev_addr[0]);
+ __ioc3_set_mac_address(dev);
ioc3_w_ehar_h(ip->ehar_h);
ioc3_w_ehar_l(ip->ehar_l);
ioc3_w_ersr(42); /* XXX should be random */
{
struct ioc3_private *ip = netdev_priv(dev);
- if (request_irq(dev->irq, ioc3_interrupt, SA_SHIRQ, ioc3_str, dev)) {
+ if (request_irq(dev->irq, ioc3_interrupt, IRQF_SHARED, ioc3_str, dev)) {
printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq);
return -EAGAIN;
&& dev->device == PCI_DEVICE_ID_SGI_IOC3;
}
+#ifdef CONFIG_SERIAL_8250
/*
* Note about serial ports and consoles:
* For console output, everyone uses the IOC3 UARTA (offset 0x178)
* "device" routine referred to in this console structure
* (ip27prom_console_dev).
*
- * Also look in ip27-pci.c:pci_fixuop_ioc3() for some comments on working
+ * Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working
* around ioc3 oddities in this respect.
*
* The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
- * (IOC3_BAUD = (22000000 / (3*16)))
*/
-static inline void ioc3_serial_probe(struct pci_dev *pdev,
- struct ioc3 *ioc3)
+static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
{
- struct serial_struct req;
+ struct uart_port port;
/*
* We need to recognice and treat the fourth MENET serial as it
if (ioc3_is_menet(pdev) && PCI_SLOT(pdev->devfn) == 3)
return;
- /* Register to interrupt zero because we share the interrupt with
- the serial driver which we don't properly support yet. */
- memset(&req, 0, sizeof(req));
- req.irq = 0;
- req.flags = IOC3_COM_FLAGS;
- req.io_type = SERIAL_IO_MEM;
- req.iomem_reg_shift = 0;
- req.baud_base = IOC3_BAUD;
-
- req.iomem_base = (unsigned char *) &ioc3->sregs.uarta;
- register_serial(&req);
-
- req.iomem_base = (unsigned char *) &ioc3->sregs.uartb;
- register_serial(&req);
+ /*
+ * Register to interrupt zero because we share the interrupt with
+ * the serial driver which we don't properly support yet.
+ *
+ * Can't use UPF_IOREMAP as the whole of IOC3 resources have already
+ * been registered.
+ */
+ memset(&port, 0, sizeof(port));
+ port.irq = 0;
+ port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ port.iotype = UPIO_MEM;
+ port.regshift = 0;
+ port.uartclk = 22000000 / 3;
+
+ port.membase = (unsigned char *) &ioc3->sregs.uarta;
+ serial8250_register_port(&port);
+
+ port.membase = (unsigned char *) &ioc3->sregs.uartb;
+ serial8250_register_port(&port);
}
+#endif
-static int __devinit ioc3_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned int sw_physid1, sw_physid2;
struct net_device *dev = NULL;
struct ioc3 *ioc3;
unsigned long ioc3_base, ioc3_size;
u32 vendor, model, rev;
- int err;
+ int err, pci_using_dac;
+
+ /* Configure DMA attributes. */
+ err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ if (!err) {
+ pci_using_dac = 1;
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR "%s: Unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto out;
+ }
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR "%s: No usable DMA configuration, "
+ "aborting.\n", pci_name(pdev));
+ goto out;
+ }
+ pci_using_dac = 0;
+ }
+
+ if (pci_enable_device(pdev))
+ return -ENODEV;
dev = alloc_etherdev(sizeof(struct ioc3_private));
- if (!dev)
- return -ENOMEM;
+ if (!dev) {
+ err = -ENOMEM;
+ goto out_disable;
+ }
+
+ if (pci_using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
err = pci_request_regions(pdev, "ioc3");
if (err)
dev->get_stats = ioc3_get_stats;
dev->do_ioctl = ioc3_ioctl;
dev->set_multicast_list = ioc3_set_multicast_list;
+ dev->set_mac_address = ioc3_set_mac_address;
dev->ethtool_ops = &ioc3_ethtool_ops;
#ifdef CONFIG_SGI_IOC3_ETH_HW_TX_CSUM
dev->features = NETIF_F_IP_CSUM;
#endif
- ioc3_setup_duplex(ip);
sw_physid1 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID1);
sw_physid2 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID2);
goto out_stop;
mii_check_media(&ip->mii, 1, 1);
+ ioc3_setup_duplex(ip);
vendor = (sw_physid1 << 12) | (sw_physid2 >> 4);
model = (sw_physid2 >> 4) & 0x3f;
pci_release_regions(pdev);
out_free:
free_netdev(dev);
+out_disable:
+ /*
+ * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+ * such a weird device ...
+ */
+out:
return err;
}
iounmap(ioc3);
pci_release_regions(pdev);
free_netdev(dev);
+ /*
+ * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+ * such a weird device ...
+ */
}
static struct pci_device_id ioc3_pci_tbl[] = {
static int __init ioc3_init_module(void)
{
- return pci_module_init(&ioc3_driver);
+ return pci_register_driver(&ioc3_driver);
}
static void __exit ioc3_cleanup_module(void)
uint32_t csum, ehsum;
uint16_t *eh;
- /* The MAC header. skb->mac.ethernet seem the logic approach
+ /* The MAC header. skb->mac seem the logic approach
to find the MAC header - except it's a NULL pointer ... */
eh = (uint16_t *) skb->data;
struct ethtool_drvinfo *info)
{
struct ioc3_private *ip = netdev_priv(dev);
-
+
strcpy (info->driver, IOC3_NAME);
strcpy (info->version, IOC3_VERSION);
strcpy (info->bus_info, pci_name(ip->pdev));
spin_lock_irq(&ip->ioc3_lock);
rc = mii_ethtool_sset(&ip->mii, cmd);
spin_unlock_irq(&ip->ioc3_lock);
-
+
return rc;
}
static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
struct ioc3_private *ip = netdev_priv(dev);
int rc;
spin_lock_irq(&ip->ioc3_lock);
- rc = generic_mii_ioctl(&ip->mii, data, cmd, NULL);
+ rc = generic_mii_ioctl(&ip->mii, if_mii(rq), cmd, NULL);
spin_unlock_irq(&ip->ioc3_lock);
return rc;