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

📄 ds.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
    struct pcmcia_bus_socket *s;    user_info_t *user;    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));        if (count != 4)	return -EINVAL;    if ((file->f_flags & O_ACCMODE) == O_RDONLY)	return -EBADF;    user = file->private_data;    if (CHECK_USER(user))	return -EIO;    s = user->socket;    if (s->state & DS_SOCKET_DEAD)        return -EIO;    if (s->req_pending) {	s->req_pending--;	get_user(s->req_result, (int __user *)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){    struct pcmcia_bus_socket *s;    user_info_t *user;    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode));        user = file->private_data;    if (CHECK_USER(user))	return POLLERR;    s = user->socket;    /*     * We don't check for a dead socket here since that     * will send cardmgr into an endless spin.     */    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){    struct pcmcia_bus_socket *s;    void __user *uarg = (char __user *)arg;    u_int size;    int ret, err;    ds_ioctl_arg_t buf;    user_info_t *user;    ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);        user = file->private_data;    if (CHECK_USER(user))	return -EIO;    s = user->socket;    if (s->state & DS_SOCKET_DEAD)        return -EIO;        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, uarg, size);	if (err) {	    ds_dbg(3, "ds_ioctl(): verify_read = %d\n", err);	    return err;	}    }    if (cmd & IOC_OUT) {	err = verify_area(VERIFY_WRITE, uarg, size);	if (err) {	    ds_dbg(3, "ds_ioctl(): verify_write = %d\n", err);	    return err;	}    }        err = ret = 0;        if (cmd & IOC_IN) __copy_from_user((char *)&buf, uarg, 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:	pcmcia_validate_mem(s->parent);	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:	pcmcia_validate_mem(s->parent);	ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);	break;    case DS_SUSPEND_CARD:	ret = pcmcia_suspend_card(s->parent);	break;    case DS_RESUME_CARD:	ret = pcmcia_resume_card(s->parent);	break;    case DS_EJECT_CARD:	err = pcmcia_eject_card(s->parent);	break;    case DS_INSERT_CARD:	err = pcmcia_insert_card(s->parent);	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(s, &buf.bind_info);	break;    case DS_GET_DEVICE_INFO:	err = get_device_info(s, &buf.bind_info, 1);	break;    case DS_GET_NEXT_DEVICE:	err = get_device_info(s, &buf.bind_info, 0);	break;    case DS_UNBIND_REQUEST:	err = unbind_request(s, &buf.bind_info);	break;    case DS_BIND_MTD:	if (!capable(CAP_SYS_ADMIN)) return -EPERM;	err = bind_mtd(s, &buf.mtd_info);	break;    default:	err = -EINVAL;    }        if ((err == 0) && (ret != CS_SUCCESS)) {	ds_dbg(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(uarg, (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,};static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev){	struct pcmcia_socket *socket = class_dev->class_data;	client_reg_t client_reg;	bind_req_t bind;	struct pcmcia_bus_socket *s;	int ret;	s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL);	if(!s)		return -ENOMEM;	memset(s, 0, sizeof(struct pcmcia_bus_socket));	atomic_set(&s->refcount, 1);    	/*	 * 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..	 */	msleep(250);	init_waitqueue_head(&s->queue);	init_waitqueue_head(&s->request);	/* initialize data */	INIT_WORK(&s->removal, handle_removal, s);	s->parent = socket;	/* Set up hotline to Card Services */	client_reg.dev_info = bind.dev_info = &dev_info;	bind.Socket = socket;	bind.Function = BIND_FN_ALL;	ret = pcmcia_bind_device(&bind);	if (ret != CS_SUCCESS) {		cs_error(NULL, BindDevice, ret);		kfree(s);		return -EINVAL;	}	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;	client_reg.event_callback_args.client_data = s;	ret = pcmcia_register_client(&s->handle, &client_reg);	if (ret != CS_SUCCESS) {		cs_error(NULL, RegisterClient, ret);		kfree(s);		return -EINVAL;	}	socket->pcmcia = s;	return 0;}static void pcmcia_bus_remove_socket(struct class_device *class_dev){	struct pcmcia_socket *socket = class_dev->class_data;	if (!socket || !socket->pcmcia)		return;	flush_scheduled_work();	pcmcia_deregister_client(socket->pcmcia->handle);	socket->pcmcia->state |= DS_SOCKET_DEAD;	pcmcia_put_bus_socket(socket->pcmcia);	socket->pcmcia = NULL;	return;}/* the pcmcia_bus_interface is used to handle pcmcia socket devices */static struct class_interface pcmcia_bus_interface = {	.class = &pcmcia_socket_class,	.add = &pcmcia_bus_add_socket,	.remove = &pcmcia_bus_remove_socket,};struct bus_type pcmcia_bus_type = {	.name = "pcmcia",};EXPORT_SYMBOL(pcmcia_bus_type);static int __init init_pcmcia_bus(void){	int i;	bus_register(&pcmcia_bus_type);	class_interface_register(&pcmcia_bus_interface);	/* 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	proc_pccard = proc_mkdir("pccard", proc_bus);	if (proc_pccard)		create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);#endif	return 0;}fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that 			       * pcmcia_socket_class is already registered */static void __exit exit_pcmcia_bus(void){	class_interface_unregister(&pcmcia_bus_interface);#ifdef CONFIG_PROC_FS	if (proc_pccard) {		remove_proc_entry("drivers", proc_pccard);		remove_proc_entry("pccard", proc_bus);	}#endif	if (major_dev != -1)		unregister_chrdev(major_dev, "pcmcia");	bus_unregister(&pcmcia_bus_type);}module_exit(exit_pcmcia_bus);/* helpers for backwards-compatible functions */static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr){	struct pcmcia_socket * s = pcmcia_get_socket_by_nr(nr);	if (s && s->pcmcia)		return s->pcmcia;	else		return NULL;}/* backwards-compatible accessing of driver --- by name! */struct cmp_data {	void *dev_info;	struct pcmcia_driver *drv;};static int cmp_drv_callback(struct device_driver *drv, void *data){	struct cmp_data *cmp = data;	if (strncmp((char *)cmp->dev_info, (char *)drv->name,		    DEV_NAME_LEN) == 0) {		cmp->drv = container_of(drv, struct pcmcia_driver, drv);		return -EINVAL;	}	return 0;}static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info){	int ret;	struct cmp_data cmp = {		.dev_info = dev_info,	};		ret = bus_for_each_drv(&pcmcia_bus_type, NULL, &cmp, cmp_drv_callback);	if (ret)		return cmp.drv;	return NULL;}

⌨️ 快捷键说明

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