1103959Smarkm/* 2103959Smarkm * BeOS Driver for Intel ICH AC'97 Link interface 3103959Smarkm * 4 * Copyright (c) 2002-2005 Marcus Overhagen <marcus@overhagen.de> 5 * 6 * All rights reserved. 7 * Redistribution and use in source and binary forms, with or without modification, 8 * are permitted provided that the following conditions are met: 9 * 10 * - Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28#include <KernelExport.h> 29#include <config_manager.h> 30#include <PCI.h> 31#include <OS.h> 32#include <malloc.h> 33 34#include "debug.h" 35#include "config.h" 36#include "ich.h" 37 38extern pci_module_info *pci; 39 40device_config c; 41device_config *config = &c; 42 43struct device_item { 44 uint16 vendor_id; 45 uint16 device_id; 46 uint8 type; 47 const char * name; 48} device_list[] = { 49 { 0x8086, 0x7195, TYPE_DEFAULT, "Intel 82443MX" }, 50 { 0x8086, 0x2415, TYPE_DEFAULT, "Intel 82801AA (ICH)" }, 51 { 0x8086, 0x2425, TYPE_DEFAULT, "Intel 82801AB (ICH0)" }, 52 { 0x8086, 0x2445, TYPE_DEFAULT, "Intel 82801BA (ICH2), Intel 82801BAM (ICH2-M)" }, 53 { 0x8086, 0x2485, TYPE_DEFAULT, "Intel 82801CA (ICH3-S), Intel 82801CAM (ICH3-M)" }, 54 { 0x8086, 0x24C5, TYPE_ICH4, "Intel 82801DB (ICH4)" }, 55 { 0x8086, 0x24D5, TYPE_ICH4, "Intel 82801EB (ICH5), Intel 82801ER (ICH5R)" }, 56 { 0x8086, 0x266E, TYPE_ICH4, "Intel 82801FB/FR/FW/FRW (ICH6)" }, 57 { 0x8086, 0x27DE, TYPE_ICH4, "Intel unknown (ICH7)" }, 58 { 0x8086, 0x2698, TYPE_ICH4, "Intel unknown (ESB2)" }, 59 { 0x8086, 0x25A6, TYPE_ICH4, "Intel unknown (ESB5)" }, 60 { 0x1039, 0x7012, TYPE_SIS7012, "SiS SI7012" }, 61 { 0x10DE, 0x01B1, TYPE_DEFAULT, "NVIDIA nForce (MCP)" }, 62 { 0x10DE, 0x006A, TYPE_DEFAULT, "NVIDIA nForce 2 (MCP2)" }, 63 { 0x10DE, 0x00DA, TYPE_DEFAULT, "NVIDIA nForce 3 (MCP3)" }, 64 { 0x10DE, 0x003A, TYPE_DEFAULT, "NVIDIA unknown (MCP04)" }, 65 { 0x10DE, 0x0059, TYPE_DEFAULT, "NVIDIA unknown (CK804)" }, 66 { 0x10DE, 0x008A, TYPE_DEFAULT, "NVIDIA unknown (CK8)" }, 67 { 0x10DE, 0x00EA, TYPE_DEFAULT, "NVIDIA unknown (CK8S)" }, 68 { 0x1022, 0x746D, TYPE_DEFAULT, "AMD AMD8111" }, 69 { 0x1022, 0x7445, TYPE_DEFAULT, "AMD AMD768" }, 70// { 0x10B9, 0x5455, TYPE_DEFAULT, "Ali 5455" }, not yet supported 71 { }, 72}; 73 74 75/** 76 * search for the ICH AC97 controller, and initialize the global config 77 */ 78status_t 79probe_device(void) 80{ 81 struct pci_info info; 82 struct pci_info *pciinfo = &info; 83 int index; 84 int i; 85 status_t result; 86 uint32 value; 87 88 // initialize whole config to 0 89 memset(config, 0, sizeof(*config)); 90 91 result = B_OK; 92 93 for (index = 0; B_OK == pci->get_nth_pci_info(index, pciinfo); index++) { 94 LOG(("Checking PCI device, vendor 0x%04x, id 0x%04x, bus 0x%02x, dev 0x%02x, func 0x%02x, rev 0x%02x, api 0x%02x, sub 0x%02x, base 0x%02x\n", 95 pciinfo->vendor_id, pciinfo->device_id, pciinfo->bus, pciinfo->device, pciinfo->function, 96 pciinfo->revision, pciinfo->class_api, pciinfo->class_sub, pciinfo->class_base)); 97 for (i = 0; device_list[i].vendor_id; i++) { 98 if (device_list[i].vendor_id == pciinfo->vendor_id && device_list[i].device_id == pciinfo->device_id) { 99 config->name = device_list[i].name; 100 config->type = device_list[i].type; 101 goto probe_ok; 102 } 103 } 104 } 105 LOG(("No compatible hardware found\n")); 106 result = B_ERROR; 107 goto probe_done; 108 109probe_ok: 110 LOG(("found %s\n",config->name)); 111 LOG(("revision = %d\n",pciinfo->revision)); 112 113 #if DEBUG 114 LOG(("bus = %d, device = %d, function = %d\n", pciinfo->bus, pciinfo->device, pciinfo->function)); 115 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_vendor_id, 2); 116 LOG(("vendor id = 0x%04x\n",value)); 117 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_device_id, 2); 118 LOG(("device id = 0x%04x\n",value)); 119 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_revision, 1); 120 LOG(("revision = 0x%02x\n",value)); 121 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_subsystem_vendor_id, 2); 122 LOG(("subsystem vendor = 0x%04x\n",value)); 123 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_subsystem_id, 2); 124 LOG(("subsystem device = 0x%04x\n",value)); 125 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x04, 2); 126 LOG(("PCICMD = %#04x\n",value)); 127 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x06, 2); 128 LOG(("PCISTS = %#04x\n",value)); 129 #endif 130 131 /* for ICH4 enable memory mapped IO and busmaster access, 132 * for old ICHs enable programmed IO and busmaster access 133 */ 134 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_PCICMD, 2); 135 if (config->type & TYPE_ICH4) 136 value |= PCI_PCICMD_MSE | PCI_PCICMD_BME; 137 else 138 value |= PCI_PCICMD_IOS | PCI_PCICMD_BME; 139 pci->write_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_PCICMD, 2, value); 140 141 #if DEBUG 142 value = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, PCI_PCICMD, 2); 143 LOG(("PCICMD = %#04x\n",value)); 144 #endif 145 146 /* read memory-io and port-io bars 147 */ 148 config->nambar = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x10, 4); 149 config->nabmbar = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x14, 4); 150 config->mmbar = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x18, 4); 151 config->mbbar = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x1C, 4); 152 config->irq = pci->read_pci_config(pciinfo->bus, pciinfo->device, pciinfo->function, 0x3C, 1); 153 154 config->nambar &= PCI_address_io_mask; 155 config->nabmbar &= PCI_address_io_mask; 156 config->mmbar &= PCI_address_memory_32_mask; 157 config->mbbar &= PCI_address_memory_32_mask; 158 159 if (config->irq == 0 || config->irq == 0xff) { 160 PRINT(("WARNING: no interrupt configured\n")); 161 /* we can continue without an interrupt, as another 162 * workaround to handle this is also implemented 163 * force irq to be 0, not 0xff if no irq assigned 164 */ 165 config->irq = 0; 166 } 167 168 /* the ICH4 uses memory mapped IO */ 169 if ((config->type & TYPE_ICH4) && ((config->mmbar == 0) || (config->mbbar == 0))) { 170 PRINT(("ERROR: memory mapped IO not configured\n")); 171 result = B_ERROR; 172 } 173 /* all other ICHs use programmed IO */ 174 if (!(config->type & TYPE_ICH4) && ((config->nambar == 0) || (config->nabmbar == 0))) { 175 PRINT(("ERROR: IO space not configured\n")); 176 result = B_ERROR; 177 } 178 179 LOG(("nambar = 0x%08x\n", config->nambar)); 180 LOG(("nabmbar = 0x%08x\n", config->nabmbar)); 181 LOG(("mmbar = 0x%08x\n", config->mmbar)); 182 LOG(("mbbar = 0x%08x\n", config->mbbar)); 183 LOG(("irq = %d\n", config->irq)); 184 185probe_done: 186 return result; 187} 188