linux/drivers/net/ethernet/8390/apne.c
<<
>>
Prefs
   1/*
   2 * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
   3 *
   4 * (C) Copyright 1997 Alain Malek
   5 *                    (Alain.Malek@cryogen.com)
   6 *
   7 * ----------------------------------------------------------------------------
   8 *
   9 * This program is based on
  10 *
  11 * ne.c:       A general non-shared-memory NS8390 ethernet driver for linux
  12 *             Written 1992-94 by Donald Becker.
  13 *
  14 * 8390.c:     A general NS8390 ethernet driver core for linux.
  15 *             Written 1992-94 by Donald Becker.
  16 *
  17 * cnetdevice: A Sana-II ethernet driver for AmigaOS
  18 *             Written by Bruce Abbott (bhabbott@inhb.co.nz)
  19 *
  20 * ----------------------------------------------------------------------------
  21 *
  22 * This file is subject to the terms and conditions of the GNU General Public
  23 * License.  See the file COPYING in the main directory of the Linux
  24 * distribution for more details.
  25 *
  26 * ----------------------------------------------------------------------------
  27 *
  28 */
  29
  30
  31#include <linux/module.h>
  32#include <linux/kernel.h>
  33#include <linux/errno.h>
  34#include <linux/pci.h>
  35#include <linux/init.h>
  36#include <linux/delay.h>
  37#include <linux/netdevice.h>
  38#include <linux/etherdevice.h>
  39#include <linux/interrupt.h>
  40#include <linux/jiffies.h>
  41
  42#include <asm/io.h>
  43#include <asm/setup.h>
  44#include <asm/amigaints.h>
  45#include <asm/amigahw.h>
  46#include <asm/amigayle.h>
  47#include <asm/amipcmcia.h>
  48
  49#include "8390.h"
  50
  51/* ---- No user-serviceable parts below ---- */
  52
  53#define DRV_NAME "apne"
  54
  55#define NE_BASE  (dev->base_addr)
  56#define NE_CMD                  0x00
  57#define NE_DATAPORT             0x10            /* NatSemi-defined port window offset. */
  58#define NE_RESET                0x1f            /* Issue a read to reset, a write to clear. */
  59#define NE_IO_EXTENT            0x20
  60
  61#define NE_EN0_ISR              0x07
  62#define NE_EN0_DCFG             0x0e
  63
  64#define NE_EN0_RSARLO           0x08
  65#define NE_EN0_RSARHI           0x09
  66#define NE_EN0_RCNTLO           0x0a
  67#define NE_EN0_RXCR             0x0c
  68#define NE_EN0_TXCR             0x0d
  69#define NE_EN0_RCNTHI           0x0b
  70#define NE_EN0_IMR              0x0f
  71
  72#define NE1SM_START_PG  0x20    /* First page of TX buffer */
  73#define NE1SM_STOP_PG   0x40    /* Last page +1 of RX ring */
  74#define NESM_START_PG   0x40    /* First page of TX buffer */
  75#define NESM_STOP_PG    0x80    /* Last page +1 of RX ring */
  76
  77
  78struct net_device * __init apne_probe(int unit);
  79static int apne_probe1(struct net_device *dev, int ioaddr);
  80
  81static void apne_reset_8390(struct net_device *dev);
  82static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
  83                          int ring_page);
  84static void apne_block_input(struct net_device *dev, int count,
  85                                                                struct sk_buff *skb, int ring_offset);
  86static void apne_block_output(struct net_device *dev, const int count,
  87                                                        const unsigned char *buf, const int start_page);
  88static irqreturn_t apne_interrupt(int irq, void *dev_id);
  89
  90static int init_pcmcia(void);
  91
  92/* IO base address used for nic */
  93
  94#define IOBASE 0x300
  95
  96/*
  97   use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
  98   you can find the values to use by looking at the cnet.device
  99   config file example (the default values are for the CNET40BC card)
 100*/
 101
 102/*
 103#define MANUAL_CONFIG 0x20
 104#define MANUAL_OFFSET 0x3f8
 105
 106#define MANUAL_HWADDR0 0x00
 107#define MANUAL_HWADDR1 0x12
 108#define MANUAL_HWADDR2 0x34
 109#define MANUAL_HWADDR3 0x56
 110#define MANUAL_HWADDR4 0x78
 111#define MANUAL_HWADDR5 0x9a
 112*/
 113
 114static const char version[] =
 115    "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
 116
 117static int apne_owned;  /* signal if card already owned */
 118
 119static u32 apne_msg_enable;
 120module_param_named(msg_enable, apne_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 121MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
 122
 123struct net_device * __init apne_probe(int unit)
 124{
 125        struct net_device *dev;
 126        struct ei_device *ei_local;
 127
 128#ifndef MANUAL_CONFIG
 129        char tuple[8];
 130#endif
 131        int err;
 132
 133        if (!MACH_IS_AMIGA)
 134                return ERR_PTR(-ENODEV);
 135
 136        if (apne_owned)
 137                return ERR_PTR(-ENODEV);
 138
 139        if ( !(AMIGAHW_PRESENT(PCMCIA)) )
 140                return ERR_PTR(-ENODEV);
 141
 142        pr_info("Looking for PCMCIA ethernet card : ");
 143
 144        /* check if a card is inserted */
 145        if (!(PCMCIA_INSERTED)) {
 146                pr_cont("NO PCMCIA card inserted\n");
 147                return ERR_PTR(-ENODEV);
 148        }
 149
 150        dev = alloc_ei_netdev();
 151        if (!dev)
 152                return ERR_PTR(-ENOMEM);
 153        if (unit >= 0) {
 154                sprintf(dev->name, "eth%d", unit);
 155                netdev_boot_setup_check(dev);
 156        }
 157        ei_local = netdev_priv(dev);
 158        ei_local->msg_enable = apne_msg_enable;
 159
 160        /* disable pcmcia irq for readtuple */
 161        pcmcia_disable_irq();
 162
 163#ifndef MANUAL_CONFIG
 164        if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
 165                (tuple[2] != CISTPL_FUNCID_NETWORK)) {
 166                pr_cont("not an ethernet card\n");
 167                /* XXX: shouldn't we re-enable irq here? */
 168                free_netdev(dev);
 169                return ERR_PTR(-ENODEV);
 170        }
 171#endif
 172
 173        pr_cont("ethernet PCMCIA card inserted\n");
 174
 175        if (!init_pcmcia()) {
 176                /* XXX: shouldn't we re-enable irq here? */
 177                free_netdev(dev);
 178                return ERR_PTR(-ENODEV);
 179        }
 180
 181        if (!request_region(IOBASE, 0x20, DRV_NAME)) {
 182                free_netdev(dev);
 183                return ERR_PTR(-EBUSY);
 184        }
 185
 186        err = apne_probe1(dev, IOBASE);
 187        if (err) {
 188                release_region(IOBASE, 0x20);
 189                free_netdev(dev);
 190                return ERR_PTR(err);
 191        }
 192        err = register_netdev(dev);
 193        if (!err)
 194                return dev;
 195
 196        pcmcia_disable_irq();
 197        free_irq(IRQ_AMIGA_PORTS, dev);
 198        pcmcia_reset();
 199        release_region(IOBASE, 0x20);
 200        free_netdev(dev);
 201        return ERR_PTR(err);
 202}
 203
 204static int __init apne_probe1(struct net_device *dev, int ioaddr)
 205{
 206    int i;
 207    unsigned char SA_prom[32];
 208    int wordlength = 2;
 209    const char *name = NULL;
 210    int start_page, stop_page;
 211#ifndef MANUAL_HWADDR0
 212    int neX000, ctron;
 213#endif
 214    static unsigned version_printed;
 215
 216    if ((apne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
 217                netdev_info(dev, version);
 218
 219    netdev_info(dev, "PCMCIA NE*000 ethercard probe");
 220
 221    /* Reset card. Who knows what dain-bramaged state it was left in. */
 222    {   unsigned long reset_start_time = jiffies;
 223
 224        outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 225
 226        while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
 227                if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
 228                        pr_cont(" not found (no reset ack).\n");
 229                        return -ENODEV;
 230                }
 231
 232        outb(0xff, ioaddr + NE_EN0_ISR);                /* Ack all intr. */
 233    }
 234
 235#ifndef MANUAL_HWADDR0
 236
 237    /* Read the 16 bytes of station address PROM.
 238       We must first initialize registers, similar to NS8390_init(eifdev, 0).
 239       We can't reliably read the SAPROM address without this.
 240       (I learned the hard way!). */
 241    {
 242        struct {unsigned long value, offset; } program_seq[] = {
 243            {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
 244            {0x48,      NE_EN0_DCFG},   /* Set byte-wide (0x48) access. */
 245            {0x00,      NE_EN0_RCNTLO}, /* Clear the count regs. */
 246            {0x00,      NE_EN0_RCNTHI},
 247            {0x00,      NE_EN0_IMR},    /* Mask completion irq. */
 248            {0xFF,      NE_EN0_ISR},
 249            {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20  Set to monitor */
 250            {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02  and loopback mode. */
 251            {32,        NE_EN0_RCNTLO},
 252            {0x00,      NE_EN0_RCNTHI},
 253            {0x00,      NE_EN0_RSARLO}, /* DMA starting at 0x0000. */
 254            {0x00,      NE_EN0_RSARHI},
 255            {E8390_RREAD+E8390_START, NE_CMD},
 256        };
 257        for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
 258            outb(program_seq[i].value, ioaddr + program_seq[i].offset);
 259        }
 260
 261    }
 262    for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
 263        SA_prom[i] = inb(ioaddr + NE_DATAPORT);
 264        SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
 265        if (SA_prom[i] != SA_prom[i+1])
 266            wordlength = 1;
 267    }
 268
 269    /*  At this point, wordlength *only* tells us if the SA_prom is doubled
 270        up or not because some broken PCI cards don't respect the byte-wide
 271        request in program_seq above, and hence don't have doubled up values.
 272        These broken cards would otherwise be detected as an ne1000.  */
 273
 274    if (wordlength == 2)
 275        for (i = 0; i < 16; i++)
 276                SA_prom[i] = SA_prom[i+i];
 277
 278    if (wordlength == 2) {
 279        /* We must set the 8390 for word mode. */
 280        outb(0x49, ioaddr + NE_EN0_DCFG);
 281        start_page = NESM_START_PG;
 282        stop_page = NESM_STOP_PG;
 283    } else {
 284        start_page = NE1SM_START_PG;
 285        stop_page = NE1SM_STOP_PG;
 286    }
 287
 288    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
 289    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
 290
 291    /* Set up the rest of the parameters. */
 292    if (neX000) {
 293        name = (wordlength == 2) ? "NE2000" : "NE1000";
 294    } else if (ctron) {
 295        name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
 296        start_page = 0x01;
 297        stop_page = (wordlength == 2) ? 0x40 : 0x20;
 298    } else {
 299        pr_cont(" not found.\n");
 300        return -ENXIO;
 301
 302    }
 303
 304#else
 305    wordlength = 2;
 306    /* We must set the 8390 for word mode. */
 307    outb(0x49, ioaddr + NE_EN0_DCFG);
 308    start_page = NESM_START_PG;
 309    stop_page = NESM_STOP_PG;
 310
 311    SA_prom[0] = MANUAL_HWADDR0;
 312    SA_prom[1] = MANUAL_HWADDR1;
 313    SA_prom[2] = MANUAL_HWADDR2;
 314    SA_prom[3] = MANUAL_HWADDR3;
 315    SA_prom[4] = MANUAL_HWADDR4;
 316    SA_prom[5] = MANUAL_HWADDR5;
 317    name = "NE2000";
 318#endif
 319
 320    dev->base_addr = ioaddr;
 321    dev->irq = IRQ_AMIGA_PORTS;
 322    dev->netdev_ops = &ei_netdev_ops;
 323
 324    /* Install the Interrupt handler */
 325    i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
 326    if (i) return i;
 327
 328    for (i = 0; i < ETH_ALEN; i++)
 329        dev->dev_addr[i] = SA_prom[i];
 330
 331    pr_cont(" %pM\n", dev->dev_addr);
 332
 333    netdev_info(dev, "%s found.\n", name);
 334
 335    ei_status.name = name;
 336    ei_status.tx_start_page = start_page;
 337    ei_status.stop_page = stop_page;
 338    ei_status.word16 = (wordlength == 2);
 339
 340    ei_status.rx_start_page = start_page + TX_PAGES;
 341
 342    ei_status.reset_8390 = &apne_reset_8390;
 343    ei_status.block_input = &apne_block_input;
 344    ei_status.block_output = &apne_block_output;
 345    ei_status.get_8390_hdr = &apne_get_8390_hdr;
 346
 347    NS8390_init(dev, 0);
 348
 349    pcmcia_ack_int(pcmcia_get_intreq());                /* ack PCMCIA int req */
 350    pcmcia_enable_irq();
 351
 352    apne_owned = 1;
 353
 354    return 0;
 355}
 356
 357/* Hard reset the card.  This used to pause for the same period that a
 358   8390 reset command required, but that shouldn't be necessary. */
 359static void
 360apne_reset_8390(struct net_device *dev)
 361{
 362    unsigned long reset_start_time = jiffies;
 363    struct ei_device *ei_local = netdev_priv(dev);
 364
 365    init_pcmcia();
 366
 367    netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
 368
 369    outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
 370
 371    ei_status.txing = 0;
 372    ei_status.dmaing = 0;
 373
 374    /* This check _should_not_ be necessary, omit eventually. */
 375    while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
 376        if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
 377                netdev_err(dev, "ne_reset_8390() did not complete.\n");
 378                break;
 379        }
 380    outb(ENISR_RESET, NE_BASE + NE_EN0_ISR);    /* Ack intr. */
 381}
 382
 383/* Grab the 8390 specific header. Similar to the block_input routine, but
 384   we don't need to be concerned with ring wrap as the header will be at
 385   the start of a page, so we optimize accordingly. */
 386
 387static void
 388apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 389{
 390
 391    int nic_base = dev->base_addr;
 392    int cnt;
 393    char *ptrc;
 394    short *ptrs;
 395
 396    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
 397    if (ei_status.dmaing) {
 398        netdev_err(dev, "DMAing conflict in ne_get_8390_hdr "
 399                   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
 400                   ei_status.dmaing, ei_status.irqlock, dev->irq);
 401        return;
 402    }
 403
 404    ei_status.dmaing |= 0x01;
 405    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
 406    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
 407    outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
 408    outb(0, nic_base + NE_EN0_RCNTHI);
 409    outb(0, nic_base + NE_EN0_RSARLO);          /* On page boundary */
 410    outb(ring_page, nic_base + NE_EN0_RSARHI);
 411    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 412
 413    if (ei_status.word16) {
 414        ptrs = (short*)hdr;
 415        for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
 416            *ptrs++ = inw(NE_BASE + NE_DATAPORT);
 417    } else {
 418        ptrc = (char*)hdr;
 419        for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++)
 420            *ptrc++ = inb(NE_BASE + NE_DATAPORT);
 421    }
 422
 423    outb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr. */
 424    ei_status.dmaing &= ~0x01;
 425
 426    le16_to_cpus(&hdr->count);
 427}
 428
 429/* Block input and output, similar to the Crynwr packet driver.  If you
 430   are porting to a new ethercard, look at the packet driver source for hints.
 431   The NEx000 doesn't share the on-board packet memory -- you have to put
 432   the packet out through the "remote DMA" dataport using outb. */
 433
 434static void
 435apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 436{
 437    int nic_base = dev->base_addr;
 438    char *buf = skb->data;
 439    char *ptrc;
 440    short *ptrs;
 441    int cnt;
 442
 443    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
 444    if (ei_status.dmaing) {
 445                netdev_err(dev, "DMAing conflict in ne_block_input "
 446                           "[DMAstat:%d][irqlock:%d][intr:%d].\n",
 447                           ei_status.dmaing, ei_status.irqlock, dev->irq);
 448        return;
 449    }
 450    ei_status.dmaing |= 0x01;
 451    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
 452    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
 453    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
 454    outb(count >> 8, nic_base + NE_EN0_RCNTHI);
 455    outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
 456    outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
 457    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 458    if (ei_status.word16) {
 459      ptrs = (short*)buf;
 460      for (cnt = 0; cnt < (count>>1); cnt++)
 461        *ptrs++ = inw(NE_BASE + NE_DATAPORT);
 462      if (count & 0x01) {
 463        buf[count-1] = inb(NE_BASE + NE_DATAPORT);
 464      }
 465    } else {
 466      ptrc = buf;
 467      for (cnt = 0; cnt < count; cnt++)
 468        *ptrc++ = inb(NE_BASE + NE_DATAPORT);
 469    }
 470
 471    outb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr. */
 472    ei_status.dmaing &= ~0x01;
 473}
 474
 475static void
 476apne_block_output(struct net_device *dev, int count,
 477                const unsigned char *buf, const int start_page)
 478{
 479    int nic_base = NE_BASE;
 480    unsigned long dma_start;
 481    char *ptrc;
 482    short *ptrs;
 483    int cnt;
 484
 485    /* Round the count up for word writes.  Do we need to do this?
 486       What effect will an odd byte count have on the 8390?
 487       I should check someday. */
 488    if (ei_status.word16 && (count & 0x01))
 489      count++;
 490
 491    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
 492    if (ei_status.dmaing) {
 493                netdev_err(dev, "DMAing conflict in ne_block_output."
 494                           "[DMAstat:%d][irqlock:%d][intr:%d]\n",
 495                           ei_status.dmaing, ei_status.irqlock, dev->irq);
 496        return;
 497    }
 498    ei_status.dmaing |= 0x01;
 499    /* We should already be in page 0, but to be safe... */
 500    outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
 501
 502    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
 503
 504   /* Now the normal output. */
 505    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
 506    outb(count >> 8,   nic_base + NE_EN0_RCNTHI);
 507    outb(0x00, nic_base + NE_EN0_RSARLO);
 508    outb(start_page, nic_base + NE_EN0_RSARHI);
 509
 510    outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
 511    if (ei_status.word16) {
 512        ptrs = (short*)buf;
 513        for (cnt = 0; cnt < count>>1; cnt++)
 514            outw(*ptrs++, NE_BASE+NE_DATAPORT);
 515    } else {
 516        ptrc = (char*)buf;
 517        for (cnt = 0; cnt < count; cnt++)
 518            outb(*ptrc++, NE_BASE + NE_DATAPORT);
 519    }
 520
 521    dma_start = jiffies;
 522
 523    while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
 524        if (time_after(jiffies, dma_start + 2*HZ/100)) {        /* 20ms */
 525                netdev_warn(dev, "timeout waiting for Tx RDC.\n");
 526                apne_reset_8390(dev);
 527                NS8390_init(dev,1);
 528                break;
 529        }
 530
 531    outb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr. */
 532    ei_status.dmaing &= ~0x01;
 533}
 534
 535static irqreturn_t apne_interrupt(int irq, void *dev_id)
 536{
 537    unsigned char pcmcia_intreq;
 538
 539    if (!(gayle.inten & GAYLE_IRQ_IRQ))
 540        return IRQ_NONE;
 541
 542    pcmcia_intreq = pcmcia_get_intreq();
 543
 544    if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
 545        pcmcia_ack_int(pcmcia_intreq);
 546        return IRQ_NONE;
 547    }
 548    if (apne_msg_enable & NETIF_MSG_INTR)
 549        pr_debug("pcmcia intreq = %x\n", pcmcia_intreq);
 550    pcmcia_disable_irq();                       /* to get rid of the sti() within ei_interrupt */
 551    ei_interrupt(irq, dev_id);
 552    pcmcia_ack_int(pcmcia_get_intreq());
 553    pcmcia_enable_irq();
 554    return IRQ_HANDLED;
 555}
 556
 557#ifdef MODULE
 558static struct net_device *apne_dev;
 559
 560static int __init apne_module_init(void)
 561{
 562        apne_dev = apne_probe(-1);
 563        return PTR_ERR_OR_ZERO(apne_dev);
 564}
 565
 566static void __exit apne_module_exit(void)
 567{
 568        unregister_netdev(apne_dev);
 569
 570        pcmcia_disable_irq();
 571
 572        free_irq(IRQ_AMIGA_PORTS, apne_dev);
 573
 574        pcmcia_reset();
 575
 576        release_region(IOBASE, 0x20);
 577
 578        free_netdev(apne_dev);
 579}
 580module_init(apne_module_init);
 581module_exit(apne_module_exit);
 582#endif
 583
 584static int init_pcmcia(void)
 585{
 586        u_char config;
 587#ifndef MANUAL_CONFIG
 588        u_char tuple[32];
 589        int offset_len;
 590#endif
 591        u_long offset;
 592
 593        pcmcia_reset();
 594        pcmcia_program_voltage(PCMCIA_0V);
 595        pcmcia_access_speed(PCMCIA_SPEED_250NS);
 596        pcmcia_write_enable();
 597
 598#ifdef MANUAL_CONFIG
 599        config = MANUAL_CONFIG;
 600#else
 601        /* get and write config byte to enable IO port */
 602
 603        if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3)
 604                return 0;
 605
 606        config = tuple[2] & 0x3f;
 607#endif
 608#ifdef MANUAL_OFFSET
 609        offset = MANUAL_OFFSET;
 610#else
 611        if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6)
 612                return 0;
 613
 614        offset_len = (tuple[2] & 0x3) + 1;
 615        offset = 0;
 616        while(offset_len--) {
 617                offset = (offset << 8) | tuple[4+offset_len];
 618        }
 619#endif
 620
 621        out_8(GAYLE_ATTRIBUTE+offset, config);
 622
 623        return 1;
 624}
 625
 626MODULE_LICENSE("GPL");
 627