From 3215df6a8e35fe6fc7c86ee0df2863c669a8e068 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 19 Jul 2011 01:15:12 -0700 Subject: mipsnet: Move the MIPS driver Move the MIPS drivers into drivers/net/ethernet/ and make the necessary Kconfig and Makefile changes. Signed-off-by: Jeff Kirsher --- drivers/net/Kconfig | 8 - drivers/net/Makefile | 1 - drivers/net/ethernet/Kconfig | 9 ++ drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/mipsnet.c | 345 +++++++++++++++++++++++++++++++++++++++++ drivers/net/mipsnet.c | 345 ----------------------------------------- 6 files changed, 355 insertions(+), 354 deletions(-) create mode 100644 drivers/net/ethernet/mipsnet.c delete mode 100644 drivers/net/mipsnet.c (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d9b3cb5aad3..d38cad2c6b7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -237,14 +237,6 @@ config MACB source "drivers/net/arm/Kconfig" -config MIPS_SIM_NET - tristate "MIPS simulator Network device" - depends on MIPS_SIM - help - The MIPSNET device is a simple Ethernet network device which is - emulated by the MIPS Simulator. - If you are not using a MIPSsim or are unsure, say N. - config SH_ETH tristate "Renesas SuperH Ethernet support" depends on SUPERH && \ diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6c17cb6c35a..389c268bc8b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -54,7 +54,6 @@ obj-$(CONFIG_MACVLAN) += macvlan.o obj-$(CONFIG_MACVTAP) += macvtap.o obj-$(CONFIG_DEFXX) += defxx.o obj-$(CONFIG_EQUALIZER) += eql.o -obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o obj-$(CONFIG_TUN) += tun.o obj-$(CONFIG_VETH) += veth.o obj-$(CONFIG_NET_NETX) += netx-eth.o diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index dae10a3eca7..f1509a59810 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -55,6 +55,15 @@ config KORINA source "drivers/net/ethernet/marvell/Kconfig" source "drivers/net/ethernet/mellanox/Kconfig" source "drivers/net/ethernet/micrel/Kconfig" + +config MIPS_SIM_NET + tristate "MIPS simulator Network device" + depends on MIPS_SIM + ---help--- + The MIPSNET device is a simple Ethernet network device which is + emulated by the MIPS Simulator. + If you are not using a MIPSsim or are unsure, say N. + source "drivers/net/ethernet/myricom/Kconfig" source "drivers/net/ethernet/natsemi/Kconfig" source "drivers/net/ethernet/8390/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index ddf097df923..50fc50a4929 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_KORINA) += korina.o obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/ obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/ obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/ +obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/ obj-$(CONFIG_NET_VENDOR_NATSEMI) += natsemi/ obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/ diff --git a/drivers/net/ethernet/mipsnet.c b/drivers/net/ethernet/mipsnet.c new file mode 100644 index 00000000000..004e64ab1f9 --- /dev/null +++ b/drivers/net/ethernet/mipsnet.c @@ -0,0 +1,345 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIPSNET_VERSION "2007-11-17" + +/* + * Net status/control block as seen by sw in the core. + */ +struct mipsnet_regs { + /* + * Device info for probing, reads as MIPSNET%d where %d is some + * form of version. + */ + u64 devId; /*0x00 */ + + /* + * read only busy flag. + * Set and cleared by the Net Device to indicate that an rx or a tx + * is in progress. + */ + u32 busy; /*0x08 */ + + /* + * Set by the Net Device. + * The device will set it once data has been received. + * The value is the number of bytes that should be read from + * rxDataBuffer. The value will decrease till 0 until all the data + * from rxDataBuffer has been read. + */ + u32 rxDataCount; /*0x0c */ +#define MIPSNET_MAX_RXTX_DATACOUNT (1 << 16) + + /* + * Settable from the MIPS core, cleared by the Net Device. + * The core should set the number of bytes it wants to send, + * then it should write those bytes of data to txDataBuffer. + * The device will clear txDataCount has been processed (not + * necessarily sent). + */ + u32 txDataCount; /*0x10 */ + + /* + * Interrupt control + * + * Used to clear the interrupted generated by this dev. + * Write a 1 to clear the interrupt. (except bit31). + * + * Bit0 is set if it was a tx-done interrupt. + * Bit1 is set when new rx-data is available. + * Until this bit is cleared there will be no other RXs. + * + * Bit31 is used for testing, it clears after a read. + * Writing 1 to this bit will cause an interrupt to be generated. + * To clear the test interrupt, write 0 to this register. + */ + u32 interruptControl; /*0x14 */ +#define MIPSNET_INTCTL_TXDONE (1u << 0) +#define MIPSNET_INTCTL_RXDONE (1u << 1) +#define MIPSNET_INTCTL_TESTBIT (1u << 31) + + /* + * Readonly core-specific interrupt info for the device to signal + * the core. The meaning of the contents of this field might change. + */ + /* XXX: the whole memIntf interrupt scheme is messy: the device + * should have no control what so ever of what VPE/register set is + * being used. + * The MemIntf should only expose interrupt lines, and something in + * the config should be responsible for the line<->core/vpe bindings. + */ + u32 interruptInfo; /*0x18 */ + + /* + * This is where the received data is read out. + * There is more data to read until rxDataReady is 0. + * Only 1 byte at this regs offset is used. + */ + u32 rxDataBuffer; /*0x1c */ + + /* + * This is where the data to transmit is written. + * Data should be written for the amount specified in the + * txDataCount register. + * Only 1 byte at this regs offset is used. + */ + u32 txDataBuffer; /*0x20 */ +}; + +#define regaddr(dev, field) \ + (dev->base_addr + offsetof(struct mipsnet_regs, field)) + +static char mipsnet_string[] = "mipsnet"; + +/* + * Copy data from the MIPSNET rx data port + */ +static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, + int len) +{ + for (; len > 0; len--, kdata++) + *kdata = inb(regaddr(dev, rxDataBuffer)); + + return inl(regaddr(dev, rxDataCount)); +} + +static inline void mipsnet_put_todevice(struct net_device *dev, + struct sk_buff *skb) +{ + int count_to_go = skb->len; + char *buf_ptr = skb->data; + + outl(skb->len, regaddr(dev, txDataCount)); + + for (; count_to_go; buf_ptr++, count_to_go--) + outb(*buf_ptr, regaddr(dev, txDataBuffer)); + + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + dev_kfree_skb(skb); +} + +static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) +{ + /* + * Only one packet at a time. Once TXDONE interrupt is serviced, the + * queue will be restarted. + */ + netif_stop_queue(dev); + mipsnet_put_todevice(dev, skb); + + return NETDEV_TX_OK; +} + +static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t len) +{ + struct sk_buff *skb; + + if (!len) + return len; + + skb = dev_alloc_skb(len + NET_IP_ALIGN); + if (!skb) { + dev->stats.rx_dropped++; + return -ENOMEM; + } + + skb_reserve(skb, NET_IP_ALIGN); + if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len)) + return -EFAULT; + + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + + netif_rx(skb); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; + + return len; +} + +static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + u32 int_flags; + irqreturn_t ret = IRQ_NONE; + + if (irq != dev->irq) + goto out_badirq; + + /* TESTBIT is cleared on read. */ + int_flags = inl(regaddr(dev, interruptControl)); + if (int_flags & MIPSNET_INTCTL_TESTBIT) { + /* TESTBIT takes effect after a write with 0. */ + outl(0, regaddr(dev, interruptControl)); + ret = IRQ_HANDLED; + } else if (int_flags & MIPSNET_INTCTL_TXDONE) { + /* Only one packet at a time, we are done. */ + dev->stats.tx_packets++; + netif_wake_queue(dev); + outl(MIPSNET_INTCTL_TXDONE, + regaddr(dev, interruptControl)); + ret = IRQ_HANDLED; + } else if (int_flags & MIPSNET_INTCTL_RXDONE) { + mipsnet_get_fromdev(dev, inl(regaddr(dev, rxDataCount))); + outl(MIPSNET_INTCTL_RXDONE, regaddr(dev, interruptControl)); + ret = IRQ_HANDLED; + } + return ret; + +out_badirq: + printk(KERN_INFO "%s: %s(): irq %d for unknown device\n", + dev->name, __func__, irq); + return ret; +} + +static int mipsnet_open(struct net_device *dev) +{ + int err; + + err = request_irq(dev->irq, mipsnet_interrupt, + IRQF_SHARED, dev->name, (void *) dev); + if (err) { + release_region(dev->base_addr, sizeof(struct mipsnet_regs)); + return err; + } + + netif_start_queue(dev); + + /* test interrupt handler */ + outl(MIPSNET_INTCTL_TESTBIT, regaddr(dev, interruptControl)); + + return 0; +} + +static int mipsnet_close(struct net_device *dev) +{ + netif_stop_queue(dev); + free_irq(dev->irq, dev); + return 0; +} + +static void mipsnet_set_mclist(struct net_device *dev) +{ +} + +static const struct net_device_ops mipsnet_netdev_ops = { + .ndo_open = mipsnet_open, + .ndo_stop = mipsnet_close, + .ndo_start_xmit = mipsnet_xmit, + .ndo_set_multicast_list = mipsnet_set_mclist, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + +static int __devinit mipsnet_probe(struct platform_device *dev) +{ + struct net_device *netdev; + int err; + + netdev = alloc_etherdev(0); + if (!netdev) { + err = -ENOMEM; + goto out; + } + + platform_set_drvdata(dev, netdev); + + netdev->netdev_ops = &mipsnet_netdev_ops; + + /* + * TODO: probe for these or load them from PARAM + */ + netdev->base_addr = 0x4200; + netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + + inl(regaddr(netdev, interruptInfo)); + + /* Get the io region now, get irq on open() */ + if (!request_region(netdev->base_addr, sizeof(struct mipsnet_regs), + "mipsnet")) { + err = -EBUSY; + goto out_free_netdev; + } + + /* + * Lacking any better mechanism to allocate a MAC address we use a + * random one ... + */ + random_ether_addr(netdev->dev_addr); + + err = register_netdev(netdev); + if (err) { + printk(KERN_ERR "MIPSNet: failed to register netdev.\n"); + goto out_free_region; + } + + return 0; + +out_free_region: + release_region(netdev->base_addr, sizeof(struct mipsnet_regs)); + +out_free_netdev: + free_netdev(netdev); + +out: + return err; +} + +static int __devexit mipsnet_device_remove(struct platform_device *device) +{ + struct net_device *dev = platform_get_drvdata(device); + + unregister_netdev(dev); + release_region(dev->base_addr, sizeof(struct mipsnet_regs)); + free_netdev(dev); + platform_set_drvdata(device, NULL); + + return 0; +} + +static struct platform_driver mipsnet_driver = { + .driver = { + .name = mipsnet_string, + .owner = THIS_MODULE, + }, + .probe = mipsnet_probe, + .remove = __devexit_p(mipsnet_device_remove), +}; + +static int __init mipsnet_init_module(void) +{ + int err; + + printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. " + "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION); + + err = platform_driver_register(&mipsnet_driver); + if (err) + printk(KERN_ERR "Driver registration failed\n"); + + return err; +} + +static void __exit mipsnet_exit_module(void) +{ + platform_driver_unregister(&mipsnet_driver); +} + +module_init(mipsnet_init_module); +module_exit(mipsnet_exit_module); diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c deleted file mode 100644 index 004e64ab1f9..00000000000 --- a/drivers/net/mipsnet.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MIPSNET_VERSION "2007-11-17" - -/* - * Net status/control block as seen by sw in the core. - */ -struct mipsnet_regs { - /* - * Device info for probing, reads as MIPSNET%d where %d is some - * form of version. - */ - u64 devId; /*0x00 */ - - /* - * read only busy flag. - * Set and cleared by the Net Device to indicate that an rx or a tx - * is in progress. - */ - u32 busy; /*0x08 */ - - /* - * Set by the Net Device. - * The device will set it once data has been received. - * The value is the number of bytes that should be read from - * rxDataBuffer. The value will decrease till 0 until all the data - * from rxDataBuffer has been read. - */ - u32 rxDataCount; /*0x0c */ -#define MIPSNET_MAX_RXTX_DATACOUNT (1 << 16) - - /* - * Settable from the MIPS core, cleared by the Net Device. - * The core should set the number of bytes it wants to send, - * then it should write those bytes of data to txDataBuffer. - * The device will clear txDataCount has been processed (not - * necessarily sent). - */ - u32 txDataCount; /*0x10 */ - - /* - * Interrupt control - * - * Used to clear the interrupted generated by this dev. - * Write a 1 to clear the interrupt. (except bit31). - * - * Bit0 is set if it was a tx-done interrupt. - * Bit1 is set when new rx-data is available. - * Until this bit is cleared there will be no other RXs. - * - * Bit31 is used for testing, it clears after a read. - * Writing 1 to this bit will cause an interrupt to be generated. - * To clear the test interrupt, write 0 to this register. - */ - u32 interruptControl; /*0x14 */ -#define MIPSNET_INTCTL_TXDONE (1u << 0) -#define MIPSNET_INTCTL_RXDONE (1u << 1) -#define MIPSNET_INTCTL_TESTBIT (1u << 31) - - /* - * Readonly core-specific interrupt info for the device to signal - * the core. The meaning of the contents of this field might change. - */ - /* XXX: the whole memIntf interrupt scheme is messy: the device - * should have no control what so ever of what VPE/register set is - * being used. - * The MemIntf should only expose interrupt lines, and something in - * the config should be responsible for the line<->core/vpe bindings. - */ - u32 interruptInfo; /*0x18 */ - - /* - * This is where the received data is read out. - * There is more data to read until rxDataReady is 0. - * Only 1 byte at this regs offset is used. - */ - u32 rxDataBuffer; /*0x1c */ - - /* - * This is where the data to transmit is written. - * Data should be written for the amount specified in the - * txDataCount register. - * Only 1 byte at this regs offset is used. - */ - u32 txDataBuffer; /*0x20 */ -}; - -#define regaddr(dev, field) \ - (dev->base_addr + offsetof(struct mipsnet_regs, field)) - -static char mipsnet_string[] = "mipsnet"; - -/* - * Copy data from the MIPSNET rx data port - */ -static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, - int len) -{ - for (; len > 0; len--, kdata++) - *kdata = inb(regaddr(dev, rxDataBuffer)); - - return inl(regaddr(dev, rxDataCount)); -} - -static inline void mipsnet_put_todevice(struct net_device *dev, - struct sk_buff *skb) -{ - int count_to_go = skb->len; - char *buf_ptr = skb->data; - - outl(skb->len, regaddr(dev, txDataCount)); - - for (; count_to_go; buf_ptr++, count_to_go--) - outb(*buf_ptr, regaddr(dev, txDataBuffer)); - - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - - dev_kfree_skb(skb); -} - -static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) -{ - /* - * Only one packet at a time. Once TXDONE interrupt is serviced, the - * queue will be restarted. - */ - netif_stop_queue(dev); - mipsnet_put_todevice(dev, skb); - - return NETDEV_TX_OK; -} - -static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t len) -{ - struct sk_buff *skb; - - if (!len) - return len; - - skb = dev_alloc_skb(len + NET_IP_ALIGN); - if (!skb) { - dev->stats.rx_dropped++; - return -ENOMEM; - } - - skb_reserve(skb, NET_IP_ALIGN); - if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len)) - return -EFAULT; - - skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_UNNECESSARY; - - netif_rx(skb); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; - - return len; -} - -static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - u32 int_flags; - irqreturn_t ret = IRQ_NONE; - - if (irq != dev->irq) - goto out_badirq; - - /* TESTBIT is cleared on read. */ - int_flags = inl(regaddr(dev, interruptControl)); - if (int_flags & MIPSNET_INTCTL_TESTBIT) { - /* TESTBIT takes effect after a write with 0. */ - outl(0, regaddr(dev, interruptControl)); - ret = IRQ_HANDLED; - } else if (int_flags & MIPSNET_INTCTL_TXDONE) { - /* Only one packet at a time, we are done. */ - dev->stats.tx_packets++; - netif_wake_queue(dev); - outl(MIPSNET_INTCTL_TXDONE, - regaddr(dev, interruptControl)); - ret = IRQ_HANDLED; - } else if (int_flags & MIPSNET_INTCTL_RXDONE) { - mipsnet_get_fromdev(dev, inl(regaddr(dev, rxDataCount))); - outl(MIPSNET_INTCTL_RXDONE, regaddr(dev, interruptControl)); - ret = IRQ_HANDLED; - } - return ret; - -out_badirq: - printk(KERN_INFO "%s: %s(): irq %d for unknown device\n", - dev->name, __func__, irq); - return ret; -} - -static int mipsnet_open(struct net_device *dev) -{ - int err; - - err = request_irq(dev->irq, mipsnet_interrupt, - IRQF_SHARED, dev->name, (void *) dev); - if (err) { - release_region(dev->base_addr, sizeof(struct mipsnet_regs)); - return err; - } - - netif_start_queue(dev); - - /* test interrupt handler */ - outl(MIPSNET_INTCTL_TESTBIT, regaddr(dev, interruptControl)); - - return 0; -} - -static int mipsnet_close(struct net_device *dev) -{ - netif_stop_queue(dev); - free_irq(dev->irq, dev); - return 0; -} - -static void mipsnet_set_mclist(struct net_device *dev) -{ -} - -static const struct net_device_ops mipsnet_netdev_ops = { - .ndo_open = mipsnet_open, - .ndo_stop = mipsnet_close, - .ndo_start_xmit = mipsnet_xmit, - .ndo_set_multicast_list = mipsnet_set_mclist, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, -}; - -static int __devinit mipsnet_probe(struct platform_device *dev) -{ - struct net_device *netdev; - int err; - - netdev = alloc_etherdev(0); - if (!netdev) { - err = -ENOMEM; - goto out; - } - - platform_set_drvdata(dev, netdev); - - netdev->netdev_ops = &mipsnet_netdev_ops; - - /* - * TODO: probe for these or load them from PARAM - */ - netdev->base_addr = 0x4200; - netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + - inl(regaddr(netdev, interruptInfo)); - - /* Get the io region now, get irq on open() */ - if (!request_region(netdev->base_addr, sizeof(struct mipsnet_regs), - "mipsnet")) { - err = -EBUSY; - goto out_free_netdev; - } - - /* - * Lacking any better mechanism to allocate a MAC address we use a - * random one ... - */ - random_ether_addr(netdev->dev_addr); - - err = register_netdev(netdev); - if (err) { - printk(KERN_ERR "MIPSNet: failed to register netdev.\n"); - goto out_free_region; - } - - return 0; - -out_free_region: - release_region(netdev->base_addr, sizeof(struct mipsnet_regs)); - -out_free_netdev: - free_netdev(netdev); - -out: - return err; -} - -static int __devexit mipsnet_device_remove(struct platform_device *device) -{ - struct net_device *dev = platform_get_drvdata(device); - - unregister_netdev(dev); - release_region(dev->base_addr, sizeof(struct mipsnet_regs)); - free_netdev(dev); - platform_set_drvdata(device, NULL); - - return 0; -} - -static struct platform_driver mipsnet_driver = { - .driver = { - .name = mipsnet_string, - .owner = THIS_MODULE, - }, - .probe = mipsnet_probe, - .remove = __devexit_p(mipsnet_device_remove), -}; - -static int __init mipsnet_init_module(void) -{ - int err; - - printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. " - "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION); - - err = platform_driver_register(&mipsnet_driver); - if (err) - printk(KERN_ERR "Driver registration failed\n"); - - return err; -} - -static void __exit mipsnet_exit_module(void) -{ - platform_driver_unregister(&mipsnet_driver); -} - -module_init(mipsnet_init_module); -module_exit(mipsnet_exit_module); -- cgit v1.2.3