diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-05-01 11:44:48 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-05-01 11:44:48 +0000 |
commit | 5f264daed90f5a6c3f817b973e83e4678ca1a91b (patch) | |
tree | f53adac27fd6e10747b918fdc4994cb5b0d6ab56 /sys/dev | |
parent | 868d765569987bf1d96fe6287713c34d48399de1 (diff) |
shuffle some code and add additional states in the reset path. use a
scheduled timeout to check for the boot process to finish in the reset
code instead of waiting for a loooong delay (still use the long delay
in the initial boot on attach because i cannot defer the
initialization there).
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_nx.c | 156 | ||||
-rw-r--r-- | sys/dev/pci/if_nxreg.h | 12 |
2 files changed, 108 insertions, 60 deletions
diff --git a/sys/dev/pci/if_nx.c b/sys/dev/pci/if_nx.c index 1968a8341f5..ddafe42cc9e 100644 --- a/sys/dev/pci/if_nx.c +++ b/sys/dev/pci/if_nx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nx.c,v 1.32 2007/05/01 11:33:40 reyk Exp $ */ +/* $OpenBSD: if_nx.c,v 1.33 2007/05/01 11:44:47 reyk Exp $ */ /* * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org> @@ -63,10 +63,11 @@ #include <dev/pci/if_nxreg.h> #ifdef NX_DEBUG -#define NXDBG_FLASH (1<<0) /* debug flash access through ROMUSB */ -#define NXDBG_WAIT (1<<1) /* poll registers */ +#define NXDBG_WAIT (1<<0) /* poll registers */ +#define NXDBG_FLASH (1<<1) /* debug flash access through ROMUSB */ #define NXDBG_CRBINIT (1<<2) /* SW register init from flash */ -#define NXDBG_ALL 0xffff /* enable all debugging messages */ +#define NXDBG_STATE (1<<3) /* Fimrware states */ +#define NXDBG_ALL 0xfffe /* enable nearly all debugging messages */ int nx_debug = 0; #define DPRINTF(_lvl, _arg...) do { \ if (nx_debug & (_lvl)) \ @@ -139,6 +140,9 @@ struct nxb_softc { struct nxb_port sc_nxp[NX_MAX_PORTS]; /* The nx ports */ int sc_nports; + + struct timeout sc_reload; + int sc_reloaded; }; struct nx_softc { @@ -157,6 +161,7 @@ int nxb_match(struct device *, void *, void *); void nxb_attach(struct device *, struct device *, void *); int nxb_query(struct nxb_softc *sc); int nxb_newstate(struct nxb_softc *, int); +void nxb_reload(void *); void nxb_mountroot(void *); int nxb_loadfirmware(struct nxb_softc *, struct nxb_firmware_header *, u_int8_t **, size_t *); @@ -310,6 +315,7 @@ nxb_attach(struct device *parent, struct device *self, void *aux) for (i = 0; i < sc->sc_nports; i++) config_found(&sc->sc_dev, &sc->sc_nxp[i], nx_print); + timeout_set(&sc->sc_reload, nxb_reload, sc); mountroothook_establish(nxb_mountroot, sc); return; @@ -521,6 +527,8 @@ nxb_newstate(struct nxb_softc *sc, int newstate) int oldstate = sc->sc_state; sc->sc_state = newstate; + DPRINTF(NXDBG_STATE, "%s(%s) state %d -> %d\n", + sc->sc_dev.dv_xname, __func__, oldstate, newstate); switch (newstate) { case NX_S_RESET: @@ -538,7 +546,7 @@ nxb_newstate(struct nxb_softc *sc, int newstate) break; case NX_S_LOADED: /* - * Wait for the device to become ready + * Initially wait for the device to become ready */ assert(oldstate == NX_S_BOOT); if (nxb_wait(sc, NXSW_CMDPEG_STATE, NXSW_CMDPEG_INIT_DONE, @@ -550,7 +558,24 @@ nxb_newstate(struct nxb_softc *sc, int newstate) return (-1); } break; + case NX_S_RELOADED: + /* + * Wait for the device to become ready + */ + assert(oldstate == NX_S_BOOT); + sc->sc_reloaded = 20; + timeout_add(&sc->sc_reload, hz); + break; case NX_S_READY: + /* XXX for state debugging */ + printf("%s: temperature 0x%08x\n", + sc->sc_dev.dv_xname, nxb_read(sc, NXSW_TEMP)); + break; + case NX_S_FAIL: + if (oldstate == NX_S_RELOADED) + printf("%s: failed to reset the firmware, " + "code 0x%x\n", sc->sc_dev.dv_xname, + nxb_read(sc, NXSW_CMDPEG_STATE)); break; default: /* no action */ @@ -581,17 +606,35 @@ nxb_mountroot(void *arg) sc->sc_fwmajor, sc->sc_fwminor, sc->sc_fwbuild); if (sc->sc_fwmajor != NX_FIRMWARE_MAJOR || sc->sc_fwminor != NX_FIRMWARE_MINOR) { - printf(", requires %u.%u.xx (%u.%u.%u)\n", + printf(", requires %u.%u.xx (%u.%u.%u)", NX_FIRMWARE_MAJOR, NX_FIRMWARE_MINOR, NX_FIRMWARE_MAJOR, NX_FIRMWARE_MINOR, NX_FIRMWARE_BUILD); - sc->sc_flags |= NXFLAG_FWINVALID; - nxb_newstate(sc, NX_S_RESET); - return; } printf("\n"); + nxb_newstate(sc, NX_S_RESET); +} + +void +nxb_reload(void *arg) +{ + struct nxb_softc *sc = (struct nxb_softc *)arg; + u_int32_t val; + + /* + * Check if the device is ready, other re-schedule or timeout + */ + val = nxb_read(sc, NXSW_CMDPEG_STATE); + if ((val & NXSW_CMDPEG_STATE_M) != NXSW_CMDPEG_INIT_DONE) { + if (!sc->sc_reloaded--) + nxb_newstate(sc, NX_S_FAIL); + else + timeout_add(&sc->sc_reload, hz); + return; + } + /* Firmware is ready for operation, allow interrupts etc. */ nxb_newstate(sc, NX_S_READY); } @@ -679,46 +722,6 @@ nxb_reset(struct nxb_softc *sc) u_int32_t *data, addr, val, ncrb; bus_size_t reg; - bzero(&fh, sizeof(fh)); - if (sc->sc_flags & NXFLAG_FWINVALID) { - if (nxb_loadfirmware(sc, &fh, &fw, &fwlen) != 0) { - printf("%s: failed to load firmware from disk\n", - sc->sc_dev.dv_xname); - goto fail; - } - } else { - if (nxb_reloadfirmware(sc, &fh, &fw, &fwlen) != 0) { - printf("%s: failed to reload firmware from flash\n", - sc->sc_dev.dv_xname); - goto fail; - } - } - - /* - * Validate the information found in the extra header - */ - val = ntohl(fh.fw_image_ver); - sc->sc_fwmajor = (val & NXB_IMAGE_MAJOR_M) >> NXB_IMAGE_MAJOR_S; - sc->sc_fwminor = (val & NXB_IMAGE_MINOR_M) >> NXB_IMAGE_MINOR_S; - sc->sc_fwbuild = (val & NXB_IMAGE_BUILD_M) >> NXB_IMAGE_BUILD_S; - if (sc->sc_flags & NXFLAG_FWINVALID) - printf("%s: using firmware %u.%u.%u\n", sc->sc_dev.dv_xname, - sc->sc_fwmajor, sc->sc_fwminor, sc->sc_fwbuild); - if (sc->sc_fwmajor != NX_FIRMWARE_MAJOR || - sc->sc_fwminor != NX_FIRMWARE_MINOR) { - printf("%s: unsupported firmware version\n", - sc->sc_dev.dv_xname); - goto fail; - } - - bootsz = ntohl(fh.fw_bootld_size); - imagesz = ntohl(fh.fw_image_size); - if ((imagesz + bootsz) != (fwlen - sizeof(fh)) || - (imagesz % 4) || (bootsz % 4)) { - printf("%s: invalid firmware image\n", sc->sc_dev.dv_xname); - goto fail; - } - /* * Reset the SW registers */ @@ -734,6 +737,7 @@ nxb_reset(struct nxb_softc *sc) if (ncrb == 0 || ncrb > NXFLASHMAP_CRBINIT_MAX) goto load; /* ignore CRBINIT and skip step */ +#if 0 /* 3. Write the CRBINIT are to PCI memory */ for (i = 0; i < ncrb; i++) { reg = i * 8; @@ -746,6 +750,7 @@ nxb_reset(struct nxb_softc *sc) if (nxb_writehw(sc, addr, val) != 0) goto fail1; } +#endif /* 4. Reset the Protocol Processing Engine */ nxb_write(sc, NXROMUSB_GLB_SW_RESET, @@ -771,6 +776,49 @@ nxb_reset(struct nxb_softc *sc) load: /* + * Load the firmware from disk or from flash + */ + bzero(&fh, sizeof(fh)); + if (sc->sc_flags & NXFLAG_FWINVALID) { + if (nxb_loadfirmware(sc, &fh, &fw, &fwlen) != 0) { + printf("%s: failed to load firmware from disk\n", + sc->sc_dev.dv_xname); + goto fail; + } + } else { + if (nxb_reloadfirmware(sc, &fh, &fw, &fwlen) != 0) { + printf("%s: failed to reload firmware from flash\n", + sc->sc_dev.dv_xname); + goto fail; + } + } + + /* + * Validate the information found in the extra header + */ + val = ntohl(fh.fw_image_ver); + sc->sc_fwmajor = (val & NXB_IMAGE_MAJOR_M) >> NXB_IMAGE_MAJOR_S; + sc->sc_fwminor = (val & NXB_IMAGE_MINOR_M) >> NXB_IMAGE_MINOR_S; + sc->sc_fwbuild = (val & NXB_IMAGE_BUILD_M) >> NXB_IMAGE_BUILD_S; + if (sc->sc_flags & NXFLAG_FWINVALID) + printf("%s: using firmware %u.%u.%u\n", sc->sc_dev.dv_xname, + sc->sc_fwmajor, sc->sc_fwminor, sc->sc_fwbuild); + if (sc->sc_fwmajor != NX_FIRMWARE_MAJOR || + sc->sc_fwminor != NX_FIRMWARE_MINOR) { + printf("%s: unsupported firmware version\n", + sc->sc_dev.dv_xname); + goto fail; + } + + bootsz = ntohl(fh.fw_bootld_size); + imagesz = ntohl(fh.fw_image_size); + if ((imagesz + bootsz) != (fwlen - sizeof(fh)) || + (imagesz % 4) || (bootsz % 4)) { + printf("%s: invalid firmware image\n", sc->sc_dev.dv_xname); + goto fail; + } + + /* * Load the images into RAM */ @@ -799,22 +847,20 @@ nxb_reset(struct nxb_softc *sc) nxb_write(sc, NXROMUSB_GLB_CHIPCLKCONTROL, NXROMUSB_GLB_CHIPCLKCONTROL_ON); nxb_write(sc, NXROMUSB_GLB_CAS_RESET, NXROMUSB_GLB_CAS_RESET_DISABLE); + free(fw, M_DEVBUF); + fw = NULL; /* * bootstrap the newly loaded firmware and wait for completion */ nxb_newstate(sc, NX_S_BOOT); - if (nxb_newstate(sc, NX_S_LOADED) != 0) + if (nxb_newstate(sc, NX_S_RELOADED) != 0) goto fail; - - /* Firmware is ready for operation, allow interrupts etc. */ - nxb_newstate(sc, NX_S_READY); - goto done; + return; fail1: printf("%s: failed to reset firmware\n", sc->sc_dev.dv_xname); fail: nxb_newstate(sc, NX_S_FAIL); - done: if (fw != NULL) free(fw, M_DEVBUF); } diff --git a/sys/dev/pci/if_nxreg.h b/sys/dev/pci/if_nxreg.h index c0ca5da8419..8f2a37e33cf 100644 --- a/sys/dev/pci/if_nxreg.h +++ b/sys/dev/pci/if_nxreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nxreg.h,v 1.16 2007/05/01 02:25:31 reyk Exp $ */ +/* $OpenBSD: if_nxreg.h,v 1.17 2007/05/01 11:44:47 reyk Exp $ */ /* * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org> @@ -44,10 +44,11 @@ enum nx_state { NX_S_FAIL = -1, /* Failed to initialize the device */ NX_S_OFFLINE = 0, /* Firmware is not active yet */ - NX_S_RESET = 1, /* Firmware is in reset state */ - NX_S_BOOT = 2, /* Chipset is booting the firmware */ - NX_S_LOADED = 3, /* Firmware is loaded but not initialized */ - NX_S_READY = 4 /* Device has been initialized and is ready */ + NX_S_RESET = 2, /* Firmware is in reset state */ + NX_S_BOOT = 3, /* Chipset is booting the firmware */ + NX_S_LOADED = 4, /* Firmware is loaded but not initialized */ + NX_S_RELOADED = 5, /* Firmware is reloaded and initialized */ + NX_S_READY = 6 /* Device has been initialized and is ready */ }; /* @@ -189,6 +190,7 @@ struct nx_statusdesc { #define NXFLASHMAP_INFO 0x00004000 /* board configuration */ #define NXFLASHMAP_INITCODE 0x00006000 /* chipset-specific code */ #define NXFLASHMAP_BOOTLOADER 0x00010000 /* boot loader */ +#define NXFLASHMAP_BOOTLDSIZE 1024 /* boot loader size */ #define NXFLASHMAP_FIRMWARE_0 0x00043000 /* compressed firmware image */ #define NXFLASHMAP_FIRMWARE_1 0x00200000 /* backup firmware image */ #define NXFLASHMAP_PXE 0x003d0000 /* PXE image */ |