diff options
Diffstat (limited to 'sys/dev/pci/ubsec.c')
-rw-r--r-- | sys/dev/pci/ubsec.c | 147 |
1 files changed, 90 insertions, 57 deletions
diff --git a/sys/dev/pci/ubsec.c b/sys/dev/pci/ubsec.c index b0f938837f9..398358256d8 100644 --- a/sys/dev/pci/ubsec.c +++ b/sys/dev/pci/ubsec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ubsec.c,v 1.1 2000/05/18 01:25:19 jason Exp $ */ +/* $OpenBSD: ubsec.c,v 1.2 2000/06/02 22:42:08 deraadt Exp $ */ /* * Copyright (c) 2000 Jason L. Wright (jason@thought.net) @@ -102,12 +102,6 @@ #define UBSEC_SID(crd,ses) (((crd) << 28) | ((ses) & 0x7ff)) #define MAX_SCATTER 10 -struct ubsec_command { - struct mbuf *src_m; - struct mbuf *dst_m; - long private_data; -}; - struct ubsec_pktctx { u_int8_t pc_deskey[24]; /* 3DES key */ u_int8_t pc_hminner[20]; /* hmac inner state */ @@ -143,8 +137,8 @@ struct ubsec_mcr { #define UBS_MCR_ERROR 0x00020000 /* error in processing */ #define UBS_MCR_ERRORCODE 0xff000000 /* error type */ -struct ubsec_queue { - LIST_ENTRY(ubsec_queue) q_next; +struct ubsec_q { + SIMPLEQ_ENTRY(ubsec_q) q_next; struct ubsec_softc *q_sc; struct cryptop *q_crp; struct ubsec_mcr q_mcr; @@ -172,8 +166,9 @@ struct ubsec_softc { int sc_5601; /* device is 5601 */ int32_t sc_cid; /* crypto tag */ u_int32_t sc_intrmask; /* interrupt mask */ - LIST_HEAD(,ubsec_queue) sc_queue; /* packet queue */ + SIMPLEQ_HEAD(,ubsec_q) sc_queue; /* packet queue */ int sc_nqueue; /* count enqueued */ + SIMPLEQ_HEAD(,ubsec_q) sc_qchip; /* on chip */ }; /* @@ -194,7 +189,8 @@ int ubsec_intr __P((void *)); 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_command *, u_int8_t *)); +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_probe(parent, match, aux) @@ -227,7 +223,8 @@ ubsec_attach(parent, self, aux) bus_size_t iosize; u_int32_t cmd; - LIST_INIT(&sc->sc_queue); + SIMPLEQ_INIT(&sc->sc_queue); + SIMPLEQ_INIT(&sc->sc_qchip); sc->sc_intrmask = BS_CTRL_MCR1INT | BS_CTRL_DMAERR; if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BLUESTEEL && @@ -290,18 +287,63 @@ ubsec_attach(parent, self, aux) #define READ_REG(sc,r) \ bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (r)) +#define WRITE_REG(sc,reg,val) \ + bus_space_write_4((sc)->sc_st, (sc)->sc_sh, reg, val) + int ubsec_intr(arg) void *arg; { struct ubsec_softc *sc = arg; u_int32_t stat; + struct ubsec_q *q; - stat = READ_REG(sc, BS_STAT) & sc->sc_intrmask; - if (stat == 0) - return (stat); + stat = READ_REG(sc, BS_STAT); + + if (stat & BS_STAT_MCR1_DONE) { + SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip, q, q_next); + if (q) { + /* XXX must generate macbuf ... */ + ubsec_callback(sc, q, NULL); + } + } + + 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) { + SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, q, q_next); + --sc->sc_nqueue; + if (q) { + SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next); + WRITE_REG(sc, BS_MCR1, (u_int32_t)&q->q_mcr); + } + } - return (1); + return (stat ? 1 : 0); +} + +int +ubsec_crypto(sc, q) + struct ubsec_softc *sc; + struct ubsec_q *q; +{ + int s; + u_int32_t stat; + + s = splnet(); + stat = READ_REG(sc, BS_STAT); + if ((stat & BS_STAT_MCR1_FULL) == 0) { + WRITE_REG(sc, BS_MCR1, (u_int32_t)&q->q_mcr); + 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); } /* @@ -337,14 +379,12 @@ ubsec_newsession(sidp, cri) if (mac) return (EINVAL); mac = 1; - } - else if (c->cri_alg == CRYPTO_DES_CBC || + } else if (c->cri_alg == CRYPTO_DES_CBC || c->cri_alg == CRYPTO_3DES_CBC) { if (cry) return (EINVAL); cry = 1; - } - else + } else return (EINVAL); } if (mac == 0 && cry == 0) @@ -370,7 +410,7 @@ int ubsec_process(crp) struct cryptop *crp; { - struct ubsec_queue *q; + struct ubsec_q *q; int card, err, i; struct ubsec_softc *sc; struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; @@ -386,13 +426,13 @@ ubsec_process(crp) sc = ubsec_cd.cd_devs[card]; - q = (struct ubsec_queue *)malloc(sizeof(struct ubsec_queue), + q = (struct ubsec_q *)malloc(sizeof(struct ubsec_q), M_DEVBUF, M_NOWAIT); if (q == NULL) { err = ENOMEM; goto errout; } - bzero(q, sizeof(struct ubsec_queue)); + bzero(q, sizeof(struct ubsec_q)); q->q_mcr.mcr_flags = 1 & UBS_MCR_PACKETS; q->q_mcr.mcr_cmdctxp = vtophys(&q->q_ctx); @@ -402,8 +442,7 @@ ubsec_process(crp) if (crp->crp_flags & CRYPTO_F_IMBUF) { q->q_src_m = (struct mbuf *)crp->crp_buf; q->q_dst_m = (struct mbuf *)crp->crp_buf; - } - else { + } else { err = EINVAL; goto errout; /* XXX only handle mbufs right now */ } @@ -420,18 +459,15 @@ ubsec_process(crp) crd1->crd_alg == CRYPTO_SHA1_HMAC96) { maccrd = crd1; enccrd = NULL; - } - else if (crd1->crd_alg == CRYPTO_DES_CBC || + } else if (crd1->crd_alg == CRYPTO_DES_CBC || crd1->crd_alg == CRYPTO_3DES_CBC) { maccrd = NULL; enccrd = crd1; - } - else { + } else { err = EINVAL; goto errout; } - } - else { + } else { if ((crd1->crd_alg == CRYPTO_MD5_HMAC96 || crd1->crd_alg == CRYPTO_SHA1_HMAC96) && (crd2->crd_alg == CRYPTO_DES_CBC || @@ -439,16 +475,14 @@ ubsec_process(crp) ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) { maccrd = crd1; enccrd = crd2; - } - else if ((crd1->crd_alg == CRYPTO_DES_CBC || + } else if ((crd1->crd_alg == CRYPTO_DES_CBC || crd1->crd_alg == CRYPTO_3DES_CBC) && (crd2->crd_alg == CRYPTO_MD5_HMAC96 || crd2->crd_alg == CRYPTO_SHA1_HMAC96) && (crd1->crd_flags & CRD_F_ENCRYPT)) { enccrd = crd1; maccrd = crd2; - } - else { + } else { /* * We cannot order the ubsec as requested */ @@ -471,8 +505,7 @@ ubsec_process(crp) if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) m_copyback(q->q_src_m, enccrd->crd_inject, sizeof(q->q_ctx.pc_iv), q->q_ctx.pc_iv); - } - else { + } else { q->q_ctx.pc_flags |= UBS_PKTCTX_INBOUND; if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) @@ -488,14 +521,9 @@ ubsec_process(crp) bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[0], 8); bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[8], 8); bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[16], 8); - } - else + } else bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[0], 24); -#if 0 - cmd->crypt_header_skip = enccrd->crd_skip; - cmd->crypt_process_len = enccrd->crd_len; -#endif } if (maccrd) { @@ -508,10 +536,6 @@ ubsec_process(crp) bcopy(maccrd->crd_key, &q->q_ctx.pc_hminner[0], maccrd->crd_klen >> 3); -#if 0 - cmd->mac_header_skip = maccrd->crd_skip; - cmd->mac_process_len = maccrd->crd_len; -#endif } q->q_src_l = mbuf2pages(q->q_src_m, &q->q_src_npa, q->q_src_packp, @@ -562,13 +586,20 @@ ubsec_process(crp) mp = &m->m_next; } q->q_dst_m = top; - } - else + } else q->q_dst_m = q->q_src_m; q->q_dst_l = mbuf2pages(q->q_dst_m, &q->q_dst_npa, q->q_dst_packp, q->q_dst_packl, MAX_SCATTER, NULL); +#if 0 + /* XXX time to incorporate the information in crd_skip... */ + + cmd->crypt_header_skip = enccrd->crd_skip; + cmd->crypt_process_len = enccrd->crd_len; + cmd->mac_header_skip = maccrd->crd_skip; + cmd->mac_process_len = maccrd->crd_len; +#endif for (i = 0; i < q->q_src_npa; i++) { struct ubsec_pktbuf *pb; @@ -603,7 +634,9 @@ ubsec_process(crp) pb->pb_next = vtophys(&q->q_dstpkt[i]); } - err = ENOMEM; + /* queues it, or sends it to the chip */ + ubsec_crypto(sc, q); + return (0); errout: if (q != NULL) { @@ -617,17 +650,17 @@ errout: } void -ubsec_callback(sc, cmd, macbuf) +ubsec_callback(sc, q, macbuf) struct ubsec_softc *sc; - struct ubsec_command *cmd; + struct ubsec_q *q; u_int8_t *macbuf; { - struct cryptop *crp = (struct cryptop *)cmd->private_data; + struct cryptop *crp = (struct cryptop *)q->q_crp; struct cryptodesc *crd; - if ((crp->crp_flags & CRYPTO_F_IMBUF) && (cmd->src_m != cmd->dst_m)) { - m_freem(cmd->src_m); - crp->crp_buf = (caddr_t)cmd->dst_m; + if ((crp->crp_flags & CRYPTO_F_IMBUF) && (q->q_src_m != q->q_dst_m)) { + m_freem(q->q_src_m); + crp->crp_buf = (caddr_t)q->q_dst_m; } if (macbuf != NULL) { @@ -641,6 +674,6 @@ ubsec_callback(sc, cmd, macbuf) } } - free(cmd, M_DEVBUF); + free(q, M_DEVBUF); crp->crp_callback(crp); } |