Bug Summary

File:obj-scan-build/../linux/pcmcia-cs/modules/cs.c
Location:line 384, column 10
Description:Access to field 'ss_entry' results in a dereference of a null pointer (loaded from variable 's')

Annotated Source Code

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 <dahinds@users.sourceforge.net>. 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_PCI1
66#define PCI_OPT" [pci]" " [pci]"
67#else
68#define PCI_OPT" [pci]" ""
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_PCI1) && \
86 !defined(CONFIG_PM) && !defined(CONFIG_PNP_BIOS)
87#define OPTIONS" [pci]" "" "" "" " none"
88#else
89#define OPTIONS" [pci]" "" "" "" PCI_OPT" [pci]" CB_OPT"" PM_OPT"" PNP_OPT""
90#endif
91
92static const char *release = "Linux PCMCIA Card Services " CS_RELEASE"3.2.8";
93#ifdef UTS_RELEASE"2.0.36"
94static const char *kernel = "kernel build: " UTS_RELEASE"2.0.36" " " UTS_VERSION"";
95#endif
96static const char *options = "options: " OPTIONS" [pci]" "" "" "";
97
98/*====================================================================*/
99
100/* Module parameters */
101
102MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
103MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE
104 "\n options:" OPTIONS);
105MODULE_LICENSE("Dual MPL/GPL");
106
107#define INT_MODULE_PARM(n, v)static int n = v; static int n = v; MODULE_PARM(n, "i")
108
109INT_MODULE_PARM(setup_delay, HZ/20)static int setup_delay = 100/20;; /* ticks */
110INT_MODULE_PARM(resume_delay, HZ/5)static int resume_delay = 100/5;; /* ticks */
111INT_MODULE_PARM(shutdown_delay, HZ/40)static int shutdown_delay = 100/40;; /* ticks */
112INT_MODULE_PARM(vcc_settle, HZ*4/10)static int vcc_settle = 100*4/10;; /* ticks */
113INT_MODULE_PARM(reset_time, 10)static int reset_time = 10;; /* usecs */
114INT_MODULE_PARM(unreset_delay, HZ/10)static int unreset_delay = 100/10;; /* ticks */
115INT_MODULE_PARM(unreset_check, HZ/10)static int unreset_check = 100/10;; /* ticks */
116INT_MODULE_PARM(unreset_limit, 50)static int unreset_limit = 50;; /* unreset_check's */
117
118/* Access speed for attribute memory windows */
119INT_MODULE_PARM(cis_speed, 300)static int cis_speed = 300;; /* ns */
120
121/* Access speed for IO windows */
122INT_MODULE_PARM(io_speed, 0)static int io_speed = 0;; /* ns */
123
124/* Optional features */
125#ifdef CONFIG_PM
126INT_MODULE_PARM(do_apm, 1)static int do_apm = 1;;
127#endif
128#ifdef CONFIG_PNP_BIOS
129INT_MODULE_PARM(do_pnp, 1)static int do_pnp = 1;;
130#endif
131
132#ifdef PCMCIA_DEBUG4
133int pc_debug=PCMCIA_DEBUG4;
134MODULE_PARM(pc_debug, "i");
135static const char *version =
136"cs.c 1.287 2004/04/09 03:54:25 (David Hinds)";
137#endif
138
139/*====================================================================*/
140
141static socket_state_t dead_socket = {
142 0, SS_DETECT0x0080, 0, 0, 0
143};
144
145/* Table of sockets */
146socket_t sockets = 0;
147socket_info_t *socket_table[MAX_SOCK8];
148
149#ifdef HAS_PROC_BUS
150struct proc_dir_entry *proc_pccard = NULL((void *) 0);
151#endif
152
153/*====================================================================*/
154
155/* String tables for error messages */
156
157typedef struct lookup_t {
158 int key;
159 char *msg;
160} lookup_t;
161
162static const lookup_t error_table[] = {
163 { CS_SUCCESS0x00, "Operation succeeded" },
164 { CS_BAD_ADAPTER0x01, "Bad adapter" },
165 { CS_BAD_ATTRIBUTE0x02, "Bad attribute", },
166 { CS_BAD_BASE0x03, "Bad base address" },
167 { CS_BAD_EDC0x04, "Bad EDC" },
168 { CS_BAD_IRQ0x06, "Bad IRQ" },
169 { CS_BAD_OFFSET0x07, "Bad offset" },
170 { CS_BAD_PAGE0x08, "Bad page number" },
171 { CS_READ_FAILURE0x09, "Read failure" },
172 { CS_BAD_SIZE0x0a, "Bad size" },
173 { CS_BAD_SOCKET0x0b, "Bad socket" },
174 { CS_BAD_TYPE0x0d, "Bad type" },
175 { CS_BAD_VCC0x0e, "Bad Vcc" },
176 { CS_BAD_VPP0x0f, "Bad Vpp" },
177 { CS_BAD_WINDOW0x11, "Bad window" },
178 { CS_WRITE_FAILURE0x12, "Write failure" },
179 { CS_NO_CARD0x14, "No card present" },
180 { CS_UNSUPPORTED_FUNCTION0x15, "Usupported function" },
181 { CS_UNSUPPORTED_MODE0x16, "Unsupported mode" },
182 { CS_BAD_SPEED0x17, "Bad speed" },
183 { CS_BUSY0x18, "Resource busy" },
184 { CS_GENERAL_FAILURE0x19, "General failure" },
185 { CS_WRITE_PROTECTED0x1a, "Write protected" },
186 { CS_BAD_ARG_LENGTH0x1b, "Bad argument length" },
187 { CS_BAD_ARGS0x1c, "Bad arguments" },
188 { CS_CONFIGURATION_LOCKED0x1d, "Configuration locked" },
189 { CS_IN_USE0x1e, "Resource in use" },
190 { CS_NO_MORE_ITEMS0x1f, "No more items" },
191 { CS_OUT_OF_RESOURCE0x20, "Out of resource" },
192 { CS_BAD_HANDLE0x21, "Bad handle" },
193 { CS_BAD_TUPLE0x40, "Bad CIS tuple" }
194};
195#define ERROR_COUNT(sizeof(error_table)/sizeof(lookup_t)) (sizeof(error_table)/sizeof(lookup_t))
196
197static 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)) (sizeof(service_table)/sizeof(lookup_t))
249
250/*======================================================================
251
252 Reset a socket to the default state
253
254======================================================================*/
255
256static 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_DEBUG4)
278static 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 += sprintflinux_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
299static void setup_socket(u_long i);
300static void shutdown_socket(u_long i);
301static void reset_socket(u_long i);
302static void unreset_socket(u_long i);
303static void parse_events(void *info, u_int events);
304
305int 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)do { if (pc_debug>(0)) printk("<7>" "cs: register_ss_entry(%d, 0x%p)\n"
, nsock, ss_entry); } while (0)
;
311
312 for (ns = 0; ns < nsock; ns++) {
313 s = kmalloclinux_kmalloc(sizeof(struct socket_info_t), GFP_KERNEL0x03);
314 if (!s) {
315 printk(KERN_NOTICE"<5>" "cs: memory allocation failure!\n");
316 return (!ns);
317 }
318 memset(s, 0, sizeof(socket_info_t))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(socket_info_t
))) ? __constant_c_and_count_memset(((s)),((0x01010101UL*(unsigned
char)(0))),((sizeof(socket_info_t)))) : __constant_c_memset(
((s)),((0x01010101UL*(unsigned char)(0))),((sizeof(socket_info_t
))))) : (__builtin_constant_p((sizeof(socket_info_t))) ? __memset_generic
((((s))),(((0))),(((sizeof(socket_info_t))))) : __memset_generic
(((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)do { } while(0);
331
332 for (i = 0; i < sockets; i++)
333 if (socket_table[i] == NULL((void *) 0)) 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 sprintflinux_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_DEBUG4
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
360void unregister_ss_entry(ss_entry_t ss_entry)
361{
362 int i, j;
363 socket_info_t *s = NULL((void *) 0);
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 sprintflinux_sprintf(name, "%02d", i);
373#ifdef PCMCIA_DEBUG4
374 remove_proc_entry("clients", s->proc);
375#endif
376 remove_proc_entry(name, proc_pccard);
377 }
378 }
379#endif
380
381 for (;;) {
1
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
382 for (i = 0; i < sockets; i++) {
2
Assuming 'i' is < 'sockets'
3
Loop condition is true. Entering loop body
10
Assuming 'i' is < 'sockets'
11
Loop condition is true. Entering loop body
383 s = socket_table[i];
12
Null pointer value stored to 's'
384 if (s->ss_entry == ss_entry) break;
4
Taking true branch
5
Execution continues on line 386
13
Access to field 'ss_entry' results in a dereference of a null pointer (loaded from variable 's')
385 }
386 if (i == sockets)
6
Taking false branch
387 break;
388 shutdown_socket(i);
389 release_cis_mem(s);
390 while (s->clients) {
7
Loop condition is false. Execution continues on line 395
391 client = s->clients;
392 s->clients = s->clients->next;
393 kfreelinux_kfree(client);
394 }
395 s->ss_entry = NULL((void *) 0);
396 kfreelinux_kfree(s);
397 socket_table[i] = NULL((void *) 0);
398 for (j = i; j < sockets-1; j++)
8
Loop condition is false. Execution continues on line 400
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
415static void free_regions(memory_handle_t *list)
416{
417 memory_handle_t tmp;
418 while (*list != NULL((void *) 0)) {
419 tmp = *list;
420 *list = tmp->info.next;
421 tmp->region_magic = 0;
422 kfreelinux_kfree(tmp);
423 }
424}
425
426static int send_event(socket_info_t *s, event_t event, int priority);
427
428static 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)do { if (pc_debug>(1)) printk("<7>" "cs: shutdown_socket(%ld)\n"
, i); } while (0)
;
434
435 /* Blank out the socket state */
436 s->state &= SOCKET_PRESENT0x0008|SOCKET_SETUP_PENDING0x0010;
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 kfreelinux_kfree(s->fake_cis);
443 s->fake_cis = NULL((void *) 0);
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 kfreelinux_kfree(s->config);
452 s->config = NULL((void *) 0);
453 }
454 for (c = &s->clients; *c; ) {
455 if ((*c)->state & CLIENT_UNBOUND0x0008) {
456 client_t *d = *c;
457 *c = (*c)->next;
458 kfreelinux_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
467static 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_PENDING0x4000) {
474 /* Does the socket need more time? */
475 DEBUG(2, "cs: setup_socket(%ld): status pending\n", i)do { if (pc_debug>(2)) printk("<7>" "cs: setup_socket(%ld): status pending\n"
, i); } while (0)
;
476 if (++s->setup_timeout > 100) {
477 printk(KERN_NOTICE"<5>" "cs: socket %ld voltage interrogation"
478 " timed out\n", i);
479 } else {
480 mod_timer(&s->setup, jiffies + HZ/10)do { del_timer(&s->setup); (&s->setup)->expires
= (jiffies + 100/10); add_timer(&s->setup); } while (
0)
;
481 }
482 } else if (val & SS_DETECT0x0080) {
483 DEBUG(1, "cs: setup_socket(%ld): applying power\n", i)do { if (pc_debug>(1)) printk("<7>" "cs: setup_socket(%ld): applying power\n"
, i); } while (0)
;
484 s->state |= SOCKET_PRESENT0x0008;
485 s->socket.flags = 0;
486 if (val & SS_3VCARD0x1000)
487 s->socket.Vcc = s->socket.Vpp = 33;
488 else if (!(val & SS_XVCARD0x2000))
489 s->socket.Vcc = s->socket.Vpp = 50;
490 else {
491 printk(KERN_NOTICE"<5>" "cs: socket %ld: unsupported "
492 "voltage key\n", i);
493 s->socket.Vcc = 0;
494 }
495 if (val & SS_CARDBUS0x0800) {
496 s->state |= SOCKET_CARDBUS0x8000;
497#ifndef CONFIG_CARDBUS
498 printk(KERN_NOTICE"<5>" "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)do { del_timer(&s->setup); (&s->setup)->expires
= (jiffies + vcc_settle); add_timer(&s->setup); } while
(0)
;
504 } else
505 DEBUG(0, "cs: setup_socket(%ld): no card!\n", i)do { if (pc_debug>(0)) printk("<7>" "cs: setup_socket(%ld): no card!\n"
, i); } while (0)
;
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
517static 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)do { if (pc_debug>(1)) printk("<7>" "cs: resetting socket %ld\n"
, i); } while (0)
;
522 s->socket.flags |= SS_OUTPUT_ENA0x0200 | SS_RESET0x0040;
523 s->ss_entry(s->sock, SS_SetSocket, &s->socket);
524 udelay((long)reset_time)(__builtin_constant_p((long)reset_time) ? __const_udelay(((long
)reset_time) * 0x10c6ul) : __udelay((long)reset_time))
;
525 s->socket.flags &= ~SS_RESET0x0040;
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)do { del_timer(&s->setup); (&s->setup)->expires
= (jiffies + unreset_delay); add_timer(&s->setup); } while
(0)
;
530} /* reset_socket */
531
532#define EVENT_MASK(0x0010|0x0080|0x0040) \
533(SOCKET_SETUP_PENDING0x0010|SOCKET_SUSPEND0x0080|SOCKET_RESET_PENDING0x0040)
534
535static 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_READY0x0040) {
542 DEBUG(1, "cs: reset done on socket %ld\n", i)do { if (pc_debug>(1)) printk("<7>" "cs: reset done on socket %ld\n"
, i); } while (0)
;
543 if (s->state & SOCKET_SUSPEND0x0080) {
544 s->state &= ~EVENT_MASK(0x0010|0x0080|0x0040);
545 if (verify_cis_cache(s) != 0)
546 parse_events(s, SS_DETECT0x0080);
547 else
548 send_event(s, CS_EVENT_PM_RESUME0x004000, CS_EVENT_PRI_LOW0);
549 } else if (s->state & SOCKET_SETUP_PENDING0x0010) {
550#ifdef CONFIG_CARDBUS
551 if (s->state & SOCKET_CARDBUS0x8000)
552 cb_alloc(s);
553#endif
554 send_event(s, CS_EVENT_CARD_INSERTION0x000004, CS_EVENT_PRI_LOW0);
555 s->state &= ~SOCKET_SETUP_PENDING0x0010;
556 } else {
557 send_event(s, CS_EVENT_CARD_RESET0x000400, CS_EVENT_PRI_LOW0);
558 if (s->reset_handle) {
559 s->reset_handle->event_callback_args.info = NULL((void *) 0);
560 EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,((s->reset_handle)->event_handler((0x001000), (0), &
(s->reset_handle)->event_callback_args))
561 CS_EVENT_PRI_LOW)((s->reset_handle)->event_handler((0x001000), (0), &
(s->reset_handle)->event_callback_args))
;
562 s->state &= ~EVENT_MASK(0x0010|0x0080|0x0040);
563 }
564 }
565 } else {
566 DEBUG(2, "cs: socket %ld not ready yet\n", i)do { if (pc_debug>(2)) printk("<7>" "cs: socket %ld not ready yet\n"
, i); } while (0)
;
567 if (++s->setup_timeout > unreset_limit) {
568 printk(KERN_NOTICE"<5>" "cs: socket %ld timed out during"
569 " reset\n", i);
570 s->state &= ~EVENT_MASK(0x0010|0x0080|0x0040);
571 } else {
572 mod_timer(&s->setup, jiffies + unreset_check)do { del_timer(&s->setup); (&s->setup)->expires
= (jiffies + unreset_check); add_timer(&s->setup); } while
(0)
;
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
586static 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",do { if (pc_debug>(1)) printk("<7>" "cs: send_event(sock %d, event %d, pri %d)\n"
, s->sock, event, priority); } while (0)
591 s->sock, event, priority)do { if (pc_debug>(1)) printk("<7>" "cs: send_event(sock %d, event %d, pri %d)\n"
, s->sock, event, priority); } while (0)
;
592 ret = 0;
593 for (; client; client = client->next) {
594 if (client->state & (CLIENT_UNBOUND0x0008|CLIENT_STALE0x0010))
595 continue;
596 if (client->EventMask & event) {
597 ret = EVENT(client, event, priority)((client)->event_handler((event), (priority), &(client
)->event_callback_args))
;
598 if (ret != 0)
599 return ret;
600 }
601 }
602 return ret;
603} /* send_event */
604
605static void do_shutdown(socket_info_t *s)
606{
607 client_t *client;
608 if (s->state & SOCKET_SHUTDOWN_PENDING0x0020)
609 return;
610 s->state |= SOCKET_SHUTDOWN_PENDING0x0020;
611 send_event(s, CS_EVENT_CARD_REMOVAL0x000008, CS_EVENT_PRI_HIGH1);
612 for (client = s->clients; client; client = client->next)
613 if (!(client->Attributes & INFO_MASTER_CLIENT0x01))
614 client->state |= CLIENT_STALE0x0010;
615 if (s->state & (SOCKET_SETUP_PENDING0x0010|SOCKET_RESET_PENDING0x0040)) {
616 DEBUG(0, "cs: flushing pending setup\n")do { if (pc_debug>(0)) printk("<7>" "cs: flushing pending setup\n"
); } while (0)
;
617 del_timer(&s->setup);
618 s->state &= ~EVENT_MASK(0x0010|0x0080|0x0040);
619 }
620 mod_timer(&s->shutdown, jiffies + shutdown_delay)do { del_timer(&s->shutdown); (&s->shutdown)->
expires = (jiffies + shutdown_delay); add_timer(&s->shutdown
); } while (0)
;
621 s->state &= ~SOCKET_PRESENT0x0008;
622}
623
624static void parse_events(void *info, u_int events)
625{
626 socket_info_t *s = info;
627 if (events & SS_DETECT0x0080) {
628 int status;
629 u_long flags;
630 spin_lock_irqsave(&s->lock, flags)do { __asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory"
); __asm__ __volatile__ ("cli": : :"memory"); } while (0)
;
631 s->ss_entry(s->sock, SS_GetStatus, &status);
632 if ((s->state & SOCKET_PRESENT0x0008) &&
633 (!(s->state & SOCKET_SUSPEND0x0080) ||
634 !(status & SS_DETECT0x0080)))
635 do_shutdown(s);
636 if (status & SS_DETECT0x0080) {
637 if (s->state & SOCKET_SETUP_PENDING0x0010) {
638 del_timer(&s->setup);
639 DEBUG(1, "cs: delaying pending setup\n")do { if (pc_debug>(1)) printk("<7>" "cs: delaying pending setup\n"
); } while (0)
;
640 }
641 s->state |= SOCKET_SETUP_PENDING0x0010;
642 s->setup.function = &setup_socket;
643 s->setup_timeout = 0;
644 if (s->state & SOCKET_SUSPEND0x0080)
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)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory");
651 }
652 if (events & SS_BATDEAD0x0010)
653 send_event(s, CS_EVENT_BATTERY_DEAD0x000010, CS_EVENT_PRI_LOW0);
654 if (events & SS_BATWARN0x0020)
655 send_event(s, CS_EVENT_BATTERY_LOW0x000020, CS_EVENT_PRI_LOW0);
656 if (events & SS_READY0x0040) {
657 if (!(s->state & SOCKET_RESET_PENDING0x0040))
658 send_event(s, CS_EVENT_READY_CHANGE0x000040, CS_EVENT_PRI_LOW0);
659 else DEBUG(1, "cs: ready change during reset\n")do { if (pc_debug>(1)) printk("<7>" "cs: ready change during reset\n"
); } while (0)
;
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_CODE131108 < VERSION(2,3,43)(((2)<<16)+(3<<8)+43))
674static int handle_pm_event(apm_event_t rqst)
675#else
676static 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")do { if (pc_debug>(1)) printk("<7>" "cs: received suspend notification\n"
); } while (0)
;
688 if (down) {
689 printk(KERN_DEBUG"<7>" "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_PRESENT0x0008) &&
696 !(s->state & SOCKET_SUSPEND0x0080)){
697 send_event(s, CS_EVENT_PM_SUSPEND0x002000, CS_EVENT_PRI_LOW0);
698 s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
699 s->state |= SOCKET_SUSPEND0x0080;
700 }
701 }
702 break;
703 case PM_RESUME:
704 DEBUG(1, "cs: received resume notification\n")do { if (pc_debug>(1)) printk("<7>" "cs: received resume notification\n"
); } while (0)
;
705 if (!down) {
706 printk(KERN_DEBUG"<7>" "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_PRESENT0x0008) || (stat & SS_DETECT0x0080))
718 parse_events(s, SS_DETECT0x0080);
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
732static 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",do { if (pc_debug>(0)) printk("<7>" "odd IO request: num %04x align %04x\n"
, num, align); } while (0)
742 num, align)do { if (pc_debug>(0)) printk("<7>" "odd IO request: num %04x align %04x\n"
, num, align); } while (0)
;
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",do { if (pc_debug>(0)) printk("<7>" "odd IO request: base %04x align %04x\n"
, *base, align); } while (0)
749 *base, align)do { if (pc_debug>(0)) printk("<7>" "odd IO request: base %04x align %04x\n"
, *base, align); } while (0)
;
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_WIN2; 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_WIN2; 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_WIN2);
790} /* alloc_io_space */
791
792static 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_WIN2; 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
816static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
825 return CS_BAD_HANDLE0x21;
826 s = SOCKET(handle)(socket_table[(handle)->Socket]);
827 if (!(s->state & SOCKET_PRESENT0x0008))
828 return CS_NO_CARD0x14;
829 if (handle->Function == BIND_FN_ALL0xff) {
830 if (reg->Function >= s->functions)
831 return CS_BAD_ARGS0x1c;
832 c = &s->config[reg->Function];
833 } else
834 c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
835 if (!(c->state & CONFIG_LOCKED0x01))
836 return CS_CONFIGURATION_LOCKED0x1d;
837
838 addr = (c->ConfigBase + reg->Offset) >> 1;
839
840 switch (reg->Action) {
841 case CS_READ1:
842 read_cis_mem(s, 1, addr, 1, &val);
843 reg->Value = val;
844 break;
845 case CS_WRITE2:
846 val = reg->Value;
847 write_cis_mem(s, 1, addr, 1, &val);
848 break;
849 default:
850 return CS_BAD_ARGS0x1c;
851 break;
852 }
853 return CS_SUCCESS0x00;
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
865static int bind_device(bind_req_t *req)
866{
867 client_t *client;
868 socket_info_t *s;
869
870 if (CHECK_SOCKET(req->Socket)(((req->Socket) >= sockets) || (socket_table[req->Socket
]->ss_entry == ((void *) 0)))
)
871 return CS_BAD_SOCKET0x0b;
872 s = SOCKET(req)(socket_table[(req)->Socket]);
873
874 client = (client_t *)kmalloclinux_kmalloc(sizeof(client_t), GFP_KERNEL0x03);
875 if (!client) return CS_OUT_OF_RESOURCE0x20;
876 memset(client, '\0', sizeof(client_t))(__builtin_constant_p('\0') ? (__builtin_constant_p((sizeof(client_t
))) ? __constant_c_and_count_memset(((client)),((0x01010101UL
*(unsigned char)('\0'))),((sizeof(client_t)))) : __constant_c_memset
(((client)),((0x01010101UL*(unsigned char)('\0'))),((sizeof(client_t
))))) : (__builtin_constant_p((sizeof(client_t))) ? __memset_generic
((((client))),((('\0'))),(((sizeof(client_t))))) : __memset_generic
(((client)),(('\0')),((sizeof(client_t))))))
;
877 client->client_magic = CLIENT_MAGIC0x51E6;
878 strncpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN32);
879 client->Socket = req->Socket;
880 client->Function = req->Function;
881 client->state = CLIENT_UNBOUND0x0008;
882 client->erase_busy.next = &client->erase_busy;
883 client->erase_busy.prev = &client->erase_busy;
884 init_waitqueue_head(&client->mtd_req)*(&client->mtd_req)=((void *) 0);
885 client->next = s->clients;
886 s->clients = client;
887 DEBUG(1, "cs: bind_device(): client 0x%p, sock %d, dev %s\n",do { if (pc_debug>(1)) printk("<7>" "cs: bind_device(): client 0x%p, sock %d, dev %s\n"
, client, client->Socket, client->dev_info); } while (0
)
888 client, client->Socket, client->dev_info)do { if (pc_debug>(1)) printk("<7>" "cs: bind_device(): client 0x%p, sock %d, dev %s\n"
, client, client->Socket, client->dev_info); } while (0
)
;
889 return CS_SUCCESS0x00;
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
901static 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)(((req->Socket) >= sockets) || (socket_table[req->Socket
]->ss_entry == ((void *) 0)))
)
907 return CS_BAD_SOCKET0x0b;
908 s = SOCKET(req)(socket_table[(req)->Socket]);
909
910 if (req->Attributes & REGION_TYPE_AM0x0001)
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((void *) 0)))
920 return CS_BAD_OFFSET0x07;
921 strncpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN32);
922
923 DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",do { if (pc_debug>(1)) printk("<7>" "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n"
, req->Attributes, req->CardOffset, (char *)req->dev_info
); } while (0)
924 req->Attributes, req->CardOffset, (char *)req->dev_info)do { if (pc_debug>(1)) printk("<7>" "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n"
, req->Attributes, req->CardOffset, (char *)req->dev_info
); } while (0)
;
925 return CS_SUCCESS0x00;
926} /* bind_mtd */
927
928/*====================================================================*/
929
930static 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)do { if (pc_debug>(1)) printk("<7>" "cs: deregister_client(%p)\n"
, handle); } while (0)
;
939 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
940 return CS_BAD_HANDLE0x21;
941 if (handle->state &
942 (CLIENT_IRQ_REQ0x0002|CLIENT_IO_REQ0x0004|CLIENT_CONFIG_LOCKED0x0001))
943 return CS_IN_USE0x1e;
944 for (i = 0; i < MAX_WIN4; i++)
945 if (handle->state & CLIENT_WIN_REQ(i)(0x20<<(i)))
946 return CS_IN_USE0x1e;
947
948 /* Disconnect all MTD links */
949 s = SOCKET(handle)(socket_table[(handle)->Socket]);
950 if (handle->mtd_count) {
951 for (region = s->a_region; region; region = region->info.next)
952 if (region->mtd == handle) region->mtd = NULL((void *) 0);
953 for (region = s->c_region; region; region = region->info.next)
954 if (region->mtd == handle) region->mtd = NULL((void *) 0);
955 }
956
957 sn = handle->Socket; s = socket_table[sn];
958
959 if ((handle->state & CLIENT_STALE0x0010) ||
960 (handle->Attributes & INFO_MASTER_CLIENT0x01)) {
961 spin_lock_irqsave(&s->lock, flags)do { __asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory"
); __asm__ __volatile__ ("cli": : :"memory"); } while (0)
;
962 client = &s->clients;
963 while ((*client) && ((*client) != handle))
964 client = &(*client)->next;
965 if (*client == NULL((void *) 0)) {
966 spin_unlock_irqrestore(&s->lock, flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory");
967 return CS_BAD_HANDLE0x21;
968 }
969 *client = handle->next;
970 handle->client_magic = 0;
971 kfreelinux_kfree(handle);
972 spin_unlock_irqrestore(&s->lock, flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory");
973 } else {
974 handle->state = CLIENT_UNBOUND0x0008;
975 handle->mtd_count = 0;
976 handle->event_handler = NULL((void *) 0);
977 }
978
979 if (--s->real_clients == 0)
980 s->ss_entry(sn, SS_RegisterCallback, NULL((void *) 0));
981
982 return CS_SUCCESS0x00;
983} /* deregister_client */
984
985/*====================================================================*/
986
987static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
994 return CS_BAD_HANDLE0x21;
995 s = SOCKET(handle)(socket_table[(handle)->Socket]);
996 if (!(s->state & SOCKET_PRESENT0x0008))
997 return CS_NO_CARD0x14;
998
999 if (handle->Function == BIND_FN_ALL0xff) {
1000 if (config->Function && (config->Function >= s->functions))
1001 return CS_BAD_ARGS0x1c;
1002 } else
1003 config->Function = handle->Function;
1004
1005#ifdef CONFIG_CARDBUS
1006 if (s->state & SOCKET_CARDBUS0x8000) {
1007 u_char fn = config->Function;
1008 memset(config, 0, sizeof(config_info_t))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(config_info_t
))) ? __constant_c_and_count_memset(((config)),((0x01010101UL
*(unsigned char)(0))),((sizeof(config_info_t)))) : __constant_c_memset
(((config)),((0x01010101UL*(unsigned char)(0))),((sizeof(config_info_t
))))) : (__builtin_constant_p((sizeof(config_info_t))) ? __memset_generic
((((config))),(((0))),(((sizeof(config_info_t))))) : __memset_generic
(((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_CARDBUS0x04;
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_CLIENT0x100;
1018 config->AssignedIRQ = s->irq.AssignedIRQ;
1019 if (config->AssignedIRQ)
1020 config->Attributes |= CONF_ENABLE_IRQ0x01;
1021 config->BasePort1 = s->io[0].BasePort;
1022 config->NumPorts1 = s->io[0].NumPorts;
1023 }
1024 return CS_SUCCESS0x00;
1025 }
1026#endif
1027
1028 c = (s->config != NULL((void *) 0)) ? &s->config[config->Function] : NULL((void *) 0);
1029
1030 if ((c == NULL((void *) 0)) || !(c->state & CONFIG_LOCKED0x01)) {
1031 config->Attributes = 0;
1032 config->Vcc = s->socket.Vcc;
1033 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
1034 return CS_SUCCESS0x00;
1035 }
1036
1037 /* !!! This is a hack !!! */
1038 memcpy(&config->Attributes, &c->Attributes, sizeof(config_t))(__builtin_constant_p(sizeof(config_t)) ? __constant_memcpy((
&config->Attributes),(&c->Attributes),(sizeof(config_t
))) : __memcpy((&config->Attributes),(&c->Attributes
),(sizeof(config_t))))
;
1039 config->Attributes |= CONF_VALID_CLIENT0x100;
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_SUCCESS0x00;
1052} /* get_configuration_info */
1053
1054/*======================================================================
1055
1056 Return information about this version of Card Services.
1057
1058======================================================================*/
1059
1060static 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_CODE0x3208;
1066 info->CSLevel = 0x0210;
1067 info->VendorString = (char *)release;
1068 return CS_SUCCESS0x00;
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
1078static int get_first_client(client_handle_t *handle, client_req_t *req)
1079{
1080 socket_t s;
1081 if (req->Attributes & CLIENT_THIS_SOCKET0x01)
1082 s = req->Socket;
1083 else
1084 s = 0;
1085 if (CHECK_SOCKET(req->Socket)(((req->Socket) >= sockets) || (socket_table[req->Socket
]->ss_entry == ((void *) 0)))
)
1086 return CS_BAD_SOCKET0x0b;
1087 if (socket_table[s]->clients == NULL((void *) 0))
1088 return CS_NO_MORE_ITEMS0x1f;
1089 *handle = socket_table[s]->clients;
1090 return CS_SUCCESS0x00;
1091} /* get_first_client */
1092
1093/*====================================================================*/
1094
1095static int get_next_client(client_handle_t *handle, client_req_t *req)
1096{
1097 socket_info_t *s;
1098 if ((handle == NULL((void *) 0)) || CHECK_HANDLE(*handle)(((*handle) == ((void *) 0)) || ((*handle)->client_magic !=
0x51E6))
)
1099 return CS_BAD_HANDLE0x21;
1100 if ((*handle)->next == NULL((void *) 0)) {
1101 if (req->Attributes & CLIENT_THIS_SOCKET0x01)
1102 return CS_NO_MORE_ITEMS0x1f;
1103 s = SOCKET(*handle)(socket_table[(*handle)->Socket]);
1104 if (s->clients == NULL((void *) 0))
1105 return CS_NO_MORE_ITEMS0x1f;
1106 *handle = s->clients;
1107 } else
1108 *handle = (*handle)->next;
1109 return CS_SUCCESS0x00;
1110} /* get_next_client */
1111
1112/*====================================================================*/
1113
1114static 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)(socket_table[((client_handle_t)*handle)->Socket]);
1122 else
1123 s = (*handle)->sock;
1124 if (!(s->state & SOCKET_PRESENT0x0008))
1125 return CS_NO_CARD0x14;
1126 for (w = idx; w < MAX_WIN4; w++)
1127 if (s->state & SOCKET_WIN_REQ(w)(0x0100<<(w))) break;
1128 if (w == MAX_WIN4)
1129 return CS_NO_MORE_ITEMS0x1f;
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_ATTRIB0x20)
1136 req->Attributes |= WIN_MEMORY_TYPE_AM0x0002;
1137 if (win->ctl.flags & MAP_ACTIVE0x01)
1138 req->Attributes |= WIN_ENABLE0x0004;
1139 if (win->ctl.flags & MAP_16BIT0x02)
1140 req->Attributes |= WIN_DATA_WIDTH_160x0008;
1141 if (win->ctl.flags & MAP_USE_WAIT0x40)
1142 req->Attributes |= WIN_USE_WAIT0x0100;
1143 *handle = win;
1144 return CS_SUCCESS0x00;
1145} /* get_window */
1146
1147static int get_first_window(client_handle_t *handle, win_req_t *req)
1148{
1149 if ((handle == NULL((void *) 0)) || CHECK_HANDLE(*handle)(((*handle) == ((void *) 0)) || ((*handle)->client_magic !=
0x51E6))
)
1150 return CS_BAD_HANDLE0x21;
1151 return get_window((window_handle_t *)handle, 0, req);
1152}
1153
1154static int get_next_window(window_handle_t *win, win_req_t *req)
1155{
1156 if ((win == NULL((void *) 0)) || ((*win)->magic != WINDOW_MAGIC0xB35C))
1157 return CS_BAD_HANDLE0x21;
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
1168static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1175 return CS_BAD_HANDLE0x21;
1176 s = SOCKET(handle)(socket_table[(handle)->Socket]);
1177 s->ss_entry(s->sock, SS_GetStatus, &val);
1178 status->CardState = status->SocketState = 0;
1179 status->CardState |= (val & SS_DETECT0x0080) ? CS_EVENT_CARD_DETECT0x000080 : 0;
1180 status->CardState |= (val & SS_CARDBUS0x0800) ? CS_EVENT_CB_DETECT0x100000 : 0;
1181 status->CardState |= (val & SS_3VCARD0x1000) ? CS_EVENT_3VCARD0x200000 : 0;
1182 status->CardState |= (val & SS_XVCARD0x2000) ? CS_EVENT_XVCARD0x400000 : 0;
1183 if (s->state & SOCKET_SUSPEND0x0080)
1184 status->CardState |= CS_EVENT_PM_SUSPEND0x002000;
1185 if (!(s->state & SOCKET_PRESENT0x0008))
1186 return CS_NO_CARD0x14;
1187 if (s->state & SOCKET_SETUP_PENDING0x0010)
1188 status->CardState |= CS_EVENT_CARD_INSERTION0x000004;
1189
1190 /* Get info from the PRR, if necessary */
1191 if (handle->Function == BIND_FN_ALL0xff) {
1192 if (status->Function && (status->Function >= s->functions))
1193 return CS_BAD_ARGS0x1c;
1194 c = (s->config != NULL((void *) 0)) ? &s->config[status->Function] : NULL((void *) 0);
1195 } else
1196 c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1197 if ((c != NULL((void *) 0)) && (c->state & CONFIG_LOCKED0x01) &&
1198 (c->IntType & (INT_MEMORY_AND_IO0x02 | INT_ZOOMED_VIDEO0x08))) {
1199 u_char reg;
1200 if (c->Present & PRESENT_PIN_REPLACE0x004) {
1201 read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR0x04)>>1, 1, &reg);
1202 status->CardState |=
1203 (reg & PRR_WP_STATUS0x01) ? CS_EVENT_WRITE_PROTECT0x000001 : 0;
1204 status->CardState |=
1205 (reg & PRR_READY_STATUS0x02) ? CS_EVENT_READY_CHANGE0x000040 : 0;
1206 status->CardState |=
1207 (reg & PRR_BVD2_STATUS0x04) ? CS_EVENT_BATTERY_LOW0x000020 : 0;
1208 status->CardState |=
1209 (reg & PRR_BVD1_STATUS0x08) ? CS_EVENT_BATTERY_DEAD0x000010 : 0;
1210 } else {
1211 /* No PRR? Then assume we're always ready */
1212 status->CardState |= CS_EVENT_READY_CHANGE0x000040;
1213 }
1214 if (c->Present & PRESENT_EXT_STATUS0x010) {
1215 read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR0x08)>>1, 1, &reg);
1216 status->CardState |=
1217 (reg & ESR_REQ_ATTN0x10) ? CS_EVENT_REQUEST_ATTENTION0x080000 : 0;
1218 }
1219 return CS_SUCCESS0x00;
1220 }
1221 status->CardState |=
1222 (val & SS_WRPROT0x0001) ? CS_EVENT_WRITE_PROTECT0x000001 : 0;
1223 status->CardState |=
1224 (val & SS_BATDEAD0x0010) ? CS_EVENT_BATTERY_DEAD0x000010 : 0;
1225 status->CardState |=
1226 (val & SS_BATWARN0x0020) ? CS_EVENT_BATTERY_LOW0x000020 : 0;
1227 status->CardState |=
1228 (val & SS_READY0x0040) ? CS_EVENT_READY_CHANGE0x000040 : 0;
1229 return CS_SUCCESS0x00;
1230} /* cs_get_status */
1231
1232/*======================================================================
1233
1234 Change the card address of an already open memory window.
1235
1236======================================================================*/
1237
1238static int get_mem_page(window_handle_t win, memreq_t *req)
1239{
1240 if ((win == NULL((void *) 0)) || (win->magic != WINDOW_MAGIC0xB35C))
1241 return CS_BAD_HANDLE0x21;
1242 req->Page = 0;
1243 req->CardOffset = win->ctl.card_start;
1244 return CS_SUCCESS0x00;
1245} /* get_mem_page */
1246
1247static int map_mem_page(window_handle_t win, memreq_t *req)
1248{
1249 socket_info_t *s;
1250 if ((win == NULL((void *) 0)) || (win->magic != WINDOW_MAGIC0xB35C))
1251 return CS_BAD_HANDLE0x21;
1252 if (req->Page != 0)
1253 return CS_BAD_PAGE0x08;
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_OFFSET0x07;
1258 return CS_SUCCESS0x00;
1259} /* map_mem_page */
1260
1261/*======================================================================
1262
1263 Modify a locked socket configuration
1264
1265======================================================================*/
1266
1267static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1274 return CS_BAD_HANDLE0x21;
1275 s = SOCKET(handle)(socket_table[(handle)->Socket]); c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1276 if (!(s->state & SOCKET_PRESENT0x0008))
1277 return CS_NO_CARD0x14;
1278 if (!(c->state & CONFIG_LOCKED0x01))
1279 return CS_CONFIGURATION_LOCKED0x1d;
1280
1281 if (mod->Attributes & CONF_IRQ_CHANGE_VALID0x100) {
1282 if (mod->Attributes & CONF_ENABLE_IRQ0x01) {
1283 c->Attributes |= CONF_ENABLE_IRQ0x01;
1284 s->socket.io_irq = s->irq.AssignedIRQ;
1285 } else {
1286 c->Attributes &= ~CONF_ENABLE_IRQ0x01;
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_VALID0x200)
1293 return CS_BAD_VCC0x0e;
1294
1295 /* We only allow changing Vpp1 and Vpp2 to the same value */
1296 if ((mod->Attributes & CONF_VPP1_CHANGE_VALID0x400) &&
1297 (mod->Attributes & CONF_VPP2_CHANGE_VALID0x800)) {
1298 if (mod->Vpp1 != mod->Vpp2)
1299 return CS_BAD_VPP0x0f;
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_VPP0x0f;
1303 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID0x400) ||
1304 (mod->Attributes & CONF_VPP2_CHANGE_VALID0x800))
1305 return CS_BAD_VPP0x0f;
1306
1307 return CS_SUCCESS0x00;
1308} /* modify_configuration */
1309
1310/*======================================================================
1311
1312 Modify the attributes of a window returned by RequestWindow.
1313
1314======================================================================*/
1315
1316static int modify_window(window_handle_t win, modwin_t *req)
1317{
1318 if ((win == NULL((void *) 0)) || (win->magic != WINDOW_MAGIC0xB35C))
1319 return CS_BAD_HANDLE0x21;
1320
1321 win->ctl.flags &= ~(MAP_ATTRIB0x20|MAP_ACTIVE0x01);
1322 if (req->Attributes & WIN_MEMORY_TYPE0x0002)
1323 win->ctl.flags |= MAP_ATTRIB0x20;
1324 if (req->Attributes & WIN_ENABLE0x0004)
1325 win->ctl.flags |= MAP_ACTIVE0x01;
1326 if (req->Attributes & WIN_DATA_WIDTH_160x0008)
1327 win->ctl.flags |= MAP_16BIT0x02;
1328 if (req->Attributes & WIN_USE_WAIT0x0100)
1329 win->ctl.flags |= MAP_USE_WAIT0x40;
1330 win->ctl.speed = req->AccessSpeed;
1331 win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl);
1332
1333 return CS_SUCCESS0x00;
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
1345static 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((void *) 0);
1353 for (ns = 0; ns < sockets; ns++) {
1354 client = socket_table[ns]->clients;
1355 while (client != NULL((void *) 0)) {
1356 if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
1357 && (client->state & CLIENT_UNBOUND0x0008)) break;
1358 client = client->next;
1359 }
1360 if (client != NULL((void *) 0)) break;
1361 }
1362 if (client == NULL((void *) 0))
1363 return CS_OUT_OF_RESOURCE0x20;
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_DETECT0x0080) &&
1374 !(s->state & SOCKET_SETUP_PENDING0x0010)) {
1375 s->state |= SOCKET_SETUP_PENDING0x0010;
1376 setup_socket(ns);
1377 }
1378 }
1379
1380 *handle = client;
1381 client->state &= ~CLIENT_UNBOUND0x0008;
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_CARDBUS0x8000)
1391 client->state |= CLIENT_CARDBUS0x8000;
1392
1393 if ((!(s->state & SOCKET_CARDBUS0x8000)) && (s->functions == 0) &&
1394 (client->Function != BIND_FN_ALL0xff)) {
1395 cistpl_longlink_mfc_t mfc;
1396 if (read_tuple(client, CISTPL_LONGLINK_MFC0x06, &mfc)
1397 == CS_SUCCESS0x00)
1398 s->functions = mfc.nfn;
1399 else
1400 s->functions = 1;
1401 s->config = kmalloclinux_kmalloc(sizeof(config_t) * s->functions,
1402 GFP_KERNEL0x03);
1403 memset(s->config, 0, sizeof(config_t) * s->functions)(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(config_t
) * s->functions)) ? __constant_c_and_count_memset(((s->
config)),((0x01010101UL*(unsigned char)(0))),((sizeof(config_t
) * s->functions))) : __constant_c_memset(((s->config))
,((0x01010101UL*(unsigned char)(0))),((sizeof(config_t) * s->
functions)))) : (__builtin_constant_p((sizeof(config_t) * s->
functions)) ? __memset_generic((((s->config))),(((0))),(((
sizeof(config_t) * s->functions)))) : __memset_generic(((s
->config)),((0)),((sizeof(config_t) * s->functions)))))
;
1404 }
1405
1406 DEBUG(1, "cs: register_client(): client 0x%p, sock %d, dev %s\n",do { if (pc_debug>(1)) printk("<7>" "cs: register_client(): client 0x%p, sock %d, dev %s\n"
, client, client->Socket, client->dev_info); } while (0
)
1407 client, client->Socket, client->dev_info)do { if (pc_debug>(1)) printk("<7>" "cs: register_client(): client 0x%p, sock %d, dev %s\n"
, client, client->Socket, client->dev_info); } while (0
)
;
1408 if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE0x000800)
1409 EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW)((client)->event_handler((0x000800), (0), &(client)->
event_callback_args))
;
1410 if ((socket_table[ns]->state & SOCKET_PRESENT0x0008) &&
1411 !(socket_table[ns]->state & SOCKET_SETUP_PENDING0x0010)) {
1412 if (client->EventMask & CS_EVENT_CARD_INSERTION0x000004)
1413 EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW)((client)->event_handler((0x000004), (0), &(client)->
event_callback_args))
;
1414 else
1415 client->PendingEvents |= CS_EVENT_CARD_INSERTION0x000004;
1416 }
1417 return CS_SUCCESS0x00;
1418} /* register_client */
1419
1420/*====================================================================*/
1421
1422static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
||
1430 !(handle->state & CLIENT_CONFIG_LOCKED0x0001))
1431 return CS_BAD_HANDLE0x21;
1432 handle->state &= ~CLIENT_CONFIG_LOCKED0x0001;
1433 s = SOCKET(handle)(socket_table[(handle)->Socket]);
1434
1435#ifdef CONFIG_CARDBUS
1436 if (handle->state & CLIENT_CARDBUS0x8000) {
1437 cb_disable(s);
1438 s->lock_count = 0;
1439 return CS_SUCCESS0x00;
1440 }
1441#endif
1442
1443 if (!(handle->state & CLIENT_STALE0x0010)) {
1444 config_t *c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1445 if (--(s->lock_count) == 0) {
1446 s->socket.flags = SS_OUTPUT_ENA0x0200;
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_REQ0x04)
1452 for (i = 0; i < MAX_IO_WIN2; 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_LOCKED0x01;
1462 }
1463
1464 return CS_SUCCESS0x00;
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
1477static int release_io(client_handle_t handle, io_req_t *req)
1478{
1479 socket_info_t *s;
1480
1481 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
|| !(handle->state & CLIENT_IO_REQ0x0004))
1482 return CS_BAD_HANDLE0x21;
1483 handle->state &= ~CLIENT_IO_REQ0x0004;
1484 s = SOCKET(handle)(socket_table[(handle)->Socket]);
1485
1486#ifdef CONFIG_CARDBUS
1487 if (handle->state & CLIENT_CARDBUS0x8000) {
1488 cb_release(s);
1489 return CS_SUCCESS0x00;
1490 }
1491#endif
1492
1493 if (!(handle->state & CLIENT_STALE0x0010)) {
1494 config_t *c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1495 if (c->state & CONFIG_LOCKED0x01)
1496 return CS_CONFIGURATION_LOCKED0x1d;
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_ARGS0x1c;
1502 c->state &= ~CONFIG_IO_REQ0x04;
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_SUCCESS0x00;
1510} /* release_io */
1511
1512/*====================================================================*/
1513
1514static int cs_release_irq(client_handle_t handle, irq_req_t *req)
1515{
1516 socket_info_t *s;
1517 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
|| !(handle->state & CLIENT_IRQ_REQ0x0002))
1518 return CS_BAD_HANDLE0x21;
1519 handle->state &= ~CLIENT_IRQ_REQ0x0002;
1520 s = SOCKET(handle)(socket_table[(handle)->Socket]);
1521
1522 if (!(handle->state & CLIENT_STALE0x0010)) {
1523 config_t *c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1524 if (c->state & CONFIG_LOCKED0x01)
1525 return CS_CONFIGURATION_LOCKED0x1d;
1526 if (c->irq.Attributes != req->Attributes)
1527 return CS_BAD_ATTRIBUTE0x02;
1528 if (s->irq.AssignedIRQ != req->AssignedIRQ)
1529 return CS_BAD_IRQ0x06;
1530 if (--s->irq.Config == 0) {
1531 c->state &= ~CONFIG_IRQ_REQ0x02;
1532 s->irq.AssignedIRQ = 0;
1533 }
1534 }
1535
1536 if (req->Attributes & IRQ_HANDLE_PRESENT0x10) {
1537 bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance)free_irq((req->AssignedIRQ),(req->Instance));
1538 }
1539
1540#ifdef CONFIG_ISA1
1541 if (req->AssignedIRQ != s->cap.pci_irq)
1542 undo_irq(req->Attributes, req->AssignedIRQ);
1543#endif
1544
1545 return CS_SUCCESS0x00;
1546} /* cs_release_irq */
1547
1548/*====================================================================*/
1549
1550static int release_window(window_handle_t win)
1551{
1552 socket_info_t *s;
1553
1554 if ((win == NULL((void *) 0)) || (win->magic != WINDOW_MAGIC0xB35C))
1555 return CS_BAD_HANDLE0x21;
1556 s = win->sock;
1557 if (!(win->handle->state & CLIENT_WIN_REQ(win->index)(0x20<<(win->index))))
1558 return CS_BAD_HANDLE0x21;
1559
1560 /* Shut down memory window */
1561 win->ctl.flags &= ~MAP_ACTIVE0x01;
1562 s->ss_entry(s->sock, SS_SetMemMap, &win->ctl);
1563 s->state &= ~SOCKET_WIN_REQ(win->index)(0x0100<<(win->index));
1564
1565 /* Release system memory */
1566 release_mem_region(win->base, win->size);
1567 win->handle->state &= ~CLIENT_WIN_REQ(win->index)(0x20<<(win->index));
1568
1569 win->magic = 0;
1570
1571 return CS_SUCCESS0x00;
1572} /* release_window */
1573
1574/*====================================================================*/
1575
1576static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1586 return CS_BAD_HANDLE0x21;
1587 i = handle->Socket; s = socket_table[i];
1588 if (!(s->state & SOCKET_PRESENT0x0008))
1589 return CS_NO_CARD0x14;
1590
1591#ifdef CONFIG_CARDBUS
1592 if (handle->state & CLIENT_CARDBUS0x8000) {
1593 if (!(req->IntType & INT_CARDBUS0x04))
1594 return CS_UNSUPPORTED_MODE0x16;
1595 if (s->lock_count != 0)
1596 return CS_CONFIGURATION_LOCKED0x1d;
1597 cb_enable(s);
1598 handle->state |= CLIENT_CONFIG_LOCKED0x0001;
1599 s->lock_count++;
1600 return CS_SUCCESS0x00;
1601 }
1602#endif
1603
1604 if (req->IntType & INT_CARDBUS0x04)
1605 return CS_UNSUPPORTED_MODE0x16;
1606 c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1607 if (c->state & CONFIG_LOCKED0x01)
1608 return CS_CONFIGURATION_LOCKED0x1d;
1609
1610 /* Do power control. We don't allow changes in Vcc. */
1611 if (s->socket.Vcc != req->Vcc)
1612 printk(KERN_DEBUG"<7>" "cs: ignoring requested Vcc\n");
1613 if (req->Vpp1 != req->Vpp2)
1614 return CS_BAD_VPP0x0f;
1615 s->socket.Vpp = req->Vpp1;
1616 if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
1617 return CS_BAD_VPP0x0f;
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_IO0x02)
1625 s->socket.flags |= SS_IOCARD0x0020;
1626 if (req->IntType & INT_ZOOMED_VIDEO0x08)
1627 s->socket.flags |= SS_ZVCARD0x0400;
1628 if (req->Attributes & CONF_ENABLE_DMA0x02)
1629 s->socket.flags |= SS_DMA_MODE0x0080;
1630 if (req->Attributes & CONF_ENABLE_SPKR0x04)
1631 s->socket.flags |= SS_SPKR_ENA0x0100;
1632 if (req->Attributes & CONF_ENABLE_IRQ0x01)
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_COPY0x008) {
1643 c->Copy = req->Copy;
1644 write_cis_mem(s, 1, (base + CISREG_SCR0x06)>>1, 1, &c->Copy);
1645 }
1646 if (req->Present & PRESENT_OPTION0x001) {
1647 if (s->functions == 1) {
1648 c->Option = req->ConfigIndex & COR_CONFIG_MASK0x3f;
1649 } else {
1650 c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK0x38;
1651 c->Option |= COR_FUNC_ENA0x01|COR_IREQ_ENA0x04;
1652 if (req->Present & PRESENT_IOBASE_00x020)
1653 c->Option |= COR_ADDR_DECODE0x02;
1654 }
1655 if (c->state & CONFIG_IRQ_REQ0x02)
1656 if (!(c->irq.Attributes & IRQ_FORCED_PULSE0x04))
1657 c->Option |= COR_LEVEL_REQ0x40;
1658 write_cis_mem(s, 1, (base + CISREG_COR0x00)>>1, 1, &c->Option);
1659 mdelay(40)do { int i; for (i=0;i<40;i++) __udelay(1000); } while (0);
1660 }
1661 if (req->Present & PRESENT_STATUS0x002) {
1662 c->Status = req->Status;
1663 write_cis_mem(s, 1, (base + CISREG_CCSR0x02)>>1, 1, &c->Status);
1664 }
1665 if (req->Present & PRESENT_PIN_REPLACE0x004) {
1666 c->Pin = req->Pin;
1667 write_cis_mem(s, 1, (base + CISREG_PRR0x04)>>1, 1, &c->Pin);
1668 }
1669 if (req->Present & PRESENT_EXT_STATUS0x010) {
1670 c->ExtStatus = req->ExtStatus;
1671 write_cis_mem(s, 1, (base + CISREG_ESR0x08)>>1, 1, &c->ExtStatus);
1672 }
1673 if (req->Present & PRESENT_IOBASE_00x020) {
1674 u_char b = c->io.BasePort1 & 0xff;
1675 write_cis_mem(s, 1, (base + CISREG_IOBASE_00x0a)>>1, 1, &b);
1676 b = (c->io.BasePort1 >> 8) & 0xff;
1677 write_cis_mem(s, 1, (base + CISREG_IOBASE_10x0c)>>1, 1, &b);
1678 }
1679 if (req->Present & PRESENT_IOSIZE0x200) {
1680 u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
1681 write_cis_mem(s, 1, (base + CISREG_IOSIZE0x12)>>1, 1, &b);
1682 }
1683
1684 /* Configure I/O windows */
1685 if (c->state & CONFIG_IO_REQ0x04) {
1686 iomap.speed = io_speed;
1687 for (i = 0; i < MAX_IO_WIN2; i++)
1688 if (s->io[i].NumPorts != 0) {
1689 iomap.map = i;
1690 iomap.flags = MAP_ACTIVE0x01;
1691 switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH0x18) {
1692 case IO_DATA_PATH_WIDTH_160x08:
1693 iomap.flags |= MAP_16BIT0x02; break;
1694 case IO_DATA_PATH_WIDTH_AUTO0x10:
1695 iomap.flags |= MAP_AUTOSZ0x04; 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_LOCKED0x01;
1707 handle->state |= CLIENT_CONFIG_LOCKED0x0001;
1708 return CS_SUCCESS0x00;
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
1718static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1724 return CS_BAD_HANDLE0x21;
1725 s = SOCKET(handle)(socket_table[(handle)->Socket]);
1726 if (!(s->state & SOCKET_PRESENT0x0008))
1727 return CS_NO_CARD0x14;
1728
1729 if (handle->state & CLIENT_CARDBUS0x8000) {
1730#ifdef CONFIG_CARDBUS
1731 int ret = cb_config(s);
1732 if (ret == CS_SUCCESS0x00)
1733 handle->state |= CLIENT_IO_REQ0x0004;
1734 return ret;
1735#else
1736 return CS_UNSUPPORTED_FUNCTION0x15;
1737#endif
1738 }
1739
1740 if (!req)
1741 return CS_UNSUPPORTED_MODE0x16;
1742 c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1743 if (c->state & CONFIG_LOCKED0x01)
1744 return CS_CONFIGURATION_LOCKED0x1d;
1745 if (c->state & CONFIG_IO_REQ0x04)
1746 return CS_IN_USE0x1e;
1747 if (req->Attributes1 & (IO_SHARED0x01 | IO_FORCE_ALIAS_ACCESS0x04))
1748 return CS_BAD_ATTRIBUTE0x02;
1749 if ((req->NumPorts2 > 0) &&
1750 (req->Attributes2 & (IO_SHARED0x01 | IO_FORCE_ALIAS_ACCESS0x04)))
1751 return CS_BAD_ATTRIBUTE0x02;
1752
1753 if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
1754 req->NumPorts1, req->IOAddrLines,
1755 handle->dev_info))
1756 return CS_IN_USE0x1e;
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_USE0x1e;
1764 }
1765 }
1766
1767 c->io = *req;
1768 c->state |= CONFIG_IO_REQ0x04;
1769 handle->state |= CLIENT_IO_REQ0x0004;
1770 return CS_SUCCESS0x00;
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
1784static 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_USE0x1e, irq = 0;
1789
1790 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1791 return CS_BAD_HANDLE0x21;
1792 s = SOCKET(handle)(socket_table[(handle)->Socket]);
1793 if (!(s->state & SOCKET_PRESENT0x0008))
1794 return CS_NO_CARD0x14;
1795 c = CONFIG(handle)(&(socket_table[(handle)->Socket])->config[(handle)
->Function])
;
1796 if (c->state & CONFIG_LOCKED0x01)
1797 return CS_CONFIGURATION_LOCKED0x1d;
1798 if (c->state & CONFIG_IRQ_REQ0x02)
1799 return CS_IN_USE0x1e;
1800
1801#ifdef CONFIG_ISA1
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_VALID0x10) {
1806 u_int mask = req->IRQInfo2 & s->cap.irq_mask;
1807 ret = ((mask >> irq) & 1) ? 0 : CS_BAD_ARGS0x1c;
1808 } else
1809 ret = ((req->IRQInfo1&IRQ_MASK0x0f) == irq) ? 0 : CS_BAD_ARGS0x1c;
1810 } else {
1811 if (req->IRQInfo1 & IRQ_INFO2_VALID0x10) {
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_MASK0x0f;
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_PRESENT0x10) {
1834 if (bus_request_irq(s->cap.bus, irq, req->Handler,request_irq((irq),(req->Handler),(((req->Attributes &
0x02) || (s->functions > 1) || (irq == s->cap.pci_irq
)) ? 0x04000000 : 0),(handle->dev_info),(req->Instance)
)
1835 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||request_irq((irq),(req->Handler),(((req->Attributes &
0x02) || (s->functions > 1) || (irq == s->cap.pci_irq
)) ? 0x04000000 : 0),(handle->dev_info),(req->Instance)
)
1836 (s->functions > 1) ||request_irq((irq),(req->Handler),(((req->Attributes &
0x02) || (s->functions > 1) || (irq == s->cap.pci_irq
)) ? 0x04000000 : 0),(handle->dev_info),(req->Instance)
)
1837 (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0,request_irq((irq),(req->Handler),(((req->Attributes &
0x02) || (s->functions > 1) || (irq == s->cap.pci_irq
)) ? 0x04000000 : 0),(handle->dev_info),(req->Instance)
)
1838 handle->dev_info, req->Instance)request_irq((irq),(req->Handler),(((req->Attributes &
0x02) || (s->functions > 1) || (irq == s->cap.pci_irq
)) ? 0x04000000 : 0),(handle->dev_info),(req->Instance)
)
)
1839 return CS_IN_USE0x1e;
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_REQ0x02;
1847 handle->state |= CLIENT_IRQ_REQ0x0002;
1848 return CS_SUCCESS0x00;
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
1858static 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)(((*handle) == ((void *) 0)) || ((*handle)->client_magic !=
0x51E6))
)
1866 return CS_BAD_HANDLE0x21;
1867 s = SOCKET(*handle)(socket_table[(*handle)->Socket]);
1868 if (!(s->state & SOCKET_PRESENT0x0008))
1869 return CS_NO_CARD0x14;
1870 if (req->Attributes & (WIN_PAGED0x0020 | WIN_SHARED0x0040))
1871 return CS_BAD_ATTRIBUTE0x02;
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_ALIGN0x0004) ||
1877 (req->Attributes & WIN_STRICT_ALIGN0x0200)) ?
1878 req->Size : s->cap.map_size);
1879 if (req->Size & (s->cap.map_size-1))
1880 return CS_BAD_SIZE0x0a;
1881 if ((req->Base && (s->cap.features & SS_CAP_STATIC_MAP0x0008)) ||
1882 (req->Base & (align-1)))
1883 return CS_BAD_BASE0x03;
1884 if (req->Base)
1885 align = 0;
1886
1887 /* Allocate system memory window */
1888 for (w = 0; w < MAX_WIN4; w++)
1889 if (!(s->state & SOCKET_WIN_REQ(w)(0x0100<<(w)))) break;
1890 if (w == MAX_WIN4)
1891 return CS_OUT_OF_RESOURCE0x20;
1892
1893 win = &s->win[w];
1894 win->magic = WINDOW_MAGIC0xB35C;
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_MAP0x0008) &&
1902 find_mem_region(&win->base, win->size, align,
1903 (req->Attributes & WIN_MAP_BELOW_1MB0x0400) ||
1904 !(s->cap.features & SS_CAP_PAGE_REGS0x0001),
1905 (*handle)->dev_info))
1906 return CS_IN_USE0x1e;
1907 (*handle)->state |= CLIENT_WIN_REQ(w)(0x20<<(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_TYPE0x0002)
1914 win->ctl.flags |= MAP_ATTRIB0x20;
1915 if (req->Attributes & WIN_ENABLE0x0004)
1916 win->ctl.flags |= MAP_ACTIVE0x01;
1917 if (req->Attributes & WIN_DATA_WIDTH_160x0008)
1918 win->ctl.flags |= MAP_16BIT0x02;
1919 if (req->Attributes & WIN_USE_WAIT0x0100)
1920 win->ctl.flags |= MAP_USE_WAIT0x40;
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_ARGS0x1c;
1926 s->state |= SOCKET_WIN_REQ(w)(0x0100<<(w));
1927
1928 /* Return window handle */
1929 req->Base = win->ctl.sys_start;
1930 *handle = (client_handle_t)win;
1931
1932 return CS_SUCCESS0x00;
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
1943static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1949 return CS_BAD_HANDLE0x21;
1950 i = handle->Socket; s = socket_table[i];
1951 if (!(s->state & SOCKET_PRESENT0x0008))
1952 return CS_NO_CARD0x14;
1953 if (s->state & SOCKET_RESET_PENDING0x0040)
1954 return CS_IN_USE0x1e;
1955 s->state |= SOCKET_RESET_PENDING0x0040;
1956
1957 ret = send_event(s, CS_EVENT_RESET_REQUEST0x000100, CS_EVENT_PRI_LOW0);
1958 if (ret != 0) {
1959 s->state &= ~SOCKET_RESET_PENDING0x0040;
1960 handle->event_callback_args.info = (void *)(u_long)ret;
1961 EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW)((handle)->event_handler((0x001000), (0), &(handle)->
event_callback_args))
;
1962 } else {
1963 DEBUG(1, "cs: resetting socket %d\n", i)do { if (pc_debug>(1)) printk("<7>" "cs: resetting socket %d\n"
, i); } while (0)
;
1964 send_event(s, CS_EVENT_RESET_PHYSICAL0x000200, CS_EVENT_PRI_LOW0);
1965 s->reset_handle = handle;
1966 reset_socket(i);
1967 }
1968 return CS_SUCCESS0x00;
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
1978static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1984 return CS_BAD_HANDLE0x21;
1985 i = handle->Socket; s = socket_table[i];
1986 if (!(s->state & SOCKET_PRESENT0x0008))
1987 return CS_NO_CARD0x14;
1988 if (s->state & SOCKET_SUSPEND0x0080)
1989 return CS_IN_USE0x1e;
1990
1991 DEBUG(1, "cs: suspending socket %d\n", i)do { if (pc_debug>(1)) printk("<7>" "cs: suspending socket %d\n"
, i); } while (0)
;
1992 send_event(s, CS_EVENT_PM_SUSPEND0x002000, CS_EVENT_PRI_LOW0);
1993 s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
1994 s->state |= SOCKET_SUSPEND0x0080;
1995
1996 return CS_SUCCESS0x00;
1997} /* suspend_card */
1998
1999static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
2005 return CS_BAD_HANDLE0x21;
2006 i = handle->Socket; s = socket_table[i];
2007 if (!(s->state & SOCKET_PRESENT0x0008))
2008 return CS_NO_CARD0x14;
2009 if (!(s->state & SOCKET_SUSPEND0x0080))
2010 return CS_IN_USE0x1e;
2011
2012 DEBUG(1, "cs: waking up socket %d\n", i)do { if (pc_debug>(1)) printk("<7>" "cs: waking up socket %d\n"
, i); } while (0)
;
2013 setup_socket(i);
2014
2015 return CS_SUCCESS0x00;
2016} /* resume_card */
2017
2018/*======================================================================
2019
2020 These handle user requests to eject or insert a card.
2021
2022======================================================================*/
2023
2024static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
2031 return CS_BAD_HANDLE0x21;
2032 i = handle->Socket; s = socket_table[i];
2033 if (!(s->state & SOCKET_PRESENT0x0008))
2034 return CS_NO_CARD0x14;
2035
2036 DEBUG(1, "cs: user eject request on socket %d\n", i)do { if (pc_debug>(1)) printk("<7>" "cs: user eject request on socket %d\n"
, i); } while (0)
;
2037
2038 ret = send_event(s, CS_EVENT_EJECTION_REQUEST0x010000, CS_EVENT_PRI_LOW0);
2039 if (ret != 0)
2040 return ret;
2041
2042 spin_lock_irqsave(&s->lock, flags)do { __asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory"
); __asm__ __volatile__ ("cli": : :"memory"); } while (0)
;
2043 do_shutdown(s);
2044 spin_unlock_irqrestore(&s->lock, flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory");
2045
2046 return CS_SUCCESS0x00;
2047
2048} /* eject_card */
2049
2050static 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
2057 return CS_BAD_HANDLE0x21;
2058 i = handle->Socket; s = socket_table[i];
2059 if (s->state & SOCKET_PRESENT0x0008)
2060 return CS_IN_USE0x1e;
2061
2062 DEBUG(1, "cs: user insert request on socket %d\n", i)do { if (pc_debug>(1)) printk("<7>" "cs: user insert request on socket %d\n"
, i); } while (0)
;
2063
2064 spin_lock_irqsave(&s->lock, flags)do { __asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory"
); __asm__ __volatile__ ("cli": : :"memory"); } while (0)
;
2065 if (!(s->state & SOCKET_SETUP_PENDING0x0010)) {
2066 s->state |= SOCKET_SETUP_PENDING0x0010;
2067 spin_unlock_irqrestore(&s->lock, flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory");
2068 s->ss_entry(i, SS_GetStatus, &status);
2069 if (status & SS_DETECT0x0080)
2070 setup_socket(i);
2071 else {
2072 s->state &= ~SOCKET_SETUP_PENDING0x0010;
2073 return CS_NO_CARD0x14;
2074 }
2075 } else
2076 spin_unlock_irqrestore(&s->lock, flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory");
2077
2078 return CS_SUCCESS0x00;
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
2088static int set_event_mask(client_handle_t handle, eventmask_t *mask)
2089{
2090 u_int events, bit;
2091 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
2092 return CS_BAD_HANDLE0x21;
2093 if (handle->Attributes & CONF_EVENT_MASK_VALID0x01)
2094 return CS_BAD_SOCKET0x0b;
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)((handle)->event_handler((bit), (0), &(handle)->event_callback_args
))
;
2101 events -= bit;
2102 }
2103 return CS_SUCCESS0x00;
2104} /* set_event_mask */
2105
2106/*====================================================================*/
2107
2108static int report_error(client_handle_t handle, error_info_t *err)
2109{
2110 int i;
2111 char *serv;
2112
2113 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
2114 printk(KERN_NOTICE"<5>");
2115 else
2116 printk(KERN_NOTICE"<5>" "%s: ", handle->dev_info);
2117
2118 for (i = 0; i < SERVICE_COUNT(sizeof(service_table)/sizeof(lookup_t)); i++)
2119 if (service_table[i].key == err->func) break;
2120 if (i < SERVICE_COUNT(sizeof(service_table)/sizeof(lookup_t)))
2121 serv = service_table[i].msg;
2122 else
2123 serv = "Unknown service number";
2124
2125 for (i = 0; i < ERROR_COUNT(sizeof(error_table)/sizeof(lookup_t)); i++)
2126 if (error_table[i].key == err->retcode) break;
2127 if (i < ERROR_COUNT(sizeof(error_table)/sizeof(lookup_t)))
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_SUCCESS0x00;
2133} /* report_error */
2134
2135/*====================================================================*/
2136
2137int CardServices(int func, void *a1, void *a2, void *a3)
2138{
2139
2140#ifdef PCMCIA_DEBUG4
2141 if (pc_debug > 2) {
2142 int i;
2143 for (i = 0; i < SERVICE_COUNT(sizeof(service_table)/sizeof(lookup_t)); i++)
2144 if (service_table[i].key == func) break;
2145 if (i < SERVICE_COUNT(sizeof(service_table)/sizeof(lookup_t)))
2146 printk(KERN_DEBUG"<7>" "cs: CardServices(%s, 0x%p, 0x%p)\n",
2147 service_table[i].msg, a1, a2);
2148 else
2149 printk(KERN_DEBUG"<7>" "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_FUNCTION0x15; 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_CODE131108 <= VERSION(2,1,17)(((2)<<16)+(1<<8)+17))
2267
2268#undef CONFIG_MODVERSIONS
2269static struct symbol_table cs_symtab = {
2270#include <linux/symtab_begin.h>
2271#undef X
2272#define X(sym) { (void *)&sym, SYMBOL_NAME_STR(sym)"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_PCI1
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
2301EXPORT_SYMBOL(register_ss_entry);
2302EXPORT_SYMBOL(unregister_ss_entry);
2303EXPORT_SYMBOL(CardServices);
2304EXPORT_SYMBOL(MTDHelperEntry);
2305#ifdef HAS_PROC_BUS
2306EXPORT_SYMBOL(proc_pccard);
2307#endif
2308#ifndef HAVE_MEMRESERVE
2309EXPORT_SYMBOL(request_mem_region);
2310EXPORT_SYMBOL(release_mem_region);
2311#endif
2312#ifdef CONFIG_PNP_BIOS
2313EXPORT_SYMBOL(check_pnp_irq);
2314#endif
2315#ifdef CONFIG_PCI1
2316EXPORT_SYMBOL(pci_irq_mask);
2317#if (LINUX_VERSION_CODE131108 < VERSION(2,3,24)(((2)<<16)+(3<<8)+24))
2318EXPORT_SYMBOL(pci_enable_device);
2319EXPORT_SYMBOL(pci_set_power_state);
2320#endif
2321#endif
2322
2323#endif
2324
2325int __init init_pcmcia_cs(void)
2326{
2327 printk(KERN_INFO"<6>" "%s\n", release);
2328#ifdef UTS_RELEASE"2.0.36"
2329 printk(KERN_INFO"<6>" " %s\n", kernel);
2330#endif
2331 printk(KERN_INFO"<6>" " %s\n", options);
2332 DEBUG(0, "%s\n", version)do { if (pc_debug>(0)) printk("<7>" "%s\n", version)
; } while (0)
;
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_PCI1
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((void *) 0));
2354 create_proc_read_entry("irq", 0, proc_pccard,
2355 proc_read_irq, NULL((void *) 0));
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((void *) 0));
2362#endif
2363#endif
2364 return 0;
2365}
2366
2367static void __exit__attribute__((__used__)) __attribute__((no_instrument_function
))
exit_pcmcia_cs(void)
2368{
2369 printk(KERN_INFO"<6>" "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_PCI1
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
2398module_init(init_pcmcia_cs)void pcmcia_modinit_pcmcia_cs (void) { init_pcmcia_cs(); return
; }
;
2399module_exit(exit_pcmcia_cs);