home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / et3000.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-11  |  7.9 KB  |  364 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 (c) 1993 Harm Hanemaayer */
  8. /* partially copyrighted (C) 1993 by Hartmut Schirmer */
  9.  
  10. /*
  11. **  Used extended ET3000 registers (EXT+xx) :
  12. **
  13. **    00 : CRT (3d4) index 23
  14. **    01 : CRT (3d4) index 24
  15. **    02 : CRT (3d4) index 25
  16. **    03 : SEQ (3c4) index 06
  17. **    04 : SEQ (3c4) index 07
  18. **    05 : Segment select (3cd)
  19. **    06 : ATT (3c0) index 16
  20. **
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <unistd.h>
  25. #include "vga.h"
  26. #include "libvga.h"
  27. #include "driver.h"
  28. #include "config.h"
  29.  
  30. #define SEG_SELECT 0x3CD
  31.  
  32. static int et3000_memory;
  33.  
  34. static int et3000_init( int, int );
  35. static int et3000_interlaced( int mode );
  36. static int et3000_unlock();
  37.  
  38.  
  39. /* Mode table */
  40. #include "et3000.regs" 
  41.  
  42. static ModeTable et3000_modes[] = {
  43.     OneModeEntry(640x480x256),
  44.     OneModeEntry(800x600x16),
  45.     OneModeEntry(800x600x256),
  46.     OneModeEntry(1024x768x16),
  47.     END_OF_MODE_TABLE  
  48. };
  49.  
  50. /*#endif*/ /* !defined(DYNAMIC) */
  51.  
  52. /* Fill in chipset specific mode information */
  53.  
  54. static int et3000_getmodeinfo( int mode, vga_modeinfo *modeinfo ) {
  55.     switch (modeinfo->colors) {
  56.         case 16 :    /* 4-plane 16 color mode */
  57.             modeinfo->maxpixels = 65536 * 8;
  58.             break;
  59.         default :
  60.             if (modeinfo->bytesperpixel > 0)
  61.                 modeinfo->maxpixels = et3000_memory * 1024 / 
  62.                         modeinfo->bytesperpixel;
  63.             else
  64.                 modeinfo->maxpixels = et3000_memory * 1024;
  65.             break;
  66.     }
  67.     modeinfo->maxlogicalwidth = 4088;
  68.     modeinfo->startaddressrange = 0x7ffff;
  69.     modeinfo->haveblit = 0;
  70.     modeinfo->flags |= HAVE_RWPAGE;
  71.     if (et3000_interlaced(mode))
  72.       modeinfo->flags |= IS_INTERLACED;
  73.     
  74.     return 0;
  75. }
  76.  
  77.  
  78. /* Read and store chipset-specific registers */
  79.  
  80. static int et3000_saveregs(unsigned char regs[])
  81. {
  82.     int i;
  83.  
  84.     et3000_unlock();
  85.     /* save extended CRT registers */
  86.     for (i = 0; i < 3; i++) {
  87.      port_out(0x23+i, CRT_I); 
  88.      regs[EXT+i] = port_in(CRT_D); 
  89.     }
  90.  
  91.     /* save extended sequencer register */
  92.     for (i=0; i < 2; ++i) {
  93.       port_out(6+i, SEQ_I); 
  94.       regs[EXT+3+i] = port_in(SEQ_D);
  95.     }
  96.  
  97.     /* save some other ET3000 specific registers */
  98.     regs[EXT+5] = port_in(0x3cd); 
  99.  
  100.     /* save extended attribute register */
  101.     port_in(IS1_R);    /* reset flip flop */
  102.     port_out(0x16, ATT_IW);
  103.     regs[EXT+6] = port_in(ATT_R);
  104.  
  105.     return 7;  /* ET3000 requires 7 additional registers */
  106. }
  107.  
  108.  
  109. /* Set chipset-specific registers */
  110.  
  111. static int et3000_setregs( const unsigned char regs[], int mode )
  112. {
  113.     int i;
  114.     unsigned char save;
  115.  
  116.     et3000_unlock();
  117.     /* write some ET3000 specific registers */
  118.     port_out(regs[EXT+5], 0x3cd);
  119.  
  120.     /* write extended sequencer register */
  121.     for (i=0; i < 2; ++i) {
  122.       port_out(6+i, SEQ_I); 
  123.       port_out(regs[EXT+3+i], SEQ_D);
  124.     }
  125.  
  126.     /* deprotect CRT register 0x25 */
  127.     port_out(0x11, CRT_I);          
  128.     save = port_in(CRT_D);
  129.     port_out(save&0x7F, CRT_D);   
  130.  
  131.     /* write extended CRT registers */
  132.     for (i = 0; i < 3; i++) {
  133.          port_out(0x23+i, CRT_I); 
  134.          port_out(regs[EXT+i], CRT_D); 
  135.     }
  136.  
  137.     /* set original CRTC 0x11 */
  138.     port_out(0x11, CRT_I);          
  139.     port_out(save, CRT_D);   
  140.  
  141.     /* write extended attribute register */
  142.     port_in(IS1_R);    /* reset flip flop */
  143.     port_out(0x16, ATT_IW);
  144.     port_out(regs[EXT+6], ATT_IW);
  145.  
  146.     return 0;
  147. }
  148.  
  149.  
  150. /* Return non-zero if mode is available */
  151.  
  152. static int et3000_modeavailable( int mode ) {
  153.     const unsigned char *regs;
  154.     struct info *info;
  155.  
  156.     regs = LOOKUPMODE(et3000_modes, mode);
  157.     if (regs == NULL || mode == GPLANE16)
  158.           return vga_driverspecs.modeavailable(mode);
  159.     if (regs==DISABLE_MODE || mode<=TEXT || mode>GLASTMODE)
  160.       return 0;
  161.  
  162.     info = &__svgalib_infotable[mode];
  163.     if (et3000_memory*1024 < info->ydim * info->xbytes)
  164.       return 0;
  165.  
  166.     return SVGADRV;
  167. }
  168.  
  169.  
  170. /* Check if mode is interlaced */
  171.  
  172. static int et3000_interlaced( int mode ) { 
  173.     const unsigned char *regs;
  174.  
  175.     if (et3000_modeavailable(mode) != SVGADRV)
  176.       return 0;
  177.     regs = LOOKUPMODE(et3000_modes, mode);
  178.     if (regs == NULL || regs == DISABLE_MODE)
  179.       return 0;
  180.     return (regs[EXT+2]&0x80) != 0;  /* CRTC 25H */
  181. }
  182.  
  183.  
  184. /* Set a mode */
  185.  
  186. static int et3000_setmode( int mode, int prv_mode ) {
  187.     const unsigned char *regs;
  188.  
  189.     switch (et3000_modeavailable(mode)) {
  190.       case STDVGADRV: 
  191.         return vga_driverspecs.setmode(mode, prv_mode);
  192.       case SVGADRV:
  193.         regs = LOOKUPMODE(et3000_modes, mode);
  194.         if (regs != NULL) break;
  195.       default:
  196.         return 1;    /* mode not available */
  197.     }
  198.  
  199.     et3000_unlock();
  200.     __vga_setregs(regs);
  201.     et3000_setregs(regs, mode);
  202.         return 0;
  203. }
  204.  
  205. /* Unlock chipset-specific registers */
  206.  
  207. static int et3000_unlock() {
  208.     /* get access to extended registers */
  209.     int base;
  210.  
  211.     base = ( port_in( 0x3cc ) & 1 ? 0x3d0 : 0x3b0);
  212.     port_out(3, 0x3bf);
  213.     port_out(0xa0, base+8);
  214.     port_out(0x24, base+4);
  215.     port_out(port_in(base+5)&0xDF, base+5);
  216.  
  217.     return 0;
  218. }
  219.  
  220.  
  221. /* Relock chipset-specific registers */
  222.  
  223. static int et3000_lock() {
  224.         return 0;
  225. }
  226.  
  227.  
  228. /* Indentify chipset; return non-zero if detected */
  229.  
  230. static int et3000_test()
  231. {
  232.     unsigned char old, val;
  233.     int  base;
  234.  
  235.     /* test for Tseng clues */
  236.     old = port_in(0x3cd);
  237.     port_out(old ^ 0x3f, 0x3cd);
  238.     val = port_in(0x3cd);
  239.     port_out(old, 0x3cd);
  240.  
  241.     /* return false if not Tseng */
  242.     if (val != (old ^ 0x3f))
  243.     return 0;
  244.  
  245.     /* test for ET3000 clues */
  246.     if (port_in(0x3cc) & 1) 
  247.     base = 0x3d4;
  248.     else 
  249.     base = 0x3b4;
  250.     port_out(0x1b, base);
  251.     old = port_in(base+1);
  252.     port_out(old ^ 0xff, base+1);
  253.     val = port_in(base+1);
  254.     port_out(old, base+1);
  255.  
  256.     /* return false if not ET3000 */    
  257.     if (val != (old ^ 0xff)) 
  258.     return 0;
  259.  
  260.     /* Found ET3000 */
  261.     et3000_init(0, 0);
  262.     return 1;
  263. }
  264.  
  265.  
  266.  
  267. static unsigned char last_page = 0x40;
  268.  
  269. /* Bank switching function - set 64K bank number */
  270. static void et3000_setpage( int page ) {
  271.     last_page = page | (page << 3) | 0x40;
  272.     port_out(last_page, SEG_SELECT);
  273. }
  274.  
  275.  
  276. /* Bank switching function - set 64K read bank number */
  277. static void et3000_setrdpage( int page ) {
  278.     last_page &= 0xC7;
  279.     last_page |= (page << 3);
  280.     port_out(last_page, SEG_SELECT);
  281. }
  282.  
  283. /* Bank switching function - set 64K write bank number */
  284. static void et3000_setwrpage( int page ) {
  285.     last_page &= 0xF8;
  286.     last_page |= page;
  287.     port_out(last_page, SEG_SELECT);
  288. }
  289.  
  290.  
  291. /* Set display start address (not for 16 color modes) */
  292. /* ET4000 supports any address in video memory (up to 1Mb) */
  293.  
  294. static int et3000_setdisplaystart( int address ) {
  295.     outw(0x3d4, 0x0d + ((address >> 2) & 0x00ff) * 256);    /* sa2-sa9 */
  296.     outw(0x3d4, 0x0c + ((address >> 2) & 0xff00));        /* sa10-sa17 */
  297.     inb(0x3da);            /* set ATC to addressing mode */
  298.     outb(0x3c0, 0x13 + 0x20);    /* select ATC reg 0x13 */
  299.     outb(0x3c0, (inb(0x3c1) & 0xf0) | ((address & 3) << 1));
  300.         /* write sa0-1 to bits 1-2 */
  301.     outb(0x3d4, 0x23);
  302.     outb(0x3d5, (inb(0x3d5) & 0xfd)
  303.         | ((address & 0x40000) >> 17));    /* write sa18 to bit 1 */
  304.     return 0;
  305. }
  306.  
  307.  
  308. /* Set logical scanline length (usually multiple of 8) */
  309.  
  310. static int et3000_setlogicalwidth( int width ) { 
  311.     outw(0x3d4, 0x13 + (width >> 3) * 256);    /* lw3-lw11 */
  312.     return 0;
  313. }
  314.  
  315.  
  316. /* Function table (exported) */
  317.  
  318. DriverSpecs et3000_driverspecs = {
  319.     et3000_saveregs,
  320.     et3000_setregs,
  321.     et3000_unlock,
  322.     et3000_lock,
  323.     et3000_test,
  324.     et3000_init,
  325.     (int (*)()) et3000_setpage,
  326.     (int (*)()) et3000_setrdpage,
  327.     (int (*)()) et3000_setwrpage,
  328.     et3000_setmode,
  329.     et3000_modeavailable,
  330.     et3000_setdisplaystart,
  331.     et3000_setlogicalwidth,
  332.     et3000_getmodeinfo,
  333.     0,    /* bitblt */
  334.     0,    /* imageblt */
  335.     0,    /* fillblt */
  336.     0,    /* hlinelistblt */
  337.     0,    /* bltwait */
  338.     0,    /* extset */
  339.     0,
  340.     0,    /* linear */
  341.     NULL    /* accelspecs */
  342. };
  343.  
  344.  
  345. /* Initialize chipset (called after detection) */
  346.  
  347. static int et3000_init( int force, int par1 ) {
  348.     int value, i;
  349.  
  350.     if (force)
  351.         et3000_memory = par1;
  352.     else {
  353.         et3000_memory = 512;
  354.         /* Any way to check this ?? */
  355.     }
  356.  
  357.     if (__svgalib_driver_report)
  358.         printf("Using Tseng ET3000 driver (%d).\n", et3000_memory);
  359.     driverspecs = &et3000_driverspecs;
  360.  
  361.     return 0;
  362. }
  363.  
  364.