aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/advansys.c382
1 files changed, 107 insertions, 275 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index c216d6a76782..0f02f3f5f63d 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -12932,6 +12932,78 @@ static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
12932} 12932}
12933 12933
12934/* 12934/*
12935 * Load the Microcode
12936 *
12937 * Write the microcode image to RISC memory starting at address 0.
12938 *
12939 * The microcode is stored compressed in the following format:
12940 *
12941 * 254 word (508 byte) table indexed by byte code followed
12942 * by the following byte codes:
12943 *
12944 * 1-Byte Code:
12945 * 00: Emit word 0 in table.
12946 * 01: Emit word 1 in table.
12947 * .
12948 * FD: Emit word 253 in table.
12949 *
12950 * Multi-Byte Code:
12951 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
12952 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
12953 *
12954 * Returns 0 or an error if the checksum doesn't match
12955 */
12956static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
12957 int memsize, int chksum)
12958{
12959 int i, j, end, len = 0;
12960 ADV_DCNT sum;
12961
12962 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
12963
12964 for (i = 253 * 2; i < size; i++) {
12965 if (buf[i] == 0xff) {
12966 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
12967 for (j = 0; j < buf[i + 1]; j++) {
12968 AdvWriteWordAutoIncLram(iop_base, word);
12969 len += 2;
12970 }
12971 i += 3;
12972 } else if (buf[i] == 0xfe) {
12973 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
12974 AdvWriteWordAutoIncLram(iop_base, word);
12975 i += 2;
12976 len += 2;
12977 } else {
12978 unsigned char off = buf[i] * 2;
12979 unsigned short word = (buf[off + 1] << 8) | buf[off];
12980 AdvWriteWordAutoIncLram(iop_base, word);
12981 len += 2;
12982 }
12983 }
12984
12985 end = len;
12986
12987 while (len < memsize) {
12988 AdvWriteWordAutoIncLram(iop_base, 0);
12989 len += 2;
12990 }
12991
12992 /* Verify the microcode checksum. */
12993 sum = 0;
12994 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
12995
12996 for (len = 0; len < end; len += 2) {
12997 sum += AdvReadWordAutoIncLram(iop_base);
12998 }
12999
13000 if (sum != chksum)
13001 return ASC_IERR_MCODE_CHKSUM;
13002
13003 return 0;
13004}
13005
13006/*
12935 * Initialize the ASC-3550. 13007 * Initialize the ASC-3550.
12936 * 13008 *
12937 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. 13009 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
@@ -12945,13 +13017,10 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
12945{ 13017{
12946 AdvPortAddr iop_base; 13018 AdvPortAddr iop_base;
12947 ushort warn_code; 13019 ushort warn_code;
12948 ADV_DCNT sum;
12949 int begin_addr; 13020 int begin_addr;
12950 int end_addr; 13021 int end_addr;
12951 ushort code_sum; 13022 ushort code_sum;
12952 int word; 13023 int word;
12953 int j;
12954 int adv_asc3550_expanded_size;
12955 int i; 13024 int i;
12956 ushort scsi_cfg1; 13025 ushort scsi_cfg1;
12957 uchar tid; 13026 uchar tid;
@@ -12960,15 +13029,14 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
12960 uchar max_cmd[ADV_MAX_TID + 1]; 13029 uchar max_cmd[ADV_MAX_TID + 1];
12961 13030
12962 /* If there is already an error, don't continue. */ 13031 /* If there is already an error, don't continue. */
12963 if (asc_dvc->err_code != 0) { 13032 if (asc_dvc->err_code != 0)
12964 return ADV_ERROR; 13033 return ADV_ERROR;
12965 }
12966 13034
12967 /* 13035 /*
12968 * The caller must set 'chip_type' to ADV_CHIP_ASC3550. 13036 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
12969 */ 13037 */
12970 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) { 13038 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
12971 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; 13039 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12972 return ADV_ERROR; 13040 return ADV_ERROR;
12973 } 13041 }
12974 13042
@@ -13012,84 +13080,11 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
13012 max_cmd[tid]); 13080 max_cmd[tid]);
13013 } 13081 }
13014 13082
13015 /* 13083 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
13016 * Load the Microcode 13084 _adv_asc3550_size, ADV_3550_MEMSIZE,
13017 * 13085 _adv_asc3550_chksum);
13018 * Write the microcode image to RISC memory starting at address 0. 13086 if (asc_dvc->err_code)
13019 */
13020 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
13021 /* Assume the following compressed format of the microcode buffer:
13022 *
13023 * 254 word (508 byte) table indexed by byte code followed
13024 * by the following byte codes:
13025 *
13026 * 1-Byte Code:
13027 * 00: Emit word 0 in table.
13028 * 01: Emit word 1 in table.
13029 * .
13030 * FD: Emit word 253 in table.
13031 *
13032 * Multi-Byte Code:
13033 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
13034 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
13035 */
13036 word = 0;
13037 for (i = 253 * 2; i < _adv_asc3550_size; i++) {
13038 if (_adv_asc3550_buf[i] == 0xff) {
13039 for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) {
13040 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13041 _adv_asc3550_buf
13042 [i +
13043 3] << 8) |
13044 _adv_asc3550_buf
13045 [i + 2]));
13046 word++;
13047 }
13048 i += 3;
13049 } else if (_adv_asc3550_buf[i] == 0xfe) {
13050 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13051 _adv_asc3550_buf[i +
13052 2]
13053 << 8) |
13054 _adv_asc3550_buf[i +
13055 1]));
13056 i += 2;
13057 word++;
13058 } else {
13059 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13060 _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2]));
13061 word++;
13062 }
13063 }
13064
13065 /*
13066 * Set 'word' for later use to clear the rest of memory and save
13067 * the expanded mcode size.
13068 */
13069 word *= 2;
13070 adv_asc3550_expanded_size = word;
13071
13072 /*
13073 * Clear the rest of ASC-3550 Internal RAM (8KB).
13074 */
13075 for (; word < ADV_3550_MEMSIZE; word += 2) {
13076 AdvWriteWordAutoIncLram(iop_base, 0);
13077 }
13078
13079 /*
13080 * Verify the microcode checksum.
13081 */
13082 sum = 0;
13083 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
13084
13085 for (word = 0; word < adv_asc3550_expanded_size; word += 2) {
13086 sum += AdvReadWordAutoIncLram(iop_base);
13087 }
13088
13089 if (sum != _adv_asc3550_chksum) {
13090 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
13091 return ADV_ERROR; 13087 return ADV_ERROR;
13092 }
13093 13088
13094 /* 13089 /*
13095 * Restore the RISC memory BIOS region. 13090 * Restore the RISC memory BIOS region.
@@ -13460,13 +13455,10 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13460{ 13455{
13461 AdvPortAddr iop_base; 13456 AdvPortAddr iop_base;
13462 ushort warn_code; 13457 ushort warn_code;
13463 ADV_DCNT sum;
13464 int begin_addr; 13458 int begin_addr;
13465 int end_addr; 13459 int end_addr;
13466 ushort code_sum; 13460 ushort code_sum;
13467 int word; 13461 int word;
13468 int j;
13469 int adv_asc38C0800_expanded_size;
13470 int i; 13462 int i;
13471 ushort scsi_cfg1; 13463 ushort scsi_cfg1;
13472 uchar byte; 13464 uchar byte;
@@ -13476,9 +13468,8 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13476 uchar max_cmd[ADV_MAX_TID + 1]; 13468 uchar max_cmd[ADV_MAX_TID + 1];
13477 13469
13478 /* If there is already an error, don't continue. */ 13470 /* If there is already an error, don't continue. */
13479 if (asc_dvc->err_code != 0) { 13471 if (asc_dvc->err_code != 0)
13480 return ADV_ERROR; 13472 return ADV_ERROR;
13481 }
13482 13473
13483 /* 13474 /*
13484 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800. 13475 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
@@ -13550,7 +13541,7 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13550 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); 13541 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
13551 if ((byte & RAM_TEST_DONE) == 0 13542 if ((byte & RAM_TEST_DONE) == 0
13552 || (byte & 0x0F) != PRE_TEST_VALUE) { 13543 || (byte & 0x0F) != PRE_TEST_VALUE) {
13553 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; 13544 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
13554 return ADV_ERROR; 13545 return ADV_ERROR;
13555 } 13546 }
13556 13547
@@ -13558,7 +13549,7 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13558 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ 13549 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
13559 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) 13550 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
13560 != NORMAL_VALUE) { 13551 != NORMAL_VALUE) {
13561 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; 13552 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
13562 return ADV_ERROR; 13553 return ADV_ERROR;
13563 } 13554 }
13564 } 13555 }
@@ -13577,99 +13568,18 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13577 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { 13568 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
13578 /* Get here if Done bit not set or Status not 0. */ 13569 /* Get here if Done bit not set or Status not 0. */
13579 asc_dvc->bist_err_code = byte; /* for BIOS display message */ 13570 asc_dvc->bist_err_code = byte; /* for BIOS display message */
13580 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; 13571 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
13581 return ADV_ERROR; 13572 return ADV_ERROR;
13582 } 13573 }
13583 13574
13584 /* We need to reset back to normal mode after LRAM test passes. */ 13575 /* We need to reset back to normal mode after LRAM test passes. */
13585 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); 13576 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
13586 13577
13587 /* 13578 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
13588 * Load the Microcode 13579 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
13589 * 13580 _adv_asc38C0800_chksum);
13590 * Write the microcode image to RISC memory starting at address 0. 13581 if (asc_dvc->err_code)
13591 *
13592 */
13593 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
13594
13595 /* Assume the following compressed format of the microcode buffer:
13596 *
13597 * 254 word (508 byte) table indexed by byte code followed
13598 * by the following byte codes:
13599 *
13600 * 1-Byte Code:
13601 * 00: Emit word 0 in table.
13602 * 01: Emit word 1 in table.
13603 * .
13604 * FD: Emit word 253 in table.
13605 *
13606 * Multi-Byte Code:
13607 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
13608 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
13609 */
13610 word = 0;
13611 for (i = 253 * 2; i < _adv_asc38C0800_size; i++) {
13612 if (_adv_asc38C0800_buf[i] == 0xff) {
13613 for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) {
13614 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13615 _adv_asc38C0800_buf
13616 [i +
13617 3] << 8) |
13618 _adv_asc38C0800_buf
13619 [i + 2]));
13620 word++;
13621 }
13622 i += 3;
13623 } else if (_adv_asc38C0800_buf[i] == 0xfe) {
13624 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13625 _adv_asc38C0800_buf
13626 [i +
13627 2] << 8) |
13628 _adv_asc38C0800_buf[i
13629 +
13630 1]));
13631 i += 2;
13632 word++;
13633 } else {
13634 AdvWriteWordAutoIncLram(iop_base, (((ushort)
13635 _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2]));
13636 word++;
13637 }
13638 }
13639
13640 /*
13641 * Set 'word' for later use to clear the rest of memory and save
13642 * the expanded mcode size.
13643 */
13644 word *= 2;
13645 adv_asc38C0800_expanded_size = word;
13646
13647 /*
13648 * Clear the rest of ASC-38C0800 Internal RAM (16KB).
13649 */
13650 for (; word < ADV_38C0800_MEMSIZE; word += 2) {
13651 AdvWriteWordAutoIncLram(iop_base, 0);
13652 }
13653
13654 /*
13655 * Verify the microcode checksum.
13656 */
13657 sum = 0;
13658 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
13659
13660 for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) {
13661 sum += AdvReadWordAutoIncLram(iop_base);
13662 }
13663 ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i);
13664
13665 ASC_DBG2(1,
13666 "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n",
13667 (ulong)sum, (ulong)_adv_asc38C0800_chksum);
13668
13669 if (sum != _adv_asc38C0800_chksum) {
13670 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
13671 return ADV_ERROR; 13582 return ADV_ERROR;
13672 }
13673 13583
13674 /* 13584 /*
13675 * Restore the RISC memory BIOS region. 13585 * Restore the RISC memory BIOS region.
@@ -13807,16 +13717,18 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13807 } 13717 }
13808 13718
13809 /* 13719 /*
13810 * All kind of combinations of devices attached to one of four connectors 13720 * All kind of combinations of devices attached to one of four
13811 * are acceptable except HVD device attached. For example, LVD device can 13721 * connectors are acceptable except HVD device attached. For example,
13812 * be attached to SE connector while SE device attached to LVD connector. 13722 * LVD device can be attached to SE connector while SE device attached
13813 * If LVD device attached to SE connector, it only runs up to Ultra speed. 13723 * to LVD connector. If LVD device attached to SE connector, it only
13724 * runs up to Ultra speed.
13814 * 13725 *
13815 * If an HVD device is attached to one of LVD connectors, return an error. 13726 * If an HVD device is attached to one of LVD connectors, return an
13816 * However, there is no way to detect HVD device attached to SE connectors. 13727 * error. However, there is no way to detect HVD device attached to
13728 * SE connectors.
13817 */ 13729 */
13818 if (scsi_cfg1 & HVD) { 13730 if (scsi_cfg1 & HVD) {
13819 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; 13731 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
13820 return ADV_ERROR; 13732 return ADV_ERROR;
13821 } 13733 }
13822 13734
@@ -13825,8 +13737,8 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13825 * set the termination value based on a table listed in a_condor.h. 13737 * set the termination value based on a table listed in a_condor.h.
13826 * 13738 *
13827 * If manual termination was specified with an EEPROM setting then 13739 * If manual termination was specified with an EEPROM setting then
13828 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to 13740 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
13829 * be 'ored' into SCSI_CFG1. 13741 * to be 'ored' into SCSI_CFG1.
13830 */ 13742 */
13831 if ((asc_dvc->cfg->termination & TERM_SE) == 0) { 13743 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
13832 /* SE automatic termination control is enabled. */ 13744 /* SE automatic termination control is enabled. */
@@ -13872,9 +13784,9 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
13872 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); 13784 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
13873 13785
13874 /* 13786 /*
13875 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits 13787 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
13876 * and set possibly modified termination control bits in the Microcode 13788 * bits and set possibly modified termination control bits in the
13877 * SCSI_CFG1 Register Value. 13789 * Microcode SCSI_CFG1 Register Value.
13878 */ 13790 */
13879 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE); 13791 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
13880 13792
@@ -14022,13 +13934,10 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
14022{ 13934{
14023 AdvPortAddr iop_base; 13935 AdvPortAddr iop_base;
14024 ushort warn_code; 13936 ushort warn_code;
14025 ADV_DCNT sum;
14026 int begin_addr; 13937 int begin_addr;
14027 int end_addr; 13938 int end_addr;
14028 ushort code_sum; 13939 ushort code_sum;
14029 long word; 13940 long word;
14030 int j;
14031 int adv_asc38C1600_expanded_size;
14032 int i; 13941 int i;
14033 ushort scsi_cfg1; 13942 ushort scsi_cfg1;
14034 uchar byte; 13943 uchar byte;
@@ -14113,7 +14022,7 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
14113 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); 14022 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
14114 if ((byte & RAM_TEST_DONE) == 0 14023 if ((byte & RAM_TEST_DONE) == 0
14115 || (byte & 0x0F) != PRE_TEST_VALUE) { 14024 || (byte & 0x0F) != PRE_TEST_VALUE) {
14116 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; 14025 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
14117 return ADV_ERROR; 14026 return ADV_ERROR;
14118 } 14027 }
14119 14028
@@ -14121,7 +14030,7 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
14121 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ 14030 DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */
14122 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) 14031 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
14123 != NORMAL_VALUE) { 14032 != NORMAL_VALUE) {
14124 asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; 14033 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
14125 return ADV_ERROR; 14034 return ADV_ERROR;
14126 } 14035 }
14127 } 14036 }
@@ -14140,95 +14049,18 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
14140 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { 14049 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
14141 /* Get here if Done bit not set or Status not 0. */ 14050 /* Get here if Done bit not set or Status not 0. */
14142 asc_dvc->bist_err_code = byte; /* for BIOS display message */ 14051 asc_dvc->bist_err_code = byte; /* for BIOS display message */
14143 asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; 14052 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
14144 return ADV_ERROR; 14053 return ADV_ERROR;
14145 } 14054 }
14146 14055
14147 /* We need to reset back to normal mode after LRAM test passes. */ 14056 /* We need to reset back to normal mode after LRAM test passes. */
14148 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); 14057 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
14149 14058
14150 /* 14059 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
14151 * Load the Microcode 14060 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
14152 * 14061 _adv_asc38C1600_chksum);
14153 * Write the microcode image to RISC memory starting at address 0. 14062 if (asc_dvc->err_code)
14154 *
14155 */
14156 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14157
14158 /*
14159 * Assume the following compressed format of the microcode buffer:
14160 *
14161 * 254 word (508 byte) table indexed by byte code followed
14162 * by the following byte codes:
14163 *
14164 * 1-Byte Code:
14165 * 00: Emit word 0 in table.
14166 * 01: Emit word 1 in table.
14167 * .
14168 * FD: Emit word 253 in table.
14169 *
14170 * Multi-Byte Code:
14171 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
14172 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
14173 */
14174 word = 0;
14175 for (i = 253 * 2; i < _adv_asc38C1600_size; i++) {
14176 if (_adv_asc38C1600_buf[i] == 0xff) {
14177 for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) {
14178 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14179 _adv_asc38C1600_buf
14180 [i +
14181 3] << 8) |
14182 _adv_asc38C1600_buf
14183 [i + 2]));
14184 word++;
14185 }
14186 i += 3;
14187 } else if (_adv_asc38C1600_buf[i] == 0xfe) {
14188 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14189 _adv_asc38C1600_buf
14190 [i +
14191 2] << 8) |
14192 _adv_asc38C1600_buf[i
14193 +
14194 1]));
14195 i += 2;
14196 word++;
14197 } else {
14198 AdvWriteWordAutoIncLram(iop_base, (((ushort)
14199 _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2]));
14200 word++;
14201 }
14202 }
14203
14204 /*
14205 * Set 'word' for later use to clear the rest of memory and save
14206 * the expanded mcode size.
14207 */
14208 word *= 2;
14209 adv_asc38C1600_expanded_size = word;
14210
14211 /*
14212 * Clear the rest of ASC-38C1600 Internal RAM (32KB).
14213 */
14214 for (; word < ADV_38C1600_MEMSIZE; word += 2) {
14215 AdvWriteWordAutoIncLram(iop_base, 0);
14216 }
14217
14218 /*
14219 * Verify the microcode checksum.
14220 */
14221 sum = 0;
14222 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
14223
14224 for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) {
14225 sum += AdvReadWordAutoIncLram(iop_base);
14226 }
14227
14228 if (sum != _adv_asc38C1600_chksum) {
14229 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
14230 return ADV_ERROR; 14063 return ADV_ERROR;
14231 }
14232 14064
14233 /* 14065 /*
14234 * Restore the RISC memory BIOS region. 14066 * Restore the RISC memory BIOS region.