⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	    if (node == bind_info->next) break;    if (node == NULL) return -ENODEV;    strncpy(bind_info->name, node->dev_name, DEV_NAME_LEN);    bind_info->name[DEV_NAME_LEN-1] = '\0';    bind_info->major = node->major;    bind_info->minor = node->minor;    bind_info->next = node->next;        return 0;} /* get_device_info *//*====================================================================*/static int unbind_request(int i, bind_info_t *bind_info){    socket_info_t *s = &socket_table[i];    socket_bind_t **b, *c;    DEBUG(2, "unbind_request(%d, '%s')\n", i,	  (char *)bind_info->dev_info);    for (b = &s->bind; *b; b = &(*b)->next)	if ((strcmp((char *)(*b)->driver->dev_info,		    (char *)bind_info->dev_info) == 0) &&	    ((*b)->function == bind_info->function))	    break;    if (*b == NULL)	return -ENODEV;        c = *b;    c->driver->use_count--;    if (c->driver->detach) {	if (c->instance)	    c->driver->detach(c->instance);    } else {	if (c->driver->use_count == 0) {	    driver_info_t **d;	    for (d = &root_driver; *d; d = &((*d)->next))		if (c->driver == *d) break;	    *d = (*d)->next;	    kfree(c->driver);	}    }    *b = c->next;    kfree(c);        return 0;} /* unbind_request *//*======================================================================    The user-mode PC Card device interface======================================================================*/static int ds_open(struct inode *inode, struct file *file){    socket_t i = MINOR(inode->i_rdev);    socket_info_t *s;    user_info_t *user;    DEBUG(0, "ds_open(socket %d)\n", i);    if ((i >= sockets) || (sockets == 0))	return -ENODEV;    s = &socket_table[i];    if ((file->f_flags & O_ACCMODE) != O_RDONLY) {	if (s->state & SOCKET_BUSY)	    return -EBUSY;	else	    s->state |= SOCKET_BUSY;    }        user = kmalloc(sizeof(user_info_t), GFP_KERNEL);    if (!user) return -ENOMEM;    user->event_tail = user->event_head = 0;    user->next = s->user;    user->user_magic = USER_MAGIC;    s->user = user;    file->private_data = user;        if (s->state & SOCKET_PRESENT)	queue_event(user, CS_EVENT_CARD_INSERTION);    return 0;} /* ds_open *//*====================================================================*/static int ds_release(struct inode *inode, struct file *file){    socket_t i = MINOR(inode->i_rdev);    socket_info_t *s;    user_info_t *user, **link;    DEBUG(0, "ds_release(socket %d)\n", i);    if ((i >= sockets) || (sockets == 0))	return 0;    lock_kernel();    s = &socket_table[i];    user = file->private_data;    if (CHECK_USER(user))	goto out;    /* Unlink user data structure */    if ((file->f_flags & O_ACCMODE) != O_RDONLY)	s->state &= ~SOCKET_BUSY;    file->private_data = NULL;    for (link = &s->user; *link; link = &(*link)->next)	if (*link == user) break;    if (link == NULL)	goto out;    *link = user->next;    user->user_magic = 0;    kfree(user);out:    unlock_kernel();    return 0;} /* ds_release *//*====================================================================*/static ssize_t ds_read(struct file *file, char *buf,		       size_t count, loff_t *ppos){    socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);    socket_info_t *s;    user_info_t *user;    DEBUG(2, "ds_read(socket %d)\n", i);        if ((i >= sockets) || (sockets == 0))	return -ENODEV;    if (count < 4)	return -EINVAL;    s = &socket_table[i];    user = file->private_data;    if (CHECK_USER(user))	return -EIO;        if (queue_empty(user)) {	interruptible_sleep_on(&s->queue);	if (signal_pending(current))	    return -EINTR;    }    put_user(get_queued_event(user), (int *)buf);    return 4;} /* ds_read *//*====================================================================*/static ssize_t ds_write(struct file *file, const char *buf,			size_t count, loff_t *ppos){    socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);    socket_info_t *s;    user_info_t *user;    DEBUG(2, "ds_write(socket %d)\n", i);        if ((i >= sockets) || (sockets == 0))	return -ENODEV;    if (count != 4)	return -EINVAL;    if ((file->f_flags & O_ACCMODE) == O_RDONLY)	return -EBADF;    s = &socket_table[i];    user = file->private_data;    if (CHECK_USER(user))	return -EIO;    if (s->req_pending) {	s->req_pending--;	get_user(s->req_result, (int *)buf);	if ((s->req_result != 0) || (s->req_pending == 0))	    wake_up_interruptible(&s->request);    } else	return -EIO;    return 4;} /* ds_write *//*====================================================================*//* No kernel lock - fine */static u_int ds_poll(struct file *file, poll_table *wait){    socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);    socket_info_t *s;    user_info_t *user;    DEBUG(2, "ds_poll(socket %d)\n", i);        if ((i >= sockets) || (sockets == 0))	return POLLERR;    s = &socket_table[i];    user = file->private_data;    if (CHECK_USER(user))	return POLLERR;    poll_wait(file, &s->queue, wait);    if (!queue_empty(user))	return POLLIN | POLLRDNORM;    return 0;} /* ds_poll *//*====================================================================*/static int ds_ioctl(struct inode * inode, struct file * file,		    u_int cmd, u_long arg){    socket_t i = MINOR(inode->i_rdev);    socket_info_t *s;    u_int size;    int ret, err;    ds_ioctl_arg_t buf;    DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", i, cmd, arg);        if ((i >= sockets) || (sockets == 0))	return -ENODEV;    s = &socket_table[i];        size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;    if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;    /* Permission check */    if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))	return -EPERM;	    if (cmd & IOC_IN) {	err = verify_area(VERIFY_READ, (char *)arg, size);	if (err) {	    DEBUG(3, "ds_ioctl(): verify_read = %d\n", err);	    return err;	}    }    if (cmd & IOC_OUT) {	err = verify_area(VERIFY_WRITE, (char *)arg, size);	if (err) {	    DEBUG(3, "ds_ioctl(): verify_write = %d\n", err);	    return err;	}    }        err = ret = 0;        if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);        switch (cmd) {    case DS_ADJUST_RESOURCE_INFO:	ret = pcmcia_adjust_resource_info(s->handle, &buf.adjust);	break;    case DS_GET_CARD_SERVICES_INFO:	ret = pcmcia_get_card_services_info(&buf.servinfo);	break;    case DS_GET_CONFIGURATION_INFO:	ret = pcmcia_get_configuration_info(s->handle, &buf.config);	break;    case DS_GET_FIRST_TUPLE:	ret = pcmcia_get_first_tuple(s->handle, &buf.tuple);	break;    case DS_GET_NEXT_TUPLE:	ret = pcmcia_get_next_tuple(s->handle, &buf.tuple);	break;    case DS_GET_TUPLE_DATA:	buf.tuple.TupleData = buf.tuple_parse.data;	buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);	ret = pcmcia_get_tuple_data(s->handle, &buf.tuple);	break;    case DS_PARSE_TUPLE:	buf.tuple.TupleData = buf.tuple_parse.data;	ret = pcmcia_parse_tuple(s->handle, &buf.tuple, &buf.tuple_parse.parse);	break;    case DS_RESET_CARD:	ret = pcmcia_reset_card(s->handle, NULL);	break;    case DS_GET_STATUS:	ret = pcmcia_get_status(s->handle, &buf.status);	break;    case DS_VALIDATE_CIS:	ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);	break;    case DS_SUSPEND_CARD:	ret = pcmcia_suspend_card(s->handle, NULL);	break;    case DS_RESUME_CARD:	ret = pcmcia_resume_card(s->handle, NULL);	break;    case DS_EJECT_CARD:	ret = pcmcia_eject_card(s->handle, NULL);	break;    case DS_INSERT_CARD:	ret = pcmcia_insert_card(s->handle, NULL);	break;    case DS_ACCESS_CONFIGURATION_REGISTER:	if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))	    return -EPERM;	ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);	break;    case DS_GET_FIRST_REGION:        ret = pcmcia_get_first_region(s->handle, &buf.region);	break;    case DS_GET_NEXT_REGION:	ret = pcmcia_get_next_region(s->handle, &buf.region);	break;    case DS_GET_FIRST_WINDOW:	buf.win_info.handle = (window_handle_t)s->handle;	ret = pcmcia_get_first_window(&buf.win_info.handle, &buf.win_info.window);	break;    case DS_GET_NEXT_WINDOW:	ret = pcmcia_get_next_window(&buf.win_info.handle, &buf.win_info.window);	break;    case DS_GET_MEM_PAGE:	ret = pcmcia_get_mem_page(buf.win_info.handle,			   &buf.win_info.map);	break;    case DS_REPLACE_CIS:	ret = pcmcia_replace_cis(s->handle, &buf.cisdump);	break;    case DS_BIND_REQUEST:	if (!capable(CAP_SYS_ADMIN)) return -EPERM;	err = bind_request(i, &buf.bind_info);	break;    case DS_GET_DEVICE_INFO:	err = get_device_info(i, &buf.bind_info, 1);	break;    case DS_GET_NEXT_DEVICE:	err = get_device_info(i, &buf.bind_info, 0);	break;    case DS_UNBIND_REQUEST:	err = unbind_request(i, &buf.bind_info);	break;    case DS_BIND_MTD:	if (!suser()) return -EPERM;	err = bind_mtd(i, &buf.mtd_info);	break;    default:	err = -EINVAL;    }        if ((err == 0) && (ret != CS_SUCCESS)) {	DEBUG(2, "ds_ioctl: ret = %d\n", ret);	switch (ret) {	case CS_BAD_SOCKET: case CS_NO_CARD:	    err = -ENODEV; break;	case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:	case CS_BAD_TUPLE:	    err = -EINVAL; break;	case CS_IN_USE:	    err = -EBUSY; break;	case CS_OUT_OF_RESOURCE:	    err = -ENOSPC; break;	case CS_NO_MORE_ITEMS:	    err = -ENODATA; break;	case CS_UNSUPPORTED_FUNCTION:	    err = -ENOSYS; break;	default:	    err = -EIO; break;	}    }        if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size);         return err;} /* ds_ioctl *//*====================================================================*/static struct file_operations ds_fops = {	owner:		THIS_MODULE,	open:		ds_open,	release:	ds_release,	ioctl:		ds_ioctl,	read:		ds_read,	write:		ds_write,	poll:		ds_poll,};EXPORT_SYMBOL(register_pccard_driver);EXPORT_SYMBOL(unregister_pccard_driver);/*====================================================================*/int __init init_pcmcia_ds(void){    client_reg_t client_reg;    servinfo_t serv;    bind_req_t bind;    socket_info_t *s;    int i, ret;        DEBUG(0, "%s\n", version);     /*     * Ugly. But we want to wait for the socket threads to have started up.     * We really should let the drivers themselves drive some of this..     */    current->state = TASK_INTERRUPTIBLE;    schedule_timeout(HZ/10);    pcmcia_get_card_services_info(&serv);    if (serv.Revision != CS_RELEASE_CODE) {	printk(KERN_NOTICE "ds: Card Services release does not match!\n");	return -1;    }    if (serv.Count == 0) {	printk(KERN_NOTICE "ds: no socket drivers loaded!\n");	return -1;    }        sockets = serv.Count;    socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL);    if (!socket_table) return -1;    for (i = 0, s = socket_table; i < sockets; i++, s++) {	s->state = 0;	s->user = NULL;	s->req_pending = 0;	init_waitqueue_head(&s->queue);	init_waitqueue_head(&s->request);	s->handle = NULL;	init_timer(&s->removal);	s->removal.data = i;	s->removal.function = &handle_removal;	s->bind = NULL;    }        /* Set up hotline to Card Services */    client_reg.dev_info = bind.dev_info = &dev_info;    client_reg.Attributes = INFO_MASTER_CLIENT;    client_reg.EventMask =	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |	CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST |        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;    client_reg.event_handler = &ds_event;    client_reg.Version = 0x0210;    for (i = 0; i < sockets; i++) {	bind.Socket = i;	bind.Function = BIND_FN_ALL;	ret = pcmcia_bind_device(&bind);	if (ret != CS_SUCCESS) {	    cs_error(NULL, BindDevice, ret);	    break;	}	client_reg.event_callback_args.client_data = &socket_table[i];	ret = pcmcia_register_client(&socket_table[i].handle,			   &client_reg);	if (ret != CS_SUCCESS) {	    cs_error(NULL, RegisterClient, ret);	    break;	}    }        /* Set up character device for user mode clients */    i = register_chrdev(0, "pcmcia", &ds_fops);    if (i == -EBUSY)	printk(KERN_NOTICE "unable to find a free device # for "	       "Driver Services\n");    else	major_dev = i;#ifdef CONFIG_PROC_FS    if (proc_pccard)	create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);    init_status = 0;#endif    return 0;}#ifdef MODULEint __init init_module(void){    return init_pcmcia_ds();}void __exit cleanup_module(void){    int i;#ifdef CONFIG_PROC_FS    if (proc_pccard)	remove_proc_entry("drivers", proc_pccard);#endif    if (major_dev != -1)	unregister_chrdev(major_dev, "pcmcia");    for (i = 0; i < sockets; i++)	pcmcia_deregister_client(socket_table[i].handle);    sockets = 0;    kfree(socket_table);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -