| 137 | // ATI/AMD SB600/SB700 freeze workaround kindly borrowed from NetBSD PR40056 |
| 138 | if (fPCIInfo->vendor_id == 0x1002 /* ATI/AMD */) { |
| 139 | bool applyWorkaround = false; |
| 140 | |
| 141 | if (fPCIInfo->device_id == 0x4386 /* SB600 EHCI controller */) { |
| 142 | // always apply on SB600 |
| 143 | applyWorkaround = true; |
| 144 | } else if (fPCIInfo->device_id == 0x4396 /* SB700/SB800 EHCI */) { |
| 145 | // only apply on certain chipsets, determined by SMBus revision |
| 146 | pci_info smbus; |
| 147 | int32 index = 0; |
| 148 | while (sPCIModule->get_nth_pci_info(index++, &smbus) >= B_OK) { |
| 149 | if (smbus.vendor_id == 0x1002 && smbus.device_id == 0x4385) { |
| 150 | /* SB600/SB700/SB800 SMBus controller */ |
| 151 | if (smbus.revision == 0x3a || smbus.revision == 0x3b) |
| 152 | applyWorkaround = true; |
| 153 | |
| 154 | break; |
| 155 | } |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | if (applyWorkaround) { |
| 160 | // "reserved" as far as documentation is concerned apparently, |
| 161 | // no real idea who figured that out how, but it's in the NetBSD |
| 162 | // patch concerning this... |
| 163 | |
| 164 | TRACE_ALWAYS("applying SB600/SB700 freeze workaround\n"); |
| 165 | uint32 workaround = sPCIModule->read_pci_config(fPCIInfo->bus, |
| 166 | fPCIInfo->device, fPCIInfo->function, 0x50, 4); |
| 167 | |
| 168 | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
| 169 | fPCIInfo->function, 0x50, 4, workaround | (1 << 27)); |
| 170 | } |
| 171 | } |
| 172 | |