1 /**	$MirOS: src/sys/dev/pci/ises.c,v 1.3 2011/11/20 18:54:47 tg Exp $ */
2 /*	$OpenBSD: ises.c,v 1.27 2004/05/07 14:42:26 millert Exp $	*/
3 
4 /*
5  * Copyright (c) 2000, 2001 H�kan Olsson (ho@crt.se)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * PCC-ISES hardware crypto accelerator
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/errno.h>
38 #include <sys/malloc.h>
39 #include <sys/kernel.h>
40 #include <sys/mbuf.h>
41 #include <sys/timeout.h>
42 #include <sys/device.h>
43 #include <sys/queue.h>
44 
45 #include <crypto/cryptodev.h>
46 #include <crypto/cryptosoft.h>
47 #include <dev/rndvar.h>
48 #include <syskern/md5.h>
49 #include <crypto/sha1.h>
50 #include <crypto/rmd160.h>
51 
52 #include <dev/pci/pcireg.h>
53 #include <dev/pci/pcivar.h>
54 #include <dev/pci/pcidevs.h>
55 
56 #include <dev/pci/isesreg.h>
57 #include <dev/pci/isesvar.h>
58 #include <dev/microcode/ises/ises_fw.h>
59 
60 /*
61  * Prototypes and count for the pci_device structure
62  */
63 int	ises_match(struct device *, void *, void *);
64 void	ises_attach(struct device *, struct device *, void *);
65 
66 void	ises_initstate(void *);
67 void	ises_hrng_init(struct ises_softc *);
68 void	ises_hrng(void *);
69 void	ises_process_oqueue(struct ises_softc *);
70 int	ises_queue_cmd(struct ises_softc *, u_int32_t, u_int32_t *,
71 		       u_int32_t (*)(struct ises_softc *, struct ises_cmd *));
72 u_int32_t ises_get_fwversion(struct ises_softc *);
73 int	ises_assert_cmd_mode(struct ises_softc *);
74 
75 int	ises_intr(void *);
76 int	ises_newsession(u_int32_t *, struct cryptoini *);
77 int	ises_freesession(u_int64_t);
78 int	ises_process(struct cryptop *);
79 void	ises_callback(struct ises_q *);
80 int	ises_feed(struct ises_softc *);
81 int	ises_bchu_switch_session(struct ises_softc *,
82 				      struct ises_session *, int);
83 u_int32_t ises_bchu_switch_final(struct ises_softc *, struct ises_cmd *);
84 
85 void	ises_read_dma(struct ises_softc *);
86 
87 #define READ_REG(sc,r) \
88     bus_space_read_4((sc)->sc_memt, (sc)->sc_memh,r)
89 
90 #define WRITE_REG(sc,reg,val) \
91     bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, reg, val)
92 
93 /* XXX This should probably be (x) = htole32((x)) */
94 #define SWAP32(x) ((x) = swap32((x)))
95 
96 #ifdef ISESDEBUG
97 #  define DPRINTF(x) printf x
98 #else
99 #  define DPRINTF(x)
100 #endif
101 
102 #ifdef ISESDEBUG
103 void	ises_debug_init(struct ises_softc *);
104 void	ises_debug_2(void);
105 void	ises_debug_loop(void *);
106 void	ises_showreg(void);
107 void	ises_debug_parse_omr(struct ises_softc *);
108 void	ises_debug_simple_cmd(struct ises_softc *, u_int32_t, u_int32_t);
109 struct ises_softc *ises_sc;
110 struct timeout ises_db_timeout;
111 int ises_db;
112 #endif
113 
114 /* For HRNG entropy collection, these values gather 1600 bytes/s */
115 #ifndef ISESRNGBITS
116 #define ISESRNGBITS	128		/* Bits per iteration (mult. of 32) */
117 #define ISESRNGIPS	100		/* Iterations per second */
118 #endif
119 
120 /* XXX Disable HRNG while debugging. */
121 #define ISES_HRNG_DISABLED
122 
123 /* Maximum number of times we try to download the firmware. */
124 #define ISES_MAX_DOWNLOAD_RETRIES	3
125 
126 struct cfattach ises_ca = {
127 	sizeof(struct ises_softc), ises_match, ises_attach,
128 };
129 
130 struct cfdriver ises_cd = {
131 	0, "ises", DV_DULL
132 };
133 
134 struct ises_stats {
135 	u_int64_t	ibytes;
136 	u_int64_t	obytes;
137 	u_int32_t	ipkts;
138 	u_int32_t	opkts;
139 	u_int32_t	invalid;
140 	u_int32_t	nomem;
141 } isesstats;
142 
143 int
ises_match(struct device * parent,void * match,void * aux)144 ises_match(struct device *parent, void *match, void *aux)
145 {
146 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
147 
148 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_PIJNENBURG &&
149 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_PIJNENBURG_PCC_ISES)
150 		return (1);
151 
152 	return (0);
153 }
154 
155 void
ises_attach(struct device * parent,struct device * self,void * aux)156 ises_attach(struct device *parent, struct device *self, void *aux)
157 {
158 	struct ises_softc *sc = (struct ises_softc *)self;
159 	struct pci_attach_args *pa = aux;
160 	pci_chipset_tag_t pc = pa->pa_pc;
161 	pci_intr_handle_t ih;
162 	const char *intrstr = NULL;
163 	bus_size_t memsize;
164 	u_int32_t cmd;
165 
166 	bus_dma_segment_t seg;
167 	int nsegs, error, state;
168 
169 	SIMPLEQ_INIT(&sc->sc_queue);
170 	SIMPLEQ_INIT(&sc->sc_qchip);
171 	SIMPLEQ_INIT(&sc->sc_cmdq);
172 	state = 0;
173 
174 	/* Verify PCI space */
175 	cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
176 	cmd |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
177 	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, cmd);
178 	cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
179 
180 	if (!(cmd & PCI_COMMAND_MEM_ENABLE)) {
181 		printf(": failed to enable memory mapping\n");
182 		return;
183 	}
184 
185 	if (!(cmd & PCI_COMMAND_MASTER_ENABLE)) {
186 		printf(": failed to enable bus mastering\n");
187 		return;
188 	}
189 
190 	/* Map control/status registers. */
191 	if (pci_mapreg_map(pa, PCI_MAPREG_START,
192 	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt,
193 	    &sc->sc_memh, NULL, &memsize, 0)) {
194 		printf(": can't find mem space\n");
195 		return;
196 	}
197 	state++;
198 
199 	/* Map interrupt. */
200 	if (pci_intr_map(pa, &ih)) {
201 		printf(": couldn't map interrupt\n");
202 		goto fail;
203 	}
204 	state++;
205 
206 	intrstr = pci_intr_string(pc, ih);
207 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ises_intr, sc,
208 	    self->dv_xname);
209 	if (sc->sc_ih == NULL) {
210 		printf(": couldn't establish interrupt\n");
211 		if (intrstr != NULL)
212 			printf(" at %s", intrstr);
213 		printf("\n");
214 		goto fail;
215 	}
216 
217 	/* Initialize DMA map */
218 	sc->sc_dmat = pa->pa_dmat;
219 	error = bus_dmamap_create(sc->sc_dmat, 1 << PGSHIFT, 1, 1 << PGSHIFT,
220 	    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_dmamap);
221 	if (error) {
222 		printf(": cannot create dma map (%d)\n", error);
223 		goto fail;
224 	}
225 	state++;
226 
227 	/* Allocate in DMAable memory. */
228 	if (bus_dmamem_alloc(sc->sc_dmat, ISES_B_DATASIZE, 1, 0, &seg, 1,
229 	    &nsegs, BUS_DMA_NOWAIT)) {
230 		printf(": can't alloc dma buffer space\n");
231 		goto fail;
232 	}
233 	state++;
234 
235 	if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, ISES_B_DATASIZE,
236 	    &sc->sc_dma_data, 0)) {
237 		printf(": can't map dma buffer space\n");
238 		goto fail;
239 	}
240 	state++;
241 
242 	printf(": %s\n", intrstr);
243 
244 	bzero(&isesstats, sizeof(isesstats));
245 
246 	sc->sc_cid = crypto_get_driverid(0);
247 
248 	if (sc->sc_cid < 0)
249 		goto fail;
250 
251 	/*
252 	 * Since none of the initialization steps generate interrupts
253 	 * for example, the hardware reset, we use a number of timeouts
254 	 * (or init states) to do the rest of the chip initialization.
255 	 */
256 
257 	sc->sc_initstate = 0;
258 	startuphook_establish(ises_initstate, sc);
259 
260 #ifdef ISESDEBUG
261 	ises_debug_init(sc);
262 #endif
263 	return;
264 
265  fail:
266 	switch (state) { /* Always fallthrough here. */
267 	case 5:
268 		bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_dma_data,
269 		    sizeof sc->sc_dma_data);
270 	case 4:
271 		bus_dmamem_free(sc->sc_dmat, &seg, nsegs);
272 	case 3:
273 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
274 	case 2:
275 		pci_intr_disestablish(pc, sc->sc_ih);
276 	case 1:
277 		bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize);
278 	default: /* 0 */
279 		break;
280 	}
281 	return;
282 }
283 
284 void
ises_initstate(void * v)285 ises_initstate(void *v)
286 {
287 	/*
288 	 * Step through chip initialization.
289 	 * sc->sc_initstate tells us what to do.
290 	 */
291 	extern int hz;
292 	struct ises_softc *sc = v;
293 	char *dv = sc->sc_dv.dv_xname;
294 	u_int32_t stat;
295 	int p, ticks, algs[CRYPTO_ALGORITHM_MAX + 1];
296 	static int retry_count = 0; /* XXX Should be in softc */
297 
298 	ticks = hz * 3 / 2; /* 1.5s */
299 
300 	p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
301 	DPRINTF(("%s: initstate %d, IDP state is %d \"%s\"\n", dv,
302 		  sc->sc_initstate, p, ises_idp_state[p]));
303 
304 	switch (sc->sc_initstate) {
305 	case 0:
306 		/* Called by dostartuphooks(9). */
307 		timeout_set(&sc->sc_timeout, ises_initstate, sc);
308 
309 		/* FALLTHROUGH */
310 		sc->sc_initstate++;
311 	case 1:
312 		/* Power up the chip (clear powerdown bit) */
313 		stat = READ_REG(sc, ISES_BO_STAT);
314 		if (stat & ISES_BO_STAT_POWERDOWN) {
315 			stat &= ~ISES_BO_STAT_POWERDOWN;
316 			WRITE_REG(sc, ISES_BO_STAT, stat);
317 			/* Selftests will take 1 second. */
318 			break;
319 		}
320 #if 1
321 		else {
322 			/* Power down the chip for sane init, then rerun. */
323 			stat |= ISES_BO_STAT_POWERDOWN;
324 			WRITE_REG(sc, ISES_BO_STAT, stat);
325 			sc->sc_initstate--; /* Rerun state 1. */
326 			break;
327 		}
328 #else
329 		/* FALLTHROUGH (chip is already powered up) */
330 		sc->sc_initstate++;
331 #endif
332 
333 	case 2:
334 		/* Perform a hardware reset */
335 		stat = 0;
336 
337 		printf ("%s: initializing...\n", dv);
338 
339 		/* Clear all possible bypass bits. */
340 		for (p = 0; p < 128; p++)
341 			WRITE_REG(sc, ISES_B_BDATAOUT, 0L);
342 
343 		stat |= ISES_BO_STAT_HWRESET;
344 		WRITE_REG(sc, ISES_BO_STAT, stat);
345 		stat &= ~ISES_BO_STAT_HWRESET;
346 		WRITE_REG(sc, ISES_BO_STAT, stat);
347 		/* Again, selftests will take 1 second. */
348 		break;
349 
350 	case 3:
351 		/* Set AConf to zero, i.e 32-bits access to A-int. */
352 		stat = READ_REG(sc, ISES_BO_STAT);
353 		stat &= ~ISES_BO_STAT_ACONF;
354 		WRITE_REG(sc, ISES_BO_STAT, stat);
355 
356 		/* Is the firmware already loaded? */
357 		if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
358 			/* Yes it is, jump ahead a bit */
359 			ticks = 1;
360 			sc->sc_initstate += 3; /* Next step --> 7 */
361 			break;
362 		}
363 
364 		/*
365 		 * Download the Basic Functionality firmware.
366 		 */
367 
368 		p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
369 		if (p == ISES_IDP_WFPL) {
370 			/* We're ready to download. */
371 			ticks = 1;
372 			sc->sc_initstate += 2; /* Next step --> 6 */
373 			break;
374 		}
375 
376 		/*
377 		 * Prior to downloading we need to reset the NSRAM.
378 		 * Setting the tamper bit will erase the contents
379 		 * in 1 microsecond.
380 		 */
381 		stat = READ_REG(sc, ISES_BO_STAT);
382 		stat |= ISES_BO_STAT_TAMPER;
383 		WRITE_REG(sc, ISES_BO_STAT, stat);
384 		ticks = 1;
385 		break;
386 
387 	case 4:
388 		/* After tamper bit has been set, powerdown chip. */
389 		stat = READ_REG(sc, ISES_BO_STAT);
390 		stat |= ISES_BO_STAT_POWERDOWN;
391 		WRITE_REG(sc, ISES_BO_STAT, stat);
392 		/* Wait one second for power to dissipate. */
393 		break;
394 
395 	case 5:
396 		/* Clear tamper and powerdown bits. */
397 		stat = READ_REG(sc, ISES_BO_STAT);
398 		stat &= ~(ISES_BO_STAT_TAMPER | ISES_BO_STAT_POWERDOWN);
399 		WRITE_REG(sc, ISES_BO_STAT, stat);
400 		/* Again we need to wait a second for selftests. */
401 		break;
402 
403 	case 6:
404 		/*
405 		 * We'll need some space in the input queue (IQF)
406 		 * and we need to be in the 'waiting for program
407 		 * length' IDP state (0x4).
408 		 */
409 		p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
410 		if (READ_REG(sc, ISES_A_IQF) < 4 || p != ISES_IDP_WFPL) {
411 			if (retry_count++ < ISES_MAX_DOWNLOAD_RETRIES) {
412 				/* Retry download. */
413 				sc->sc_initstate -= 5; /* Next step --> 2 */
414 				ticks = 1;
415 				break;
416 			}
417 			retry_count = 0;
418 			printf("%s: cannot download firmware, "
419 			    "IDP state is \"%s\"\n", dv, ises_idp_state[p]);
420 			return;
421 		}
422 
423 		/* Write firmware length */
424 		WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPLEN);
425 
426 		/* Write firmware code */
427 		for (p = 0; p < sizeof(ises_bf_fw)/sizeof(u_int32_t); p++) {
428 			WRITE_REG(sc, ISES_A_IQD, ises_bf_fw[p]);
429 			if (READ_REG(sc, ISES_A_IQF) < 4)
430 				DELAY(10);
431 		}
432 
433 		/* Write firmware CRC */
434 		WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPCRC);
435 
436 		/* Wait 1s while chip resets and runs selftests */
437 		break;
438 
439 	case 7:
440 		/* Did the download succed? */
441 		if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
442 			ticks = 1;
443 			break;
444 		}
445 
446 		/* We failed. */
447 		goto fail;
448 
449 	case 8:
450 		if (ises_assert_cmd_mode(sc) < 0)
451 			goto fail;
452 
453 		/*
454 		 * Now that the basic functionality firmware should be
455 		 * up and running, try to get the firmware version.
456 		 */
457 
458 		stat = ises_get_fwversion(sc);
459 		if (stat == 0)
460 			goto fail;
461 
462 		printf("%s: firmware v%d.%d loaded (%d bytes)", dv,
463 		    stat & 0xffff, (stat >> 16) & 0xffff, ISES_BF_IDPLEN << 2);
464 
465 		/* We can use firmware versions 1.x & 2.x */
466 		switch (stat & 0xffff) {
467 		case 0:
468 			printf(" diagnostic, %s disabled\n", dv);
469 			goto fail;
470 		case 1: /* Basic Func "base" firmware */
471 		case 2: /* Basic Func "ipsec" firmware, no ADP code */
472 			break;
473 		default:
474 			printf(" unknown, %s disabled\n", dv);
475 			goto fail;
476 		}
477 
478 		stat = READ_REG(sc, ISES_A_STAT);
479 		DPRINTF((", mode %s",
480 		    ises_sw_mode[ISES_STAT_SW_MODE(stat)]));
481 
482 		/* Reuse the timeout for HRNG entropy collection. */
483 		timeout_del(&sc->sc_timeout);
484 		ises_hrng_init(sc);
485 
486 		/* Set the interrupt mask */
487 		sc->sc_intrmask = ISES_STAT_BCHU_OAF | ISES_STAT_BCHU_ERR |
488 		    ISES_STAT_BCHU_OFHF | ISES_STAT_SW_OQSINC |
489 		    ISES_STAT_LNAU_BUSY_1 | ISES_STAT_LNAU_ERR_1 |
490 		    ISES_STAT_LNAU_BUSY_2 | ISES_STAT_LNAU_ERR_2;
491 #if 0
492 		    ISES_STAT_BCHU_ERR | ISES_STAT_BCHU_OAF |
493 		    ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE |
494 		    ISES_STAT_BCHU_OFHF | ISES_STAT_BCHU_OFF;
495 #endif
496 
497 		WRITE_REG(sc, ISES_A_INTE, sc->sc_intrmask);
498 
499 		/* We're done. */
500 		printf("\n");
501 
502 		/* Register ourselves with crypto framework. */
503 		bzero(algs, sizeof(algs));
504 
505 		algs[CRYPTO_3DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
506 		algs[CRYPTO_DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
507 		algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
508 		algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
509 		algs[CRYPTO_RIPEMD160_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
510 
511 		crypto_register(sc->sc_cid, algs,
512 		    ises_newsession, ises_freesession, ises_process);
513 		return;
514 
515 	default:
516 		printf("%s: entered unknown initstate %d\n", dv,
517 		    sc->sc_initstate);
518 		goto fail;
519 	}
520 
521 	/* Increment state counter and schedule next step in 'ticks' ticks. */
522 	sc->sc_initstate++;
523 	timeout_add(&sc->sc_timeout, ticks);
524 	return;
525 
526  fail:
527 	printf("%s: firmware failure\n", dv);
528 	timeout_del(&sc->sc_timeout);
529 	return;
530 }
531 
532 /* Put a command on the A-interface queue. */
533 int
ises_queue_cmd(struct ises_softc * sc,u_int32_t cmd,u_int32_t * data,u_int32_t (* callback)(struct ises_softc *,struct ises_cmd *))534 ises_queue_cmd(struct ises_softc *sc, u_int32_t cmd, u_int32_t *data,
535 	       u_int32_t (*callback)(struct ises_softc *, struct ises_cmd *))
536 {
537 	struct ises_cmd *cq;
538 	int p, len, s, code;
539 
540 	len = cmd >> 24;
541 	code = (cmd >> 16) & 0xFF;
542 
543 #ifdef ISESDEBUG
544 	if (code != ISES_CMD_HBITS) /* ... since this happens 100 times/s */
545 		DPRINTF(("%s: queueing cmd 0x%x len %d\n", sc->sc_dv.dv_xname,
546 		    code, len));
547 #endif
548 
549 	s = splnet();
550 
551 	if (len > READ_REG(sc, ISES_A_IQF)) {
552 		splx(s);
553 		return (EAGAIN); /* XXX ENOMEM ? */
554 	}
555 
556 	cq = (struct ises_cmd *)
557 	    malloc(sizeof (struct ises_cmd), M_DEVBUF, M_NOWAIT);
558 	if (cq == NULL) {
559 		splx(s);
560 		isesstats.nomem++;
561 		return (ENOMEM);
562 	}
563 	bzero(cq, sizeof (struct ises_cmd));
564 	cq->cmd_code = code;
565 	cq->cmd_cb = callback;
566 	cq->cmd_session = sc->sc_cursession;
567 	SIMPLEQ_INSERT_TAIL(&sc->sc_cmdq, cq, cmd_next);
568 
569 	WRITE_REG(sc, ISES_A_IQD, cmd);
570 
571 	/* LNAU register data should be written in reverse order */
572 	if ((code >= ISES_CMD_LW_A_1 && code <= ISES_CMD_LW_U_1) || /* LNAU1 */
573 	    (code >= ISES_CMD_LW_A_2 && code <= ISES_CMD_LW_U_2))   /* LNAU2 */
574 		for (p = len - 1; p >= 0; p--)
575 			WRITE_REG(sc, ISES_A_IQD, *(data + p));
576 	else
577 		for (p = 0; p < len; p++)
578 			WRITE_REG(sc, ISES_A_IQD, *(data + p));
579 
580 	/* Signal 'command ready'. */
581 	WRITE_REG(sc, ISES_A_IQS, 0);
582 
583 	splx(s);
584 	return (0);
585 }
586 
587 /* Process all completed responses in the output queue. */
588 void
ises_process_oqueue(struct ises_softc * sc)589 ises_process_oqueue(struct ises_softc *sc)
590 {
591 #ifdef ISESDEBUG
592 	char *dv = sc->sc_dv.dv_xname;
593 #endif
594 	struct ises_cmd *cq;
595 	struct ises_session *ses;
596 	u_int32_t oqs, r, d;
597 	int cmd, len, c, s;
598 
599 	r = READ_REG(sc, ISES_A_OQS);
600 	if (r > 1)
601 		DPRINTF(("%s:process_oqueue: OQS=%d\n", dv, r));
602 
603 	/* OQS gives us the number of responses we have to process. */
604 	while ((oqs = READ_REG(sc, ISES_A_OQS)) > 0) {
605 		/* Read command response. [ len(8) | cmd(8) | rc(16) ] */
606 		r = READ_REG(sc, ISES_A_OQD);
607 		len = (r >> 24);
608 		cmd = (r >> 16) & 0xff;
609 		r   = r & 0xffff;
610 
611 		s = splnet();
612 		if (!SIMPLEQ_EMPTY(&sc->sc_cmdq)) {
613 			cq = SIMPLEQ_FIRST(&sc->sc_cmdq);
614 			SIMPLEQ_REMOVE_HEAD(&sc->sc_cmdq, cmd_next);
615 			cq->cmd_rlen = len;
616 		} else {
617 			cq = NULL;
618 			DPRINTF(("%s:process_oqueue: cmd queue empty!\n", dv));
619 		}
620 		splx(s);
621 
622 		if (r) {
623 			/* Ouch. This command generated an error */
624 			DPRINTF(("%s:process_oqueue: cmd 0x%x err %d\n", dv,
625 			    cmd, (r & ISES_RC_MASK)));
626 			/* Abort any running session switch to force a retry.*/
627 			sc->sc_switching = 0;
628 			/* Return to CMD mode. This will reset all queues. */
629 			(void)ises_assert_cmd_mode(sc);
630 		} else {
631 			/* Use specified callback, if any */
632 			if (cq && cq->cmd_cb) {
633 				if (cmd == cq->cmd_code) {
634 					cq->cmd_cb(sc, cq);
635 					cmd = ISES_CMD_NONE;
636 				} else {
637 					DPRINTF(("%s:process_oqueue: expected"
638 					    " cmd 0x%x, got 0x%x\n", dv,
639 					    cq->cmd_code, cmd));
640 					/* XXX Some error handling here? */
641 				}
642 			}
643 
644 			switch (cmd) {
645 			case ISES_CMD_NONE:
646 				break;
647 
648 			case ISES_CMD_HBITS:
649 				/* XXX How about increasing the pool size? */
650 				/* XXX Use add_entropy_words instead? */
651 				/* XXX ... at proper spl */
652 				/* Cmd generated by ises_rng() via timeouts */
653 				while (len--) {
654 					d = READ_REG(sc, ISES_A_OQD);
655 					add_true_randomness(d);
656 				}
657 				break;
658 
659 			case ISES_CMD_LUPLOAD_1:
660 				/* Get result of LNAU 1 operation. */
661 				DPRINTF(("%s:process_oqueue: LNAU 1 result "
662 				     "upload (len=%d)\n", dv, len));
663 				sc->sc_lnau1_rlen = len;
664 				bzero(sc->sc_lnau1_r, 2048 / 8);
665 				while (len--) {
666 					/* first word is LSW */
667 					sc->sc_lnau1_r[len] =
668 					    READ_REG(sc, ISES_A_OQD);
669 				}
670 				break;
671 
672 			case ISES_CMD_LUPLOAD_2:
673 				/* Get result of LNAU 1 operation. */
674 				DPRINTF(("%s:process_oqueue: LNAU 2 result "
675 				     "upload (len=%d)\n", dv, len));
676 				sc->sc_lnau2_rlen = len;
677 				bzero(sc->sc_lnau1_r, 2048 / 8);
678 				while (len--) {
679 					/* first word is LSW */
680 					sc->sc_lnau2_r[len] =
681 					    READ_REG(sc, ISES_A_OQD);
682 				}
683 				break;
684 
685 			case ISES_CMD_BR_OMR:
686 				ses = &sc->sc_sessions[cq->cmd_session];
687 				ses->omr = READ_REG(sc, ISES_A_OQD);
688 				DPRINTF(("%s:process_oqueue: read OMR[%08x]\n",
689 				    dv, ses->omr));
690 #ifdef ISESDEBUG
691 				ises_debug_parse_omr(sc);
692 #endif
693 				break;
694 
695 			case ISES_CMD_BSWITCH:
696 				/* XXX Currently BSWITCH does not work. */
697 				DPRINTF(("%s:process_oqueue: BCHU_SWITCH\n"));
698 				/* Put switched BCHU session in cur session. */
699 				ses = &sc->sc_sessions[cq->cmd_session];
700 				for(c = 0; len > 0; len--, c++)
701 #if 0 /* Don't store the key, just drain the data */
702 					*((u_int32_t *)&ses + c) =
703 #endif
704 					    READ_REG(sc, ISES_A_OQD);
705 
706 				sc->sc_switching = 0;
707 				ises_feed (sc);
708 				break;
709 
710 			case ISES_CMD_BW_HMLR:
711 				/* XXX Obsoleted by ises_bchu_switch_final */
712 				DPRINTF(("%s:process_oqueue: CMD_BW_HMLR !?\n",
713 				    dv));
714 				break;
715 
716 			default:
717 				/* All other are ok (no response data) */
718 				DPRINTF(("%s:process_oqueue cmd 0x%x len %d\n",
719 				    dv, cmd, len));
720 				if (cq && cq->cmd_cb)
721 					len -= cq->cmd_cb(sc, cq);
722 			}
723 		}
724 
725 		if (cq)
726 			free(cq, M_DEVBUF);
727 
728 		/* This will drain any remaining data and ACK this reponse. */
729 		while (len-- > 0)
730 			d = READ_REG(sc, ISES_A_OQD);
731 		WRITE_REG(sc, ISES_A_OQS, 0);
732 		if (oqs > 1)
733 			DELAY(1); /* Wait for fw to decrement OQS (8 clocks) */
734 	}
735 }
736 
737 int
ises_intr(void * arg)738 ises_intr(void *arg)
739 {
740 	struct ises_softc *sc = arg;
741 	u_int32_t ints, dma_status, cmd;
742 	char *dv = sc->sc_dv.dv_xname;
743 
744 	dma_status = READ_REG(sc, ISES_DMA_STATUS);
745 
746 	if (!(dma_status & (ISES_DMA_STATUS_R_ERR | ISES_DMA_STATUS_W_ERR))) {
747 		if ((sc->sc_dma_mask & ISES_DMA_STATUS_R_RUN) != 0 &&
748 		    (dma_status & ISES_DMA_STATUS_R_RUN) == 0) {
749 			DPRINTF(("%s: DMA read complete\n", dv));
750 
751 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
752 			    sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
753 
754 			/* XXX Pick up and return the data.*/
755 
756 			WRITE_REG(sc, ISES_DMA_RESET, 0);
757 		}
758 		if ((sc->sc_dma_mask & ISES_DMA_STATUS_W_RUN) != 0 &&
759 		    (dma_status & ISES_DMA_STATUS_W_RUN) == 0) {
760 			DPRINTF(("%s: DMA write complete\n", dv));
761 
762 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
763 			    sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
764 
765 			WRITE_REG(sc, ISES_DMA_RESET, 0);
766 			ises_feed(sc);
767 		}
768 	} else {
769 		printf ("%s: DMA error\n", dv);
770 		WRITE_REG(sc, ISES_DMA_RESET, 0);
771 	}
772 
773 	ints = READ_REG(sc, ISES_A_INTS);
774 	if (!(ints & sc->sc_intrmask)) {
775 		DPRINTF (("%s: other intr mask [%08x]\n", ints));
776 		return (0); /* Not our interrupt. */
777 	}
778 
779 	/* Clear all set intr bits. */
780 	WRITE_REG(sc, ISES_A_INTS, ints);
781 
782 #if 0
783 	/* Check it we've got room for more data. */
784 	if (READ_REG(sc, ISES_A_STAT) &
785 	    (ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE))
786 		ises_feed(sc);
787 #endif
788 
789 	/* Does the A-intf output queue have data we need to process? */
790 	if (ints & ISES_STAT_SW_OQSINC)
791 		ises_process_oqueue(sc);
792 
793 	if (ints & ISES_STAT_LNAU_BUSY_1) {
794 		DPRINTF(("%s:ises_intr: LNAU 1 job complete\n", dv));
795 		/* upload LNAU 1 result (into sc->sc_lnau1_r) */
796 		cmd = ISES_MKCMD(ISES_CMD_LUPLOAD_1, 0);
797 		ises_queue_cmd(sc, cmd, NULL, NULL);
798 	}
799 
800 	if (ints & ISES_STAT_LNAU_BUSY_2) {
801 		DPRINTF(("%s:ises_intr: LNAU 2 job complete\n", dv));
802 		/* upload LNAU 2 result (into sc->sc_lnau2_r) */
803 		cmd = ISES_MKCMD(ISES_CMD_LUPLOAD_2, 0);
804 		ises_queue_cmd(sc, cmd, NULL, NULL);
805 	}
806 
807 	if (ints & ISES_STAT_LNAU_ERR_1) {
808 		DPRINTF(("%s:ises_intr: LNAU 1 error\n", dv));
809 		sc->sc_lnau1_rlen = -1;
810 	}
811 
812 	if (ints & ISES_STAT_LNAU_ERR_2) {
813 		DPRINTF(("%s:ises_intr: LNAU 2 error\n", dv));
814 		sc->sc_lnau2_rlen = -1;
815 	}
816 
817 	if (ints & ISES_STAT_BCHU_OAF) {	/* output data available */
818 		DPRINTF(("%s:ises_intr: BCHU_OAF bit set\n", dv));
819 		/* Read DMA data from B-interface. */
820 		ises_read_dma (sc);
821 	}
822 
823 	if (ints & ISES_STAT_BCHU_ERR) {	/* We got a BCHU error */
824 		DPRINTF(("%s:ises_intr: BCHU error\n", dv));
825 		/* XXX Error handling */
826 	}
827 
828 	if (ints & ISES_STAT_BCHU_OFHF) {	/* Output is half full */
829 		DPRINTF(("%s:ises_intr: BCHU output FIFO half full\n", dv));
830 		/* XXX drain data? */
831 	}
832 
833 #if 0 /* XXX Useful? */
834 	if (ints & ISES_STAT_BCHU_OFF) {	/* Output is full */
835 		/* XXX drain data / error handling? */
836 	}
837 #endif
838 	return (1);
839 }
840 
841 int
ises_feed(struct ises_softc * sc)842 ises_feed(struct ises_softc *sc)
843 {
844 	struct ises_q *q;
845 	bus_dma_segment_t *ds = &sc->sc_dmamap->dm_segs[0];
846 	u_int32_t dma_status;
847 	int s;
848 #ifdef ISESDEBUG
849 	char *dv = sc->sc_dv.dv_xname;
850 #endif
851 
852 	DPRINTF(("%s:ises_feed: called (sc = %p)\n", dv, sc));
853 	DELAY(1000000);
854 
855 	s = splnet();
856 	/* Anything to do? */
857 	if (SIMPLEQ_EMPTY(&sc->sc_queue) ||
858 	    (READ_REG(sc, ISES_A_STAT) & ISES_STAT_BCHU_IFF)) {
859 		splx(s);
860 		return (0);
861 	}
862 
863 	/* Pick the first */
864 	q = SIMPLEQ_FIRST(&sc->sc_queue);
865 	splx(s);
866 
867 	/* If we're currently switching sessions, we'll have to wait. */
868 	if (sc->sc_switching != 0) {
869 		DPRINTF(("%s:ises_feed: waiting for session switch\n", dv));
870 		return (0);
871 	}
872 
873 	/* If on-chip data is not correct for this data, switch session. */
874 	if (sc->sc_cursession != q->q_sesn) {
875 		/* Session switch required */
876 		DPRINTF(("%s:ises_feed: initiating session switch\n", dv));
877 		if (ises_bchu_switch_session (sc, &q->q_session, q->q_sesn))
878 			sc->sc_cursession = q->q_sesn;
879 		else
880 			DPRINTF(("%s:ises_feed: session switch failed\n", dv));
881 		return (0);
882 	}
883 
884 	DPRINTF(("%s:ises_feed: feed to chip (q = %p)\n", dv, q));
885 	DELAY(2000000);
886 
887 	s = splnet();
888 	SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, q_next);
889 	SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
890 	--sc->sc_nqueue;
891 	splx(s);
892 
893 	if (q->q_crp->crp_flags & CRYPTO_F_IMBUF)
894 		bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_dmamap,
895 		    q->q_src.mbuf, BUS_DMA_NOWAIT);
896 	else if (q->q_crp->crp_flags & CRYPTO_F_IOV)
897 		bus_dmamap_load_uio(sc->sc_dmat, sc->sc_dmamap, q->q_src.uio,
898 		    BUS_DMA_NOWAIT);
899 	/* ... else */
900 
901 	/* Start writing data to the ises. */
902 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
903 	    sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
904 
905 	DPRINTF(("%s:ises_feed: writing DMA\n", dv));
906 	DELAY(1000000);
907 
908 	sc->sc_dma_mask |= ISES_DMA_STATUS_W_RUN;
909 
910 	WRITE_REG(sc, ISES_DMA_WRITE_START, ds->ds_addr);
911 	WRITE_REG(sc, ISES_DMA_WRITE_COUNT, ISES_DMA_WCOUNT(ds->ds_len));
912 
913 	dma_status = READ_REG(sc, ISES_DMA_STATUS);
914 	dma_status |= ISES_DMA_CTRL_ILT | ISES_DMA_CTRL_RLINE;
915 	WRITE_REG(sc, ISES_DMA_CTRL, dma_status);
916 
917 	DPRINTF(("%s:ises_feed: done\n", dv));
918 	return (0);
919 }
920 
921 /*
922  * Allocate a new 'session' and return an encoded session id.  'sidp'
923  * contains our registration id, and should contain an encoded session
924  * id on successful allocation.
925  */
926 int
ises_newsession(u_int32_t * sidp,struct cryptoini * cri)927 ises_newsession(u_int32_t *sidp, struct cryptoini *cri)
928 {
929 	struct cryptoini *c, *mac = NULL, *enc = NULL;
930 	struct ises_softc *sc = NULL;
931 	struct ises_session *ses;
932 	MD5_CTX	   md5ctx;
933 	SHA1_CTX   sha1ctx;
934 	RMD160_CTX rmd160ctx;
935 	int i, sesn;
936 #ifdef ISESDEBUG
937 	char *dv;
938 #endif
939 
940 	if (sidp == NULL || cri == NULL)
941 		return (EINVAL);
942 
943 	for (i = 0; i < ises_cd.cd_ndevs; i++) {
944 		sc = ises_cd.cd_devs[i];
945 		if (sc == NULL || sc->sc_cid == (*sidp))
946 			break;
947 	}
948 	if (sc == NULL)
949 		return (EINVAL);
950 #ifdef ISESDEBUG
951 	dv = sc->sc_dv.dv_xname;
952 #endif
953 
954 	DPRINTF(("%s:ises_newsession: start\n", dv));
955 
956 	for (c = cri; c != NULL; c = c->cri_next) {
957 		if (c->cri_alg == CRYPTO_MD5_HMAC ||
958 		    c->cri_alg == CRYPTO_SHA1_HMAC ||
959 		    c->cri_alg == CRYPTO_RIPEMD160_HMAC) {
960 			if (mac)
961 				return (EINVAL);
962 			mac = c;
963 		} else if (c->cri_alg == CRYPTO_DES_CBC ||
964 		    c->cri_alg == CRYPTO_3DES_CBC) {
965 			if (enc)
966 				return (EINVAL);
967 			enc = c;
968 		} else
969 			return (EINVAL);
970 	}
971 	if (mac == 0 && enc == 0)
972 		return (EINVAL);
973 
974 #ifdef ISESDEBUG
975 	printf ("%s:ises_newsession: mac=%p(%d) enc=%p(%d)\n",
976 	   dv, mac, (mac ? mac->cri_alg : -1), enc, (enc ? enc->cri_alg : -1));
977 #endif
978 
979 	/* Allocate a new session */
980 	if (sc->sc_sessions == NULL) {
981 		ses = sc->sc_sessions = (struct ises_session *)
982 		    malloc(sizeof(struct ises_session), M_DEVBUF, M_NOWAIT);
983 		if (ses == NULL) {
984 			isesstats.nomem++;
985 			return (ENOMEM);
986 		}
987 		sc->sc_cursession = -1;
988 		sesn = 0;
989 		sc->sc_nsessions = 1;
990 	} else {
991 		ses = NULL;
992 		for (sesn = 0; sesn < sc->sc_nsessions; sesn++)
993 			if (sc->sc_sessions[sesn].omr == 0) {
994 				ses = &sc->sc_sessions[sesn];
995 				sc->sc_cursession = sesn;
996 				break;
997 			}
998 
999 		if (ses == NULL) {
1000 			i = sc->sc_nsessions * sizeof(struct ises_session);
1001 			ses = (struct ises_session *)
1002 			    malloc(i + sizeof(struct ises_session), M_DEVBUF,
1003 			    M_NOWAIT);
1004 			if (ses == NULL) {
1005 				isesstats.nomem++;
1006 				return (ENOMEM);
1007 			}
1008 
1009 			bcopy(sc->sc_sessions, ses, i);
1010 			bzero(sc->sc_sessions, i);
1011 			free(sc->sc_sessions, M_DEVBUF);
1012 			sc->sc_sessions = ses;
1013 			ses = &sc->sc_sessions[sc->sc_nsessions];
1014 			sc->sc_cursession = sc->sc_nsessions;
1015 			sc->sc_nsessions++;
1016 		}
1017 	}
1018 
1019 	DPRINTF(("%s:ises_newsession: nsessions=%d cursession=%d\n", dv,
1020 	    sc->sc_nsessions, sc->sc_cursession));
1021 
1022 	bzero(ses, sizeof(struct ises_session));
1023 
1024 	/* Select data path through B-interface. */
1025 	ses->omr |= ISES_SELR_BCHU_DIS;
1026 
1027 	if (enc) {
1028 		/* get an IV, network byte order */
1029 		/* XXX switch to using builtin HRNG ! */
1030 		get_random_bytes(ses->sccr, sizeof(ses->sccr));
1031 
1032 		/* crypto key */
1033 		if (enc->cri_alg == CRYPTO_DES_CBC) {
1034 			bcopy(enc->cri_key, &ses->kr[0], 8);
1035 			bcopy(enc->cri_key, &ses->kr[2], 8);
1036 			bcopy(enc->cri_key, &ses->kr[4], 8);
1037 		} else
1038 			bcopy(enc->cri_key, &ses->kr[0], 24);
1039 
1040 		SWAP32(ses->kr[0]);
1041 		SWAP32(ses->kr[1]);
1042 		SWAP32(ses->kr[2]);
1043 		SWAP32(ses->kr[3]);
1044 		SWAP32(ses->kr[4]);
1045 		SWAP32(ses->kr[5]);
1046 	}
1047 
1048 	if (mac) {
1049 		for (i = 0; i < mac->cri_klen / 8; i++)
1050 			mac->cri_key[i] ^= HMAC_IPAD_VAL;
1051 
1052 		switch (mac->cri_alg) {
1053 		case CRYPTO_MD5_HMAC:
1054 			MD5Init(&md5ctx);
1055 			MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
1056 			MD5Update(&md5ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
1057 			    (mac->cri_klen / 8));
1058 			MD5Final((u_int8_t *)&ses->cvr, &md5ctx);
1059 			break;
1060 		case CRYPTO_SHA1_HMAC:
1061 			SHA1Init(&sha1ctx);
1062 			SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
1063 			SHA1Update(&sha1ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
1064 			    (mac->cri_klen / 8));
1065 			SHA1Final((u_int8_t *)ses->cvr, &sha1ctx);
1066 			break;
1067 		case CRYPTO_RIPEMD160_HMAC:
1068 		default:
1069 			RMD160Init(&rmd160ctx);
1070 			RMD160Update(&rmd160ctx, mac->cri_key,
1071 			    mac->cri_klen / 8);
1072 			RMD160Update(&rmd160ctx, hmac_ipad_buffer,
1073 			    HMAC_BLOCK_LEN - (mac->cri_klen / 8));
1074 			RMD160Final((u_int8_t *)ses->cvr, &rmd160ctx);
1075 			break;
1076 		}
1077 
1078 		for (i = 0; i < mac->cri_klen / 8; i++)
1079 			mac->cri_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
1080 
1081 		switch (mac->cri_alg) {
1082 		case CRYPTO_MD5_HMAC:
1083 			MD5Init(&md5ctx);
1084 			MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
1085 			MD5Update(&md5ctx, hmac_opad_buffer, HMAC_BLOCK_LEN -
1086 			    (mac->cri_klen / 8));
1087 			MD5Update(&md5ctx, (u_int8_t *)ses->cvr,
1088 			    sizeof(md5ctx.state));
1089 			MD5Final((u_int8_t *)ses->cvr, &md5ctx);
1090 			break;
1091 		case CRYPTO_SHA1_HMAC:
1092 			SHA1Init(&sha1ctx);
1093 			SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
1094 			SHA1Update(&sha1ctx, hmac_opad_buffer, HMAC_BLOCK_LEN -
1095 			    (mac->cri_klen / 8));
1096 			SHA1Update(&sha1ctx, (u_int8_t *)ses->cvr,
1097 			    sizeof(sha1ctx.state));
1098 			SHA1Final((u_int8_t *)ses->cvr, &sha1ctx);
1099 			break;
1100 		case CRYPTO_RIPEMD160_HMAC:
1101 		default:
1102 			RMD160Init(&rmd160ctx);
1103 			RMD160Update(&rmd160ctx, mac->cri_key,
1104 			    mac->cri_klen / 8);
1105 			RMD160Update(&rmd160ctx, hmac_opad_buffer,
1106 			    HMAC_BLOCK_LEN - (mac->cri_klen / 8));
1107 			RMD160Update(&rmd160ctx, (u_int8_t *)ses->cvr,
1108 			    sizeof(rmd160ctx.state));
1109 			RMD160Final((u_int8_t *)ses->cvr, &rmd160ctx);
1110 			break;
1111 		}
1112 
1113 		for (i = 0; i < mac->cri_klen / 8; i++)
1114 			mac->cri_key[i] ^= HMAC_OPAD_VAL;
1115 	}
1116 
1117 	DPRINTF(("%s:ises_newsession: done\n", dv));
1118 	*sidp = ISES_SID(sc->sc_dv.dv_unit, sesn);
1119 	return (0);
1120 }
1121 
1122 /* Deallocate a session. */
1123 int
ises_freesession(u_int64_t tsid)1124 ises_freesession(u_int64_t tsid)
1125 {
1126 	struct ises_softc *sc;
1127 	int card, sesn;
1128 	u_int32_t sid = ((u_int32_t)tsid) & 0xffffffff;
1129 
1130 	card = ISES_CARD(sid);
1131 	if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL)
1132 		return (EINVAL);
1133 
1134 	sc = ises_cd.cd_devs[card];
1135 	sesn = ISES_SESSION(sid);
1136 
1137 	DPRINTF(("%s:ises_freesession: freeing session %d\n",
1138 	    sc->sc_dv.dv_xname, sesn));
1139 
1140 	if (sc->sc_cursession == sesn)
1141 		sc->sc_cursession = -1;
1142 
1143 	bzero(&sc->sc_sessions[sesn], sizeof(sc->sc_sessions[sesn]));
1144 
1145 	return (0);
1146 }
1147 
1148 /* Called by the crypto framework, crypto(9). */
1149 int
ises_process(struct cryptop * crp)1150 ises_process(struct cryptop *crp)
1151 {
1152 	struct ises_softc *sc;
1153 	struct ises_q *q;
1154 	struct cryptodesc *maccrd, *enccrd, *crd;
1155 	struct ises_session *ses;
1156 	int card, s, err = EINVAL;
1157 	int encoffset, macoffset, cpskip, sskip, dskip, stheend, dtheend;
1158 	int cpoffset, coffset;
1159 #if 0
1160 	int nicealign;
1161 #endif
1162 #ifdef ISESDEBUG
1163 	char *dv;
1164 #endif
1165 
1166 	if (crp == NULL || crp->crp_callback == NULL)
1167 		return (EINVAL);
1168 
1169 	card = ISES_CARD(crp->crp_sid);
1170 	if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL)
1171 		goto errout;
1172 
1173 	sc = ises_cd.cd_devs[card];
1174 #ifdef ISESDEBUG
1175 	dv = sc->sc_dv.dv_xname;
1176 #endif
1177 
1178 	DPRINTF(("%s:ises_process: start (crp = %p)\n", dv, crp));
1179 
1180 	s = splnet();
1181 	if (sc->sc_nqueue == ISES_MAX_NQUEUE) {
1182 		splx(s);
1183 		goto memerr;
1184 	}
1185 	splx(s);
1186 
1187 	q = (struct ises_q *)malloc(sizeof(struct ises_q), M_DEVBUF, M_NOWAIT);
1188 	if (q == NULL)
1189 		goto memerr;
1190 	bzero(q, sizeof(struct ises_q));
1191 
1192 	q->q_sesn = ISES_SESSION(crp->crp_sid);
1193 	ses = &sc->sc_sessions[q->q_sesn];
1194 
1195 	DPRINTF(("%s:ises_process: session %d selected\n", dv, q->q_sesn));
1196 
1197 	q->q_sc = sc;
1198 	q->q_crp = crp;
1199 
1200 	if (crp->crp_flags & CRYPTO_F_IMBUF) {
1201 		q->q_src.mbuf = (struct mbuf *)crp->crp_buf;
1202 		q->q_dst.mbuf = (struct mbuf *)crp->crp_buf;
1203 	} else if (crp->crp_flags & CRYPTO_F_IOV) {
1204 		q->q_src.uio = (struct uio *)crp->crp_buf;
1205 		q->q_dst.uio = (struct uio *)crp->crp_buf;
1206 	} else {
1207 		/* XXX for now... */
1208 		goto errout;
1209 	}
1210 
1211 	/*
1212 	 * Check if the crypto descriptors are sane. We accept:
1213 	 * - just one crd; either auth or crypto
1214 	 * - two crds; must be one auth and one crypto, although now
1215 	 *   for encryption we only want the first to be crypto, while
1216 	 *   for decryption the second one should be crypto.
1217 	 */
1218 	maccrd = enccrd = NULL;
1219 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1220 		switch (crd->crd_alg) {
1221 		case CRYPTO_MD5_HMAC:
1222 		case CRYPTO_SHA1_HMAC:
1223 		case CRYPTO_RIPEMD160_HMAC:
1224 			if (maccrd || (enccrd &&
1225 			    (enccrd->crd_flags & CRD_F_ENCRYPT) == 0))
1226 				goto errout;
1227 			maccrd = crd;
1228 			break;
1229 		case CRYPTO_DES_CBC:
1230 		case CRYPTO_3DES_CBC:
1231 			if (enccrd ||
1232 			    (maccrd && (crd->crd_flags & CRD_F_ENCRYPT)))
1233 				goto errout;
1234 			enccrd = crd;
1235 			break;
1236 		default:
1237 			goto errout;
1238 		}
1239 	}
1240 	if (!maccrd && !enccrd)
1241 		goto errout;
1242 
1243 	DPRINTF(("%s:ises_process: enc=%p mac=%p\n", dv, enccrd, maccrd));
1244 
1245 	/* Select data path through B-interface. */
1246 	q->q_session.omr |= ISES_SELR_BCHU_DIS;
1247 
1248 	if (enccrd) {
1249 		encoffset = enccrd->crd_skip;
1250 
1251 		/* Select algorithm */
1252 		if (enccrd->crd_alg == CRYPTO_3DES_CBC)
1253 			q->q_session.omr |= ISES_SOMR_BOMR_3DES;
1254 		else
1255 			q->q_session.omr |= ISES_SOMR_BOMR_DES;
1256 
1257 		/* Set CBC mode */
1258 		q->q_session.omr |= ISES_SOMR_FMR_CBC;
1259 
1260 		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
1261 			/* Set encryption bit */
1262 			q->q_session.omr |= ISES_SOMR_EDR;
1263 
1264 			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1265 				bcopy(enccrd->crd_iv, q->q_session.sccr, 8);
1266 			else {
1267 				q->q_session.sccr[0] = ses->sccr[0];
1268 				q->q_session.sccr[1] = ses->sccr[1];
1269 			}
1270 
1271 			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
1272 				if (crp->crp_flags & CRYPTO_F_IMBUF)
1273 					m_copyback(q->q_src.mbuf,
1274 					    enccrd->crd_inject, 8,
1275 					    (caddr_t)q->q_session.sccr);
1276 				else if (crp->crp_flags & CRYPTO_F_IOV)
1277 					cuio_copyback(q->q_src.uio,
1278 					    enccrd->crd_inject, 8,
1279 					    (caddr_t)q->q_session.sccr);
1280 				/* XXX else ... */
1281 			}
1282 		} else {
1283 			/* Clear encryption bit == decrypt mode */
1284 			q->q_session.omr &= ~ISES_SOMR_EDR;
1285 
1286 			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1287 				bcopy(enccrd->crd_iv, q->q_session.sccr, 8);
1288 			else if (crp->crp_flags & CRYPTO_F_IMBUF)
1289 				m_copydata(q->q_src.mbuf, enccrd->crd_inject,
1290 				    8, (caddr_t)q->q_session.sccr);
1291 			else if (crp->crp_flags & CRYPTO_F_IOV)
1292 				cuio_copydata(q->q_src.uio,
1293 				    enccrd->crd_inject, 8,
1294 				    (caddr_t)q->q_session.sccr);
1295 			/* XXX else ... */
1296 		}
1297 
1298 		q->q_session.kr[0] = ses->kr[0];
1299 		q->q_session.kr[1] = ses->kr[1];
1300 		q->q_session.kr[2] = ses->kr[2];
1301 		q->q_session.kr[3] = ses->kr[3];
1302 		q->q_session.kr[4] = ses->kr[4];
1303 		q->q_session.kr[5] = ses->kr[5];
1304 
1305 		SWAP32(q->q_session.sccr[0]);
1306 		SWAP32(q->q_session.sccr[1]);
1307 	}
1308 
1309 	if (maccrd) {
1310 		macoffset = maccrd->crd_skip;
1311 
1312 		/* Select algorithm */
1313 		switch (crd->crd_alg) {
1314 		case CRYPTO_MD5_HMAC:
1315 			q->q_session.omr |= ISES_HOMR_HFR_MD5;
1316 			break;
1317 		case CRYPTO_SHA1_HMAC:
1318 			q->q_session.omr |= ISES_HOMR_HFR_SHA1;
1319 			break;
1320 		case CRYPTO_RIPEMD160_HMAC:
1321 		default:
1322 			q->q_session.omr |= ISES_HOMR_HFR_RMD160;
1323 			break;
1324 		}
1325 
1326 		q->q_session.cvr[0] = ses->cvr[0];
1327 		q->q_session.cvr[1] = ses->cvr[1];
1328 		q->q_session.cvr[2] = ses->cvr[2];
1329 		q->q_session.cvr[3] = ses->cvr[3];
1330 		q->q_session.cvr[4] = ses->cvr[4];
1331 	}
1332 
1333 	if (enccrd && maccrd) {
1334 		/* XXX Check if ises handles differing end of auth/enc etc */
1335 		/* XXX For now, assume not (same as ubsec). */
1336 		if (((encoffset + enccrd->crd_len) !=
1337 		    (macoffset + maccrd->crd_len)) ||
1338 		    (enccrd->crd_skip < maccrd->crd_skip)) {
1339 			goto errout;
1340 		}
1341 
1342 		sskip = maccrd->crd_skip;
1343 		cpskip = dskip = enccrd->crd_skip;
1344 		stheend = maccrd->crd_len;
1345 		dtheend = enccrd->crd_len;
1346 		coffset = cpskip - sskip;
1347 		cpoffset = cpskip + dtheend;
1348 		/* XXX DEBUG ? */
1349 	} else {
1350 		cpskip = dskip = sskip = macoffset + encoffset;
1351 		dtheend = enccrd ? enccrd->crd_len : maccrd->crd_len;
1352 		stheend = dtheend;
1353 		cpoffset = cpskip + dtheend;
1354 		coffset = 0;
1355 	}
1356 	q->q_offset = coffset >> 2;
1357 
1358 #if 0	/* XXX not sure about this, in bus_dma context */
1359 
1360 	if (crp->crp_flags & CRYPTO_F_IMBUF)
1361 		q->q_src_l = mbuf2pages(q->q_src.mbuf, &q->q_src_npa,
1362 		    q->q_src_packp, q->q_src_packl, 1, &nicealign);
1363 	else if (crp->crp_flags & CRYPTO_F_IOV)
1364 		q->q_src_l = iov2pages(q->q_src.uio, &q->q_src_npa,
1365 		    q->q_src_packp, q->q_src_packl, 1, &nicealign);
1366 	/* XXX else */
1367 
1368 	DPRINTF(("%s:ises_process: foo2pages called!\n", dv));
1369 
1370 	if (q->q_src_l == 0)
1371 		goto memerr;
1372 	else if (q->q_src_l > 0xfffc) {
1373 		err = EIO;
1374 		goto errout;
1375 	}
1376 
1377 	/* XXX ... */
1378 
1379 	if (enccrd == NULL && maccrd != NULL) {
1380 		/* XXX ... */
1381 	} else {
1382 		if (!nicealign && (crp->crp_flags & CRYPTO_F_IOV)) {
1383 			goto errout;
1384 		} else if (!nicealign && (crp->crp_flags & CRYPTO_F_IMBUF)) {
1385 			int totlen, len;
1386 			struct mbuf *m, *top, **mp;
1387 
1388 			totlen = q->q_dst_l = q->q_src_l;
1389 			if (q->q_src.mbuf->m_flags & M_PKTHDR) {
1390 				MGETHDR(m, M_DONTWAIT, MT_DATA);
1391 				M_DUP_PKTHDR(m, q->q_src.mbuf);
1392 				len = MHLEN;
1393 			} else {
1394 				MGET(m, M_DONTWAIT, MT_DATA);
1395 				len = MLEN;
1396 			}
1397 			if (m == NULL)
1398 				goto memerr;
1399 			if (totlen >= MINCLSIZE) {
1400 				MCLGET(m, M_DONTWAIT);
1401 				if (m->m_flags & M_EXT)
1402 					len = MCLBYTES;
1403 			}
1404 			m->m_len = len;
1405 			top = NULL;
1406 			mp = &top;
1407 
1408 			while (totlen > 0) {
1409 				if (top) {
1410 					MGET(m, M_DONTWAIT, MT_DATA);
1411 					if (m == NULL) {
1412 						m_freem(top);
1413 						goto memerr;
1414 					}
1415 					len = MLEN;
1416 				}
1417 				if (top && totlen >= MINCLSIZE) {
1418 					MCLGET(m, M_DONTWAIT);
1419 					if (m->m_flags & M_EXT)
1420 						len = MCLBYTES;
1421 				}
1422 				m->m_len = len = min(totlen, len);
1423 				totlen -= len;
1424 				*mp = m;
1425 
1426 				mp = &m->m_next;
1427 			}
1428 			q->q_dst.mbuf = top;
1429 #if notyet
1430 			ubsec_mcopy(q->q_src.mbuf, q->q_dst.mbuf, cpskip, cpoffset);
1431 #endif
1432 		} else
1433 			q->q_dst.mbuf = q->q_src.mbuf;
1434 
1435 #if 0
1436 		/* XXX ? */
1437 		q->q_dst_l = mbuf2pages(q->q_dst.mbuf, &q->q_dst_npa,
1438 		    &q->q_dst_packp, &q->q_dst_packl, 1, NULL);
1439 #endif
1440 	}
1441 
1442 #endif /* XXX */
1443 
1444 	DPRINTF(("%s:ises_process: queueing request\n", dv));
1445 
1446 	s = splnet();
1447 	SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next);
1448 	sc->sc_nqueue++;
1449 	splx(s);
1450 	ises_feed(sc);
1451 
1452 	return (0);
1453 
1454 memerr:
1455 	err = ENOMEM;
1456 	isesstats.nomem++;
1457 errout:
1458 	DPRINTF(("%s:ises_process: an error occurred, err=%d, q=%p\n", dv,
1459 		 err, q));
1460 
1461 	if (err == EINVAL)
1462 		isesstats.invalid++;
1463 
1464 	if (q) {
1465 		if (q->q_src.mbuf != q->q_dst.mbuf)
1466 			m_freem(q->q_dst.mbuf);
1467 		free(q, M_DEVBUF);
1468 	}
1469 	crp->crp_etype = err;
1470 	crypto_done(crp);
1471 	return (0);
1472 }
1473 
1474 void
ises_callback(struct ises_q * q)1475 ises_callback(struct ises_q *q)
1476 {
1477 	struct cryptop *crp = (struct cryptop *)q->q_crp;
1478 	struct cryptodesc *crd;
1479 	struct ises_softc *sc = q->q_sc;
1480 	u_int8_t *sccr;
1481 
1482 	if ((crp->crp_flags & CRYPTO_F_IMBUF) &&
1483 	    (q->q_src.mbuf != q->q_dst.mbuf)) {
1484 		m_freem(q->q_src.mbuf);
1485 		crp->crp_buf = (caddr_t)q->q_dst.mbuf;
1486 	}
1487 
1488 	if (q->q_session.omr & ISES_SOMR_EDR) {
1489 		/* Copy out IV after encryption. */
1490 		sccr = (u_int8_t *)&sc->sc_sessions[q->q_sesn].sccr;
1491 		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1492 			if (crd->crd_alg != CRYPTO_DES_CBC &&
1493 			    crd->crd_alg != CRYPTO_3DES_CBC)
1494 				continue;
1495 			if (crp->crp_flags & CRYPTO_F_IMBUF)
1496 				m_copydata((struct mbuf *)crp->crp_buf,
1497 				    crd->crd_skip + crd->crd_len - 8, 8, sccr);
1498 			else if (crp->crp_flags & CRYPTO_F_IOV)
1499 				cuio_copydata((struct uio *)crp->crp_buf,
1500 				    crd->crd_skip + crd->crd_len - 8, 8, sccr);
1501 		}
1502 	}
1503 
1504 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1505 		if (crd->crd_alg != CRYPTO_MD5_HMAC &&
1506 		    crd->crd_alg != CRYPTO_SHA1_HMAC &&
1507 		    crd->crd_alg != CRYPTO_RIPEMD160_HMAC)
1508 			continue;
1509 		if (crp->crp_flags & CRYPTO_F_IMBUF)
1510 			m_copyback((struct mbuf *)crp->crp_buf,
1511 			   crd->crd_inject, 12, (u_int8_t *)q->q_macbuf);
1512 		else if (crp->crp_flags & CRYPTO_F_IOV)
1513 			bcopy((u_int8_t *)q->q_macbuf, crp->crp_mac, 12);
1514 		/* XXX else ... */
1515 		break;
1516 	}
1517 
1518 	free(q, M_DEVBUF);
1519 	DPRINTF(("%s:ises_callback: calling crypto_done\n",
1520 	    sc->sc_dv.dv_xname));
1521 	crypto_done(crp);
1522 }
1523 
1524 /* Initilize the ISES hardware RNG, and set up timeouts. */
1525 void
ises_hrng_init(struct ises_softc * sc)1526 ises_hrng_init(struct ises_softc *sc)
1527 {
1528 	u_int32_t cmd, r;
1529 	int i;
1530 #ifdef ISESDEBUG
1531 	struct timeval tv1, tv2;
1532 #endif
1533 
1534 	/* Asking for random data will seed LFSR and start the RBG */
1535 	cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
1536 	r   = 8; /* 8 * 32 = 256 bits */
1537 
1538 	if (ises_queue_cmd(sc, cmd, &r, NULL))
1539 		return;
1540 
1541 	/* Wait until response arrives. */
1542 	for (i = 1000; i && READ_REG(sc, ISES_A_OQS) == 0; i--)
1543 		DELAY(10);
1544 
1545 	if (!READ_REG(sc, ISES_A_OQS))
1546 		return;
1547 
1548 	/* Drain cmd response and 8*32 bits data */
1549 	for (i = 0; i <= r; i++)
1550 		(void)READ_REG(sc, ISES_A_OQD);
1551 
1552 	/* ACK the response */
1553 	WRITE_REG(sc, ISES_A_OQS, 0);
1554 	DELAY(1);
1555 	printf(", %s rng active", sc->sc_dv.dv_xname);
1556 
1557 #ifdef ISESDEBUG
1558 	/* Benchmark the HRNG. */
1559 
1560 	/*
1561 	 * XXX These values gets surprisingly large. Docs state the
1562 	 * HNRG produces > 1 mbit/s of random data. The values I'm seeing
1563 	 * are much higher, ca 2.7-2.8 mbit/s. AFAICT the algorithm is sound.
1564 	 * Compiler optimization issues, perhaps?
1565 	 */
1566 
1567 #define ISES_WPR 250
1568 #define ISES_ROUNDS 100
1569 	cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
1570 	r = ISES_WPR;
1571 
1572 	/* Queue 100 cmds; each generate 250 32-bit words of rnd data. */
1573 	microtime(&tv1);
1574 	for (i = 0; i < ISES_ROUNDS; i++)
1575 		ises_queue_cmd(sc, cmd, &r, NULL);
1576 	for (i = 0; i < ISES_ROUNDS; i++) {
1577 		while (READ_REG(sc, ISES_A_OQS) == 0) ; /* Wait for response */
1578 
1579 		(void)READ_REG(sc, ISES_A_OQD);		/* read response */
1580 		for (r = ISES_WPR; r--;)
1581 			(void)READ_REG(sc, ISES_A_OQD);	/* read data */
1582 		WRITE_REG(sc, ISES_A_OQS, 0);		/* ACK resp */
1583 		DELAY(1); /* OQS needs 1us to decrement */
1584 	}
1585 	microtime(&tv2);
1586 
1587 	timersub(&tv2, &tv1, &tv1);
1588 	tv1.tv_usec += 1000000 * tv1.tv_sec;
1589 	printf(", %dKb/sec",
1590 	    ISES_WPR * ISES_ROUNDS * 32 / 1024 * 1000000 / tv1.tv_usec);
1591 #endif
1592 
1593 	timeout_set(&sc->sc_timeout, ises_hrng, sc);
1594 #ifndef ISES_HRNG_DISABLED
1595 	ises_hrng(sc); /* Call first update */
1596 #endif
1597 }
1598 
1599 /* Called by timeout (and once by ises_init_hrng()). */
1600 void
ises_hrng(void * v)1601 ises_hrng(void *v)
1602 {
1603 	/*
1604 	 * Throw a HRNG read random bits command on the command queue.
1605 	 * The normal loop will manage the result and add it to the pool.
1606 	 */
1607 	struct ises_softc *sc = v;
1608 	u_int32_t cmd, n;
1609 	extern int hz; /* from param.c */
1610 
1611 	timeout_add(&sc->sc_timeout, hz / ISESRNGIPS);
1612 
1613 	if (ises_assert_cmd_mode(sc) != 0)
1614 		return;
1615 
1616 	cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
1617 	n   = (ISESRNGBITS >> 5) & 0xff; /* ask for N 32 bit words */
1618 
1619 	ises_queue_cmd(sc, cmd, &n, NULL);
1620 }
1621 
1622 u_int32_t
ises_get_fwversion(struct ises_softc * sc)1623 ises_get_fwversion(struct ises_softc *sc)
1624 {
1625 	u_int32_t r;
1626 	int i;
1627 
1628 	r = ISES_MKCMD(ISES_CMD_CHIP_ID, 0);
1629 	WRITE_REG(sc, ISES_A_IQD, r);
1630 	WRITE_REG(sc, ISES_A_IQS, 0);
1631 
1632 	for (i = 100; i > 0 && READ_REG(sc, ISES_A_OQS) == 0; i--)
1633 		DELAY(1);
1634 
1635 	if (i < 1)
1636 		return (0); /* No response */
1637 
1638 	r = READ_REG(sc, ISES_A_OQD);
1639 
1640 	/* Check validity. On error drain reponse data. */
1641 	if (((r >> 16) & 0xff) != ISES_CMD_CHIP_ID ||
1642 	    ((r >> 24) & 0xff) != 3 || (r & ISES_RC_MASK) != ISES_RC_SUCCESS) {
1643 		if ((r & ISES_RC_MASK) == ISES_RC_SUCCESS)
1644 			for (i = ((r >> 24) & 0xff); i; i--)
1645 				(void)READ_REG(sc, ISES_A_OQD);
1646 		r = 0;
1647 		goto out;
1648 	}
1649 
1650 	r = READ_REG(sc, ISES_A_OQD); /* read version */
1651 	(void)READ_REG(sc, ISES_A_OQD); /* Discard 64bit "chip-id" */
1652 	(void)READ_REG(sc, ISES_A_OQD);
1653  out:
1654 	WRITE_REG(sc, ISES_A_OQS, 0); /* Ack the response */
1655 	DELAY(1);
1656 	return (r);
1657 }
1658 
1659 /*
1660  * ises_assert_cmd_mode() returns
1661  *   -1 for failure to go to cmd
1662  *    0 if mode already was cmd
1663  *   >0 if mode was other (WFC/WFR) but now is cmd (this has reset the queues)
1664  */
1665 int
ises_assert_cmd_mode(struct ises_softc * sc)1666 ises_assert_cmd_mode(struct ises_softc *sc)
1667 {
1668 	switch (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT))) {
1669 	case 0x0: /* Selftest. XXX This is a transient state. */
1670 		DELAY(1000000);
1671 		if (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0)
1672 			return (-1);
1673 		return (ises_assert_cmd_mode(sc));
1674 	case 0x1: /* Command mode */
1675 		return (0);
1676 	case 0x2: /* Waiting For Continue / WFC */
1677 		bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
1678 		    ISES_A_CTRL_CONTINUE);
1679 		DELAY(1);
1680 		return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ?
1681 		    1 : -1);
1682 	case 0x3: /* Waiting For Reset / WFR */
1683 		bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
1684 		    ISES_A_CTRL_RESET);
1685 		DELAY(1000000);
1686 		return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ?
1687 		    2 : -1);
1688 	default:
1689 		return (-1); /* Unknown mode */
1690 	}
1691 }
1692 
1693 int
ises_bchu_switch_session(struct ises_softc * sc,struct ises_session * ss,int new_session)1694 ises_bchu_switch_session (struct ises_softc *sc, struct ises_session *ss,
1695 			  int new_session)
1696 {
1697 	/* It appears that the BCHU_SWITCH_SESSION command is broken. */
1698 	/* We have to work around it. */
1699 
1700 	u_int32_t cmd;
1701 
1702 	/* Do we have enough in-queue space? Count cmds + data, 16bit words. */
1703 	if ((8 * 2 + sizeof (*ss) / 2) > READ_REG(sc, ISES_A_IQF))
1704 		return (0);
1705 
1706 	/* Mark 'switch' in progress. */
1707 	sc->sc_switching = new_session + 1;
1708 
1709 	/* Write the key. */
1710 	cmd = ISES_MKCMD(ISES_CMD_BW_KR0, 2);
1711 	ises_queue_cmd(sc, cmd, &ss->kr[4], NULL);
1712 	cmd = ISES_MKCMD(ISES_CMD_BW_KR1, 2);
1713 	ises_queue_cmd(sc, cmd, &ss->kr[2], NULL);
1714 	cmd = ISES_MKCMD(ISES_CMD_BW_KR2, 2);
1715 	ises_queue_cmd(sc, cmd, &ss->kr[0], NULL);
1716 
1717 	/* Write OMR - Operation Method Register, clears SCCR+CVR+DBCR+HMLR */
1718 	cmd = ISES_MKCMD(ISES_CMD_BW_OMR, 1);
1719 	ises_queue_cmd(sc, cmd, &ss->omr, NULL);
1720 
1721 	/* Write SCCR - Symmetric Crypto Chaining Register (IV) */
1722 	cmd = ISES_MKCMD(ISES_CMD_BW_SCCR, 2);
1723 	ises_queue_cmd(sc, cmd, &ss->sccr[0], NULL);
1724 
1725 	/* Write CVR - Chaining Variables Register (hash state) */
1726 	cmd = ISES_MKCMD(ISES_CMD_BW_CVR, 5);
1727 	ises_queue_cmd(sc, cmd, &ss->cvr[0], NULL);
1728 
1729 	/* Write DBCR - Data Block Count Register */
1730 	cmd = ISES_MKCMD(ISES_CMD_BW_DBCR, 2);
1731 	ises_queue_cmd(sc, cmd, &ss->dbcr[0], NULL);
1732 
1733 	/* Write HMLR - Hash Message Length Register - last cmd in switch */
1734 	cmd = ISES_MKCMD(ISES_CMD_BW_HMLR, 2);
1735 	ises_queue_cmd(sc, cmd, &ss->hmlr[0], ises_bchu_switch_final);
1736 
1737 	return (1);
1738 }
1739 
1740 u_int32_t
ises_bchu_switch_final(struct ises_softc * sc,struct ises_cmd * cmd)1741 ises_bchu_switch_final (struct ises_softc *sc, struct ises_cmd *cmd)
1742 {
1743 	/* Session switch is complete. */
1744 
1745 	DPRINTF(("%s:ises_bchu_switch_final: switch complete\n",
1746 	    sc->sc_dv.dv_xname));
1747 
1748 	sc->sc_cursession = sc->sc_switching - 1;
1749 	sc->sc_switching = 0;
1750 
1751 	/* Retry/restart feed. */
1752 	ises_feed(sc);
1753 
1754 	return (0);
1755 }
1756 
1757 /* XXX Currently unused. */
1758 void
ises_read_dma(struct ises_softc * sc)1759 ises_read_dma (struct ises_softc *sc)
1760 {
1761 	bus_dma_segment_t *ds = &sc->sc_dmamap->dm_segs[0];
1762 	u_int32_t dma_status;
1763 
1764 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
1765 	    sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1766 
1767 	WRITE_REG(sc, ISES_DMA_READ_START, ds->ds_addr);
1768 	WRITE_REG(sc, ISES_DMA_READ_START, ISES_DMA_RCOUNT(ds->ds_len));
1769 
1770 	dma_status = READ_REG(sc, ISES_DMA_STATUS);
1771 	dma_status |= ISES_DMA_CTRL_ILT | ISES_DMA_CTRL_WRITE;
1772 	WRITE_REG(sc, ISES_DMA_CTRL, dma_status);
1773 }
1774 
1775 #ifdef ISESDEBUG
1776 /*
1777  * Development code section below here.
1778  */
1779 
1780 void
ises_debug_init(struct ises_softc * sc)1781 ises_debug_init (struct ises_softc *sc)
1782 {
1783 	ises_sc = sc;
1784 	ises_db = 0;
1785 	timeout_set (&ises_db_timeout, ises_debug_loop, sc);
1786 	timeout_add (&ises_db_timeout, 100);
1787 	printf ("ises0: ISESDEBUG active (ises_sc = %p)\n", ises_sc);
1788 }
1789 
1790 void
ises_debug_2(void)1791 ises_debug_2 (void)
1792 {
1793 	timeout_set (&ises_db_timeout, ises_debug_loop, ises_sc);
1794 	timeout_add (&ises_db_timeout, 100);
1795 	printf ("ises0: another debug timeout scheduled!\n");
1796 }
1797 
1798 void
ises_debug_simple_cmd(struct ises_softc * sc,u_int32_t code,u_int32_t d)1799 ises_debug_simple_cmd (struct ises_softc *sc, u_int32_t code, u_int32_t d)
1800 {
1801 	u_int32_t cmd, data;
1802 
1803 	cmd = ISES_MKCMD(code, (d ? 1 : 0));
1804 	data = d;
1805 	ises_queue_cmd(sc, cmd, &d, NULL);
1806 }
1807 
1808 void
ises_debug_loop(void * v)1809 ises_debug_loop (void *v)
1810 {
1811 	struct ises_softc *sc = (struct ises_softc *)v;
1812 	struct ises_session ses;
1813 	u_int32_t cmd, stat;
1814 	int i;
1815 
1816 	if (ises_db)
1817 		printf ("ises0: ises_db = %d  sc = %p\n", ises_db, sc);
1818 
1819 	timeout_add (&ises_db_timeout, 300); /* Every 3 secs */
1820 
1821 	stat = READ_REG(sc, ISES_A_OQS);
1822 	cmd  = READ_REG(sc, ISES_A_IQS);
1823 	if (stat || cmd)
1824 		printf ("ises0: IQS=%d OQS=%d / IQF=%d OQF=%d\n",
1825 		    cmd, stat, READ_REG(sc, ISES_A_IQF),
1826 		    READ_REG(sc, ISES_A_OQF));
1827 
1828 	switch (ises_db) {
1829 	default:
1830 		/* 0 - do nothing (just loop) */
1831 		break;
1832 	case 1:
1833 		/* Just dump register info */
1834 		ises_showreg();
1835 		break;
1836 	case 2:
1837 		/* Reset LNAU 1 registers */
1838 		ises_debug_simple_cmd(sc, ISES_CMD_LRESET_1, 0);
1839 
1840 		/* Compute R = (141 * 5623) % 117 (R should be 51 (0x33)) */
1841 		ises_debug_simple_cmd(sc, ISES_CMD_LW_A_1, 141);
1842 		ises_debug_simple_cmd(sc, ISES_CMD_LW_B_1, 5623);
1843 		ises_debug_simple_cmd(sc, ISES_CMD_LW_N_1, 117);
1844 
1845 		/* Launch LNAU operation. */
1846 		ises_debug_simple_cmd(sc, ISES_CMD_LMULMOD_1, 0);
1847 		break;
1848 	case 3:
1849 		/* Read result LNAU_1 R register (should not be necessary) */
1850 		ises_debug_simple_cmd(sc, ISES_CMD_LUPLOAD_1, 0);
1851 		break;
1852 	case 4:
1853 		/* Print result */
1854 		printf ("LNAU_1 R length = %d\n", sc->sc_lnau1_rlen);
1855 		for (i = 0; i < sc->sc_lnau1_rlen; i++)
1856 			printf ("W%02d-[%08x]-(%u)\t%s", i, sc->sc_lnau1_r[i],
1857 			    sc->sc_lnau1_r[i], (i%4)==3 ? "\n" : "");
1858 		printf ("%s", (i%4) ? "\n" : "");
1859 		break;
1860 	case 5:
1861 		/* Crypto. */
1862 
1863 		/* Load BCHU session data */
1864 		bzero(&ses, sizeof ses);
1865 		ses.kr[0] = 0xD0;
1866 		ses.kr[1] = 0xD1;
1867 		ses.kr[2] = 0xD2;
1868 		ses.kr[3] = 0xD3;
1869 		ses.kr[4] = 0xD4;
1870 		ses.kr[5] = 0xD5;
1871 
1872 		/* cipher data out is hash in, SHA1, 3DES, encrypt, ECB */
1873 		ses.omr = ISES_SELR_BCHU_HISOF | ISES_HOMR_HFR_SHA1 |
1874 		    ISES_SOMR_BOMR_3DES | ISES_SOMR_EDR | ISES_SOMR_FMR_ECB;
1875 
1876 #if 1
1877 		printf ("Queueing home-cooked session switch\n");
1878 		ises_bchu_switch_session(sc, &ses, 0);
1879 #else /* switch session does not appear to work - it never returns */
1880 		printf ("Queueing BCHU session switch\n");
1881 		cmd = ISES_MKCMD(ISES_CMD_BSWITCH, sizeof ses / 4);
1882 		printf ("session is %d 32bit words (== 18 ?), cmd = [%08x]\n",
1883 			sizeof ses / 4, cmd);
1884 		ises_queue_cmd(sc, cmd, (u_int32_t *)&ses, NULL);
1885 #endif
1886 
1887 		break;
1888 	case 96:
1889 		printf ("Stopping HRNG data collection\n");
1890 		timeout_del(&sc->sc_timeout);
1891 		break;
1892 	case 97:
1893 		printf ("Restarting HRNG data collection\n");
1894 		if (!timeout_pending(&sc->sc_timeout))
1895 			timeout_add(&sc->sc_timeout, hz);
1896 		break;
1897 	case 98:
1898 		printf ("Resetting (wait >1s before cont.)\n");
1899 		stat = ISES_BO_STAT_HWRESET;
1900 		WRITE_REG(sc, ISES_BO_STAT, stat);
1901 		stat &= ~ISES_BO_STAT_HWRESET;
1902 		WRITE_REG(sc, ISES_BO_STAT, stat);
1903 		break;
1904 	case 99:
1905 		printf ("Resetting everything!\n");
1906 		if (timeout_pending(&sc->sc_timeout))
1907 			timeout_del(&sc->sc_timeout);
1908 		timeout_set(&sc->sc_timeout, ises_initstate, sc);
1909 		sc->sc_initstate = 0;
1910 		ises_initstate(sc);
1911 		break;
1912 	}
1913 
1914 	ises_db = 0;
1915 }
1916 
1917 void
ises_showreg(void)1918 ises_showreg (void)
1919 {
1920 	struct ises_softc *sc = ises_sc;
1921 	u_int32_t stat, cmd;
1922 
1923 	/* Board register */
1924 
1925 	printf ("Board register: ");
1926 	stat = READ_REG(sc, ISES_BO_STAT);
1927 
1928 	if (stat & ISES_BO_STAT_LOOP)
1929 		printf ("LoopMode ");
1930 	if (stat & ISES_BO_STAT_TAMPER)
1931 		printf ("Tamper ");
1932 	if (stat & ISES_BO_STAT_POWERDOWN)
1933 		printf ("PowerDown ");
1934 	if (stat & ISES_BO_STAT_ACONF)
1935 		printf ("16bitA-IF ");
1936 	if (stat & ISES_BO_STAT_HWRESET)
1937 		printf ("HWReset");
1938 	if (stat & ISES_BO_STAT_AIRQ)
1939 		printf ("A-IFintr");
1940 	printf("\n");
1941 
1942 	/* A interface */
1943 
1944 	printf ("A Interface STAT register: \n\tLNAU-[");
1945 	stat = READ_REG(sc, ISES_A_STAT);
1946 	if (stat & ISES_STAT_LNAU_MASKED)
1947 		printf ("masked");
1948 	else {
1949 		if (stat & ISES_STAT_LNAU_BUSY_1)
1950 			printf ("busy1 ");
1951 		if (stat & ISES_STAT_LNAU_ERR_1)
1952 			printf ("err1 ");
1953 		if (stat & ISES_STAT_LNAU_BUSY_2)
1954 			printf ("busy2 ");
1955 		if (stat & ISES_STAT_LNAU_ERR_2)
1956 			printf ("err2 ");
1957 	}
1958 	printf ("]\n\tBCHU-[");
1959 
1960 	if (stat & ISES_STAT_BCHU_MASKED)
1961 		printf ("masked");
1962 	else {
1963 		if (stat & ISES_STAT_BCHU_BUSY)
1964 			printf ("busy ");
1965 		if (stat & ISES_STAT_BCHU_ERR)
1966 			printf ("err ");
1967 		if (stat & ISES_STAT_BCHU_SCIF)
1968 			printf ("cr-inop ");
1969 		if (stat & ISES_STAT_BCHU_HIF)
1970 			printf ("ha-inop ");
1971 		if (stat & ISES_STAT_BCHU_DDB)
1972 			printf ("dscd-data ");
1973 		if (stat & ISES_STAT_BCHU_IRF)
1974 			printf ("inp-req ");
1975 		if (stat & ISES_STAT_BCHU_OAF)
1976 			printf ("out-avail ");
1977 		if (stat & ISES_STAT_BCHU_DIE)
1978 			printf ("inp-enabled ");
1979 		if (stat & ISES_STAT_BCHU_UE)
1980 			printf ("ififo-empty ");
1981 		if (stat & ISES_STAT_BCHU_IFE)
1982 			printf ("ififo-half ");
1983 		if (stat & ISES_STAT_BCHU_IFHE)
1984 			printf ("ififo-full ");
1985 		if (stat & ISES_STAT_BCHU_OFE)
1986 			printf ("ofifo-empty ");
1987 		if (stat & ISES_STAT_BCHU_OFHF)
1988 			printf ("ofifo-half ");
1989 		if (stat & ISES_STAT_BCHU_OFF)
1990 			printf ("ofifo-full ");
1991 	}
1992 	printf ("] \n\tmisc-[");
1993 
1994 	if (stat & ISES_STAT_HW_DA)
1995 		printf ("downloaded-appl ");
1996 	if (stat & ISES_STAT_HW_ACONF)
1997 		printf ("A-IF-conf ");
1998 	if (stat & ISES_STAT_SW_WFOQ)
1999 		printf ("OQ-wait ");
2000 	if (stat & ISES_STAT_SW_OQSINC)
2001 		printf ("OQS-increased ");
2002 	printf ("]\n\t");
2003 
2004 	if (stat & ISES_STAT_HW_DA)
2005 		printf ("SW-mode is \"%s\"",
2006 		    ises_sw_mode[ISES_STAT_SW_MODE(stat)]);
2007 	else
2008 		printf ("IDP-state is \"%s\"",
2009 		    ises_idp_state[ISES_STAT_IDP_STATE(stat)]);
2010 	printf ("\n");
2011 
2012 	printf ("\tOQS = %d  IQS = %d  OQF = %d  IQF = %d\n",
2013 	    READ_REG(sc, ISES_A_OQS), READ_REG(sc, ISES_A_IQS),
2014 	    READ_REG(sc, ISES_A_OQF), READ_REG(sc, ISES_A_IQF));
2015 
2016 	/* B interface */
2017 
2018 	printf ("B-interface status register contains [%08x]\n",
2019 	    READ_REG(sc, ISES_B_STAT));
2020 
2021 	/* DMA */
2022 
2023 	printf ("DMA read starts at 0x%x, length %d bytes\n",
2024 	    READ_REG(sc, ISES_DMA_READ_START),
2025 	    READ_REG(sc, ISES_DMA_READ_COUNT) >> 16);
2026 
2027 	printf ("DMA write starts at 0x%x, length %d bytes\n",
2028 	    READ_REG(sc, ISES_DMA_WRITE_START),
2029 	    READ_REG(sc, ISES_DMA_WRITE_COUNT) & 0x00ff);
2030 
2031 	stat = READ_REG(sc, ISES_DMA_STATUS);
2032 	printf ("DMA status register contains [%08x]\n", stat);
2033 
2034 	if (stat & ISES_DMA_CTRL_ILT)
2035 		printf (" -- Ignore latency timer\n");
2036 	if (stat & 0x0C000000)
2037 		printf (" -- PCI Read - multiple\n");
2038 	else if (stat & 0x08000000)
2039 		printf (" -- PCI Read - line\n");
2040 
2041 	if (stat & ISES_DMA_STATUS_R_RUN)
2042 		printf (" -- PCI Read running/incomplete\n");
2043 	else
2044 		printf (" -- PCI Read complete\n");
2045 	if (stat & ISES_DMA_STATUS_R_ERR)
2046 		printf (" -- PCI Read DMA Error\n");
2047 
2048 	if (stat & ISES_DMA_STATUS_W_RUN)
2049 		printf (" -- PCI Write running/incomplete\n");
2050 	else
2051 		printf (" -- PCI Write complete\n");
2052 	if (stat & ISES_DMA_STATUS_W_ERR)
2053 		printf (" -- PCI Write DMA Error\n");
2054 
2055 	/* OMR / HOMR / SOMR */
2056 
2057 	/*
2058 	 * All these means throwing a cmd on to the A-interface, and then
2059 	 * reading the result.
2060 	 *
2061 	 * Currently, put debug output in process_oqueue...
2062 	 */
2063 
2064 	printf ("Queueing Operation Method Register (OMR) READ cmd...\n");
2065 	cmd = ISES_MKCMD(ISES_CMD_BR_OMR, 0);
2066 	ises_queue_cmd(sc, cmd, NULL, NULL);
2067 }
2068 
2069 void
ises_debug_parse_omr(struct ises_softc * sc)2070 ises_debug_parse_omr (struct ises_softc *sc)
2071 {
2072 	u_int32_t omr = sc->sc_sessions[sc->sc_cursession].omr;
2073 
2074 	printf ("SELR : ");
2075 	if (omr & ISES_SELR_BCHU_EH)
2076 		printf ("cont-on-error ");
2077 	else
2078 		printf ("stop-on-error ");
2079 
2080 	if (omr & ISES_SELR_BCHU_HISOF)
2081 		printf ("HU-input-is-SCU-output ");
2082 
2083 	if (omr & ISES_SELR_BCHU_DIS)
2084 		printf ("data-interface-select=B ");
2085 	else
2086 		printf ("data-interface-select=DataIn/DataOut ");
2087 
2088 	printf ("\n");
2089 
2090 	printf ("HOMR : ");
2091 	if (omr & ISES_HOMR_HMTR)
2092 		printf ("expect-padded-hash-msg ");
2093 	else
2094 		printf ("expect-plaintext-hash-msg ");
2095 
2096 	printf ("ER=%d ", (omr & ISES_HOMR_ER) >> 20); /* ick */
2097 
2098 	printf ("HFR=");
2099 	switch (omr & ISES_HOMR_HFR) {
2100 	case ISES_HOMR_HFR_NOP:
2101 		printf ("inactive ");
2102 		break;
2103 	case ISES_HOMR_HFR_MD5:
2104 		printf ("MD5 ");
2105 		break;
2106 	case ISES_HOMR_HFR_RMD160:
2107 		printf ("RMD160 ");
2108 		break;
2109 	case ISES_HOMR_HFR_RMD128:
2110 		printf ("RMD128 ");
2111 		break;
2112 	case ISES_HOMR_HFR_SHA1:
2113 		printf ("SHA-1 ");
2114 		break;
2115 	default:
2116 		printf ("reserved! ");
2117 		break;
2118 	}
2119 	printf ("\nSOMR : ");
2120 
2121 	switch (omr & ISES_SOMR_BOMR) {
2122 	case ISES_SOMR_BOMR_NOP:
2123 		printf ("NOP ");
2124 		break;
2125 	case ISES_SOMR_BOMR_TRANSPARENT:
2126 		printf ("transparent ");
2127 		break;
2128 	case ISES_SOMR_BOMR_DES:
2129 		printf ("DES ");
2130 		break;
2131 	case ISES_SOMR_BOMR_3DES2:
2132 		printf ("3DES-2 ");
2133 		break;
2134 	case ISES_SOMR_BOMR_3DES:
2135 		printf ("3DES-3 ");
2136 		break;
2137 	default:
2138 		if (omr & ISES_SOMR_BOMR_SAFER)
2139 			printf ("SAFER ");
2140 		else
2141 			printf ("reserved! ");
2142 		break;
2143 	}
2144 
2145 	if (omr & ISES_SOMR_EDR)
2146 		printf ("mode=encrypt ");
2147 	else
2148 		printf ("mode=decrypt ");
2149 
2150 	switch (omr & ISES_SOMR_FMR) {
2151 	case ISES_SOMR_FMR_ECB:
2152 		printf ("ECB");
2153 		break;
2154 	case ISES_SOMR_FMR_CBC:
2155 		printf ("CBC");
2156 		break;
2157 	case ISES_SOMR_FMR_CFB64:
2158 		printf ("CFB64");
2159 		break;
2160 	case ISES_SOMR_FMR_OFB64:
2161 		printf ("OFB64");
2162 		break;
2163 	default:
2164 		/* Nada */
2165 	}
2166 	printf ("\n");
2167 }
2168 
2169 #endif /* ISESDEBUG */
2170