home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Examples / DriverKit / S3 / S3_reloc.tproj / S3SetMode.m < prev    next >
Text File  |  1996-03-26  |  12KB  |  439 lines

  1. /* Copyright (c) 1993-1996 by NeXT Software, 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
  439.