Annotation of Examples/DriverKit/S3/S3_reloc.tproj/S3SetMode.m, revision 1.1

1.1     ! root        1: /* Copyright (c) 1993 by NeXT Computer, Inc.
        !             2:  * All rights reserved.
        !             3:  *
        !             4:  * S3SetMode.m -- Mode support for the S3.
        !             5:  *
        !             6:  * Author:  Derek B Clegg      21 May 1993
        !             7:  * Based on work by Peter Graffagnino, 31 January 1993.
        !             8:  */
        !             9: #import <string.h>
        !            10: #import <driverkit/generalFuncs.h>
        !            11: #import <driverkit/i386/ioPorts.h>
        !            12: #import "S3.h"
        !            13: 
        !            14: /* The `S3SetMode' category of `S3'. */
        !            15: 
        !            16: @implementation S3 (SetMode)
        !            17: 
        !            18: - (void)reportConfiguration
        !            19: {
        !            20:     const char *adapterString, *busString, *memString, *dacString;
        !            21: 
        !            22:     switch (adapter) {
        !            23:     case S3_805: adapterString = "86C805"; break;
        !            24:     case S3_928: adapterString = "86C928"; break;
        !            25:     default: adapterString = "(unknown adapter)"; break;
        !            26:     }
        !            27: 
        !            28:     switch (busConfiguration) {
        !            29:     case S3_EISA_BUS: busString = "EISA"; break;
        !            30:     case S3_LOCAL_BUS: busString = "Local"; break;
        !            31:     case S3_ISA_BUS: busString = "ISA"; break;
        !            32:     default: busString = "Unknown"; break;
        !            33:     }
        !            34: 
        !            35:     switch (availableMemory) {
        !            36:     case FOUR_MEGABYTES: memString = "4 Mb VRAM"; break;
        !            37:     case THREE_MEGABYTES: memString = "3 Mb VRAM"; break;
        !            38:     case TWO_MEGABYTES: memString = "2 Mb VRAM"; break;
        !            39:     case ONE_MEGABYTE: memString = "1 Mb VRAM"; break;
        !            40:     case ONE_MEGABYTE/2: memString = "500 Kb VRAM"; break;
        !            41:     default: memString = "(unknown memory size)"; break;
        !            42:     }
        !            43: 
        !            44:     switch (dac) {
        !            45:     case Bt484: dacString = "Brooktree 484"; break;
        !            46:     case Bt485: dacString = "Brooktree 485"; break;
        !            47:     case Bt485A: dacString = "Brooktree 485A"; break;
        !            48:     case ATT20C491: dacString = "AT&T 20C491 or compatible"; break;
        !            49:     default: dacString = "Unknown"; break;
        !            50:     }
        !            51: 
        !            52:     IOLog("%s: S3 %s; %s bus; %s; %s DAC.\n", [self name], adapterString,
        !            53:          busString, memString, dacString);
        !            54: }
        !            55: 
        !            56: - determineConfiguration
        !            57: {
        !            58:     int value, lockRegisterValue;
        !            59: 
        !            60:     /* If we turn out not to be an S3, we preserve the old value
        !            61:      * of the lock register. */
        !            62: 
        !            63:     lockRegisterValue = rread(VGA_CRTC_INDEX, S3_REG_LOCK1);
        !            64:     rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, S3_LOCK1_KEY);
        !            65:     
        !            66:     /* Get the adapter type. */
        !            67: 
        !            68:     value = rread(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX);
        !            69: 
        !            70:     switch (value & S3_CHIP_ID_MASK) {
        !            71:     case S3_CHIP_ID_805:
        !            72:        adapter = S3_805;
        !            73:        modeTable = S3_805_ModeTable;
        !            74:        modeTableCount = S3_805_ModeTableCount;
        !            75:        break;
        !            76:     case S3_CHIP_ID_928:
        !            77:        adapter = S3_928;
        !            78:        modeTable = S3_928_ModeTable;
        !            79:        modeTableCount = S3_928_ModeTableCount;
        !            80:        break;
        !            81:     default:
        !            82:        IOLog("%s: Unrecognized adapter.\n", [self name]);
        !            83:        /* If we're not an S3, reset things to the way we found them.... */
        !            84:        rwrite(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX, value);
        !            85:        rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, lockRegisterValue);
        !            86:        adapter = UnknownAdapter;
        !            87:        modeTable = 0;
        !            88:        modeTableCount = 0;
        !            89:        return nil;
        !            90:        break;
        !            91:     }
        !            92: 
        !            93:     /* Get the bus and memory configuration. */
        !            94: 
        !            95:     value = rread(VGA_CRTC_INDEX, S3_CONFG_REG1_INDEX);
        !            96: 
        !            97:     busConfiguration = value & S3_BUS_SELECT_MASK;
        !            98: 
        !            99:     switch (value & S3_MEM_SIZE_MASK) {
        !           100:     case S3_HALF_MEG: availableMemory = ONE_MEGABYTE/2; break;
        !           101:     case S3_1_MEG: availableMemory = ONE_MEGABYTE; break;
        !           102:     case S3_2_MEG: availableMemory = TWO_MEGABYTES; break;
        !           103:     case S3_3_MEG: availableMemory = THREE_MEGABYTES; break;
        !           104:     case S3_4_MEG: availableMemory = FOUR_MEGABYTES; break;
        !           105:     default:
        !           106:        IOLog("%s: Unrecognized memory configuration.\n", [self name]);
        !           107:        availableMemory = 0;
        !           108:        return nil;
        !           109:     }
        !           110: 
        !           111:     [self determineDACType];
        !           112:     [self reportConfiguration];
        !           113: 
        !           114:     S3_lockRegisters();
        !           115:     return self;
        !           116: }
        !           117: 
        !           118: /* Select a display mode based on the adapter type, the bus configuration,
        !           119:  * and the memory configuration.  Return the selected mode, or -1 if no mode
        !           120:  * is valid.
        !           121:  */
        !           122: - selectMode
        !           123: {
        !           124:     int k, mode;
        !           125:     const S3Mode *modeData;
        !           126:     BOOL valid[modeTableCount];
        !           127: 
        !           128:     for (k = 0; k < modeTableCount; k++) {
        !           129:        modeData = modeTable[k].parameters;
        !           130:        valid[k] = (modeData->memSize <= availableMemory 
        !           131:                    && modeData->adapter == adapter);
        !           132:     }
        !           133: 
        !           134:     mode = [self selectMode:modeTable count:modeTableCount valid:valid];
        !           135:     if (mode < 0) {
        !           136:        IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
        !           137:        if (adapter == S3_805)
        !           138:            mode = S3_805_defaultMode;
        !           139:        else
        !           140:            mode = S3_928_defaultMode;
        !           141:     }
        !           142:     *[self displayInfo] = modeTable[mode];
        !           143:     return self;
        !           144: }
        !           145: 
        !           146: - initializeMode
        !           147: {
        !           148:     int k, count;
        !           149:     const S3Mode *mode;
        !           150:     const IODisplayInfo *displayInfo;
        !           151:     unsigned char crtc[VGA_CRTC_COUNT];
        !           152:     unsigned char miscOutput[1];
        !           153:     unsigned char xcrtc[2*S3_EXTENDED_REGISTER_MAX];
        !           154:     unsigned char modeControl[S3_MODE_COUNT];
        !           155:     unsigned char advFunctionControl[1];
        !           156: 
        !           157:     displayInfo = [self displayInfo];
        !           158:     mode = displayInfo->parameters;
        !           159:        
        !           160:     /* Turn off the screen. */
        !           161: 
        !           162:     outb(VGA_SEQ_DATA, mode->vgaData.seqx[1] | 0x20);
        !           163: 
        !           164:     /* Sequencer. */
        !           165: 
        !           166:     for (k = 0; k < VGA_SEQ_COUNT; k++) {
        !           167:        if (k == 1)
        !           168:            continue;
        !           169:        outb(VGA_SEQ_INDEX, k);
        !           170:        outb(VGA_SEQ_DATA, mode->vgaData.seqx[k]);
        !           171:     }
        !           172: 
        !           173:     S3_unlockRegisters();
        !           174: 
        !           175:     /* Unlock the CRTC registers. */
        !           176:     rrmw(VGA_CRTC_INDEX, 0x11, ~0x80, 0x00);
        !           177:     rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00);
        !           178: 
        !           179:     /* Set up the CRTC parameters. */
        !           180: 
        !           181:     count = [self parametersForMode:mode->name
        !           182:         forStringKey:"CRTC Registers" 
        !           183:         parameters:crtc
        !           184:         count:sizeof(crtc)];
        !           185:     if (count > 0) {
        !           186:        IOLog("%s: Using crtc parameters from instance table.\n", [self name]);
        !           187:        for (k = 0; k < count; k++)
        !           188:            rwrite(VGA_CRTC_INDEX, k, crtc[k]);
        !           189:     } else {
        !           190:        for (k = 0; k < VGA_CRTC_COUNT; k++)
        !           191:            rwrite(VGA_CRTC_INDEX, k, mode->vgaData.crtc[k]);
        !           192:     }
        !           193: 
        !           194:     /* Initialize the address flip-flop for the attribute controller. */
        !           195: 
        !           196:     inb(VGA_INPUT_STATUS_1);
        !           197:     /* Set up the attribute controller registers. */
        !           198:     for (k = 0; k < VGA_ATTR_COUNT; k++) {
        !           199:        outb(VGA_ATTR_INDEX, k);
        !           200:        outb(VGA_ATTR_DATA, mode->vgaData.attr[k]);
        !           201:     }
        !           202: 
        !           203:     /* Start the sequencer. */
        !           204:     rwrite(VGA_SEQ_INDEX, 0x00, 0x03);
        !           205: 
        !           206:     /* Set up the graphics controller registers. */
        !           207:     for (k = 0; k < VGA_GRFX_COUNT; k++)
        !           208:        rwrite(VGA_GRFX_INDEX, k, mode->vgaData.grfx[k]);
        !           209: 
        !           210:     /* Set the miscellaneous output register (0x3C2). */
        !           211: 
        !           212:     count = [self parametersForMode:mode->name
        !           213:         forStringKey:"MiscOutput Register" 
        !           214:         parameters:miscOutput
        !           215:         count:sizeof(miscOutput)];
        !           216:     if (count > 0) {
        !           217:        IOLog("%s: Using miscOutput parameter from instance table.\n",
        !           218:              [self name]);
        !           219:        outb(VGA_MISC_OUTPUT, miscOutput[0]);
        !           220:     } else {
        !           221:        outb(VGA_MISC_OUTPUT, mode->vgaData.miscOutput);
        !           222:     }
        !           223: 
        !           224:     /* Reset the address flip-flop for the attribute controller and
        !           225:      * enable the palette. */
        !           226:     inb(VGA_INPUT_STATUS_1);
        !           227:     outb(VGA_ATTR_INDEX, 0x20);
        !           228: 
        !           229:     /* Set up the extended CRTC registers. */
        !           230: 
        !           231:     count = [self parametersForMode:mode->name
        !           232:         forStringKey:"XCRTC Registers"
        !           233:         parameters:xcrtc
        !           234:         count:sizeof(xcrtc)];
        !           235:     if (count > 0) {
        !           236:        IOLog("%s: Using extended crtc parameters from instance table.\n",
        !           237:              [self name]);
        !           238:        for (k = 0; k < count && xcrtc[k] != 0; k += 2)
        !           239:            rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]);
        !           240:     } else {
        !           241:        for (k = 0; k < S3_XCRTC_COUNT && mode->xcrtc[k] != 0; k += 2)
        !           242:            rwrite(VGA_CRTC_INDEX, mode->xcrtc[k], mode->xcrtc[k+1]);
        !           243:     }
        !           244: 
        !           245:     /* Set the mode control register. */
        !           246:     count = [self parametersForMode:mode->name
        !           247:         forStringKey:"Mode Control Register"
        !           248:         parameters:modeControl
        !           249:         count:sizeof(modeControl)];
        !           250:     if (count > 0) {
        !           251:        IOLog("%s: Using mode control parameters from instance table.\n",
        !           252:              [self name]);
        !           253:        for (k = 0; k < count; k += 2) {
        !           254:            if (displayInfo->refreshRate == modeControl[k]/*refreshRate*/) {
        !           255:                rwrite(VGA_CRTC_INDEX, 0x42, modeControl[k+1]/*modeControl*/);
        !           256:                break;
        !           257:            }
        !           258:        }
        !           259:        if (k >= count)
        !           260:            IOLog("%s: Warning: Unable to set the refresh rate.\n",
        !           261:                  [self name]);
        !           262:     } else {
        !           263:        for (k = 0; k < S3_MODE_COUNT; k++) {
        !           264:            if (displayInfo->refreshRate == mode->modeControl[k].refreshRate) {
        !           265:                rwrite(VGA_CRTC_INDEX, 0x42, mode->modeControl[k].modeControl);
        !           266:                break;
        !           267:            }
        !           268:        }
        !           269:        if (k == S3_MODE_COUNT)
        !           270:            IOLog("%s: Warning: Unable to set the refresh rate.\n",
        !           271:                  [self name]);
        !           272:     }
        !           273: 
        !           274:     /* Unlock access to the enhanced commands registers. */
        !           275:     rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01);
        !           276: 
        !           277:     /* Set the advanced function control register (0x4AE8). */
        !           278: 
        !           279:     count = [self parametersForMode:mode->name
        !           280:         forStringKey:"Advanced Function Control Register"
        !           281:         parameters:advFunctionControl
        !           282:         count:sizeof(advFunctionControl)];
        !           283:     if (count > 0) {
        !           284:        outw(S3_ADVFUNC_CNTL, advFunctionControl[0]);
        !           285:     } else {
        !           286:        outw(S3_ADVFUNC_CNTL, mode->advFuncCntl);
        !           287:     }
        !           288: 
        !           289:     /* Lock the register set. */
        !           290:     rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x00);
        !           291: 
        !           292:     /* Program the DAC. */
        !           293:     [self programDAC];
        !           294: 
        !           295:     /* Lock the registers. */
        !           296:     S3_lockRegisters();
        !           297: 
        !           298:     /* Enable the screen */
        !           299:     rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x00);
        !           300:     return self;
        !           301: }
        !           302: 
        !           303: - enableLinearFrameBuffer
        !           304: {
        !           305:     int lawSize;
        !           306:     S3Mode *mode;
        !           307:     IODisplayInfo *displayInfo;
        !           308: 
        !           309:     displayInfo = [self displayInfo];
        !           310:     mode = displayInfo->parameters;
        !           311: 
        !           312:     S3_unlockRegisters();
        !           313: 
        !           314:     /* Tell the chip where the frame buffer is mapped in. */
        !           315: 
        !           316:     rwrite(VGA_CRTC_INDEX, S3_LAW_POS_LO, (videoRamAddress >> 16) & 0xFF);
        !           317:     rwrite(VGA_CRTC_INDEX, S3_LAW_POS_HI, (videoRamAddress >> 24) & 0xFF);
        !           318:     
        !           319:     /* Set the linear address window size. */
        !           320: 
        !           321:     switch (mode->memSize) {
        !           322:     case ONE_MEGABYTE:
        !           323:        lawSize = S3_LAW_SIZE_1M;
        !           324:        break;
        !           325:     case TWO_MEGABYTES:
        !           326:        lawSize = S3_LAW_SIZE_2M;
        !           327:        break;
        !           328:     case THREE_MEGABYTES:
        !           329:     case FOUR_MEGABYTES:
        !           330:        lawSize = S3_LAW_SIZE_4M;
        !           331:        break;
        !           332:     default:
        !           333:        IOLog("%s: Invalid linear address window size for mode `%s'.\n",
        !           334:              [self name], mode->name);
        !           335:        return nil;
        !           336:     }
        !           337:        
        !           338:     /* Set the linear address window size. */
        !           339:     rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_SIZE_MASK, lawSize);
        !           340: 
        !           341:     if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) {
        !           342:        /* Wait for the graphics accelerator to stop. */
        !           343:        while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK)
        !           344:            ;
        !           345:        /* Disable 8514 register access. */
        !           346:        rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK, 
        !           347:             S3_8514_DISABLE_ACCESS);
        !           348:     }
        !           349:     
        !           350:     /* Turn off mmio. */
        !           351:     rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_1, ~S3_MMIO_ACCESS_MASK, 
        !           352:         S3_DISABLE_MMIO_ACCESS);
        !           353:     
        !           354:     if (writePostingEnabled) {
        !           355:        /* Enable fast write buffer (write posting into FIFO). */
        !           356:        rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK, 
        !           357:             S3_WRITE_POST_ENABLE);
        !           358:     } else {
        !           359:        /* Disable fast write buffer. */
        !           360:        rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK, 
        !           361:             S3_WRITE_POST_DISABLE);
        !           362:     }
        !           363: 
        !           364:     if (readAheadCacheEnabled) {
        !           365:        /* Enable read-ahead cache. */
        !           366:        rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK, 
        !           367:             S3_ENABLE_PREFETCH);
        !           368:        /* Max out the read-ahead cache. */
        !           369:        rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_2, ~S3_PREFETCH_CTRL_MASK, 
        !           370:             S3_PREFETCH_MAX);
        !           371:     } else {
        !           372:        /* Disable read-ahead cache. */
        !           373:        rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK, 
        !           374:             S3_DISABLE_PREFETCH);
        !           375:     }
        !           376: 
        !           377:     /* Turn on the linear address window. */
        !           378:     rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_ENABLE_LAW);
        !           379: 
        !           380:     S3_lockRegisters();
        !           381: 
        !           382:     /* Clear the screen. */
        !           383:     memset(displayInfo->frameBuffer, 0, mode->memSize);
        !           384:     return self;
        !           385: }
        !           386: 
        !           387: - resetVGA
        !           388: {
        !           389:     int k;
        !           390:     static const unsigned char xcrtc[S3_XCRTC_COUNT] = {
        !           391:        0x31, 0x85, 0x32, 0x10, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
        !           392:        0x3A, 0x85, 0x3B, 0x5A, 0x3C, 0x10, 0x40, 0x58, 0x43, 0x00,
        !           393:        0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x54, 0x38, 0x56, 0x00,
        !           394:        0x57, 0x00, 0x5C, 0x31, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00,
        !           395:        0x60, 0x07, 0x61, 0x80, 0x62, 0xA1, 0x63, 0xA1,
        !           396:     };
        !           397: 
        !           398:     /* Disable the linear framebuffer. */
        !           399:     S3_unlockRegisters();
        !           400: 
        !           401:     if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) {
        !           402:        /* Wait for the graphics accelerator to stop. */
        !           403:        while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK)
        !           404:            ;
        !           405:        /* Disable 8514 register access. */
        !           406:        rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK, 
        !           407:             S3_8514_DISABLE_ACCESS);
        !           408:     }
        !           409:     
        !           410:     /* Turn off the linear address window. */
        !           411:     rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_DISABLE_LAW);
        !           412: 
        !           413:     /* Turn off the display. */
        !           414:     rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x20);
        !           415: 
        !           416:     /* Unlock the CRTC registers. */
        !           417:     rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00);
        !           418: 
        !           419:     /* Unlock access to the enhanced commands registers. */
        !           420:     rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01);
        !           421: 
        !           422:     /* Set VGA mode. */
        !           423:     outw(S3_ADVFUNC_CNTL, 0x02);
        !           424: 
        !           425:     /* Set the DAC for VGA mode. */
        !           426:     [self resetDAC];
        !           427: 
        !           428:     /* Set up the extended CRTC registers. */
        !           429:     for (k = 0; k < S3_XCRTC_COUNT && xcrtc[k] != 0; k += 2)
        !           430:        rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]);
        !           431: 
        !           432:     VGASetMode(0x03);
        !           433: 
        !           434:     S3_lockRegisters();
        !           435: 
        !           436:     return self;
        !           437: }
        !           438: @end

unix.superglobalmegacorp.com

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