Make the driver to work with firmware version 4.1.12 (other 4.X.Y should

also do it). Three problems have been encountered:

1. The initialisation command does not work in interrupt mode. Whether
   this is a firmware bug or a feature is not clear. The original Fore
   drivers execute the initialize command always in polling mode, so
   it appears that this behaviour is expected. When we detect a 4.X.Y
   firmware do busy wait on the command status.

2. The command code of the GET_PROM command has changed. This is an
   unofficial command anyway. What was GET_PROM in 3.X.Y is CLEAR_STATS
   in 4.X.Y (although unimplemented in the firmware). We need to
   use the correct code depending on the firmware.

3. The 4.X.Y firmware can set the error flag in the command status
   without also setting the completion flag (as the documenation says).
   Check both variants.

An additional field in the per-card structure fu_ft4 is TRUE when we have
detected a 4.X.Y firmware. Otherwise it is false. The behaviour of the
driver when using a 3.X.Y firmware should be identical to the previous
behaviour.

This change will enable traffic shaping of (at least one) CBR channels.
This commit is contained in:
Hartmut Brandt 2003-07-31 14:20:07 +00:00
parent 251dee13f1
commit 50b751a7d4
5 changed files with 68 additions and 4 deletions

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 {
/*

View file

@ -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

View file

@ -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;