diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2002-07-21 19:08:27 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2002-07-21 19:08:27 +0000 |
commit | 9e04bf3168e8b2a3263b81b382f66632747a4fb7 (patch) | |
tree | e10d660167f6a61465d55c9bac772123da7c4ee3 | |
parent | 6d84cff3d1b9d5354e842c923b55c97b940c9b36 (diff) |
Deal with the fact that one of the 7811 revisions cannot correctly handle
burst writes (bridges may coalesce sequential writes into a burst) by
inserting a read (I know, icky!) in between sequential writes. Thanks
to sam@errno.com, GTGI, and Hifn for helping track this one down.
-rw-r--r-- | sys/dev/pci/hifn7751.c | 42 | ||||
-rw-r--r-- | sys/dev/pci/hifn7751reg.h | 7 | ||||
-rw-r--r-- | sys/dev/pci/hifn7751var.h | 27 |
3 files changed, 66 insertions, 10 deletions
diff --git a/sys/dev/pci/hifn7751.c b/sys/dev/pci/hifn7751.c index c5259d93a2e..51387d280f4 100644 --- a/sys/dev/pci/hifn7751.c +++ b/sys/dev/pci/hifn7751.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hifn7751.c,v 1.123 2002/07/16 21:27:39 jason Exp $ */ +/* $OpenBSD: hifn7751.c,v 1.124 2002/07/21 19:08:26 jason Exp $ */ /* * Invertex AEON / Hifn 7751 driver @@ -109,6 +109,7 @@ void hifn_rng(void *); void hifn_tick(void *); void hifn_abort(struct hifn_softc *); void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, int *); +void hifn_write_waw_4(struct hifn_softc *, int, bus_size_t, u_int32_t); struct hifn_stats hifnstats; @@ -193,6 +194,19 @@ hifn_attach(parent, self, aux) cmd &= 0xffff0000; pci_conf_write(sc->sc_pci_pc, sc->sc_pci_tag, HIFN_RETRY_TIMEOUT, cmd); + if (sc->sc_flags & HIFN_IS_7811) { + u_int32_t revid; + + READ_REG_1(sc, HIFN_1_REVID); + if (revid == 0x2) + sc->sc_flags |= HIFN_NO_BURSTWRITE; + } + + if (sc->sc_flags & HIFN_NO_BURSTWRITE) { + sc->sc_waw_lastgroup = -1; + sc->sc_waw_lastreg = 0xffffffff; + } + sc->sc_dmat = pa->pa_dmat; if (bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_dma), 1, sizeof(*sc->sc_dma), 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) { @@ -2279,3 +2293,29 @@ hifn_callback(sc, cmd, macbuf) free(cmd, M_DEVBUF); crypto_done(crp); } + +void +hifn_write_waw_4(sc, reggrp, reg, val) + struct hifn_softc *sc; + int reggrp; + bus_size_t reg; + u_int32_t val; +{ + /* + * 7811 PB3 rev/2 parts lock-up on burst writes to Group 0 + * and Group 1 registers; avoid conditions that could create + * burst writes by doing a read in between the writes. + */ + if (sc->sc_waw_lastgroup != reggrp) + goto chipit; + if (sc->sc_waw_lastreg == reg - 4) + bus_space_read_4(sc->sc_st1, sc->sc_sh1, HIFN_1_REVID); + +chipit: + sc->sc_waw_lastgroup = reggrp; + sc->sc_waw_lastreg = reg; + if (reggrp == 0) + bus_space_write_4(sc->sc_st0, sc->sc_sh0, reg, val); + else + bus_space_write_4(sc->sc_st1, sc->sc_sh1, reg, val); +} diff --git a/sys/dev/pci/hifn7751reg.h b/sys/dev/pci/hifn7751reg.h index 087062447df..cc515372a73 100644 --- a/sys/dev/pci/hifn7751reg.h +++ b/sys/dev/pci/hifn7751reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hifn7751reg.h,v 1.35 2002/04/08 17:49:42 jason Exp $ */ +/* $OpenBSD: hifn7751reg.h,v 1.36 2002/07/21 19:08:26 jason Exp $ */ /* * Invertex AEON / Hifn 7751 driver @@ -352,11 +352,6 @@ typedef struct hifn_desc { #define HIFN_UNLOCK_SECRET1 0xf4 #define HIFN_UNLOCK_SECRET2 0xfc -#define WRITE_REG_1(sc,reg,val) \ - bus_space_write_4((sc)->sc_st1, (sc)->sc_sh1, reg, val) -#define READ_REG_1(sc,reg) \ - bus_space_read_4((sc)->sc_st1, (sc)->sc_sh1, reg) - /********************************************************************* * Structs for board commands * diff --git a/sys/dev/pci/hifn7751var.h b/sys/dev/pci/hifn7751var.h index ec0bcd70bb6..6f672fe4330 100644 --- a/sys/dev/pci/hifn7751var.h +++ b/sys/dev/pci/hifn7751var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hifn7751var.h,v 1.42 2002/04/08 17:49:42 jason Exp $ */ +/* $OpenBSD: hifn7751var.h,v 1.43 2002/07/21 19:08:26 jason Exp $ */ /* * Invertex AEON / Hifn 7751 driver @@ -155,6 +155,7 @@ struct hifn_softc { #define HIFN_HAS_RNG 1 #define HIFN_HAS_PUBLIC 2 #define HIFN_IS_7811 4 +#define HIFN_NO_BURSTWRITE 8 struct timeout sc_rngto, sc_tickto; int sc_rngfirst; int sc_rnghz; @@ -162,12 +163,32 @@ struct hifn_softc { struct hifn_session sc_sessions[2048]; pci_chipset_tag_t sc_pci_pc; pcitag_t sc_pci_tag; + bus_size_t sc_waw_lastreg; + int sc_waw_lastgroup; }; -#define WRITE_REG_0(sc,reg,val) \ - bus_space_write_4((sc)->sc_st0, (sc)->sc_sh0, reg, val) +#define WRITE_REG_0(sc,reg,val) \ + do { \ + if (sc->sc_flags & HIFN_NO_BURSTWRITE) \ + hifn_write_waw_4((sc), 0, (reg), (val)); \ + else \ + bus_space_write_4((sc)->sc_st0, (sc)->sc_sh0, \ + (reg), (val)); \ + } while (0) + +#define WRITE_REG_1(sc,reg,val) \ + do { \ + if (sc->sc_flags & HIFN_NO_BURSTWRITE) \ + hifn_write_waw_4((sc), 1, (reg), (val)); \ + else \ + bus_space_write_4((sc)->sc_st1, (sc)->sc_sh1, \ + (reg), (val)); \ + } while (0) + #define READ_REG_0(sc,reg) \ bus_space_read_4((sc)->sc_st0, (sc)->sc_sh0, reg) +#define READ_REG_1(sc,reg) \ + bus_space_read_4((sc)->sc_st1, (sc)->sc_sh1, reg) /* * hifn_command_t |