diff options
author | David Collins <davec@cvs.openbsd.org> | 2007-09-06 03:55:20 +0000 |
---|---|---|
committer | David Collins <davec@cvs.openbsd.org> | 2007-09-06 03:55:20 +0000 |
commit | f8c96ede7b0639506649e012452ecee7bf1f9be2 (patch) | |
tree | febe4382788142bf06dc9d20711f790a97a81d4e /sys | |
parent | 05ed5a77d91b39a2b7282cb779a045e879d72925 (diff) |
Add nvram read and validate functions. ok marco@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/qli_pci.c | 100 | ||||
-rw-r--r-- | sys/dev/pci/qlireg.h | 29 |
2 files changed, 125 insertions, 4 deletions
diff --git a/sys/dev/pci/qli_pci.c b/sys/dev/pci/qli_pci.c index 990aae3058e..0d5508dbdb9 100644 --- a/sys/dev/pci/qli_pci.c +++ b/sys/dev/pci/qli_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qli_pci.c,v 1.5 2007/09/05 22:39:15 marco Exp $ */ +/* $OpenBSD: qli_pci.c,v 1.6 2007/09/06 03:55:19 davec Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2007 David Collins <dave@davec.name> @@ -47,6 +47,7 @@ #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) /* #define QLI_DEBUG */ +#define QLI_DEBUG #ifdef QLI_DEBUG #define DPRINTF(x...) do { if (qli_debug) printf(x); } while(0) #define DNPRINTF(n,x...) do { if (qli_debug & n) printf(x); } while(0) @@ -135,6 +136,9 @@ void qli_pci_attach(struct device *, struct device *, void *); int qli_ioctl(struct device *, u_long, caddr_t); int qli_lock_sem(struct qli_softc *, u_int32_t, u_int32_t); void qli_unlock_sem(struct qli_softc *, u_int32_t); +void qli_eeprom_out(struct qli_softc *, u_int32_t); +u_int16_t qli_read_nvram(struct qli_softc *, u_int32_t); +int qli_validate_nvram(struct qli_softc *); int qli_lock_driver(struct qli_softc *); void qli_write(struct qli_softc *, volatile u_int32_t *, u_int32_t); u_int32_t qli_read(struct qli_softc *, volatile u_int32_t *); @@ -564,9 +568,99 @@ qli_lock_sem(struct qli_softc *sc, u_int32_t shift, u_int32_t mask) return (rv); } +void +qli_eeprom_out(struct qli_softc *sc, u_int32_t data) +{ + qli_write(sc, QLI_NVRAM(sc), data); + delay(1); +} + +u_int16_t +qli_read_nvram(struct qli_softc *sc, u_int32_t offset) +{ + int i; + u_int32_t s, mask, data; + u_int16_t val = 0; +#ifdef QLI_DEBUG + u_int32_t qli_debug_save = qli_debug; + + qli_debug = 0; +#endif /* QLI_DEBUG */ + + /* select chip */ + s = QLI_NVRAM_MASK | QLI_NVRAM_SELECT; + qli_eeprom_out(sc, s); + + /* start bit */ + qli_eeprom_out(sc, s | QLI_NVRAM_DATA_OUT); + qli_eeprom_out(sc, s | QLI_NVRAM_DATA_OUT | QLI_NVRAM_CLOCK); + qli_eeprom_out(sc, s | QLI_NVRAM_DATA_OUT); /* clock low */ + + /* send read command */ + mask = 1 << (QLI_NVRAM_NUM_CMD_BITS - 1); + for (i = 0; i < QLI_NVRAM_NUM_CMD_BITS; i++) { + data = ((QLI_NVRAM_CMD_READ << i) & mask) ? + QLI_NVRAM_DATA_OUT : 0; + + qli_eeprom_out(sc, s | data); + qli_eeprom_out(sc, s | data | QLI_NVRAM_CLOCK); + qli_eeprom_out(sc, s | data); + } + + /* send read address */ + mask = 1 << (QLI_NVRAM_NUM_ADDR_BITS(sc) - 1); + for (i = 0; i < QLI_NVRAM_NUM_ADDR_BITS(sc); i++) { + data = ((offset << i) & mask) ? QLI_NVRAM_DATA_OUT : 0; + qli_eeprom_out(sc, s | data); + qli_eeprom_out(sc, s | data | QLI_NVRAM_CLOCK); + qli_eeprom_out(sc, s | data); + } + + /* read data */ + for (i = 0; i < QLI_NVRAM_NUM_DATA_BITS; i++) { + qli_eeprom_out(sc, s | QLI_NVRAM_CLOCK); + qli_eeprom_out(sc, s); + data = (qli_read(sc, QLI_NVRAM(sc)) & QLI_NVRAM_DATA_IN) ? + 1 : 0; + val = (val << 1) | data; + } + + /* deselect chip */ + s = QLI_NVRAM_MASK; + qli_write(sc, QLI_NVRAM(sc), s); + +#ifdef QLI_DEBUG + qli_debug = qli_debug_save; +#endif /* QLI_DEBUG */ + + DNPRINTF(QLI_D_RW, "%s: qli_nvram_read 0x%x 0x%04x\n", DEVNAME(sc), + offset, val); + + return (val); +} + int -qli_start_firmware(struct qli_softc *sc) +qli_validate_nvram(struct qli_softc *sc) { + int i, rv = 1; + u_int16_t nvram_checksum = 0; + + DNPRINTF(QLI_D_MISC, "%s: qli_validate_nvram\n", DEVNAME(sc)); + + for (i = 0; i < QLI_NVRAM_SIZE(sc); i++) + nvram_checksum += qli_read_nvram(sc, i); + + DNPRINTF(QLI_D_MISC, "%s: nvram checksum 0x%04x\n", DEVNAME(sc), + nvram_checksum); + + if (nvram_checksum == 0) + rv = 0; + + return (rv); +} + +int +qli_start_firmware(struct qli_softc *sc) { int rv = 1, reset_required = 1, config_required = 0; int boot_required = 0, i; u_int32_t mbox[QLI_MBOX_SIZE], r; @@ -645,7 +739,7 @@ qli_start_firmware(struct qli_softc *sc) goto unlock_driver; } - if (0 /*qli_validate_nvram(sc)*/) { + if (qli_validate_nvram(sc)) { printf("%s: invalid NVRAM checksum. Flash your " "controller", DEVNAME(sc)); diff --git a/sys/dev/pci/qlireg.h b/sys/dev/pci/qlireg.h index 24ccbe54040..15f42a51f91 100644 --- a/sys/dev/pci/qlireg.h +++ b/sys/dev/pci/qlireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: qlireg.h,v 1.4 2007/09/05 22:39:15 marco Exp $ */ +/* $OpenBSD: qlireg.h,v 1.5 2007/09/06 03:55:19 davec Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * Copyright (c) 2007 David Collins <dave@davec.name> @@ -417,3 +417,30 @@ struct qli_reg { #define QLI_EXT_HW_CFG_DDR_DRIVE_STRENGTH_15MA (0x2000) #define QLI_EXT_HW_CFG_DDR_DRIVE_STRENGTH_18MA (0x4000) #define QLI_EXT_HW_CFG_DDR_DRIVE_STRENGTH_24MA (0x6000) + +/* nvram */ +#define QLI_NVRAM_MASK (0xf<<16) +#define QLI_NVRAM(s) (s->sc_ql4010 ? \ + &s->sc_reg->u1.isp4010.q10_nvram : \ + &s->sc_reg->u1.isp4022.q22_nvram) + +#define QLI_NVRAM_CLOCK (0x1<<0) +#define QLI_NVRAM_SELECT (0x1<<1) +#define QLI_NVRAM_DATA_OUT (0x1<<2) +#define QLI_NVRAM_DATA_IN (0x1<<3) + +#define QLI_NVRAM_SIZE_4010 (0x100) +#define QLI_NVRAM_SIZE_4022 (0x400) +#define QLI_NVRAM_SIZE(s) (s->sc_ql4010 ? \ + QLI_NVRAM_SIZE_4010 : QLI_NVRAM_SIZE_4022) + +#define QLI_NVRAM_NUM_CMD_BITS (0x2) +#define QLI_NVRAM_CMD_READ (0x2) + +#define QLI_NVRAM_NUM_ADDR_BITS_4010 (0x8) +#define QLI_NVRAM_NUM_ADDR_BITS_4022 (0xa) +#define QLI_NVRAM_NUM_ADDR_BITS(s) (s->sc_ql4010 ? \ + QLI_NVRAM_NUM_ADDR_BITS_4010 : \ + QLI_NVRAM_NUM_ADDR_BITS_4022) + +#define QLI_NVRAM_NUM_DATA_BITS (0x10) |