summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/ubsec.c181
-rw-r--r--sys/dev/pci/ubsecreg.h33
-rw-r--r--sys/dev/pci/ubsecvar.h14
3 files changed, 192 insertions, 36 deletions
diff --git a/sys/dev/pci/ubsec.c b/sys/dev/pci/ubsec.c
index 5abc71c7c30..a53469ce500 100644
--- a/sys/dev/pci/ubsec.c
+++ b/sys/dev/pci/ubsec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ubsec.c,v 1.142 2009/03/25 12:17:30 reyk Exp $ */
+/* $OpenBSD: ubsec.c,v 1.143 2009/03/27 13:31:30 reyk Exp $ */
/*
* Copyright (c) 2000 Jason L. Wright (jason@thought.net)
@@ -90,6 +90,7 @@ void ubsec_feed(struct ubsec_softc *);
void ubsec_mcopy(struct mbuf *, struct mbuf *, int, int);
void ubsec_callback2(struct ubsec_softc *, struct ubsec_q2 *);
void ubsec_feed2(struct ubsec_softc *);
+void ubsec_feed4(struct ubsec_softc *);
void ubsec_rng(void *);
int ubsec_dma_malloc(struct ubsec_softc *, bus_size_t,
struct ubsec_dma_alloc *, int);
@@ -133,6 +134,10 @@ const struct pci_matchid ubsec_devices[] = {
{ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5821 },
{ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5822 },
{ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5823 },
+ { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5825 },
+ { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5860 },
+ { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5861 },
+ { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5862 },
{ PCI_VENDOR_SUN, PCI_PRODUCT_SUN_SCA1K },
{ PCI_VENDOR_SUN, PCI_PRODUCT_SUN_5821 },
};
@@ -151,6 +156,7 @@ ubsec_attach(struct device *parent, struct device *self, void *aux)
struct pci_attach_args *pa = aux;
pci_chipset_tag_t pc = pa->pa_pc;
pci_intr_handle_t ih;
+ pcireg_t memtype;
const char *intrstr = NULL;
struct ubsec_dma *dmap;
bus_size_t iosize;
@@ -163,8 +169,11 @@ ubsec_attach(struct device *parent, struct device *self, void *aux)
SIMPLEQ_INIT(&sc->sc_queue2);
SIMPLEQ_INIT(&sc->sc_qchip2);
SIMPLEQ_INIT(&sc->sc_q2free);
+ SIMPLEQ_INIT(&sc->sc_queue4);
+ SIMPLEQ_INIT(&sc->sc_qchip4);
sc->sc_statmask = BS_STAT_MCR1_DONE | BS_STAT_DMAERR;
+ sc->sc_maxaggr = UBS_MIN_AGGR;
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BLUESTEEL &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BLUESTEEL_5601)
@@ -177,15 +186,10 @@ ubsec_attach(struct device *parent, struct device *self, void *aux)
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM &&
(PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5820 ||
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5822 ||
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5823))
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5822))
sc->sc_flags |= UBS_FLAGS_KEY | UBS_FLAGS_RNG |
UBS_FLAGS_LONGCTX | UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY;
- if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM &&
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5823)
- sc->sc_flags |= UBS_FLAGS_AES;
-
if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5821) ||
(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN &&
@@ -197,7 +201,32 @@ ubsec_attach(struct device *parent, struct device *self, void *aux)
UBS_FLAGS_LONGCTX | UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY;
}
- if (pci_mapreg_map(pa, BS_BAR, PCI_MAPREG_TYPE_MEM, 0,
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM &&
+ (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5823 ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5825))
+ sc->sc_flags |= UBS_FLAGS_KEY | UBS_FLAGS_RNG |
+ UBS_FLAGS_LONGCTX | UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY |
+ UBS_FLAGS_AES;
+
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM &&
+ (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5860 ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5861 ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_5862)) {
+ sc->sc_maxaggr = UBS_MAX_AGGR;
+ sc->sc_statmask |=
+ BS_STAT_MCR1_ALLEMPTY | BS_STAT_MCR2_ALLEMPTY |
+ BS_STAT_MCR3_ALLEMPTY | BS_STAT_MCR4_ALLEMPTY;
+ sc->sc_flags |= UBS_FLAGS_MULTIMCR | UBS_FLAGS_HWNORM |
+ UBS_FLAGS_LONGCTX | UBS_FLAGS_AES |
+ UBS_FLAGS_KEY | UBS_FLAGS_BIGKEY;
+#if 0
+ /* The RNG is not yet supported */
+ sc->sc_flags |= UBS_FLAGS_RNG | UBS_FLAGS_RNG4;
+#endif
+ }
+
+ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BS_BAR);
+ if (pci_mapreg_map(pa, BS_BAR, memtype, 0,
&sc->sc_st, &sc->sc_sh, NULL, &iosize, 0)) {
printf(": can't find mem space\n");
return;
@@ -285,7 +314,10 @@ ubsec_attach(struct device *parent, struct device *self, void *aux)
#ifndef UBSEC_NO_RNG
if (sc->sc_flags & UBS_FLAGS_RNG) {
- sc->sc_statmask |= BS_STAT_MCR2_DONE;
+ if (sc->sc_flags & UBS_FLAGS_RNG4)
+ sc->sc_statmask |= BS_STAT_MCR4_DONE;
+ else
+ sc->sc_statmask |= BS_STAT_MCR2_DONE;
if (ubsec_dma_malloc(sc, sizeof(struct ubsec_mcr),
&sc->sc_rng.rng_q.q_mcr, 0))
@@ -342,6 +374,7 @@ ubsec_intr(void *arg)
volatile u_int32_t stat;
struct ubsec_q *q;
struct ubsec_dma *dmap;
+ u_int16_t flags;
int npkts = 0, i;
stat = READ_REG(sc, BS_STAT);
@@ -404,7 +437,13 @@ ubsec_intr(void *arg)
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
mcr = (struct ubsec_mcr *)q2->q_mcr.dma_vaddr;
- if ((mcr->mcr_flags & htole16(UBS_MCR_DONE)) == 0) {
+
+ /* A bug in new devices requires to swap this field */
+ if (sc->sc_flags & UBS_FLAGS_MULTIMCR)
+ flags = swap16(mcr->mcr_flags);
+ else
+ flags = mcr->mcr_flags;
+ if ((flags & htole16(UBS_MCR_DONE)) == 0) {
bus_dmamap_sync(sc->sc_dmat,
q2->q_mcr.dma_map, 0,
q2->q_mcr.dma_map->dm_mapsize,
@@ -421,6 +460,39 @@ ubsec_intr(void *arg)
ubsec_feed2(sc);
}
}
+ if ((sc->sc_flags & UBS_FLAGS_RNG4) && (stat & BS_STAT_MCR4_DONE)) {
+ struct ubsec_q2 *q2;
+ struct ubsec_mcr *mcr;
+
+ while (!SIMPLEQ_EMPTY(&sc->sc_qchip4)) {
+ q2 = SIMPLEQ_FIRST(&sc->sc_qchip4);
+
+ bus_dmamap_sync(sc->sc_dmat, q2->q_mcr.dma_map,
+ 0, q2->q_mcr.dma_map->dm_mapsize,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+
+ mcr = (struct ubsec_mcr *)q2->q_mcr.dma_vaddr;
+
+ /* A bug in new devices requires to swap this field */
+ flags = swap16(mcr->mcr_flags);
+
+ if ((flags & htole16(UBS_MCR_DONE)) == 0) {
+ bus_dmamap_sync(sc->sc_dmat,
+ q2->q_mcr.dma_map, 0,
+ q2->q_mcr.dma_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ break;
+ }
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip4, q_next);
+ ubsec_callback2(sc, q2);
+ /*
+ * Don't send any more packet to chip if there has been
+ * a DMAERR.
+ */
+ if (!(stat & BS_STAT_DMAERR))
+ ubsec_feed4(sc);
+ }
+ }
/*
* Check to see if we got any DMA Error
@@ -456,8 +528,8 @@ ubsec_feed(struct ubsec_softc *sc)
u_int32_t stat;
npkts = sc->sc_nqueue;
- if (npkts > UBS_MAX_AGGR)
- npkts = UBS_MAX_AGGR;
+ if (npkts > sc->sc_maxaggr)
+ npkts = sc->sc_maxaggr;
if (npkts < 2)
goto feed1;
@@ -1461,6 +1533,33 @@ ubsec_feed2(struct ubsec_softc *sc)
}
/*
+ * feed the RNG (used instead of ubsec_feed2() on 5827+ devices)
+ */
+void
+ubsec_feed4(struct ubsec_softc *sc)
+{
+ struct ubsec_q2 *q;
+
+ while (!SIMPLEQ_EMPTY(&sc->sc_queue4)) {
+ if (READ_REG(sc, BS_STAT) & BS_STAT_MCR4_FULL)
+ break;
+ q = SIMPLEQ_FIRST(&sc->sc_queue4);
+
+ bus_dmamap_sync(sc->sc_dmat, q->q_mcr.dma_map, 0,
+ q->q_mcr.dma_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sc_dmat, q->q_ctx.dma_map, 0,
+ q->q_ctx.dma_map->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
+
+ WRITE_REG(sc, BS_MCR4, q->q_mcr.dma_paddr);
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_queue4, q_next);
+ --sc->sc_nqueue4;
+ SIMPLEQ_INSERT_TAIL(&sc->sc_qchip4, q, q_next);
+ }
+}
+
+/*
* Callback for handling random numbers
*/
void
@@ -1575,15 +1674,20 @@ ubsec_rng(void *vsc)
struct ubsec_q2_rng *rng = &sc->sc_rng;
struct ubsec_mcr *mcr;
struct ubsec_ctx_rngbypass *ctx;
- int s;
+ int s, *nqueue;
s = splnet();
if (rng->rng_used) {
splx(s);
return;
}
- sc->sc_nqueue2++;
- if (sc->sc_nqueue2 >= UBS_MAX_NQUEUE)
+ if (sc->sc_flags & UBS_FLAGS_RNG4)
+ nqueue = &sc->sc_nqueue4;
+ else
+ nqueue = &sc->sc_nqueue2;
+
+ (*nqueue)++;
+ if (*nqueue >= UBS_MAX_NQUEUE)
goto out;
mcr = (struct ubsec_mcr *)rng->rng_q.q_mcr.dma_vaddr;
@@ -1607,9 +1711,15 @@ ubsec_rng(void *vsc)
bus_dmamap_sync(sc->sc_dmat, rng->rng_buf.dma_map, 0,
rng->rng_buf.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
- SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rng->rng_q, q_next);
- rng->rng_used = 1;
- ubsec_feed2(sc);
+ if (sc->sc_flags & UBS_FLAGS_RNG4) {
+ SIMPLEQ_INSERT_TAIL(&sc->sc_queue4, &rng->rng_q, q_next);
+ rng->rng_used = 1;
+ ubsec_feed4(sc);
+ } else {
+ SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rng->rng_q, q_next);
+ rng->rng_used = 1;
+ ubsec_feed2(sc);
+ }
splx(s);
return;
@@ -1618,7 +1728,7 @@ out:
/*
* Something weird happened, generate our own call back.
*/
- sc->sc_nqueue2--;
+ (*nqueue)--;
splx(s);
timeout_add(&sc->sc_rngto, sc->sc_rnghz);
}
@@ -1677,16 +1787,23 @@ ubsec_dma_free(struct ubsec_softc *sc, struct ubsec_dma_alloc *dma)
void
ubsec_reset_board(struct ubsec_softc *sc)
{
- volatile u_int32_t ctrl;
+ volatile u_int32_t ctrl;
- ctrl = READ_REG(sc, BS_CTRL);
- ctrl |= BS_CTRL_RESET;
- WRITE_REG(sc, BS_CTRL, ctrl);
+ /* Reset the device */
+ ctrl = READ_REG(sc, BS_CTRL);
+ ctrl |= BS_CTRL_RESET;
+ WRITE_REG(sc, BS_CTRL, ctrl);
+
+ /*
+ * Wait aprox. 30 PCI clocks = 900 ns = 0.9 us
+ */
+ DELAY(10);
- /*
- * Wait aprox. 30 PCI clocks = 900 ns = 0.9 us
- */
- DELAY(10);
+ /* Enable RNG and interrupts on newer devices */
+ if (sc->sc_flags & UBS_FLAGS_MULTIMCR) {
+ WRITE_REG(sc, BS_CFG, BS_CFG_RNG);
+ WRITE_REG(sc, BS_INT, BS_INT_DMAINT);
+ }
}
/*
@@ -1709,6 +1826,16 @@ ubsec_init_board(struct ubsec_softc *sc)
if (sc->sc_flags & UBS_FLAGS_HWNORM)
ctrl &= ~BS_CTRL_SWNORM;
+ if (sc->sc_flags & UBS_FLAGS_MULTIMCR) {
+ ctrl |= BS_CTRL_BSIZE240;
+ ctrl &= ~BS_CTRL_MCR3INT; /* MCR3 is reserved for SSL */
+
+ if (sc->sc_flags & UBS_FLAGS_RNG4)
+ ctrl |= BS_CTRL_MCR4INT;
+ else
+ ctrl &= ~BS_CTRL_MCR4INT;
+ }
+
WRITE_REG(sc, BS_CTRL, ctrl);
}
diff --git a/sys/dev/pci/ubsecreg.h b/sys/dev/pci/ubsecreg.h
index aa0c6f011a3..9e881f6b877 100644
--- a/sys/dev/pci/ubsecreg.h
+++ b/sys/dev/pci/ubsecreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ubsecreg.h,v 1.29 2009/03/25 12:17:30 reyk Exp $ */
+/* $OpenBSD: ubsecreg.h,v 1.30 2009/03/27 13:31:30 reyk Exp $ */
/*
* Copyright (c) 2000 Theo de Raadt
@@ -54,11 +54,15 @@
/*
* DMA Control & Status Registers (offset from BS_BAR)
*/
-#define BS_MCR1 0x00 /* DMA Master Command Record 1 */
-#define BS_CTRL 0x04 /* DMA Control */
-#define BS_STAT 0x08 /* DMA Status */
-#define BS_ERR 0x0c /* DMA Error Address */
-#define BS_MCR2 0x10 /* DMA Master Command Record 2 */
+#define BS_MCR1 0x0000 /* DMA Master Command Record 1 */
+#define BS_CTRL 0x0004 /* DMA Control */
+#define BS_STAT 0x0008 /* DMA Status */
+#define BS_ERR 0x000c /* DMA Error Address */
+#define BS_MCR2 0x0010 /* DMA Master Command Record 2 */
+#define BS_MCR3 0x0014 /* 5827+, DMA Master Command Record 3 */
+#define BS_MCR4 0x001c /* 5827+, DMA Master Command Record 4 */
+#define BS_CFG 0x0700 /* 5827+, Configuration Register */
+#define BS_INT 0x0f00 /* 5827+, Interrupt Register */
/* BS_CTRL - DMA Control */
#define BS_CTRL_RESET 0x80000000 /* hardware reset, 5805/5820 */
@@ -74,11 +78,14 @@
#define BS_CTRL_RNG_8 0x01000000 /* 1bit rn/eight slow clocks */
#define BS_CTRL_RNG_16 0x01800000 /* 1bit rn/16 slow clocks */
#define BS_CTRL_SWNORM 0x00400000 /* 582[01], sw normalization */
+#define BS_CTRL_MCR3INT 0x00400000 /* 5827+, intr for MCR3 */
+#define BS_CTRL_MCR4INT 0x00200000 /* 5827+, intr for MCR4 */
+#define BS_CTRL_BSIZE240 0x000f0000 /* 5827+, burst size 240 */
#define BS_CTRL_FRAG_M 0x0000ffff /* output fragment size mask */
#define BS_CTRL_LITTLE_ENDIAN (BS_CTRL_BE32 | BS_CTRL_BE64)
/* BS_STAT - DMA Status */
-#define BS_STAT_MCR1_BUSY 0x80000000 /* MCR1 is busy */
+#define BS_STAT_MCR_BUSY 0x80000000 /* MCR is busy */
#define BS_STAT_MCR1_FULL 0x40000000 /* MCR1 is full */
#define BS_STAT_MCR1_DONE 0x20000000 /* MCR1 is done */
#define BS_STAT_DMAERR 0x10000000 /* DMA error */
@@ -86,11 +93,23 @@
#define BS_STAT_MCR2_DONE 0x04000000 /* MCR2 is done */
#define BS_STAT_MCR1_ALLEMPTY 0x02000000 /* 5821, MCR1 is empty */
#define BS_STAT_MCR2_ALLEMPTY 0x01000000 /* 5821, MCR2 is empty */
+#define BS_STAT_MCR3_ALLEMPTY 0x00800000 /* 5827+, MCR3 is empty */
+#define BS_STAT_MCR4_ALLEMPTY 0x00400000 /* 5827+, MCR4 is empty */
+#define BS_STAT_MCR3_FULL 0x00080000 /* 5827+, MCR3 is full */
+#define BS_STAT_MCR3_DONE 0x00040000 /* 5827+, MCR3 is done */
+#define BS_STAT_MCR4_FULL 0x00020000 /* 5827+, MCR4 is full */
+#define BS_STAT_MCR4_DONE 0x00010000 /* 5827+, MCR4 is done */
/* BS_ERR - DMA Error Address */
#define BS_ERR_ADDR 0xfffffffc /* error address mask */
#define BS_ERR_READ 0x00000002 /* fault was on read */
+/* BS_CFG */
+#define BS_CFG_RNG 0x00000001 /* 5827+, enable RNG */
+
+/* BS_INT */
+#define BS_INT_DMAINT 0x80000000 /* 5827+, enable DMA intr */
+
/* DES/3DES */
struct ubsec_pktctx {
u_int32_t pc_deskey[6]; /* 3DES key */
diff --git a/sys/dev/pci/ubsecvar.h b/sys/dev/pci/ubsecvar.h
index 521c39e7d1d..6e3ae4c87f7 100644
--- a/sys/dev/pci/ubsecvar.h
+++ b/sys/dev/pci/ubsecvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ubsecvar.h,v 1.37 2009/03/25 12:17:30 reyk Exp $ */
+/* $OpenBSD: ubsecvar.h,v 1.38 2009/03/27 13:31:30 reyk Exp $ */
/*
* Copyright (c) 2000 Theo de Raadt
@@ -39,7 +39,11 @@
#define UBS_MAX_SCATTER 64 /* Maximum scatter/gather depth */
#ifndef UBS_MAX_AGGR
-#define UBS_MAX_AGGR 5 /* Maximum aggregation count */
+#define UBS_MAX_AGGR 17 /* Maximum aggregation count */
+#endif
+
+#ifndef UBS_MIN_AGGR
+#define UBS_MIN_AGGR 5 /* < 5827, Maximum aggregation count */
#endif
#define UBSEC_CARD(sid) (((sid) & 0xf0000000) >> 28)
@@ -131,6 +135,8 @@ struct ubsec_dma {
#define UBS_FLAGS_HWNORM 0x08 /* hardware normalization */
#define UBS_FLAGS_RNG 0x10 /* hardware rng */
#define UBS_FLAGS_AES 0x20 /* supports aes */
+#define UBS_FLAGS_MULTIMCR 0x40 /* 5827+ with 4 MCRs */
+#define UBS_FLAGS_RNG4 0x80 /* 5827+ RNG on MCR4 */
struct ubsec_q {
SIMPLEQ_ENTRY(ubsec_q) q_next;
@@ -158,6 +164,7 @@ struct ubsec_softc {
int sc_flags; /* device specific flags */
u_int32_t sc_statmask; /* interrupt status mask */
int32_t sc_cid; /* crypto tag */
+ int sc_maxaggr; /* max pkt aggregation */
SIMPLEQ_HEAD(,ubsec_q) sc_queue; /* packet queue, mcr1 */
int sc_nqueue; /* count enqueued, mcr1 */
SIMPLEQ_HEAD(,ubsec_q) sc_qchip; /* on chip, mcr1 */
@@ -165,6 +172,9 @@ struct ubsec_softc {
SIMPLEQ_HEAD(,ubsec_q2) sc_queue2; /* packet queue, mcr2 */
int sc_nqueue2; /* count enqueued, mcr2 */
SIMPLEQ_HEAD(,ubsec_q2) sc_qchip2; /* on chip, mcr2 */
+ SIMPLEQ_HEAD(,ubsec_q2) sc_queue4; /* packet queue, mcr4 */
+ int sc_nqueue4; /* count enqueued, mcr4 */
+ SIMPLEQ_HEAD(,ubsec_q2) sc_qchip4; /* on chip, mcr4 */
int sc_nsessions; /* # of sessions */
struct ubsec_session *sc_sessions; /* sessions */
struct timeout sc_rngto; /* rng timeout */