summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-05-01 11:44:48 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-05-01 11:44:48 +0000
commit5f264daed90f5a6c3f817b973e83e4678ca1a91b (patch)
treef53adac27fd6e10747b918fdc4994cb5b0d6ab56 /sys/dev
parent868d765569987bf1d96fe6287713c34d48399de1 (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.c156
-rw-r--r--sys/dev/pci/if_nxreg.h12
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 */