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