diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2009-03-27 13:31:31 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2009-03-27 13:31:31 +0000 |
commit | 7ecf0fa0e4e5306c76993619765601e117a70d72 (patch) | |
tree | 513ba43cf06040ce5be1090b28000a6232da271e /sys/dev | |
parent | dd0e74472f5a73374d15e266c574cd676c280728 (diff) |
Add support for the BCM5825 and the next-generation BCM5860, 5861,
5862 Broadcom CryptoNetX IPSec/SSL Security Processors. The 5825 is a
faster version of the already supported 5823, and the even faster 586x
series is a bit different and needed some more changes. The RNG
engine on the 586x is not supported yet but I hope to fix it soon...
ubsec0 at pci4 dev 0 function 0 "Broadcom 5862" rev 0x01: 3DES MD5 SHA1 AES PK, apic 10 int 10 (irq 11)
tested by phessler@ and me
ok deraadt@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/ubsec.c | 181 | ||||
-rw-r--r-- | sys/dev/pci/ubsecreg.h | 33 | ||||
-rw-r--r-- | sys/dev/pci/ubsecvar.h | 14 |
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 */ |