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

1.1     ! root        1: /*======================================================================
        !             2: 
        !             3:     PCMCIA Card Services -- core services
        !             4: 
        !             5:     cs.c 1.287 2004/04/09 03:54:25
        !             6:     
        !             7:     The contents of this file are subject to the Mozilla Public
        !             8:     License Version 1.1 (the "License"); you may not use this file
        !             9:     except in compliance with the License. You may obtain a copy of
        !            10:     the License at http://www.mozilla.org/MPL/
        !            11: 
        !            12:     Software distributed under the License is distributed on an "AS
        !            13:     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
        !            14:     implied. See the License for the specific language governing
        !            15:     rights and limitations under the License.
        !            16: 
        !            17:     The initial developer of the original code is David A. Hinds
        !            18:     <[email protected]>.  Portions created by David A. Hinds
        !            19:     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
        !            20: 
        !            21:     Alternatively, the contents of this file may be used under the
        !            22:     terms of the GNU General Public License version 2 (the "GPL"), in
        !            23:     which case the provisions of the GPL are applicable instead of the
        !            24:     above.  If you wish to allow the use of your version of this file
        !            25:     only under the terms of the GPL and not to allow others to use
        !            26:     your version of this file under the MPL, indicate your decision
        !            27:     by deleting the provisions above and replace them with the notice
        !            28:     and other provisions required by the GPL.  If you do not delete
        !            29:     the provisions above, a recipient may use your version of this
        !            30:     file under either the MPL or the GPL.
        !            31:     
        !            32: ======================================================================*/
        !            33: 
        !            34: #include <linux/module.h>
        !            35: #include <linux/init.h>
        !            36: #include <linux/kernel.h>
        !            37: #include <linux/config.h>
        !            38: #include <linux/string.h>
        !            39: #include <linux/major.h>
        !            40: #include <linux/errno.h>
        !            41: #include <linux/slab.h>
        !            42: #include <linux/mm.h>
        !            43: #include <linux/sched.h>
        !            44: #include <linux/timer.h>
        !            45: #include <linux/ioport.h>
        !            46: #include <linux/delay.h>
        !            47: #include <linux/proc_fs.h>
        !            48: #include <linux/pm.h>
        !            49: #include <linux/pci.h>
        !            50: #include <linux/spinlock.h>
        !            51: #include <asm/system.h>
        !            52: #include <asm/irq.h>
        !            53: 
        !            54: #define IN_CARD_SERVICES
        !            55: #include <pcmcia/version.h>
        !            56: #include <pcmcia/cs_types.h>
        !            57: #include <pcmcia/ss.h>
        !            58: #include <pcmcia/cs.h>
        !            59: #include <pcmcia/bulkmem.h>
        !            60: #include <pcmcia/cistpl.h>
        !            61: #include <pcmcia/cisreg.h>
        !            62: #include <pcmcia/bus_ops.h>
        !            63: #include "cs_internal.h"
        !            64: 
        !            65: #ifdef CONFIG_PCI
        !            66: #define PCI_OPT " [pci]"
        !            67: #else
        !            68: #define PCI_OPT ""
        !            69: #endif
        !            70: #ifdef CONFIG_CARDBUS
        !            71: #define CB_OPT " [cardbus]"
        !            72: #else
        !            73: #define CB_OPT ""
        !            74: #endif
        !            75: #ifdef CONFIG_PM
        !            76: #define PM_OPT " [apm]"
        !            77: #else
        !            78: #define PM_OPT ""
        !            79: #endif
        !            80: #ifdef CONFIG_PNP_BIOS
        !            81: #define PNP_OPT " [pnp]"
        !            82: #else
        !            83: #define PNP_OPT ""
        !            84: #endif
        !            85: #if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && \
        !            86:     !defined(CONFIG_PM) && !defined(CONFIG_PNP_BIOS)
        !            87: #define OPTIONS " none"
        !            88: #else
        !            89: #define OPTIONS PCI_OPT CB_OPT PM_OPT PNP_OPT
        !            90: #endif
        !            91: 
        !            92: static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
        !            93: #ifdef UTS_RELEASE
        !            94: static const char *kernel = "kernel build: " UTS_RELEASE " " UTS_VERSION;
        !            95: #endif
        !            96: static const char *options = "options: " OPTIONS;
        !            97: 
        !            98: /*====================================================================*/
        !            99: 
        !           100: /* Module parameters */
        !           101: 
        !           102: MODULE_AUTHOR("David Hinds <[email protected]>");
        !           103: MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE
        !           104:                   "\n  options:" OPTIONS);
        !           105: MODULE_LICENSE("Dual MPL/GPL");
        !           106: 
        !           107: #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
        !           108: 
        !           109: INT_MODULE_PARM(setup_delay,   HZ/20);         /* ticks */
        !           110: INT_MODULE_PARM(resume_delay,  HZ/5);          /* ticks */
        !           111: INT_MODULE_PARM(shutdown_delay,        HZ/40);         /* ticks */
        !           112: INT_MODULE_PARM(vcc_settle,    HZ*4/10);       /* ticks */
        !           113: INT_MODULE_PARM(reset_time,    10);            /* usecs */
        !           114: INT_MODULE_PARM(unreset_delay, HZ/10);         /* ticks */
        !           115: INT_MODULE_PARM(unreset_check, HZ/10);         /* ticks */
        !           116: INT_MODULE_PARM(unreset_limit, 50);            /* unreset_check's */
        !           117: 
        !           118: /* Access speed for attribute memory windows */
        !           119: INT_MODULE_PARM(cis_speed,     300);           /* ns */
        !           120: 
        !           121: /* Access speed for IO windows */
        !           122: INT_MODULE_PARM(io_speed,      0);             /* ns */
        !           123: 
        !           124: /* Optional features */
        !           125: #ifdef CONFIG_PM
        !           126: INT_MODULE_PARM(do_apm, 1);
        !           127: #endif
        !           128: #ifdef CONFIG_PNP_BIOS
        !           129: INT_MODULE_PARM(do_pnp, 1);
        !           130: #endif
        !           131: 
        !           132: #ifdef PCMCIA_DEBUG
        !           133: int pc_debug=PCMCIA_DEBUG;
        !           134: MODULE_PARM(pc_debug, "i");
        !           135: static const char *version =
        !           136: "cs.c 1.287 2004/04/09 03:54:25 (David Hinds)";
        !           137: #endif
        !           138: 
        !           139: /*====================================================================*/
        !           140: 
        !           141: static socket_state_t dead_socket = {
        !           142:     0, SS_DETECT, 0, 0, 0
        !           143: };
        !           144: 
        !           145: /* Table of sockets */
        !           146: socket_t sockets = 0;
        !           147: socket_info_t *socket_table[MAX_SOCK];
        !           148: 
        !           149: #ifdef HAS_PROC_BUS
        !           150: struct proc_dir_entry *proc_pccard = NULL;
        !           151: #endif
        !           152: 
        !           153: /*====================================================================*/
        !           154: 
        !           155: /* String tables for error messages */
        !           156: 
        !           157: typedef struct lookup_t {
        !           158:     int key;
        !           159:     char *msg;
        !           160: } lookup_t;
        !           161: 
        !           162: static const lookup_t error_table[] = {
        !           163:     { CS_SUCCESS,              "Operation succeeded" },
        !           164:     { CS_BAD_ADAPTER,          "Bad adapter" },
        !           165:     { CS_BAD_ATTRIBUTE,        "Bad attribute", },
        !           166:     { CS_BAD_BASE,             "Bad base address" },
        !           167:     { CS_BAD_EDC,              "Bad EDC" },
        !           168:     { CS_BAD_IRQ,              "Bad IRQ" },
        !           169:     { CS_BAD_OFFSET,           "Bad offset" },
        !           170:     { CS_BAD_PAGE,             "Bad page number" },
        !           171:     { CS_READ_FAILURE,         "Read failure" },
        !           172:     { CS_BAD_SIZE,             "Bad size" },
        !           173:     { CS_BAD_SOCKET,           "Bad socket" },
        !           174:     { CS_BAD_TYPE,             "Bad type" },
        !           175:     { CS_BAD_VCC,              "Bad Vcc" },
        !           176:     { CS_BAD_VPP,              "Bad Vpp" },
        !           177:     { CS_BAD_WINDOW,           "Bad window" },
        !           178:     { CS_WRITE_FAILURE,                "Write failure" },
        !           179:     { CS_NO_CARD,              "No card present" },
        !           180:     { CS_UNSUPPORTED_FUNCTION, "Usupported function" },
        !           181:     { CS_UNSUPPORTED_MODE,     "Unsupported mode" },
        !           182:     { CS_BAD_SPEED,            "Bad speed" },
        !           183:     { CS_BUSY,                 "Resource busy" },
        !           184:     { CS_GENERAL_FAILURE,      "General failure" },
        !           185:     { CS_WRITE_PROTECTED,      "Write protected" },
        !           186:     { CS_BAD_ARG_LENGTH,       "Bad argument length" },
        !           187:     { CS_BAD_ARGS,             "Bad arguments" },
        !           188:     { CS_CONFIGURATION_LOCKED, "Configuration locked" },
        !           189:     { CS_IN_USE,               "Resource in use" },
        !           190:     { CS_NO_MORE_ITEMS,                "No more items" },
        !           191:     { CS_OUT_OF_RESOURCE,      "Out of resource" },
        !           192:     { CS_BAD_HANDLE,           "Bad handle" },
        !           193:     { CS_BAD_TUPLE,            "Bad CIS tuple" }
        !           194: };
        !           195: #define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
        !           196: 
        !           197: static const lookup_t service_table[] = {
        !           198:     { AccessConfigurationRegister,     "AccessConfigurationRegister" },
        !           199:     { AddSocketServices,               "AddSocketServices" },
        !           200:     { AdjustResourceInfo,              "AdjustResourceInfo" },
        !           201:     { CheckEraseQueue,                 "CheckEraseQueue" },
        !           202:     { CloseMemory,                     "CloseMemory" },
        !           203:     { DeregisterClient,                        "DeregisterClient" },
        !           204:     { DeregisterEraseQueue,            "DeregisterEraseQueue" },
        !           205:     { GetCardServicesInfo,             "GetCardServicesInfo" },
        !           206:     { GetClientInfo,                   "GetClientInfo" },
        !           207:     { GetConfigurationInfo,            "GetConfigurationInfo" },
        !           208:     { GetEventMask,                    "GetEventMask" },
        !           209:     { GetFirstClient,                  "GetFirstClient" },
        !           210:     { GetFirstRegion,                  "GetFirstRegion" },
        !           211:     { GetFirstTuple,                   "GetFirstTuple" },
        !           212:     { GetNextClient,                   "GetNextClient" },
        !           213:     { GetNextRegion,                   "GetNextRegion" },
        !           214:     { GetNextTuple,                    "GetNextTuple" },
        !           215:     { GetStatus,                       "GetStatus" },
        !           216:     { GetTupleData,                    "GetTupleData" },
        !           217:     { MapMemPage,                      "MapMemPage" },
        !           218:     { ModifyConfiguration,             "ModifyConfiguration" },
        !           219:     { ModifyWindow,                    "ModifyWindow" },
        !           220:     { OpenMemory,                      "OpenMemory" },
        !           221:     { ParseTuple,                      "ParseTuple" },
        !           222:     { ReadMemory,                      "ReadMemory" },
        !           223:     { RegisterClient,                  "RegisterClient" },
        !           224:     { RegisterEraseQueue,              "RegisterEraseQueue" },
        !           225:     { RegisterMTD,                     "RegisterMTD" },
        !           226:     { ReleaseConfiguration,            "ReleaseConfiguration" },
        !           227:     { ReleaseIO,                       "ReleaseIO" },
        !           228:     { ReleaseIRQ,                      "ReleaseIRQ" },
        !           229:     { ReleaseWindow,                   "ReleaseWindow" },
        !           230:     { RequestConfiguration,            "RequestConfiguration" },
        !           231:     { RequestIO,                       "RequestIO" },
        !           232:     { RequestIRQ,                      "RequestIRQ" },
        !           233:     { RequestSocketMask,               "RequestSocketMask" },
        !           234:     { RequestWindow,                   "RequestWindow" },
        !           235:     { ResetCard,                       "ResetCard" },
        !           236:     { SetEventMask,                    "SetEventMask" },
        !           237:     { ValidateCIS,                     "ValidateCIS" },
        !           238:     { WriteMemory,                     "WriteMemory" },
        !           239:     { BindDevice,                      "BindDevice" },
        !           240:     { BindMTD,                         "BindMTD" },
        !           241:     { ReportError,                     "ReportError" },
        !           242:     { SuspendCard,                     "SuspendCard" },
        !           243:     { ResumeCard,                      "ResumeCard" },
        !           244:     { EjectCard,                       "EjectCard" },
        !           245:     { InsertCard,                      "InsertCard" },
        !           246:     { ReplaceCIS,                      "ReplaceCIS" }
        !           247: };
        !           248: #define SERVICE_COUNT (sizeof(service_table)/sizeof(lookup_t))
        !           249: 
        !           250: /*======================================================================
        !           251: 
        !           252:     Reset a socket to the default state
        !           253:     
        !           254: ======================================================================*/
        !           255: 
        !           256: static void init_socket(socket_info_t *s)
        !           257: {
        !           258:     int i;
        !           259:     pccard_io_map io = { 0, 0, 0, 0, 1 };
        !           260:     pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
        !           261: 
        !           262:     mem.sys_stop = s->cap.map_size;
        !           263:     s->socket = dead_socket;
        !           264:     s->ss_entry(s->sock, SS_SetSocket, &s->socket);
        !           265:     for (i = 0; i < 2; i++) {
        !           266:        io.map = i;
        !           267:        s->ss_entry(s->sock, SS_SetIOMap, &io);
        !           268:     }
        !           269:     for (i = 0; i < 5; i++) {
        !           270:        mem.map = i;
        !           271:        s->ss_entry(s->sock, SS_SetMemMap, &mem);
        !           272:     }
        !           273: }
        !           274: 
        !           275: /*====================================================================*/
        !           276: 
        !           277: #if defined(HAS_PROC_BUS) && defined(PCMCIA_DEBUG)
        !           278: static int proc_read_clients(char *buf, char **start, off_t pos,
        !           279:                             int count, int *eof, void *data)
        !           280: {
        !           281:     socket_info_t *s = data;
        !           282:     client_handle_t c;
        !           283:     char *p = buf;
        !           284: 
        !           285:     for (c = s->clients; c; c = c->next)
        !           286:        p += sprintf(p, "fn %x: '%s' [attr 0x%04x] [state 0x%04x]\n",
        !           287:                     c->Function, c->dev_info, c->Attributes, c->state);
        !           288:     return (p - buf);
        !           289: }
        !           290: #endif
        !           291: 
        !           292: /*======================================================================
        !           293: 
        !           294:     Low-level PC Card interface drivers need to register with Card
        !           295:     Services using these calls.
        !           296:     
        !           297: ======================================================================*/
        !           298: 
        !           299: static void setup_socket(u_long i);
        !           300: static void shutdown_socket(u_long i);
        !           301: static void reset_socket(u_long i);
        !           302: static void unreset_socket(u_long i);
        !           303: static void parse_events(void *info, u_int events);
        !           304: 
        !           305: int register_ss_entry(int nsock, ss_entry_t ss_entry)
        !           306: {
        !           307:     int i, ns;
        !           308:     socket_info_t *s;
        !           309: 
        !           310:     DEBUG(0, "cs: register_ss_entry(%d, 0x%p)\n", nsock, ss_entry);
        !           311: 
        !           312:     for (ns = 0; ns < nsock; ns++) {
        !           313:        s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL);
        !           314:        if (!s) {
        !           315:            printk(KERN_NOTICE "cs: memory allocation failure!\n");
        !           316:            return (!ns);
        !           317:        }
        !           318:        memset(s, 0, sizeof(socket_info_t));
        !           319:     
        !           320:        s->ss_entry = ss_entry;
        !           321:        s->sock = ns;
        !           322:        s->setup.data = sockets;
        !           323:        s->setup.function = &setup_socket;
        !           324:        s->shutdown.data = sockets;
        !           325:        s->shutdown.function = &shutdown_socket;
        !           326:        /* base address = 0, map = 0 */
        !           327:        s->cis_mem.flags = 0;
        !           328:        s->cis_mem.speed = cis_speed;
        !           329:        s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
        !           330:        spin_lock_init(&s->lock);
        !           331:        
        !           332:        for (i = 0; i < sockets; i++)
        !           333:            if (socket_table[i] == NULL) break;
        !           334:        socket_table[i] = s;
        !           335:        if (i == sockets) sockets++;
        !           336: 
        !           337:        init_socket(s);
        !           338:        ss_entry(ns, SS_InquireSocket, &s->cap);
        !           339: #ifdef HAS_PROC_BUS
        !           340:        if (proc_pccard) {
        !           341:            char name[3];
        !           342:            sprintf(name, "%02d", i);
        !           343:            s->proc = proc_mkdir(name, proc_pccard);
        !           344:            if (s->proc)
        !           345:                ss_entry(ns, SS_ProcSetup, s->proc);
        !           346: #ifdef PCMCIA_DEBUG
        !           347:            if (s->proc)
        !           348:                create_proc_read_entry("clients", 0, s->proc,
        !           349:                                       proc_read_clients, s);
        !           350: #endif
        !           351:        }
        !           352: #endif
        !           353:     }
        !           354:     
        !           355:     return 0;
        !           356: } /* register_ss_entry */
        !           357: 
        !           358: /*====================================================================*/
        !           359: 
        !           360: void unregister_ss_entry(ss_entry_t ss_entry)
        !           361: {
        !           362:     int i, j;
        !           363:     socket_info_t *s = NULL;
        !           364:     client_t *client;
        !           365: 
        !           366: #ifdef HAS_PROC_BUS
        !           367:     for (i = 0; i < sockets; i++) {
        !           368:        s = socket_table[i];
        !           369:        if (s->ss_entry != ss_entry) continue;
        !           370:        if (proc_pccard) {
        !           371:            char name[3];
        !           372:            sprintf(name, "%02d", i);
        !           373: #ifdef PCMCIA_DEBUG
        !           374:            remove_proc_entry("clients", s->proc);
        !           375: #endif
        !           376:            remove_proc_entry(name, proc_pccard);
        !           377:        }
        !           378:     }
        !           379: #endif
        !           380: 
        !           381:     for (;;) {
        !           382:        for (i = 0; i < sockets; i++) {
        !           383:            s = socket_table[i];
        !           384:            if (s->ss_entry == ss_entry) break;
        !           385:        }
        !           386:        if (i == sockets)
        !           387:            break;
        !           388:        shutdown_socket(i);
        !           389:        release_cis_mem(s);
        !           390:        while (s->clients) {
        !           391:            client = s->clients;
        !           392:            s->clients = s->clients->next;
        !           393:            kfree(client);
        !           394:        }
        !           395:        s->ss_entry = NULL;
        !           396:        kfree(s);
        !           397:        socket_table[i] = NULL;
        !           398:        for (j = i; j < sockets-1; j++)
        !           399:            socket_table[j] = socket_table[j+1];
        !           400:        sockets--;
        !           401:     }
        !           402:     
        !           403: } /* unregister_ss_entry */
        !           404: 
        !           405: /*======================================================================
        !           406: 
        !           407:     Shutdown_Socket() and setup_socket() are scheduled using add_timer
        !           408:     calls by the main event handler when card insertion and removal
        !           409:     events are received.  Shutdown_Socket() unconfigures a socket and
        !           410:     turns off socket power.  Setup_socket() turns on socket power
        !           411:     and resets the socket, in two stages.
        !           412: 
        !           413: ======================================================================*/
        !           414: 
        !           415: static void free_regions(memory_handle_t *list)
        !           416: {
        !           417:     memory_handle_t tmp;
        !           418:     while (*list != NULL) {
        !           419:        tmp = *list;
        !           420:        *list = tmp->info.next;
        !           421:        tmp->region_magic = 0;
        !           422:        kfree(tmp);
        !           423:     }
        !           424: }
        !           425: 
        !           426: static int send_event(socket_info_t *s, event_t event, int priority);
        !           427: 
        !           428: static void shutdown_socket(u_long i)
        !           429: {
        !           430:     socket_info_t *s = socket_table[i];
        !           431:     client_t **c;
        !           432:     
        !           433:     DEBUG(1, "cs: shutdown_socket(%ld)\n", i);
        !           434: 
        !           435:     /* Blank out the socket state */
        !           436:     s->state &= SOCKET_PRESENT|SOCKET_SETUP_PENDING;
        !           437:     init_socket(s);
        !           438:     s->irq.AssignedIRQ = s->irq.Config = 0;
        !           439:     s->lock_count = 0;
        !           440:     s->cis_used = 0;
        !           441:     if (s->fake_cis) {
        !           442:        kfree(s->fake_cis);
        !           443:        s->fake_cis = NULL;
        !           444:     }
        !           445: #ifdef CONFIG_CARDBUS
        !           446:     cb_release_cis_mem(s);
        !           447:     cb_free(s);
        !           448: #endif
        !           449:     s->functions = 0;
        !           450:     if (s->config) {
        !           451:        kfree(s->config);
        !           452:        s->config = NULL;
        !           453:     }
        !           454:     for (c = &s->clients; *c; ) {
        !           455:        if ((*c)->state & CLIENT_UNBOUND) {
        !           456:            client_t *d = *c;
        !           457:            *c = (*c)->next;
        !           458:            kfree(d);
        !           459:        } else {
        !           460:            c = &((*c)->next);
        !           461:        }
        !           462:     }
        !           463:     free_regions(&s->a_region);
        !           464:     free_regions(&s->c_region);
        !           465: } /* shutdown_socket */
        !           466: 
        !           467: static void setup_socket(u_long i)
        !           468: {
        !           469:     int val;
        !           470:     socket_info_t *s = socket_table[i];
        !           471: 
        !           472:     s->ss_entry(s->sock, SS_GetStatus, &val);
        !           473:     if (val & SS_PENDING) {
        !           474:        /* Does the socket need more time? */
        !           475:        DEBUG(2, "cs: setup_socket(%ld): status pending\n", i);
        !           476:        if (++s->setup_timeout > 100) {
        !           477:            printk(KERN_NOTICE "cs: socket %ld voltage interrogation"
        !           478:                   " timed out\n", i);
        !           479:        } else {
        !           480:            mod_timer(&s->setup, jiffies + HZ/10);
        !           481:        }
        !           482:     } else if (val & SS_DETECT) {
        !           483:        DEBUG(1, "cs: setup_socket(%ld): applying power\n", i);
        !           484:        s->state |= SOCKET_PRESENT;
        !           485:        s->socket.flags = 0;
        !           486:        if (val & SS_3VCARD)
        !           487:            s->socket.Vcc = s->socket.Vpp = 33;
        !           488:        else if (!(val & SS_XVCARD))
        !           489:            s->socket.Vcc = s->socket.Vpp = 50;
        !           490:        else {
        !           491:            printk(KERN_NOTICE "cs: socket %ld: unsupported "
        !           492:                   "voltage key\n", i);
        !           493:            s->socket.Vcc = 0;
        !           494:        }
        !           495:        if (val & SS_CARDBUS) {
        !           496:            s->state |= SOCKET_CARDBUS;
        !           497: #ifndef CONFIG_CARDBUS
        !           498:            printk(KERN_NOTICE "cs: unsupported card type detected!\n");
        !           499: #endif
        !           500:        }
        !           501:        s->ss_entry(s->sock, SS_SetSocket, &s->socket);
        !           502:        s->setup.function = &reset_socket;
        !           503:        mod_timer(&s->setup, jiffies + vcc_settle);
        !           504:     } else
        !           505:        DEBUG(0, "cs: setup_socket(%ld): no card!\n", i);
        !           506: } /* setup_socket */
        !           507: 
        !           508: /*======================================================================
        !           509: 
        !           510:     Reset_socket() and unreset_socket() handle hard resets.  Resets
        !           511:     have several causes: card insertion, a call to reset_socket, or
        !           512:     recovery from a suspend/resume cycle.  Unreset_socket() sends
        !           513:     a CS event that matches the cause of the reset.
        !           514:     
        !           515: ======================================================================*/
        !           516: 
        !           517: static void reset_socket(u_long i)
        !           518: {
        !           519:     socket_info_t *s = socket_table[i];
        !           520: 
        !           521:     DEBUG(1, "cs: resetting socket %ld\n", i);
        !           522:     s->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
        !           523:     s->ss_entry(s->sock, SS_SetSocket, &s->socket);
        !           524:     udelay((long)reset_time);
        !           525:     s->socket.flags &= ~SS_RESET;
        !           526:     s->ss_entry(s->sock, SS_SetSocket, &s->socket);
        !           527:     s->setup_timeout = 0;
        !           528:     s->setup.function = &unreset_socket;
        !           529:     mod_timer(&s->setup, jiffies + unreset_delay);
        !           530: } /* reset_socket */
        !           531: 
        !           532: #define EVENT_MASK \
        !           533: (SOCKET_SETUP_PENDING|SOCKET_SUSPEND|SOCKET_RESET_PENDING)
        !           534: 
        !           535: static void unreset_socket(u_long i)
        !           536: {
        !           537:     socket_info_t *s = socket_table[i];
        !           538:     int val;
        !           539: 
        !           540:     s->ss_entry(s->sock, SS_GetStatus, &val);
        !           541:     if (val & SS_READY) {
        !           542:        DEBUG(1, "cs: reset done on socket %ld\n", i);
        !           543:        if (s->state & SOCKET_SUSPEND) {
        !           544:            s->state &= ~EVENT_MASK;
        !           545:            if (verify_cis_cache(s) != 0)
        !           546:                parse_events(s, SS_DETECT);
        !           547:            else
        !           548:                send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
        !           549:        } else if (s->state & SOCKET_SETUP_PENDING) {
        !           550: #ifdef CONFIG_CARDBUS
        !           551:            if (s->state & SOCKET_CARDBUS)
        !           552:                cb_alloc(s);
        !           553: #endif
        !           554:            send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
        !           555:            s->state &= ~SOCKET_SETUP_PENDING;
        !           556:        } else {
        !           557:            send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
        !           558:            if (s->reset_handle) {
        !           559:                s->reset_handle->event_callback_args.info = NULL;
        !           560:                EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,
        !           561:                      CS_EVENT_PRI_LOW);
        !           562:                s->state &= ~EVENT_MASK;
        !           563:            }
        !           564:        }
        !           565:     } else {
        !           566:        DEBUG(2, "cs: socket %ld not ready yet\n", i);
        !           567:        if (++s->setup_timeout > unreset_limit) {
        !           568:            printk(KERN_NOTICE "cs: socket %ld timed out during"
        !           569:                   " reset\n", i);
        !           570:            s->state &= ~EVENT_MASK;
        !           571:        } else {
        !           572:            mod_timer(&s->setup, jiffies + unreset_check);
        !           573:        }
        !           574:     }
        !           575: } /* unreset_socket */
        !           576: 
        !           577: /*======================================================================
        !           578: 
        !           579:     The central event handler.  Send_event() sends an event to all
        !           580:     valid clients.  Parse_events() interprets the event bits from
        !           581:     a card status change report.  Do_shotdown() handles the high
        !           582:     priority stuff associated with a card removal.
        !           583:     
        !           584: ======================================================================*/
        !           585: 
        !           586: static int send_event(socket_info_t *s, event_t event, int priority)
        !           587: {
        !           588:     client_t *client = s->clients;
        !           589:     int ret;
        !           590:     DEBUG(1, "cs: send_event(sock %d, event %d, pri %d)\n",
        !           591:          s->sock, event, priority);
        !           592:     ret = 0;
        !           593:     for (; client; client = client->next) { 
        !           594:        if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
        !           595:            continue;
        !           596:        if (client->EventMask & event) {
        !           597:            ret = EVENT(client, event, priority);
        !           598:            if (ret != 0)
        !           599:                return ret;
        !           600:        }
        !           601:     }
        !           602:     return ret;
        !           603: } /* send_event */
        !           604: 
        !           605: static void do_shutdown(socket_info_t *s)
        !           606: {
        !           607:     client_t *client;
        !           608:     if (s->state & SOCKET_SHUTDOWN_PENDING)
        !           609:        return;
        !           610:     s->state |= SOCKET_SHUTDOWN_PENDING;
        !           611:     send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
        !           612:     for (client = s->clients; client; client = client->next)
        !           613:        if (!(client->Attributes & INFO_MASTER_CLIENT))
        !           614:            client->state |= CLIENT_STALE;
        !           615:     if (s->state & (SOCKET_SETUP_PENDING|SOCKET_RESET_PENDING)) {
        !           616:        DEBUG(0, "cs: flushing pending setup\n");
        !           617:        del_timer(&s->setup);
        !           618:        s->state &= ~EVENT_MASK;
        !           619:     }
        !           620:     mod_timer(&s->shutdown, jiffies + shutdown_delay);
        !           621:     s->state &= ~SOCKET_PRESENT;
        !           622: }
        !           623: 
        !           624: static void parse_events(void *info, u_int events)
        !           625: {
        !           626:     socket_info_t *s = info;
        !           627:     if (events & SS_DETECT) {
        !           628:        int status;
        !           629:        u_long flags;
        !           630:        spin_lock_irqsave(&s->lock, flags);
        !           631:        s->ss_entry(s->sock, SS_GetStatus, &status);
        !           632:        if ((s->state & SOCKET_PRESENT) &&
        !           633:            (!(s->state & SOCKET_SUSPEND) ||
        !           634:             !(status & SS_DETECT)))
        !           635:            do_shutdown(s);
        !           636:        if (status & SS_DETECT) {
        !           637:            if (s->state & SOCKET_SETUP_PENDING) {
        !           638:                del_timer(&s->setup);
        !           639:                DEBUG(1, "cs: delaying pending setup\n");
        !           640:            }
        !           641:            s->state |= SOCKET_SETUP_PENDING;
        !           642:            s->setup.function = &setup_socket;
        !           643:            s->setup_timeout = 0;
        !           644:            if (s->state & SOCKET_SUSPEND)
        !           645:                s->setup.expires = jiffies + resume_delay;
        !           646:            else
        !           647:                s->setup.expires = jiffies + setup_delay;
        !           648:            add_timer(&s->setup);
        !           649:        }
        !           650:        spin_unlock_irqrestore(&s->lock, flags);
        !           651:     }
        !           652:     if (events & SS_BATDEAD)
        !           653:        send_event(s, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);
        !           654:     if (events & SS_BATWARN)
        !           655:        send_event(s, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
        !           656:     if (events & SS_READY) {
        !           657:        if (!(s->state & SOCKET_RESET_PENDING))
        !           658:            send_event(s, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
        !           659:        else DEBUG(1, "cs: ready change during reset\n");
        !           660:     }
        !           661: } /* parse_events */
        !           662: 
        !           663: /*======================================================================
        !           664: 
        !           665:     Another event handler, for power management events.
        !           666: 
        !           667:     This does not comply with the latest PC Card spec for handling
        !           668:     power management events.
        !           669:     
        !           670: ======================================================================*/
        !           671: 
        !           672: #ifdef CONFIG_PM
        !           673: #if (LINUX_VERSION_CODE < VERSION(2,3,43))
        !           674: static int handle_pm_event(apm_event_t rqst)
        !           675: #else
        !           676: static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst,
        !           677:                           void *data)
        !           678: #endif
        !           679: {
        !           680:     int i, stat;
        !           681:     socket_info_t *s;
        !           682:     static int down = 0;
        !           683: 
        !           684:     /* <linux/pm.h> hides a hack so this works with old APM support */
        !           685:     switch (rqst) {
        !           686:     case PM_SUSPEND:
        !           687:        DEBUG(1, "cs: received suspend notification\n");
        !           688:        if (down) {
        !           689:            printk(KERN_DEBUG "cs: received extra suspend event\n");
        !           690:            break;
        !           691:        }
        !           692:        down = 1;
        !           693:        for (i = 0; i < sockets; i++) {
        !           694:            s = socket_table[i];
        !           695:            if ((s->state & SOCKET_PRESENT) &&
        !           696:                !(s->state & SOCKET_SUSPEND)){
        !           697:                send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
        !           698:                s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
        !           699:                s->state |= SOCKET_SUSPEND;
        !           700:            }
        !           701:        }
        !           702:        break;
        !           703:     case PM_RESUME:
        !           704:        DEBUG(1, "cs: received resume notification\n");
        !           705:        if (!down) {
        !           706:            printk(KERN_DEBUG "cs: received bogus resume event\n");
        !           707:            break;
        !           708:        }
        !           709:        down = 0;
        !           710:        for (i = 0; i < sockets; i++) {
        !           711:            s = socket_table[i];
        !           712:            /* Do this just to reinitialize the socket */
        !           713:            init_socket(s);
        !           714:            s->ss_entry(s->sock, SS_GetStatus, &stat);
        !           715:            /* If there was or is a card here, we need to do something
        !           716:               about it... but parse_events will sort it all out. */
        !           717:                    if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT))
        !           718:                parse_events(s, SS_DETECT);
        !           719:        }
        !           720:        break;
        !           721:     }
        !           722:     return 0;
        !           723: } /* handle_pm_event */
        !           724: #endif
        !           725: 
        !           726: /*======================================================================
        !           727: 
        !           728:     Special stuff for managing IO windows, because they are scarce.
        !           729:     
        !           730: ======================================================================*/
        !           731: 
        !           732: static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
        !           733:                          ioaddr_t num, u_int lines, char *name)
        !           734: {
        !           735:     int i;
        !           736:     ioaddr_t try, align;
        !           737: 
        !           738:     align = (*base) ? (lines ? 1<<lines : 0) : 1;
        !           739:     if (align && (align < num)) {
        !           740:        if (*base) {
        !           741:            DEBUG(0, "odd IO request: num %04x align %04x\n",
        !           742:                  num, align);
        !           743:            align = 0;
        !           744:        } else
        !           745:            while (align && (align < num)) align <<= 1;
        !           746:     }
        !           747:     if (*base & ~(align-1)) {
        !           748:        DEBUG(0, "odd IO request: base %04x align %04x\n",
        !           749:              *base, align);
        !           750:        while (*base & ~(align-1)) align <<= 1;
        !           751:     }
        !           752:     /* Check for an already-allocated window that must conflict with
        !           753:        what was asked for.  It is a hack because it does not catch all
        !           754:        potential conflicts, just the most obvious ones. */
        !           755:     for (i = 0; i < MAX_IO_WIN; i++)
        !           756:        if ((s->io[i].NumPorts != 0) &&
        !           757:            ((s->io[i].BasePort & (align-1)) == *base))
        !           758:            return 1;
        !           759:     for (i = 0; i < MAX_IO_WIN; i++) {
        !           760:        if (s->io[i].NumPorts == 0) {
        !           761:            if (find_io_region(base, num, align, name) == 0) {
        !           762:                s->io[i].Attributes = attr;
        !           763:                s->io[i].BasePort = *base;
        !           764:                s->io[i].NumPorts = s->io[i].InUse = num;
        !           765:                break;
        !           766:            } else
        !           767:                return 1;
        !           768:        } else if (s->io[i].Attributes != attr)
        !           769:            continue;
        !           770:        /* Try to extend top of window */
        !           771:        try = s->io[i].BasePort + s->io[i].NumPorts;
        !           772:        if ((*base == 0) || (*base == try))
        !           773:            if (find_io_region(&try, num, 0, name) == 0) {
        !           774:                *base = try;
        !           775:                s->io[i].NumPorts += num;
        !           776:                s->io[i].InUse += num;
        !           777:                break;
        !           778:            }
        !           779:        /* Try to extend bottom of window */
        !           780:        try = s->io[i].BasePort - num;
        !           781:        if ((*base == 0) || (*base == try))
        !           782:            if (find_io_region(&try, num, 0, name) == 0) {
        !           783:                s->io[i].BasePort = *base = try;
        !           784:                s->io[i].NumPorts += num;
        !           785:                s->io[i].InUse += num;
        !           786:                break;
        !           787:            }
        !           788:     }
        !           789:     return (i == MAX_IO_WIN);
        !           790: } /* alloc_io_space */
        !           791: 
        !           792: static void release_io_space(socket_info_t *s, ioaddr_t base,
        !           793:                             ioaddr_t num)
        !           794: {
        !           795:     int i;
        !           796:     release_region(base, num);
        !           797:     for (i = 0; i < MAX_IO_WIN; i++) {
        !           798:        if ((s->io[i].BasePort <= base) &&
        !           799:            (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
        !           800:            s->io[i].InUse -= num;
        !           801:            /* Free the window if no one else is using it */
        !           802:            if (s->io[i].InUse == 0)
        !           803:                s->io[i].NumPorts = 0;
        !           804:        }
        !           805:     }
        !           806: }
        !           807: 
        !           808: /*======================================================================
        !           809: 
        !           810:     Access_configuration_register() reads and writes configuration
        !           811:     registers in attribute memory.  Memory window 0 is reserved for
        !           812:     this and the tuple reading services.
        !           813:     
        !           814: ======================================================================*/
        !           815: 
        !           816: static int access_configuration_register(client_handle_t handle,
        !           817:                                         conf_reg_t *reg)
        !           818: {
        !           819:     socket_info_t *s;
        !           820:     config_t *c;
        !           821:     int addr;
        !           822:     u_char val;
        !           823:     
        !           824:     if (CHECK_HANDLE(handle))
        !           825:        return CS_BAD_HANDLE;
        !           826:     s = SOCKET(handle);
        !           827:     if (!(s->state & SOCKET_PRESENT))
        !           828:        return CS_NO_CARD;
        !           829:     if (handle->Function == BIND_FN_ALL) {
        !           830:        if (reg->Function >= s->functions)
        !           831:            return CS_BAD_ARGS;
        !           832:        c = &s->config[reg->Function];
        !           833:     } else
        !           834:        c = CONFIG(handle);
        !           835:     if (!(c->state & CONFIG_LOCKED))
        !           836:        return CS_CONFIGURATION_LOCKED;
        !           837: 
        !           838:     addr = (c->ConfigBase + reg->Offset) >> 1;
        !           839:     
        !           840:     switch (reg->Action) {
        !           841:     case CS_READ:
        !           842:        read_cis_mem(s, 1, addr, 1, &val);
        !           843:        reg->Value = val;
        !           844:        break;
        !           845:     case CS_WRITE:
        !           846:        val = reg->Value;
        !           847:        write_cis_mem(s, 1, addr, 1, &val);
        !           848:        break;
        !           849:     default:
        !           850:        return CS_BAD_ARGS;
        !           851:        break;
        !           852:     }
        !           853:     return CS_SUCCESS;
        !           854: } /* access_configuration_register */
        !           855: 
        !           856: /*======================================================================
        !           857: 
        !           858:     Bind_device() associates a device driver with a particular socket.
        !           859:     It is normally called by Driver Services after it has identified
        !           860:     a newly inserted card.  An instance of that driver will then be
        !           861:     eligible to register as a client of this socket.
        !           862:     
        !           863: ======================================================================*/
        !           864: 
        !           865: static int bind_device(bind_req_t *req)
        !           866: {
        !           867:     client_t *client;
        !           868:     socket_info_t *s;
        !           869: 
        !           870:     if (CHECK_SOCKET(req->Socket))
        !           871:        return CS_BAD_SOCKET;
        !           872:     s = SOCKET(req);
        !           873: 
        !           874:     client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL);
        !           875:     if (!client) return CS_OUT_OF_RESOURCE;
        !           876:     memset(client, '\0', sizeof(client_t));
        !           877:     client->client_magic = CLIENT_MAGIC;
        !           878:     strncpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
        !           879:     client->Socket = req->Socket;
        !           880:     client->Function = req->Function;
        !           881:     client->state = CLIENT_UNBOUND;
        !           882:     client->erase_busy.next = &client->erase_busy;
        !           883:     client->erase_busy.prev = &client->erase_busy;
        !           884:     init_waitqueue_head(&client->mtd_req);
        !           885:     client->next = s->clients;
        !           886:     s->clients = client;
        !           887:     DEBUG(1, "cs: bind_device(): client 0x%p, sock %d, dev %s\n",
        !           888:          client, client->Socket, client->dev_info);
        !           889:     return CS_SUCCESS;
        !           890: } /* bind_device */
        !           891: 
        !           892: /*======================================================================
        !           893: 
        !           894:     Bind_mtd() associates a device driver with a particular memory
        !           895:     region.  It is normally called by Driver Services after it has
        !           896:     identified a memory device type.  An instance of the corresponding
        !           897:     driver will then be able to register to control this region.
        !           898:     
        !           899: ======================================================================*/
        !           900: 
        !           901: static int bind_mtd(mtd_bind_t *req)
        !           902: {
        !           903:     socket_info_t *s;
        !           904:     memory_handle_t region;
        !           905:     
        !           906:     if (CHECK_SOCKET(req->Socket))
        !           907:        return CS_BAD_SOCKET;
        !           908:     s = SOCKET(req);
        !           909:     
        !           910:     if (req->Attributes & REGION_TYPE_AM)
        !           911:        region = s->a_region;
        !           912:     else
        !           913:        region = s->c_region;
        !           914:     
        !           915:     while (region) {
        !           916:        if (region->info.CardOffset == req->CardOffset) break;
        !           917:        region = region->info.next;
        !           918:     }
        !           919:     if (!region || (region->mtd != NULL))
        !           920:        return CS_BAD_OFFSET;
        !           921:     strncpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
        !           922:     
        !           923:     DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
        !           924:          req->Attributes, req->CardOffset, (char *)req->dev_info);
        !           925:     return CS_SUCCESS;
        !           926: } /* bind_mtd */
        !           927: 
        !           928: /*====================================================================*/
        !           929: 
        !           930: static int deregister_client(client_handle_t handle)
        !           931: {
        !           932:     client_t **client;
        !           933:     socket_info_t *s;
        !           934:     memory_handle_t region;
        !           935:     u_long flags;
        !           936:     int i, sn;
        !           937:     
        !           938:     DEBUG(1, "cs: deregister_client(%p)\n", handle);
        !           939:     if (CHECK_HANDLE(handle))
        !           940:        return CS_BAD_HANDLE;
        !           941:     if (handle->state &
        !           942:        (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
        !           943:        return CS_IN_USE;
        !           944:     for (i = 0; i < MAX_WIN; i++)
        !           945:        if (handle->state & CLIENT_WIN_REQ(i))
        !           946:            return CS_IN_USE;
        !           947: 
        !           948:     /* Disconnect all MTD links */
        !           949:     s = SOCKET(handle);
        !           950:     if (handle->mtd_count) {
        !           951:        for (region = s->a_region; region; region = region->info.next)
        !           952:            if (region->mtd == handle) region->mtd = NULL;
        !           953:        for (region = s->c_region; region; region = region->info.next)
        !           954:            if (region->mtd == handle) region->mtd = NULL;
        !           955:     }
        !           956:     
        !           957:     sn = handle->Socket; s = socket_table[sn];
        !           958: 
        !           959:     if ((handle->state & CLIENT_STALE) ||
        !           960:        (handle->Attributes & INFO_MASTER_CLIENT)) {
        !           961:        spin_lock_irqsave(&s->lock, flags);
        !           962:        client = &s->clients;
        !           963:        while ((*client) && ((*client) != handle))
        !           964:            client = &(*client)->next;
        !           965:        if (*client == NULL) {
        !           966:            spin_unlock_irqrestore(&s->lock, flags);
        !           967:            return CS_BAD_HANDLE;
        !           968:        }
        !           969:        *client = handle->next;
        !           970:        handle->client_magic = 0;
        !           971:        kfree(handle);
        !           972:        spin_unlock_irqrestore(&s->lock, flags);
        !           973:     } else {
        !           974:        handle->state = CLIENT_UNBOUND;
        !           975:        handle->mtd_count = 0;
        !           976:        handle->event_handler = NULL;
        !           977:     }
        !           978: 
        !           979:     if (--s->real_clients == 0)
        !           980:        s->ss_entry(sn, SS_RegisterCallback, NULL);
        !           981:     
        !           982:     return CS_SUCCESS;
        !           983: } /* deregister_client */
        !           984: 
        !           985: /*====================================================================*/
        !           986: 
        !           987: static int get_configuration_info(client_handle_t handle,
        !           988:                                  config_info_t *config)
        !           989: {
        !           990:     socket_info_t *s;
        !           991:     config_t *c;
        !           992:     
        !           993:     if (CHECK_HANDLE(handle))
        !           994:        return CS_BAD_HANDLE;
        !           995:     s = SOCKET(handle);
        !           996:     if (!(s->state & SOCKET_PRESENT))
        !           997:        return CS_NO_CARD;
        !           998: 
        !           999:     if (handle->Function == BIND_FN_ALL) {
        !          1000:        if (config->Function && (config->Function >= s->functions))
        !          1001:            return CS_BAD_ARGS;
        !          1002:     } else
        !          1003:        config->Function = handle->Function;
        !          1004:     
        !          1005: #ifdef CONFIG_CARDBUS
        !          1006:     if (s->state & SOCKET_CARDBUS) {
        !          1007:        u_char fn = config->Function;
        !          1008:        memset(config, 0, sizeof(config_info_t));
        !          1009:        config->Function = fn;
        !          1010:        config->Vcc = s->socket.Vcc;
        !          1011:        config->Vpp1 = config->Vpp2 = s->socket.Vpp;
        !          1012:        config->Option = s->cap.cardbus;
        !          1013:        config->IntType = INT_CARDBUS;
        !          1014:        /* This is a nasty hack */
        !          1015:        pcibios_read_config_dword(s->cap.cardbus, 0, 0, &config->ConfigBase);
        !          1016:        if (s->cb_config) {
        !          1017:            config->Attributes = CONF_VALID_CLIENT;
        !          1018:            config->AssignedIRQ = s->irq.AssignedIRQ;
        !          1019:            if (config->AssignedIRQ)
        !          1020:                config->Attributes |= CONF_ENABLE_IRQ;
        !          1021:            config->BasePort1 = s->io[0].BasePort;
        !          1022:            config->NumPorts1 = s->io[0].NumPorts;
        !          1023:        }
        !          1024:        return CS_SUCCESS;
        !          1025:     }
        !          1026: #endif
        !          1027:     
        !          1028:     c = (s->config != NULL) ? &s->config[config->Function] : NULL;
        !          1029:     
        !          1030:     if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
        !          1031:        config->Attributes = 0;
        !          1032:        config->Vcc = s->socket.Vcc;
        !          1033:        config->Vpp1 = config->Vpp2 = s->socket.Vpp;
        !          1034:        return CS_SUCCESS;
        !          1035:     }
        !          1036:     
        !          1037:     /* !!! This is a hack !!! */
        !          1038:     memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
        !          1039:     config->Attributes |= CONF_VALID_CLIENT;
        !          1040:     config->CardValues = c->CardValues;
        !          1041:     config->IRQAttributes = c->irq.Attributes;
        !          1042:     config->AssignedIRQ = s->irq.AssignedIRQ;
        !          1043:     config->BasePort1 = c->io.BasePort1;
        !          1044:     config->NumPorts1 = c->io.NumPorts1;
        !          1045:     config->Attributes1 = c->io.Attributes1;
        !          1046:     config->BasePort2 = c->io.BasePort2;
        !          1047:     config->NumPorts2 = c->io.NumPorts2;
        !          1048:     config->Attributes2 = c->io.Attributes2;
        !          1049:     config->IOAddrLines = c->io.IOAddrLines;
        !          1050:     
        !          1051:     return CS_SUCCESS;
        !          1052: } /* get_configuration_info */
        !          1053: 
        !          1054: /*======================================================================
        !          1055: 
        !          1056:     Return information about this version of Card Services.
        !          1057:     
        !          1058: ======================================================================*/
        !          1059: 
        !          1060: static int get_card_services_info(servinfo_t *info)
        !          1061: {
        !          1062:     info->Signature[0] = 'C';
        !          1063:     info->Signature[1] = 'S';
        !          1064:     info->Count = sockets;
        !          1065:     info->Revision = CS_RELEASE_CODE;
        !          1066:     info->CSLevel = 0x0210;
        !          1067:     info->VendorString = (char *)release;
        !          1068:     return CS_SUCCESS;
        !          1069: } /* get_card_services_info */
        !          1070: 
        !          1071: /*======================================================================
        !          1072: 
        !          1073:     Note that get_first_client() *does* recognize the Socket field
        !          1074:     in the request structure.
        !          1075:     
        !          1076: ======================================================================*/
        !          1077: 
        !          1078: static int get_first_client(client_handle_t *handle, client_req_t *req)
        !          1079: {
        !          1080:     socket_t s;
        !          1081:     if (req->Attributes & CLIENT_THIS_SOCKET)
        !          1082:        s = req->Socket;
        !          1083:     else
        !          1084:        s = 0;
        !          1085:     if (CHECK_SOCKET(req->Socket))
        !          1086:        return CS_BAD_SOCKET;
        !          1087:     if (socket_table[s]->clients == NULL)
        !          1088:        return CS_NO_MORE_ITEMS;
        !          1089:     *handle = socket_table[s]->clients;
        !          1090:     return CS_SUCCESS;
        !          1091: } /* get_first_client */
        !          1092: 
        !          1093: /*====================================================================*/
        !          1094: 
        !          1095: static int get_next_client(client_handle_t *handle, client_req_t *req)
        !          1096: {
        !          1097:     socket_info_t *s;
        !          1098:     if ((handle == NULL) || CHECK_HANDLE(*handle))
        !          1099:        return CS_BAD_HANDLE;
        !          1100:     if ((*handle)->next == NULL) {
        !          1101:        if (req->Attributes & CLIENT_THIS_SOCKET)
        !          1102:            return CS_NO_MORE_ITEMS;
        !          1103:        s = SOCKET(*handle);
        !          1104:        if (s->clients == NULL)
        !          1105:            return CS_NO_MORE_ITEMS;
        !          1106:        *handle = s->clients;
        !          1107:     } else
        !          1108:        *handle = (*handle)->next;
        !          1109:     return CS_SUCCESS;
        !          1110: } /* get_next_client */
        !          1111: 
        !          1112: /*====================================================================*/
        !          1113: 
        !          1114: static int get_window(window_handle_t *handle, int idx, win_req_t *req)
        !          1115: {
        !          1116:     socket_info_t *s;
        !          1117:     window_t *win;
        !          1118:     int w;
        !          1119: 
        !          1120:     if (idx == 0)
        !          1121:        s = SOCKET((client_handle_t)*handle);
        !          1122:     else
        !          1123:        s = (*handle)->sock;
        !          1124:     if (!(s->state & SOCKET_PRESENT))
        !          1125:        return CS_NO_CARD;
        !          1126:     for (w = idx; w < MAX_WIN; w++)
        !          1127:        if (s->state & SOCKET_WIN_REQ(w)) break;
        !          1128:     if (w == MAX_WIN)
        !          1129:        return CS_NO_MORE_ITEMS;
        !          1130:     win = &s->win[w];
        !          1131:     req->Base = win->ctl.sys_start;
        !          1132:     req->Size = win->ctl.sys_stop - win->ctl.sys_start + 1;
        !          1133:     req->AccessSpeed = win->ctl.speed;
        !          1134:     req->Attributes = 0;
        !          1135:     if (win->ctl.flags & MAP_ATTRIB)
        !          1136:        req->Attributes |= WIN_MEMORY_TYPE_AM;
        !          1137:     if (win->ctl.flags & MAP_ACTIVE)
        !          1138:        req->Attributes |= WIN_ENABLE;
        !          1139:     if (win->ctl.flags & MAP_16BIT)
        !          1140:        req->Attributes |= WIN_DATA_WIDTH_16;
        !          1141:     if (win->ctl.flags & MAP_USE_WAIT)
        !          1142:        req->Attributes |= WIN_USE_WAIT;
        !          1143:     *handle = win;
        !          1144:     return CS_SUCCESS;
        !          1145: } /* get_window */
        !          1146: 
        !          1147: static int get_first_window(client_handle_t *handle, win_req_t *req)
        !          1148: {
        !          1149:     if ((handle == NULL) || CHECK_HANDLE(*handle))
        !          1150:        return CS_BAD_HANDLE;
        !          1151:     return get_window((window_handle_t *)handle, 0, req);
        !          1152: }
        !          1153: 
        !          1154: static int get_next_window(window_handle_t *win, win_req_t *req)
        !          1155: {
        !          1156:     if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
        !          1157:        return CS_BAD_HANDLE;
        !          1158:     return get_window(win, (*win)->index+1, req);
        !          1159: }
        !          1160: 
        !          1161: /*======================================================================
        !          1162: 
        !          1163:     Get the current socket state bits.  We don't support the latched
        !          1164:     SocketState yet: I haven't seen any point for it.
        !          1165:     
        !          1166: ======================================================================*/
        !          1167: 
        !          1168: static int cs_get_status(client_handle_t handle, cs_status_t *status)
        !          1169: {
        !          1170:     socket_info_t *s;
        !          1171:     config_t *c;
        !          1172:     int val;
        !          1173:     
        !          1174:     if (CHECK_HANDLE(handle))
        !          1175:        return CS_BAD_HANDLE;
        !          1176:     s = SOCKET(handle);
        !          1177:     s->ss_entry(s->sock, SS_GetStatus, &val);
        !          1178:     status->CardState = status->SocketState = 0;
        !          1179:     status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
        !          1180:     status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
        !          1181:     status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
        !          1182:     status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
        !          1183:     if (s->state & SOCKET_SUSPEND)
        !          1184:        status->CardState |= CS_EVENT_PM_SUSPEND;
        !          1185:     if (!(s->state & SOCKET_PRESENT))
        !          1186:        return CS_NO_CARD;
        !          1187:     if (s->state & SOCKET_SETUP_PENDING)
        !          1188:        status->CardState |= CS_EVENT_CARD_INSERTION;
        !          1189:     
        !          1190:     /* Get info from the PRR, if necessary */
        !          1191:     if (handle->Function == BIND_FN_ALL) {
        !          1192:        if (status->Function && (status->Function >= s->functions))
        !          1193:            return CS_BAD_ARGS;
        !          1194:        c = (s->config != NULL) ? &s->config[status->Function] : NULL;
        !          1195:     } else
        !          1196:        c = CONFIG(handle);
        !          1197:     if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
        !          1198:        (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
        !          1199:        u_char reg;
        !          1200:        if (c->Present & PRESENT_PIN_REPLACE) {
        !          1201:            read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
        !          1202:            status->CardState |=
        !          1203:                (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
        !          1204:            status->CardState |=
        !          1205:                (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
        !          1206:            status->CardState |=
        !          1207:                (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
        !          1208:            status->CardState |=
        !          1209:                (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
        !          1210:        } else {
        !          1211:            /* No PRR?  Then assume we're always ready */
        !          1212:            status->CardState |= CS_EVENT_READY_CHANGE;
        !          1213:        }
        !          1214:        if (c->Present & PRESENT_EXT_STATUS) {
        !          1215:            read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
        !          1216:            status->CardState |=
        !          1217:                (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
        !          1218:        }
        !          1219:        return CS_SUCCESS;
        !          1220:     }
        !          1221:     status->CardState |=
        !          1222:        (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
        !          1223:     status->CardState |=
        !          1224:        (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
        !          1225:     status->CardState |=
        !          1226:        (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
        !          1227:     status->CardState |=
        !          1228:        (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
        !          1229:     return CS_SUCCESS;
        !          1230: } /* cs_get_status */
        !          1231: 
        !          1232: /*======================================================================
        !          1233: 
        !          1234:     Change the card address of an already open memory window.
        !          1235:     
        !          1236: ======================================================================*/
        !          1237: 
        !          1238: static int get_mem_page(window_handle_t win, memreq_t *req)
        !          1239: {
        !          1240:     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
        !          1241:        return CS_BAD_HANDLE;
        !          1242:     req->Page = 0;
        !          1243:     req->CardOffset = win->ctl.card_start;
        !          1244:     return CS_SUCCESS;
        !          1245: } /* get_mem_page */
        !          1246: 
        !          1247: static int map_mem_page(window_handle_t win, memreq_t *req)
        !          1248: {
        !          1249:     socket_info_t *s;
        !          1250:     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
        !          1251:        return CS_BAD_HANDLE;
        !          1252:     if (req->Page != 0)
        !          1253:        return CS_BAD_PAGE;
        !          1254:     s = win->sock;
        !          1255:     win->ctl.card_start = req->CardOffset;
        !          1256:     if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0)
        !          1257:        return CS_BAD_OFFSET;
        !          1258:     return CS_SUCCESS;
        !          1259: } /* map_mem_page */
        !          1260: 
        !          1261: /*======================================================================
        !          1262: 
        !          1263:     Modify a locked socket configuration
        !          1264:     
        !          1265: ======================================================================*/
        !          1266: 
        !          1267: static int modify_configuration(client_handle_t handle,
        !          1268:                                modconf_t *mod)
        !          1269: {
        !          1270:     socket_info_t *s;
        !          1271:     config_t *c;
        !          1272:     
        !          1273:     if (CHECK_HANDLE(handle))
        !          1274:        return CS_BAD_HANDLE;
        !          1275:     s = SOCKET(handle); c = CONFIG(handle);
        !          1276:     if (!(s->state & SOCKET_PRESENT))
        !          1277:        return CS_NO_CARD;
        !          1278:     if (!(c->state & CONFIG_LOCKED))
        !          1279:        return CS_CONFIGURATION_LOCKED;
        !          1280:     
        !          1281:     if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
        !          1282:        if (mod->Attributes & CONF_ENABLE_IRQ) {
        !          1283:            c->Attributes |= CONF_ENABLE_IRQ;
        !          1284:            s->socket.io_irq = s->irq.AssignedIRQ;
        !          1285:        } else {
        !          1286:            c->Attributes &= ~CONF_ENABLE_IRQ;
        !          1287:            s->socket.io_irq = 0;
        !          1288:        }
        !          1289:        s->ss_entry(s->sock, SS_SetSocket, &s->socket);
        !          1290:     }
        !          1291: 
        !          1292:     if (mod->Attributes & CONF_VCC_CHANGE_VALID)
        !          1293:        return CS_BAD_VCC;
        !          1294: 
        !          1295:     /* We only allow changing Vpp1 and Vpp2 to the same value */
        !          1296:     if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
        !          1297:        (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
        !          1298:        if (mod->Vpp1 != mod->Vpp2)
        !          1299:            return CS_BAD_VPP;
        !          1300:        c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
        !          1301:        if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
        !          1302:            return CS_BAD_VPP;
        !          1303:     } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
        !          1304:               (mod->Attributes & CONF_VPP2_CHANGE_VALID))
        !          1305:        return CS_BAD_VPP;
        !          1306: 
        !          1307:     return CS_SUCCESS;
        !          1308: } /* modify_configuration */
        !          1309: 
        !          1310: /*======================================================================
        !          1311: 
        !          1312:     Modify the attributes of a window returned by RequestWindow.
        !          1313: 
        !          1314: ======================================================================*/
        !          1315: 
        !          1316: static int modify_window(window_handle_t win, modwin_t *req)
        !          1317: {
        !          1318:     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
        !          1319:        return CS_BAD_HANDLE;
        !          1320: 
        !          1321:     win->ctl.flags &= ~(MAP_ATTRIB|MAP_ACTIVE);
        !          1322:     if (req->Attributes & WIN_MEMORY_TYPE)
        !          1323:        win->ctl.flags |= MAP_ATTRIB;
        !          1324:     if (req->Attributes & WIN_ENABLE)
        !          1325:        win->ctl.flags |= MAP_ACTIVE;
        !          1326:     if (req->Attributes & WIN_DATA_WIDTH_16)
        !          1327:        win->ctl.flags |= MAP_16BIT;
        !          1328:     if (req->Attributes & WIN_USE_WAIT)
        !          1329:        win->ctl.flags |= MAP_USE_WAIT;
        !          1330:     win->ctl.speed = req->AccessSpeed;
        !          1331:     win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl);
        !          1332:     
        !          1333:     return CS_SUCCESS;
        !          1334: } /* modify_window */
        !          1335: 
        !          1336: /*======================================================================
        !          1337: 
        !          1338:     Register_client() uses the dev_info_t handle to match the
        !          1339:     caller with a socket.  The driver must have already been bound
        !          1340:     to a socket with bind_device() -- in fact, bind_device()
        !          1341:     allocates the client structure that will be used.
        !          1342:     
        !          1343: ======================================================================*/
        !          1344: 
        !          1345: static int register_client(client_handle_t *handle, client_reg_t *req)
        !          1346: {
        !          1347:     client_t *client;
        !          1348:     socket_info_t *s;
        !          1349:     socket_t ns;
        !          1350:     
        !          1351:     /* Look for unbound client with matching dev_info */
        !          1352:     client = NULL;
        !          1353:     for (ns = 0; ns < sockets; ns++) {
        !          1354:        client = socket_table[ns]->clients;
        !          1355:        while (client != NULL) {
        !          1356:            if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
        !          1357:                && (client->state & CLIENT_UNBOUND)) break;
        !          1358:            client = client->next;
        !          1359:        }
        !          1360:        if (client != NULL) break;
        !          1361:     }
        !          1362:     if (client == NULL)
        !          1363:        return CS_OUT_OF_RESOURCE;
        !          1364: 
        !          1365:     s = socket_table[ns];
        !          1366:     if (++s->real_clients == 1) {
        !          1367:        ss_callback_t call;
        !          1368:        int status;
        !          1369:        call.handler = &parse_events;
        !          1370:        call.info = s;
        !          1371:        s->ss_entry(ns, SS_RegisterCallback, &call);
        !          1372:        s->ss_entry(ns, SS_GetStatus, &status);
        !          1373:        if ((status & SS_DETECT) &&
        !          1374:            !(s->state & SOCKET_SETUP_PENDING)) {
        !          1375:            s->state |= SOCKET_SETUP_PENDING;
        !          1376:            setup_socket(ns);
        !          1377:        }
        !          1378:     }
        !          1379: 
        !          1380:     *handle = client;
        !          1381:     client->state &= ~CLIENT_UNBOUND;
        !          1382:     client->Socket = ns;
        !          1383:     client->Attributes = req->Attributes;
        !          1384:     client->EventMask = req->EventMask;
        !          1385:     client->event_handler = req->event_handler;
        !          1386:     client->event_callback_args = req->event_callback_args;
        !          1387:     client->event_callback_args.client_handle = client;
        !          1388:     client->event_callback_args.bus = s->cap.bus;
        !          1389: 
        !          1390:     if (s->state & SOCKET_CARDBUS)
        !          1391:        client->state |= CLIENT_CARDBUS;
        !          1392:     
        !          1393:     if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
        !          1394:        (client->Function != BIND_FN_ALL)) {
        !          1395:        cistpl_longlink_mfc_t mfc;
        !          1396:        if (read_tuple(client, CISTPL_LONGLINK_MFC, &mfc)
        !          1397:            == CS_SUCCESS)
        !          1398:            s->functions = mfc.nfn;
        !          1399:        else
        !          1400:            s->functions = 1;
        !          1401:        s->config = kmalloc(sizeof(config_t) * s->functions,
        !          1402:                            GFP_KERNEL);
        !          1403:        memset(s->config, 0, sizeof(config_t) * s->functions);
        !          1404:     }
        !          1405:     
        !          1406:     DEBUG(1, "cs: register_client(): client 0x%p, sock %d, dev %s\n",
        !          1407:          client, client->Socket, client->dev_info);
        !          1408:     if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
        !          1409:        EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
        !          1410:     if ((socket_table[ns]->state & SOCKET_PRESENT) &&
        !          1411:        !(socket_table[ns]->state & SOCKET_SETUP_PENDING)) {
        !          1412:        if (client->EventMask & CS_EVENT_CARD_INSERTION)
        !          1413:            EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
        !          1414:        else
        !          1415:            client->PendingEvents |= CS_EVENT_CARD_INSERTION;
        !          1416:     }
        !          1417:     return CS_SUCCESS;
        !          1418: } /* register_client */
        !          1419: 
        !          1420: /*====================================================================*/
        !          1421: 
        !          1422: static int release_configuration(client_handle_t handle,
        !          1423:                                 config_req_t *req)
        !          1424: {
        !          1425:     socket_info_t *s;
        !          1426:     pccard_io_map io = { 0, 0, 0, 0, 1 };
        !          1427:     int i;
        !          1428:     
        !          1429:     if (CHECK_HANDLE(handle) ||
        !          1430:        !(handle->state & CLIENT_CONFIG_LOCKED))
        !          1431:        return CS_BAD_HANDLE;
        !          1432:     handle->state &= ~CLIENT_CONFIG_LOCKED;
        !          1433:     s = SOCKET(handle);
        !          1434:     
        !          1435: #ifdef CONFIG_CARDBUS
        !          1436:     if (handle->state & CLIENT_CARDBUS) {
        !          1437:        cb_disable(s);
        !          1438:        s->lock_count = 0;
        !          1439:        return CS_SUCCESS;
        !          1440:     }
        !          1441: #endif
        !          1442:     
        !          1443:     if (!(handle->state & CLIENT_STALE)) {
        !          1444:        config_t *c = CONFIG(handle);
        !          1445:        if (--(s->lock_count) == 0) {
        !          1446:            s->socket.flags = SS_OUTPUT_ENA;
        !          1447:            s->socket.Vpp = 0;
        !          1448:            s->socket.io_irq = 0;
        !          1449:            s->ss_entry(s->sock, SS_SetSocket, &s->socket);
        !          1450:        }
        !          1451:        if (c->state & CONFIG_IO_REQ)
        !          1452:            for (i = 0; i < MAX_IO_WIN; i++) {
        !          1453:                if (s->io[i].NumPorts == 0)
        !          1454:                    continue;
        !          1455:                s->io[i].Config--;
        !          1456:                if (s->io[i].Config != 0)
        !          1457:                    continue;
        !          1458:                io.map = i;
        !          1459:                s->ss_entry(s->sock, SS_SetIOMap, &io);
        !          1460:            }
        !          1461:        c->state &= ~CONFIG_LOCKED;
        !          1462:     }
        !          1463:     
        !          1464:     return CS_SUCCESS;
        !          1465: } /* release_configuration */
        !          1466: 
        !          1467: /*======================================================================
        !          1468: 
        !          1469:     Release_io() releases the I/O ranges allocated by a client.  This
        !          1470:     may be invoked some time after a card ejection has already dumped
        !          1471:     the actual socket configuration, so if the client is "stale", we
        !          1472:     don't bother checking the port ranges against the current socket
        !          1473:     values.
        !          1474:     
        !          1475: ======================================================================*/
        !          1476: 
        !          1477: static int release_io(client_handle_t handle, io_req_t *req)
        !          1478: {
        !          1479:     socket_info_t *s;
        !          1480:     
        !          1481:     if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
        !          1482:        return CS_BAD_HANDLE;
        !          1483:     handle->state &= ~CLIENT_IO_REQ;
        !          1484:     s = SOCKET(handle);
        !          1485:     
        !          1486: #ifdef CONFIG_CARDBUS
        !          1487:     if (handle->state & CLIENT_CARDBUS) {
        !          1488:        cb_release(s);
        !          1489:        return CS_SUCCESS;
        !          1490:     }
        !          1491: #endif
        !          1492:     
        !          1493:     if (!(handle->state & CLIENT_STALE)) {
        !          1494:        config_t *c = CONFIG(handle);
        !          1495:        if (c->state & CONFIG_LOCKED)
        !          1496:            return CS_CONFIGURATION_LOCKED;
        !          1497:        if ((c->io.BasePort1 != req->BasePort1) ||
        !          1498:            (c->io.NumPorts1 != req->NumPorts1) ||
        !          1499:            (c->io.BasePort2 != req->BasePort2) ||
        !          1500:            (c->io.NumPorts2 != req->NumPorts2))
        !          1501:            return CS_BAD_ARGS;
        !          1502:        c->state &= ~CONFIG_IO_REQ;
        !          1503:     }
        !          1504: 
        !          1505:     release_io_space(s, req->BasePort1, req->NumPorts1);
        !          1506:     if (req->NumPorts2)
        !          1507:        release_io_space(s, req->BasePort2, req->NumPorts2);
        !          1508:     
        !          1509:     return CS_SUCCESS;
        !          1510: } /* release_io */
        !          1511: 
        !          1512: /*====================================================================*/
        !          1513: 
        !          1514: static int cs_release_irq(client_handle_t handle, irq_req_t *req)
        !          1515: {
        !          1516:     socket_info_t *s;
        !          1517:     if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
        !          1518:        return CS_BAD_HANDLE;
        !          1519:     handle->state &= ~CLIENT_IRQ_REQ;
        !          1520:     s = SOCKET(handle);
        !          1521:     
        !          1522:     if (!(handle->state & CLIENT_STALE)) {
        !          1523:        config_t *c = CONFIG(handle);
        !          1524:        if (c->state & CONFIG_LOCKED)
        !          1525:            return CS_CONFIGURATION_LOCKED;
        !          1526:        if (c->irq.Attributes != req->Attributes)
        !          1527:            return CS_BAD_ATTRIBUTE;
        !          1528:        if (s->irq.AssignedIRQ != req->AssignedIRQ)
        !          1529:            return CS_BAD_IRQ;
        !          1530:        if (--s->irq.Config == 0) {
        !          1531:            c->state &= ~CONFIG_IRQ_REQ;
        !          1532:            s->irq.AssignedIRQ = 0;
        !          1533:        }
        !          1534:     }
        !          1535:     
        !          1536:     if (req->Attributes & IRQ_HANDLE_PRESENT) {
        !          1537:        bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance);
        !          1538:     }
        !          1539: 
        !          1540: #ifdef CONFIG_ISA
        !          1541:     if (req->AssignedIRQ != s->cap.pci_irq)
        !          1542:        undo_irq(req->Attributes, req->AssignedIRQ);
        !          1543: #endif
        !          1544:     
        !          1545:     return CS_SUCCESS;
        !          1546: } /* cs_release_irq */
        !          1547: 
        !          1548: /*====================================================================*/
        !          1549: 
        !          1550: static int release_window(window_handle_t win)
        !          1551: {
        !          1552:     socket_info_t *s;
        !          1553:     
        !          1554:     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
        !          1555:        return CS_BAD_HANDLE;
        !          1556:     s = win->sock;
        !          1557:     if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
        !          1558:        return CS_BAD_HANDLE;
        !          1559: 
        !          1560:     /* Shut down memory window */
        !          1561:     win->ctl.flags &= ~MAP_ACTIVE;
        !          1562:     s->ss_entry(s->sock, SS_SetMemMap, &win->ctl);
        !          1563:     s->state &= ~SOCKET_WIN_REQ(win->index);
        !          1564: 
        !          1565:     /* Release system memory */
        !          1566:     release_mem_region(win->base, win->size);
        !          1567:     win->handle->state &= ~CLIENT_WIN_REQ(win->index);
        !          1568: 
        !          1569:     win->magic = 0;
        !          1570:     
        !          1571:     return CS_SUCCESS;
        !          1572: } /* release_window */
        !          1573: 
        !          1574: /*====================================================================*/
        !          1575: 
        !          1576: static int request_configuration(client_handle_t handle,
        !          1577:                                 config_req_t *req)
        !          1578: {
        !          1579:     int i;
        !          1580:     u_int base;
        !          1581:     socket_info_t *s;
        !          1582:     config_t *c;
        !          1583:     pccard_io_map iomap;
        !          1584:     
        !          1585:     if (CHECK_HANDLE(handle))
        !          1586:        return CS_BAD_HANDLE;
        !          1587:     i = handle->Socket; s = socket_table[i];
        !          1588:     if (!(s->state & SOCKET_PRESENT))
        !          1589:        return CS_NO_CARD;
        !          1590:     
        !          1591: #ifdef CONFIG_CARDBUS
        !          1592:     if (handle->state & CLIENT_CARDBUS) {
        !          1593:        if (!(req->IntType & INT_CARDBUS))
        !          1594:            return CS_UNSUPPORTED_MODE;
        !          1595:        if (s->lock_count != 0)
        !          1596:            return CS_CONFIGURATION_LOCKED;
        !          1597:        cb_enable(s);
        !          1598:        handle->state |= CLIENT_CONFIG_LOCKED;
        !          1599:        s->lock_count++;
        !          1600:        return CS_SUCCESS;
        !          1601:     }
        !          1602: #endif
        !          1603:     
        !          1604:     if (req->IntType & INT_CARDBUS)
        !          1605:        return CS_UNSUPPORTED_MODE;
        !          1606:     c = CONFIG(handle);
        !          1607:     if (c->state & CONFIG_LOCKED)
        !          1608:        return CS_CONFIGURATION_LOCKED;
        !          1609: 
        !          1610:     /* Do power control.  We don't allow changes in Vcc. */
        !          1611:     if (s->socket.Vcc != req->Vcc)
        !          1612:        printk(KERN_DEBUG "cs: ignoring requested Vcc\n");
        !          1613:     if (req->Vpp1 != req->Vpp2)
        !          1614:        return CS_BAD_VPP;
        !          1615:     s->socket.Vpp = req->Vpp1;
        !          1616:     if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
        !          1617:        return CS_BAD_VPP;
        !          1618:     
        !          1619:     c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
        !          1620:     
        !          1621:     /* Pick memory or I/O card, DMA mode, interrupt */
        !          1622:     c->IntType = req->IntType;
        !          1623:     c->Attributes = req->Attributes;
        !          1624:     if (req->IntType & INT_MEMORY_AND_IO)
        !          1625:        s->socket.flags |= SS_IOCARD;
        !          1626:     if (req->IntType & INT_ZOOMED_VIDEO)
        !          1627:        s->socket.flags |= SS_ZVCARD;
        !          1628:     if (req->Attributes & CONF_ENABLE_DMA)
        !          1629:        s->socket.flags |= SS_DMA_MODE;
        !          1630:     if (req->Attributes & CONF_ENABLE_SPKR)
        !          1631:        s->socket.flags |= SS_SPKR_ENA;
        !          1632:     if (req->Attributes & CONF_ENABLE_IRQ)
        !          1633:        s->socket.io_irq = s->irq.AssignedIRQ;
        !          1634:     else
        !          1635:        s->socket.io_irq = 0;
        !          1636:     s->ss_entry(s->sock, SS_SetSocket, &s->socket);
        !          1637:     s->lock_count++;
        !          1638:     
        !          1639:     /* Set up CIS configuration registers */
        !          1640:     base = c->ConfigBase = req->ConfigBase;
        !          1641:     c->Present = c->CardValues = req->Present;
        !          1642:     if (req->Present & PRESENT_COPY) {
        !          1643:        c->Copy = req->Copy;
        !          1644:        write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
        !          1645:     }
        !          1646:     if (req->Present & PRESENT_OPTION) {
        !          1647:        if (s->functions == 1) {
        !          1648:            c->Option = req->ConfigIndex & COR_CONFIG_MASK;
        !          1649:        } else {
        !          1650:            c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
        !          1651:            c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
        !          1652:            if (req->Present & PRESENT_IOBASE_0)
        !          1653:                c->Option |= COR_ADDR_DECODE;
        !          1654:        }
        !          1655:        if (c->state & CONFIG_IRQ_REQ)
        !          1656:            if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
        !          1657:                c->Option |= COR_LEVEL_REQ;
        !          1658:        write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
        !          1659:        mdelay(40);
        !          1660:     }
        !          1661:     if (req->Present & PRESENT_STATUS) {
        !          1662:        c->Status = req->Status;
        !          1663:        write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
        !          1664:     }
        !          1665:     if (req->Present & PRESENT_PIN_REPLACE) {
        !          1666:        c->Pin = req->Pin;
        !          1667:        write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
        !          1668:     }
        !          1669:     if (req->Present & PRESENT_EXT_STATUS) {
        !          1670:        c->ExtStatus = req->ExtStatus;
        !          1671:        write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
        !          1672:     }
        !          1673:     if (req->Present & PRESENT_IOBASE_0) {
        !          1674:        u_char b = c->io.BasePort1 & 0xff;
        !          1675:        write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
        !          1676:        b = (c->io.BasePort1 >> 8) & 0xff;
        !          1677:        write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
        !          1678:     }
        !          1679:     if (req->Present & PRESENT_IOSIZE) {
        !          1680:        u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
        !          1681:        write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
        !          1682:     }
        !          1683:     
        !          1684:     /* Configure I/O windows */
        !          1685:     if (c->state & CONFIG_IO_REQ) {
        !          1686:        iomap.speed = io_speed;
        !          1687:        for (i = 0; i < MAX_IO_WIN; i++)
        !          1688:            if (s->io[i].NumPorts != 0) {
        !          1689:                iomap.map = i;
        !          1690:                iomap.flags = MAP_ACTIVE;
        !          1691:                switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
        !          1692:                case IO_DATA_PATH_WIDTH_16:
        !          1693:                    iomap.flags |= MAP_16BIT; break;
        !          1694:                case IO_DATA_PATH_WIDTH_AUTO:
        !          1695:                    iomap.flags |= MAP_AUTOSZ; break;
        !          1696:                default:
        !          1697:                    break;
        !          1698:                }
        !          1699:                iomap.start = s->io[i].BasePort;
        !          1700:                iomap.stop = iomap.start + s->io[i].NumPorts - 1;
        !          1701:                s->ss_entry(s->sock, SS_SetIOMap, &iomap);
        !          1702:                s->io[i].Config++;
        !          1703:            }
        !          1704:     }
        !          1705:     
        !          1706:     c->state |= CONFIG_LOCKED;
        !          1707:     handle->state |= CLIENT_CONFIG_LOCKED;
        !          1708:     return CS_SUCCESS;
        !          1709: } /* request_configuration */
        !          1710: 
        !          1711: /*======================================================================
        !          1712:   
        !          1713:     Request_io() reserves ranges of port addresses for a socket.
        !          1714:     I have not implemented range sharing or alias addressing.
        !          1715:     
        !          1716: ======================================================================*/
        !          1717: 
        !          1718: static int request_io(client_handle_t handle, io_req_t *req)
        !          1719: {
        !          1720:     socket_info_t *s;
        !          1721:     config_t *c;
        !          1722:     
        !          1723:     if (CHECK_HANDLE(handle))
        !          1724:        return CS_BAD_HANDLE;
        !          1725:     s = SOCKET(handle);
        !          1726:     if (!(s->state & SOCKET_PRESENT))
        !          1727:        return CS_NO_CARD;
        !          1728: 
        !          1729:     if (handle->state & CLIENT_CARDBUS) {
        !          1730: #ifdef CONFIG_CARDBUS
        !          1731:        int ret = cb_config(s);
        !          1732:        if (ret == CS_SUCCESS)
        !          1733:            handle->state |= CLIENT_IO_REQ;
        !          1734:        return ret;
        !          1735: #else
        !          1736:        return CS_UNSUPPORTED_FUNCTION;
        !          1737: #endif
        !          1738:     }
        !          1739: 
        !          1740:     if (!req)
        !          1741:        return CS_UNSUPPORTED_MODE;
        !          1742:     c = CONFIG(handle);
        !          1743:     if (c->state & CONFIG_LOCKED)
        !          1744:        return CS_CONFIGURATION_LOCKED;
        !          1745:     if (c->state & CONFIG_IO_REQ)
        !          1746:        return CS_IN_USE;
        !          1747:     if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))
        !          1748:        return CS_BAD_ATTRIBUTE;
        !          1749:     if ((req->NumPorts2 > 0) &&
        !          1750:        (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)))
        !          1751:        return CS_BAD_ATTRIBUTE;
        !          1752: 
        !          1753:     if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
        !          1754:                       req->NumPorts1, req->IOAddrLines,
        !          1755:                       handle->dev_info))
        !          1756:        return CS_IN_USE;
        !          1757: 
        !          1758:     if (req->NumPorts2) {
        !          1759:        if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
        !          1760:                           req->NumPorts2, req->IOAddrLines,
        !          1761:                           handle->dev_info)) {
        !          1762:            release_io_space(s, req->BasePort1, req->NumPorts1);
        !          1763:            return CS_IN_USE;
        !          1764:        }
        !          1765:     }
        !          1766: 
        !          1767:     c->io = *req;
        !          1768:     c->state |= CONFIG_IO_REQ;
        !          1769:     handle->state |= CLIENT_IO_REQ;
        !          1770:     return CS_SUCCESS;
        !          1771: } /* request_io */
        !          1772: 
        !          1773: /*======================================================================
        !          1774: 
        !          1775:     Request_irq() reserves an irq for this client.
        !          1776: 
        !          1777:     Also, since Linux only reserves irq's when they are actually
        !          1778:     hooked, we don't guarantee that an irq will still be available
        !          1779:     when the configuration is locked.  Now that I think about it,
        !          1780:     there might be a way to fix this using a dummy handler.
        !          1781:     
        !          1782: ======================================================================*/
        !          1783: 
        !          1784: static int cs_request_irq(client_handle_t handle, irq_req_t *req)
        !          1785: {
        !          1786:     socket_info_t *s;
        !          1787:     config_t *c;
        !          1788:     int ret = CS_IN_USE, irq = 0;
        !          1789:     
        !          1790:     if (CHECK_HANDLE(handle))
        !          1791:        return CS_BAD_HANDLE;
        !          1792:     s = SOCKET(handle);
        !          1793:     if (!(s->state & SOCKET_PRESENT))
        !          1794:        return CS_NO_CARD;
        !          1795:     c = CONFIG(handle);
        !          1796:     if (c->state & CONFIG_LOCKED)
        !          1797:        return CS_CONFIGURATION_LOCKED;
        !          1798:     if (c->state & CONFIG_IRQ_REQ)
        !          1799:        return CS_IN_USE;
        !          1800:     
        !          1801: #ifdef CONFIG_ISA
        !          1802:     if (s->irq.AssignedIRQ != 0) {
        !          1803:        /* If the interrupt is already assigned, it must match */
        !          1804:        irq = s->irq.AssignedIRQ;
        !          1805:        if (req->IRQInfo1 & IRQ_INFO2_VALID) {
        !          1806:            u_int mask = req->IRQInfo2 & s->cap.irq_mask;
        !          1807:            ret = ((mask >> irq) & 1) ? 0 : CS_BAD_ARGS;
        !          1808:        } else
        !          1809:            ret = ((req->IRQInfo1&IRQ_MASK) == irq) ? 0 : CS_BAD_ARGS;
        !          1810:     } else {
        !          1811:        if (req->IRQInfo1 & IRQ_INFO2_VALID) {
        !          1812:            u_int try, mask = req->IRQInfo2 & s->cap.irq_mask;
        !          1813:            for (try = 0; try < 2; try++) {
        !          1814:                for (irq = 0; irq < 16; irq++)
        !          1815:                    if ((mask >> irq) & 1) {
        !          1816:                        ret = try_irq(req->Attributes, irq, try);
        !          1817:                        if (ret == 0) break;
        !          1818:                    }
        !          1819:                if (ret == 0) break;
        !          1820:            }
        !          1821:        } else {
        !          1822:            irq = req->IRQInfo1 & IRQ_MASK;
        !          1823:            ret = try_irq(req->Attributes, irq, 1);
        !          1824:        }
        !          1825:     }
        !          1826: #endif
        !          1827:     if (ret != 0) {
        !          1828:        if (!s->cap.pci_irq)
        !          1829:            return ret;
        !          1830:        irq = s->cap.pci_irq;
        !          1831:     }
        !          1832: 
        !          1833:     if (req->Attributes & IRQ_HANDLE_PRESENT) {
        !          1834:        if (bus_request_irq(s->cap.bus, irq, req->Handler,
        !          1835:                            ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || 
        !          1836:                             (s->functions > 1) ||
        !          1837:                             (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0,
        !          1838:                            handle->dev_info, req->Instance))
        !          1839:            return CS_IN_USE;
        !          1840:     }
        !          1841: 
        !          1842:     c->irq.Attributes = req->Attributes;
        !          1843:     s->irq.AssignedIRQ = req->AssignedIRQ = irq;
        !          1844:     s->irq.Config++;
        !          1845:     
        !          1846:     c->state |= CONFIG_IRQ_REQ;
        !          1847:     handle->state |= CLIENT_IRQ_REQ;
        !          1848:     return CS_SUCCESS;
        !          1849: } /* cs_request_irq */
        !          1850: 
        !          1851: /*======================================================================
        !          1852: 
        !          1853:     Request_window() establishes a mapping between card memory space
        !          1854:     and system memory space.
        !          1855: 
        !          1856: ======================================================================*/
        !          1857: 
        !          1858: static int request_window(client_handle_t *handle, win_req_t *req)
        !          1859: {
        !          1860:     socket_info_t *s;
        !          1861:     window_t *win;
        !          1862:     u_long align;
        !          1863:     int w;
        !          1864:     
        !          1865:     if (CHECK_HANDLE(*handle))
        !          1866:        return CS_BAD_HANDLE;
        !          1867:     s = SOCKET(*handle);
        !          1868:     if (!(s->state & SOCKET_PRESENT))
        !          1869:        return CS_NO_CARD;
        !          1870:     if (req->Attributes & (WIN_PAGED | WIN_SHARED))
        !          1871:        return CS_BAD_ATTRIBUTE;
        !          1872: 
        !          1873:     /* Window size defaults to smallest available */
        !          1874:     if (req->Size == 0)
        !          1875:        req->Size = s->cap.map_size;
        !          1876:     align = (((s->cap.features & SS_CAP_MEM_ALIGN) ||
        !          1877:              (req->Attributes & WIN_STRICT_ALIGN)) ?
        !          1878:             req->Size : s->cap.map_size);
        !          1879:     if (req->Size & (s->cap.map_size-1))
        !          1880:        return CS_BAD_SIZE;
        !          1881:     if ((req->Base && (s->cap.features & SS_CAP_STATIC_MAP)) ||
        !          1882:        (req->Base & (align-1)))
        !          1883:        return CS_BAD_BASE;
        !          1884:     if (req->Base)
        !          1885:        align = 0;
        !          1886: 
        !          1887:     /* Allocate system memory window */
        !          1888:     for (w = 0; w < MAX_WIN; w++)
        !          1889:        if (!(s->state & SOCKET_WIN_REQ(w))) break;
        !          1890:     if (w == MAX_WIN)
        !          1891:        return CS_OUT_OF_RESOURCE;
        !          1892: 
        !          1893:     win = &s->win[w];
        !          1894:     win->magic = WINDOW_MAGIC;
        !          1895:     win->index = w;
        !          1896:     win->handle = *handle;
        !          1897:     win->sock = s;
        !          1898:     win->base = req->Base;
        !          1899:     win->size = req->Size;
        !          1900: 
        !          1901:     if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
        !          1902:        find_mem_region(&win->base, win->size, align,
        !          1903:                        (req->Attributes & WIN_MAP_BELOW_1MB) ||
        !          1904:                        !(s->cap.features & SS_CAP_PAGE_REGS),
        !          1905:                        (*handle)->dev_info))
        !          1906:        return CS_IN_USE;
        !          1907:     (*handle)->state |= CLIENT_WIN_REQ(w);
        !          1908: 
        !          1909:     /* Configure the socket controller */
        !          1910:     win->ctl.map = w+1;
        !          1911:     win->ctl.flags = 0;
        !          1912:     win->ctl.speed = req->AccessSpeed;
        !          1913:     if (req->Attributes & WIN_MEMORY_TYPE)
        !          1914:        win->ctl.flags |= MAP_ATTRIB;
        !          1915:     if (req->Attributes & WIN_ENABLE)
        !          1916:        win->ctl.flags |= MAP_ACTIVE;
        !          1917:     if (req->Attributes & WIN_DATA_WIDTH_16)
        !          1918:        win->ctl.flags |= MAP_16BIT;
        !          1919:     if (req->Attributes & WIN_USE_WAIT)
        !          1920:        win->ctl.flags |= MAP_USE_WAIT;
        !          1921:     win->ctl.sys_start = win->base;
        !          1922:     win->ctl.sys_stop = win->base + win->size-1;
        !          1923:     win->ctl.card_start = 0;
        !          1924:     if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0)
        !          1925:        return CS_BAD_ARGS;
        !          1926:     s->state |= SOCKET_WIN_REQ(w);
        !          1927: 
        !          1928:     /* Return window handle */
        !          1929:     req->Base = win->ctl.sys_start;
        !          1930:     *handle = (client_handle_t)win;
        !          1931:     
        !          1932:     return CS_SUCCESS;
        !          1933: } /* request_window */
        !          1934: 
        !          1935: /*======================================================================
        !          1936: 
        !          1937:     I'm not sure which "reset" function this is supposed to use,
        !          1938:     but for now, it uses the low-level interface's reset, not the
        !          1939:     CIS register.
        !          1940:     
        !          1941: ======================================================================*/
        !          1942: 
        !          1943: static int reset_card(client_handle_t handle, client_req_t *req)
        !          1944: {
        !          1945:     int i, ret;
        !          1946:     socket_info_t *s;
        !          1947:     
        !          1948:     if (CHECK_HANDLE(handle))
        !          1949:        return CS_BAD_HANDLE;
        !          1950:     i = handle->Socket; s = socket_table[i];
        !          1951:     if (!(s->state & SOCKET_PRESENT))
        !          1952:        return CS_NO_CARD;
        !          1953:     if (s->state & SOCKET_RESET_PENDING)
        !          1954:        return CS_IN_USE;
        !          1955:     s->state |= SOCKET_RESET_PENDING;
        !          1956: 
        !          1957:     ret = send_event(s, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
        !          1958:     if (ret != 0) {
        !          1959:        s->state &= ~SOCKET_RESET_PENDING;
        !          1960:        handle->event_callback_args.info = (void *)(u_long)ret;
        !          1961:        EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW);
        !          1962:     } else {
        !          1963:        DEBUG(1, "cs: resetting socket %d\n", i);
        !          1964:        send_event(s, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
        !          1965:        s->reset_handle = handle;
        !          1966:        reset_socket(i);
        !          1967:     }
        !          1968:     return CS_SUCCESS;
        !          1969: } /* reset_card */
        !          1970: 
        !          1971: /*======================================================================
        !          1972: 
        !          1973:     These shut down or wake up a socket.  They are sort of user
        !          1974:     initiated versions of the APM suspend and resume actions.
        !          1975:     
        !          1976: ======================================================================*/
        !          1977: 
        !          1978: static int suspend_card(client_handle_t handle, client_req_t *req)
        !          1979: {
        !          1980:     int i;
        !          1981:     socket_info_t *s;
        !          1982:     
        !          1983:     if (CHECK_HANDLE(handle))
        !          1984:        return CS_BAD_HANDLE;
        !          1985:     i = handle->Socket; s = socket_table[i];
        !          1986:     if (!(s->state & SOCKET_PRESENT))
        !          1987:        return CS_NO_CARD;
        !          1988:     if (s->state & SOCKET_SUSPEND)
        !          1989:        return CS_IN_USE;
        !          1990: 
        !          1991:     DEBUG(1, "cs: suspending socket %d\n", i);
        !          1992:     send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
        !          1993:     s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
        !          1994:     s->state |= SOCKET_SUSPEND;
        !          1995: 
        !          1996:     return CS_SUCCESS;
        !          1997: } /* suspend_card */
        !          1998: 
        !          1999: static int resume_card(client_handle_t handle, client_req_t *req)
        !          2000: {
        !          2001:     int i;
        !          2002:     socket_info_t *s;
        !          2003:     
        !          2004:     if (CHECK_HANDLE(handle))
        !          2005:        return CS_BAD_HANDLE;
        !          2006:     i = handle->Socket; s = socket_table[i];
        !          2007:     if (!(s->state & SOCKET_PRESENT))
        !          2008:        return CS_NO_CARD;
        !          2009:     if (!(s->state & SOCKET_SUSPEND))
        !          2010:        return CS_IN_USE;
        !          2011: 
        !          2012:     DEBUG(1, "cs: waking up socket %d\n", i);
        !          2013:     setup_socket(i);
        !          2014: 
        !          2015:     return CS_SUCCESS;
        !          2016: } /* resume_card */
        !          2017: 
        !          2018: /*======================================================================
        !          2019: 
        !          2020:     These handle user requests to eject or insert a card.
        !          2021:     
        !          2022: ======================================================================*/
        !          2023: 
        !          2024: static int eject_card(client_handle_t handle, client_req_t *req)
        !          2025: {
        !          2026:     int i, ret;
        !          2027:     socket_info_t *s;
        !          2028:     u_long flags;
        !          2029:     
        !          2030:     if (CHECK_HANDLE(handle))
        !          2031:        return CS_BAD_HANDLE;
        !          2032:     i = handle->Socket; s = socket_table[i];
        !          2033:     if (!(s->state & SOCKET_PRESENT))
        !          2034:        return CS_NO_CARD;
        !          2035: 
        !          2036:     DEBUG(1, "cs: user eject request on socket %d\n", i);
        !          2037: 
        !          2038:     ret = send_event(s, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
        !          2039:     if (ret != 0)
        !          2040:        return ret;
        !          2041: 
        !          2042:     spin_lock_irqsave(&s->lock, flags);
        !          2043:     do_shutdown(s);
        !          2044:     spin_unlock_irqrestore(&s->lock, flags);
        !          2045:     
        !          2046:     return CS_SUCCESS;
        !          2047:     
        !          2048: } /* eject_card */
        !          2049: 
        !          2050: static int insert_card(client_handle_t handle, client_req_t *req)
        !          2051: {
        !          2052:     int i, status;
        !          2053:     socket_info_t *s;
        !          2054:     u_long flags;
        !          2055:     
        !          2056:     if (CHECK_HANDLE(handle))
        !          2057:        return CS_BAD_HANDLE;
        !          2058:     i = handle->Socket; s = socket_table[i];
        !          2059:     if (s->state & SOCKET_PRESENT)
        !          2060:        return CS_IN_USE;
        !          2061: 
        !          2062:     DEBUG(1, "cs: user insert request on socket %d\n", i);
        !          2063: 
        !          2064:     spin_lock_irqsave(&s->lock, flags);
        !          2065:     if (!(s->state & SOCKET_SETUP_PENDING)) {
        !          2066:        s->state |= SOCKET_SETUP_PENDING;
        !          2067:        spin_unlock_irqrestore(&s->lock, flags);
        !          2068:        s->ss_entry(i, SS_GetStatus, &status);
        !          2069:        if (status & SS_DETECT)
        !          2070:            setup_socket(i);
        !          2071:        else {
        !          2072:            s->state &= ~SOCKET_SETUP_PENDING;
        !          2073:            return CS_NO_CARD;
        !          2074:        }
        !          2075:     } else
        !          2076:        spin_unlock_irqrestore(&s->lock, flags);
        !          2077: 
        !          2078:     return CS_SUCCESS;
        !          2079: } /* insert_card */
        !          2080: 
        !          2081: /*======================================================================
        !          2082: 
        !          2083:     Maybe this should send a CS_EVENT_CARD_INSERTION event if we
        !          2084:     haven't sent one to this client yet?
        !          2085:     
        !          2086: ======================================================================*/
        !          2087: 
        !          2088: static int set_event_mask(client_handle_t handle, eventmask_t *mask)
        !          2089: {
        !          2090:     u_int events, bit;
        !          2091:     if (CHECK_HANDLE(handle))
        !          2092:        return CS_BAD_HANDLE;
        !          2093:     if (handle->Attributes & CONF_EVENT_MASK_VALID)
        !          2094:        return CS_BAD_SOCKET;
        !          2095:     handle->EventMask = mask->EventMask;
        !          2096:     events = handle->PendingEvents & handle->EventMask;
        !          2097:     handle->PendingEvents -= events;
        !          2098:     while (events != 0) {
        !          2099:        bit = ((events ^ (events-1)) + 1) >> 1;
        !          2100:        EVENT(handle, bit, CS_EVENT_PRI_LOW);
        !          2101:        events -= bit;
        !          2102:     }
        !          2103:     return CS_SUCCESS;
        !          2104: } /* set_event_mask */
        !          2105: 
        !          2106: /*====================================================================*/
        !          2107: 
        !          2108: static int report_error(client_handle_t handle, error_info_t *err)
        !          2109: {
        !          2110:     int i;
        !          2111:     char *serv;
        !          2112: 
        !          2113:     if (CHECK_HANDLE(handle))
        !          2114:        printk(KERN_NOTICE);
        !          2115:     else
        !          2116:        printk(KERN_NOTICE "%s: ", handle->dev_info);
        !          2117:     
        !          2118:     for (i = 0; i < SERVICE_COUNT; i++)
        !          2119:        if (service_table[i].key == err->func) break;
        !          2120:     if (i < SERVICE_COUNT)
        !          2121:        serv = service_table[i].msg;
        !          2122:     else
        !          2123:        serv = "Unknown service number";
        !          2124: 
        !          2125:     for (i = 0; i < ERROR_COUNT; i++)
        !          2126:        if (error_table[i].key == err->retcode) break;
        !          2127:     if (i < ERROR_COUNT)
        !          2128:        printk("%s: %s\n", serv, error_table[i].msg);
        !          2129:     else
        !          2130:        printk("%s: Unknown error code %#x\n", serv, err->retcode);
        !          2131: 
        !          2132:     return CS_SUCCESS;
        !          2133: } /* report_error */
        !          2134: 
        !          2135: /*====================================================================*/
        !          2136: 
        !          2137: int CardServices(int func, void *a1, void *a2, void *a3)
        !          2138: {
        !          2139: 
        !          2140: #ifdef PCMCIA_DEBUG
        !          2141:     if (pc_debug > 2) {
        !          2142:        int i;
        !          2143:        for (i = 0; i < SERVICE_COUNT; i++)
        !          2144:            if (service_table[i].key == func) break;
        !          2145:        if (i < SERVICE_COUNT)
        !          2146:            printk(KERN_DEBUG "cs: CardServices(%s, 0x%p, 0x%p)\n",
        !          2147:                   service_table[i].msg, a1, a2);
        !          2148:        else
        !          2149:            printk(KERN_DEBUG "cs: CardServices(Unknown func %d, "
        !          2150:                   "0x%p, 0x%p)\n", func, a1, a2);
        !          2151:     }
        !          2152: #endif
        !          2153:     switch (func) {
        !          2154:     case AccessConfigurationRegister:
        !          2155:        return access_configuration_register(a1, a2); break;
        !          2156:     case AdjustResourceInfo:
        !          2157:        return adjust_resource_info(a1, a2); break;
        !          2158:     case CheckEraseQueue:
        !          2159:        return check_erase_queue(a1); break;
        !          2160:     case CloseMemory:
        !          2161:        return close_memory(a1); break;
        !          2162:     case CopyMemory:
        !          2163:        return copy_memory(a1, a2); break;
        !          2164:     case DeregisterClient:
        !          2165:        return deregister_client(a1); break;
        !          2166:     case DeregisterEraseQueue:
        !          2167:        return deregister_erase_queue(a1); break;
        !          2168:     case GetFirstClient:
        !          2169:        return get_first_client(a1, a2); break;
        !          2170:     case GetCardServicesInfo:
        !          2171:        return get_card_services_info(a1); break;
        !          2172:     case GetConfigurationInfo:
        !          2173:        return get_configuration_info(a1, a2); break;
        !          2174:     case GetNextClient:
        !          2175:        return get_next_client(a1, a2); break;
        !          2176:     case GetFirstRegion:
        !          2177:        return get_first_region(a1, a2); break;
        !          2178:     case GetFirstTuple:
        !          2179:        return get_first_tuple(a1, a2); break;
        !          2180:     case GetNextRegion:
        !          2181:        return get_next_region(a1, a2); break;
        !          2182:     case GetNextTuple:
        !          2183:        return get_next_tuple(a1, a2); break;
        !          2184:     case GetStatus:
        !          2185:        return cs_get_status(a1, a2); break;
        !          2186:     case GetTupleData:
        !          2187:        return get_tuple_data(a1, a2); break;
        !          2188:     case MapMemPage:
        !          2189:        return map_mem_page(a1, a2); break;
        !          2190:     case ModifyConfiguration:
        !          2191:        return modify_configuration(a1, a2); break;
        !          2192:     case ModifyWindow:
        !          2193:        return modify_window(a1, a2); break;
        !          2194:     case OpenMemory:
        !          2195:        return open_memory(a1, a2);
        !          2196:     case ParseTuple:
        !          2197:        return parse_tuple(a1, a2, a3); break;
        !          2198:     case ReadMemory:
        !          2199:        return read_memory(a1, a2, a3); break;
        !          2200:     case RegisterClient:
        !          2201:        return register_client(a1, a2); break;
        !          2202:     case RegisterEraseQueue:
        !          2203:        return register_erase_queue(a1, a2); break;
        !          2204:     case RegisterMTD:
        !          2205:        return register_mtd(a1, a2); break;
        !          2206:     case ReleaseConfiguration:
        !          2207:        return release_configuration(a1, a2); break;
        !          2208:     case ReleaseIO:
        !          2209:        return release_io(a1, a2); break;
        !          2210:     case ReleaseIRQ:
        !          2211:        return cs_release_irq(a1, a2); break;
        !          2212:     case ReleaseWindow:
        !          2213:        return release_window(a1); break;
        !          2214:     case RequestConfiguration:
        !          2215:        return request_configuration(a1, a2); break;
        !          2216:     case RequestIO:
        !          2217:        return request_io(a1, a2); break;
        !          2218:     case RequestIRQ:
        !          2219:        return cs_request_irq(a1, a2); break;
        !          2220:     case RequestWindow:
        !          2221:        return request_window(a1, a2); break;
        !          2222:     case ResetCard:
        !          2223:        return reset_card(a1, a2); break;
        !          2224:     case SetEventMask:
        !          2225:        return set_event_mask(a1, a2); break;
        !          2226:     case ValidateCIS:
        !          2227:        return validate_cis(a1, a2); break;
        !          2228:     case WriteMemory:
        !          2229:        return write_memory(a1, a2, a3); break;
        !          2230:     case BindDevice:
        !          2231:        return bind_device(a1); break;
        !          2232:     case BindMTD:
        !          2233:        return bind_mtd(a1); break;
        !          2234:     case ReportError:
        !          2235:        return report_error(a1, a2); break;
        !          2236:     case SuspendCard:
        !          2237:        return suspend_card(a1, a2); break;
        !          2238:     case ResumeCard:
        !          2239:        return resume_card(a1, a2); break;
        !          2240:     case EjectCard:
        !          2241:        return eject_card(a1, a2); break;
        !          2242:     case InsertCard:
        !          2243:        return insert_card(a1, a2); break;
        !          2244:     case ReplaceCIS:
        !          2245:        return replace_cis(a1, a2); break;
        !          2246:     case GetFirstWindow:
        !          2247:        return get_first_window(a1, a2); break;
        !          2248:     case GetNextWindow:
        !          2249:        return get_next_window(a1, a2); break;
        !          2250:     case GetMemPage:
        !          2251:        return get_mem_page(a1, a2); break;
        !          2252:     default:
        !          2253:        return CS_UNSUPPORTED_FUNCTION; break;
        !          2254:     }
        !          2255:     
        !          2256: } /* CardServices */
        !          2257: 
        !          2258: /*======================================================================
        !          2259: 
        !          2260:     OS-specific module glue goes here
        !          2261:     
        !          2262: ======================================================================*/
        !          2263: 
        !          2264: #include <linux/pci.h>
        !          2265: 
        !          2266: #if (LINUX_VERSION_CODE <= VERSION(2,1,17))
        !          2267: 
        !          2268: #undef CONFIG_MODVERSIONS
        !          2269: static struct symbol_table cs_symtab = {
        !          2270: #include <linux/symtab_begin.h>
        !          2271: #undef X
        !          2272: #define X(sym) { (void *)&sym, SYMBOL_NAME_STR(sym) }
        !          2273:     X(register_ss_entry),
        !          2274:     X(unregister_ss_entry),
        !          2275:     X(CardServices),
        !          2276:     X(MTDHelperEntry),
        !          2277: #ifdef HAS_PROC_BUS
        !          2278:     X(proc_pccard),
        !          2279: #endif
        !          2280: #ifndef HAVE_MEMRESERVE
        !          2281:     X(request_mem_region),
        !          2282:     X(release_mem_region),
        !          2283: #endif
        !          2284: #ifdef CONFIG_PNP_BIOS
        !          2285:     X(check_pnp_irq),
        !          2286: #endif
        !          2287: #ifdef CONFIG_PCI
        !          2288:     X(pci_irq_mask),
        !          2289:     X(pci_devices),
        !          2290:     X(pci_root),
        !          2291:     X(pci_find_slot),
        !          2292:     X(pci_find_class),
        !          2293:     X(pci_enable_device),
        !          2294:     X(pci_set_power_state),
        !          2295: #endif
        !          2296: #include <linux/symtab_end.h>
        !          2297: };
        !          2298: 
        !          2299: #else
        !          2300: 
        !          2301: EXPORT_SYMBOL(register_ss_entry);
        !          2302: EXPORT_SYMBOL(unregister_ss_entry);
        !          2303: EXPORT_SYMBOL(CardServices);
        !          2304: EXPORT_SYMBOL(MTDHelperEntry);
        !          2305: #ifdef HAS_PROC_BUS
        !          2306: EXPORT_SYMBOL(proc_pccard);
        !          2307: #endif
        !          2308: #ifndef HAVE_MEMRESERVE
        !          2309: EXPORT_SYMBOL(request_mem_region);
        !          2310: EXPORT_SYMBOL(release_mem_region);
        !          2311: #endif
        !          2312: #ifdef CONFIG_PNP_BIOS
        !          2313: EXPORT_SYMBOL(check_pnp_irq);
        !          2314: #endif
        !          2315: #ifdef CONFIG_PCI
        !          2316: EXPORT_SYMBOL(pci_irq_mask);
        !          2317: #if (LINUX_VERSION_CODE < VERSION(2,3,24))
        !          2318: EXPORT_SYMBOL(pci_enable_device);
        !          2319: EXPORT_SYMBOL(pci_set_power_state);
        !          2320: #endif
        !          2321: #endif
        !          2322: 
        !          2323: #endif
        !          2324: 
        !          2325: int __init init_pcmcia_cs(void)
        !          2326: {
        !          2327:     printk(KERN_INFO "%s\n", release);
        !          2328: #ifdef UTS_RELEASE
        !          2329:     printk(KERN_INFO "  %s\n", kernel);
        !          2330: #endif
        !          2331:     printk(KERN_INFO "  %s\n", options);
        !          2332:     DEBUG(0, "%s\n", version);
        !          2333: #ifdef CONFIG_PM
        !          2334:     if (do_apm)
        !          2335:        pm_register(PM_SYS_DEV, PM_SYS_PCMCIA, handle_pm_event);
        !          2336: #endif
        !          2337: #ifdef CONFIG_PCI
        !          2338:     pci_fixup_init();
        !          2339: #endif
        !          2340: #ifdef CONFIG_PNP_BIOS
        !          2341:     if (do_pnp) {
        !          2342:        pnp_bios_init();
        !          2343:        pnp_proc_init();
        !          2344:        pnp_rsrc_init();
        !          2345:     }
        !          2346: #endif
        !          2347:     register_symtab(&cs_symtab);
        !          2348: #ifdef HAS_PROC_BUS
        !          2349:     proc_pccard = proc_mkdir("pccard", proc_bus);
        !          2350: #ifdef CONFIG_PNP_BIOS
        !          2351:     if (proc_pccard) {
        !          2352:        create_proc_read_entry("ioport", 0, proc_pccard,
        !          2353:                               proc_read_io, NULL);
        !          2354:        create_proc_read_entry("irq", 0, proc_pccard,
        !          2355:                               proc_read_irq, NULL);
        !          2356:     }
        !          2357: #endif
        !          2358: #ifndef HAVE_MEMRESERVE
        !          2359:     if (proc_pccard)
        !          2360:        create_proc_read_entry("memory", 0, proc_pccard,
        !          2361:                               proc_read_mem, NULL);
        !          2362: #endif
        !          2363: #endif
        !          2364:     return 0;
        !          2365: }
        !          2366: 
        !          2367: static void __exit exit_pcmcia_cs(void)
        !          2368: {
        !          2369:     printk(KERN_INFO "unloading PCMCIA Card Services\n");
        !          2370: #ifdef HAS_PROC_BUS
        !          2371:     if (proc_pccard) {
        !          2372: #ifdef CONFIG_PNP_BIOS
        !          2373:        remove_proc_entry("ioport", proc_pccard);
        !          2374:        remove_proc_entry("irq", proc_pccard);
        !          2375: #endif
        !          2376: #ifndef HAVE_MEMRESERVE
        !          2377:        remove_proc_entry("memory", proc_pccard);
        !          2378: #endif
        !          2379:        remove_proc_entry("pccard", proc_bus);
        !          2380:     }
        !          2381: #endif
        !          2382: #ifdef CONFIG_PM
        !          2383:     if (do_apm)
        !          2384:        pm_unregister_all(handle_pm_event);
        !          2385: #endif
        !          2386: #ifdef CONFIG_PCI
        !          2387:     pci_fixup_done();
        !          2388: #endif
        !          2389: #ifdef CONFIG_PNP_BIOS
        !          2390:     if (do_pnp) {
        !          2391:        pnp_proc_done();
        !          2392:        pnp_rsrc_done();
        !          2393:     }
        !          2394: #endif
        !          2395:     release_resource_db();
        !          2396: }
        !          2397: 
        !          2398: module_init(init_pcmcia_cs);
        !          2399: module_exit(exit_pcmcia_cs);

unix.superglobalmegacorp.com

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