summaryrefslogtreecommitdiffstats
path: root/sys/dev/hfa
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hfa')
-rw-r--r--sys/dev/hfa/fore_aali.h2
-rw-r--r--sys/dev/hfa/fore_command.c12
-rw-r--r--sys/dev/hfa/fore_init.c53
-rw-r--r--sys/dev/hfa/fore_intr.c4
-rw-r--r--sys/dev/hfa/fore_var.h1
5 files changed, 68 insertions, 4 deletions
diff --git a/sys/dev/hfa/fore_aali.h b/sys/dev/hfa/fore_aali.h
index ccf3922..3e00a94 100644
--- a/sys/dev/hfa/fore_aali.h
+++ b/sys/dev/hfa/fore_aali.h
@@ -331,6 +331,8 @@ typedef volatile unsigned long Cmd_code;
#define CMD_SET_OC3_REG 0x07 /* Set SUNI OC3 registers */
#define CMD_GET_OC3_REG 0x08 /* Get SUNI OC3 registers */
#define CMD_GET_PROM 0x09 /* Get PROM data */
+#define CMD_ZERO_STATS4 0x09 /* FT 4 Zero stats (unimpl) */
+#define CMD_GET_PROM4 0x0a /* FT 4 Get PROM data */
#define CMD_INTR_REQ 0x80 /* Request host interrupt */
#endif /* _KERNEL */
diff --git a/sys/dev/hfa/fore_command.c b/sys/dev/hfa/fore_command.c
index e73091f..d4442a9 100644
--- a/sys/dev/hfa/fore_command.c
+++ b/sys/dev/hfa/fore_command.c
@@ -235,8 +235,9 @@ fore_cmd_drain(fup)
/*
* Process each completed entry
+ * ForeThought 4 may set QSTAT_ERROR without QSTAT_COMPLETED.
*/
- while (*fup->fu_cmd_head->hcq_status & QSTAT_COMPLETED) {
+ while (*fup->fu_cmd_head->hcq_status & (QSTAT_COMPLETED | QSTAT_ERROR)) {
hcp = fup->fu_cmd_head;
@@ -333,6 +334,14 @@ fore_cmd_drain(fup)
break;
case CMD_GET_PROM:
+ if (fup->fu_ft4)
+ goto unknown;
+ goto prom;
+
+ case CMD_GET_PROM4:
+ if (!fup->fu_ft4)
+ goto unknown;
+ prom:
if (*hcp->hcq_status & QSTAT_ERROR) {
/*
* Couldn't get PROM data
@@ -371,6 +380,7 @@ fore_cmd_drain(fup)
break;
default:
+ unknown:
log(LOG_ERR, "fore_cmd_drain: unknown command %ld\n",
hcp->hcq_code);
}
diff --git a/sys/dev/hfa/fore_init.c b/sys/dev/hfa/fore_init.c
index 216ed32a..2957b7c 100644
--- a/sys/dev/hfa/fore_init.c
+++ b/sys/dev/hfa/fore_init.c
@@ -95,6 +95,8 @@ fore_initialize(fup)
Init_parms *inp;
caddr_t errmsg;
u_long vers;
+ u_int c, wait;
+#define MAX_WAIT 100
/*
* Must wait until firmware has been downloaded and is running
@@ -149,6 +151,11 @@ fore_initialize(fup)
sizeof(fup->fu_config.ac_firm_vers), "%ld.%ld.%ld",
(vers >> 16) & 0xff, (vers >> 8) & 0xff, vers & 0xff);
+ if (((vers >> 16) & 0xff) == 4)
+ fup->fu_ft4 = 1;
+ else
+ fup->fu_ft4 = 0;
+
#ifdef notdef
/*
* Turn on CP debugging
@@ -193,7 +200,41 @@ fore_initialize(fup)
* the CP to interrupt to signal completion
*/
inp->init_status = CP_WRITE(QSTAT_PENDING);
- inp->init_cmd = CP_WRITE(CMD_INIT | CMD_INTR_REQ);
+
+ if (!fup->fu_ft4) {
+ inp->init_cmd = CP_WRITE(CMD_INIT | CMD_INTR_REQ);
+ return;
+ }
+ inp->init_cmd = CP_WRITE(CMD_INIT);
+
+ /*
+ * With the ForeThought 4.X image it appears that we need to
+ * busy wait on the initializisation command to complete.
+ * Otherwise the command queue address (the first word
+ * of the queue structure) will be mangled.
+ */
+ c = 0;
+ for (wait = 0; wait < MAX_WAIT; wait++) {
+ c = CP_READ(inp->init_status);
+ if (c & QSTAT_COMPLETED)
+ break;
+ DELAY(1000);
+ }
+ if (c & QSTAT_ERROR) {
+ log(LOG_ERR, "fore initialization failed: intf=%s%d, "
+ "hbeat=0x%lx\n", fup->fu_pif.pif_name,
+ fup->fu_pif.pif_unit, (u_long)CP_READ(aap->aali_heartbeat));
+ fore_interface_free(fup);
+ return;
+ }
+ if (!(c & QSTAT_COMPLETED)) {
+ log(LOG_ERR, "fore initialization timed out: intf=%s%d, "
+ "hbeat=0x%lx\n", fup->fu_pif.pif_name, fup->fu_pif.pif_unit,
+ (u_long)CP_READ(aap->aali_heartbeat));
+ fore_interface_free(fup);
+ return;
+ }
+ fore_initialize_complete(fup);
return;
failed:
@@ -277,6 +318,9 @@ fore_initialize_complete(fup)
* This will be called after CP initialization has completed.
* There is (currently) no retry if this fails.
*
+ * It took me some time to find out that FT3 and FT4 use different
+ * operation codes for GET_PROM.
+ *
* Called at interrupt level.
*
* Arguments:
@@ -302,7 +346,10 @@ fore_get_prom(fup)
/*
* Queue entry available, so set our view of things up
*/
- hcp->hcq_code = CMD_GET_PROM;
+ if (fup->fu_ft4)
+ hcp->hcq_code = CMD_GET_PROM4;
+ else
+ hcp->hcq_code = CMD_GET_PROM;
hcp->hcq_arg = NULL;
fup->fu_cmd_tail = hcp->hcq_next;
@@ -319,7 +366,7 @@ fore_get_prom(fup)
return;
}
cqp->cmdq_prom.prom_buffer = (CP_dma) CP_WRITE(fup->fu_promd);
- cqp->cmdq_prom.prom_cmd = CP_WRITE(CMD_GET_PROM | CMD_INTR_REQ);
+ cqp->cmdq_prom.prom_cmd = CP_WRITE(hcp->hcq_code | CMD_INTR_REQ);
} else {
/*
diff --git a/sys/dev/hfa/fore_intr.c b/sys/dev/hfa/fore_intr.c
index 2193a51..319c665 100644
--- a/sys/dev/hfa/fore_intr.c
+++ b/sys/dev/hfa/fore_intr.c
@@ -171,6 +171,10 @@ fore_intr(arg)
*/
if ((fup->fu_flags & CUF_INITED) == 0) {
+ if (fup->fu_ft4)
+ /* may not happen */
+ goto done;
+
/*
* We're just initializing device now, so see if
* the initialization command has completed
diff --git a/sys/dev/hfa/fore_var.h b/sys/dev/hfa/fore_var.h
index 6f7dd4c..ba26928 100644
--- a/sys/dev/hfa/fore_var.h
+++ b/sys/dev/hfa/fore_var.h
@@ -226,6 +226,7 @@ struct fore_unit {
Fore_prom *fu_prom; /* Device PROM buffer */
Fore_prom *fu_promd; /* Device PROM buffer (DMA) */
struct callout_handle fu_thandle; /* Timer handle */
+ int fu_ft4; /* Running ForeThought 4 firmware */
};
typedef struct fore_unit Fore_unit;
OpenPOWER on IntegriCloud