Loading drivers/net/mipsnet.c +31 −32 Original line number Diff line number Diff line Loading @@ -7,12 +7,12 @@ #define DEBUG #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/platform_device.h> #include <asm/io.h> #include <asm/mips-boards/simint.h> #include "mipsnet.h" /* actual device IO mapping */ Loading @@ -33,9 +33,8 @@ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, if (available_len < len) return -EFAULT; for (; len > 0; len--, kdata++) { for (; len > 0; len--, kdata++) *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer)); } return inl(mipsnet_reg_address(dev, rxDataCount)); } Loading @@ -54,9 +53,8 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev, pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n", dev->name, __FUNCTION__, skb->len); for (; count_to_go; buf_ptr++, count_to_go--) { for (; count_to_go; buf_ptr++, count_to_go--) outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer)); } dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; Loading @@ -83,7 +81,8 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count) struct sk_buff *skb; size_t len = count; if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) { skb = alloc_skb(len + 2, GFP_KERNEL); if (!skb) { dev->stats.rx_dropped++; return -ENOMEM; } Loading Loading @@ -128,7 +127,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) dev->name, __FUNCTION__); outl(MIPSNET_INTCTL_TXDONE, mipsnet_reg_address(dev, interruptControl)); // only one packet at a time, we are done. /* only one packet at a time, we are done. */ netif_wake_queue(dev); } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) { pr_debug("%s:%s(): got RX data\n", Loading @@ -143,13 +142,15 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) { pr_debug("%s:%s(): got test interrupt\n", dev->name, __FUNCTION__); // TESTBIT is cleared on read. // And takes effect after a write with 0 /* * TESTBIT is cleared on read. * And takes effect after a write with 0 */ outl(0, mipsnet_reg_address(dev, interruptControl)); } else { pr_debug("%s:%s(): no valid fags 0x%016llx\n", dev->name, __FUNCTION__, interruptFlags); // Maybe shared IRQ, just ignore, no clearing. /* Maybe shared IRQ, just ignore, no clearing. */ retval = IRQ_NONE; } Loading @@ -159,7 +160,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) retval = IRQ_NONE; } return retval; } //mipsnet_interrupt() } static int mipsnet_open(struct net_device *dev) { Loading @@ -182,7 +183,7 @@ static int mipsnet_open(struct net_device *dev) netif_start_queue(dev); // test interrupt handler /* test interrupt handler */ outl(MIPSNET_INTCTL_TESTBIT, mipsnet_reg_address(dev, interruptControl)); Loading @@ -199,8 +200,6 @@ static int mipsnet_close(struct net_device *dev) static void mipsnet_set_mclist(struct net_device *dev) { // we don't do anything return; } static int __init mipsnet_probe(struct device *dev) Loading Loading @@ -228,7 +227,7 @@ static int __init mipsnet_probe(struct device *dev) netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + inl(mipsnet_reg_address(netdev, interruptInfo)); // Get the io region now, get irq on open() /* Get the io region now, get irq on open() */ if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) { pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} " "for dev is not availble.\n", netdev->name, Loading drivers/net/mipsnet.h +44 −39 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ * (Why not use bit fields? can't be bothered with cross-platform struct * packing.) */ typedef struct _net_control_block { /// dev info for probing /// reads as MIPSNET%d where %d is some form of version struct net_control_block { /* * dev info for probing * reads as MIPSNET%d where %d is some form of version */ uint64_t devId; /* 0x00 */ /* Loading @@ -47,10 +49,10 @@ typedef struct _net_control_block { #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). * 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). */ uint32_t txDataCount; /* 0x10 */ Loading @@ -72,16 +74,19 @@ typedef struct _net_control_block { #define MIPSNET_INTCTL_TXDONE ((uint32_t)(1 << 0)) #define MIPSNET_INTCTL_RXDONE ((uint32_t)(1 << 1)) #define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1 << 31)) #define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT) #define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE | \ MIPSNET_INTCTL_RXDONE | \ MIPSNET_INTCTL_TESTBIT) /* * Readonly core-specific interrupt info for the device to signal the core. * The meaning of the contents of this field might change. */ /*###\todo: 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. * Readonly core-specific interrupt info for the device to signal the * core. The meaning of the contents of this field might change. * * TODO: 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. */ uint32_t interruptInfo; /* 0x18 */ Loading @@ -93,15 +98,15 @@ typedef struct _net_control_block { uint32_t 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. * 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. */ uint32_t txDataBuffer; /* 0x20 */ } MIPS_T_NetControl; }; #define MIPSNET_IO_EXTENT 0x40 /* being generous */ #define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field) #define field_offset(field) (offsetof(struct net_control_block, field)) #endif /* __MIPSNET_H */ Loading
drivers/net/mipsnet.c +31 −32 Original line number Diff line number Diff line Loading @@ -7,12 +7,12 @@ #define DEBUG #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/platform_device.h> #include <asm/io.h> #include <asm/mips-boards/simint.h> #include "mipsnet.h" /* actual device IO mapping */ Loading @@ -33,9 +33,8 @@ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, if (available_len < len) return -EFAULT; for (; len > 0; len--, kdata++) { for (; len > 0; len--, kdata++) *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer)); } return inl(mipsnet_reg_address(dev, rxDataCount)); } Loading @@ -54,9 +53,8 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev, pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n", dev->name, __FUNCTION__, skb->len); for (; count_to_go; buf_ptr++, count_to_go--) { for (; count_to_go; buf_ptr++, count_to_go--) outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer)); } dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; Loading @@ -83,7 +81,8 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count) struct sk_buff *skb; size_t len = count; if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) { skb = alloc_skb(len + 2, GFP_KERNEL); if (!skb) { dev->stats.rx_dropped++; return -ENOMEM; } Loading Loading @@ -128,7 +127,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) dev->name, __FUNCTION__); outl(MIPSNET_INTCTL_TXDONE, mipsnet_reg_address(dev, interruptControl)); // only one packet at a time, we are done. /* only one packet at a time, we are done. */ netif_wake_queue(dev); } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) { pr_debug("%s:%s(): got RX data\n", Loading @@ -143,13 +142,15 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) { pr_debug("%s:%s(): got test interrupt\n", dev->name, __FUNCTION__); // TESTBIT is cleared on read. // And takes effect after a write with 0 /* * TESTBIT is cleared on read. * And takes effect after a write with 0 */ outl(0, mipsnet_reg_address(dev, interruptControl)); } else { pr_debug("%s:%s(): no valid fags 0x%016llx\n", dev->name, __FUNCTION__, interruptFlags); // Maybe shared IRQ, just ignore, no clearing. /* Maybe shared IRQ, just ignore, no clearing. */ retval = IRQ_NONE; } Loading @@ -159,7 +160,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) retval = IRQ_NONE; } return retval; } //mipsnet_interrupt() } static int mipsnet_open(struct net_device *dev) { Loading @@ -182,7 +183,7 @@ static int mipsnet_open(struct net_device *dev) netif_start_queue(dev); // test interrupt handler /* test interrupt handler */ outl(MIPSNET_INTCTL_TESTBIT, mipsnet_reg_address(dev, interruptControl)); Loading @@ -199,8 +200,6 @@ static int mipsnet_close(struct net_device *dev) static void mipsnet_set_mclist(struct net_device *dev) { // we don't do anything return; } static int __init mipsnet_probe(struct device *dev) Loading Loading @@ -228,7 +227,7 @@ static int __init mipsnet_probe(struct device *dev) netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + inl(mipsnet_reg_address(netdev, interruptInfo)); // Get the io region now, get irq on open() /* Get the io region now, get irq on open() */ if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) { pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} " "for dev is not availble.\n", netdev->name, Loading
drivers/net/mipsnet.h +44 −39 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ * (Why not use bit fields? can't be bothered with cross-platform struct * packing.) */ typedef struct _net_control_block { /// dev info for probing /// reads as MIPSNET%d where %d is some form of version struct net_control_block { /* * dev info for probing * reads as MIPSNET%d where %d is some form of version */ uint64_t devId; /* 0x00 */ /* Loading @@ -47,10 +49,10 @@ typedef struct _net_control_block { #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). * 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). */ uint32_t txDataCount; /* 0x10 */ Loading @@ -72,16 +74,19 @@ typedef struct _net_control_block { #define MIPSNET_INTCTL_TXDONE ((uint32_t)(1 << 0)) #define MIPSNET_INTCTL_RXDONE ((uint32_t)(1 << 1)) #define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1 << 31)) #define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT) #define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE | \ MIPSNET_INTCTL_RXDONE | \ MIPSNET_INTCTL_TESTBIT) /* * Readonly core-specific interrupt info for the device to signal the core. * The meaning of the contents of this field might change. */ /*###\todo: 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. * Readonly core-specific interrupt info for the device to signal the * core. The meaning of the contents of this field might change. * * TODO: 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. */ uint32_t interruptInfo; /* 0x18 */ Loading @@ -93,15 +98,15 @@ typedef struct _net_control_block { uint32_t 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. * 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. */ uint32_t txDataBuffer; /* 0x20 */ } MIPS_T_NetControl; }; #define MIPSNET_IO_EXTENT 0x40 /* being generous */ #define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field) #define field_offset(field) (offsetof(struct net_control_block, field)) #endif /* __MIPSNET_H */