Bug Summary

File:obj-scan-build/../linux/pcmcia-cs/modules/ds.c
Location:line 317, column 5
Description:Value stored to 'i' is never read

Annotated Source Code

1/*======================================================================
2
3 PC Card Driver Services
4
5 ds.c 1.115 2002/10/12 19:03:44
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/major.h>
38#include <linux/string.h>
39#include <linux/errno.h>
40#include <linux/slab.h>
41#include <linux/mm.h>
42#include <linux/fcntl.h>
43#include <linux/sched.h>
44#include <linux/timer.h>
45#include <linux/ioctl.h>
46#include <linux/proc_fs.h>
47#if (LINUX_VERSION_CODE131108 >= KERNEL_VERSION(2,1,23)(((2)<<16)+(1<<8)+23))
48#include <linux/poll.h>
49#endif
50
51/*
52 * <pcmcia/cs.h> defines io_req_t which is not used in this file, but
53 * which clashes with the io_req_t needed for the Mach devices. Rename
54 * it to cardservice_io_req_t to avoid this clash.
55 */
56#define io_req_t cardservice_io_req_t
57#include <pcmcia/version.h>
58#include <pcmcia/cs_types.h>
59#include <pcmcia/cs.h>
60#include <pcmcia/bulkmem.h>
61#include <pcmcia/cistpl.h>
62#include <pcmcia/ds.h>
63#undef io_req_t
64
65/*====================================================================*/
66
67/* Module parameters */
68
69MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
70MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
71MODULE_LICENSE("Dual MPL/GPL");
72
73#define INT_MODULE_PARM(n, v)static int n = v; static int n = v; MODULE_PARM(n, "i")
74
75#ifdef PCMCIA_DEBUG4
76INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG)static int pc_debug = 4;;
77#define DEBUG(n, args...)if (pc_debug>(n)) printk("<7>" args...) if (pc_debug>(n)) printk(KERN_DEBUG"<7>" args)
78static const char *version =
79"ds.c 1.115 2002/10/12 19:03:44 (David Hinds)";
80#else
81#define DEBUG(n, args...)if (pc_debug>(n)) printk("<7>" args...)
82#endif
83
84/*====================================================================*/
85
86typedef struct driver_info_t {
87 dev_info_t dev_info;
88 int use_count, status;
89 dev_link_t *(*attach)(void);
90 void (*detach)(dev_link_t *);
91 struct driver_info_t *next;
92} driver_info_t;
93
94typedef struct socket_bind_t {
95 driver_info_t *driver;
96 u_char function;
97 dev_link_t *instance;
98 struct socket_bind_t *next;
99} socket_bind_t;
100
101/* Device user information */
102#define MAX_EVENTS32 32
103#define USER_MAGIC0x7ea4 0x7ea4
104#define CHECK_USER(u)(((u) == ((void *) 0)) || ((u)->user_magic != 0x7ea4)) \
105 (((u) == NULL((void *) 0)) || ((u)->user_magic != USER_MAGIC0x7ea4))
106typedef struct user_info_t {
107 u_int user_magic;
108 int event_head, event_tail;
109 event_t event[MAX_EVENTS32];
110 struct user_info_t *next;
111} user_info_t;
112
113/* Socket state information */
114typedef struct socket_info_t {
115 client_handle_t handle;
116 int state;
117 user_info_t *user;
118 int req_pending, req_result;
119 wait_queue_head_t queue, request;
120 struct timer_list removal;
121 socket_bind_t *bind;
122} socket_info_t;
123
124#define SOCKET_PRESENT0x01 0x01
125#define SOCKET_BUSY0x02 0x02
126#define SOCKET_REMOVAL_PENDING0x10 0x10
127
128/*====================================================================*/
129
130/* Device driver ID passed to Card Services */
131static dev_info_t dev_info = "Driver Services";
132
133/* Linked list of all registered device drivers */
134static driver_info_t *root_driver = NULL((void *) 0);
135
136static int sockets = 0, major_dev = -1;
137static socket_info_t *socket_table = NULL((void *) 0);
138
139extern struct proc_dir_entry *proc_pccard;
140
141/* We use this to distinguish in-kernel from modular drivers */
142static int init_status = 1;
143
144/*====================================================================*/
145
146static void cs_error(client_handle_t handle, int func, int ret)
147{
148 error_info_t err = { func, ret };
149 CardServices(ReportError, handle, &err);
150}
151
152/*======================================================================
153
154 Register_pccard_driver() and unregister_pccard_driver() are used
155 tell Driver Services that a PC Card client driver is available to
156 be bound to sockets.
157
158======================================================================*/
159
160int register_pccard_driver(dev_info_t *dev_info,
161 dev_link_t *(*attach)(void),
162 void (*detach)(dev_link_t *))
163{
164 driver_info_t *driver;
165 socket_bind_t *b;
166 int i;
167
168 DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info)if (pc_debug>(0)) printk("<7>" "ds: register_pccard_driver('%s')\n"
, (char *)dev_info)
;
169 for (driver = root_driver; driver; driver = driver->next)
170 if (strncmp((char *)dev_info, (char *)driver->dev_info,
171 DEV_NAME_LEN32) == 0)
172 break;
173 if (!driver) {
174 driver = kmalloclinux_kmalloc(sizeof(driver_info_t), GFP_KERNEL0x03);
175 if (!driver) return -ENOMEM12;
176 strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN32);
177 driver->use_count = 0;
178 driver->status = init_status;
179 driver->next = root_driver;
180 root_driver = driver;
181 }
182
183 driver->attach = attach;
184 driver->detach = detach;
185 if (driver->use_count == 0) return 0;
186
187 /* Instantiate any already-bound devices */
188 for (i = 0; i < sockets; i++)
189 for (b = socket_table[i].bind; b; b = b->next) {
190 if (b->driver != driver) continue;
191 b->instance = driver->attach();
192 if (b->instance == NULL((void *) 0))
193 printk(KERN_NOTICE"<5>" "ds: unable to create instance "
194 "of '%s'!\n", driver->dev_info);
195 }
196
197 return 0;
198} /* register_pccard_driver */
199
200/*====================================================================*/
201
202int unregister_pccard_driver(dev_info_t *dev_info)
203{
204 driver_info_t *target, **d = &root_driver;
205 socket_bind_t *b;
206 int i;
207
208 DEBUG(0, "ds: unregister_pccard_driver('%s')\n",if (pc_debug>(0)) printk("<7>" "ds: unregister_pccard_driver('%s')\n"
, (char *)dev_info)
209 (char *)dev_info)if (pc_debug>(0)) printk("<7>" "ds: unregister_pccard_driver('%s')\n"
, (char *)dev_info)
;
210 while ((*d) && (strncmp((*d)->dev_info, (char *)dev_info,
211 DEV_NAME_LEN32) != 0))
212 d = &(*d)->next;
213 if (*d == NULL((void *) 0))
214 return -ENODEV19;
215
216 target = *d;
217 if (target->use_count == 0) {
218 *d = target->next;
219 kfree(target);
220 } else {
221 /* Blank out any left-over device instances */
222 target->attach = NULL((void *) 0); target->detach = NULL((void *) 0);
223 for (i = 0; i < sockets; i++)
224 for (b = socket_table[i].bind; b; b = b->next)
225 if (b->driver == target) b->instance = NULL((void *) 0);
226 }
227 return 0;
228} /* unregister_pccard_driver */
229
230/*====================================================================*/
231
232#ifdef HAS_PROC_BUS
233static int proc_read_drivers(char *buf, char **start, off_t pos,
234 int count, int *eof, void *data)
235{
236 driver_info_t *d;
237 char *p = buf;
238 for (d = root_driver; d; d = d->next)
239 p += sprintflinux_sprintf(p, "%-24.24s %d %d\n", d->dev_info,
240 d->status, d->use_count);
241 return (p - buf);
242}
243#endif
244
245/*======================================================================
246
247 These manage a ring buffer of events pending for one user process
248
249======================================================================*/
250
251static int queue_empty(user_info_t *user)
252{
253 return (user->event_head == user->event_tail);
254}
255
256static event_t get_queued_event(user_info_t *user)
257{
258 user->event_tail = (user->event_tail+1) % MAX_EVENTS32;
259 return user->event[user->event_tail];
260}
261
262static void queue_event(user_info_t *user, event_t event)
263{
264 user->event_head = (user->event_head+1) % MAX_EVENTS32;
265 if (user->event_head == user->event_tail)
266 user->event_tail = (user->event_tail+1) % MAX_EVENTS32;
267 user->event[user->event_head] = event;
268}
269
270static void handle_event(socket_info_t *s, event_t event)
271{
272 user_info_t *user;
273 for (user = s->user; user; user = user->next)
274 queue_event(user, event);
275 wake_up_interruptiblewake_up(&s->queue);
276}
277
278static int handle_request(socket_info_t *s, event_t event)
279{
280 if (s->req_pending != 0)
281 return CS_IN_USE0x1e;
282 if (s->state & SOCKET_BUSY0x02)
283 s->req_pending = 1;
284 handle_event(s, event);
285 if (s->req_pending > 0) {
286 interruptible_sleep_on(&s->request);
287 if (signal_pending(current)0)
288 return CS_IN_USE0x1e;
289 else
290 return s->req_result;
291 }
292 return CS_SUCCESS0x00;
293}
294
295static void handle_removal(u_long sn)
296{
297 socket_info_t *s = &socket_table[sn];
298 handle_event(s, CS_EVENT_CARD_REMOVAL0x000008);
299 s->state &= ~SOCKET_REMOVAL_PENDING0x10;
300}
301
302/*======================================================================
303
304 The card status event handler.
305
306======================================================================*/
307
308static int ds_event(event_t event, int priority,
309 event_callback_args_t *args)
310{
311 socket_info_t *s;
312 int i;
313
314 DEBUG(1, "ds: ds_event(0x%06x, %d, 0x%p)\n",if (pc_debug>(1)) printk("<7>" "ds: ds_event(0x%06x, %d, 0x%p)\n"
, event, priority, args->client_handle)
315 event, priority, args->client_handle)if (pc_debug>(1)) printk("<7>" "ds: ds_event(0x%06x, %d, 0x%p)\n"
, event, priority, args->client_handle)
;
316 s = args->client_data;
317 i = s - socket_table;
Value stored to 'i' is never read
318
319 switch (event) {
320
321 case CS_EVENT_CARD_REMOVAL0x000008:
322 s->state &= ~SOCKET_PRESENT0x01;
323 if (!(s->state & SOCKET_REMOVAL_PENDING0x10)) {
324 s->state |= SOCKET_REMOVAL_PENDING0x10;
325 s->removal.expires = jiffies + HZ100/10;
326 add_timer(&s->removal);
327 }
328 break;
329
330 case CS_EVENT_CARD_INSERTION0x000004:
331 s->state |= SOCKET_PRESENT0x01;
332 handle_event(s, event);
333 break;
334
335 case CS_EVENT_EJECTION_REQUEST0x010000:
336 return handle_request(s, event);
337 break;
338
339 default:
340 handle_event(s, event);
341 break;
342 }
343
344 return 0;
345} /* ds_event */
346
347/*======================================================================
348
349 bind_mtd() connects a memory region with an MTD client.
350
351======================================================================*/
352
353static int bind_mtd(int i, mtd_info_t *mtd_info)
354{
355 mtd_bind_t bind_req;
356 int ret;
357
358 bind_req.dev_info = &mtd_info->dev_info;
359 bind_req.Attributes = mtd_info->Attributes;
360 bind_req.Socket = i;
361 bind_req.CardOffset = mtd_info->CardOffset;
362 ret = CardServices(BindMTD, &bind_req);
363 if (ret != CS_SUCCESS0x00) {
364 cs_error(NULL((void *) 0), BindMTD, ret);
365 printk(KERN_NOTICE"<5>" "ds: unable to bind MTD '%s' to socket %d"
366 " offset 0x%x\n",
367 (char *)bind_req.dev_info, i, bind_req.CardOffset);
368 return -ENODEV19;
369 }
370 return 0;
371} /* bind_mtd */
372
373/*======================================================================
374
375 bind_request() connects a socket to a particular client driver.
376 It looks up the specified device ID in the list of registered
377 drivers, binds it to the socket, and tries to create an instance
378 of the device. unbind_request() deletes a driver instance.
379
380======================================================================*/
381
382static int bind_request(int i, bind_info_t *bind_info)
383{
384 struct driver_info_t *driver;
385 socket_bind_t *b;
386 bind_req_t bind_req;
387 socket_info_t *s = &socket_table[i];
388 int ret;
389
390 DEBUG(2, "bind_request(%d, '%s')\n", i,if (pc_debug>(2)) printk("<7>" "bind_request(%d, '%s')\n"
, i, (char *)bind_info->dev_info)
391 (char *)bind_info->dev_info)if (pc_debug>(2)) printk("<7>" "bind_request(%d, '%s')\n"
, i, (char *)bind_info->dev_info)
;
392 for (driver = root_driver; driver; driver = driver->next)
393 if (strcmp((char *)driver->dev_info,
394 (char *)bind_info->dev_info) == 0)
395 break;
396 if (driver == NULL((void *) 0)) {
397 driver = kmalloclinux_kmalloc(sizeof(driver_info_t), GFP_KERNEL0x03);
398 if (!driver) return -ENOMEM12;
399 strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN32);
400 driver->use_count = 0;
401 driver->next = root_driver;
402 driver->attach = NULL((void *) 0); driver->detach = NULL((void *) 0);
403 root_driver = driver;
404 }
405
406 for (b = s->bind; b; b = b->next)
407 if ((driver == b->driver) &&
408 (bind_info->function == b->function))
409 break;
410 if (b != NULL((void *) 0)) {
411 bind_info->instance = b->instance;
412 return -EBUSY16;
413 }
414 b = kmalloclinux_kmalloc(sizeof(socket_bind_t), GFP_KERNEL0x03);
415 if (!b)
416 return -ENOMEM12;
417
418 bind_req.Socket = i;
419 bind_req.Function = bind_info->function;
420 bind_req.dev_info = &driver->dev_info;
421 ret = CardServices(BindDevice, &bind_req);
422 if (ret != CS_SUCCESS0x00) {
423 cs_error(NULL((void *) 0), BindDevice, ret);
424 printk(KERN_NOTICE"<5>" "ds: unable to bind '%s' to socket %d\n",
425 (char *)dev_info, i);
426 kfree(b);
427 return -ENODEV19;
428 }
429
430 /* Add binding to list for this socket */
431 driver->use_count++;
432 b->driver = driver;
433 b->function = bind_info->function;
434 b->instance = NULL((void *) 0);
435 b->next = s->bind;
436 s->bind = b;
437
438 if (driver->attach) {
439 b->instance = driver->attach();
440 if (b->instance == NULL((void *) 0)) {
441 printk(KERN_NOTICE"<5>" "ds: unable to create instance "
442 "of '%s'!\n", (char *)bind_info->dev_info);
443 return -ENODEV19;
444 }
445 }
446
447 return 0;
448} /* bind_request */
449
450/*====================================================================*/
451
452static int get_device_info(int i, bind_info_t *bind_info, int first)
453{
454 socket_info_t *s = &socket_table[i];
455 socket_bind_t *b;
456 dev_node_t *node;
457
458 for (b = s->bind; b; b = b->next)
459 if ((strcmp((char *)b->driver->dev_info,
460 (char *)bind_info->dev_info) == 0) &&
461 (b->function == bind_info->function))
462 break;
463 if (b == NULL((void *) 0)) return -ENODEV19;
464 if ((b->instance == NULL((void *) 0)) ||
465 (b->instance->state & DEV_CONFIG_PENDING0x10))
466 return -EAGAIN11;
467 if (first)
468 node = b->instance->dev;
469 else
470 for (node = b->instance->dev; node; node = node->next)
471 if (node == bind_info->next) break;
472 if (node == NULL((void *) 0)) return -ENODEV19;
473
474 strncpy(bind_info->name, node->dev_name, DEV_NAME_LEN32);
475 bind_info->name[DEV_NAME_LEN32-1] = '\0';
476 bind_info->major = node->major;
477 bind_info->minor = node->minor;
478 bind_info->next = node->next;
479
480 return 0;
481} /* get_device_info */
482
483/*====================================================================*/
484
485static int unbind_request(int i, bind_info_t *bind_info)
486{
487 socket_info_t *s = &socket_table[i];
488 socket_bind_t **b, *c;
489
490 DEBUG(2, "unbind_request(%d, '%s')\n", i,if (pc_debug>(2)) printk("<7>" "unbind_request(%d, '%s')\n"
, i, (char *)bind_info->dev_info)
491 (char *)bind_info->dev_info)if (pc_debug>(2)) printk("<7>" "unbind_request(%d, '%s')\n"
, i, (char *)bind_info->dev_info)
;
492 for (b = &s->bind; *b; b = &(*b)->next)
493 if ((strcmp((char *)(*b)->driver->dev_info,
494 (char *)bind_info->dev_info) == 0) &&
495 ((*b)->function == bind_info->function))
496 break;
497 if (*b == NULL((void *) 0))
498 return -ENODEV19;
499
500 c = *b;
501 c->driver->use_count--;
502 if (c->driver->detach) {
503 if (c->instance)
504 c->driver->detach(c->instance);
505 } else {
506 if (c->driver->use_count == 0) {
507 driver_info_t **d;
508 for (d = &root_driver; *d; d = &((*d)->next))
509 if (c->driver == *d) break;
510 *d = (*d)->next;
511 kfree(c->driver);
512 }
513 }
514 *b = c->next;
515 kfree(c);
516
517 return 0;
518} /* unbind_request */
519
520/*======================================================================
521
522 The user-mode PC Card device interface
523
524======================================================================*/
525
526/* Disable all the ds filesystem operations. */
527#ifndef MACH1
528
529static int ds_open(struct inode *inode, struct file *file)
530{
531 socket_t i = MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1));
532 socket_info_t *s;
533 user_info_t *user;
534
535 DEBUG(0, "ds_open(socket %d)\n", i)if (pc_debug>(0)) printk("<7>" "ds_open(socket %d)\n"
, i)
;
536 if ((i >= sockets) || (sockets == 0))
537 return -ENODEV19;
538 s = &socket_table[i];
539 if ((file->f_flags & O_ACCMODE0003) != O_RDONLY00) {
540 if (s->state & SOCKET_BUSY0x02)
541 return -EBUSY16;
542 else
543 s->state |= SOCKET_BUSY0x02;
544 }
545
546 MOD_INC_USE_COUNTdo { } while (0);
547 user = kmalloclinux_kmalloc(sizeof(user_info_t), GFP_KERNEL0x03);
548 if (!user) {
549 MOD_DEC_USE_COUNTdo { } while (0);
550 return -ENOMEM12;
551 }
552 user->event_tail = user->event_head = 0;
553 user->next = s->user;
554 user->user_magic = USER_MAGIC0x7ea4;
555 s->user = user;
556 file->private_data = user;
557
558 if (s->state & SOCKET_PRESENT0x01)
559 queue_event(user, CS_EVENT_CARD_INSERTION0x000004);
560 return 0;
561} /* ds_open */
562
563/*====================================================================*/
564
565static FS_RELEASE_T ds_release(struct inode *inode, struct file *file)
566{
567 socket_t i = MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1));
568 socket_info_t *s;
569 user_info_t *user, **link;
570
571 DEBUG(0, "ds_release(socket %d)\n", i)if (pc_debug>(0)) printk("<7>" "ds_release(socket %d)\n"
, i)
;
572 if ((i >= sockets) || (sockets == 0))
573 return (FS_RELEASE_T)0;
574 s = &socket_table[i];
575 user = file->private_data;
576 if (CHECK_USER(user)(((user) == ((void *) 0)) || ((user)->user_magic != 0x7ea4
))
)
577 return (FS_RELEASE_T)0;
578
579 /* Unlink user data structure */
580 if ((file->f_flags & O_ACCMODE0003) != O_RDONLY00)
581 s->state &= ~SOCKET_BUSY0x02;
582 file->private_data = NULL((void *) 0);
583 for (link = &s->user; *link; link = &(*link)->next)
584 if (*link == user) break;
585 if (link == NULL((void *) 0))
586 return (FS_RELEASE_T)0;
587 *link = user->next;
588 user->user_magic = 0;
589 kfree(user);
590
591 MOD_DEC_USE_COUNTdo { } while (0);
592 return (FS_RELEASE_T)0;
593} /* ds_release */
594
595/*====================================================================*/
596
597static ssize_t ds_read FOPS(struct inode *inode,
598 struct file *file, char *buf,
599 size_t count, loff_t *ppos)
600{
601 socket_t i = MINOR(F_INODE(file)->i_rdev)((F_INODE(file)->i_rdev) & ((1<<8) - 1));
602 socket_info_t *s;
603 user_info_t *user;
604
605 DEBUG(2, "ds_read(socket %d)\n", i)if (pc_debug>(2)) printk("<7>" "ds_read(socket %d)\n"
, i)
;
606
607 if ((i >= sockets) || (sockets == 0))
608 return -ENODEV19;
609 if (count < 4)
610 return -EINVAL22;
611 s = &socket_table[i];
612 user = file->private_data;
613 if (CHECK_USER(user)(((user) == ((void *) 0)) || ((user)->user_magic != 0x7ea4
))
)
614 return -EIO5;
615
616 if (queue_empty(user)) {
617 interruptible_sleep_on(&s->queue);
618 if (signal_pending(current)0)
619 return -EINTR4;
620 }
621 put_user(get_queued_event(user), (int *)buf)__put_user((unsigned long)(get_queued_event(user)),((int *)buf
),sizeof(*((int *)buf)))
;
622 return 4;
623} /* ds_read */
624
625/*====================================================================*/
626
627static ssize_t ds_write FOPS(struct inode *inode,
628 struct file *file, const char *buf,
629 size_t count, loff_t *ppos)
630{
631 socket_t i = MINOR(F_INODE(file)->i_rdev)((F_INODE(file)->i_rdev) & ((1<<8) - 1));
632 socket_info_t *s;
633 user_info_t *user;
634
635 DEBUG(2, "ds_write(socket %d)\n", i)if (pc_debug>(2)) printk("<7>" "ds_write(socket %d)\n"
, i)
;
636
637 if ((i >= sockets) || (sockets == 0))
638 return -ENODEV19;
639 if (count != 4)
640 return -EINVAL22;
641 if ((file->f_flags & O_ACCMODE0003) == O_RDONLY00)
642 return -EBADF9;
643 s = &socket_table[i];
644 user = file->private_data;
645 if (CHECK_USER(user)(((user) == ((void *) 0)) || ((user)->user_magic != 0x7ea4
))
)
646 return -EIO5;
647
648 if (s->req_pending) {
649 s->req_pending--;
650 get_user(s->req_result, (int *)buf);
651 if ((s->req_result != 0) || (s->req_pending == 0))
652 wake_up_interruptiblewake_up(&s->request);
653 } else
654 return -EIO5;
655
656 return 4;
657} /* ds_write */
658
659/*====================================================================*/
660
661#if (LINUX_VERSION_CODE131108 < VERSION(2,1,23)(((2)<<16)+(1<<8)+23))
662
663static int ds_select(struct inode *inode, struct file *file,
664 int sel_type, select_table *wait)
665{
666 socket_t i = MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1));
667 socket_info_t *s;
668 user_info_t *user;
669
670 DEBUG(2, "ds_select(socket %d)\n", i)if (pc_debug>(2)) printk("<7>" "ds_select(socket %d)\n"
, i)
;
671
672 if ((i >= sockets) || (sockets == 0))
673 return -ENODEV19;
674 s = &socket_table[i];
675 user = file->private_data;
676 if (CHECK_USER(user)(((user) == ((void *) 0)) || ((user)->user_magic != 0x7ea4
))
)
677 return -EIO5;
678 if (sel_type != SEL_IN1)
679 return 0;
680 if (!queue_empty(user))
681 return 1;
682 select_wait(&s->queue, wait);
683 return 0;
684} /* ds_select */
685
686#else
687
688static u_int ds_poll(struct file *file, poll_table *wait)
689{
690 socket_t i = MINOR(F_INODE(file)->i_rdev)((F_INODE(file)->i_rdev) & ((1<<8) - 1));
691 socket_info_t *s;
692 user_info_t *user;
693
694 DEBUG(2, "ds_poll(socket %d)\n", i)if (pc_debug>(2)) printk("<7>" "ds_poll(socket %d)\n"
, i)
;
695
696 if ((i >= sockets) || (sockets == 0))
697 return POLLERR;
698 s = &socket_table[i];
699 user = file->private_data;
700 if (CHECK_USER(user)(((user) == ((void *) 0)) || ((user)->user_magic != 0x7ea4
))
)
701 return POLLERR;
702 POLL_WAIT(file, &s->queue, wait);
703 if (!queue_empty(user))
704 return POLLIN | POLLRDNORM;
705 return 0;
706} /* ds_poll */
707
708#endif
709
710/*====================================================================*/
711
712#endif /* !defined(MACH) */
713
714static int ds_ioctl(struct inode * inode, struct file * file,
715 u_int cmd, u_long arg)
716{
717 socket_t i = MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1));
718 socket_info_t *s;
719 u_int size;
720 int ret, err;
721 ds_ioctl_arg_t buf;
722
723 DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", i, cmd, arg)if (pc_debug>(2)) printk("<7>" "ds_ioctl(socket %d, %#x, %#lx)\n"
, i, cmd, arg)
;
724
725 if ((i >= sockets) || (sockets == 0))
726 return -ENODEV19;
727 s = &socket_table[i];
728
729 size = (cmd & IOCSIZE_MASK(((1 << 14)-1) << ((0 +8)+8))) >> IOCSIZE_SHIFT(((0 +8)+8));
730 if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL22;
731
732 /* Permission check */
733 if (!(cmd & IOC_OUT(2U << (((0 +8)+8)+14))) && !capable(CAP_SYS_ADMIN)suser())
734 return -EPERM1;
735
736#ifndef MACH1
737 if (cmd & IOC_IN(1U << (((0 +8)+8)+14))) {
738 err = verify_area(VERIFY_READ0, (char *)arg, size);
739 if (err) {
740 DEBUG(3, "ds_ioctl(): verify_read = %d\n", err)if (pc_debug>(3)) printk("<7>" "ds_ioctl(): verify_read = %d\n"
, err)
;
741 return err;
742 }
743 }
744 if (cmd & IOC_OUT(2U << (((0 +8)+8)+14))) {
745 err = verify_area(VERIFY_WRITE1, (char *)arg, size);
746 if (err) {
747 DEBUG(3, "ds_ioctl(): verify_write = %d\n", err)if (pc_debug>(3)) printk("<7>" "ds_ioctl(): verify_write = %d\n"
, err)
;
748 return err;
749 }
750 }
751#endif
752
753 err = ret = 0;
754
755#ifndef MACH1
756 if (cmd & IOC_IN(1U << (((0 +8)+8)+14))) copy_from_user((char *)&buf, (char *)arg, size);
757#else
758 if (cmd & IOC_IN(1U << (((0 +8)+8)+14))) memcpy((char *) &buf, (char *) arg, size)(__builtin_constant_p(size) ? __constant_memcpy(((char *) &
buf),((char *) arg),(size)) : __memcpy(((char *) &buf),((
char *) arg),(size)))
;
759#endif
760
761 switch (cmd) {
762 case DS_ADJUST_RESOURCE_INFO(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((2)) << 0) | ((sizeof(adjust_t)) << ((0 +8
)+8)))
:
763 ret = CardServices(AdjustResourceInfo, s->handle, &buf.adjust);
764 break;
765 case DS_GET_CARD_SERVICES_INFO(((2U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((1)) << 0) | ((sizeof(servinfo_t)) << ((0 +8)+
8)))
:
766 ret = CardServices(GetCardServicesInfo, &buf.servinfo);
767 break;
768 case DS_GET_CONFIGURATION_INFO(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((3)) << 0) | ((sizeof(config_info_t)) << (
(0 +8)+8)))
:
769 ret = CardServices(GetConfigurationInfo, s->handle, &buf.config);
770 break;
771 case DS_GET_FIRST_TUPLE(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((4)) << 0) | ((sizeof(tuple_t)) << ((0 +8)
+8)))
:
772 ret = CardServices(GetFirstTuple, s->handle, &buf.tuple);
773 break;
774 case DS_GET_NEXT_TUPLE(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((5)) << 0) | ((sizeof(tuple_t)) << ((0 +8)
+8)))
:
775 ret = CardServices(GetNextTuple, s->handle, &buf.tuple);
776 break;
777 case DS_GET_TUPLE_DATA(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((6)) << 0) | ((sizeof(tuple_parse_t)) << (
(0 +8)+8)))
:
778 buf.tuple.TupleData = buf.tuple_parse.data;
779 buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
780 ret = CardServices(GetTupleData, s->handle, &buf.tuple);
781 break;
782 case DS_PARSE_TUPLE(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((7)) << 0) | ((sizeof(tuple_parse_t)) << (
(0 +8)+8)))
:
783 buf.tuple.TupleData = buf.tuple_parse.data;
784 ret = CardServices(ParseTuple, s->handle, &buf.tuple,
785 &buf.tuple_parse.parse);
786 break;
787 case DS_RESET_CARD(((0U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((8)) << 0) | ((0) << ((0 +8)+8)))
:
788 ret = CardServices(ResetCard, s->handle, NULL((void *) 0));
789 break;
790 case DS_GET_STATUS(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((9)) << 0) | ((sizeof(cs_status_t)) << ((0
+8)+8)))
:
791 ret = CardServices(GetStatus, s->handle, &buf.status);
792 break;
793 case DS_VALIDATE_CIS(((2U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((11)) << 0) | ((sizeof(cisinfo_t)) << ((0 +8)+
8)))
:
794 ret = CardServices(ValidateCIS, s->handle, &buf.cisinfo);
795 break;
796 case DS_SUSPEND_CARD(((0U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((12)) << 0) | ((0) << ((0 +8)+8)))
:
797 ret = CardServices(SuspendCard, s->handle, NULL((void *) 0));
798 break;
799 case DS_RESUME_CARD(((0U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((13)) << 0) | ((0) << ((0 +8)+8)))
:
800 ret = CardServices(ResumeCard, s->handle, NULL((void *) 0));
801 break;
802 case DS_EJECT_CARD(((0U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((14)) << 0) | ((0) << ((0 +8)+8)))
:
803 ret = CardServices(EjectCard, s->handle, NULL((void *) 0));
804 break;
805 case DS_INSERT_CARD(((0U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((15)) << 0) | ((0) << ((0 +8)+8)))
:
806 ret = CardServices(InsertCard, s->handle, NULL((void *) 0));
807 break;
808 case DS_ACCESS_CONFIGURATION_REGISTER(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((10)) << 0) | ((sizeof(conf_reg_t)) << ((0
+8)+8)))
:
809 if ((buf.conf_reg.Action == CS_WRITE2) && !capable(CAP_SYS_ADMIN)suser())
810 return -EPERM1;
811 ret = CardServices(AccessConfigurationRegister, s->handle,
812 &buf.conf_reg);
813 break;
814 case DS_GET_FIRST_REGION(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((16)) << 0) | ((sizeof(region_info_t)) << (
(0 +8)+8)))
:
815 ret = CardServices(GetFirstRegion, s->handle, &buf.region);
816 break;
817 case DS_GET_NEXT_REGION(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((17)) << 0) | ((sizeof(region_info_t)) << (
(0 +8)+8)))
:
818 ret = CardServices(GetNextRegion, s->handle, &buf.region);
819 break;
820 case DS_GET_FIRST_WINDOW(((2U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((19)) << 0) | ((sizeof(win_info_t)) << ((0 +8)
+8)))
:
821 buf.win_info.handle = (window_handle_t)s->handle;
822 ret = CardServices(GetFirstWindow, &buf.win_info.handle,
823 &buf.win_info.window);
824 break;
825 case DS_GET_NEXT_WINDOW(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((20)) << 0) | ((sizeof(win_info_t)) << ((0
+8)+8)))
:
826 ret = CardServices(GetNextWindow, &buf.win_info.handle,
827 &buf.win_info.window);
828 break;
829 case DS_GET_MEM_PAGE(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((21)) << 0) | ((sizeof(win_info_t)) << ((0
+8)+8)))
:
830 ret = CardServices(GetMemPage, buf.win_info.handle,
831 &buf.win_info.map);
832 break;
833 case DS_REPLACE_CIS(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((18)) << 0) | ((sizeof(cisdump_t)) << ((0 +
8)+8)))
:
834 ret = CardServices(ReplaceCIS, s->handle, &buf.cisdump);
835 break;
836 case DS_BIND_REQUEST(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((60)) << 0) | ((sizeof(bind_info_t)) << ((
0 +8)+8)))
:
837 if (!capable(CAP_SYS_ADMIN)suser()) return -EPERM1;
838 err = bind_request(i, &buf.bind_info);
839 break;
840 case DS_GET_DEVICE_INFO(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((61)) << 0) | ((sizeof(bind_info_t)) << ((
0 +8)+8)))
:
841 err = get_device_info(i, &buf.bind_info, 1);
842 break;
843 case DS_GET_NEXT_DEVICE(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((62)) << 0) | ((sizeof(bind_info_t)) << ((
0 +8)+8)))
:
844 err = get_device_info(i, &buf.bind_info, 0);
845 break;
846 case DS_UNBIND_REQUEST(((1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8)) |
(((63)) << 0) | ((sizeof(bind_info_t)) << ((0 +8
)+8)))
:
847 err = unbind_request(i, &buf.bind_info);
848 break;
849 case DS_BIND_MTD(((2U|1U) << (((0 +8)+8)+14)) | ((('d')) << (0 +8
)) | (((64)) << 0) | ((sizeof(mtd_info_t)) << ((0
+8)+8)))
:
850 if (!capable(CAP_SYS_ADMIN)suser()) return -EPERM1;
851 err = bind_mtd(i, &buf.mtd_info);
852 break;
853 default:
854 err = -EINVAL22;
855 }
856
857 if ((err == 0) && (ret != CS_SUCCESS0x00)) {
858 DEBUG(2, "ds_ioctl: ret = %d\n", ret)if (pc_debug>(2)) printk("<7>" "ds_ioctl: ret = %d\n"
, ret)
;
859 switch (ret) {
860 case CS_BAD_SOCKET0x0b: case CS_NO_CARD0x14:
861 err = -ENODEV19; break;
862 case CS_BAD_ARGS0x1c: case CS_BAD_ATTRIBUTE0x02: case CS_BAD_IRQ0x06:
863 case CS_BAD_TUPLE0x40:
864 err = -EINVAL22; break;
865 case CS_IN_USE0x1e:
866 err = -EBUSY16; break;
867 case CS_OUT_OF_RESOURCE0x20:
868 err = -ENOSPC28; break;
869 case CS_NO_MORE_ITEMS0x1f:
870 err = -ENODATA61; break;
871 case CS_UNSUPPORTED_FUNCTION0x15:
872 err = -ENOSYS38; break;
873 default:
874 err = -EIO5; break;
875 }
876 }
877
878#ifndef MACH1
879 if (cmd & IOC_OUT(2U << (((0 +8)+8)+14))) copy_to_user((char *)arg, (char *)&buf, size)memcpy_tofs((char *)arg,(char *)&buf,size);
880#else
881 if (cmd & IOC_OUT(2U << (((0 +8)+8)+14))) memcpy((char *) arg, (char *) &buf, size)(__builtin_constant_p(size) ? __constant_memcpy(((char *) arg
),((char *) &buf),(size)) : __memcpy(((char *) arg),((char
*) &buf),(size)))
;
882#endif
883
884 return err;
885} /* ds_ioctl */
886
887/*====================================================================*/
888
889#ifndef MACH1
890
891static struct file_operations ds_fops = {
892 open: ds_open,
893 release: ds_release,
894 ioctl: ds_ioctl,
895 read: ds_read,
896 write: ds_write,
897#if (LINUX_VERSION_CODE131108 < VERSION(2,1,23)(((2)<<16)+(1<<8)+23))
898 select: ds_select
899#else
900 poll: ds_poll
901#endif
902};
903
904#if (LINUX_VERSION_CODE131108 <= VERSION(2,1,17)(((2)<<16)+(1<<8)+17))
905
906#undef CONFIG_MODVERSIONS
907static struct symbol_table ds_symtab = {
908#include <linux/symtab_begin.h>
909#undef X
910#define X(sym) { (void *)&sym, SYMBOL_NAME_STR(sym)"sym" }
911 X(register_pccard_driver),
912 X(unregister_pccard_driver),
913#include <linux/symtab_end.h>
914};
915
916#else
917
918EXPORT_SYMBOL(register_pccard_driver);
919EXPORT_SYMBOL(unregister_pccard_driver);
920
921#endif
922
923#endif /* !defined(MACH) */
924
925/*====================================================================*/
926
927int __init init_pcmcia_ds(void)
928{
929 client_reg_t client_reg;
930 servinfo_t serv;
931 bind_req_t bind;
932 socket_info_t *s;
933 int i, ret;
934
935 DEBUG(0, "%s\n", version)if (pc_debug>(0)) printk("<7>" "%s\n", version);
936
937 CardServices(GetCardServicesInfo, &serv);
938 if (serv.Revision != CS_RELEASE_CODE0x3208) {
939 printk(KERN_NOTICE"<5>" "ds: Card Services release does not match!\n");
940 return -EINVAL22;
941 }
942 if (serv.Count == 0) {
943 printk(KERN_NOTICE"<5>" "ds: no socket drivers loaded!\n");
944 return -1;
945 }
946
947 sockets = serv.Count;
948 socket_table = kmalloclinux_kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL0x03);
949 if (!socket_table) return -1;
950 for (i = 0, s = socket_table; i < sockets; i++, s++) {
951 s->state = 0;
952 s->user = NULL((void *) 0);
953 s->req_pending = 0;
954 init_waitqueue_head(&s->queue)*(&s->queue)=((void *) 0);
955 init_waitqueue_head(&s->request)*(&s->request)=((void *) 0);
956 s->handle = NULL((void *) 0);
957 init_timer(&s->removal);
958 s->removal.data = i;
959 s->removal.function = &handle_removal;
960 s->bind = NULL((void *) 0);
961 }
962
963 /* Set up hotline to Card Services */
964 client_reg.dev_info = bind.dev_info = &dev_info;
965 client_reg.Attributes = INFO_MASTER_CLIENT0x01;
966 client_reg.EventMask =
967 CS_EVENT_CARD_INSERTION0x000004 | CS_EVENT_CARD_REMOVAL0x000008 |
968 CS_EVENT_RESET_PHYSICAL0x000200 | CS_EVENT_CARD_RESET0x000400 |
969 CS_EVENT_EJECTION_REQUEST0x010000 | CS_EVENT_INSERTION_REQUEST0x008000 |
970 CS_EVENT_PM_SUSPEND0x002000 | CS_EVENT_PM_RESUME0x004000;
971 client_reg.event_handler = &ds_event;
972 client_reg.Version = 0x0210;
973 for (i = 0; i < sockets; i++) {
974 bind.Socket = i;
975 bind.Function = BIND_FN_ALL0xff;
976 ret = CardServices(BindDevice, &bind);
977 if (ret != CS_SUCCESS0x00) {
978 cs_error(NULL((void *) 0), BindDevice, ret);
979 break;
980 }
981 client_reg.event_callback_args.client_data = &socket_table[i];
982 ret = CardServices(RegisterClient, &socket_table[i].handle,
983 &client_reg);
984 if (ret != CS_SUCCESS0x00) {
985 cs_error(NULL((void *) 0), RegisterClient, ret);
986 break;
987 }
988 }
989
990#ifndef MACH1
991 /* Set up character device for user mode clients */
992 i = register_chrdev(0, "pcmcia", &ds_fops);
993 if (i == -EBUSY16)
994 printk(KERN_NOTICE"<5>" "unable to find a free device # for "
995 "Driver Services\n");
996 else
997 major_dev = i;
998 register_symtab(&ds_symtab);
999#endif
1000
1001#ifdef HAS_PROC_BUS
1002 if (proc_pccard)
1003 create_proc_read_entry("drivers", 0, proc_pccard,
1004 proc_read_drivers, NULL((void *) 0));
1005 init_status = 0;
1006#endif
1007 return 0;
1008}
1009
1010#ifdef MODULE
1011
1012int __init init_module(void)
1013{
1014 return init_pcmcia_ds();
1015}
1016
1017void __exit__attribute__((__used__)) __attribute__((no_instrument_function
))
cleanup_module(void)
1018{
1019 int i;
1020#ifdef HAS_PROC_BUS
1021 if (proc_pccard)
1022 remove_proc_entry("drivers", proc_pccard);
1023#endif
1024 if (major_dev != -1)
1025 unregister_chrdev(major_dev, "pcmcia");
1026 for (i = 0; i < sockets; i++)
1027 CardServices(DeregisterClient, socket_table[i].handle);
1028 sockets = 0;
1029 kfree(socket_table);
1030}
1031
1032#endif
1033
1034/*====================================================================*/
1035
1036/* Include the interface glue code to GNU Mach. */
1037#include "../glue/ds.c"
1038
1039/*====================================================================*/