Annotation of Examples/DriverKit/ATI/ATI_reloc.tproj/ATI.m, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.