diff options
| author | Matthew Wilcox <matthew@wil.cx> | 2007-09-09 10:56:28 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:47:33 -0400 |
| commit | b9d9661400dde3fb2027f5da8db600c66d0f876b (patch) | |
| tree | 20d5b9f934af079afac71a320fdb0be053b8da21 /drivers | |
| parent | a9f4a59a949c5de6313dcf4ebe2f91448c008a37 (diff) | |
[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>
Diffstat (limited to 'drivers')
| -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. |
