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