[SCSI] advansys: Create AdvLoadMicrocode
Split AdvLoadMicrocode out of AdvInitAsc3550Driver, AdvInitAsc38C0800Driver and AdvInitAsc38C1600Driver. Signed-off-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
a9f4a59a94
commit
b9d9661400
@ -12931,6 +12931,78 @@ static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
|
|||||||
} while (buf_size > 0);
|
} while (buf_size > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the Microcode
|
||||||
|
*
|
||||||
|
* Write the microcode image to RISC memory starting at address 0.
|
||||||
|
*
|
||||||
|
* The microcode is stored compressed in the following format:
|
||||||
|
*
|
||||||
|
* 254 word (508 byte) table indexed by byte code followed
|
||||||
|
* by the following byte codes:
|
||||||
|
*
|
||||||
|
* 1-Byte Code:
|
||||||
|
* 00: Emit word 0 in table.
|
||||||
|
* 01: Emit word 1 in table.
|
||||||
|
* .
|
||||||
|
* FD: Emit word 253 in table.
|
||||||
|
*
|
||||||
|
* Multi-Byte Code:
|
||||||
|
* FE WW WW: (3 byte code) Word to emit is the next word WW WW.
|
||||||
|
* FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
|
||||||
|
*
|
||||||
|
* Returns 0 or an error if the checksum doesn't match
|
||||||
|
*/
|
||||||
|
static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
|
||||||
|
int memsize, int chksum)
|
||||||
|
{
|
||||||
|
int i, j, end, len = 0;
|
||||||
|
ADV_DCNT sum;
|
||||||
|
|
||||||
|
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
||||||
|
|
||||||
|
for (i = 253 * 2; i < size; i++) {
|
||||||
|
if (buf[i] == 0xff) {
|
||||||
|
unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
|
||||||
|
for (j = 0; j < buf[i + 1]; j++) {
|
||||||
|
AdvWriteWordAutoIncLram(iop_base, word);
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
i += 3;
|
||||||
|
} else if (buf[i] == 0xfe) {
|
||||||
|
unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
|
||||||
|
AdvWriteWordAutoIncLram(iop_base, word);
|
||||||
|
i += 2;
|
||||||
|
len += 2;
|
||||||
|
} else {
|
||||||
|
unsigned char off = buf[i] * 2;
|
||||||
|
unsigned short word = (buf[off + 1] << 8) | buf[off];
|
||||||
|
AdvWriteWordAutoIncLram(iop_base, word);
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end = len;
|
||||||
|
|
||||||
|
while (len < memsize) {
|
||||||
|
AdvWriteWordAutoIncLram(iop_base, 0);
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify the microcode checksum. */
|
||||||
|
sum = 0;
|
||||||
|
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
||||||
|
|
||||||
|
for (len = 0; len < end; len += 2) {
|
||||||
|
sum += AdvReadWordAutoIncLram(iop_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sum != chksum)
|
||||||
|
return ASC_IERR_MCODE_CHKSUM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the ASC-3550.
|
* Initialize the ASC-3550.
|
||||||
*
|
*
|
||||||
@ -12945,13 +13017,10 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
{
|
{
|
||||||
AdvPortAddr iop_base;
|
AdvPortAddr iop_base;
|
||||||
ushort warn_code;
|
ushort warn_code;
|
||||||
ADV_DCNT sum;
|
|
||||||
int begin_addr;
|
int begin_addr;
|
||||||
int end_addr;
|
int end_addr;
|
||||||
ushort code_sum;
|
ushort code_sum;
|
||||||
int word;
|
int word;
|
||||||
int j;
|
|
||||||
int adv_asc3550_expanded_size;
|
|
||||||
int i;
|
int i;
|
||||||
ushort scsi_cfg1;
|
ushort scsi_cfg1;
|
||||||
uchar tid;
|
uchar tid;
|
||||||
@ -12960,15 +13029,14 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
uchar max_cmd[ADV_MAX_TID + 1];
|
uchar max_cmd[ADV_MAX_TID + 1];
|
||||||
|
|
||||||
/* If there is already an error, don't continue. */
|
/* If there is already an error, don't continue. */
|
||||||
if (asc_dvc->err_code != 0) {
|
if (asc_dvc->err_code != 0)
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The caller must set 'chip_type' to ADV_CHIP_ASC3550.
|
* The caller must set 'chip_type' to ADV_CHIP_ASC3550.
|
||||||
*/
|
*/
|
||||||
if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
|
if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
|
||||||
asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
|
asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13012,84 +13080,11 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
max_cmd[tid]);
|
max_cmd[tid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
|
||||||
* Load the Microcode
|
_adv_asc3550_size, ADV_3550_MEMSIZE,
|
||||||
*
|
_adv_asc3550_chksum);
|
||||||
* Write the microcode image to RISC memory starting at address 0.
|
if (asc_dvc->err_code)
|
||||||
*/
|
|
||||||
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
|
||||||
/* Assume the following compressed format of the microcode buffer:
|
|
||||||
*
|
|
||||||
* 254 word (508 byte) table indexed by byte code followed
|
|
||||||
* by the following byte codes:
|
|
||||||
*
|
|
||||||
* 1-Byte Code:
|
|
||||||
* 00: Emit word 0 in table.
|
|
||||||
* 01: Emit word 1 in table.
|
|
||||||
* .
|
|
||||||
* FD: Emit word 253 in table.
|
|
||||||
*
|
|
||||||
* Multi-Byte Code:
|
|
||||||
* FE WW WW: (3 byte code) Word to emit is the next word WW WW.
|
|
||||||
* FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
|
|
||||||
*/
|
|
||||||
word = 0;
|
|
||||||
for (i = 253 * 2; i < _adv_asc3550_size; i++) {
|
|
||||||
if (_adv_asc3550_buf[i] == 0xff) {
|
|
||||||
for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc3550_buf
|
|
||||||
[i +
|
|
||||||
3] << 8) |
|
|
||||||
_adv_asc3550_buf
|
|
||||||
[i + 2]));
|
|
||||||
word++;
|
|
||||||
}
|
|
||||||
i += 3;
|
|
||||||
} else if (_adv_asc3550_buf[i] == 0xfe) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc3550_buf[i +
|
|
||||||
2]
|
|
||||||
<< 8) |
|
|
||||||
_adv_asc3550_buf[i +
|
|
||||||
1]));
|
|
||||||
i += 2;
|
|
||||||
word++;
|
|
||||||
} else {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2]));
|
|
||||||
word++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set 'word' for later use to clear the rest of memory and save
|
|
||||||
* the expanded mcode size.
|
|
||||||
*/
|
|
||||||
word *= 2;
|
|
||||||
adv_asc3550_expanded_size = word;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clear the rest of ASC-3550 Internal RAM (8KB).
|
|
||||||
*/
|
|
||||||
for (; word < ADV_3550_MEMSIZE; word += 2) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Verify the microcode checksum.
|
|
||||||
*/
|
|
||||||
sum = 0;
|
|
||||||
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
|
||||||
|
|
||||||
for (word = 0; word < adv_asc3550_expanded_size; word += 2) {
|
|
||||||
sum += AdvReadWordAutoIncLram(iop_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum != _adv_asc3550_chksum) {
|
|
||||||
asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
|
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore the RISC memory BIOS region.
|
* Restore the RISC memory BIOS region.
|
||||||
@ -13460,13 +13455,10 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
{
|
{
|
||||||
AdvPortAddr iop_base;
|
AdvPortAddr iop_base;
|
||||||
ushort warn_code;
|
ushort warn_code;
|
||||||
ADV_DCNT sum;
|
|
||||||
int begin_addr;
|
int begin_addr;
|
||||||
int end_addr;
|
int end_addr;
|
||||||
ushort code_sum;
|
ushort code_sum;
|
||||||
int word;
|
int word;
|
||||||
int j;
|
|
||||||
int adv_asc38C0800_expanded_size;
|
|
||||||
int i;
|
int i;
|
||||||
ushort scsi_cfg1;
|
ushort scsi_cfg1;
|
||||||
uchar byte;
|
uchar byte;
|
||||||
@ -13476,9 +13468,8 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
uchar max_cmd[ADV_MAX_TID + 1];
|
uchar max_cmd[ADV_MAX_TID + 1];
|
||||||
|
|
||||||
/* If there is already an error, don't continue. */
|
/* If there is already an error, don't continue. */
|
||||||
if (asc_dvc->err_code != 0) {
|
if (asc_dvc->err_code != 0)
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
|
* The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
|
||||||
@ -13550,7 +13541,7 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
|
byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
|
||||||
if ((byte & RAM_TEST_DONE) == 0
|
if ((byte & RAM_TEST_DONE) == 0
|
||||||
|| (byte & 0x0F) != PRE_TEST_VALUE) {
|
|| (byte & 0x0F) != PRE_TEST_VALUE) {
|
||||||
asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
|
asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13558,7 +13549,7 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
|
DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
|
||||||
if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
|
if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
|
||||||
!= NORMAL_VALUE) {
|
!= NORMAL_VALUE) {
|
||||||
asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
|
asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13577,99 +13568,18 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
|
if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
|
||||||
/* Get here if Done bit not set or Status not 0. */
|
/* Get here if Done bit not set or Status not 0. */
|
||||||
asc_dvc->bist_err_code = byte; /* for BIOS display message */
|
asc_dvc->bist_err_code = byte; /* for BIOS display message */
|
||||||
asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
|
asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to reset back to normal mode after LRAM test passes. */
|
/* We need to reset back to normal mode after LRAM test passes. */
|
||||||
AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
|
AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
|
||||||
|
|
||||||
/*
|
asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
|
||||||
* Load the Microcode
|
_adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
|
||||||
*
|
_adv_asc38C0800_chksum);
|
||||||
* Write the microcode image to RISC memory starting at address 0.
|
if (asc_dvc->err_code)
|
||||||
*
|
|
||||||
*/
|
|
||||||
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
|
||||||
|
|
||||||
/* Assume the following compressed format of the microcode buffer:
|
|
||||||
*
|
|
||||||
* 254 word (508 byte) table indexed by byte code followed
|
|
||||||
* by the following byte codes:
|
|
||||||
*
|
|
||||||
* 1-Byte Code:
|
|
||||||
* 00: Emit word 0 in table.
|
|
||||||
* 01: Emit word 1 in table.
|
|
||||||
* .
|
|
||||||
* FD: Emit word 253 in table.
|
|
||||||
*
|
|
||||||
* Multi-Byte Code:
|
|
||||||
* FE WW WW: (3 byte code) Word to emit is the next word WW WW.
|
|
||||||
* FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
|
|
||||||
*/
|
|
||||||
word = 0;
|
|
||||||
for (i = 253 * 2; i < _adv_asc38C0800_size; i++) {
|
|
||||||
if (_adv_asc38C0800_buf[i] == 0xff) {
|
|
||||||
for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc38C0800_buf
|
|
||||||
[i +
|
|
||||||
3] << 8) |
|
|
||||||
_adv_asc38C0800_buf
|
|
||||||
[i + 2]));
|
|
||||||
word++;
|
|
||||||
}
|
|
||||||
i += 3;
|
|
||||||
} else if (_adv_asc38C0800_buf[i] == 0xfe) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc38C0800_buf
|
|
||||||
[i +
|
|
||||||
2] << 8) |
|
|
||||||
_adv_asc38C0800_buf[i
|
|
||||||
+
|
|
||||||
1]));
|
|
||||||
i += 2;
|
|
||||||
word++;
|
|
||||||
} else {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2]));
|
|
||||||
word++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set 'word' for later use to clear the rest of memory and save
|
|
||||||
* the expanded mcode size.
|
|
||||||
*/
|
|
||||||
word *= 2;
|
|
||||||
adv_asc38C0800_expanded_size = word;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clear the rest of ASC-38C0800 Internal RAM (16KB).
|
|
||||||
*/
|
|
||||||
for (; word < ADV_38C0800_MEMSIZE; word += 2) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Verify the microcode checksum.
|
|
||||||
*/
|
|
||||||
sum = 0;
|
|
||||||
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
|
||||||
|
|
||||||
for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) {
|
|
||||||
sum += AdvReadWordAutoIncLram(iop_base);
|
|
||||||
}
|
|
||||||
ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i);
|
|
||||||
|
|
||||||
ASC_DBG2(1,
|
|
||||||
"AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n",
|
|
||||||
(ulong)sum, (ulong)_adv_asc38C0800_chksum);
|
|
||||||
|
|
||||||
if (sum != _adv_asc38C0800_chksum) {
|
|
||||||
asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
|
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore the RISC memory BIOS region.
|
* Restore the RISC memory BIOS region.
|
||||||
@ -13807,16 +13717,18 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All kind of combinations of devices attached to one of four connectors
|
* All kind of combinations of devices attached to one of four
|
||||||
* are acceptable except HVD device attached. For example, LVD device can
|
* connectors are acceptable except HVD device attached. For example,
|
||||||
* be attached to SE connector while SE device attached to LVD connector.
|
* LVD device can be attached to SE connector while SE device attached
|
||||||
* If LVD device attached to SE connector, it only runs up to Ultra speed.
|
* to LVD connector. If LVD device attached to SE connector, it only
|
||||||
|
* runs up to Ultra speed.
|
||||||
*
|
*
|
||||||
* If an HVD device is attached to one of LVD connectors, return an error.
|
* If an HVD device is attached to one of LVD connectors, return an
|
||||||
* However, there is no way to detect HVD device attached to SE connectors.
|
* error. However, there is no way to detect HVD device attached to
|
||||||
|
* SE connectors.
|
||||||
*/
|
*/
|
||||||
if (scsi_cfg1 & HVD) {
|
if (scsi_cfg1 & HVD) {
|
||||||
asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
|
asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13825,8 +13737,8 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
* set the termination value based on a table listed in a_condor.h.
|
* set the termination value based on a table listed in a_condor.h.
|
||||||
*
|
*
|
||||||
* If manual termination was specified with an EEPROM setting then
|
* If manual termination was specified with an EEPROM setting then
|
||||||
* 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to
|
* 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
|
||||||
* be 'ored' into SCSI_CFG1.
|
* to be 'ored' into SCSI_CFG1.
|
||||||
*/
|
*/
|
||||||
if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
|
if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
|
||||||
/* SE automatic termination control is enabled. */
|
/* SE automatic termination control is enabled. */
|
||||||
@ -13872,9 +13784,9 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
|
scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits
|
* Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
|
||||||
* and set possibly modified termination control bits in the Microcode
|
* bits and set possibly modified termination control bits in the
|
||||||
* SCSI_CFG1 Register Value.
|
* Microcode SCSI_CFG1 Register Value.
|
||||||
*/
|
*/
|
||||||
scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
|
scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
|
||||||
|
|
||||||
@ -14022,13 +13934,10 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
{
|
{
|
||||||
AdvPortAddr iop_base;
|
AdvPortAddr iop_base;
|
||||||
ushort warn_code;
|
ushort warn_code;
|
||||||
ADV_DCNT sum;
|
|
||||||
int begin_addr;
|
int begin_addr;
|
||||||
int end_addr;
|
int end_addr;
|
||||||
ushort code_sum;
|
ushort code_sum;
|
||||||
long word;
|
long word;
|
||||||
int j;
|
|
||||||
int adv_asc38C1600_expanded_size;
|
|
||||||
int i;
|
int i;
|
||||||
ushort scsi_cfg1;
|
ushort scsi_cfg1;
|
||||||
uchar byte;
|
uchar byte;
|
||||||
@ -14113,7 +14022,7 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
|
byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
|
||||||
if ((byte & RAM_TEST_DONE) == 0
|
if ((byte & RAM_TEST_DONE) == 0
|
||||||
|| (byte & 0x0F) != PRE_TEST_VALUE) {
|
|| (byte & 0x0F) != PRE_TEST_VALUE) {
|
||||||
asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
|
asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14121,7 +14030,7 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
|
DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
|
||||||
if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
|
if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
|
||||||
!= NORMAL_VALUE) {
|
!= NORMAL_VALUE) {
|
||||||
asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST;
|
asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14140,95 +14049,18 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
|
|||||||
if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
|
if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
|
||||||
/* Get here if Done bit not set or Status not 0. */
|
/* Get here if Done bit not set or Status not 0. */
|
||||||
asc_dvc->bist_err_code = byte; /* for BIOS display message */
|
asc_dvc->bist_err_code = byte; /* for BIOS display message */
|
||||||
asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST;
|
asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to reset back to normal mode after LRAM test passes. */
|
/* We need to reset back to normal mode after LRAM test passes. */
|
||||||
AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
|
AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
|
||||||
|
|
||||||
/*
|
asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
|
||||||
* Load the Microcode
|
_adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
|
||||||
*
|
_adv_asc38C1600_chksum);
|
||||||
* Write the microcode image to RISC memory starting at address 0.
|
if (asc_dvc->err_code)
|
||||||
*
|
|
||||||
*/
|
|
||||||
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Assume the following compressed format of the microcode buffer:
|
|
||||||
*
|
|
||||||
* 254 word (508 byte) table indexed by byte code followed
|
|
||||||
* by the following byte codes:
|
|
||||||
*
|
|
||||||
* 1-Byte Code:
|
|
||||||
* 00: Emit word 0 in table.
|
|
||||||
* 01: Emit word 1 in table.
|
|
||||||
* .
|
|
||||||
* FD: Emit word 253 in table.
|
|
||||||
*
|
|
||||||
* Multi-Byte Code:
|
|
||||||
* FE WW WW: (3 byte code) Word to emit is the next word WW WW.
|
|
||||||
* FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
|
|
||||||
*/
|
|
||||||
word = 0;
|
|
||||||
for (i = 253 * 2; i < _adv_asc38C1600_size; i++) {
|
|
||||||
if (_adv_asc38C1600_buf[i] == 0xff) {
|
|
||||||
for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc38C1600_buf
|
|
||||||
[i +
|
|
||||||
3] << 8) |
|
|
||||||
_adv_asc38C1600_buf
|
|
||||||
[i + 2]));
|
|
||||||
word++;
|
|
||||||
}
|
|
||||||
i += 3;
|
|
||||||
} else if (_adv_asc38C1600_buf[i] == 0xfe) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc38C1600_buf
|
|
||||||
[i +
|
|
||||||
2] << 8) |
|
|
||||||
_adv_asc38C1600_buf[i
|
|
||||||
+
|
|
||||||
1]));
|
|
||||||
i += 2;
|
|
||||||
word++;
|
|
||||||
} else {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, (((ushort)
|
|
||||||
_adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2]));
|
|
||||||
word++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set 'word' for later use to clear the rest of memory and save
|
|
||||||
* the expanded mcode size.
|
|
||||||
*/
|
|
||||||
word *= 2;
|
|
||||||
adv_asc38C1600_expanded_size = word;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clear the rest of ASC-38C1600 Internal RAM (32KB).
|
|
||||||
*/
|
|
||||||
for (; word < ADV_38C1600_MEMSIZE; word += 2) {
|
|
||||||
AdvWriteWordAutoIncLram(iop_base, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Verify the microcode checksum.
|
|
||||||
*/
|
|
||||||
sum = 0;
|
|
||||||
AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
|
|
||||||
|
|
||||||
for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) {
|
|
||||||
sum += AdvReadWordAutoIncLram(iop_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum != _adv_asc38C1600_chksum) {
|
|
||||||
asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
|
|
||||||
return ADV_ERROR;
|
return ADV_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore the RISC memory BIOS region.
|
* Restore the RISC memory BIOS region.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user