1 /* 2 * Copyright 2006-2007, 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 <OS.h> 15 #include <KernelExport.h> 16 #include <SupportDefs.h> 17 #include <PCI.h> 18 19 #include <stdlib.h> 20 #include <stdio.h> 21 #include <string.h> 22 #include <malloc.h> 23 24 #define TRACE_DRIVER 25 #ifdef TRACE_DRIVER 26 # define TRACE(x) dprintf x 27 #else 28 # define TRACE(x) ; 29 #endif 30 31 #define MAX_CARDS 4 32 33 // list of supported devices 34 const struct supported_device { 35 uint32 device_id; 36 int32 type; 37 const char *name; 38 } kSupportedDevices[] = { 39 {0x3577, INTEL_TYPE_8xx | INTEL_TYPE_83x, "i830GM"}, 40 {0x2562, INTEL_TYPE_8xx | INTEL_TYPE_83x, "i845G"}, 41 42 {0x2572, INTEL_TYPE_8xx | INTEL_TYPE_85x, "i865G"}, 43 {0x3582, INTEL_TYPE_8xx | INTEL_TYPE_85x, "i855G"}, 44 45 {0x2792, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i910"}, 46 {0x258a, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i915"}, 47 {0x2582, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i915G"}, 48 {0x2592, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i915GM"}, 49 {0x2772, INTEL_TYPE_9xx | INTEL_TYPE_945, "i945G"}, 50 {0x27a2, INTEL_TYPE_9xx | INTEL_TYPE_945, "i945GM"}, 51 {0x29a2, INTEL_TYPE_9xx | INTEL_TYPE_965, "i965G"}, 52 {0x29b2, INTEL_TYPE_9xx | INTEL_TYPE_G33, "G33G"}, 53 {0x29c2, INTEL_TYPE_9xx | INTEL_TYPE_G33, "Q35G"}, 54 {0x29d2, INTEL_TYPE_9xx | INTEL_TYPE_G33, "Q33G"}, 55 }; 56 57 int32 api_version = B_CUR_DRIVER_API_VERSION; 58 59 char *gDeviceNames[MAX_CARDS + 1]; 60 intel_info *gDeviceInfo[MAX_CARDS]; 61 pci_module_info *gPCI; 62 lock gLock; 63 64 65 static status_t 66 get_next_intel_extreme(int32 *_cookie, pci_info &info, uint32 &type) 67 { 68 int32 index = *_cookie; 69 70 // find devices 71 72 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 73 // check vendor 74 if (info.vendor_id != VENDOR_ID_INTEL 75 || info.class_base != PCI_display 76 || info.class_sub != 0) 77 continue; 78 79 // check device 80 for (uint32 i = 0; i < sizeof(kSupportedDevices) 81 / sizeof(kSupportedDevices[0]); i++) { 82 if (info.device_id == kSupportedDevices[i].device_id) { 83 type = i; 84 *_cookie = index + 1; 85 return B_OK; 86 } 87 } 88 } 89 90 return B_ENTRY_NOT_FOUND; 91 } 92 93 94 extern "C" const char ** 95 publish_devices(void) 96 { 97 TRACE((DEVICE_NAME ": publish_devices()\n")); 98 return (const char **)gDeviceNames; 99 } 100 101 102 extern "C" status_t 103 init_hardware(void) 104 { 105 TRACE((DEVICE_NAME ": init_hardware()\n")); 106 107 status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI); 108 if (status != B_OK) { 109 TRACE((DEVICE_NAME ": pci module unavailable\n")); 110 return status; 111 } 112 113 int32 cookie = 0; 114 uint32 type; 115 pci_info info; 116 status = get_next_intel_extreme(&cookie, info, type); 117 118 put_module(B_PCI_MODULE_NAME); 119 return status; 120 } 121 122 123 extern "C" status_t 124 init_driver(void) 125 { 126 TRACE((DEVICE_NAME ": init_driver()\n")); 127 128 status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI); 129 if (status != B_OK) { 130 TRACE((DEVICE_NAME ": pci module unavailable\n")); 131 return status; 132 } 133 134 status = init_lock(&gLock, "intel extreme ksync"); 135 if (status < B_OK) { 136 put_module(B_PCI_MODULE_NAME); 137 return status; 138 } 139 140 // find devices 141 142 int32 found = 0; 143 144 for (int32 cookie = 0; found < MAX_CARDS;) { 145 pci_info *info = (pci_info *)malloc(sizeof(pci_info)); 146 if (info == NULL) 147 break; 148 149 uint32 type; 150 status = get_next_intel_extreme(&cookie, *info, type); 151 if (status < B_OK) { 152 free(info); 153 break; 154 } 155 156 // create device names & allocate device info structure 157 158 char name[64]; 159 sprintf(name, "graphics/intel_extreme_%02x%02x%02x", 160 info->bus, info->device, 161 info->function); 162 163 gDeviceNames[found] = strdup(name); 164 if (gDeviceNames[found] == NULL) 165 break; 166 167 gDeviceInfo[found] = (intel_info *)malloc(sizeof(intel_info)); 168 if (gDeviceInfo[found] == NULL) { 169 free(gDeviceNames[found]); 170 break; 171 } 172 173 // initialize the structure for later use 174 175 memset(gDeviceInfo[found], 0, sizeof(intel_info)); 176 gDeviceInfo[found]->init_status = B_NO_INIT; 177 gDeviceInfo[found]->id = found; 178 gDeviceInfo[found]->pci = info; 179 gDeviceInfo[found]->registers = (uint8 *)info->u.h0.base_registers[0]; 180 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 181 gDeviceInfo[found]->device_type = kSupportedDevices[type].type; 182 183 dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found, 184 kSupportedDevices[type].name, info->revision); 185 found++; 186 } 187 188 gDeviceNames[found] = NULL; 189 190 if (found == 0) { 191 uninit_lock(&gLock); 192 put_module(B_PCI_MODULE_NAME); 193 return ENODEV; 194 } 195 196 return B_OK; 197 } 198 199 200 extern "C" void 201 uninit_driver(void) 202 { 203 TRACE((DEVICE_NAME ": uninit_driver()\n")); 204 205 uninit_lock(&gLock); 206 207 // free device related structures 208 char *name; 209 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 210 free(gDeviceInfo[index]); 211 free(name); 212 } 213 214 put_module(B_PCI_MODULE_NAME); 215 } 216 217 218 extern "C" device_hooks * 219 find_device(const char *name) 220 { 221 int index; 222 223 TRACE((DEVICE_NAME ": find_device()\n")); 224 225 for (index = 0; gDeviceNames[index] != NULL; index++) { 226 if (!strcmp(name, gDeviceNames[index])) 227 return &gDeviceHooks; 228 } 229 230 return NULL; 231 } 232 233 /* 234 extern "C" void 235 wake_driver(void) 236 { 237 // for compatibility with Dano, only 238 } 239 240 241 extern "C" void 242 suspend_driver(void) 243 { 244 // for compatibility with Dano, only 245 } 246 */ 247