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

📄 cm4000_cs.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (copy_to_user(argp, &status, sizeof(int)))				return -EFAULT;		}		return 0;	case CM_IOCGATR:		DEBUGP(4, dev, "... in CM_IOCGATR\n");		{			struct atreq __user *atreq = argp;			int tmp;			/* allow nonblocking io and being interrupted */			if (wait_event_interruptible			    (dev->atrq,			     ((filp->f_flags & O_NONBLOCK)			      || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags)				  != 0)))) {				if (filp->f_flags & O_NONBLOCK)					return -EAGAIN;				return -ERESTARTSYS;			}			if (test_bit(IS_ATR_VALID, &dev->flags) == 0) {				tmp = -1;				if (copy_to_user(&(atreq->atr_len), &tmp,						 sizeof(int)))					return -EFAULT;			} else {				if (copy_to_user(atreq->atr, dev->atr,						 dev->atr_len))					return -EFAULT;				tmp = dev->atr_len;				if (copy_to_user(&(atreq->atr_len), &tmp, sizeof(int)))					return -EFAULT;			}			return 0;		}	case CM_IOCARDOFF:#ifdef PCMCIA_DEBUG		DEBUGP(4, dev, "... in CM_IOCARDOFF\n");		if (dev->flags0 & 0x01) {			DEBUGP(4, dev, "    Card inserted\n");		} else {			DEBUGP(2, dev, "    No card inserted\n");		}		if (dev->flags0 & 0x02) {			DEBUGP(4, dev, "    Card powered\n");		} else {			DEBUGP(2, dev, "    Card not powered\n");		}#endif		/* is a card inserted and powered? */		if ((dev->flags0 & 0x01) && (dev->flags0 & 0x02)) {			/* get IO lock */			if (wait_event_interruptible			    (dev->ioq,			     ((filp->f_flags & O_NONBLOCK)			      || (test_and_set_bit(LOCK_IO, (void *)&dev->flags)				  == 0)))) {				if (filp->f_flags & O_NONBLOCK)					return -EAGAIN;				return -ERESTARTSYS;			}			/* Set Flags0 = 0x42 */			DEBUGP(4, dev, "Set Flags0=0x42 \n");			xoutb(0x42, REG_FLAGS0(iobase));			clear_bit(IS_ATR_PRESENT, &dev->flags);			clear_bit(IS_ATR_VALID, &dev->flags);			dev->mstate = M_CARDOFF;			clear_bit(LOCK_IO, &dev->flags);			if (wait_event_interruptible			    (dev->atrq,			     ((filp->f_flags & O_NONBLOCK)			      || (test_bit(IS_ATR_VALID, (void *)&dev->flags) !=				  0)))) {				if (filp->f_flags & O_NONBLOCK)					return -EAGAIN;				return -ERESTARTSYS;			}		}		/* release lock */		clear_bit(LOCK_IO, &dev->flags);		wake_up_interruptible(&dev->ioq);		return 0;	case CM_IOCSPTS:		{			struct ptsreq krnptsreq;			if (copy_from_user(&krnptsreq, argp,					   sizeof(struct ptsreq)))				return -EFAULT;			rc = 0;			DEBUGP(4, dev, "... in CM_IOCSPTS\n");			/* wait for ATR to get valid */			if (wait_event_interruptible			    (dev->atrq,			     ((filp->f_flags & O_NONBLOCK)			      || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags)				  != 0)))) {				if (filp->f_flags & O_NONBLOCK)					return -EAGAIN;				return -ERESTARTSYS;			}			/* get IO lock */			if (wait_event_interruptible			    (dev->ioq,			     ((filp->f_flags & O_NONBLOCK)			      || (test_and_set_bit(LOCK_IO, (void *)&dev->flags)				  == 0)))) {				if (filp->f_flags & O_NONBLOCK)					return -EAGAIN;				return -ERESTARTSYS;			}			if ((rc = set_protocol(dev, &krnptsreq)) != 0) {				/* auto power_on again */				dev->mstate = M_FETCH_ATR;				clear_bit(IS_ATR_VALID, &dev->flags);			}			/* release lock */			clear_bit(LOCK_IO, &dev->flags);			wake_up_interruptible(&dev->ioq);		}		return rc;#ifdef PCMCIA_DEBUG	case CM_IOSDBGLVL:	/* set debug log level */		{			int old_pc_debug = 0;			old_pc_debug = pc_debug;			if (copy_from_user(&pc_debug, argp, sizeof(int)))				return -EFAULT;			if (old_pc_debug != pc_debug)				DEBUGP(0, dev, "Changed debug log level "				       "to %i\n", pc_debug);		}		return rc;#endif	default:		DEBUGP(4, dev, "... in default (unknown IOCTL code)\n");		return -EINVAL;	}}static int cmm_open(struct inode *inode, struct file *filp){	struct cm4000_dev *dev;	struct pcmcia_device *link;	int rc, minor = iminor(inode);	if (minor >= CM4000_MAX_DEV)		return -ENODEV;	link = dev_table[minor];	if (link == NULL || !pcmcia_dev_present(link))		return -ENODEV;	if (link->open)		return -EBUSY;	dev = link->priv;	filp->private_data = dev;	DEBUGP(2, dev, "-> cmm_open(device=%d.%d process=%s,%d)\n",	      imajor(inode), minor, current->comm, current->pid);	/* init device variables, they may be "polluted" after close	 * or, the device may never have been closed (i.e. open failed)	 */	ZERO_DEV(dev);	/* opening will always block since the	 * monitor will be started by open, which	 * means we have to wait for ATR becoming	 * vaild = block until valid (or card	 * inserted)	 */	if (filp->f_flags & O_NONBLOCK)		return -EAGAIN;	dev->mdelay = T_50MSEC;	/* start monitoring the cardstatus */	start_monitor(dev);	link->open = 1;		/* only one open per device */	rc = 0;	DEBUGP(2, dev, "<- cmm_open\n");	return nonseekable_open(inode, filp);}static int cmm_close(struct inode *inode, struct file *filp){	struct cm4000_dev *dev;	struct pcmcia_device *link;	int minor = iminor(inode);	if (minor >= CM4000_MAX_DEV)		return -ENODEV;	link = dev_table[minor];	if (link == NULL)		return -ENODEV;	dev = link->priv;	DEBUGP(2, dev, "-> cmm_close(maj/min=%d.%d)\n",	       imajor(inode), minor);	stop_monitor(dev);	ZERO_DEV(dev);	link->open = 0;		/* only one open per device */	wake_up(&dev->devq);	/* socket removed? */	DEBUGP(2, dev, "cmm_close\n");	return 0;}static void cmm_cm4000_release(struct pcmcia_device * link){	struct cm4000_dev *dev = link->priv;	/* dont terminate the monitor, rather rely on	 * close doing that for us.	 */	DEBUGP(3, dev, "-> cmm_cm4000_release\n");	while (link->open) {		printk(KERN_INFO MODULE_NAME ": delaying release until "		       "process has terminated\n");		/* note: don't interrupt us:		 * close the applications which own		 * the devices _first_ !		 */		wait_event(dev->devq, (link->open == 0));	}	/* dev->devq=NULL;	this cannot be zeroed earlier */	DEBUGP(3, dev, "<- cmm_cm4000_release\n");	return;}/*==== Interface to PCMCIA Layer =======================================*/static int cm4000_config(struct pcmcia_device * link, int devno){	struct cm4000_dev *dev;	tuple_t tuple;	cisparse_t parse;	u_char buf[64];	int fail_fn, fail_rc;	int rc;	/* read the config-tuples */	tuple.DesiredTuple = CISTPL_CONFIG;	tuple.Attributes = 0;	tuple.TupleData = buf;	tuple.TupleDataMax = sizeof(buf);	tuple.TupleOffset = 0;	if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {		fail_fn = GetFirstTuple;		goto cs_failed;	}	if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {		fail_fn = GetTupleData;		goto cs_failed;	}	if ((fail_rc =	     pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) {		fail_fn = ParseTuple;		goto cs_failed;	}	link->conf.ConfigBase = parse.config.base;	link->conf.Present = parse.config.rmask[0];	link->io.BasePort2 = 0;	link->io.NumPorts2 = 0;	link->io.Attributes2 = 0;	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;	for (rc = pcmcia_get_first_tuple(link, &tuple);	     rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {		rc = pcmcia_get_tuple_data(link, &tuple);		if (rc != CS_SUCCESS)			continue;		rc = pcmcia_parse_tuple(link, &tuple, &parse);		if (rc != CS_SUCCESS)			continue;		link->conf.ConfigIndex = parse.cftable_entry.index;		if (!parse.cftable_entry.io.nwin)			continue;		/* Get the IOaddr */		link->io.BasePort1 = parse.cftable_entry.io.win[0].base;		link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;		link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;		if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))			link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;		if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))			link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;		link->io.IOAddrLines = parse.cftable_entry.io.flags		    & CISTPL_IO_LINES_MASK;		rc = pcmcia_request_io(link, &link->io);		if (rc == CS_SUCCESS)			break;	/* we are done */	}	if (rc != CS_SUCCESS)		goto cs_release;	link->conf.IntType = 00000002;	if ((fail_rc =	     pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {		fail_fn = RequestConfiguration;		goto cs_release;	}	dev = link->priv;	sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);	dev->node.major = major;	dev->node.minor = devno;	dev->node.next = NULL;	link->dev_node = &dev->node;	return 0;cs_failed:	cs_error(link, fail_fn, fail_rc);cs_release:	cm4000_release(link);	return -ENODEV;}static int cm4000_suspend(struct pcmcia_device *link){	struct cm4000_dev *dev;	dev = link->priv;	stop_monitor(dev);	return 0;}static int cm4000_resume(struct pcmcia_device *link){	struct cm4000_dev *dev;	dev = link->priv;	if (link->open)		start_monitor(dev);	return 0;}static void cm4000_release(struct pcmcia_device *link){	cmm_cm4000_release(link->priv);	/* delay release until device closed */	pcmcia_disable_device(link);}static int cm4000_probe(struct pcmcia_device *link){	struct cm4000_dev *dev;	int i, ret;	for (i = 0; i < CM4000_MAX_DEV; i++)		if (dev_table[i] == NULL)			break;	if (i == CM4000_MAX_DEV) {		printk(KERN_NOTICE MODULE_NAME ": all devices in use\n");		return -ENODEV;	}	/* create a new cm4000_cs device */	dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL);	if (dev == NULL)		return -ENOMEM;	dev->p_dev = link;	link->priv = dev;	link->conf.IntType = INT_MEMORY_AND_IO;	dev_table[i] = link;	init_waitqueue_head(&dev->devq);	init_waitqueue_head(&dev->ioq);	init_waitqueue_head(&dev->atrq);	init_waitqueue_head(&dev->readq);	ret = cm4000_config(link, i);	if (ret)		return ret;	class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,			    "cmm%d", i);	return 0;}static void cm4000_detach(struct pcmcia_device *link){	struct cm4000_dev *dev = link->priv;	int devno;	/* find device */	for (devno = 0; devno < CM4000_MAX_DEV; devno++)		if (dev_table[devno] == link)			break;	if (devno == CM4000_MAX_DEV)		return;	stop_monitor(dev);	cm4000_release(link);	dev_table[devno] = NULL; 	kfree(dev);	class_device_destroy(cmm_class, MKDEV(major, devno));	return;}static struct file_operations cm4000_fops = {	.owner	= THIS_MODULE,	.read	= cmm_read,	.write	= cmm_write,	.ioctl	= cmm_ioctl,	.open	= cmm_open,	.release= cmm_close,};static struct pcmcia_device_id cm4000_ids[] = {	PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0002),	PCMCIA_DEVICE_PROD_ID12("CardMan", "4000", 0x2FB368CA, 0xA2BD8C39),	PCMCIA_DEVICE_NULL,};MODULE_DEVICE_TABLE(pcmcia, cm4000_ids);static struct pcmcia_driver cm4000_driver = {	.owner	  = THIS_MODULE,	.drv	  = {		.name = "cm4000_cs",		},	.probe    = cm4000_probe,	.remove   = cm4000_detach,	.suspend  = cm4000_suspend,	.resume   = cm4000_resume,	.id_table = cm4000_ids,};static int __init cmm_init(void){	int rc;	printk(KERN_INFO "%s\n", version);	cmm_class = class_create(THIS_MODULE, "cardman_4000");	if (!cmm_class)		return -1;	major = register_chrdev(0, DEVICE_NAME, &cm4000_fops);	if (major < 0) {		printk(KERN_WARNING MODULE_NAME			": could not get major number\n");		return -1;	}	rc = pcmcia_register_driver(&cm4000_driver);	if (rc < 0) {		unregister_chrdev(major, DEVICE_NAME);		return rc;	}	return 0;}static void __exit cmm_exit(void){	printk(KERN_INFO MODULE_NAME ": unloading\n");	pcmcia_unregister_driver(&cm4000_driver);	unregister_chrdev(major, DEVICE_NAME);	class_destroy(cmm_class);};module_init(cmm_init);module_exit(cmm_exit);MODULE_LICENSE("Dual BSD/GPL");

⌨️ 快捷键说明

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