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 */ 10 11 12 #include "driver.h" 13 #include "device.h" 14 #include "lock.h" 15 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <string.h> 19 20 #include <AGP.h> 21 #include <KernelExport.h> 22 #include <OS.h> 23 #include <PCI.h> 24 #include <SupportDefs.h> 25 26 27 #define TRACE_DRIVER 28 #ifdef TRACE_DRIVER 29 # define TRACE(x) dprintf x 30 #else 31 # define TRACE(x) ; 32 #endif 33 34 #define MAX_CARDS 1 35 36 37 // list of supported devices 38 const struct supported_device { 39 uint32 device_id; 40 int32 type; 41 const char* name; 42 } kSupportedDevices[] = { 43 //R600 series (HD 2xxx - 42xx) 44 // Radeon 2400 - RV610 45 {0x9611, 0, "Radeon HD 3100"}, /*RV620, IGP*/ 46 {0x9613, 0, "Radeon HD 3100"}, /*RV620, IGP*/ 47 {0x9610, 0, "Radeon HD 3200"}, /*RV620, IGP*/ 48 {0x9612, 0, "Radeon HD 3200"}, /*RV620, IGP*/ 49 {0x9615, 0, "Radeon HD 3200"}, /*RV620, IGP*/ 50 // Radeon 3410 - RV620 51 // Radeon 3430 - RV620 52 {0x95c5, 0, "Radeon HD 3450"}, /*RV620*/ 53 // Radeon 3470 - RV620 54 // Radeon 4200 - RV620 55 // Radeon 4225 - RV620 56 // Radeon 4250 - RV620 57 // Radeon 4270 - RV620 58 // Radeon 2600 - RV630 59 // Radeon 2700 - RV630 60 // Radeon 3650 - RV635 61 // Radeon 3670 - RV635 62 // Radeon 3850 - RV670 63 // Radeon 3870 - RV670 64 // Radeon 3850 x2 - RV680 65 // Radeon 3870 x2 - RV680 66 67 //R700 series (HD 43xx - HD 48xx) 68 // Radeon 4330 - RV710 69 {0x954f, 0, "Radeon HD 4350"}, /*RV710*/ 70 {0x9555, 0, "Radeon HD 4350"}, /*RV710*/ 71 // Radeon 4530 - RV710 72 {0x9540, 0, "Radeon HD 4550"} /*RV710*/ 73 // Radeon 4570 - RV710 74 // Radeon 4650 - RV730 75 // Radeon 4670 - RV730 76 // Radeon 4830 - RV740 77 // Radeon 4850 - RV770 78 // Radeon 4860 - RV740 79 // Radeon 4870 - RV770 80 // Radeon 4870 x2 - RV770 81 }; 82 83 84 const uint32 kATIVendorId = 0x1002; 85 86 87 int32 api_version = B_CUR_DRIVER_API_VERSION; 88 89 90 char* gDeviceNames[MAX_CARDS + 1]; 91 radeon_info* gDeviceInfo[MAX_CARDS]; 92 pci_module_info* gPCI; 93 mutex gLock; 94 95 96 static status_t 97 get_next_radeon_hd(int32 *_cookie, pci_info &info, uint32 &type) 98 { 99 int32 index = *_cookie; 100 101 // find devices 102 103 for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { 104 // check vendor 105 if (info.vendor_id != kATIVendorId 106 || info.class_base != PCI_display 107 || info.class_sub != PCI_vga) 108 continue; 109 110 // check device 111 for (uint32 i = 0; i < sizeof(kSupportedDevices) 112 / sizeof(kSupportedDevices[0]); i++) { 113 if (info.device_id == kSupportedDevices[i].device_id) { 114 type = i; 115 *_cookie = index + 1; 116 return B_OK; 117 } 118 } 119 } 120 121 return B_ENTRY_NOT_FOUND; 122 } 123 124 125 extern "C" const char ** 126 publish_devices(void) 127 { 128 TRACE((DEVICE_NAME ": publish_devices()\n")); 129 return (const char **)gDeviceNames; 130 } 131 132 133 extern "C" status_t 134 init_hardware(void) 135 { 136 TRACE((DEVICE_NAME ": init_hardware()\n")); 137 138 status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI); 139 if (status != B_OK) { 140 TRACE((DEVICE_NAME ": pci module unavailable\n")); 141 return status; 142 } 143 144 int32 cookie = 0; 145 uint32 type; 146 pci_info info; 147 status = get_next_radeon_hd(&cookie, info, type); 148 149 put_module(B_PCI_MODULE_NAME); 150 return status; 151 } 152 153 154 extern "C" status_t 155 init_driver(void) 156 { 157 TRACE((DEVICE_NAME ": init_driver()\n")); 158 159 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 160 if (status != B_OK) { 161 TRACE((DEVICE_NAME ": pci module unavailable\n")); 162 return status; 163 } 164 165 mutex_init(&gLock, "radeon hd ksync"); 166 167 // find devices 168 169 int32 found = 0; 170 171 for (int32 cookie = 0; found < MAX_CARDS;) { 172 pci_info* info = (pci_info*)malloc(sizeof(pci_info)); 173 if (info == NULL) 174 break; 175 176 uint32 type; 177 status = get_next_radeon_hd(&cookie, *info, type); 178 if (status < B_OK) { 179 free(info); 180 break; 181 } 182 183 // create device names & allocate device info structure 184 185 char name[64]; 186 sprintf(name, "graphics/radeon_hd_%02x%02x%02x", 187 info->bus, info->device, 188 info->function); 189 190 gDeviceNames[found] = strdup(name); 191 if (gDeviceNames[found] == NULL) 192 break; 193 194 gDeviceInfo[found] = (radeon_info*)malloc(sizeof(radeon_info)); 195 if (gDeviceInfo[found] == NULL) { 196 free(gDeviceNames[found]); 197 break; 198 } 199 200 // initialize the structure for later use 201 202 memset(gDeviceInfo[found], 0, sizeof(radeon_info)); 203 gDeviceInfo[found]->init_status = B_NO_INIT; 204 gDeviceInfo[found]->id = found; 205 gDeviceInfo[found]->pci = info; 206 gDeviceInfo[found]->registers = (uint8 *)info->u.h0.base_registers[0]; 207 gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name; 208 gDeviceInfo[found]->device_type = kSupportedDevices[type].type; 209 210 dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found, 211 kSupportedDevices[type].name, info->revision); 212 213 found++; 214 } 215 216 gDeviceNames[found] = NULL; 217 218 if (found == 0) { 219 mutex_destroy(&gLock); 220 put_module(B_AGP_GART_MODULE_NAME); 221 put_module(B_PCI_MODULE_NAME); 222 return ENODEV; 223 } 224 225 return B_OK; 226 } 227 228 229 extern "C" void 230 uninit_driver(void) 231 { 232 TRACE((DEVICE_NAME ": uninit_driver()\n")); 233 234 mutex_destroy(&gLock); 235 236 // free device related structures 237 char* name; 238 for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { 239 free(gDeviceInfo[index]); 240 free(name); 241 } 242 243 put_module(B_PCI_MODULE_NAME); 244 } 245 246 247 extern "C" device_hooks* 248 find_device(const char* name) 249 { 250 int index; 251 252 TRACE((DEVICE_NAME ": find_device()\n")); 253 254 for (index = 0; gDeviceNames[index] != NULL; index++) { 255 if (!strcmp(name, gDeviceNames[index])) 256 return &gDeviceHooks; 257 } 258 259 return NULL; 260 } 261 262