|
|
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, ®); ! 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, ®); ! 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);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.