1644570b8SJeff Kirsher /* 2644570b8SJeff Kirsher * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200 3644570b8SJeff Kirsher * 4644570b8SJeff Kirsher * (C) Copyright 1997 Alain Malek 5644570b8SJeff Kirsher * (Alain.Malek@cryogen.com) 6644570b8SJeff Kirsher * 7644570b8SJeff Kirsher * ---------------------------------------------------------------------------- 8644570b8SJeff Kirsher * 9644570b8SJeff Kirsher * This program is based on 10644570b8SJeff Kirsher * 11644570b8SJeff Kirsher * ne.c: A general non-shared-memory NS8390 ethernet driver for linux 12644570b8SJeff Kirsher * Written 1992-94 by Donald Becker. 13644570b8SJeff Kirsher * 14644570b8SJeff Kirsher * 8390.c: A general NS8390 ethernet driver core for linux. 15644570b8SJeff Kirsher * Written 1992-94 by Donald Becker. 16644570b8SJeff Kirsher * 17644570b8SJeff Kirsher * cnetdevice: A Sana-II ethernet driver for AmigaOS 18644570b8SJeff Kirsher * Written by Bruce Abbott (bhabbott@inhb.co.nz) 19644570b8SJeff Kirsher * 20644570b8SJeff Kirsher * ---------------------------------------------------------------------------- 21644570b8SJeff Kirsher * 22644570b8SJeff Kirsher * This file is subject to the terms and conditions of the GNU General Public 23644570b8SJeff Kirsher * License. See the file COPYING in the main directory of the Linux 24644570b8SJeff Kirsher * distribution for more details. 25644570b8SJeff Kirsher * 26644570b8SJeff Kirsher * ---------------------------------------------------------------------------- 27644570b8SJeff Kirsher * 28644570b8SJeff Kirsher */ 29644570b8SJeff Kirsher 30644570b8SJeff Kirsher 31644570b8SJeff Kirsher #include <linux/module.h> 32644570b8SJeff Kirsher #include <linux/kernel.h> 33644570b8SJeff Kirsher #include <linux/errno.h> 34644570b8SJeff Kirsher #include <linux/pci.h> 35644570b8SJeff Kirsher #include <linux/init.h> 36644570b8SJeff Kirsher #include <linux/delay.h> 37644570b8SJeff Kirsher #include <linux/netdevice.h> 38644570b8SJeff Kirsher #include <linux/etherdevice.h> 39644570b8SJeff Kirsher #include <linux/interrupt.h> 40644570b8SJeff Kirsher #include <linux/jiffies.h> 41644570b8SJeff Kirsher 42644570b8SJeff Kirsher #include <asm/system.h> 43644570b8SJeff Kirsher #include <asm/io.h> 44644570b8SJeff Kirsher #include <asm/setup.h> 45644570b8SJeff Kirsher #include <asm/amigaints.h> 46644570b8SJeff Kirsher #include <asm/amigahw.h> 47644570b8SJeff Kirsher #include <asm/amigayle.h> 48644570b8SJeff Kirsher #include <asm/amipcmcia.h> 49644570b8SJeff Kirsher 50644570b8SJeff Kirsher #include "8390.h" 51644570b8SJeff Kirsher 52644570b8SJeff Kirsher /* ---- No user-serviceable parts below ---- */ 53644570b8SJeff Kirsher 54644570b8SJeff Kirsher #define DRV_NAME "apne" 55644570b8SJeff Kirsher 56644570b8SJeff Kirsher #define NE_BASE (dev->base_addr) 57644570b8SJeff Kirsher #define NE_CMD 0x00 58644570b8SJeff Kirsher #define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ 59644570b8SJeff Kirsher #define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ 60644570b8SJeff Kirsher #define NE_IO_EXTENT 0x20 61644570b8SJeff Kirsher 62644570b8SJeff Kirsher #define NE_EN0_ISR 0x07 63644570b8SJeff Kirsher #define NE_EN0_DCFG 0x0e 64644570b8SJeff Kirsher 65644570b8SJeff Kirsher #define NE_EN0_RSARLO 0x08 66644570b8SJeff Kirsher #define NE_EN0_RSARHI 0x09 67644570b8SJeff Kirsher #define NE_EN0_RCNTLO 0x0a 68644570b8SJeff Kirsher #define NE_EN0_RXCR 0x0c 69644570b8SJeff Kirsher #define NE_EN0_TXCR 0x0d 70644570b8SJeff Kirsher #define NE_EN0_RCNTHI 0x0b 71644570b8SJeff Kirsher #define NE_EN0_IMR 0x0f 72644570b8SJeff Kirsher 73644570b8SJeff Kirsher #define NE1SM_START_PG 0x20 /* First page of TX buffer */ 74644570b8SJeff Kirsher #define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ 75644570b8SJeff Kirsher #define NESM_START_PG 0x40 /* First page of TX buffer */ 76644570b8SJeff Kirsher #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ 77644570b8SJeff Kirsher 78644570b8SJeff Kirsher 79644570b8SJeff Kirsher struct net_device * __init apne_probe(int unit); 80644570b8SJeff Kirsher static int apne_probe1(struct net_device *dev, int ioaddr); 81644570b8SJeff Kirsher 82644570b8SJeff Kirsher static void apne_reset_8390(struct net_device *dev); 83644570b8SJeff Kirsher static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, 84644570b8SJeff Kirsher int ring_page); 85644570b8SJeff Kirsher static void apne_block_input(struct net_device *dev, int count, 86644570b8SJeff Kirsher struct sk_buff *skb, int ring_offset); 87644570b8SJeff Kirsher static void apne_block_output(struct net_device *dev, const int count, 88644570b8SJeff Kirsher const unsigned char *buf, const int start_page); 89644570b8SJeff Kirsher static irqreturn_t apne_interrupt(int irq, void *dev_id); 90644570b8SJeff Kirsher 91644570b8SJeff Kirsher static int init_pcmcia(void); 92644570b8SJeff Kirsher 93644570b8SJeff Kirsher /* IO base address used for nic */ 94644570b8SJeff Kirsher 95644570b8SJeff Kirsher #define IOBASE 0x300 96644570b8SJeff Kirsher 97644570b8SJeff Kirsher /* 98644570b8SJeff Kirsher use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand 99644570b8SJeff Kirsher you can find the values to use by looking at the cnet.device 100644570b8SJeff Kirsher config file example (the default values are for the CNET40BC card) 101644570b8SJeff Kirsher */ 102644570b8SJeff Kirsher 103644570b8SJeff Kirsher /* 104644570b8SJeff Kirsher #define MANUAL_CONFIG 0x20 105644570b8SJeff Kirsher #define MANUAL_OFFSET 0x3f8 106644570b8SJeff Kirsher 107644570b8SJeff Kirsher #define MANUAL_HWADDR0 0x00 108644570b8SJeff Kirsher #define MANUAL_HWADDR1 0x12 109644570b8SJeff Kirsher #define MANUAL_HWADDR2 0x34 110644570b8SJeff Kirsher #define MANUAL_HWADDR3 0x56 111644570b8SJeff Kirsher #define MANUAL_HWADDR4 0x78 112644570b8SJeff Kirsher #define MANUAL_HWADDR5 0x9a 113644570b8SJeff Kirsher */ 114644570b8SJeff Kirsher 115644570b8SJeff Kirsher static const char version[] = 116644570b8SJeff Kirsher "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n"; 117644570b8SJeff Kirsher 118644570b8SJeff Kirsher static int apne_owned; /* signal if card already owned */ 119644570b8SJeff Kirsher 120644570b8SJeff Kirsher struct net_device * __init apne_probe(int unit) 121644570b8SJeff Kirsher { 122644570b8SJeff Kirsher struct net_device *dev; 123644570b8SJeff Kirsher #ifndef MANUAL_CONFIG 124644570b8SJeff Kirsher char tuple[8]; 125644570b8SJeff Kirsher #endif 126644570b8SJeff Kirsher int err; 127644570b8SJeff Kirsher 128644570b8SJeff Kirsher if (!MACH_IS_AMIGA) 129644570b8SJeff Kirsher return ERR_PTR(-ENODEV); 130644570b8SJeff Kirsher 131644570b8SJeff Kirsher if (apne_owned) 132644570b8SJeff Kirsher return ERR_PTR(-ENODEV); 133644570b8SJeff Kirsher 134644570b8SJeff Kirsher if ( !(AMIGAHW_PRESENT(PCMCIA)) ) 135644570b8SJeff Kirsher return ERR_PTR(-ENODEV); 136644570b8SJeff Kirsher 137644570b8SJeff Kirsher printk("Looking for PCMCIA ethernet card : "); 138644570b8SJeff Kirsher 139644570b8SJeff Kirsher /* check if a card is inserted */ 140644570b8SJeff Kirsher if (!(PCMCIA_INSERTED)) { 141644570b8SJeff Kirsher printk("NO PCMCIA card inserted\n"); 142644570b8SJeff Kirsher return ERR_PTR(-ENODEV); 143644570b8SJeff Kirsher } 144644570b8SJeff Kirsher 145644570b8SJeff Kirsher dev = alloc_ei_netdev(); 146644570b8SJeff Kirsher if (!dev) 147644570b8SJeff Kirsher return ERR_PTR(-ENOMEM); 148644570b8SJeff Kirsher if (unit >= 0) { 149644570b8SJeff Kirsher sprintf(dev->name, "eth%d", unit); 150644570b8SJeff Kirsher netdev_boot_setup_check(dev); 151644570b8SJeff Kirsher } 152644570b8SJeff Kirsher 153644570b8SJeff Kirsher /* disable pcmcia irq for readtuple */ 154644570b8SJeff Kirsher pcmcia_disable_irq(); 155644570b8SJeff Kirsher 156644570b8SJeff Kirsher #ifndef MANUAL_CONFIG 157644570b8SJeff Kirsher if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) || 158644570b8SJeff Kirsher (tuple[2] != CISTPL_FUNCID_NETWORK)) { 159644570b8SJeff Kirsher printk("not an ethernet card\n"); 160644570b8SJeff Kirsher /* XXX: shouldn't we re-enable irq here? */ 161644570b8SJeff Kirsher free_netdev(dev); 162644570b8SJeff Kirsher return ERR_PTR(-ENODEV); 163644570b8SJeff Kirsher } 164644570b8SJeff Kirsher #endif 165644570b8SJeff Kirsher 166644570b8SJeff Kirsher printk("ethernet PCMCIA card inserted\n"); 167644570b8SJeff Kirsher 168644570b8SJeff Kirsher if (!init_pcmcia()) { 169644570b8SJeff Kirsher /* XXX: shouldn't we re-enable irq here? */ 170644570b8SJeff Kirsher free_netdev(dev); 171644570b8SJeff Kirsher return ERR_PTR(-ENODEV); 172644570b8SJeff Kirsher } 173644570b8SJeff Kirsher 174644570b8SJeff Kirsher if (!request_region(IOBASE, 0x20, DRV_NAME)) { 175644570b8SJeff Kirsher free_netdev(dev); 176644570b8SJeff Kirsher return ERR_PTR(-EBUSY); 177644570b8SJeff Kirsher } 178644570b8SJeff Kirsher 179644570b8SJeff Kirsher err = apne_probe1(dev, IOBASE); 180644570b8SJeff Kirsher if (err) { 181644570b8SJeff Kirsher release_region(IOBASE, 0x20); 182644570b8SJeff Kirsher free_netdev(dev); 183644570b8SJeff Kirsher return ERR_PTR(err); 184644570b8SJeff Kirsher } 185644570b8SJeff Kirsher err = register_netdev(dev); 186644570b8SJeff Kirsher if (!err) 187644570b8SJeff Kirsher return dev; 188644570b8SJeff Kirsher 189644570b8SJeff Kirsher pcmcia_disable_irq(); 190644570b8SJeff Kirsher free_irq(IRQ_AMIGA_PORTS, dev); 191644570b8SJeff Kirsher pcmcia_reset(); 192644570b8SJeff Kirsher release_region(IOBASE, 0x20); 193644570b8SJeff Kirsher free_netdev(dev); 194644570b8SJeff Kirsher return ERR_PTR(err); 195644570b8SJeff Kirsher } 196644570b8SJeff Kirsher 197644570b8SJeff Kirsher static int __init apne_probe1(struct net_device *dev, int ioaddr) 198644570b8SJeff Kirsher { 199644570b8SJeff Kirsher int i; 200644570b8SJeff Kirsher unsigned char SA_prom[32]; 201644570b8SJeff Kirsher int wordlength = 2; 202644570b8SJeff Kirsher const char *name = NULL; 203644570b8SJeff Kirsher int start_page, stop_page; 204644570b8SJeff Kirsher #ifndef MANUAL_HWADDR0 205644570b8SJeff Kirsher int neX000, ctron; 206644570b8SJeff Kirsher #endif 207644570b8SJeff Kirsher static unsigned version_printed; 208644570b8SJeff Kirsher 209644570b8SJeff Kirsher if (ei_debug && version_printed++ == 0) 210644570b8SJeff Kirsher printk(version); 211644570b8SJeff Kirsher 212644570b8SJeff Kirsher printk("PCMCIA NE*000 ethercard probe"); 213644570b8SJeff Kirsher 214644570b8SJeff Kirsher /* Reset card. Who knows what dain-bramaged state it was left in. */ 215644570b8SJeff Kirsher { unsigned long reset_start_time = jiffies; 216644570b8SJeff Kirsher 217644570b8SJeff Kirsher outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); 218644570b8SJeff Kirsher 219644570b8SJeff Kirsher while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) 220644570b8SJeff Kirsher if (time_after(jiffies, reset_start_time + 2*HZ/100)) { 221644570b8SJeff Kirsher printk(" not found (no reset ack).\n"); 222644570b8SJeff Kirsher return -ENODEV; 223644570b8SJeff Kirsher } 224644570b8SJeff Kirsher 225644570b8SJeff Kirsher outb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */ 226644570b8SJeff Kirsher } 227644570b8SJeff Kirsher 228644570b8SJeff Kirsher #ifndef MANUAL_HWADDR0 229644570b8SJeff Kirsher 230644570b8SJeff Kirsher /* Read the 16 bytes of station address PROM. 231644570b8SJeff Kirsher We must first initialize registers, similar to NS8390_init(eifdev, 0). 232644570b8SJeff Kirsher We can't reliably read the SAPROM address without this. 233644570b8SJeff Kirsher (I learned the hard way!). */ 234644570b8SJeff Kirsher { 235644570b8SJeff Kirsher struct {unsigned long value, offset; } program_seq[] = { 236644570b8SJeff Kirsher {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/ 237644570b8SJeff Kirsher {0x48, NE_EN0_DCFG}, /* Set byte-wide (0x48) access. */ 238644570b8SJeff Kirsher {0x00, NE_EN0_RCNTLO}, /* Clear the count regs. */ 239644570b8SJeff Kirsher {0x00, NE_EN0_RCNTHI}, 240644570b8SJeff Kirsher {0x00, NE_EN0_IMR}, /* Mask completion irq. */ 241644570b8SJeff Kirsher {0xFF, NE_EN0_ISR}, 242644570b8SJeff Kirsher {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */ 243644570b8SJeff Kirsher {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode. */ 244644570b8SJeff Kirsher {32, NE_EN0_RCNTLO}, 245644570b8SJeff Kirsher {0x00, NE_EN0_RCNTHI}, 246644570b8SJeff Kirsher {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000. */ 247644570b8SJeff Kirsher {0x00, NE_EN0_RSARHI}, 248644570b8SJeff Kirsher {E8390_RREAD+E8390_START, NE_CMD}, 249644570b8SJeff Kirsher }; 250644570b8SJeff Kirsher for (i = 0; i < ARRAY_SIZE(program_seq); i++) { 251644570b8SJeff Kirsher outb(program_seq[i].value, ioaddr + program_seq[i].offset); 252644570b8SJeff Kirsher } 253644570b8SJeff Kirsher 254644570b8SJeff Kirsher } 255644570b8SJeff Kirsher for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) { 256644570b8SJeff Kirsher SA_prom[i] = inb(ioaddr + NE_DATAPORT); 257644570b8SJeff Kirsher SA_prom[i+1] = inb(ioaddr + NE_DATAPORT); 258644570b8SJeff Kirsher if (SA_prom[i] != SA_prom[i+1]) 259644570b8SJeff Kirsher wordlength = 1; 260644570b8SJeff Kirsher } 261644570b8SJeff Kirsher 262644570b8SJeff Kirsher /* At this point, wordlength *only* tells us if the SA_prom is doubled 263644570b8SJeff Kirsher up or not because some broken PCI cards don't respect the byte-wide 264644570b8SJeff Kirsher request in program_seq above, and hence don't have doubled up values. 265644570b8SJeff Kirsher These broken cards would otherwise be detected as an ne1000. */ 266644570b8SJeff Kirsher 267644570b8SJeff Kirsher if (wordlength == 2) 268644570b8SJeff Kirsher for (i = 0; i < 16; i++) 269644570b8SJeff Kirsher SA_prom[i] = SA_prom[i+i]; 270644570b8SJeff Kirsher 271644570b8SJeff Kirsher if (wordlength == 2) { 272644570b8SJeff Kirsher /* We must set the 8390 for word mode. */ 273644570b8SJeff Kirsher outb(0x49, ioaddr + NE_EN0_DCFG); 274644570b8SJeff Kirsher start_page = NESM_START_PG; 275644570b8SJeff Kirsher stop_page = NESM_STOP_PG; 276644570b8SJeff Kirsher } else { 277644570b8SJeff Kirsher start_page = NE1SM_START_PG; 278644570b8SJeff Kirsher stop_page = NE1SM_STOP_PG; 279644570b8SJeff Kirsher } 280644570b8SJeff Kirsher 281644570b8SJeff Kirsher neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); 282644570b8SJeff Kirsher ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); 283644570b8SJeff Kirsher 284644570b8SJeff Kirsher /* Set up the rest of the parameters. */ 285644570b8SJeff Kirsher if (neX000) { 286644570b8SJeff Kirsher name = (wordlength == 2) ? "NE2000" : "NE1000"; 287644570b8SJeff Kirsher } else if (ctron) { 288644570b8SJeff Kirsher name = (wordlength == 2) ? "Ctron-8" : "Ctron-16"; 289644570b8SJeff Kirsher start_page = 0x01; 290644570b8SJeff Kirsher stop_page = (wordlength == 2) ? 0x40 : 0x20; 291644570b8SJeff Kirsher } else { 292644570b8SJeff Kirsher printk(" not found.\n"); 293644570b8SJeff Kirsher return -ENXIO; 294644570b8SJeff Kirsher 295644570b8SJeff Kirsher } 296644570b8SJeff Kirsher 297644570b8SJeff Kirsher #else 298644570b8SJeff Kirsher wordlength = 2; 299644570b8SJeff Kirsher /* We must set the 8390 for word mode. */ 300644570b8SJeff Kirsher outb(0x49, ioaddr + NE_EN0_DCFG); 301644570b8SJeff Kirsher start_page = NESM_START_PG; 302644570b8SJeff Kirsher stop_page = NESM_STOP_PG; 303644570b8SJeff Kirsher 304644570b8SJeff Kirsher SA_prom[0] = MANUAL_HWADDR0; 305644570b8SJeff Kirsher SA_prom[1] = MANUAL_HWADDR1; 306644570b8SJeff Kirsher SA_prom[2] = MANUAL_HWADDR2; 307644570b8SJeff Kirsher SA_prom[3] = MANUAL_HWADDR3; 308644570b8SJeff Kirsher SA_prom[4] = MANUAL_HWADDR4; 309644570b8SJeff Kirsher SA_prom[5] = MANUAL_HWADDR5; 310644570b8SJeff Kirsher name = "NE2000"; 311644570b8SJeff Kirsher #endif 312644570b8SJeff Kirsher 313644570b8SJeff Kirsher dev->base_addr = ioaddr; 314644570b8SJeff Kirsher dev->irq = IRQ_AMIGA_PORTS; 315644570b8SJeff Kirsher dev->netdev_ops = &ei_netdev_ops; 316644570b8SJeff Kirsher 317644570b8SJeff Kirsher /* Install the Interrupt handler */ 318644570b8SJeff Kirsher i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev); 319644570b8SJeff Kirsher if (i) return i; 320644570b8SJeff Kirsher 321644570b8SJeff Kirsher for(i = 0; i < ETHER_ADDR_LEN; i++) 322644570b8SJeff Kirsher dev->dev_addr[i] = SA_prom[i]; 323644570b8SJeff Kirsher 324644570b8SJeff Kirsher printk(" %pM\n", dev->dev_addr); 325644570b8SJeff Kirsher 326644570b8SJeff Kirsher printk("%s: %s found.\n", dev->name, name); 327644570b8SJeff Kirsher 328644570b8SJeff Kirsher ei_status.name = name; 329644570b8SJeff Kirsher ei_status.tx_start_page = start_page; 330644570b8SJeff Kirsher ei_status.stop_page = stop_page; 331644570b8SJeff Kirsher ei_status.word16 = (wordlength == 2); 332644570b8SJeff Kirsher 333644570b8SJeff Kirsher ei_status.rx_start_page = start_page + TX_PAGES; 334644570b8SJeff Kirsher 335644570b8SJeff Kirsher ei_status.reset_8390 = &apne_reset_8390; 336644570b8SJeff Kirsher ei_status.block_input = &apne_block_input; 337644570b8SJeff Kirsher ei_status.block_output = &apne_block_output; 338644570b8SJeff Kirsher ei_status.get_8390_hdr = &apne_get_8390_hdr; 339644570b8SJeff Kirsher 340644570b8SJeff Kirsher NS8390_init(dev, 0); 341644570b8SJeff Kirsher 342644570b8SJeff Kirsher pcmcia_ack_int(pcmcia_get_intreq()); /* ack PCMCIA int req */ 343644570b8SJeff Kirsher pcmcia_enable_irq(); 344644570b8SJeff Kirsher 345644570b8SJeff Kirsher apne_owned = 1; 346644570b8SJeff Kirsher 347644570b8SJeff Kirsher return 0; 348644570b8SJeff Kirsher } 349644570b8SJeff Kirsher 350644570b8SJeff Kirsher /* Hard reset the card. This used to pause for the same period that a 351644570b8SJeff Kirsher 8390 reset command required, but that shouldn't be necessary. */ 352644570b8SJeff Kirsher static void 353644570b8SJeff Kirsher apne_reset_8390(struct net_device *dev) 354644570b8SJeff Kirsher { 355644570b8SJeff Kirsher unsigned long reset_start_time = jiffies; 356644570b8SJeff Kirsher 357644570b8SJeff Kirsher init_pcmcia(); 358644570b8SJeff Kirsher 359644570b8SJeff Kirsher if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies); 360644570b8SJeff Kirsher 361644570b8SJeff Kirsher outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); 362644570b8SJeff Kirsher 363644570b8SJeff Kirsher ei_status.txing = 0; 364644570b8SJeff Kirsher ei_status.dmaing = 0; 365644570b8SJeff Kirsher 366644570b8SJeff Kirsher /* This check _should_not_ be necessary, omit eventually. */ 367644570b8SJeff Kirsher while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0) 368644570b8SJeff Kirsher if (time_after(jiffies, reset_start_time + 2*HZ/100)) { 369644570b8SJeff Kirsher printk("%s: ne_reset_8390() did not complete.\n", dev->name); 370644570b8SJeff Kirsher break; 371644570b8SJeff Kirsher } 372644570b8SJeff Kirsher outb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr. */ 373644570b8SJeff Kirsher } 374644570b8SJeff Kirsher 375644570b8SJeff Kirsher /* Grab the 8390 specific header. Similar to the block_input routine, but 376644570b8SJeff Kirsher we don't need to be concerned with ring wrap as the header will be at 377644570b8SJeff Kirsher the start of a page, so we optimize accordingly. */ 378644570b8SJeff Kirsher 379644570b8SJeff Kirsher static void 380644570b8SJeff Kirsher apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) 381644570b8SJeff Kirsher { 382644570b8SJeff Kirsher 383644570b8SJeff Kirsher int nic_base = dev->base_addr; 384644570b8SJeff Kirsher int cnt; 385644570b8SJeff Kirsher char *ptrc; 386644570b8SJeff Kirsher short *ptrs; 387644570b8SJeff Kirsher 388644570b8SJeff Kirsher /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 389644570b8SJeff Kirsher if (ei_status.dmaing) { 390644570b8SJeff Kirsher printk("%s: DMAing conflict in ne_get_8390_hdr " 391644570b8SJeff Kirsher "[DMAstat:%d][irqlock:%d][intr:%d].\n", 392644570b8SJeff Kirsher dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); 393644570b8SJeff Kirsher return; 394644570b8SJeff Kirsher } 395644570b8SJeff Kirsher 396644570b8SJeff Kirsher ei_status.dmaing |= 0x01; 397644570b8SJeff Kirsher outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); 398644570b8SJeff Kirsher outb(ENISR_RDC, nic_base + NE_EN0_ISR); 399644570b8SJeff Kirsher outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO); 400644570b8SJeff Kirsher outb(0, nic_base + NE_EN0_RCNTHI); 401644570b8SJeff Kirsher outb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */ 402644570b8SJeff Kirsher outb(ring_page, nic_base + NE_EN0_RSARHI); 403644570b8SJeff Kirsher outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); 404644570b8SJeff Kirsher 405644570b8SJeff Kirsher if (ei_status.word16) { 406644570b8SJeff Kirsher ptrs = (short*)hdr; 407644570b8SJeff Kirsher for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++) 408644570b8SJeff Kirsher *ptrs++ = inw(NE_BASE + NE_DATAPORT); 409644570b8SJeff Kirsher } else { 410644570b8SJeff Kirsher ptrc = (char*)hdr; 411644570b8SJeff Kirsher for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++) 412644570b8SJeff Kirsher *ptrc++ = inb(NE_BASE + NE_DATAPORT); 413644570b8SJeff Kirsher } 414644570b8SJeff Kirsher 415644570b8SJeff Kirsher outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ 416644570b8SJeff Kirsher ei_status.dmaing &= ~0x01; 417644570b8SJeff Kirsher 418644570b8SJeff Kirsher le16_to_cpus(&hdr->count); 419644570b8SJeff Kirsher } 420644570b8SJeff Kirsher 421644570b8SJeff Kirsher /* Block input and output, similar to the Crynwr packet driver. If you 422644570b8SJeff Kirsher are porting to a new ethercard, look at the packet driver source for hints. 423644570b8SJeff Kirsher The NEx000 doesn't share the on-board packet memory -- you have to put 424644570b8SJeff Kirsher the packet out through the "remote DMA" dataport using outb. */ 425644570b8SJeff Kirsher 426644570b8SJeff Kirsher static void 427644570b8SJeff Kirsher apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) 428644570b8SJeff Kirsher { 429644570b8SJeff Kirsher int nic_base = dev->base_addr; 430644570b8SJeff Kirsher char *buf = skb->data; 431644570b8SJeff Kirsher char *ptrc; 432644570b8SJeff Kirsher short *ptrs; 433644570b8SJeff Kirsher int cnt; 434644570b8SJeff Kirsher 435644570b8SJeff Kirsher /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 436644570b8SJeff Kirsher if (ei_status.dmaing) { 437644570b8SJeff Kirsher printk("%s: DMAing conflict in ne_block_input " 438644570b8SJeff Kirsher "[DMAstat:%d][irqlock:%d][intr:%d].\n", 439644570b8SJeff Kirsher dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); 440644570b8SJeff Kirsher return; 441644570b8SJeff Kirsher } 442644570b8SJeff Kirsher ei_status.dmaing |= 0x01; 443644570b8SJeff Kirsher outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); 444644570b8SJeff Kirsher outb(ENISR_RDC, nic_base + NE_EN0_ISR); 445644570b8SJeff Kirsher outb(count & 0xff, nic_base + NE_EN0_RCNTLO); 446644570b8SJeff Kirsher outb(count >> 8, nic_base + NE_EN0_RCNTHI); 447644570b8SJeff Kirsher outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO); 448644570b8SJeff Kirsher outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI); 449644570b8SJeff Kirsher outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); 450644570b8SJeff Kirsher if (ei_status.word16) { 451644570b8SJeff Kirsher ptrs = (short*)buf; 452644570b8SJeff Kirsher for (cnt = 0; cnt < (count>>1); cnt++) 453644570b8SJeff Kirsher *ptrs++ = inw(NE_BASE + NE_DATAPORT); 454644570b8SJeff Kirsher if (count & 0x01) { 455644570b8SJeff Kirsher buf[count-1] = inb(NE_BASE + NE_DATAPORT); 456644570b8SJeff Kirsher } 457644570b8SJeff Kirsher } else { 458644570b8SJeff Kirsher ptrc = (char*)buf; 459644570b8SJeff Kirsher for (cnt = 0; cnt < count; cnt++) 460644570b8SJeff Kirsher *ptrc++ = inb(NE_BASE + NE_DATAPORT); 461644570b8SJeff Kirsher } 462644570b8SJeff Kirsher 463644570b8SJeff Kirsher outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ 464644570b8SJeff Kirsher ei_status.dmaing &= ~0x01; 465644570b8SJeff Kirsher } 466644570b8SJeff Kirsher 467644570b8SJeff Kirsher static void 468644570b8SJeff Kirsher apne_block_output(struct net_device *dev, int count, 469644570b8SJeff Kirsher const unsigned char *buf, const int start_page) 470644570b8SJeff Kirsher { 471644570b8SJeff Kirsher int nic_base = NE_BASE; 472644570b8SJeff Kirsher unsigned long dma_start; 473644570b8SJeff Kirsher char *ptrc; 474644570b8SJeff Kirsher short *ptrs; 475644570b8SJeff Kirsher int cnt; 476644570b8SJeff Kirsher 477644570b8SJeff Kirsher /* Round the count up for word writes. Do we need to do this? 478644570b8SJeff Kirsher What effect will an odd byte count have on the 8390? 479644570b8SJeff Kirsher I should check someday. */ 480644570b8SJeff Kirsher if (ei_status.word16 && (count & 0x01)) 481644570b8SJeff Kirsher count++; 482644570b8SJeff Kirsher 483644570b8SJeff Kirsher /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 484644570b8SJeff Kirsher if (ei_status.dmaing) { 485644570b8SJeff Kirsher printk("%s: DMAing conflict in ne_block_output." 486644570b8SJeff Kirsher "[DMAstat:%d][irqlock:%d][intr:%d]\n", 487644570b8SJeff Kirsher dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); 488644570b8SJeff Kirsher return; 489644570b8SJeff Kirsher } 490644570b8SJeff Kirsher ei_status.dmaing |= 0x01; 491644570b8SJeff Kirsher /* We should already be in page 0, but to be safe... */ 492644570b8SJeff Kirsher outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); 493644570b8SJeff Kirsher 494644570b8SJeff Kirsher outb(ENISR_RDC, nic_base + NE_EN0_ISR); 495644570b8SJeff Kirsher 496644570b8SJeff Kirsher /* Now the normal output. */ 497644570b8SJeff Kirsher outb(count & 0xff, nic_base + NE_EN0_RCNTLO); 498644570b8SJeff Kirsher outb(count >> 8, nic_base + NE_EN0_RCNTHI); 499644570b8SJeff Kirsher outb(0x00, nic_base + NE_EN0_RSARLO); 500644570b8SJeff Kirsher outb(start_page, nic_base + NE_EN0_RSARHI); 501644570b8SJeff Kirsher 502644570b8SJeff Kirsher outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); 503644570b8SJeff Kirsher if (ei_status.word16) { 504644570b8SJeff Kirsher ptrs = (short*)buf; 505644570b8SJeff Kirsher for (cnt = 0; cnt < count>>1; cnt++) 506644570b8SJeff Kirsher outw(*ptrs++, NE_BASE+NE_DATAPORT); 507644570b8SJeff Kirsher } else { 508644570b8SJeff Kirsher ptrc = (char*)buf; 509644570b8SJeff Kirsher for (cnt = 0; cnt < count; cnt++) 510644570b8SJeff Kirsher outb(*ptrc++, NE_BASE + NE_DATAPORT); 511644570b8SJeff Kirsher } 512644570b8SJeff Kirsher 513644570b8SJeff Kirsher dma_start = jiffies; 514644570b8SJeff Kirsher 515644570b8SJeff Kirsher while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) 516644570b8SJeff Kirsher if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ 517644570b8SJeff Kirsher printk("%s: timeout waiting for Tx RDC.\n", dev->name); 518644570b8SJeff Kirsher apne_reset_8390(dev); 519644570b8SJeff Kirsher NS8390_init(dev,1); 520644570b8SJeff Kirsher break; 521644570b8SJeff Kirsher } 522644570b8SJeff Kirsher 523644570b8SJeff Kirsher outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ 524644570b8SJeff Kirsher ei_status.dmaing &= ~0x01; 525644570b8SJeff Kirsher } 526644570b8SJeff Kirsher 527644570b8SJeff Kirsher static irqreturn_t apne_interrupt(int irq, void *dev_id) 528644570b8SJeff Kirsher { 529644570b8SJeff Kirsher unsigned char pcmcia_intreq; 530644570b8SJeff Kirsher 531644570b8SJeff Kirsher if (!(gayle.inten & GAYLE_IRQ_IRQ)) 532644570b8SJeff Kirsher return IRQ_NONE; 533644570b8SJeff Kirsher 534644570b8SJeff Kirsher pcmcia_intreq = pcmcia_get_intreq(); 535644570b8SJeff Kirsher 536644570b8SJeff Kirsher if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) { 537644570b8SJeff Kirsher pcmcia_ack_int(pcmcia_intreq); 538644570b8SJeff Kirsher return IRQ_NONE; 539644570b8SJeff Kirsher } 540644570b8SJeff Kirsher if (ei_debug > 3) 541644570b8SJeff Kirsher printk("pcmcia intreq = %x\n", pcmcia_intreq); 542644570b8SJeff Kirsher pcmcia_disable_irq(); /* to get rid of the sti() within ei_interrupt */ 543644570b8SJeff Kirsher ei_interrupt(irq, dev_id); 544644570b8SJeff Kirsher pcmcia_ack_int(pcmcia_get_intreq()); 545644570b8SJeff Kirsher pcmcia_enable_irq(); 546644570b8SJeff Kirsher return IRQ_HANDLED; 547644570b8SJeff Kirsher } 548644570b8SJeff Kirsher 549644570b8SJeff Kirsher #ifdef MODULE 550644570b8SJeff Kirsher static struct net_device *apne_dev; 551644570b8SJeff Kirsher 552644570b8SJeff Kirsher static int __init apne_module_init(void) 553644570b8SJeff Kirsher { 554644570b8SJeff Kirsher apne_dev = apne_probe(-1); 555644570b8SJeff Kirsher if (IS_ERR(apne_dev)) 556644570b8SJeff Kirsher return PTR_ERR(apne_dev); 557644570b8SJeff Kirsher return 0; 558644570b8SJeff Kirsher } 559644570b8SJeff Kirsher 560644570b8SJeff Kirsher static void __exit apne_module_exit(void) 561644570b8SJeff Kirsher { 562644570b8SJeff Kirsher unregister_netdev(apne_dev); 563644570b8SJeff Kirsher 564644570b8SJeff Kirsher pcmcia_disable_irq(); 565644570b8SJeff Kirsher 566644570b8SJeff Kirsher free_irq(IRQ_AMIGA_PORTS, apne_dev); 567644570b8SJeff Kirsher 568644570b8SJeff Kirsher pcmcia_reset(); 569644570b8SJeff Kirsher 570644570b8SJeff Kirsher release_region(IOBASE, 0x20); 571644570b8SJeff Kirsher 572644570b8SJeff Kirsher free_netdev(apne_dev); 573644570b8SJeff Kirsher } 574644570b8SJeff Kirsher module_init(apne_module_init); 575644570b8SJeff Kirsher module_exit(apne_module_exit); 576644570b8SJeff Kirsher #endif 577644570b8SJeff Kirsher 578644570b8SJeff Kirsher static int init_pcmcia(void) 579644570b8SJeff Kirsher { 580644570b8SJeff Kirsher u_char config; 581644570b8SJeff Kirsher #ifndef MANUAL_CONFIG 582644570b8SJeff Kirsher u_char tuple[32]; 583644570b8SJeff Kirsher int offset_len; 584644570b8SJeff Kirsher #endif 585644570b8SJeff Kirsher u_long offset; 586644570b8SJeff Kirsher 587644570b8SJeff Kirsher pcmcia_reset(); 588644570b8SJeff Kirsher pcmcia_program_voltage(PCMCIA_0V); 589644570b8SJeff Kirsher pcmcia_access_speed(PCMCIA_SPEED_250NS); 590644570b8SJeff Kirsher pcmcia_write_enable(); 591644570b8SJeff Kirsher 592644570b8SJeff Kirsher #ifdef MANUAL_CONFIG 593644570b8SJeff Kirsher config = MANUAL_CONFIG; 594644570b8SJeff Kirsher #else 595644570b8SJeff Kirsher /* get and write config byte to enable IO port */ 596644570b8SJeff Kirsher 597644570b8SJeff Kirsher if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3) 598644570b8SJeff Kirsher return 0; 599644570b8SJeff Kirsher 600644570b8SJeff Kirsher config = tuple[2] & 0x3f; 601644570b8SJeff Kirsher #endif 602644570b8SJeff Kirsher #ifdef MANUAL_OFFSET 603644570b8SJeff Kirsher offset = MANUAL_OFFSET; 604644570b8SJeff Kirsher #else 605644570b8SJeff Kirsher if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6) 606644570b8SJeff Kirsher return 0; 607644570b8SJeff Kirsher 608644570b8SJeff Kirsher offset_len = (tuple[2] & 0x3) + 1; 609644570b8SJeff Kirsher offset = 0; 610644570b8SJeff Kirsher while(offset_len--) { 611644570b8SJeff Kirsher offset = (offset << 8) | tuple[4+offset_len]; 612644570b8SJeff Kirsher } 613644570b8SJeff Kirsher #endif 614644570b8SJeff Kirsher 615644570b8SJeff Kirsher out_8(GAYLE_ATTRIBUTE+offset, config); 616644570b8SJeff Kirsher 617644570b8SJeff Kirsher return 1; 618644570b8SJeff Kirsher } 619644570b8SJeff Kirsher 620644570b8SJeff Kirsher MODULE_LICENSE("GPL"); 621