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 47 {0x2792, INTEL_TYPE_91x, "i910"}, 48 {0x258a, INTEL_TYPE_91x, "i915"}, 49 {0x2582, INTEL_TYPE_91x, "i915G"}, 50 {0x2592, INTEL_TYPE_91x, "i915GM"}, 51 {0x2772, INTEL_TYPE_945, "i945G"}, 52 {0x27a2, INTEL_TYPE_945, "i945GM"}, 53 {0x27ae, INTEL_TYPE_945M, "i945GME"}, 54 {0x29a2, INTEL_TYPE_965, "i965G"}, 55 {0x2a02, INTEL_TYPE_965M, "i965GM"}, 56 {0x29b2, INTEL_TYPE_G33, "G33G"}, 57 {0x29c2, INTEL_TYPE_G33, "Q35G"}, 58 {0x29d2, INTEL_TYPE_G33, "Q33G"}, 59 60 {0x2e32, INTEL_TYPE_GM45, "GMA_X4500_VGA"}, 61 {0x2a42, INTEL_TYPE_GM45, "GM45"}, 62 63 {0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"}, 64 {0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"}, 65 }; 66 67 int32 api_version = B_CUR_DRIVER_API_VERSION; 68 69 char* gDeviceNames[MAX_CARDS + 1]; 70 intel_info* gDeviceInfo[MAX_CARDS]; 71 pci_module_info* gPCI; 72 agp_gart_module_info* gGART; 73 mutex gLock; 74 75 76 static status_t 77 get_next_intel_extreme(int32 *_cookie, pci_info &info, uint32 &type) 78 { 79 int32 index = *_cookie; 80 81 // find devices 82 83 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 84 // check vendor 85 if (info.vendor_id != VENDOR_ID_INTEL 86 || info.class_base != PCI_display 87 || info.class_sub != PCI_vga) 88 continue; 89 90 // check device 91 for (uint32 i = 0; i < sizeof(kSupportedDevices) 92 / sizeof(kSupportedDevices[0]); i++) { 93 if (info.device_id == kSupportedDevices[i].device_id) { 94 type = i; 95 *_cookie = index + 1; 96 return B_OK; 97 } 98 } 99 } 100 101 return B_ENTRY_NOT_FOUND; 102 } 103 104 105 extern "C" const char ** 106 publish_devices(void) 107 { 108 TRACE((DEVICE_NAME ": publish_devices()\n")); 109 return (const char **)gDeviceNames; 110 } 111 112 113 extern "C" status_t 114 init_hardware(void) 115 { 116 TRACE((DEVICE_NAME ": init_hardware()\n")); 117 118 status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI); 119 if (status != B_OK) { 120 TRACE((DEVICE_NAME ": pci module unavailable\n")); 121 return status; 122 } 123 124 int32 cookie = 0; 125 uint32 type; 126 pci_info info; 127 status = get_next_intel_extreme(&cookie, info, type); 128 129 put_module(B_PCI_MODULE_NAME); 130 return status; 131 } 132 133 134 extern "C" status_t 135 init_driver(void) 136 { 137 TRACE((DEVICE_NAME ": init_driver()\n")); 138 139 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 140 if (status != B_OK) { 141 TRACE((DEVICE_NAME ": pci module unavailable\n")); 142 return status; 143 } 144 145 status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART); 146 if (status != B_OK) { 147 TRACE((DEVICE_NAME ": AGP GART module unavailable\n")); 148 put_module(B_PCI_MODULE_NAME); 149 return status; 150 } 151 152 mutex_init(&gLock, "intel extreme ksync"); 153 154 // find devices 155 156 int32 found = 0; 157 158 for (int32 cookie = 0; found < MAX_CARDS;) { 159 pci_info* info = (pci_info*)malloc(sizeof(pci_info)); 160 if (info == NULL) 161 break; 162 163 uint32 type; 164 status = get_next_intel_extreme(&cookie, *info, type); 165 if (status < B_OK) { 166 free(info); 167 break; 168 } 169 170 // create device names & allocate device info structure 171 172 char name[64]; 173 sprintf(name, "graphics/intel_extreme_%02x%02x%02x", 174 info->bus, info->device, 175 info->function); 176 177 gDeviceNames[found] = strdup(name); 178 if (gDeviceNames[found] == NULL) 179 break; 180 181 gDeviceInfo[found] = (intel_info*)malloc(sizeof(intel_info)); 182 if (gDeviceInfo[found] == NULL) { 183 free(gDeviceNames[found]); 184 break; 185 } 186 187 // initialize the structure for later use 188 189 memset(gDeviceInfo[found], 0, sizeof(intel_info)); 190 gDeviceInfo[found]->init_status = B_NO_INIT; 191 gDeviceInfo[found]->id = found; 192 gDeviceInfo[found]->pci = info; 193 gDeviceInfo[found]->registers = (uint8 *)info->u.h0.base_registers[0]; 194 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 195 gDeviceInfo[found]->device_type = kSupportedDevices[type].type; 196 197 dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found, 198 kSupportedDevices[type].name, info->revision); 199 200 found++; 201 } 202 203 gDeviceNames[found] = NULL; 204 205 if (found == 0) { 206 mutex_destroy(&gLock); 207 put_module(B_AGP_GART_MODULE_NAME); 208 put_module(B_PCI_MODULE_NAME); 209 return ENODEV; 210 } 211 212 return B_OK; 213 } 214 215 216 extern "C" void 217 uninit_driver(void) 218 { 219 TRACE((DEVICE_NAME ": uninit_driver()\n")); 220 221 mutex_destroy(&gLock); 222 223 // free device related structures 224 char* name; 225 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 226 free(gDeviceInfo[index]); 227 free(name); 228 } 229 230 put_module(B_AGP_GART_MODULE_NAME); 231 put_module(B_PCI_MODULE_NAME); 232 } 233 234 235 extern "C" device_hooks* 236 find_device(const char* name) 237 { 238 int index; 239 240 TRACE((DEVICE_NAME ": find_device()\n")); 241 242 for (index = 0; gDeviceNames[index] != NULL; index++) { 243 if (!strcmp(name, gDeviceNames[index])) 244 return &gDeviceHooks; 245 } 246 247 return NULL; 248 } 249 250