linux/drivers/pcmcia/pcmcia_ioctl.c
<<
>>
Prefs
   1/*
   2 * pcmcia_ioctl.c -- ioctl interface for cardmgr and cardctl
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * The initial developer of the original code is David A. Hinds
   9 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  10 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  11 *
  12 * (C) 1999             David A. Hinds
  13 * (C) 2003 - 2004      Dominik Brodowski
  14 */
  15
  16/*
  17 * This file will go away soon.
  18 */
  19
  20
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/init.h>
  24#include <linux/major.h>
  25#include <linux/errno.h>
  26#include <linux/ioctl.h>
  27#include <linux/proc_fs.h>
  28#include <linux/poll.h>
  29#include <linux/pci.h>
  30#include <linux/smp_lock.h>
  31#include <linux/workqueue.h>
  32
  33#include <pcmcia/cs_types.h>
  34#include <pcmcia/cs.h>
  35#include <pcmcia/cistpl.h>
  36#include <pcmcia/cisreg.h>
  37#include <pcmcia/ds.h>
  38#include <pcmcia/ss.h>
  39
  40#include "cs_internal.h"
  41
  42static int major_dev = -1;
  43
  44
  45/* Device user information */
  46#define MAX_EVENTS      32
  47#define USER_MAGIC      0x7ea4
  48#define CHECK_USER(u) \
  49    (((u) == NULL) || ((u)->user_magic != USER_MAGIC))
  50
  51typedef struct user_info_t {
  52        u_int                   user_magic;
  53        int                     event_head, event_tail;
  54        event_t                 event[MAX_EVENTS];
  55        struct user_info_t      *next;
  56        struct pcmcia_socket    *socket;
  57} user_info_t;
  58
  59
  60#ifdef CONFIG_PCMCIA_DEBUG
  61extern int ds_pc_debug;
  62
  63#define ds_dbg(lvl, fmt, arg...) do {           \
  64        if (ds_pc_debug >= lvl)                         \
  65                printk(KERN_DEBUG "ds: " fmt , ## arg);         \
  66} while (0)
  67#else
  68#define ds_dbg(lvl, fmt, arg...) do { } while (0)
  69#endif
  70
  71static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,
  72                                                unsigned int function)
  73{
  74        struct pcmcia_device *p_dev = NULL;
  75        unsigned long flags;
  76
  77        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
  78        list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
  79                if (p_dev->func == function) {
  80                        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
  81                        return pcmcia_get_dev(p_dev);
  82                }
  83        }
  84        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
  85        return NULL;
  86}
  87
  88/* backwards-compatible accessing of driver --- by name! */
  89
  90static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info)
  91{
  92        struct device_driver *drv;
  93        struct pcmcia_driver *p_drv;
  94
  95        drv = driver_find((char *) dev_info, &pcmcia_bus_type);
  96        if (!drv)
  97                return NULL;
  98
  99        p_drv = container_of(drv, struct pcmcia_driver, drv);
 100
 101        return (p_drv);
 102}
 103
 104
 105#ifdef CONFIG_PROC_FS
 106static struct proc_dir_entry *proc_pccard = NULL;
 107
 108static int proc_read_drivers_callback(struct device_driver *driver, void *d)
 109{
 110        char **p = d;
 111        struct pcmcia_driver *p_drv = container_of(driver,
 112                                                   struct pcmcia_driver, drv);
 113
 114        *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name,
 115#ifdef CONFIG_MODULE_UNLOAD
 116                      (p_drv->owner) ? module_refcount(p_drv->owner) : 1
 117#else
 118                      1
 119#endif
 120        );
 121        d = (void *) p;
 122
 123        return 0;
 124}
 125
 126static int proc_read_drivers(char *buf, char **start, off_t pos,
 127                             int count, int *eof, void *data)
 128{
 129        char *p = buf;
 130        int rc;
 131
 132        rc = bus_for_each_drv(&pcmcia_bus_type, NULL,
 133                              (void *) &p, proc_read_drivers_callback);
 134        if (rc < 0)
 135                return rc;
 136
 137        return (p - buf);
 138}
 139#endif
 140
 141
 142#ifdef CONFIG_PCMCIA_PROBE
 143
 144static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
 145{
 146        int irq;
 147        u32 mask;
 148
 149        irq = adj->resource.irq.IRQ;
 150        if ((irq < 0) || (irq > 15))
 151                return -EINVAL;
 152
 153        if (adj->Action != REMOVE_MANAGED_RESOURCE)
 154                return 0;
 155
 156        mask = 1 << irq;
 157
 158        if (!(s->irq_mask & mask))
 159                return 0;
 160
 161        s->irq_mask &= ~mask;
 162
 163        return 0;
 164}
 165
 166#else
 167
 168static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
 169        return 0;
 170}
 171
 172#endif
 173
 174static int pcmcia_adjust_resource_info(adjust_t *adj)
 175{
 176        struct pcmcia_socket *s;
 177        int ret = -ENOSYS;
 178        unsigned long flags;
 179
 180        down_read(&pcmcia_socket_list_rwsem);
 181        list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
 182
 183                if (adj->Resource == RES_IRQ)
 184                        ret = adjust_irq(s, adj);
 185
 186                else if (s->resource_ops->add_io) {
 187                        unsigned long begin, end;
 188
 189                        /* you can't use the old interface if the new
 190                         * one was used before */
 191                        spin_lock_irqsave(&s->lock, flags);
 192                        if ((s->resource_setup_new) &&
 193                            !(s->resource_setup_old)) {
 194                                spin_unlock_irqrestore(&s->lock, flags);
 195                                continue;
 196                        } else if (!(s->resource_setup_old))
 197                                s->resource_setup_old = 1;
 198                        spin_unlock_irqrestore(&s->lock, flags);
 199
 200                        switch (adj->Resource) {
 201                        case RES_MEMORY_RANGE:
 202                                begin = adj->resource.memory.Base;
 203                                end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
 204                                if (s->resource_ops->add_mem)
 205                                        ret =s->resource_ops->add_mem(s, adj->Action, begin, end);
 206                        case RES_IO_RANGE:
 207                                begin = adj->resource.io.BasePort;
 208                                end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
 209                                if (s->resource_ops->add_io)
 210                                        ret = s->resource_ops->add_io(s, adj->Action, begin, end);
 211                        }
 212                        if (!ret) {
 213                                /* as there's no way we know this is the
 214                                 * last call to adjust_resource_info, we
 215                                 * always need to assume this is the latest
 216                                 * one... */
 217                                spin_lock_irqsave(&s->lock, flags);
 218                                s->resource_setup_done = 1;
 219                                spin_unlock_irqrestore(&s->lock, flags);
 220                        }
 221                }
 222        }
 223        up_read(&pcmcia_socket_list_rwsem);
 224
 225        return (ret);
 226}
 227
 228/** pccard_get_status
 229 *
 230 * Get the current socket state bits.  We don't support the latched
 231 * SocketState yet: I haven't seen any point for it.
 232 */
 233
 234static int pccard_get_status(struct pcmcia_socket *s,
 235                             struct pcmcia_device *p_dev,
 236                             cs_status_t *status)
 237{
 238        config_t *c;
 239        int val;
 240
 241        s->ops->get_status(s, &val);
 242        status->CardState = status->SocketState = 0;
 243        status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
 244        status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
 245        status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
 246        status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
 247        if (s->state & SOCKET_SUSPEND)
 248                status->CardState |= CS_EVENT_PM_SUSPEND;
 249        if (!(s->state & SOCKET_PRESENT))
 250                return -ENODEV;
 251
 252        c = (p_dev) ? p_dev->function_config : NULL;
 253
 254        if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
 255            (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
 256                u_char reg;
 257                if (c->CardValues & PRESENT_PIN_REPLACE) {
 258                        pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
 259                        status->CardState |=
 260                                (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
 261                        status->CardState |=
 262                                (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
 263                        status->CardState |=
 264                                (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
 265                        status->CardState |=
 266                                (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
 267                } else {
 268                        /* No PRR?  Then assume we're always ready */
 269                        status->CardState |= CS_EVENT_READY_CHANGE;
 270                }
 271                if (c->CardValues & PRESENT_EXT_STATUS) {
 272                        pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
 273                        status->CardState |=
 274                                (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
 275                }
 276                return 0;
 277        }
 278        status->CardState |=
 279                (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
 280        status->CardState |=
 281                (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
 282        status->CardState |=
 283                (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
 284        status->CardState |=
 285                (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
 286        return 0;
 287} /* pccard_get_status */
 288
 289int pccard_get_configuration_info(struct pcmcia_socket *s,
 290                                  struct pcmcia_device *p_dev,
 291                                  config_info_t *config)
 292{
 293        config_t *c;
 294
 295        if (!(s->state & SOCKET_PRESENT))
 296                return -ENODEV;
 297
 298
 299#ifdef CONFIG_CARDBUS
 300        if (s->state & SOCKET_CARDBUS) {
 301                memset(config, 0, sizeof(config_info_t));
 302                config->Vcc = s->socket.Vcc;
 303                config->Vpp1 = config->Vpp2 = s->socket.Vpp;
 304                config->Option = s->cb_dev->subordinate->number;
 305                if (s->state & SOCKET_CARDBUS_CONFIG) {
 306                        config->Attributes = CONF_VALID_CLIENT;
 307                        config->IntType = INT_CARDBUS;
 308                        config->AssignedIRQ = s->irq.AssignedIRQ;
 309                        if (config->AssignedIRQ)
 310                                config->Attributes |= CONF_ENABLE_IRQ;
 311                        if (s->io[0].res) {
 312                                config->BasePort1 = s->io[0].res->start;
 313                                config->NumPorts1 = s->io[0].res->end -
 314                                        config->BasePort1 + 1;
 315                        }
 316                }
 317                return 0;
 318        }
 319#endif
 320
 321        if (p_dev) {
 322                c = p_dev->function_config;
 323                config->Function = p_dev->func;
 324        } else {
 325                c = NULL;
 326                config->Function = 0;
 327        }
 328
 329        if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
 330                config->Attributes = 0;
 331                config->Vcc = s->socket.Vcc;
 332                config->Vpp1 = config->Vpp2 = s->socket.Vpp;
 333                return 0;
 334        }
 335
 336        config->Attributes = c->Attributes | CONF_VALID_CLIENT;
 337        config->Vcc = s->socket.Vcc;
 338        config->Vpp1 = config->Vpp2 = s->socket.Vpp;
 339        config->IntType = c->IntType;
 340        config->ConfigBase = c->ConfigBase;
 341        config->Status = c->Status;
 342        config->Pin = c->Pin;
 343        config->Copy = c->Copy;
 344        config->Option = c->Option;
 345        config->ExtStatus = c->ExtStatus;
 346        config->Present = config->CardValues = c->CardValues;
 347        config->IRQAttributes = c->irq.Attributes;
 348        config->AssignedIRQ = s->irq.AssignedIRQ;
 349        config->BasePort1 = c->io.BasePort1;
 350        config->NumPorts1 = c->io.NumPorts1;
 351        config->Attributes1 = c->io.Attributes1;
 352        config->BasePort2 = c->io.BasePort2;
 353        config->NumPorts2 = c->io.NumPorts2;
 354        config->Attributes2 = c->io.Attributes2;
 355        config->IOAddrLines = c->io.IOAddrLines;
 356
 357        return 0;
 358} /* pccard_get_configuration_info */
 359
 360
 361/*======================================================================
 362
 363    These manage a ring buffer of events pending for one user process
 364
 365======================================================================*/
 366
 367
 368static int queue_empty(user_info_t *user)
 369{
 370    return (user->event_head == user->event_tail);
 371}
 372
 373static event_t get_queued_event(user_info_t *user)
 374{
 375    user->event_tail = (user->event_tail+1) % MAX_EVENTS;
 376    return user->event[user->event_tail];
 377}
 378
 379static void queue_event(user_info_t *user, event_t event)
 380{
 381    user->event_head = (user->event_head+1) % MAX_EVENTS;
 382    if (user->event_head == user->event_tail)
 383        user->event_tail = (user->event_tail+1) % MAX_EVENTS;
 384    user->event[user->event_head] = event;
 385}
 386
 387void handle_event(struct pcmcia_socket *s, event_t event)
 388{
 389    user_info_t *user;
 390    for (user = s->user; user; user = user->next)
 391        queue_event(user, event);
 392    wake_up_interruptible(&s->queue);
 393}
 394
 395
 396/*======================================================================
 397
 398    bind_request() and bind_device() are merged by now. Register_client()
 399    is called right at the end of bind_request(), during the driver's
 400    ->attach() call. Individual descriptions:
 401
 402    bind_request() connects a socket to a particular client driver.
 403    It looks up the specified device ID in the list of registered
 404    drivers, binds it to the socket, and tries to create an instance
 405    of the device.  unbind_request() deletes a driver instance.
 406
 407    Bind_device() associates a device driver with a particular socket.
 408    It is normally called by Driver Services after it has identified
 409    a newly inserted card.  An instance of that driver will then be
 410    eligible to register as a client of this socket.
 411
 412    Register_client() uses the dev_info_t handle to match the
 413    caller with a socket.  The driver must have already been bound
 414    to a socket with bind_device() -- in fact, bind_device()
 415    allocates the client structure that will be used.
 416
 417======================================================================*/
 418
 419static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)
 420{
 421        struct pcmcia_driver *p_drv;
 422        struct pcmcia_device *p_dev;
 423        int ret = 0;
 424        unsigned long flags;
 425
 426        s = pcmcia_get_socket(s);
 427        if (!s)
 428                return -EINVAL;
 429
 430        ds_dbg(2, "bind_request(%d, '%s')\n", s->sock,
 431               (char *)bind_info->dev_info);
 432
 433        p_drv = get_pcmcia_driver(&bind_info->dev_info);
 434        if (!p_drv) {
 435                ret = -EINVAL;
 436                goto err_put;
 437        }
 438
 439        if (!try_module_get(p_drv->owner)) {
 440                ret = -EINVAL;
 441                goto err_put_driver;
 442        }
 443
 444        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
 445        list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
 446                if (p_dev->func == bind_info->function) {
 447                        if ((p_dev->dev.driver == &p_drv->drv)) {
 448                                if (p_dev->cardmgr) {
 449                                        /* if there's already a device
 450                                         * registered, and it was registered
 451                                         * by userspace before, we need to
 452                                         * return the "instance". */
 453                                        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 454                                        bind_info->instance = p_dev;
 455                                        ret = -EBUSY;
 456                                        goto err_put_module;
 457                                } else {
 458                                        /* the correct driver managed to bind
 459                                         * itself magically to the correct
 460                                         * device. */
 461                                        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 462                                        p_dev->cardmgr = p_drv;
 463                                        ret = 0;
 464                                        goto err_put_module;
 465                                }
 466                        } else if (!p_dev->dev.driver) {
 467                                /* there's already a device available where
 468                                 * no device has been bound to yet. So we don't
 469                                 * need to register a device! */
 470                                spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 471                                goto rescan;
 472                        }
 473                }
 474        }
 475        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 476
 477        p_dev = pcmcia_device_add(s, bind_info->function);
 478        if (!p_dev) {
 479                ret = -EIO;
 480                goto err_put_module;
 481        }
 482
 483rescan:
 484        p_dev->cardmgr = p_drv;
 485
 486        /* if a driver is already running, we can abort */
 487        if (p_dev->dev.driver)
 488                goto err_put_module;
 489
 490        /*
 491         * Prevent this racing with a card insertion.
 492         */
 493        mutex_lock(&s->skt_mutex);
 494        ret = bus_rescan_devices(&pcmcia_bus_type);
 495        mutex_unlock(&s->skt_mutex);
 496        if (ret)
 497                goto err_put_module;
 498
 499        /* check whether the driver indeed matched. I don't care if this
 500         * is racy or not, because it can only happen on cardmgr access
 501         * paths...
 502         */
 503        if (!(p_dev->dev.driver == &p_drv->drv))
 504                p_dev->cardmgr = NULL;
 505
 506 err_put_module:
 507        module_put(p_drv->owner);
 508 err_put_driver:
 509        put_driver(&p_drv->drv);
 510 err_put:
 511        pcmcia_put_socket(s);
 512
 513        return (ret);
 514} /* bind_request */
 515
 516#ifdef CONFIG_CARDBUS
 517
 518static struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s)
 519{
 520        if (!s || !(s->state & SOCKET_CARDBUS))
 521                return NULL;
 522
 523        return s->cb_dev->subordinate;
 524}
 525#endif
 526
 527static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first)
 528{
 529        dev_node_t *node;
 530        struct pcmcia_device *p_dev;
 531        struct pcmcia_driver *p_drv;
 532        unsigned long flags;
 533        int ret = 0;
 534
 535#ifdef CONFIG_CARDBUS
 536        /*
 537         * Some unbelievably ugly code to associate the PCI cardbus
 538         * device and its driver with the PCMCIA "bind" information.
 539         */
 540        {
 541                struct pci_bus *bus;
 542
 543                bus = pcmcia_lookup_bus(s);
 544                if (bus) {
 545                        struct list_head *list;
 546                        struct pci_dev *dev = NULL;
 547
 548                        list = bus->devices.next;
 549                        while (list != &bus->devices) {
 550                                struct pci_dev *pdev = pci_dev_b(list);
 551                                list = list->next;
 552
 553                                if (first) {
 554                                        dev = pdev;
 555                                        break;
 556                                }
 557
 558                                /* Try to handle "next" here some way? */
 559                        }
 560                        if (dev && dev->driver) {
 561                                strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
 562                                bind_info->major = 0;
 563                                bind_info->minor = 0;
 564                                bind_info->next = NULL;
 565                                return 0;
 566                        }
 567                }
 568        }
 569#endif
 570
 571        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
 572        list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
 573                if (p_dev->func == bind_info->function) {
 574                        p_dev = pcmcia_get_dev(p_dev);
 575                        if (!p_dev)
 576                                continue;
 577                        goto found;
 578                }
 579        }
 580        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 581        return -ENODEV;
 582
 583 found:
 584        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 585
 586        p_drv = to_pcmcia_drv(p_dev->dev.driver);
 587        if (p_drv && !p_dev->_locked) {
 588                ret = -EAGAIN;
 589                goto err_put;
 590        }
 591
 592        if (first)
 593                node = p_dev->dev_node;
 594        else
 595                for (node = p_dev->dev_node; node; node = node->next)
 596                        if (node == bind_info->next)
 597                                break;
 598        if (!node) {
 599                ret = -ENODEV;
 600                goto err_put;
 601        }
 602
 603        strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
 604        bind_info->major = node->major;
 605        bind_info->minor = node->minor;
 606        bind_info->next = node->next;
 607
 608 err_put:
 609        pcmcia_put_dev(p_dev);
 610        return (ret);
 611} /* get_device_info */
 612
 613
 614static int ds_open(struct inode *inode, struct file *file)
 615{
 616    socket_t i = iminor(inode);
 617    struct pcmcia_socket *s;
 618    user_info_t *user;
 619    static int warning_printed = 0;
 620    int ret = 0;
 621
 622    ds_dbg(0, "ds_open(socket %d)\n", i);
 623
 624    lock_kernel();
 625    s = pcmcia_get_socket_by_nr(i);
 626    if (!s) {
 627            ret = -ENODEV;
 628            goto out;
 629    }
 630    s = pcmcia_get_socket(s);
 631    if (!s) {
 632            ret = -ENODEV;
 633            goto out;
 634    }
 635
 636    if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 637            if (s->pcmcia_state.busy) {
 638                    pcmcia_put_socket(s);
 639                    ret = -EBUSY;
 640                    goto out;
 641            }
 642        else
 643            s->pcmcia_state.busy = 1;
 644    }
 645
 646    user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
 647    if (!user) {
 648            pcmcia_put_socket(s);
 649            ret = -ENOMEM;
 650            goto out;
 651    }
 652    user->event_tail = user->event_head = 0;
 653    user->next = s->user;
 654    user->user_magic = USER_MAGIC;
 655    user->socket = s;
 656    s->user = user;
 657    file->private_data = user;
 658
 659    if (!warning_printed) {
 660            printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
 661                        "usage from process: %s.\n", current->comm);
 662            printk(KERN_INFO "pcmcia: This interface will soon be removed from "
 663                        "the kernel; please expect breakage unless you upgrade "
 664                        "to new tools.\n");
 665            printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
 666                        "utils/kernel/pcmcia/pcmcia.html for details.\n");
 667            warning_printed = 1;
 668    }
 669
 670    if (s->pcmcia_state.present)
 671        queue_event(user, CS_EVENT_CARD_INSERTION);
 672out:
 673    unlock_kernel();
 674    return ret;
 675} /* ds_open */
 676
 677/*====================================================================*/
 678
 679static int ds_release(struct inode *inode, struct file *file)
 680{
 681    struct pcmcia_socket *s;
 682    user_info_t *user, **link;
 683
 684    ds_dbg(0, "ds_release(socket %d)\n", iminor(inode));
 685
 686    user = file->private_data;
 687    if (CHECK_USER(user))
 688        goto out;
 689
 690    s = user->socket;
 691
 692    /* Unlink user data structure */
 693    if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 694        s->pcmcia_state.busy = 0;
 695    }
 696    file->private_data = NULL;
 697    for (link = &s->user; *link; link = &(*link)->next)
 698        if (*link == user) break;
 699    if (link == NULL)
 700        goto out;
 701    *link = user->next;
 702    user->user_magic = 0;
 703    kfree(user);
 704    pcmcia_put_socket(s);
 705out:
 706    return 0;
 707} /* ds_release */
 708
 709/*====================================================================*/
 710
 711static ssize_t ds_read(struct file *file, char __user *buf,
 712                       size_t count, loff_t *ppos)
 713{
 714    struct pcmcia_socket *s;
 715    user_info_t *user;
 716    int ret;
 717
 718    ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode));
 719
 720    if (count < 4)
 721        return -EINVAL;
 722
 723    user = file->private_data;
 724    if (CHECK_USER(user))
 725        return -EIO;
 726
 727    s = user->socket;
 728    if (s->pcmcia_state.dead)
 729        return -EIO;
 730
 731    ret = wait_event_interruptible(s->queue, !queue_empty(user));
 732    if (ret == 0)
 733        ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4;
 734
 735    return ret;
 736} /* ds_read */
 737
 738/*====================================================================*/
 739
 740static ssize_t ds_write(struct file *file, const char __user *buf,
 741                        size_t count, loff_t *ppos)
 742{
 743    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode));
 744
 745    if (count != 4)
 746        return -EINVAL;
 747    if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 748        return -EBADF;
 749
 750    return -EIO;
 751} /* ds_write */
 752
 753/*====================================================================*/
 754
 755/* No kernel lock - fine */
 756static u_int ds_poll(struct file *file, poll_table *wait)
 757{
 758    struct pcmcia_socket *s;
 759    user_info_t *user;
 760
 761    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode));
 762
 763    user = file->private_data;
 764    if (CHECK_USER(user))
 765        return POLLERR;
 766    s = user->socket;
 767    /*
 768     * We don't check for a dead socket here since that
 769     * will send cardmgr into an endless spin.
 770     */
 771    poll_wait(file, &s->queue, wait);
 772    if (!queue_empty(user))
 773        return POLLIN | POLLRDNORM;
 774    return 0;
 775} /* ds_poll */
 776
 777/*====================================================================*/
 778
 779static int ds_ioctl(struct inode * inode, struct file * file,
 780                    u_int cmd, u_long arg)
 781{
 782    struct pcmcia_socket *s;
 783    void __user *uarg = (char __user *)arg;
 784    u_int size;
 785    int ret, err;
 786    ds_ioctl_arg_t *buf;
 787    user_info_t *user;
 788
 789    ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
 790
 791    user = file->private_data;
 792    if (CHECK_USER(user))
 793        return -EIO;
 794
 795    s = user->socket;
 796    if (s->pcmcia_state.dead)
 797        return -EIO;
 798
 799    size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
 800    if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
 801
 802    /* Permission check */
 803    if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
 804        return -EPERM;
 805
 806    if (cmd & IOC_IN) {
 807        if (!access_ok(VERIFY_READ, uarg, size)) {
 808            ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT);
 809            return -EFAULT;
 810        }
 811    }
 812    if (cmd & IOC_OUT) {
 813        if (!access_ok(VERIFY_WRITE, uarg, size)) {
 814            ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT);
 815            return -EFAULT;
 816        }
 817    }
 818    buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL);
 819    if (!buf)
 820        return -ENOMEM;
 821
 822    err = ret = 0;
 823
 824    if (cmd & IOC_IN) {
 825        if (__copy_from_user((char *)buf, uarg, size)) {
 826            err = -EFAULT;
 827            goto free_out;
 828        }
 829    }
 830
 831    switch (cmd) {
 832    case DS_ADJUST_RESOURCE_INFO:
 833        ret = pcmcia_adjust_resource_info(&buf->adjust);
 834        break;
 835    case DS_GET_CONFIGURATION_INFO:
 836        if (buf->config.Function &&
 837           (buf->config.Function >= s->functions))
 838            ret = -EINVAL;
 839        else {
 840            struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
 841            ret = pccard_get_configuration_info(s, p_dev, &buf->config);
 842            pcmcia_put_dev(p_dev);
 843        }
 844        break;
 845    case DS_GET_FIRST_TUPLE:
 846        mutex_lock(&s->skt_mutex);
 847        pcmcia_validate_mem(s);
 848        mutex_unlock(&s->skt_mutex);
 849        ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
 850        break;
 851    case DS_GET_NEXT_TUPLE:
 852        ret = pccard_get_next_tuple(s, BIND_FN_ALL, &buf->tuple);
 853        break;
 854    case DS_GET_TUPLE_DATA:
 855        buf->tuple.TupleData = buf->tuple_parse.data;
 856        buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data);
 857        ret = pccard_get_tuple_data(s, &buf->tuple);
 858        break;
 859    case DS_PARSE_TUPLE:
 860        buf->tuple.TupleData = buf->tuple_parse.data;
 861        ret = pcmcia_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
 862        break;
 863    case DS_RESET_CARD:
 864        ret = pcmcia_reset_card(s);
 865        break;
 866    case DS_GET_STATUS:
 867            if (buf->status.Function &&
 868                (buf->status.Function >= s->functions))
 869                    ret = -EINVAL;
 870            else {
 871                    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
 872                    ret = pccard_get_status(s, p_dev, &buf->status);
 873                    pcmcia_put_dev(p_dev);
 874            }
 875            break;
 876    case DS_VALIDATE_CIS:
 877        mutex_lock(&s->skt_mutex);
 878        pcmcia_validate_mem(s);
 879        mutex_unlock(&s->skt_mutex);
 880        ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo.Chains);
 881        break;
 882    case DS_SUSPEND_CARD:
 883        ret = pcmcia_suspend_card(s);
 884        break;
 885    case DS_RESUME_CARD:
 886        ret = pcmcia_resume_card(s);
 887        break;
 888    case DS_EJECT_CARD:
 889        err = pcmcia_eject_card(s);
 890        break;
 891    case DS_INSERT_CARD:
 892        err = pcmcia_insert_card(s);
 893        break;
 894    case DS_ACCESS_CONFIGURATION_REGISTER:
 895        if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) {
 896            err = -EPERM;
 897            goto free_out;
 898        }
 899
 900        ret = -EINVAL;
 901
 902        if (!(buf->conf_reg.Function &&
 903             (buf->conf_reg.Function >= s->functions))) {
 904                struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
 905                if (p_dev) {
 906                        ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
 907                        pcmcia_put_dev(p_dev);
 908                }
 909        }
 910        break;
 911    case DS_GET_FIRST_REGION:
 912    case DS_GET_NEXT_REGION:
 913    case DS_BIND_MTD:
 914        if (!capable(CAP_SYS_ADMIN)) {
 915                err = -EPERM;
 916                goto free_out;
 917        } else {
 918                static int printed = 0;
 919                if (!printed) {
 920                        printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n");
 921                        printk(KERN_WARNING "MTD handling any more.\n");
 922                        printed++;
 923                }
 924        }
 925        err = -EINVAL;
 926        goto free_out;
 927        break;
 928    case DS_GET_FIRST_WINDOW:
 929        ret = pcmcia_get_window(s, &buf->win_info.handle, 0,
 930                        &buf->win_info.window);
 931        break;
 932    case DS_GET_NEXT_WINDOW:
 933        ret = pcmcia_get_window(s, &buf->win_info.handle,
 934                        buf->win_info.handle->index + 1, &buf->win_info.window);
 935        break;
 936    case DS_GET_MEM_PAGE:
 937        ret = pcmcia_get_mem_page(buf->win_info.handle,
 938                           &buf->win_info.map);
 939        break;
 940    case DS_REPLACE_CIS:
 941        ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length);
 942        break;
 943    case DS_BIND_REQUEST:
 944        if (!capable(CAP_SYS_ADMIN)) {
 945                err = -EPERM;
 946                goto free_out;
 947        }
 948        err = bind_request(s, &buf->bind_info);
 949        break;
 950    case DS_GET_DEVICE_INFO:
 951        err = get_device_info(s, &buf->bind_info, 1);
 952        break;
 953    case DS_GET_NEXT_DEVICE:
 954        err = get_device_info(s, &buf->bind_info, 0);
 955        break;
 956    case DS_UNBIND_REQUEST:
 957        err = 0;
 958        break;
 959    default:
 960        err = -EINVAL;
 961    }
 962
 963    if ((err == 0) && (ret != 0)) {
 964        ds_dbg(2, "ds_ioctl: ret = %d\n", ret);
 965        switch (ret) {
 966        case -ENODEV:
 967        case -EINVAL:
 968        case -EBUSY:
 969        case -ENOSYS:
 970            err = ret;
 971            break;
 972        case -ENOMEM:
 973            err = -ENOSPC; break;
 974        case -ENOSPC:
 975            err = -ENODATA; break;
 976        default:
 977            err = -EIO; break;
 978        }
 979    }
 980
 981    if (cmd & IOC_OUT) {
 982        if (__copy_to_user(uarg, (char *)buf, size))
 983            err = -EFAULT;
 984    }
 985
 986free_out:
 987    kfree(buf);
 988    return err;
 989} /* ds_ioctl */
 990
 991/*====================================================================*/
 992
 993static const struct file_operations ds_fops = {
 994        .owner          = THIS_MODULE,
 995        .open           = ds_open,
 996        .release        = ds_release,
 997        .ioctl          = ds_ioctl,
 998        .read           = ds_read,
 999        .write          = ds_write,
1000        .poll           = ds_poll,
1001};
1002
1003void __init pcmcia_setup_ioctl(void) {
1004        int i;
1005
1006        /* Set up character device for user mode clients */
1007        i = register_chrdev(0, "pcmcia", &ds_fops);
1008        if (i < 0)
1009                printk(KERN_NOTICE "unable to find a free device # for "
1010                       "Driver Services (error=%d)\n", i);
1011        else
1012                major_dev = i;
1013
1014#ifdef CONFIG_PROC_FS
1015        proc_pccard = proc_mkdir("bus/pccard", NULL);
1016        if (proc_pccard)
1017                create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);
1018#endif
1019}
1020
1021
1022void __exit pcmcia_cleanup_ioctl(void) {
1023#ifdef CONFIG_PROC_FS
1024        if (proc_pccard) {
1025                remove_proc_entry("drivers", proc_pccard);
1026                remove_proc_entry("bus/pccard", NULL);
1027        }
1028#endif
1029        if (major_dev != -1)
1030                unregister_chrdev(major_dev, "pcmcia");
1031}
1032
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.