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

📄 cm4000_cs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* check card convention */	if (test_bit(IS_INVREV, &dev->flags))		str_invert_revert(dev->pts, 4);	/* reset SM */	xoutb(0x80, REG_FLAGS0(iobase));	/* Enable access to the message buffer */	DEBUGP(5, dev, "Enable access to the messages buffer\n");	dev->flags1 = 0x20	/* T_Active */	    | (test_bit(IS_INVREV, &dev->flags) ? 0x02 : 0x00) /* inv parity */	    | ((dev->baudv >> 8) & 0x01);	/* MSB-baud */	xoutb(dev->flags1, REG_FLAGS1(iobase));	DEBUGP(5, dev, "Enable message buffer -> flags1 = 0x%.2x\n",	       dev->flags1);	/* write challenge to the buffer */	DEBUGP(5, dev, "Write challenge to buffer: ");	for (i = 0; i < 4; i++) {		xoutb(i, REG_BUF_ADDR(iobase));		xoutb(dev->pts[i], REG_BUF_DATA(iobase));	/* buf data */#ifdef PCMCIA_DEBUG		if (pc_debug >= 5)			printk("0x%.2x ", dev->pts[i]);	}	if (pc_debug >= 5)		printk("\n");#else	}#endif	/* set number of bytes to write */	DEBUGP(5, dev, "Set number of bytes to write\n");	xoutb(0x04, REG_NUM_SEND(iobase));	/* Trigger CARDMAN CONTROLLER */	xoutb(0x50, REG_FLAGS0(iobase));	/* Monitor progress */	/* wait for xmit done */	DEBUGP(5, dev, "Waiting for NumRecBytes getting valid\n");	for (i = 0; i < 100; i++) {		if (inb(REG_FLAGS0(iobase)) & 0x08) {			DEBUGP(5, dev, "NumRecBytes is valid\n");			break;		}		mdelay(10);	}	if (i == 100) {		DEBUGP(5, dev, "Timeout waiting for NumRecBytes getting "		       "valid\n");		rc = -EIO;		goto exit_setprotocol;	}	DEBUGP(5, dev, "Reading NumRecBytes\n");	for (i = 0; i < 100; i++) {		io_read_num_rec_bytes(iobase, &num_bytes_read);		if (num_bytes_read >= 4) {			DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read);			break;		}		mdelay(10);	}	/* check whether it is a short PTS reply? */	if (num_bytes_read == 3)		i = 0;	if (i == 100) {		DEBUGP(5, dev, "Timeout reading num_bytes_read\n");		rc = -EIO;		goto exit_setprotocol;	}	DEBUGP(5, dev, "Reset the CARDMAN CONTROLLER\n");	xoutb(0x80, REG_FLAGS0(iobase));	/* Read PPS reply */	DEBUGP(5, dev, "Read PPS reply\n");	for (i = 0; i < num_bytes_read; i++) {		xoutb(i, REG_BUF_ADDR(iobase));		pts_reply[i] = inb(REG_BUF_DATA(iobase));	}#ifdef PCMCIA_DEBUG	DEBUGP(2, dev, "PTSreply: ");	for (i = 0; i < num_bytes_read; i++) {		if (pc_debug >= 5)			printk("0x%.2x ", pts_reply[i]);	}	printk("\n");#endif	/* PCMCIA_DEBUG */	DEBUGP(5, dev, "Clear Tactive in Flags1\n");	xoutb(0x20, REG_FLAGS1(iobase));	/* Compare ptsreq and ptsreply */	if ((dev->pts[0] == pts_reply[0]) &&	    (dev->pts[1] == pts_reply[1]) &&	    (dev->pts[2] == pts_reply[2]) && (dev->pts[3] == pts_reply[3])) {		/* setcardparameter according to PPS */		dev->baudv = calc_baudv(dev->pts[2]);		set_cardparameter(dev);	} else if ((dev->pts[0] == pts_reply[0]) &&		   ((dev->pts[1] & 0xef) == pts_reply[1]) &&		   ((pts_reply[0] ^ pts_reply[1]) == pts_reply[2])) {		/* short PTS reply, set card parameter to default values */		dev->baudv = calc_baudv(0x11);		set_cardparameter(dev);	} else		rc = -EIO;exit_setprotocol:	DEBUGP(3, dev, "<- set_protocol\n");	return rc;}static int io_detect_cm4000(ioaddr_t iobase, struct cm4000_dev *dev){	/* note: statemachine is assumed to be reset */	if (inb(REG_FLAGS0(iobase)) & 8) {		clear_bit(IS_ATR_VALID, &dev->flags);		set_bit(IS_CMM_ABSENT, &dev->flags);		return 0;	/* detect CMM = 1 -> failure */	}	/* xoutb(0x40, REG_FLAGS1(iobase)); detectCMM */	xoutb(dev->flags1 | 0x40, REG_FLAGS1(iobase));	if ((inb(REG_FLAGS0(iobase)) & 8) == 0) {		clear_bit(IS_ATR_VALID, &dev->flags);		set_bit(IS_CMM_ABSENT, &dev->flags);		return 0;	/* detect CMM=0 -> failure */	}	/* clear detectCMM again by restoring original flags1 */	xoutb(dev->flags1, REG_FLAGS1(iobase));	return 1;}static void terminate_monitor(struct cm4000_dev *dev){	/* tell the monitor to stop and wait until	 * it terminates.	 */	DEBUGP(3, dev, "-> terminate_monitor\n");	wait_event_interruptible(dev->devq,				 test_and_set_bit(LOCK_MONITOR,						  (void *)&dev->flags));	/* now, LOCK_MONITOR has been set.	 * allow a last cycle in the monitor.	 * the monitor will indicate that it has	 * finished by clearing this bit.	 */	DEBUGP(5, dev, "Now allow last cycle of monitor!\n");	while (test_bit(LOCK_MONITOR, (void *)&dev->flags))		msleep(25);	DEBUGP(5, dev, "Delete timer\n");	del_timer_sync(&dev->timer);#ifdef PCMCIA_DEBUG	dev->monitor_running = 0;#endif	DEBUGP(3, dev, "<- terminate_monitor\n");}/* * monitor the card every 50msec. as a side-effect, retrieve the * atr once a card is inserted. another side-effect of retrieving the * atr is that the card will be powered on, so there is no need to * power on the card explictely from the application: the driver * is already doing that for you. */static void monitor_card(unsigned long p){	struct cm4000_dev *dev = (struct cm4000_dev *) p;	ioaddr_t iobase = dev->link.io.BasePort1;	unsigned short s;	struct ptsreq ptsreq;	int i, atrc;	DEBUGP(7, dev, "->  monitor_card\n");	/* if someone has set the lock for us: we're done! */	if (test_and_set_bit(LOCK_MONITOR, &dev->flags)) {		DEBUGP(4, dev, "About to stop monitor\n");		/* no */		dev->rlen =		    dev->rpos =		    dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0;		dev->mstate = M_FETCH_ATR;		clear_bit(LOCK_MONITOR, &dev->flags);		/* close et al. are sleeping on devq, so wake it */		wake_up_interruptible(&dev->devq);		DEBUGP(2, dev, "<- monitor_card (we are done now)\n");		return;	}	/* try to lock io: if it is already locked, just add another timer */	if (test_and_set_bit(LOCK_IO, (void *)&dev->flags)) {		DEBUGP(4, dev, "Couldn't get IO lock\n");		goto return_with_timer;	}	/* is a card/a reader inserted at all ? */	dev->flags0 = xinb(REG_FLAGS0(iobase));	DEBUGP(7, dev, "dev->flags0 = 0x%2x\n", dev->flags0);	DEBUGP(7, dev, "smartcard present: %s\n",	       dev->flags0 & 1 ? "yes" : "no");	DEBUGP(7, dev, "cardman present: %s\n",	       dev->flags0 == 0xff ? "no" : "yes");	if ((dev->flags0 & 1) == 0	/* no smartcard inserted */	    || dev->flags0 == 0xff) {	/* no cardman inserted */		/* no */		dev->rlen =		    dev->rpos =		    dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0;		dev->mstate = M_FETCH_ATR;		dev->flags &= 0x000000ff; /* only keep IO and MONITOR locks */		if (dev->flags0 == 0xff) {			DEBUGP(4, dev, "set IS_CMM_ABSENT bit\n");			set_bit(IS_CMM_ABSENT, &dev->flags);		} else if (test_bit(IS_CMM_ABSENT, &dev->flags)) {			DEBUGP(4, dev, "clear IS_CMM_ABSENT bit "			       "(card is removed)\n");			clear_bit(IS_CMM_ABSENT, &dev->flags);		}		goto release_io;	} else if ((dev->flags0 & 1) && test_bit(IS_CMM_ABSENT, &dev->flags)) {		/* cardman and card present but cardman was absent before		 * (after suspend with inserted card) */		DEBUGP(4, dev, "clear IS_CMM_ABSENT bit (card is inserted)\n");		clear_bit(IS_CMM_ABSENT, &dev->flags);	}	if (test_bit(IS_ATR_VALID, &dev->flags) == 1) {		DEBUGP(7, dev, "believe ATR is already valid (do nothing)\n");		goto release_io;	}	switch (dev->mstate) {		unsigned char flags0;	case M_CARDOFF:		DEBUGP(4, dev, "M_CARDOFF\n");		flags0 = inb(REG_FLAGS0(iobase));		if (flags0 & 0x02) {			/* wait until Flags0 indicate power is off */			dev->mdelay = T_10MSEC;		} else {			/* Flags0 indicate power off and no card inserted now;			 * Reset CARDMAN CONTROLLER */			xoutb(0x80, REG_FLAGS0(iobase));			/* prepare for fetching ATR again: after card off ATR			 * is read again automatically */			dev->rlen =			    dev->rpos =			    dev->atr_csum =			    dev->atr_len_retry = dev->cwarn = 0;			dev->mstate = M_FETCH_ATR;			/* minimal gap between CARDOFF and read ATR is 50msec */			dev->mdelay = T_50MSEC;		}		break;	case M_FETCH_ATR:		DEBUGP(4, dev, "M_FETCH_ATR\n");		xoutb(0x80, REG_FLAGS0(iobase));		DEBUGP(4, dev, "Reset BAUDV to 9600\n");		dev->baudv = 0x173;	/* 9600 */		xoutb(0x02, REG_STOPBITS(iobase));	/* stopbits=2 */		xoutb(0x73, REG_BAUDRATE(iobase));	/* baud value */		xoutb(0x21, REG_FLAGS1(iobase));	/* T_Active=1, baud							   value */		/* warm start vs. power on: */		xoutb(dev->flags0 & 2 ? 0x46 : 0x44, REG_FLAGS0(iobase));		dev->mdelay = T_40MSEC;		dev->mstate = M_TIMEOUT_WAIT;		break;	case M_TIMEOUT_WAIT:		DEBUGP(4, dev, "M_TIMEOUT_WAIT\n");		/* numRecBytes */		io_read_num_rec_bytes(iobase, &dev->atr_len);		dev->mdelay = T_10MSEC;		dev->mstate = M_READ_ATR_LEN;		break;	case M_READ_ATR_LEN:		DEBUGP(4, dev, "M_READ_ATR_LEN\n");		/* infinite loop possible, since there is no timeout */#define	MAX_ATR_LEN_RETRY	100		if (dev->atr_len == io_read_num_rec_bytes(iobase, &s)) {			if (dev->atr_len_retry++ >= MAX_ATR_LEN_RETRY) {					/* + XX msec */				dev->mdelay = T_10MSEC;				dev->mstate = M_READ_ATR;			}		} else {			dev->atr_len = s;			dev->atr_len_retry = 0;	/* set new timeout */		}		DEBUGP(4, dev, "Current ATR_LEN = %i\n", dev->atr_len);		break;	case M_READ_ATR:		DEBUGP(4, dev, "M_READ_ATR\n");		xoutb(0x80, REG_FLAGS0(iobase));	/* reset SM */		for (i = 0; i < dev->atr_len; i++) {			xoutb(i, REG_BUF_ADDR(iobase));			dev->atr[i] = inb(REG_BUF_DATA(iobase));		}		/* Deactivate T_Active flags */		DEBUGP(4, dev, "Deactivate T_Active flags\n");		dev->flags1 = 0x01;		xoutb(dev->flags1, REG_FLAGS1(iobase));		/* atr is present (which doesnt mean it's valid) */		set_bit(IS_ATR_PRESENT, &dev->flags);		if (dev->atr[0] == 0x03)			str_invert_revert(dev->atr, dev->atr_len);		atrc = parse_atr(dev);		if (atrc == 0) {	/* atr invalid */			dev->mdelay = 0;			dev->mstate = M_BAD_CARD;		} else {			dev->mdelay = T_50MSEC;			dev->mstate = M_ATR_PRESENT;			set_bit(IS_ATR_VALID, &dev->flags);		}		if (test_bit(IS_ATR_VALID, &dev->flags) == 1) {			DEBUGP(4, dev, "monitor_card: ATR valid\n"); 			/* if ta1 == 0x11, no PPS necessary (default values) */			/* do not do PPS with multi protocol cards */			if ((test_bit(IS_AUTOPPS_ACT, &dev->flags) == 0) &&			    (dev->ta1 != 0x11) &&			    !(test_bit(IS_ANY_T0, &dev->flags) &&			    test_bit(IS_ANY_T1, &dev->flags))) {				DEBUGP(4, dev, "Perform AUTOPPS\n");				set_bit(IS_AUTOPPS_ACT, &dev->flags);				ptsreq.protocol = ptsreq.protocol =				    (0x01 << dev->proto);				ptsreq.flags = 0x01;				ptsreq.pts1 = 0x00;				ptsreq.pts2 = 0x00;				ptsreq.pts3 = 0x00;				if (set_protocol(dev, &ptsreq) == 0) {					DEBUGP(4, dev, "AUTOPPS ret SUCC\n");					clear_bit(IS_AUTOPPS_ACT, &dev->flags);					wake_up_interruptible(&dev->atrq);				} else {					DEBUGP(4, dev, "AUTOPPS failed: "					       "repower using defaults\n");					/* prepare for repowering  */					clear_bit(IS_ATR_PRESENT, &dev->flags);					clear_bit(IS_ATR_VALID, &dev->flags);					dev->rlen =					    dev->rpos =					    dev->atr_csum =					    dev->atr_len_retry = dev->cwarn = 0;					dev->mstate = M_FETCH_ATR;					dev->mdelay = T_50MSEC;				}			} else {				/* for cards which use slightly different				 * params (extra guard time) */				set_cardparameter(dev);				if (test_bit(IS_AUTOPPS_ACT, &dev->flags) == 1)					DEBUGP(4, dev, "AUTOPPS already active "					       "2nd try:use default values\n");				if (dev->ta1 == 0x11)					DEBUGP(4, dev, "No AUTOPPS necessary "					       "TA(1)==0x11\n");				if (test_bit(IS_ANY_T0, &dev->flags)				    && test_bit(IS_ANY_T1, &dev->flags))					DEBUGP(4, dev, "Do NOT perform AUTOPPS "					       "with multiprotocol cards\n");				clear_bit(IS_AUTOPPS_ACT, &dev->flags);				wake_up_interruptible(&dev->atrq);			}		} else {			DEBUGP(4, dev, "ATR invalid\n");			wake_up_interruptible(&dev->atrq);		}		break;	case M_BAD_CARD:		DEBUGP(4, dev, "M_BAD_CARD\n");		/* slow down warning, but prompt immediately after insertion */		if (dev->cwarn == 0 || dev->cwarn == 10) {			set_bit(IS_BAD_CARD, &dev->flags);			printk(KERN_WARNING MODULE_NAME ": device %s: ",			       dev->node.dev_name);			if (test_bit(IS_BAD_CSUM, &dev->flags)) {				DEBUGP(4, dev, "ATR checksum (0x%.2x, should "				       "be zero) failed\n", dev->atr_csum);			}#ifdef PCMCIA_DEBUG			else if (test_bit(IS_BAD_LENGTH, &dev->flags)) {				DEBUGP(4, dev, "ATR length error\n");			} else {				DEBUGP(4, dev, "card damaged or wrong way "					"inserted\n");			}#endif			dev->cwarn = 0;			wake_up_interruptible(&dev->atrq);	/* wake open */		}		dev->cwarn++;		dev->mdelay = T_100MSEC;		dev->mstate = M_FETCH_ATR;		break;	default:		DEBUGP(7, dev, "Unknown action\n");		break;		/* nothing */	}release_io:	DEBUGP(7, dev, "release_io\n");	clear_bit(LOCK_IO, &dev->flags);	wake_up_interruptible(&dev->ioq);	/* whoever needs IO */return_with_timer:	DEBUGP(7, dev, "<- monitor_card (returns with timer)\n");	dev->timer.expires = jiffies + dev->mdelay;	add_timer(&dev->timer);	clear_bit(LOCK_MONITOR, &dev->flags);}/* Interface to userland (file_operations) */static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,			loff_t *ppos){	struct cm4000_dev *dev = filp->private_data;	ioaddr_t iobase = dev->link.io.BasePort1;	ssize_t rc;	int i, j, k;	DEBUGP(2, dev, "-> cmm_read(%s,%d)\n", current->comm, current->pid);	if (count == 0)		/* according to manpage */		return 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))		return -EIO;	/* also see the note about this in cmm_write */	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)		return -EIO;	/* this one implements blocking IO */	if (wait_event_interruptible	    (dev->readq,	     ((filp->f_flags & O_NONBLOCK) || (dev->rpos < dev->rlen)))) {		if (filp->f_flags & O_NONBLOCK)			return -EAGAIN;		return -ERESTARTSYS;	}	/* 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;	}	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;		}		rc = -EIO;		goto release_io;	}	DEBUGP(4, dev, "begin read answer\n");	j = min(count, (size_t)(dev->rlen - dev->rpos));	k = dev->rpos;	if (k + j > 255)		j = 256 - k;	DEBUGP(4, dev, "read1 j=%d\n", j);	for (i = 0; i < j; i++) {		xoutb(k++, REG_BUF_ADDR(iobase));		dev->rbuf[i] = xinb(REG_BUF_DATA(iobase));	}	j = min(count, (size_t)(dev->rlen - dev->rpos));	if (k + j > 255) {		DEBUGP(4, dev, "read2 j=%d\n", j);		dev->flags1 |= 0x10;	/* MSB buf addr set */		xoutb(dev->flags1, REG_FLAGS1(iobase));

⌨️ 快捷键说明

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