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