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