1 /* 2 * Copyright (c) 2002, Thomas Kurschel 3 * Copyright 2004-2011 Haiku, Inc. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Thomas Kurschel 8 * Clemens Zeidler, <haiku@clemens-zeidler.de> 9 * Alexander von Gluck IV, kallisti5@unixzen.com 10 */ 11 12 13 #include "driver.h" 14 #include "device.h" 15 #include "lock.h" 16 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <string.h> 20 21 #include <AGP.h> 22 #include <KernelExport.h> 23 #include <OS.h> 24 #include <PCI.h> 25 #include <SupportDefs.h> 26 27 28 #define TRACE_DRIVER 29 #ifdef TRACE_DRIVER 30 # define TRACE(x...) dprintf("radeon_hd: " x) 31 #else 32 # define TRACE(x...) ; 33 #endif 34 35 #define MAX_CARDS 1 36 37 38 // list of supported devices 39 const struct supported_device { 40 uint32 device_id; 41 uint16 chipset; 42 const char* name; 43 } kSupportedDevices[] = { 44 // R600 series (HD24xx - HD42xx) 45 // Codename: Pele 46 {0x94c7, RADEON_R600 | 0x10, "Radeon HD 2350"}, /*RV610*/ 47 {0x94c1, RADEON_R600 | 0x10, "Radeon HD 2400"}, /*RV610, IGP*/ 48 {0x94c3, RADEON_R600 | 0x10, "Radeon HD 2400"}, /*RV610*/ 49 {0x94cc, RADEON_R600 | 0x10, "Radeon HD 2400"}, /*RV610*/ 50 {0x9588, RADEON_R600 | 0x30, "Radeon HD 2600"}, /*RV630*/ 51 {0x958a, RADEON_R600 | 0x30, "Radeon HD 2600 X2"}, /*RV630*/ 52 // Radeon 2700 - RV630 53 {0x9400, RADEON_R600 | 0x0, "Radeon HD 2900"}, /*RV600*/ 54 {0x9405, RADEON_R600 | 0x0, "Radeon HD 2900"}, /*RV600*/ 55 {0x9611, RADEON_R600 | 0x20, "Radeon HD 3100"}, /*RV620, IGP*/ 56 {0x9613, RADEON_R600 | 0x20, "Radeon HD 3100"}, /*RV620, IGP*/ 57 {0x9610, RADEON_R600 | 0x10, "Radeon HD 3200"}, /*RV610, IGP*/ 58 {0x9612, RADEON_R600 | 0x10, "Radeon HD 3200"}, /*RV610, IGP*/ 59 {0x9615, RADEON_R600 | 0x10, "Radeon HD 3200"}, /*RV610, IGP*/ 60 {0x9614, RADEON_R600 | 0x10, "Radeon HD 3300"}, /*RV610, IGP*/ 61 // Radeon 3430 - RV620 62 {0x95c5, RADEON_R600 | 0x20, "Radeon HD 3450"}, /*RV620*/ 63 {0x95c6, RADEON_R600 | 0x20, "Radeon HD 3450"}, /*RV620*/ 64 {0x95c7, RADEON_R600 | 0x20, "Radeon HD 3450"}, /*RV620*/ 65 {0x95c9, RADEON_R600 | 0x20, "Radeon HD 3450"}, /*RV620*/ 66 {0x95c4, RADEON_R600 | 0x20, "Radeon HD 3470"}, /*RV620*/ 67 {0x95c0, RADEON_R600 | 0x20, "Radeon HD 3550"}, /*RV620*/ 68 {0x9581, RADEON_R600 | 0x30, "Radeon HD 3600"}, /*RV630*/ 69 {0x9583, RADEON_R600 | 0x30, "Radeon HD 3600"}, /*RV630*/ 70 {0x9598, RADEON_R600 | 0x30, "Radeon HD 3600"}, /*RV630*/ 71 {0x9591, RADEON_R600 | 0x35, "Radeon HD 3600"}, /*RV635*/ 72 {0x9589, RADEON_R600 | 0x30, "Radeon HD 3610"}, /*RV630*/ 73 // Radeon 3650 - RV635 74 // Radeon 3670 - RV635 75 {0x9507, RADEON_R600 | 0x70, "Radeon HD 3830"}, /*RV670*/ 76 {0x9505, RADEON_R600 | 0x70, "Radeon HD 3850"}, /*RV670, IGP*/ 77 {0x9513, RADEON_R600 | 0x80, "Radeon HD 3850 X2"}, /*RV670*/ 78 {0x9501, RADEON_R600 | 0x70, "Radeon HD 3870"}, /*RV670*/ 79 {0x950F, RADEON_R600 | 0x80, "Radeon HD 3870 X2"}, /*R680*/ 80 {0x9710, RADEON_R600 | 0x20, "Radeon HD 4200"}, /*RV620, IGP*/ 81 // Radeon 4225 - RV620 82 {0x9712, RADEON_R600 | 0x20, "Radeon HD 4270"}, /*RV620, IGP*/ 83 84 // R700 series (HD4330 - HD4890, HD51xx, HD5xxV) 85 // Codename: Wekiva 86 // Radeon 4330 - RV710 87 {0x954f, RADEON_R700 | 0x10, "Radeon HD 4300"}, /*RV710*/ 88 {0x9552, RADEON_R700 | 0x10, "Radeon HD 4300"}, /*RV710*/ 89 {0x9555, RADEON_R700 | 0x10, "Radeon HD 4350"}, /*RV710*/ 90 {0x9540, RADEON_R700 | 0x10, "Radeon HD 4550"}, /*RV710*/ 91 {0x9498, RADEON_R700 | 0x30, "Radeon HD 4650"}, /*RV740*/ 92 {0x94b4, RADEON_R700 | 0x40, "Radeon HD 4700"}, /*RV740*/ 93 {0x9490, RADEON_R700 | 0x30, "Radeon HD 4710"}, /*RV740*/ 94 {0x94b3, RADEON_R700 | 0x40, "Radeon HD 4770"}, /*RV740*/ 95 {0x94b5, RADEON_R700 | 0x40, "Radeon HD 4770"}, /*RV740*/ 96 {0x944a, RADEON_R700 | 0x70, "Radeon HD 4800"}, /*RV740*/ 97 {0x944e, RADEON_R700 | 0x70, "Radeon HD 4810"}, /*RV740*/ 98 {0x944c, RADEON_R700 | 0x70, "Radeon HD 4830"}, /*RV740*/ 99 {0x9442, RADEON_R700 | 0x70, "Radeon HD 4850"}, /*RV770*/ 100 {0x9443, RADEON_R700 | 0x70, "Radeon HD 4850 X2"}, /*RV770*/ 101 {0x94a1, RADEON_R700 | 0x90, "Radeon HD 4860"}, /*RV780, IGP*/ 102 {0x9440, RADEON_R700 | 0x70, "Radeon HD 4870"}, /*RV770*/ 103 {0x9441, RADEON_R700 | 0x70, "Radeon HD 4870 X2"}, /*RV770*/ 104 105 // R800 series (HD54xx - HD59xx) 106 // Codename: Evergreen 107 {0x68e1, RADEON_R800 | 0x0, "Radeon HD 5430"}, /*RV8XX*/ 108 {0x68f9, RADEON_R800 | 0x0, "Radeon HD 5450"}, /*RV8XX*/ 109 {0x68e0, RADEON_R800 | 0x0, "Radeon HD 5470"}, /*RV8XX*/ 110 {0x68da, RADEON_R800 | 0x0, "Radeon HD 5500"}, /*RV8XX*/ 111 {0x68d9, RADEON_R800 | 0x0, "Radeon HD 5570"}, /*RV8XX*/ 112 {0x68b9, RADEON_R800 | 0x0, "Radeon HD 5600"}, /*RV8XX*/ 113 {0x68c1, RADEON_R800 | 0x0, "Radeon HD 5650"}, /*RV8XX*/ 114 {0x68d8, RADEON_R800 | 0x0, "Radeon HD 5670"}, /*RV8XX*/ 115 {0x68be, RADEON_R800 | 0x0, "Radeon HD 5700"}, /*RV8XX*/ 116 {0x68b8, RADEON_R800 | 0x0, "Radeon HD 5770"}, /*RV8XX*/ 117 {0x689e, RADEON_R800 | 0x0, "Radeon HD 5800"}, /*RV8XX*/ 118 {0x6899, RADEON_R800 | 0x0, "Radeon HD 5850"}, /*RV8XX*/ 119 {0x6898, RADEON_R800 | 0x0, "Radeon HD 5870"}, /*RV8XX*/ 120 {0x689c, RADEON_R800 | 0x0, "Radeon HD 5900"} /*RV8XX*/ 121 }; 122 123 124 int32 api_version = B_CUR_DRIVER_API_VERSION; 125 126 127 char* gDeviceNames[MAX_CARDS + 1]; 128 radeon_info* gDeviceInfo[MAX_CARDS]; 129 pci_module_info* gPCI; 130 mutex gLock; 131 132 133 static status_t 134 get_next_radeon_hd(int32 *_cookie, pci_info &info, uint32 &type) 135 { 136 int32 index = *_cookie; 137 138 // find devices 139 140 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 141 // check vendor 142 if (info.vendor_id != VENDOR_ID_ATI 143 || info.class_base != PCI_display 144 || info.class_sub != PCI_vga) 145 continue; 146 147 // check device 148 for (uint32 i = 0; i < sizeof(kSupportedDevices) 149 / sizeof(kSupportedDevices[0]); i++) { 150 if (info.device_id == kSupportedDevices[i].device_id) { 151 type = i; 152 *_cookie = index + 1; 153 return B_OK; 154 } 155 } 156 } 157 158 return B_ENTRY_NOT_FOUND; 159 } 160 161 162 extern "C" const char ** 163 publish_devices(void) 164 { 165 TRACE("%s\n", __func__); 166 return (const char **)gDeviceNames; 167 } 168 169 170 extern "C" status_t 171 init_hardware(void) 172 { 173 TRACE("%s\n", __func__); 174 175 status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); 176 if (status != B_OK) { 177 dprintf(DEVICE_NAME ": ERROR: pci module unavailable\n"); 178 return status; 179 } 180 181 int32 cookie = 0; 182 uint32 type; 183 pci_info info; 184 status = get_next_radeon_hd(&cookie, info, type); 185 186 put_module(B_PCI_MODULE_NAME); 187 return status; 188 } 189 190 191 extern "C" status_t 192 init_driver(void) 193 { 194 TRACE("%s\n", __func__); 195 196 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 197 if (status != B_OK) { 198 dprintf(DEVICE_NAME ": ERROR: pci module unavailable\n"); 199 return status; 200 } 201 202 mutex_init(&gLock, "radeon hd ksync"); 203 204 // find devices 205 206 int32 found = 0; 207 208 for (int32 cookie = 0; found < MAX_CARDS;) { 209 pci_info* info = (pci_info*)malloc(sizeof(pci_info)); 210 if (info == NULL) 211 break; 212 213 uint32 type; 214 status = get_next_radeon_hd(&cookie, *info, type); 215 if (status < B_OK) { 216 free(info); 217 break; 218 } 219 220 // create device names & allocate device info structure 221 222 char name[64]; 223 sprintf(name, "graphics/radeon_hd_%02x%02x%02x", 224 info->bus, info->device, 225 info->function); 226 227 gDeviceNames[found] = strdup(name); 228 if (gDeviceNames[found] == NULL) 229 break; 230 231 gDeviceInfo[found] = (radeon_info*)malloc(sizeof(radeon_info)); 232 if (gDeviceInfo[found] == NULL) { 233 free(gDeviceNames[found]); 234 break; 235 } 236 237 // initialize the structure for later use 238 239 memset(gDeviceInfo[found], 0, sizeof(radeon_info)); 240 gDeviceInfo[found]->init_status = B_NO_INIT; 241 gDeviceInfo[found]->id = found; 242 gDeviceInfo[found]->pci = info; 243 gDeviceInfo[found]->registers = (uint8 *)info->u.h0.base_registers[0]; 244 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 245 gDeviceInfo[found]->device_chipset = kSupportedDevices[type].chipset; 246 247 dprintf(DEVICE_NAME ": GPU(%ld) %s, revision = 0x%x\n", found, 248 kSupportedDevices[type].name, info->revision); 249 250 found++; 251 } 252 253 gDeviceNames[found] = NULL; 254 255 if (found == 0) { 256 mutex_destroy(&gLock); 257 put_module(B_AGP_GART_MODULE_NAME); 258 put_module(B_PCI_MODULE_NAME); 259 return ENODEV; 260 } 261 262 return B_OK; 263 } 264 265 266 extern "C" void 267 uninit_driver(void) 268 { 269 TRACE("%s\n", __func__); 270 271 mutex_destroy(&gLock); 272 273 // free device related structures 274 char* name; 275 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 276 free(gDeviceInfo[index]); 277 free(name); 278 } 279 280 put_module(B_PCI_MODULE_NAME); 281 } 282 283 284 extern "C" device_hooks* 285 find_device(const char* name) 286 { 287 int index; 288 289 TRACE("%s\n", __func__); 290 291 for (index = 0; gDeviceNames[index] != NULL; index++) { 292 if (!strcmp(name, gDeviceNames[index])) 293 return &gDeviceHooks; 294 } 295 296 return NULL; 297 } 298 299