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

📄 cm4000_cs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
		for (; i < j; i++) {			xoutb(k++, REG_BUF_ADDR(iobase));			dev->rbuf[i] = xinb(REG_BUF_DATA(iobase));		}	}	if (dev->proto == 0 && count > dev->rlen - dev->rpos) {		DEBUGP(4, dev, "T=0 and count > buffer\n");		dev->rbuf[i] = dev->rbuf[i - 1];		dev->rbuf[i - 1] = dev->procbyte;		j++;	}	count = j;	dev->rpos = dev->rlen + 1;	/* Clear T1Active */	DEBUGP(4, dev, "Clear T1Active\n");	dev->flags1 &= 0xdf;	xoutb(dev->flags1, REG_FLAGS1(iobase));	xoutb(0, REG_FLAGS1(iobase));	/* clear detectCMM */	/* last check before exit */	if (!io_detect_cm4000(iobase, dev))		count = -ENODEV;	if (test_bit(IS_INVREV, &dev->flags) && count > 0)		str_invert_revert(dev->rbuf, count);	if (copy_to_user(buf, dev->rbuf, count))		return -EFAULT;release_io:	clear_bit(LOCK_IO, &dev->flags);	wake_up_interruptible(&dev->ioq);	DEBUGP(2, dev, "<- cmm_read returns: rc = %Zi\n",	       (rc < 0 ? rc : count));	return rc < 0 ? rc : count;}static ssize_t cmm_write(struct file *filp, const char __user *buf,			 size_t count, loff_t *ppos){	struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;	ioaddr_t iobase = dev->link.io.BasePort1;	unsigned short s;	unsigned char tmp;	unsigned char infolen;	unsigned char sendT0;	unsigned short nsend;	unsigned short nr;	ssize_t rc;	int i;	DEBUGP(2, dev, "-> cmm_write(%s,%d)\n", current->comm, current->pid);	if (count == 0)		/* according to manpage */		return 0;	if (dev->proto == 0 && count < 4) {		/* T0 must have at least 4 bytes */		DEBUGP(4, dev, "T0 short write\n");		return -EIO;	}	nr = count & 0x1ff;	/* max bytes to write */	sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0;	if ((dev->link.state & DEV_PRESENT) == 0 ||	/* socket removed */	    test_bit(IS_CMM_ABSENT, &dev->flags))		return -ENODEV;	if (test_bit(IS_BAD_CSUM, &dev->flags)) {		DEBUGP(4, dev, "bad csum\n");		return -EIO;	}	/*	 * wait for atr to become valid.	 * note: it is important to lock this code. if we dont, the monitor	 * could be run between test_bit and the the call the sleep on the	 * atr-queue.  if *then* the monitor detects atr valid, it will wake up	 * any process on the atr-queue, *but* since we have been interrupted,	 * we do not yet sleep on this queue. this would result in a missed	 * wake_up and the calling process would sleep forever (until	 * interrupted).  also, do *not* restore_flags before sleep_on, because	 * this could result in the same situation!	 */	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) {	/* invalid atr */		DEBUGP(4, dev, "invalid ATR\n");		return -EIO;	}	/* lock io */	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 (copy_from_user(dev->sbuf, buf, ((count > 512) ? 512 : count)))		return -EFAULT;	rc = 0;	dev->flags0 = inb(REG_FLAGS0(iobase));	if ((dev->flags0 & 1) == 0	/* no smartcard inserted */	    || dev->flags0 == 0xff) {	/* no cardman inserted */		clear_bit(IS_ATR_VALID, &dev->flags);		if (dev->flags0 & 1) {			set_bit(IS_CMM_ABSENT, &dev->flags);			rc = -ENODEV;		} else {			DEBUGP(4, dev, "IO error\n");			rc = -EIO;		}		goto release_io;	}	xoutb(0x80, REG_FLAGS0(iobase));	/* reset SM  */	if (!io_detect_cm4000(iobase, dev)) {		rc = -ENODEV;		goto release_io;	}	/* reflect T=0 send/read mode in flags1 */	dev->flags1 |= (sendT0);	set_cardparameter(dev);	/* dummy read, reset flag procedure received */	tmp = inb(REG_FLAGS1(iobase));	dev->flags1 = 0x20	/* T_Active */	    | (sendT0)	    | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0)/* inverse parity  */	    | (((dev->baudv - 1) & 0x0100) >> 8);	/* MSB-Baud */	DEBUGP(1, dev, "set dev->flags1 = 0x%.2x\n", dev->flags1);	xoutb(dev->flags1, REG_FLAGS1(iobase));	/* xmit data */	DEBUGP(4, dev, "Xmit data\n");	for (i = 0; i < nr; i++) {		if (i >= 256) {			dev->flags1 = 0x20	/* T_Active */			    | (sendT0)	/* SendT0 */				/* inverse parity: */			    | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0)			    | (((dev->baudv - 1) & 0x0100) >> 8) /* MSB-Baud */			    | 0x10;	/* set address high */			DEBUGP(4, dev, "dev->flags = 0x%.2x - set address "			       "high\n", dev->flags1);			xoutb(dev->flags1, REG_FLAGS1(iobase));		}		if (test_bit(IS_INVREV, &dev->flags)) {			DEBUGP(4, dev, "Apply inverse convention for 0x%.2x "				"-> 0x%.2x\n", (unsigned char)dev->sbuf[i],			      invert_revert(dev->sbuf[i]));			xoutb(i, REG_BUF_ADDR(iobase));			xoutb(invert_revert(dev->sbuf[i]),			      REG_BUF_DATA(iobase));		} else {			xoutb(i, REG_BUF_ADDR(iobase));			xoutb(dev->sbuf[i], REG_BUF_DATA(iobase));		}	}	DEBUGP(4, dev, "Xmit done\n");	if (dev->proto == 0) {		/* T=0 proto: 0 byte reply  */		if (nr == 4) {			DEBUGP(4, dev, "T=0 assumes 0 byte reply\n");			xoutb(i, REG_BUF_ADDR(iobase));			if (test_bit(IS_INVREV, &dev->flags))				xoutb(0xff, REG_BUF_DATA(iobase));			else				xoutb(0x00, REG_BUF_DATA(iobase));		}		/* numSendBytes */		if (sendT0)			nsend = nr;		else {			if (nr == 4)				nsend = 5;			else {				nsend = 5 + (unsigned char)dev->sbuf[4];				if (dev->sbuf[4] == 0)					nsend += 0x100;			}		}	} else		nsend = nr;	/* T0: output procedure byte */	if (test_bit(IS_INVREV, &dev->flags)) {		DEBUGP(4, dev, "T=0 set Procedure byte (inverse-reverse) "		       "0x%.2x\n", invert_revert(dev->sbuf[1]));		xoutb(invert_revert(dev->sbuf[1]), REG_NUM_BYTES(iobase));	} else {		DEBUGP(4, dev, "T=0 set Procedure byte 0x%.2x\n", dev->sbuf[1]);		xoutb(dev->sbuf[1], REG_NUM_BYTES(iobase));	}	DEBUGP(1, dev, "set NumSendBytes = 0x%.2x\n",	       (unsigned char)(nsend & 0xff));	xoutb((unsigned char)(nsend & 0xff), REG_NUM_SEND(iobase));	DEBUGP(1, dev, "Trigger CARDMAN CONTROLLER (0x%.2x)\n",	       0x40	/* SM_Active */	      | (dev->flags0 & 2 ? 0 : 4)	/* power on if needed */	      |(dev->proto ? 0x10 : 0x08)	/* T=1/T=0 */	      |(nsend & 0x100) >> 8 /* MSB numSendBytes */ );	xoutb(0x40		/* SM_Active */	      | (dev->flags0 & 2 ? 0 : 4)	/* power on if needed */	      |(dev->proto ? 0x10 : 0x08)	/* T=1/T=0 */	      |(nsend & 0x100) >> 8,	/* MSB numSendBytes */	      REG_FLAGS0(iobase));	/* wait for xmit done */	if (dev->proto == 1) {		DEBUGP(4, dev, "Wait for xmit done\n");		for (i = 0; i < 1000; i++) {			if (inb(REG_FLAGS0(iobase)) & 0x08)				break;			msleep_interruptible(10);		}		if (i == 1000) {			DEBUGP(4, dev, "timeout waiting for xmit done\n");			rc = -EIO;			goto release_io;		}	}	/* T=1: wait for infoLen */	infolen = 0;	if (dev->proto) {		/* wait until infoLen is valid */		for (i = 0; i < 6000; i++) {	/* max waiting time of 1 min */			io_read_num_rec_bytes(iobase, &s);			if (s >= 3) {				infolen = inb(REG_FLAGS1(iobase));				DEBUGP(4, dev, "infolen=%d\n", infolen);				break;			}			msleep_interruptible(10);		}		if (i == 6000) {			DEBUGP(4, dev, "timeout waiting for infoLen\n");			rc = -EIO;			goto release_io;		}	} else		clear_bit(IS_PROCBYTE_PRESENT, &dev->flags);	/* numRecBytes | bit9 of numRecytes */	io_read_num_rec_bytes(iobase, &dev->rlen);	for (i = 0; i < 600; i++) {	/* max waiting time of 2 sec */		if (dev->proto) {			if (dev->rlen >= infolen + 4)				break;		}		msleep_interruptible(10);		/* numRecBytes | bit9 of numRecytes */		io_read_num_rec_bytes(iobase, &s);		if (s > dev->rlen) {			DEBUGP(1, dev, "NumRecBytes inc (reset timeout)\n");			i = 0;	/* reset timeout */			dev->rlen = s;		}		/* T=0: we are done when numRecBytes doesn't		 *      increment any more and NoProcedureByte		 *      is set and numRecBytes == bytes sent + 6		 *      (header bytes + data + 1 for sw2)		 *      except when the card replies an error		 *      which means, no data will be sent back.		 */		else if (dev->proto == 0) {			if ((inb(REG_BUF_ADDR(iobase)) & 0x80)) {				/* no procedure byte received since last read */				DEBUGP(1, dev, "NoProcedure byte set\n");				/* i=0; */			} else {				/* procedure byte received since last read */				DEBUGP(1, dev, "NoProcedure byte unset "					"(reset timeout)\n");				dev->procbyte = inb(REG_FLAGS1(iobase));				DEBUGP(1, dev, "Read procedure byte 0x%.2x\n",				      dev->procbyte);				i = 0;	/* resettimeout */			}			if (inb(REG_FLAGS0(iobase)) & 0x08) {				DEBUGP(1, dev, "T0Done flag (read reply)\n");				break;			}		}		if (dev->proto)			infolen = inb(REG_FLAGS1(iobase));	}	if (i == 600) {		DEBUGP(1, dev, "timeout waiting for numRecBytes\n");		rc = -EIO;		goto release_io;	} else {		if (dev->proto == 0) {			DEBUGP(1, dev, "Wait for T0Done bit to be  set\n");			for (i = 0; i < 1000; i++) {				if (inb(REG_FLAGS0(iobase)) & 0x08)					break;				msleep_interruptible(10);			}			if (i == 1000) {				DEBUGP(1, dev, "timeout waiting for T0Done\n");				rc = -EIO;				goto release_io;			}			dev->procbyte = inb(REG_FLAGS1(iobase));			DEBUGP(4, dev, "Read procedure byte 0x%.2x\n",			      dev->procbyte);			io_read_num_rec_bytes(iobase, &dev->rlen);			DEBUGP(4, dev, "Read NumRecBytes = %i\n", dev->rlen);		}	}	/* T=1: read offset=zero, T=0: read offset=after challenge */	dev->rpos = dev->proto ? 0 : nr == 4 ? 5 : nr > dev->rlen ? 5 : nr;	DEBUGP(4, dev, "dev->rlen = %i,  dev->rpos = %i, nr = %i\n",	      dev->rlen, dev->rpos, nr);release_io:	DEBUGP(4, dev, "Reset SM\n");	xoutb(0x80, REG_FLAGS0(iobase));	/* reset SM */	if (rc < 0) {		DEBUGP(4, dev, "Write failed but clear T_Active\n");		dev->flags1 &= 0xdf;		xoutb(dev->flags1, REG_FLAGS1(iobase));	}	clear_bit(LOCK_IO, &dev->flags);	wake_up_interruptible(&dev->ioq);	wake_up_interruptible(&dev->readq);	/* tell read we have data */	/* ITSEC E2: clear write buffer */	memset((char *)dev->sbuf, 0, 512);	/* return error or actually written bytes */	DEBUGP(2, dev, "<- cmm_write\n");	return rc < 0 ? rc : nr;}static void start_monitor(struct cm4000_dev *dev){	DEBUGP(3, dev, "-> start_monitor\n");	if (!dev->monitor_running) {		DEBUGP(5, dev, "create, init and add timer\n");		init_timer(&dev->timer);		dev->monitor_running = 1;		dev->timer.expires = jiffies;		dev->timer.data = (unsigned long) dev;		dev->timer.function = monitor_card;		add_timer(&dev->timer);	} else		DEBUGP(5, dev, "monitor already running\n");	DEBUGP(3, dev, "<- start_monitor\n");}static void stop_monitor(struct cm4000_dev *dev){	DEBUGP(3, dev, "-> stop_monitor\n");	if (dev->monitor_running) {		DEBUGP(5, dev, "stopping monitor\n");		terminate_monitor(dev);		/* reset monitor SM */		clear_bit(IS_ATR_VALID, &dev->flags);		clear_bit(IS_ATR_PRESENT, &dev->flags);	} else		DEBUGP(5, dev, "monitor already stopped\n");	DEBUGP(3, dev, "<- stop_monitor\n");}static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,		     unsigned long arg){	struct cm4000_dev *dev = filp->private_data;	ioaddr_t iobase = dev->link.io.BasePort1;	dev_link_t *link;	int size;	int rc;	void __user *argp = (void __user *)arg;#ifdef PCMCIA_DEBUG	char *ioctl_names[CM_IOC_MAXNR + 1] = {		[_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS",		[_IOC_NR(CM_IOCGATR)] "CM_IOCGATR",		[_IOC_NR(CM_IOCARDOFF)] "CM_IOCARDOFF",		[_IOC_NR(CM_IOCSPTS)] "CM_IOCSPTS",		[_IOC_NR(CM_IOSDBGLVL)] "CM4000_DBGLVL",	};#endif	DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode),	       iminor(inode), ioctl_names[_IOC_NR(cmd)]);	link = dev_table[iminor(inode)];	if (!(DEV_OK(link))) {		DEBUGP(4, dev, "DEV_OK false\n");		return -ENODEV;	}	if (test_bit(IS_CMM_ABSENT, &dev->flags)) {		DEBUGP(4, dev, "CMM_ABSENT flag set\n");		return -ENODEV;	}	if (_IOC_TYPE(cmd) != CM_IOC_MAGIC) {		DEBUGP(4, dev, "ioctype mismatch\n");		return -EINVAL;	}	if (_IOC_NR(cmd) > CM_IOC_MAXNR) {		DEBUGP(4, dev, "iocnr mismatch\n");		return -EINVAL;	}	size = _IOC_SIZE(cmd);	rc = 0;	DEBUGP(4, dev, "iocdir=%.4x iocr=%.4x iocw=%.4x iocsize=%d cmd=%.4x\n",	      _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd);	if (_IOC_DIR(cmd) & _IOC_READ) {		if (!access_ok(VERIFY_WRITE, argp, size))			return -EFAULT;	}	if (_IOC_DIR(cmd) & _IOC_WRITE) {		if (!access_ok(VERIFY_READ, argp, size))			return -EFAULT;	}	switch (cmd) {	case CM_IOCGSTATUS:		DEBUGP(4, dev, " ... in CM_IOCGSTATUS\n");		{			int status;			/* clear other bits, but leave inserted & powered as			 * they are */			status = dev->flags0 & 3;			if (test_bit(IS_ATR_PRESENT, &dev->flags))				status |= CM_ATR_PRESENT;			if (test_bit(IS_ATR_VALID, &dev->flags))				status |= CM_ATR_VALID;			if (test_bit(IS_CMM_ABSENT, &dev->flags))				status |= CM_NO_READER;			if (test_bit(IS_BAD_CARD, &dev->flags))				status |= CM_BAD_CARD;			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

⌨️ 快捷键说明

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