Annotation of Gnu-Mach/linux/pcmcia-cs/modules/ds.c, revision 1.1.1.1

1.1       root        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:     <[email protected]>.  Portions created by David A. Hinds
                     19:     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
                     20: 
                     21:     Alternatively, the contents of this file may be used under the
                     22:     terms of the GNU General Public License version 2 (the "GPL"), in
                     23:     which case the provisions of the GPL are applicable instead of the
                     24:     above.  If you wish to allow the use of your version of this file
                     25:     only under the terms of the GPL and not to allow others to use
                     26:     your version of this file under the MPL, indicate your decision
                     27:     by deleting the provisions above and replace them with the notice
                     28:     and other provisions required by the GPL.  If you do not delete
                     29:     the provisions above, a recipient may use your version of this
                     30:     file under either the MPL or the GPL.
                     31:     
                     32: ======================================================================*/
                     33: 
                     34: #include <linux/module.h>
                     35: #include <linux/init.h>
                     36: #include <linux/kernel.h>
                     37: #include <linux/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_CODE >= KERNEL_VERSION(2,1,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: 
                     69: MODULE_AUTHOR("David Hinds <[email protected]>");
                     70: MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
                     71: MODULE_LICENSE("Dual MPL/GPL");
                     72: 
                     73: #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
                     74: 
                     75: #ifdef PCMCIA_DEBUG
                     76: INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
                     77: #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
                     78: static const char *version =
                     79: "ds.c 1.115 2002/10/12 19:03:44 (David Hinds)";
                     80: #else
                     81: #define DEBUG(n, args...)
                     82: #endif
                     83: 
                     84: /*====================================================================*/
                     85: 
                     86: typedef 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: 
                     94: typedef 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_EVENTS     32
                    103: #define USER_MAGIC     0x7ea4
                    104: #define CHECK_USER(u) \
                    105:     (((u) == NULL) || ((u)->user_magic != USER_MAGIC))
                    106: typedef struct user_info_t {
                    107:     u_int              user_magic;
                    108:     int                        event_head, event_tail;
                    109:     event_t            event[MAX_EVENTS];
                    110:     struct user_info_t *next;
                    111: } user_info_t;
                    112: 
                    113: /* Socket state information */
                    114: typedef 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_PRESENT         0x01
                    125: #define SOCKET_BUSY            0x02
                    126: #define SOCKET_REMOVAL_PENDING 0x10
                    127: 
                    128: /*====================================================================*/
                    129: 
                    130: /* Device driver ID passed to Card Services */
                    131: static dev_info_t dev_info = "Driver Services";
                    132: 
                    133: /* Linked list of all registered device drivers */
                    134: static driver_info_t *root_driver = NULL;
                    135: 
                    136: static int sockets = 0, major_dev = -1;
                    137: static socket_info_t *socket_table = NULL;
                    138: 
                    139: extern struct proc_dir_entry *proc_pccard;
                    140: 
                    141: /* We use this to distinguish in-kernel from modular drivers */
                    142: static int init_status = 1;
                    143: 
                    144: /*====================================================================*/
                    145: 
                    146: static 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: 
                    160: int 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);
                    169:     for (driver = root_driver; driver; driver = driver->next)
                    170:        if (strncmp((char *)dev_info, (char *)driver->dev_info,
                    171:                    DEV_NAME_LEN) == 0)
                    172:            break;
                    173:     if (!driver) {
                    174:        driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
                    175:        if (!driver) return -ENOMEM;
                    176:        strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
                    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)
                    193:                printk(KERN_NOTICE "ds: unable to create instance "
                    194:                       "of '%s'!\n", driver->dev_info);
                    195:        }
                    196:     
                    197:     return 0;
                    198: } /* register_pccard_driver */
                    199: 
                    200: /*====================================================================*/
                    201: 
                    202: int 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",
                    209:          (char *)dev_info);
                    210:     while ((*d) && (strncmp((*d)->dev_info, (char *)dev_info,
                    211:                            DEV_NAME_LEN) != 0))
                    212:        d = &(*d)->next;
                    213:     if (*d == NULL)
                    214:        return -ENODEV;
                    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; target->detach = NULL;
                    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;
                    226:     }
                    227:     return 0;
                    228: } /* unregister_pccard_driver */
                    229: 
                    230: /*====================================================================*/
                    231: 
                    232: #ifdef HAS_PROC_BUS
                    233: static 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 += 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: 
                    251: static int queue_empty(user_info_t *user)
                    252: {
                    253:     return (user->event_head == user->event_tail);
                    254: }
                    255: 
                    256: static event_t get_queued_event(user_info_t *user)
                    257: {
                    258:     user->event_tail = (user->event_tail+1) % MAX_EVENTS;
                    259:     return user->event[user->event_tail];
                    260: }
                    261: 
                    262: static void queue_event(user_info_t *user, event_t event)
                    263: {
                    264:     user->event_head = (user->event_head+1) % MAX_EVENTS;
                    265:     if (user->event_head == user->event_tail)
                    266:        user->event_tail = (user->event_tail+1) % MAX_EVENTS;
                    267:     user->event[user->event_head] = event;
                    268: }
                    269: 
                    270: static 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_interruptible(&s->queue);
                    276: }
                    277: 
                    278: static int handle_request(socket_info_t *s, event_t event)
                    279: {
                    280:     if (s->req_pending != 0)
                    281:        return CS_IN_USE;
                    282:     if (s->state & SOCKET_BUSY)
                    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))
                    288:            return CS_IN_USE;
                    289:        else
                    290:            return s->req_result;
                    291:     }
                    292:     return CS_SUCCESS;
                    293: }
                    294: 
                    295: static void handle_removal(u_long sn)
                    296: {
                    297:     socket_info_t *s = &socket_table[sn];
                    298:     handle_event(s, CS_EVENT_CARD_REMOVAL);
                    299:     s->state &= ~SOCKET_REMOVAL_PENDING;
                    300: }
                    301: 
                    302: /*======================================================================
                    303: 
                    304:     The card status event handler.
                    305:     
                    306: ======================================================================*/
                    307: 
                    308: static 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",
                    315:          event, priority, args->client_handle);
                    316:     s = args->client_data;
                    317:     i = s - socket_table;
                    318:     
                    319:     switch (event) {
                    320:        
                    321:     case CS_EVENT_CARD_REMOVAL:
                    322:        s->state &= ~SOCKET_PRESENT;
                    323:        if (!(s->state & SOCKET_REMOVAL_PENDING)) {
                    324:            s->state |= SOCKET_REMOVAL_PENDING;
                    325:            s->removal.expires = jiffies + HZ/10;
                    326:            add_timer(&s->removal);
                    327:        }
                    328:        break;
                    329:        
                    330:     case CS_EVENT_CARD_INSERTION:
                    331:        s->state |= SOCKET_PRESENT;
                    332:        handle_event(s, event);
                    333:        break;
                    334: 
                    335:     case CS_EVENT_EJECTION_REQUEST:
                    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: 
                    353: static 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_SUCCESS) {
                    364:        cs_error(NULL, BindMTD, ret);
                    365:        printk(KERN_NOTICE "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 -ENODEV;
                    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: 
                    382: static 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,
                    391:          (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) {
                    397:        driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
                    398:        if (!driver) return -ENOMEM;
                    399:        strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN);
                    400:        driver->use_count = 0;
                    401:        driver->next = root_driver;
                    402:        driver->attach = NULL; driver->detach = NULL;
                    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) {
                    411:        bind_info->instance = b->instance;
                    412:        return -EBUSY;
                    413:     }
                    414:     b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
                    415:     if (!b)
                    416:        return -ENOMEM;
                    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_SUCCESS) {
                    423:        cs_error(NULL, BindDevice, ret);
                    424:        printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
                    425:               (char *)dev_info, i);
                    426:        kfree(b);
                    427:        return -ENODEV;
                    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;
                    435:     b->next = s->bind;
                    436:     s->bind = b;
                    437:     
                    438:     if (driver->attach) {
                    439:        b->instance = driver->attach();
                    440:        if (b->instance == NULL) {
                    441:            printk(KERN_NOTICE "ds: unable to create instance "
                    442:                   "of '%s'!\n", (char *)bind_info->dev_info);
                    443:            return -ENODEV;
                    444:        }
                    445:     }
                    446:     
                    447:     return 0;
                    448: } /* bind_request */
                    449: 
                    450: /*====================================================================*/
                    451: 
                    452: static 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) return -ENODEV;
                    464:     if ((b->instance == NULL) ||
                    465:        (b->instance->state & DEV_CONFIG_PENDING))
                    466:        return -EAGAIN;
                    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) return -ENODEV;
                    473: 
                    474:     strncpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
                    475:     bind_info->name[DEV_NAME_LEN-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: 
                    485: static 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,
                    491:          (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)
                    498:        return -ENODEV;
                    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 MACH
                    528: 
                    529: static int ds_open(struct inode *inode, struct file *file)
                    530: {
                    531:     socket_t i = MINOR(inode->i_rdev);
                    532:     socket_info_t *s;
                    533:     user_info_t *user;
                    534: 
                    535:     DEBUG(0, "ds_open(socket %d)\n", i);
                    536:     if ((i >= sockets) || (sockets == 0))
                    537:        return -ENODEV;
                    538:     s = &socket_table[i];
                    539:     if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
                    540:        if (s->state & SOCKET_BUSY)
                    541:            return -EBUSY;
                    542:        else
                    543:            s->state |= SOCKET_BUSY;
                    544:     }
                    545:     
                    546:     MOD_INC_USE_COUNT;
                    547:     user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
                    548:     if (!user) {
                    549:        MOD_DEC_USE_COUNT;
                    550:        return -ENOMEM;
                    551:     }
                    552:     user->event_tail = user->event_head = 0;
                    553:     user->next = s->user;
                    554:     user->user_magic = USER_MAGIC;
                    555:     s->user = user;
                    556:     file->private_data = user;
                    557:     
                    558:     if (s->state & SOCKET_PRESENT)
                    559:        queue_event(user, CS_EVENT_CARD_INSERTION);
                    560:     return 0;
                    561: } /* ds_open */
                    562: 
                    563: /*====================================================================*/
                    564: 
                    565: static FS_RELEASE_T ds_release(struct inode *inode, struct file *file)
                    566: {
                    567:     socket_t i = MINOR(inode->i_rdev);
                    568:     socket_info_t *s;
                    569:     user_info_t *user, **link;
                    570: 
                    571:     DEBUG(0, "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))
                    577:        return (FS_RELEASE_T)0;
                    578: 
                    579:     /* Unlink user data structure */
                    580:     if ((file->f_flags & O_ACCMODE) != O_RDONLY)
                    581:        s->state &= ~SOCKET_BUSY;
                    582:     file->private_data = NULL;
                    583:     for (link = &s->user; *link; link = &(*link)->next)
                    584:        if (*link == user) break;
                    585:     if (link == NULL)
                    586:        return (FS_RELEASE_T)0;
                    587:     *link = user->next;
                    588:     user->user_magic = 0;
                    589:     kfree(user);
                    590:     
                    591:     MOD_DEC_USE_COUNT;
                    592:     return (FS_RELEASE_T)0;
                    593: } /* ds_release */
                    594: 
                    595: /*====================================================================*/
                    596: 
                    597: static 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);
                    602:     socket_info_t *s;
                    603:     user_info_t *user;
                    604: 
                    605:     DEBUG(2, "ds_read(socket %d)\n", i);
                    606:     
                    607:     if ((i >= sockets) || (sockets == 0))
                    608:        return -ENODEV;
                    609:     if (count < 4)
                    610:        return -EINVAL;
                    611:     s = &socket_table[i];
                    612:     user = file->private_data;
                    613:     if (CHECK_USER(user))
                    614:        return -EIO;
                    615:     
                    616:     if (queue_empty(user)) {
                    617:        interruptible_sleep_on(&s->queue);
                    618:        if (signal_pending(current))
                    619:            return -EINTR;
                    620:     }
                    621:     put_user(get_queued_event(user), (int *)buf);
                    622:     return 4;
                    623: } /* ds_read */
                    624: 
                    625: /*====================================================================*/
                    626: 
                    627: static 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);
                    632:     socket_info_t *s;
                    633:     user_info_t *user;
                    634: 
                    635:     DEBUG(2, "ds_write(socket %d)\n", i);
                    636:     
                    637:     if ((i >= sockets) || (sockets == 0))
                    638:        return -ENODEV;
                    639:     if (count != 4)
                    640:        return -EINVAL;
                    641:     if ((file->f_flags & O_ACCMODE) == O_RDONLY)
                    642:        return -EBADF;
                    643:     s = &socket_table[i];
                    644:     user = file->private_data;
                    645:     if (CHECK_USER(user))
                    646:        return -EIO;
                    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_interruptible(&s->request);
                    653:     } else
                    654:        return -EIO;
                    655: 
                    656:     return 4;
                    657: } /* ds_write */
                    658: 
                    659: /*====================================================================*/
                    660: 
                    661: #if (LINUX_VERSION_CODE < VERSION(2,1,23))
                    662: 
                    663: static 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);
                    667:     socket_info_t *s;
                    668:     user_info_t *user;
                    669: 
                    670:     DEBUG(2, "ds_select(socket %d)\n", i);
                    671:     
                    672:     if ((i >= sockets) || (sockets == 0))
                    673:        return -ENODEV;
                    674:     s = &socket_table[i];
                    675:     user = file->private_data;
                    676:     if (CHECK_USER(user))
                    677:        return -EIO;
                    678:     if (sel_type != SEL_IN)
                    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: 
                    688: static u_int ds_poll(struct file *file, poll_table *wait)
                    689: {
                    690:     socket_t i = MINOR(F_INODE(file)->i_rdev);
                    691:     socket_info_t *s;
                    692:     user_info_t *user;
                    693: 
                    694:     DEBUG(2, "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))
                    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: 
                    714: static 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);
                    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);
                    724:     
                    725:     if ((i >= sockets) || (sockets == 0))
                    726:        return -ENODEV;
                    727:     s = &socket_table[i];
                    728:     
                    729:     size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
                    730:     if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
                    731: 
                    732:     /* Permission check */
                    733:     if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
                    734:        return -EPERM;
                    735:        
                    736: #ifndef MACH
                    737:     if (cmd & IOC_IN) {
                    738:        err = verify_area(VERIFY_READ, (char *)arg, size);
                    739:        if (err) {
                    740:            DEBUG(3, "ds_ioctl(): verify_read = %d\n", err);
                    741:            return err;
                    742:        }
                    743:     }
                    744:     if (cmd & IOC_OUT) {
                    745:        err = verify_area(VERIFY_WRITE, (char *)arg, size);
                    746:        if (err) {
                    747:            DEBUG(3, "ds_ioctl(): verify_write = %d\n", err);
                    748:            return err;
                    749:        }
                    750:     }
                    751: #endif
                    752:     
                    753:     err = ret = 0;
                    754:     
                    755: #ifndef MACH
                    756:     if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);
                    757: #else
                    758:     if (cmd & IOC_IN) memcpy((char *) &buf, (char *) arg, size);
                    759: #endif
                    760:     
                    761:     switch (cmd) {
                    762:     case DS_ADJUST_RESOURCE_INFO:
                    763:        ret = CardServices(AdjustResourceInfo, s->handle, &buf.adjust);
                    764:        break;
                    765:     case DS_GET_CARD_SERVICES_INFO:
                    766:        ret = CardServices(GetCardServicesInfo, &buf.servinfo);
                    767:        break;
                    768:     case DS_GET_CONFIGURATION_INFO:
                    769:        ret = CardServices(GetConfigurationInfo, s->handle, &buf.config);
                    770:        break;
                    771:     case DS_GET_FIRST_TUPLE:
                    772:        ret = CardServices(GetFirstTuple, s->handle, &buf.tuple);
                    773:        break;
                    774:     case DS_GET_NEXT_TUPLE:
                    775:        ret = CardServices(GetNextTuple, s->handle, &buf.tuple);
                    776:        break;
                    777:     case DS_GET_TUPLE_DATA:
                    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:
                    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:
                    788:        ret = CardServices(ResetCard, s->handle, NULL);
                    789:        break;
                    790:     case DS_GET_STATUS:
                    791:        ret = CardServices(GetStatus, s->handle, &buf.status);
                    792:        break;
                    793:     case DS_VALIDATE_CIS:
                    794:        ret = CardServices(ValidateCIS, s->handle, &buf.cisinfo);
                    795:        break;
                    796:     case DS_SUSPEND_CARD:
                    797:        ret = CardServices(SuspendCard, s->handle, NULL);
                    798:        break;
                    799:     case DS_RESUME_CARD:
                    800:        ret = CardServices(ResumeCard, s->handle, NULL);
                    801:        break;
                    802:     case DS_EJECT_CARD:
                    803:        ret = CardServices(EjectCard, s->handle, NULL);
                    804:        break;
                    805:     case DS_INSERT_CARD:
                    806:        ret = CardServices(InsertCard, s->handle, NULL);
                    807:        break;
                    808:     case DS_ACCESS_CONFIGURATION_REGISTER:
                    809:        if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
                    810:            return -EPERM;
                    811:        ret = CardServices(AccessConfigurationRegister, s->handle,
                    812:                           &buf.conf_reg);
                    813:        break;
                    814:     case DS_GET_FIRST_REGION:
                    815:         ret = CardServices(GetFirstRegion, s->handle, &buf.region);
                    816:        break;
                    817:     case DS_GET_NEXT_REGION:
                    818:        ret = CardServices(GetNextRegion, s->handle, &buf.region);
                    819:        break;
                    820:     case DS_GET_FIRST_WINDOW:
                    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:
                    826:        ret = CardServices(GetNextWindow, &buf.win_info.handle,
                    827:                           &buf.win_info.window);
                    828:        break;
                    829:     case DS_GET_MEM_PAGE:
                    830:        ret = CardServices(GetMemPage, buf.win_info.handle,
                    831:                           &buf.win_info.map);
                    832:        break;
                    833:     case DS_REPLACE_CIS:
                    834:        ret = CardServices(ReplaceCIS, s->handle, &buf.cisdump);
                    835:        break;
                    836:     case DS_BIND_REQUEST:
                    837:        if (!capable(CAP_SYS_ADMIN)) return -EPERM;
                    838:        err = bind_request(i, &buf.bind_info);
                    839:        break;
                    840:     case DS_GET_DEVICE_INFO:
                    841:        err = get_device_info(i, &buf.bind_info, 1);
                    842:        break;
                    843:     case DS_GET_NEXT_DEVICE:
                    844:        err = get_device_info(i, &buf.bind_info, 0);
                    845:        break;
                    846:     case DS_UNBIND_REQUEST:
                    847:        err = unbind_request(i, &buf.bind_info);
                    848:        break;
                    849:     case DS_BIND_MTD:
                    850:        if (!capable(CAP_SYS_ADMIN)) return -EPERM;
                    851:        err = bind_mtd(i, &buf.mtd_info);
                    852:        break;
                    853:     default:
                    854:        err = -EINVAL;
                    855:     }
                    856:     
                    857:     if ((err == 0) && (ret != CS_SUCCESS)) {
                    858:        DEBUG(2, "ds_ioctl: ret = %d\n", ret);
                    859:        switch (ret) {
                    860:        case CS_BAD_SOCKET: case CS_NO_CARD:
                    861:            err = -ENODEV; break;
                    862:        case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
                    863:        case CS_BAD_TUPLE:
                    864:            err = -EINVAL; break;
                    865:        case CS_IN_USE:
                    866:            err = -EBUSY; break;
                    867:        case CS_OUT_OF_RESOURCE:
                    868:            err = -ENOSPC; break;
                    869:        case CS_NO_MORE_ITEMS:
                    870:            err = -ENODATA; break;
                    871:        case CS_UNSUPPORTED_FUNCTION:
                    872:            err = -ENOSYS; break;
                    873:        default:
                    874:            err = -EIO; break;
                    875:        }
                    876:     }
                    877:     
                    878: #ifndef MACH
                    879:     if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size);
                    880: #else
                    881:     if (cmd & IOC_OUT) memcpy((char *) arg, (char *) &buf, size);
                    882: #endif
                    883:      
                    884:     return err;
                    885: } /* ds_ioctl */
                    886: 
                    887: /*====================================================================*/
                    888: 
                    889: #ifndef MACH
                    890: 
                    891: static 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_CODE < VERSION(2,1,23))
                    898:     select:    ds_select
                    899: #else
                    900:     poll:      ds_poll
                    901: #endif
                    902: };
                    903: 
                    904: #if (LINUX_VERSION_CODE <= VERSION(2,1,17))
                    905: 
                    906: #undef CONFIG_MODVERSIONS
                    907: static struct symbol_table ds_symtab = {
                    908: #include <linux/symtab_begin.h>
                    909: #undef X
                    910: #define X(sym) { (void *)&sym, SYMBOL_NAME_STR(sym) }
                    911:     X(register_pccard_driver),
                    912:     X(unregister_pccard_driver),
                    913: #include <linux/symtab_end.h>
                    914: };
                    915: 
                    916: #else
                    917: 
                    918: EXPORT_SYMBOL(register_pccard_driver);
                    919: EXPORT_SYMBOL(unregister_pccard_driver);
                    920: 
                    921: #endif
                    922: 
                    923: #endif /* !defined(MACH) */
                    924: 
                    925: /*====================================================================*/
                    926: 
                    927: int __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);
                    936:     
                    937:     CardServices(GetCardServicesInfo, &serv);
                    938:     if (serv.Revision != CS_RELEASE_CODE) {
                    939:        printk(KERN_NOTICE "ds: Card Services release does not match!\n");
                    940:        return -EINVAL;
                    941:     }
                    942:     if (serv.Count == 0) {
                    943:        printk(KERN_NOTICE "ds: no socket drivers loaded!\n");
                    944:        return -1;
                    945:     }
                    946:     
                    947:     sockets = serv.Count;
                    948:     socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL);
                    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;
                    953:        s->req_pending = 0;
                    954:        init_waitqueue_head(&s->queue);
                    955:        init_waitqueue_head(&s->request);
                    956:        s->handle = NULL;
                    957:        init_timer(&s->removal);
                    958:        s->removal.data = i;
                    959:        s->removal.function = &handle_removal;
                    960:        s->bind = NULL;
                    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_CLIENT;
                    966:     client_reg.EventMask =
                    967:        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
                    968:        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
                    969:        CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST |
                    970:         CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
                    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_ALL;
                    976:        ret = CardServices(BindDevice, &bind);
                    977:        if (ret != CS_SUCCESS) {
                    978:            cs_error(NULL, 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_SUCCESS) {
                    985:            cs_error(NULL, RegisterClient, ret);
                    986:            break;
                    987:        }
                    988:     }
                    989:     
                    990: #ifndef MACH
                    991:     /* Set up character device for user mode clients */
                    992:     i = register_chrdev(0, "pcmcia", &ds_fops);
                    993:     if (i == -EBUSY)
                    994:        printk(KERN_NOTICE "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);
                   1005:     init_status = 0;
                   1006: #endif
                   1007:     return 0;
                   1008: }
                   1009: 
                   1010: #ifdef MODULE
                   1011: 
                   1012: int __init init_module(void)
                   1013: {
                   1014:     return init_pcmcia_ds();
                   1015: }
                   1016: 
                   1017: void __exit 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: /*====================================================================*/

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.