Annotation of Examples/DriverKit/ATI/ATI_reloc.tproj/ATI.m, revision 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.