home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1992, 1993, 1994 NeXT Computer, Inc. All rights reserved.
- *
- * ATI.m - ATI display driver.
- *
- * HISTORY
- * 07 Oct 92 Joe Pasqua
- * Created.
- * 01 June 93 Mike Paquette
- * Rewrite: Convert from Corsair device driver to general MACH32 chipset
- * driver. Add support for multiple DACs and CRT setups.
- * Add 8 bit monochrome support. Add support for non-Cosair
- * implementations.
- * 7 July 1993 Derek B Clegg
- * Cleaned up for external release.
- * Mon Aug 15 17:18:12 PDT 1994 James C. Lee
- * add 8-bit color support by integrating Peter Graffagnino's mods
- */
-
- #import <driverkit/generalFuncs.h>
- #import <driverkit/i386/ioPorts.h>
- #import <driverkit/i386/directDevice.h>
- #import <driverkit/i386/IOEISADeviceDescription.h>
- #import <ansi/string.h>
- #import "ATI.h"
-
- #define ONE_MEG (1024 * 1024)
-
- @implementation ATI
-
- static void
- UnlockShadowSet(int set)
- {
- outb(SHADOW_SET, 2);
- outb(SHADOW_CNTL, 0);
- outb(SHADOW_SET, 1);
- outb(SHADOW_CNTL, 0);
- outb(SHADOW_SET, set);
- }
-
- static void
- LockShadowSet(void)
- {
- outb(SHADOW_SET, 1);
- outb(SHADOW_CNTL, 0x3F);
- outb(SHADOW_SET, 2);
- outb(SHADOW_CNTL, 0x3F);
- outb(SHADOW_SET, 0);
- }
-
- static void
- ProgramShadowSet(int set, const ATI_CRTCSetup *setup)
- {
- UnlockShadowSet(set);
-
- outb(DISP_CNTL, 0x53); /* Reset, blanking display. */
- outb(H_TOTAL, setup->h_total);
- outb(H_DISP, setup->h_disp);
- outb(H_SYNC_START, setup->h_sync_start);
- outb(H_SYNC_WIDTH, setup->h_sync_wid);
- outw(V_TOTAL, setup->v_total);
- outw(V_DISP, setup->v_disp);
- outw(V_SYNC_START, setup->v_sync_start);
- outb(V_SYNC_WID, setup->v_sync_wid);
- outb(DISP_CNTL, setup->disp_cntl);
- outw(CLOCK_SELECT, setup->clock_select);
-
- /* Zero overscan registers to avoid weird borders. */
- outw(HORIZONTAL_OVERSCAN, 0);
- outw(VERTICAL_OVERSCAN, 0);
- outb(OVERSCAN_COLOR_BLUE, 0);
- outb(OVERSCAN_COLOR_GREEN, 0);
- outb(OVERSCAN_COLOR_RED, 0);
-
- LockShadowSet();
- }
-
- static void
- SelectShadowSet(int set)
- {
- unsigned char v;
-
- switch (set) {
- case 0:
- v = 2;
- break;
- case 1:
- v = 3;
- break;
- case 2:
- v = 7;
- break;
- default:
- return;
- }
- outb(ADVFUNC_CNTL, v);
- }
-
- static void
- SetMemOffset(void)
- {
- unsigned int vga_boundary;
-
- /* Get the video memory boundary, in 256K pages. The 8514 controller
- * cannot access memory below this, and the VGA controller cannot
- * access memory above this. */
- vga_boundary = inb(MEM_BNDRY) & 0x0f;
-
- /* Set the start of the CRT buffer to match the start of the
- * 8514 controller VRAM address. We also set up the graphics engine... */
- outb(GE_OFFSET_HI, vga_boundary);
- outb(CRT_OFFSET_HI, vga_boundary);
- outb(GE_OFFSET_LO, 0);
- outb(CRT_OFFSET_LO, 0);
- }
-
- /*
- * Returns the physical base address of the memory aperature. The method
- * used to decode this varies based on the BIOS and Mach32 chip type.
- */
- static unsigned int
- MemoryAperatureBaseAddress(void)
- {
- unsigned char *ip;
- unsigned int location; /* Base address in Mbytes */
-
- /*
- * The PC BIOS is broken into 2 Kb slices. On startup, the ATI BIOS
- * stashes away which 2 Kb slice it live in in scratch reg 0.
- */
- ip = (unsigned char *)
- (((inb(ROM_SCRATCH_PAD_0) & 0x7F) * 0x800) + ATI_BIOS_BASEADDR);
-
- /* Look up the BIOS flag to see if it uses extended or simple format */
- if ( (ip[0x62] & 1) != 0 ) /* Corsair/Nova style BIOS */
- {
- /*
- * MEM_CFG+1 specifies an address from 0-127 Mb
- * (MSB is always 0), and the scratch register specifies
- * what the external hardware decodes, up to 4 Gb.
- */
- location = ((inb(ROM_SCRATCH_PAD_0 + 1) & 0x1F) << 7)
- | (inb(MEM_CFG + 1));
- }
- else /* No external address decode. Just use MEM_CFG register */
- {
- if ((inb(CONFIG_STATUS_2 + 1) & MEM_APERATURE_4GB_RANGE) != 0)
- location = inw( MEM_CFG ) >> 4;
- else
- location = inb( MEM_CFG + 1 );
- }
- #if DEBUG
- IOLog("MemoryAperatureBaseAddress() == 0x%x\n", location * ONE_MEG);
- #endif
- return (location * ONE_MEG); /* Return phys address in bytes, not Mb */
- }
-
- /*
- * Returns the physical base address of the memory aperature. The method
- * used to decode this varies based on the BIOS and Mach32 chip type.
- */
- static BOOL
- SetMemoryAperatureBaseAddress(unsigned int newLocation)
- {
- unsigned char *ip;
- unsigned int location;
- #if DEBUG
- IOLog("SetMemoryAperatureBaseAddress(0x%x)\n", newLocation );
- #endif
- /* Convert location to Mbytes. Make sure it's on a 1 Mb boundry */
- if ( (newLocation & (ONE_MEG - 1)) != 0 )
- return NO;
- location = newLocation / ONE_MEG;
-
- /*
- * The PC BIOS is broken into 2 Kb slices. On startup, the ATI BIOS
- * stashes away which 2 Kb slice it live in in scratch reg 0.
- */
- ip = (unsigned char *)
- (((inb(ROM_SCRATCH_PAD_0) & 0x7F) * 0x800) + ATI_BIOS_BASEADDR);
-
- /* Look up the BIOS flag to see if it uses extended or simple format */
- if ( (ip[0x62] & 1) != 0 ) /* Corsair/Nova style BIOS */
- {
- /*
- * It's never safe to reprogram these, as we don't know
- * how to set the off-chip decoding logic.
- */
- return NO;
- }
- else /* No external address decode. Just use MEM_CFG register */
- {
- if ((inb(CONFIG_STATUS_2 + 1) & MEM_APERATURE_4GB_RANGE) != 0)
- {
- outw(MEM_CFG, (location << 4)|(inw( MEM_CFG ) & 0xF));
- }
- else
- {
- if ( newLocation > ATI_LOCALBUS_VRAM_ADDRESS )
- return NO; /* Invalid addr for this config */
- outb( MEM_CFG + 1, location );
- }
- }
- #if DEBUG
- IOLog("SetMemoryAperatureBaseAddress(0x%x) succeeds\n", newLocation );
- #endif
- return YES;
- }
-
- /* Undo our munging of the DAC. Put DAC back in a state usable by VGA mode.
- */
- static void
- reset_DAC(void)
- {
- ATI_DAC dac_type;
-
- /* Disable VGA passthrough mode so the DAC may be programmed. */
- outw(CLOCK_SELECT, inw(CLOCK_SELECT) | 1);
-
- dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7;
- switch(dac_type) {
- case ATI_DAC_ATT20C491: /* ATT 20C491 */
- case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */
- /* TO DO: Not tested yet */
- outw(EXT_GE_CONFIG, 0x101A); /* DAC reg 1. */
- outb(DAC_MASK, 0); /* VGA mode. */
- break;
-
- case ATI_DAC_68875: /* ATI or TI 34075. */
- outw(EXT_GE_CONFIG, 0x201A); /* DAC reg 1. */
- outb(INPUT_CLK_SEL, 0); /* clock 0. */
- outb(OUTPUT_CLK_SEL, 0); /* SCLK & VCLK 1. */
- outb(MUX_CNTL, 0x2D); /* MUX CNTL to 8/16. */
-
- /* Set default 8 BPP delay and blank adjust. */
- outw(LOCAL_CNTL, (inw(LOCAL_CNTL) | 0x8));
- /* Set PIXEL DELAY = 3, BLANK ADJ = 0 (0xC). */
- outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xF0) | 0xC);
- /* Set horizontal skew. */
- outw(HORIZONTAL_OVERSCAN, 1);
- break;
-
- case ATI_DAC_68830: /* ATI 68830*/
- default:
- /* Set PIXEL DELAY = 0, BLANK ADJ = 0. */
- outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xF0) | 0);
- /* Set horizontal skew. */
- outw(HORIZONTAL_OVERSCAN, 0);
- break;
- }
-
- /* Put DAC in 6 bit mode, engine in 8 bit mode. */
- outw(EXT_GE_CONFIG, 0x001A); /* reset EXT_DAC_ADDR */
- /* Enable VGA passthrough mode. */
- outw(CLOCK_SELECT, inw(CLOCK_SELECT) & ~1);
- }
-
- static void
- program_TI34075(const ATI_DACSetup *parm, const IODisplayInfo *displayMode)
- {
- ATI_CRTCSetup *setup;
-
- /* DAC RS 3 active, 8 bit pixel width. */
- outw(EXT_GE_CONFIG, 0x201A);
- outb(OUTPUT_CLK_SEL, parm->out_clk);
- outb(MUX_CNTL, parm->mux);
- outb(INPUT_CLK_SEL, parm->in_clk);
- outw(EXT_GE_CONFIG, parm->GE_config);
- outb(DAC_MASK, parm->mask);
-
- /* Set blank adjust and pixel delay values per parm->delay_timing. */
- outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xf0) | parm->delay_timing);
-
- setup = (ATI_CRTCSetup *)displayMode->parameters;
- if (setup->mux_flag == 0)
- return;
-
- /* Set PIXEL DELAY = 0, BLANK ADJ = 1. */
- outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xF0) | 1);
-
- UnlockShadowSet(2);
- outw(CLOCK_SELECT, setup->clock_select);
- LockShadowSet();
- SelectShadowSet(2);
- }
-
- static void
- program_ATI68830(const ATI_DACSetup *parm, const IODisplayInfo *displayMode)
- {
- /* Set pixel depth, packing, aliased monitor ID of 2. */
- outw(EXT_GE_CONFIG, parm->GE_config & 0x0fff);
- }
-
- /* Brooktree Bt481, Bt482 or ATT 20C491 RAMDAC setup code.
- * On entry, the CRT controller is programmed, and VGA passthru is disabled.
- * TO DO: Test with ATT 20C491.
- */
- static void
- program_Bt481(const ATI_DACSetup *parm, const IODisplayInfo *displayMode)
- {
- /* The clock should already be set appropriately for a 'slow', or
- * double-clocked DAC on entry. */
-
- /* Activate the TrueColor mode in the DAC. */
-
- /* DAC RS 2 active, 8 bit pixel width. */
- outw(EXT_GE_CONFIG, 0x101A);
-
- /* Set reg 6 to correct mode. */
- outb(DAC_MASK, parm->mode);
-
- /* Set blank adjust and pixel delay values. */
- outb(MISC_CNTL + 1, (inb(R_MISC_CNTL + 1) & 0xf0) | parm->delay_timing);
-
- /* Set pixel depth, packing, aliased monitor ID of 2. */
- outw(EXT_GE_CONFIG, parm->GE_config & 0x0fff);
-
- /* Set the appropriate DAC pixel mask. */
- outb(DAC_MASK, parm->mask);
- }
-
- /* Set up a simple gamma corrected grayscale. We rely on the Window Server
- * invoking this function once via IO_SET_TRANSFER_TABLE during startup.
- */
- static void
- ATISetTransferTable(const unsigned int *table, const IODisplayInfo *display,
- int brightness)
- {
- ATI_DAC dac_type;
- int g, val;
- unsigned int scale;
-
- /*
- * can only adjust ramdac for 8bit gray and 8bit color
- */
- if (display == 0 || display->bitsPerPixel != IO_8BitsPerPixel ||
- table == 0)
- return;
- dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7;
-
- switch (dac_type) {
- case ATI_DAC_68875: /* ATI or TI 34075 */
- case ATI_DAC_68830: /* ATI 68830*/
- case ATI_DAC_Bt476:
- scale = 0;
- break;
- case ATI_DAC_ATT20C491: /* ATT 20C491 */
- case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */
- default:
- scale = 2;
- break;
- }
-
- outb(DAC_W_INDEX, 0);
-
- if (display->colorSpace == IO_RGBColorSpace ) {
- for (g = 0; g < IO_8BPP_TRANSFER_TABLE_SIZE; g++) {
- val = (table[g] >> 24);
- if (scale)
- val >>= scale;
- outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val));
- val = ((table[g] & 0xFF0000) >> 16);
- if (scale)
- val >>= scale;
- outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val));
- val = ((table[g] & 0xFF00) >> 8);
- if (scale)
- val >>= scale;
- outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val));
- }
- } else {
- for (g = 0; g < IO_8BPP_TRANSFER_TABLE_SIZE; g++) {
- val = (table[g] & 0x000000FF);
- if (scale)
- val >>= scale;
- outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val));
- outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val));
- outb(DAC_DATA, EV_SCALE_BRIGHTNESS(brightness, val));
- }
- }
- }
-
- - (void)setupHardware
- {
- ATI_DAC dac_type;
- const ATI_DACSetup *parm;
-
- SetMemOffset(); /* Set VGA VRAM memory offset. */
-
- dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7;
-
- /* Load a register shadow set with our desired setup. */
-
- /* Load CRT regs, and enable controller in appropriate mode, unblanking
- * the display in the process. */
- ProgramShadowSet(2, CRTControllerSetup);
-
- /* Select our setup, re-enabling the CRT controller. */
- SelectShadowSet(2);
-
- /* At this point, the CRT timing is set, VGA passthrough is disabled,
- * and the pixel clock is set. We need to place the DAC in the correct
- * mode of operation. */
-
- if (displayMode->bitsPerPixel == IO_15BitsPerPixel)
- parm = &ATI_DAC_Setup_15BPP;
- else
- parm = &ATI_DAC_Setup_8BPP;
-
- switch (dac_type) {
- case ATI_DAC_68830: /* ATI 68830*/
- program_ATI68830(parm, displayMode);
- outw(HORZ_OVERSCAN, 1);
- break;
-
- case ATI_DAC_ATT20C491: /* ATT 20C491 */
- case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */
- program_Bt481(parm, displayMode);
- break;
-
- case ATI_DAC_68875: /* ATI or TI 34075 */
- program_TI34075(parm, displayMode);
- break;
-
- default:
- /* Bt476 or some other unusable part. */
- IOLog("%s: Unknown DAC on ATI board - ID:%d\n", [self name], dac_type);
- break;
- }
-
- /* Set the CRT pitch, in units of (pixels_per_line/8).
- * CAUTION: Writing ADVFUNC_CNTL or MEM_CNTL (0xbee8) resets
- * this to 1024 pixels/line. */
- outb(CRT_LINE_PITCH, CRTControllerSetup->xres >> 3);
-
- /* Also set the graphics engine... */
- outb(GE_PITCH, CRTControllerSetup->xres >> 3);
- }
-
- - (vm_offset_t)prepareMemoryAperture
- {
- unsigned int physLoc;
- vm_offset_t virtLoc;
- vm_size_t length, needed_length;
- ATI_DAC dac_type;
- int mode, k;
- BOOL valid[ATIModeCount];
- BOOL slowDAC = NO;
- IORange *range;
- const IODisplayInfo *displayTable;
- int numTableEntries;
- const IODisplayInfo *displayDefault;
-
- /* Set memory boundary to share. */
- outb(MEM_BNDRY, 0);
- /* Enable memory aperture with a 4 Mb width, page sel for page 0. */
- outb(MEM_CFG, (inb(MEM_CFG) & 0xf0) | 0x02);
-
- /* Get memory aperture location (units in Mbyte). This is hardware
- * and version dependent. The high 8 bits of MEM_CFG specify the
- * memory aperature location between 0 and 127Mb, in 1 Mb units.
- */
- range = [[self deviceDescription] memoryRangeList];
- if (range == NULL) {
- IOLog("%s: No memory range set.\n", [self name]);
- return 0;
- }
-
- physLoc = 0; /* Default to Configure app settings. */
-
- /* Use the Misc Options register (36EE) bits 2&3 to determine
- * the amount of installed memory. 0 = 512, 1 = 1M, 2 = 2M, 3 = 4M.
- * Select a timing setup based on available memory and DACs.
- * We do this here instead of in goLinear so we can report the
- * potential frame buffer size early in the startup sequence.
- */
- dac_type = (inb(CONFIG_STATUS_1 + 1) >> 1) & 7;
-
- switch (dac_type) {
- case ATI_DAC_68830: /* ATI 68830*/
- case ATI_DAC_68875: /* ATI or TI 34075 */
- slowDAC = NO;
- break;
- case ATI_DAC_ATT20C491: /* ATT 20C491 */
- case ATI_DAC_Bt476: /* Brooktree Bt476, Bt478 */
- case ATI_DAC_Bt481: /* Brooktree Bt481, Bt482 */
- default:
- /* These DACs can't handle the clock rates at 1024x768. */
- slowDAC = YES;
- break;
- }
-
- switch ((inb(MISC_OPTIONS) & 0x0c) >> 2) {
- default:
- case 0: /* 512 Kb VRAM. */
- return (vm_offset_t)0;
- case 1: /* 1 Mb VRAM. */
- length = ONE_MEG;
- break;
- case 2: /* 2 Mb VRAM. */
- case 3: /* 4 Mb VRAM. */
- length = 2 * ONE_MEG; /* The most we currently need. */
- break;
- }
-
- switch (ati_flavor) {
- case ATI_EISA_Card: /* Definitely programmable address. */
- case ATILocalBusCard: /* Usually a programmable address. */
- /* Read out the full address using the mechanism endorsed by
- * ATI. This mechanism is supported by ATI in their Windows
- * driver, and every vendor we've tested follows it rather than
- * rolling their own drivers.
- */
- physLoc = MemoryAperatureBaseAddress();
-
- /* If the address is in a range supported by the Mach32
- * chipset (below 128 Mb), try to program it. Otherwise,
- * we'll assume the address is hardwired, and pick it up
- * using the ATI endorsed addressing mechanism. */
- if ( physLoc != range->start )
- SetMemoryAperatureBaseAddress( range->start );
- /* FALL THRU */
-
- default: /* Unknown device. */
- case ATI_NovaCard: /* Not programmable in prototypes tested. */
- case ATICorsair: /* Not programmable. */
- /* Read out the full address using the mechanism endorsed by
- * ATI. This mechanism is supported by ATI in their Windows
- * driver, and every vendor we've tested follows it rather than
- * rolling their own drivers.
- */
- physLoc = MemoryAperatureBaseAddress();
-
- /* If the address doesn't match the one set in Configure, complain.
- * We then override the Configure address with the address reported
- * by the hardware. This gives the driver a fighting chance of
- * working correctly, and works around a bug in 3.1 Configure and
- * DriverKit which prevents setting addresses in the high 2 Gb of
- * address space.
- */
- if (range->start != physLoc || range->size < length) {
- IOLog("%s: FB addr decodes as 0x%x, overriding configured "
- "addr 0x%x.\n", [self name], physLoc, range->start);
-
- /* Force the range to match the hardware config,
- * so the Window Server will work correctly. */
- range->start = physLoc;
- range->size = length;
- /* Reprogram the device description with usable values. */
- [[self deviceDescription] setMemoryRangeList:range
- num:[[self deviceDescription] numMemoryRanges]];
- }
- break;
- }
-
- /* Enable kernel access with the appropriate mapping. */
-
- virtLoc = [self mapFrameBufferAtPhysicalAddress:physLoc length:length];
- if (virtLoc == 0)
- return virtLoc;
-
- /* If the DAC is a slow double-clocked part (ATT20C491, Bt481) use
- * the special setup for the part. */
-
- if (slowDAC == YES) {
- displayTable = ATISlowDACMode;
- numTableEntries = ATISlowDACModeCount;
- displayDefault = &ATISlowDACMode[ATI_DEFAULT_SlowDAC_MODE];
- } else {
- displayTable = ATIMode;
- numTableEntries = ATIModeCount;
- displayDefault = (length > ONE_MEG) ? &ATIMode[ATI_DEFAULT_2MEG_MODE]
- : &ATIMode[ATI_DEFAULT_1MEG_MODE];
- }
-
- /* Determine which entries are valid for the amount of memory in the
- * system. */
-
- for (k = 0; k < numTableEntries; k++) {
- needed_length = displayTable[k].width * displayTable[k].height;
- if (displayTable[k].bitsPerPixel != IO_8BitsPerPixel)
- needed_length *= sizeof(short);
- valid[k] = (needed_length <= length);
- /* The 68830 DAC can't handle higher res than 1024x768. */
- if ( dac_type == ATI_DAC_68830 && displayTable[k].width > 1024 )
- valid[k] = NO;
- }
-
- /* Look up the correct entry to use. */
- mode = [self selectMode:displayTable count:numTableEntries valid:valid];
- if (mode < 0)
- displayMode = displayDefault;
- else
- displayMode = &displayTable[mode];
- CRTControllerSetup = (ATI_CRTCSetup *)displayMode->parameters;
- return virtLoc;
- }
-
- - (void)establishLinearFB
- {
- /* Local Bus timing magic */
- if ( inw( MACH32_STEP6_ID_REG ) != MACH32_STEP6_ID_VALUE )
- {
- asm volatile(
- "pushl %eax; \n"
- "pushl %edx; \n"
- "; \n"
- "movl 0x01CE, %edx; \n"
- "movl 0xAE, %eax; \n"
- "outb %al, %dx; \n"
- "incl %edx; \n"
- "inb %dx, %al; \n"
- "andb $ ~0x10, %al; \n"
- "movb %al, %ah; \n"
- "movb $0xAE, %al; \n"
- "decl %edx; \n"
- "outw %ax, %dx; \n"
- "; \n"
- "movl $0x2185,%eax; \n"
- "outw %ax,%dx; \n"
- "; \n"
- "movl $0x01CE, %edx; \n"
- "movl $0xAE, %eax; \n"
- "outb %al, %dx; \n"
- "incl %edx; \n"
- "inb %dx, %al; \n"
- "orb $ 0x10, %al; \n"
- "movb %al, %ah; \n"
- "movl $0xAE, %al; \n"
- "decl %edx; \n"
- "outw %ax, %dx; \n"
- "; \n"
- "popl %edx; \n"
- "popl %eax; \n");
- };
-
- /* Program controller to 16bpp or 8bpp mode. */
- [self setupHardware];
- }
-
- /* Determine whether there is an ATi chipset present.
- * 1) Check for an EISA card. If found, we're done.
- * 2) Check for EISA CPU board ID. If it's a Corsair, we're done.
- * 3) Fallback: assume a localbus+ISA card. (No ID mechanism!)
- */
- - (boolean_t)ATIPresent
- {
- int slot;
- unsigned int product_id;
-
- /* First, scan for a board in an EISA slot. */
- if ([self isEISAPresent] == TRUE) {
- for (slot = 1; slot < 16; slot++) {
- if ([self getEISAId:&product_id forSlot:slot] == TRUE) {
- switch (product_id & ~0x0f) {
- case ATI_EISA_ID:
- ati_flavor = ATI_EISA_Card;
- return TRUE;
- case ATI_NOVA_PBUS_EISA_ID:
- ati_flavor = ATI_NovaCard;
- return TRUE;
- }
- }
- }
-
- /* Examine the EISA ID for the motherboard, found in 'slot 0'.
- * Do this AFTER the slot scan, so we preferentially use boards
- * in the EISA slots.
- */
- if ([self getEISAId:&product_id forSlot:0] == TRUE
- && (product_id & ~0x0f) == INTEL_CORSAIR_ID) {
- ati_flavor = ATICorsair;
- return TRUE;
- }
- }
-
- IOLog("%s: Assuming a local bus ATI card.\n", [self name]);
- ati_flavor = ATILocalBusCard;
- return TRUE;
- }
-
- - (void)enterLinearMode
- {
- [self establishLinearFB];
- }
-
- - initFromDeviceDescription:deviceDescription
- {
- void *frameBuffer;
- IODisplayInfo *display;
-
- if ([super initFromDeviceDescription:deviceDescription] == nil)
- return [super free];
-
- if (![self ATIPresent])
- return [super free];
-
- display = [self displayInfo];
- frameBuffer = (void *)[self prepareMemoryAperture];
- if (frameBuffer == 0)
- return nil;
- *display = *displayMode;
- display->frameBuffer = frameBuffer;
- display->flags = IO_DISPLAY_CACHE_WRITETHROUGH;
- if (displayMode->bitsPerPixel == IO_15BitsPerPixel) {
- display->flags |= IO_DISPLAY_NEEDS_SOFTWARE_GAMMA_CORRECTION;
- } else if (displayMode->bitsPerPixel == IO_8BitsPerPixel) {
- display->flags |= IO_DISPLAY_HAS_TRANSFER_TABLE;
- }
- return self;
- }
-
- - free
- {
- return [super free];
- }
-
- - (void)revertToVGAMode
- {
- /* Select VGA setup, re-enabling the VGA CRT controller. */
- SelectShadowSet(0); /* Select VGA CRT configuration. */
- reset_DAC(); /* Restore DAC for VGA operation. */
- [super revertToVGAMode]; /* Let superclass do generic VGA stuff. */
- }
-
-
- /* Set the transfer tables.
- */
- - setTransferTable:(const unsigned int *)table count:(int)numEntries
- {
- if (transferTable != 0)
- IOFree(transferTable, sizeof(unsigned int)* transferTableCount);
-
- transferTableCount = numEntries;
-
- transferTable = IOMalloc(sizeof(unsigned int) * numEntries);
- bcopy(table, transferTable, sizeof(unsigned int) * numEntries);
- ATISetTransferTable(table, [self displayInfo], EV_SCREEN_MAX_BRIGHTNESS);
- return self;
- }
-
- /* Set the brightness to `level'.
- */
- - setBrightness:(int)level token:(int)t
- {
- if (level < EV_SCREEN_MIN_BRIGHTNESS || level > EV_SCREEN_MAX_BRIGHTNESS) {
- IOLog("%s Invalid brightness level `%d'.\n", [[self class] name],
- level);
- return nil;
- }
- brightnessLevel = level;
- ATISetTransferTable(transferTable, [self displayInfo], brightnessLevel);
- return self;
- }
-
- @end
-