gpr.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /* $OpenBSD: gpr.c,v 1.16 2011/07/03 15:47:17 matthew Exp $ */
  2. /*
  3. * Copyright (c) 2002, Federico G. Schwindt
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in
  13. * the documentation and/or other materials provided with the
  14. * distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. /*
  29. * A driver for the Gemplus GPR400 SmartCard reader.
  30. *
  31. * The gpr400 driver written by Wolf Geldmacher <wgeldmacher@paus.ch> for
  32. * Linux was used as documentation.
  33. */
  34. #include <sys/param.h>
  35. #include <sys/kernel.h>
  36. #include <sys/device.h>
  37. #include <sys/systm.h>
  38. #include <sys/conf.h>
  39. #include <sys/file.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/proc.h>
  42. #include <dev/pcmcia/pcmciavar.h>
  43. #include <dev/pcmcia/pcmciareg.h>
  44. #include <dev/pcmcia/pcmciadevs.h>
  45. #include <dev/pcmcia/gprio.h>
  46. /* Registers in I/O space (32 bytes) */
  47. #define GPR400_HAP_CTRL 0x00 /* Handshake and PRG Control */
  48. #define GPR400_RESET 0x01 /* Master reset */
  49. #define GPR400_IREQ 0x02 /* Interrupt request */
  50. #define GPR400_INTR 0x04 /* Interrupt */
  51. /* bits 3..8 PRG control */
  52. #define GPR400_PD_CTRL 0x01 /* PRG data */
  53. /* bytes 3..32 used for data exchange */
  54. /* Registers in attribute memory (read only) */
  55. #define GPR400_SETUP 0x018 /* General Setup */
  56. #define GPR400_LOCK_MASK 0x08 /* 0: locked, 1: unlocked */
  57. #define GPR400_REG1 0x01a /* SmartCard Reg. 1 */
  58. #define GPR400_DET_MASK 0x08 /* 0: in the reader, 1: removed */
  59. #define GPR400_INS_MASK 0x80 /* 0: not inserted, 1: inserted */
  60. #define GPR400_REG2 0x01c /* SmartCard Reg. 2 */
  61. #define GPR400_CAC 0x01e /* Clock and Control */
  62. /* TLV */
  63. #define GPR400_CLOSE 0x10 /* Close session */
  64. #define GPR400_OPEN 0x20 /* Open session */
  65. #define GPR400_APDU 0x30 /* APDU exchange */
  66. #define GPR400_POWER 0x40 /* Power down/Standby */
  67. /* 0: Power down, 1: Standby */
  68. #define GPR400_SELECT 0x50 /* Select card */
  69. #define GPR400_DRV0 0x00 /* Downloaded driver 0 */
  70. #define GPR400_ISODRV 0x02 /* ISO7816-3 driver */
  71. #define GPR400_CLK_MASK 0x08 /* 0: 3.68MHz, 1: 7.36MHz */
  72. #define GPR400_STATUS 0xA0 /* Reader status */
  73. #define GPR400_CONT 0x04 /* Chain block */
  74. #define GPR400_MEM_LEN 0x1000
  75. #define GPRUNIT(x) (minor(x) & 0x0f)
  76. #ifdef GPRDEBUG
  77. int gprdebug;
  78. #define DPRINTF(x) if (gprdebug) printf x
  79. #else
  80. #define DPRINTF(x)
  81. #endif
  82. struct gpr_softc {
  83. struct device sc_dev;
  84. struct pcmcia_function *sc_pf;
  85. bus_space_handle_t sc_ioh;
  86. bus_space_tag_t sc_iot;
  87. struct pcmcia_io_handle sc_pioh;
  88. int sc_iowin;
  89. bus_space_handle_t sc_memh;
  90. bus_space_tag_t sc_memt;
  91. struct pcmcia_mem_handle sc_pmemh;
  92. int sc_memwin;
  93. bus_addr_t sc_offset;
  94. void * sc_ih;
  95. };
  96. int gpr_match(struct device *, void *, void *);
  97. void gpr_attach(struct device *, struct device *, void *);
  98. int gpr_detach(struct device *, int);
  99. int gpr_activate(struct device *, int);
  100. int gpropen(dev_t, int, int, struct proc *);
  101. int gprclose(dev_t, int, int, struct proc *);
  102. int gprioctl(dev_t, u_long, caddr_t, int, struct proc *);
  103. int gpr_intr(void *);
  104. int tlvput(struct gpr_softc *, int, u_int8_t *, int);
  105. struct cfattach gpr_ca = {
  106. sizeof(struct gpr_softc), gpr_match, gpr_attach, gpr_detach,
  107. gpr_activate
  108. };
  109. struct cfdriver gpr_cd = {
  110. NULL, "gpr", DV_DULL
  111. };
  112. int
  113. gpr_match(struct device *parent, void *match, void *aux)
  114. {
  115. struct pcmcia_attach_args *pa = aux;
  116. if (pa->manufacturer == PCMCIA_VENDOR_GEMPLUS &&
  117. pa->product == PCMCIA_PRODUCT_GEMPLUS_GPR400)
  118. return (1);
  119. return (0);
  120. }
  121. void
  122. gpr_attach(struct device *parent, struct device *self, void *aux)
  123. {
  124. struct gpr_softc *sc = (void *)self;
  125. struct pcmcia_attach_args *pa = aux;
  126. struct pcmcia_config_entry *cfe;
  127. const char *intrstr;
  128. for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe;
  129. cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
  130. if (!pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
  131. cfe->iospace[0].length, cfe->iospace[0].length,
  132. &sc->sc_pioh))
  133. break;
  134. }
  135. if (cfe == NULL) {
  136. printf(": can't alloc i/o space\n");
  137. goto fail_io_alloc;
  138. }
  139. pcmcia_function_init(pa->pf, cfe);
  140. if (pcmcia_function_enable(pa->pf)) {
  141. printf(": function enable failed\n");
  142. goto fail_enable;
  143. }
  144. if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0,
  145. sc->sc_pioh.size, &sc->sc_pioh, &sc->sc_iowin)) {
  146. printf(": can't map i/o space\n");
  147. goto fail_io_map;
  148. }
  149. /*
  150. * GPR400 has some registers in attribute memory as well.
  151. */
  152. if (pcmcia_mem_alloc(pa->pf, GPR400_MEM_LEN, &sc->sc_pmemh)) {
  153. printf(": can't map mem space\n");
  154. goto fail_mem_alloc;
  155. }
  156. if (pcmcia_mem_map(pa->pf, PCMCIA_MEM_ATTR, pa->pf->ccr_base,
  157. GPR400_MEM_LEN, &sc->sc_pmemh, &sc->sc_offset, &sc->sc_memwin)) {
  158. printf(": can't map memory\n");
  159. goto fail_mem_map;
  160. }
  161. sc->sc_pf = pa->pf;
  162. sc->sc_iot = sc->sc_pioh.iot;
  163. sc->sc_ioh = sc->sc_pioh.ioh;
  164. sc->sc_memt = sc->sc_pmemh.memt;
  165. sc->sc_memh = sc->sc_pmemh.memh;
  166. printf(" port 0x%lx/%d", sc->sc_pioh.addr, sc->sc_pioh.size);
  167. sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, gpr_intr, sc,
  168. sc->sc_dev.dv_xname);
  169. intrstr = pcmcia_intr_string(sc->sc_pf, sc->sc_ih);
  170. printf("%s%s\n", *intrstr ? ", " : "", intrstr);
  171. if (sc->sc_ih != NULL)
  172. return;
  173. pcmcia_mem_unmap(pa->pf, sc->sc_memwin);
  174. fail_mem_map:
  175. pcmcia_mem_free(pa->pf, &sc->sc_pmemh);
  176. fail_mem_alloc:
  177. pcmcia_io_unmap(pa->pf, sc->sc_iowin);
  178. fail_io_map:
  179. pcmcia_function_disable(pa->pf);
  180. fail_enable:
  181. pcmcia_io_free(pa->pf, &sc->sc_pioh);
  182. fail_io_alloc:
  183. return;
  184. }
  185. int
  186. gpr_detach(struct device *dev, int flags)
  187. {
  188. struct gpr_softc *sc = (struct gpr_softc *)dev;
  189. pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
  190. pcmcia_io_free(sc->sc_pf, &sc->sc_pioh);
  191. pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
  192. pcmcia_mem_free(sc->sc_pf, &sc->sc_pmemh);
  193. return (0);
  194. }
  195. int
  196. gpr_activate(struct device *dev, int act)
  197. {
  198. struct gpr_softc *sc = (struct gpr_softc *)dev;
  199. switch (act) {
  200. case DVACT_DEACTIVATE:
  201. if (sc->sc_ih)
  202. pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
  203. sc->sc_ih = NULL;
  204. pcmcia_function_disable(sc->sc_pf);
  205. break;
  206. }
  207. return (0);
  208. }
  209. int
  210. gpropen(dev_t dev, int flags, int mode, struct proc *p)
  211. {
  212. int unit = GPRUNIT(dev);
  213. struct gpr_softc *sc;
  214. DPRINTF(("%s: flags %d, mode %d\n", __func__, flags, mode));
  215. if (unit >= gpr_cd.cd_ndevs ||
  216. (sc = gpr_cd.cd_devs[unit]) == NULL)
  217. return (ENXIO);
  218. return (tlvput(sc, GPR400_SELECT, "\x02", 1));
  219. }
  220. int
  221. gprclose(dev_t dev, int flags, int mode, struct proc *p)
  222. {
  223. int unit = GPRUNIT(dev);
  224. struct gpr_softc *sc = gpr_cd.cd_devs[unit];
  225. DPRINTF(("%s: flags %d, mode %d\n", __func__, flags, mode));
  226. (void)tlvput(sc, GPR400_CLOSE, (u_int8_t *)0, 0);
  227. return (0);
  228. }
  229. int
  230. gprioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
  231. {
  232. int unit = GPRUNIT(dev);
  233. struct gpr_softc *sc = gpr_cd.cd_devs[unit];
  234. int error;
  235. DPRINTF(("%s: cmd %d, flags 0x%x\n", __func__, cmd, flags));
  236. switch (cmd) {
  237. case GPR_RESET:
  238. case GPR_SELECT:
  239. case GPR_POWER:
  240. case GPR_CLOSE:
  241. if ((flags & FWRITE) == 0)
  242. return (EACCES);
  243. default:
  244. break;
  245. }
  246. switch (cmd) {
  247. case GPR_RESET:
  248. /*
  249. * To reset and power up the reader, set bit 0 in the
  250. * HAP register for at least 5us and wait for 20ms.
  251. */
  252. bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL,
  253. GPR400_RESET);
  254. delay(10);
  255. bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL, 0);
  256. tsleep(sc, PWAIT, "gpreset", hz / 40);
  257. /* FALLTHROUGH */
  258. case GPR_SELECT:
  259. error = tlvput(sc, GPR400_SELECT, "\x02", 1);
  260. break;
  261. case GPR_POWER:
  262. {
  263. u_int8_t *mode;
  264. if (*(int *)addr)
  265. mode = "\x01"; /* Standby */
  266. else
  267. mode = "\x00"; /* Power down */
  268. error = tlvput(sc, GPR400_POWER, mode, 1);
  269. }
  270. break;
  271. case GPR_CLOSE:
  272. error = tlvput(sc, GPR400_CLOSE, (u_int8_t *)0, 0);
  273. break;
  274. case GPR_RAM:
  275. {
  276. struct gpr400_ram r;
  277. bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
  278. sc->sc_offset, (u_int8_t *)&r,
  279. sizeof(struct gpr400_ram));
  280. error = copyout(&r, addr, sizeof(struct gpr400_ram));
  281. }
  282. break;
  283. case GPR_CMD:
  284. case GPR_OPEN:
  285. case GPR_STATUS:
  286. case GPR_TLV:
  287. default:
  288. error = EINVAL;
  289. break;
  290. };
  291. return (error);
  292. }
  293. int
  294. gpr_intr(void *arg)
  295. {
  296. struct gpr_softc *sc = arg;
  297. u_int8_t val;
  298. DPRINTF(("%s: got interrupt\n", __func__));
  299. /* Ack interrupt */
  300. val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL);
  301. bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL,
  302. val & ~GPR400_INTR);
  303. wakeup(sc);
  304. return (1);
  305. }
  306. int
  307. tlvput(struct gpr_softc *sc, int cmd, u_int8_t *data, int len)
  308. {
  309. int resid, ret;
  310. DPRINTF(("%s: cmd 0x%x, data %p, len %d\n", __func__,
  311. cmd, data, len));
  312. resid = len;
  313. do {
  314. int n, s;
  315. n = min(resid, 28);
  316. resid -= n;
  317. if (resid)
  318. cmd |= GPR400_CONT;
  319. else
  320. cmd &= ~GPR400_CONT;
  321. DPRINTF(("%s: sending cmd 0x%x, len %d, left %d\n",
  322. __func__, cmd, n, resid));
  323. bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0x02, cmd);
  324. bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0x03, n);
  325. if (n) {
  326. bus_space_write_region_1(sc->sc_iot, sc->sc_ioh,
  327. 0x04, data, n);
  328. data += n;
  329. }
  330. s = spltty();
  331. /* Tell the reader to process this command. */
  332. bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL,
  333. GPR400_IREQ);
  334. tsleep(sc, PCATCH, "tlvput", 0);
  335. splx(s);
  336. /* Read the status. */
  337. ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0x04);
  338. DPRINTF(("%s: ret %d\n", __func__, ret));
  339. if (ret != 0x00 || (!resid && ret != 0xe7))
  340. return (EIO);
  341. } while (resid > 0);
  342. return (0);
  343. }