This source file includes following definitions.
- gpr_match
- gpr_attach
- gpr_detach
- gpr_activate
- gpropen
- gprclose
- gprioctl
- gpr_intr
- tlvput
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/ioctl.h>
43 #include <sys/conf.h>
44
45 #include <dev/pcmcia/pcmciavar.h>
46 #include <dev/pcmcia/pcmciareg.h>
47 #include <dev/pcmcia/pcmciadevs.h>
48
49 #include <dev/pcmcia/gprio.h>
50
51
52 #define GPR400_HAP_CTRL 0x00
53 #define GPR400_RESET 0x01
54 #define GPR400_IREQ 0x02
55 #define GPR400_INTR 0x04
56
57 #define GPR400_PD_CTRL 0x01
58
59
60
61 #define GPR400_SETUP 0x018
62 #define GPR400_LOCK_MASK 0x08
63 #define GPR400_REG1 0x01a
64 #define GPR400_DET_MASK 0x08
65 #define GPR400_INS_MASK 0x80
66 #define GPR400_REG2 0x01c
67 #define GPR400_CAC 0x01e
68
69
70 #define GPR400_CLOSE 0x10
71 #define GPR400_OPEN 0x20
72 #define GPR400_APDU 0x30
73 #define GPR400_POWER 0x40
74
75 #define GPR400_SELECT 0x50
76 #define GPR400_DRV0 0x00
77 #define GPR400_ISODRV 0x02
78 #define GPR400_CLK_MASK 0x08
79 #define GPR400_STATUS 0xA0
80
81 #define GPR400_CONT 0x04
82
83 #define GPR400_MEM_LEN 0x1000
84
85 #define GPRUNIT(x) (minor(x) & 0x0f)
86
87 #ifdef GPRDEBUG
88 int gprdebug;
89 #define DPRINTF(x) if (gprdebug) printf x
90 #else
91 #define DPRINTF(x)
92 #endif
93
94 struct gpr_softc {
95 struct device sc_dev;
96
97 struct pcmcia_function *sc_pf;
98
99 bus_space_handle_t sc_ioh;
100 bus_space_tag_t sc_iot;
101
102 struct pcmcia_io_handle sc_pioh;
103 int sc_iowin;
104
105 bus_space_handle_t sc_memh;
106 bus_space_tag_t sc_memt;
107
108 struct pcmcia_mem_handle sc_pmemh;
109 int sc_memwin;
110 bus_addr_t sc_offset;
111
112 void * sc_ih;
113 };
114
115 int gpr_match(struct device *, void *, void *);
116 void gpr_attach(struct device *, struct device *, void *);
117 int gpr_detach(struct device *, int);
118 int gpr_activate(struct device *, enum devact);
119
120 int gpropen(dev_t, int, int, struct proc *);
121 int gprclose(dev_t, int, int, struct proc *);
122 int gprioctl(dev_t, u_long, caddr_t, int, struct proc *);
123
124 int gpr_intr(void *);
125
126 int tlvput(struct gpr_softc *, int, u_int8_t *, int);
127
128 struct cfattach gpr_ca = {
129 sizeof(struct gpr_softc), gpr_match, gpr_attach, gpr_detach,
130 gpr_activate
131 };
132
133 struct cfdriver gpr_cd = {
134 NULL, "gpr", DV_DULL
135 };
136
137 int
138 gpr_match(struct device *parent, void *match, void *aux)
139 {
140 struct pcmcia_attach_args *pa = aux;
141
142 if (pa->manufacturer == PCMCIA_VENDOR_GEMPLUS &&
143 pa->product == PCMCIA_PRODUCT_GEMPLUS_GPR400)
144 return (1);
145
146 return (0);
147 }
148
149 void
150 gpr_attach(struct device *parent, struct device *self, void *aux)
151 {
152 struct gpr_softc *sc = (void *)self;
153 struct pcmcia_attach_args *pa = aux;
154 struct pcmcia_config_entry *cfe;
155 const char *intrstr;
156
157 for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe;
158 cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
159
160 if (!pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
161 cfe->iospace[0].length, cfe->iospace[0].length,
162 &sc->sc_pioh))
163 break;
164 }
165
166 if (cfe == NULL) {
167 printf(": can't alloc i/o space\n");
168 goto fail_io_alloc;
169 }
170
171 pcmcia_function_init(pa->pf, cfe);
172 if (pcmcia_function_enable(pa->pf)) {
173 printf(": function enable failed\n");
174 goto fail_enable;
175 }
176
177 if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0,
178 sc->sc_pioh.size, &sc->sc_pioh, &sc->sc_iowin)) {
179 printf(": can't map i/o space\n");
180 goto fail_io_map;
181 }
182
183
184
185
186 if (pcmcia_mem_alloc(pa->pf, GPR400_MEM_LEN, &sc->sc_pmemh)) {
187 printf(": can't map mem space\n");
188 goto fail_mem_alloc;
189 }
190
191 if (pcmcia_mem_map(pa->pf, PCMCIA_MEM_ATTR, pa->pf->ccr_base,
192 GPR400_MEM_LEN, &sc->sc_pmemh, &sc->sc_offset, &sc->sc_memwin)) {
193 printf(": can't map memory\n");
194 goto fail_mem_map;
195 }
196
197 sc->sc_pf = pa->pf;
198 sc->sc_iot = sc->sc_pioh.iot;
199 sc->sc_ioh = sc->sc_pioh.ioh;
200 sc->sc_memt = sc->sc_pmemh.memt;
201 sc->sc_memh = sc->sc_pmemh.memh;
202
203 printf(" port 0x%lx/%d", sc->sc_pioh.addr, sc->sc_pioh.size);
204
205 sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, gpr_intr, sc,
206 sc->sc_dev.dv_xname);
207 intrstr = pcmcia_intr_string(sc->sc_pf, sc->sc_ih);
208 printf("%s%s\n", *intrstr ? ", " : "", intrstr);
209 if (sc->sc_ih != NULL)
210 return;
211
212 pcmcia_mem_unmap(pa->pf, sc->sc_memwin);
213 fail_mem_map:
214 pcmcia_mem_free(pa->pf, &sc->sc_pmemh);
215 fail_mem_alloc:
216 pcmcia_io_unmap(pa->pf, sc->sc_iowin);
217 fail_io_map:
218 pcmcia_function_disable(pa->pf);
219 fail_enable:
220 pcmcia_io_free(pa->pf, &sc->sc_pioh);
221 fail_io_alloc:
222 return;
223 }
224
225 int
226 gpr_detach(struct device *dev, int flags)
227 {
228 struct gpr_softc *sc = (struct gpr_softc *)dev;
229
230 pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
231 pcmcia_io_free(sc->sc_pf, &sc->sc_pioh);
232 pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
233 pcmcia_mem_free(sc->sc_pf, &sc->sc_pmemh);
234
235 return (0);
236 }
237
238 int
239 gpr_activate(struct device *dev, enum devact act)
240 {
241 struct gpr_softc *sc = (struct gpr_softc *)dev;
242
243 switch (act) {
244 case DVACT_ACTIVATE:
245 pcmcia_function_enable(sc->sc_pf);
246 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY,
247 gpr_intr, sc, sc->sc_dev.dv_xname);
248 break;
249
250 case DVACT_DEACTIVATE:
251 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
252 pcmcia_function_disable(sc->sc_pf);
253 break;
254 }
255
256 return (0);
257 }
258
259 int
260 gpropen(dev_t dev, int flags, int mode, struct proc *p)
261 {
262 int unit = GPRUNIT(dev);
263 struct gpr_softc *sc;
264
265 DPRINTF(("%s: flags %d, mode %d\n", __func__, flags, mode));
266
267 if (unit >= gpr_cd.cd_ndevs ||
268 (sc = gpr_cd.cd_devs[unit]) == NULL)
269 return (ENXIO);
270
271 return (tlvput(sc, GPR400_SELECT, "\x02", 1));
272 }
273
274 int
275 gprclose(dev_t dev, int flags, int mode, struct proc *p)
276 {
277 int unit = GPRUNIT(dev);
278 struct gpr_softc *sc = gpr_cd.cd_devs[unit];
279
280 DPRINTF(("%s: flags %d, mode %d\n", __func__, flags, mode));
281
282 (void)tlvput(sc, GPR400_CLOSE, (u_int8_t *)0, 0);
283
284 return (0);
285 }
286
287 int
288 gprioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
289 {
290 int unit = GPRUNIT(dev);
291 struct gpr_softc *sc = gpr_cd.cd_devs[unit];
292 int error;
293
294 DPRINTF(("%s: cmd %d, flags 0x%x\n", __func__, cmd, flags));
295
296 switch (cmd) {
297 case GPR_RESET:
298
299
300
301
302 bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL,
303 GPR400_RESET);
304 delay(10);
305 bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL, 0);
306 tsleep(sc, PWAIT, "gpreset", hz / 40);
307
308
309 case GPR_SELECT:
310 error = tlvput(sc, GPR400_SELECT, "\x02", 1);
311 break;
312
313 case GPR_POWER:
314 {
315 u_int8_t *mode;
316
317 if (*(int *)addr)
318 mode = "\x01";
319 else
320 mode = "\x00";
321
322 error = tlvput(sc, GPR400_POWER, mode, 1);
323 }
324 break;
325
326 case GPR_CLOSE:
327 error = tlvput(sc, GPR400_CLOSE, (u_int8_t *)0, 0);
328 break;
329
330 case GPR_RAM:
331 {
332 struct gpr400_ram r;
333
334 bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
335 sc->sc_offset, &r, sizeof(struct gpr400_ram));
336 error = copyout(&r, addr, sizeof(struct gpr400_ram));
337 }
338 break;
339
340 case GPR_CMD:
341 case GPR_OPEN:
342 case GPR_STATUS:
343 case GPR_TLV:
344 default:
345 error = EINVAL;
346 break;
347 };
348
349 return (error);
350 }
351
352 int
353 gpr_intr(void *arg)
354 {
355 struct gpr_softc *sc = arg;
356 u_int8_t val;
357
358 DPRINTF(("%s: got interrupt\n", __func__));
359
360
361 val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL);
362 bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL,
363 val & ~GPR400_INTR);
364
365 wakeup(sc);
366
367 return (1);
368 }
369
370 int
371 tlvput(struct gpr_softc *sc, int cmd, u_int8_t *data, int len)
372 {
373 int resid, ret;
374
375 DPRINTF(("%s: cmd 0x%x, data %p, len %d\n", __func__,
376 cmd, data, len));
377
378 resid = len;
379 do {
380 int n, s;
381
382 n = min(resid, 28);
383 resid -= n;
384
385 if (resid)
386 cmd |= GPR400_CONT;
387 else
388 cmd &= ~GPR400_CONT;
389
390 DPRINTF(("%s: sending cmd 0x%x, len %d, left %d\n",
391 __func__, cmd, n, resid));
392
393 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0x02, cmd);
394 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0x03, n);
395
396 if (n) {
397 bus_space_write_region_1(sc->sc_iot, sc->sc_ioh,
398 0x04, data, n);
399 data += n;
400 }
401
402 s = spltty();
403
404
405 bus_space_write_1(sc->sc_iot, sc->sc_ioh, GPR400_HAP_CTRL,
406 GPR400_IREQ);
407
408 tsleep(sc, PCATCH, "tlvput", 0);
409
410 splx(s);
411
412
413 ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0x04);
414
415 DPRINTF(("%s: ret %d\n", __func__, ret));
416
417 if (ret != 0x00 || (!resid && ret != 0xe7))
418 return (EIO);
419
420 } while (resid > 0);
421
422 return (0);
423 }