1 /* 2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "driver.h" 11 #include "device.h" 12 #include "lock.h" 13 14 #include <stdlib.h> 15 #include <stdio.h> 16 #include <string.h> 17 18 #include <AGP.h> 19 #include <KernelExport.h> 20 #include <OS.h> 21 #include <PCI.h> 22 #include <SupportDefs.h> 23 24 25 #define TRACE_DRIVER 26 #ifdef TRACE_DRIVER 27 # define TRACE(x) dprintf x 28 #else 29 # define TRACE(x) ; 30 #endif 31 32 #define MAX_CARDS 4 33 34 35 // list of supported devices 36 const struct supported_device { 37 uint32 device_id; 38 int32 type; 39 const char* name; 40 } kSupportedDevices[] = { 41 {0x3577, INTEL_TYPE_83x, "i830GM"}, 42 {0x2562, INTEL_TYPE_83x, "i845G"}, 43 44 {0x2572, INTEL_TYPE_85x, "i865G"}, 45 {0x3582, INTEL_TYPE_85x, "i855G"}, 46 {0x358e, INTEL_TYPE_85x, "i855G"}, 47 48 {0x2582, INTEL_TYPE_915, "i915G"}, 49 {0x258a, INTEL_TYPE_915, "i915"}, 50 {0x2592, INTEL_TYPE_915M, "i915GM"}, 51 {0x2792, INTEL_TYPE_915, "i910"}, 52 {0x2772, INTEL_TYPE_945, "i945G"}, 53 {0x27a2, INTEL_TYPE_945M, "i945GM"}, 54 {0x27ae, INTEL_TYPE_945M, "i945GME"}, 55 {0x2972, INTEL_TYPE_965, "i946G"}, 56 {0x2982, INTEL_TYPE_965, "G35"}, 57 {0x2992, INTEL_TYPE_965, "i965Q"}, 58 {0x29a2, INTEL_TYPE_965, "i965G"}, 59 {0x2a02, INTEL_TYPE_965M, "i965GM"}, 60 {0x2a12, INTEL_TYPE_965M, "i965GME"}, 61 {0x29b2, INTEL_TYPE_G33, "G33G"}, 62 {0x29c2, INTEL_TYPE_G33, "Q35G"}, 63 {0x29d2, INTEL_TYPE_G33, "Q33G"}, 64 65 {0x2a42, INTEL_TYPE_GM45, "GM45"}, 66 {0x2e02, INTEL_TYPE_G45, "IGD"}, 67 {0x2e12, INTEL_TYPE_G45, "Q45"}, 68 {0x2e22, INTEL_TYPE_G45, "G45"}, 69 {0x2e32, INTEL_TYPE_G45, "G41"}, 70 {0x2e42, INTEL_TYPE_G45, "B43"}, 71 {0x2e92, INTEL_TYPE_G45, "B43"}, 72 73 {0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"}, 74 {0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"}, 75 76 {0x0042, INTEL_TYPE_ILKG, "IronLake Desktop"}, 77 {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, 78 {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, 79 {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, 80 81 {0x0102, INTEL_TYPE_SNBG, "SandyBridge Desktop GT1"}, 82 {0x0112, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2"}, 83 {0x0122, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2+"}, 84 {0x0106, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT1"}, 85 {0x0116, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2"}, 86 {0x0126, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2+"}, 87 {0x010a, INTEL_TYPE_SNBGS, "SandyBridge Server"} 88 }; 89 90 int32 api_version = B_CUR_DRIVER_API_VERSION; 91 92 char* gDeviceNames[MAX_CARDS + 1]; 93 intel_info* gDeviceInfo[MAX_CARDS]; 94 pci_module_info* gPCI; 95 agp_gart_module_info* gGART; 96 mutex gLock; 97 98 99 static status_t 100 get_next_intel_extreme(int32* _cookie, pci_info &info, uint32 &type) 101 { 102 int32 index = *_cookie; 103 104 // find devices 105 106 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 107 // check vendor 108 if (info.vendor_id != VENDOR_ID_INTEL 109 || info.class_base != PCI_display 110 || info.class_sub != PCI_vga) 111 continue; 112 113 // check device 114 for (uint32 i = 0; i < sizeof(kSupportedDevices) 115 / sizeof(kSupportedDevices[0]); i++) { 116 if (info.device_id == kSupportedDevices[i].device_id) { 117 type = i; 118 *_cookie = index + 1; 119 return B_OK; 120 } 121 } 122 } 123 124 return B_ENTRY_NOT_FOUND; 125 } 126 127 128 extern "C" const char** 129 publish_devices(void) 130 { 131 TRACE((DEVICE_NAME ": publish_devices()\n")); 132 return (const char**)gDeviceNames; 133 } 134 135 136 extern "C" status_t 137 init_hardware(void) 138 { 139 TRACE((DEVICE_NAME ": init_hardware()\n")); 140 141 status_t status = get_module(B_PCI_MODULE_NAME,(module_info**)&gPCI); 142 if (status != B_OK) { 143 TRACE((DEVICE_NAME ": pci module unavailable\n")); 144 return status; 145 } 146 147 int32 cookie = 0; 148 uint32 type; 149 pci_info info; 150 status = get_next_intel_extreme(&cookie, info, type); 151 152 put_module(B_PCI_MODULE_NAME); 153 return status; 154 } 155 156 157 extern "C" status_t 158 init_driver(void) 159 { 160 TRACE((DEVICE_NAME ": init_driver()\n")); 161 162 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 163 if (status != B_OK) { 164 TRACE((DEVICE_NAME ": pci module unavailable\n")); 165 return status; 166 } 167 168 status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART); 169 if (status != B_OK) { 170 TRACE((DEVICE_NAME ": AGP GART module unavailable\n")); 171 put_module(B_PCI_MODULE_NAME); 172 return status; 173 } 174 175 mutex_init(&gLock, "intel extreme ksync"); 176 177 // find devices 178 179 int32 found = 0; 180 181 for (int32 cookie = 0; found < MAX_CARDS;) { 182 pci_info* info = (pci_info*)malloc(sizeof(pci_info)); 183 if (info == NULL) 184 break; 185 186 uint32 type; 187 status = get_next_intel_extreme(&cookie, *info, type); 188 if (status < B_OK) { 189 free(info); 190 break; 191 } 192 193 // create device names & allocate device info structure 194 195 char name[64]; 196 sprintf(name, "graphics/intel_extreme_%02x%02x%02x", 197 info->bus, info->device, 198 info->function); 199 200 gDeviceNames[found] = strdup(name); 201 if (gDeviceNames[found] == NULL) 202 break; 203 204 gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info)); 205 if (gDeviceInfo[found] == NULL) { 206 free(gDeviceNames[found]); 207 break; 208 } 209 210 // initialize the structure for later use 211 212 memset(gDeviceInfo[found], 0, sizeof(intel_info)); 213 gDeviceInfo[found]->init_status = B_NO_INIT; 214 gDeviceInfo[found]->id = found; 215 gDeviceInfo[found]->pci = info; 216 gDeviceInfo[found]->registers = (uint8*)info->u.h0.base_registers[0]; 217 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 218 gDeviceInfo[found]->device_type = kSupportedDevices[type].type; 219 220 dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found, 221 kSupportedDevices[type].name, info->revision); 222 223 found++; 224 } 225 226 gDeviceNames[found] = NULL; 227 228 if (found == 0) { 229 mutex_destroy(&gLock); 230 put_module(B_AGP_GART_MODULE_NAME); 231 put_module(B_PCI_MODULE_NAME); 232 return ENODEV; 233 } 234 235 return B_OK; 236 } 237 238 239 extern "C" void 240 uninit_driver(void) 241 { 242 TRACE((DEVICE_NAME ": uninit_driver()\n")); 243 244 mutex_destroy(&gLock); 245 246 // free device related structures 247 char* name; 248 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 249 free(gDeviceInfo[index]); 250 free(name); 251 } 252 253 put_module(B_AGP_GART_MODULE_NAME); 254 put_module(B_PCI_MODULE_NAME); 255 } 256 257 258 extern "C" device_hooks* 259 find_device(const char* name) 260 { 261 int index; 262 263 TRACE((DEVICE_NAME ": find_device()\n")); 264 265 for (index = 0; gDeviceNames[index] != NULL; index++) { 266 if (!strcmp(name, gDeviceNames[index])) 267 return &gDeviceHooks; 268 } 269 270 return NULL; 271 } 272 273