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);
}