1 /* 2 Copyright (c) 2002, Thomas Kurschel 3 4 5 Part of Radeon kernel driver 6 7 Graphics card detection 8 */ 9 10 11 #include "radeon_driver.h" 12 13 #include <stdio.h> 14 15 16 // this table is gathered from different sources 17 // and may even contain some wrong entries 18 #define VENDOR_ID_ATI 0x1002 19 20 // R100 21 #define DEVICE_ID_RADEON_QD 0x5144 22 #define DEVICE_ID_RADEON_QE 0x5145 23 #define DEVICE_ID_RADEON_QF 0x5146 24 #define DEVICE_ID_RADEON_QG 0x5147 25 26 // RV100 27 #define DEVICE_ID_RADEON_QY 0x5159 28 #define DEVICE_ID_RADEON_QZ 0x515a 29 30 // M6 31 #define DEVICE_ID_RADEON_LY 0x4c59 32 #define DEVICE_ID_RADEON_LZ 0x4c5a 33 34 // RV200 35 #define DEVICE_ID_RADEON_QW 0x5157 36 #define DEVICE_ID_RADEON_QX 0x5158 37 38 // R200 mobility 39 #define DEVICE_ID_RADEON_LW 0x4c57 40 #define DEVICE_ID_RADEON_LX 0x4c58 41 42 // R200 43 #define DEVICE_ID_RADEON_QH 0x5148 44 #define DEVICE_ID_RADEON_QI 0x5149 45 #define DEVICE_ID_RADEON_QJ 0x514a 46 #define DEVICE_ID_RADEON_QK 0x514b 47 #define DEVICE_ID_RADEON_QL 0x514c 48 #define DEVICE_ID_RADEON_QM 0x514d 49 50 #define DEVICE_ID_RADEON_Qh 0x5168 51 #define DEVICE_ID_RADEON_Qi 0x5169 52 #define DEVICE_ID_RADEON_Qj 0x516a 53 #define DEVICE_ID_RADEON_Qk 0x516b 54 55 #define DEVICE_ID_RADEON_BB 0x4242 56 57 // RV250 58 #define DEVICE_ID_RADEON_Id 0x4964 59 #define DEVICE_ID_RADEON_Ie 0x4965 60 #define DEVICE_ID_RADEON_If 0x4966 61 #define DEVICE_ID_RADEON_Ig 0x4967 62 63 // M9 64 #define DEVICE_ID_RADEON_Ld 0x4c64 65 #define DEVICE_ID_RADEON_Le 0x4c65 66 #define DEVICE_ID_RADEON_Lf 0x4c66 67 #define DEVICE_ID_RADEON_Lg 0x4c67 68 69 // M9+ 70 #define DEVICE_ID_RADEON_5c61 0x5c61 71 72 // RV280 73 #define DEVICE_ID_RADEON_Zprea 0x5960 74 #define DEVICE_ID_RADEON_Za 0x5961 75 #define DEVICE_ID_RADEON_Zd 0x5964 76 77 // r300 78 #define DEVICE_ID_RADEON_ND 0x4e44 79 #define DEVICE_ID_RADEON_NE 0x4e45 80 #define DEVICE_ID_RADEON_NF 0x4e46 81 #define DEVICE_ID_RADEON_NG 0x4e47 82 83 // r300-4P 84 #define DEVICE_ID_RADEON_AD 0x4144 85 #define DEVICE_ID_RADEON_AE 0x4145 86 #define DEVICE_ID_RADEON_AF 0x4146 87 #define DEVICE_ID_RADEON_AG 0x4147 88 89 // rv350 90 #define DEVICE_ID_RADEON_AP 0x4150 91 #define DEVICE_ID_RADEON_AQ 0x4151 92 93 // m10 94 #define DEVICE_ID_RADEON_NP 0x4e50 95 // Mobility Fire GL T2 - any idea about the chip? 96 #define DEVICE_ID_RADEON_NT 0x4e54 97 98 // rv360 99 #define DEVICE_ID_RADEON_AR 0x4152 100 101 // r350 102 #define DEVICE_ID_RADEON_AH 0x4148 103 #define DEVICE_ID_RADEON_NH 0x4e48 104 #define DEVICE_ID_RADEON_NI 0x4e49 105 106 // r360 107 #define DEVICE_ID_RADEON_NJ 0x4e4a 108 109 // rs100 110 #define DEVICE_ID_IGP320M 0x4336 111 112 // rs200 113 #define DEVICE_ID_RADEON_C7 0x4337 114 #define DEVICE_ID_RADEON_A7 0x4137 115 116 typedef struct { 117 uint16 device_id; 118 radeon_type asic; 119 char *name; 120 } RadeonDevice; 121 122 // list of supported devices 123 RadeonDevice radeon_device_list[] = { 124 // original Radeons, now called r100 125 { DEVICE_ID_RADEON_QD, rt_r100, "Radeon 7200 / Radeon / ALL-IN-WONDER Radeon" }, 126 { DEVICE_ID_RADEON_QE, rt_r100, "Radeon QE" }, 127 { DEVICE_ID_RADEON_QF, rt_r100, "Radeon QF" }, 128 { DEVICE_ID_RADEON_QG, rt_r100, "Radeon QG" }, 129 130 // Radeon VE (low-cost, dual CRT, no TCL), now called RV100 131 { DEVICE_ID_RADEON_QY, rt_ve, "Radeon 7000 / Radeon VE" }, 132 { DEVICE_ID_RADEON_QZ, rt_ve, "Radeon QZ VE" }, 133 134 // mobility version of original Radeon (based on VE), now called M6 135 { DEVICE_ID_RADEON_LY, rt_m6, "Radeon Mobility" }, 136 { DEVICE_ID_RADEON_LZ, rt_m6, "Radeon Mobility M6 LZ" }, 137 138 // rs100 (integrated Radeon, seems to be a Radeon VE) 139 { DEVICE_ID_IGP320M, rt_rs100, "IGP320M" }, 140 141 // RV200 (dual CRT) 142 { DEVICE_ID_RADEON_QW, rt_rv200, "Radeon 7500 / ALL-IN-WONDER Radeon 7500" }, 143 { DEVICE_ID_RADEON_QX, rt_rv200, "Radeon 7500 QX" }, 144 145 // M7 (based on RV200) 146 { DEVICE_ID_RADEON_LW, rt_m7, "Radeon Mobility 7500" }, 147 { DEVICE_ID_RADEON_LX, rt_m7, "Radeon Mobility 7500 GL" }, 148 149 // R200 150 { DEVICE_ID_RADEON_QH, rt_r200, "ATI Fire GL E1" }, // chip type: fgl8800 151 { DEVICE_ID_RADEON_QI, rt_r200, "Radeon 8500 QI" }, 152 { DEVICE_ID_RADEON_QJ, rt_r200, "Radeon 8500 QJ" }, 153 { DEVICE_ID_RADEON_QK, rt_r200, "Radeon 8500 QK" }, 154 { DEVICE_ID_RADEON_QL, rt_r200, "Radeon 8500 / 8500LE / ALL-IN-WONDER Radeon 8500" }, 155 { DEVICE_ID_RADEON_QM, rt_r200, "Radeon 9100" }, 156 157 { DEVICE_ID_RADEON_Qh, rt_r200, "Radeon 8500 Qh" }, 158 { DEVICE_ID_RADEON_Qi, rt_r200, "Radeon 8500 Qi" }, 159 { DEVICE_ID_RADEON_Qj, rt_r200, "Radeon 8500 Qj" }, 160 { DEVICE_ID_RADEON_Qk, rt_r200, "Radeon 8500 Qk" }, 161 { DEVICE_ID_RADEON_BB, rt_r200, "ALL-IN-Wonder Radeon 8500 DV" }, 162 163 // RV250 (cut-down R200 with integrated TV-Out) 164 { DEVICE_ID_RADEON_Id, rt_rv250, "Radeon 9000 Id" }, 165 { DEVICE_ID_RADEON_Ie, rt_rv250, "Radeon 9000 Ie" }, 166 { DEVICE_ID_RADEON_If, rt_rv250, "Radeon 9000" }, 167 { DEVICE_ID_RADEON_Ig, rt_rv250, "Radeon 9000 Ig" }, 168 169 // M9 (based on rv250) 170 { DEVICE_ID_RADEON_Ld, rt_m9, "Radeon Mobility 9000 Ld" }, 171 { DEVICE_ID_RADEON_Le, rt_m9, "Radeon Mobility 9000 Le" }, 172 { DEVICE_ID_RADEON_Lf, rt_m9, "Radeon Mobility 9000 Lf" }, 173 { DEVICE_ID_RADEON_Lg, rt_m9, "Radeon Mobility 9000 Lg" }, 174 175 // RV280 (rv250 with higher frequency) 176 // this entry violates naming scheme, so it's probably wrong 177 { DEVICE_ID_RADEON_Zprea, rt_rv280, "Radeon 9200" }, 178 { DEVICE_ID_RADEON_Za, rt_rv280, "Radeon 9200" }, 179 { DEVICE_ID_RADEON_Zd, rt_rv280, "Radeon 9200 SE" }, 180 181 // M9+ (based on rv280) 182 { DEVICE_ID_RADEON_5c61,rt_m9plus, "Radeon Mobility 9200" }, 183 184 // R300 185 { DEVICE_ID_RADEON_ND, rt_r300, "Radeon 9700 ND" }, 186 { DEVICE_ID_RADEON_NE, rt_r300, "Radeon 9700 NE" }, 187 { DEVICE_ID_RADEON_NF, rt_r300, "Radeon 9600 XT" }, 188 { DEVICE_ID_RADEON_NG, rt_r300, "Radeon 9700 NG" }, 189 190 { DEVICE_ID_RADEON_AD, rt_r300, "Radeon 9700 AD" }, 191 { DEVICE_ID_RADEON_AE, rt_r300, "Radeon 9700 AE" }, 192 { DEVICE_ID_RADEON_AF, rt_r300, "Radeon 9700 AF" }, 193 { DEVICE_ID_RADEON_AG, rt_r300, "Radeon 9700 AG" }, 194 195 // RV350 196 { DEVICE_ID_RADEON_AP, rt_rv350, "Radeon 9600 AP" }, 197 { DEVICE_ID_RADEON_AQ, rt_rv350, "Radeon 9600 AQ" }, 198 199 // M10 (based on rv350) 200 { DEVICE_ID_RADEON_NP, rt_m10, "Radeon Mobility 9600 NP" }, 201 // not sure about that: ROM signature is "RADEON" which means r100 202 { DEVICE_ID_RADEON_NT, rt_m10, "Radeon Mobility FireGL T2" }, 203 204 // RV360 (probably minor revision of rv350) 205 { DEVICE_ID_RADEON_AR, rt_rv360, "Radeon 9600 AR" }, 206 207 // R350 208 { DEVICE_ID_RADEON_AH, rt_r350, "Radeon 9800 AH" }, 209 { DEVICE_ID_RADEON_NH, rt_r350, "Radeon 9800 Pro NH" }, 210 { DEVICE_ID_RADEON_NI, rt_r350, "Radeon 9800 NI" }, 211 212 // R360 (probably minor revision of r350) 213 { DEVICE_ID_RADEON_NJ, rt_r360, "Radeon 9800 XT" }, 214 215 // rs100 (aka IGP 320) 216 { DEVICE_ID_IGP320M, rt_rs100, "Radeon IGP 320M" }, 217 218 // rs200 (aka IGP 340) 219 { DEVICE_ID_RADEON_C7, rt_rs200, "IGP330M/340M/350M (U2) 4337" }, 220 { DEVICE_ID_RADEON_A7, rt_rs200, "IGP 340" }, 221 222 { 0, 0, NULL } 223 }; 224 225 226 // list of supported vendors (there aren't many ;) 227 static struct { 228 uint16 vendor_id; 229 RadeonDevice *devices; 230 } SupportedVendors[] = { 231 { VENDOR_ID_ATI, radeon_device_list }, 232 { 0x0000, NULL } 233 }; 234 235 // check, whether there is *any* supported card plugged in 236 bool Radeon_CardDetect( void ) 237 { 238 long pci_index = 0; 239 pci_info pcii; 240 bool found_one = FALSE; 241 242 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK) 243 return B_ERROR; 244 245 while ((*pci_bus->get_nth_pci_info)(pci_index, &pcii) == B_NO_ERROR) { 246 int vendor = 0; 247 248 while (SupportedVendors[vendor].vendor_id) { 249 if (SupportedVendors[vendor].vendor_id == pcii.vendor_id) { 250 RadeonDevice *devices = SupportedVendors[vendor].devices; 251 252 while (devices->device_id) { 253 if (devices->device_id == pcii.device_id ) { 254 rom_info ri; 255 256 if( Radeon_MapBIOS( &pcii, &ri ) == B_OK ) { 257 Radeon_UnmapBIOS( &ri ); 258 259 SHOW_INFO( 0, "found supported device pci index %ld, device 0x%04x/0x%04x", 260 pci_index, pcii.vendor_id, pcii.device_id ); 261 found_one = TRUE; 262 goto done; 263 } 264 } 265 devices++; 266 } 267 } 268 vendor++; 269 } 270 271 pci_index++; 272 } 273 SHOW_INFO0( 0, "no supported devices found" ); 274 275 done: 276 put_module(B_PCI_MODULE_NAME); 277 278 return (found_one ? B_OK : B_ERROR); 279 } 280 281 // !extend this array whenever a new ASIC is a added! 282 static struct { 283 const char *name; // name of ASIC 284 tv_chip_type tv_chip; // TV-Out chip (if any) 285 bool has_crtc2; // has second CRTC 286 bool is_mobility; // mobility chip 287 bool has_vip; // has VIP/I2C 288 bool new_pll; // reference divider of PPLL moved to other location 289 bool is_igp; // integrated graphics 290 } asic_properties[] = 291 { 292 { "r100", tc_external_rt1, false, false, true, false, false }, // only original Radeons have one crtc only 293 { "ve", tc_internal_rt1, true, false, true, false, false }, 294 { "m6", tc_internal_rt1, true, true, false, false, false }, 295 { "rs100", tc_internal_rt1, true, true, false, false, true }, 296 { "rv200", tc_internal_rt2, true, false, true, false, false }, 297 { "m7", tc_internal_rt1, true, true, false, false, false }, 298 { "rs200", tc_internal_rt1, true, true, false, false, true }, 299 { "r200", tc_external_rt1, true, false, true, false, false }, // r200 has external TV-Out encoder 300 { "rv250", tc_internal_rt2, true, false, true, false, false }, 301 { "m9", tc_internal_rt2, true, true, false, false, false }, 302 { "rv280", tc_internal_rt2, true, false, true, false, false }, 303 { "m9plus", tc_internal_rt2, true, true, false, false, false }, 304 { "r300", tc_internal_rt2, true, false, true, true, false }, 305 { "r300_4p",tc_internal_rt2, true, false, true, true, false }, 306 { "rv350", tc_internal_rt2, true, false, true, true, false }, 307 { "m10", tc_internal_rt2, true, true, false, true, false }, 308 { "rv360", tc_internal_rt2, true, false, true, true, false }, 309 { "r350", tc_internal_rt2, true, false, true, true, false }, 310 { "r360", tc_internal_rt2, true, false, true, true, false } 311 }; 312 313 314 // get next supported device 315 static bool probeDevice( device_info *di ) 316 { 317 int vendor; 318 319 /* if we match a supported vendor */ 320 for( vendor = 0; SupportedVendors[vendor].vendor_id; ++vendor ) { 321 RadeonDevice *device; 322 323 if( SupportedVendors[vendor].vendor_id != di->pcii.vendor_id ) 324 continue; 325 326 for( device = SupportedVendors[vendor].devices; device->device_id; ++device ) { 327 // avoid double-detection 328 if (device->device_id != di->pcii.device_id ) 329 continue; 330 331 di->num_crtc = asic_properties[device->asic].has_crtc2 ? 2 : 1; 332 di->tv_chip = asic_properties[device->asic].tv_chip; 333 di->asic = device->asic; 334 di->is_mobility = asic_properties[device->asic].is_mobility; 335 di->has_vip = asic_properties[device->asic].has_vip; 336 di->new_pll = asic_properties[device->asic].new_pll; 337 di->is_igp = asic_properties[device->asic].is_igp; 338 339 if( Radeon_MapBIOS( &di->pcii, &di->rom ) != B_OK ) 340 // give up checking this device - no BIOS, no fun 341 return false; 342 343 if( Radeon_ReadBIOSData( di ) != B_OK ) { 344 Radeon_UnmapBIOS( &di->rom ); 345 return false; 346 } 347 348 // we don't need BIOS any more 349 Radeon_UnmapBIOS( &di->rom ); 350 351 SHOW_INFO( 0, "found %s; ASIC: %s", device->name, asic_properties[device->asic].name ); 352 353 sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X", 354 di->pcii.vendor_id, di->pcii.device_id, 355 di->pcii.bus, di->pcii.device, di->pcii.function); 356 SHOW_FLOW( 3, "making /dev/%s", di->name ); 357 358 // we always publish it as a video grabber; we should check for Rage 359 // Theater, but the corresponding code (vip.c) needs a fully initialized 360 // driver, and this is too much hazzly, so we leave it to the media add-on 361 // to verify that the card really supports video-in 362 sprintf(di->video_name, "video/radeon/%04X_%04X_%02X%02X%02X", 363 di->pcii.vendor_id, di->pcii.device_id, 364 di->pcii.bus, di->pcii.device, di->pcii.function); 365 366 di->is_open = 0; 367 di->shared_area = -1; 368 di->si = NULL; 369 370 return true; 371 } 372 } 373 374 return false; 375 } 376 377 378 // gather list of supported devices 379 // (currently, we rely on proper BIOS detection, which 380 // only works for primary graphics adapter, so multiple 381 // devices won't really work) 382 void Radeon_ProbeDevices( void ) 383 { 384 uint32 pci_index = 0; 385 uint32 count = 0; 386 device_info *di = devices->di; 387 388 while( count < MAX_DEVICES ) { 389 memset( di, 0, sizeof( *di )); 390 391 if( (*pci_bus->get_nth_pci_info)(pci_index, &(di->pcii)) != B_NO_ERROR) 392 break; 393 394 if( probeDevice( di )) { 395 devices->device_names[2*count] = di->name; 396 devices->device_names[2*count+1] = di->video_name; 397 di++; 398 count++; 399 } 400 401 pci_index++; 402 } 403 404 devices->count = count; 405 devices->device_names[2*count] = NULL; 406 407 SHOW_INFO( 0, "%ld supported devices", count ); 408 } 409