| 3411 | | # $_[0]: Chip to detect (0 = LM78, 2 = LM79) |
| 3412 | | # $_[1]: Address |
| 3413 | | # Returns: undef if not detected, 6 if detected. |
| 3414 | | # Note: Only address 0x290 is scanned at this moment. |
| 3415 | | sub lm78_isa_detect |
| 3416 | | { |
| 3417 | | my ($chip, $addr) = @_; |
| 3418 | | my $val = inb($addr + 1); |
| 3419 | | return if inb($addr + 2) != $val or inb($addr + 3) != $val or |
| 3420 | | inb($addr + 7) != $val; |
| 3421 | | |
| 3422 | | $val = inb($addr + 5); |
| 3423 | | outb($addr + 5, ~$val & 0x7f); |
| 3424 | | if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) { |
| 3425 | | outb($addr+5, $val); |
| 3426 | | return; |
| 3427 | | } |
| 3428 | | |
| 3429 | | return unless (isa_read_i5d6($addr, 0x40) & 0x80) == 0x00; |
| 3430 | | my $reg = isa_read_i5d6($addr, 0x49); |
| 3431 | | return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20 or $reg == 0x40)) or |
| 3432 | | ($chip == 2 and ($reg & 0xfe) == 0xc0); |
| 3433 | | |
| 3434 | | # Explicitly prevent misdetection of Winbond chips |
| 3435 | | $reg = isa_read_i5d6($addr, 0x4f); |
| 3436 | | return if $reg == 0xa3 || $reg == 0x5c; |
| 3437 | | |
| 3438 | | # Explicitly prevent misdetection of ITE chips |
| 3439 | | $reg = isa_read_i5d6($addr, 0x58); |
| 3440 | | return if $reg == 0x90; |
| 3441 | | |
| 3442 | | return 6; |
| 3443 | | } |
| 3444 | | |
| 4510 | | # $_[0]: Chip to detect (0 = W83781D, 1 = W83782D) |
| 4511 | | # $_[1]: Address |
| 4512 | | # Returns: undef if not detected, (8) if detected. |
| 4513 | | sub w83781d_isa_detect |
| 4514 | | { |
| 4515 | | my ($chip, $addr) = @_; |
| 4516 | | my ($reg1, $reg2); |
| 4517 | | my $val = inb($addr + 1); |
| 4518 | | return if inb($addr + 2) != $val or inb($addr + 3) != $val or |
| 4519 | | inb($addr + 7) != $val; |
| 4520 | | |
| 4521 | | $val = inb($addr + 5); |
| 4522 | | outb($addr+5, ~$val & 0x7f); |
| 4523 | | if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) { |
| 4524 | | outb($addr+5, $val); |
| 4525 | | return; |
| 4526 | | } |
| 4527 | | |
| 4528 | | $reg1 = isa_read_i5d6($addr, 0x4e); |
| 4529 | | $reg2 = isa_read_i5d6($addr, 0x4f); |
| 4530 | | return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or |
| 4531 | | (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c); |
| 4532 | | return unless ($reg1 & 0x07) == 0x00; |
| 4533 | | $reg1 = isa_read_i5d6($addr, 0x58); |
| 4534 | | return if $chip == 0 and ($reg1 & 0xfe) != 0x10; |
| 4535 | | return if $chip == 1 and ($reg1 & 0xfe) != 0x30; |
| 4536 | | |
| 4537 | | return 8; |
| 4538 | | } |
| 4539 | | |
| | 5147 | } |
| | 5148 | |
| | 5149 | # All ISA detection functions below take at least 1 parameter: |
| | 5150 | # $_[0]: Address |
| | 5151 | # Some of these functions which can detect more than one type of device, |
| | 5152 | # take a second parameter: |
| | 5153 | # $_[1]: Chip to detect |
| | 5154 | |
| | 5155 | # Chip to detect: 0 = LM78, 2 = LM79 |
| | 5156 | sub lm78_isa_detect |
| | 5157 | { |
| | 5158 | my ($addr, $chip) = @_; |
| | 5159 | my $val = inb($addr + 1); |
| | 5160 | return if inb($addr + 2) != $val or inb($addr + 3) != $val or |
| | 5161 | inb($addr + 7) != $val; |
| | 5162 | |
| | 5163 | $val = inb($addr + 5); |
| | 5164 | outb($addr + 5, ~$val & 0x7f); |
| | 5165 | if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) { |
| | 5166 | outb($addr+5, $val); |
| | 5167 | return; |
| | 5168 | } |
| | 5169 | |
| | 5170 | return unless (isa_read_i5d6($addr, 0x40) & 0x80) == 0x00; |
| | 5171 | my $reg = isa_read_i5d6($addr, 0x49); |
| | 5172 | return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20 or $reg == 0x40)) or |
| | 5173 | ($chip == 2 and ($reg & 0xfe) == 0xc0); |
| | 5174 | |
| | 5175 | # Explicitly prevent misdetection of Winbond chips |
| | 5176 | $reg = isa_read_i5d6($addr, 0x4f); |
| | 5177 | return if $reg == 0xa3 || $reg == 0x5c; |
| | 5178 | |
| | 5179 | # Explicitly prevent misdetection of ITE chips |
| | 5180 | $reg = isa_read_i5d6($addr, 0x58); |
| | 5181 | return if $reg == 0x90; |
| | 5182 | |
| | 5183 | return 6; |
| | 5184 | } |
| | 5185 | |
| | 5186 | # Chip to detect: 0 = W83781D, 1 = W83782D |
| | 5187 | sub w83781d_isa_detect |
| | 5188 | { |
| | 5189 | my ($addr, $chip) = @_; |
| | 5190 | my ($reg1, $reg2); |
| | 5191 | my $val = inb($addr + 1); |
| | 5192 | return if inb($addr + 2) != $val or inb($addr + 3) != $val or |
| | 5193 | inb($addr + 7) != $val; |
| | 5194 | |
| | 5195 | $val = inb($addr + 5); |
| | 5196 | outb($addr+5, ~$val & 0x7f); |
| | 5197 | if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) { |
| | 5198 | outb($addr+5, $val); |
| | 5199 | return; |
| | 5200 | } |
| | 5201 | |
| | 5202 | $reg1 = isa_read_i5d6($addr, 0x4e); |
| | 5203 | $reg2 = isa_read_i5d6($addr, 0x4f); |
| | 5204 | return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or |
| | 5205 | (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c); |
| | 5206 | return unless ($reg1 & 0x07) == 0x00; |
| | 5207 | $reg1 = isa_read_i5d6($addr, 0x58); |
| | 5208 | return if $chip == 0 and ($reg1 & 0xfe) != 0x10; |
| | 5209 | return if $chip == 1 and ($reg1 & 0xfe) != 0x30; |
| | 5210 | |
| | 5211 | return 8; |
| | 5212 | } |
| | 5213 | |
| | 5214 | # These are simple detectors that only look for a register at the |
| | 5215 | # standard location. |
| | 5216 | # For KCS, use the STATUS register. For SMIC, use the FLAGS register. |
| | 5217 | sub ipmi_kcs_detect |
| | 5218 | { |
| | 5219 | return if inb(0x0ca3) == 0xff; |
| | 5220 | return 4; |
| | 5221 | } |
| | 5222 | |
| | 5223 | sub ipmi_smic_detect |
| | 5224 | { |
| | 5225 | return if inb(0x0cab) == 0xff; |
| | 5226 | return 4; |