Annotation of Examples/DriverKit/S3/S3_reloc.tproj/S3SetMode.m, revision 1.1.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.