home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / oak.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-11  |  19.8 KB  |  740 lines

  1. /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen
  2.  
  3. This library is free software; you can redistribute it and/or
  4. modify it without any restrictions. This library is distributed
  5. in the hope that it will be useful, but without any warranty.
  6.  
  7. Multi-chipset support Copyright 1993 Harm Hanemaayer
  8. partially copyrighted (C) 1993 by Hartmut Schirmer
  9.  
  10. OTI-067/077/087 support driver release 1.2 (12 September 1994)
  11. Rewritten/fleshed out by Christopher Wiles (a0017097@wsuaix.csc.wsu.edu)
  12.  
  13. Features in this release: 
  14.      * _real_ 640x480x256 mode
  15.     * 800x600x16, 800x600x256 modes
  16.     * 1024x768x16, 1024x768x256 modes
  17.     * 640x480x32K, 800x600x32K modes
  18.     * 1280x1024x16 mode (untested)
  19.     * OTI-087 chipset support, including 2M variants
  20.  
  21.  
  22. Still left to do:
  23.     * linear addressing
  24.       The stubs are in the code, and can be activated by setting
  25.       OTI87_LINEAR_OK to 1 (I've set it to 0).  The '87 goes into and out
  26.       of linear mode just fine; I'm having a hell of a time getting SVGALIB
  27.       to use the linear buffer instead of the bank switched buffer at A0000.
  28.       In any event, if someone feels adventurous, the bones are present.
  29.  
  30.     * 64K/16M modes
  31.       64K/16M modes appear to be broken.  I couldn't even switch them in
  32.       from Oak's own DOS test utility ...
  33.  
  34.     * 1280x1024 modes
  35.       I've included a definition for the 16 color mode.  I couldn't test
  36.       it, as my monitor's maximum resolution is 1024x768.  According to
  37.       the documentation, a 2 meg board should be able to do an interlaced
  38.       1280x1024x256.  I couldn't force Oak's BIOS to enter that mode.
  39.       Could be because I have only 1 meg on board.
  40.  
  41. */
  42.  
  43. #include <stdio.h>
  44. #include "vga.h"
  45. #include "libvga.h"
  46. #include "driver.h"
  47. #include <sys/mman.h>
  48. #include "oak.regs"
  49.  
  50. #define OTI_MISC_DATA EXT+01
  51. #define OTI_BCOMPAT_DATA EXT+02
  52. #define OTI_SEGMENT_DATA EXT+03
  53. #define OTI_CONFIG_DATA    EXT+04
  54. #define OTI_OVERFLOW_DATA EXT+05
  55. #define OTI_HSYNC2_DATA EXT+06
  56. #define OTI_OVERFLOW2_DATA EXT+07
  57.  
  58. #define CLOCK_DATA EXT + 08
  59. #define OVERFLOW_DATA EXT + 09
  60. #define OTI87_HSYNC2_DATA EXT+10
  61. #define OTI87_XCRTC_DATA EXT+11
  62. #define OTI87_COLORS_DATA EXT+12
  63. #define OTI87_FIFO_DATA EXT+13
  64. #define OTI87_MODESELECT_DATA EXT+14
  65. #define OTI87_FEATURE_DATA EXT+15
  66. #define OTI87_XREADSEGMENT_DATA EXT+16
  67. #define OTI87_XWRITESEGMENT_DATA EXT+17
  68. #define OTI87_RAMDAC_DATA EXT+18
  69.  
  70. #define OTI_INDEX 0x3DE            /* Oak extended index register */
  71. #define OTI_R_W 0x3DF            /* Oak extended r/w register */
  72. #define OTI_CRT_CNTL 0xC        /* Oak CRT COntrol Register */
  73. #define OTI_MISC  0xD            /* Oak Misc register */
  74. #define OTI_BCOMPAT  0xE        /* Oak Back compat register */
  75. #define OTI_SEGMENT  0x11        /* Oak segment register */
  76. #define OTI_CONFIG  0x12        /* Oak config register */
  77. #define OTI_OVERFLOW  0x14        /* Oak overflow register */
  78. #define OTI_OVERFLOW2  0x16        /* Oak overflow2 register */
  79.  
  80. #define OTI87_PRODUCT 0x00        /* Oak product register */
  81. #define OTI87_STATUS 0x02        /* Oak status register */
  82. #define OTI87_VIDMAP 0x05        /* Oak video memory register */
  83. #define OTI87_CLOCK 0x06        /* Oak clock select register */
  84. #define OTI87_OVERFLOW 0x14        /* Oak overflow register */
  85. #define OTI87_HSYNC2 0x15        /* Oak hsynch/2 register */
  86. #define OTI87_XCRTC 0x17        /* Oak extended CRTC register */
  87. #define OTI87_COLORS 0x19        /* Oak color range register */
  88. #define OTI87_FIFO 0x20            /* Oak FIFO depth register */
  89. #define OTI87_MODESELECT 0x21        /* Oak mode select register */
  90. #define OTI87_FEATURE 0x22        /* Oak feature select register */
  91. #define OTI87_XREADSEGMENT 0x23        /* Oak extended read segment reg. */
  92. #define OTI87_XWRITESEGMENT 0x24    /* Oak extended write seg. reg. */
  93. #define OTI87_XCOMMONSEGMENT 0x25    /* Oak extended common register */
  94.  
  95. #define OTI87_OK_LINEAR 0        /* Set to 1 for linear addressing */
  96. #define DAC_SC11487 0x3c6        /* Sierra DAC command register */
  97. #define DAC_REVERT 0x3c8        /* Clears DAC from command mode */
  98.  
  99. static int oak_chiptype;
  100. static int oak_memory;
  101. static int oak_lockreg_save;
  102. static unsigned char last_page = 0;
  103. static void *linearframebuffer;
  104. static unsigned char *VGAMemory_Save;
  105.  
  106. static int oak_init(int, int, int);
  107. static int oak_interlaced( int mode );
  108. static int oak_memorydetect();
  109. static int oak_chipdetect();
  110. static int oak_inlinearmode();
  111. static int OAKGetByte( int );
  112.  
  113. static void oak_unlock();
  114. static void oak_setlinearmode();
  115. static void oak_clearlinearmode();
  116. static void oak_setpage( int page );
  117. static void OAK_WriteDAC( int function );
  118. static void OAKSetByte( int, int );
  119.  
  120. /* Mode table */
  121.  
  122. static ModeTable oak_modes[] = {
  123.     OneModeEntry(640x480x256),
  124.     OneModeEntry(640x480x32K),
  125.     OneModeEntry(800x600x16),
  126.     OneModeEntry(1024x768x16),
  127.     OneModeEntry(800x600x256),
  128.     OneModeEntry(800x600x32K),
  129.     OneModeEntry(1024x768x256),
  130.     OneModeEntry(1280x1024x16),
  131.     END_OF_MODE_TABLE  
  132. };
  133.  
  134. /* oak_getmodeinfo( int mode, vga_modeinfo *modeinfo)    Tell SVGALIB stuff
  135.  *
  136.  * Return mode information (blityes/no, start address, interlace, linear
  137.  */
  138.  
  139. static void oak_getmodeinfo( int mode, vga_modeinfo *modeinfo ) {
  140.     if (modeinfo->bytesperpixel > 0) {
  141.         modeinfo->maxpixels = oak_memory * 1024 / modeinfo->bytesperpixel;
  142.     }
  143.     else {
  144.         modeinfo->maxpixels = oak_memory * 1024;    /* any val */
  145.     }
  146.  
  147.     modeinfo->maxlogicalwidth = 2040;
  148.     modeinfo->startaddressrange = 0xfffff;
  149.     modeinfo->haveblit = 0;
  150.     modeinfo->flags |= HAVE_RWPAGE;
  151.  
  152.     if (oak_interlaced(mode)) {
  153.         modeinfo->flags |= IS_INTERLACED;
  154.     }
  155.  
  156.     if ((oak_chiptype == 87) & (OTI87_OK_LINEAR == 1)) {
  157.         modeinfo->flags |= CAPABLE_LINEAR;
  158.         modeinfo->flags |= EXT_INFO_AVAILABLE;
  159.         modeinfo->chiptype = 87;
  160.         modeinfo->aperture_size = oak_memorydetect();
  161.         modeinfo->set_aperture_page = oak_setpage;
  162.         if (oak_inlinearmode()) {
  163.             modeinfo->flags |= IS_LINEAR;
  164.             /* The following line was missing? */
  165.             modeinfo->linear_aperture = linearframebuffer;
  166.         }
  167.     }
  168. }
  169.  
  170. /* oak_saveregs( unsigned char regs[] )            Save extended regs
  171.  *
  172.  * Save extended registers into regs[].
  173.  * OTI-067/077 have eight registers
  174.  * OTI-087 has nineteen registers (only 11 used for native mode)
  175.  *
  176.  */
  177.  
  178. static int oak_saveregs( unsigned char regs[] )
  179. {
  180.     oak_unlock();
  181.     regs[OTI_SEGMENT_DATA] = OAKGetByte(OTI_SEGMENT);
  182.     regs[OTI_MISC_DATA] = OAKGetByte(OTI_MISC);
  183.     regs[OTI_BCOMPAT_DATA] = OAKGetByte(OTI_BCOMPAT);
  184.     regs[OTI_CONFIG_DATA] = OAKGetByte(OTI_CONFIG);
  185.     regs[OTI_OVERFLOW_DATA] = OAKGetByte(OTI_OVERFLOW);
  186.     regs[OTI_HSYNC2_DATA] = OAKGetByte(OTI87_HSYNC2);
  187.     regs[OTI_OVERFLOW2_DATA] = OAKGetByte(OTI_OVERFLOW2);
  188.     if (oak_chiptype == 87) {
  189.         regs[EXT + 8] = OAKGetByte(OTI87_CLOCK);
  190.         regs[EXT + 9] = OAKGetByte(OTI87_OVERFLOW);
  191.         regs[OTI87_HSYNC2_DATA] = OAKGetByte(OTI87_HSYNC2);
  192.         regs[OTI87_XCRTC_DATA] = OAKGetByte(OTI87_XCRTC);
  193.         regs[OTI87_COLORS_DATA] = OAKGetByte(OTI87_COLORS);
  194.         regs[OTI87_FIFO_DATA] = OAKGetByte(OTI87_FIFO_DATA);
  195.         regs[OTI87_MODESELECT_DATA] = OAKGetByte(OTI87_MODESELECT);
  196.         regs[OTI87_FEATURE_DATA] = OAKGetByte(OTI87_FEATURE_DATA);
  197.         regs[OTI87_XREADSEGMENT_DATA] = OAKGetByte(OTI87_XREADSEGMENT);
  198.         regs[OTI87_XWRITESEGMENT_DATA] = OAKGetByte(OTI87_XWRITESEGMENT);
  199.     }
  200.     return 19; /*19 additional registers */
  201. }
  202.  
  203. /* oak_setregs( unsigned char regs[], int mode )    Set Oak registers
  204.  *
  205.  * Set extended registers for specified graphics mode
  206.  * regs [EXT+1] through [EXT+7] used for OTI-067/77
  207.  * regs [EXT+9] through [EXT+17] used for OTI-087 native mode
  208.  */
  209.  
  210. static void oak_setregs( unsigned char regs[], int mode ) {
  211.     int junk;
  212.  
  213.     oak_unlock();
  214.     if (oak_chiptype == 87) {
  215.         OAKSetByte(OTI87_XREADSEGMENT, regs[OTI87_XREADSEGMENT_DATA]);
  216.         OAKSetByte(OTI87_XWRITESEGMENT, regs[OTI87_XWRITESEGMENT_DATA]);
  217.  
  218.         outb(0x3c4, 0);        /* reset sync. */
  219.         junk = inb(0x3c5);
  220.         outw(0x3c4, 0x00 + ((junk & 0xfd) << 8));
  221.             
  222.         OAKSetByte(OTI87_CLOCK, regs[EXT + 8]);
  223.         OAKSetByte(OTI87_FIFO, regs[OTI87_FIFO_DATA]);
  224.         OAKSetByte(OTI87_MODESELECT, regs[OTI87_MODESELECT_DATA]);
  225.  
  226.         outw(0x3c4, 0x00 + (junk << 8)); /* set sync. */
  227.  
  228.         OAKSetByte(OTI87_XCRTC, regs[OTI87_XCRTC_DATA]);
  229.         OAKSetByte(OTI87_OVERFLOW, regs[EXT + 9]);
  230.         OAKSetByte(OTI87_HSYNC2, regs[OTI87_HSYNC2_DATA]);
  231.         OAK_WriteDAC(regs[OTI87_RAMDAC_DATA]);
  232.     }
  233.     else {
  234.         OAKSetByte(OTI_SEGMENT, regs[OTI_SEGMENT_DATA]);
  235.  
  236.         /* doc says don't OTI-MISC unless sync. reset is off */
  237.         outb(0x3c4, 0);
  238.         junk = inb(0x3c5);
  239.         outw(0x3C4, 0x00 + ((junk & 0xFD) << 8)); /* now disable the timing sequencer */
  240.         
  241.         OAKSetByte(OTI_MISC, regs[OTI_MISC_DATA]);
  242.  
  243.         /* put sequencer back */
  244.         outw(0x3C4, 0x00 + (junk << 8));
  245.  
  246.         OAKSetByte(OTI_BCOMPAT, regs[OTI_BCOMPAT_DATA]);
  247.         OAKSetByte(OTI_CONFIG, regs[OTI_CONFIG_DATA]);
  248.         OAKSetByte(OTI_OVERFLOW, regs[OTI_OVERFLOW_DATA]);
  249.         OAKSetByte(OTI87_HSYNC2, regs[OTI_HSYNC2_DATA]);
  250.         OAKSetByte(OTI_OVERFLOW2, regs[OTI_OVERFLOW2_DATA]);
  251.     }
  252. }
  253.  
  254. /* oak_modeavailable( int mode )            Check if mode supported
  255.  *
  256.  * Verify that desired graphics mode can be displayed by chip/memory combo
  257.  * Returns SVGADRV flag if SVGA, vga_chipsetfunctions if VGA, 0 otherwise
  258.  */
  259.  
  260. static int oak_modeavailable( int mode ) {
  261.     const unsigned char *regs;
  262.     struct info *info;
  263.  
  264.     regs = LOOKUPMODE(oak_modes, mode);
  265.     if (regs == NULL || mode == GPLANE16) {
  266.         return vga_driverspecs.modeavailable(mode);
  267.     }
  268.     if (regs==DISABLE_MODE || mode<=TEXT || mode>GLASTMODE) {
  269.         return 0;
  270.     }
  271.     info = &__svgalib_infotable[mode];
  272.     if (oak_memory*1024 < info->ydim * info->xbytes) {
  273.         return 0;
  274.     }
  275.     return SVGADRV;
  276. }
  277.  
  278.  
  279.  
  280. /* oak_interlaced( int mode )                Is mode interlaced?
  281.  *
  282.  * Self-explanatory.
  283.  * Returns non-zero if mode is interlaced (bit 7)
  284.  */
  285.  
  286. static int oak_interlaced( int mode ) { 
  287.     const unsigned char *regs;
  288.  
  289.     if (oak_modeavailable(mode) != SVGADRV) {
  290.         return 0;
  291.     }
  292.     else {
  293.         regs = LOOKUPMODE(oak_modes, mode);
  294.         if (regs == NULL || regs == DISABLE_MODE) {
  295.             return 0;
  296.         }
  297.         else {
  298.             return regs[EXT+05] & 0x80;
  299.         }
  300.     }
  301. }
  302.  
  303. /* oak_setmode( int mode, int prv_mode )        Set graphics mode
  304.  *
  305.  * Attempts to set a graphics mode.
  306.  * Returns 0 if successful, 1 if unsuccessful
  307.  * 
  308.  * Calls vga_chipsetfunctions if VGA mode)
  309.  */
  310.  
  311. static int oak_setmode( int mode, int prv_mode ) {
  312.     const unsigned char *rp;
  313.     unsigned char regs[sizeof(g640x480x256_regs)];
  314.  
  315.     if ((oak_chiptype == 87) & (OTI87_OK_LINEAR == 1)) {
  316.         oak_clearlinearmode();
  317.     }
  318.     rp = LOOKUPMODE(oak_modes, mode);
  319.     if (rp == NULL || mode == GPLANE16)
  320.         return (int)(vga_driverspecs.setmode(mode, prv_mode));
  321.     if (!oak_modeavailable(mode))
  322.         return 1;    /* mode not available */
  323.  
  324.     /* Update the register information */
  325.     memcpy(regs, rp, sizeof(regs));
  326.  
  327.     /*  Number of memory chips */
  328.     if (oak_chiptype != 87) {
  329.         regs[OTI_MISC_DATA] &= 0x3F; 
  330.         regs[OTI_MISC_DATA] |= (oak_memory==1024 ? 0x40 : 0x00);
  331.         regs[OTI_MISC_DATA] |= (oak_memory>=512  ? 0x80 : 0x00);
  332.         if (oak_chiptype == 77) {
  333.             regs[OTI_CONFIG_DATA] |= 0x08;
  334.         }
  335.         else {
  336.             regs[OTI_CONFIG_DATA] &= 0xF7;
  337.         }
  338.     }
  339.  
  340.     if (__svgalib_infotable[mode].colors == 16) {
  341.  
  342.         /* switch from 256 to 16 color mode (from XFree86) */
  343.         regs[SEQ+4] &= 0xf7; /* Switch off chain 4 mode */
  344.         if (oak_chiptype == 87) {
  345.             regs[OTI87_FIFO_DATA] &= 0xf0;
  346.             regs[OTI87_MODESELECT_DATA] &= 0xf3;
  347.         }
  348.         else {
  349.             regs[OTI_MISC_DATA] &= 0xf0;
  350.             regs[OTI_MISC_DATA] |= 0x18;
  351.         }    
  352.     }
  353.  
  354.     __vga_setregs(regs);
  355.     oak_setregs(regs, mode);
  356.     if ((oak_chiptype == 87) & (OTI87_OK_LINEAR == 1)) {
  357.         oak_setlinearmode();
  358.     }
  359.  
  360.     return 0;
  361. }
  362.  
  363.  
  364.  
  365.  
  366. /* oak_unlock()                        Unlock Oak registers
  367.  *
  368.  * Enable register changes
  369.  * 
  370.  * _No effect with OTI-087 -- register is nonfunctional_
  371.  */
  372.  
  373. static void oak_unlock() {
  374.     int temp;
  375.     /* Unprotect CRTC[0-7] */
  376.     outb(CRT_I, 0x11);
  377.     temp = inb(CRT_D);
  378.     outb(CRT_D, temp & 0x7F);
  379.     temp = OAKGetByte(OTI_CRT_CNTL);
  380.     OAKSetByte(OTI_CRT_CNTL, temp & 0xf0);
  381.         oak_lockreg_save = temp;
  382. }
  383.  
  384. /* oak_lock()                        Lock Oak registers
  385.  *
  386.  * Prevents registers from accidental change
  387.  * 
  388.  * _No effect with OTI-087 -- register is nonfunctional_
  389.  */
  390.  
  391. static void oak_lock() {
  392.     int temp;
  393.     /* don't set the i/o write test bit, though we cleared it on entry */
  394.     OAKSetByte(OTI_CRT_CNTL, oak_lockreg_save & 0xf7);
  395.     /* Protect CRTC[0-7] */
  396.     outb(CRT_I, 0x11); temp = inb(CRT_D);
  397.     outb(CRT_D, (temp & 0x7F) | 0x80);
  398. }
  399.  
  400. /* oak_test()                        Probe for Oak card
  401.  *
  402.  * Checks for Oak segment register, then chip type and memory size.
  403.  * 
  404.  * Returns 1 for Oak, 0 otherwise.
  405.  */
  406.  
  407. static int oak_test() {
  408.     int save, temp1;
  409.     oak_unlock();    
  410.  
  411.     save = OAKGetByte(OTI_SEGMENT);
  412.     OAKSetByte(OTI_SEGMENT, save ^ 0x11);
  413.     temp1 = OAKGetByte(OTI_SEGMENT);
  414.     OAKSetByte(OTI_SEGMENT, save);
  415.     if (temp1 != ( save ^ 0x11 )) {
  416.         oak_lock();            /* unsuccesful */
  417.         return 0;
  418.     }
  419.  
  420.     /* HH: Only allow 087, 077 support seems to be broken for at */
  421.     /* least one 512K card. May be due to mode dump configuring */
  422.     /* for 1024K. */
  423.     if (oak_chipdetect() < 87)
  424.         return 0;
  425.  
  426.     return oak_init(0, 0, 0);
  427. }
  428.  
  429. /* oak_setpage( int page )                Set read/write pages
  430.  *
  431.  * Sets both read and write extended segments (64k bank number)
  432.  * Should be good for 5 bits with OTI-087
  433.  */
  434.  
  435. static void oak_setpage( int page ) {
  436.     if (oak_chiptype == 87) {
  437.         OAKSetByte(OTI87_XCOMMONSEGMENT, page);
  438.     }
  439.     else {
  440.         OAKSetByte(OTI_SEGMENT, (last_page = page | (page << 4)) << 8);
  441.     }
  442. }
  443.  
  444. /* oak_setrdpage( int page )                Set read page
  445.  *
  446.  * Sets read extended segment (64k bank number)
  447.  * Should be good for 5 bits with OTI-087
  448.  */
  449.  
  450. static void oak_setrdpage( int page ) {
  451.     if (oak_chiptype == 87) {
  452.         OAKSetByte(OTI87_XREADSEGMENT, page);
  453.     }
  454.     else {
  455.         last_page &= 0xF0;
  456.         last_page |= page;
  457.         OAKSetByte(OTI_SEGMENT, last_page);
  458.     }
  459. }
  460.  
  461. /* oak_setwrpage( int page )                Set write page
  462.  *
  463.  * Sets write extended segment (64k bank number)
  464.  * Should be good for 5 bits with OTI-087
  465.  */
  466.  
  467. static void oak_setwrpage( int page ) {
  468.     if (oak_chiptype == 87) {
  469.         OAKSetByte(OTI87_XWRITESEGMENT, page);
  470.     }
  471.     else {
  472.         last_page &= 0x0F;
  473.         last_page |= page<<4;
  474.         OAKSetByte(OTI_SEGMENT, last_page);
  475.     }
  476. }
  477.  
  478. /* oak_setdisplaystart( int address )            Set display address
  479.  *
  480.  * Sets display start address.
  481.  * First word goes into 0x3d4 indices 0x0c and 0x0d
  482.  * If 067, bit 16 goes to OTI_OVERFLOW bit 3
  483.  * If 077, bit 17 goes to OTI_OVERFLOW2 bit 3
  484.  * If 087, bits 16, 17, and 18 go to OTI87_XCRTC bits 0-2
  485.  */ 
  486.  
  487. static void oak_setdisplaystart( int address ) {
  488.     outw(0x3d4, 0x0d + ((address >> 2) & 0x00ff) * 256);    /* sa2-sa9 */
  489.     outw(0x3d4, 0x0c + ((address >> 2) & 0xff00));        /* sa10-sa17 */
  490.     inb(0x3da);            /* set ATC to addressing mode */
  491.     outb(0x3c0, 0x13 + 0x20);    /* select ATC reg 0x13 */
  492.     outb(0x3c0, (inb(0x3c1) & 0xf0) | ((address & 3) << 1));
  493.         /* write sa0-1 to bits 1-2 */
  494.  
  495.     if (oak_chiptype == 87) {
  496.         OAKSetByte(OTI87_XCRTC, (address & 0x1c0000) >> 18);
  497.     }
  498.     else {
  499.         OAKSetByte(OTI_OVERFLOW, (OAKGetByte(OTI_OVERFLOW) & 0xf7)
  500.             | ((address & 0x40000) >> 15 ));
  501.             /* write sa18 to bit 3 */
  502.         if (oak_chiptype == 77) {
  503.             OAKSetByte(OTI_OVERFLOW2, 
  504.                 (OAKGetByte(OTI_OVERFLOW2) & 0xf7)
  505.                 | ((address & 0x80000) >> 16));
  506.                 /* write sa19 to bit 3 */
  507.         }
  508.     }
  509. }
  510.  
  511. /* oak_setlogicalwidth( int width )            Set scanline length
  512.  *
  513.  * Set logical scanline length (usually multiple of 8)
  514.  * Multiples of 8 to 2040
  515.  */
  516.  
  517. static void oak_setlogicalwidth( int width ) { 
  518.     outw(0x3d4, 0x13 + (width >> 3) * 256);    /* lw3-lw11 */
  519. }
  520.  
  521. /* oak_init ( int force, int par1, int par2)        Initialize chipset
  522.  *
  523.  * Detects Oak chipset type and installed video memory.
  524.  * Returns 1 if chipset is supported, 0 otherwise
  525.  */
  526.  
  527. static int oak_init( int force, int par1, int par2) {
  528.     if (force) {
  529.         oak_chiptype = par1;
  530.         oak_memory = par2;    
  531.     }
  532.     else {
  533.         oak_chiptype = oak_chipdetect ();
  534.         if (oak_chiptype == 0) {
  535.             return 0;            /* not supported */
  536.         }
  537.         oak_memory = oak_memorydetect();
  538.     }
  539.     if (__svgalib_driver_report) {
  540.         printf("Using Oak driver (OTI-0%d, %dK).\n", oak_chiptype, 
  541.             oak_memory);
  542.     }
  543.     driverspecs = &oak_driverspecs;
  544.     return 1;
  545. }
  546.  
  547. /* oak_memorydetect()                Report installed video RAM
  548.  *
  549.  * Returns size (in Kb) of installed video memory
  550.  * Defined values are 256, 512, 1024, and 2048 (OTI-087 only)
  551.  */
  552.  
  553. static int oak_memorydetect() {
  554.     int temp1;
  555.     if (oak_chiptype == 87) {
  556.         temp1 = OAKGetByte(OTI87_STATUS) & 0x06;
  557.         if (temp1 == 0x06)
  558.             return 2048;
  559.         else if (temp1 == 0x04)
  560.             return 1024;
  561.         else if (temp1 == 0x02)
  562.             return 512;
  563.         else if (temp1 == 0x00)
  564.             return 512;
  565.         else {
  566.             printf("Oak driver: Invalid amount of memory. Using 256K.\n");
  567.             return 256;
  568.         }
  569.     }
  570.     else {
  571.         temp1 = OAKGetByte(OTI_MISC) & 0xc0;
  572.         if (temp1 == 0xC0 )
  573.             return 1024;
  574.         else if (temp1 == 0x80 )
  575.             return 512;
  576.         else if (temp1 == 0x00 )
  577.             return 256;
  578.         else {
  579.             printf("Oak driver: Invalid amount of memory. Using 256K.\n");
  580.             return 256;
  581.         }
  582.     }
  583. }
  584.  
  585. /* oak_chipdetect()                Detect Oak chip type
  586.  *
  587.  * Returns chip id (67, 77, 87) if video chipset is a supported Oak type
  588.  * (57 is _not_ supported).
  589.  * Returns 0 otherwise
  590.  */
  591.  
  592. static int oak_chipdetect() {
  593.     int  temp1;
  594.     temp1 = OAKGetByte(OTI87_PRODUCT) & 0x01;
  595.     if (temp1 == 0x01) {
  596.         return 87;
  597.     }
  598.     else {
  599.         temp1 = inb(OTI_INDEX);
  600.         temp1 &= 0xE0;
  601.         switch (temp1) {
  602.             case 0x40 : 
  603.             return 67;
  604.             case 0xA0 :
  605.             return 77;
  606.             default :
  607.                 printf("Oak driver: Unknown chipset (id = %2x)\n", temp1);
  608.                 oak_lock();
  609.                 return 0;
  610.         }
  611.     }
  612. }
  613.  
  614. /* oak_inlinearmode()            Check if OTI-087 is in linear mode
  615.  *
  616.  * Bit 0 set if yes, clear if no
  617.  * Return: true/false
  618.  */
  619.  
  620. static int oak_inlinearmode() {
  621.     return (OAKGetByte(OTI87_VIDMAP) & 0x01) != 0;
  622. }
  623.  
  624. /* oak_setlinearmode()            Set linear mode for OTI-087
  625.  * 
  626.  * For simplicity's sake, we're forcing map at the E0000 (14M) mark
  627.  * We grab the memory size from OTI87_STATUS, and we're mapping it all.
  628.  * 
  629.  * Video map register looks like this:
  630.  *    Bit 0:   0 = VGA mapping (A0000-BFFFF) 1 = Linear
  631.  *    Bit 1:   0 = Enable DMA 1 = Disable DMA
  632.  *    Bit 2/3: Aperature (256/512/1024/2048, bitwise)
  633.  *    Bit 4-7: Starting address (High nybble, 1-F)
  634.  */
  635.  
  636. static void oak_setlinearmode() {
  637.     int temp1;
  638.     temp1 = ((OAKGetByte(OTI87_STATUS) & 0x06) << 1) | 0xe1;
  639.     OAKSetByte(OTI87_VIDMAP, temp1);
  640.     linearframebuffer = (unsigned char *)mmap((caddr_t) 0x40000000, 
  641.                 oak_memory * 1024,
  642.                 PROT_READ|PROT_WRITE,
  643.                 MAP_SHARED|MAP_FIXED,
  644.                 __svgalib_mem_fd,
  645.                 0xe00000);        
  646.     VGAMemory_Save = __svgalib_graph_mem;
  647. /*    __svgalib_graph_mem = linearframebuffer; */
  648. /*     graph_mem = __svgalib_graph_mem; */
  649.     __svgalib_modeinfo_linearset |= IS_LINEAR;
  650. }
  651.  
  652. /* oak_clearlinearmode()            Stop linear mode for OTI-087
  653.  *
  654.  * Switches linear mode off, reset aperture and address range
  655.  * (see oak_golinearmode() for register description)
  656.  */
  657.  
  658. static void oak_clearlinearmode() {
  659.     OAKSetByte(OTI87_VIDMAP, 0x00);
  660.     __svgalib_modeinfo_linearset ^= IS_LINEAR;
  661.     __svgalib_graph_mem = VGAMemory_Save; 
  662.      graph_mem = VGAMemory_Save;
  663.     munmap((caddr_t) 0x40000000, oak_memory * 1024);
  664.  
  665. }
  666.  
  667. /* OAK_WriteDAC ( int dac_value )            Write value to DAC
  668.  *
  669.  * Writes function command to DAC at 0x03c6
  670.  * (Assumes that DAC is SC11487 ... may not work for others)
  671.  *
  672.  */
  673.  
  674. static void OAK_WriteDAC ( int dac_value ) {
  675.     inb(DAC_REVERT);        /* reset DAC r/w pointer */
  676.     inb(DAC_SC11487);        /* do this four times to set register A */
  677.     inb(DAC_SC11487);
  678.     inb(DAC_SC11487);
  679.     inb(DAC_SC11487);
  680.     outb(DAC_SC11487, dac_value);
  681.     inb(DAC_REVERT);        /* and reset DAC ... */
  682. }
  683.  
  684. /* OAKSetByte ( index, value)                Set extended register
  685.  *
  686.  * Puts a specified value in a specified extended register.
  687.  * Splitting this commonly used instruction sequence into its own subroutine
  688.  * saves about 100 bytes of code overall ...
  689.  */
  690.  
  691. static void OAKSetByte( int OTI_index, int OTI_value) {
  692.     outb(OTI_INDEX, OTI_index);
  693.     outb(OTI_R_W, OTI_value);
  694. }
  695.  
  696. /* OAKGetByte ( index )                    Returns ext. register
  697.  *
  698.  * Returns value from specified extended register.
  699.  * As with OakSetByte, this tightens the code considerably.
  700.  */
  701.  
  702. static int OAKGetByte( int OTI_index) {
  703.     outb(OTI_INDEX, OTI_index);
  704.     return inb(OTI_R_W);
  705. }
  706.  
  707. /* Function table (exported) */
  708.  
  709. DriverSpecs oak_driverspecs = {
  710.     oak_saveregs,
  711.     (int (*)()) oak_setregs,
  712.     (int (*)()) oak_unlock,
  713.     (int (*)()) oak_lock,
  714.     oak_test,
  715.     oak_init,
  716.     (int (*)()) oak_setpage,
  717.     (int (*)()) oak_setrdpage,
  718.     (int (*)()) oak_setwrpage,
  719.     oak_setmode,
  720.     oak_modeavailable,
  721.     (int (*)()) oak_setdisplaystart,
  722.     (int (*)()) oak_setlogicalwidth,
  723.     (int (*)()) oak_getmodeinfo,
  724.     0,    /* bitblt */
  725.     0,    /* imageblt */
  726.     0,    /* fillblt */
  727.     0,    /* hlinelistblt */
  728.     0,    /* bltwait */
  729.     0,    /* extset */
  730.     0,
  731.     0,    /* linear */
  732.     NULL,    /* accelspecs */
  733. #if 0
  734.     (int (*)()) oak_setlinearmode,
  735.     (int (*)()) oak_clearlinearmode,
  736.     (int (*)()) OAK_WriteDAC,
  737. #endif
  738. };
  739.  
  740.