Annotation of Gnu-Mach/linux/pcmcia-cs/modules/ds.c, revision 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.