diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-11 04:02:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-11 04:02:40 +0000 |
commit | e47f00743fc4776491344f2c618cc8dc2c23bcbc (patch) | |
tree | 13e03a113a82a184c51c19c209867cfd3a59b3b9 /drivers/net/hydra.c | |
parent | b2ad5f821b1381492d792ca10b1eb7a107b48f14 (diff) |
Merge with Linux 2.4.0.
Diffstat (limited to 'drivers/net/hydra.c')
-rw-r--r-- | drivers/net/hydra.c | 788 |
1 files changed, 180 insertions, 608 deletions
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index a840222af..c50444ad0 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -1,24 +1,16 @@ -/* Linux/68k Hydra Amiganet board driver v2.1 BETA */ -/* copyleft by Topi Kanerva (topi@susanna.oulu.fi) */ -/* also some code & lots of fixes by Timo Rossi (trossi@cc.jyu.fi) */ - -/* The code is mostly based on the linux/68k Ariadne driver */ -/* copyrighted by Geert Uytterhoeven (geert@linux-m68k.org) */ -/* and Peter De Schrijver (Peter.DeSchrijver@linux.cc.kuleuven.ac.be) */ +/* New Hydra driver using generic 8390 core */ +/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */ /* This file is subject to the terms and conditions of the GNU General */ /* Public License. See the file COPYING in the main directory of the */ /* Linux distribution for more details. */ +/* Peter De Schrijver (p2@mind.be) */ +/* Oldenburg 2000 */ + /* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a */ /* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM */ /* and 10BASE-2 (thin coax) and AUI connectors. */ -/* */ -/* Changes */ -/* Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/06/2000 */ -/* - check init_etherdev in hydra_probe */ -/* - dev->priv is already zeroed by init_etherdev */ - #include <linux/module.h> #include <linux/kernel.h> @@ -42,649 +34,229 @@ #include <asm/amigahw.h> #include <linux/zorro.h> -#include "hydra.h" - - -#define HYDRA_DEBUG -#undef HAVE_MULTICAST - -#define HYDRA_VERSION "v2.1 BETA" - -#undef HYDRA_DEBUG /* define this for (lots of) debugging information */ +#include "8390.h" -#if 0 /* currently hardwired to one transmit buffer */ - #define TX_RING_SIZE 5 - #define RX_RING_SIZE 16 -#else - #define TX_RING_SIZE 1 - #define RX_RING_SIZE 8 -#endif +#define NE_BASE (dev->base_addr) +#define NE_CMD (0x00*2) -#define ETHER_MIN_LEN 64 -#define ETHER_MAX_LEN 1518 -#define ETHER_ADDR_LEN 6 +#define NE_EN0_ISR (0x07*2) +#define NE_EN0_DCFG (0x0e*2) +#define NE_EN0_RSARLO (0x08*2) +#define NE_EN0_RSARHI (0x09*2) +#define NE_EN0_RCNTLO (0x0a*2) +#define NE_EN0_RXCR (0x0c*2) +#define NE_EN0_TXCR (0x0d*2) +#define NE_EN0_RCNTHI (0x0b*2) +#define NE_EN0_IMR (0x0f*2) -/* - * let's define here nice macros for writing and reading NIC registers - * - * the CIA accesses here are uses to make sure the minimum time - * requirement between NIC chip selects is met. - */ -#define WRITE_REG(reg, val) (ciaa.pra, ((u8)(*(nicbase+(reg))=val))) -#define READ_REG(reg) (ciaa.pra, ((u8)(*(nicbase+(reg))))) +#define NESM_START_PG 0x0 /* First page of TX buffer */ +#define NESM_STOP_PG 0x40 /* Last page +1 of RX ring */ -/* mask value for the interrupts we use */ -#define NIC_INTS (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW | ISR_CNT) +#define HYDRA_NIC_BASE 0xffe1 +#define HYDRA_ADDRPROM 0xffc0 +#define HYDRA_VERSION "v3.0alpha" -/* only broadcasts, no promiscuous mode for now */ -#define NIC_RCRBITS (0) +#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8)) -/* - * Private Device Data - */ -struct hydra_private -{ - u16 tx_page_start; - u16 rx_page_start; - u16 rx_page_stop; - u16 next_pkt; - struct net_device_stats stats; -}; +#ifdef MODULE +static struct net_device *root_hydra_dev = NULL; +#endif +static int __init hydra_probe(void); +static int hydra_init(unsigned long board); static int hydra_open(struct net_device *dev); -static int hydra_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void hydra_interrupt(int irq, void *data, struct pt_regs *fp); -static void __inline__ hydra_rx(struct net_device *dev, struct hydra_private *priv, volatile u8 *nicbase); static int hydra_close(struct net_device *dev); -static struct net_device_stats *hydra_get_stats(struct net_device *dev); -#ifdef HAVE_MULTICAST -static void set_multicast_list(struct net_device *dev, int num_addrs, void *addrs); -#endif - - -/* this is now coherent with the C version below, */ -/* compile the source with -D__USE_ASM__ if you */ -/* want it - it'll only be some 10% faster though */ - -#if defined (__GNUC__) && defined (__mc68000__) && defined (USE_ASM) - -static __inline__ void *memcpyw(u16 *dest, u16 *src, int len) +static void hydra_reset_8390(struct net_device *dev); +static void hydra_get_8390_hdr(struct net_device *dev, + struct e8390_pkt_hdr *hdr, int ring_page); +static void hydra_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset); +static void hydra_block_output(struct net_device *dev, int count, + const unsigned char *buf, int start_page); +static void __exit hydra_cleanup(void); + +static int __init hydra_probe(void) { - __asm__(" move.l %0,%/a1; move.l %1,%/a0; move.l %2,%/d0 \n\t" - " cmpi.l #2,%/d0 \n\t" - "1: bcs.s 2f \n\t" - " move.w %/a0@+,%/a1@+ \n\t" - " subq.l #2,%/d0 \n\t" - " bra.s 1b \n\t" - "2: cmpi.l #1,%/d0 \n\t" - " bne.s 3f \n\t" - " move.w %/a0@,%/d0 \n\t" - " swap.w %/d0 \n\t" - " move.b %/d0,%/a1@ \n\t" - "3: moveq #0,%/d0 \n\t" - : - : "g" (dest), "g" (src), "g" (len) - : "a1", "a0", "d0"); - return; + struct zorro_dev *z = NULL; + unsigned long board; + int err = -ENODEV; + + if (load_8390_module("hydra.c")) + return -ENOSYS; + + while ((z = zorro_find_device(ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET, z))) { + board = z->resource.start; + if (!request_mem_region(board, 0x10000, "Hydra")) + continue; + if ((err = hydra_init(ZTWO_VADDR(board)))) { + release_mem_region(board, 0x10000); + return err; + } + err = 0; + } + + if (err == -ENODEV) { + printk("No Hydra ethernet card found.\n"); + unload_8390_module(); + } + return err; } -#else - -/* hydra memory can only be read or written as words or longwords. */ -/* that will mean that we'll have to write a special memcpy for it. */ -/* this one here relies on the fact that _writes_ to hydra memory */ -/* are guaranteed to be of even length. (reads can be arbitrary) */ - -/* - * FIXME: Surely we should be using the OS generic stuff and do - * - * memcpy(dest,src,(len+1)&~1); - * - * Can a 68K guy with this card check that ? - better yet - * use a copy/checksum on it. - */ - -static void memcpyw(u16 *dest, u16 *src, int len) +int __init hydra_init(unsigned long board) { - if(len & 1) - len++; + struct net_device *dev; + unsigned long ioaddr = board+HYDRA_NIC_BASE; + const char *name = NULL; + int start_page, stop_page; + int j; + + static u32 hydra_offsets[16] = { + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, + 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, + }; + + dev = init_etherdev(0, 0); + if (!dev) + return -ENOMEM; + + for(j = 0; j < ETHER_ADDR_LEN; j++) + dev->dev_addr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j)); + + /* We must set the 8390 for word mode. */ + writeb(0x4b, ioaddr + NE_EN0_DCFG); + start_page = NESM_START_PG; + stop_page = NESM_STOP_PG; + + dev->base_addr = ioaddr; + dev->irq = IRQ_AMIGA_PORTS; + + /* Install the Interrupt handler */ + if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, "Hydra Ethernet", + dev)) + return -EAGAIN; + + /* Allocate dev->priv and fill in 8390 specific dev fields. */ + if (ethdev_init(dev)) { + printk("Unable to get memory for dev->priv.\n"); + return -ENOMEM; + } - while (len >= 2) - { - *(dest++) = *(src++); - len -= 2; - } -} + name = "NE2000"; -#endif + printk("%s: hydra at 0x%08lx, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n", dev->name, ZTWO_PADDR(board), + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); -int __init hydra_probe(struct net_device *dev) -{ - struct zorro_dev *z = NULL; - int j; + ei_status.name = name; + ei_status.tx_start_page = start_page; + ei_status.stop_page = stop_page; + ei_status.word16 = 1; + ei_status.bigendian = 1; -#ifdef HYDRA_DEBUG - printk("hydra_probe(%x)\n", dev); -#endif + ei_status.rx_start_page = start_page + TX_PAGES; - while ((z = zorro_find_device(ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET, z))) { - unsigned long board = z->resource.start; - unsigned long base_addr = board+HYDRA_NIC_BASE; - - if (!request_mem_region(base_addr, 0x20, "NS8390")) - continue; - if (!request_mem_region(board, 0x4000, "RAM")) { - release_mem_region(base_addr, 0x20); - continue; - } - - dev = init_etherdev(NULL, sizeof(struct hydra_private)); - - if (!dev) { - release_mem_region(base_addr, 0x20); - release_mem_region(board, 0x4000); - continue; - } - SET_MODULE_OWNER(dev); - - for(j = 0; j < ETHER_ADDR_LEN; j++) - dev->dev_addr[j] = *((u8 *)ZTWO_VADDR(board + HYDRA_ADDRPROM + 2*j)); - - printk("%s: hydra at 0x%08x, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n", - dev->name, (int)board, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - - dev->base_addr = ZTWO_VADDR(base_addr); - dev->mem_start = ZTWO_VADDR(board); - dev->mem_end = dev->mem_start+0x4000; - - dev->open = &hydra_open; - dev->stop = &hydra_close; - dev->hard_start_xmit = &hydra_start_xmit; - dev->get_stats = &hydra_get_stats; -#ifdef HAVE_MULTICAST - dev->set_multicast_list = &set_multicast_list; + ei_status.reset_8390 = &hydra_reset_8390; + ei_status.block_input = &hydra_block_input; + ei_status.block_output = &hydra_block_output; + ei_status.get_8390_hdr = &hydra_get_8390_hdr; + ei_status.reg_offset = hydra_offsets; + dev->open = &hydra_open; + dev->stop = &hydra_close; +#ifdef MODULE + ei_status.priv = (unsigned long)root_hydra_dev; + root_hydra_dev = dev; #endif - - /* - * Cannot yet do multicast - */ - dev->flags&=~IFF_MULTICAST; - return(0); - } - return(-ENODEV); + NS8390_init(dev, 0); + return 0; } - static int hydra_open(struct net_device *dev) { - struct hydra_private *priv = (struct hydra_private *)dev->priv; - volatile u8 *nicbase = (u8 *)dev->base_addr; - int i; - -#ifdef HYDRA_DEBUG - printk("hydra_open(0x%x)\n", dev); -#endif - - /* first, initialize the private structure */ - priv->tx_page_start = 0; /* these are 256 byte buffers for NS8390 */ - priv->rx_page_start = 6; - priv->rx_page_stop = 62; /* these values are hard coded for now */ - - /* Reset the NS8390 NIC */ - WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP); - - /* be sure that the NIC is in stopped state */ - while(!(READ_REG(NIC_ISR) & ISR_RST)); - - /* word transfer, big endian bytes, loopback, FIFO threshold 4 bytes */ - WRITE_REG(NIC_DCR, DCR_WTS | DCR_BOS | DCR_LS | DCR_FT0); - - /* clear remote byte count registers */ - WRITE_REG(NIC_RBCR0, 0); - WRITE_REG(NIC_RBCR1, 0); - - /* accept packets addressed to this card and also broadcast packets */ - WRITE_REG(NIC_RCR, NIC_RCRBITS); - - /* enable loopback mode 1 */ - WRITE_REG(NIC_TCR, TCR_LB1); - - /* initialize receive buffer ring */ - WRITE_REG(NIC_PSTART, priv->rx_page_start); - WRITE_REG(NIC_PSTOP, priv->rx_page_stop); - WRITE_REG(NIC_BNDRY, priv->rx_page_start); - - /* clear interrupts */ - WRITE_REG(NIC_ISR, 0xff); - - /* enable interrupts */ - WRITE_REG(NIC_IMR, NIC_INTS); - - /* set the ethernet hardware address */ - WRITE_REG(NIC_CR, CR_PAGE1 | CR_NODMA | CR_STOP); /* goto page 1 */ - - WRITE_REG(NIC_PAR0, dev->dev_addr[0]); - WRITE_REG(NIC_PAR1, dev->dev_addr[1]); - WRITE_REG(NIC_PAR2, dev->dev_addr[2]); - WRITE_REG(NIC_PAR3, dev->dev_addr[3]); - WRITE_REG(NIC_PAR4, dev->dev_addr[4]); - WRITE_REG(NIC_PAR5, dev->dev_addr[5]); - - /* clear multicast hash table */ - for(i = 0; i < 8; i++) - WRITE_REG(NIC_MAR0 + 2*i, 0); - - priv->next_pkt = priv->rx_page_start+1; /* init our s/w variable */ - WRITE_REG(NIC_CURR, priv->next_pkt); /* set the next buf for current */ - - /* goto page 0, start NIC */ - WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START); - - /* take interface out of loopback */ - WRITE_REG(NIC_TCR, 0); - - netif_start_queue(dev); - - i = request_irq(IRQ_AMIGA_PORTS, hydra_interrupt, SA_SHIRQ, - dev->name, dev); - if (i) return i; - - return(0); + ei_open(dev); + MOD_INC_USE_COUNT; + return 0; } - static int hydra_close(struct net_device *dev) { - struct hydra_private *priv = (struct hydra_private *)dev->priv; - volatile u8 *nicbase = (u8 *)dev->base_addr; - int n = 5000; - - netif_stop_queue(dev); - -#ifdef HYDRA_DEBUG - printk("%s: Shutting down ethercard\n", dev->name); - printk("%s: %d packets missed\n", dev->name, priv->stats.rx_missed_errors); -#endif - - WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP); - - /* wait for NIC to stop (what a nice timeout..) */ - while(((READ_REG(NIC_ISR) & ISR_RST) == 0) && --n); - - free_irq(IRQ_AMIGA_PORTS, dev); - - return(0); + if (ei_debug > 1) + printk("%s: Shutting down ethercard.\n", dev->name); + ei_close(dev); + MOD_DEC_USE_COUNT; + return 0; } - -static void hydra_interrupt(int irq, void *data, struct pt_regs *fp) -{ - volatile u8 *nicbase; - - struct net_device *dev = (struct net_device *) data; - struct hydra_private *priv; - u16 intbits; - - if(dev == NULL) - { - printk("hydra_interrupt(): irq for unknown device\n"); - return; - } - - /* this is not likely a problem - i think */ - if(dev->interrupt) - printk("%s: re-entering the interrupt handler\n", dev->name); - - dev->interrupt = 1; - - priv = (struct hydra_private *) dev->priv; - nicbase = (u8 *)dev->base_addr; - - /* select page 0 */ - WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA); - - intbits = READ_REG(NIC_ISR) & NIC_INTS; - if(intbits == 0) - { - dev->interrupt = 0; - return; - } - - /* acknowledge all interrupts, by clearing the interrupt flag */ - WRITE_REG(NIC_ISR, intbits); - - if((intbits & ISR_PTX) && !(intbits & ISR_TXE)) - { - dev->tbusy = 0; - mark_bh(NET_BH); - } - - if((intbits & ISR_PRX) && !(intbits & ISR_RXE))/* packet received OK */ - hydra_rx(dev, priv, nicbase); - - if(intbits & ISR_TXE) - priv->stats.tx_errors++; - - if(intbits & ISR_RXE) - priv->stats.rx_errors++; - - if(intbits & ISR_CNT) - { - /* - * read the tally counters and (currently) ignore the values - * might be useful because of bugs of some versions of the 8390 NIC - */ -#ifdef HYDRA_DEBUG - printk("hydra_interrupt(): ISR_CNT\n"); -#endif - (void)READ_REG(NIC_CNTR0); - (void)READ_REG(NIC_CNTR1); - (void)READ_REG(NIC_CNTR2); - } - - if(intbits & ISR_OVW) - { -#ifdef HYDRA_DEBUG - WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA); -/* another one just too much for me to comprehend - basically this could */ -/* only occur because of invalid access to hydra ram, thus invalidating */ -/* the interrupt bits read - in average usage these do not occur at all */ - printk("hydra_interrupt(): overwrite warning, NIC_ISR %02x, NIC_CURR %02x\n", - intbits, READ_REG(NIC_CURR)); - WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA); -#endif - - - /* overwrite warning occurred, stop NIC & check the BOUNDARY pointer */ - /* FIXME - real overwrite handling needed !! */ - - printk("hydra_interrupt(): overwrite warning, resetting NIC\n"); - WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP); - while(!(READ_REG(NIC_ISR) & ISR_RST)); - /* wait for NIC to reset */ - WRITE_REG(NIC_DCR, DCR_WTS | DCR_BOS | DCR_LS | DCR_FT0); - WRITE_REG(NIC_RBCR0, 0); - WRITE_REG(NIC_RBCR1, 0); - WRITE_REG(NIC_RCR, NIC_RCRBITS); - WRITE_REG(NIC_TCR, TCR_LB1); - WRITE_REG(NIC_PSTART, priv->rx_page_start); - WRITE_REG(NIC_PSTOP, priv->rx_page_stop); - WRITE_REG(NIC_BNDRY, priv->rx_page_start); - WRITE_REG(NIC_ISR, 0xff); - WRITE_REG(NIC_IMR, NIC_INTS); - /* currently this _won't_ reset my hydra, even though it is */ - /* basically the same code as in the board init - any ideas? */ - - priv->next_pkt = priv->rx_page_start+1; /* init our s/w variable */ - WRITE_REG(NIC_CURR, priv->next_pkt); /* set the next buf for current */ - - WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START); - - WRITE_REG(NIC_TCR, 0); - } - - dev->interrupt = 0; - return; - } - - -/* - * packet transmit routine - */ - -static int hydra_start_xmit(struct sk_buff *skb, struct net_device *dev) +static void hydra_reset_8390(struct net_device *dev) { - struct hydra_private *priv = (struct hydra_private *)dev->priv; - volatile u8 *nicbase = (u8 *)dev->base_addr; - int len, len1; - - /* Transmitter timeout, serious problems. */ - - if(dev->tbusy) - { - int tickssofar = jiffies - dev->trans_start; - if(tickssofar < 20) - return(1); - WRITE_REG(NIC_CR, CR_STOP); - printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, 0); - priv->stats.tx_errors++; - dev->tbusy = 0; - dev->trans_start = jiffies; - return(0); - } - - len=skb->len; - - /* fill in a tx ring entry */ - -#ifdef HYDRA_DEBUG - printk("TX pkt type 0x%04x from ", ((u16 *)skb->data)[6]); - { - int i; - u8 *ptr = &((u8 *)skb->data)[6]; - for (i = 0; i < 6; i++) - printk("%02x", ptr[i]); - } - printk(" to "); - { - int i; - u8 *ptr = (u8 *)skb->data; - for (i = 0; i < 6; i++) - printk("%02x", ptr[i]); - } - printk(" data 0x%08x len %d\n", (int)skb->data, len); -#endif - - /* - * make sure that the packet size is at least the minimum - * allowed ethernet packet length. - * (FIXME: Should also clear the unused space...) - * note: minimum packet length is 64, including CRC - */ - len1 = len; - - if(len < (ETHER_MIN_LEN-4)) - len = (ETHER_MIN_LEN-1); - - /* make sure we've got an even number of bytes to copy to hydra's mem */ - if(len & 1) len++; - - if((u32)(dev->mem_start + (priv->tx_page_start << 8)) < 0x80000000) - printk("weirdness: memcpyw(txbuf, skbdata, len): txbuf = 0x%x\n", (u_int)(dev->mem_start+(priv->tx_page_start<<8))); - - /* copy the packet data to the transmit buffer - in the ethernet card RAM */ - memcpyw((u16 *)(dev->mem_start + (priv->tx_page_start << 8)), - (u16 *)skb->data, len); - /* clear the unused space */ - for(; len1<len; len1++) - (u16)*((u8 *)dev->mem_start + (priv->tx_page_start<<8) + len1) - = 0; - dev_kfree_skb(skb); - - priv->stats.tx_packets++; - - cli(); - /* make sure we are on the correct page */ - WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START); - - /* here we configure the transmit page start register etc */ - /* notice that this code is hardwired to one transmit buffer */ - WRITE_REG(NIC_TPSR, priv->tx_page_start); - WRITE_REG(NIC_TBCR0, len & 0xff); - WRITE_REG(NIC_TBCR1, len >> 8); - - /* commit the packet to the wire */ - WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA | CR_TXP); - sti(); - - dev->trans_start = jiffies; - - return(0); + printk("Hydra hw reset not there\n"); } - -static void __inline__ hydra_rx(struct net_device *dev, struct hydra_private *priv, volatile u8 *nicbase) +static void hydra_get_8390_hdr(struct net_device *dev, + struct e8390_pkt_hdr *hdr, int ring_page) { - volatile u16 *board_ram_ptr; - struct sk_buff *skb; - int hdr_next_pkt, pkt_len, len1, boundary; - - - /* remove packet(s) from the ring and commit them to TCP layer */ - WRITE_REG(NIC_CR, CR_PAGE1 | CR_NODMA | CR_START); /* page 1 */ - while(priv->next_pkt != READ_REG(NIC_CURR)) /* should read this only once? */ - { - board_ram_ptr = (u16 *)(dev->mem_start + (priv->next_pkt << 8)); - -#ifdef HYDRA_DEBUG - printk("next_pkt = 0x%x, board_ram_ptr = 0x%x\n", priv->next_pkt, board_ram_ptr); -#endif - - /* the following must be done with two steps, or - GCC optimizes it to a byte access to Hydra memory, - which doesn't work... */ - hdr_next_pkt = board_ram_ptr[0]; - hdr_next_pkt >>= 8; - - pkt_len = board_ram_ptr[1]; - pkt_len = ((pkt_len >> 8) | ((pkt_len & 0xff) << 8)); - -#ifdef HYDRA_DEBUG - printk("hydra_interrupt(): hdr_next_pkt = 0x%02x, len = %d\n", hdr_next_pkt, pkt_len); -#endif - - if(pkt_len >= ETHER_MIN_LEN && pkt_len <= ETHER_MAX_LEN) - { - /* note that board_ram_ptr is u16 */ - /* CRC is not included in the packet length */ - - pkt_len -= 4; - skb = dev_alloc_skb(pkt_len+2); - if(skb == NULL) - { - printk(KERN_INFO "%s: memory squeeze, dropping packet.\n", dev->name); - priv->stats.rx_dropped++; - } - else - { - skb->dev = dev; - skb_reserve(skb, 2); - if(hdr_next_pkt < priv->next_pkt && hdr_next_pkt != priv->rx_page_start) - { - /* here, the packet is wrapped */ - len1 = ((priv->rx_page_stop - priv->next_pkt)<<8)-4; - - memcpyw((u16 *)skb_put(skb, len1), (u16 *)(board_ram_ptr+2), len1); - memcpyw((u16 *)skb_put(skb, pkt_len-len1), (u16 *)(dev->mem_start+(priv->rx_page_start<<8)), pkt_len-len1); - -#ifdef HYDRA_DEBUG - printk("wrapped packet: %d/%d bytes\n", len1, pkt_len-len1); -#endif - } /* ... here, packet is not wrapped */ - else - memcpyw((u16 *) skb_put(skb, pkt_len), (u16 *)(board_ram_ptr+2), pkt_len); - } - } - else - { - WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA); - printk("hydra_interrupt(): invalid packet len: %d, NIC_CURR = %02x\n", pkt_len, READ_REG(NIC_CURR)); -/* -this is the error i kept getting until i switched to 0.9.10. it still doesn't -mean that the bug would have gone away - so be alarmed. the packet is likely -being fetched from a wrong memory location - but why - dunno - -note-for-v2.1: not really problem anymore. hasn't been for a long time. -*/ - - WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA); - /* should probably reset the NIC here ?? */ - - hydra_open(dev); /* FIXME - i shouldn't really be doing this. */ - return; - } - - /* now, update the next_pkt pointer */ - if(hdr_next_pkt < priv->rx_page_stop) - priv->next_pkt = hdr_next_pkt; - else - printk("hydra_interrupt(): invalid next_pkt pointer %d\n", hdr_next_pkt); - - /* update the boundary pointer */ - boundary = priv->next_pkt - 1; - if(boundary < priv->rx_page_start) - boundary = priv->rx_page_stop - 1; - - /* set NIC to page 0 to update the NIC_BNDRY register */ - WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA); - WRITE_REG(NIC_BNDRY, boundary); - - /* select page1 to access the NIC_CURR register */ - WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA); - - - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - priv->stats.rx_packets++; - - } - return; + int nic_base = dev->base_addr; + short *ptrs; + unsigned long hdr_start= (nic_base-HYDRA_NIC_BASE) + + ((ring_page - NESM_START_PG)<<8); + ptrs = (short *)hdr; + + *(ptrs++) = readw(hdr_start); + *((short *)hdr) = WORDSWAP(*((short *)hdr)); + hdr_start += 2; + *(ptrs++) = readw(hdr_start); + *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1)); } - -static struct net_device_stats *hydra_get_stats(struct net_device *dev) +static void hydra_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset) { - struct hydra_private *priv = (struct hydra_private *)dev->priv; -#if 0 - u8 *board = (u8 *)dev->mem_start; + unsigned long nic_base = dev->base_addr; + unsigned long mem_base = nic_base - HYDRA_NIC_BASE; + unsigned long xfer_start = mem_base + ring_offset - (NESM_START_PG<<8); - short saved_addr; -#endif -/* currently does nothing :) i'll finish this later */ + if (count&1) + count++; - return(&priv->stats); -} + if (xfer_start+count > mem_base + (NESM_STOP_PG<<8)) { + int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start; -#ifdef HAVE_MULTICAST -static void set_multicast_list(struct net_device *dev, int num_addrs, void *addrs) -{ - struct hydra_private *priv = (struct hydra_private *)dev->priv; - u8 *board = (u8 *)dev->mem_start; + memcpy_fromio(skb->data,xfer_start,semi_count); + count -= semi_count; + memcpy_fromio(skb->data+semi_count, mem_base, count); + } else + memcpy_fromio(skb->data, xfer_start,count); - /* yes, this code is also waiting for someone to complete.. :) */ - /* (personally i don't care about multicasts at all :) */ - return; } -#endif - - -#ifdef MODULE -static struct net_device hydra_dev; -int init_module(void) +static void hydra_block_output(struct net_device *dev, int count, + const unsigned char *buf, int start_page) { - int err; + unsigned long nic_base = dev->base_addr; + unsigned long mem_base = nic_base - HYDRA_NIC_BASE; - hydra_dev.init = hydra_probe; - if ((err = register_netdev(&hydra_dev))) { - if (err == -EIO) - printk("No Hydra board found. Module not loaded.\n"); - return(err); - } - return(0); + if (count&1) + count++; + + memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count); } -void cleanup_module(void) +static void __exit hydra_cleanup(void) { - struct hydra_private *priv = (struct hydra_private *)hydra_dev.priv; +#ifdef MODULE + struct net_device *dev, *next; - unregister_netdev(&hydra_dev); - release_mem_region(ZTWO_PADDR(hydra_dev.base_addr), 0x20); - release_mem_region(ZTWO_PADDR(hydra_dev.mem_start), 0x4000); - kfree(priv); + while ((dev = root_hydra_dev)) { + next = (struct net_device *)(ei_status.priv); + unregister_netdev(dev); + free_irq(IRQ_AMIGA_PORTS, dev); + release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000); + kfree(dev); + root_hydra_dev = next; + } + unload_8390_module(); +#endif } -#endif /* MODULE */ +module_init(hydra_probe); +module_exit(hydra_cleanup); |