X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fioc3-eth.c;h=ae71ed57c12db04f624f01d4c7c9324576376f06;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=a93cda669010bb710d3f690eb606beef02b80d29;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index a93cda669..ae71ed57c 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -44,19 +44,17 @@ #include #include #include +#include #ifdef CONFIG_SERIAL_8250 -#include -#include -#define IOC3_BAUD (22000000 / (3*16)) -#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#include +#include #endif #include #include #include #include -#include #include #include @@ -463,6 +461,29 @@ static void ioc3_get_eaddr(struct ioc3_private *ip) 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 @@ -477,7 +498,7 @@ static int ioc3_mdio_read(struct net_device *dev, int phy, int reg) 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) @@ -506,7 +527,7 @@ static struct net_device_stats *ioc3_get_stats(struct net_device *dev) 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; @@ -1014,9 +1035,7 @@ static void ioc3_init(struct net_device *dev) (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 */ @@ -1100,6 +1119,7 @@ static inline int ioc3_is_menet(struct pci_dev *pdev) && 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) @@ -1121,17 +1141,15 @@ static inline int ioc3_is_menet(struct pci_dev *pdev) * "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 @@ -1145,24 +1163,29 @@ static inline void ioc3_serial_probe(struct pci_dev *pdev, 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; @@ -1170,11 +1193,39 @@ static int __devinit ioc3_probe(struct pci_dev *pdev, 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) @@ -1237,12 +1288,12 @@ static int __devinit ioc3_probe(struct pci_dev *pdev, 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); @@ -1251,6 +1302,7 @@ static int __devinit ioc3_probe(struct pci_dev *pdev, 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; @@ -1269,6 +1321,12 @@ out_res: 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; } @@ -1282,6 +1340,10 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev) 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[] = { @@ -1299,7 +1361,7 @@ static struct pci_driver ioc3_driver = { 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) @@ -1333,7 +1395,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) 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; @@ -1465,7 +1527,7 @@ static void ioc3_get_drvinfo (struct net_device *dev, 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)); @@ -1491,7 +1553,7 @@ static int ioc3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irq(&ip->ioc3_lock); rc = mii_ethtool_sset(&ip->mii, cmd); spin_unlock_irq(&ip->ioc3_lock); - + return rc; }