diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/advansys.c | 382 |
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 | */ | ||
12956 | static 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. |