Annotation of Gnu-Mach/linux/pcmcia-cs/modules/i82365.c, revision 1.1

1.1     ! root        1: /*======================================================================
        !             2: 
        !             3:     Device driver for Intel 82365 and compatible PC Card controllers,
        !             4:     and Yenta-compatible PCI-to-CardBus controllers.
        !             5: 
        !             6:     i82365.c 1.358 2003/09/13 17:34:01
        !             7: 
        !             8:     The contents of this file are subject to the Mozilla Public
        !             9:     License Version 1.1 (the "License"); you may not use this file
        !            10:     except in compliance with the License. You may obtain a copy of
        !            11:     the License at http://www.mozilla.org/MPL/
        !            12: 
        !            13:     Software distributed under the License is distributed on an "AS
        !            14:     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
        !            15:     implied. See the License for the specific language governing
        !            16:     rights and limitations under the License.
        !            17: 
        !            18:     The initial developer of the original code is David A. Hinds
        !            19:     <[email protected]>.  Portions created by David A. Hinds
        !            20:     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
        !            21: 
        !            22:     Alternatively, the contents of this file may be used under the
        !            23:     terms of the GNU General Public License version 2 (the "GPL"), in
        !            24:     which case the provisions of the GPL are applicable instead of the
        !            25:     above.  If you wish to allow the use of your version of this file
        !            26:     only under the terms of the GPL and not to allow others to use
        !            27:     your version of this file under the MPL, indicate your decision
        !            28:     by deleting the provisions above and replace them with the notice
        !            29:     and other provisions required by the GPL.  If you do not delete
        !            30:     the provisions above, a recipient may use your version of this
        !            31:     file under either the MPL or the GPL.
        !            32: 
        !            33: ======================================================================*/
        !            34: 
        !            35: #include <linux/module.h>
        !            36: #include <linux/init.h>
        !            37: #include <linux/config.h>
        !            38: #include <linux/types.h>
        !            39: #include <linux/fcntl.h>
        !            40: #include <linux/string.h>
        !            41: #include <linux/kernel.h>
        !            42: #include <linux/errno.h>
        !            43: #include <linux/timer.h>
        !            44: #include <linux/sched.h>
        !            45: #include <linux/slab.h>
        !            46: #include <linux/pci.h>
        !            47: #include <linux/ioport.h>
        !            48: #include <linux/delay.h>
        !            49: #include <linux/proc_fs.h>
        !            50: #include <linux/spinlock.h>
        !            51: #include <asm/irq.h>
        !            52: #include <asm/io.h>
        !            53: #include <asm/bitops.h>
        !            54: #include <asm/system.h>
        !            55: 
        !            56: #include <pcmcia/version.h>
        !            57: #include <pcmcia/cs_types.h>
        !            58: #include <pcmcia/ss.h>
        !            59: #include <pcmcia/cs.h>
        !            60: 
        !            61: /* ISA-bus controllers */
        !            62: #include "i82365.h"
        !            63: #include "cirrus.h"
        !            64: #include "vg468.h"
        !            65: #include "ricoh.h"
        !            66: #include "o2micro.h"
        !            67: 
        !            68: /* PCI-bus controllers */
        !            69: #include "yenta.h"
        !            70: #include "ti113x.h"
        !            71: #include "smc34c90.h"
        !            72: #include "topic.h"
        !            73: #include "ene.h"
        !            74: 
        !            75: /*====================================================================*/
        !            76: 
        !            77: /* Module parameters */
        !            78: 
        !            79: MODULE_AUTHOR("David Hinds <[email protected]>");
        !            80: MODULE_DESCRIPTION("Intel ExCA/Yenta PCMCIA socket driver");
        !            81: MODULE_LICENSE("Dual MPL/GPL");
        !            82: 
        !            83: #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
        !            84: 
        !            85: /* General options */
        !            86: INT_MODULE_PARM(poll_interval, 0);     /* in ticks, 0 means never */
        !            87: INT_MODULE_PARM(cycle_time, 120);      /* in ns, 120 ns = 8.33 MHz */
        !            88: INT_MODULE_PARM(do_scan, 1);           /* Probe free interrupts? */
        !            89: 
        !            90: /* Cirrus options */
        !            91: INT_MODULE_PARM(has_dma, -1);
        !            92: INT_MODULE_PARM(has_led, -1);
        !            93: INT_MODULE_PARM(has_ring, -1);
        !            94: INT_MODULE_PARM(has_vsense, 0);
        !            95: INT_MODULE_PARM(dynamic_mode, 0);
        !            96: INT_MODULE_PARM(freq_bypass, -1);
        !            97: INT_MODULE_PARM(setup_time, -1);
        !            98: INT_MODULE_PARM(cmd_time, -1);
        !            99: INT_MODULE_PARM(recov_time, -1);
        !           100: 
        !           101: #ifdef CONFIG_ISA
        !           102: INT_MODULE_PARM(i365_base, 0x3e0);     /* IO address for probes */
        !           103: INT_MODULE_PARM(extra_sockets, 0);     /* Probe at i365_base+2? */
        !           104: INT_MODULE_PARM(ignore, -1);           /* Ignore this socket # */
        !           105: INT_MODULE_PARM(cs_irq, 0);            /* card status irq */
        !           106: INT_MODULE_PARM(irq_mask, 0xffff);     /* bit map of irq's to use */
        !           107: static int irq_list[16] = { -1 };
        !           108: MODULE_PARM(irq_list, "1-16i");
        !           109: INT_MODULE_PARM(async_clock, -1);      /* Vadem specific */
        !           110: INT_MODULE_PARM(cable_mode, -1);
        !           111: INT_MODULE_PARM(wakeup, 0);            /* Cirrus specific */
        !           112: #endif
        !           113: 
        !           114: #ifdef CONFIG_PCI
        !           115: static int pci_irq_list[8] = { 0 };    /* PCI interrupt assignments */
        !           116: MODULE_PARM(pci_irq_list, "1-8i");
        !           117: INT_MODULE_PARM(do_pci_probe, 1);      /* Scan for PCI bridges? */
        !           118: INT_MODULE_PARM(fast_pci, -1);
        !           119: INT_MODULE_PARM(cb_write_post, -1);
        !           120: INT_MODULE_PARM(irq_mode, -1);         /* Override BIOS routing? */
        !           121: INT_MODULE_PARM(hold_time, -1);                /* Ricoh specific */
        !           122: INT_MODULE_PARM(p2cclk, -1);           /* TI specific */
        !           123: #endif
        !           124: 
        !           125: #if defined(CONFIG_ISA) && defined(CONFIG_PCI)
        !           126: INT_MODULE_PARM(pci_csc, 1);           /* PCI card status irqs? */
        !           127: INT_MODULE_PARM(pci_int, 1);           /* PCI IO card irqs? */
        !           128: #elif defined(CONFIG_ISA) && !defined(CONFIG_PCI)
        !           129: #define pci_csc                0
        !           130: #define pci_int                0
        !           131: #elif !defined(CONFIG_ISA) && defined(CONFIG_PCI)
        !           132: #define pci_csc                0
        !           133: #define pci_int                1               /* We must use PCI irq's */
        !           134: #else
        !           135: #error "No bus architectures defined!"
        !           136: #endif
        !           137: 
        !           138: #ifdef PCMCIA_DEBUG
        !           139: INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
        !           140: #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
        !           141: static const char *version =
        !           142: "i82365.c 1.358 2003/09/13 17:34:01 (David Hinds)";
        !           143: #else
        !           144: #define DEBUG(n, args...) do { } while (0)
        !           145: #endif
        !           146: 
        !           147: /*====================================================================*/
        !           148: 
        !           149: typedef struct socket_info_t {
        !           150:     u_short            type, flags;
        !           151:     socket_cap_t       cap;
        !           152:     ioaddr_t           ioaddr;
        !           153:     u_short            psock;
        !           154:     u_char             cs_irq, intr;
        !           155:     void               (*handler)(void *info, u_int events);
        !           156:     void               *info;
        !           157: #ifdef HAS_PROC_BUS
        !           158:     struct proc_dir_entry *proc;
        !           159: #endif
        !           160:     u_char             pci_irq_code;
        !           161: #ifdef CONFIG_PCI
        !           162:     u_short            vendor, device;
        !           163:     u_char             revision, bus, devfn;
        !           164:     u_short            bcr;
        !           165:     u_char             pci_lat, cb_lat, sub_bus, cache;
        !           166:     u_int              cb_phys;
        !           167:     char               *cb_virt;
        !           168: #endif
        !           169:     union {
        !           170:        cirrus_state_t          cirrus;
        !           171:        vg46x_state_t           vg46x;
        !           172:        o2micro_state_t         o2micro;
        !           173:        ti113x_state_t          ti113x;
        !           174:        ricoh_state_t           ricoh;
        !           175:        topic_state_t           topic;
        !           176:     } state;
        !           177: } socket_info_t;
        !           178: 
        !           179: /* Where we keep track of our sockets... */
        !           180: static int sockets = 0;
        !           181: static socket_info_t socket[8] = {
        !           182:     { 0, }, /* ... */
        !           183: };
        !           184: 
        !           185: #ifdef CONFIG_ISA
        !           186: static int grab_irq;
        !           187: #ifdef __SMP__
        !           188: static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
        !           189: #endif
        !           190: #define ISA_LOCK(s, f) \
        !           191:     if (!((s)->flags & IS_CARDBUS)) spin_lock_irqsave(&isa_lock, f)
        !           192: #define ISA_UNLOCK(n, f) \
        !           193:     if (!((s)->flags & IS_CARDBUS)) spin_unlock_irqrestore(&isa_lock, f)
        !           194: #else
        !           195: #define ISA_LOCK(n, f) do { } while (0)
        !           196: #define ISA_UNLOCK(n, f) do { } while (0)
        !           197: #endif
        !           198: 
        !           199: static void pcic_interrupt_wrapper(u_long data);
        !           200: static struct timer_list poll_timer = {
        !           201:     function: pcic_interrupt_wrapper
        !           202: };
        !           203: 
        !           204: #define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
        !           205: 
        !           206: /*====================================================================*/
        !           207: 
        !           208: /* Some PCI shortcuts */
        !           209: 
        !           210: #ifdef CONFIG_PCI
        !           211: static int pci_readb(socket_info_t *s, int r, u_char *v)
        !           212: { return pcibios_read_config_byte(s->bus, s->devfn, r, v); }
        !           213: static int pci_writeb(socket_info_t *s, int r, u_char v)
        !           214: { return pcibios_write_config_byte(s->bus, s->devfn, r, v); }
        !           215: static int pci_readw(socket_info_t *s, int r, u_short *v)
        !           216: { return pcibios_read_config_word(s->bus, s->devfn, r, v); }
        !           217: static int pci_writew(socket_info_t *s, int r, u_short v)
        !           218: { return pcibios_write_config_word(s->bus, s->devfn, r, v); }
        !           219: static int pci_readl(socket_info_t *s, int r, u_int *v)
        !           220: { return pcibios_read_config_dword(s->bus, s->devfn, r, v); }
        !           221: static int pci_writel(socket_info_t *s, int r, u_int v)
        !           222: { return pcibios_write_config_dword(s->bus, s->devfn, r, v); }
        !           223: #endif
        !           224: 
        !           225: #define cb_readb(s, r)         readb((s)->cb_virt + (r))
        !           226: #define cb_readl(s, r)         readl((s)->cb_virt + (r))
        !           227: #define cb_writeb(s, r, v)     writeb(v, (s)->cb_virt + (r))
        !           228: #define cb_writel(s, r, v)     writel(v, (s)->cb_virt + (r))
        !           229: 
        !           230: /*====================================================================*/
        !           231: 
        !           232: /* These definitions must match the pcic table! */
        !           233: typedef enum pcic_id {
        !           234: #ifdef CONFIG_ISA
        !           235:     IS_I82365A, IS_I82365B, IS_I82365DF, IS_IBM, IS_RF5Cx96,
        !           236:     IS_VLSI, IS_VG468, IS_VG469, IS_PD6710, IS_PD672X, IS_VT83C469,
        !           237: #endif
        !           238: #ifdef CONFIG_PCI
        !           239:     IS_I82092AA, IS_OM82C092G, CIRRUS_PCIC_ID, O2MICRO_PCIC_ID,
        !           240:     RICOH_PCIC_ID, SMC_PCIC_ID, TI_PCIC_ID, ENE_PCIC_ID,
        !           241:     TOPIC_PCIC_ID, IS_UNK_PCI, IS_UNK_CARDBUS
        !           242: #endif
        !           243: } pcic_id;
        !           244: 
        !           245: /* Flags for classifying groups of controllers */
        !           246: #define IS_VADEM       0x0001
        !           247: #define IS_CIRRUS      0x0002
        !           248: #define IS_TI          0x0004
        !           249: #define IS_O2MICRO     0x0008
        !           250: #define IS_TOPIC       0x0020
        !           251: #define IS_RICOH       0x0040
        !           252: #define IS_UNKNOWN     0x0400
        !           253: #define IS_VG_PWR      0x0800
        !           254: #define IS_DF_PWR      0x1000
        !           255: #define IS_PCI         0x2000
        !           256: #define IS_CARDBUS     0x4000
        !           257: #define IS_ALIVE       0x8000
        !           258: 
        !           259: typedef struct pcic_t {
        !           260:     char               *name;
        !           261:     u_short            flags;
        !           262: #ifdef CONFIG_PCI
        !           263:     u_short            vendor, device;
        !           264: #endif
        !           265: } pcic_t;
        !           266: 
        !           267: #define ID(a,b) PCI_VENDOR_ID_##a,PCI_DEVICE_ID_##a##_##b
        !           268: 
        !           269: static pcic_t pcic[] = {
        !           270: #ifdef CONFIG_ISA
        !           271:     { "Intel i82365sl A step", 0 },
        !           272:     { "Intel i82365sl B step", 0 },
        !           273:     { "Intel i82365sl DF", IS_DF_PWR },
        !           274:     { "IBM Clone", 0 },
        !           275:     { "Ricoh RF5C296/396", 0 },
        !           276:     { "VLSI 82C146", 0 },
        !           277:     { "Vadem VG-468", IS_VADEM },
        !           278:     { "Vadem VG-469", IS_VADEM|IS_VG_PWR },
        !           279:     { "Cirrus PD6710", IS_CIRRUS },
        !           280:     { "Cirrus PD672x", IS_CIRRUS },
        !           281:     { "VIA VT83C469", IS_CIRRUS },
        !           282: #endif
        !           283: #ifdef CONFIG_PCI
        !           284:     { "Intel 82092AA", IS_PCI, ID(INTEL, 82092AA_0) },
        !           285:     { "Omega Micro 82C092G", IS_PCI, ID(OMEGA, 82C092G) },
        !           286:     CIRRUS_PCIC_INFO, O2MICRO_PCIC_INFO, RICOH_PCIC_INFO,
        !           287:     SMC_PCIC_INFO, TI_PCIC_INFO, ENE_PCIC_INFO, TOPIC_PCIC_INFO,
        !           288:     { "Unknown", IS_PCI|IS_UNKNOWN, 0, 0 },
        !           289:     { "Unknown", IS_CARDBUS|IS_UNKNOWN, 0, 0 }
        !           290: #endif
        !           291: };
        !           292: 
        !           293: #define PCIC_COUNT     (sizeof(pcic)/sizeof(pcic_t))
        !           294: 
        !           295: /*====================================================================*/
        !           296: 
        !           297: static u_char i365_get(socket_info_t *s, u_short reg)
        !           298: {
        !           299: #ifdef CONFIG_PCI
        !           300:     if (s->cb_virt)
        !           301:        return cb_readb(s, 0x0800 + reg);
        !           302: #endif
        !           303:     outb(I365_REG(s->psock, reg), s->ioaddr);
        !           304:     return inb(s->ioaddr+1);
        !           305: }
        !           306: 
        !           307: static void i365_set(socket_info_t *s, u_short reg, u_char data)
        !           308: {
        !           309: #ifdef CONFIG_PCI
        !           310:     if (s->cb_virt) {
        !           311:        cb_writeb(s, 0x0800 + reg, data);
        !           312:        return;
        !           313:     }
        !           314: #endif
        !           315:     outb(I365_REG(s->psock, reg), s->ioaddr);
        !           316:     outb(data, s->ioaddr+1);
        !           317: }
        !           318: 
        !           319: static void i365_bset(socket_info_t *s, u_short reg, u_char mask)
        !           320: {
        !           321:     i365_set(s, reg, i365_get(s, reg) | mask);
        !           322: }
        !           323: 
        !           324: static void i365_bclr(socket_info_t *s, u_short reg, u_char mask)
        !           325: {
        !           326:     i365_set(s, reg, i365_get(s, reg) & ~mask);
        !           327: }
        !           328: 
        !           329: static void i365_bflip(socket_info_t *s, u_short reg, u_char mask, int b)
        !           330: {
        !           331:     u_char d = i365_get(s, reg);
        !           332:     i365_set(s, reg, (b) ? (d | mask) : (d & ~mask));
        !           333: }
        !           334: 
        !           335: static u_short i365_get_pair(socket_info_t *s, u_short reg)
        !           336: {
        !           337:     return (i365_get(s, reg) + (i365_get(s, reg+1) << 8));
        !           338: }
        !           339: 
        !           340: static void i365_set_pair(socket_info_t *s, u_short reg, u_short data)
        !           341: {
        !           342:     i365_set(s, reg, data & 0xff);
        !           343:     i365_set(s, reg+1, data >> 8);
        !           344: }
        !           345: 
        !           346: /*======================================================================
        !           347: 
        !           348:     Code to save and restore global state information for Cirrus
        !           349:     PD67xx controllers, and to set and report global configuration
        !           350:     options.
        !           351: 
        !           352:     The VIA controllers also use these routines, as they are mostly
        !           353:     Cirrus lookalikes, without the timing registers.
        !           354:     
        !           355: ======================================================================*/
        !           356: 
        !           357: #ifdef CONFIG_PCI
        !           358: 
        !           359: static int __init get_pci_irq(socket_info_t *s)
        !           360: {
        !           361:     u8 irq = pci_irq_list[s - socket];
        !           362:     if (!irq)
        !           363:        irq = pci_find_slot(s->bus, s->devfn)->irq;
        !           364:     if (irq >= NR_IRQS) irq = 0;
        !           365:     s->cap.pci_irq = irq;
        !           366:     return irq;
        !           367: }
        !           368: 
        !           369: #endif
        !           370: 
        !           371: static void __init cirrus_get_state(socket_info_t *s)
        !           372: {
        !           373:     cirrus_state_t *p = &s->state.cirrus;
        !           374:     int i;
        !           375: 
        !           376:     p->misc1 = i365_get(s, PD67_MISC_CTL_1);
        !           377:     p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
        !           378:     p->misc2 = i365_get(s, PD67_MISC_CTL_2);
        !           379:     if (s->flags & IS_PCI)
        !           380:        p->ectl1 = pd67_ext_get(s, PD67_EXT_CTL_1);
        !           381:     for (i = 0; i < 6; i++)
        !           382:        p->timer[i] = i365_get(s, PD67_TIME_SETUP(0)+i);
        !           383: }
        !           384: 
        !           385: static void cirrus_set_state(socket_info_t *s)
        !           386: {
        !           387:     cirrus_state_t *p = &s->state.cirrus;
        !           388:     u_char misc;
        !           389:     int i;
        !           390: 
        !           391:     misc = i365_get(s, PD67_MISC_CTL_2);
        !           392:     i365_set(s, PD67_MISC_CTL_2, p->misc2);
        !           393:     if (misc & PD67_MC2_SUSPEND) mdelay(50);
        !           394:     misc = i365_get(s, PD67_MISC_CTL_1);
        !           395:     misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
        !           396:     i365_set(s, PD67_MISC_CTL_1, misc | p->misc1);
        !           397:     if (s->flags & IS_PCI)
        !           398:        pd67_ext_set(s, PD67_EXT_CTL_1, p->ectl1);
        !           399:     else if (has_vsense) {
        !           400:        socket_info_t *t = (s->psock) ? s : s+1;
        !           401:        pd67_ext_set(t, PD67_EXT_CTL_2, PD67_EC2_GPSTB_IOR);
        !           402:     }
        !           403:     for (i = 0; i < 6; i++)
        !           404:        i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]);
        !           405: }
        !           406: 
        !           407: #ifdef CONFIG_PCI
        !           408: static int cirrus_set_irq_mode(socket_info_t *s, int pcsc, int pint)
        !           409: {
        !           410:     flip(s->bcr, PD6832_BCR_MGMT_IRQ_ENA, !pcsc);
        !           411:     return 0;
        !           412: }
        !           413: #endif
        !           414: 
        !           415: static u_int __init cirrus_set_opts(socket_info_t *s, char *buf)
        !           416: {
        !           417:     cirrus_state_t *p = &s->state.cirrus;
        !           418:     u_int mask = 0xffff;
        !           419: 
        !           420:     p->misc1 |= PD67_MC1_SPKR_ENA;
        !           421:     if (has_ring == -1) has_ring = 1;
        !           422:     flip(p->misc2, PD67_MC2_IRQ15_RI, has_ring);
        !           423:     flip(p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode);
        !           424:     if (p->misc2 & PD67_MC2_IRQ15_RI)
        !           425:        strcat(buf, " [ring]");
        !           426:     if (p->misc2 & PD67_MC2_DYNAMIC_MODE)
        !           427:        strcat(buf, " [dyn mode]");
        !           428:     if (p->misc1 & PD67_MC1_INPACK_ENA)
        !           429:        strcat(buf, " [inpack]");
        !           430:     if (!(s->flags & (IS_PCI|IS_CARDBUS))) {
        !           431:        flip(p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass);
        !           432:        if (p->misc2 & PD67_MC2_FREQ_BYPASS)
        !           433:            strcat(buf, " [freq bypass]");
        !           434:        if (p->misc2 & PD67_MC2_IRQ15_RI)
        !           435:            mask &= ~0x8000;
        !           436:        if (has_led > 0) {
        !           437:            strcat(buf, " [led]");
        !           438:            mask &= ~0x1000;
        !           439:        }
        !           440:        if (has_dma > 0) {
        !           441:            strcat(buf, " [dma]");
        !           442:            mask &= ~0x0600;
        !           443:        }
        !           444: #ifdef CONFIG_PCI
        !           445:     } else {
        !           446:        p->misc1 &= ~PD67_MC1_MEDIA_ENA;
        !           447:        p->misc1 &= ~(PD67_MC1_PULSE_MGMT | PD67_MC1_PULSE_IRQ);
        !           448:        p->ectl1 &= ~(PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ);
        !           449:        flip(p->misc2, PD67_MC2_FAST_PCI, fast_pci);
        !           450:        if (p->misc2 & PD67_MC2_IRQ15_RI)
        !           451:            mask &= (s->type == IS_PD6730) ? ~0x0400 : ~0x8000;
        !           452:        if ((s->flags & IS_PCI) && (irq_mode == 1) && get_pci_irq(s)) {
        !           453:            /* Configure PD6729 bridge for PCI interrupts */
        !           454:            p->ectl1 |= PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ;
        !           455:            s->pci_irq_code = 3; /* PCI INTA = "irq 3" */
        !           456:            buf += strlen(buf);
        !           457:            sprintf(buf, " [pci irq %d]", s->cap.pci_irq);
        !           458:            mask = 0;
        !           459:        }
        !           460: #endif
        !           461:     }
        !           462: #ifdef CONFIG_ISA
        !           463:     if (s->type != IS_VT83C469)
        !           464: #endif
        !           465:     {
        !           466:        if (setup_time >= 0)
        !           467:            p->timer[0] = p->timer[3] = setup_time;
        !           468:        if (cmd_time > 0) {
        !           469:            p->timer[1] = cmd_time;
        !           470:            p->timer[4] = cmd_time*2+4;
        !           471:        }
        !           472:        if (p->timer[1] == 0) {
        !           473:            p->timer[1] = 6; p->timer[4] = 16;
        !           474:            if (p->timer[0] == 0)
        !           475:                p->timer[0] = p->timer[3] = 1;
        !           476:        }
        !           477:        if (recov_time >= 0)
        !           478:            p->timer[2] = p->timer[5] = recov_time;
        !           479:        buf += strlen(buf);
        !           480:        sprintf(buf, " [%d/%d/%d] [%d/%d/%d]", p->timer[0], p->timer[1],
        !           481:                p->timer[2], p->timer[3], p->timer[4], p->timer[5]);
        !           482:     }
        !           483:     return mask;
        !           484: }
        !           485: 
        !           486: /*======================================================================
        !           487: 
        !           488:     Code to save and restore global state information for Vadem VG468
        !           489:     and VG469 controllers, and to set and report global configuration
        !           490:     options.
        !           491:     
        !           492: ======================================================================*/
        !           493: 
        !           494: #ifdef CONFIG_ISA
        !           495: 
        !           496: static void __init vg46x_get_state(socket_info_t *s)
        !           497: {
        !           498:     vg46x_state_t *p = &s->state.vg46x;
        !           499:     p->ctl = i365_get(s, VG468_CTL);
        !           500:     if (s->type == IS_VG469)
        !           501:        p->ema = i365_get(s, VG469_EXT_MODE);
        !           502: }
        !           503: 
        !           504: static void vg46x_set_state(socket_info_t *s)
        !           505: {
        !           506:     vg46x_state_t *p = &s->state.vg46x;
        !           507:     i365_set(s, VG468_CTL, p->ctl);
        !           508:     if (s->type == IS_VG469)
        !           509:        i365_set(s, VG469_EXT_MODE, p->ema);
        !           510: }
        !           511: 
        !           512: static u_int __init vg46x_set_opts(socket_info_t *s, char *buf)
        !           513: {
        !           514:     vg46x_state_t *p = &s->state.vg46x;
        !           515:     
        !           516:     flip(p->ctl, VG468_CTL_ASYNC, async_clock);
        !           517:     flip(p->ema, VG469_MODE_CABLE, cable_mode);
        !           518:     if (p->ctl & VG468_CTL_ASYNC)
        !           519:        strcat(buf, " [async]");
        !           520:     if (p->ctl & VG468_CTL_INPACK)
        !           521:        strcat(buf, " [inpack]");
        !           522:     if (s->type == IS_VG469) {
        !           523:        u_char vsel = i365_get(s, VG469_VSELECT);
        !           524:        if (vsel & VG469_VSEL_EXT_STAT) {
        !           525:            strcat(buf, " [ext mode]");
        !           526:            if (vsel & VG469_VSEL_EXT_BUS)
        !           527:                strcat(buf, " [isa buf]");
        !           528:        }
        !           529:        if (p->ema & VG469_MODE_CABLE)
        !           530:            strcat(buf, " [cable]");
        !           531:        if (p->ema & VG469_MODE_COMPAT)
        !           532:            strcat(buf, " [c step]");
        !           533:     }
        !           534:     return 0xffff;
        !           535: }
        !           536: 
        !           537: #endif
        !           538: 
        !           539: /*======================================================================
        !           540: 
        !           541:     Code to save and restore global state information for TI 1130 and
        !           542:     TI 1131 controllers, and to set and report global configuration
        !           543:     options.
        !           544:     
        !           545: ======================================================================*/
        !           546: 
        !           547: #ifdef CONFIG_PCI
        !           548: 
        !           549: static void __init ti113x_get_state(socket_info_t *s)
        !           550: {
        !           551:     ti113x_state_t *p = &s->state.ti113x;
        !           552:     pci_readl(s, TI113X_SYSTEM_CONTROL, &p->sysctl);
        !           553:     pci_readb(s, TI113X_CARD_CONTROL, &p->cardctl);
        !           554:     pci_readb(s, TI113X_DEVICE_CONTROL, &p->devctl);
        !           555:     pci_readb(s, TI1250_DIAGNOSTIC, &p->diag);
        !           556:     pci_readl(s, TI12XX_IRQMUX, &p->irqmux);
        !           557: }
        !           558: 
        !           559: static void ti113x_set_state(socket_info_t *s)
        !           560: {
        !           561:     ti113x_state_t *p = &s->state.ti113x;
        !           562:     pci_writel(s, TI113X_SYSTEM_CONTROL, p->sysctl);
        !           563:     pci_writeb(s, TI113X_CARD_CONTROL, p->cardctl);
        !           564:     pci_writeb(s, TI113X_DEVICE_CONTROL, p->devctl);
        !           565:     pci_writeb(s, TI1250_MULTIMEDIA_CTL, 0);
        !           566:     pci_writeb(s, TI1250_DIAGNOSTIC, p->diag);
        !           567:     pci_writel(s, TI12XX_IRQMUX, p->irqmux);
        !           568:     i365_set_pair(s, TI113X_IO_OFFSET(0), 0);
        !           569:     i365_set_pair(s, TI113X_IO_OFFSET(1), 0);
        !           570: }
        !           571: 
        !           572: static int ti113x_set_irq_mode(socket_info_t *s, int pcsc, int pint)
        !           573: {
        !           574:     ti113x_state_t *p = &s->state.ti113x;
        !           575:     s->intr = (pcsc) ? I365_INTR_ENA : 0;
        !           576:     if (s->type <= IS_TI1131) {
        !           577:        p->cardctl &= ~(TI113X_CCR_PCI_IRQ_ENA |
        !           578:                        TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
        !           579:        if (pcsc)
        !           580:            p->cardctl |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC;
        !           581:        if (pint)
        !           582:            p->cardctl |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ;
        !           583:     } else if (s->type == IS_TI1250A) {
        !           584:        p->diag &= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
        !           585:        if (pcsc)
        !           586:            p->diag |= TI1250_DIAG_PCI_CSC;
        !           587:        if (pint)
        !           588:            p->diag |= TI1250_DIAG_PCI_IREQ;
        !           589:     }
        !           590:     return 0;
        !           591: }
        !           592: 
        !           593: static u_int __init ti113x_set_opts(socket_info_t *s, char *buf)
        !           594: {
        !           595:     ti113x_state_t *p = &s->state.ti113x;
        !           596:     u_int mask = 0xffff;
        !           597:     int old = (s->type <= IS_TI1131);
        !           598:     
        !           599:     flip(p->cardctl, TI113X_CCR_RIENB, has_ring);
        !           600:     p->cardctl &= ~TI113X_CCR_ZVENABLE;
        !           601:     p->cardctl |= TI113X_CCR_SPKROUTEN;
        !           602:     if (!old) flip(p->sysctl, TI122X_SCR_P2CCLK, p2cclk);
        !           603:     switch (irq_mode) {
        !           604:     case 0:
        !           605:        p->devctl &= ~TI113X_DCR_IMODE_MASK;
        !           606:        p->irqmux = (p->irqmux & ~0x0f) | 0x02; /* route INTA */
        !           607:        if (!(p->sysctl & TI122X_SCR_INTRTIE))
        !           608:            p->irqmux = (p->irqmux & ~0xf0) | 0x20; /* route INTB */
        !           609:        break;
        !           610:     case 1:
        !           611:        p->devctl &= ~TI113X_DCR_IMODE_MASK;
        !           612:        p->devctl |= TI113X_DCR_IMODE_ISA;
        !           613:        break;
        !           614:     case 2:
        !           615:        p->devctl &= ~TI113X_DCR_IMODE_MASK;
        !           616:        p->devctl |= TI113X_DCR_IMODE_SERIAL;
        !           617:        break;
        !           618:     case 3:
        !           619:        p->devctl &= ~TI113X_DCR_IMODE_MASK;
        !           620:        p->devctl |= TI12XX_DCR_IMODE_ALL_SERIAL;
        !           621:        break;
        !           622:     default:
        !           623:        /* Feeble fallback: if PCI-only but no PCI irq, try ISA */
        !           624:        if (((p->devctl & TI113X_DCR_IMODE_MASK) == 0) &&
        !           625:            (s->cap.pci_irq == 0))
        !           626:            p->devctl |= TI113X_DCR_IMODE_ISA;
        !           627:     }
        !           628:     if (p->cardctl & TI113X_CCR_RIENB) {
        !           629:        strcat(buf, " [ring]");
        !           630:        if (old) mask &= ~0x8000;
        !           631:     }
        !           632:     if (old && (p->sysctl & TI113X_SCR_CLKRUN_ENA)) {
        !           633:        if (p->sysctl & TI113X_SCR_CLKRUN_SEL) {
        !           634:            strcat(buf, " [clkrun irq 12]");
        !           635:            mask &= ~0x1000;
        !           636:        } else {
        !           637:            strcat(buf, " [clkrun irq 10]");
        !           638:            mask &= ~0x0400;
        !           639:        }
        !           640:     }
        !           641:     switch (p->devctl & TI113X_DCR_IMODE_MASK) {
        !           642:     case TI12XX_DCR_IMODE_PCI_ONLY:
        !           643:        strcat(buf, " [pci only]");
        !           644:        mask = 0;
        !           645:        break;
        !           646:     case TI113X_DCR_IMODE_ISA:
        !           647:        strcat(buf, " [isa irq]");
        !           648:        if (old) mask &= ~0x0018;
        !           649:        break;
        !           650:     case TI113X_DCR_IMODE_SERIAL:
        !           651:        strcat(buf, " [pci + serial irq]");
        !           652:        mask = 0xffff;
        !           653:        break;
        !           654:     case TI12XX_DCR_IMODE_ALL_SERIAL:
        !           655:        strcat(buf, " [serial pci & irq]");
        !           656:        mask = 0xffff;
        !           657:        break;
        !           658:     }
        !           659:     return mask;
        !           660: }
        !           661: 
        !           662: #endif
        !           663: 
        !           664: /*======================================================================
        !           665: 
        !           666:     Code to save and restore global state information for the Ricoh
        !           667:     RL5C4XX controllers, and to set and report global configuration
        !           668:     options.
        !           669: 
        !           670:     The interrupt test doesn't seem to be reliable with Ricoh
        !           671:     bridges.  It seems to depend on what type of card is in the
        !           672:     socket, and on the history of that socket, in some way that
        !           673:     doesn't show up in the current socket state.
        !           674: 
        !           675: ======================================================================*/
        !           676: 
        !           677: #ifdef CONFIG_PCI
        !           678: 
        !           679: static void __init ricoh_get_state(socket_info_t *s)
        !           680: {
        !           681:     ricoh_state_t *p = &s->state.ricoh;
        !           682:     pci_readw(s, RL5C4XX_CONFIG, &p->config);
        !           683:     pci_readw(s, RL5C4XX_MISC, &p->misc);
        !           684:     pci_readw(s, RL5C4XX_16BIT_CTL, &p->ctl);
        !           685:     pci_readw(s, RL5C4XX_16BIT_IO_0, &p->io);
        !           686:     pci_readw(s, RL5C4XX_16BIT_MEM_0, &p->mem);
        !           687: }
        !           688: 
        !           689: static void ricoh_set_state(socket_info_t *s)
        !           690: {
        !           691:     ricoh_state_t *p = &s->state.ricoh;
        !           692:     pci_writew(s, RL5C4XX_CONFIG, p->config);
        !           693:     pci_writew(s, RL5C4XX_MISC, p->misc);
        !           694:     pci_writew(s, RL5C4XX_16BIT_CTL, p->ctl);
        !           695:     pci_writew(s, RL5C4XX_16BIT_IO_0, p->io);
        !           696:     pci_writew(s, RL5C4XX_16BIT_MEM_0, p->mem);
        !           697: }
        !           698: 
        !           699: static u_int __init ricoh_set_opts(socket_info_t *s, char *buf)
        !           700: {
        !           701:     ricoh_state_t *p = &s->state.ricoh;
        !           702:     u_int mask = 0xffff;
        !           703:     int old = (s->type < IS_RL5C475);
        !           704: 
        !           705:     p->ctl = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
        !           706:     if (old)
        !           707:        p->ctl |= RL5C46X_16CTL_LEVEL_1 | RL5C46X_16CTL_LEVEL_2;
        !           708:     else
        !           709:        p->config |= RL5C4XX_CONFIG_PREFETCH;
        !           710: 
        !           711:     if (setup_time >= 0) {
        !           712:        p->io = (p->io & ~RL5C4XX_SETUP_MASK) +
        !           713:            ((setup_time+1) << RL5C4XX_SETUP_SHIFT);
        !           714:        p->mem = (p->mem & ~RL5C4XX_SETUP_MASK) +
        !           715:            (setup_time << RL5C4XX_SETUP_SHIFT);
        !           716:     }
        !           717:     if (cmd_time >= 0) {
        !           718:        p->io = (p->io & ~RL5C4XX_CMD_MASK) +
        !           719:            (cmd_time << RL5C4XX_CMD_SHIFT);
        !           720:        p->mem = (p->mem & ~RL5C4XX_CMD_MASK) +
        !           721:            (cmd_time << RL5C4XX_CMD_SHIFT);
        !           722:     }
        !           723:     if (hold_time >= 0) {
        !           724:        p->io = (p->io & ~RL5C4XX_HOLD_MASK) +
        !           725:            (hold_time << RL5C4XX_HOLD_SHIFT);
        !           726:        p->mem = (p->mem & ~RL5C4XX_HOLD_MASK) +
        !           727:            (hold_time << RL5C4XX_HOLD_SHIFT);
        !           728:     }
        !           729:     if (irq_mode == 0) {
        !           730:        mask = 0;
        !           731:        p->misc &= ~RL5C47X_MISC_SRIRQ_ENA;
        !           732:        sprintf(buf, " [pci only]");
        !           733:        buf += strlen(buf);
        !           734:     } else if (!old) {
        !           735:        switch (irq_mode) {
        !           736:        case 1:
        !           737:            p->misc &= ~RL5C47X_MISC_SRIRQ_ENA; break;
        !           738:        case 2:
        !           739:            p->misc |= RL5C47X_MISC_SRIRQ_ENA; break;
        !           740:        }
        !           741:        if (p->misc & RL5C47X_MISC_SRIRQ_ENA)
        !           742:            sprintf(buf, " [serial irq]");
        !           743:        else
        !           744:            sprintf(buf, " [isa irq]");
        !           745:        buf += strlen(buf);
        !           746:     }
        !           747:     sprintf(buf, " [io %d/%d/%d] [mem %d/%d/%d]",
        !           748:            (p->io & RL5C4XX_SETUP_MASK) >> RL5C4XX_SETUP_SHIFT,
        !           749:            (p->io & RL5C4XX_CMD_MASK) >> RL5C4XX_CMD_SHIFT,
        !           750:            (p->io & RL5C4XX_HOLD_MASK) >> RL5C4XX_HOLD_SHIFT,
        !           751:            (p->mem & RL5C4XX_SETUP_MASK) >> RL5C4XX_SETUP_SHIFT,
        !           752:            (p->mem & RL5C4XX_CMD_MASK) >> RL5C4XX_CMD_SHIFT,
        !           753:            (p->mem & RL5C4XX_HOLD_MASK) >> RL5C4XX_HOLD_SHIFT);
        !           754:     return mask;
        !           755: }
        !           756: 
        !           757: #endif
        !           758: 
        !           759: /*======================================================================
        !           760: 
        !           761:     Code to save and restore global state information for O2Micro
        !           762:     controllers, and to set and report global configuration options.
        !           763:     
        !           764: ======================================================================*/
        !           765: 
        !           766: #ifdef CONFIG_PCI
        !           767: 
        !           768: static void __init o2micro_get_state(socket_info_t *s)
        !           769: {
        !           770:     o2micro_state_t *p = &s->state.o2micro;
        !           771:     if ((s->revision == 0x34) || (s->revision == 0x62) ||
        !           772:        (s->type == IS_OZ6812)) {
        !           773:        p->mode_a = i365_get(s, O2_MODE_A_2);
        !           774:        p->mode_b = i365_get(s, O2_MODE_B_2);
        !           775:     } else {
        !           776:        p->mode_a = i365_get(s, O2_MODE_A);
        !           777:        p->mode_b = i365_get(s, O2_MODE_B);
        !           778:     }
        !           779:     p->mode_c = i365_get(s, O2_MODE_C);
        !           780:     p->mode_d = i365_get(s, O2_MODE_D);
        !           781:     if (s->flags & IS_CARDBUS) {
        !           782:        p->mhpg = i365_get(s, O2_MHPG_DMA);
        !           783:        p->fifo = i365_get(s, O2_FIFO_ENA);
        !           784:        p->mode_e = i365_get(s, O2_MODE_E);
        !           785:     }
        !           786: }
        !           787: 
        !           788: static void o2micro_set_state(socket_info_t *s)
        !           789: {
        !           790:     o2micro_state_t *p = &s->state.o2micro;
        !           791:     if ((s->revision == 0x34) || (s->revision == 0x62) ||
        !           792:        (s->type == IS_OZ6812)) {
        !           793:        i365_set(s, O2_MODE_A_2, p->mode_a);
        !           794:        i365_set(s, O2_MODE_B_2, p->mode_b);
        !           795:     } else {
        !           796:        i365_set(s, O2_MODE_A, p->mode_a);
        !           797:        i365_set(s, O2_MODE_B, p->mode_b);
        !           798:     }
        !           799:     i365_set(s, O2_MODE_C, p->mode_c);
        !           800:     i365_set(s, O2_MODE_D, p->mode_d);
        !           801:     if (s->flags & IS_CARDBUS) {
        !           802:        i365_set(s, O2_MHPG_DMA, p->mhpg);
        !           803:        i365_set(s, O2_FIFO_ENA, p->fifo);
        !           804:        i365_set(s, O2_MODE_E, p->mode_e);
        !           805:     }
        !           806: }
        !           807: 
        !           808: static u_int __init o2micro_set_opts(socket_info_t *s, char *buf)
        !           809: {
        !           810:     o2micro_state_t *p = &s->state.o2micro;
        !           811:     u_int mask = 0xffff;
        !           812: 
        !           813:     p->mode_b = (p->mode_b & ~O2_MODE_B_IDENT) | O2_MODE_B_ID_CSTEP;
        !           814:     flip(p->mode_b, O2_MODE_B_IRQ15_RI, has_ring);
        !           815:     p->mode_c &= ~(O2_MODE_C_ZVIDEO | O2_MODE_C_DREQ_MASK);
        !           816:     if (s->flags & IS_CARDBUS) {
        !           817:        p->mode_d &= ~O2_MODE_D_W97_IRQ;
        !           818:        p->mode_e &= ~O2_MODE_E_MHPG_DMA;
        !           819:        p->mhpg = O2_MHPG_CINT_ENA | O2_MHPG_CSC_ENA;
        !           820:        if (s->revision == 0x34)
        !           821:            p->mode_c = 0x20;
        !           822:     } else {
        !           823:        if (p->mode_b & O2_MODE_B_IRQ15_RI) mask &= ~0x8000;
        !           824:     }
        !           825:     if (p->mode_b & O2_MODE_B_IRQ15_RI)
        !           826:        strcat(buf, " [ring]");
        !           827:     if (irq_mode != -1)
        !           828:        p->mode_d = irq_mode;
        !           829:     if (p->mode_d & O2_MODE_D_ISA_IRQ) {
        !           830:        strcat(buf, " [pci+isa]");
        !           831:     } else {
        !           832:        switch (p->mode_d & O2_MODE_D_IRQ_MODE) {
        !           833:        case O2_MODE_D_IRQ_PCPCI:
        !           834:            strcat(buf, " [pc/pci]"); break;
        !           835:        case O2_MODE_D_IRQ_PCIWAY:
        !           836:            strcat(buf, " [pci/way]"); break;
        !           837:        case O2_MODE_D_IRQ_PCI:
        !           838:            strcat(buf, " [pci only]"); mask = 0; break;
        !           839:        }
        !           840:     }
        !           841:     if (s->flags & IS_CARDBUS) {
        !           842:        if (p->mode_d & O2_MODE_D_W97_IRQ)
        !           843:            strcat(buf, " [win97]");
        !           844:     }
        !           845:     return mask;
        !           846: }
        !           847: 
        !           848: #endif
        !           849: 
        !           850: /*======================================================================
        !           851: 
        !           852:     Code to save and restore global state information for the Toshiba
        !           853:     ToPIC 95 and 97 controllers, and to set and report global
        !           854:     configuration options.
        !           855:     
        !           856: ======================================================================*/
        !           857: 
        !           858: #ifdef CONFIG_PCI
        !           859: 
        !           860: static void __init topic_get_state(socket_info_t *s)
        !           861: {
        !           862:     topic_state_t *p = &s->state.topic;
        !           863:     pci_readb(s, TOPIC_SLOT_CONTROL, &p->slot);
        !           864:     pci_readb(s, TOPIC_CARD_CONTROL, &p->ccr);
        !           865:     pci_readb(s, TOPIC_CARD_DETECT, &p->cdr);
        !           866:     pci_readl(s, TOPIC_REGISTER_CONTROL, &p->rcr);
        !           867:     p->fcr = i365_get(s, TOPIC_FUNCTION_CONTROL);
        !           868: }
        !           869: 
        !           870: static void topic_set_state(socket_info_t *s)
        !           871: {
        !           872:     topic_state_t *p = &s->state.topic;
        !           873:     u_int state;
        !           874:     pci_writeb(s, TOPIC_SLOT_CONTROL, p->slot);
        !           875:     pci_writeb(s, TOPIC_CARD_CONTROL, p->ccr);
        !           876:     pci_writeb(s, TOPIC_CARD_DETECT, p->cdr);
        !           877:     pci_writel(s, TOPIC_REGISTER_CONTROL, p->rcr);
        !           878:     i365_set(s, TOPIC_FUNCTION_CONTROL, p->fcr);
        !           879:     state = cb_readl(s, CB_SOCKET_STATE);
        !           880:     if (!(state & CB_SS_32BIT))
        !           881:        cb_writel(s, CB_SOCKET_CONTROL, 0);
        !           882:     if (!(state & CB_SS_VSENSE))
        !           883:        cb_writel(s, CB_SOCKET_FORCE, CB_SF_CVSTEST);
        !           884: }
        !           885: 
        !           886: static u_int __init topic_set_opts(socket_info_t *s, char *buf)
        !           887: {
        !           888:     topic_state_t *p = &s->state.topic;
        !           889: 
        !           890:     p->slot |= TOPIC_SLOT_SLOTON|TOPIC_SLOT_SLOTEN;
        !           891:     p->slot &= ~TOPIC_SLOT_ID_LOCK;
        !           892:     p->cdr |= TOPIC_CDR_MODE_PC32;
        !           893:     p->cdr &= ~(TOPIC_CDR_SW_DETECT);
        !           894:     p->ccr |= TOPIC97_ICR_IRQSEL;
        !           895:     p->fcr |= TOPIC_FCR_3V_ENA;
        !           896:     sprintf(buf, " [slot 0x%02x] [ccr 0x%02x] [cdr 0x%02x] [rcr 0x%02x]",
        !           897:            p->slot, p->ccr, p->cdr, p->rcr);
        !           898:     return 0xffff;
        !           899: }
        !           900: 
        !           901: #endif
        !           902: 
        !           903: /*======================================================================
        !           904: 
        !           905:     Routines to handle common CardBus options
        !           906:     
        !           907: ======================================================================*/
        !           908: 
        !           909: /* Default settings for PCI command configuration register */
        !           910: #define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \
        !           911:                  PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
        !           912: 
        !           913: #ifdef CONFIG_PCI
        !           914: 
        !           915: static void __init cb_get_state(socket_info_t *s)
        !           916: {
        !           917:     pci_readb(s, PCI_CACHE_LINE_SIZE, &s->cache);
        !           918:     pci_readb(s, PCI_LATENCY_TIMER, &s->pci_lat);
        !           919:     pci_readb(s, CB_LATENCY_TIMER, &s->cb_lat);
        !           920:     pci_readb(s, CB_CARDBUS_BUS, &s->cap.cardbus);
        !           921:     pci_readb(s, CB_SUBORD_BUS, &s->sub_bus);
        !           922:     pci_readw(s, CB_BRIDGE_CONTROL, &s->bcr);
        !           923:     get_pci_irq(s);
        !           924: }
        !           925: 
        !           926: static void cb_set_state(socket_info_t *s)
        !           927: {
        !           928:     pci_set_power_state(pci_find_slot(s->bus, s->devfn), 0);
        !           929:     pci_writel(s, CB_LEGACY_MODE_BASE, 0);
        !           930:     pci_writel(s, PCI_BASE_ADDRESS_0, s->cb_phys);
        !           931:     pci_writew(s, PCI_COMMAND, CMD_DFLT);
        !           932:     pci_writeb(s, PCI_CACHE_LINE_SIZE, s->cache);
        !           933:     pci_writeb(s, PCI_LATENCY_TIMER, s->pci_lat);
        !           934:     pci_writeb(s, CB_LATENCY_TIMER, s->cb_lat);
        !           935:     pci_writeb(s, CB_CARDBUS_BUS, s->cap.cardbus);
        !           936:     pci_writeb(s, CB_SUBORD_BUS, s->sub_bus);
        !           937:     pci_writew(s, CB_BRIDGE_CONTROL, s->bcr);
        !           938: }
        !           939: 
        !           940: static int cb_get_irq_mode(socket_info_t *s)
        !           941: {
        !           942:     return (!(s->bcr & CB_BCR_ISA_IRQ));
        !           943: }
        !           944: 
        !           945: static int cb_set_irq_mode(socket_info_t *s, int pcsc, int pint)
        !           946: {
        !           947:     flip(s->bcr, CB_BCR_ISA_IRQ, !(pint));
        !           948:     if (s->flags & IS_CIRRUS)
        !           949:        return cirrus_set_irq_mode(s, pcsc, pint);
        !           950:     else if (s->flags & IS_TI)
        !           951:        return ti113x_set_irq_mode(s, pcsc, pint);
        !           952:     /* By default, assume that we can't do ISA status irqs */
        !           953:     return (!pcsc);
        !           954: }
        !           955: 
        !           956: static void __init cb_set_opts(socket_info_t *s, char *buf)
        !           957: {
        !           958:     s->bcr |= CB_BCR_WRITE_POST;
        !           959:     /* some TI1130's seem to exhibit problems with write posting */
        !           960:     if (((s->type == IS_TI1130) && (s->revision == 4) &&
        !           961:         (cb_write_post < 0)) || (cb_write_post == 0))
        !           962:        s->bcr &= ~CB_BCR_WRITE_POST;
        !           963:     if (s->cache == 0) s->cache = 8;
        !           964:     if (s->pci_lat == 0) s->pci_lat = 0xa8;
        !           965:     if (s->cb_lat == 0) s->cb_lat = 0xb0;
        !           966:     if (s->cap.pci_irq == 0)
        !           967:        strcat(buf, " [no pci irq]");
        !           968:     else
        !           969:        sprintf(buf, " [pci irq %d]", s->cap.pci_irq);
        !           970:     buf += strlen(buf);
        !           971:     if (!(s->flags & IS_TOPIC))
        !           972:        s->cap.features |= SS_CAP_PAGE_REGS;
        !           973:     sprintf(buf, " [lat %d/%d] [bus %d/%d]",
        !           974:            s->pci_lat, s->cb_lat, s->cap.cardbus, s->sub_bus);
        !           975: }
        !           976: 
        !           977: #endif
        !           978: 
        !           979: /*======================================================================
        !           980: 
        !           981:     Power control for Cardbus controllers: used both for 16-bit and
        !           982:     Cardbus cards.
        !           983:     
        !           984: ======================================================================*/
        !           985: 
        !           986: #ifdef CONFIG_PCI
        !           987: 
        !           988: static void cb_get_power(socket_info_t *s, socket_state_t *state)
        !           989: {
        !           990:     u_int reg = cb_readl(s, CB_SOCKET_CONTROL);
        !           991:     state->Vcc = state->Vpp = 0;
        !           992:     switch (reg & CB_SC_VCC_MASK) {
        !           993:     case CB_SC_VCC_3V:         state->Vcc = 33; break;
        !           994:     case CB_SC_VCC_5V:         state->Vcc = 50; break;
        !           995:     }
        !           996:     switch (reg & CB_SC_VPP_MASK) {
        !           997:     case CB_SC_VPP_3V:         state->Vpp = 33; break;
        !           998:     case CB_SC_VPP_5V:         state->Vpp = 50; break;
        !           999:     case CB_SC_VPP_12V:                state->Vpp = 120; break;
        !          1000:     }
        !          1001: }
        !          1002: 
        !          1003: static int cb_set_power(socket_info_t *s, socket_state_t *state)
        !          1004: {
        !          1005:     u_int reg = 0;
        !          1006:     /* restart card voltage detection if it seems appropriate */
        !          1007:     if ((state->Vcc == 0) && (state->Vpp == 0) &&
        !          1008:        !(cb_readl(s, CB_SOCKET_STATE) & CB_SS_VSENSE))
        !          1009:        cb_writel(s, CB_SOCKET_FORCE, CB_SF_CVSTEST);
        !          1010:     switch (state->Vcc) {
        !          1011:     case 0:            reg = 0; break;
        !          1012:     case 33:           reg = CB_SC_VCC_3V; break;
        !          1013:     case 50:           reg = CB_SC_VCC_5V; break;
        !          1014:     default:           return -EINVAL;
        !          1015:     }
        !          1016:     switch (state->Vpp) {
        !          1017:     case 0:            break;
        !          1018:     case 33:           reg |= CB_SC_VPP_3V; break;
        !          1019:     case 50:           reg |= CB_SC_VPP_5V; break;
        !          1020:     case 120:          reg |= CB_SC_VPP_12V; break;
        !          1021:     default:           return -EINVAL;
        !          1022:     }
        !          1023:     if (reg != cb_readl(s, CB_SOCKET_CONTROL))
        !          1024:        cb_writel(s, CB_SOCKET_CONTROL, reg);
        !          1025:     return 0;
        !          1026: }
        !          1027: 
        !          1028: #endif
        !          1029: 
        !          1030: /*======================================================================
        !          1031: 
        !          1032:     Generic routines to get and set controller options
        !          1033:     
        !          1034: ======================================================================*/
        !          1035: 
        !          1036: static void __init get_bridge_state(socket_info_t *s)
        !          1037: {
        !          1038:     if (s->flags & IS_CIRRUS)
        !          1039:        cirrus_get_state(s);
        !          1040: #ifdef CONFIG_ISA
        !          1041:     else if (s->flags & IS_VADEM)
        !          1042:        vg46x_get_state(s);
        !          1043: #endif
        !          1044: #ifdef CONFIG_PCI
        !          1045:     else if (s->flags & IS_O2MICRO)
        !          1046:        o2micro_get_state(s);
        !          1047:     else if (s->flags & IS_TI)
        !          1048:        ti113x_get_state(s);
        !          1049:     else if (s->flags & IS_RICOH)
        !          1050:        ricoh_get_state(s);
        !          1051:     else if (s->flags & IS_TOPIC)
        !          1052:        topic_get_state(s);
        !          1053:     if (s->flags & IS_CARDBUS)
        !          1054:        cb_get_state(s);
        !          1055: #endif
        !          1056: }
        !          1057: 
        !          1058: static void set_bridge_state(socket_info_t *s)
        !          1059: {
        !          1060: #ifdef CONFIG_PCI
        !          1061:     if (s->flags & IS_CARDBUS)
        !          1062:        cb_set_state(s);
        !          1063: #endif
        !          1064:     if (s->flags & IS_CIRRUS) {
        !          1065:        cirrus_set_state(s);
        !          1066:     } else {
        !          1067:        i365_set(s, I365_GBLCTL, 0x00);
        !          1068:        i365_set(s, I365_GENCTL, 0x00);
        !          1069:        /* Trouble: changes timing of memory operations */
        !          1070:        /* i365_bset(s, I365_ADDRWIN, I365_ADDR_MEMCS16); */
        !          1071:     }
        !          1072:     i365_bflip(s, I365_INTCTL, I365_INTR_ENA, s->intr);
        !          1073: #ifdef CONFIG_ISA
        !          1074:     if (s->flags & IS_VADEM)
        !          1075:        vg46x_set_state(s);
        !          1076: #endif
        !          1077: #ifdef CONFIG_PCI
        !          1078:     if (s->flags & IS_O2MICRO)
        !          1079:        o2micro_set_state(s);
        !          1080:     else if (s->flags & IS_TI)
        !          1081:        ti113x_set_state(s);
        !          1082:     else if (s->flags & IS_RICOH)
        !          1083:        ricoh_set_state(s);
        !          1084:     else if (s->flags & IS_TOPIC)
        !          1085:        topic_set_state(s);
        !          1086: #endif
        !          1087: }
        !          1088: 
        !          1089: static u_int __init set_bridge_opts(socket_info_t *s, u_short ns)
        !          1090: {
        !          1091:     u_short i;
        !          1092:     u_int m = 0xffff;
        !          1093:     char buf[128];
        !          1094: 
        !          1095:     for (i = 0; i < ns; i++) {
        !          1096:        if (s[i].flags & IS_ALIVE) {
        !          1097:            printk(KERN_INFO "    host opts [%d]: already alive!\n", i);
        !          1098:            continue;
        !          1099:        }
        !          1100:        buf[0] = '\0';
        !          1101:        get_bridge_state(s+i);
        !          1102:        if (s[i].flags & IS_CIRRUS)
        !          1103:            m = cirrus_set_opts(s+i, buf);
        !          1104: #ifdef CONFIG_ISA
        !          1105:        else if (s[i].flags & IS_VADEM)
        !          1106:            m = vg46x_set_opts(s+i, buf);
        !          1107: #endif
        !          1108: #ifdef CONFIG_PCI
        !          1109:        else if (s[i].flags & IS_O2MICRO)
        !          1110:            m = o2micro_set_opts(s+i, buf);
        !          1111:        else if (s[i].flags & IS_TI)
        !          1112:            m = ti113x_set_opts(s+i, buf);
        !          1113:        else if (s[i].flags & IS_RICOH)
        !          1114:            m = ricoh_set_opts(s+i, buf);
        !          1115:        else if (s[i].flags & IS_TOPIC)
        !          1116:            m = topic_set_opts(s+i, buf);
        !          1117:        if (s[i].flags & IS_CARDBUS)
        !          1118:            cb_set_opts(s+i, buf+strlen(buf));
        !          1119: #endif
        !          1120:        set_bridge_state(s+i);
        !          1121:        printk(KERN_INFO "    host opts [%d]:%s\n", i,
        !          1122:               (*buf) ? buf : " none");
        !          1123:     }
        !          1124: #ifdef CONFIG_PCI
        !          1125:     m &= ~pci_irq_mask;
        !          1126: #endif
        !          1127:     return m;
        !          1128: }
        !          1129: 
        !          1130: /*======================================================================
        !          1131: 
        !          1132:     Interrupt testing code, for ISA and PCI interrupts
        !          1133:     
        !          1134: ======================================================================*/
        !          1135: 
        !          1136: static volatile u_int irq_hits, irq_shared;
        !          1137: static volatile socket_info_t *irq_sock;
        !          1138: 
        !          1139: static void irq_count(int irq, void *dev, struct pt_regs *regs)
        !          1140: {
        !          1141:     irq_hits++;
        !          1142:     DEBUG(2, "-> hit on irq %d\n", irq);
        !          1143:     if (!irq_shared && (irq_hits > 100)) {
        !          1144:        printk(KERN_INFO "    PCI irq %d seems to be wedged!\n", irq);
        !          1145:        disable_irq(irq);
        !          1146:        return;
        !          1147:     }
        !          1148: #ifdef CONFIG_PCI
        !          1149:     if (irq_sock->flags & IS_CARDBUS) {
        !          1150:        cb_writel(irq_sock, CB_SOCKET_EVENT, -1);
        !          1151:     } else
        !          1152: #endif
        !          1153:     i365_get((socket_info_t *)irq_sock, I365_CSC);
        !          1154:     return;
        !          1155: }
        !          1156: 
        !          1157: static u_int __init test_irq(socket_info_t *s, int irq, int pci)
        !          1158: {
        !          1159:     u_char csc = (pci) ? 0 : irq;
        !          1160: 
        !          1161: #ifdef CONFIG_PNP_BIOS
        !          1162:     extern int check_pnp_irq(int);
        !          1163:     if (!pci && check_pnp_irq(irq)) return 1;
        !          1164: #endif
        !          1165: 
        !          1166:     DEBUG(2, "  testing %s irq %d\n", pci ? "PCI" : "ISA", irq);
        !          1167:     irq_sock = s; irq_shared = irq_hits = 0;
        !          1168:     if (request_irq(irq, irq_count, 0, "scan", socket)) {
        !          1169:        irq_shared++;
        !          1170:        if (!pci || request_irq(irq, irq_count, SA_SHIRQ, "scan", socket))
        !          1171:            return 1;
        !          1172:     }
        !          1173:     irq_hits = 0;
        !          1174: 
        !          1175: #ifndef MACH
        !          1176:     __set_current_state(TASK_UNINTERRUPTIBLE);
        !          1177:     schedule_timeout(HZ/100);
        !          1178: #else
        !          1179:     /* TODO: Is this really what we want?  */
        !          1180:     {
        !          1181:       unsigned long flags;
        !          1182:       
        !          1183:       save_flags(flags);
        !          1184: 
        !          1185:       mdelay(1);
        !          1186: #endif
        !          1187: 
        !          1188:     if (irq_hits && !irq_shared) {
        !          1189:        free_irq(irq, socket);
        !          1190:        DEBUG(2, "    spurious hit!\n");
        !          1191:        return 1;
        !          1192:     }
        !          1193: 
        !          1194:     /* Generate one interrupt */
        !          1195: #ifdef CONFIG_PCI
        !          1196:     if (s->flags & IS_CARDBUS) {
        !          1197:        cb_writel(s, CB_SOCKET_EVENT, -1);
        !          1198:        i365_set(s, I365_CSCINT, I365_CSC_STSCHG | (csc << 4));
        !          1199:        cb_writel(s, CB_SOCKET_EVENT, -1);
        !          1200:        cb_writel(s, CB_SOCKET_MASK, CB_SM_CSTSCHG);
        !          1201:        cb_writel(s, CB_SOCKET_FORCE, CB_SE_CSTSCHG);
        !          1202:        mdelay(1);
        !          1203:        cb_writel(s, CB_SOCKET_EVENT, -1);
        !          1204:        cb_writel(s, CB_SOCKET_MASK, 0);
        !          1205:     } else
        !          1206: #endif
        !          1207:     {
        !          1208:        i365_set(s, I365_CSCINT, I365_CSC_DETECT | (csc << 4));
        !          1209:        i365_bset(s, I365_GENCTL, I365_CTL_SW_IRQ);
        !          1210:        mdelay(1);
        !          1211:     }
        !          1212: 
        !          1213: #ifdef MACH
        !          1214:     restore_flags(flags);
        !          1215:     }
        !          1216: 
        !          1217: #endif
        !          1218: 
        !          1219:     free_irq(irq, socket);
        !          1220: 
        !          1221:     /* mask all interrupts */
        !          1222:     i365_set(s, I365_CSCINT, 0);
        !          1223:     DEBUG(2, "    hits = %d\n", irq_hits);
        !          1224:     
        !          1225:     return pci ? (irq_hits == 0) : (irq_hits != 1);
        !          1226: }
        !          1227: 
        !          1228: #ifdef CONFIG_ISA
        !          1229: static int _check_irq(int irq, int flags)
        !          1230: {
        !          1231: #ifdef CONFIG_PNP_BIOS
        !          1232:     extern int check_pnp_irq(int);
        !          1233:     if ((flags != SA_SHIRQ) && check_pnp_irq(irq))
        !          1234:        return -1;
        !          1235: #endif
        !          1236:     if (request_irq(irq, irq_count, flags, "x", irq_count) != 0)
        !          1237:        return -1;
        !          1238:     free_irq(irq, irq_count);
        !          1239:     return 0;
        !          1240: }
        !          1241: 
        !          1242: static u_int __init isa_scan(socket_info_t *s, u_int mask0)
        !          1243: {
        !          1244:     u_int mask1 = 0;
        !          1245:     int i;
        !          1246: 
        !          1247: #ifdef CONFIG_PCI
        !          1248:     /* Only scan if we can select ISA csc irq's */
        !          1249:     if (!(s->flags & IS_CARDBUS) || (cb_set_irq_mode(s, 0, 0) == 0))
        !          1250: #endif
        !          1251:     if (do_scan) {
        !          1252:        set_bridge_state(s);
        !          1253:        i365_set(s, I365_CSCINT, 0);
        !          1254:        for (i = 0; i < 16; i++)
        !          1255:            if ((mask0 & (1 << i)) && (test_irq(s, i, 0) == 0))
        !          1256:                mask1 |= (1 << i);
        !          1257:        for (i = 0; i < 16; i++)
        !          1258:            if ((mask1 & (1 << i)) && (test_irq(s, i, 0) != 0))
        !          1259:                mask1 ^= (1 << i);
        !          1260:     }
        !          1261:     
        !          1262:     printk(KERN_INFO "    ISA irqs (");
        !          1263:     /* we trust TI bridges to do this right */
        !          1264:     if (mask1 || (s->flags & IS_TI)) {
        !          1265:        printk("scanned");
        !          1266:     } else {
        !          1267:        /* Fallback: just find interrupts that aren't in use */
        !          1268:        for (i = 0; i < 16; i++)
        !          1269:            if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0))
        !          1270:                mask1 |= (1 << i);
        !          1271:        printk("default");
        !          1272:        /* If scan failed, default to polled status */
        !          1273:        if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
        !          1274:     }
        !          1275:     printk(") = ");
        !          1276:     
        !          1277:     for (i = 0; i < 16; i++)
        !          1278:        if (mask1 & (1<<i))
        !          1279:            printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
        !          1280:     if (mask1 == 0) printk("none!");
        !          1281:     
        !          1282:     return mask1;
        !          1283: }
        !          1284: #endif /* CONFIG_ISA */
        !          1285: 
        !          1286: #ifdef CONFIG_PCI
        !          1287: static int __init pci_scan(socket_info_t *s)
        !          1288: {
        !          1289:     int ret;
        !          1290:     if ((s->flags & IS_RICOH) || !(s->flags & IS_CARDBUS) || !do_scan) {
        !          1291:        /* for PCI-to-PCMCIA bridges, just check for wedged irq */
        !          1292:        irq_sock = s; irq_hits = 0;
        !          1293:        if (request_irq(s->cap.pci_irq, irq_count, 0, "scan", socket))
        !          1294:            return 1;
        !          1295:        udelay(50);
        !          1296:        free_irq(s->cap.pci_irq, socket);
        !          1297:        return (!irq_hits);
        !          1298:     }
        !          1299:     cb_set_irq_mode(s, 1, 0);
        !          1300:     set_bridge_state(s);
        !          1301:     i365_set(s, I365_CSCINT, 0);
        !          1302:     ret = ((test_irq(s, s->cap.pci_irq, 1) == 0) &&
        !          1303:           (test_irq(s, s->cap.pci_irq, 1) == 0));
        !          1304:     if (!ret)
        !          1305:        printk(KERN_INFO "    PCI irq %d test failed\n",
        !          1306:               s->cap.pci_irq);
        !          1307:     return ret;
        !          1308: }
        !          1309: #endif /* CONFIG_PCI */
        !          1310: 
        !          1311: /*====================================================================*/
        !          1312: 
        !          1313: #ifdef CONFIG_ISA
        !          1314: 
        !          1315: static int __init isa_identify(u_short port, u_short sock)
        !          1316: {
        !          1317:     socket_info_t *s = socket+sockets;
        !          1318:     u_char val;
        !          1319:     int type = -1;
        !          1320: 
        !          1321:     /* Use the next free entry in the socket table */
        !          1322:     s->ioaddr = port;
        !          1323:     s->psock = sock;
        !          1324:     
        !          1325:     /* Wake up a sleepy Cirrus controller */
        !          1326:     if (wakeup) {
        !          1327:        i365_bclr(s, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
        !          1328:        /* Pause at least 50 ms */
        !          1329:        mdelay(50);
        !          1330:     }
        !          1331:     
        !          1332:     if ((val = i365_get(s, I365_IDENT)) & 0x70)
        !          1333:        return -1;
        !          1334:     switch (val) {
        !          1335:     case 0x82:
        !          1336:        type = IS_I82365A; break;
        !          1337:     case 0x83:
        !          1338:        type = IS_I82365B; break;
        !          1339:     case 0x84:
        !          1340:        type = IS_I82365DF; break;
        !          1341:     case 0x88: case 0x89: case 0x8a:
        !          1342:        type = IS_IBM; break;
        !          1343:     }
        !          1344:     
        !          1345:     /* Check for Vadem VG-468 chips */
        !          1346:     outb(0x0e, port);
        !          1347:     outb(0x37, port);
        !          1348:     i365_bset(s, VG468_MISC, VG468_MISC_VADEMREV);
        !          1349:     val = i365_get(s, I365_IDENT);
        !          1350:     if (val & I365_IDENT_VADEM) {
        !          1351:        i365_bclr(s, VG468_MISC, VG468_MISC_VADEMREV);
        !          1352:        type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;
        !          1353:     }
        !          1354: 
        !          1355:     /* Check for Ricoh chips */
        !          1356:     val = i365_get(s, RF5C_CHIP_ID);
        !          1357:     if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
        !          1358:        type = IS_RF5Cx96;
        !          1359:     
        !          1360:     /* Check for Cirrus CL-PD67xx chips */
        !          1361:     i365_set(s, PD67_CHIP_INFO, 0);
        !          1362:     val = i365_get(s, PD67_CHIP_INFO);
        !          1363:     if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
        !          1364:        val = i365_get(s, PD67_CHIP_INFO);
        !          1365:        if ((val & PD67_INFO_CHIP_ID) == 0) {
        !          1366:            type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
        !          1367:            i365_set(s, PD67_EXT_INDEX, 0xe5);
        !          1368:            if (i365_get(s, PD67_EXT_INDEX) != 0xe5)
        !          1369:                type = IS_VT83C469;
        !          1370:        }
        !          1371:     }
        !          1372:     return type;
        !          1373: } /* isa_identify */
        !          1374: 
        !          1375: #endif
        !          1376: 
        !          1377: /*======================================================================
        !          1378: 
        !          1379:     See if a card is present, powered up, in IO mode, and already
        !          1380:     bound to a (non PC Card) Linux driver.  We leave these alone.
        !          1381: 
        !          1382:     We make an exception for cards that seem to be serial devices.
        !          1383:     
        !          1384: ======================================================================*/
        !          1385: 
        !          1386: static int __init is_alive(socket_info_t *s)
        !          1387: {
        !          1388:     u_char stat;
        !          1389:     u_short start, stop;
        !          1390:     
        !          1391:     stat = i365_get(s, I365_STATUS);
        !          1392:     start = i365_get_pair(s, I365_IO(0)+I365_W_START);
        !          1393:     stop = i365_get_pair(s, I365_IO(0)+I365_W_STOP);
        !          1394:     if ((stop - start < 0x40) && (stop - start >= 0x07) &&
        !          1395:        ((start & 0xfeef) != 0x02e8) && (start >= 0x100) &&
        !          1396:        (stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) &&
        !          1397:        (i365_get(s, I365_INTCTL) & I365_PC_IOCARD) &&
        !          1398:        (i365_get(s, I365_ADDRWIN) & I365_ENA_IO(0)) &&
        !          1399:        (check_region(start, stop-start+1) != 0))
        !          1400:        return 1;
        !          1401:     else
        !          1402:        return 0;
        !          1403: }
        !          1404: 
        !          1405: /*====================================================================*/
        !          1406: 
        !          1407: static void __init add_socket(u_int port, int psock, int type)
        !          1408: {
        !          1409:     socket_info_t *s = socket+sockets;
        !          1410:     s->ioaddr = port;
        !          1411:     s->psock = psock;
        !          1412:     s->type = type;
        !          1413:     s->flags = pcic[type].flags;
        !          1414:     if (is_alive(s))
        !          1415:        s->flags |= IS_ALIVE;
        !          1416:     sockets++;
        !          1417: }
        !          1418: 
        !          1419: static void __init add_pcic(int ns, int type)
        !          1420: {
        !          1421:     u_int mask = 0, i;
        !          1422:     int use_pci = 0, isa_irq = 0;
        !          1423:     socket_info_t *s = &socket[sockets-ns];
        !          1424: 
        !          1425:     if (s->ioaddr > 0) request_region(s->ioaddr, 2, "i82365");
        !          1426:     
        !          1427:     printk(KERN_INFO "  %s", pcic[type].name);
        !          1428: #ifdef CONFIG_PCI
        !          1429:     if (s->flags & IS_UNKNOWN)
        !          1430:        printk(" [%04x %04x]", s->vendor, s->device);
        !          1431:     printk(" rev %02x", s->revision);
        !          1432:     if (s->flags & IS_CARDBUS)
        !          1433:        printk(" PCI-to-CardBus at slot %02x:%02x, mem %#08x\n",
        !          1434:               s->bus, PCI_SLOT(s->devfn), s->cb_phys);
        !          1435:     else if (s->flags & IS_PCI)
        !          1436:        printk(" PCI-to-PCMCIA at slot %02x:%02x, port %#x\n",
        !          1437:               s->bus, PCI_SLOT(s->devfn), s->ioaddr);
        !          1438:     else
        !          1439: #endif
        !          1440:        printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x\n",
        !          1441:               s->ioaddr, s->psock*0x40);
        !          1442: 
        !          1443: #ifdef CONFIG_ISA
        !          1444:     if (irq_list[0] == -1)
        !          1445:        mask = irq_mask;
        !          1446:     else
        !          1447:        for (i = mask = 0; i < 16; i++)
        !          1448:            mask |= (1<<irq_list[i]);
        !          1449: #endif
        !          1450:     /* Set host options, build basic interrupt mask */
        !          1451:     mask &= I365_ISA_IRQ_MASK & set_bridge_opts(s, ns);
        !          1452: 
        !          1453: #ifdef CONFIG_PCI
        !          1454:     /* Can we use PCI interrupts for card status changes? */
        !          1455:     if (pci_csc || pci_int) {
        !          1456:        for (i = 0; i < ns; i++)
        !          1457:            if (!s[i].cap.pci_irq || !pci_scan(&s[i])) break;
        !          1458:        use_pci = (i == ns);
        !          1459:     }
        !          1460: #endif
        !          1461: #ifdef CONFIG_ISA
        !          1462:     /* Scan, report ISA card interrupts */
        !          1463:     if (mask)
        !          1464:        mask = isa_scan(s, mask);
        !          1465: #endif
        !          1466: 
        !          1467: #ifdef CONFIG_PCI
        !          1468:     if (!mask)
        !          1469:        printk(KERN_INFO "    %s card interrupts,",
        !          1470:               (use_pci && pci_int) ? "PCI" : "*NO*");
        !          1471:     if (use_pci && pci_csc)
        !          1472:        printk(" PCI status changes\n");
        !          1473: #endif
        !          1474: 
        !          1475: #ifdef CONFIG_ISA
        !          1476:     /* Poll if only two sensible interrupts available */
        !          1477:     if (!(use_pci && pci_csc) && !poll_interval) {
        !          1478:        u_int tmp = (mask & 0xff20);
        !          1479:        tmp = tmp & (tmp-1);
        !          1480:        if ((tmp & (tmp-1)) == 0)
        !          1481:            poll_interval = HZ;
        !          1482:     }
        !          1483:     /* Only try an ISA cs_irq if this is the first controller */
        !          1484:     if (!(use_pci && pci_csc) && !grab_irq &&
        !          1485:        (cs_irq || !poll_interval)) {
        !          1486:        /* Avoid irq 12 unless it is explicitly requested */
        !          1487:        u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
        !          1488:        for (isa_irq = 15; isa_irq > 0; isa_irq--)
        !          1489:            if (cs_mask & (1 << isa_irq)) break;
        !          1490:        if (isa_irq) {
        !          1491:            grab_irq = 1;
        !          1492:            cs_irq = isa_irq;
        !          1493:            printk(" status change on irq %d\n", isa_irq);
        !          1494:        }
        !          1495:     }
        !          1496: #endif
        !          1497:     
        !          1498:     if (!(use_pci && pci_csc) && !isa_irq) {
        !          1499:        if (poll_interval == 0)
        !          1500:            poll_interval = HZ;
        !          1501:        printk(" polling interval = %d ms\n", poll_interval*1000/HZ);
        !          1502:     }
        !          1503:     
        !          1504:     /* Update socket interrupt information, capabilities */
        !          1505:     for (i = 0; i < ns; i++) {
        !          1506:        s[i].cap.features |= SS_CAP_PCCARD;
        !          1507:        s[i].cap.map_size = 0x1000;
        !          1508:        s[i].cap.irq_mask = mask;
        !          1509:        if (!use_pci)
        !          1510:            s[i].cap.pci_irq = 0;
        !          1511:        s[i].cs_irq = isa_irq;
        !          1512: #ifdef CONFIG_PCI
        !          1513:        if (s[i].flags & IS_CARDBUS) {
        !          1514:            s[i].cap.features |= SS_CAP_CARDBUS;
        !          1515:            cb_set_irq_mode(s+i, pci_csc && s[i].cap.pci_irq, 0);
        !          1516:        }
        !          1517: #endif
        !          1518:     }
        !          1519: 
        !          1520: } /* add_pcic */
        !          1521: 
        !          1522: /*====================================================================*/
        !          1523: 
        !          1524: #ifdef CONFIG_PCI
        !          1525: 
        !          1526: static int __init pci_lookup(u_int class, struct pci_dev **id,
        !          1527:                             u_char *bus, u_char *devfn)
        !          1528: {
        !          1529:     if ((*id = pci_find_class(class<<8, *id)) != NULL) {
        !          1530:        *bus = (*id)->bus->number;
        !          1531:        *devfn = (*id)->devfn;
        !          1532:        return 0;
        !          1533:     } else return -1;
        !          1534: }
        !          1535: 
        !          1536: static void __init add_pci_bridge(int type, u_short v, u_short d)
        !          1537: {
        !          1538:     socket_info_t *s = &socket[sockets];
        !          1539:     u_int addr, ns;
        !          1540: 
        !          1541:     pci_enable_device(pci_find_slot(s->bus, s->devfn));
        !          1542:     pci_writew(s, PCI_COMMAND, CMD_DFLT);
        !          1543: 
        !          1544:     if (type == PCIC_COUNT) type = IS_UNK_PCI;
        !          1545:     pci_readl(s, PCI_BASE_ADDRESS_0, &addr);
        !          1546:     addr &= ~0x1;
        !          1547:     for (ns = 0; ns < ((type == IS_I82092AA) ? 4 : 2); ns++) {
        !          1548:        s[ns].bus = s->bus; s[ns].devfn = s->devfn;
        !          1549:        s[ns].vendor = v; s[ns].device = d;
        !          1550:        add_socket(addr, ns, type);
        !          1551:     }
        !          1552:     add_pcic(ns, type);
        !          1553: }
        !          1554: 
        !          1555: static int check_cb_mapping(socket_info_t *s)
        !          1556: {
        !          1557:     u_int state = cb_readl(s, CB_SOCKET_STATE) >> 16;
        !          1558:     /* A few sanity checks to validate the bridge mapping */
        !          1559:     if ((cb_readb(s, 0x800+I365_IDENT) & 0x70) ||
        !          1560:        (cb_readb(s, 0x800+I365_CSC) && cb_readb(s, 0x800+I365_CSC) &&
        !          1561:         cb_readb(s, 0x800+I365_CSC)) || cb_readl(s, CB_SOCKET_FORCE) ||
        !          1562:        ((state & ~0x3000) || !(state & 0x3000)))
        !          1563:        return 1;
        !          1564:     return 0;
        !          1565: }
        !          1566: 
        !          1567: static void __init add_cb_bridge(int type, u_short v, u_short d0)
        !          1568: {
        !          1569:     socket_info_t *s = &socket[sockets];
        !          1570:     u_char bus = s->bus, devfn = s->devfn;
        !          1571:     u_short d, ns;
        !          1572:     u_char a, r, max;
        !          1573:     
        !          1574:     /* PCI bus enumeration is broken on some systems */
        !          1575:     for (ns = 0; ns < sockets; ns++)
        !          1576:        if ((socket[ns].bus == bus) &&
        !          1577:            (socket[ns].devfn == devfn))
        !          1578:            return;
        !          1579:     
        !          1580:     if (type == PCIC_COUNT) type = IS_UNK_CARDBUS;
        !          1581:     pci_readb(s, PCI_HEADER_TYPE, &a);
        !          1582:     pci_readb(s, PCI_CLASS_REVISION, &r);
        !          1583:     max = (a & 0x80) ? 8 : 1;
        !          1584:     for (ns = 0; ns < max; ns++, s++, devfn++) {
        !          1585:        s->bus = bus; s->devfn = devfn;
        !          1586:        if (pci_readw(s, PCI_DEVICE_ID, &d) || (d != d0))
        !          1587:            break;
        !          1588:        s->vendor = v; s->device = d; s->revision = r;
        !          1589: 
        !          1590:        pci_enable_device(pci_find_slot(bus, devfn));
        !          1591:        pci_set_power_state(pci_find_slot(bus, devfn), 0);
        !          1592:        pci_writew(s, PCI_COMMAND, CMD_DFLT);
        !          1593: 
        !          1594:        /* Set up CardBus register mapping */
        !          1595:        pci_writel(s, CB_LEGACY_MODE_BASE, 0);
        !          1596:        pci_readl(s, PCI_BASE_ADDRESS_0, &s->cb_phys);
        !          1597:        if (s->cb_phys == 0) {
        !          1598:            printk("\n" KERN_NOTICE "  Bridge register mapping failed:"
        !          1599:                   " check cb_mem_base setting\n");
        !          1600:            break;
        !          1601:        }
        !          1602:        s->cb_virt = ioremap(s->cb_phys, 0x1000);
        !          1603:        if (check_cb_mapping(s) != 0) {
        !          1604:            printk("\n" KERN_NOTICE "  Bad bridge mapping at "
        !          1605:                   "0x%08x!\n", s->cb_phys);
        !          1606:            break;
        !          1607:        }
        !          1608: 
        !          1609:        request_mem_region(s->cb_phys, 0x1000, "i82365");
        !          1610:        add_socket(0, 0, type);
        !          1611:     }
        !          1612:     if (ns == 0) return;
        !          1613:     
        !          1614:     add_pcic(ns, type);
        !          1615: 
        !          1616:     /* Look up PCI bus bridge structures if needed */
        !          1617:     s -= ns;
        !          1618:     for (a = 0; a < ns; a++) {
        !          1619:        struct pci_dev *self = pci_find_slot(bus, s[a].devfn);
        !          1620: #if (LINUX_VERSION_CODE >= VERSION(2,3,40))
        !          1621:        s[a].cap.cb_bus = self->subordinate;
        !          1622: #else
        !          1623:        struct pci_bus *child;
        !          1624:        for (child = self->bus->children; child; child = child->next)
        !          1625:            if (child->number == s[a].cap.cardbus) break;
        !          1626:        s[a].cap.cb_bus = child;
        !          1627: #endif
        !          1628:     }
        !          1629: }
        !          1630: 
        !          1631: static void __init pci_probe(u_int class)
        !          1632: {
        !          1633:     socket_info_t *s = &socket[sockets];
        !          1634:     u_short i, v, d;
        !          1635:     struct pci_dev *id;
        !          1636:     
        !          1637:     id = 0;
        !          1638:     while (pci_lookup(class, &id, &s->bus, &s->devfn) == 0) {
        !          1639:        if (PCI_FUNC(s->devfn) != 0) continue;
        !          1640:        pci_readw(s, PCI_VENDOR_ID, &v);
        !          1641:        pci_readw(s, PCI_DEVICE_ID, &d);
        !          1642:        for (i = 0; i < PCIC_COUNT; i++)
        !          1643:            if ((pcic[i].vendor == v) && (pcic[i].device == d)) break;
        !          1644:        /* The "ToPIC95-A" is unusable as a CardBus bridge */
        !          1645:        if (i == IS_TOPIC95_A)
        !          1646:            continue;
        !          1647:        if (((i < PCIC_COUNT) && (pcic[i].flags & IS_CARDBUS)) ||
        !          1648:            (class == PCI_CLASS_BRIDGE_CARDBUS))
        !          1649:            add_cb_bridge(i, v, d);
        !          1650:        else
        !          1651:            add_pci_bridge(i, v, d);
        !          1652:        s = &socket[sockets];
        !          1653:     }
        !          1654: }
        !          1655: 
        !          1656: #endif
        !          1657: 
        !          1658: /*====================================================================*/
        !          1659: 
        !          1660: #ifdef CONFIG_ISA
        !          1661: 
        !          1662: static void __init isa_probe(ioaddr_t base)
        !          1663: {
        !          1664:     int i, j, sock, k, ns, id;
        !          1665:     ioaddr_t port;
        !          1666: 
        !          1667:     if (check_region(base, 2) != 0) {
        !          1668:        if (sockets == 0)
        !          1669:            printk("port conflict at %#x\n", base);
        !          1670:        return;
        !          1671:     }
        !          1672: 
        !          1673:     id = isa_identify(base, 0);
        !          1674:     if ((id == IS_I82365DF) && (isa_identify(base, 1) != id)) {
        !          1675:        for (i = 0; i < 4; i++) {
        !          1676:            if (i == ignore) continue;
        !          1677:            port = base + ((i & 1) << 2) + ((i & 2) << 1);
        !          1678:            sock = (i & 1) << 1;
        !          1679:            if (isa_identify(port, sock) == IS_I82365DF) {
        !          1680:                add_socket(port, sock, IS_VLSI);
        !          1681:                add_pcic(1, IS_VLSI);
        !          1682:            }
        !          1683:        }
        !          1684:     } else {
        !          1685:        for (i = 0; i < 4; i += 2) {
        !          1686:            port = base + 2*(i>>2);
        !          1687:            sock = (i & 3);
        !          1688:            id = isa_identify(port, sock);
        !          1689:            if (id < 0) continue;
        !          1690: 
        !          1691:            for (j = ns = 0; j < 2; j++) {
        !          1692:                /* Does the socket exist? */
        !          1693:                if ((ignore == i+j) || (isa_identify(port, sock+j) < 0))
        !          1694:                    continue;
        !          1695:                /* Check for bad socket decode */
        !          1696:                for (k = 0; k <= sockets; k++)
        !          1697:                    i365_set(socket+k, I365_MEM(0)+I365_W_OFF, k);
        !          1698:                for (k = 0; k <= sockets; k++)
        !          1699:                    if (i365_get(socket+k, I365_MEM(0)+I365_W_OFF) != k)
        !          1700:                        break;
        !          1701:                if (k <= sockets) break;
        !          1702:                add_socket(port, sock+j, id); ns++;
        !          1703:            }
        !          1704:            if (ns != 0) add_pcic(ns, id);
        !          1705:        }
        !          1706:     }
        !          1707: }
        !          1708: 
        !          1709: #endif
        !          1710: 
        !          1711: /*======================================================================
        !          1712: 
        !          1713:     The card status event handler.  This may either be interrupt
        !          1714:     driven or polled.  It monitors mainly for card insert and eject
        !          1715:     events; there are various other kinds of events that can be
        !          1716:     monitored (ready/busy, status change, etc), but they are almost
        !          1717:     never used.
        !          1718:     
        !          1719: ======================================================================*/
        !          1720: 
        !          1721: static void pcic_interrupt(int irq, void *dev, struct pt_regs *regs)
        !          1722: {
        !          1723:     int i, j, csc;
        !          1724:     u_int events, active;
        !          1725: #ifdef CONFIG_ISA
        !          1726:     u_long flags = 0;
        !          1727: #endif
        !          1728:     
        !          1729:     DEBUG(2, "i82365: pcic_interrupt(%d)\n", irq);
        !          1730: 
        !          1731:     for (j = 0; j < 20; j++) {
        !          1732:        active = 0;
        !          1733:        for (i = 0; i < sockets; i++) {
        !          1734:            socket_info_t *s = &socket[i];
        !          1735:            if ((s->cs_irq != irq) && (s->cap.pci_irq != irq))
        !          1736:                continue;
        !          1737:            ISA_LOCK(s, flags);
        !          1738:            csc = i365_get(s, I365_CSC);
        !          1739: #ifdef CONFIG_PCI
        !          1740:            if ((s->flags & IS_CARDBUS) &&
        !          1741:                (cb_readl(s, CB_SOCKET_EVENT) & CB_SE_CCD)) {
        !          1742:                cb_writel(s, CB_SOCKET_EVENT, CB_SE_CCD);
        !          1743:                csc |= I365_CSC_DETECT;
        !          1744:            }
        !          1745: #endif
        !          1746:            if ((csc == 0) || (!s->handler) ||
        !          1747:                (i365_get(s, I365_IDENT) & 0x70)) {
        !          1748:                ISA_UNLOCK(s, flags);
        !          1749:                continue;
        !          1750:            }
        !          1751:            events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
        !          1752:            if (i365_get(s, I365_INTCTL) & I365_PC_IOCARD) {
        !          1753:                events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
        !          1754:            } else {
        !          1755:                events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
        !          1756:                events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
        !          1757:                events |= (csc & I365_CSC_READY) ? SS_READY : 0;
        !          1758:            }
        !          1759:            ISA_UNLOCK(s, flags);
        !          1760:            DEBUG(1, "i82365: socket %d event 0x%04x\n", i, events);
        !          1761:            if (events)
        !          1762:                s->handler(s->info, events);
        !          1763:            active |= events;
        !          1764:        }
        !          1765:        if (!active) break;
        !          1766:     }
        !          1767:     if (j == 20)
        !          1768:        printk(KERN_NOTICE "i82365: infinite loop in interrupt "
        !          1769:               "handler: active = 0x%04x\n", active);
        !          1770: 
        !          1771:     DEBUG(2, "i82365: interrupt done\n");
        !          1772: } /* pcic_interrupt */
        !          1773: 
        !          1774: static void pcic_interrupt_wrapper(u_long data)
        !          1775: {
        !          1776:     pcic_interrupt(0, NULL, NULL);
        !          1777:     poll_timer.expires = jiffies + poll_interval;
        !          1778:     add_timer(&poll_timer);
        !          1779: }
        !          1780: 
        !          1781: /*====================================================================*/
        !          1782: 
        !          1783: static int pcic_register_callback(socket_info_t *s, ss_callback_t *call)
        !          1784: {
        !          1785:     if (call == NULL) {
        !          1786:        s->handler = NULL;
        !          1787:        MOD_DEC_USE_COUNT;
        !          1788:     } else {
        !          1789:        MOD_INC_USE_COUNT;
        !          1790:        s->handler = call->handler;
        !          1791:        s->info = call->info;
        !          1792:     }
        !          1793:     return 0;
        !          1794: } /* pcic_register_callback */
        !          1795: 
        !          1796: /*====================================================================*/
        !          1797: 
        !          1798: static int pcic_inquire_socket(socket_info_t *s, socket_cap_t *cap)
        !          1799: {
        !          1800:     *cap = s->cap;
        !          1801:     return 0;
        !          1802: }
        !          1803: 
        !          1804: /*====================================================================*/
        !          1805: 
        !          1806: static int i365_get_status(socket_info_t *s, u_int *value)
        !          1807: {
        !          1808:     u_int status;
        !          1809:     
        !          1810:     status = i365_get(s, I365_STATUS);
        !          1811:     *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
        !          1812:        ? SS_DETECT : 0;
        !          1813:     if (i365_get(s, I365_INTCTL) & I365_PC_IOCARD) {
        !          1814:        *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
        !          1815:     } else {
        !          1816:        *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
        !          1817:        *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
        !          1818:     }
        !          1819:     *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
        !          1820:     *value |= (status & I365_CS_READY) ? SS_READY : 0;
        !          1821:     *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
        !          1822: 
        !          1823: #ifdef CONFIG_PCI
        !          1824:     if (s->flags & IS_CARDBUS) {
        !          1825:        status = cb_readl(s, CB_SOCKET_STATE);
        !          1826:        *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0;
        !          1827:        *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0;
        !          1828:        *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0;
        !          1829:        *value |= (status & CB_SS_VSENSE) ? 0 : SS_PENDING;
        !          1830:     } else if (s->flags & IS_O2MICRO) {
        !          1831:        status = i365_get(s, O2_MODE_B);
        !          1832:        *value |= (status & O2_MODE_B_VS1) ? 0 : SS_3VCARD;
        !          1833:        *value |= (status & O2_MODE_B_VS2) ? 0 : SS_XVCARD;
        !          1834:     }
        !          1835: #endif
        !          1836:     if ((s->flags & IS_CIRRUS) &&
        !          1837:        ((s->flags & IS_PCI) || has_vsense)) {
        !          1838:        socket_info_t *t = (s->psock) ? s : s+1;
        !          1839:        status = pd67_ext_get(t, PD67_EXTERN_DATA);
        !          1840:        *value |= (status & PD67_EXD_VS1(s->psock)) ? 0 : SS_3VCARD;
        !          1841:        *value |= (status & PD67_EXD_VS2(s->psock)) ? 0 : SS_XVCARD;
        !          1842:     }
        !          1843: #ifdef CONFIG_ISA
        !          1844:     if (s->type == IS_VG469) {
        !          1845:        status = i365_get(s, VG469_VSENSE);
        !          1846:        if (s->psock & 1) {
        !          1847:            *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;
        !          1848:            *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;
        !          1849:        } else {
        !          1850:            *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;
        !          1851:            *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
        !          1852:        }
        !          1853:     }
        !          1854: #endif
        !          1855:     /* For now, ignore cards with unsupported voltage keys */
        !          1856:     if (*value & SS_XVCARD)
        !          1857:        *value &= ~(SS_DETECT|SS_3VCARD|SS_XVCARD);
        !          1858:     DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", s-socket, *value);
        !          1859:     return 0;
        !          1860: } /* i365_get_status */
        !          1861: 
        !          1862: /*====================================================================*/
        !          1863: 
        !          1864: static int i365_get_socket(socket_info_t *s, socket_state_t *state)
        !          1865: {
        !          1866:     u_char reg, vcc, vpp;
        !          1867:     
        !          1868:     reg = i365_get(s, I365_POWER);
        !          1869:     state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
        !          1870:     state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
        !          1871:     vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
        !          1872:     state->Vcc = state->Vpp = 0;
        !          1873: #ifdef CONFIG_PCI
        !          1874:     if ((s->flags & IS_CARDBUS) && !(s->flags & IS_TOPIC)) {
        !          1875:        cb_get_power(s, state);
        !          1876:     } else
        !          1877: #endif
        !          1878:     {
        !          1879:        if ((s->flags & IS_CIRRUS) && (reg & I365_VCC_5V)) {
        !          1880:            state->Vcc = (i365_get(s, PD67_MISC_CTL_1) &
        !          1881:                          PD67_MC1_VCC_3V) ? 33 : 50;
        !          1882:        } else if ((s->flags & IS_VG_PWR) && (reg & I365_VCC_5V)) {
        !          1883:            state->Vcc = (i365_get(s, VG469_VSELECT) &
        !          1884:                          VG469_VSEL_VCC) ? 33 : 50;
        !          1885:        } else if ((s->flags & IS_DF_PWR) || (s->flags & IS_TOPIC)) {
        !          1886:            if (vcc == I365_VCC_3V) state->Vcc = 33;
        !          1887:            if (vcc == I365_VCC_5V) state->Vcc = 50;
        !          1888:        } else {
        !          1889:            if (reg & I365_VCC_5V) state->Vcc = 50;
        !          1890:        }
        !          1891:        if (vpp == I365_VPP1_5V)
        !          1892:            state->Vpp = (s->flags & IS_DF_PWR) ? 50 : state->Vcc;
        !          1893:        if (vpp == I365_VPP1_12V) state->Vpp = 120;
        !          1894:     }
        !          1895: 
        !          1896:     /* IO card, RESET flags, IO interrupt */
        !          1897:     reg = i365_get(s, I365_INTCTL);
        !          1898:     state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
        !          1899:     state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
        !          1900: #ifdef CONFIG_PCI
        !          1901:     if (cb_get_irq_mode(s) != 0)
        !          1902:        state->io_irq = s->cap.pci_irq;
        !          1903:     else
        !          1904: #endif
        !          1905:        state->io_irq = reg & I365_IRQ_MASK;
        !          1906:     
        !          1907:     /* Card status change mask */
        !          1908:     reg = i365_get(s, I365_CSCINT);
        !          1909:     state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
        !          1910:     if (state->flags & SS_IOCARD) {
        !          1911:        state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
        !          1912:     } else {
        !          1913:        state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
        !          1914:        state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
        !          1915:        state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
        !          1916:     }
        !          1917:     
        !          1918:     DEBUG(2, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
        !          1919:          "io_irq %d, csc_mask %#2.2x\n", s-socket, state->flags,
        !          1920:          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
        !          1921:     return 0;
        !          1922: } /* i365_get_socket */
        !          1923: 
        !          1924: /*====================================================================*/
        !          1925: 
        !          1926: static int i365_set_socket(socket_info_t *s, socket_state_t *state)
        !          1927: {
        !          1928:     u_char reg;
        !          1929:     
        !          1930:     DEBUG(2, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
        !          1931:          "io_irq %d, csc_mask %#2.2x)\n", s-socket, state->flags,
        !          1932:          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
        !          1933:     
        !          1934:     /* First set global controller options */
        !          1935: #ifdef CONFIG_PCI
        !          1936:     if (s->cap.pci_irq)
        !          1937:        cb_set_irq_mode(s, pci_csc, (s->cap.pci_irq == state->io_irq));
        !          1938:     s->bcr &= ~CB_BCR_CB_RESET;
        !          1939: #endif
        !          1940:     set_bridge_state(s);
        !          1941:     
        !          1942:     /* IO card, RESET flag, IO interrupt */
        !          1943:     reg = s->intr | ((state->io_irq == s->cap.pci_irq) ?
        !          1944:                     s->pci_irq_code : state->io_irq);
        !          1945:     reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
        !          1946:     reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
        !          1947:     i365_set(s, I365_INTCTL, reg);
        !          1948:     
        !          1949:     reg = I365_PWR_NORESET;
        !          1950:     if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
        !          1951:     if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
        !          1952: 
        !          1953: #ifdef CONFIG_PCI
        !          1954:     if ((s->flags & IS_CARDBUS) && !(s->flags & IS_TOPIC)) {
        !          1955:        cb_set_power(s, state);
        !          1956:        reg |= i365_get(s, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK);
        !          1957:     } else
        !          1958: #endif
        !          1959:     {
        !          1960:        int new = s->flags & (IS_TOPIC|IS_CIRRUS|IS_VG_PWR|IS_DF_PWR);
        !          1961:        int vcc3 = (state->Vcc == 33), df = (s->flags & IS_DF_PWR);
        !          1962: 
        !          1963:        if (state->Vcc == 50) {
        !          1964:            reg |= I365_VCC_5V;
        !          1965:        } else if (new && vcc3) {
        !          1966:            reg |= ((s->flags & (IS_TOPIC|IS_DF_PWR)) ?
        !          1967:                    I365_VCC_3V : I365_VCC_5V);
        !          1968:        } else if (state->Vcc)
        !          1969:            return -EINVAL;
        !          1970:        if (s->flags & IS_CIRRUS)
        !          1971:            i365_bflip(s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V, vcc3);
        !          1972:        if (s->flags & IS_VG_PWR)
        !          1973:            i365_bflip(s, VG469_VSELECT, VG469_VSEL_VCC, vcc3);
        !          1974: 
        !          1975:        if (state->Vpp == 120) {
        !          1976:            reg |= I365_VPP1_12V | (new ? 0 : I365_VPP2_12V);
        !          1977:        } else if (state->Vpp == (df ? 50 : state->Vcc)) {
        !          1978:            reg |= I365_VPP1_5V | (new ? 0 : I365_VPP2_5V);
        !          1979:        } else if (state->Vpp)
        !          1980:            return -EINVAL;
        !          1981:     }
        !          1982:     
        !          1983:     if (reg != i365_get(s, I365_POWER))
        !          1984:        i365_set(s, I365_POWER, reg);
        !          1985: 
        !          1986:     /* Card status change interrupt mask */
        !          1987:     reg = (s->cap.pci_irq ? s->pci_irq_code : s->cs_irq) << 4;
        !          1988:     if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
        !          1989:     if (state->flags & SS_IOCARD) {
        !          1990:        if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
        !          1991:     } else {
        !          1992:        if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
        !          1993:        if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
        !          1994:        if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
        !          1995:     }
        !          1996:     i365_set(s, I365_CSCINT, reg);
        !          1997:     i365_get(s, I365_CSC);
        !          1998: #ifdef CONFIG_PCI
        !          1999:     if (s->flags & IS_CARDBUS) {
        !          2000:        if (s->cs_irq || (pci_csc && s->cap.pci_irq))
        !          2001:            cb_writel(s, CB_SOCKET_MASK, CB_SM_CCD);
        !          2002:        cb_writel(s, CB_SOCKET_EVENT, -1);
        !          2003:     }
        !          2004: #endif
        !          2005: 
        !          2006:     return 0;
        !          2007: } /* i365_set_socket */
        !          2008: 
        !          2009: /*====================================================================*/
        !          2010: 
        !          2011: static int i365_get_io_map(socket_info_t *s, struct pccard_io_map *io)
        !          2012: {
        !          2013:     u_char map, ioctl, addr;
        !          2014:     
        !          2015:     map = io->map;
        !          2016:     if (map > 1) return -EINVAL;
        !          2017:     io->start = i365_get_pair(s, I365_IO(map)+I365_W_START);
        !          2018:     io->stop = i365_get_pair(s, I365_IO(map)+I365_W_STOP);
        !          2019:     ioctl = i365_get(s, I365_IOCTL);
        !          2020:     addr = i365_get(s, I365_ADDRWIN);
        !          2021:     io->speed = (ioctl & I365_IOCTL_WAIT(map)) ? cycle_time : 0;
        !          2022:     io->flags  = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
        !          2023:     io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
        !          2024:     io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
        !          2025:     io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
        !          2026:     DEBUG(3, "i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, %#4.4x-%#4.4x\n",
        !          2027:          s-socket, map, io->flags, io->speed, io->start, io->stop);
        !          2028:     return 0;
        !          2029: } /* i365_get_io_map */
        !          2030: 
        !          2031: /*====================================================================*/
        !          2032: 
        !          2033: static int i365_set_io_map(socket_info_t *s, struct pccard_io_map *io)
        !          2034: {
        !          2035:     u_char map, ioctl;
        !          2036:     
        !          2037:     DEBUG(3, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, %#4.4x-%#4.4x)\n",
        !          2038:          s-socket, io->map, io->flags, io->speed, io->start, io->stop);
        !          2039:     map = io->map;
        !          2040:     if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
        !          2041:        (io->stop < io->start)) return -EINVAL;
        !          2042:     /* Turn off the window before changing anything */
        !          2043:     if (i365_get(s, I365_ADDRWIN) & I365_ENA_IO(map))
        !          2044:        i365_bclr(s, I365_ADDRWIN, I365_ENA_IO(map));
        !          2045:     i365_set_pair(s, I365_IO(map)+I365_W_START, io->start);
        !          2046:     i365_set_pair(s, I365_IO(map)+I365_W_STOP, io->stop);
        !          2047:     ioctl = i365_get(s, I365_IOCTL) & ~I365_IOCTL_MASK(map);
        !          2048:     if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
        !          2049:     if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
        !          2050:     if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
        !          2051:     if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
        !          2052:     i365_set(s, I365_IOCTL, ioctl);
        !          2053:     /* Turn on the window if necessary */
        !          2054:     if (io->flags & MAP_ACTIVE)
        !          2055:        i365_bset(s, I365_ADDRWIN, I365_ENA_IO(map));
        !          2056:     return 0;
        !          2057: } /* i365_set_io_map */
        !          2058: 
        !          2059: /*====================================================================*/
        !          2060: 
        !          2061: static int i365_get_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
        !          2062: {
        !          2063:     u_short base, i;
        !          2064:     u_char map, addr;
        !          2065:     
        !          2066:     map = mem->map;
        !          2067:     if (map > 4) return -EINVAL;
        !          2068:     addr = i365_get(s, I365_ADDRWIN);
        !          2069:     mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
        !          2070:     base = I365_MEM(map);
        !          2071:     
        !          2072:     i = i365_get_pair(s, base+I365_W_START);
        !          2073:     mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0;
        !          2074:     mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0;
        !          2075:     mem->sys_start = ((u_long)(i & 0x0fff) << 12);
        !          2076:     
        !          2077:     i = i365_get_pair(s, base+I365_W_STOP);
        !          2078:     mem->speed  = (i & I365_MEM_WS0) ? 1 : 0;
        !          2079:     mem->speed += (i & I365_MEM_WS1) ? 2 : 0;
        !          2080:     mem->speed *= cycle_time;
        !          2081:     mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff;
        !          2082:     
        !          2083:     i = i365_get_pair(s, base+I365_W_OFF);
        !          2084:     mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
        !          2085:     mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0;
        !          2086:     mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
        !          2087:     mem->card_start &= 0x3ffffff;
        !          2088: 
        !          2089: #ifdef CONFIG_PCI
        !          2090:     /* Take care of high byte, for PCI controllers */
        !          2091:     if (s->type == IS_PD6729) {
        !          2092:        addr = pd67_ext_get(s, PD67_MEM_PAGE(map)) << 24;
        !          2093:        mem->sys_stop += addr; mem->sys_start += addr;
        !          2094:     } else if (s->flags & IS_CARDBUS) {
        !          2095:        addr = i365_get(s, CB_MEM_PAGE(map)) << 24;
        !          2096:        mem->sys_stop += addr; mem->sys_start += addr;
        !          2097:     }
        !          2098: #endif
        !          2099:     
        !          2100:     DEBUG(3, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
        !          2101:          "5lx, %#5.5x\n", s-socket, mem->map, mem->flags, mem->speed,
        !          2102:          mem->sys_start, mem->sys_stop, mem->card_start);
        !          2103:     return 0;
        !          2104: } /* i365_get_mem_map */
        !          2105: 
        !          2106: /*====================================================================*/
        !          2107:   
        !          2108: static int i365_set_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
        !          2109: {
        !          2110:     u_short base, i;
        !          2111:     u_char map;
        !          2112:     
        !          2113:     DEBUG(3, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
        !          2114:          "lx, %#5.5x)\n", s-socket, mem->map, mem->flags, mem->speed,
        !          2115:          mem->sys_start, mem->sys_stop, mem->card_start);
        !          2116: 
        !          2117:     map = mem->map;
        !          2118:     if ((map > 4) || (mem->card_start > 0x3ffffff) ||
        !          2119:        (mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
        !          2120:        return -EINVAL;
        !          2121:     if (!(s->flags & (IS_PCI|IS_CARDBUS)) &&
        !          2122:        ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff)))
        !          2123:        return -EINVAL;
        !          2124:        
        !          2125:     /* Turn off the window before changing anything */
        !          2126:     if (i365_get(s, I365_ADDRWIN) & I365_ENA_MEM(map))
        !          2127:        i365_bclr(s, I365_ADDRWIN, I365_ENA_MEM(map));
        !          2128: 
        !          2129: #ifdef CONFIG_PCI
        !          2130:     /* Take care of high byte, for PCI controllers */
        !          2131:     if (s->type == IS_PD6729) {
        !          2132:        pd67_ext_set(s, PD67_MEM_PAGE(map), (mem->sys_start >> 24));
        !          2133:     } else if (s->flags & IS_CARDBUS)
        !          2134:        i365_set(s, CB_MEM_PAGE(map), mem->sys_start >> 24);
        !          2135: #endif
        !          2136:     
        !          2137:     base = I365_MEM(map);
        !          2138:     i = (mem->sys_start >> 12) & 0x0fff;
        !          2139:     if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
        !          2140:     if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
        !          2141:     i365_set_pair(s, base+I365_W_START, i);
        !          2142:     
        !          2143:     i = (mem->sys_stop >> 12) & 0x0fff;
        !          2144:     switch (mem->speed / cycle_time) {
        !          2145:     case 0:    break;
        !          2146:     case 1:    i |= I365_MEM_WS0; break;
        !          2147:     case 2:    i |= I365_MEM_WS1; break;
        !          2148:     default:   i |= I365_MEM_WS1 | I365_MEM_WS0; break;
        !          2149:     }
        !          2150:     i365_set_pair(s, base+I365_W_STOP, i);
        !          2151:     
        !          2152:     i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
        !          2153:     if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
        !          2154:     if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
        !          2155:     i365_set_pair(s, base+I365_W_OFF, i);
        !          2156:     
        !          2157:     /* Turn on the window if necessary */
        !          2158:     if (mem->flags & MAP_ACTIVE)
        !          2159:        i365_bset(s, I365_ADDRWIN, I365_ENA_MEM(map));
        !          2160:     return 0;
        !          2161: } /* i365_set_mem_map */
        !          2162: 
        !          2163: /*======================================================================
        !          2164: 
        !          2165:     The few things that are strictly for Cardbus cards goes here.
        !          2166: 
        !          2167: ======================================================================*/
        !          2168: 
        !          2169: #ifdef CONFIG_CARDBUS
        !          2170: 
        !          2171: static int cb_get_status(socket_info_t *s, u_int *value)
        !          2172: {
        !          2173:     u_int state = cb_readl(s, CB_SOCKET_STATE);
        !          2174:     *value = (state & CB_SS_32BIT) ? SS_CARDBUS : 0;
        !          2175:     *value |= (state & CB_SS_CCD) ? 0 : SS_DETECT;
        !          2176:     *value |= (state & CB_SS_CSTSCHG) ? SS_STSCHG : 0;
        !          2177:     *value |= (state & CB_SS_PWRCYCLE) ? (SS_POWERON|SS_READY) : 0;
        !          2178:     *value |= (state & CB_SS_3VCARD) ? SS_3VCARD : 0;
        !          2179:     *value |= (state & CB_SS_XVCARD) ? SS_XVCARD : 0;
        !          2180:     *value |= (state & CB_SS_VSENSE) ? 0 : SS_PENDING;
        !          2181:     DEBUG(1, "yenta: GetStatus(%d) = %#4.4x\n", s-socket, *value);
        !          2182:     return 0;
        !          2183: } /* cb_get_status */
        !          2184: 
        !          2185: static int cb_get_socket(socket_info_t *s, socket_state_t *state)
        !          2186: {
        !          2187:     u_short bcr;
        !          2188: 
        !          2189:     cb_get_power(s, state);
        !          2190:     pci_readw(s, CB_BRIDGE_CONTROL, &bcr);
        !          2191:     state->flags |= (bcr & CB_BCR_CB_RESET) ? SS_RESET : 0;
        !          2192:     if (cb_get_irq_mode(s) != 0)
        !          2193:        state->io_irq = s->cap.pci_irq;
        !          2194:     else
        !          2195:        state->io_irq = i365_get(s, I365_INTCTL) & I365_IRQ_MASK;
        !          2196:     DEBUG(2, "yenta: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d"
        !          2197:          ", io_irq %d, csc_mask %#2.2x\n", s-socket, state->flags,
        !          2198:          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
        !          2199:     return 0;
        !          2200: } /* cb_get_socket */
        !          2201: 
        !          2202: static int cb_set_socket(socket_info_t *s, socket_state_t *state)
        !          2203: {
        !          2204:     u_int reg;
        !          2205:     
        !          2206:     DEBUG(2, "yenta: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
        !          2207:          "io_irq %d, csc_mask %#2.2x)\n", s-socket, state->flags,
        !          2208:          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
        !          2209:     
        !          2210:     /* First set global controller options */
        !          2211:     if (s->cap.pci_irq)
        !          2212:        cb_set_irq_mode(s, pci_csc, (s->cap.pci_irq == state->io_irq));
        !          2213:     s->bcr &= ~CB_BCR_CB_RESET;
        !          2214:     s->bcr |= (state->flags & SS_RESET) ? CB_BCR_CB_RESET : 0;
        !          2215:     set_bridge_state(s);
        !          2216:     
        !          2217:     cb_set_power(s, state);
        !          2218:     
        !          2219:     /* Handle IO interrupt using ISA routing */
        !          2220:     reg = s->intr;
        !          2221:     if (state->io_irq != s->cap.pci_irq) reg |= state->io_irq;
        !          2222:     i365_set(s, I365_INTCTL, reg);
        !          2223:     
        !          2224:     /* Handle CSC mask */
        !          2225:     if (!s->cs_irq && (!pci_csc || !s->cap.pci_irq))
        !          2226:        return 0;
        !          2227:     reg = (s->cs_irq << 4);
        !          2228:     if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
        !          2229:     i365_set(s, I365_CSCINT, reg);
        !          2230:     i365_get(s, I365_CSC);
        !          2231:     cb_writel(s, CB_SOCKET_MASK, CB_SM_CCD);
        !          2232:     cb_writel(s, CB_SOCKET_EVENT, -1);
        !          2233:     
        !          2234:     return 0;
        !          2235: } /* cb_set_socket */
        !          2236: 
        !          2237: static int cb_get_bridge(socket_info_t *s, struct cb_bridge_map *m)
        !          2238: {
        !          2239:     u_char map = m->map;
        !          2240: 
        !          2241:     if (map > 1) return -EINVAL;
        !          2242:     m->flags &= MAP_IOSPACE;
        !          2243:     map += (m->flags & MAP_IOSPACE) ? 2 : 0;
        !          2244:     pci_readl(s, CB_MEM_BASE(map), &m->start);
        !          2245:     pci_readl(s, CB_MEM_LIMIT(map), &m->stop);
        !          2246:     if (m->start || m->stop) {
        !          2247:        m->flags |= MAP_ACTIVE;
        !          2248:        m->stop |= (map > 1) ? 3 : 0x0fff;
        !          2249:     }
        !          2250:     if (map > 1) {
        !          2251:        u_short bcr;
        !          2252:        pci_readw(s, CB_BRIDGE_CONTROL, &bcr);
        !          2253:        m->flags |= (bcr & CB_BCR_PREFETCH(map)) ? MAP_PREFETCH : 0;
        !          2254:     }
        !          2255:     DEBUG(3, "yenta: GetBridge(%d, %d) = %#2.2x, %#4.4x-%#4.4x\n",
        !          2256:          s-socket, map, m->flags, m->start, m->stop);
        !          2257:     return 0;
        !          2258: }
        !          2259: 
        !          2260: static int cb_set_bridge(socket_info_t *s, struct cb_bridge_map *m)
        !          2261: {
        !          2262:     u_char map;
        !          2263:     
        !          2264:     DEBUG(3, "yenta: SetBridge(%d, %d, %#2.2x, %#4.4x-%#4.4x)\n",
        !          2265:          s-socket, m->map, m->flags, m->start, m->stop);
        !          2266:     map = m->map;
        !          2267:     if (!(s->flags & IS_CARDBUS) || (map > 1) || (m->stop < m->start))
        !          2268:        return -EINVAL;
        !          2269:     if (m->flags & MAP_IOSPACE) {
        !          2270:        if ((m->stop > 0xffff) || (m->start & 3) ||
        !          2271:            ((m->stop & 3) != 3))
        !          2272:            return -EINVAL;
        !          2273:        map += 2;
        !          2274:     } else {
        !          2275:        if ((m->start & 0x0fff) || ((m->stop & 0x0fff) != 0x0fff))
        !          2276:            return -EINVAL;
        !          2277:        s->bcr &= ~CB_BCR_PREFETCH(map);
        !          2278:        s->bcr |= (m->flags & MAP_PREFETCH) ? CB_BCR_PREFETCH(map) : 0;
        !          2279:        pci_writew(s, CB_BRIDGE_CONTROL, s->bcr);
        !          2280:     }
        !          2281:     if (m->flags & MAP_ACTIVE) {
        !          2282:        pci_writel(s, CB_MEM_BASE(map), m->start);
        !          2283:        pci_writel(s, CB_MEM_LIMIT(map), m->stop);
        !          2284:     } else {
        !          2285:        pci_writel(s, CB_MEM_LIMIT(map), 0);
        !          2286:        pci_writel(s, CB_MEM_BASE(map), 0);
        !          2287:     }
        !          2288:     return 0;
        !          2289: }
        !          2290: 
        !          2291: #endif /* CONFIG_CARDBUS */
        !          2292: 
        !          2293: /*======================================================================
        !          2294: 
        !          2295:     Routines for accessing socket information and register dumps via
        !          2296:     /proc/bus/pccard/...
        !          2297:     
        !          2298: ======================================================================*/
        !          2299: 
        !          2300: #ifdef HAS_PROC_BUS
        !          2301: 
        !          2302: static int proc_read_info(char *buf, char **start, off_t pos,
        !          2303:                          int count, int *eof, void *data)
        !          2304: {
        !          2305:     socket_info_t *s = data;
        !          2306:     char *p = buf;
        !          2307:     p += sprintf(p, "type:     %s\npsock:    %d\n",
        !          2308:                 pcic[s->type].name, s->psock);
        !          2309: #ifdef CONFIG_PCI
        !          2310:     if (s->flags & (IS_PCI|IS_CARDBUS))
        !          2311:        p += sprintf(p, "bus:      %02x\ndevfn:    %02x.%1x\n",
        !          2312:                     s->bus, PCI_SLOT(s->devfn), PCI_FUNC(s->devfn));
        !          2313:     if (s->flags & IS_CARDBUS)
        !          2314:        p += sprintf(p, "cardbus:  %02x\n", s->cap.cardbus);
        !          2315: #endif
        !          2316:     return (p - buf);
        !          2317: }
        !          2318: 
        !          2319: static int proc_read_exca(char *buf, char **start, off_t pos,
        !          2320:                          int count, int *eof, void *data)
        !          2321: {
        !          2322:     socket_info_t *s = data;
        !          2323:     char *p = buf;
        !          2324:     int i, top;
        !          2325:     
        !          2326: #ifdef CONFIG_ISA
        !          2327:     u_long flags = 0;
        !          2328: #endif
        !          2329:     ISA_LOCK(s, flags);
        !          2330:     top = 0x40;
        !          2331:     if (s->flags & IS_CARDBUS)
        !          2332:        top = (s->flags & IS_CIRRUS) ? 0x140 : 0x50;
        !          2333:     for (i = 0; i < top; i += 4) {
        !          2334:        if (i == 0x50) {
        !          2335:            p += sprintf(p, "\n");
        !          2336:            i = 0x100;
        !          2337:        }
        !          2338:        p += sprintf(p, "%02x %02x %02x %02x%s",
        !          2339:                     i365_get(s,i), i365_get(s,i+1),
        !          2340:                     i365_get(s,i+2), i365_get(s,i+3),
        !          2341:                     ((i % 16) == 12) ? "\n" : " ");
        !          2342:     }
        !          2343:     ISA_UNLOCK(s, flags);
        !          2344:     return (p - buf);
        !          2345: }
        !          2346: 
        !          2347: #ifdef CONFIG_PCI
        !          2348: static int proc_read_pci(char *buf, char **start, off_t pos,
        !          2349:                         int count, int *eof, void *data)
        !          2350: {
        !          2351:     socket_info_t *s = data;
        !          2352:     char *p = buf;
        !          2353:     u_int a, b, c, d;
        !          2354:     int i;
        !          2355:     
        !          2356:     for (i = 0; i < 0xc0; i += 0x10) {
        !          2357:        pci_readl(s, i, &a);
        !          2358:        pci_readl(s, i+4, &b);
        !          2359:        pci_readl(s, i+8, &c);
        !          2360:        pci_readl(s, i+12, &d);
        !          2361:        p += sprintf(p, "%08x %08x %08x %08x\n", a, b, c, d);
        !          2362:     }
        !          2363:     return (p - buf);
        !          2364: }
        !          2365: 
        !          2366: static int proc_read_cardbus(char *buf, char **start, off_t pos,
        !          2367:                             int count, int *eof, void *data)
        !          2368: {
        !          2369:     socket_info_t *s = data;
        !          2370:     char *p = buf;
        !          2371:     int i, top;
        !          2372: 
        !          2373:     top = (s->flags & IS_O2MICRO) ? 0x30 : 0x20;
        !          2374:     for (i = 0; i < top; i += 0x10)
        !          2375:        p += sprintf(p, "%08x %08x %08x %08x\n",
        !          2376:                     cb_readl(s,i+0x00), cb_readl(s,i+0x04),
        !          2377:                     cb_readl(s,i+0x08), cb_readl(s,i+0x0c));
        !          2378:     return (p - buf);
        !          2379: }
        !          2380: #endif
        !          2381: 
        !          2382: static void pcic_proc_setup(socket_info_t *s, struct proc_dir_entry *base)
        !          2383: {
        !          2384:     create_proc_read_entry("info", 0, base, proc_read_info, s);
        !          2385:     create_proc_read_entry("exca", 0, base, proc_read_exca, s);
        !          2386: #ifdef CONFIG_PCI
        !          2387:     if (s->flags & (IS_PCI|IS_CARDBUS))
        !          2388:        create_proc_read_entry("pci", 0, base, proc_read_pci, s);
        !          2389:     if (s->flags & IS_CARDBUS)
        !          2390:        create_proc_read_entry("cardbus", 0, base, proc_read_cardbus, s);
        !          2391: #endif
        !          2392:     s->proc = base;
        !          2393: }
        !          2394: 
        !          2395: static void pcic_proc_remove(socket_info_t *s)
        !          2396: {
        !          2397:     struct proc_dir_entry *base = s->proc;
        !          2398:     if (base == NULL) return;
        !          2399:     remove_proc_entry("info", base);
        !          2400:     remove_proc_entry("exca", base);
        !          2401: #ifdef CONFIG_PCI
        !          2402:     if (s->flags & (IS_PCI|IS_CARDBUS))
        !          2403:        remove_proc_entry("pci", base);
        !          2404:     if (s->flags & IS_CARDBUS)
        !          2405:        remove_proc_entry("cardbus", base);
        !          2406: #endif
        !          2407: }
        !          2408: 
        !          2409: #endif /* HAS_PROC_BUS */
        !          2410: 
        !          2411: /*====================================================================*/
        !          2412: 
        !          2413: typedef int (*subfn_t)(socket_info_t *, void *);
        !          2414: 
        !          2415: static subfn_t pcic_service_table[] = {
        !          2416:     (subfn_t)&pcic_register_callback,
        !          2417:     (subfn_t)&pcic_inquire_socket,
        !          2418:     (subfn_t)&i365_get_status,
        !          2419:     (subfn_t)&i365_get_socket,
        !          2420:     (subfn_t)&i365_set_socket,
        !          2421:     (subfn_t)&i365_get_io_map,
        !          2422:     (subfn_t)&i365_set_io_map,
        !          2423:     (subfn_t)&i365_get_mem_map,
        !          2424:     (subfn_t)&i365_set_mem_map,
        !          2425: #ifdef CONFIG_CARDBUS
        !          2426:     (subfn_t)&cb_get_bridge,
        !          2427:     (subfn_t)&cb_set_bridge,
        !          2428: #else
        !          2429:     NULL, NULL,
        !          2430: #endif
        !          2431: #ifdef HAS_PROC_BUS
        !          2432:     (subfn_t)&pcic_proc_setup
        !          2433: #endif
        !          2434: };
        !          2435: 
        !          2436: #define NFUNC (sizeof(pcic_service_table)/sizeof(subfn_t))
        !          2437: 
        !          2438: static int pcic_service(u_int sock, u_int cmd, void *arg)
        !          2439: {
        !          2440:     socket_info_t *s = &socket[sock];
        !          2441:     subfn_t fn;
        !          2442:     int ret;
        !          2443: #ifdef CONFIG_ISA
        !          2444:     u_long flags = 0;
        !          2445: #endif
        !          2446: 
        !          2447:     if (cmd >= NFUNC)
        !          2448:        return -EINVAL;
        !          2449: 
        !          2450:     if (s->flags & IS_ALIVE) {
        !          2451:        if (cmd == SS_GetStatus)
        !          2452:            *(u_int *)arg = 0;
        !          2453:        return -EINVAL;
        !          2454:     }
        !          2455:     
        !          2456:     fn = pcic_service_table[cmd];
        !          2457: #ifdef CONFIG_CARDBUS
        !          2458:     if ((s->flags & IS_CARDBUS) &&
        !          2459:        (cb_readl(s, CB_SOCKET_STATE) & CB_SS_32BIT)) {
        !          2460:        if (cmd == SS_GetStatus)
        !          2461:            fn = (subfn_t)&cb_get_status;
        !          2462:        else if (cmd == SS_GetSocket)
        !          2463:            fn = (subfn_t)&cb_get_socket;
        !          2464:        else if (cmd == SS_SetSocket)
        !          2465:            fn = (subfn_t)&cb_set_socket;
        !          2466:     }
        !          2467: #endif
        !          2468: 
        !          2469:     ISA_LOCK(s, flags);
        !          2470:     ret = (fn == NULL) ? -EINVAL : fn(s, arg);
        !          2471:     ISA_UNLOCK(s, flags);
        !          2472:     return ret;
        !          2473: } /* pcic_service */
        !          2474: 
        !          2475: /*====================================================================*/
        !          2476: 
        !          2477: int __init init_i82365(void)
        !          2478: {
        !          2479:     servinfo_t serv;
        !          2480:     CardServices(GetCardServicesInfo, &serv);
        !          2481:     if (serv.Revision != CS_RELEASE_CODE) {
        !          2482:        printk(KERN_NOTICE "i82365: Card Services release "
        !          2483:               "does not match!\n");
        !          2484:        return -EINVAL;
        !          2485:     }
        !          2486:     DEBUG(0, "%s\n", version);
        !          2487: 
        !          2488: #ifdef CONFIG_PCI
        !          2489:     if (pcic[IS_UNK_CARDBUS].flags != (IS_CARDBUS|IS_UNKNOWN)) {
        !          2490:        printk(KERN_NOTICE "i82365: bad pcic_id enumeration!\n");
        !          2491:        return -EINVAL;
        !          2492:     }
        !          2493: #endif
        !          2494: 
        !          2495:     printk(KERN_INFO "Intel ISA/PCI/CardBus PCIC probe:\n");
        !          2496:     sockets = 0;
        !          2497: 
        !          2498: #ifdef CONFIG_PCI
        !          2499:     if (do_pci_probe && pcibios_present()) {
        !          2500:        pci_probe(PCI_CLASS_BRIDGE_CARDBUS);
        !          2501:        pci_probe(PCI_CLASS_BRIDGE_PCMCIA);
        !          2502:     }
        !          2503: #endif
        !          2504: 
        !          2505: #ifdef CONFIG_ISA
        !          2506:     isa_probe(i365_base);
        !          2507:     if (!sockets || extra_sockets)
        !          2508:        isa_probe(i365_base+2);
        !          2509: #endif
        !          2510: 
        !          2511:     if (sockets == 0) {
        !          2512:        printk(KERN_INFO "  no bridges found.\n");
        !          2513:        return -ENODEV;
        !          2514:     }
        !          2515: 
        !          2516:     /* Set up interrupt handler(s) */
        !          2517: #ifdef CONFIG_ISA
        !          2518:     if (grab_irq != 0)
        !          2519:        request_irq(cs_irq, pcic_interrupt, 0, "i82365", socket);
        !          2520: #endif
        !          2521: #ifdef CONFIG_PCI
        !          2522:     if (pci_csc) {
        !          2523:        u_int i, irq, mask = 0;
        !          2524:        for (i = 0; i < sockets; i++) {
        !          2525:            irq = socket[i].cap.pci_irq;
        !          2526:            if (irq && !(mask & (1<<irq)))
        !          2527:                request_irq(irq, pcic_interrupt, SA_SHIRQ, "i82365", socket);
        !          2528:            mask |= (1<<irq);
        !          2529:        }
        !          2530:     }
        !          2531: #endif
        !          2532: 
        !          2533:     if (register_ss_entry(sockets, &pcic_service) != 0)
        !          2534:        printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
        !          2535: 
        !          2536:     /* Finally, schedule a polling interrupt */
        !          2537:     if (poll_interval != 0) {
        !          2538:        poll_timer.expires = jiffies + poll_interval;
        !          2539:        add_timer(&poll_timer);
        !          2540:     }
        !          2541: 
        !          2542:     return 0;
        !          2543: 
        !          2544: } /* init_i82365 */
        !          2545: 
        !          2546: static void __exit exit_i82365(void)
        !          2547: {
        !          2548:     int i;
        !          2549: #ifdef HAS_PROC_BUS
        !          2550:     for (i = 0; i < sockets; i++)
        !          2551:        pcic_proc_remove(&socket[i]);
        !          2552: #endif
        !          2553:     unregister_ss_entry(&pcic_service);
        !          2554:     if (poll_interval != 0)
        !          2555:        del_timer(&poll_timer);
        !          2556: #ifdef CONFIG_ISA
        !          2557:     if (grab_irq != 0)
        !          2558:        free_irq(cs_irq, socket);
        !          2559: #endif
        !          2560: #ifdef CONFIG_PCI
        !          2561:     if (pci_csc) {
        !          2562:        u_int irq, mask = 0;
        !          2563:        for (i = 0; i < sockets; i++) {
        !          2564:            irq = socket[i].cap.pci_irq;
        !          2565:            if (irq && !(mask & (1<<irq)))
        !          2566:                free_irq(irq, socket);
        !          2567:            mask |= (1<<irq);
        !          2568:        }
        !          2569:     }
        !          2570: #endif
        !          2571:     for (i = 0; i < sockets; i++) {
        !          2572:        socket_info_t *s = &socket[i];
        !          2573:        /* Turn off all interrupt sources! */
        !          2574:        i365_set(s, I365_CSCINT, 0);
        !          2575: #ifdef CONFIG_PCI
        !          2576:        if (s->flags & IS_CARDBUS)
        !          2577:            cb_writel(s, CB_SOCKET_MASK, 0);
        !          2578:        if (s->cb_virt) {
        !          2579:            iounmap(s->cb_virt);
        !          2580:            release_mem_region(s->cb_phys, 0x1000);
        !          2581:        } else
        !          2582: #endif
        !          2583:            release_region(s->ioaddr, 2);
        !          2584:     }
        !          2585: } /* exit_i82365 */
        !          2586: 
        !          2587: module_init(init_i82365);
        !          2588: module_exit(exit_i82365);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.