mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-06 06:37:59 +00:00
CS89x0 : Use ioread16/iowrite16 on all platforms
The use of the inw/outw functions by the cs89x0 platform driver results in NULL pointer references on ARM platforms and platforms that do not provide ISA-style programmed I/O accessors. Using inw/outw also accesses the wrong address space on platforms that have a PCI I/O space that is not identity-mapped into the physical address space. Signed-off-by: Jaccon Bastiaansen <jaccon.bastiaansen@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a508da6cc0
commit
09dcd604ae
1 changed files with 182 additions and 157 deletions
|
@ -222,6 +222,8 @@ struct net_local {
|
||||||
int send_underrun; /* keep track of how many underruns in a row we get */
|
int send_underrun; /* keep track of how many underruns in a row we get */
|
||||||
int force; /* force various values; see FORCE* above. */
|
int force; /* force various values; see FORCE* above. */
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
void __iomem *virt_addr;/* CS89x0 virtual address. */
|
||||||
|
unsigned long size; /* Length of CS89x0 memory region. */
|
||||||
#if ALLOW_DMA
|
#if ALLOW_DMA
|
||||||
int use_dma; /* Flag: we're using dma */
|
int use_dma; /* Flag: we're using dma */
|
||||||
int dma; /* DMA channel */
|
int dma; /* DMA channel */
|
||||||
|
@ -230,16 +232,9 @@ struct net_local {
|
||||||
unsigned char *end_dma_buff; /* points to the end of the buffer */
|
unsigned char *end_dma_buff; /* points to the end of the buffer */
|
||||||
unsigned char *rx_dma_ptr; /* points to the next packet */
|
unsigned char *rx_dma_ptr; /* points to the next packet */
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CS89x0_PLATFORM
|
|
||||||
void __iomem *virt_addr;/* Virtual address for accessing the CS89x0. */
|
|
||||||
unsigned long phys_addr;/* Physical address for accessing the CS89x0. */
|
|
||||||
unsigned long size; /* Length of CS89x0 memory region. */
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Index to functions, as function prototypes. */
|
/* Index to functions, as function prototypes. */
|
||||||
|
|
||||||
static int cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular);
|
|
||||||
static int net_open(struct net_device *dev);
|
static int net_open(struct net_device *dev);
|
||||||
static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
|
static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
|
||||||
static irqreturn_t net_interrupt(int irq, void *dev_id);
|
static irqreturn_t net_interrupt(int irq, void *dev_id);
|
||||||
|
@ -267,7 +262,8 @@ static void release_dma_buff(struct net_local *lp);
|
||||||
/*
|
/*
|
||||||
* Permit 'cs89x0_dma=N' in the kernel boot environment
|
* Permit 'cs89x0_dma=N' in the kernel boot environment
|
||||||
*/
|
*/
|
||||||
#if !defined(MODULE) && (ALLOW_DMA != 0)
|
#if !defined(MODULE)
|
||||||
|
#if ALLOW_DMA
|
||||||
static int g_cs89x0_dma;
|
static int g_cs89x0_dma;
|
||||||
|
|
||||||
static int __init dma_fn(char *str)
|
static int __init dma_fn(char *str)
|
||||||
|
@ -277,9 +273,8 @@ static int __init dma_fn(char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
__setup("cs89x0_dma=", dma_fn);
|
__setup("cs89x0_dma=", dma_fn);
|
||||||
#endif /* !defined(MODULE) && (ALLOW_DMA != 0) */
|
#endif /* ALLOW_DMA */
|
||||||
|
|
||||||
#ifndef MODULE
|
|
||||||
static int g_cs89x0_media__force;
|
static int g_cs89x0_media__force;
|
||||||
|
|
||||||
static int __init media_fn(char *str)
|
static int __init media_fn(char *str)
|
||||||
|
@ -291,58 +286,6 @@ static int __init media_fn(char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
__setup("cs89x0_media=", media_fn);
|
__setup("cs89x0_media=", media_fn);
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_CS89x0_PLATFORM
|
|
||||||
/* Check for a network adaptor of this type, and return '0' iff one exists.
|
|
||||||
If dev->base_addr == 0, probe all likely locations.
|
|
||||||
If dev->base_addr == 1, always return failure.
|
|
||||||
If dev->base_addr == 2, allocate space for the device and return success
|
|
||||||
(detachable devices only).
|
|
||||||
Return 0 on success.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct net_device * __init cs89x0_probe(int unit)
|
|
||||||
{
|
|
||||||
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
|
|
||||||
unsigned *port;
|
|
||||||
int err = 0;
|
|
||||||
int irq;
|
|
||||||
int io;
|
|
||||||
|
|
||||||
if (!dev)
|
|
||||||
return ERR_PTR(-ENODEV);
|
|
||||||
|
|
||||||
sprintf(dev->name, "eth%d", unit);
|
|
||||||
netdev_boot_setup_check(dev);
|
|
||||||
io = dev->base_addr;
|
|
||||||
irq = dev->irq;
|
|
||||||
|
|
||||||
if (net_debug)
|
|
||||||
printk("cs89x0:cs89x0_probe(0x%x)\n", io);
|
|
||||||
|
|
||||||
if (io > 0x1ff) { /* Check a single specified location. */
|
|
||||||
err = cs89x0_probe1(dev, io, 0);
|
|
||||||
} else if (io != 0) { /* Don't probe at all. */
|
|
||||||
err = -ENXIO;
|
|
||||||
} else {
|
|
||||||
for (port = netcard_portlist; *port; port++) {
|
|
||||||
if (cs89x0_probe1(dev, *port, 0) == 0)
|
|
||||||
break;
|
|
||||||
dev->irq = irq;
|
|
||||||
}
|
|
||||||
if (!*port)
|
|
||||||
err = -ENODEV;
|
|
||||||
}
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
return dev;
|
|
||||||
out:
|
|
||||||
free_netdev(dev);
|
|
||||||
printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
|
|
||||||
return ERR_PTR(err);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_MACH_IXDP2351)
|
#if defined(CONFIG_MACH_IXDP2351)
|
||||||
|
@ -369,36 +312,22 @@ writeword(unsigned long base_addr, int portno, u16 value)
|
||||||
{
|
{
|
||||||
__raw_writel(value, base_addr + (portno << 1));
|
__raw_writel(value, base_addr + (portno << 1));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static u16
|
|
||||||
readword(unsigned long base_addr, int portno)
|
|
||||||
{
|
|
||||||
return inw(base_addr + portno);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
writeword(unsigned long base_addr, int portno, u16 value)
|
|
||||||
{
|
|
||||||
outw(value, base_addr + portno);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void readwords(struct net_local *lp, int portno, void *buf, int length)
|
||||||
readwords(unsigned long base_addr, int portno, void *buf, int length)
|
|
||||||
{
|
{
|
||||||
u8 *buf8 = (u8 *)buf;
|
u8 *buf8 = (u8 *)buf;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
u16 tmp16;
|
u16 tmp16;
|
||||||
|
|
||||||
tmp16 = readword(base_addr, portno);
|
tmp16 = ioread16(lp->virt_addr + portno);
|
||||||
*buf8++ = (u8)tmp16;
|
*buf8++ = (u8)tmp16;
|
||||||
*buf8++ = (u8)(tmp16 >> 8);
|
*buf8++ = (u8)(tmp16 >> 8);
|
||||||
} while (--length);
|
} while (--length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void writewords(struct net_local *lp, int portno, void *buf, int length)
|
||||||
writewords(unsigned long base_addr, int portno, void *buf, int length)
|
|
||||||
{
|
{
|
||||||
u8 *buf8 = (u8 *)buf;
|
u8 *buf8 = (u8 *)buf;
|
||||||
|
|
||||||
|
@ -407,22 +336,26 @@ writewords(unsigned long base_addr, int portno, void *buf, int length)
|
||||||
|
|
||||||
tmp16 = *buf8++;
|
tmp16 = *buf8++;
|
||||||
tmp16 |= (*buf8++) << 8;
|
tmp16 |= (*buf8++) << 8;
|
||||||
writeword(base_addr, portno, tmp16);
|
iowrite16(tmp16, lp->virt_addr + portno);
|
||||||
} while (--length);
|
} while (--length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16
|
static u16
|
||||||
readreg(struct net_device *dev, u16 regno)
|
readreg(struct net_device *dev, u16 regno)
|
||||||
{
|
{
|
||||||
writeword(dev->base_addr, ADD_PORT, regno);
|
struct net_local *lp = netdev_priv(dev);
|
||||||
return readword(dev->base_addr, DATA_PORT);
|
|
||||||
|
iowrite16(regno, lp->virt_addr + ADD_PORT);
|
||||||
|
return ioread16(lp->virt_addr + DATA_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
writereg(struct net_device *dev, u16 regno, u16 value)
|
writereg(struct net_device *dev, u16 regno, u16 value)
|
||||||
{
|
{
|
||||||
writeword(dev->base_addr, ADD_PORT, regno);
|
struct net_local *lp = netdev_priv(dev);
|
||||||
writeword(dev->base_addr, DATA_PORT, value);
|
|
||||||
|
iowrite16(regno, lp->virt_addr + ADD_PORT);
|
||||||
|
iowrite16(value, lp->virt_addr + DATA_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
|
@ -505,7 +438,7 @@ static const struct net_device_ops net_ops = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
|
cs89x0_probe1(struct net_device *dev, void __iomem *ioaddr, int modular)
|
||||||
{
|
{
|
||||||
struct net_local *lp = netdev_priv(dev);
|
struct net_local *lp = netdev_priv(dev);
|
||||||
static unsigned version_printed;
|
static unsigned version_printed;
|
||||||
|
@ -529,50 +462,22 @@ cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
|
||||||
#endif
|
#endif
|
||||||
lp->force = g_cs89x0_media__force;
|
lp->force = g_cs89x0_media__force;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab the region so we can find another board if autoIRQ fails. */
|
printk(KERN_DEBUG "PP_addr at %p[%x]: 0x%x\n",
|
||||||
/* WTF is going on here? */
|
ioaddr, ADD_PORT, ioread16(ioaddr + ADD_PORT));
|
||||||
if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
|
iowrite16(PP_ChipID, ioaddr + ADD_PORT);
|
||||||
printk(KERN_ERR "%s: request_region(0x%lx, 0x%x) failed\n",
|
|
||||||
DRV_NAME, ioaddr, NETCARD_IO_EXTENT);
|
|
||||||
retval = -EBUSY;
|
|
||||||
goto out1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if they give us an odd I/O address, then do ONE write to
|
tmp = ioread16(ioaddr + DATA_PORT);
|
||||||
the address port, to get it back to address zero, where we
|
|
||||||
expect to find the EISA signature word. An IO with a base of 0x3
|
|
||||||
will skip the test for the ADD_PORT. */
|
|
||||||
if (ioaddr & 1) {
|
|
||||||
if (net_debug > 1)
|
|
||||||
printk(KERN_INFO "%s: odd ioaddr 0x%lx\n", dev->name, ioaddr);
|
|
||||||
if ((ioaddr & 2) != 2)
|
|
||||||
if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
|
|
||||||
printk(KERN_ERR "%s: bad signature 0x%x\n",
|
|
||||||
dev->name, readword(ioaddr & ~3, ADD_PORT));
|
|
||||||
retval = -ENODEV;
|
|
||||||
goto out2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ioaddr &= ~3;
|
|
||||||
printk(KERN_DEBUG "PP_addr at %lx[%x]: 0x%x\n",
|
|
||||||
ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
|
|
||||||
writeword(ioaddr, ADD_PORT, PP_ChipID);
|
|
||||||
|
|
||||||
tmp = readword(ioaddr, DATA_PORT);
|
|
||||||
if (tmp != CHIP_EISA_ID_SIG) {
|
if (tmp != CHIP_EISA_ID_SIG) {
|
||||||
printk(KERN_DEBUG "%s: incorrect signature at %lx[%x]: 0x%x!="
|
printk(KERN_DEBUG "%s: incorrect signature at %p[%x]: 0x%x!="
|
||||||
CHIP_EISA_ID_SIG_STR "\n",
|
CHIP_EISA_ID_SIG_STR "\n",
|
||||||
dev->name, ioaddr, DATA_PORT, tmp);
|
dev->name, ioaddr, DATA_PORT, tmp);
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
goto out2;
|
goto out1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in the 'dev' fields. */
|
lp->virt_addr = ioaddr;
|
||||||
dev->base_addr = ioaddr;
|
|
||||||
|
|
||||||
/* get the chip type */
|
/* get the chip type */
|
||||||
rev_type = readreg(dev, PRODUCT_ID_ADD);
|
rev_type = readreg(dev, PRODUCT_ID_ADD);
|
||||||
|
@ -590,12 +495,12 @@ cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
|
||||||
if (net_debug && version_printed++ == 0)
|
if (net_debug && version_printed++ == 0)
|
||||||
printk(version);
|
printk(version);
|
||||||
|
|
||||||
printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#3lx ",
|
printk(KERN_INFO "%s: cs89%c0%s rev %c found at %p ",
|
||||||
dev->name,
|
dev->name,
|
||||||
lp->chip_type==CS8900?'0':'2',
|
lp->chip_type==CS8900?'0':'2',
|
||||||
lp->chip_type==CS8920M?"M":"",
|
lp->chip_type==CS8920M?"M":"",
|
||||||
lp->chip_revision,
|
lp->chip_revision,
|
||||||
dev->base_addr);
|
lp->virt_addr);
|
||||||
|
|
||||||
reset_chip(dev);
|
reset_chip(dev);
|
||||||
|
|
||||||
|
@ -787,16 +692,125 @@ cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
|
||||||
|
|
||||||
retval = register_netdev(dev);
|
retval = register_netdev(dev);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out3;
|
goto out2;
|
||||||
return 0;
|
return 0;
|
||||||
out3:
|
|
||||||
writeword(dev->base_addr, ADD_PORT, PP_ChipID);
|
|
||||||
out2:
|
out2:
|
||||||
release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
|
iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
|
||||||
out1:
|
out1:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_CS89x0_PLATFORM
|
||||||
|
/*
|
||||||
|
* This function converts the I/O port addres used by the cs89x0_probe() and
|
||||||
|
* init_module() functions to the I/O memory address used by the
|
||||||
|
* cs89x0_probe1() function.
|
||||||
|
*/
|
||||||
|
static int __init
|
||||||
|
cs89x0_ioport_probe(struct net_device *dev, unsigned long ioport, int modular)
|
||||||
|
{
|
||||||
|
struct net_local *lp = netdev_priv(dev);
|
||||||
|
int ret;
|
||||||
|
void __iomem *io_mem;
|
||||||
|
|
||||||
|
if (!lp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev->base_addr = ioport;
|
||||||
|
|
||||||
|
if (!request_region(ioport, NETCARD_IO_EXTENT, DRV_NAME)) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
io_mem = ioport_map(ioport & ~3, NETCARD_IO_EXTENT);
|
||||||
|
if (!io_mem) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if they give us an odd I/O address, then do ONE write to
|
||||||
|
the address port, to get it back to address zero, where we
|
||||||
|
expect to find the EISA signature word. An IO with a base of 0x3
|
||||||
|
will skip the test for the ADD_PORT. */
|
||||||
|
if (ioport & 1) {
|
||||||
|
if (net_debug > 1)
|
||||||
|
printk(KERN_INFO "%s: odd ioaddr 0x%lx\n",
|
||||||
|
dev->name,
|
||||||
|
ioport);
|
||||||
|
if ((ioport & 2) != 2)
|
||||||
|
if ((ioread16(io_mem + ADD_PORT) & ADD_MASK) !=
|
||||||
|
ADD_SIG) {
|
||||||
|
printk(KERN_ERR "%s: bad signature 0x%x\n",
|
||||||
|
dev->name,
|
||||||
|
ioread16(io_mem + ADD_PORT));
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto unmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cs89x0_probe1(dev, io_mem, modular);
|
||||||
|
if (!ret)
|
||||||
|
goto out;
|
||||||
|
unmap:
|
||||||
|
ioport_unmap(io_mem);
|
||||||
|
release:
|
||||||
|
release_region(ioport, NETCARD_IO_EXTENT);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MODULE
|
||||||
|
/* Check for a network adaptor of this type, and return '0' iff one exists.
|
||||||
|
If dev->base_addr == 0, probe all likely locations.
|
||||||
|
If dev->base_addr == 1, always return failure.
|
||||||
|
If dev->base_addr == 2, allocate space for the device and return success
|
||||||
|
(detachable devices only).
|
||||||
|
Return 0 on success.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct net_device * __init cs89x0_probe(int unit)
|
||||||
|
{
|
||||||
|
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
|
||||||
|
unsigned *port;
|
||||||
|
int err = 0;
|
||||||
|
int irq;
|
||||||
|
int io;
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
sprintf(dev->name, "eth%d", unit);
|
||||||
|
netdev_boot_setup_check(dev);
|
||||||
|
io = dev->base_addr;
|
||||||
|
irq = dev->irq;
|
||||||
|
|
||||||
|
if (net_debug)
|
||||||
|
printk(KERN_INFO "cs89x0:cs89x0_probe(0x%x)\n", io);
|
||||||
|
|
||||||
|
if (io > 0x1ff) { /* Check a single specified location. */
|
||||||
|
err = cs89x0_ioport_probe(dev, io, 0);
|
||||||
|
} else if (io != 0) { /* Don't probe at all. */
|
||||||
|
err = -ENXIO;
|
||||||
|
} else {
|
||||||
|
for (port = netcard_portlist; *port; port++) {
|
||||||
|
if (cs89x0_ioport_probe(dev, *port, 0) == 0)
|
||||||
|
break;
|
||||||
|
dev->irq = irq;
|
||||||
|
}
|
||||||
|
if (!*port)
|
||||||
|
err = -ENODEV;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
return dev;
|
||||||
|
out:
|
||||||
|
free_netdev(dev);
|
||||||
|
printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*********************************
|
/*********************************
|
||||||
* This page contains DMA routines
|
* This page contains DMA routines
|
||||||
|
@ -956,7 +970,6 @@ static void __init reset_chip(struct net_device *dev)
|
||||||
#if !defined(CONFIG_MACH_MX31ADS)
|
#if !defined(CONFIG_MACH_MX31ADS)
|
||||||
#if !defined(CS89x0_NONISA_IRQ)
|
#if !defined(CS89x0_NONISA_IRQ)
|
||||||
struct net_local *lp = netdev_priv(dev);
|
struct net_local *lp = netdev_priv(dev);
|
||||||
int ioaddr = dev->base_addr;
|
|
||||||
#endif /* CS89x0_NONISA_IRQ */
|
#endif /* CS89x0_NONISA_IRQ */
|
||||||
int reset_start_time;
|
int reset_start_time;
|
||||||
|
|
||||||
|
@ -968,13 +981,15 @@ static void __init reset_chip(struct net_device *dev)
|
||||||
#if !defined(CS89x0_NONISA_IRQ)
|
#if !defined(CS89x0_NONISA_IRQ)
|
||||||
if (lp->chip_type != CS8900) {
|
if (lp->chip_type != CS8900) {
|
||||||
/* Hardware problem requires PNP registers to be reconfigured after a reset */
|
/* Hardware problem requires PNP registers to be reconfigured after a reset */
|
||||||
writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
|
iowrite16(PP_CS8920_ISAINT, lp->virt_addr + ADD_PORT);
|
||||||
outb(dev->irq, ioaddr + DATA_PORT);
|
iowrite8(dev->irq, lp->virt_addr + DATA_PORT);
|
||||||
outb(0, ioaddr + DATA_PORT + 1);
|
iowrite8(0, lp->virt_addr + DATA_PORT + 1);
|
||||||
|
|
||||||
writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB);
|
iowrite16(PP_CS8920_ISAMemB, lp->virt_addr + ADD_PORT);
|
||||||
outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
|
iowrite8((dev->mem_start >> 16) & 0xff,
|
||||||
outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1);
|
lp->virt_addr + DATA_PORT);
|
||||||
|
iowrite8((dev->mem_start >> 8) & 0xff,
|
||||||
|
lp->virt_addr + DATA_PORT + 1);
|
||||||
}
|
}
|
||||||
#endif /* CS89x0_NONISA_IRQ */
|
#endif /* CS89x0_NONISA_IRQ */
|
||||||
|
|
||||||
|
@ -1092,6 +1107,7 @@ detect_tp(struct net_device *dev)
|
||||||
static int
|
static int
|
||||||
send_test_pkt(struct net_device *dev)
|
send_test_pkt(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
struct net_local *lp = netdev_priv(dev);
|
||||||
char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
|
char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
|
||||||
0, 46, /* A 46 in network order */
|
0, 46, /* A 46 in network order */
|
||||||
0, 0, /* DSAP=0 & SSAP=0 fields */
|
0, 0, /* DSAP=0 & SSAP=0 fields */
|
||||||
|
@ -1103,8 +1119,8 @@ send_test_pkt(struct net_device *dev)
|
||||||
memcpy(test_packet, dev->dev_addr, ETH_ALEN);
|
memcpy(test_packet, dev->dev_addr, ETH_ALEN);
|
||||||
memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
|
memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
|
||||||
|
|
||||||
writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL);
|
iowrite16(TX_AFTER_ALL, lp->virt_addr + TX_CMD_PORT);
|
||||||
writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN);
|
iowrite16(ETH_ZLEN, lp->virt_addr + TX_LEN_PORT);
|
||||||
|
|
||||||
/* Test to see if the chip has allocated memory for the packet */
|
/* Test to see if the chip has allocated memory for the packet */
|
||||||
while (jiffies - timenow < 5)
|
while (jiffies - timenow < 5)
|
||||||
|
@ -1114,7 +1130,7 @@ send_test_pkt(struct net_device *dev)
|
||||||
return 0; /* this shouldn't happen */
|
return 0; /* this shouldn't happen */
|
||||||
|
|
||||||
/* Write the contents of the packet */
|
/* Write the contents of the packet */
|
||||||
writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
|
writewords(lp, TX_FRAME_PORT, test_packet, (ETH_ZLEN+1) >> 1);
|
||||||
|
|
||||||
if (net_debug > 1) printk("Sending test packet ");
|
if (net_debug > 1) printk("Sending test packet ");
|
||||||
/* wait a couple of jiffies for packet to be received */
|
/* wait a couple of jiffies for packet to be received */
|
||||||
|
@ -1458,8 +1474,8 @@ static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev)
|
||||||
netif_stop_queue(dev);
|
netif_stop_queue(dev);
|
||||||
|
|
||||||
/* initiate a transmit sequence */
|
/* initiate a transmit sequence */
|
||||||
writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
|
iowrite16(lp->send_cmd, lp->virt_addr + TX_CMD_PORT);
|
||||||
writeword(dev->base_addr, TX_LEN_PORT, skb->len);
|
iowrite16(skb->len, lp->virt_addr + TX_LEN_PORT);
|
||||||
|
|
||||||
/* Test to see if the chip has allocated memory for the packet */
|
/* Test to see if the chip has allocated memory for the packet */
|
||||||
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
|
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
|
||||||
|
@ -1473,7 +1489,7 @@ static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev)
|
||||||
return NETDEV_TX_BUSY;
|
return NETDEV_TX_BUSY;
|
||||||
}
|
}
|
||||||
/* Write the contents of the packet */
|
/* Write the contents of the packet */
|
||||||
writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
|
writewords(lp, TX_FRAME_PORT, skb->data, (skb->len+1) >> 1);
|
||||||
spin_unlock_irqrestore(&lp->lock, flags);
|
spin_unlock_irqrestore(&lp->lock, flags);
|
||||||
dev->stats.tx_bytes += skb->len;
|
dev->stats.tx_bytes += skb->len;
|
||||||
dev_kfree_skb (skb);
|
dev_kfree_skb (skb);
|
||||||
|
@ -1499,10 +1515,9 @@ static irqreturn_t net_interrupt(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct net_device *dev = dev_id;
|
struct net_device *dev = dev_id;
|
||||||
struct net_local *lp;
|
struct net_local *lp;
|
||||||
int ioaddr, status;
|
int status;
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
ioaddr = dev->base_addr;
|
|
||||||
lp = netdev_priv(dev);
|
lp = netdev_priv(dev);
|
||||||
|
|
||||||
/* we MUST read all the events out of the ISQ, otherwise we'll never
|
/* we MUST read all the events out of the ISQ, otherwise we'll never
|
||||||
|
@ -1512,7 +1527,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id)
|
||||||
course, if you're on a slow machine, and packets are arriving
|
course, if you're on a slow machine, and packets are arriving
|
||||||
faster than you can read them off, you're screwed. Hasta la
|
faster than you can read them off, you're screwed. Hasta la
|
||||||
vista, baby! */
|
vista, baby! */
|
||||||
while ((status = readword(dev->base_addr, ISQ_PORT))) {
|
while ((status = ioread16(lp->virt_addr + ISQ_PORT))) {
|
||||||
if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
|
if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
|
||||||
handled = 1;
|
handled = 1;
|
||||||
switch(status & ISQ_EVENT_MASK) {
|
switch(status & ISQ_EVENT_MASK) {
|
||||||
|
@ -1608,12 +1623,12 @@ count_rx_errors(int status, struct net_device *dev)
|
||||||
static void
|
static void
|
||||||
net_rx(struct net_device *dev)
|
net_rx(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
struct net_local *lp = netdev_priv(dev);
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int status, length;
|
int status, length;
|
||||||
|
|
||||||
int ioaddr = dev->base_addr;
|
status = ioread16(lp->virt_addr + RX_FRAME_PORT);
|
||||||
status = readword(ioaddr, RX_FRAME_PORT);
|
length = ioread16(lp->virt_addr + RX_FRAME_PORT);
|
||||||
length = readword(ioaddr, RX_FRAME_PORT);
|
|
||||||
|
|
||||||
if ((status & RX_OK) == 0) {
|
if ((status & RX_OK) == 0) {
|
||||||
count_rx_errors(status, dev);
|
count_rx_errors(status, dev);
|
||||||
|
@ -1631,9 +1646,9 @@ net_rx(struct net_device *dev)
|
||||||
}
|
}
|
||||||
skb_reserve(skb, 2); /* longword align L3 header */
|
skb_reserve(skb, 2); /* longword align L3 header */
|
||||||
|
|
||||||
readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
|
readwords(lp, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
|
||||||
if (length & 1)
|
if (length & 1)
|
||||||
skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
|
skb->data[length-1] = ioread16(lp->virt_addr + RX_FRAME_PORT);
|
||||||
|
|
||||||
if (net_debug > 3) {
|
if (net_debug > 3) {
|
||||||
printk( "%s: received %d byte packet of type %x\n",
|
printk( "%s: received %d byte packet of type %x\n",
|
||||||
|
@ -1886,7 +1901,7 @@ int __init init_module(void)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ret = cs89x0_probe1(dev, io, 1);
|
ret = cs89x0_ioport_probe(dev, io, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1900,8 +1915,11 @@ out:
|
||||||
void __exit
|
void __exit
|
||||||
cleanup_module(void)
|
cleanup_module(void)
|
||||||
{
|
{
|
||||||
|
struct net_local *lp = netdev_priv(dev_cs89x0);
|
||||||
|
|
||||||
unregister_netdev(dev_cs89x0);
|
unregister_netdev(dev_cs89x0);
|
||||||
writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
|
iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
|
||||||
|
ioport_unmap(lp->virt_addr);
|
||||||
release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
|
release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
|
||||||
free_netdev(dev_cs89x0);
|
free_netdev(dev_cs89x0);
|
||||||
}
|
}
|
||||||
|
@ -1913,6 +1931,7 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
|
||||||
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
|
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
|
||||||
struct net_local *lp;
|
struct net_local *lp;
|
||||||
struct resource *mem_res;
|
struct resource *mem_res;
|
||||||
|
void __iomem *virt_addr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
@ -1928,22 +1947,21 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
|
||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->phys_addr = mem_res->start;
|
|
||||||
lp->size = resource_size(mem_res);
|
lp->size = resource_size(mem_res);
|
||||||
if (!request_mem_region(lp->phys_addr, lp->size, DRV_NAME)) {
|
if (!request_mem_region(mem_res->start, lp->size, DRV_NAME)) {
|
||||||
dev_warn(&dev->dev, "request_mem_region() failed.\n");
|
dev_warn(&dev->dev, "request_mem_region() failed.\n");
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->virt_addr = ioremap(lp->phys_addr, lp->size);
|
virt_addr = ioremap(mem_res->start, lp->size);
|
||||||
if (!lp->virt_addr) {
|
if (!virt_addr) {
|
||||||
dev_warn(&dev->dev, "ioremap() failed.\n");
|
dev_warn(&dev->dev, "ioremap() failed.\n");
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cs89x0_probe1(dev, (unsigned long)lp->virt_addr, 0);
|
err = cs89x0_probe1(dev, virt_addr, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n");
|
dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n");
|
||||||
goto unmap;
|
goto unmap;
|
||||||
|
@ -1953,9 +1971,9 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unmap:
|
unmap:
|
||||||
iounmap(lp->virt_addr);
|
iounmap(virt_addr);
|
||||||
release:
|
release:
|
||||||
release_mem_region(lp->phys_addr, lp->size);
|
release_mem_region(mem_res->start, lp->size);
|
||||||
free:
|
free:
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
return err;
|
return err;
|
||||||
|
@ -1965,10 +1983,17 @@ static int cs89x0_platform_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct net_device *dev = platform_get_drvdata(pdev);
|
struct net_device *dev = platform_get_drvdata(pdev);
|
||||||
struct net_local *lp = netdev_priv(dev);
|
struct net_local *lp = netdev_priv(dev);
|
||||||
|
struct resource *mem_res;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This platform_get_resource() call will not return NULL, because
|
||||||
|
* the same call in cs89x0_platform_probe() has returned a non NULL
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
unregister_netdev(dev);
|
unregister_netdev(dev);
|
||||||
iounmap(lp->virt_addr);
|
iounmap(lp->virt_addr);
|
||||||
release_mem_region(lp->phys_addr, lp->size);
|
release_mem_region(mem_res->start, lp->size);
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue