|
|
1.1 ! root 1: /* Copyright (c) 1992, 1993, 1994 NeXT Computer, Inc. All rights reserved. ! 2: * ! 3: * ATI.m - ATI display driver. ! 4: * ! 5: * HISTORY ! 6: * 07 Oct 92 Joe Pasqua ! 7: * Created. ! 8: * 01 June 93 Mike Paquette ! 9: * Rewrite: Convert from Corsair device driver to general MACH32 chipset ! 10: * driver. Add support for multiple DACs and CRT setups. ! 11: * Add 8 bit monochrome support. Add support for non-Cosair ! 12: * implementations. ! 13: * 7 July 1993 Derek B Clegg ! 14: * Cleaned up for external release. ! 15: * Mon Aug 15 17:18:12 PDT 1994 James C. Lee ! 16: * add 8-bit color support by integrating Peter Graffagnino's mods ! 17: */ ! 18: ! 19: #import <driverkit/generalFuncs.h> ! 20: #import <driverkit/i386/ioPorts.h> ! 21: #import <driverkit/i386/directDevice.h> ! 22: #import <driverkit/i386/IOEISADeviceDescription.h> ! 23: #import <ansi/string.h> ! 24: #import "ATI.h" ! 25: ! 26: #define ONE_MEG (1024 * 1024) ! 27: ! 28: @implementation ATI ! 29: ! 30: static void ! 31: UnlockShadowSet(int set) ! 32: { ! 33: outb(SHADOW_SET, 2); ! 34: outb(SHADOW_CNTL, 0); ! 35: outb(SHADOW_SET, 1); ! 36: outb(SHADOW_CNTL, 0); ! 37: outb(SHADOW_SET, set); ! 38: } ! 39: ! 40: static void ! 41: LockShadowSet(void) ! 42: { ! 43: outb(SHADOW_SET, 1); ! 44: outb(SHADOW_CNTL, 0x3F); ! 45: outb(SHADOW_SET, 2); ! 46: outb(SHADOW_CNTL, 0x3F); ! 47: outb(SHADOW_SET, 0); ! 48: } ! 49: ! 50: static void ! 51: ProgramShadowSet(int set, const ATI_CRTCSetup *setup) ! 52: { ! 53: UnlockShadowSet(set); ! 54: ! 55: outb(DISP_CNTL, 0x53); /* Reset, blanking display. */ ! 56: outb(H_TOTAL, setup->h_total); ! 57: outb(H_DISP, setup->h_disp); ! 58: outb(H_SYNC_START, setup->h_sync_start); ! 59: outb(H_SYNC_WIDTH, setup->h_sync_wid); ! 60: outw(V_TOTAL, setup->v_total); ! 61: outw(V_DISP, setup->v_disp); ! 62: outw(V_SYNC_START, setup->v_sync_start); ! 63: outb(V_SYNC_WID, setup->v_sync_wid); ! 64: outb(DISP_CNTL, setup->disp_cntl); ! 65: outw(CLOCK_SELECT, setup->clock_select); ! 66: ! 67: /* Zero overscan registers to avoid weird borders. */ ! 68: outw(HORIZONTAL_OVERSCAN, 0); ! 69: outw(VERTICAL_OVERSCAN, 0); ! 70: outb(OVERSCAN_COLOR_BLUE, 0); ! 71: outb(OVERSCAN_COLOR_GREEN, 0); ! 72: outb(OVERSCAN_COLOR_RED, 0); ! 73: ! 74: LockShadowSet(); ! 75: } ! 76: ! 77: static void ! 78: SelectShadowSet(int set) ! 79: { ! 80: unsigned char v; ! 81: ! 82: switch (set) { ! 83: case 0: ! 84: v = 2; ! 85: break; ! 86: case 1: ! 87: v = 3; ! 88: break; ! 89: case 2: ! 90: v = 7; ! 91: break; ! 92: default: ! 93: return; ! 94: } ! 95: outb(ADVFUNC_CNTL, v); ! 96: } ! 97: ! 98: static void ! 99: SetMemOffset(void) ! 100: { ! 101: unsigned int vga_boundary; ! 102: ! 103: /* Get the video memory boundary, in 256K pages. The 8514 controller ! 104: * cannot access memory below this, and the VGA controller cannot ! 105: * access memory above this. */ ! 106: vga_boundary = inb(MEM_BNDRY) & 0x0f; ! 107: ! 108: /* Set the start of the CRT buffer to match the start of the ! 109: * 8514 controller VRAM address. We also set up the graphics engine... */ ! 110: outb(GE_OFFSET_HI, vga_boundary); ! 111: outb(CRT_OFFSET_HI, vga_boundary); ! 112: outb(GE_OFFSET_LO, 0); ! 113: outb(CRT_OFFSET_LO, 0); ! 114: } ! 115: ! 116: /* ! 117: * Returns the physical base address of the memory aperature. The method ! 118: * used to decode this varies based on the BIOS and Mach32 chip type. ! 119: */ ! 120: static unsigned int ! 121: MemoryAperatureBaseAddress(void) ! 122: { ! 123: unsigned char *ip; ! 124: unsigned int location; /* Base address in Mbytes */ ! 125: ! 126: /* ! 127: * The PC BIOS is broken into 2 Kb slices. On startup, the ATI BIOS ! 128: * stashes away which 2 Kb slice it live in in scratch reg 0. ! 129: */ ! 130: ip = (unsigned char *) ! 131: (((inb(ROM_SCRATCH_PAD_0) & 0x7F) * 0x800) + ATI_BIOS_BASEADDR); ! 132: ! 133: /* Look up the BIOS flag to see if it uses extended or simple format */ ! 134: if ( (ip[0x62] & 1) != 0 ) /* Corsair/Nova style BIOS */ ! 135: { ! 136: /* ! 137: * MEM_CFG+1 specifies an address from 0-127 Mb ! 138: * (MSB is always 0), and the scratch register specifies ! 139: * what the external hardware decodes, up to 4 Gb. ! 140: */ ! 141: location = ((inb(ROM_SCRATCH_PAD_0 + 1) & 0x1F) << 7) ! 142: | (inb(MEM_CFG + 1)); ! 143: } ! 144: else /* No external address decode. Just use MEM_CFG register */ ! 145: { ! 146: if ((inb(CONFIG_STATUS_2 + 1) & MEM_APERATURE_4GB_RANGE) != 0) ! 147: location = inw( MEM_CFG ) >> 4; ! 148: else ! 149: location = inb( MEM_CFG + 1 ); ! 150: } ! 151: #if DEBUG ! 152: IOLog("MemoryAperatureBaseAddress() == 0x%x\n", location * ONE_MEG); ! 153: #endif ! 154: return (location * ONE_MEG); /* Return phys address in bytes, not Mb */ ! 155: } ! 156: ! 157: /* ! 158: * Returns the physical base address of the memory aperature. The method ! 159: * used to decode this varies based on the BIOS and Mach32 chip type. ! 160: */ ! 161: static BOOL ! 162: SetMemoryAperatureBaseAddress(unsigned int newLocation) ! 163: { ! 164: unsigned char *ip; ! 165: unsigned int location; ! 166: #if DEBUG ! 167: IOLog("SetMemoryAperatureBaseAddress(0x%x)\n", newLocation ); ! 168: #endif ! 169: /* Convert location to Mbytes. Make sure it's on a 1 Mb boundry */ ! 170: if ( (newLocation & (ONE_MEG - 1)) != 0 ) ! 171: return NO; ! 172: location = newLocation / ONE_MEG; ! 173: ! 174: /* ! 175: * The PC BIOS is broken into 2 Kb slices. On startup, the ATI BIOS ! 176: * stashes away which 2 Kb slice it live in in scratch reg 0. ! 177: */ ! 178: ip = (unsigned char *) ! 179: (((inb(ROM_SCRATCH_PAD_0) & 0x7F) * 0x800) + ATI_BIOS_BASEADDR); ! 180: ! 181: /* Look up the BIOS flag to see if it uses extended or simple format */ ! 182: if ( (ip[0x62] & 1) != 0 ) /* Corsair/Nova style BIOS */ ! 183: { ! 184: /* ! 185: * It's never safe to reprogram these, as we don't know ! 186: * how to set the off-chip decoding logic. ! 187: */ ! 188: return NO; ! 189: } ! 190: else /* No external address decode. Just use MEM_CFG register */ ! 191: { ! 192: if ((inb(CONFIG_STATUS_2 + 1) & MEM_APERATURE_4GB_RANGE) != 0) ! 193: { ! 194: outw(MEM_CFG, (location << 4)|(inw( MEM_CFG ) & 0xF)); ! 195: } ! 196: else ! 197: { ! 198: if ( newLocation > ATI_LOCALBUS_VRAM_ADDRESS ) ! 199: return NO; /* Invalid addr for this config */ ! 200: outb( MEM_CFG + 1, location ); ! 201: } ! 202: } ! 203: #if DEBUG ! 204: IOLog("SetMemoryAperatureBaseAddress(0x%x) succeeds\n", newLocation ); ! 205: #endif ! 206: return YES; ! 207: } ! 208: ! 209: /* Undo our munging of the DAC. Put DAC back in a state usable by VGA mode. ! 210: */ ! 211: static void ! 212: reset_DAC(void) ! 213: { ! 214: ATI_DAC dac_type; ! 215: ! 216: /* Disable VGA passthrough mode so the DAC may be programmed. */ ! 217: outw(CLOCK_SELECT, inw(CLOCK_SELECT) | 1); ! 218: ! 219: dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7; ! 220: switch(dac_type) { ! 221: case ATI_DAC_ATT20C491: /* ATT 20C491 */ ! 222: case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */ ! 223: /* TO DO: Not tested yet */ ! 224: outw(EXT_GE_CONFIG, 0x101A); /* DAC reg 1. */ ! 225: outb(DAC_MASK, 0); /* VGA mode. */ ! 226: break; ! 227: ! 228: case ATI_DAC_68875: /* ATI or TI 34075. */ ! 229: outw(EXT_GE_CONFIG, 0x201A); /* DAC reg 1. */ ! 230: outb(INPUT_CLK_SEL, 0); /* clock 0. */ ! 231: outb(OUTPUT_CLK_SEL, 0); /* SCLK & VCLK 1. */ ! 232: outb(MUX_CNTL, 0x2D); /* MUX CNTL to 8/16. */ ! 233: ! 234: /* Set default 8 BPP delay and blank adjust. */ ! 235: outw(LOCAL_CNTL, (inw(LOCAL_CNTL) | 0x8)); ! 236: /* Set PIXEL DELAY = 3, BLANK ADJ = 0 (0xC). */ ! 237: outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xF0) | 0xC); ! 238: /* Set horizontal skew. */ ! 239: outw(HORIZONTAL_OVERSCAN, 1); ! 240: break; ! 241: ! 242: case ATI_DAC_68830: /* ATI 68830*/ ! 243: default: ! 244: /* Set PIXEL DELAY = 0, BLANK ADJ = 0. */ ! 245: outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xF0) | 0); ! 246: /* Set horizontal skew. */ ! 247: outw(HORIZONTAL_OVERSCAN, 0); ! 248: break; ! 249: } ! 250: ! 251: /* Put DAC in 6 bit mode, engine in 8 bit mode. */ ! 252: outw(EXT_GE_CONFIG, 0x001A); /* reset EXT_DAC_ADDR */ ! 253: /* Enable VGA passthrough mode. */ ! 254: outw(CLOCK_SELECT, inw(CLOCK_SELECT) & ~1); ! 255: } ! 256: ! 257: static void ! 258: program_TI34075(const ATI_DACSetup *parm, const IODisplayInfo *displayMode) ! 259: { ! 260: ATI_CRTCSetup *setup; ! 261: ! 262: /* DAC RS 3 active, 8 bit pixel width. */ ! 263: outw(EXT_GE_CONFIG, 0x201A); ! 264: outb(OUTPUT_CLK_SEL, parm->out_clk); ! 265: outb(MUX_CNTL, parm->mux); ! 266: outb(INPUT_CLK_SEL, parm->in_clk); ! 267: outw(EXT_GE_CONFIG, parm->GE_config); ! 268: outb(DAC_MASK, parm->mask); ! 269: ! 270: /* Set blank adjust and pixel delay values per parm->delay_timing. */ ! 271: outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xf0) | parm->delay_timing); ! 272: ! 273: setup = (ATI_CRTCSetup *)displayMode->parameters; ! 274: if (setup->mux_flag == 0) ! 275: return; ! 276: ! 277: /* Set PIXEL DELAY = 0, BLANK ADJ = 1. */ ! 278: outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xF0) | 1); ! 279: ! 280: UnlockShadowSet(2); ! 281: outw(CLOCK_SELECT, setup->clock_select); ! 282: LockShadowSet(); ! 283: SelectShadowSet(2); ! 284: } ! 285: ! 286: static void ! 287: program_ATI68830(const ATI_DACSetup *parm, const IODisplayInfo *displayMode) ! 288: { ! 289: /* Set pixel depth, packing, aliased monitor ID of 2. */ ! 290: outw(EXT_GE_CONFIG, parm->GE_config & 0x0fff); ! 291: } ! 292: ! 293: /* Brooktree Bt481, Bt482 or ATT 20C491 RAMDAC setup code. ! 294: * On entry, the CRT controller is programmed, and VGA passthru is disabled. ! 295: * TO DO: Test with ATT 20C491. ! 296: */ ! 297: static void ! 298: program_Bt481(const ATI_DACSetup *parm, const IODisplayInfo *displayMode) ! 299: { ! 300: /* The clock should already be set appropriately for a 'slow', or ! 301: * double-clocked DAC on entry. */ ! 302: ! 303: /* Activate the TrueColor mode in the DAC. */ ! 304: ! 305: /* DAC RS 2 active, 8 bit pixel width. */ ! 306: outw(EXT_GE_CONFIG, 0x101A); ! 307: ! 308: /* Set reg 6 to correct mode. */ ! 309: outb(DAC_MASK, parm->mode); ! 310: ! 311: /* Set blank adjust and pixel delay values. */ ! 312: outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xf0) | parm->delay_timing); ! 313: ! 314: /* Set pixel depth, packing, aliased monitor ID of 2. */ ! 315: outw(EXT_GE_CONFIG, parm->GE_config & 0x0fff); ! 316: ! 317: /* Set the appropriate DAC pixel mask. */ ! 318: outb(DAC_MASK, parm->mask); ! 319: } ! 320: ! 321: /* Set up a simple gamma corrected grayscale. We rely on the Window Server ! 322: * invoking this function once via IO_SET_TRANSFER_TABLE during startup. ! 323: */ ! 324: static void ! 325: ATISetTransferTable(const unsigned int *table, const IODisplayInfo *display, ! 326: int brightness) ! 327: { ! 328: ATI_DAC dac_type; ! 329: int g, val; ! 330: unsigned int scale; ! 331: ! 332: /* ! 333: * can only adjust ramdac for 8bit gray and 8bit color ! 334: */ ! 335: if (display == 0 || display->bitsPerPixel != IO_8BitsPerPixel || ! 336: table == 0) ! 337: return; ! 338: dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7; ! 339: ! 340: switch (dac_type) { ! 341: case ATI_DAC_68875: /* ATI or TI 34075 */ ! 342: case ATI_DAC_68830: /* ATI 68830*/ ! 343: case ATI_DAC_Bt476: ! 344: scale = 0; ! 345: break; ! 346: case ATI_DAC_ATT20C491: /* ATT 20C491 */ ! 347: case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */ ! 348: default: ! 349: scale = 2; ! 350: break; ! 351: } ! 352: ! 353: outb(DAC_W_INDEX, 0); ! 354: ! 355: if (display->colorSpace == IO_RGBColorSpace ) { ! 356: for (g = 0; g < IO_8BPP_TRANSFER_TABLE_SIZE; g++) { ! 357: val = (table[g] >> 24); ! 358: if (scale) ! 359: val >>= scale; ! 360: outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val)); ! 361: val = ((table[g] & 0xFF0000) >> 16); ! 362: if (scale) ! 363: val >>= scale; ! 364: outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val)); ! 365: val = ((table[g] & 0xFF00) >> 8); ! 366: if (scale) ! 367: val >>= scale; ! 368: outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val)); ! 369: } ! 370: } else { ! 371: for (g = 0; g < IO_8BPP_TRANSFER_TABLE_SIZE; g++) { ! 372: val = (table[g] & 0x000000FF); ! 373: if (scale) ! 374: val >>= scale; ! 375: outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val)); ! 376: outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val)); ! 377: outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val)); ! 378: } ! 379: } ! 380: } ! 381: ! 382: - (void)setupHardware ! 383: { ! 384: ATI_DAC dac_type; ! 385: const ATI_DACSetup *parm; ! 386: ! 387: SetMemOffset(); /* Set VGA VRAM memory offset. */ ! 388: ! 389: dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7; ! 390: ! 391: /* Load a register shadow set with our desired setup. */ ! 392: ! 393: /* Load CRT regs, and enable controller in appropriate mode, unblanking ! 394: * the display in the process. */ ! 395: ProgramShadowSet(2, CRTControllerSetup); ! 396: ! 397: /* Select our setup, re-enabling the CRT controller. */ ! 398: SelectShadowSet(2); ! 399: ! 400: /* At this point, the CRT timing is set, VGA passthrough is disabled, ! 401: * and the pixel clock is set. We need to place the DAC in the correct ! 402: * mode of operation. */ ! 403: ! 404: if (displayMode->bitsPerPixel == IO_15BitsPerPixel) ! 405: parm = &ATI_DAC_Setup_15BPP; ! 406: else ! 407: parm = &ATI_DAC_Setup_8BPP; ! 408: ! 409: switch (dac_type) { ! 410: case ATI_DAC_68830: /* ATI 68830*/ ! 411: program_ATI68830(parm, displayMode); ! 412: outw(HORZ_OVERSCAN, 1); ! 413: break; ! 414: ! 415: case ATI_DAC_ATT20C491: /* ATT 20C491 */ ! 416: case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */ ! 417: program_Bt481(parm, displayMode); ! 418: break; ! 419: ! 420: case ATI_DAC_68875: /* ATI or TI 34075 */ ! 421: program_TI34075(parm, displayMode); ! 422: break; ! 423: ! 424: default: ! 425: /* Bt476 or some other unusable part. */ ! 426: IOLog("%s: Unknown DAC on ATI board - ID:%d\n", [self name], dac_type); ! 427: break; ! 428: } ! 429: ! 430: /* Set the CRT pitch, in units of (pixels_per_line/8). ! 431: * CAUTION: Writing ADVFUNC_CNTL or MEM_CNTL (0xbee8) resets ! 432: * this to 1024 pixels/line. */ ! 433: outb(CRT_LINE_PITCH, CRTControllerSetup->xres >> 3); ! 434: ! 435: /* Also set the graphics engine... */ ! 436: outb(GE_PITCH, CRTControllerSetup->xres >> 3); ! 437: } ! 438: ! 439: - (vm_offset_t)prepareMemoryAperture ! 440: { ! 441: unsigned int physLoc; ! 442: vm_offset_t virtLoc; ! 443: vm_size_t length, needed_length; ! 444: ATI_DAC dac_type; ! 445: int mode, k; ! 446: BOOL valid[ATIModeCount]; ! 447: BOOL slowDAC = NO; ! 448: IORange *range; ! 449: const IODisplayInfo *displayTable; ! 450: int numTableEntries; ! 451: const IODisplayInfo *displayDefault; ! 452: ! 453: /* Set memory boundary to share. */ ! 454: outb(MEM_BNDRY, 0); ! 455: /* Enable memory aperture with a 4 Mb width, page sel for page 0. */ ! 456: outb(MEM_CFG, (inb(MEM_CFG) & 0xf0) | 0x02); ! 457: ! 458: /* Get memory aperture location (units in Mbyte). This is hardware ! 459: * and version dependent. The high 8 bits of MEM_CFG specify the ! 460: * memory aperature location between 0 and 127Mb, in 1 Mb units. ! 461: */ ! 462: range = [[self deviceDescription] memoryRangeList]; ! 463: if (range == NULL) { ! 464: IOLog("%s: No memory range set.\n", [self name]); ! 465: return 0; ! 466: } ! 467: ! 468: physLoc = 0; /* Default to Configure app settings. */ ! 469: ! 470: /* Use the Misc Options register (36EE) bits 2&3 to determine ! 471: * the amount of installed memory. 0 = 512, 1 = 1M, 2 = 2M, 3 = 4M. ! 472: * Select a timing setup based on available memory and DACs. ! 473: * We do this here instead of in goLinear so we can report the ! 474: * potential frame buffer size early in the startup sequence. ! 475: */ ! 476: dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7; ! 477: ! 478: switch (dac_type) { ! 479: case ATI_DAC_68830: /* ATI 68830*/ ! 480: case ATI_DAC_68875: /* ATI or TI 34075 */ ! 481: slowDAC = NO; ! 482: break; ! 483: case ATI_DAC_ATT20C491: /* ATT 20C491 */ ! 484: case ATI_DAC_Bt476: /* Brooktree Bt476, Bt478 */ ! 485: case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */ ! 486: default: ! 487: /* These DACs can't handle the clock rates at 1024x768. */ ! 488: slowDAC = YES; ! 489: break; ! 490: } ! 491: ! 492: switch ((inb(MISC_OPTIONS) & 0x0c) >> 2) { ! 493: default: ! 494: case 0: /* 512 Kb VRAM. */ ! 495: return (vm_offset_t)0; ! 496: case 1: /* 1 Mb VRAM. */ ! 497: length = ONE_MEG; ! 498: break; ! 499: case 2: /* 2 Mb VRAM. */ ! 500: case 3: /* 4 Mb VRAM. */ ! 501: length = 2 * ONE_MEG; /* The most we currently need. */ ! 502: break; ! 503: } ! 504: ! 505: switch (ati_flavor) { ! 506: case ATI_EISA_Card: /* Definitely programmable address. */ ! 507: case ATILocalBusCard: /* Usually a programmable address. */ ! 508: /* Read out the full address using the mechanism endorsed by ! 509: * ATI. This mechanism is supported by ATI in their Windows ! 510: * driver, and every vendor we've tested follows it rather than ! 511: * rolling their own drivers. ! 512: */ ! 513: physLoc = MemoryAperatureBaseAddress(); ! 514: ! 515: /* If the address is in a range supported by the Mach32 ! 516: * chipset (below 128 Mb), try to program it. Otherwise, ! 517: * we'll assume the address is hardwired, and pick it up ! 518: * using the ATI endorsed addressing mechanism. */ ! 519: if ( physLoc != range->start ) ! 520: SetMemoryAperatureBaseAddress( range->start ); ! 521: /* FALL THRU */ ! 522: ! 523: default: /* Unknown device. */ ! 524: case ATI_NovaCard: /* Not programmable in prototypes tested. */ ! 525: case ATICorsair: /* Not programmable. */ ! 526: /* Read out the full address using the mechanism endorsed by ! 527: * ATI. This mechanism is supported by ATI in their Windows ! 528: * driver, and every vendor we've tested follows it rather than ! 529: * rolling their own drivers. ! 530: */ ! 531: physLoc = MemoryAperatureBaseAddress(); ! 532: ! 533: /* If the address doesn't match the one set in Configure, complain. ! 534: * We then override the Configure address with the address reported ! 535: * by the hardware. This gives the driver a fighting chance of ! 536: * working correctly, and works around a bug in 3.1 Configure and ! 537: * DriverKit which prevents setting addresses in the high 2 Gb of ! 538: * address space. ! 539: */ ! 540: if (range->start != physLoc || range->size < length) { ! 541: IOLog("%s: FB addr decodes as 0x%x, overriding configured " ! 542: "addr 0x%x.\n", [self name], physLoc, range->start); ! 543: ! 544: /* Force the range to match the hardware config, ! 545: * so the Window Server will work correctly. */ ! 546: range->start = physLoc; ! 547: range->size = length; ! 548: /* Reprogram the device description with usable values. */ ! 549: [[self deviceDescription] setMemoryRangeList:range ! 550: num:[[self deviceDescription] numMemoryRanges]]; ! 551: } ! 552: break; ! 553: } ! 554: ! 555: /* Enable kernel access with the appropriate mapping. */ ! 556: ! 557: virtLoc = [self mapFrameBufferAtPhysicalAddress:physLoc length:length]; ! 558: if (virtLoc == 0) ! 559: return virtLoc; ! 560: ! 561: /* If the DAC is a slow double-clocked part (ATT20C491, Bt481) use ! 562: * the special setup for the part. */ ! 563: ! 564: if (slowDAC == YES) { ! 565: displayTable = ATISlowDACMode; ! 566: numTableEntries = ATISlowDACModeCount; ! 567: displayDefault = &ATISlowDACMode[ATI_DEFAULT_SlowDAC_MODE]; ! 568: } else { ! 569: displayTable = ATIMode; ! 570: numTableEntries = ATIModeCount; ! 571: displayDefault = (length > ONE_MEG) ? &ATIMode[ATI_DEFAULT_2MEG_MODE] ! 572: : &ATIMode[ATI_DEFAULT_1MEG_MODE]; ! 573: } ! 574: ! 575: /* Determine which entries are valid for the amount of memory in the ! 576: * system. */ ! 577: ! 578: for (k = 0; k < numTableEntries; k++) { ! 579: needed_length = displayTable[k].width * displayTable[k].height; ! 580: if (displayTable[k].bitsPerPixel != IO_8BitsPerPixel) ! 581: needed_length *= sizeof(short); ! 582: valid[k] = (needed_length <= length); ! 583: /* The 68830 DAC can't handle higher res than 1024x768. */ ! 584: if ( dac_type == ATI_DAC_68830 && displayTable[k].width > 1024 ) ! 585: valid[k] = NO; ! 586: } ! 587: ! 588: /* Look up the correct entry to use. */ ! 589: mode = [self selectMode:displayTable count:numTableEntries valid:valid]; ! 590: if (mode < 0) ! 591: displayMode = displayDefault; ! 592: else ! 593: displayMode = &displayTable[mode]; ! 594: CRTControllerSetup = (ATI_CRTCSetup *)displayMode->parameters; ! 595: return virtLoc; ! 596: } ! 597: ! 598: - (void)establishLinearFB ! 599: { ! 600: /* Local Bus timing magic */ ! 601: if ( inw( MACH32_STEP6_ID_REG ) != MACH32_STEP6_ID_VALUE ) ! 602: { ! 603: asm volatile( ! 604: "pushl %eax; \n" ! 605: "pushl %edx; \n" ! 606: "; \n" ! 607: "movl 0x01CE, %edx; \n" ! 608: "movl 0xAE, %eax; \n" ! 609: "outb %al, %dx; \n" ! 610: "incl %edx; \n" ! 611: "inb %dx, %al; \n" ! 612: "andb $ ~0x10, %al; \n" ! 613: "movb %al, %ah; \n" ! 614: "movb $0xAE, %al; \n" ! 615: "decl %edx; \n" ! 616: "outw %ax, %dx; \n" ! 617: "; \n" ! 618: "movl $0x2185,%eax; \n" ! 619: "outw %ax,%dx; \n" ! 620: "; \n" ! 621: "movl $0x01CE, %edx; \n" ! 622: "movl $0xAE, %eax; \n" ! 623: "outb %al, %dx; \n" ! 624: "incl %edx; \n" ! 625: "inb %dx, %al; \n" ! 626: "orb $ 0x10, %al; \n" ! 627: "movb %al, %ah; \n" ! 628: "movl $0xAE, %al; \n" ! 629: "decl %edx; \n" ! 630: "outw %ax, %dx; \n" ! 631: "; \n" ! 632: "popl %edx; \n" ! 633: "popl %eax; \n"); ! 634: }; ! 635: ! 636: /* Program controller to 16bpp or 8bpp mode. */ ! 637: [self setupHardware]; ! 638: } ! 639: ! 640: /* Determine whether there is an ATi chipset present. ! 641: * 1) Check for an EISA card. If found, we're done. ! 642: * 2) Check for EISA CPU board ID. If it's a Corsair, we're done. ! 643: * 3) Fallback: assume a localbus+ISA card. (No ID mechanism!) ! 644: */ ! 645: - (boolean_t)ATIPresent ! 646: { ! 647: int slot; ! 648: unsigned int product_id; ! 649: ! 650: /* First, scan for a board in an EISA slot. */ ! 651: if ([self isEISAPresent] == TRUE) { ! 652: for (slot = 1; slot < 16; slot++) { ! 653: if ([self getEISAId:&product_id forSlot:slot] == TRUE) { ! 654: switch (product_id & ~0x0f) { ! 655: case ATI_EISA_ID: ! 656: ati_flavor = ATI_EISA_Card; ! 657: return TRUE; ! 658: case ATI_NOVA_PBUS_EISA_ID: ! 659: ati_flavor = ATI_NovaCard; ! 660: return TRUE; ! 661: } ! 662: } ! 663: } ! 664: ! 665: /* Examine the EISA ID for the motherboard, found in 'slot 0'. ! 666: * Do this AFTER the slot scan, so we preferentially use boards ! 667: * in the EISA slots. ! 668: */ ! 669: if ([self getEISAId:&product_id forSlot:0] == TRUE ! 670: && (product_id & ~0x0f) == INTEL_CORSAIR_ID) { ! 671: ati_flavor = ATICorsair; ! 672: return TRUE; ! 673: } ! 674: } ! 675: ! 676: IOLog("%s: Assuming a local bus ATI card.\n", [self name]); ! 677: ati_flavor = ATILocalBusCard; ! 678: return TRUE; ! 679: } ! 680: ! 681: - (void)enterLinearMode ! 682: { ! 683: [self establishLinearFB]; ! 684: } ! 685: ! 686: - initFromDeviceDescription:deviceDescription ! 687: { ! 688: void *frameBuffer; ! 689: IODisplayInfo *display; ! 690: ! 691: if ([super initFromDeviceDescription:deviceDescription] == nil) ! 692: return [super free]; ! 693: ! 694: if (![self ATIPresent]) ! 695: return [super free]; ! 696: ! 697: display = [self displayInfo]; ! 698: frameBuffer = (void *)[self prepareMemoryAperture]; ! 699: if (frameBuffer == 0) ! 700: return nil; ! 701: *display = *displayMode; ! 702: display->frameBuffer = frameBuffer; ! 703: display->flags = IO_DISPLAY_CACHE_WRITETHROUGH; ! 704: if (displayMode->bitsPerPixel == IO_15BitsPerPixel) { ! 705: display->flags |= IO_DISPLAY_NEEDS_SOFTWARE_GAMMA_CORRECTION; ! 706: } else if (displayMode->bitsPerPixel == IO_8BitsPerPixel) { ! 707: display->flags |= IO_DISPLAY_HAS_TRANSFER_TABLE; ! 708: } ! 709: return self; ! 710: } ! 711: ! 712: - free ! 713: { ! 714: return [super free]; ! 715: } ! 716: ! 717: - (void)revertToVGAMode ! 718: { ! 719: /* Select VGA setup, re-enabling the VGA CRT controller. */ ! 720: SelectShadowSet(0); /* Select VGA CRT configuration. */ ! 721: reset_DAC(); /* Restore DAC for VGA operation. */ ! 722: [super revertToVGAMode]; /* Let superclass do generic VGA stuff. */ ! 723: } ! 724: ! 725: ! 726: /* Set the transfer tables. ! 727: */ ! 728: - setTransferTable:(const unsigned int *)table count:(int)numEntries ! 729: { ! 730: if (transferTable != 0) ! 731: IOFree(transferTable, sizeof(unsigned int)* transferTableCount); ! 732: ! 733: transferTableCount = numEntries; ! 734: ! 735: transferTable = IOMalloc(sizeof(unsigned int) * numEntries); ! 736: bcopy(table, transferTable, sizeof(unsigned int) * numEntries); ! 737: ATISetTransferTable(table, [self displayInfo], EV_SCREEN_MAX_BRIGHTNESS); ! 738: return self; ! 739: } ! 740: ! 741: /* Set the brightness to `level'. ! 742: */ ! 743: - setBrightness:(int)level token:(int)t ! 744: { ! 745: if (level < EV_SCREEN_MIN_BRIGHTNESS || level > EV_SCREEN_MAX_BRIGHTNESS) { ! 746: IOLog("%s Invalid brightness level `%d'.\n", [[self class] name], ! 747: level); ! 748: return nil; ! 749: } ! 750: brightnessLevel = level; ! 751: ATISetTransferTable(transferTable, [self displayInfo], brightnessLevel); ! 752: return self; ! 753: } ! 754: ! 755: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.