summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/ubsec.c137
-rw-r--r--sys/dev/pci/ubsecreg.h22
-rw-r--r--sys/dev/pci/ubsecvar.h23
3 files changed, 170 insertions, 12 deletions
diff --git a/sys/dev/pci/ubsec.c b/sys/dev/pci/ubsec.c
index 7ae5b94f5b4..5bee0a61135 100644
--- a/sys/dev/pci/ubsec.c
+++ b/sys/dev/pci/ubsec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ubsec.c,v 1.36 2001/01/11 18:56:50 deraadt Exp $ */
+/* $OpenBSD: ubsec.c,v 1.37 2001/01/29 00:39:20 jason Exp $ */
/*
* Copyright (c) 2000 Jason L. Wright (jason@thought.net)
@@ -87,6 +87,9 @@ int ubsec_process __P((struct cryptop *));
void ubsec_callback __P((struct ubsec_q *));
int ubsec_feed __P((struct ubsec_softc *));
void ubsec_mcopy __P((struct mbuf *, struct mbuf *, int, int));
+void ubsec_callback2 __P((struct ubsec_q2 *));
+int ubsec_feed2 __P((struct ubsec_softc *));
+void ubsec_rng __P((void *));
#define READ_REG(sc,r) \
bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (r))
@@ -131,13 +134,18 @@ ubsec_attach(parent, self, aux)
SIMPLEQ_INIT(&sc->sc_queue);
SIMPLEQ_INIT(&sc->sc_qchip);
+ SIMPLEQ_INIT(&sc->sc_queue2);
+ SIMPLEQ_INIT(&sc->sc_qchip2);
+ sc->sc_statmask = BS_STAT_MCR1_DONE | BS_STAT_DMAERR;
if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BLUESTEEL &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BLUESTEEL_5601) ||
(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM &&
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5805))
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5805)) {
+ sc->sc_statmask |= BS_STAT_MCR2_DONE;
sc->sc_5601 = 1;
-
+ }
+
cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
cmd |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, cmd);
@@ -190,6 +198,11 @@ ubsec_attach(parent, self, aux)
READ_REG(sc, BS_CTRL) | BS_CTRL_MCR1INT | BS_CTRL_DMAERR |
(sc->sc_5601 ? BS_CTRL_MCR2INT : 0));
+ if (sc->sc_5601) {
+ timeout_set(&sc->sc_rngto, ubsec_rng, sc);
+ timeout_add(&sc->sc_rngto, hz);
+ }
+
printf(": %s\n", intrstr);
}
@@ -200,12 +213,13 @@ ubsec_intr(arg)
struct ubsec_softc *sc = arg;
volatile u_int32_t stat, a;
struct ubsec_q *q;
+ struct ubsec_q2 *q2;
struct ubsec_mcr *mcr;
int npkts = 0, i;
stat = READ_REG(sc, BS_STAT);
- stat &= (BS_STAT_MCR1_DONE | BS_STAT_MCR2_DONE | BS_STAT_DMAERR);
+ stat &= sc->sc_statmask;
if (stat == 0)
return (0);
@@ -259,6 +273,19 @@ ubsec_intr(arg)
if (npkts > 1)
printf("intr: %d pkts\n", npkts);
#endif
+ ubsec_feed(sc);
+ }
+
+ if (sc->sc_5601 && (stat & BS_STAT_MCR2_DONE)) {
+ while (!SIMPLEQ_EMPTY(&sc->sc_qchip2)) {
+ q2 = SIMPLEQ_FIRST(&sc->sc_qchip2);
+
+ if ((q2->q_mcr->mcr_flags & UBS_MCR_DONE) == 0)
+ break;
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip2, q2, q_next);
+ ubsec_callback2(q2);
+ ubsec_feed2(sc);
+ }
}
if (stat & BS_STAT_DMAERR) {
@@ -266,10 +293,8 @@ ubsec_intr(arg)
printf("%s: dmaerr %s@%08x\n", sc->sc_dv.dv_xname,
(a & BS_ERR_READ) ? "read" : "write",
a & ~BS_ERR_READ);
- panic("to let theo see things");
}
- ubsec_feed(sc);
return (1);
}
@@ -549,7 +574,7 @@ ubsec_process(crp)
sc = ubsec_cd.cd_devs[card];
s = splnet();
- if (sc->sc_nqueue == UBS_MAX_NQUEUE) {
+ if (sc->sc_nqueue >= UBS_MAX_NQUEUE) {
splx(s);
err = ENOMEM;
goto errout;
@@ -1019,3 +1044,101 @@ ubsec_mcopy(srcm, dstm, hoffset, toffset)
}
}
}
+
+/*
+ * feed the key generator, must be called at splnet() or higher.
+ */
+int
+ubsec_feed2(sc)
+ struct ubsec_softc *sc;
+{
+ struct ubsec_q2 *q;
+
+ while (!SIMPLEQ_EMPTY(&sc->sc_queue2)) {
+ if (READ_REG(sc, BS_STAT) & BS_STAT_MCR2_FULL)
+ break;
+ q = SIMPLEQ_FIRST(&sc->sc_queue2);
+ WRITE_REG(sc, BS_MCR2, (u_int32_t)vtophys(q->q_mcr));
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_queue2, q, q_next);
+ --sc->sc_nqueue2;
+ SIMPLEQ_INSERT_TAIL(&sc->sc_qchip2, q, q_next);
+ }
+ return (0);
+}
+
+void
+ubsec_callback2(q)
+ struct ubsec_q2 *q;
+{
+ struct ubsec_keyctx *ctx = q->q_ctx;
+
+ switch (ctx->ctx_op) {
+ case UBS_CTXOP_RNGBYPASS: {
+ struct ubsec_rng *rng = q->q_private;
+ volatile u_int32_t *dat;
+ int i;
+
+ dat = rng->rng_buf;
+ for (i = 0; i < UBS_RNGBUFSZ; i++, dat++)
+ add_true_randomness(*dat);
+ free(rng, M_DEVBUF);
+ free(q, M_DEVBUF);
+ break;
+ }
+ default:
+ printf("%s: unknown ctx op: %x\n", ctx->ctx_op);
+ break;
+ }
+}
+
+void
+ubsec_rng(vsc)
+ void *vsc;
+{
+ struct ubsec_softc *sc = vsc;
+ struct ubsec_q2 *q;
+ struct ubsec_rng *rng;
+ int s;
+
+ s = splnet();
+ if (sc->sc_nqueue2 >= UBS_MAX_NQUEUE) {
+ splx(s);
+ goto out;
+ }
+ splx(s);
+
+ q = (struct ubsec_q2 *)malloc(sizeof(struct ubsec_q2), M_DEVBUF, M_NOWAIT);
+ if (q == NULL)
+ goto out;
+
+ rng = (struct ubsec_rng *)malloc(sizeof(struct ubsec_rng),
+ M_DEVBUF, M_NOWAIT);
+ if (rng == NULL) {
+ free(q, M_DEVBUF);
+ goto out;
+ }
+
+ q->q_mcr = &rng->rng_mcr;
+ q->q_ctx = &rng->rng_ctx;
+ q->q_private = rng;
+ q->q_sc = sc;
+
+ bzero(rng, sizeof(*rng));
+
+ rng->rng_mcr.mcr_pkts = 1;
+ rng->rng_mcr.mcr_cmdctxp = (u_int32_t)vtophys(&rng->rng_ctx);
+ rng->rng_ctx.rbp_len = sizeof(struct ubsec_rngbypass_ctx);
+ rng->rng_ctx.rbp_op = UBS_CTXOP_RNGBYPASS;
+ rng->rng_mcr.mcr_opktbuf.pb_addr = (u_int32_t)vtophys(&rng->rng_buf[0]);
+ rng->rng_mcr.mcr_opktbuf.pb_len = ((sizeof(u_int32_t) * UBS_RNGBUFSZ))
+ & UBS_PKTBUF_LEN;
+
+ s = splnet();
+ SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, q, q_next);
+ sc->sc_nqueue2++;
+ ubsec_feed2(sc);
+ splx(s);
+
+out:
+ timeout_add(&sc->sc_rngto, hz);
+}
diff --git a/sys/dev/pci/ubsecreg.h b/sys/dev/pci/ubsecreg.h
index b4b042c1620..59b90e9a4d1 100644
--- a/sys/dev/pci/ubsecreg.h
+++ b/sys/dev/pci/ubsecreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ubsecreg.h,v 1.7 2000/08/13 22:06:48 deraadt Exp $ */
+/* $OpenBSD: ubsecreg.h,v 1.8 2001/01/29 00:39:20 jason Exp $ */
/*
* Copyright (c) 2000 Theo de Raadt
@@ -120,3 +120,23 @@ struct ubsec_mcr_add {
#define UBS_MCR_DONE 0x0001 /* mcr has been processed */
#define UBS_MCR_ERROR 0x0002 /* error in processing */
#define UBS_MCR_ERRORCODE 0xff00 /* error type */
+
+struct ubsec_keyctx {
+ volatile u_int16_t ctx_len; /* command length */
+ volatile u_int16_t ctx_op; /* operation code */
+ volatile u_int8_t ctx_pad[60]; /* padding */
+};
+#define UBS_CTXOP_RNGBYPASS 0x41
+
+struct ubsec_rngbypass_ctx {
+ volatile u_int16_t rbp_len; /* command length, 64 */
+ volatile u_int16_t rbp_op; /* rng bypass, 0x41 */
+ volatile u_int8_t rbp_pad[60]; /* padding */
+};
+
+#define UBS_RNGBUFSZ 16
+struct ubsec_rng {
+ struct ubsec_mcr rng_mcr;
+ struct ubsec_rngbypass_ctx rng_ctx;
+ volatile u_int32_t rng_buf[UBS_RNGBUFSZ];
+};
diff --git a/sys/dev/pci/ubsecvar.h b/sys/dev/pci/ubsecvar.h
index f7a00d48bda..dc6c951de7e 100644
--- a/sys/dev/pci/ubsecvar.h
+++ b/sys/dev/pci/ubsecvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ubsecvar.h,v 1.11 2001/01/11 18:56:50 deraadt Exp $ */
+/* $OpenBSD: ubsecvar.h,v 1.12 2001/01/29 00:39:21 jason Exp $ */
/*
* Copyright (c) 2000 Theo de Raadt
@@ -34,12 +34,17 @@ struct ubsec_softc {
bus_space_tag_t sc_st; /* memory tag */
bus_dma_tag_t sc_dmat; /* dma tag */
int sc_5601; /* device is 5601 */
+ u_int32_t sc_statmask; /* interrupt status mask */
int32_t sc_cid; /* crypto tag */
- SIMPLEQ_HEAD(,ubsec_q) sc_queue; /* packet queue */
- int sc_nqueue; /* count enqueued */
- SIMPLEQ_HEAD(,ubsec_q) sc_qchip; /* on chip */
+ SIMPLEQ_HEAD(,ubsec_q) sc_queue; /* packet queue, mcr1 */
+ int sc_nqueue; /* count enqueued, mcr1 */
+ SIMPLEQ_HEAD(,ubsec_q) sc_qchip; /* on chip, mcr1 */
+ SIMPLEQ_HEAD(,ubsec_q2) sc_queue2; /* packet queue, mcr2 */
+ int sc_nqueue2; /* count enqueued, mcr2 */
+ SIMPLEQ_HEAD(,ubsec_q2) sc_qchip2; /* on chip, mcr2 */
int sc_nsessions; /* # of sessions */
struct ubsec_session *sc_sessions; /* sessions */
+ struct timeout sc_rngto; /* rng timeout */
};
struct ubsec_q {
@@ -64,6 +69,16 @@ struct ubsec_q {
int q_sesn;
};
+struct ubsec_q2 {
+ SIMPLEQ_ENTRY(ubsec_q2) q_next;
+ struct ubsec_softc *q_sc;
+ struct ubsec_mcr *q_mcr;
+ void *q_ctx;
+ struct ubsec_pktbuf q_srcpkt[MAX_SCATTER-1];
+ struct ubsec_pktbuf q_dstpkt[MAX_SCATTER-1];
+ void *q_private;
+};
+
struct ubsec_session {
u_int32_t ses_used;
u_int32_t ses_deskey[6]; /* 3DES key */