static void monitor_card()

in pcmcia/cm4000_cs.c [665:922]


static void monitor_card(struct timer_list *t)
{
	struct cm4000_dev *dev = from_timer(dev, t, timer);
	unsigned int iobase = dev->p_dev->resource[0]->start;
	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) {
	case M_CARDOFF: {
		unsigned char flags0;

		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 doesn't 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 = (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);
			dev_warn(&dev->p_dev->dev, MODULE_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 CM4000_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");
	mod_timer(&dev->timer, jiffies + dev->mdelay);
	clear_bit(LOCK_MONITOR, &dev->flags);
}