- pre2
[davej-history.git] / drivers / pcmcia / cs.c
blob547a18076a3220906286b8ffde4d3100580429ad
1 /*======================================================================
3 PCMCIA Card Services -- core services
5 cs.c 1.267 2000/08/30 22:07:31
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/
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.
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU Public License version 2 (the "GPL"), in which
23 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.
32 ======================================================================*/
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/malloc.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 <asm/system.h>
51 #include <asm/irq.h>
53 #define IN_CARD_SERVICES
54 #include <pcmcia/version.h>
55 #include <pcmcia/cs_types.h>
56 #include <pcmcia/ss.h>
57 #include <pcmcia/cs.h>
58 #include <pcmcia/bulkmem.h>
59 #include <pcmcia/cistpl.h>
60 #include <pcmcia/cisreg.h>
61 #include <pcmcia/bus_ops.h>
62 #include"cs_internal.h"
63 #include"rsrc_mgr.h"
65 #ifdef PCMCIA_DEBUG
66 int pc_debug = PCMCIA_DEBUG;
67 MODULE_PARM(pc_debug,"i");
68 static const char*version =
69 "cs.c 1.267 2000/08/30 22:07:31 (David Hinds)";
70 #endif
72 #ifdef CONFIG_PCI
73 #define PCI_OPT" [pci]"
74 #else
75 #define PCI_OPT""
76 #endif
77 #ifdef CONFIG_CARDBUS
78 #define CB_OPT" [cardbus]"
79 #else
80 #define CB_OPT""
81 #endif
82 #ifdef CONFIG_PM
83 #define PM_OPT" [pm]"
84 #else
85 #define PM_OPT""
86 #endif
87 #if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && !defined(CONFIG_PM)
88 #define OPTIONS" none"
89 #else
90 #define OPTIONS PCI_OPT CB_OPT PM_OPT
91 #endif
93 static const char*release ="Linux PCMCIA Card Services " CS_RELEASE;
94 static const char*options ="options: " OPTIONS;
96 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
97 MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE
98 "\noptions:" OPTIONS);
100 /*====================================================================*/
102 /* Parameters that can be set with 'insmod' */
104 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n,"i")
106 INT_MODULE_PARM(setup_delay, HZ/20);/* ticks */
107 INT_MODULE_PARM(resume_delay, HZ/5);/* ticks */
108 INT_MODULE_PARM(shutdown_delay, HZ/40);/* ticks */
109 INT_MODULE_PARM(vcc_settle,400);/* msecs */
110 INT_MODULE_PARM(reset_time,10);/* usecs */
111 INT_MODULE_PARM(unreset_delay,100);/* msecs */
112 INT_MODULE_PARM(unreset_check,100);/* msecs */
113 INT_MODULE_PARM(unreset_limit,30);/* unreset_check's */
115 /* Access speed for attribute memory windows */
116 INT_MODULE_PARM(cis_speed,300);/* ns */
118 /* Access speed for IO windows */
119 INT_MODULE_PARM(io_speed,0);/* ns */
121 /* Optional features */
122 #ifdef CONFIG_PM
123 INT_MODULE_PARM(do_apm,1);
124 #else
125 INT_MODULE_PARM(do_apm,0);
126 #endif
128 /*====================================================================*/
130 socket_state_t dead_socket = {
131 0, SS_DETECT,0,0,0
134 /* Table of sockets */
135 socket_t sockets =0;
136 socket_info_t *socket_table[MAX_SOCK];
138 #ifdef CONFIG_PROC_FS
139 struct proc_dir_entry *proc_pccard = NULL;
140 #endif
142 /*====================================================================*/
144 /* String tables for error messages */
146 typedefstruct lookup_t {
147 int key;
148 char*msg;
149 } lookup_t;
151 static const lookup_t error_table[] = {
152 { CS_SUCCESS,"Operation succeeded"},
153 { CS_BAD_ADAPTER,"Bad adapter"},
154 { CS_BAD_ATTRIBUTE,"Bad attribute", },
155 { CS_BAD_BASE,"Bad base address"},
156 { CS_BAD_EDC,"Bad EDC"},
157 { CS_BAD_IRQ,"Bad IRQ"},
158 { CS_BAD_OFFSET,"Bad offset"},
159 { CS_BAD_PAGE,"Bad page number"},
160 { CS_READ_FAILURE,"Read failure"},
161 { CS_BAD_SIZE,"Bad size"},
162 { CS_BAD_SOCKET,"Bad socket"},
163 { CS_BAD_TYPE,"Bad type"},
164 { CS_BAD_VCC,"Bad Vcc"},
165 { CS_BAD_VPP,"Bad Vpp"},
166 { CS_BAD_WINDOW,"Bad window"},
167 { CS_WRITE_FAILURE,"Write failure"},
168 { CS_NO_CARD,"No card present"},
169 { CS_UNSUPPORTED_FUNCTION,"Usupported function"},
170 { CS_UNSUPPORTED_MODE,"Unsupported mode"},
171 { CS_BAD_SPEED,"Bad speed"},
172 { CS_BUSY,"Resource busy"},
173 { CS_GENERAL_FAILURE,"General failure"},
174 { CS_WRITE_PROTECTED,"Write protected"},
175 { CS_BAD_ARG_LENGTH,"Bad argument length"},
176 { CS_BAD_ARGS,"Bad arguments"},
177 { CS_CONFIGURATION_LOCKED,"Configuration locked"},
178 { CS_IN_USE,"Resource in use"},
179 { CS_NO_MORE_ITEMS,"No more items"},
180 { CS_OUT_OF_RESOURCE,"Out of resource"},
181 { CS_BAD_HANDLE,"Bad handle"},
182 { CS_BAD_TUPLE,"Bad CIS tuple"}
184 #define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
186 static const lookup_t service_table[] = {
187 { AccessConfigurationRegister,"AccessConfigurationRegister"},
188 { AddSocketServices,"AddSocketServices"},
189 { AdjustResourceInfo,"AdjustResourceInfo"},
190 { CheckEraseQueue,"CheckEraseQueue"},
191 { CloseMemory,"CloseMemory"},
192 { DeregisterClient,"DeregisterClient"},
193 { DeregisterEraseQueue,"DeregisterEraseQueue"},
194 { GetCardServicesInfo,"GetCardServicesInfo"},
195 { GetClientInfo,"GetClientInfo"},
196 { GetConfigurationInfo,"GetConfigurationInfo"},
197 { GetEventMask,"GetEventMask"},
198 { GetFirstClient,"GetFirstClient"},
199 { GetFirstRegion,"GetFirstRegion"},
200 { GetFirstTuple,"GetFirstTuple"},
201 { GetNextClient,"GetNextClient"},
202 { GetNextRegion,"GetNextRegion"},
203 { GetNextTuple,"GetNextTuple"},
204 { GetStatus,"GetStatus"},
205 { GetTupleData,"GetTupleData"},
206 { MapMemPage,"MapMemPage"},
207 { ModifyConfiguration,"ModifyConfiguration"},
208 { ModifyWindow,"ModifyWindow"},
209 { OpenMemory,"OpenMemory"},
210 { ParseTuple,"ParseTuple"},
211 { ReadMemory,"ReadMemory"},
212 { RegisterClient,"RegisterClient"},
213 { RegisterEraseQueue,"RegisterEraseQueue"},
214 { RegisterMTD,"RegisterMTD"},
215 { ReleaseConfiguration,"ReleaseConfiguration"},
216 { ReleaseIO,"ReleaseIO"},
217 { ReleaseIRQ,"ReleaseIRQ"},
218 { ReleaseWindow,"ReleaseWindow"},
219 { RequestConfiguration,"RequestConfiguration"},
220 { RequestIO,"RequestIO"},
221 { RequestIRQ,"RequestIRQ"},
222 { RequestSocketMask,"RequestSocketMask"},
223 { RequestWindow,"RequestWindow"},
224 { ResetCard,"ResetCard"},
225 { SetEventMask,"SetEventMask"},
226 { ValidateCIS,"ValidateCIS"},
227 { WriteMemory,"WriteMemory"},
228 { BindDevice,"BindDevice"},
229 { BindMTD,"BindMTD"},
230 { ReportError,"ReportError"},
231 { SuspendCard,"SuspendCard"},
232 { ResumeCard,"ResumeCard"},
233 { EjectCard,"EjectCard"},
234 { InsertCard,"InsertCard"},
235 { ReplaceCIS,"ReplaceCIS"}
237 #define SERVICE_COUNT (sizeof(service_table)/sizeof(lookup_t))
239 /*======================================================================
241 These functions are just shorthand for the actual low-level drivers
243 ======================================================================*/
245 static intregister_callback(socket_info_t *s,void(*handler)(void*,unsigned int),void* info)
247 return s->ss_entry->register_callback(s->sock, handler, info);
250 static intget_socket_status(socket_info_t *s,int*val)
252 return s->ss_entry->get_status(s->sock, val);
255 static intset_socket(socket_info_t *s, socket_state_t *state)
257 return s->ss_entry->set_socket(s->sock, state);
260 static intset_io_map(socket_info_t *s,struct pccard_io_map *io)
262 return s->ss_entry->set_io_map(s->sock, io);
265 static intset_mem_map(socket_info_t *s,struct pccard_mem_map *mem)
267 return s->ss_entry->set_mem_map(s->sock, mem);
270 static intsuspend_socket(socket_info_t *s)
272 s->socket = dead_socket;
273 return s->ss_entry->suspend(s->sock);
276 static intinit_socket(socket_info_t *s)
278 s->socket = dead_socket;
279 return s->ss_entry->init(s->sock);
282 /*====================================================================*/
284 #if defined(CONFIG_PROC_FS) && defined(PCMCIA_DEBUG)
285 static intproc_read_clients(char*buf,char**start, off_t pos,
286 int count,int*eof,void*data)
288 socket_info_t *s = data;
289 client_handle_t c;
290 char*p = buf;
292 for(c = s->clients; c; c = c->next)
293 p +=sprintf(p,"fn %x: '%s' [attr 0x%04x] [state 0x%04x]\n",
294 c->Function, c->dev_info, c->Attributes, c->state);
295 return(p - buf);
297 #endif
299 /*======================================================================
301 Low-level PC Card interface drivers need to register with Card
302 Services using these calls.
304 ======================================================================*/
306 static voidsetup_socket(socket_info_t *);
307 static voidshutdown_socket(socket_info_t *);
308 static voidreset_socket(socket_info_t *);
309 static voidunreset_socket(socket_info_t *);
310 static voidparse_events(void*info, u_int events);
312 socket_info_t *pcmcia_register_socket(int slot,
313 struct pccard_operations * ss_entry,
314 int use_bus_pm)
316 socket_info_t *s;
317 int i;
319 DEBUG(0,"cs: pcmcia_register_socket(0x%p)\n", ss_entry);
321 s =kmalloc(sizeof(struct socket_info_t), GFP_KERNEL);
322 memset(s,0,sizeof(socket_info_t));
324 s->ss_entry = ss_entry;
325 s->sock = slot;
327 /* base address = 0, map = 0 */
328 s->cis_mem.flags =0;
329 s->cis_mem.speed = cis_speed;
330 s->use_bus_pm = use_bus_pm;
331 s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
332 spin_lock_init(&s->lock);
334 for(i =0; i < sockets; i++)
335 if(socket_table[i] == NULL)break;
336 socket_table[i] = s;
337 if(i == sockets) sockets++;
339 init_socket(s);
340 ss_entry->inquire_socket(slot, &s->cap);
341 #ifdef CONFIG_PROC_FS
342 if(proc_pccard) {
343 char name[3];
344 sprintf(name,"%02d", i);
345 s->proc =proc_mkdir(name, proc_pccard);
346 if(s->proc)
347 ss_entry->proc_setup(slot, s->proc);
348 #ifdef PCMCIA_DEBUG
349 if(s->proc)
350 create_proc_read_entry("clients",0, s->proc,
351 proc_read_clients, s);
352 #endif
354 #endif
355 return s;
356 }/* pcmcia_register_socket */
358 intregister_ss_entry(int nsock,struct pccard_operations * ss_entry)
360 int ns;
362 DEBUG(0,"cs: register_ss_entry(%d, 0x%p)\n", nsock, ss_entry);
364 for(ns =0; ns < nsock; ns++) {
365 pcmcia_register_socket(ns, ss_entry,0);
368 return0;
369 }/* register_ss_entry */
371 /*====================================================================*/
373 voidpcmcia_unregister_socket(socket_info_t *s)
375 int j, socket = -1;
376 client_t *client;
378 for(j =0; j < MAX_SOCK; j++)
379 if(socket_table [j] == s) {
380 socket = j;
381 break;
383 if(socket <0)
384 return;
386 #ifdef CONFIG_PROC_FS
387 if(proc_pccard) {
388 char name[3];
389 sprintf(name,"%02d", socket);
390 #ifdef PCMCIA_DEBUG
391 remove_proc_entry("clients", s->proc);
392 #endif
393 remove_proc_entry(name, proc_pccard);
395 #endif
397 shutdown_socket(s);
398 release_cis_mem(s);
399 while(s->clients) {
400 client = s->clients;
401 s->clients = s->clients->next;
402 kfree(client);
404 s->ss_entry = NULL;
405 kfree(s);
407 socket_table[socket] = NULL;
408 for(j = socket; j < sockets-1; j++)
409 socket_table[j] = socket_table[j+1];
410 sockets--;
411 }/* pcmcia_unregister_socket */
413 voidunregister_ss_entry(struct pccard_operations * ss_entry)
415 int i;
417 for(i =0; i < sockets; i++) {
418 socket_info_t *socket = socket_table[i];
419 if(socket->ss_entry == ss_entry)
420 pcmcia_unregister_socket(socket);
421 else
422 i++;
424 }/* unregister_ss_entry */
426 /*======================================================================
428 Shutdown_Socket() and setup_socket() are scheduled using add_timer
429 calls by the main event handler when card insertion and removal
430 events are received. Shutdown_Socket() unconfigures a socket and
431 turns off socket power. Setup_socket() turns on socket power
432 and resets the socket, in two stages.
434 ======================================================================*/
436 static voidfree_regions(memory_handle_t *list)
438 memory_handle_t tmp;
439 while(*list != NULL) {
440 tmp = *list;
441 *list = tmp->info.next;
442 tmp->region_magic =0;
443 kfree(tmp);
447 static intsend_event(socket_info_t *s, event_t event,int priority);
449 static voidmsleep(unsigned int msec)
451 current->state = TASK_INTERRUPTIBLE;
452 schedule_timeout( (msec * HZ +999) /1000);
455 static voidshutdown_socket(socket_info_t *s)
457 client_t **c;
459 DEBUG(1,"cs: shutdown_socket(%p)\n", s);
461 /* Blank out the socket state */
462 s->state &= SOCKET_PRESENT|SOCKET_SETUP_PENDING;
463 init_socket(s);
464 s->irq.AssignedIRQ = s->irq.Config =0;
465 s->lock_count =0;
466 s->cis_used =0;
467 if(s->fake_cis) {
468 kfree(s->fake_cis);
469 s->fake_cis = NULL;
471 #ifdef CONFIG_CARDBUS
472 cb_release_cis_mem(s);
473 cb_free(s);
474 #endif
475 s->functions =0;
476 if(s->config) {
477 kfree(s->config);
478 s->config = NULL;
480 for(c = &s->clients; *c; ) {
481 if((*c)->state & CLIENT_UNBOUND) {
482 client_t *d = *c;
483 *c = (*c)->next;
484 kfree(d);
485 }else{
486 c = &((*c)->next);
489 free_regions(&s->a_region);
490 free_regions(&s->c_region);
491 }/* shutdown_socket */
493 static voidsetup_socket(socket_info_t *s)
495 int val;
496 int setup_timeout =100;
498 /* Wait for "not pending" */
499 for(;;) {
500 get_socket_status(s, &val);
501 if(!(val & SS_PENDING))
502 break;
503 if(--setup_timeout) {
504 msleep(100);
505 continue;
507 printk(KERN_NOTICE "cs: socket %p voltage interrogation"
508 " timed out\n", s);
509 return;
512 if(val & SS_DETECT) {
513 DEBUG(1,"cs: setup_socket(%p): applying power\n", s);
514 s->state |= SOCKET_PRESENT;
515 s->socket.flags =0;
516 if(val & SS_3VCARD)
517 s->socket.Vcc = s->socket.Vpp =33;
518 else if(!(val & SS_XVCARD))
519 s->socket.Vcc = s->socket.Vpp =50;
520 else{
521 printk(KERN_NOTICE "cs: socket %p: unsupported "
522 "voltage key\n", s);
523 s->socket.Vcc =0;
525 if(val & SS_CARDBUS) {
526 s->state |= SOCKET_CARDBUS;
527 #ifndef CONFIG_CARDBUS
528 printk(KERN_NOTICE "cs: unsupported card type detected!\n");
529 #endif
531 set_socket(s, &s->socket);
532 msleep(vcc_settle);
533 reset_socket(s);
534 }else
535 DEBUG(0,"cs: setup_socket(%p): no card!\n", s);
536 }/* setup_socket */
538 /*======================================================================
540 Reset_socket() and unreset_socket() handle hard resets. Resets
541 have several causes: card insertion, a call to reset_socket, or
542 recovery from a suspend/resume cycle. Unreset_socket() sends
543 a CS event that matches the cause of the reset.
545 ======================================================================*/
547 static voidreset_socket(socket_info_t *s)
549 DEBUG(1,"cs: resetting socket %p\n", s);
550 s->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
551 set_socket(s, &s->socket);
552 udelay((long)reset_time);
553 s->socket.flags &= ~SS_RESET;
554 set_socket(s, &s->socket);
555 msleep(unreset_delay);
556 unreset_socket(s);
557 }/* reset_socket */
559 #define EVENT_MASK \
560 (SOCKET_SETUP_PENDING|SOCKET_SUSPEND|SOCKET_RESET_PENDING)
562 static voidunreset_socket(socket_info_t *s)
564 int setup_timeout = unreset_limit;
565 int val;
567 /* Wait for "ready" */
568 for(;;) {
569 get_socket_status(s, &val);
570 if(val & SS_READY)
571 break;
572 DEBUG(2,"cs: socket %ld not ready yet\n", i);
573 if(--setup_timeout) {
574 msleep(unreset_check);
575 continue;
577 printk(KERN_NOTICE "cs: socket %p timed out during"
578 " reset\n", s);
579 s->state &= ~EVENT_MASK;
580 return;
583 DEBUG(1,"cs: reset done on socket %p\n", s);
584 if(s->state & SOCKET_SUSPEND) {
585 s->state &= ~EVENT_MASK;
586 if(verify_cis_cache(s) !=0)
587 parse_events(s, SS_DETECT);
588 else
589 send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
590 }else if(s->state & SOCKET_SETUP_PENDING) {
591 #ifdef CONFIG_CARDBUS
592 if(s->state & SOCKET_CARDBUS)
593 cb_alloc(s);
594 #endif
595 send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
596 s->state &= ~SOCKET_SETUP_PENDING;
597 }else{
598 send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
599 if(s->reset_handle) {
600 s->reset_handle->event_callback_args.info = NULL;
601 EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,
602 CS_EVENT_PRI_LOW);
604 s->state &= ~EVENT_MASK;
606 }/* unreset_socket */
608 /*======================================================================
610 The central event handler. Send_event() sends an event to all
611 valid clients. Parse_events() interprets the event bits from
612 a card status change report. Do_shotdown() handles the high
613 priority stuff associated with a card removal.
615 ======================================================================*/
617 static intsend_event(socket_info_t *s, event_t event,int priority)
619 client_t *client = s->clients;
620 int ret;
621 DEBUG(1,"cs: send_event(sock %d, event %d, pri %d)\n",
622 s->sock, event, priority);
623 ret =0;
624 for(; client; client = client->next) {
625 if(client->state & (CLIENT_UNBOUND|CLIENT_STALE))
626 continue;
627 if(client->EventMask & event) {
628 ret =EVENT(client, event, priority);
629 if(ret !=0)
630 return ret;
633 return ret;
634 }/* send_event */
636 static voiddo_shutdown(socket_info_t *s)
638 client_t *client;
639 if(s->state & SOCKET_SHUTDOWN_PENDING)
640 return;
641 s->state |= SOCKET_SHUTDOWN_PENDING;
642 send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
643 for(client = s->clients; client; client = client->next)
644 if(!(client->Attributes & INFO_MASTER_CLIENT))
645 client->state |= CLIENT_STALE;
646 if(s->state & (SOCKET_SETUP_PENDING|SOCKET_RESET_PENDING)) {
647 DEBUG(0,"cs: flushing pending setup\n");
648 s->state &= ~EVENT_MASK;
650 msleep(shutdown_delay);
651 s->state &= ~SOCKET_PRESENT;
652 shutdown_socket(s);
655 static voidparse_events(void*info, u_int events)
657 socket_info_t *s = info;
658 if(events & SS_DETECT) {
659 int status;
661 get_socket_status(s, &status);
662 if((s->state & SOCKET_PRESENT) &&
663 (!(s->state & SOCKET_SUSPEND) ||
664 !(status & SS_DETECT)))
665 do_shutdown(s);
666 if(status & SS_DETECT) {
667 if(s->state & SOCKET_SETUP_PENDING) {
668 DEBUG(1,"cs: delaying pending setup\n");
669 return;
671 s->state |= SOCKET_SETUP_PENDING;
672 if(s->state & SOCKET_SUSPEND)
673 msleep(resume_delay);
674 else
675 msleep(setup_delay);
676 setup_socket(s);
679 if(events & SS_BATDEAD)
680 send_event(s, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);
681 if(events & SS_BATWARN)
682 send_event(s, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
683 if(events & SS_READY) {
684 if(!(s->state & SOCKET_RESET_PENDING))
685 send_event(s, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
686 elseDEBUG(1,"cs: ready change during reset\n");
688 }/* parse_events */
690 /*======================================================================
692 Another event handler, for power management events.
694 This does not comply with the latest PC Card spec for handling
695 power management events.
697 ======================================================================*/
699 voidpcmcia_suspend_socket(socket_info_t *s)
701 if((s->state & SOCKET_PRESENT) && !(s->state & SOCKET_SUSPEND)) {
702 send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
703 suspend_socket(s);
704 s->state |= SOCKET_SUSPEND;
708 voidpcmcia_resume_socket(socket_info_t *s)
710 int stat;
712 /* Do this just to reinitialize the socket */
713 init_socket(s);
714 get_socket_status(s, &stat);
716 /* If there was or is a card here, we need to do something
717 about it... but parse_events will sort it all out. */
718 if((s->state & SOCKET_PRESENT) || (stat & SS_DETECT))
719 parse_events(s, SS_DETECT);
722 static inthandle_pm_event(struct pm_dev *dev, pm_request_t rqst,void*data)
724 int i;
725 socket_info_t *s;
727 /* only for busses that don't suspend/resume slots directly */
729 switch(rqst) {
730 case PM_SUSPEND:
731 DEBUG(1,"cs: received suspend notification\n");
732 for(i =0; i < sockets; i++) {
733 s = socket_table [i];
734 if(!s->use_bus_pm)
735 pcmcia_suspend_socket(socket_table [i]);
737 break;
738 case PM_RESUME:
739 DEBUG(1,"cs: received resume notification\n");
740 for(i =0; i < sockets; i++) {
741 s = socket_table [i];
742 if(!s->use_bus_pm)
743 pcmcia_resume_socket(socket_table [i]);
745 break;
747 return0;
748 }/* handle_pm_event */
750 /*======================================================================
752 Special stuff for managing IO windows, because they are scarce.
754 ======================================================================*/
756 static intalloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
757 ioaddr_t num, u_int lines,char*name)
759 int i;
760 ioaddr_t try, align;
762 align = (*base) ? (lines ?1<<lines :0) :1;
763 if(align && (align < num)) {
764 if(*base) {
765 DEBUG(0,"odd IO request: num %04x align %04x\n",
766 num, align);
767 align =0;
768 }else
769 while(align && (align < num)) align <<=1;
771 if(*base & ~(align-1)) {
772 DEBUG(0,"odd IO request: base %04x align %04x\n",
773 *base, align);
774 align =0;
776 /* Check for an already-allocated window that must conflict with
777 what was asked for. It is a hack because it does not catch all
778 potential conflicts, just the most obvious ones. */
779 for(i =0; i < MAX_IO_WIN; i++)
780 if((s->io[i].NumPorts !=0) &&
781 ((s->io[i].BasePort & (align-1)) == *base))
782 return1;
783 for(i =0; i < MAX_IO_WIN; i++) {
784 if(s->io[i].NumPorts ==0) {
785 if(find_io_region(base, num, align, name) ==0) {
786 s->io[i].Attributes = attr;
787 s->io[i].BasePort = *base;
788 s->io[i].NumPorts = s->io[i].InUse = num;
789 break;
790 }else
791 return1;
792 }else if(s->io[i].Attributes != attr)
793 continue;
794 /* Try to extend top of window */
795 try= s->io[i].BasePort + s->io[i].NumPorts;
796 if((*base ==0) || (*base ==try))
797 if(find_io_region(&try, num,0, name) ==0) {
798 *base =try;
799 s->io[i].NumPorts += num;
800 s->io[i].InUse += num;
801 break;
803 /* Try to extend bottom of window */
804 try= s->io[i].BasePort - num;
805 if((*base ==0) || (*base ==try))
806 if(find_io_region(&try, num,0, name) ==0) {
807 s->io[i].BasePort = *base =try;
808 s->io[i].NumPorts += num;
809 s->io[i].InUse += num;
810 break;
813 return(i == MAX_IO_WIN);
814 }/* alloc_io_space */
816 static voidrelease_io_space(socket_info_t *s, ioaddr_t base,
817 ioaddr_t num)
819 int i;
820 release_region(base, num);
821 for(i =0; i < MAX_IO_WIN; i++) {
822 if((s->io[i].BasePort <= base) &&
823 (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
824 s->io[i].InUse -= num;
825 /* Free the window if no one else is using it */
826 if(s->io[i].InUse ==0)
827 s->io[i].NumPorts =0;
832 /*======================================================================
834 Access_configuration_register() reads and writes configuration
835 registers in attribute memory. Memory window 0 is reserved for
836 this and the tuple reading services.
838 ======================================================================*/
840 intpcmcia_access_configuration_register(client_handle_t handle,
841 conf_reg_t *reg)
843 socket_info_t *s;
844 config_t *c;
845 int addr;
846 u_char val;
848 if(CHECK_HANDLE(handle))
849 return CS_BAD_HANDLE;
850 s =SOCKET(handle);
851 if(handle->Function == BIND_FN_ALL) {
852 if(reg->Function >= s->functions)
853 return CS_BAD_ARGS;
854 c = &s->config[reg->Function];
855 }else
856 c =CONFIG(handle);
857 if(!(c->state & CONFIG_LOCKED))
858 return CS_CONFIGURATION_LOCKED;
860 addr = (c->ConfigBase + reg->Offset) >>1;
862 switch(reg->Action) {
863 case CS_READ:
864 read_cis_mem(s,1, addr,1, &val);
865 reg->Value = val;
866 break;
867 case CS_WRITE:
868 val = reg->Value;
869 write_cis_mem(s,1, addr,1, &val);
870 break;
871 default:
872 return CS_BAD_ARGS;
873 break;
875 return CS_SUCCESS;
876 }/* access_configuration_register */
878 /*======================================================================
880 Bind_device() associates a device driver with a particular socket.
881 It is normally called by Driver Services after it has identified
882 a newly inserted card. An instance of that driver will then be
883 eligible to register as a client of this socket.
885 ======================================================================*/
887 intpcmcia_bind_device(bind_req_t *req)
889 client_t *client;
890 socket_info_t *s;
892 if(CHECK_SOCKET(req->Socket))
893 return CS_BAD_SOCKET;
894 s =SOCKET(req);
896 client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL);
897 if(!client)return CS_OUT_OF_RESOURCE;
898 memset(client,'\0',sizeof(client_t));
899 client->client_magic = CLIENT_MAGIC;
900 strncpy(client->dev_info, (char*)req->dev_info, DEV_NAME_LEN);
901 client->Socket = req->Socket;
902 client->Function = req->Function;
903 client->state = CLIENT_UNBOUND;
904 client->erase_busy.next = &client->erase_busy;
905 client->erase_busy.prev = &client->erase_busy;
906 init_waitqueue_head(&client->mtd_req);
907 client->next = s->clients;
908 s->clients = client;
909 DEBUG(1,"cs: bind_device(): client 0x%p, sock %d, dev %s\n",
910 client, client->Socket, client->dev_info);
911 return CS_SUCCESS;
912 }/* bind_device */
914 /*======================================================================
916 Bind_mtd() associates a device driver with a particular memory
917 region. It is normally called by Driver Services after it has
918 identified a memory device type. An instance of the corresponding
919 driver will then be able to register to control this region.
921 ======================================================================*/
923 intpcmcia_bind_mtd(mtd_bind_t *req)
925 socket_info_t *s;
926 memory_handle_t region;
928 if(CHECK_SOCKET(req->Socket))
929 return CS_BAD_SOCKET;
930 s =SOCKET(req);
932 if(req->Attributes & REGION_TYPE_AM)
933 region = s->a_region;
934 else
935 region = s->c_region;
937 while(region) {
938 if(region->info.CardOffset == req->CardOffset)break;
939 region = region->info.next;
941 if(!region || (region->mtd != NULL))
942 return CS_BAD_OFFSET;
943 strncpy(region->dev_info, (char*)req->dev_info, DEV_NAME_LEN);
945 DEBUG(1,"cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
946 req->Attributes, req->CardOffset, (char*)req->dev_info);
947 return CS_SUCCESS;
948 }/* bind_mtd */
950 /*====================================================================*/
952 intpcmcia_deregister_client(client_handle_t handle)
954 client_t **client;
955 socket_info_t *s;
956 memory_handle_t region;
957 u_long flags;
958 int i, sn;
960 DEBUG(1,"cs: deregister_client(%p)\n", handle);
961 if(CHECK_HANDLE(handle))
962 return CS_BAD_HANDLE;
963 if(handle->state &
964 (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
965 return CS_IN_USE;
966 for(i =0; i < MAX_WIN; i++)
967 if(handle->state &CLIENT_WIN_REQ(i))
968 return CS_IN_USE;
970 /* Disconnect all MTD links */
971 s =SOCKET(handle);
972 if(handle->mtd_count) {
973 for(region = s->a_region; region; region = region->info.next)
974 if(region->mtd == handle) region->mtd = NULL;
975 for(region = s->c_region; region; region = region->info.next)
976 if(region->mtd == handle) region->mtd = NULL;
979 sn = handle->Socket; s = socket_table[sn];
981 if((handle->state & CLIENT_STALE) ||
982 (handle->Attributes & INFO_MASTER_CLIENT)) {
983 spin_lock_irqsave(&s->lock, flags);
984 client = &s->clients;
985 while((*client) && ((*client) != handle))
986 client = &(*client)->next;
987 if(*client == NULL) {
988 spin_unlock_irqrestore(&s->lock, flags);
989 return CS_BAD_HANDLE;
991 *client = handle->next;
992 handle->client_magic =0;
993 kfree(handle);
994 spin_unlock_irqrestore(&s->lock, flags);
995 }else{
996 handle->state = CLIENT_UNBOUND;
997 handle->mtd_count =0;
998 handle->event_handler = NULL;
1001 if(--s->real_clients ==0)
1002 register_callback(s, NULL, NULL);
1004 return CS_SUCCESS;
1005 }/* deregister_client */
1007 /*====================================================================*/
1009 intpcmcia_get_configuration_info(client_handle_t handle,
1010 config_info_t *config)
1012 socket_info_t *s;
1013 config_t *c;
1015 if(CHECK_HANDLE(handle))
1016 return CS_BAD_HANDLE;
1017 s =SOCKET(handle);
1018 if(!(s->state & SOCKET_PRESENT))
1019 return CS_NO_CARD;
1021 if(handle->Function == BIND_FN_ALL) {
1022 if(config->Function && (config->Function >= s->functions))
1023 return CS_BAD_ARGS;
1024 }else
1025 config->Function = handle->Function;
1027 #ifdef CONFIG_CARDBUS
1028 if(s->state & SOCKET_CARDBUS) {
1029 u_char fn = config->Function;
1030 memset(config,0,sizeof(config_info_t));
1031 config->Function = fn;
1032 config->Vcc = s->socket.Vcc;
1033 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
1034 config->Option = s->cap.cb_dev->subordinate->number;
1035 if(s->cb_config) {
1036 config->Attributes = CONF_VALID_CLIENT;
1037 config->IntType = INT_CARDBUS;
1038 config->AssignedIRQ = s->irq.AssignedIRQ;
1039 if(config->AssignedIRQ)
1040 config->Attributes |= CONF_ENABLE_IRQ;
1041 config->BasePort1 = s->io[0].BasePort;
1042 config->NumPorts1 = s->io[0].NumPorts;
1044 return CS_SUCCESS;
1046 #endif
1048 c = (s->config != NULL) ? &s->config[config->Function] : NULL;
1050 if((c == NULL) || !(c->state & CONFIG_LOCKED)) {
1051 config->Attributes =0;
1052 config->Vcc = s->socket.Vcc;
1053 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
1054 return CS_SUCCESS;
1057 /* !!! This is a hack !!! */
1058 memcpy(&config->Attributes, &c->Attributes,sizeof(config_t));
1059 config->Attributes |= CONF_VALID_CLIENT;
1060 config->CardValues = c->CardValues;
1061 config->IRQAttributes = c->irq.Attributes;
1062 config->AssignedIRQ = s->irq.AssignedIRQ;
1063 config->BasePort1 = c->io.BasePort1;
1064 config->NumPorts1 = c->io.NumPorts1;
1065 config->Attributes1 = c->io.Attributes1;
1066 config->BasePort2 = c->io.BasePort2;
1067 config->NumPorts2 = c->io.NumPorts2;
1068 config->Attributes2 = c->io.Attributes2;
1069 config->IOAddrLines = c->io.IOAddrLines;
1071 return CS_SUCCESS;
1072 }/* get_configuration_info */
1074 /*======================================================================
1076 Return information about this version of Card Services.
1078 ======================================================================*/
1080 intpcmcia_get_card_services_info(servinfo_t *info)
1082 info->Signature[0] ='C';
1083 info->Signature[1] ='S';
1084 info->Count = sockets;
1085 info->Revision = CS_RELEASE_CODE;
1086 info->CSLevel =0x0210;
1087 info->VendorString = (char*)release;
1088 return CS_SUCCESS;
1089 }/* get_card_services_info */
1091 /*======================================================================
1093 Note that get_first_client() *does* recognize the Socket field
1094 in the request structure.
1096 ======================================================================*/
1098 intpcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
1100 socket_t s;
1101 if(req->Attributes & CLIENT_THIS_SOCKET)
1102 s = req->Socket;
1103 else
1104 s =0;
1105 if(CHECK_SOCKET(req->Socket))
1106 return CS_BAD_SOCKET;
1107 if(socket_table[s]->clients == NULL)
1108 return CS_NO_MORE_ITEMS;
1109 *handle = socket_table[s]->clients;
1110 return CS_SUCCESS;
1111 }/* get_first_client */
1113 /*====================================================================*/
1115 intpcmcia_get_next_client(client_handle_t *handle, client_req_t *req)
1117 socket_info_t *s;
1118 if((handle == NULL) ||CHECK_HANDLE(*handle))
1119 return CS_BAD_HANDLE;
1120 if((*handle)->next == NULL) {
1121 if(req->Attributes & CLIENT_THIS_SOCKET)
1122 return CS_NO_MORE_ITEMS;
1123 s =SOCKET(*handle);
1124 if(s->clients == NULL)
1125 return CS_NO_MORE_ITEMS;
1126 *handle = s->clients;
1127 }else
1128 *handle = (*handle)->next;
1129 return CS_SUCCESS;
1130 }/* get_next_client */
1132 /*====================================================================*/
1134 intpcmcia_get_window(window_handle_t *handle,int idx, win_req_t *req)
1136 socket_info_t *s;
1137 window_t *win;
1138 int w;
1140 if(idx ==0)
1141 s =SOCKET((client_handle_t)*handle);
1142 else
1143 s = (*handle)->sock;
1144 if(!(s->state & SOCKET_PRESENT))
1145 return CS_NO_CARD;
1146 for(w = idx; w < MAX_WIN; w++)
1147 if(s->state &SOCKET_WIN_REQ(w))break;
1148 if(w == MAX_WIN)
1149 return CS_NO_MORE_ITEMS;
1150 win = &s->win[w];
1151 req->Base = win->ctl.sys_start;
1152 req->Size = win->ctl.sys_stop - win->ctl.sys_start +1;
1153 req->AccessSpeed = win->ctl.speed;
1154 req->Attributes =0;
1155 if(win->ctl.flags & MAP_ATTRIB)
1156 req->Attributes |= WIN_MEMORY_TYPE_AM;
1157 if(win->ctl.flags & MAP_ACTIVE)
1158 req->Attributes |= WIN_ENABLE;
1159 if(win->ctl.flags & MAP_16BIT)
1160 req->Attributes |= WIN_DATA_WIDTH_16;
1161 if(win->ctl.flags & MAP_USE_WAIT)
1162 req->Attributes |= WIN_USE_WAIT;
1163 *handle = win;
1164 return CS_SUCCESS;
1165 }/* get_window */
1167 intpcmcia_get_first_window(window_handle_t *win, win_req_t *req)
1169 if((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
1170 return CS_BAD_HANDLE;
1171 returnpcmcia_get_window(win,0, req);
1174 intpcmcia_get_next_window(window_handle_t *win, win_req_t *req)
1176 if((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
1177 return CS_BAD_HANDLE;
1178 returnpcmcia_get_window(win, (*win)->index+1, req);
1181 /*=====================================================================
1183 Return the PCI device associated with a card..
1185 ======================================================================*/
1187 #ifdef CONFIG_CARDBUS
1189 struct pci_bus *pcmcia_lookup_bus(client_handle_t handle)
1191 socket_info_t *s;
1193 if(CHECK_HANDLE(handle))
1194 return NULL;
1195 s =SOCKET(handle);
1196 if(!(s->state & SOCKET_CARDBUS))
1197 return NULL;
1199 return s->cap.cb_dev->subordinate;
1202 EXPORT_SYMBOL(pcmcia_lookup_bus);
1204 #endif
1206 /*======================================================================
1208 Get the current socket state bits. We don't support the latched
1209 SocketState yet: I haven't seen any point for it.
1211 ======================================================================*/
1213 intpcmcia_get_status(client_handle_t handle, cs_status_t *status)
1215 socket_info_t *s;
1216 config_t *c;
1217 int val;
1219 if(CHECK_HANDLE(handle))
1220 return CS_BAD_HANDLE;
1221 s =SOCKET(handle);
1222 get_socket_status(s, &val);
1223 status->CardState = status->SocketState =0;
1224 status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT :0;
1225 status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT :0;
1226 status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD :0;
1227 status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD :0;
1228 if(s->state & SOCKET_SUSPEND)
1229 status->CardState |= CS_EVENT_PM_SUSPEND;
1230 if(!(s->state & SOCKET_PRESENT))
1231 return CS_NO_CARD;
1232 if(s->state & SOCKET_SETUP_PENDING)
1233 status->CardState |= CS_EVENT_CARD_INSERTION;
1235 /* Get info from the PRR, if necessary */
1236 if(handle->Function == BIND_FN_ALL) {
1237 if(status->Function && (status->Function >= s->functions))
1238 return CS_BAD_ARGS;
1239 c = (s->config != NULL) ? &s->config[status->Function] : NULL;
1240 }else
1241 c =CONFIG(handle);
1242 if((c != NULL) && (c->state & CONFIG_LOCKED) &&
1243 (c->IntType & INT_MEMORY_AND_IO)) {
1244 u_char reg;
1245 if(c->Present & PRESENT_PIN_REPLACE) {
1246 read_cis_mem(s,1, (c->ConfigBase+CISREG_PRR)>>1,1, &reg);
1247 status->CardState |=
1248 (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT :0;
1249 status->CardState |=
1250 (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE :0;
1251 status->CardState |=
1252 (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW :0;
1253 status->CardState |=
1254 (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD :0;
1255 }else{
1256 /* No PRR? Then assume we're always ready */
1257 status->CardState |= CS_EVENT_READY_CHANGE;
1259 if(c->Present & PRESENT_EXT_STATUS) {
1260 read_cis_mem(s,1, (c->ConfigBase+CISREG_ESR)>>1,1, &reg);
1261 status->CardState |=
1262 (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION :0;
1264 return CS_SUCCESS;
1266 status->CardState |=
1267 (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT :0;
1268 status->CardState |=
1269 (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD :0;
1270 status->CardState |=
1271 (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW :0;
1272 status->CardState |=
1273 (val & SS_READY) ? CS_EVENT_READY_CHANGE :0;
1274 return CS_SUCCESS;
1275 }/* get_status */
1277 /*======================================================================
1279 Change the card address of an already open memory window.
1281 ======================================================================*/
1283 intpcmcia_get_mem_page(window_handle_t win, memreq_t *req)
1285 if((win == NULL) || (win->magic != WINDOW_MAGIC))
1286 return CS_BAD_HANDLE;
1287 req->Page =0;
1288 req->CardOffset = win->ctl.card_start;
1289 return CS_SUCCESS;
1290 }/* get_mem_page */
1292 intpcmcia_map_mem_page(window_handle_t win, memreq_t *req)
1294 socket_info_t *s;
1295 if((win == NULL) || (win->magic != WINDOW_MAGIC))
1296 return CS_BAD_HANDLE;
1297 if(req->Page !=0)
1298 return CS_BAD_PAGE;
1299 s = win->sock;
1300 win->ctl.card_start = req->CardOffset;
1301 if(set_mem_map(s, &win->ctl) !=0)
1302 return CS_BAD_OFFSET;
1303 return CS_SUCCESS;
1304 }/* map_mem_page */
1306 /*======================================================================
1308 Modify a locked socket configuration
1310 ======================================================================*/
1312 intpcmcia_modify_configuration(client_handle_t handle,
1313 modconf_t *mod)
1315 socket_info_t *s;
1316 config_t *c;
1318 if(CHECK_HANDLE(handle))
1319 return CS_BAD_HANDLE;
1320 s =SOCKET(handle); c =CONFIG(handle);
1321 if(!(s->state & SOCKET_PRESENT))
1322 return CS_NO_CARD;
1323 if(!(c->state & CONFIG_LOCKED))
1324 return CS_CONFIGURATION_LOCKED;
1326 if(mod->Attributes & CONF_IRQ_CHANGE_VALID) {
1327 if(mod->Attributes & CONF_ENABLE_IRQ) {
1328 c->Attributes |= CONF_ENABLE_IRQ;
1329 s->socket.io_irq = s->irq.AssignedIRQ;
1330 }else{
1331 c->Attributes &= ~CONF_ENABLE_IRQ;
1332 s->socket.io_irq =0;
1334 set_socket(s, &s->socket);
1337 if(mod->Attributes & CONF_VCC_CHANGE_VALID)
1338 return CS_BAD_VCC;
1340 /* We only allow changing Vpp1 and Vpp2 to the same value */
1341 if((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
1342 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
1343 if(mod->Vpp1 != mod->Vpp2)
1344 return CS_BAD_VPP;
1345 c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
1346 if(set_socket(s, &s->socket))
1347 return CS_BAD_VPP;
1348 }else if((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
1349 (mod->Attributes & CONF_VPP2_CHANGE_VALID))
1350 return CS_BAD_VPP;
1352 return CS_SUCCESS;
1353 }/* modify_configuration */
1355 /*======================================================================
1357 Modify the attributes of a window returned by RequestWindow.
1359 ======================================================================*/
1361 intpcmcia_modify_window(window_handle_t win, modwin_t *req)
1363 if((win == NULL) || (win->magic != WINDOW_MAGIC))
1364 return CS_BAD_HANDLE;
1366 win->ctl.flags &= ~(MAP_ATTRIB|MAP_ACTIVE);
1367 if(req->Attributes & WIN_MEMORY_TYPE)
1368 win->ctl.flags |= MAP_ATTRIB;
1369 if(req->Attributes & WIN_ENABLE)
1370 win->ctl.flags |= MAP_ACTIVE;
1371 if(req->Attributes & WIN_DATA_WIDTH_16)
1372 win->ctl.flags |= MAP_16BIT;
1373 if(req->Attributes & WIN_USE_WAIT)
1374 win->ctl.flags |= MAP_USE_WAIT;
1375 win->ctl.speed = req->AccessSpeed;
1376 set_mem_map(win->sock, &win->ctl);
1378 return CS_SUCCESS;
1379 }/* modify_window */
1381 /*======================================================================
1383 Register_client() uses the dev_info_t handle to match the
1384 caller with a socket. The driver must have already been bound
1385 to a socket with bind_device() -- in fact, bind_device()
1386 allocates the client structure that will be used.
1388 ======================================================================*/
1390 intpcmcia_register_client(client_handle_t *handle, client_reg_t *req)
1392 client_t *client;
1393 socket_info_t *s;
1394 socket_t ns;
1396 /* Look for unbound client with matching dev_info */
1397 client = NULL;
1398 for(ns =0; ns < sockets; ns++) {
1399 client = socket_table[ns]->clients;
1400 while(client != NULL) {
1401 if((strcmp(client->dev_info, (char*)req->dev_info) ==0)
1402 && (client->state & CLIENT_UNBOUND))break;
1403 client = client->next;
1405 if(client != NULL)break;
1407 if(client == NULL)
1408 return CS_OUT_OF_RESOURCE;
1410 s = socket_table[ns];
1411 if(++s->real_clients ==1) {
1412 int status;
1413 register_callback(s, &parse_events, s);
1414 get_socket_status(s, &status);
1415 if((status & SS_DETECT) &&
1416 !(s->state & SOCKET_SETUP_PENDING)) {
1417 s->state |= SOCKET_SETUP_PENDING;
1418 setup_socket(s);
1422 *handle = client;
1423 client->state &= ~CLIENT_UNBOUND;
1424 client->Socket = ns;
1425 client->Attributes = req->Attributes;
1426 client->EventMask = req->EventMask;
1427 client->event_handler = req->event_handler;
1428 client->event_callback_args = req->event_callback_args;
1429 client->event_callback_args.client_handle = client;
1430 client->event_callback_args.bus = s->cap.bus;
1432 if(s->state & SOCKET_CARDBUS)
1433 client->state |= CLIENT_CARDBUS;
1435 if((!(s->state & SOCKET_CARDBUS)) && (s->functions ==0) &&
1436 (client->Function != BIND_FN_ALL)) {
1437 cistpl_longlink_mfc_t mfc;
1438 if(read_tuple(client, CISTPL_LONGLINK_MFC, &mfc)
1439 == CS_SUCCESS)
1440 s->functions = mfc.nfn;
1441 else
1442 s->functions =1;
1443 s->config =kmalloc(sizeof(config_t) * s->functions,
1444 GFP_KERNEL);
1445 memset(s->config,0,sizeof(config_t) * s->functions);
1448 DEBUG(1,"cs: register_client(): client 0x%p, sock %d, dev %s\n",
1449 client, client->Socket, client->dev_info);
1450 if(client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
1451 EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
1452 if((socket_table[ns]->state & SOCKET_PRESENT) &&
1453 !(socket_table[ns]->state & SOCKET_SETUP_PENDING)) {
1454 if(client->EventMask & CS_EVENT_CARD_INSERTION)
1455 EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
1456 else
1457 client->PendingEvents |= CS_EVENT_CARD_INSERTION;
1459 return CS_SUCCESS;
1460 }/* register_client */
1462 /*====================================================================*/
1464 intpcmcia_release_configuration(client_handle_t handle)
1466 pccard_io_map io = {0,0,0,0,1};
1467 socket_info_t *s;
1468 int i;
1470 if(CHECK_HANDLE(handle) ||
1471 !(handle->state & CLIENT_CONFIG_LOCKED))
1472 return CS_BAD_HANDLE;
1473 handle->state &= ~CLIENT_CONFIG_LOCKED;
1474 s =SOCKET(handle);
1476 #ifdef CONFIG_CARDBUS
1477 if(handle->state & CLIENT_CARDBUS) {
1478 cb_disable(s);
1479 s->lock_count =0;
1480 return CS_SUCCESS;
1482 #endif
1484 if(!(handle->state & CLIENT_STALE)) {
1485 config_t *c =CONFIG(handle);
1486 if(--(s->lock_count) ==0) {
1487 s->socket.flags = SS_OUTPUT_ENA;
1488 s->socket.Vpp =0;
1489 s->socket.io_irq =0;
1490 set_socket(s, &s->socket);
1492 if(c->state & CONFIG_IO_REQ)
1493 for(i =0; i < MAX_IO_WIN; i++) {
1494 if(s->io[i].NumPorts ==0)
1495 continue;
1496 s->io[i].Config--;
1497 if(s->io[i].Config !=0)
1498 continue;
1499 io.map = i;
1500 set_io_map(s, &io);
1502 c->state &= ~CONFIG_LOCKED;
1505 return CS_SUCCESS;
1506 }/* release_configuration */
1508 /*======================================================================
1510 Release_io() releases the I/O ranges allocated by a client. This
1511 may be invoked some time after a card ejection has already dumped
1512 the actual socket configuration, so if the client is "stale", we
1513 don't bother checking the port ranges against the current socket
1514 values.
1516 ======================================================================*/
1518 intpcmcia_release_io(client_handle_t handle, io_req_t *req)
1520 socket_info_t *s;
1522 if(CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
1523 return CS_BAD_HANDLE;
1524 handle->state &= ~CLIENT_IO_REQ;
1525 s =SOCKET(handle);
1527 #ifdef CONFIG_CARDBUS
1528 if(handle->state & CLIENT_CARDBUS) {
1529 cb_release(s);
1530 return CS_SUCCESS;
1532 #endif
1534 if(!(handle->state & CLIENT_STALE)) {
1535 config_t *c =CONFIG(handle);
1536 if(c->state & CONFIG_LOCKED)
1537 return CS_CONFIGURATION_LOCKED;
1538 if((c->io.BasePort1 != req->BasePort1) ||
1539 (c->io.NumPorts1 != req->NumPorts1) ||
1540 (c->io.BasePort2 != req->BasePort2) ||
1541 (c->io.NumPorts2 != req->NumPorts2))
1542 return CS_BAD_ARGS;
1543 c->state &= ~CONFIG_IO_REQ;
1546 release_io_space(s, req->BasePort1, req->NumPorts1);
1547 if(req->NumPorts2)
1548 release_io_space(s, req->BasePort2, req->NumPorts2);
1550 return CS_SUCCESS;
1551 }/* release_io */
1553 /*====================================================================*/
1555 intpcmcia_release_irq(client_handle_t handle, irq_req_t *req)
1557 socket_info_t *s;
1558 if(CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
1559 return CS_BAD_HANDLE;
1560 handle->state &= ~CLIENT_IRQ_REQ;
1561 s =SOCKET(handle);
1563 if(!(handle->state & CLIENT_STALE)) {
1564 config_t *c =CONFIG(handle);
1565 if(c->state & CONFIG_LOCKED)
1566 return CS_CONFIGURATION_LOCKED;
1567 if(c->irq.Attributes != req->Attributes)
1568 return CS_BAD_ATTRIBUTE;
1569 if(s->irq.AssignedIRQ != req->AssignedIRQ)
1570 return CS_BAD_IRQ;
1571 if(--s->irq.Config ==0) {
1572 c->state &= ~CONFIG_IRQ_REQ;
1573 s->irq.AssignedIRQ =0;
1577 if(req->Attributes & IRQ_HANDLE_PRESENT) {
1578 bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance);
1581 #ifdef CONFIG_ISA
1582 if(req->AssignedIRQ != s->cap.pci_irq)
1583 undo_irq(req->Attributes, req->AssignedIRQ);
1584 #endif
1586 return CS_SUCCESS;
1587 }/* cs_release_irq */
1589 /*====================================================================*/
1591 intpcmcia_release_window(window_handle_t win)
1593 socket_info_t *s;
1595 if((win == NULL) || (win->magic != WINDOW_MAGIC))
1596 return CS_BAD_HANDLE;
1597 s = win->sock;
1598 if(!(win->handle->state &CLIENT_WIN_REQ(win->index)))
1599 return CS_BAD_HANDLE;
1601 /* Shut down memory window */
1602 win->ctl.flags &= ~MAP_ACTIVE;
1603 set_mem_map(s, &win->ctl);
1604 s->state &= ~SOCKET_WIN_REQ(win->index);
1606 /* Release system memory */
1607 release_mem_region(win->base, win->size);
1608 win->handle->state &= ~CLIENT_WIN_REQ(win->index);
1610 win->magic =0;
1612 return CS_SUCCESS;
1613 }/* release_window */
1615 /*====================================================================*/
1617 intpcmcia_request_configuration(client_handle_t handle,
1618 config_req_t *req)
1620 int i;
1621 u_int base;
1622 socket_info_t *s;
1623 config_t *c;
1624 pccard_io_map iomap;
1626 if(CHECK_HANDLE(handle))
1627 return CS_BAD_HANDLE;
1628 i = handle->Socket; s = socket_table[i];
1629 if(!(s->state & SOCKET_PRESENT))
1630 return CS_NO_CARD;
1632 #ifdef CONFIG_CARDBUS
1633 if(handle->state & CLIENT_CARDBUS) {
1634 if(!(req->IntType & INT_CARDBUS))
1635 return CS_UNSUPPORTED_MODE;
1636 if(s->lock_count !=0)
1637 return CS_CONFIGURATION_LOCKED;
1638 cb_enable(s);
1639 handle->state |= CLIENT_CONFIG_LOCKED;
1640 s->lock_count++;
1641 return CS_SUCCESS;
1643 #endif
1645 if(req->IntType & INT_CARDBUS)
1646 return CS_UNSUPPORTED_MODE;
1647 c =CONFIG(handle);
1648 if(c->state & CONFIG_LOCKED)
1649 return CS_CONFIGURATION_LOCKED;
1651 /* Do power control. We don't allow changes in Vcc. */
1652 if(s->socket.Vcc != req->Vcc)
1653 return CS_BAD_VCC;
1654 if(req->Vpp1 != req->Vpp2)
1655 return CS_BAD_VPP;
1656 s->socket.Vpp = req->Vpp1;
1657 if(set_socket(s, &s->socket))
1658 return CS_BAD_VPP;
1660 c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
1662 /* Pick memory or I/O card, DMA mode, interrupt */
1663 c->IntType = req->IntType;
1664 c->Attributes = req->Attributes;
1665 if(req->IntType & INT_MEMORY_AND_IO)
1666 s->socket.flags |= SS_IOCARD;
1667 if(req->Attributes & CONF_ENABLE_DMA)
1668 s->socket.flags |= SS_DMA_MODE;
1669 if(req->Attributes & CONF_ENABLE_SPKR)
1670 s->socket.flags |= SS_SPKR_ENA;
1671 if(req->Attributes & CONF_ENABLE_IRQ)
1672 s->socket.io_irq = s->irq.AssignedIRQ;
1673 else
1674 s->socket.io_irq =0;
1675 set_socket(s, &s->socket);
1676 s->lock_count++;
1678 /* Set up CIS configuration registers */
1679 base = c->ConfigBase = req->ConfigBase;
1680 c->Present = c->CardValues = req->Present;
1681 if(req->Present & PRESENT_COPY) {
1682 c->Copy = req->Copy;
1683 write_cis_mem(s,1, (base + CISREG_SCR)>>1,1, &c->Copy);
1685 if(req->Present & PRESENT_OPTION) {
1686 if(s->functions ==1) {
1687 c->Option = req->ConfigIndex & COR_CONFIG_MASK;
1688 }else{
1689 c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
1690 c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
1691 if(req->Present & PRESENT_IOBASE_0)
1692 c->Option |= COR_ADDR_DECODE;
1694 if(c->state & CONFIG_IRQ_REQ)
1695 if(!(c->irq.Attributes & IRQ_FORCED_PULSE))
1696 c->Option |= COR_LEVEL_REQ;
1697 write_cis_mem(s,1, (base + CISREG_COR)>>1,1, &c->Option);
1698 udelay(40*1000);
1700 if(req->Present & PRESENT_STATUS) {
1701 c->Status = req->Status;
1702 write_cis_mem(s,1, (base + CISREG_CCSR)>>1,1, &c->Status);
1704 if(req->Present & PRESENT_PIN_REPLACE) {
1705 c->Pin = req->Pin;
1706 write_cis_mem(s,1, (base + CISREG_PRR)>>1,1, &c->Pin);
1708 if(req->Present & PRESENT_EXT_STATUS) {
1709 c->ExtStatus = req->ExtStatus;
1710 write_cis_mem(s,1, (base + CISREG_ESR)>>1,1, &c->ExtStatus);
1712 if(req->Present & PRESENT_IOBASE_0) {
1713 i = c->io.BasePort1 &0xff;
1714 write_cis_mem(s,1, (base + CISREG_IOBASE_0)>>1,1, &i);
1715 i = (c->io.BasePort1 >>8) &0xff;
1716 write_cis_mem(s,1, (base + CISREG_IOBASE_1)>>1,1, &i);
1718 if(req->Present & PRESENT_IOSIZE) {
1719 i = c->io.NumPorts1 + c->io.NumPorts2 -1;
1720 write_cis_mem(s,1, (base + CISREG_IOSIZE)>>1,1, &i);
1723 /* Configure I/O windows */
1724 if(c->state & CONFIG_IO_REQ) {
1725 iomap.speed = io_speed;
1726 for(i =0; i < MAX_IO_WIN; i++)
1727 if(s->io[i].NumPorts !=0) {
1728 iomap.map = i;
1729 iomap.flags = MAP_ACTIVE;
1730 switch(s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
1731 case IO_DATA_PATH_WIDTH_16:
1732 iomap.flags |= MAP_16BIT;break;
1733 case IO_DATA_PATH_WIDTH_AUTO:
1734 iomap.flags |= MAP_AUTOSZ;break;
1735 default:
1736 break;
1738 iomap.start = s->io[i].BasePort;
1739 iomap.stop = iomap.start + s->io[i].NumPorts -1;
1740 set_io_map(s, &iomap);
1741 s->io[i].Config++;
1745 c->state |= CONFIG_LOCKED;
1746 handle->state |= CLIENT_CONFIG_LOCKED;
1747 return CS_SUCCESS;
1748 }/* request_configuration */
1750 /*======================================================================
1752 Request_io() reserves ranges of port addresses for a socket.
1753 I have not implemented range sharing or alias addressing.
1755 ======================================================================*/
1757 intpcmcia_request_io(client_handle_t handle, io_req_t *req)
1759 socket_info_t *s;
1760 config_t *c;
1762 if(CHECK_HANDLE(handle))
1763 return CS_BAD_HANDLE;
1764 s =SOCKET(handle);
1765 if(!(s->state & SOCKET_PRESENT))
1766 return CS_NO_CARD;
1768 if(handle->state & CLIENT_CARDBUS) {
1769 #ifdef CONFIG_CARDBUS
1770 int ret =cb_config(s);
1771 if(ret == CS_SUCCESS)
1772 handle->state |= CLIENT_IO_REQ;
1773 return ret;
1774 #else
1775 return CS_UNSUPPORTED_FUNCTION;
1776 #endif
1779 if(!req)
1780 return CS_UNSUPPORTED_MODE;
1781 c =CONFIG(handle);
1782 if(c->state & CONFIG_LOCKED)
1783 return CS_CONFIGURATION_LOCKED;
1784 if(c->state & CONFIG_IO_REQ)
1785 return CS_IN_USE;
1786 if(req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))
1787 return CS_BAD_ATTRIBUTE;
1788 if((req->NumPorts2 >0) &&
1789 (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)))
1790 return CS_BAD_ATTRIBUTE;
1792 if(alloc_io_space(s, req->Attributes1, &req->BasePort1,
1793 req->NumPorts1, req->IOAddrLines,
1794 handle->dev_info))
1795 return CS_IN_USE;
1797 if(req->NumPorts2) {
1798 if(alloc_io_space(s, req->Attributes2, &req->BasePort2,
1799 req->NumPorts2, req->IOAddrLines,
1800 handle->dev_info)) {
1801 release_io_space(s, req->BasePort1, req->NumPorts1);
1802 return CS_IN_USE;
1806 c->io = *req;
1807 c->state |= CONFIG_IO_REQ;
1808 handle->state |= CLIENT_IO_REQ;
1809 return CS_SUCCESS;
1810 }/* request_io */
1812 /*======================================================================
1814 Request_irq() reserves an irq for this client.
1816 Also, since Linux only reserves irq's when they are actually
1817 hooked, we don't guarantee that an irq will still be available
1818 when the configuration is locked. Now that I think about it,
1819 there might be a way to fix this using a dummy handler.
1821 ======================================================================*/
1823 intpcmcia_request_irq(client_handle_t handle, irq_req_t *req)
1825 socket_info_t *s;
1826 config_t *c;
1827 inttry, ret =0, irq =0;
1828 u_int mask;
1830 if(CHECK_HANDLE(handle))
1831 return CS_BAD_HANDLE;
1832 s =SOCKET(handle);
1833 if(!(s->state & SOCKET_PRESENT))
1834 return CS_NO_CARD;
1835 c =CONFIG(handle);
1836 if(c->state & CONFIG_LOCKED)
1837 return CS_CONFIGURATION_LOCKED;
1838 if(c->state & CONFIG_IRQ_REQ)
1839 return CS_IN_USE;
1841 /* Short cut: if there are no ISA interrupts, then it is PCI */
1842 if(!s->cap.irq_mask)
1843 irq = s->cap.pci_irq;
1844 #ifdef CONFIG_ISA
1845 else if(s->irq.AssignedIRQ !=0) {
1846 /* If the interrupt is already assigned, it must match */
1847 irq = s->irq.AssignedIRQ;
1848 if(req->IRQInfo1 & IRQ_INFO2_VALID) {
1849 mask = req->IRQInfo2 & s->cap.irq_mask;
1850 ret = ((mask >> irq) &1) ?0: CS_BAD_ARGS;
1851 }else
1852 ret = ((req->IRQInfo1&IRQ_MASK) == irq) ?0: CS_BAD_ARGS;
1853 }else{
1854 ret = CS_IN_USE;
1855 if(req->IRQInfo1 & IRQ_INFO2_VALID) {
1856 mask = req->IRQInfo2 & s->cap.irq_mask;
1857 for(try=0;try<2;try++) {
1858 for(irq =0; irq <32; irq++)
1859 if((mask >> irq) &1) {
1860 ret =try_irq(req->Attributes, irq,try);
1861 if(ret ==0)break;
1863 if(ret ==0)break;
1865 }else{
1866 irq = req->IRQInfo1 & IRQ_MASK;
1867 ret =try_irq(req->Attributes, irq,1);
1870 #endif
1871 if(ret !=0)return ret;
1873 if(req->Attributes & IRQ_HANDLE_PRESENT) {
1874 if(bus_request_irq(s->cap.bus, irq, req->Handler,
1875 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
1876 (s->functions >1) ||
1877 (irq == s->cap.pci_irq)) ? SA_SHIRQ :0,
1878 handle->dev_info, req->Instance))
1879 return CS_IN_USE;
1882 c->irq.Attributes = req->Attributes;
1883 s->irq.AssignedIRQ = req->AssignedIRQ = irq;
1884 s->irq.Config++;
1886 c->state |= CONFIG_IRQ_REQ;
1887 handle->state |= CLIENT_IRQ_REQ;
1888 return CS_SUCCESS;
1889 }/* cs_request_irq */
1891 /*======================================================================
1893 Request_window() establishes a mapping between card memory space
1894 and system memory space.
1896 ======================================================================*/
1898 intpcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
1900 socket_info_t *s;
1901 window_t *win;
1902 u_long align;
1903 int w;
1905 if(CHECK_HANDLE(*handle))
1906 return CS_BAD_HANDLE;
1907 s =SOCKET(*handle);
1908 if(!(s->state & SOCKET_PRESENT))
1909 return CS_NO_CARD;
1910 if(req->Attributes & (WIN_PAGED | WIN_SHARED))
1911 return CS_BAD_ATTRIBUTE;
1913 /* Window size defaults to smallest available */
1914 if(req->Size ==0)
1915 req->Size = s->cap.map_size;
1916 align = (((s->cap.features & SS_CAP_MEM_ALIGN) ||
1917 (req->Attributes & WIN_STRICT_ALIGN)) ?
1918 req->Size : s->cap.map_size);
1919 if(req->Size & (s->cap.map_size-1))
1920 return CS_BAD_SIZE;
1921 if((req->Base && (s->cap.features & SS_CAP_STATIC_MAP)) ||
1922 (req->Base & (align-1)))
1923 return CS_BAD_BASE;
1924 if(req->Base)
1925 align =0;
1927 /* Allocate system memory window */
1928 for(w =0; w < MAX_WIN; w++)
1929 if(!(s->state &SOCKET_WIN_REQ(w)))break;
1930 if(w == MAX_WIN)
1931 return CS_OUT_OF_RESOURCE;
1933 win = &s->win[w];
1934 win->magic = WINDOW_MAGIC;
1935 win->index = w;
1936 win->handle = *handle;
1937 win->sock = s;
1938 win->base = req->Base;
1939 win->size = req->Size;
1941 if(!(s->cap.features & SS_CAP_STATIC_MAP) &&
1942 find_mem_region(&win->base, win->size, align,
1943 (req->Attributes & WIN_MAP_BELOW_1MB) ||
1944 !(s->cap.features & SS_CAP_PAGE_REGS),
1945 (*handle)->dev_info))
1946 return CS_IN_USE;
1947 (*handle)->state |=CLIENT_WIN_REQ(w);
1949 /* Configure the socket controller */
1950 win->ctl.map = w+1;
1951 win->ctl.flags =0;
1952 win->ctl.speed = req->AccessSpeed;
1953 if(req->Attributes & WIN_MEMORY_TYPE)
1954 win->ctl.flags |= MAP_ATTRIB;
1955 if(req->Attributes & WIN_ENABLE)
1956 win->ctl.flags |= MAP_ACTIVE;
1957 if(req->Attributes & WIN_DATA_WIDTH_16)
1958 win->ctl.flags |= MAP_16BIT;
1959 if(req->Attributes & WIN_USE_WAIT)
1960 win->ctl.flags |= MAP_USE_WAIT;
1961 win->ctl.sys_start = win->base;
1962 win->ctl.sys_stop = win->base + win->size-1;
1963 win->ctl.card_start =0;
1964 if(set_mem_map(s, &win->ctl) !=0)
1965 return CS_BAD_ARGS;
1966 s->state |=SOCKET_WIN_REQ(w);
1968 /* Return window handle */
1969 req->Base = win->ctl.sys_start;
1970 *wh = win;
1972 return CS_SUCCESS;
1973 }/* request_window */
1975 /*======================================================================
1977 I'm not sure which "reset" function this is supposed to use,
1978 but for now, it uses the low-level interface's reset, not the
1979 CIS register.
1981 ======================================================================*/
1983 intpcmcia_reset_card(client_handle_t handle, client_req_t *req)
1985 int i, ret;
1986 socket_info_t *s;
1988 if(CHECK_HANDLE(handle))
1989 return CS_BAD_HANDLE;
1990 i = handle->Socket; s = socket_table[i];
1991 if(!(s->state & SOCKET_PRESENT))
1992 return CS_NO_CARD;
1993 if(s->state & SOCKET_RESET_PENDING)
1994 return CS_IN_USE;
1995 s->state |= SOCKET_RESET_PENDING;
1997 ret =send_event(s, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
1998 if(ret !=0) {
1999 s->state &= ~SOCKET_RESET_PENDING;
2000 handle->event_callback_args.info = (void*)(u_long)ret;
2001 EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW);
2002 }else{
2003 DEBUG(1,"cs: resetting socket %d\n", i);
2004 send_event(s, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
2005 s->reset_handle = handle;
2006 reset_socket(s);
2008 return CS_SUCCESS;
2009 }/* reset_card */
2011 /*======================================================================
2013 These shut down or wake up a socket. They are sort of user
2014 initiated versions of the APM suspend and resume actions.
2016 ======================================================================*/
2018 intpcmcia_suspend_card(client_handle_t handle, client_req_t *req)
2020 int i;
2021 socket_info_t *s;
2023 if(CHECK_HANDLE(handle))
2024 return CS_BAD_HANDLE;
2025 i = handle->Socket; s = socket_table[i];
2026 if(!(s->state & SOCKET_PRESENT))
2027 return CS_NO_CARD;
2028 if(s->state & SOCKET_SUSPEND)
2029 return CS_IN_USE;
2031 DEBUG(1,"cs: suspending socket %d\n", i);
2032 send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
2033 suspend_socket(s);
2034 s->state |= SOCKET_SUSPEND;
2036 return CS_SUCCESS;
2037 }/* suspend_card */
2039 intpcmcia_resume_card(client_handle_t handle, client_req_t *req)
2041 int i;
2042 socket_info_t *s;
2044 if(CHECK_HANDLE(handle))
2045 return CS_BAD_HANDLE;
2046 i = handle->Socket; s = socket_table[i];
2047 if(!(s->state & SOCKET_PRESENT))
2048 return CS_NO_CARD;
2049 if(!(s->state & SOCKET_SUSPEND))
2050 return CS_IN_USE;
2052 DEBUG(1,"cs: waking up socket %d\n", i);
2053 setup_socket(s);
2055 return CS_SUCCESS;
2056 }/* resume_card */
2058 /*======================================================================
2060 These handle user requests to eject or insert a card.
2062 ======================================================================*/
2064 intpcmcia_eject_card(client_handle_t handle, client_req_t *req)
2066 int i, ret;
2067 socket_info_t *s;
2068 u_long flags;
2070 if(CHECK_HANDLE(handle))
2071 return CS_BAD_HANDLE;
2072 i = handle->Socket; s = socket_table[i];
2073 if(!(s->state & SOCKET_PRESENT))
2074 return CS_NO_CARD;
2076 DEBUG(1,"cs: user eject request on socket %d\n", i);
2078 ret =send_event(s, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
2079 if(ret !=0)
2080 return ret;
2082 spin_lock_irqsave(&s->lock, flags);
2083 do_shutdown(s);
2084 spin_unlock_irqrestore(&s->lock, flags);
2086 return CS_SUCCESS;
2088 }/* eject_card */
2090 intpcmcia_insert_card(client_handle_t handle, client_req_t *req)
2092 int i, status;
2093 socket_info_t *s;
2094 u_long flags;
2096 if(CHECK_HANDLE(handle))
2097 return CS_BAD_HANDLE;
2098 i = handle->Socket; s = socket_table[i];
2099 if(s->state & SOCKET_PRESENT)
2100 return CS_IN_USE;
2102 DEBUG(1,"cs: user insert request on socket %d\n", i);
2104 spin_lock_irqsave(&s->lock, flags);
2105 if(!(s->state & SOCKET_SETUP_PENDING)) {
2106 s->state |= SOCKET_SETUP_PENDING;
2107 spin_unlock_irqrestore(&s->lock, flags);
2108 get_socket_status(s, &status);
2109 if(status & SS_DETECT)
2110 setup_socket(s);
2111 else{
2112 s->state &= ~SOCKET_SETUP_PENDING;
2113 return CS_NO_CARD;
2115 }else
2116 spin_unlock_irqrestore(&s->lock, flags);
2118 return CS_SUCCESS;
2119 }/* insert_card */
2121 /*======================================================================
2123 Maybe this should send a CS_EVENT_CARD_INSERTION event if we
2124 haven't sent one to this client yet?
2126 ======================================================================*/
2128 intpcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask)
2130 u_int events, bit;
2131 if(CHECK_HANDLE(handle))
2132 return CS_BAD_HANDLE;
2133 if(handle->Attributes & CONF_EVENT_MASK_VALID)
2134 return CS_BAD_SOCKET;
2135 handle->EventMask = mask->EventMask;
2136 events = handle->PendingEvents & handle->EventMask;
2137 handle->PendingEvents -= events;
2138 while(events !=0) {
2139 bit = ((events ^ (events-1)) +1) >>1;
2140 EVENT(handle, bit, CS_EVENT_PRI_LOW);
2141 events -= bit;
2143 return CS_SUCCESS;
2144 }/* set_event_mask */
2146 /*====================================================================*/
2148 intpcmcia_report_error(client_handle_t handle, error_info_t *err)
2150 int i;
2151 char*serv;
2153 if(CHECK_HANDLE(handle))
2154 printk(KERN_NOTICE);
2155 else
2156 printk(KERN_NOTICE "%s: ", handle->dev_info);
2158 for(i =0; i < SERVICE_COUNT; i++)
2159 if(service_table[i].key == err->func)break;
2160 if(i < SERVICE_COUNT)
2161 serv = service_table[i].msg;
2162 else
2163 serv ="Unknown service number";
2165 for(i =0; i < ERROR_COUNT; i++)
2166 if(error_table[i].key == err->retcode)break;
2167 if(i < ERROR_COUNT)
2168 printk("%s: %s\n", serv, error_table[i].msg);
2169 else
2170 printk("%s: Unknown error code %#x\n", serv, err->retcode);
2172 return CS_SUCCESS;
2173 }/* report_error */
2175 /*====================================================================*/
2177 intCardServices(int func,void*a1,void*a2,void*a3)
2180 #ifdef PCMCIA_DEBUG
2181 if(pc_debug >2) {
2182 int i;
2183 for(i =0; i < SERVICE_COUNT; i++)
2184 if(service_table[i].key == func)break;
2185 if(i < SERVICE_COUNT)
2186 printk(KERN_DEBUG "cs: CardServices(%s, 0x%p, 0x%p)\n",
2187 service_table[i].msg, a1, a2);
2188 else
2189 printk(KERN_DEBUG "cs: CardServices(Unknown func %d, "
2190 "0x%p, 0x%p)\n", func, a1, a2);
2192 #endif
2193 switch(func) {
2194 case AccessConfigurationRegister:
2195 returnpcmcia_access_configuration_register(a1, a2);break;
2196 case AdjustResourceInfo:
2197 returnpcmcia_adjust_resource_info(a1, a2);break;
2198 case CheckEraseQueue:
2199 returnpcmcia_check_erase_queue(a1);break;
2200 case CloseMemory:
2201 returnpcmcia_close_memory(a1);break;
2202 case CopyMemory:
2203 returnpcmcia_copy_memory(a1, a2);break;
2204 case DeregisterClient:
2205 returnpcmcia_deregister_client(a1);break;
2206 case DeregisterEraseQueue:
2207 returnpcmcia_deregister_erase_queue(a1);break;
2208 case GetFirstClient:
2209 returnpcmcia_get_first_client(a1, a2);break;
2210 case GetCardServicesInfo:
2211 returnpcmcia_get_card_services_info(a1);break;
2212 case GetConfigurationInfo:
2213 returnpcmcia_get_configuration_info(a1, a2);break;
2214 case GetNextClient:
2215 returnpcmcia_get_next_client(a1, a2);break;
2216 case GetFirstRegion:
2217 returnpcmcia_get_first_region(a1, a2);break;
2218 case GetFirstTuple:
2219 returnpcmcia_get_first_tuple(a1, a2);break;
2220 case GetNextRegion:
2221 returnpcmcia_get_next_region(a1, a2);break;
2222 case GetNextTuple:
2223 returnpcmcia_get_next_tuple(a1, a2);break;
2224 case GetStatus:
2225 returnpcmcia_get_status(a1, a2);break;
2226 case GetTupleData:
2227 returnpcmcia_get_tuple_data(a1, a2);break;
2228 case MapMemPage:
2229 returnpcmcia_map_mem_page(a1, a2);break;
2230 case ModifyConfiguration:
2231 returnpcmcia_modify_configuration(a1, a2);break;
2232 case ModifyWindow:
2233 returnpcmcia_modify_window(a1, a2);break;
2234 case OpenMemory:
2235 /* return pcmcia_open_memory(a1, a2); */
2237 memory_handle_t m;
2238 int ret =pcmcia_open_memory(a1, a2, &m);
2239 *(memory_handle_t *)a1 = m;
2240 return ret;
2242 break;
2243 case ParseTuple:
2244 returnpcmcia_parse_tuple(a1, a2, a3);break;
2245 case ReadMemory:
2246 returnpcmcia_read_memory(a1, a2, a3);break;
2247 case RegisterClient:
2248 returnpcmcia_register_client(a1, a2);break;
2249 case RegisterEraseQueue:
2251 eraseq_handle_t w;
2252 int ret =pcmcia_register_erase_queue(a1, a2, &w);
2253 *(eraseq_handle_t *)a1 = w;
2254 return ret;
2256 break;
2257 /* return pcmcia_register_erase_queue(a1, a2); break; */
2259 returnpcmcia_register_mtd(a1, a2);break;
2260 case ReleaseConfiguration:
2261 returnpcmcia_release_configuration(a1);break;
2262 case ReleaseIO:
2263 returnpcmcia_release_io(a1, a2);break;
2264 case ReleaseIRQ:
2265 returnpcmcia_release_irq(a1, a2);break;
2266 case ReleaseWindow:
2267 returnpcmcia_release_window(a1);break;
2268 case RequestConfiguration:
2269 returnpcmcia_request_configuration(a1, a2);break;
2270 case RequestIO:
2271 returnpcmcia_request_io(a1, a2);break;
2272 case RequestIRQ:
2273 returnpcmcia_request_irq(a1, a2);break;
2274 case RequestWindow:
2276 window_handle_t w;
2277 int ret =pcmcia_request_window(a1, a2, &w);
2278 *(window_handle_t *)a1 = w;
2279 return ret;
2281 break;
2282 case ResetCard:
2283 returnpcmcia_reset_card(a1, a2);break;
2284 case SetEventMask:
2285 returnpcmcia_set_event_mask(a1, a2);break;
2286 case ValidateCIS:
2287 returnpcmcia_validate_cis(a1, a2);break;
2288 case WriteMemory:
2289 returnpcmcia_write_memory(a1, a2, a3);break;
2290 case BindDevice:
2291 returnpcmcia_bind_device(a1);break;
2292 case BindMTD:
2293 returnpcmcia_bind_mtd(a1);break;
2294 case ReportError:
2295 returnpcmcia_report_error(a1, a2);break;
2296 case SuspendCard:
2297 returnpcmcia_suspend_card(a1, a2);break;
2298 case ResumeCard:
2299 returnpcmcia_resume_card(a1, a2);break;
2300 case EjectCard:
2301 returnpcmcia_eject_card(a1, a2);break;
2302 case InsertCard:
2303 returnpcmcia_insert_card(a1, a2);break;
2304 case ReplaceCIS:
2305 returnpcmcia_replace_cis(a1, a2);break;
2306 case GetFirstWindow:
2307 returnpcmcia_get_first_window(a1, a2);break;
2308 case GetNextWindow:
2309 returnpcmcia_get_next_window(a1, a2);break;
2310 case GetMemPage:
2311 returnpcmcia_get_mem_page(a1, a2);break;
2312 default:
2313 return CS_UNSUPPORTED_FUNCTION;break;
2316 }/* CardServices */
2318 /*======================================================================
2320 OS-specific module glue goes here
2322 ======================================================================*/
2323 /* in alpha order */
2324 EXPORT_SYMBOL(pcmcia_access_configuration_register);
2325 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
2326 EXPORT_SYMBOL(pcmcia_bind_device);
2327 EXPORT_SYMBOL(pcmcia_bind_mtd);
2328 EXPORT_SYMBOL(pcmcia_check_erase_queue);
2329 EXPORT_SYMBOL(pcmcia_close_memory);
2330 EXPORT_SYMBOL(pcmcia_copy_memory);
2331 EXPORT_SYMBOL(pcmcia_deregister_client);
2332 EXPORT_SYMBOL(pcmcia_deregister_erase_queue);
2333 EXPORT_SYMBOL(pcmcia_eject_card);
2334 EXPORT_SYMBOL(pcmcia_get_first_client);
2335 EXPORT_SYMBOL(pcmcia_get_card_services_info);
2336 EXPORT_SYMBOL(pcmcia_get_configuration_info);
2337 EXPORT_SYMBOL(pcmcia_get_mem_page);
2338 EXPORT_SYMBOL(pcmcia_get_next_client);
2339 EXPORT_SYMBOL(pcmcia_get_first_region);
2340 EXPORT_SYMBOL(pcmcia_get_first_tuple);
2341 EXPORT_SYMBOL(pcmcia_get_first_window);
2342 EXPORT_SYMBOL(pcmcia_get_next_region);
2343 EXPORT_SYMBOL(pcmcia_get_next_tuple);
2344 EXPORT_SYMBOL(pcmcia_get_next_window);
2345 EXPORT_SYMBOL(pcmcia_get_status);
2346 EXPORT_SYMBOL(pcmcia_get_tuple_data);
2347 EXPORT_SYMBOL(pcmcia_insert_card);
2348 EXPORT_SYMBOL(pcmcia_map_mem_page);
2349 EXPORT_SYMBOL(pcmcia_modify_configuration);
2350 EXPORT_SYMBOL(pcmcia_modify_window);
2351 EXPORT_SYMBOL(pcmcia_open_memory);
2352 EXPORT_SYMBOL(pcmcia_parse_tuple);
2353 EXPORT_SYMBOL(pcmcia_read_memory);
2354 EXPORT_SYMBOL(pcmcia_register_client);
2355 EXPORT_SYMBOL(pcmcia_register_erase_queue);
2356 EXPORT_SYMBOL(pcmcia_register_mtd);
2357 EXPORT_SYMBOL(pcmcia_release_configuration);
2358 EXPORT_SYMBOL(pcmcia_release_io);
2359 EXPORT_SYMBOL(pcmcia_release_irq);
2360 EXPORT_SYMBOL(pcmcia_release_window);
2361 EXPORT_SYMBOL(pcmcia_replace_cis);
2362 EXPORT_SYMBOL(pcmcia_report_error);
2363 EXPORT_SYMBOL(pcmcia_request_configuration);
2364 EXPORT_SYMBOL(pcmcia_request_io);
2365 EXPORT_SYMBOL(pcmcia_request_irq);
2366 EXPORT_SYMBOL(pcmcia_request_window);
2367 EXPORT_SYMBOL(pcmcia_reset_card);
2368 EXPORT_SYMBOL(pcmcia_resume_card);
2369 EXPORT_SYMBOL(pcmcia_set_event_mask);
2370 EXPORT_SYMBOL(pcmcia_suspend_card);
2371 EXPORT_SYMBOL(pcmcia_validate_cis);
2372 EXPORT_SYMBOL(pcmcia_write_memory);
2374 EXPORT_SYMBOL(dead_socket);
2375 EXPORT_SYMBOL(register_ss_entry);
2376 EXPORT_SYMBOL(unregister_ss_entry);
2377 EXPORT_SYMBOL(CardServices);
2378 EXPORT_SYMBOL(MTDHelperEntry);
2379 #ifdef CONFIG_PROC_FS
2380 EXPORT_SYMBOL(proc_pccard);
2381 #endif
2383 EXPORT_SYMBOL(pcmcia_register_socket);
2384 EXPORT_SYMBOL(pcmcia_unregister_socket);
2385 EXPORT_SYMBOL(pcmcia_suspend_socket);
2386 EXPORT_SYMBOL(pcmcia_resume_socket);
2388 static int __init init_pcmcia_cs(void)
2390 printk(KERN_INFO "%s\n", release);
2391 printk(KERN_INFO " %s\n", options);
2392 DEBUG(0,"%s\n", version);
2393 if(do_apm)
2394 pm_register(PM_SYS_DEV, PM_SYS_PCMCIA, handle_pm_event);
2395 #ifdef CONFIG_PROC_FS
2396 proc_pccard =proc_mkdir("pccard", proc_bus);
2397 #endif
2398 return0;
2401 static void __exit exit_pcmcia_cs(void)
2403 printk(KERN_INFO "unloading PCMCIA Card Services\n");
2404 #ifdef CONFIG_PROC_FS
2405 if(proc_pccard) {
2406 remove_proc_entry("pccard", proc_bus);
2408 #endif
2409 if(do_apm)
2410 pm_unregister_all(handle_pm_event);
2411 release_resource_db();
2414 module_init(init_pcmcia_cs);
2415 module_exit(exit_pcmcia_cs);
2417 /*====================================================================*/
close