summaryrefslogtreecommitdiff
path: root/sys/dev/pci/ubsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/ubsec.c')
-rw-r--r--sys/dev/pci/ubsec.c160
1 files changed, 111 insertions, 49 deletions
diff --git a/sys/dev/pci/ubsec.c b/sys/dev/pci/ubsec.c
index 5bb90de78a2..692cf481be2 100644
--- a/sys/dev/pci/ubsec.c
+++ b/sys/dev/pci/ubsec.c
@@ -1,7 +1,8 @@
-/* $OpenBSD: ubsec.c,v 1.6 2000/06/10 05:09:37 deraadt Exp $ */
+/* $OpenBSD: ubsec.c,v 1.7 2000/06/12 19:50:35 deraadt Exp $ */
/*
* Copyright (c) 2000 Jason L. Wright (jason@thought.net)
+ * Copyright (c) 2000 Theo de Raadt (deraadt@openbsd.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -78,7 +79,7 @@ int ubsec_newsession __P((u_int32_t *, struct cryptoini *));
int ubsec_freesession __P((u_int64_t));
int ubsec_process __P((struct cryptop *));
void ubsec_callback __P((struct ubsec_softc *, struct ubsec_q *, u_int8_t *));
-int ubsec_crypto __P((struct ubsec_softc *, struct ubsec_q *q));
+int ubsec_feed __P((struct ubsec_softc *));
#define READ_REG(sc,r) \
bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (r))
@@ -100,6 +101,9 @@ ubsec_probe(parent, match, aux)
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BLUESTEEL &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BLUESTEEL_5601)
return (1);
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5805)
+ return (1);
return (0);
}
@@ -121,8 +125,10 @@ ubsec_attach(parent, self, aux)
SIMPLEQ_INIT(&sc->sc_qchip);
sc->sc_intrmask = BS_CTRL_MCR1INT | BS_CTRL_DMAERR;
- if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BLUESTEEL &&
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BLUESTEEL_5601) {
+ 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_BLUESTEEL &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BLUESTEEL_5601)) {
sc->sc_intrmask |= BS_CTRL_MCR2INT;
sc->sc_5601 = 1;
}
@@ -185,8 +191,9 @@ ubsec_intr(arg)
void *arg;
{
struct ubsec_softc *sc = arg;
- u_int32_t stat;
+ volatile u_int32_t stat, a;
struct ubsec_q *q;
+ int npkts = 0;
stat = READ_REG(sc, BS_STAT);
@@ -194,58 +201,56 @@ ubsec_intr(arg)
if (stat == 0)
return (0);
+ WRITE_REG(sc, BS_STAT, stat); /* IACK */
+
if (stat & BS_STAT_MCR1_DONE) {
- q = SIMPLEQ_FIRST(&sc->sc_qchip);
- SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip, q, q_next);
- if (q) {
- /* XXX must generate macbuf ... */
+ while (!SIMPLEQ_EMPTY(&sc->sc_qchip)) {
+ q = SIMPLEQ_FIRST(&sc->sc_qchip);
+ if ((q->q_mcr.mcr_flags & UBS_MCR_DONE) == 0)
+ break;
+ npkts++;
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip, q, q_next);
+#ifdef UBSEC_DEBUG
+ printf("intr: callback q %08x flags %04x\n", q,
+ q->q_mcr.mcr_flags);
+#endif
ubsec_callback(sc, q, NULL);
}
- }
-
-#if 0
- if (stat & BS_STAT_MCR2_DONE) {
- ...
- }
+#ifdef UBSEC_DEBUG
+ if (npkts > 1)
+ printf("intr: %d pkts\n", npkts);
#endif
-
- if (stat & BS_STAT_DMAERR) {
- printf("%s: dmaerr\n", sc->sc_dv.dv_xname);
}
- /* if MCR is non-full, put a new command in it */
- if ((stat & BS_STAT_MCR1_FULL) == 0) {
- if (!SIMPLEQ_EMPTY(&sc->sc_queue)) {
- q = SIMPLEQ_FIRST(&sc->sc_queue);
- SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, q, q_next);
- --sc->sc_nqueue;
- SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
- WRITE_REG(sc, BS_MCR1, (u_int32_t)vtophys(&q->q_mcr));
- }
+ if (stat & BS_STAT_DMAERR) {
+ a = READ_REG(sc, BS_ERR);
+ printf("%s: dmaerr %s@%08x\n", sc->sc_dv.dv_xname,
+ (a & BS_ERR_READ) ? "read" : "write",
+ a & ~BS_ERR_READ);
}
- WRITE_REG(sc, BS_STAT, stat);
+ ubsec_feed(sc);
return (1);
}
int
-ubsec_crypto(sc, q)
+ubsec_feed(sc)
struct ubsec_softc *sc;
- struct ubsec_q *q;
{
- int s;
- u_int32_t stat;
+ struct ubsec_q *q;
- s = splnet();
- stat = READ_REG(sc, BS_STAT);
- if ((stat & BS_STAT_MCR1_FULL) == 0) {
+ while (!SIMPLEQ_EMPTY(&sc->sc_queue)) {
+ if (READ_REG(sc, BS_STAT) & BS_STAT_MCR1_FULL)
+ break;
+ q = SIMPLEQ_FIRST(&sc->sc_queue);
WRITE_REG(sc, BS_MCR1, (u_int32_t)vtophys(&q->q_mcr));
+#ifdef UBSEC_DEBUG
+ printf("feed: q->chip %08x %08x\n", q, (u_int32_t)vtophys(&q->q_mcr));
+#endif
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, q, q_next);
+ --sc->sc_nqueue;
SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
- } else {
- SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next);
- sc->sc_nqueue++;
}
- splx(s);
return (0);
}
@@ -314,7 +319,7 @@ ubsec_process(crp)
struct cryptop *crp;
{
struct ubsec_q *q;
- int card, err, i, j;
+ int card, err, i, j, s;
struct ubsec_softc *sc;
struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
int encoffset = 0, macoffset = 0, sskip, dskip;
@@ -339,7 +344,8 @@ ubsec_process(crp)
}
bzero(q, sizeof(struct ubsec_q));
- q->q_mcr.mcr_flags = 1 & UBS_MCR_PACKETS;
+ q->q_mcr.mcr_pkts = 1;
+ q->q_mcr.mcr_flags = 0;
q->q_mcr.mcr_cmdctxp = vtophys(&q->q_ctx);
q->q_sc = sc;
q->q_crp = crp;
@@ -468,12 +474,18 @@ ubsec_process(crp)
struct mbuf *m, *top, **mp;
totlen = q->q_dst_l = q->q_src_l;
- MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (q->q_src_m->m_flags & M_PKTHDR) {
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ M_COPY_PKTHDR(m, q->q_src_m);
+ len = MHLEN;
+ } else {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ len = MLEN;
+ }
if (m == NULL) {
err = ENOMEM;
goto errout;
}
- len = MHLEN;
if (totlen >= MINCLSIZE) {
MCLGET(m, M_DONTWAIT);
if (m->m_flags & M_EXT)
@@ -510,10 +522,18 @@ ubsec_process(crp)
q->q_dst_l = mbuf2pages(q->q_dst_m, &q->q_dst_npa, q->q_dst_packp,
q->q_dst_packl, MAX_SCATTER, NULL);
- j = 0;
- for (i = 0; i < q->q_src_npa; i++) {
+ q->q_mcr.mcr_pktlen = q->q_dst_l - sskip;
+
+#ifdef UBSEC_DEBUG
+ printf("src skip: %d\n", sskip);
+#endif
+ for (i = j = 0; i < q->q_src_npa; i++) {
struct ubsec_pktbuf *pb;
+#ifdef UBSEC_DEBUG
+ printf(" src[%d->%d]: %d@%x\n", i, j,
+ q->q_src_packl[i], q->q_src_packp[i]);
+#endif
if (sskip) {
if (sskip >= q->q_src_packl[i]) {
sskip -= q->q_src_packl[i];
@@ -529,6 +549,9 @@ ubsec_process(crp)
else
pb = &q->q_srcpkt[j - 1];
+#ifdef UBSEC_DEBUG
+ printf(" pb v %08x p %08x\n", pb, vtophys(pb));
+#endif
pb->pb_addr = q->q_src_packp[i];
pb->pb_len = q->q_src_packl[i];
@@ -538,11 +561,29 @@ ubsec_process(crp)
pb->pb_next = vtophys(&q->q_srcpkt[j]);
j++;
}
+#ifdef UBSEC_DEBUG
+ printf(" buf[%x]: %d@%x -> %x\n", vtophys(&q->q_mcr),
+ q->q_mcr.mcr_ipktbuf.pb_len,
+ q->q_mcr.mcr_ipktbuf.pb_addr,
+ q->q_mcr.mcr_ipktbuf.pb_next);
+ for (i = 0; i < j - 1; i++) {
+ printf(" buf[%x]: %d@%x -> %x\n", vtophys(&q->q_srcpkt[i]),
+ q->q_srcpkt[i].pb_len,
+ q->q_srcpkt[i].pb_addr,
+ q->q_srcpkt[i].pb_next);
+ }
+#endif
- j = 0;
- for (i = 0; i < q->q_dst_npa; i++) {
+#ifdef UBSEC_DEBUG
+ printf("dst skip: %d\n", dskip);
+#endif
+ for (i = j = 0; i < q->q_dst_npa; i++) {
struct ubsec_pktbuf *pb;
+#ifdef UBSEC_DEBUG
+ printf(" dst[%d->%d]: %d@%x\n", i, j,
+ q->q_dst_packl[i], q->q_dst_packp[i]);
+#endif
if (dskip) {
if (dskip >= q->q_dst_packl[i]) {
dskip -= q->q_dst_packl[i];
@@ -558,6 +599,9 @@ ubsec_process(crp)
else
pb = &q->q_dstpkt[j - 1];
+#ifdef UBSEC_DEBUG
+ printf(" pb v %08x p %08x\n", pb, vtophys(pb));
+#endif
pb->pb_addr = q->q_dst_packp[i];
pb->pb_len = q->q_dst_packl[i];
@@ -567,9 +611,26 @@ ubsec_process(crp)
pb->pb_next = vtophys(&q->q_dstpkt[j]);
j++;
}
+#ifdef UBSEC_DEBUG
+ printf(" buf[%d, %x]: %d@%x -> %x\n", 0,
+ vtophys(&q->q_mcr),
+ q->q_mcr.mcr_opktbuf.pb_len,
+ q->q_mcr.mcr_opktbuf.pb_addr,
+ q->q_mcr.mcr_opktbuf.pb_next);
+ for (i = 0; i < j - 1; i++) {
+ printf(" buf[%d, %x]: %d@%x -> %x\n", i+1,
+ vtophys(&q->q_dstpkt[i]),
+ q->q_dstpkt[i].pb_len,
+ q->q_dstpkt[i].pb_addr,
+ q->q_dstpkt[i].pb_next);
+ }
+#endif
- /* queues it, or sends it to the chip */
- ubsec_crypto(sc, q);
+ s = splnet();
+ SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next);
+ sc->sc_nqueue++;
+ ubsec_feed(sc);
+ splx(s);
return (0);
errout:
@@ -598,6 +659,7 @@ ubsec_callback(sc, q, macbuf)
}
if (macbuf != NULL) {
+ printf("copying macbuf\n");
for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
if (crd->crd_alg != CRYPTO_MD5_HMAC96 &&
crd->crd_alg != CRYPTO_SHA1_HMAC96)