X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fcs89x0.c;h=ef54ebeb29b85196ea8626a4597ec46437076912;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=7e616f7aa558ea6928f2f89e67388d8a5139a7f3;hpb=e686509282835a634ee3285c39a1b5b04ee2a88f;p=linux-2.6.git diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 7e616f7aa..ef54ebeb2 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -84,6 +84,18 @@ Oskar Schirmer : oskar@scara.com : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=) + Deepak Saxena : dsaxena@plexity.net + : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support + + Dmitry Pervushin : dpervushin@ru.mvista.com + : PNX010X platform support + + Deepak Saxena : dsaxena@plexity.net + : Intel IXDP2351 platform support + + Dmitry Pervushin : dpervushin@ru.mvista.com + : PNX010X platform support + */ /* Always include 'config.h' first in case the user wants to turn on @@ -97,7 +109,11 @@ * Note that even if DMA is turned off we still support the 'dma' and 'use_dma' * module options so we don't break any startup scripts. */ +#ifndef CONFIG_ISA_DMA_API +#define ALLOW_DMA 0 +#else #define ALLOW_DMA 1 +#endif /* * Set this to zero to remove all the debug statements via @@ -128,10 +144,12 @@ #include #include #include +#include +#include #include -#include #include +#include #if ALLOW_DMA #include #endif @@ -162,6 +180,21 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0}; static unsigned int netcard_portlist[] __initdata = { 0x0300, 0}; static unsigned int cs8900_irq_map[] = {1,0,0,0}; +#elif defined(CONFIG_MACH_IXDP2351) +static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; +static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0}; +#include +#elif defined(CONFIG_ARCH_IXDP2X01) +#include +static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; +static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; +#elif defined(CONFIG_ARCH_PNX010X) +#include +#include +#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ +#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */ +static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0}; +static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0}; #else static unsigned int netcard_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; @@ -228,6 +261,9 @@ static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer static int get_eeprom_cksum(int off, int len, int *buffer); static int set_mac_address(struct net_device *dev, void *addr); static void count_rx_errors(int status, struct net_local *lp); +#ifdef CONFIG_NET_POLL_CONTROLLER +static void net_poll_controller(struct net_device *dev); +#endif #if ALLOW_DMA static void get_dma_channel(struct net_device *dev); static void release_dma_buff(struct net_local *lp); @@ -307,13 +343,7 @@ struct net_device * __init cs89x0_probe(int unit) } if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - outw(PP_ChipID, dev->base_addr + ADD_PORT); - release_region(dev->base_addr, NETCARD_IO_EXTENT); out: free_netdev(dev); printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n"); @@ -321,30 +351,96 @@ out: } #endif -static int -readreg(struct net_device *dev, int portno) +#if defined(CONFIG_MACH_IXDP2351) +static u16 +readword(unsigned long base_addr, int portno) { - outw(portno, dev->base_addr + ADD_PORT); - return inw(dev->base_addr + DATA_PORT); + return __raw_readw(base_addr + (portno << 1)); } static void -writereg(struct net_device *dev, int portno, int value) +writeword(unsigned long base_addr, int portno, u16 value) +{ + __raw_writew(value, base_addr + (portno << 1)); +} +#elif defined(CONFIG_ARCH_IXDP2X01) +static u16 +readword(unsigned long base_addr, int portno) { - outw(portno, dev->base_addr + ADD_PORT); - outw(value, dev->base_addr + DATA_PORT); + return __raw_readl(base_addr + (portno << 1)); } -static int -readword(struct net_device *dev, int portno) +static void +writeword(unsigned long base_addr, int portno, u16 value) { - return inw(dev->base_addr + portno); + __raw_writel(value, base_addr + (portno << 1)); +} +#elif defined(CONFIG_ARCH_PNX010X) +static u16 +readword(unsigned long base_addr, int portno) +{ + return inw(base_addr + (portno << 1)); } static void -writeword(struct net_device *dev, int portno, int value) +writeword(unsigned long base_addr, int portno, u16 value) { - outw(value, dev->base_addr + portno); + outw(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 + +static void +readwords(unsigned long base_addr, int portno, void *buf, int length) +{ + u8 *buf8 = (u8 *)buf; + + do { + u16 tmp16; + + tmp16 = readword(base_addr, portno); + *buf8++ = (u8)tmp16; + *buf8++ = (u8)(tmp16 >> 8); + } while (--length); +} + +static void +writewords(unsigned long base_addr, int portno, void *buf, int length) +{ + u8 *buf8 = (u8 *)buf; + + do { + u16 tmp16; + + tmp16 = *buf8++; + tmp16 |= (*buf8++) << 8; + writeword(base_addr, portno, tmp16); + } while (--length); +} + +static u16 +readreg(struct net_device *dev, u16 regno) +{ + writeword(dev->base_addr, ADD_PORT, regno); + return readword(dev->base_addr, DATA_PORT); +} + +static void +writereg(struct net_device *dev, u16 regno, u16 value) +{ + writeword(dev->base_addr, ADD_PORT, regno); + writeword(dev->base_addr, DATA_PORT, value); } static int __init @@ -392,6 +488,19 @@ get_eeprom_cksum(int off, int len, int *buffer) return -1; } +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + */ +static void net_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + net_interrupt(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif + /* This is the real probe routine. Linux has a history of friendly device probes on the ISA bus. A good device probes avoids doing writes, and verifies that the correct device exists and functions. @@ -404,6 +513,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) struct net_local *lp = netdev_priv(dev); static unsigned version_printed; int i; + int tmp; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; int retval; @@ -425,6 +535,30 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) #endif } +#ifdef CONFIG_ARCH_PNX010X + initialize_ebi(); + + /* Map GPIO registers for the pins connected to the CS8900a. */ + if (map_cirrus_gpio() < 0) + return -ENODEV; + + reset_cirrus(); + + /* Map event-router registers. */ + if (map_event_router() < 0) + return -ENODEV; + + enable_cirrus_irq(); + + unmap_cirrus_gpio(); + unmap_event_router(); + + dev->base_addr = ioaddr; + + for (i = 0 ; i < 3 ; i++) + readreg(dev, 0); +#endif + /* Grab the region so we can find another board if autoIRQ fails. */ /* WTF is going on here? */ if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { @@ -436,8 +570,8 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) #ifdef CONFIG_SH_HICOSH4 /* truely reset the chip */ - outw(0x0114, ioaddr + ADD_PORT); - outw(0x0040, ioaddr + DATA_PORT); + writeword(ioaddr, ADD_PORT, 0x0114); + writeword(ioaddr, DATA_PORT, 0x0040); #endif /* if they give us an odd I/O address, then do ONE write to @@ -448,20 +582,24 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) if (net_debug > 1) printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr); if ((ioaddr & 2) != 2) - if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) { + if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) { printk(KERN_ERR "%s: bad signature 0x%x\n", - dev->name, inw((ioaddr & ~3)+ ADD_PORT)); + dev->name, readword(ioaddr & ~3, ADD_PORT)); retval = -ENODEV; goto out2; } - ioaddr &= ~3; - outw(PP_ChipID, ioaddr + ADD_PORT); } -printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); + printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", + ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); - if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) { - printk(KERN_ERR "%s: incorrect signature 0x%x\n", - dev->name, inw(ioaddr + DATA_PORT)); + ioaddr &= ~3; + writeword(ioaddr, ADD_PORT, PP_ChipID); + + tmp = readword(ioaddr, DATA_PORT); + if (tmp != CHIP_EISA_ID_SIG) { + printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!=" + CHIP_EISA_ID_SIG_STR "\n", + dev->name, ioaddr, DATA_PORT, tmp); retval = -ENODEV; goto out2; } @@ -665,6 +803,9 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); } else { i = lp->isa_config & INT_NO_MASK; if (lp->chip_type == CS8900) { +#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) + i = cs8900_irq_map[0]; +#else /* Translate the IRQ using the IRQ mapping table. */ if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0])) printk("\ncs89x0: invalid ISA interrupt number %d\n", i); @@ -681,6 +822,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT) lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8); } +#endif } if (!dev->irq) dev->irq = i; @@ -714,11 +856,20 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); dev->get_stats = net_get_stats; dev->set_multicast_list = set_multicast_list; dev->set_mac_address = set_mac_address; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = net_poll_controller; +#endif printk("\n"); if (net_debug) printk("cs89x0_probe1() successful\n"); + + retval = register_netdev(dev); + if (retval) + goto out3; return 0; +out3: + writeword(dev->base_addr, ADD_PORT, PP_ChipID); out2: release_region(ioaddr & ~3, NETCARD_IO_EXTENT); out1: @@ -884,26 +1035,30 @@ skip_this_frame: void __init reset_chip(struct net_device *dev) { +#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) struct net_local *lp = netdev_priv(dev); int ioaddr = dev->base_addr; +#endif int reset_start_time; writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET); /* wait 30 ms */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(30*HZ/1000); + msleep(30); +#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) if (lp->chip_type != CS8900) { /* Hardware problem requires PNP registers to be reconfigured after a reset */ - outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT); + writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); outb(dev->irq, ioaddr + DATA_PORT); outb(0, ioaddr + DATA_PORT + 1); - outw(PP_CS8920_ISAMemB, ioaddr + ADD_PORT); + writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB); outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT); outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1); } +#endif /* IXDP2x01 */ + /* Wait until the chip is reset */ reset_start_time = jiffies; while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2) @@ -1028,8 +1183,8 @@ send_test_pkt(struct net_device *dev) memcpy(test_packet, dev->dev_addr, ETH_ALEN); memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN); - writeword(dev, TX_CMD_PORT, TX_AFTER_ALL); - writeword(dev, TX_LEN_PORT, ETH_ZLEN); + writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL); + writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN); /* Test to see if the chip has allocated memory for the packet */ while (jiffies - timenow < 5) @@ -1039,7 +1194,7 @@ send_test_pkt(struct net_device *dev) return 0; /* this shouldn't happen */ /* Write the contents of the packet */ - outsw(dev->base_addr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); + writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); if (net_debug > 1) printk("Sending test packet "); /* wait a couple of jiffies for packet to be received */ @@ -1124,7 +1279,7 @@ net_open(struct net_device *dev) int i; int ret; -#ifndef CONFIG_SH_HICOSH4 /* uses irq#1, so this won't work */ +#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */ if (dev->irq < 2) { /* Allow interrupts to be generated by the chip */ /* Cirrus' release had this: */ @@ -1155,12 +1310,14 @@ net_open(struct net_device *dev) else #endif { +#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) if (((1 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); ret = -EAGAIN; goto bad_out; } +#endif /* FIXME: Cirrus' release had this: */ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ ); /* And 2.3.47 had this: */ @@ -1238,6 +1395,9 @@ net_open(struct net_device *dev) case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); } +#ifdef CONFIG_ARCH_PNX010X + result = A_CNF_10B_T; +#endif if (!result) { printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name); release_irq: @@ -1376,8 +1536,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); /* initiate a transmit sequence */ - writeword(dev, TX_CMD_PORT, lp->send_cmd); - writeword(dev, TX_LEN_PORT, skb->len); + writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd); + writeword(dev->base_addr, TX_LEN_PORT, skb->len); /* Test to see if the chip has allocated memory for the packet */ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { @@ -1391,8 +1551,9 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) return 1; } /* Write the contents of the packet */ - outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1); + writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1); spin_unlock_irq(&lp->lock); + lp->stats.tx_bytes += skb->len; dev->trans_start = jiffies; dev_kfree_skb (skb); @@ -1430,7 +1591,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs) course, if you're on a slow machine, and packets are arriving faster than you can read them off, you're screwed. Hasta la vista, baby! */ - while ((status = readword(dev, ISQ_PORT))) { + while ((status = readword(dev->base_addr, ISQ_PORT))) { if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status); handled = 1; switch(status & ISQ_EVENT_MASK) { @@ -1524,8 +1685,8 @@ net_rx(struct net_device *dev) int status, length; int ioaddr = dev->base_addr; - status = inw(ioaddr + RX_FRAME_PORT); - length = inw(ioaddr + RX_FRAME_PORT); + status = readword(ioaddr, RX_FRAME_PORT); + length = readword(ioaddr, RX_FRAME_PORT); if ((status & RX_OK) == 0) { count_rx_errors(status, lp); @@ -1544,9 +1705,9 @@ net_rx(struct net_device *dev) skb_reserve(skb, 2); /* longword align L3 header */ skb->dev = dev; - insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1); + readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1); if (length & 1) - skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT); + skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT); if (net_debug > 3) { printk( "%s: received %d byte packet of type %x\n", @@ -1566,7 +1727,7 @@ static void release_dma_buff(struct net_local *lp) { if (lp->dma_buff) { free_pages((unsigned long)(lp->dma_buff), get_order(lp->dmasize * 1024)); - lp->dma_buff = 0; + lp->dma_buff = NULL; } } #endif @@ -1575,7 +1736,9 @@ static void release_dma_buff(struct net_local *lp) static int net_close(struct net_device *dev) { +#if ALLOW_DMA struct net_local *lp = netdev_priv(dev); +#endif netif_stop_queue(dev); @@ -1685,14 +1848,14 @@ static int use_dma; /* These generate unused var warnings if ALLOW_DMA = 0 */ static int dma; static int dmasize=16; /* or 64 */ -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(debug, "i"); -MODULE_PARM(media, "c8"); -MODULE_PARM(duplex, "i"); -MODULE_PARM(dma , "i"); -MODULE_PARM(dmasize , "i"); -MODULE_PARM(use_dma , "i"); +module_param(io, int, 0); +module_param(irq, int, 0); +module_param(debug, int, 0); +module_param_string(media, media, sizeof(media), 0); +module_param(duplex, int, 0); +module_param(dma , int, 0); +module_param(dmasize , int, 0); +module_param(use_dma , int, 0); MODULE_PARM_DESC(io, "cs89x0 I/O base address"); MODULE_PARM_DESC(irq, "cs89x0 IRQ number"); #if DEBUGGING @@ -1806,13 +1969,6 @@ init_module(void) if (ret) goto out; - if (register_netdev(dev) != 0) { - printk(KERN_ERR "cs89x0.c: No card found at 0x%x\n", io); - ret = -ENXIO; - outw(PP_ChipID, dev->base_addr + ADD_PORT); - release_region(dev->base_addr, NETCARD_IO_EXTENT); - goto out; - } dev_cs89x0 = dev; return 0; out: @@ -1824,7 +1980,7 @@ void cleanup_module(void) { unregister_netdev(dev_cs89x0); - outw(PP_ChipID, dev_cs89x0->base_addr + ADD_PORT); + writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID); release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT); free_netdev(dev_cs89x0); }