1 /* Author: 2 Rudolf Cornelissen 4/2003-11/2004 3 */ 4 5 #define MODULE_BIT 0x00008000 6 7 #include "nm_std.h" 8 9 static status_t test_ram(void); 10 static status_t nmxxxx_general_powerup (void); 11 static status_t nm_general_bios_to_powergraphics(void); 12 13 static void nm_dump_configuration_space (void) 14 { 15 #define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \ 16 uint32 value = CFGR(reg); \ 17 MSG(("configuration_space 0x%02x %20s 0x%08x\n", \ 18 NMCFG_##reg, #reg, value)); \ 19 } while (0) 20 DUMP_CFG (DEVID, 0); 21 DUMP_CFG (DEVCTRL, 0); 22 DUMP_CFG (CLASS, 0); 23 DUMP_CFG (HEADER, 0); 24 DUMP_CFG (BASE1FB, 0); 25 DUMP_CFG (BASE2REG1,0); 26 DUMP_CFG (BASE3REG2,0); 27 DUMP_CFG (BASE4, 0); 28 DUMP_CFG (BASE5, 0); 29 DUMP_CFG (BASE6, 0); 30 DUMP_CFG (BASE7, 0); 31 DUMP_CFG (SUBSYSID1,0); 32 DUMP_CFG (ROMBASE, 0); 33 DUMP_CFG (CAPPTR, 0); 34 DUMP_CFG (CFG_1, 0); 35 DUMP_CFG (INTERRUPT,0); 36 DUMP_CFG (CFG_3, 0); 37 DUMP_CFG (CFG_4, 0); 38 DUMP_CFG (CFG_5, 0); 39 DUMP_CFG (CFG_6, 0); 40 DUMP_CFG (CFG_7, 0); 41 DUMP_CFG (CFG_8, 0); 42 DUMP_CFG (CFG_9, 0); 43 DUMP_CFG (CFG_10, 0); 44 DUMP_CFG (CFG_11, 0); 45 DUMP_CFG (CFG_12, 0); 46 DUMP_CFG (CFG_13, 0); 47 DUMP_CFG (CFG_14, 0); 48 DUMP_CFG (CFG_15, 0); 49 DUMP_CFG (CFG_16, 0); 50 DUMP_CFG (CFG_17, 0); 51 DUMP_CFG (CFG_18, 0); 52 DUMP_CFG (CFG_19, 0); 53 DUMP_CFG (CFG_20, 0); 54 DUMP_CFG (CFG_21, 0); 55 DUMP_CFG (CFG_22, 0); 56 DUMP_CFG (CFG_23, 0); 57 DUMP_CFG (CFG_24, 0); 58 DUMP_CFG (CFG_25, 0); 59 DUMP_CFG (CFG_26, 0); 60 DUMP_CFG (CFG_27, 0); 61 DUMP_CFG (CFG_28, 0); 62 DUMP_CFG (CFG_29, 0); 63 DUMP_CFG (CFG_30, 0); 64 DUMP_CFG (CFG_31, 0); 65 DUMP_CFG (CFG_32, 0); 66 DUMP_CFG (CFG_33, 0); 67 DUMP_CFG (CFG_34, 0); 68 DUMP_CFG (CFG_35, 0); 69 DUMP_CFG (CFG_36, 0); 70 DUMP_CFG (CFG_37, 0); 71 DUMP_CFG (CFG_38, 0); 72 DUMP_CFG (CFG_39, 0); 73 DUMP_CFG (CFG_40, 0); 74 DUMP_CFG (CFG_41, 0); 75 DUMP_CFG (CFG_42, 0); 76 DUMP_CFG (CFG_43, 0); 77 DUMP_CFG (CFG_44, 0); 78 DUMP_CFG (CFG_45, 0); 79 DUMP_CFG (CFG_46, 0); 80 DUMP_CFG (CFG_47, 0); 81 DUMP_CFG (CFG_48, 0); 82 DUMP_CFG (CFG_49, 0); 83 DUMP_CFG (CFG_50, 0); 84 #undef DUMP_CFG 85 } 86 87 status_t nm_general_powerup() 88 { 89 status_t status; 90 91 LOG(1,("POWERUP: Haiku Neomagic Accelerant 0.11 running.\n")); 92 93 /* detect card type and power it up */ 94 switch(CFGR(DEVID)) 95 { 96 case 0x000110c8: //NM2070 ISA 97 si->ps.card_type = NM2070; 98 LOG(4,("POWERUP: Detected MagicGraph 128 (NM2070)\n")); 99 break; 100 case 0x000210c8: //NM2090 ISA 101 si->ps.card_type = NM2090; 102 LOG(4,("POWERUP: Detected MagicGraph 128V (NM2090)\n")); 103 break; 104 case 0x000310c8: //NM2093 ISA 105 si->ps.card_type = NM2093; 106 LOG(4,("POWERUP: Detected MagicGraph 128ZV (NM2093)\n")); 107 break; 108 case 0x008310c8: //NM2097 PCI 109 si->ps.card_type = NM2097; 110 LOG(4,("POWERUP: Detected MagicGraph 128ZV+ (NM2097)\n")); 111 break; 112 case 0x000410c8: //NM2160 PCI 113 si->ps.card_type = NM2160; 114 LOG(4,("POWERUP: Detected MagicGraph 128XD (NM2160)\n")); 115 break; 116 case 0x000510c8: //NM2200 117 si->ps.card_type = NM2200; 118 LOG(4,("POWERUP: Detected MagicMedia 256AV (NM2200)\n")); 119 break; 120 case 0x002510c8: //NM2230 121 si->ps.card_type = NM2230; 122 LOG(4,("POWERUP: Detected MagicMedia 256AV+ (NM2230)\n")); 123 break; 124 case 0x000610c8: //NM2360 125 si->ps.card_type = NM2360; 126 LOG(4,("POWERUP: Detected MagicMedia 256ZX (NM2360)\n")); 127 break; 128 case 0x001610c8: //NM2380 129 si->ps.card_type = NM2380; 130 LOG(4,("POWERUP: Detected MagicMedia 256XL+ (NM2380)\n")); 131 break; 132 default: 133 LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID))); 134 return B_ERROR; 135 } 136 137 /* power up the card */ 138 status = nmxxxx_general_powerup(); 139 140 /* override memory detection if requested by user */ 141 if (si->settings.memory != 0) 142 si->ps.memory_size = si->settings.memory; 143 144 return status; 145 } 146 147 static status_t test_ram(void) 148 { 149 uint32 value, offset; 150 status_t result = B_OK; 151 152 /* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */ 153 if (si->fbc.frame_buffer == NULL) 154 { 155 LOG(8,("INIT: test_ram detected NULL pointer.\n")); 156 return B_ERROR; 157 } 158 159 for (offset = 0, value = 0x55aa55aa; offset < 256; offset++) 160 { 161 /* write testpattern to cardRAM */ 162 ((uint32 *)si->fbc.frame_buffer)[offset] = value; 163 /* toggle testpattern */ 164 value = 0xffffffff - value; 165 } 166 167 for (offset = 0, value = 0x55aa55aa; offset < 256; offset++) 168 { 169 /* readback and verify testpattern from cardRAM */ 170 if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR; 171 /* toggle testpattern */ 172 value = 0xffffffff - value; 173 } 174 return result; 175 } 176 177 /* NOTE: 178 * This routine *has* to be done *after* SetDispplayMode has been executed, 179 * or test results will not be representative! 180 * (CAS latency is dependant on nm setup on some (DRAM) boards) */ 181 status_t nm_set_cas_latency() 182 { 183 /* check current RAM access to see if we need to change anything */ 184 if (test_ram() == B_OK) 185 { 186 LOG(4,("INIT: RAM access OK.\n")); 187 return B_OK; 188 } 189 190 /* check if we read PINS at starttime so we have valid registersettings at our disposal */ 191 LOG(4,("INIT: RAM access errors; not fixable: missing coldstart specs.\n")); 192 return B_ERROR; 193 } 194 195 void nm_unlock() 196 { 197 /* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */ 198 ISAGRPHW(GRPHXLOCK, 0x26); 199 } 200 201 static status_t nmxxxx_general_powerup() 202 { 203 uint8 temp; 204 // status_t result; 205 206 LOG(4, ("INIT: powerup\n")); 207 if (si->settings.logmask & 0x80000000) nm_dump_configuration_space(); 208 209 /* set ISA registermapping to VGA colormode */ 210 temp = (ISARB(MISCR) | 0x01); 211 /* we need to wait a bit or the card will mess-up it's register values.. */ 212 snooze(10); 213 ISAWB(MISCW, temp); 214 215 /* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */ 216 ISAGRPHW(GRPHXLOCK, 0x26); 217 218 /* unlock cards CRTC registers */ 219 //don't touch: most cards get into trouble on this! 220 // ISAGRPHW(GENLOCK, 0x00); 221 222 /* initialize the shared_info struct */ 223 set_specs(); 224 /* log the struct settings */ 225 dump_specs(); 226 227 /* activate PCI access: b7 = framebuffer, b6 = registers */ 228 ISAGRPHW(IFACECTRL2, 0xc0); 229 230 /* disable VGA-mode cursor (just to be sure) */ 231 ISACRTCW(VGACURCTRL, 0x00); 232 233 /* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */ 234 /*if (si->settings.usebios || (result != B_OK)) */return nm_general_bios_to_powergraphics(); 235 236 /*power up the PLLs,LUT,DAC*/ 237 LOG(2,("INIT: powerup\n")); 238 239 /* turn off both displays and the hardcursor (also disables transfers) */ 240 nm_crtc_dpms(false, false, false); 241 nm_crtc_cursor_hide(); 242 243 /* setup sequencer clocking mode */ 244 ISASEQW(CLKMODE, 0x21); 245 246 //fixme: setup coldstart capability... 247 248 /* turn on display */ 249 nm_crtc_dpms(true, true, true); 250 251 return B_OK; 252 } 253 254 status_t nm_general_output_select() 255 { 256 /* log currently selected output */ 257 switch (nm_general_output_read() & 0x03) 258 { 259 case 0x01: 260 LOG(2, ("INIT: external CRT only mode active\n")); 261 break; 262 case 0x02: 263 LOG(2, ("INIT: internal LCD only mode active\n")); 264 break; 265 case 0x03: 266 LOG(2, ("INIT: simultaneous LCD/CRT mode active\n")); 267 break; 268 } 269 return B_OK; 270 } 271 272 uint8 nm_general_output_read() 273 { 274 uint8 size_outputs; 275 276 /* read panelsize and currently active outputs */ 277 size_outputs = ISAGRPHR(PANELCTRL1); 278 279 /* update noted currently active outputs if prudent: 280 * - tracks active output devices, even if the keyboard shortcut is used because 281 * using that key will take the selected output devices out of DPMS sleep mode 282 * if programmed via these bits; 283 * - when the shortcut key is not used, and DPMS was in a power-saving mode while 284 * programmed via these bits, an output device will (still) be shut-off. */ 285 if (si->ps.card_type < NM2200) 286 { 287 /* both output devices do DPMS via these bits. 288 * if one of the bits is on we have a valid setting if no power-saving mode 289 * is active, or the keyboard shortcut key for selecting output devices has 290 * been used during power-saving mode. */ 291 if (size_outputs & 0x03) si->ps.outputs = (size_outputs & 0x03); 292 } 293 else 294 { 295 /* check if any power-saving mode active */ 296 if (!(ISASEQR(CLKMODE) & 0x20)) 297 { 298 /* screen is on: 299 * we can 'safely' copy both output devices settings... */ 300 if (size_outputs & 0x03) 301 { 302 si->ps.outputs = (size_outputs & 0x03); 303 } 304 else 305 { 306 /* ... unless no output is active, as this is illegal then */ 307 si->ps.outputs = 0x02; 308 309 LOG(4, ("INIT: illegal outputmode detected, assuming internal mode!\n")); 310 } 311 } 312 else 313 { 314 /* screen is off: 315 * only the internal panel does DPMS via these bits, so the external setting 316 * can always be copied */ 317 si->ps.outputs &= 0xfe; 318 si->ps.outputs |= (size_outputs & 0x01); 319 /* if the panel is on, we can note that (the shortcut key has been used) */ 320 if (size_outputs & 0x02) si->ps.outputs |= 0x02; 321 } 322 } 323 324 return ((size_outputs & 0xfc) | (si->ps.outputs & 0x03)); 325 } 326 327 /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/ 328 static 329 status_t nm_general_bios_to_powergraphics() 330 { 331 uint8 temp; 332 333 LOG(2, ("INIT: Skipping card coldstart!\n")); 334 335 /* turn off display */ 336 nm_crtc_dpms(false, false, false); 337 338 /* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */ 339 /* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */ 340 ISACRTCW(MODECTL, 0xc3); 341 /* ... plain sequential memory use, more than 64Kb RAM installed, 342 * switch to graphics mode ... */ 343 ISASEQW(MEMMODE, 0x0e); 344 /* ... disable bitplane tweaking ... */ 345 /* note: 346 * NeoMagic cards have custom b4-b7 use in this register! */ 347 ISAGRPHW(ENSETRESET, 0x80); 348 /* ... no logical function tweaking with display data, no data rotation ... */ 349 ISAGRPHW(DATAROTATE, 0x00); 350 /* ... reset read map select to plane 0 ... */ 351 ISAGRPHW(READMAPSEL, 0x00); 352 /* ... set standard mode ... */ 353 ISAGRPHW(MODE, 0x00); 354 /* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again), 355 * select standard adressing ... */ 356 ISAGRPHW(MISC, 0x05); 357 /* ... disable bit masking ... */ 358 ISAGRPHW(BITMASK, 0xff); 359 /* ... attributes are in color, switch to graphics mode (again) ... */ 360 ISAATBW(MODECTL, 0x01); 361 /* ... set overscan color to black ... */ 362 ISAATBW(OSCANCOLOR, 0x00); 363 /* ... enable all color planes ... */ 364 ISAATBW(COLPLANE_EN, 0x0f); 365 /* ... reset horizontal pixelpanning ... */ 366 ISAATBW(HORPIXPAN, 0x00); 367 /* ... reset colorpalette groupselect bits ... */ 368 ISAATBW(COLSEL, 0x00); 369 /* ... do unknown standard VGA register ... */ 370 /* note: 371 * NeoMagic cards have custom b6 use in this register! */ 372 ISAATBW(0x16, 0x01); 373 /* ... and enable all four byteplanes. */ 374 ISASEQW(MAPMASK, 0x0f); 375 376 /* setup sequencer clocking mode */ 377 ISASEQW(CLKMODE, 0x21); 378 379 /* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */ 380 ISAGRPHW(FBSTADDE, 0x10); 381 382 /* this register has influence on the CRTC framebuffer offset, so reset! */ 383 //fixme: investigate further... 384 ISAGRPHW(0x15, 0x00); 385 386 /* enable fast PCI write bursts (b4-5) */ 387 temp = ((ISAGRPHR(IFACECTRL1) & 0x0f) | 0x30); 388 /* we need to wait a bit or the card will mess-up it's register values.. */ 389 snooze(10); 390 ISAGRPHW(IFACECTRL1, temp); 391 392 /* this speeds up RAM writes according to XFree driver */ 393 // fixme: don't touch until more is known: part of RAM or CORE PLL??? 394 // ISAGRPHW(SPEED, 0xc0); 395 396 /* turn on display */ 397 nm_crtc_dpms(true, true, true); 398 399 return B_OK; 400 } 401 402 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify 403 * virtual_size to the nearest valid maximum for the mode on the card if not so. 404 * Then: check if virtual_width adheres to the cards _multiple_ constraints, and 405 * create mode slopspace if not so. 406 * We use acc multiple constraints here if we expect we can use acceleration, because 407 * acc constraints are worse than CRTC constraints. 408 * 409 * Mode slopspace is reflected in fbc->bytes_per_row BTW. */ 410 status_t nm_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode) 411 { 412 /* Note: 413 * This routine assumes that the CRTC memory pitch granularity is 'smaller than', 414 * or 'equals' the acceleration engine memory pitch granularity! */ 415 416 uint32 video_pitch = 0; 417 uint32 crtc_mask; 418 uint8 depth = 8; 419 420 /* determine pixel multiple based on CRTC memory pitch constraints. 421 * (Note: Don't mix this up with CRTC timing contraints! Those are 422 * multiples of 8 for horizontal, 1 for vertical timing.) 423 * 424 * CRTC pitch constraints are 'officially' the same for all Neomagic cards */ 425 switch (si->ps.card_type) 426 { 427 case NM2070: 428 switch (target->space) 429 { 430 case B_CMAP8: crtc_mask = 0x07; depth = 8; break; 431 /* Note for NM2070 only: 432 * The following depths have bandwidth trouble (pixel noise) with the 433 * 'official' crtc_masks (used as defaults below). Masks of 0x1f are 434 * needed (confirmed 15 and 16 bit spaces) to minimize this. */ 435 //fixme: doublecheck for NM2090 and NM2093: correct code if needed! 436 case B_RGB15: crtc_mask = 0x1f; depth = 16; break; 437 case B_RGB16: crtc_mask = 0x1f; depth = 16; break; 438 case B_RGB24: crtc_mask = 0x1f; depth = 24; break; 439 default: 440 LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space)); 441 return B_ERROR; 442 } 443 break; 444 default: 445 switch (target->space) 446 { 447 case B_CMAP8: crtc_mask = 0x07; depth = 8; break; 448 case B_RGB15: crtc_mask = 0x03; depth = 16; break; 449 case B_RGB16: crtc_mask = 0x03; depth = 16; break; 450 case B_RGB24: crtc_mask = 0x07; depth = 24; break; 451 default: 452 LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space)); 453 return B_ERROR; 454 } 455 break; 456 } 457 458 /* check if we can setup this mode with acceleration: */ 459 *acc_mode = true; 460 461 /* pre-NM2200 cards don't support accelerated 24bit modes */ 462 if ((si->ps.card_type < NM2200) && (target->space == B_RGB24)) *acc_mode = false; 463 464 /* virtual_width */ 465 if (si->ps.card_type == NM2070) 466 { 467 /* confirmed NM2070 */ 468 if (target->virtual_width > 1024) *acc_mode = false; 469 } 470 else 471 { 472 /* confirmed for all cards */ 473 if (target->virtual_width > 1600) *acc_mode = false; 474 } 475 476 /* virtual_height (confirmed NM2070, NM2097, NM2160 and NM2200 */ 477 if (target->virtual_height > 1024) *acc_mode = false; 478 479 /* now check virtual_size based on CRTC constraints and modify if needed */ 480 //fixme: checkout cardspecs here!! (NM2160 can do 8192 _bytes_ at least (in theory)) 481 { 482 /* virtual_width */ 483 switch(target->space) 484 { 485 case B_CMAP8: 486 if (target->virtual_width > 16368) 487 target->virtual_width = 16368; 488 break; 489 case B_RGB15_LITTLE: 490 case B_RGB16_LITTLE: 491 if (target->virtual_width > 8184) 492 target->virtual_width = 8184; 493 break; 494 case B_RGB24_LITTLE: 495 if (target->virtual_width > 5456) 496 target->virtual_width = 5456; 497 break; 498 } 499 500 /* virtual_height: The only constraint here is the cards memory size which is 501 * checked later on in ProposeMode: virtual_height is adjusted then if needed. 502 * 'Limiting here' to the variable size that's at least available (uint16). */ 503 if (target->virtual_height > 65535) target->virtual_height = 65535; 504 } 505 506 /* OK, now we know that virtual_width is valid, and it's needing no slopspace if 507 * it was confined above, so we can finally calculate safely if we need slopspace 508 * for this mode... */ 509 if (*acc_mode) 510 { 511 if (si->ps.card_type == NM2070) 512 { 513 uint32 acc_mask = 0; 514 515 /* determine pixel multiple based on 2D engine constraints */ 516 switch (target->space) 517 { 518 case B_CMAP8: acc_mask = 0x07; break; 519 /* Note: 520 * The following depths have actual acc_masks of 0x03. 0x1f is used 521 * because on lower acc_masks more bandwidth trouble arises. 522 * (pixel noise) */ 523 //fixme: doublecheck for NM2090 and NM2093: correct code if needed! 524 case B_RGB15: acc_mask = 0x1f; break; 525 case B_RGB16: acc_mask = 0x1f; break; 526 } 527 video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask); 528 } 529 else 530 { 531 /* Note: 532 * We prefer unaccelerated modes above accelerated ones here if not enough 533 * RAM exists and the mode can be closer matched to the requested one if 534 * unaccelerated. We do this because of the large amount of slopspace 535 * sometimes needed here to keep a mode accelerated. */ 536 537 uint32 mem_avail, bytes_X_height; 538 539 /* calculate amount of available memory */ 540 mem_avail = (si->ps.memory_size * 1024); 541 if (si->settings.hardcursor) mem_avail -= si->ps.curmem_size; 542 /* helper */ 543 bytes_X_height = (depth >> 3) * target->virtual_height; 544 545 /* Accelerated modes work with a table, there are very few fixed settings.. */ 546 if (target->virtual_width == 640) video_pitch = 640; 547 else 548 if (target->virtual_width <= 800) 549 { 550 if (((800 * bytes_X_height) > mem_avail) && 551 (target->virtual_width < (800 - crtc_mask))) 552 *acc_mode = false; 553 else 554 video_pitch = 800; 555 } 556 else 557 if (target->virtual_width <= 1024) 558 { 559 if (((1024 * bytes_X_height) > mem_avail) && 560 (target->virtual_width < (1024 - crtc_mask))) 561 *acc_mode = false; 562 else 563 video_pitch = 1024; 564 } 565 else 566 if (target->virtual_width <= 1152) 567 { 568 if (((1152 * bytes_X_height) > mem_avail) && 569 (target->virtual_width < (1152 - crtc_mask))) 570 *acc_mode = false; 571 else 572 video_pitch = 1152; 573 } 574 else 575 if (target->virtual_width <= 1280) 576 { 577 if (((1280 * bytes_X_height) > mem_avail) && 578 (target->virtual_width < (1280 - crtc_mask))) 579 *acc_mode = false; 580 else 581 video_pitch = 1280; 582 } 583 else 584 if (target->virtual_width <= 1600) 585 { 586 if (((1600 * bytes_X_height) > mem_avail) && 587 (target->virtual_width < (1600 - crtc_mask))) 588 *acc_mode = false; 589 else 590 video_pitch = 1600; 591 } 592 } 593 } 594 if (!*acc_mode) 595 video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask); 596 597 LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n", 598 video_pitch, target->space)); 599 if (target->virtual_width != video_pitch) 600 LOG(2,("INIT: effective mode slopspace is %d pixels\n", 601 (video_pitch - target->virtual_width))); 602 603 /* now calculate bytes_per_row for this mode */ 604 *bytes_per_row = video_pitch * (depth >> 3); 605 606 return B_OK; 607 } 608