📄 cm4000_cs.c
字号:
/* 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 + -