commit 84436a5ae080b08a18e90979f16b09b47353d587 Author: Felisp Date: Thu Nov 23 00:11:45 2023 +0100 Initiall commit from latest release http://my.svgalib.org/svgalib/svgalib-1.9.25.tar.gz http://my.svgalib.org/svgalib/ diff --git a/0-README b/0-README new file mode 100644 index 0000000..826c7dc --- /dev/null +++ b/0-README @@ -0,0 +1,957 @@ +svgalib(7) Svgalib User Manual svgalib(7) + + + +1mNAME0m + svgalib - a low level graphics library for linux + +1mTABLE OF CONTENTS0m + 1m0. 22mIntroduction + 1m1. 22mInstallation + 1m2. 22mHow to use svgalib + 1m3. 22mDescription of svgalib functions + 1m4. 22mOverview of supported SVGA chipsets and modes + 1m5. 22mDetailed comments on certain device drivers + 1m6. 22mGoals + 1m7. 22mReferences (location of latest version, apps etc.) + 1m8. 22mKnown bugs + + +1m0. INTRODUCTION0m + This is a low level graphics library for Linux, originally based on + VGAlib 1.2 by Tommy Frandsen. VGAlib supported a number of standard VGA + graphics modes, as well as Tseng ET4000 high resolution 256-color + modes. As of now, support for many more chipsets has been added. See + section 1m4 Overview of supported SVGA chipsets and modes0m + + It supports transparent virtual console switching, that is, you can + switch consoles to and from text and graphics mode consoles using + alt-[function key]. Also, svgalib corrects most of VGAlib's textmode + corruption behaviour by catching 1mSIGSEGV22m, 1mSIGFPE22m, 1mSIGILL22m, and other + fatal signals and ensuring that a program is running in the currently + visible virtual console before setting a graphics mode. + + Note right here that 1mSIGUSR1 22mand 1mSIGUSR2 22mare used to manage console + switching internally in 1msvgalib22m. You can not use them in your pro- + grams. If your program needs to use one of those signals, svgalib can + be compiled to use other signals, by editing libvga.h + + This version includes code to hunt for a free virtual console on its + own in case you are not starting the program from one (but instead over + a network or modem login, from within 1mscreen22m(1) or an 1mxterm22m(1)). Pro- + vided there is a free console, this succeeds if you are root or if the + svgalib calling user own the current console. This is to avoid people + not using the console being able to fiddle with it. On graceful exit + the program returns to the console from which it was started. Other- + wise it remains in text mode at the VC which svgalib allocated to allow + you to see any error messages. In any case, any I/O the svgalib makes + in text mode (after calling 1mvga_init22m(3)) will also take place at this + new console. + + Alas, some games misuse their suid root privilege and run as full root + process. svgalib cannot detect this and allows Joe Blow User to open a + new VC on the console. If this annoys you, 1mROOT_VC_SHORTCUT 22min 4mMake-0m + 4mfile.cfg24m allows you to disable allocating a new VC for root (except + when he owns the current console) when you compile svgalib. This is the + default. + + When the library is used by a program at run-time, first the chipset is + detected and the appropriate driver is used. This means that a graphics + program will work on any card that is supported by svgalib, if the mode + it uses is supported by the chipset driver for that card. The library + is upwardly compatible with VGAlib. + + The set of drawing functions provided by svgalib itself is limited + (unchanged from VGAlib) and unoptimized; you can however use 1mvga_set-0m + 1mpage22m(3) and 1mvga_getgraphmem22m(3) (which points to the 64K VGA + framebuffer) in a program or graphics library. A fast external frame- + buffer graphics library for linear and banked 1, 2, 3 and 4 bytes per + pixel modes is included (it also indirectly supports planar VGA modes). + It is documented in 1mvgagl22m(7). + + One obvious application of the library is a picture viewer. Several are + available, along with animation viewers. See the 1m7. References 22mat the + end of this document. + + I have added a simple VGA textmode font restoration utility (1mrestore-0m + 1mfont22m(1)) which may help if you suffer from XFree86 textmode font cor- + ruption. It can also be used to change the textmode font. It comes with + some other textmode utilities: 1mrestoretextmode22m(1) (which saves/restores + textmode registers), 1mrestorepalette22m(1), and the script 1mtextmode22m(1). If + you run the 1msavetextmode22m(1) script to save textmode information to + 4m/tmp24m, you'll be able to restore textmode by running the 1mtextmode22m(1) + script. + + +1m1. INSTALLATION0m + Installation is easy in general but there are many options and things + you should keep in mind. This document however assumes that 1msvgalib 22mis + already installed. + + If you need information on installation see 4m0-INSTALL24m which comes with + the svgalib distribution. + + However, even after installation of the library you might need to con- + figure svgalib using the file 4m/etc/vga/libvga.config24m. Checkout section + 1m4 Overview of supported SVGA chipsets and modes 22mand 1mlibvga.config22m(5) + for information. + + +1m2. HOW TO USE SVGALIB0m + For basic svgalib usage (no mouse, no raw keyboard) add 1m#include0m + 1m 22mat the beginning your program. Use 1mvga_init22m(3) as your first + 1msvgalib 22mcall. This will give up root privileges right after initializa- + tion, making setuid-root binaries relatively safe. + + The function 1mvga_getdefaultmode22m(3) checks the environment variable + 1mSVGALIB_DEFAULT_MODE 22mfor a default mode, and returns the corresponding + mode number. The environment string can either be a mode number or a + mode name as in (1mG640x480x222m, 1mG640x480x1622m, 1mG640x480x256 22m, 1mG640x480x32K22m, + 1mG640x480x64K22m, 1mG640x480x16M22m). As an example, to set the default graph- + ics mode to 640x480, 256 colors, use: + + 1mexport SVGALIB_DEFAULT_MODE=G640x480x2560m + + on the 1mbash(1) 22mcommand line. If a program needs just a linear VGA/SVGA + resolution (as required by 1mvgagl22m(7)), only modes where 1mbytesperpixel 22min + the 1mvga_modeinfo 22mstructure returned by 1mvga_getmodeinfo22m(3) is greater or + equal to 1 should be accepted (this is 0 for tweaked planar 256-color + VGA modes). + + Use 1mvga_setmode(4m22mgraphicsmode24m1m) 22mto set a graphics mode. Use 1mvga_set-0m + 1mmode(TEXT) 22mto restore textmode before program exit. + + Programs that use svgalib must 1m#include22m; if they also use the + external graphics library 1mvgagl22m(7), you must also 1m#include22m. + Linking must be done with 1m-lvga 22m(and 1m-lvgagl 22mbefore 1m-lvga22m, if 1mvgagl22m(7) + is used). You can save binary space by removing the unused chipset + drivers in 4mMakefile.cfg24m if you only use specific chipsets. However this + reduces the flexibility of svgalib and has a significant effect only + when you use the static libraries. You should better use the shared + libraries and these will load only the really used parts anyway. + + Functions in the 1mvgagl22m(7) library have the prefix 1mgl_22m. Please see + 1mvgagl22m(7) for details. + + There are demos with sources available which will also help to get you + started, in recomended order of interest: 1mvgatest22m(6), 1mkeytest22m(6), + 1mmousetest22m(6), 1meventtest22m(6), 1mforktest22m(6), 1mbg_test22m(6), 1mscrolltest22m(6), + 1mspeedtest22m(6), 1mfun22m(6), 1mspin22m(6), 1mtestlinear22m(6), 1mlineart22m(6), 1mtestgl22m(6), + 1maccel22m(6), 1mtestaccel22m(6), 1mplane22m(6), and 1mwrapdemo22m(6). + + Debugging your programs will turn out to be rather difficult, because + the svgalib application can not restore textmode when it returns to the + debugger. + + Happy are the users with a serial terminal, X-station, or another way + to log into the machine from network. These can use + + 1mtextmode . + + Supports 640x480x256, 800x600x256, 1024x768x256 (interlaced and non- + interlaced) Might be useful to add 16-color modes (for those equipped + with a 512K TVGA9000) for the 8900 and 9000 cards. + + 320x200x{32K, 64K, 16M}, 640x480x{256, 32K, 64K, 16M}, 800x600x{256, + 32K, 64K, 16M}, 1024x768x{16, 256}, 800x600x{16, 256, 32K, 64K} modes + are supported for the TVGA 9440. + + Autodetection can be forced with a: + + 1mchipset TVGA 4m22mmemory24m 4mflags0m + + line in the config file. + + 4mmemory24m is the amount of VGA memory in KB, 4mflags24m is composed of three + bits: + + 1mbit2 = false, bit1 = false0m + force 8900. + + 1mbit2 = false, bit1 = true0m + force 9440. + + 1mbit2 = true, bit1 = false0m + force 9680. + + 1mbit0 = true0m + force noninterlaced. + + 1mbit0 = false0m + force interlaced which only matters on 8900's with at + least 1M since there is no 512K interlaced mode on the + 8900 or any of the other cards. + + + 1mTseng ET4000/ET4000W32(i/p)0m + Derived from VGAlib; not the same register values. ET4000 register + values are not compatible; see 1msvgalib.et400022m(7). + + Make sure the colors are right in hicolor mode; the vgatest program + should draw the same color bars for 256 and hicolor modes (the DAC type + is defined at compilation in 4met4000.regs24m or the dynamic registers + file). ET4000/W32 based cards usually have an AT&T or Sierra 15025/6 + DAC. With recent W32p based cards, you might have some luck with the + AT&T DAC type. If the high resolution modes don't work, you can try + dumping the registers in DOS using the program in the 4met4000/24m directory + and putting them in a file (4m/etc/vga/libvga.et400024m is parsed at runtime + if 1mDYNAMIC 22mis defined in 4mMakefile.cfg24m at compilation (this is + default)). + + Supported modes are 640x480x256, 800x600x256, 1024x768x256, + 640x480x32K, 800x600x32K, 640x480x16M, etc. + + Reports of ET4000/W32i/p functionality are welcome. + + There may be a problem with the way the hicolor DAC register is han- + dled; dumped registers may use one of two timing methods, with the + value written to the register for a particular DAC for a hicolor mode + (in vgahico.c) being correct for just one of the these methods. As a + consequence some dumped resolutions may work while others don't. + + + 1mTseng ET60000m + Most modes of which the card is capable are supported. The 8 15 16 24 + and 32 bit modes are supported. + + The ET6000 has a built in DAC and there is no problem coming from that + area. The ET6000 is capable of acceleration, but this as well as + sprites are not yet implemented in the driver. + + The driver now uses modelines in libvga.config for user defined modes. + It is sometimes useful to add a modeline for a resolution which does + not display well. For example, the G400x600 is too far to the right of + the screen using standard modes. This is corrected by including in + 1mlibvga.config 22mthe line + + Modeline "400x600@72" 25.000 400 440 488 520 600 639 644 666 + + More examples are given below. + + This driver was provided by Don Secrest. + + + 1mVESA0m + Please read README.vesa and README.lrmi in doc subdirectory of the + standard distribution. + + Go figure! I turned off autodetection in the release, as a broken bios + will be called too, maybe crashing the machine. Enforce 1mVESA 22mmode by + putting a 1mchipset VESA 22min the end of your 4mlibvga.config24m(5). + + Note that it will leave protected mode and call the cards bios opening + the door to many hazards. + + +1m5. DETAILED COMMENTS ON CERTAIN DEVICE DRIVERS0m + This section contains detailed information by the authors on certain + chipsets. + + + 1mAT3D (AT25)0m + Also known as Promotion at25. Popular as the 2D part of a voodoo rush + card. + + I have written a driver for this chipset, based on the XF86 driver for + this chipset. + + The programs that work with this driver include all the programs in the + demos directory, zgv and dvisvga (tmview). + + I believe it should be easy to make it work on AT24, AT6422. + + + 1mATI Mach320m + Please see 1msvgalib.mach3222m(7). + + + 1mATI Mach640m + The rage.c driver works only on mach64 based cards with internal DAC. + The driver might misdetect the base frequency the card uses, so if when + setting any svgalib modes the screen blanks, or complains about out of + bound freqencies, or the display is unsynced, then try adding the + option 1mRageDoubleClock 22mto the config file. + + + 1mChips and Technologies chipsets 65525, 65535, 65546, 65548, 65550, and0m + 1m65554 (usually in laptops).0m + Please see 1msvgalib.chips22m(7). + + + 1mTseng ET4000/ET4000W32(i/p)0m + Please see 1msvgalib.et400022m(7). + + + 1mTseng ET60000m + I have only 2 Mbytes of memory on my ET6000 card, so I am not able to + get all possible modes running. I haven't even tried to do all of the + modes which I am capable of doing, but I am confident that I can manage + more modes when I have time. I have enough modes working to make the + card useful, so I felt it was worth while to add the driver to svgalib + now. + + Linear graphics is working on this card, both with and without BACK- + GROUND enabled, and vga_runinbackground works. + + I decided it was best to quit working on more modes and try to get + acceleration and sprites working. + + My et6000 card is on a PCI bus. The card will run on a vesa bus, but + since I don't have one on my machine I couldn't develop vesa bus han- + dling. I quit if the bus is a vesa bus. + + I check for an et6000 card, which can be unequivocally identified. The + et4000 driver does not properly identify et4000 cards. It thinks the + et6000 card is an et4000, but can only run it in vga modes. + + I have found the following four modelines to be useful in 1mlibvga.config0m + or in 1m~/.svgalibrc 22mfor proper display of some modes. + + Modeline "512x384@79" 25.175 512 560 592 640 384 428 436 494 + Modeline "400x300@72" 25.000 400 456 472 520 300 319 332 350 DOUBLES- + CAN + Modeline "512x480@71" 25.175 512 584 600 656 480 500 510 550 + Modeline "400x600@72" 25.000 400 440 488 520 600 639 644 666 + + Don Secrest Aug 21, 1999 + + + + 1mOak Technologies OTI-037/67/77/870m + First a few comments of me (Michael Weller ): + + As of this writing (1.2.8) fixes were made to the oak driver by Frodo + Looijaard to reenable OTI-067 support. It is unknown + right now if they might have broken OTI-087 support. The author of the + '87 support Christopher Wiles owns no longer an + OTI-087 card and can thus no longer give optimal support to this + driver. Thus you might be better off contacting me or Frodo for ques- + tions. If you are a knowledgable OTI-087 user and experience problems + you are welcome to provide fixes. No user of a OTI-087 is currently + known to me, so if you are able to fix problems with the driver please + do so (and contact me) as noone else can. + + Michael. + + Now back to the original Oak information: + + The original OTI driver, which supported the OTI-067/77 at 640x480x256, + has been augmented with the following features: + + + 1m1) 22mSupported resolutions/colors have been expanded to 640x480x32K, + 800x600x256/32K, 1024x768x256, and 1280x1024x16. + + 1m2) 22mThe OTI-087 (all variants) is now supported. Video memory is + correctly recognized. + + + The driver as it exists now is somewhat schizoid. As the '87 incorpo- + rates a completely different set of extended registers, I found it nec- + essary to split its routines from the others. Further, I did not have + access to either a '67 or a '77 for testing the new resolutions. If + using them causes your monitor/video card to fry, your dog to bite you, + and so forth, I warned you. The driver works on my '87, and that's all + I guarantee. Period. + + Heh. Now, if someone wants to try them out ... let me know if they + work. + + New from last release: + + 32K modes now work for 640x480 and 800x600. I found that the Sierra + DAC information in VGADOC3.ZIP is, well, wrong. But, then again, the + information for the '87 was wrong also. + + 64K modes 1mdo not 22mwork. I can't even get Oak's BIOS to enter those + modes. + + I have included a 1280x1024x16 mode, but I haven't tested it. My moni- + tor can't handle that resolution. According to the documentation, with + 2 megs the '87 should be able to do an interlaced 1280x1024x256 ... + again, I couldn't get the BIOS to do the mode. I haven't 2 megs any- + way, so there it sits. + + I have included routines for entering and leaving linear mode. They + 1mshould 22mwork, but they don't. It looks like a pointer to the frame + buffer is not being passed to SVGALIB. I've been fighting with this + one for a month. If anyone wants to play with this, let me know if it + can be make to work. I've got exams that I need to pass. + + Tidbit: I pulled the extended register info out of the video BIOS. + When the information thus obtained failed to work, I procured the + OTI-087 data book. It appears that Oak's video BIOS sets various modes + incorrectly (e.g. setting 8-bit color as 4, wrong dot clock frequen- + cies, etc.). Sort of makes me wonder ... + + Christopher M. Wiles (a0017097@wsuaix.csc.wsu.edu) + 12 September 1994 + + +1m6. GOALS0m + I think the ability to use a VGA/SVGA graphics resolution in one vir- + tual console, and being able to switch to any other virtual console + and back makes a fairly useful implementation of graphics modes in the + Linux console. + + Programs that use 1msvgalib 22mmust be setuid root. I don't know how desir- + able it is to have this changed; direct port access can hardly be done + without. Root privileges can now be given up right after initializa- + tion. I noticed some unimplemented stuff in the kernel header files + that may be useful, although doing all register I/O via the kernel + would incur a significant context-switching overhead. An alternative + might be to have a pseudo 4m/dev/vga24m device that yields the required per- + missions when opened, the device being readable by programs in group + vga. + + It is important that textmode is restored properly and reliably; it is + fairly reliable at the moment, but fast console switching back and + forth between two consoles running graphics can give problems. Wild + virtual console switching also sometimes corrupts the contents of the + textmode screen buffer (not the textmode registers or font). Also if a + program crashes it may write into the area where the saved textmode + registers are stored, causing textmode not be restored correctly. It + would be a good idea to somehow store this information in a 'safe' area + (say a kernel buffer). Note that the 1mvga_safety_fork22m(3) thing has the + same idea. + + Currently, programs that are in graphics mode are suspended while not + in the current virtual console. Would it be a good idea to let them run + in the background, virtualizing framebuffer actions (this should not be + too hard for linear banked SVGA modes)? It would be nice to have, say, + a raytracer with a real-time display run in the background (although + just using a separate real-time viewing program is much more elegant). + + Anyone wanting to rewrite it all in a cleaner way (something with load- + able kernel modules shouldn't hurt performance with linear frame- + buffer/vgagl type applications) is encouraged. + + Also, if anyone feels really strongly about a low-resource and true- + color supporting graphical window environment with cut-and-paste, I + believe it would be surprisingly little work to come up with a simple + but very useful client-server system with shmem, the most useful appli- + cations being fairly trivial to write (e.g. shell window, bitmap + viewer). And many X apps would port trivially. + + This is old information, please be sure to read 1msvgalib.faq22m(7) if you + are interested in further goals. + + +1m7. REFERENCES0m + The latest version of svgalib can be found on 4msunsite.unc.edu24m in + 4m/pub/Linux/libs/graphics24m or 4mtsx-11.mit.edu24m in 4m/pub/linux/sources/libs0m + as 4msvgalib-X.X.X.tar.gz24m. As of this writing the latest version is + 4msvgalib-1.4.1.tar.gz24m. There are countless mirrors of these ftp servers + in the world. Certainly a server close to you will carry it. + + The original VGAlib is on 4mtsx-11.mit.edu24m, + 4mpub/linux/sources/libs/vgalib12.tar.Z24m. 4mtvgalib-1.0.tar.Z24m is in the + same directory. + + SLS has long been distributing an old version of VGAlib. Slackware + keeps a fairly up-to-date version of svgalib, but it may be installed + in different directories from what svgalib likes to do by default. The + current svgalib install tries to remove most of this. It also removes + 4m/usr/bin/setmclk24m and 4m/usr/bin/convfont24m, which is a security risk if + setuid-root. Actually the recent makefiles try to do a really good job + to cleanup the mess which some distributions make. + + If you want to recompile the a.out shared library, you will need the + DLL 'tools' package (found on 4mtsx-11.mit.edu24m, 4mGCC24m dir). To make it + work with recent ELF compiler's you actually need to hand patch it. You + should probably not try to compile it. Compiling the ELF library is + deadly simple. + + And here is a list of other references which is horribly outdated. + There are many more svgalib applications as well as the directories + might have changed. However, these will give you a start point and + names to hunt for on CD's or in ftp archives. + + + 1mViewers (in /pub/Linux/apps/graphics/viewers on sunsite.unc.edu):0m + 1mspic 22mPicture viewer; JPG/PPM/GIF; truecolor; scrolling. + 1mzgv 22mFull-featured viewer with nice file selector. + 1msee-jpeg0m + Shows picture as it is being built up. + 1mmpeg-linux0m + svgalib port of the Berkeley MPEG decoder (mpeg_play); it also + includes an X binary. + 1mflip 22mFLI/FLC player (supports SVGA-resolution). + + + 1mGames (in /pub/Linux/games on sunsite.unc.edu):0m + 1mbdash 22mB*lderdash clone with sound. + 1msasteroids0m + Very smooth arcade asteroids game. + 1myatzy 22mNeat mouse controlled dice game. + 1mvga_cardgames0m + Collection of graphical card games. + 1mvga_gamespack0m + Connect4, othello and mines. + 1mwt 22mFree state-of-the-art Doom-like engine. + 1mMaelstrom0m + A very nice asteroids style game port from Mac. + 1mKoules 22mA game. (I've no idea what it looks like) + + + 1mDocs0m + In the vga directory of the 1mSIMTEL MSDOS 22mcollection, there is a package + called 4mvgadoc324m which is a collection of VGA/SVGA register information. + + The XFree86 driver sources distributed with the link-kit may be help- + ful. + + + 1mMiscellaneous0m + There's an alternative RAW-mode keyboard library by Russell Marks for + use with 1msvgalib 22mon 4msunsite.unc.edu24m. + + 1mLIBGRX22m, the extensive framebuffer library by Csaba Biegl distributed + with 1mDJGPP22m, has been ported to Linux. Contact Hartmut Schirmer + (phc27@rz.uni-kiel.d400.de, subject prefix "HARTMUT:"). A more up-to- + date port by Daniel Jackson (djackson@icomp.intel.com) is on 4msun-0m + 4msite.unc.edu24m. + + The vgalib ghostscript device driver sources can be found on 4msun-0m + 4msite.unc.edu24m, 4m/pub/Linux/apps/graphics24m. Ghostscript patches from + Slackware: 4mftp.cdrom.com24m, 4m/pub/linux/misc24m. 1mgnuplot 22mpatches are on 4msun-0m + 4msite.unc.edu24m. + + Mitch D'Souza has written font functions that work in 16 color modes + and can use VGA textmode (codepage format) fonts; these can be found in + his 1mg3fax 22mpackage in 4msunsite.unc.edu24m. These functions may go into a + later version of 1msvgalib22m. + + +1m8. KNOWN BUGS0m + This section is most probably outdated, none of these problems are no + longer reported. + + Using a 132 column textmode may cause graphics modes to fail. Try using + something like 80x28. + + The console switching doesn't preserve some registers that may be used + to draw in planar VGA modes. + + Wild console switching can cause the text screen to be corrupted, espe- + cially when switching between two graphics consoles. + + On ET4000, having run XFree86 may cause high resolution modes to fail + (this is more XFree86's fault). + + The Trident probing routine in the XFree86 server may cause standard + VGA modes to fail after exiting X on a Cirrus. Try putting a 'Chipset' + line in your Xconfig to avoid the Trident probe, or use the link kit to + build a server without the Trident driver. Saving and restoring the + textmode registers with savetextmode/textmode (restoretextmode) should + also work. [Note: svgalib now resets the particular extended register, + but only if the Cirrus driver is used (i.e. the chipset is not forced + to VGA)] [This is fixed in XFree86 v2.1] + + Some Paradise VGA cards may not work even in standard VGA modes. Can + anyone confirm this? + + Piping data into a graphics program has problems. I am not sure why. A + pity, since zcatting a 5Mb FLC file into flip on a 4Mb machine would be + fun. + + The 1mtseng3.exe 22mDOS program include as source in the svgalib distribu- + tion doesn't recognize any modes on some ET4000 cards. Also ET4000 + cards with a Acumos/Cirrus DAC may only work correctly in 64K color + mode. + + +1mFILES0m + 4m/etc/vga/libvga.config0m + 4m/etc/vga/libvga.et40000m + + +1mSEE ALSO0m + 1msvgalib.et400022m(7), 1msvgalib.chips22m(7), 1msvgalib.mach3222m(7), 1mvgagl22m(7), 1mlib-0m + 1mvga.config22m(5), 1m3d22m(6), 1maccel22m(6), 1mbg_test22m(6), 1meventtest22m(6), 1mforktest22m(6), + 1mfun22m(6), 1mkeytest22m(6), 1mlineart22m(5), 1mmousetest22m(6), 1mjoytest22m(6), 1mmjoytest22m(6), + 1mscrolltest22m(6), 1mspeedtest22m(6), 1mspin22m(6), 1mtestaccel22m(6), 1mtestgl22m(6), 1mtestlin-0m + 1mear22m(6), 1mvgatest22m(6), 1mplane22m(6), 1mwrapdemo22m(6), 1mconvfont22m(1), 1mdumpreg22m(1), + 1mfix132x4322m(1), 1mrestorefont22m(1), 1mrestorepalette22m(1), 1mrestoretextmode22m(1), + 1mrunx22m(1), 1msavetextmode22m(1), 1msetmclk22m(1), 1mtextmode22m(1), 1mmach32info22m(1). + + +1mAUTHOR0m + There are many authors of svgalib. This page was edited by Michael + Weller . The original documentation and + most of 1msvgalib 22mwas done by Harm Hanemaayer + though. + + + +Svgalib 1.4.1 16 December 1999 svgalib(7) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6b18cce --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +This package is copyrighted by the people who wrote it. +You may do with it whatever you want. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..38a3244 --- /dev/null +++ b/Makefile @@ -0,0 +1,353 @@ +#---------------------------------------------------------------------OU +# Makefile for SVGAlib. +# +# It's pretty unreadable, but just doing make install should be +# enough. This will install the header files and shared library first +# (which is enough to compile things), after which the static version is +# optionally compiled and installed (if it fails, the shared libraries +# should still work fine). +# +#---------------------------------------------------------------------- + +# *** NO SERVICIBLE PARTS HERE! +# All options are in Makefile.cfg. + +#include Makefile.ppc +include Makefile.cfg + +#---------------------------------------------------------------------- +# Rules Section +#---------------------------------------------------------------------- + +# In case someone goes for the demos w/o installing svgalib make +# the static libs first. +ifdef INSTALLSHAREDLIB + PREDEMO = +else + PREDEMO = static +endif + +# A flag if this is a distribution: +DISTRIBUTION = $(shell sh -c "echo sharedlib/DIST*") + +UTILS = restorefont runx restorepalette restoretextmode textmode \ + savetextmode dumpreg fix132x43 + +OBSOLETEHDIRS = /usr/include/ /usr/include/vga/ /usr/local/include/ /usr/local/include/vga/ +OBSOLETEBDIRS = /usr/bin/ /usr/local/bin/ + +OBSOLETEHEADERS = /inc/vga.h /inc/vgakeyboard.h /inc/vgamouse.h /inc/vgagl.h /inc/vgajoystick.h + +OBSOLETELIBLINKS = /lib/libvga.so /lib/libvga.so.1 /lib/libvgagl.so /lib/libvgagl.so.1 + +OBSOLETESHAREDIMAGES = /lib/libvga.so.1.* /lib/libvga.so + +# for ELF +OBSOLETESHAREDIMAGES += /lib/libvgagl.so.1.* /lib/libvgagl.so + +OBSOLETELDIRS = /lib/ /usr/lib/ /usr/local/lib/ /usr/share/lib/ \ + $(shell sed 's?\#.*$$??' /etc/ld.so.conf 2>/dev/null | \ + sed 's?\([^/]\)[ ]*$$?\1/ ?' | grep -v aout/ ) + +SHAREDLIBS = sharedlib/libvga.so.$(VERSION) sharedlib/libvgagl.so.$(VERSION) +SVGALIBSHAREDSTUBS = +JUMP = + +BACKUP = ../svgalib-$(VERSION).tar.gz + +default: + @echo "To install SVGAlib, do one of the following:" + @echo "" + @echo " make clean - clean every thing. Do this after every change" + @echo " of Makefile.cfg!" + @echo " make install - compile & install components specified in Makefile.cfg" + @echo " make demoprogs - make demo programs in demo/ and threeDKit/" + @echo "" + @echo " make uninstall - remove an existing installation from various" + @echo " common places. (old traces often confuse the" + @echo " compiler even when svgalib is not installed anew)" + @echo " (make install includes an uninstall first)" + @echo "" + @echo " Be sure to read the file 0-INSTALL!" + @echo "" + +.PHONY: default all install installheaders installconfig +.PHONY: clean distclean indent uninstall +.PHONY: force_remake remake_shared shared static +.PHONY: indent-gnu + +installheaders: + @echo Installing header files in $(includedir). + @mkdir -p $(includedir) + @cp $(SRCDIR)/src/vga.h $(includedir)/vga.h + @chmod a+r $(includedir)/vga.h + @cp $(SRCDIR)/gl/vgagl.h $(includedir)/vgagl.h + @chmod a+r $(includedir)/vgagl.h + @cp $(SRCDIR)/src/mouse/vgamouse.h $(includedir)/vgamouse.h + @chmod a+r $(includedir)/vgamouse.h + @cp $(SRCDIR)/src/joystick/vgajoystick.h $(includedir)/vgajoystick.h + @chmod a+r $(includedir)/vgajoystick.h + @cp $(SRCDIR)/src/keyboard/vgakeyboard.h $(includedir)/vgakeyboard.h + @chmod a+r $(includedir)/vgakeyboard.h + +installsharedlib: $(SHAREDLIBS) $(SVGALIBSHAREDSTUBS) + @echo Installing shared library image as \ + $(addprefix $(sharedlibdir)/,$(notdir $(SHAREDLIBS))). + @mkdir -p ${sharedlibdir}; + @for foo in $(notdir $(SHAREDLIBS)); do \ + $(INSTALL_SHLIB) sharedlib/$$foo $(sharedlibdir)/$$foo; \ + (cd $(sharedlibdir); \ + ln -sf $$foo `echo $$foo | sed 's/\.so\..*/.so/'` ); \ + done + @./fixldsoconf + -ldconfig + +installstaticlib: static + @echo Installing static libraries in $(libdir). + @mkdir -p $(libdir) + @$(INSTALL_DATA) staticlib/libvga.a $(libdir)/libvga.a + @chmod a+r $(libdir)/libvga.a + @$(INSTALL_DATA) staticlib/libvgagl.a $(libdir)/libvgagl.a + @chmod a+r $(libdir)/libvgagl.a + +installutils: textutils $(LRMI) + @if [ ! -d $(bindir) ]; then \ + echo No $(bindir) directory, creating it.; \ + mkdir -p $(bindir); \ + fi + @echo Installing textmode utilities in $(bindir): + @echo "restorefont: Save/restore textmode font." + @$(INSTALL_PROGRAM) utils/restorefont $(bindir) + @echo "restorepalette: Set standard VGA palette." + @$(INSTALL_PROGRAM) utils/restorepalette $(bindir) + @echo "dumpreg: Write ASCII dump of SVGA registers." + @$(INSTALL_PROGRAM) utils/dumpreg $(bindir) + @echo "restoretextmode: Save/restore textmode registers." + @$(INSTALL_PROGRAM) utils/restoretextmode $(bindir) + @echo "textmode: Script that tries to restore textmode." + @$(INSTALL_SCRIPT) utils/textmode $(bindir) + @echo "savetextmode: Script that saves textmode information used by 'textmode'." + @$(INSTALL_SCRIPT) utils/savetextmode $(bindir) +ifeq ($(LRMI),lrmi) + @echo "mode3: Restore textmode by setting VESA mode 3." + @$(INSTALL_PROGRAM) lrmi-0.6m/mode3 $(bindir) +endif + @echo "Installing keymap utilities in $(bindir):" + @echo "svgakeymap: Perl script that generates scancode conversion maps." + @$(INSTALL_SCRIPT) utils/svgakeymap $(bindir) + +installconfig: + mkdir -p ${datadir}; + @if [ \( -f /usr/local/lib/libvga.config -a ! -f $(datadir)/libvga.config \) ]; then \ + echo "Moving old config file /usr/local/lib/libvga.config to $(datadir)." ; \ + mv -f /usr/local/lib/libvga.config $(datadir)/libvga.config; \ + fi + @if [ \( -f /usr/local/lib/libvga.et4000 -a ! -f $(datadir)/libvga.et4000 \) ]; then \ + echo "Moving old config file /usr/local/lib/libvga.et4000 to $(datadir)." ; \ + mv -f /usr/local/lib/libvga.et4000 $(datadir)/libvga.et4000; \ + fi + @if [ \( -f /usr/local/lib/libvga.ega -a ! -f $(datadir)/libvga.ega \) ]; then \ + echo "Moving old config file /usr/local/lib/libvga.ega to $(datadir)." ; \ + mv -f /usr/local/lib/libvga.ega $(datadir)/libvga.ega; \ + fi + @if [ \( -f /etc/mach32.eeprom -a ! -f $(datadir)/mach32.eeprom \) ]; then \ + echo Consider moving your /etc/mach32.eeprom file to $(datadir) ; \ + echo and changing $(datadir)/libvga.config appropriately. ; \ + fi + @if [ ! -f $(datadir)/libvga.config ]; then \ + echo Installing default configuration file in $(datadir).; \ + cp $(CONFDIR)/libvga.config $(datadir)/libvga.config; \ + fi + @if [ ! -f $(datadir)/libvga.et4000 ]; then \ + echo Installing dynamically loaded ET4000 registers in $(datadir).; \ + cp $(CONFDIR)/et4000.regs $(datadir)/libvga.et4000; \ + fi + @if [ ! -f $(datadir)/default.keymap ]; then \ + echo Installing default keymap file in $(datadir).; \ + cp $(CONFDIR)/default.keymap $(datadir)/null.keymap; \ + fi + @if [ ! -f $(datadir)/dvorak-us.keymap ]; then \ + echo Installing Dvorak keymap file in $(datadir).; \ + cp $(CONFDIR)/dvorak-us.keymap $(datadir)/dvorak-us.keymap; \ + fi + +installman: + (cd doc; $(MAKE) -f $(SRCDIR)/doc/Makefile SRCDIR="$(SRCDIR)" install ) + +installmodule: + (cd kernel/svgalib_helper ; $(MAKE) default modules_install ) + +installmodule.alt: + (cd kernel/svgalib_helper ; $(MAKE) -f Makefile.alt modules_install ) + +installdev: + (cd kernel/svgalib_helper ; $(MAKE) device ) + +lib3dkit-install: + (cd threeDKit/; $(MAKE) install) + +install: installheaders $(INSTALLSHAREDLIB) installconfig \ + $(INSTALLSTATICLIB) $(INSTALLUTILS) $(INSTALLMAN) $(INSTALLMODULE) $(INSTALLDEV) \ + lib3dkit-install + @echo + @echo + @echo Now run "'make demoprogs'" to make the test and demo programs in + @echo demos/ and threedkit/. + +uninstall: + @echo "Removing textmode utilities..." + @for i in $(OBSOLETEBDIRS); do \ + for prog in $(UTILS); do \ + rm -f $$i$$prog ; \ + done ; \ + done + @echo "Removing shared library stubs (old & current)..." + @for i in $(OBSOLETELDIRS); do \ + rm -f `echo /lib/libvga.so.$(VERSION) /lib/libvgagl.so.$(VERSION) \ + $(OBSOLETELIBLINKS) /lib/libvga.sa /lib/libvgagl.sa \ + | sed s?/lib/?$$i?g`; \ + done +ifndef KEEPSHAREDLIBS + @echo "Removing shared library images (old & current)..." + @for i in $(OBSOLETELDIRS); do \ + rm -f `echo $(OBSOLETESHAREDIMAGES) | sed s?/lib/?$$i?g`; \ + done +endif + @echo "Removing static libraries..." + @for i in $(OBSOLETELDIRS); do \ + rm -f `echo /lib/libvga.a /lib/libvgagl.a | sed s?/lib/?$$i?g`; \ + done + @echo "Removing header files..." + @for i in $(OBSOLETEHDIRS); do \ + rm -f `echo $(OBSOLETEHEADERS) | sed s?/inc/?$$i?g`; \ + done + (cd doc; $(MAKE) -f $(SRCDIR)/doc/Makefile SRCDIR="$(SRCDIR)" uninstall) + + +SHAREDDIRS0 = sharedlib/mouse sharedlib/keyboard sharedlib/ramdac \ + sharedlib/clockchip sharedlib/joystick \ + sharedlib/drivers +SHAREDDIRS = $(SHAREDDIRS0) $(JUMP) +STATICDIRS = staticlib/mouse staticlib/keyboard staticlib/ramdac \ + staticlib/clockchip staticlib/joystick \ + staticlib/drivers +UTILDIRS = utils +DEMODIRS = demos threeDKit + +$(SHAREDDIRS0) $(STATICDIRS) $(DEMODIRS): + mkdir -p $@ + +utils: + mkdir -p utils + if [ ! -f utils/runx ]; then \ + cp $(SRCDIR)/utils/runx $(SRCDIR)/utils/savetextmode \ + $(SRCDIR)/utils/textmode utils; \ + fi + +static: staticlib/libvga.a staticlib/libvgagl.a + +.PHONY: staticlib/libvgagl.a staticlib/libvga.a + +staticlib/libvgagl.a staticlib/libvga.a: $(STATICDIRS) + (cd $(dir $@); \ + $(MAKE) -f $(SRCDIR)/src/Makefile $(notdir $@) \ + SRCDIR="$(SRCDIR)" DLLFLAGS="" \ + ) + +# ELF + +.PHONY: sharedlib/libvga.so.$(VERSION) sharedlib/libvgagl.so.$(VERSION) + +shared: $(SHAREDLIBS) $(SVGALIBSHAREDSTUBS) + +sharedlib/libvga.so.$(VERSION): $(SHAREDDIRS) + @rm -f sharedlib/DISTRIBUTION + (cd $(dir $@); \ + $(MAKE) -f $(SRCDIR)/src/Makefile $(notdir $@) \ + SRCDIR="$(SRCDIR)" DLLFLAGS="$(DLLFLAGS)"; \ + ln -fs libvga.so.$(VERSION) libvga.so; \ + ) + +sharedlib/libvgagl.a: $(SHAREDDIRS) + (cd $(dir $@); \ + $(MAKE) -f $(SRCDIR)/gl/Makefile $(notdir $@) \ + SRCDIR="$(SRCDIR)" DLLFLAGS="$(DLLFLAGS)" \ + ) + +sharedlib/libvgagl.so.$(VERSION): $(SHAREDDIRS) + (cd $(dir $@); \ + $(MAKE) -f $(SRCDIR)/gl/Makefile $(notdir $@) \ + SRCDIR="$(SRCDIR)" DLLFLAGS="$(DLLFLAGS)"; \ + ln -fs libvgagl.so.$(VERSION) libvgagl.so; \ + ) + +demoprogs: $(PREDEMO) $(DEMODIRS) + @for dir in $(DEMODIRS); do \ + if [ -d $(SRCDIR)/$$dir ]; then \ + (cd $$dir; \ + $(MAKE) -f $(SRCDIR)/$$dir/Makefile SRCDIR="$(SRCDIR)"); \ + fi; \ + done + +textutils: $(UTILDIRS) + (cd utils; \ + $(MAKE) -f $(SRCDIR)/utils/Makefile SRCDIR="$(SRCDIR)") + +lrmi: + (cd lrmi-0.6m;\ + $(MAKE)) + +backup: $(BACKUP) + +$(BACKUP): +# I tried using a dependency, but make reordered them +# thus I have to do it this way: + $(MAKE) shared + $(MAKE) distclean + + sed 's/^TARGET_FORMAT = a.out$$/# TARGET_FORMAT = a.out/' \ + $(SRCDIR)/Makefile.cfg | \ + sed 's/^#[ ]*TARGET_FORMAT = elf$$/TARGET_FORMAT = elf/' \ + > mkcfg ; \ + mv mkcfg $(SRCDIR)/Makefile.cfg; \ + (cd ..; \ + find svgalib-$(VERSION) ! -type d -print | sort | tar -cvf- -T- ) \ + | gzip -9 >$(BACKUP) + +distclean: + (cd $(SRCDIR)/doc; $(MAKE) clean) + (cd $(SRCDIR)/doc; $(MAKE) ../0-README) + (cd $(SRCDIR)/src; $(MAKE) clean) + (cd $(SRCDIR)/gl; $(MAKE) clean) + (cd $(SRCDIR)/utils; $(MAKE) clean) + (cd $(SRCDIR)/demos; $(MAKE) clean) + (cd $(SRCDIR)/threeDKit; $(MAKE) clean) + (cd $(SRCDIR)/lrmi-0.6m; $(MAKE) clean) + (cd $(SRCDIR)/kernel/svgalib_helper; $(MAKE) clean) + rm -f *.orig + find . \( -name '.depend*' -o -name '*~*' \) -exec rm {} \; + rm -rf sharedlib/[!l]* sharedlib/l[!i]* sharedlib/li[!b]* staticlib + rm -rf sharedlib/*.a core + mkdir -p sharedlib + touch sharedlib/DISTRIBUTION + +clean: distclean + rm -rf sharedlib + +indent: + find demos gl mach src support -name '*.[ch]' -exec indent -kr {} \; + indent -kr src/*.regs + +indent-gnu: + find demos gl mach src support -name '*.[ch]' -exec indent -gnu {} \; + indent -gnu src/*.regs + +dkms: + rm -rf /usr/src/svgalib_helper-$(VERSION) + mkdir -p /usr/src/svgalib_helper-$(VERSION) + cp -a kernel/svgalib_helper/* /usr/src/svgalib_helper-$(VERSION) + dkms add -m svgalib_helper -v $(VERSION) + dkms build -m svgalib_helper -v $(VERSION) + dkms install -m svgalib_helper -v $(VERSION) + +FORCE: diff --git a/Makefile.cfg b/Makefile.cfg new file mode 100644 index 0000000..6bc93d1 --- /dev/null +++ b/Makefile.cfg @@ -0,0 +1,362 @@ +#---------------------------------------------------------------------- +# SVGAlib Compile-time configuration file +#---------------------------------------------------------------------- +# If you change ANYTHING in here you MUST 'make clean' and remake what +# you need. +# +# BEWARE! The toggle settings (INCLUDE_*_DRIVER and such) are set when +# the symbols are set. The value is pointless. Even setting a variable +# to n means yes! + +MAJOR_VER = 1 +MINOR_VER = 9.25 +VERSION = $(MAJOR_VER).$(MINOR_VER) + +#---------------------------------------------------------------------- +# Kernel module Configuration Section +#---------------------------------------------------------------------- +# Char major device used by module +SVGALIB_HELPER_MAJOR = 209 + +# Linux kernel includes +ifeq ($(S_KERNELRELEASE),) +S_KERNELRELEASE = $(shell uname -r) +endif + +INCLUDEDIR = /lib/modules/$(S_KERNELRELEASE)/build/include + +DIREXIST = $(shell if [ -e $(INCLUDEDIR) ] ; then echo OK ; fi) +ifneq ($(DIREXIST), OK) +INCLUDEDIR = /usr/src/linux/include +endif + +ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) + +#---------------------------------------------------------------------- +# Configuration Section +#---------------------------------------------------------------------- +# Source directory. +#srcdir = /usr/local/src/svgalib-$(VERSION) +SRCDIR = $(shell sh -c pwd) + +CONFDIR = $(SRCDIR)/src/config + +# Common prefix for installation directories. +# NOTE: This directory must exist when you start the install. +TOPDIR= +prefix = $(TOPDIR)/usr/local +exec_prefix = $(prefix) + +# Directory where the shared stubs and static library will be installed. +libdir = $(exec_prefix)/lib + +# Directory where the shared library will be installed. +sharedlibdir = $(exec_prefix)/lib + +# Directory where the font and textmode utilities will be installed. +bindir = $(exec_prefix)/bin + +# Directory where the run-time configuration files will be installed. +datadir = $(TOPDIR)/etc/vga + +# Directory where the header files will be installed. +includedir = $(prefix)/include + +# Directory where the man files will be installed. +mandir = $(prefix)/share/man + +# Target binary format. +TARGET_FORMAT = elf + +# Uncomment this to use lrmi-0.9, instead of 0.6 +# USE_LRMI_9 = y + +# uncomment any of the following line to print some debug messages +# DEBUG = yes +# DEBUG_CONF = yes +# DEBUG_ACCEL = yes +# DEBUG_KEYBOARD = yes + +# uncomment this if your compiler fails on compiling the assembler in +# src/vgaconvplanar.c, gl/inlstring.h, gl/line.c or gl/scale.c +# NO_ASM = y + +# uncomment if you want to set attribute controller and dac without delay +# This breaks original VGA, but seems to work on new cards. +NO_DELAY = y + +# Uncomment this if you want root processes to be able to always get a new +# VC. Alas, some games misuse suid root privs and become root, svgalib cannot +# detect this and will allow Joe blow user to open a new virtual VC. If this +# annoys you, comment out the next line (which is the default already) +ROOT_VC_SHORTCUT = y + +# Uncomment thit to use libc's memcpy, instead of simple while loop. +# Use demos/linearspeed to see which is faster to video memory. +LIBC_MEMCPY = y + +# Uncomment this if you want to compile and install the static libs. +# INSTALLSTATICLIB = installstaticlib + +# Comment this out if you don't want to install the shared libs. +# If you do not install the shared nor the static libs, 'make static' +# first to enforce just building the static lib, then the demos will +# use this local static library! +INSTALLSHAREDLIB = installsharedlib + +# Comment this out if you want to keep old shared images. Old header files, +# library stubs and static libraries CANNOT be kept in public locations +# except when you rename them yourself. +# KEEPSHAREDLIBS = keep + +# Comment this out if you don't want to compile and install the utilities. +INSTALLUTILS = installutils + +# Comment this out if you don't want to install the man pages by default +INSTALLMAN = installman + +# Remove the '# ' from one of the next two lines if you want to install the +# man pages compressed (with gzip) or not. If you comment out both lines, +# the Makefiles will try to figure out if your system supports gzipped man +# pages and install them when possible. + +# MANFORMAT = compressed +# MANFORMAT = uncompressed + +# This is the command to update the man pages whatis database. +# This is a slow command. If you are not very patient, simple +# comment out this line +# MAKEWHATIS = makewhatis # Beware, this will really need a few minutes! + +# Comment this out if you use devfs or udev and don't want to make svga nodes +# INSTALLDEV = installdev + +# Select which makefile to use to install the module, or comment both out if +# you are going to install the kernel module manually +INSTALLMODULE = installmodule +# INSTALLMODULE = installmodule.alt + +# +# Comment out any driver that you don't want included in the library. + +# These drivers are obsolete and quite likely broken: + +#INCLUDE_ET4000_DRIVER = y +#INCLUDE_OAK_DRIVER = y +#INCLUDE_EGA_DRIVER = y +#INCLUDE_MACH32_DRIVER = y +#INCLUDE_ET3000_DRIVER = y +#INCLUDE_GVGA6400_DRIVER = y +#INCLUDE_ATI_DRIVER = y + +# End of obsolete drivers. + +INCLUDE_CHIPS_DRIVER = y + +INCLUDE_APM_DRIVER = y +INCLUDE_NV3_DRIVER = y +INCLUDE_G400_DRIVER = y +INCLUDE_R128_DRIVER = y +INCLUDE_VESA_DRIVER = y +INCLUDE_MX_DRIVER = y +INCLUDE_RENDITION_DRIVER = y +INCLUDE_RAGE_DRIVER = y +INCLUDE_BANSHEE_DRIVER = y +INCLUDE_SIS_DRIVER = y +INCLUDE_I740_DRIVER = y +INCLUDE_I810_DRIVER = y +INCLUDE_LAGUNA_DRIVER = y +INCLUDE_TRIDENT_DRIVER = y +INCLUDE_SAVAGE_DRIVER = y +INCLUDE_MILLENNIUM_DRIVER = y +##INCLUDE_G450C2_DRIVER = y +INCLUDE_PM2_DRIVER = y +INCLUDE_UNICHROME_DRIVER = y + +INCLUDE_NEO_DRIVER = y +INCLUDE_ET6000_DRIVER = y +INCLUDE_FBDEV_DRIVER = y + +# These drivers are obsolete, but most likely still work: + +INCLUDE_PARADISE_DRIVER = y +INCLUDE_ARK_DRIVER = y +INCLUDE_S3_DRIVER = y +INCLUDE_CIRRUS_DRIVER = y +INCLUDE_TVGA_DRIVER = y +INCLUDE_ALI_DRIVER = y + + +# +# Comment out any adapter you don't want to autodetect. +# +#INCLUDE_ET4000_DRIVER_TEST = y +INCLUDE_CIRRUS_DRIVER_TEST = y +INCLUDE_TVGA_DRIVER_TEST = y +INCLUDE_OAK_DRIVER_TEST = y +INCLUDE_EGA_DRIVER_TEST = y +INCLUDE_MACH32_DRIVER_TEST = y +INCLUDE_GVGA6400_DRIVER_TEST = y +INCLUDE_S3_DRIVER_TEST = y +INCLUDE_ET3000_DRIVER_TEST = y +INCLUDE_ARK_DRIVER_TEST = y +INCLUDE_ATI_DRIVER_TEST = y +INCLUDE_ALI_DRIVER_TEST = y +INCLUDE_CHIPS_DRIVER_TEST = y +INCLUDE_APM_DRIVER_TEST = y +INCLUDE_NV3_DRIVER_TEST = y +INCLUDE_G400_DRIVER_TEST = y +INCLUDE_R128_DRIVER_TEST = y +INCLUDE_ET6000_DRIVER_TEST = y +INCLUDE_MX_DRIVER_TEST = y +INCLUDE_TRIDENT_DRIVER_TEST = y +INCLUDE_PARADISE_DRIVER_TEST = y +INCLUDE_RAGE_DRIVER_TEST = y +INCLUDE_BANSHEE_DRIVER_TEST = y +INCLUDE_SIS_DRIVER_TEST = y +INCLUDE_I740_DRIVER_TEST = y +INCLUDE_I810_DRIVER_TEST = y +INCLUDE_LAGUNA_DRIVER_TEST = y +INCLUDE_NEO_DRIVER_TEST = y +INCLUDE_SAVAGE_DRIVER_TEST = y +INCLUDE_MILLENNIUM_DRIVER_TEST = y +INCLUDE_RENDITION_DRIVER_TEST = y +INCLUDE_PM2_DRIVER_TEST = y +INCLUDE_UNICHROME_DRIVER_TEST = y + +#INCLUDE_FBDEV_DRIVER_TEST = y + +#Might be too dangerous: +#INCLUDE_VESA_DRIVER_TEST = y + +# +# Comment out any dac support that you don't want included in the library. +# +# you must include SIERRA_DAC, if you include any of SCxxxx DACs. + + +INCLUDE_NORMAL_DAC = y +INCLUDE_S3_SDAC_DAC = y +INCLUDE_S3_GENDAC_DAC = y +INCLUDE_S3_TRIO64_DAC = y +INCLUDE_SIERRA_DAC = y +INCLUDE_SC15025_DAC = y +INCLUDE_ATT20C490_DAC = y +INCLUDE_ATT20C498_DAC = y +INCLUDE_ICW_DAC = y +INCLUDE_IBMRGB52x_DAC = y +INCLUDE_SC1148X_DAC = y +INCLUDE_ICS_GENDAC_DAC = y + +# +# Comment out any dac you don't want to autodetect. +# (not all dacs can be autodetected, at this time) +# +INCLUDE_S3_SDAC_DAC_TEST = y +INCLUDE_S3_GENDAC_DAC_TEST = y +INCLUDE_SC15025_DAC_TEST = y +INCLUDE_ATT20C490_DAC_TEST = y +INCLUDE_IBMRGB52x_DAC_TEST = y +INCLUDE_SC1148X_DAC_TEST = y +INCLUDE_ICS_GENDAC_DAC_TEST = y + +# LRMI - disbaled for non i386 +LRMI = lrmi + +# Location of the svgalib configuration file. +SVGALIB_CONFIG_FILE = $(datadir)/libvga.config + +# Defining DYNAMIC enables runtime parsing of the file defined by +# ET4000_REGS (usually /etc/libvga.et4000) for the et4000 +# driver. See et4000/README for details. Commenting this out again +# saves binary space. +# +# If you just want to use the et4000.regs in the source directory, +# comment out the definition of DYNAMIC. DYNAMIC allows development of new +# resolutions without recompiling. +DYNAMIC = y +ET4000_REGS = $(datadir)/libvga.et4000 + +# The EGA driver may load additional modes (SuperEGA cards) like the +# et4000 driver does. Just define the configuration file below. +# [This should be taken with a grain of salt, EGA is untested.] +#EGA_REGS = $(datadir)/libvga.ega + +# Defining USE_CLOCKS will cause the ET4000 driver to measure clock +# frequencies (they are not actually used yet). +#USE_CLOCKS = y + +# Uncomment to allow mouse type overrides +ALLOW_MOUSE_OVERRIDE = y + +#---------------------------------------------------------------------- +# Compiler Section +#---------------------------------------------------------------------- + +# Compiler used. +PC = ppc386 + +ifndef CC + CC = gcc +endif + + +ifndef CFLAGS + OPTIMIZE = -fomit-frame-pointer -O2 -fno-strength-reduce -pipe +else + OPTIMIZE := $(CFLAGS) +endif + +# You might want to add -m386 here if you have a recently installed +# (486 configured) compiler on a 386. The only real difference is the +# generous alignment padding of function entry-points for the 486. +WARN = -Wall -Wstrict-prototypes +INCLUDES = -I$(srcdir)/include -I. +CFLAGS = $(WARN) $(DLLFLAGS) $(INCLUDES) $(OPTIMIZE) $(DEFINES) +LDFLAGS = -s + +# additional flags for shared lib. +DLLFLAGS = -fPIC -DPIC + +# Utilites used. +AR = ar +INSTALL_PROGRAM = install -sm755 +INSTALL_SCRIPT = install -m755 +INSTALL_SHLIB = install -m755 +INSTALL_DATA = install -m644 + +ifneq ($(ARCH),i386) + NO_ASM = y + INCLUDE_VESA_DRIVER= + + INCLUDE_CHIPS_DRIVER= + INCLUDE_ET4000_DRIVER= + INCLUDE_MACH32_DRIVER= + INCLUDE_NEO_DRIVER= + INCLUDE_TVGA_DRIVER= + INCLUDE_I810_DRIVER= + LRMI= +endif + +ifeq ($(ARCH),ppc) + INCLUDE_S3_DRIVER= +endif + +ifneq ($(INCLUDE_S3_DRIVER),y) + INCLUDE_NORMAL_DAC = + INCLUDE_S3_SDAC_DAC = + INCLUDE_S3_GENDAC_DAC = + INCLUDE_S3_TRIO64_DAC = + INCLUDE_SIERRA_DAC = + INCLUDE_SC15025_DAC = + INCLUDE_ATT20C490_DAC = + INCLUDE_ATT20C498_DAC = + INCLUDE_ICW_DAC = + INCLUDE_IBMRGB52x_DAC = + INCLUDE_SC1148X_DAC = +endif + +ifeq ($(NO_HELPER),y) + INSTALLDEV = + INSTALLMODULE = +endif diff --git a/README b/README new file mode 100644 index 0000000..02fcd2e --- /dev/null +++ b/README @@ -0,0 +1,14 @@ +This is an _alpha_ release. Don't use it if you are not interested in +svgalib development. + +Program using svgalib 1.9.0 or later don't need root provoleges (suid +root). They do need access to /dev/svga, which is a char device +with major 209 and minor 0. +The module svgalib_helper need also be inserted. + +To make the devices, and the module (kernel 2.4 or newer), change to directory +kernel/svgalib_helper, and type make install. + +There is a compile time option to return to old behaviour, of using root +privileges to access /dev/mem, instead of svgalib helper. To compile for this +select the NO_HELPER option in Makefile.cfg. diff --git a/demos/Makefile b/demos/Makefile new file mode 100644 index 0000000..f7052f3 --- /dev/null +++ b/demos/Makefile @@ -0,0 +1,75 @@ +#---------------------------------------------------------------------- +# Makefile for SVGAlib demo programs. +# +# This file is a part of SVGAlib. +#---------------------------------------------------------------------- + +include ../Makefile.cfg + +srcdir = .. +VPATH = $(srcdir)/demos + +#---------------------------------------------------------------------- +# Compiler Section (overrides Makefile.cfg) +#---------------------------------------------------------------------- + +CFLAGS = $(WARN) $(OPTIMIZE) -I$(srcdir)/include -I$(srcdir)/gl $(DEBFLAGS) +ifeq (a.out, $(TARGET_FORMAT)) + CFLAGS += -DSVGA_AOUT +endif + +#---------------------------------------------------------------------- +# Rules Section +#---------------------------------------------------------------------- + +PROGS = fun testgl speedtest mousetest vgatest scrolltest testlinear \ + keytest testaccel accel forktest eventtest spin bg_test printftest \ + joytest mjoytest bankspeed lineart linearspeed addmodetest \ + svidtune linearfork cursor vgatweak buildcsr + +# Determine what library (static or shared) we will be linking programs with +ifdef INSTALLSHAREDLIB + LIBS = -lvgagl -lvga +endif +ifndef LIBS + LIBS = ../staticlib/libvgagl.a ../staticlib/libvga.a -lm + LVGADEP = $(LIBS) +endif + +all: $(PROGS) + +.PHONY: all clean cleanbin dep + +$(PROGS): $(LVGADEP) + +.c: + $(CC) $(CFLAGS) $(LDFLAGS) -o $* $*.c $(LIBS) + +rwpage: rwpage.pp + $(PC) -Rintel rwpage.pp + +testaccel: testaccel.c + $(CC) $(CFLAGS) $(LDFLAGS) -o testaccel testaccel.c $(LIBS) -lm + +accel: accel.c + $(CC) $(CFLAGS) $(LDFLAGS) -o accel accel.c $(LIBS) -lm + +linearspeed: linearspeed.c memset.o + $(CC) $(CFLAGS) $(LDFLAGS) -o linearspeed linearspeed.c memset.o $(LIBS) + +buildcsr: mkcur.o + $(CC) -o buildcsr $(LDFLAGS) mkcur.o -lvgagl -lvga + +clean: cleanbin + rm -f .depend *.o *~ *.bak core + +cleanbin: + rm -f $(PROGS) rwpage + +# +# No dependencies required here. +# + +dep: +.depend: + diff --git a/demos/accel.c b/demos/accel.c new file mode 100644 index 0000000..ea70aba --- /dev/null +++ b/demos/accel.c @@ -0,0 +1,1018 @@ + +/* + * This is only a tool to test the acceleration primitives. + * Do not use the primitives as library graphics functions; + * have higher level functions make use of acceleration + * primitives if available, otherwise using normal framebuffer code. + * For example, the vgagl should use acceleration when it can. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "vga.h" +#include "vgagl.h" +#include "wizard.xbm" +#include "wizardmsk.xbm" + +#define CROSS_SZ 5 + +#define LOGO_NAME "linuxlogo.bitmap" +#define LOGO_WIDTH 201 +#define LOGO_HEIGHT 85 + +#define BOXES_Y 3 +#define BOXES_X 4 +#define BOXES_B 10 + +#define BOXES_WIDTH (WIDTH/BOXES_X) +#define BOXES_HEIGHT ((HEIGHT - 8) / BOXES_Y) + +#define COPY_OFF 3 + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define abs(a) (((a) < 0) ? -(a) : (a)) + +#define QIXLINES 200 + +int vgamode; +int background_blits; +unsigned char *bitmap; +int accelfuncs, ropfuncs, transfuncs; +int ropmodes, transmodes; +int maxy; + +unsigned char blitimage[LOGO_WIDTH * LOGO_HEIGHT], *scaleimage, *expandimage; +unsigned char conv_wizard_bits[wizard_height * ((wizard_width + 31) & ~31)]; +unsigned char conv_wizardmsk_bits[wizardmsk_height * ((wizardmsk_width + 31) & ~31)]; + +void Configure(void); +void DrawDots(void); +void DoAccelTest(void (*accelfunc) (void), char *name, int exp_pixelrate, + int pixels_per_call); +void FillBoxTest(void); +void HlineBoxTest(void); +void ScreenCopyTest(void); +void ScrollTest(void); +void FillBoxXORTest(void); +void PutBitmapTest(void); +void PositionTest(void); +void GetLogo(void); +void ScaleLogo(void); +void RopTest(void); +void QixDemo(int rop, char *txt); + +void convxbm(int width, int height, unsigned char *bits, unsigned char *conv_bits); + +int main(void) +{ + vga_modeinfo *minfo; + + vga_init(); + + Configure(); + + /* Getting accel info only works if the mode it set. */ + vga_setlinearaddressing(); + vga_setmode(vgamode); + + accelfuncs = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL); + ropfuncs = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ROP); + transfuncs = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_TRANSPARENCY); + ropmodes = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ROPMODES); + transmodes = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_TRANSMODES); + minfo = vga_getmodeinfo(vgamode); + if (minfo->bytesperpixel) + maxy = minfo->maxpixels / (minfo->linewidth / minfo->bytesperpixel); + else + maxy = HEIGHT; + + usleep(100000); + vga_setmode(TEXT); + + if (accelfuncs == 0) { + printf("No acceleration supported.\n"); + exit(0); + } + printf("Accelflags: 0x%08X\n", accelfuncs); + + if (accelfuncs & ACCELFLAG_FILLBOX) + printf("FillBox supported.\n"); + if (accelfuncs & ACCELFLAG_SCREENCOPY) + printf("ScreenCopy supported.\n"); + if (accelfuncs & ACCELFLAG_PUTIMAGE) + printf("PutImage supported.\n"); + if (accelfuncs & ACCELFLAG_DRAWLINE) + printf("DrawLine.\n"); + if (accelfuncs & ACCELFLAG_SETFGCOLOR) + printf("SetFGColor supported.\n"); + if (accelfuncs & ACCELFLAG_SETBGCOLOR) + printf("SetBGColor supported.\n"); + if (accelfuncs & ACCELFLAG_SETTRANSPARENCY) + printf("SetTransparency supported.\n"); + if (accelfuncs & ACCELFLAG_SETRASTEROP) + printf("SetRasterOp supported.\n"); + if (accelfuncs & ACCELFLAG_PUTBITMAP) + printf("PutBitmap supported.\n"); + if (accelfuncs & ACCELFLAG_SCREENCOPYBITMAP) + printf("ScreenCopyBitmap supported.\n"); + if (accelfuncs & ACCELFLAG_DRAWHLINELIST) + printf("DrawHLineList supported.\n"); + if (accelfuncs & ACCELFLAG_POLYLINE) + printf("PolyLine supported.\n"); + if (accelfuncs & ACCELFLAG_POLYHLINE) + printf("PolyHLine supported.\n"); + if (accelfuncs & ACCELFLAG_POLYFILLMODE) + printf("PolyFillMode supported.\n"); + if (accelfuncs & ACCELFLAG_SETMODE) + printf("SetMode supported.\n"); + if (accelfuncs & ACCELFLAG_SYNC) + printf("Sync supported.\n"); + + if (accelfuncs & ACCELFLAG_SETRASTEROP) { + printf("\nRopAccelflags: 0x%08X\n", ropfuncs); + printf("RopModes: 0x%08X", ropmodes); + if (ropmodes & (1 << ROP_COPY)) + printf(" Copy"); + if (ropmodes & (1 << ROP_OR)) + printf(" Or"); + if (ropmodes & (1 << ROP_AND)) + printf(" And"); + if (ropmodes & (1 << ROP_XOR)) + printf(" Xor"); + if (ropmodes & (1 << ROP_INVERT)) + printf(" Invert"); + printf("\n"); + if (ropfuncs & ACCELFLAG_FILLBOX) + printf("FillBox supported.\n"); + if (ropfuncs & ACCELFLAG_SCREENCOPY) + printf("ScreenCopy supported.\n"); + if (ropfuncs & ACCELFLAG_PUTIMAGE) + printf("PutImage supported.\n"); + if (ropfuncs & ACCELFLAG_DRAWLINE) + printf("DrawLine.\n"); + if (ropfuncs & ACCELFLAG_PUTBITMAP) + printf("PutBitmap supported.\n"); + if (ropfuncs & ACCELFLAG_SCREENCOPYBITMAP) + printf("ScreenCopyBitmap supported.\n"); + if (ropfuncs & ACCELFLAG_DRAWHLINELIST) + printf("DrawHLineList supported.\n"); + if (ropfuncs & ACCELFLAG_POLYLINE) + printf("PolyLine supported.\n"); + if (ropfuncs & ACCELFLAG_POLYHLINE) + printf("PolyHLine supported.\n"); + if (ropfuncs & ACCELFLAG_POLYFILLMODE) + printf("PolyFillMode supported.\n"); + } + + if (accelfuncs & ACCELFLAG_SETTRANSPARENCY) { + printf("\nTransparencyAccelflags: 0x%08X\n", transfuncs); + printf("TranparencyModes: 0x%08X", transmodes); + if (transmodes & (1 << ENABLE_TRANSPARENCY_COLOR)) + printf(" TransparentColor"); + if (transmodes & (1 << ENABLE_BITMAP_TRANSPARENCY)) + printf(" TransparentBitmap"); + printf("\n"); + if (transfuncs & ACCELFLAG_FILLBOX) + printf("FillBox supported.\n"); + if (transfuncs & ACCELFLAG_SCREENCOPY) + printf("ScreenCopy supported.\n"); + if (transfuncs & ACCELFLAG_PUTIMAGE) + printf("PutImage supported.\n"); + if (transfuncs & ACCELFLAG_DRAWLINE) + printf("DrawLine.\n"); + if (transfuncs & ACCELFLAG_PUTBITMAP) + printf("PutBitmap supported.\n"); + if (transfuncs & ACCELFLAG_SCREENCOPYBITMAP) + printf("ScreenCopyBitmap supported.\n"); + if (transfuncs & ACCELFLAG_DRAWHLINELIST) + printf("DrawHLineList supported.\n"); + if (transfuncs & ACCELFLAG_POLYLINE) + printf("PolyLine supported.\n"); + if (transfuncs & ACCELFLAG_POLYHLINE) + printf("PolyHLine supported.\n"); + if (transfuncs & ACCELFLAG_POLYFILLMODE) + printf("PolyFillMode supported.\n"); + } + + printf("\nPress enter to start test.\n"); + getchar(); + + convxbm(wizard_width, wizard_height, wizard_bits, conv_wizard_bits); + convxbm(wizardmsk_width, wizardmsk_height, wizardmsk_bits, conv_wizardmsk_bits); + GetLogo(); + + vga_setmode(vgamode); + gl_setcontextvga(vgamode); + + ScaleLogo(); + gl_setcontextvga(vgamode); + + if (COLORS == 256) + gl_setrgbpalette(); + gl_setwritemode(FONT_COMPRESSED); + gl_setfont(8, 8, gl_font8x8); + gl_setfontcolors(gl_rgbcolor(0, 0, 0), gl_rgbcolor(255, 255, 255)); + + background_blits = 0; + if (accelfuncs & ACCELFLAG_SYNC) + background_blits = 1; + + PositionTest(); + gl_clearscreen(0); + if (accelfuncs & ACCELFLAG_SETRASTEROP) + RopTest(); + + QixDemo(ROP_COPY, "Replace QuixDemo"); + QixDemo(ROP_XOR, "Xor QuixDemo"); + if (accelfuncs & ACCELFLAG_FILLBOX) + DoAccelTest( + FillBoxTest, + "FillBox", + 50000000 / BYTESPERPIXEL, + WIDTH * HEIGHT * 256 + ); + + if (accelfuncs & ACCELFLAG_SCREENCOPY) { + DrawDots(); + gl_write(1, 1, "Measuring ACCEL_SCREENCOPY"); + DoAccelTest( + ScreenCopyTest, + "ScreenCopy", + 20000000 / BYTESPERPIXEL, + WIDTH * (HEIGHT / 3) * 3 + ); + } + if ((accelfuncs & ACCELFLAG_SCREENCOPY) + && (accelfuncs & ACCELFLAG_FILLBOX) + && (maxy > HEIGHT)) { + DrawDots(); + gl_write(1, HEIGHT - 9, "Scrolling with SCREENCOPY & FILLBOX"); + DoAccelTest( + ScrollTest, + "Scroll Demo", + 20000000 / BYTESPERPIXEL, + WIDTH * HEIGHT + ); + } + if (accelfuncs & ACCELFLAG_DRAWHLINELIST) + DoAccelTest( + HlineBoxTest, + "FillBox with DrawHlineList", + 50000000 / BYTESPERPIXEL, + WIDTH * HEIGHT * 256 + ); + + if ((accelfuncs & ACCELFLAG_FILLBOX) + && (accelfuncs & ACCELFLAG_SETRASTEROP) + && (ropfuncs & ACCELFLAG_FILLBOX)) { + DrawDots(); + gl_write(1, 1, "FILLBOX, xor with varying colors"); + DoAccelTest( + FillBoxXORTest, + "FillBox XOR", + 30000000 / BYTESPERPIXEL, + WIDTH * HEIGHT * 256 + ); + } + if (accelfuncs & ACCELFLAG_PUTBITMAP) { + bitmap = malloc(WIDTH * HEIGHT / 8); + memset(bitmap, 0x55, WIDTH * HEIGHT / 8); + DrawDots(); + DoAccelTest( + PutBitmapTest, + "PutBitmap", + 30000000 / BYTESPERPIXEL, + WIDTH * HEIGHT * 2 + ); + } + vga_setmode(TEXT); + exit(-1); +} + + +void Configure(void) +{ + int allowed[GLASTMODE + 1]; + + for (;;) { + int i; + int m; + for (i = G320x200x16; i <= GLASTMODE; i++) { + allowed[i] = 0; + if (vga_hasmode(i) + && vga_getmodeinfo(i)->bytesperpixel >= 1) { + printf("%2d %s\n", i, vga_getmodename(i)); + allowed[i] = 1; + } + } + + printf("\nWhich mode? "); + scanf("%d", &m); + getchar(); + printf("\n"); + if (m >= G320x200x16 && m <= GLASTMODE) { + vgamode = m; + break; + } + } +} + +void convxbm(int width, int height, unsigned char *bits, unsigned char *conv_bits) +{ + int scanline = ((width + 31) & ~31); + int y; + + scanline >>= 3; + width = (width + 7) >> 3; + for(y = 0; y < height; y++, conv_bits += scanline, bits += width) { + memcpy(conv_bits, bits, width); + if (width < scanline) + memset(conv_bits + width, 0, scanline - width); + } +} + +static unsigned char rotbyte(unsigned char c) +{ + unsigned char bit = 0x80, res = 0; + + for (; c; c >>= 1, bit >>= 1) + if (c & 1) + res |= bit; + return res; +} + +void DrawDots(void) +{ + int i, n; + /* Fill the screen with random dots. */ + gl_clearscreen(0); + n = WIDTH * HEIGHT / 100; /* 1% filled. */ + for (i = 0; i < n; i++) + gl_setpixel(rand() % WIDTH, rand() % HEIGHT, rand() % COLORS); +} + +void DoAccelTest(void (*accelfunc) (void), char *name, int exp_pixelrate, + int pixels_per_call) +{ + int i, n, startclock, diffclock; + int rate, byterate; + if (exp_pixelrate < 0) + /* Special case, #iterations indicated. */ + n = -exp_pixelrate; + else + /* Aim for about 5 seconds. */ + n = exp_pixelrate * 5 / pixels_per_call + 1; + + if (background_blits) + vga_accel(ACCEL_SETMODE, BLITS_IN_BACKGROUND); + + startclock = clock(); + for (i = 0; i < n; i++) + (*accelfunc) (); + if (background_blits) + vga_accel(ACCEL_SYNC); + diffclock = clock() - startclock; + if (diffclock == 0) { + /* At least let the program continue if something strange happens */ + printf("%s: Timing Error",name); + } else { + rate = (long long) n *pixels_per_call * 100 / diffclock; + byterate = rate * BYTESPERPIXEL; + printf("%s: %ld.%ld Mpixels/s (%ld.%ld Mbytes/s)\n", name, + rate / 1000000L, (rate % 1000000L) / 100000L, + byterate / 1000000L, (byterate % 1000000L) / 100000L); + } +} + +void FillBoxTest(void) +{ + int i; + for (i = 0; i < 256; i++) { + vga_accel(ACCEL_SETFGCOLOR, i); + vga_accel(ACCEL_FILLBOX, 0, 0, WIDTH, HEIGHT); + } +} + +void ScreenCopyTest(void) +{ + /* Copy first 1/3 to second 1/3. */ + vga_accel(ACCEL_SCREENCOPY, 0, 0, 0, HEIGHT / 3, WIDTH, HEIGHT / 3); + /* Copy third 1/3 to first 1/3. */ + vga_accel(ACCEL_SCREENCOPY, 0, (HEIGHT / 3) * 2, 0, 0, + WIDTH, HEIGHT / 3); + /* Copy second 1/3 to third 1/3. */ + vga_accel(ACCEL_SCREENCOPY, 0, HEIGHT / 3, 0, (HEIGHT / 3) * 2, + WIDTH, HEIGHT / 3); +} + +void ScrollTest(void) +{ + int i; + /* + * First write the line that will be scrolled into the screen, + * located after the visible screen. + */ + /* Clear the line. */ + vga_accel(ACCEL_SETFGCOLOR, 0); + vga_accel(ACCEL_FILLBOX, 0, HEIGHT, WIDTH, 1); + if (background_blits) + vga_accel(ACCEL_SYNC); + /* Write some new dots. */ + for (i = 0; i < WIDTH / 100; i++) + gl_setpixel(rand() % WIDTH, HEIGHT, rand() % COLORS); + /* Scroll. */ + vga_accel(ACCEL_SCREENCOPY, 0, 1, 0, 0, + WIDTH, HEIGHT); +} + +void FillBoxXORTest(void) +{ + vga_accel(ACCEL_SETRASTEROP, ROP_XOR); + vga_accel(ACCEL_SYNC); + FillBoxTest(); + vga_accel(ACCEL_SETRASTEROP, ROP_COPY); +} + +void PutBitmapTest(void) +{ + vga_accel(ACCEL_SETBGCOLOR, 0); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_PUTBITMAP, 0, 0, WIDTH, HEIGHT, bitmap); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 0, 255)); + vga_accel(ACCEL_PUTBITMAP, 0, 0, WIDTH, HEIGHT, bitmap); +} + +void DrawCross(int x, int y, int color) { + int i; + + for(i = y - CROSS_SZ; i <= y + CROSS_SZ; i++) + if (y != i) + gl_setpixel(x, i, color); + for(i = x - CROSS_SZ; i <= x + CROSS_SZ; i++) + gl_setpixel(i, y, color); +} + +void GetLogo(void) { + FILE *fd; + + fd = fopen(LOGO_NAME, "rb"); + if (!fd) { + read_err: + perror("Problems reading linuxlogo.bitmap"); + exit(2); + } + if (1 != fread(blitimage, LOGO_WIDTH * LOGO_HEIGHT, 1, fd)) + goto read_err; + fclose(fd); +} + +void ScaleLogo(void) { + unsigned char *ptr; + int w, h, x, y; + + expandimage = malloc(LOGO_WIDTH * LOGO_HEIGHT * BYTESPERPIXEL); + w = BOXES_WIDTH - 2 * BOXES_B - 2; + h = BOXES_HEIGHT - 2 * BOXES_B - 2; + scaleimage = malloc(w * h * BYTESPERPIXEL); + if (!scaleimage || !expandimage) { + perror("Out of buffer memory"); + exit(2); + } + gl_setcontextvirtual(LOGO_WIDTH, LOGO_HEIGHT, BYTESPERPIXEL, BITSPERPIXEL, expandimage); + for(y = 0, ptr = blitimage; y < LOGO_HEIGHT; y++) + for(x = 0; x < LOGO_WIDTH; x++, ptr++) { + gl_setpixelrgb(x, y, (7 & *ptr) << 5, (7 & (*ptr >> 3)) << 5, + (3 & (*ptr >> 6)) << 6); + } + gl_scalebox(LOGO_WIDTH, LOGO_HEIGHT, expandimage, w, h, scaleimage); +} + +void DrawFrame(int x1, int y1, int x2, int y2, int color) { + DrawCross(x1, y1, color); + DrawCross(x2, y1, color); + DrawCross(x1, y2, color); + DrawCross(x2, y2, color); +} + +void DrawHlines(int x, int y, int w, int h) { + int i, *xmin, *xmax; + + xmin = alloca(sizeof(int) * h); + xmax = alloca(sizeof(int) * h); + + for(i = 0; i < h; i++) + xmin[i] = x + (i * w - i + (h >> 2)) / (h - 1); + + x += w - 1; + for(i = 0; i < h; xmax[i++] = x); + vga_accel(ACCEL_DRAWHLINELIST, y, h, xmin, xmax); +} + +void HlineBoxTest(void) { + int i, *xmin, *xmax; + + xmin = alloca(sizeof(int) * HEIGHT); + xmax = alloca(sizeof(int) * HEIGHT); + + memset(xmin, 0, sizeof(int) * HEIGHT); + for(i = 0; i < HEIGHT; xmax[i++] = WIDTH - 1); + for (i = 0; i < 256; i++) { + vga_accel(ACCEL_SETFGCOLOR, i); + vga_accel(ACCEL_DRAWHLINELIST, 0, HEIGHT, xmin, xmax); + } +} + +static void draw_poly(unsigned short *coords) { + /* Intended bug: */ + vga_accel(ACCEL_POLYLINE, ACCEL_START | ACCEL_END, 2, coords); + vga_accel(ACCEL_POLYLINE, ACCEL_START, 2, coords + 2); + /* Proper continuation: */ + vga_accel(ACCEL_POLYLINE, 0, 7, coords + 4); +} + +static void draw_polyhli(int x, int y, int w, int h) { + int n, i, j, dp, flag = ACCEL_START; + unsigned short coords[40]; + + vga_lockvc(); + for(i = 0; i < h;) { + for(j = n = dp = 0; (j < 3) && (i < h); j++, i++) { + n++; + if (i < (h >> 1)) { + coords[dp++] = 6; + coords[dp++] = x; + coords[dp++] = x + (((w / 4) * (h - i)) / h); + coords[dp++] = x + (w / 2) - (((w / 6) * ((h >> 1) - i)) / h); + coords[dp++] = x + (w / 2) + (((w / 6) * ((h >> 1) - i)) / h); + coords[dp++] = x + w - 1 - (((w / 4) * (h - i)) / h); + coords[dp++] = x + w - 1; + } else { + coords[dp++] = 8; + coords[dp++] = x; + coords[dp++] = x + (((w / 4) * (h - i)) / h); + coords[dp++] = x + ((3 * w) / 8) - (((w / 6) * (i - (h >> 1))) / h); + coords[dp++] = x + ((3 * w) / 8) + (((w / 6) * (i - (h >> 1))) / h); + coords[dp++] = x + ((5 * w) / 8) - (((w / 6) * (i - (h >> 1))) / h); + coords[dp++] = x + ((5 * w) / 8) + (((w / 6) * (i - (h >> 1))) / h); + coords[dp++] = x + w - 1 - (((w / 4) * (h - i)) / h); + coords[dp++] = x + w - 1; + } + } + if (n) + vga_accel(ACCEL_POLYHLINE, flag | ((i >= h) ? ACCEL_END : 0), y, n, coords); + flag = 0; + } + vga_unlockvc(); +} + +static void draw_polygon(int mode, int x, int y, int w, int h) { + const unsigned short W = x + w - 1, H = y + h - 1; + unsigned short coords[] = { + x, y, W, y, W, H, (x + W)/2, y, + x, H, W, (y + H)/2, (x + W)/2, H, + x, (y + H)/2, W, (y + H)/2, + x, y}; + if (mode) { + int i; + + for(i = 0; i < (sizeof(coords) / sizeof(unsigned short) - 3); i += 2) + if (coords[i + 1] != coords[i + 3]) + vga_accel(ACCEL_DRAWLINE, coords[i], coords[i + 1], coords[i + 2], coords[i + 3]); + } else { + vga_accel(ACCEL_POLYLINE, ACCEL_START, sizeof(coords) / (2 * sizeof(unsigned short)), + coords); + } +} + +void PositionTest(void) { + int x, y, red, i = 0, w, h; + + red = gl_rgbcolor(255, 0, 0); + w = BOXES_WIDTH - 2 * BOXES_B; + h = BOXES_HEIGHT - 2 * BOXES_B; + gl_write(0, 0, "Testing accelerator positioning:"); + + for(y = BOXES_B + 8; y < HEIGHT; y += BOXES_HEIGHT) + for(x = BOXES_B; x < WIDTH; x += BOXES_WIDTH) { + DrawFrame(x, y, x + w - 1, y + h - 1, red); + switch(i++) { + case 0: + if (accelfuncs & ACCELFLAG_FILLBOX) { + gl_write(x + 1, y + h + 3, "Fillbox"); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + vga_accel(ACCEL_FILLBOX, x + 1, y + 1, w - 2, h - 2); + } + break; + case 1: + if (accelfuncs & ACCELFLAG_DRAWLINE) { + gl_write(x + 1, y + h + 3, "Linedraw"); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + vga_accel(ACCEL_DRAWLINE, x + 1, y + 1, x + w - 2, y + h - 2); + vga_accel(ACCEL_DRAWLINE, x + w - 2, y + 1, x + 1, y + h - 2); + } + break; + case 2: + if (accelfuncs & ACCELFLAG_PUTIMAGE) { + gl_write(x + 1, y + h + 3, "Putimage"); + vga_accel(ACCEL_PUTIMAGE, x + 1, y + 1, w - 2, h - 2, scaleimage); + } + break; + case 3: + if (accelfuncs & ACCELFLAG_SCREENCOPY) { + gl_write(x + 1, y + h + 3, "Screencopy (l->h)"); + gl_putbox(x + 1, y + 1, w - 2, h - 2, scaleimage); + vga_accel(ACCEL_SCREENCOPY, x + 1, y + 1, + x + COPY_OFF, y + COPY_OFF, w - 2, h - 2); + DrawFrame(x + COPY_OFF - 1, y + COPY_OFF - 1, + x + COPY_OFF + w - 2, y + COPY_OFF + h - 2, + gl_rgbcolor(0, 255, 0)); + } + break; + case 4: + if (accelfuncs & ACCELFLAG_SCREENCOPY) { + gl_write(x + 1, y + h + 3, "Screencopy (h->l)"); + gl_putbox(x + 1, y + 1, w - 2, h - 2, scaleimage); + vga_accel(ACCEL_SCREENCOPY, x + 1, y + 1, + x - COPY_OFF, y - COPY_OFF, w - 2, h - 2); + DrawFrame(x - COPY_OFF - 1, y - COPY_OFF - 1, + x - COPY_OFF + w - 2, y - COPY_OFF + h - 2, + gl_rgbcolor(0, 255, 0)); + } + break; + case 5: + if (accelfuncs & ACCELFLAG_DRAWHLINELIST) { + gl_write(x + 1, y + h + 3, "Hlinelist"); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + DrawHlines(x + 1, y + 1, w - 2, h - 2); + } + break; + case 6: + if (accelfuncs & ACCELFLAG_PUTBITMAP) { + int xo, yo, i; + unsigned int bmaptmp[8]; + + gl_write(x + 1, y + h + 3, "PutBitmap"); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + for(i = 0; i < 8; i++) + bmaptmp[i] = rotbyte(gl_font8x8['0' * 8 + i]); + vga_accel(ACCEL_PUTBITMAP, x + 1, y + 1, + 8, 8, bmaptmp); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(0, 255, 0)); + for(i = 0; i < 8; i++) + bmaptmp[i] = rotbyte(gl_font8x8['1' * 8 + i]); + vga_accel(ACCEL_PUTBITMAP, x + w - 9, y + 1, + 8, 8, bmaptmp); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 0, 0)); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(255, 255, 255)); + for(i = 0; i < 8; i++) + bmaptmp[i] = rotbyte(gl_font8x8['2' * 8 + i]); + vga_accel(ACCEL_PUTBITMAP, x + 1, y + h - 9, + 8, 8, bmaptmp); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(0, 0, 0)); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 255)); + for(i = 0; i < 8; i++) + bmaptmp[i] = rotbyte(gl_font8x8['3' * 8 + i]); + vga_accel(ACCEL_PUTBITMAP, x + w - 9, y + h - 9, + 8, 8, bmaptmp); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 0)); + xo = (w - wizard_width) / 2; + yo = (h - wizard_height) / 2; + vga_accel(ACCEL_PUTBITMAP, x + xo, y + yo, + wizard_width, wizard_height, conv_wizard_bits); + } + break; + case 7: + if ((accelfuncs & ACCELFLAG_PUTBITMAP) && + (accelfuncs & ACCELFLAG_SETTRANSPARENCY) && + (transfuncs & ACCELFLAG_PUTBITMAP) && + (transmodes & (1 << ENABLE_BITMAP_TRANSPARENCY))) { + + gl_write(x + 1, y + h + 3, "BitmapTransparency"); + gl_putbox(x + 1, y + 1, w - 2, h - 2, scaleimage); + vga_accel(ACCEL_SETTRANSPARENCY, ENABLE_BITMAP_TRANSPARENCY); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 0, 0)); + vga_accel(ACCEL_PUTBITMAP, x + 1, y + 1, + wizardmsk_width, wizardmsk_height, conv_wizardmsk_bits); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 0)); + vga_accel(ACCEL_PUTBITMAP, x + 1, y + 1, + wizard_width, wizard_height, conv_wizard_bits); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_PUTBITMAP, x + w - wizard_width - 1, y + 1, + wizard_width, wizard_height, conv_wizard_bits); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + vga_accel(ACCEL_PUTBITMAP, x + 1, y + h - wizard_height - 1, + wizard_width, wizard_height, conv_wizard_bits); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 255)); + vga_accel(ACCEL_PUTBITMAP, x + w - wizard_width - 1, + y + h - wizard_height - 1, + wizard_width, wizard_height, conv_wizard_bits); + vga_accel(ACCEL_SETTRANSPARENCY, DISABLE_BITMAP_TRANSPARENCY); + } + break; + case 8: + if (accelfuncs & ACCELFLAG_SCREENCOPYMONO) { + gl_write(x + 1, y + h + 3, "MonoScreenCopy"); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + vga_accel(ACCEL_SCREENCOPYMONO, x + 1, y + h + 3, + x + 1, y + 1, 14 * 8, 8); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(0, 255, 0)); + vga_accel(ACCEL_SCREENCOPYMONO, x + 1, y + h + 3, + x + w - 1 - 14 * 8, y + 1, 14 * 8, 8); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 0, 0)); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(255, 255, 255)); + vga_accel(ACCEL_SCREENCOPYMONO, x + 1, y + h + 3, + x + 1, y + h - 9, 14 * 8, 8); + vga_accel(ACCEL_SETBGCOLOR, gl_rgbcolor(0, 0, 0)); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 255)); + vga_accel(ACCEL_SCREENCOPYMONO, x + 1, y + h + 3, + x + w - 1 - 14 * 8, y + h - 9, 14 * 8, 8); + } + break; + case 9: + if (accelfuncs & ACCELFLAG_POLYLINE) { + unsigned short X = x + 1, Y = y + 1, W = x + w - 2, + H = y + (h >> 1) - 2; + + unsigned short coords[] = { + X, Y, (X + W)/2, Y, W, Y, + W, H, X + (3 * (W - X))/4, H, + (X + W)/2, (Y + H)/2, + X + (W - X)/4, H, X, H, X, Y + }; + + gl_write(x + 1, y + h + 3, "Polyline"); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + + draw_poly(coords); + + if ((ropfuncs & ACCELFLAG_POLYLINE) && + (accelfuncs & ACCELFLAG_SETRASTEROP) && + (ropmodes & (1 << ROP_XOR))) { + vga_accel(ACCEL_SETRASTEROP, ROP_XOR); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 255)); + } + + H = y + h - 2 - H; + for (X = 1; X < (sizeof(coords) / sizeof(unsigned short)); X += 2) { + coords[X] += H; + } + draw_poly(coords); + + if ((ropfuncs & ACCELFLAG_POLYLINE) && + (accelfuncs & ACCELFLAG_SETRASTEROP)) { + vga_accel(ACCEL_SETRASTEROP, ROP_COPY); + } + } + break; + case 10: + if (accelfuncs & ACCELFLAG_POLYHLINE) { + gl_write(x + 1, y + h + 3, "PolyHLine"); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + + draw_polyhli(x + 1, y + 1, w - 2, h - 2); + } + break; + case 11: + if ((accelfuncs & ACCELFLAG_POLYLINE) && + (accelfuncs & ACCELFLAG_SETRASTEROP) && + (accelfuncs & ACCELFLAG_SCREENCOPYMONO) && + (accelfuncs & ACCELFLAG_POLYFILLMODE) && + (accelfuncs & ACCELFLAG_DRAWLINE) && + (ropfuncs & ACCELFLAG_DRAWLINE) && + (maxy > (HEIGHT + h)) && + (ropmodes & (1 << ROP_XOR))) { + gl_write(x + 1, y + h + 3, "PolygonFillMode"); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 0, 0)); + vga_accel(ACCEL_FILLBOX, x + 1, HEIGHT, w - 2, h - 2); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 255)); + vga_accel(ACCEL_SETRASTEROP, ROP_XOR); + vga_accel(ACCEL_POLYFILLMODE, 1); + draw_polygon(1, x + 1, HEIGHT, w - 2, h - 2); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_SETRASTEROP, ROP_COPY); + vga_accel(ACCEL_SCREENCOPYMONO, x + 1, HEIGHT, + x + 1, y + 1, w - 2, h - 2); + vga_accel(ACCEL_POLYFILLMODE, 0); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + draw_polygon(0, x + 1, y + 1, w - 2, h - 2); + } + goto endtest; + } + } + + endtest: + vga_getch(); +} + +void drawdisk(int x, int y, int n, int *xmin, int *xmax) { + int i; + int *xmin2, *xmax2; + + xmin2 = alloca(sizeof(int) * n); + xmax2 = alloca(sizeof(int) * n); + for (i = 0; i < n; i++) { + xmin2[i] = xmin[i] + x; + xmax2[i] = xmax[i] + x; + } + vga_accel(ACCEL_DRAWHLINELIST, y, n, xmin2, xmax2); +} + +char *RopNames[] = { "Copy/Replace", "Or", "And", "Xor", "Invert" }; + +void RopTest(void) { + int x, y, i, w, h, wsq, xo, yo, red, x1, x2; + int *xmin, *xmax; + + if (!(ropfuncs & (ACCEL_DRAWHLINELIST | ACCELFLAG_FILLBOX))) { + printf("Rasteroperation test needs HLINELIST or FILLBOX\n"); + return; + } + + vga_accel(ACCEL_SETTRANSPARENCY, ENABLE_TRANSPARENCY_COLOR, gl_rgbcolor(255, 0, 0)); + w = BOXES_WIDTH - 2 * BOXES_B; + h = BOXES_HEIGHT - 2 * BOXES_B; + wsq = min((w * 2)/3, (h * 2)/3); + + xmin = alloca(sizeof(int) * wsq); + xmax = alloca(sizeof(int) * wsq); + + xo = wsq / 2; + yo = xo * xo; + for (i = 0; i < wsq; i++) { + red = sqrt(yo - (i - xo) * (i - xo)); + xmin[i] = xo - red; + xmax[i] = xo + red; + } + + yo = h - wsq - 1; + xo = (w - wsq) / 2; + red = gl_rgbcolor(255, 0, 0); + x1 = xo - (wsq - yo)/2; + if (x1 < 1) + x1 = 1; + x2 = w - wsq - x1; + + gl_write(0, 0, "Testing raster operations:"); + + for(y = BOXES_B + 8, i = 0; y < HEIGHT; y += BOXES_HEIGHT) + for(x = BOXES_B; x < WIDTH; x += BOXES_WIDTH) { + DrawFrame(x, y, x + w - 1, y + h - 1, red); + if (! (ropmodes & (1 << i))) + goto nextrop; + if ((i == ROP_AND) || (i == ROP_XOR)) { + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 255)); + vga_accel(ACCEL_FILLBOX, x + 1, y + 1, w - 2, h - 2); + if (accelfuncs & ACCELFLAG_DRAWHLINELIST) { + vga_accel(ACCEL_SETRASTEROP, i); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 255)); + drawdisk(x + x1, y + 1, wsq, xmin, xmax); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 255)); + drawdisk(x + x2, y + 1, wsq, xmin, xmax); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 0)); + drawdisk(x + xo, y + yo, wsq, xmin, xmax); + } else { + vga_accel(ACCEL_SETRASTEROP, i); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 255)); + vga_accel(ACCEL_FILLBOX, x + x1, y + 1, wsq, wsq); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 255)); + vga_accel(ACCEL_FILLBOX, x + x2, y + 1, wsq, wsq); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 255, 0)); + vga_accel(ACCEL_FILLBOX, x + xo, y + yo, wsq, wsq); + } + } else { + if (accelfuncs & ACCELFLAG_DRAWHLINELIST) { + vga_accel(ACCEL_SETRASTEROP, i); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 0)); + drawdisk(x + x1, y + 1, wsq, xmin, xmax); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + drawdisk(x + x2, y + 1, wsq, xmin, xmax); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 0, 255)); + drawdisk(x + xo, y + yo, wsq, xmin, xmax); + } else { + vga_accel(ACCEL_SETRASTEROP, i); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(255, 0, 0)); + vga_accel(ACCEL_FILLBOX, x + x1, y + 1, wsq, wsq); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 255, 0)); + vga_accel(ACCEL_FILLBOX, x + x2, y + 1, wsq, wsq); + vga_accel(ACCEL_SETFGCOLOR, gl_rgbcolor(0, 0, 255)); + vga_accel(ACCEL_FILLBOX, x + xo, y + yo, wsq, wsq); + } + } + vga_accel(ACCEL_SETRASTEROP, ROP_COPY); + gl_write(x + 1, y + h + 3, RopNames[i]); + nextrop: + i++; + if (i >= (sizeof(RopNames) / sizeof(char *))) + goto endtest; + } + + endtest: + vga_getch(); +} + +void QixDemo(int rop, char *txt) { + int current = 0, dx1, dy1, dx2, dy2, i, cols = 1, cx1, cx2, cy1, cy2; + int startclock, diffclock; + unsigned long pixels = 0; + unsigned int numlines = 0; + struct { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; + int col; + int pix; + } lines[QIXLINES]; + + if ( !(ropmodes & (1 << rop)) || + !(accelfuncs & ACCELFLAG_DRAWLINE)) + return; + if ((rop != ROP_COPY) && + !(accelfuncs & ACCELFLAG_SETRASTEROP)) + return; + DrawDots(); + gl_write(1, 1, txt); + memset(lines, 0, sizeof(lines)); + cx1 = rand() % WIDTH; + cy1 = rand() % HEIGHT; + cx2 = rand() % WIDTH; + cy2 = rand() % HEIGHT; + dx1 = 5 - rand() % 10; + dy1 = 5 - rand() % 10; + dx2 = 5 - rand() % 10; + dy2 = 5 - rand() % 10; + if (rop != ROP_COPY) + vga_accel(ACCEL_SETRASTEROP, rop); + startclock = clock(); + for(i = 0; i < 10000; i++) { + diffclock = clock() - startclock; + if (diffclock > 5 * CLOCKS_PER_SEC) + break; + if (lines[current].col) { + if (rop != ROP_COPY) + vga_accel(ACCEL_SETFGCOLOR, lines[current].col); + else + vga_accel(ACCEL_SETFGCOLOR, 0); + vga_accel(ACCEL_DRAWLINE, lines[current].x1, lines[current].y1, + lines[current].x2, lines[current].y2); + numlines++; + pixels += lines[current].pix; + } + cx1 += dx1; + if ((cx1 < 0) || (cx1 >= WIDTH)) { + dx1 = -dx1; + cx1 += dx1 << 1; + } + cx2 += dx2; + if ((cx2 < 0) || (cx2 >= WIDTH)) { + dx2 = -dx2; + cx2 += dx2 << 1; + } + cy1 += dy1; + if ((cy1 < 0) || (cy1 >= HEIGHT)) { + dy1 = -dy1; + cy1 += dy1 << 1; + } + cy2 += dy2; + if ((cy2 < 0) || (cy2 >= HEIGHT)) { + dy2 = -dy2; + cy2 += dy2 << 1; + } + lines[current].x1 = cx1; + lines[current].x2 = cx2; + lines[current].y1 = cy1; + lines[current].y2 = cy2; + lines[current].col = cols; + vga_accel(ACCEL_SETFGCOLOR, cols++); + if (cols >= COLORS) + cols = 1; + vga_accel(ACCEL_DRAWLINE, lines[current].x1, lines[current].y1, + lines[current].x2, lines[current].y2); + numlines++; + pixels += lines[current].pix = max(abs(lines[current].x1 - lines[current].x2), + abs(lines[current].y1 - lines[current].y2)); + current++; + if (current >= QIXLINES) + current = 0; + } + if (rop != ROP_COPY) + vga_accel(ACCEL_SETRASTEROP, ROP_COPY); + cy1 = ((long long) numlines * CLOCKS_PER_SEC) / diffclock; + cx1 = ((long long) pixels * CLOCKS_PER_SEC) / diffclock; + cx2 = cx1 * BYTESPERPIXEL; + printf("%s: %ld.%ld Klines/s (%ld.%ld Mpixels/s or %ld.%ld Mbytes/s)\n", txt, + cy1 / 1000L, (cy1 % 1000L) / 100L, + cx1 / 1000000L, (cx1 % 1000000L) / 100000L, + cx2 / 1000000L, (cx2 % 1000000L) / 100000L); +} diff --git a/demos/addmodetest.c b/demos/addmodetest.c new file mode 100644 index 0000000..ead0dcd --- /dev/null +++ b/demos/addmodetest.c @@ -0,0 +1,238 @@ +/* From VGAlib, changed for svgalib */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + + +#include +#include /* for usleep( long ) */ +#include +#include +#include "vga.h" + +static unsigned char line[2048 * 3]; + +static void testmode(int mode) +{ + int xmax, ymax, i, x, y, yw, ys, c; + vga_modeinfo *modeinfo; + + vga_setmode(mode); + + modeinfo = vga_getmodeinfo(mode); + + printf("Width: %d Height: %d Colors: %d\n", + modeinfo->width, + modeinfo->height, + modeinfo->colors); + printf("DisplayStartRange: %xh Maxpixels: %d Blit: %s\n", + modeinfo->startaddressrange, + modeinfo->maxpixels, + modeinfo->haveblit ? "YES" : "NO"); + printf("Offset: %i Bytes Per Pixel: %d\n", + modeinfo->linewidth, + modeinfo->bytesperpixel); + +#ifdef TEST_MODEX + if (modeinfo->colors == 256) + printf("Switching to ModeX ... %s\n", + (vga_setmodeX()? "done" : "failed")); +#endif + + vga_screenoff(); + + xmax = vga_getxdim() - 1; + ymax = vga_getydim() - 1; + + vga_setcolor(vga_white()); + vga_drawline(0, 0, xmax, 0); + vga_drawline(xmax, 0, xmax, ymax); + vga_drawline(xmax, ymax, 0, ymax); + vga_drawline(0, ymax, 0, 0); + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(10 + i * 5, 10, 90 + i * 5, 90); + } + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(90 + i * 5, 10, 10 + i * 5, 90); + } + + vga_screenon(); + + ys = 100; + yw = (ymax - 100) / 4; + switch (vga_getcolors()) { + case 256: + for (i = 0; i < 60; ++i) { + c = (i * 64) / 60; + vga_setpalette(i + 16, c, c, c); + vga_setpalette(i + 16 + 60, c, 0, 0); + vga_setpalette(i + 16 + (2 * 60), 0, c, 0); + vga_setpalette(i + 16 + (3 * 60), 0, 0, c); + } + line[0] = line[xmax] = 15; + line[1] = line[xmax - 1] = 0; + for (x = 2; x < xmax - 1; ++x) + line[x] = (((x - 2) * 60) / (xmax - 3)) + 16; + for (y = ys; y < ys + yw; ++y) + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) + vga_drawscanline(y, line); + break; + + case 1 << 15: + case 1 << 16: + case 1 << 24: + for (x = 2; x < xmax - 1; ++x) { + c = ((x - 2) * 256) / (xmax - 3); + y = ys; + vga_setrgbcolor(c, c, c); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(c, 0, 0); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(0, c, 0); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(0, 0, c); + vga_drawline(x, y, x, y + yw - 1); + } + for (x = 0; x < 64; x++) { + for (y = 0; y < 64; y++) { + vga_setrgbcolor(x * 4 + 3, y * 4 + 3, 0); + vga_drawpixel(xmax / 2 - 160 + x, y + ymax / 2 - 80); + vga_setrgbcolor(x * 4 + 3, 0, y * 4 + 3); + vga_drawpixel(xmax / 2 - 32 + x, y + ymax / 2 - 80); + vga_setrgbcolor(0, x * 4 + 3, y * 4 + 3); + vga_drawpixel(xmax / 2 + 160 - 64 + x, y + ymax / 2 - 80); + + vga_setrgbcolor(x * 4 + 3, y * 4 + 3, 255); + vga_drawpixel(xmax / 2 - 160 + x, y + ymax / 2 + 16); + vga_setrgbcolor(x * 4 + 3, 255, y * 4 + 3); + vga_drawpixel(xmax / 2 - 32 + x, y + ymax / 2 + 16); + vga_setrgbcolor(255, x * 4 + 3, y * 4 + 3); + vga_drawpixel(xmax / 2 + 160 - 64 + x, y + ymax / 2 + 16); + } + } + break; + default: + if (vga_getcolors() == 16) { + for (i = 0; i < xmax - 1; i++) + line[i] = (i + 2) % 16; + line[0] = line[xmax] = 15; + line[1] = line[xmax - 1] = 0; + } + if (vga_getcolors() == 2) { + for (i = 0; i <= xmax; i++) + line[i] = 0x11; + line[0] = 0x91; + } + for (i = 100; i < ymax - 1; i++) + vga_drawscanline(i, line); + break; + + } + if (getchar() == 'd') + vga_dumpregs(); + + vga_setmode(TEXT); +} + +int main(int argc, char *argv[]) +{ + int mode; + int tests=0xffffffff; + + if(argc>1)tests=strtol(argv[1],NULL,0); + + vga_init(); /* Initialize. */ + + + if(tests&1){ + vga_addtiming(45000,720,776,880,936,540,570,576,600,0); + vga_addtiming(36000,720,756,872,950,540,542,547,565,0); + mode=vga_addmode(720,540,1<<24,720*4,4); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + + if(tests&2){ + vga_addtiming(45000,720,776,880,936,720,750,756,800,0); + vga_addtiming(36000,720,756,872,950,720,723,729,750,0); + mode=vga_addmode(720,720,1<<24,720*4,4); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + + if(tests&4){ + vga_guesstiming(576,432,0,0); + mode=vga_addmode(576,432,1<<16,576*2,2); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + + if(tests&8){ + vga_guesstiming(576,431,1,0); + mode=vga_addmode(576,431,1<<16,576*2,2); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + + if(tests&16){ + vga_guesstiming(360,271,1,0); + mode=vga_addmode(360,271,1<<16,360*2,2); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + + if(tests&32){ + vga_guesstiming(360,270,1,0); + mode=vga_addmode(360,270,1<<16,360*2,2); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + + if(tests&64){ + vga_guesstiming(672,800,257,0); + mode=vga_addmode(672,800,1<<16,672*2,2); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + if(tests&128){ + vga_guesstiming(712,800,257,0); + mode=vga_addmode(712,800,1<<16,712*2,2); + printf("Mode=%i\n",mode); + if (vga_hasmode(mode)) + testmode(mode); + else printf("Error: Video mode not supported by driver\n"); + }; + + return 0; +} diff --git a/demos/arrow.h b/demos/arrow.h new file mode 100644 index 0000000..3bb096d --- /dev/null +++ b/demos/arrow.h @@ -0,0 +1,17 @@ +unsigned int arrow[64] = { +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00200000, 0x00700000, +0x00380000, 0x00180000, 0x001c0000, 0x000e0000, +0x00070000, 0x00038000, 0x00018000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xc0000000, 0xb0000000, 0x4c000000, 0x43000000, +0x20c00000, 0x20300000, 0x10080000, 0x10100000, +0x08300000, 0x08600000, 0x04e00000, 0x05f00000, +0x03380000, 0x00180000, 0x001c0000, 0x000e0000, +0x00070000, 0x00038000, 0x00018000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000}; diff --git a/demos/bankspeed.c b/demos/bankspeed.c new file mode 100644 index 0000000..89e9fe8 --- /dev/null +++ b/demos/bankspeed.c @@ -0,0 +1,169 @@ + +#include +#include +#include +#include +#include +#include + +/* The logo was drawn by John Remyn. */ +/* Feel free to provide a more beautiful/official/thought provoking/cool */ +/* logo to replace it. */ +#define LOGOWIDTH 201 +#define LOGOHEIGHT 85 + +int VGAMODE; +int VIRTUAL; + +GraphicsContext *backscreen; +GraphicsContext *physicalscreen; +void *logobitmap; + + +void loadbitmap(char *filename, void *buf) +{ + FILE *f; + f = fopen(filename, "rb"); + if(f==NULL)return; + fread(buf, 1, 17095, f); + fclose(f); +} + + +void test(void) +{ + int i, j; + + if (VIRTUAL) + gl_setcontext(backscreen); + + gl_clearscreen(0); + for (i = 0; i < 5; i++) { + gl_clearscreen(0); + for (j = 0; j < 100000; j++) + gl_setpixel(random() % WIDTH, random() % HEIGHT, + random() % COLORS); + } + + if (VIRTUAL) + gl_copyscreen(physicalscreen); + +} + + +void setcustompalette(void) +{ + /* colors 0-31 are an RGB mix (bits 0 and 1 red, 2 green, 3 and 4 blue) */ + /* 32-63 black to red */ + /* 64-95 black to green */ + /* 96-127 black to yellow */ + /* 128-159 black to blue */ + /* 160-191 black to magenta */ + /* 192-223 black to cyan */ + /* 224-255 black to white */ + Palette pal; + int i; + for (i = 0; i < 256; i++) { + int r, g, b; + r = g = b = 0; + if ((i & 32) > 0) + r = (i & 31) << 1; + if ((i & 64) > 0) + g = (i & 31) << 1; + if ((i & 128) > 0) + b = (i & 31) << 1; + if (i < 32) { + r = (i & 3) << 4; /* 2 bits */ + g = (i & 4) << 3; /* 1 bit */ + b = (i & 24) << 1; /* 2 bits */ + } + pal.color[i].red = r; + pal.color[i].green = g; + pal.color[i].blue = b; + } + gl_setpalette(&pal); +} + + +void logotest(void) +{ + int h; + void *scaled; + /* Set logo palette. */ + setcustompalette(); + /* Create logo bitmap */ + logobitmap = alloca(LOGOWIDTH * LOGOHEIGHT); + loadbitmap("linuxlogo.bitmap", logobitmap); + /* Allocate buffer for scaled bitmap. */ + scaled = alloca(WIDTH * HEIGHT); + gl_clearscreen(0); + /* Stretch vertically. */ + for (h = 0; h <= LOGOHEIGHT; h++) { + gl_scalebox(LOGOWIDTH, LOGOHEIGHT, logobitmap, + LOGOWIDTH, h, scaled); + gl_putbox(0, 0, LOGOWIDTH, h, scaled); + if (VIRTUAL) + gl_copyscreen(physicalscreen); + } + gl_clearscreen(0); + /* Scale to screen resolution. */ + gl_scalebox(LOGOWIDTH, LOGOHEIGHT, logobitmap, WIDTH, HEIGHT, scaled); + gl_putbox(0, 0, WIDTH, HEIGHT, scaled); + gl_copyscreen(physicalscreen); +} + + +int main(void) +{ + clock_t t1, t2; + + vga_init(); + t1=clock(); + VGAMODE = vga_getdefaultmode(); + if (VGAMODE == -1) + VGAMODE = G320x200x256; /* Default mode. */ + + if (!vga_hasmode(VGAMODE)) { + printf("Mode not available.\n"); + exit(-1); + } + VIRTUAL = 0; /* No virtual screen. */ + if (vga_getmodeinfo(VGAMODE)->colors == 16 || + (vga_getmodeinfo(VGAMODE)->flags & IS_MODEX)) + /* These modes are supported indirectly by vgagl. */ + VIRTUAL = 1; + + if (VIRTUAL) { + /* Create virtual screen. */ + gl_setcontextvgavirtual(VGAMODE); + backscreen = gl_allocatecontext(); + gl_getcontext(backscreen); + } + vga_setmode(VGAMODE); + gl_setcontextvga(VGAMODE); /* Physical screen context. */ + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + if (COLORS == 256) + gl_setrgbpalette(); + + test(); + + /* Now do the same with clipping enabled. */ + gl_clearscreen(0); + gl_setclippingwindow(WIDTH / 4, HEIGHT / 4, WIDTH - WIDTH / 4 - 1, + HEIGHT - HEIGHT / 4 - 1); + + test(); + + gl_disableclipping(); + if (COLORS == 256) + /* Show the logo if using 256 color mode. */ + logotest(); + + if (VIRTUAL) + gl_freecontext(backscreen); + t2=clock(); + printf("total:%1.2f sec\n",(1.0*t2-t1)/CLOCKS_PER_SEC); + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/bg_test.c b/demos/bg_test.c new file mode 100644 index 0000000..f786c1e --- /dev/null +++ b/demos/bg_test.c @@ -0,0 +1,129 @@ +/* bg_test.c + + + Copyright (c) 1997 Michael Friman. All rights reserved. + + +*/ + +#include +#include +#include +#include +#include +#include + +/* + If you really want to see background runin, add after + vga_setmode vga_runinbackground(1) in fun. + Remember to compile the svgalib with background. +*/ + +int go = 0; +int linear = 0; + +void drawline(int x1, int y1, int x2, int y2) + +{ + if (linear) + { + gl_line(x1,y1,x2,y2,vga_white()); + } + else + { + vga_drawline(x1,y1,x2,y2); + } +} + +void set_go(void) + +{ + go=1; + return; +} + +int main(int argc, char *argv[]) + +{ + int x[2]; + int y[2]; + int counter; + int mode; + + if ((argc > 2) || ((argc == 2) && (strcmp(argv[1], "linear") != 0))) + { + fputs("Usage: bg_test [linear]\n", stderr); + exit(2); + } + vga_init(); + printf("This is small test for background runin.\n"); + if (vga_runinbackground_version()==1 || vga_runinbackground_version()>=3) + { + printf("Background runin enabled. mode %d\n", vga_runinbackground_version()); + } + else + { + printf("Svgalib is not background capable.\n"); + printf("Test ended.\n"); + return(0); + } + printf("Switch to another console when the box appears.\n"); + printf("Press enter to continue or CTRL-c to stop.\n"); + getchar(); + + mode = vga_getdefaultmode(); + if (mode < 0) + mode = G320x200x256; + if (argc == 2) + { + if (vga_getmodeinfo(mode)->flags & CAPABLE_LINEAR) + { + vga_setlinearaddressing(); + fputs("Linear mode set.\n", stderr); + linear = 1; + } + else + { + fputs("Linear mode unavailable.\n", stderr); + } + } + vga_setmode(mode); + if (linear) + gl_setcontextvga(mode); + vga_runinbackground(VGA_GOTOBACK,set_go); + vga_runinbackground(1); + x[0]=0; + y[0]=0; + x[1]=vga_getxdim()-1; + y[1]=vga_getydim()-1; + + if (!linear) + vga_setcolor(vga_white()); + counter=(y[1]/11)*5+1; + while(counter<=(y[1]/11)*6) + { + drawline((x[1]/11)*5,counter,(x[1]/11)*6,counter); + counter++; + } + + /* Program won't go further without console switching. */ + + while(!go) usleep(1000); + + drawline(x[0],y[0],x[1],y[0]); + drawline(x[1],y[0],x[1],y[1]); + drawline(x[1],y[1],x[0],y[1]); + drawline(x[0],y[1],x[0],y[0]); + + drawline(x[0],y[0],x[1],y[1]); + drawline(x[1],y[0],x[0],y[1]); + + + while(!vga_getkey()); + + vga_setmode(TEXT); + + printf("Ok.\n"); + return(0); +} + diff --git a/demos/clut.xbm b/demos/clut.xbm new file mode 100644 index 0000000..b2a9b26 --- /dev/null +++ b/demos/clut.xbm @@ -0,0 +1,50 @@ +#define clut_width 18 +#define clut_height 233 +static char clut_bits[] = { + 0xe0,0x07,0x00,0xf8,0x0f,0x00,0xfc,0x1f,0x00,0x3e,0x1c,0x00,0x1e,0x30,0x00, + 0x07,0x20,0x00,0x03,0x20,0x00,0x01,0x20,0x00,0x01,0x20,0x00,0x01,0x30,0x00, + 0x03,0x10,0x00,0x1e,0x0c,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00, + 0x80,0x1f,0x00,0xc0,0x3f,0x00,0xc0,0x20,0x00,0x20,0x20,0x00,0x20,0x20,0x00, + 0x20,0x18,0x00,0xe0,0x1f,0x00,0xc0,0x0f,0x00,0x80,0x07,0x00,0x00,0x00,0x00, + 0x00,0x3e,0x00,0xf1,0x3f,0x00,0xff,0x3f,0x00,0xff,0x21,0x00,0x0f,0x10,0x00, + 0x00,0x00,0x00,0x00,0x0f,0x00,0x80,0x1f,0x00,0xc0,0x3f,0x00,0xc0,0x20,0x00, + 0x20,0x20,0x00,0x20,0x20,0x00,0x20,0x18,0x00,0xe0,0x1f,0x00,0xc0,0x0f,0x00, + 0x80,0x07,0x00,0x00,0x00,0x00,0x20,0x3c,0x00,0xe0,0x3f,0x00,0xe0,0x3f,0x00, + 0xe0,0x03,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0xe0,0x00,0x00,0xe0,0x00,0x00, + 0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x3e,0x00,0xf1,0x3f,0x00,0xff,0x3f,0x00,0xff,0x21,0x00,0x0f,0x10,0x00, + 0x00,0x00,0x00,0x00,0x0f,0x00,0x80,0x1f,0x00,0xc0,0x3f,0x00,0xc0,0x20,0x00, + 0x20,0x20,0x00,0x20,0x20,0x00,0x20,0x18,0x00,0xe0,0x1f,0x00,0xc0,0x0f,0x00, + 0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x80,0x1f,0x00,0xc0,0x3f,0x00, + 0xc0,0x20,0x00,0x20,0x20,0x00,0x20,0x20,0x00,0x20,0x18,0x00,0xe0,0x1f,0x00, + 0xc0,0x0f,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0xf1,0x3f,0x00, + 0xff,0x3f,0x00,0xff,0x03,0x00,0x8f,0x00,0x00,0x40,0x0e,0x00,0x60,0x3e,0x00, + 0xe0,0x3d,0x00,0xe0,0x31,0x00,0xc0,0x10,0x00,0x00,0x08,0x00,0x20,0x1e,0x00, + 0xe0,0x3f,0x00,0xe0,0x3f,0x00,0xe0,0x31,0x00,0x00,0x10,0x00,0x00,0x08,0x00, + 0x00,0x3e,0x00,0xe0,0x3f,0x00,0xe0,0x3f,0x00,0xe0,0x21,0x00,0x00,0x10,0x00, + 0x00,0x00,0x02,0x00,0xc0,0x03,0x20,0xfe,0x03,0xe0,0xff,0x03,0xe0,0x3f,0x02, + 0xe0,0x21,0x00,0x40,0x20,0x00,0x20,0x20,0x00,0x20,0x18,0x00,0xe0,0x1f,0x00, + 0xc0,0x0f,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x3e,0x00,0xe0,0x3f,0x00, + 0xfc,0x3f,0x00,0xfc,0x21,0x00,0x3c,0x10,0x00,0x20,0x00,0x00,0x20,0x00,0x00, + 0x00,0x0f,0x00,0x80,0x1f,0x00,0xc0,0x3f,0x00,0xc0,0x20,0x00,0x20,0x20,0x00, + 0x20,0x10,0x00,0x40,0x1c,0x00,0xe0,0x3f,0x00,0xe0,0x3f,0x00,0xe0,0x23,0x00, + 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0xf1,0x1f,0x00,0xff,0x3f,0x00, + 0xff,0x21,0x00,0x4f,0x20,0x00,0x20,0x20,0x00,0x20,0x18,0x00,0xe0,0x1f,0x00, + 0xc0,0x0f,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0xf1,0x3f,0x00, + 0xff,0x3f,0x00,0xff,0x21,0x00,0x0f,0x10,0x00,0x00,0x00,0x00,0x00,0x0f,0x00, + 0x80,0x1f,0x00,0xc0,0x3f,0x00,0xc0,0x24,0x00,0x20,0x24,0x00,0x20,0x22,0x00, + 0x20,0x13,0x00,0xe0,0x13,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0e,0x00,0xe0,0x1f,0x00, + 0xe0,0x3f,0x00,0xe0,0x31,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x00,0x0e,0x00, + 0xe0,0x1f,0x00,0xe0,0x3f,0x00,0xe0,0x31,0x00,0x00,0x30,0x00,0x00,0x10,0x00, + 0x60,0x18,0x00,0xe0,0x0c,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x20,0x3e,0x00, + 0xe0,0x3f,0x00,0xe6,0x3f,0x00,0xe6,0x21,0x00,0x06,0x10,0x00,0x00,0x00,0x00, + 0x00,0x0f,0x00,0x80,0x1f,0x00,0xc0,0x3f,0x00,0xc0,0x20,0x00,0x20,0x20,0x00, + 0x20,0x20,0x00,0x20,0x10,0x00,0x40,0x1e,0x00,0xf1,0x3f,0x00,0xff,0x3f,0x00, + 0xff,0x21,0x00,0x0f,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x3e,0x00, + 0xe0,0x3f,0x00,0xfc,0x3f,0x00,0xfc,0x21,0x00,0x3c,0x10,0x00,0x20,0x00,0x00, + 0x20,0x00,0x00,0x00,0x3e,0x00,0xf1,0x3f,0x00,0xff,0x3f,0x00,0xff,0x01,0x00, + 0x8f,0x00,0x00,0x40,0x00,0x00,0x60,0x3c,0x00,0xe0,0x3f,0x00,0xe0,0x3f,0x00, + 0xc0,0x23,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc0,0x3c,0x00, + 0xe0,0x3d,0x00,0xe0,0x19,0x00,0xc0,0x00,0x00}; diff --git a/demos/cursor.c b/demos/cursor.c new file mode 100644 index 0000000..f7d9db1 --- /dev/null +++ b/demos/cursor.c @@ -0,0 +1,231 @@ +#include +#include +#include +#include +#include +#include +#include + +int mode = G1024x768x64K; + +uint32_t mag_glass_bits[] = { + 0x3f8, 0x60c, 0x9e2, 0x1a13, 0x1401, 0x1401, 0x1001, 0x1001, + 0x1001, 0x1003, 0x1802, 0x340c, 0x6ff8, 0xd800, 0xb000, 0xe000, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x3f8, 0x60c, 0x9e2, 0x1a13, 0x1401, 0x1401, 0x1001, 0x1001, + 0x1001, 0x1003, 0x1802, 0x340c, 0x6ff8, 0xd800, 0xb000, 0xe000, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +uint32_t mag_glass_filled[] = { + 0x3f8, 0x60c, 0x9e2, 0x1a13, 0x1401, 0x1401, 0x1001, 0x1001, + 0x1001, 0x1003, 0x1802, 0x340c, 0x6ff8, 0xd800, 0xb000, 0xe000, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x3f8, 0x7fc, 0xffe, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, + 0x1fff, 0x1fff, 0x1ffe, 0x3ffc, 0x7ff8, 0xf800, 0xe000, 0xe000, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +uint32_t *c2; +static unsigned char line[2048*4]; +static void drawpattern(void) +{ + int xmax, ymax, i, x, y, yw, ys, c; + vga_modeinfo *modeinfo; + + modeinfo = vga_getmodeinfo(mode); + + xmax = vga_getxdim() - 1; + ymax = vga_getydim() - 1; + + vga_setcolor(vga_white()); + vga_drawline(0, 0, xmax, 0); + vga_drawline(xmax, 0, xmax, ymax); + vga_drawline(xmax, ymax, 0, ymax); + vga_drawline(0, ymax, 0, 0); + + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(10 + i * 5, 10, 90 + i * 5, 90); + } + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(90 + i * 5, 10, 10 + i * 5, 90); + } + + vga_screenon(); + + ys = 100; + yw = (ymax - 100) / 4; + switch (vga_getcolors()) { + case 256: + for (i = 0; i < 60; ++i) { + c = (i * 64) / 60; + vga_setpalette(i + 16, c, c, c); + vga_setpalette(i + 16 + 60, c, 0, 0); + vga_setpalette(i + 16 + (2 * 60), 0, c, 0); + vga_setpalette(i + 16 + (3 * 60), 0, 0, c); + } + line[0] = line[xmax] = 15; + line[1] = line[xmax - 1] = 0; + for (x = 2; x < xmax - 1; ++x) + line[x] = (((x - 2) * 60) / (xmax - 3)) + 16; + for (y = ys; y < ys + yw; ++y) /* gray */ + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) /* red */ + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) /* green */ + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) /* blue */ + vga_drawscanline(y, line); + break; + + case 1 << 15: + case 1 << 16: + case 1 << 24: + for (x = 2; x < xmax - 1; ++x) { + c = ((x - 2) * 256) / (xmax - 3); + y = ys; + vga_setrgbcolor(c, c, c); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(c, 0, 0); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(0, c, 0); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(0, 0, c); + vga_drawline(x, y, x, y + yw - 1); + } + for (x = 0; x < 64; x++) { + for (y = 0; y < 64; y++) { + vga_setrgbcolor(x * 4 + 3, y * 4 + 3, 0); + vga_drawpixel(xmax / 2 - 160 + x, y + ymax / 2 - 80); + vga_setrgbcolor(x * 4 + 3, 0, y * 4 + 3); + vga_drawpixel(xmax / 2 - 32 + x, y + ymax / 2 - 80); + vga_setrgbcolor(0, x * 4 + 3, y * 4 + 3); + vga_drawpixel(xmax / 2 + 160 - 64 + x, y + ymax / 2 - 80); + + vga_setrgbcolor(x * 4 + 3, y * 4 + 3, 255); + vga_drawpixel(xmax / 2 - 160 + x, y + ymax / 2 + 16); + vga_setrgbcolor(x * 4 + 3, 255, y * 4 + 3); + vga_drawpixel(xmax / 2 - 32 + x, y + ymax / 2 + 16); + vga_setrgbcolor(255, x * 4 + 3, y * 4 + 3); + vga_drawpixel(xmax / 2 + 160 - 64 + x, y + ymax / 2 + 16); + } + } + break; + default: + if (vga_getcolors() == 16) { + for (i = 0; i < xmax - 1; i++) + line[i] = (i + 2) % 16; + line[0] = line[xmax] = 15; + line[1] = line[xmax - 1] = 0; + } + if (vga_getcolors() == 2) { + for (i = 0; i <= xmax; i++) + line[i] = 0x11; + line[0] = 0x91; + } + for (i = 100; i < ymax - 1; i++) + vga_drawscanline(i, line); + break; + + } +} + +int main(int argc, char *argv[]) { + int i,s,j; + unsigned char *g; + + vga_init(); + vga_setmousesupport(1); + printf("%i\n",vga_initcursor(argc-1)); + + vga_setmode(mode); + vga_setlinearaddressing(); + vga_setcursorposition(100,100); + + c2=malloc(256); + j=1; + for(i=0;i<32;i++) { + *(c2+i)=j; + *(c2+32+i)=j; + j<<=1; + } + + if(vga_getcolors()==256) + for (i = 0; i < 60; ++i) { + j = (i * 64) / 60; + vga_setpalette(i + 16, j, j, j); + vga_setpalette(i + 16 + 60, j, 0, 0); + vga_setpalette(i + 16 + (2 * 60), 0, j, 0); + vga_setpalette(i + 16 + (3 * 60), 0, 0, j); + } + vga_setcursorimage(0,0,0,0xff0000,(unsigned char *)c2); + vga_setcursorimage(1,0,0,0xffffff,(unsigned char *)mag_glass_bits); + vga_setcursorimage(2,0,0xff1080,0x0f0fff,(unsigned char *)mag_glass_filled); + vga_selectcursor(1); + vga_showcursor(1); + vga_showcursor(2); + g=vga_getgraphmem(); + +#if 1 + drawpattern(); +#else + for(j=0;j<256*1024;j++) { + if((j&0x3ff)==0x3ff)usleep(1000); + *(g+2*j)=0x00; + *(g+2*j+1)=(j*83/69)&0xff; + } + + for(j=256*1024;j<384*1024;j++) { + if((j&0x3ff)==0x3ff)usleep(1000); + *(g+2*j)=0; + *(g+2*j+1)=0; + } + for(j=384*1024;j<512*1024;j++) { +// if((j&0x3ff)==0x3ff)usleep(1000); + *(g+2*j)=0xff; + *(g+2*j+1)=0x7f; + } + for(j=512*1024;j<2048*1024;j++) { +// if((j&0x3ff)==0x3ff)usleep(1000); + *(g+2*j)=((j>>9)&1)*(((~j)>>4)&0x1f); + *(g+2*j+1)=(1-((j>>9)&1)) * ((j>>2)&0x7c); + } +#endif + + i=1; + + vga_showcursor(3); + s=3; + while(!(mouse_getbutton()&4)) { + mouse_waitforupdate(); + vga_setcursorposition(mouse_getx(),mouse_gety()); + if(mouse_getbutton()&1) { + vga_selectcursor(i=(i+1)%3); + } +#if 1 + if(mouse_getbutton()&2) { + vga_showcursor(s=(s+1)%4); + } +#else + if(mouse_getbutton()&2) { + vga_dumpregs(); + } +#endif + } + vga_setmode(TEXT); + return 0; +} diff --git a/demos/eightbpp.xbm b/demos/eightbpp.xbm new file mode 100644 index 0000000..2252f7d --- /dev/null +++ b/demos/eightbpp.xbm @@ -0,0 +1,17 @@ +#define eightbpp_width 23 +#define eightbpp_height 66 +static char eightbpp_bits[] = { + 0x00,0xf0,0x01,0x00,0xfc,0x01,0x78,0xfc,0x03,0xfe,0x07,0x03,0xfe,0x03,0x02, + 0xe3,0x03,0x02,0xc1,0x07,0x02,0x81,0x0f,0x03,0x81,0xff,0x03,0xc3,0xff,0x01, + 0x7f,0xfe,0x01,0x7e,0x78,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0xff,0x01,0xf1,0xff,0x01,0xff,0xff,0x03, + 0xff,0x03,0x03,0xff,0x00,0x02,0x8f,0x00,0x02,0x40,0x00,0x03,0xc0,0xc0,0x03, + 0xc0,0xff,0x01,0x80,0xff,0x01,0x80,0xff,0x00,0x00,0x3e,0x40,0x00,0x00,0x40, + 0x00,0x00,0x78,0x40,0x80,0x7f,0x40,0xf8,0x7f,0xc0,0xff,0x7f,0xc0,0xff,0x47, + 0xc0,0xff,0x41,0xc0,0x07,0x03,0x80,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x03, + 0xc0,0xc0,0x03,0xc0,0xff,0x01,0x80,0xff,0x01,0x80,0xff,0x00,0x00,0x3e,0x40, + 0x00,0x00,0x40,0x00,0x00,0x78,0x40,0x80,0x7f,0x40,0xf8,0x7f,0xc0,0xff,0x7f, + 0xc0,0xff,0x47,0xc0,0xff,0x41,0xc0,0x07,0x03,0x80,0x00,0x02,0x40,0x00,0x02, + 0x40,0x00,0x03,0xc0,0xc0,0x03,0xc0,0xff,0x01,0x80,0xff,0x01,0x80,0xff,0x00, + 0x00,0x3e,0x00}; diff --git a/demos/eventtest.c b/demos/eventtest.c new file mode 100644 index 0000000..68d3c52 --- /dev/null +++ b/demos/eventtest.c @@ -0,0 +1,258 @@ +/* Program to test the vga_waitevent function. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USE_RAWKEYBOARD + +static int newcolor(void) +{ + if (BYTESPERPIXEL == 1) + return random() % 15 + 1; + return gl_rgbcolor(random() & 255, random() & 255, random() & 255); +} + +static void ping(void) +{ + putchar('\a'); + fflush(stdout); +} + +/* read data from fd. Write string if '\n' encountered */ +void process_input(int fd) +{ + static char textbuf[80], *data = textbuf; + char inbuf[80]; + int len, i; + + len = read(fd, inbuf, 80); + if (len <= 0) + return; + for (i = 0; i < len; i++) { + if (inbuf[i] == '\n') { + *data = 0; + gl_write(0, 10, textbuf); + ping(); + data = textbuf; + } else { + *data++ = inbuf[i]; + } + } +} + +void child(int fd) +{ + time_t last_time = 0, now; + FILE *output; + + output = fdopen(fd, "w"); + for (;;) { /* when parent dies we get killed by SIGPIPE */ + now = time(NULL); + if (now / 5 > last_time) { /* a new minute started */ + last_time = now / 5; + fputs(ctime(&now), output); + fputc('\n', output); + fflush(output); + } + sleep(1); + } +} + +int main(void) +{ + struct timeval timeout; + fd_set inputs; + char bitmap[16 * 16 * 4]; /* big enough for 10x10 bitmap in any mode */ + int vgamode, color, pipefd[2], x, y, button, event, cursorsize = 5; + char loop = 1, drawcursor = 1; +#ifdef USE_RAWKEYBOARD + char space_pressed = 0; +#endif + + puts("This is a demo showing the abilities of the new vga_waitevent() function\n" + "If something goes wrong it might hang your machine. Thus hit -C now\n" + "to bailout if in doubt.\n" + "Use mouse to move cursor. 1-9,0 to set the cursor size. Space to change the\n" + "cursor color. Left button to draw. Right button or 'Q' to bailout.\n" + "The cursor goes on/off every half second by usage of a timeout passed to\n" + "vga_waitevent. Every 5 secs a string from a child process (the time) arrives\n" + "asynchronously and is displayed by the frontend."); +#ifdef USE_RAWKEYBOARD + puts("\nBEWARE! This has been compiled to use the raw keyboard. A crash might\n" + "render the console unusable. (but shouldn't)."); +#endif + fputs("\nHit if brave enough, else ^C to bailout: ", stdout); + fflush(stdout); + getchar(); + fflush(stdin); /* clear I/O buffer */ + + pipe(pipefd); + if (fork() == 0) { /* fork off b4 touching graphix to avoid side effects */ + close(pipefd[0]); /* Important: close reading side, else it remains */ + /* opened by child when parent exits and we don't get */ + /* a SIGPIPE! */ + child(pipefd[1]); + } + vga_init(); + vgamode = vga_getdefaultmode(); + if (vgamode == -1) + vgamode = G320x200x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(-1); + } + /* Enable automatic mouse setup at mode set. */ + vga_setmousesupport(1); + vga_setmode(vgamode); + /* Disable wrapping (default). */ + /* mouse_setwrap(MOUSE_NOWRAP); */ + gl_setcontextvga(vgamode); + gl_enableclipping(); + + /* There might be some scrap data in the serial buffer + from the mouse. It will make vga_waitevent block + because it thinks the mouse wants to send data but + then no mouse packet arrives. */ + color = newcolor(); + x = 0; + y = 0; + gl_setwritemode(WRITEMODE_OVERWRITE | FONT_COMPRESSED); + gl_setfont(8, 8, gl_font8x8); + gl_setfontcolors(0, newcolor()); + +#ifdef USE_RAWKEYBOARD + if (keyboard_init()) { + printf("Could not initialize keyboard.\n"); + exit(1); + } +#endif + + while (loop) { + gl_getbox(x, y, 10, 10, bitmap); + if (drawcursor) { + gl_hline(x, y, x + cursorsize, color); + gl_hline(x, y + cursorsize, x + cursorsize, color); + gl_line(x, y, x, y + cursorsize, color); + gl_line(x + cursorsize, y, x + cursorsize, y + cursorsize, color); + } + FD_ZERO(&inputs); + FD_SET(pipefd[0], &inputs); + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* 0.5 second time out */ + event = vga_waitevent(VGA_MOUSEEVENT | VGA_KEYEVENT, + &inputs, NULL, NULL, &timeout); + gl_putbox(x, y, 10, 10, bitmap); + if (timeout.tv_sec || timeout.tv_usec) { + /* No timeout. An actual event occured. Reset to visible + cursor. Note: + This is actually a bug as the cursor will get visible on time + updates. However, it's better this way for demo/test + purposes. */ + drawcursor = 1; + } else { + drawcursor ^= 1; + } + if (FD_ISSET(pipefd[0], &inputs)) + process_input(pipefd[0]); + if (event & VGA_MOUSEEVENT) { + x = mouse_getx(); + y = mouse_gety(); + button = mouse_getbutton(); + if (button & MOUSE_LEFTBUTTON) + gl_fillbox(x, y, cursorsize + 1, cursorsize + 1, color); + if (button & MOUSE_RIGHTBUTTON) + loop = 0; + } + if (event & VGA_KEYEVENT) { +#ifdef USE_RAWKEYBOARD + if (keyboard_keypressed(SCANCODE_1)) + cursorsize = 0; + if (keyboard_keypressed(SCANCODE_2)) + cursorsize = 1; + if (keyboard_keypressed(SCANCODE_3)) + cursorsize = 2; + if (keyboard_keypressed(SCANCODE_4)) + cursorsize = 3; + if (keyboard_keypressed(SCANCODE_5)) + cursorsize = 4; + if (keyboard_keypressed(SCANCODE_6)) + cursorsize = 5; + if (keyboard_keypressed(SCANCODE_7)) + cursorsize = 6; + if (keyboard_keypressed(SCANCODE_8)) + cursorsize = 7; + if (keyboard_keypressed(SCANCODE_9)) + cursorsize = 8; + if (keyboard_keypressed(SCANCODE_0)) + cursorsize = 9; + if (keyboard_keypressed(SCANCODE_Q)) + loop = 0; + if (keyboard_keypressed(SCANCODE_SPACE)) { + if (!space_pressed) { + color = newcolor(); + space_pressed = 1; + } + } else { + space_pressed = 0; + } +#else + switch (vga_getch()) { + case '1': + cursorsize = 0; + break; + case '2': + cursorsize = 1; + break; + case '3': + cursorsize = 2; + break; + case '4': + cursorsize = 3; + break; + case '5': + cursorsize = 4; + break; + case '6': + cursorsize = 5; + break; + case '7': + cursorsize = 6; + break; + case '8': + cursorsize = 7; + break; + case '9': + cursorsize = 8; + break; + case '0': + cursorsize = 9; + break; + case ' ': + color = newcolor(); + break; + case 'q': + case 'Q': + loop = 0; + break; + default: + ping(); + break; + } +#endif + } + } + +#ifdef USE_RAWKEYBOARD + keyboard_close(); /* Don't forget this! */ +#endif + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/fish_monster.h b/demos/fish_monster.h new file mode 100644 index 0000000..dccbcfb --- /dev/null +++ b/demos/fish_monster.h @@ -0,0 +1,54 @@ +/* Hand edited by M. Weller by from an original XPM file */ +#define fish_monster_w 33 +#define fish_monster_h 33 +/* width height ncolors chars_per_pixel */ +static unsigned char fish_monster233[] = +{0x00, 0xf1, 0xf4, 0x07, 0xff, 0xc0}; +static unsigned short fish_monster555[] = +{0x0000, 0x125f, 0x431c, 0x7c00, 0x7fff, 0x001f}; +static unsigned short fish_monster565[] = +{0x0000, 0x249f, 0x861c, 0xf800, 0xffff, 0x001f}; +static unsigned int fish_monster888[] = +{ + 0x00000000, + 0x002900ff, + 0x0080e0e0, + 0x00ff0000, + 0x00ffffff, + 0x000000ff}; + +/* pixels */ +static char *fish_monster = +"dddddddddddd```dddddd``ddddddd``d" +"ddddddddddd`eee``dddd`e``ddd``e`d" +"ddddddd``````aaee`ddd`e`e```e`e`d" +"ddddd```bbbbb```ee`dd`aae`e`eab`d" +"dddd`ddd`bb```bb``e`dd``aaeaa``dd" +"ddd`dd```b`dd``bbb``dddd`bbb`dddd" +"dd``dd```b`d```bbbb`ddddd`b`ddddd" +"dd`b````bbb```bbbbbb`dddd`b`ddddd" +"d`bbbbbbbbbbbbbbbbbbb`dd`bb`ddddd" +"d`````bbb````bbbbbbbbb``bbbb`dddd" +"`ccccc```cccc``bbbbbbbbbbbbb`dddd" +"`cccccccccccccc`bbbbbbbbbbbb`dddd" +"d````ccccc````cc`bbbbbbbbbbbb`ddd" +"d`d`d`````d`d``cc`bbbbbbbbbbb`ddd" +"d`d`d`d`d`d`d```c`bbbbb``bbbb`ddd" +"dd`d``d`d```````cc`bbbbba`bbb`ddd" +"dddddd```````````c`bbbb`ae`bb`ddd" +"dddddd```````````c`bbbba`e`bb`ddd" +"ddd`dd```````````c`bbb`ae``b`dddd" +"dd`d`````````````c`b`aa`ee`b`dddd" +"dd`d`d`d`````d``cc`bb`ee``bb`dddd" +"d````d`d`d`d`d`cc`bbbb```bb`ddddd" +"`ccc`````d`d``ccc`bbbbbbbbb`ddddd" +"`cccccccc```cccc`bbbbbbbbbb`ddddd" +"d```ccccccccccc`bbbbbbbbbb`dddddd" +"dd`b````ccccc``bbbbbbbbbbb`dddddd" +"dd`bbbbb`````bbbbbbbbbbbb`ddddddd" +"ddd`bbbbbbbbbbbbbbbbbbbb`dddddddd" +"dddd`bbbbbbbbbbbbbbbbb``ddddddddd" +"ddddd``bbbbbbbbbbbbb``ddddddddddd" +"ddddddd```bbbbbbb```ddddddddddddd" +"dddddddddd```````dddddddddddddddd" +"ddddddddddddddddddddddddddddddddd"; diff --git a/demos/forktest.c b/demos/forktest.c new file mode 100644 index 0000000..1d7df81 --- /dev/null +++ b/demos/forktest.c @@ -0,0 +1,164 @@ +/* Program to test the svgalib keyboard functions. */ +/* and stress vga_safety_fork() */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define zero_sa_mask(maskptr) memset(maskptr, 0, sizeof(sigset_t)) + +static char sig2release[] = +{SIGHUP, SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGIOT, SIGBUS, SIGFPE, + SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, + SIGXCPU, SIGXFSZ, SIGVTALRM, + SIGPROF, SIGPWR}; + + +static int newcolor(void) +{ + if (BYTESPERPIXEL == 1) + return random() % 15 + 1; + return gl_rgbcolor(random() & 255, random() & 255, random() & 255); +} + + +static void timeout(int sig) +{ + keyboard_close(); + vga_setmode(TEXT); + puts("Automatic termination after 60 seconds."); + exit(1); +} + +void shutdown(void) +{ + puts("Shutdown called!"); +} + +int main(void) +{ + struct sigaction siga; + int vgamode, color, leftpressed; + int x, y; + + printf("\nWARNING: This program will set the keyboard to RAW mode.\n" + "The keyboard routines in svgalib have not been tested\n" + "very much. There may be no recovery if something goes\n" + "wrong.\n\n" + "Press ctrl-c now to bail out, enter to continue.\n" + "In the test itself, use 'q' or Escape to quit.\n" + "It will also terminate after 60 seconds.\n" + "Use any cursor keys to move, keypad 0 or enter to change color.\n\n" + "\aWARNING, this version of keytest explicitly removes all svgalib\n" + "automatic restore funcs, s.t. when you kill it from the outside\n" + "only vga_safety_fork() can rescue you. Use this svgalib test tool\n" + "with EXTREME! care.\n" + ); + + getchar(); + + vga_safety_fork(shutdown); /* Does already enter a videomode */ + + vga_init(); + + /* Never do this in your code! */ + siga.sa_flags = 0; + zero_sa_mask(&(siga.sa_mask)); + for (x = 0; x < sizeof(sig2release); x++) { + siga.sa_handler = SIG_DFL; + sigaction(sig2release[x], &siga, NULL); + } + + vgamode = vga_getdefaultmode(); + if ((vgamode == -1) || (vga_getmodeinfo(vgamode)->bytesperpixel != 1)) + vgamode = G320x200x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(1); + } + vga_setmode(vgamode); + gl_setcontextvga(vgamode); + gl_enableclipping(); + + signal(SIGALRM, timeout); + + /* This installs the default handler, which is good enough for most */ + /* purposes. */ + if (keyboard_init()) { + printf("Could not initialize keyboard.\n"); + exit(1); + } + /* Translate to 4 keypad cursor keys, and unify enter key. */ + keyboard_translatekeys(TRANSLATE_CURSORKEYS | TRANSLATE_KEYPADENTER | + TRANSLATE_DIAGONAL); + /* (TRANSLATE_DIAGONAL seems to give problems.) Michael: No doesn't... + but might not do what you expect.. */ + + alarm(60); /* Terminate after 60 seconds for safety. */ + + x = WIDTH / 2; + y = HEIGHT / 2; + color = newcolor(); + leftpressed = 0; + for (;;) { + /* Draw moving box. */ + gl_fillbox(x, y, 5, 5, color); + + /* Draw key status bar at top of screen. */ + gl_putbox(0, 0, 128, 1, keyboard_getstate()); + + /* Wait about 1/100th of a second. */ + /* Note that use of this function makes things less */ + /* smooth because of timer latency. */ + usleep(10000); + + keyboard_update(); + + /* Move. */ + if (keyboard_keypressed(SCANCODE_CURSORLEFT)) + x--; + if (keyboard_keypressed(SCANCODE_CURSORRIGHT)) + x++; + if (keyboard_keypressed(SCANCODE_CURSORUP)) + y--; + if (keyboard_keypressed(SCANCODE_CURSORDOWN)) + y++; + + /* Boundary checks. */ + if (x < 0) + x = 0; + if (x >= WIDTH) + x = WIDTH - 1; + if (y < 1) + y = 1; + if (y >= HEIGHT) + y = HEIGHT - 1; + + /* Check for color change. */ + if (keyboard_keypressed(SCANCODE_KEYPAD0) || + keyboard_keypressed(SCANCODE_ENTER)) { + if (!leftpressed) { + color = newcolor(); + leftpressed = 1; + } + } else + leftpressed = 0; + + if (keyboard_keypressed(SCANCODE_Q) || + keyboard_keypressed(SCANCODE_ESCAPE)) + break; + } + + keyboard_close(); /* Don't forget this! */ + + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/fun.c b/demos/fun.c new file mode 100644 index 0000000..cd6ea89 --- /dev/null +++ b/demos/fun.c @@ -0,0 +1,533 @@ +/* Roaming-blobs-on-mars-collect-some-dust-on-a-tropical-island-and-go-pearl- + diving-before-population-goes-out-of-control. */ + +/* Each frame, a background virtual screen is copied to a virtual screen; */ +/* sprites (well, pixels) are written on that virtual screen; and the */ +/* virtual screen is copied to video memory. The background is updated as */ +/* appropriate. This simple animation technique works well for 320x200 */ +/* because it's so small. */ + + +#include +#include +#include +#include +#include +#include +#include + + +/* This can be changed into any 256 color mode. */ +/* For planar 256 color modes, enable page flipping. */ +/* Even 16 color modes work (ugly colors). */ +#define VGAMODE G800x600x256 + +//#define USE_PAGEFLIPPING + +/* #define USE_SMALLOC */ + +/* This is the size of the animated window. */ +#define MAPWIDTH 800 +#define MAPHEIGHT 560 + +#define MAXMOVERS 2000 +#define MAXCITIES 1000 +#define NUMBEROFCITIES 20 +#define NUMBEROFMOVERS 1400 +#define MOVERTHRESHOLD 1400 +#define MOVERLIFETIME 1000 +#define COLORTIME 2000 + +#define randomn( n ) (random() % n) +#define red(x) (32 + x) +#define green(x) (64 + x) +#define yellow(x) (96 + x) +#define blue(x) (128 + x) +#define magenta(x) (160 + x) +#define cyan(x) (192 + x) +#define white(x) (224 + x) + + +/* Data types */ + +typedef struct { + int x; + int y; +} Position; + +#define STAT_ACTIVE 1 + +typedef struct { + int stat; + int x; + int y; + int vx; + int vy; + int color; + int time; +} Mover; + +typedef struct { + int x; + int y; + int pop; + int hit; +} City; + +/* Global variables */ + +int map[MAPWIDTH][MAPHEIGHT]; +/* Map encoding i: */ +/* (0 - 0xffff Mover number i) */ +/* 0x10000... Part of city (i - 0x10000) */ + +Mover mover[MAXMOVERS]; +int nu_movers = 0; +City city[MAXCITIES]; +int nu_cities = 0; +int mytime = 0; /* used to be "time" but collids w/libc function time() */ +int pop = 0; +int framerate, framecount, frameclock; + +GraphicsContext *physicalscreen; +GraphicsContext *backscreen; +GraphicsContext *background; + + +void error(char *s) +{ + printf("%s\n", s); + vga_setmode(TEXT); + exit(0); +} + +void setcustompalette(void) +{ + /* colors 0-31 are a RGB mix (bits 0 and 1 red, 2 green, 3 and 4 blue) */ + /* 32-63 black to red */ + /* 64-95 black to green */ + /* 96-127 black to yellow */ + /* 128-159 black to blue */ + /* 160-191 black to magenta */ + /* 192-223 black to cyan */ + /* 224-255 black to white */ + Palette pal; + int i; + for (i = 0; i < 256; i++) { + int r, g, b; + r = g = b = 0; + if ((i & 32) > 0) + r = (i & 31) << 1; + if ((i & 64) > 0) + g = (i & 31) << 1; + if ((i & 128) > 0) + b = (i & 31) << 1; + if (i < 32) { + r = (i & 3) << 4; /* 2 bits */ + g = (i & 4) << 3; /* 1 bit */ + b = (i & 24) << 1; /* 2 bits */ + } + pal.color[i].red = r; + pal.color[i].green = g; + pal.color[i].blue = b; + } + gl_setpalette(&pal); +} + +void initfont(void) +{ + void *font; +#ifdef USE_SMALLOC + font = smalloc(256 * 8 * 8 * BYTESPERPIXEL); +#else + font = malloc(256 * 8 * 8 * BYTESPERPIXEL); +#endif + gl_expandfont(8, 8, white(24), gl_font8x8, font); + gl_setfont(8, 8, font); +} + +int fsize(FILE * f) +{ + int oldpos, size; + oldpos = ftell(f); + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, oldpos, SEEK_SET); + return size; +} + +void loadfile(char **buf, char *fname) +{ + FILE *f; + int size; + f = fopen(fname, "rb"); + size = fsize(f); + *buf = malloc(size); + fread(*buf, 1, size, f); + fclose(f); +} + + +/* Map */ + +void clearmap(void) +{ + int x, y; + for (y = 0; y < MAPHEIGHT; y++) + for (x = 0; x < MAPWIDTH; x++) + map[x][y] = 0; +} + +Position +findfreeposition(void) +{ + int x, y; + Position p; + do { + x = randomn(MAPWIDTH); + y = randomn(MAPHEIGHT); + } + while (map[x][y] != 0); + p.x = x; + p.y = y; + return p; +} + + +/* Movers */ + +void initmovers(void) +{ + int i; + for (i = 0; i < MAXMOVERS; i++) + mover[i].stat = 0; +} + +int findfreemoverslot(void) +{ + int i; + for (i = 0; i < MAXMOVERS; i++) + if (!(mover[i].stat & STAT_ACTIVE)) + return i; + error("Mover table overflow"); + return 0; +} + +void addrandommover(void) +{ + Position p = findfreeposition(); + int i = findfreemoverslot(); + int c; + mover[i].x = p.x; + mover[i].y = p.y; + do { + mover[i].vx = randomn(3) - 1; + mover[i].vy = randomn(3) - 1; + } + while (mover[i].vx == 0 && mover[i].vy == 0); + mover[i].stat = STAT_ACTIVE; + switch (randomn(4)) { + case 0: + c = blue(20); + break; + case 1: + c = green(20); + break; + case 2: + c = magenta(20); + break; + default: + c = cyan(20); + break; + } + mover[i].time = 0; + mover[i].color = c; + nu_movers++; +} + +void killmover(int i) +{ + mover[i].stat = 0; + nu_movers--; +} + +void drawmover(int i) +{ + gl_setpixel(mover[i].x, mover[i].y, mover[i].color); +} + + +/* Cities */ + +void initcities(void) +{ + nu_cities = 0; +} + +void addcity(int x, int y) +{ + int i = nu_cities++; + map[x][y] = i + 0x10000; + city[i].x = x; + city[i].y = y; + city[i].pop = 1; + city[i].hit = 0; +} + +int cityat(int x, int y) +{ + if (map[x][y] >= 0x10000) + return map[x][y] - 0x10000; + else + return -1; +} + +int citycolor(void) +{ + static int colortable[5] = + {yellow(31), blue(31), white(31), green(31), cyan(31)}; + return colortable[(mytime / COLORTIME) % 5] + - (mytime % COLORTIME) * 25 / COLORTIME; +} + +void growcity(int cx, int cy, int x, int y, int ct) +{ +/* add city unit at (x, y) adjacent to city unit (cx, cy) */ + int c; + map[x][y] = ct + 0x10000; + c = citycolor(); + gl_setpixel(x, y, c); + city[ct].pop++; + city[ct].hit = 20; + pop++; +} + + +/* Main components */ + +void createbackground(void) +{ +/* Create fancy dark red background */ + int x, y; + for (y = 0; y < MAPHEIGHT; y++) + for (x = 0; x < MAPWIDTH; x++) { + int i = 0; + int n = 0; + int c; + if (x > 0) { + i += gl_getpixel(x - 1, y) - red(0); + n++; + } + if (y > 0) { + i += gl_getpixel(x, y - 1) - red(0); + n++; + } + c = (i + randomn(16)) / (n + 1); + if (c > 9) + c = 9; + gl_setpixel(x, y, red(0) + c); + } +} + +void drawbackground(void) +{ +/* Build up background from map data */ + int x, y; + gl_setcontext(background); + gl_clearscreen(0); + createbackground(); + for (y = 0; y < MAPHEIGHT; y++) + for (x = 0; x < MAPWIDTH; x++) { + int c = cityat(x, y); + if (c != -1) + gl_setpixel(x, y, citycolor()); + } +} + +void createcities(void) +{ + int i; + for (i = 0; i < NUMBEROFCITIES; i++) { + Position p = findfreeposition(); + addcity(p.x, p.y); + } +} + +void writestat(void) +{ + char s[41]; + int i, x, y; + int maxpopcity, maxpop; + sprintf(s, "Pop %7d Time %7d Rate %5d.%d", pop, mytime, + framerate / 10, framerate % 10); + gl_setwritemode(WRITEMODE_OVERWRITE); + gl_write(0, HEIGHT - 8, s); + maxpop = -1; + maxpopcity = 0; + for (i = 0; i < nu_cities; i++) + if (city[i].pop > maxpop) { + maxpop = city[i].pop; + maxpopcity = i; + } + gl_enableclipping(); + gl_circle(city[maxpopcity].x, city[maxpopcity].y, 10, + blue(31)); + gl_disableclipping(); + + gl_setwritemode(WRITEMODE_MASKED); + x = city[maxpopcity].x; + y = city[maxpopcity].y; + sprintf(s, "%d", maxpop); + /* clipping */ + if (x + strlen(s) * 8 > MAPWIDTH) + x = MAPWIDTH - strlen(s) * 8; + if (y + 8 > MAPHEIGHT) + y = MAPHEIGHT - 8; + gl_write(x, y, s); +} + +void drawscreen(void) +{ + int i; + /* Copy background to backscreen. */ + gl_setcontext(background); + gl_copyscreen(backscreen); + + /* Now draw the objects in backscreen. */ + gl_setcontext(backscreen); + + for (i = 0; i < MAXMOVERS; i++) + if (mover[i].stat & STAT_ACTIVE) { + drawmover(i); + } + writestat(); + + /* Copy backscreen to physical screen. */ + gl_copyscreen(physicalscreen); +} + +void move(void) +{ + int i; + gl_setcontext(background); + for (i = 0; i < MAXMOVERS; i++) + if (mover[i].stat & STAT_ACTIVE) { + int nx, ny; + int c; + if (++mover[i].time == MOVERLIFETIME) { + killmover(i); + continue; + } + for (;;) { + nx = mover[i].x + mover[i].vx; + ny = mover[i].y + mover[i].vy; + if (nx < 0 || nx >= MAPWIDTH) { + mover[i].vx = -mover[i].vx; + continue; + } + if (ny < 0 || ny >= MAPHEIGHT) { + mover[i].vy = -mover[i].vy; + continue; + } + break; + } + c = cityat(nx, ny); + if (c != -1) { /* found city */ + killmover(i); + growcity(nx, ny, mover[i].x, mover[i].y, c); + continue; /* next mover */ + } + mover[i].x = nx; + mover[i].y = ny; + } + if (pop >= MAPWIDTH * MAPHEIGHT * 255 / 256) { + /* start all over again */ + printf("fun: new run.\n"); + pop = 0; + mytime = 0; + clearmap(); + initcities(); + createcities(); + drawbackground(); + } +} + +void createmovers(void) +{ + int i; + for (i = 0; i < NUMBEROFMOVERS; i++) + addrandommover(); +} + +int main(void) +{ + vga_init(); + + clearmap(); + initmovers(); + createcities(); + createmovers(); + + vga_setmode(VGAMODE); + gl_setcontextvga(VGAMODE); + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + +#ifdef USE_PAGEFLIPPING + /* Try to enable page flipping. */ +printf("pf=%i\n", gl_enablepageflipping(physicalscreen)); +#endif + setcustompalette(); + /* initfont() here caused trouble with planar 256 color modes. */ + + gl_setcontextvgavirtual(VGAMODE); + backscreen = gl_allocatecontext(); + gl_getcontext(backscreen); +#ifdef USE_SMALLOC + free(backscreen->vbuf); + backscreen->vbuf = smalloc(BYTEWIDTH * HEIGHT); + gl_setcontext(backscreen); +#endif + + initfont(); + + gl_setcontextvgavirtual(VGAMODE); + background = gl_allocatecontext(); + gl_getcontext(background); +#ifdef USE_SMALLOC + free(background->vbuf); + background->vbuf = smalloc(BYTEWIDTH * HEIGHT); + gl_setcontext(background); +#endif + + drawbackground(); + + framerate = 0; + framecount = 0; + frameclock = clock(); + + for (;;) { + int i; + drawscreen(); + move(); + for (i = 0; i < 4; i++) + if (nu_movers < MOVERTHRESHOLD) + addrandommover(); + mytime++; + /* Update frame rate every 3 seconds. */ + framecount++; + if (clock() - frameclock >= CLOCKS_PER_SEC) { + framerate = framecount * CLOCKS_PER_SEC / (clock() - frameclock); + framecount = 0; + frameclock = clock(); + } + } + +#ifndef USE_SMALLOC + gl_freecontext(backscreen); + gl_freecontext(background); +#endif + + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/joytest.c b/demos/joytest.c new file mode 100644 index 0000000..bca6b8b --- /dev/null +++ b/demos/joytest.c @@ -0,0 +1,61 @@ +/* + * joytest.c 1.0 + * Cpoyright (C) 1998 Daniel Engström + * + */ + +/* + * This is a simple joystick test program and an example + * how to write programs using the vgajoystick library routines + */ + +/* + * usage: joytest + */ + +#include +#include +#include +#include +#include + +char *axe_name[] = { "X", "Y", "Z", }; + +int main (int argc, char **argv) +{ + int joystick, axes, buttons, i; + + if (argc != 2) { + fprintf(stderr, "usage: joytest \n"); + exit (1); + } + + joystick = atoi(argv[1]); + + if (joystick_init(joystick, JOY_CALIB_STDOUT) < 0) + exit(1); + + axes = joystick_getnumaxes(joystick); + buttons = joystick_getnumbuttons(joystick); + printf("Joystick %d has %d axes and %d buttons.\n", joystick, axes, buttons); + + if (axes > 3) + axes = 3; + + printf("Press enter to start testing ... (interrupt to exit)\n"); + getchar(); + for(;;) + { + while(!joystick_update()); + + for (i = 0; i < buttons; i++) + printf("B%d: %s ", i, joystick_getbutton(joystick, i) ? "down" : "up "); + for (i = 0; i < axes; i++) + printf("%s: %4d ", axe_name[i], joystick_getaxis(joystick, i)); + putchar('\n'); + usleep(100); + } + + joystick_close(joystick); + return 0; +} diff --git a/demos/keytest.c b/demos/keytest.c new file mode 100644 index 0000000..74acf3e --- /dev/null +++ b/demos/keytest.c @@ -0,0 +1,130 @@ +/* Program to test the svgalib keyboard functions. */ + +#include +#include +#include +#include +#include +#include +#include +#include + + + +static int newcolor(void) +{ + if (BYTESPERPIXEL == 1) + return random() % 15 + 1; + return gl_rgbcolor(random() & 255, random() & 255, random() & 255); +} + + +static void timeout(int sig) +{ + keyboard_close(); + vga_setmode(TEXT); + puts("Automatic termination after 60 seconds."); + exit(1); +} + +int main(void) +{ + int vgamode, color, leftpressed; + int x, y; + vga_init(); + vgamode = vga_getdefaultmode(); + if ((vgamode == -1) || (vga_getmodeinfo(vgamode)->bytesperpixel != 1)) + vgamode = G320x200x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(1); + } + printf("\nWARNING: This program will set the keyboard to RAW mode.\n" + "The keyboard routines in svgalib have not been tested\n" + "very much. There may be no recovery if something goes\n" + "wrong.\n\n" + "Press ctrl-c now to bail out, enter to continue.\n" + "In the test itself, use 'q' or Escape to quit.\n" + "It will also terminate after 60 seconds.\n" + "Use any cursor keys to move, keypad 0 or enter to change color.\n"); + + getchar(); + + vga_setmode(vgamode); + gl_setcontextvga(vgamode); + gl_enableclipping(); + + signal(SIGALRM, timeout); + + /* This installs the default handler, which is good enough for most */ + /* purposes. */ + if (keyboard_init()) { + printf("Could not initialize keyboard.\n"); + exit(1); + } + /* Translate to 4 keypad cursor keys, and unify enter key. */ + keyboard_translatekeys(TRANSLATE_CURSORKEYS | TRANSLATE_KEYPADENTER | + TRANSLATE_DIAGONAL); + /* (TRANSLATE_DIAGONAL seems to give problems.) Michael: No doesn't... + but might not do what you expect.. */ + + alarm(60); /* Terminate after 60 seconds for safety. */ + + x = WIDTH / 2; + y = HEIGHT / 2; + color = newcolor(); + leftpressed = 0; + for (;;) { + /* Draw moving box. */ + gl_fillbox(x, y, 5, 5, color); + + /* Draw key status bar at top of screen. */ + gl_putbox(0, 0, 128, 1, keyboard_getstate()); + + /* Wait about 1/100th of a second. */ + /* Note that use of this function makes things less */ + /* smooth because of timer latency. */ + usleep(10000); + + keyboard_update(); + + /* Move. */ + if (keyboard_keypressed(SCANCODE_CURSORLEFT)) + x--; + if (keyboard_keypressed(SCANCODE_CURSORRIGHT)) + x++; + if (keyboard_keypressed(SCANCODE_CURSORUP)) + y--; + if (keyboard_keypressed(SCANCODE_CURSORDOWN)) + y++; + + /* Boundary checks. */ + if (x < 0) + x = 0; + if (x >= WIDTH) + x = WIDTH - 1; + if (y < 1) + y = 1; + if (y >= HEIGHT) + y = HEIGHT - 1; + + /* Check for color change. */ + if (keyboard_keypressed(SCANCODE_KEYPAD0) || + keyboard_keypressed(SCANCODE_ENTER)) { + if (!leftpressed) { + color = newcolor(); + leftpressed = 1; + } + } else + leftpressed = 0; + + if (keyboard_keypressed(SCANCODE_Q) || + keyboard_keypressed(SCANCODE_ESCAPE)) + break; + } + + keyboard_close(); /* Don't forget this! */ + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/linearfork.c b/demos/linearfork.c new file mode 100644 index 0000000..e0d3075 --- /dev/null +++ b/demos/linearfork.c @@ -0,0 +1,165 @@ +/* Program to test the svgalib keyboard functions. */ +/* and stress vga_safety_fork() */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define zero_sa_mask(maskptr) memset(maskptr, 0, sizeof(sigset_t)) + +static char sig2release[] = +{SIGHUP, SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGIOT, SIGBUS, SIGFPE, + SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, + SIGXCPU, SIGXFSZ, SIGVTALRM, + SIGPROF, SIGPWR}; + + +static int newcolor(void) +{ + if (BYTESPERPIXEL == 1) + return random() % 15 + 1; + return gl_rgbcolor(random() & 255, random() & 255, random() & 255); +} + + +static void timeout(int sig) +{ + keyboard_close(); + vga_setmode(TEXT); + puts("Automatic termination after 60 seconds."); + exit(1); +} + +void shutdown(void) +{ + puts("Shutdown called!"); +} + +int main(void) +{ + struct sigaction siga; + int vgamode, color, leftpressed; + int x, y; + + printf("\nWARNING: This program will set the keyboard to RAW mode.\n" + "The keyboard routines in svgalib have not been tested\n" + "very much. There may be no recovery if something goes\n" + "wrong.\n\n" + "Press ctrl-c now to bail out, enter to continue.\n" + "In the test itself, use 'q' or Escape to quit.\n" + "It will also terminate after 60 seconds.\n" + "Use any cursor keys to move, keypad 0 or enter to change color.\n\n" + "\aWARNING, this version of keytest explicitly removes all svgalib\n" + "automatic restore funcs, s.t. when you kill it from the outside\n" + "only vga_safety_fork() can rescue you. Use this svgalib test tool\n" + "with EXTREME! care.\n" + ); + + getchar(); + + vga_safety_fork(shutdown); /* Does already enter a videomode */ + + vga_init(); + + /* Never do this in your code! */ + siga.sa_flags = 0; + zero_sa_mask(&(siga.sa_mask)); + for (x = 0; x < sizeof(sig2release); x++) { + siga.sa_handler = SIG_DFL; + sigaction(sig2release[x], &siga, NULL); + } + + vgamode = vga_getdefaultmode(); + if ((vgamode == -1) || (vga_getmodeinfo(vgamode)->bytesperpixel != 1)) + vgamode = G640x480x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(1); + } + vga_setmode(vgamode); + vga_setlinearaddressing(); + gl_setcontextvga(vgamode); + gl_enableclipping(); + + signal(SIGALRM, timeout); + + /* This installs the default handler, which is good enough for most */ + /* purposes. */ + if (keyboard_init()) { + printf("Could not initialize keyboard.\n"); + exit(1); + } + /* Translate to 4 keypad cursor keys, and unify enter key. */ + keyboard_translatekeys(TRANSLATE_CURSORKEYS | TRANSLATE_KEYPADENTER | + TRANSLATE_DIAGONAL); + /* (TRANSLATE_DIAGONAL seems to give problems.) Michael: No doesn't... + but might not do what you expect.. */ + + alarm(60); /* Terminate after 60 seconds for safety. */ + + x = WIDTH / 2; + y = HEIGHT / 2; + color = newcolor(); + leftpressed = 0; + for (;;) { + /* Draw moving box. */ + gl_fillbox(x, y, 5, 5, color); + + /* Draw key status bar at top of screen. */ + gl_putbox(0, 0, 128, 1, keyboard_getstate()); + + /* Wait about 1/100th of a second. */ + /* Note that use of this function makes things less */ + /* smooth because of timer latency. */ + usleep(10000); + + keyboard_update(); + + /* Move. */ + if (keyboard_keypressed(SCANCODE_CURSORLEFT)) + x--; + if (keyboard_keypressed(SCANCODE_CURSORRIGHT)) + x++; + if (keyboard_keypressed(SCANCODE_CURSORUP)) + y--; + if (keyboard_keypressed(SCANCODE_CURSORDOWN)) + y++; + + /* Boundary checks. */ + if (x < 0) + x = 0; + if (x >= WIDTH) + x = WIDTH - 1; + if (y < 1) + y = 1; + if (y >= HEIGHT) + y = HEIGHT - 1; + + /* Check for color change. */ + if (keyboard_keypressed(SCANCODE_KEYPAD0) || + keyboard_keypressed(SCANCODE_ENTER)) { + if (!leftpressed) { + color = newcolor(); + leftpressed = 1; + } + } else + leftpressed = 0; + + if (keyboard_keypressed(SCANCODE_Q) || + keyboard_keypressed(SCANCODE_ESCAPE)) + break; + } + + keyboard_close(); /* Don't forget this! */ + + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/linearspeed.c b/demos/linearspeed.c new file mode 100644 index 0000000..75a5b57 --- /dev/null +++ b/demos/linearspeed.c @@ -0,0 +1,422 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define LINEAR_ADDRESSING + + +int VGAMODE, USEGL; +GraphicsContext *physicalscreen; +GraphicsContext *backscreen; +int fast=0; + +void screen1(void) +{ + int x, y; + for (y = 0; y < HEIGHT; y++) + for (x = 0; x < WIDTH; x++) + /* limited RGB palette in 256-color modes */ + /* some color information is not used in */ + /* 15-bit color modes */ + gl_setpixelrgb(x, y, + x * 256 / WIDTH, + 255 - x * 256 / WIDTH, + y * 256 / HEIGHT); +} + + +void configure(void) +{ + int allowed[GLASTMODE + 1]; + + for (;;) { + int i; + int m; + for (i = G320x200x16; i <= GLASTMODE; i++) { + allowed[i] = 0; + if (vga_hasmode(i)) { + printf("%2d %s\n", i, vga_getmodename(i)); + allowed[i] = 1; + } + } + + printf("\nWhich mode? "); + scanf("%d", &m); + getchar(); + printf("\n"); + if (m >= G320x200x16 && m <= GLASTMODE) { + VGAMODE = m; + if (vga_getmodeinfo(m)->bytesperpixel >= 1) + USEGL = 1; + else + USEGL = 0; + break; + } + } + + vga_setmode(VGAMODE); +#ifdef LINEAR_ADDRESSING + vga_setlinearaddressing(); +#endif + if (USEGL) { + gl_setcontextvga(VGAMODE); + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + } +} + + +void blit(void) +{ + gl_clearscreen(0x86); + vga_imageblt(vga_getgraphmem(), 0, WIDTH - 128, HEIGHT - 128, + WIDTH * BYTESPERPIXEL); +/* vga_bitblt(0, 100 * WIDTH * BYTESPERPIXEL, 50, 50, WIDTH * BYTESPERPIXEL); + vga_fillblt(100 * BYTESPERPIXEL, 50, 50, WIDTH * BYTESPERPIXEL, 0x86); + */ +} + + +#if 0 + +/* May help on well-designed motherboards. */ + +/* IT DOES MAKE A DIFFERENCE! REP STOSL IS SLOWER */ +/* (CL-GD5434 VLB zero-wait writes -- 2/3 cycles); rep stos takes 4 */ + +#if 1 + +static inline void * + __memset(void *s, char c, size_t count) +{ + __asm__( + "cld\n\t" + "cmpl $12,%%edx\n\t" + "jl 1f\n\t" /* if (count >= 12) */ + + "movzbl %%al,%%ax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $8,%%ecx\n\t" /* c |= c << 8 */ + "orl %%ecx,%%eax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $16,%%ecx\n\t" /* c |= c << 16 */ + "orl %%ecx,%%eax\n\t" + + "movl %%edx,%%ecx\n\t" + "negl %%ecx\n\t" + "andl $3,%%ecx\n\t" /* (-s % 4) */ + "subl %%ecx,%%edx\n\t" /* count -= (-s % 4) */ + "rep ; stosb\n\t" /* align to longword boundary */ + + "movl %%edx,%%ecx\n\t" + "shrl $2,%%ecx\n\t" + + "cmpl $32,%%ecx\n\t" /* do loop unrolling for */ + "jl 2f\n\t" /* chunks of 128 bytes */ + "jmp 3f\n\t" + ".align 4,0x90\n\t" + + "3:\n\t" + "movl %%eax,(%%edi)\n\t" + "movl %%eax,4(%%edi)\n\t" + "movl %%eax,8(%%edi)\n\t" + "movl %%eax,12(%%edi)\n\t" + "movl %%eax,16(%%edi)\n\t" + "movl %%eax,20(%%edi)\n\t" + "movl %%eax,24(%%edi)\n\t" + "movl %%eax,28(%%edi)\n\t" + "movl %%eax,32(%%edi)\n\t" + "movl %%eax,36(%%edi)\n\t" + "movl %%eax,40(%%edi)\n\t" + "movl %%eax,44(%%edi)\n\t" + "movl %%eax,48(%%edi)\n\t" + "movl %%eax,52(%%edi)\n\t" + "movl %%eax,56(%%edi)\n\t" + "movl %%eax,60(%%edi)\n\t" + "movl %%eax,64(%%edi)\n\t" + "movl %%eax,68(%%edi)\n\t" + "movl %%eax,72(%%edi)\n\t" + "movl %%eax,76(%%edi)\n\t" + "movl %%eax,80(%%edi)\n\t" + "movl %%eax,84(%%edi)\n\t" + "movl %%eax,88(%%edi)\n\t" + "movl %%eax,92(%%edi)\n\t" + "movl %%eax,96(%%edi)\n\t" + "movl %%eax,100(%%edi)\n\t" + "movl %%eax,104(%%edi)\n\t" + "movl %%eax,108(%%edi)\n\t" + "subl $32,%%ecx\n\t" + "movl %%eax,112(%%edi)\n\t" + "movl %%eax,116(%%edi)\n\t" + "movl %%eax,120(%%edi)\n\t" + "movl %%eax,124(%%edi)\n\t" + "addl $128,%%edi\n\t" + "cmpl $32,%%ecx\n\t" + "jge 3b\n\t" + + "2:\n\t" + "rep ; stosl\n\t" /* fill remaining longwords */ + + "andl $3,%%edx\n" /* fill last few bytes */ + "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ + "rep ; stosb\n\t" + : : "a"(c), "D"(s), "d"(count) + : "ax", "cx", "dx", "di"); + return s; +} + +#else /* 8-bit writes. */ + +static inline void * + __memset(void *s, char c, size_t count) +{ + __asm__( + "cld\n\t" + "cmpl $12,%%edx\n\t" + "jl 1f\n\t" /* if (count >= 12) */ + + "movzbl %%al,%%ax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $8,%%ecx\n\t" /* c |= c << 8 */ + "orl %%ecx,%%eax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $16,%%ecx\n\t" /* c |= c << 16 */ + "orl %%ecx,%%eax\n\t" + + "movl %%edx,%%ecx\n\t" + "negl %%ecx\n\t" + "andl $3,%%ecx\n\t" /* (-s % 4) */ + "subl %%ecx,%%edx\n\t" /* count -= (-s % 4) */ + "rep ; stosb\n\t" /* align to longword boundary */ + + "movl %%edx,%%ecx\n\t" + "shrl $2,%%ecx\n\t" + + "cmpl $32,%%ecx\n\t" /* do loop unrolling for */ + "jl 2f\n\t" /* chunks of 128 bytes */ + "jmp 3f\n\t" + ".align 4,0x90\n\t" + + "3:\n\t" + "movb %%al,(%%edi)\n\t" + "movb %%al,1(%%edi)\n\t" + "movb %%al,2(%%edi)\n\t" + "movl %%al,3(%%edi)\n\t" + "movl %%al,4(%%edi)\n\t" + "movl %%al,5(%%edi)\n\t" + "movl %%al,6(%%edi)\n\t" + "movl %%al,7(%%edi)\n\t" + "movl %%al,8(%%edi)\n\t" + "movl %%al,9(%%edi)\n\t" + "movl %%al,10(%%edi)\n\t" + "movl %%al,11(%%edi)\n\t" + "movl %%al,12(%%edi)\n\t" + "movl %%al,13(%%edi)\n\t" + "movl %%al,14(%%edi)\n\t" + "movl %%al,15(%%edi)\n\t" + "movl %%al,16(%%edi)\n\t" + "movl %%al,17(%%edi)\n\t" + "movl %%al,18(%%edi)\n\t" + "movl %%al,19(%%edi)\n\t" + "movl %%al,20(%%edi)\n\t" + "movl %%al,21(%%edi)\n\t" + "movl %%al,22(%%edi)\n\t" + "movl %%al,23(%%edi)\n\t" + "movl %%al,24(%%edi)\n\t" + "movl %%al,25(%%edi)\n\t" + "movl %%al,26(%%edi)\n\t" + "movl %%al,27(%%edi)\n\t" + "movl %%al,28(%%edi)\n\t" + "subl $8,%%ecx\n\t" + "movl %%al,29(%%edi)\n\t" + "movl %%al,30(%%edi)\n\t" + "movl %%al,31(%%edi)\n\t" + "addl $32,%%edi\n\t" + "cmpl $8,%%ecx\n\t" + "jge 3b\n\t" + + "2:\n\t" + "rep ; stosl\n\t" /* fill remaining longwords */ + + "andl $3,%%edx\n" /* fill last few bytes */ + "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ + "rep ; stosb\n\t" + : : "a"(c), "D"(s), "d"(count) + : "ax", "cx", "dx", "di"); + return s; +} + +#endif + +#define memset __memset + +#endif + + +void speed(void) +{ + int i; + int start_clock; + int finish_clock; + int diff_clock; + unsigned char *vgabase = vga_getgraphmem()+128*1024; + char *base; + struct timeval tv1, tv2; + + +#ifndef LINEAR_ADDRESSING + if (VGAMODE >= G640x480x256) + vga_setpage(0); +#endif + + base=malloc(655360); + + gettimeofday(&tv1, NULL); + + for (i = 0; i < 500; i++) { + memset(vgabase, i & 255, 1048576); + } + + gettimeofday(&tv2, NULL); + + diff_clock = (tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec); + printf("memset video memory timing: %3d.%1ds, %dM/s\n", diff_clock / 1000000, + (diff_clock % 1000000), 500000000 / diff_clock); + + if(fast)return; + + start_clock = clock(); + + for (i = 0; i < 500; i++) { + memcpy(vgabase, base, 655360); + } + + finish_clock = clock(); + + diff_clock = (finish_clock - start_clock)*10/CLOCKS_PER_SEC; + printf("memcpy to video memory timing: %3d.%1ds, %dK/s\n", diff_clock / 10, + (diff_clock % 10), 64*5000*10 / diff_clock); + + + start_clock = clock(); + + for (i = 0; i < 500; i++) { + memcpy(base, vgabase, 655360); + } + + finish_clock = clock(); + + diff_clock = (finish_clock - start_clock)*10/CLOCKS_PER_SEC; + printf("memcpy from video memory timing: %3d.%1ds, %dK/s\n", diff_clock / 10, + (diff_clock % 10), 64*5000*10 / diff_clock); + + + + start_clock = clock(); + + for (i = 0; i < 500; i++) { + unsigned char *j; + unsigned char *k; + unsigned char *l; + l=vgabase; + k=base; + j=base; + j+=655360; + while(k1)fast=1; + + vga_init(); + + printf("This is a video memory speed tester. Note that the first " + "screen doesn't test\nanything (nor does the 3 second pause " + "that follows).\n\n"); + + configure(); + + if (COLORS == 256) + gl_setrgbpalette(); /* set RGB palette */ + + if (USEGL) + screen1(); + sleep(2); + +/* vga_screenoff(); */ + + speed(); + if(!fast)sysmem_speed(); + + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/lineart.c b/demos/lineart.c new file mode 100644 index 0000000..dd96aca --- /dev/null +++ b/demos/lineart.c @@ -0,0 +1,132 @@ +/* A program to test any mode for linear. Default mode is G640x480x256 = 10 +** or parameters may be used giving modes as integers. +** linp [mode mode ...] +** Don Secrest Oct. 1998 +*/ + +#include +#include +#include +#include +#include + +static void screen(int mode) +{ + int bpp,bott,endp,linlen,i,j,bii,col,p; + vga_modeinfo *minf; + unsigned char *vbuf; + int mem; + + if(mode == 0) + { + printf("Usage:lineart [mode mode ...]\n\nwhere mode is an integer.\n"); + return; + } + if(! vga_hasmode(mode)) { + printf("Invalid mode %d\n",mode); + return; + } + vga_setmode(mode); + minf = vga_getmodeinfo(mode); + if(! (minf->flags & CAPABLE_LINEAR)){ + vga_setmode(TEXT); + printf("The mode %d is not capable of linear\n",mode); + return; + } + vga_setpage(0); + if(vga_setlinearaddressing() == -1) { + vga_setmode(TEXT); + printf("Could not set linear addressing for mode %d\n",mode); + return; + } + bpp = minf->bytesperpixel; + linlen = minf->width*bpp; + bott = linlen*17; /* pointer 17 pixels wide. */ + endp = linlen*minf->height; + mem = minf->linewidth*minf->height; + + /* Do random pixels */ + vbuf = vga_getgraphmem(); + printf("Memory mapped to %08x. Mode = %d.\n",(int) vbuf,mode); + memset(vbuf,0,mem); /* Clear out 2 megabytes of memory, */ + for(i = 0;i < 100000;i++) + { + p = rand() % mem-2; + *(vbuf + p) = rand() & 0xff; + if(bpp > 1) + *(vbuf + p + 1) = rand() & 0xff; + if(bpp == 3) + *(vbuf + p + 2) = rand() & 0xff; + } + + /* Place marker at top left and bottem right. */ + for(i = 0;i < 44;i += bpp) { + *(vbuf + i) = 0x60; + *(vbuf + bott + i) = 0x60; + *(vbuf + endp - i) = 0x60; + bii = endp -1 -bott; + *(vbuf + bii -i) = 0x60; + if(bpp > 1) { + *(vbuf + i + 1) = 0x60; + *(vbuf + i + 1 + bott) = 0x60; + *(vbuf - i - 1 + endp) = 0x60; + *(vbuf - i - 1 + bii) = 0x60; + } + if(bpp == 3) { + *(vbuf + i + 2) = 0x60; + *(vbuf + i + 2 + bott) = 0x60; + *(vbuf - i - 2 + endp) = 0x60; + *(vbuf - i - 2 + bii) = 0x60; + } + col = (i == 0 || i >= 42)? 0x60:0; + for(j = 1;j < 17;j++) { + *(vbuf + i + linlen*j) = col; + *(vbuf - i + endp -1 - linlen*j) = col; + if(bpp > 1) { + *(vbuf + i + 1 + linlen*j) = col; + *(vbuf - i - 2 + endp - linlen*j) = col; + } + if(bpp == 3) { + *(vbuf + i + 2 + linlen*j) = col; + *(vbuf - i - 3 + endp - linlen*j) = col; + } + } + } + for(i = 5;i < 12;i += bpp) + for(j = 4;j < 12;j++) { + *(vbuf + i + linlen*j) = 0x3f; + *(vbuf + endp - i - bpp - linlen*j) = 0x3f; + } + getchar(); /* Wait for a key punch */ +} + +int +main(int argc,char *argv[]) +{ + int mode,c; + + vga_init(); + c=1; + if(argc == 1) + screen(10); /* G640x480x256 */ + else + c = 0; + while(argc > 1) + { + argc--; + c++; + if(isdigit(*argv[c])) + mode = atoi(argv[c]); + else if(*argv[c] == 'G') + mode = vga_getmodenumber(argv[c]); + else + { + printf("Unknown mode %s\n",argv[c]); + continue; + } + screen(mode); + } + vga_setmode(TEXT); + return 0; +} + diff --git a/demos/linuxlogo.bitmap b/demos/linuxlogo.bitmap new file mode 100644 index 0000000..1e43a6b --- /dev/null +++ b/demos/linuxlogo.bitmap @@ -0,0 +1 @@ +˜™™——˜™›œœœœ›œœ›˜—————————•‘˜‘˜˜”™•˜™˜—š›™™™œ————————————————•”‘‘’–•–•––—–———”””’‘’‘‘‘™šœœ›˜™˜™››šš˜šš™™œœžœ™™˜’‘‘‘’’““”““””•™œ›œœœœ›œžžžœœš™•••••”’’š›š›™››œšš›—˜›œœœ›››œ›œ›˜———————””‘’’“š˜˜™™™™™™—˜˜———˜—————————————•‘‘‘’’”•––•”•–———–””””’‘‘˜™šššœœœžœšœœš›œžŸœ›™‘‘‘“““’“““˜ššœœœš›œœ›œ››š™™•••••”’‘™šœžœ›ššš›ššš››œœœœšššš›œ›œ›——˜˜™›™˜˜™’’“’•™—™—˜˜—˜—™˜————————————––––”“‘““”••••••––––••”•••”‘‘˜š™™›œœžžŸžžžŸŸŸŸžœš™™‘’“’‘‘‘˜˜š›™œœœœš››››››œš™š™••••••”’’“˜œœžžœ›šššœ™œžœœœ››ššš™™š››œœœœœ˜™˜œ›š˜‘‘’’’’“”–˜™˜™˜—˜˜˜˜˜˜——————————–––““’˜‘’’’’‘“””••–––••”••••––•‘‘™˜™™››œœžžŸŸŸŸŸžž›œŽŽŽ“’’’‘‘’‘˜™™˜››››šššš™™ššššš™™˜˜••••••“’“’šœžžžœ›››š›œžžžœœœœ›š™š™™™››š›œœ›žžŸž™š˜‘‘‘‘’’•–™˜˜™˜˜˜—˜˜———————————••’’’‘’’‘‘‘’”””–•••••””••••––’‘Ž˜™˜˜™ššœ››œœœžŸŸŸžžŒ‹ŽŽŒ˜‘’’™™˜‘˜›š™™˜ŒŒŒ™™˜™™™˜˜•••••••””“’’˜š››œœ››œ›››œžžœœœœšš™˜™™š››š™›œžžžžž›šš˜‘‘‘’”–˜›™›š›››—˜™™˜———————–•“‘‘‘‘‘˜‘‘‘““”•”•””••”””••••–““‘‘˜‘››œœœœœœœŽŒŒŽŒ‰‹ŒŒ‹Ž™š›š™˜‘™˜ŒŒŒ‹‹™˜˜™˜™”•••••••••”““‘˜ššœ›šš™›šššžœœšš˜˜˜š›››š™››žžžžžžš›˜‘’““—™šžœœšœ›™™š˜™˜———————”‘‘‘‘‘˜˜‘‘’““””””””••””””•••–”“˜œœ››œœœœŽŒŽŒŒŠˆ‹‰ŠŒŒŒ‹œ›››˜˜ŒŒ‹‹‹‹˜˜‘˜““••••••–””””“”“‘˜™˜˜š™™™˜šššžœœ›™™™›››šš›››žŸžžžœ›š”’“‘˜˜—˜œ›œœœ››™™˜˜————–••’‘‘‘‘˜˜‘’““““’“““”••””””••Ž•ŽŽŽŽ™™œšš™››œŒŠŒŒŒ‹Š‡ˆ‡‹‹Œ‹ŒŽ›››˜˜ŽŽŽŽŒ‹ŠŠŠŠ‹‹’“’•–––––••””“““”‘’˜‘‘’™™žœœš™š››šš››œœžŸžžœœ™““““”™™šž›œ››š›š˜˜—””““‘‘‘‘™™˜’’“’’‘‘’’“•••””“”ŽŽŽŒŽŽŒŒ‹˜•ššš›››ŽŒ‹Š‰‰‰Š‰ŠŠ‡‡‡š™ŽŽŽŽŽŽŽŽŒŒŒŒŠ‰‰‰ˆ˜™’‘“––––•••–”“““““’’‘‘‘’’˜™žžœ›š››š›››žžžžžŸž›š““““•™šš›žžœœš›››››™™”””‘‘˜˜™š˜‘‘‘’‘‘‘’’”•••““‹‹ŒŒ‹ŒŽŒŒ‹‹‹‹‹›ŽŽŽ‹Šˆˆˆ‰‰Š‰‡‡‡‡‹˜ŽŽŽŽŽŽŒŒ‹ŒŒŠ‰‰ˆˆš˜Œ‘‘“”––•••–––““““‘’‘‘‘’‘‘‘’’’’‘‘‘‘‘‘’’™žžžžœœœœœ›››žžžžžŸš˜““”˜›žžšœœ™šš˜˜˜™˜™˜™™š™˜˜’‘‘‘‘“““”•””ŒŠŒŒ‹‹ŽŒŒ‹‹‹‹‹‹‹ŒŽŽŽŒ‹‰ˆˆˆˆ‰Š‰‡‡‡†‡ŠŽŽŽŽŒ‹‹‹‹ŠŠ‰‰‰‰˜‹Œ’““––••––––•””““’’‘’’‘‘’‘““““’’‘‘’’““˜žžžžœ›œœœœœŽžŽŽ›”””•™œœžžžšššš˜˜“˜˜˜˜˜š™š›œ™˜˜‘’””““”‹‹ŒŒŒŠ‹‹‹ŠŠŠŠŠŠŠ‰ŒŒŒŽŽŒŒ‰ˆˆ‡‡‡ˆˆˆ‰‰‰Š‰‡‡‡ˆŒŽŒŒŒŒŒŽŠ‰ˆ‰‰ˆ‰‰‰ŠŠ‹‹’”•——––––––••”““”’“’’‘‘‘’“”“““’‘‘’’““”žžžžžŽŽœœœœœœŒœ•“”””˜šžžŸ››šš™˜˜’‘˜˜˜˜˜™š››››™˜˜’’”””“‹ŒŽŽŽŠŒŽŽŽŠŠŠ‰ˆ‰ŠŠŠˆˆŒŒŒŒŒ‹‰‡‡‡‡‡‡‡‡‡ˆ‰ŠŠ‡‰‡‡‡‹ŒŒŒŒŒ‹‰ˆ‰‰‡‡ˆ‰‰Š‹‰‹’–——–––––––••””••’’’’‘’‘””““““’’’’“””ŸŸŸŸŽŽŽŽŽŒ‹œ‰œœœ›ŠŒŠ‹Œ˜‘’’œœššš’’˜™™ššœœ››››˜‘’““””ŽŽŒŽŽŠŽŽŽŒ‹ˆ‰‰ˆ‡‡ˆ‰‡ˆˆ‹ŒŒŒ‹ŠŠˆ‡‡‡‡‡‡‡‡‡‡‡ˆ‰‡‡Š‰‡‡‹ŒŠŒŒŒŒ‹Š‹ˆˆ‡‡‡ˆ‰ˆˆˆ‰Š‘”•—––––––––•””•””“””’’’“””“““”””“””•ŸŸŸžžžŽŽŽŽŒŒŠ‰œŠœ›opqsttwxwwxxwz{{}ŽŽœœœœœšš˜˜š™™›œ››››™‘’ŽŽŽŒŽŽŒŽŽŽŒ‹‹ˆˆˆ‡‡‡‡‡‡‡‡Š‹‹‹Š‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆŠ‡Š‰ŠŠŠŒŒ‹‹ŠŠ‰‰‰‡‡‡‡‡‡‡ˆ‰““–—––––––––”•”””••••““““””“””•••”••ŸŸžžŽ‹‹ŒŒ‰‹Š‰ˆœœ››n????>>===;;::89zŒœœœššš™™˜™šš›œœœœœ››™™™‘ŽŽŽ‹ŒŽŽŽŽŽ‹‹‹Š‡‡‡‡‡‡‡‡‡ˆŠŠ‹‹‰‰‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆˆ‰‡‰ŠŠ‰Œ‹ŠŠŠ‡ˆ‡‡‡‡‡‡‡‡‡‡‡““”–—––”––––—–••••••••””“””•”••––———ŒŒŒŒ‹‹Š‹‰‰‰ž‹‰ˆœœn>???==;<<==>;::x™˜˜™š›™™›››œ›™™˜ŽŒŒŠ‹ŽŽŽŽŒŠŠŠ‰ˆ‡‡‡‡‡‡‡‡‡ˆ‰ˆŠ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‡ˆ‡‰‰Š‹Œ‹Š‰‡ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡““”•——–––––———•••••••––•••••––—————™Š‹ŠŠ‹‹ŒŠŠŠ‰‰Š‰Š‹‹‹‹‰œœo>>?=<;<:;;==<=>>==:88:9;<===wŽ˜”‘˜’’‘˜™˜™™˜™™š˜™˜““““‹ŒŒŠŽŽŽŽŽŒŒŠ‰‰‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆˆˆˆŠ‹‹Šˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‘”•—–————————–––––––––––———————————‡ˆˆˆˆˆˆˆ‡‡‰‰‹ŒŒŒŒŒŒŒ‰p>>>=<:8978:<;==u••˜’““’’“˜˜˜˜˜˜™‘“””ŽŽŒŽŽŒŒ‹ˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆˆ‹Š‰‰‹‰‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡“•–————–—–————–––––––––————————————ˆˆˆˆˆˆˆˆˆˆŠ‹ŽŽŒŒ‹r<=<><;8:79:98;=y”“’“”“““˜˜˜™‘‘’”””“ŽŽŒŒ‹ˆ‡‡‡‡‡‡‡‡ˆˆˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‹‹‰ˆˆ‰‰‡‡‡‡‡‡‡‡‡‡‡‡˜‡‡‘”––—————–——————–––––––—————————————ˆˆˆˆˆ‰‰Š‹ŒŽŽŽŽŒs===<<;;:88989;;{“’’“•“”””˜’’’’”••••––ŽŽ‹Šˆ‡‡‡‡‡‡‡ˆˆˆˆˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‰ŠŠˆˆˆ‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡™‡‡’”•–——————————————––––•——————————————ˆˆ‰‰ŠŠ‹‹Žu;;=<>=;:<;:9;;;}Ž‘‘”•”””””‘‘’““””˜˜••–ŽŽŒŠˆˆ‡‡‡‡‡ˆˆˆˆˆ‰‰‰‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‰Šˆ‰‰‰‰‡‡‡‡‡‡‡‡‡‡‡‡™™‡™™•–———————————————————–——————————————ˆ‰Š‹‹ŒŒŽŽŽz;;;<>>==>><<;;;ŽŽ’“•••””••’“““’““”””˜˜•–––ŽŽ––ŒŒ‹‰‡‡‡‡ˆˆˆˆˆ‰‰‰‰‰‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‰ˆ‰‰‰‰‡‡‡‡‡‡‡‡‡‡‡‡‡‡™š™š—————————————————————•—————————————‰Š‹‹ŽŽz:;;>>>==>>>=<<>ŽŽ”–•••–––”“““““””””˜–—–˜–––––ŒŒˆˆ‡‡ˆˆˆˆ‰‰‰‰‰‰‰ˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‰ˆ‰‹Š‰‡‡‡‡‡‡‡‡‡‡‡‡‡š™š›™˜–——————————————————––•—––—————————‹Š‹ŒŽŽy;;>>?>>>>~ŽŽ–—––––––”””””•”””™™—˜™˜•••••ŽŒ‰‰‡ˆˆˆ‰‰‰‰‰‰‰‰ˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‰‰ˆŠ‹‹‹‡‡‡‡‡‡‡‡‡™‡‡‡‡‡››š–™˜˜———————————————––––•–——————————‹‹ŒŽx;;=;<===??>>>>=~ŽŽ“’•–—–––––””””••••••™—˜˜˜˜••••ŽŽŒ‰‰ˆˆˆ‰‰‰‰‰‰‰‰ˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆŠŒŠ‹ŒŒŠˆ‡‡‡‡‡‡‡‡‡‡‡‡‡››šš˜™–——————————–—————––•–——————————˜ŠŽŽŽŽŽŽŽŽŽŽx=<=;<<==??>>>>=~ŽŽ˜‘‘‘‘–•—––––•””••••šš˜™˜˜˜™–––––Œ‰Š‹ŠŠ‹ŠŠ‰‰‰‰‰ˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‰‰‹Œ‹ŒŒŒ‹‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡œ™œ›š™™˜˜—————–—–––—–––—–––——————————™‹ŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽx===;<;<>>=<~Ž™˜‘“—––––••””•˜™™™š˜™™––•”•”ŒŠŠŒŒ‹ŒŒŠŠ‰‰‰ˆˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‰‹Œ‹ŒŒŒŒ‹Šˆ‡ˆ‡‡‡‡‡‡‡‡‡‡›œœš™š–––––––•••••–––•––––—————————™ŒŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽy>==>;;<>>??>==<~™˜—————•”“˜˜™™™š™™™–”””““‘ŽŒŒŒ‹‹ŒŒŒŠŠ‰ˆˆˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆŠŠ‹ŒŒŒŒŒŒ‹Š‰‡‡‡‡‡‡‡‡•‡˜˜™œš™š˜•™”•••–••••••––•••––––——————˜˜™‹‹ŒŒŒŽŽŽŽŽŽŽŽŽŽŽ}>?==<>>>>???>><}›™˜–••”•–•˜•˜ššššš›˜”˜˜•””˜ŽŒ‹Š‹ŒŒŒŠ‰ˆˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ŠŠŠ‹ŽŒŒ‹‹‹ŒŠˆˆ‰‰‡‡‡ˆ‰•˜••šœ™™š˜™””•••••••••–•••••••••—————˜˜˜‰Š‹‹‹‹ŽŽŽŽŽŽŽŽŽ>=>>==>>=>>?>>=}›™––””•••–••˜š™™™™››“˜˜˜”˜™™šœ›œœ™›š™™‹ŠŠŠ‹‹Š‰ˆˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆŒ‹‹‹‹‹Ž‹‹Œ‹‹ŠŠŠ‰ˆ‡ˆˆ‰Š“”“™œ›š˜”•”””••”•””””“”””“••••••——™˜—˜™‡‡‹‹‹Š‹ŒŒŽ==>>>=>=>>>>?>>}™˜“•”•””••”•˜š™š™š›œ››šššš˜™™š™œžœš””ŽŠŠŠŠ‹Š‰ˆˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‹Œ‹‡‰‹ŒŒ‰‹Œ‹‹‹‹‰‰‰ˆˆŠ‰Š‰“˜“šœš”••”””••”“”””“““”““”•••••–—››™™šˆ‰Š‰ˆˆ‰‰Œ‹‹ŒŒŒŒŒŒŽ<<<==>?>>>>=>>?}œš’”••””””“™™šš™›œ›ššœššššš››žžžœœœš˜šœ‹ŠŠŠŠ‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆˆ‰ˆŠŠŒ‹‡Š‰Š‹ŒŒ‰‰‹ŒŒ‹‹ŠŠŠŠŠ‰‰‡‡‰’“™›˜””””””••““””“”““’““””••••––—šš™š‰Šˆ‡ˆˆ‰‰ˆŠˆˆŠŠ‰ŠŠŠ‹Ž<=<<=>?>>>==>>>{œš‘’“•••““‘˜š›››šœœ›‘™™š››œœžžŸž›œ››™œš™ŽŒ‹ŠŠŠ‰ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‰Š‹‹‹Œ‹‹ŒŠ‹‹‰‹ŒˆŠŠŒŒŒ‹Š‰‰Š‰‡ˆŠ‰‹’’šš”””””””•””“”“””““’’””””•••––——˜™›Š‡‡‡‡‡‰‡‡‡‡‡‡‡‡ˆŠŠŠ‹ŽŽ=<<<>>??==<>>>>yž™‘’’””“˜˜˜‘™››››œš™‘˜›šœœžžŸšœ™ššš›œ›Œ‹ŠŠ‰‰‡‡‡‡‡‡‡‡‡‡‡ˆ‡ˆ‰‰‰‹‹‹ŒŒ‹‹‡‹ŠŒŠ‹‰‹Š‹‹‰‹ŒŒ‰‰Š‰Šˆ‡‰ŠŒ“™›˜”””””””•”“““““”““’“””””•••––—”˜™›‡ˆ‡‡‡ˆ‡‡‡‡‡‡‡‡‡‡ˆŠŠ‹Ž;;;<=>?=====>>=xŸŸžžœ›‘‘’““‘˜™š™›œœœ›˜’‘‘““››Ÿœœœšœš™›˜™ššš™˜•ŽŒ‹‰‡‡‡‡‡‡‡‡‡‡‡ˆˆˆŠŠ‰‰‹‹ŒŽŽ‹ŒŠ†Š‹ˆŠŠˆŠˆ‰ˆŠˆŠŠ‰‰‰‡‡‡‡ŠŒ”™™˜™”””“““”””””•“’’“’’“””””••–•••’™›‡ˆ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆŠŠŒ9<:;;=<<==<<<==:xŸŸs12525578;:::=>>pw>=????>=;=<;;=:{›’w=;<=™˜}???????????>?=={ˆˆu79;;:8575564445rv>>>=>><;8::;765p‡‡‡‡‡‡‰ˆˆ“””•z876886665898763y“”’“”””–••““‘˜™™‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‰‰Š‹Œ:9;989:<;:<;:99wŸžs1213644:;::=>??nq===??<;8879:;:7u™˜v9>???????>=;:;<{’{<>????????<8::6y™–u7369<:785674544rŽŒŽs>?>>==<;9;87555rˆ‡‡‰ˆˆ‰‹“““}88867755979<663w’’““’’“”•“”’‘˜˜™š‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‰‹‹Œ:79665969:::965wžžr5353349;;<=?>??n‘n=><;7757465::<8s™˜u:<=??????;=997>>==::9856456s‡‡ˆˆ‰‰‹“˜~9787878558::;88t’’’’’“’””’•’™ššš‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‹‹Œ696355647988954wžr8837467><=>????n’n><=874344475779s‘r9;?>??=51112y˜˜v33237;=94223363rŒŒ‹ˆ‰r??====::8754579uŒ‹‰‰‰™~9:898956589;::9s‘’‘’’‘“’’‘’™šš›‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‹‹334566666657<55wœ›q9;8757:;=>?????n”‘n>=;85355534358:t’˜q8<=??????=7:786v‘w367:9:=>;765321x•”x23238;:61222243pŽ‹ŠŠŠs>>==<=:8546888:v‹‹‰‹Ž};;9:87677889:=;r‘˜™™››‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆ‹‹24499:697867758x››s>=;;>;=????????n”’n<;954356654347:s‘“o:<9;986st266768:::775465z”“w322398821122254qŒŒ‹Œ’”“q>>>>=:74339::9:z‹‹{::;:::986679::???????????n”’n:;743567653347;q’˜o????????<<>9656ss2377499;::86787z’w633367311111368q˜™ŽŒŒŒ’‘q>>>?;64526:;9;:yŽx;;==<::977778<>8889y››r???????????????n’’n98833556653248>><63335;8:999y<<>>>=87678:::u™”n?????>??>=;::61r•’q53378==???????>xy55657621237:9::t”“ŽŽŽ‘‘o>==54346<:9778<=?>>>;:985:<;:s™™™›˜‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡ˆŠŠ88898<>????<>;>>???????????n“‘n?<84433444579;>s˜”o??????><=?<;832r–”q3568;>?????????uv7555453326:<;:9t™™˜““Ž‘’n=<8576:=;7779;>??>=::;:9;=>>>>??????????n–”n><;:773323569:?r“”o?????;??==?=743s”“q67:8>????>>>??>st;56444666798998r™šœ™”ŽŽn<8899:=<888:;>??>><:9::;??uœp>>>>>???>>>????n–•n;:;;<931235589>o“–o?????;??964r––p79:>????>>>>>??s“’t;96334445752254u˜˜™™”ŽŽŒŒn;99:;><:989;>>>>>><::<=s™ˆˆ‡‡‡‡‡‡‡‡‡‡‡‰ˆœ›™›‰žž~5566:>>>=>=>>>>>??>>?<852r—–p;<>??>>>>>>>>??s‘“u<;7422345441134v˜š›™˜ŽŒ‹ŒŒŒ‹n=<;:;<>><99;==>>=>>>=====s˜™˜Šˆˆ‡‡‡‡‡ˆ‰ˆŠŒŠ™œŸšžž‹x3456:=?????????u››n?>=<=??>>>>;;;>n””n7:9:<:743366898n˜•o???=??;<>?:7775p•–p<>>?>>>>=>>>>??t“‘v=<7544264331114u˜š›š™ŽŒ‹‹‹‹Œn;;=:;::;<<;;;<<>>>>>>?===>>r™™š˜‰Š‰‰ˆ‡‡‰‰‰‰ŒŒ“šš›žžv32469=?????????s››n>>?>>>=:767n“‘p7:9<>;88754488;n••o8>?;<==<==:8975p••n>>>?==<==>>>???r’’v=;9866775121113v™›š›ŒŠ‹‹p879<:87899::::<<=>>?????>>>??sš˜™˜šˆŠŠŠ‹ŠŠŠŒŒ–™›š››œt52459;?????????rš›o>>>=<=>?>>:;664n‘o::9===968657;8=n••o7>>=<<<<==>>?>>r’’v>=<976656311111yš›šššŒŒ‹q777798567899969{<<=????????????s˜š™š››ˆŠŠ‹‹ŒŒŒ™˜˜šš˜™œu216359???????>>rššn>><=<==>??<9322n”’r;<<<;=>;;78;<:>n••n99:;<:::;;;;::;o•”n?==<=;<<==>>=>>r”“v>>;757544111112z››šŽ›šŽŒs456656645798877z;==????????????r˜›™›œ›žŒŒŒŒŒŒŽš›™—˜™˜™™›œœt33277<>>uš™q<<;<==>>?=<8545n–”r;;<=<>?<=;;:9==<<<=<<<>=;==s–”x<::676242111111yš›šŽ˜Œt775556775555557}{:=>????????????q™šš™››œžŒŒŒ–œš————˜˜˜˜››™w66788=??????>>???9;9??q•–n8779687:;=>???>n—“n>===<=<=;<<:::8u—–z=:6676121111113xš››Ž™w;99899;97665542~|;>?????????????q™œ™™™ššžŽŽ–˜™˜™——˜—™—™›š™y97:<==>????=<=;v™™s9::<<:9999;:;:;r••q<;<<<;=?????=;=r•–n:8867788<=???>?n–”n>>===?=<<;85489y•”z<:7841111111144y™ššŽŽx;;:9:<=;9788755~|>??????????????sš™›››œ‹ŒŽŽŽŽŽ˜™˜›œ—————˜›š™˜x9:=>>>>>??>>>=9w•”t9:88<<:9:::<;98t––r==;<<==?????<;?>>=>n—”n?>>>?><;;999679z•{<;7654311121258{™šššŽy==<;:;<=<;98754~’{???????????????w˜™™››š›‹ŒŽŽŽ–˜šš™˜———™˜™™——x:;=?>>>>>?>>>>><<=>>>?>>=;<===>=n—–n?????==;;9;643:z“”{:;=965431313498|™™™šz<=??>==<;;=;875’“’‘{>>?????????????x˜™š›š››‹‹Ž•—šš˜™˜————š™š™——y<<=>>>===?===>=z’“x8657876769;<:::s——t>>>=>>>?>=:<:<;;;<;n——n?????===<<:8:67z’”{===:973125568:;|ŽŽš};>>??><;;;<<:89™”““‘‘‘’’’“z=>?????????????z˜™š™›››ŒŒ•–™š™š™——––›™š™——xz|~~|}{ywvsrttrrsttrsutt—–tssuvvvwvxwutusqp••rpppnnnpnqnpppnnn——nnnnnnnqquyyzzzyy””{{{|||}~}}~~~~~}}~}}||||}}}}}šš˜˜““‘’’••••••{{xwwxwvwxxxx{{|}˜˜™›››ŒŒ‹Ž“–™šš™™š™šš›šš™–––——•™™™˜™ššš™š™˜‘“’’”““”••——–—————–––•–•–”“’‘’”’””””••••–••———––•”””““““““”””•”•“˜˜™Œ‹ŠŠ‹ŒŒŒš›žž›˜˜™œššœ˜˜””•––––––•–––•””““““‘™™š››ŽŒŒ™šš™˜šš›››šš˜–––••˜™”˜˜˜”™™šš˜‘’“““”””•——————––•”•–•““‘‘‘‘”•–––––•••———–™••••”““”““””“’ŽŒ‹Š‹‹ŒŽŽ›ž™™š™›œœ›š›š˜˜———–––––—————•““““”’˜™šš›ŽŒŠ‹ŒŒ›š›œžžš››››™˜˜”˜˜•˜™š™”’™ššš’’’“””””–—————––”––——•’‘‘‘‘’“•––•––––šš•••••”””““””‘‘ŽŒŽŽŽŽ™›œŽš˜™™™žœ››”•–—š›™——————™——————•“””“’™šš™‹‹œœœœš››››š™™˜”˜™šš›˜‘™“””•”“”————•”••••—“’‘‘‘‘’‘“•–––•–˜šš˜••••–••””‘‘Œ‹ŽŽŽ˜šš›ŽŽ‘™ššžœœ›˜——˜›š˜šš—˜˜˜™—————–”“””“šš™šŒœžœœœœœœ›œš“”˜™š››™‘˜‘“”””•”•–—–––•••••“’‘“““”“’”•––••–›œœœš––––••••ŽŽŽš™™›œŽŽšŽœœœ›™˜˜—™œ—™˜˜—˜™˜———————–•”“š›ššœ‰ŠŒ‹ŒŽŽœœœœœœœžž››““’™˜šš˜”–—•”””•—––––––––––•”••–”•”—•———––šœœœ›™™–••••••’’ŽŽŽŽ™™ŽŽŽ™™ššœŽŽŽŽ›Žššš™˜˜›š˜——————™™————————–•’‘œœžœœœ‰‰Š‹›œ›››šš›œœ›››‘’’‘˜‘’”””““•–––––•––––––•–•”–•’––—–——š™›š˜”””””––“’ŽŒ™™šŽ˜šš›œœœ›™š›™™™šš—›™———˜˜˜˜™˜—————————›œœ›œŠŠŠŒŠ›ššœš›šššš›œœžœ››š›˜‘‘‘”’••––—–––––––––––————––•––——š››œœœ›š™š˜”“””•“““ŽŽ˜›š™ššœ›œœœš™ššš™™š™š˜™——™™˜˜˜——————————–Žœœœ‹‹‹Œšš›š›šššššš›œ›™š˜‘’•––––––––––––––––———–––––––——šœ›œœ›š›š™“““‘‘ŒŽ˜›››™™›››œœ›šš››››™šš˜˜™——˜˜—˜———————————œ‹‹‹››šššœ™ššššššœœœ›™›™™˜˜™™˜˜‘•––––––•––––––––––——–––––––––™šœœœ››œ™˜’Ž™™œœ›šš›šœœ›šš››››šš™˜˜˜———˜˜˜——————————Žž›ŽŽ››™™››™™šššš›œœœœ››šš˜˜˜™™š˜˜‘”•––––––•––––––––––—•••••––™™›œœœœ›š™™˜‘ŽŽ™™›œœšššš›œœ›š›››š™˜™˜™—š™—™™™˜———————ŽŽŽŽŽž›œœœ›š›››š™››››š››œœœ›››™™™™˜™˜’”•––––––––––––––––—–••••••––š™›››œœž›™š™’‘ŒŒ™™›™šš˜˜›šœœ›››œš™™™˜————™šššš˜————————ŽŽŽŽŽžšœœ›››œšš™™™››šš›››œ››™šš˜˜š™›˜˜‘‘’”•–––––––—–––––––—••”””••••––“š››››œœžœšš›š˜ŽŒŒ‘™™™ššš™˜š›››œœ›š™™™™————˜ššš™——————————ŽŒŽŽœ››œœ›š™˜‘˜™™››œ™››™™˜˜™™›š˜‘’•–––––––——–––––—•••””””••••–™šš“›››››œœ››šš™‘ŽŒŒŽ‘’™š›››š™™››››™šš™™˜––———™š™——————————ŒŽŒ˜š™šœœœš™˜‘˜˜››œž››™˜š™œœ›‘“••––––––————————–•••”””””•••–˜˜šš™š™™šššœœ››šš‘ŽŽ‘‘‘‘‘‘˜˜››ššš››œœšš™šš•••––™˜™———————————ŽŽŽŒŽŽŒš›ššš›››™˜˜‘‘˜˜›œžžžœœš™šš™œœ™’”••–––––————————––••••”™”””••–˜™™šš›œœ›Ž™™š™ššœœœš™™™‘’ŽŒŽ‘’‘‘‘‘˜˜™ššš›š›œš›š›™”•–˜™™™˜—–––––—————Ž˜ššš™™šššš™™™›œ›œ˜˜›™œ‘’••––––—————————––•••˜˜˜˜™”˜••˜˜™››œœœ›œŽœ™™™ššš›››››™™™˜’ŽŽ‘‘’‘™™™š›š››œ›œ›™š“”–––™——–––––––————————•Žž›š™˜š™ššš™˜™™š››œœœœš˜˜‘’•––––––ŽŽ——————––•••••˜˜™™•”–˜˜šœœœœœ›œœš˜›››™šš›š››™š˜˜˜˜”ŽŽ‘‘‘‘’“‘‘‘˜™™™šššœœ›œ™™™““•–˜–˜–––––––––—————–••Ž’’‘œ›š™›™šš™™™™™šššœœœ›œ›˜‘”••–––––———————–––••••˜˜™˜™™™™™™œœœœœœ›˜™˜™šš››œ›››™™˜““•”’‘’“’“‘‘‘˜˜˜š™ššœœœ›™š™““”™––•••••––––––——Ž——•””’Ÿ’œœš™›™š™™šš™™™™™›š›œš˜‘“•••–••••–—————––˜–•˜•˜˜˜˜š›››™™›œœœžœœ™š™˜™™š››œ›š™š™““‘’”“‘‘‘‘“’’‘˜˜š™™œœœœœœ™˜™’““™˜••”””””–––––——”——””””“š››ŸŸ™ššš‘™˜™˜ššššš˜™™›š››‘‘“••”•••••–—————––˜–˜˜™™™™››œ›šš››œžžžœ››š™’˜‘˜›œš™™™‘’‘‘’‘‘‘‘‘’‘’˜˜™™›˜š™™š›š™™˜’’’˜™•”””””””––––—––•–””““‘‘šššžžžŸŸ˜‘šš™šš™š™™šš›™˜˜™ššš˜‘‘‘“•”””••••––—————––˜–˜›™˜šš›š›œœžžžŸŸŸ››œšš™˜‘›š˜˜˜‘’‘‘˜š˜™™˜š™š™˜›˜˜˜“““““””””–––——–”“’’™ššžžžŸŸ‘™š™š››šš™™™›™˜™™š›™’•“”””••••–––—————––˜šœššš›šš›œžžžžŸœœ›šœ›˜‘’‘‘’’“‘‘˜˜˜˜™™™˜šš˜˜˜‘‘““““”””•––—–•’’‘™™™šœœžžžŸŸ \ No newline at end of file diff --git a/demos/memset.c b/demos/memset.c new file mode 100644 index 0000000..64ea636 --- /dev/null +++ b/demos/memset.c @@ -0,0 +1,91 @@ +/* Set a block of memory to some byte value. + For Intel 80x86, x>=3. + Copyright (C) 1991, 1992, 1993, 1997, 1998 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#ifdef __i386__ + +#if defined(__GNUC__) + +#undef memset + +#define op_t unsigned int +#define OPSIZ 4 + + +void * +memset (void *dstpp, int c, size_t len) +{ + int d0; + unsigned long int dstp = (unsigned long int) dstpp; + + /* This explicit register allocation + improves code very much indeed. */ + register op_t x asm("ax"); + + x = (unsigned char) c; + + /* Clear the direction flag, so filling will move forward. */ + asm volatile("cld"); + + /* This threshold value is optimal. */ + if (len >= 12) + { + /* Fill X with four copies of the char we want to fill with. */ + x |= (x << 8); + x |= (x << 16); + + /* Adjust LEN for the bytes handled in the first loop. */ + len -= (-dstp) % OPSIZ; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + + /* Fill bytes until DSTP is aligned on a longword boundary. */ + asm volatile("rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp), "=c" (d0) : + "0" (dstp), "1" ((-dstp) % OPSIZ), "a" (x) : + "memory"); + + /* Fill longwords. */ + asm volatile("rep\n" + "stosl" /* %0, %2, %3 */ : + "=D" (dstp), "=c" (d0) : + "0" (dstp), "1" (len / OPSIZ), "a" (x) : + "memory"); + len %= OPSIZ; + } + + /* Write the last few bytes. */ + asm volatile("rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp), "=c" (d0) : + "0" (dstp), "1" (len), "a" (x) : + "memory"); + + return dstpp; +} + +#else /* __GNUC__ */ +#include +#endif + +#endif /* __i386__ */ diff --git a/demos/mjoytest.c b/demos/mjoytest.c new file mode 100644 index 0000000..74acd9e --- /dev/null +++ b/demos/mjoytest.c @@ -0,0 +1,291 @@ +/* Program to test the svgalib joystick functions. */ +/* Written by M. Weller */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char *optarg; +extern int optind, opterr, optopt; + +#define PENCILSIZE 5 + +struct { + int wx; /* xoffset to add to scaled joystick position to get cx */ + int cx, cy; /* onscreen coords of pencil */ + int jx, jy; /* current joystick status */ + int tx; /* onscreen xcoord of text for joypos */ + char bitmap[PENCILSIZE * PENCILSIZE * 4]; /* big enough in any screen mode */ + int ox, oy; /* location of saved patch, ox < 0 for no data saved */ + int color; /* drawing color */ + int drawing; /* we are drawing (actually shadows button 1 state) */ + int newpos; /* cx/cy changed, draw new pencil position */ +} joypanel[2]; + +int wy, sx, sy, ty; /* wy, ty y coords of wx, tx. sx/sy are scale values: + * (jx * sx + 128) / 256 is pencil coords (add wx for screen + * coords). Same for y. */ + +int newcolor(void) +{ + if (BYTESPERPIXEL == 1) + return random() % 15 + 1; + return gl_rgbcolor(random() & 255, random() & 255, random() & 255); +} + +void draw_pencil(int i) { + char msg[100]; + + if (!joypanel[i].newpos) + return; + + sprintf(msg, "x = %4d, y = %4d", joypanel[i].jx, joypanel[i].jy); + gl_write(joypanel[i].tx, ty, msg); + + if (joypanel[i].ox >= 0) + gl_putbox(joypanel[i].ox, joypanel[i].oy, PENCILSIZE, PENCILSIZE, joypanel[i].bitmap); + + /* If not drawing, save destination area */ + if (!joypanel[i].drawing) + gl_getbox(joypanel[i].ox = joypanel[i].cx, joypanel[i].oy = joypanel[i].cy, + PENCILSIZE, PENCILSIZE, joypanel[i].bitmap); + else + joypanel[i].ox = -1; + + gl_fillbox(joypanel[i].cx, joypanel[i].cy, PENCILSIZE, PENCILSIZE, joypanel[i].color); + joypanel[i].newpos = 0; +} + +void init_screen(void) { + int white; + + gl_clearscreen(0); + + white = vga_white(); + + gl_line(0, 0, WIDTH - 2, 0, white); + gl_line(0, 0, 0, HEIGHT - 1, white); + gl_line(WIDTH/2, 0, WIDTH/2, HEIGHT - 1, white); + gl_line(WIDTH - 2, 0, WIDTH - 2 , HEIGHT - 1, white); + gl_line(0, 11, WIDTH - 2, 11, white); + gl_line(0, HEIGHT - 1, WIDTH - 2, HEIGHT - 1, white); + + ty = 2; + sx = WIDTH / 2 - 3 - PENCILSIZE; + sy = HEIGHT - 6 - PENCILSIZE - 9; + wy = 2 + 8 + 3 + (((sy << 7) + 128) >> 8); + + joypanel[0].color = white; + joypanel[0].drawing = 0; + joypanel[0].newpos = 1; + joypanel[0].ox = -1; + joypanel[0].tx = 2; + joypanel[0].jx = 0; + joypanel[0].jy = 0; + joypanel[0].wx = 2 + (((sx << 7) + 128) >> 8); + joypanel[0].cx = joypanel[0].wx; + joypanel[0].cy = wy; + + draw_pencil(0); + + joypanel[1].color = white; + joypanel[1].drawing = 0; + joypanel[1].newpos = 1; + joypanel[1].ox = -1; + joypanel[1].tx = WIDTH / 2 + 2; + joypanel[1].jx = 0; + joypanel[1].jy = 0; + joypanel[1].wx = joypanel[0].wx + joypanel[1].tx; + joypanel[1].cx = joypanel[0].cx + joypanel[1].tx; + joypanel[1].cy = wy; + + draw_pencil(1); +} + +void myhandler(int event, int number, char value, int joydev) { +#if 0 + printf("%d: %d %d %d\n", joydev, event, number, (int)value); +#endif + switch(event) { + case JOY_EVENTBUTTONUP: + if (!number) + joypanel[joydev].drawing = 0; + else { + joypanel[joydev].color = newcolor(); + joypanel[joydev].newpos = 1; + } + break; + case JOY_EVENTBUTTONDOWN: + if (!number) + joypanel[joydev].drawing = 1; + break; + case JOY_EVENTAXIS: + switch(number) { + case 0: /* x */ + joypanel[joydev].jx = value; + joypanel[joydev].cx = joypanel[joydev].wx + ((((int)value) * sx + 128) / 256); + joypanel[joydev].newpos = 1; + break; + case 1: + joypanel[joydev].jy = value; + joypanel[joydev].cy = wy + ((((int)value) * sy + 128) / 256); + joypanel[joydev].newpos = 1; + break; + } + } + /* Note that any reserved events are ignored */ +} + +void usage(void) { + puts("Usage: mjoytest [-j ] [svgalib mode]\n" + "\ttest multiple joystick support and joystick sharing."); + exit(1); +} + +void mycalout(const char *msg) { + gl_printf(-1, -1, msg); +} + +int main(int argc, char *argv[]) { + int vgamode = -1; + int which, joymask = 3; + struct timeval timeout; + + while(EOF != (which = getopt(argc, argv, "j:m:"))) { + switch(which) { + case 'j': + if (!strcmp(optarg, "0")) + joymask = 1; + else if (!strcmp(optarg, "1")) + joymask = 1; + else + usage(); + break; + case 'm': + vgamode = vga_getmodenumber(optarg); + if (vgamode < 0) + usage(); + break; + default: + usage(); + } + } + if (optind < argc) { + if (optind != 1 + argc) + usage(); + if (vgamode >= 0) + usage(); + vgamode = vga_getmodenumber(argv[optind]); + if (vgamode < 0) + usage(); + } + vga_init(); + if (vgamode < 0) + vgamode = vga_getdefaultmode(); + if (vgamode < 0) + vgamode = G320x200x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(-1); + } + + puts("In the demo, press\n" + "<1> to calibrate joystick 1.\n" + "<2> to calibrate joystick 2.\n" + " to clear the screen (<1> & <2> do this too).\n" + " to exit (-C should work too.\n" + "Joystick button 1 enables drawing while pressed.\n" + "Joystick button 2 selects next color.\n" + "\nNow hit to start the demo."); + + getchar(); + fflush(stdin); + + for (which = 0; which < 2; which++) { + if (!(joymask & (1 << which))) + continue; + errno = 0; + if (joystick_init(which, JOY_CALIB_STDOUT) < 0) { + if (errno) + printf("Unable to initialize joystick %d: %s.\n", which, strerror(errno)); + else + printf("Unable to initialize joystick %d.\n", which); + } + } + + joystick_sethandler(-1, myhandler); + + vga_setmode(vgamode); + gl_setcontextvga(vgamode); + + gl_setwritemode(FONT_COMPRESSED | WRITEMODE_OVERWRITE); + gl_setfontcolors(0, vga_white()); + gl_setfont(8, 8, gl_font8x8); + + init_screen(); + + for(;;) { + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + which = vga_waitevent(VGA_KEYEVENT, NULL, NULL, NULL, &timeout); + if (which & VGA_KEYEVENT) { + switch(vga_getch()) { + case '1': + gl_printf(2, 2, ""); + if (1 & joymask) { + vga_lockvc(); + joystick_init(0, mycalout); + /* IMPORTANT, reenable ownhandler! */ + joystick_sethandler(0, myhandler); + vga_unlockvc(); + } + init_screen(); + break; + case '2': + gl_printf(2, 2, ""); + if (2 & joymask) { + vga_lockvc(); + joystick_init(1, mycalout); + /* IMPORTANT, reenable ownhandler! */ + joystick_sethandler(1, myhandler); + vga_unlockvc(); + } + init_screen(); + break; + case 'c': + case 'C': + init_screen(); + break; + case 'q': + case 'Q': + goto leave_loop; + default: + putchar('\a'); + fflush(stdout); + break; + } + } + which = joystick_update(); + if (which & 1); + draw_pencil(0); /* It makes only sense to check for the newpos flag + * if something happened with the joystick at all */ + if (which & 2); + draw_pencil(1); + } + leave_loop: + printf("Shutting down.\n"); + + vga_setmode(TEXT); + exit(0); +} + diff --git a/demos/mkcur.c b/demos/mkcur.c new file mode 100644 index 0000000..583aa8f --- /dev/null +++ b/demos/mkcur.c @@ -0,0 +1,223 @@ +/* Make cursor mkcur.c A program to build a cursor. Started Jan 27, 2001 */ +/* Don Secrest */ + +#include +#include +#include +#include +#include +#include +#include "arrow.h" + +unsigned char *fnt=0; +static int software = 0,psiz; +static unsigned int sprt[64] = {0}; + +void usage(void) +{ + puts("Usage:\n" + "buildcsr -p -b -m -s\n" + "\tDraw sprite by holding down the left mouse button.\n" + "\tDraw color 2 type 2 and use left button.\n" + "\tRight mouse button to erase pixels.\n" + "\t-p print out the sprite as a header file to be compiled\n" + "\t-b print out the sprite as a binary file to be read by a program\n" + "\t-m to use any mode. Default is vga_default mode or G640x480x256.\n" + "\t-s to use software cursor. Default is to use hardware cursor if it\n" + "\t exits." + ); + exit(2); +}; + +void setcursor(int *arrow,int cursor, int color0, int color1) +{ + static int init = 1; + + if(init) + { + init = 0; + if(cursor != 0) + vga_setcursorimage(cursor,0,color0,color1,(void *)arrow); + else + { + vga_setmousesupport(1); + vga_initcursor(software); + } + } + vga_setcursorimage(cursor,0,color0,color1,(void *) arrow); + /* if(vga_selectcursor(0) == -1) + { + vga_setmode(TEXT); + printf("Cursor select failure.\n"); + exit(1); + } */ + vga_selectcursor(cursor); + mouse_setposition(0,0); + mouse_setxrange(-5,psiz - 1); + mouse_setyrange(0,psiz - 1); + return; +}; + +int main(int argc,char **argv) +{ + int vgamode,opt,vmode=0,color1,color2,xmax,ymax,i,j,px,dx,colnum; + int colors; + char *nameb=0,*namep=0; + FILE *binfile=0,*progfile=0; + + while(EOF !=(opt = getopt(argc,argv,"p:b:m:s"))) + switch(opt){ + case 'p': + namep = optarg; + break; + case 'b': + nameb = optarg; + break; + case 'm': + vmode = atoi(optarg); + break; + case 's': + software = 1; + break; + case ':': + printf("Missingh argument.\n"); + usage(); + case '?': + printf("Unknown argument, %c\n",optopt); + usage(); + } + + vga_init(); + if(vmode) + vgamode = vmode; + else + vgamode = vga_getdefaultmode(); + if(vgamode == -1) + vgamode = G640x480x256; + if(!vga_hasmode(vgamode)){ + printf("Mode %d not available\n",vgamode); + exit(1); + } + vga_setmode(vgamode); + gl_setcontextvga(vgamode); + gl_enableclipping(); + fnt = gl_font8x8; + gl_setfont(8,8,fnt); + gl_setwritemode(FONT_COMPRESSED + WRITEMODE_OVERWRITE); + gl_setfontcolors(0,vga_white()); + colors = color1 = gl_rgbcolor(0,200,0); + color2 = gl_rgbcolor(100,0,100); + xmax = vga_getxdim(); + ymax = vga_getydim(); + colnum = vga_getcolors(); + if(colnum == 256) + vga_setcolor(vga_white()); + else + vga_setrgbcolor(255,255,255); + psiz = (xmax < ymax)?xmax:ymax; + i = (psiz -8)/32; + psiz = i*32 - 1; + j = (i*5)/6; + px = j; + dx = i; + setcursor(arrow,0,0xff0000,0x0000ff); + vga_drawline(0,0,psiz+1,0); + vga_drawline(psiz+1,0,psiz+1,psiz); + vga_drawline(psiz+1,psiz,0,psiz); + vga_drawline(0,psiz,0,0); + gl_printf(1,psiz+1,"Type n: new sprite, o: old, q: quit"); + gl_fillbox(290,psiz+1,px,px,colors); + do + { + int evt,mx,my,button,key; + + evt = vga_waitevent(VGA_MOUSEEVENT | VGA_KEYEVENT,NULL,NULL,NULL,NULL); + if(evt & VGA_KEYEVENT) + { + key = vga_getkey(); + if(key == 'q' || key == 'Q') + break; + if(key == 'n') + { + setcursor(sprt,1,0xff0000,0x0000ff); + } + if(key == 'o') + { + setcursor(arrow,0,0xff0000,0x0000ff); + } + if(key == '2') + { + colors = color2; + gl_fillbox(290,psiz+1,px,px,colors); + } + if(key == '1') + { + colors = color1; + gl_fillbox(290,psiz+1,px,px,colors); + } + } + if(evt & VGA_MOUSEEVENT) + { + int x,y,add; + unsigned int loc; + + button = 0; + mouse_update(); + mx = mouse_getx(); + my = mouse_gety(); + button = mouse_getbutton(); + vga_setcursorposition(mx,my); + vga_showcursor(1); + if(button) + { + vga_showcursor(2); + x = 1 + (mx/dx)*dx; + y = 1 + (my/dx)*dx; + gl_fillbox(x,y,px,px,colors); + add = y/dx +32; + loc = 1 << (31 - x/dx); + if(button & 4) + { + sprt[add] = sprt[add] | loc; + if(colors == color2) + sprt[add - 32] = sprt[add - 32] | loc; + } + else if(button & 1) + { + vga_showcursor(2); + x = 1 + (mx/dx)*dx; + y = 1 + (my/dx)*dx; + gl_fillbox(x,y,px,px,0); + sprt[add] = sprt[add] & (~loc); /* erase it. */ + sprt[add - 32] = sprt[add - 32] & (~loc); + } + } + } + }while(1); + vga_setmode(TEXT); + if(namep) + { + if((progfile = fopen(namep,"w"))) + { + fprintf(progfile,"unsigned int %s[64] = {\n",namep); + for(i = 0;i < 63;i++) + { + fprintf(progfile,"0x%08x, ",sprt[i]); + if((i+1)%4 == 0) + fprintf(progfile,"\n"); + } + fprintf(progfile,"0x%08x};\n",sprt[63]); + } + else + printf("Unable to open file %s.\n",namep); + } + if(nameb) + { + if((binfile = fopen(nameb,"w"))) + fwrite(sprt,4,64,binfile); + else + printf("Unable to open file %s.\n",nameb); + } + printf("psiz = %d, px = %d, dx = %d\n",psiz,px,dx); + return(0); +} diff --git a/demos/mousetest.c b/demos/mousetest.c new file mode 100644 index 0000000..cc93781 --- /dev/null +++ b/demos/mousetest.c @@ -0,0 +1,140 @@ +/* Program to test the svgalib mouse functions. */ +/* Updated to use middle button and rx axis (for wheel mice) + by Brion Vibber , 5 July 1998 */ + +#include +#include +#include +#include +#include +#include + +/* Manually open and close mouse? */ +#define MANUALLY_SETUP_MOUSE_NOT + + +static int newcolor(void) +{ + if (BYTESPERPIXEL == 1) + return random() % 15 + 1; + return gl_rgbcolor(random() & 255, random() & 255, random() & 255); +} + + +int main(void) +{ + int vgamode, color, leftpressed, middlepressed; + int x, y, rx, ox, oy, boxsize, button, wheel; + struct MouseCaps caps; + + vga_init(); + vgamode = vga_getdefaultmode(); + if (vgamode == -1) + vgamode = G320x200x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(-1); + } +#ifndef MANUALLY_SETUP_MOUSE + /* Enable automatic mouse setup at mode set. */ + vga_setmousesupport(1); +#endif + vga_setmode(vgamode); + /* Disable wrapping (default). */ + /* mouse_setwrap(MOUSE_NOWRAP); */ + gl_setcontextvga(vgamode); + gl_enableclipping(); + +#ifdef MANUALLY_SETUP_MOUSE + mouse_init("/dev/mouse", MOUSE_MICROSOFT, MOUSE_DEFAULTSAMPLERATE); + mouse_setxrange(0, WIDTH - 1); + mouse_setyrange(0, HEIGHT - 1); + mouse_setwrap(MOUSE_NOWRAP); +#endif + + /* Check the mouse capabilities */ + if(mouse_getcaps(&caps)) { + /* Failed! Old library version... Check the mouse type. */ + switch(vga_getmousetype() & MOUSE_TYPE_MASK) { + case MOUSE_INTELLIMOUSE: + case MOUSE_IMPS2: + wheel = 1; + break; + default: + wheel = 0; + } + } else { + /* If this is a wheel mouse, interpret rx as a wheel */ + wheel = ((caps.info & MOUSE_INFO_WHEEL) != 0); + } + + /* To be able to test fake mouse events... */ + if (keyboard_init()) { + printf("Could not initialize keyboard.\n"); + exit(1); + } + + /* Set the range for the wheel */ + if(wheel) + mouse_setrange_6d(0,0, 0,0, 0, 0, -180,180, 0,0, 0,0, MOUSE_RXDIM); + + color = newcolor(); + leftpressed = middlepressed = x = y = rx = ox = oy = 0; + boxsize = 5; + + for (;;) { + keyboard_update(); + gl_fillbox(x, y, boxsize, boxsize, color); + mouse_update(); + + /* The RX axis represents the wheel on an wheel mouse */ + mouse_getposition_6d(&x, &y, NULL, &rx, NULL, NULL); + + if(wheel && rx) { + /* For clarity - wipe the old location out + so we can redraw with the new box size */ + gl_fillbox(ox, oy, boxsize, boxsize, 0); + + /* Interpret wheel turns; we care only about direction, + not amount, for our purposes */ + boxsize += (rx / abs(rx)); + (boxsize < 1)?(boxsize = 1):((boxsize > 10)?(boxsize = 10):0); + + /* Zero the wheel position */ + mouse_setposition_6d(0,0,0, 0,0,0, MOUSE_RXDIM); + } + + ox = x; oy = y; + + button = mouse_getbutton(); + if (button & MOUSE_LEFTBUTTON) { + if (!leftpressed) { + color = newcolor(); + leftpressed = 1; + } + } else + leftpressed = 0; + + if (button & MOUSE_MIDDLEBUTTON) { + if (!middlepressed) { + /* Move the cursor to a random location */ + mouse_setposition_6d(random() % WIDTH, random() % HEIGHT,0, + 0,0,0, + MOUSE_2DIM); + middlepressed = 1; + } + } else + middlepressed = 0; + + if (button & MOUSE_RIGHTBUTTON) + break; + } + +#ifdef MANUALLY_SETUP_MOUSE + mouse_close(); +#endif + + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/printftest.c b/demos/printftest.c new file mode 100644 index 0000000..82031f2 --- /dev/null +++ b/demos/printftest.c @@ -0,0 +1,72 @@ +/* Program to test the svgalib keyboard functions. */ + +#include +#include +#include +#include +#include +#include +#include + +void usage(void) +{ + puts("Usage: printftest \n" + "\tread text from keyboard and display it on screen\n" + "\tat position (x, y).\n" + "\t-D for quit\n" + "\t-R for carriage return\n" + "\t for line feed\n" + "\t for tab\n" + "\t-G for bell\n" + "\t-H for backspace (non overwriting)\n" + ); + exit(2); +} + +int main(int argc, char **argv) +{ + int x, y; + char buffer[2]; + int vgamode; + int key, retval = 0; + + if (argc != 3) + usage(); + if (1 != sscanf(argv[1], "%d%c", &x, buffer)) + usage(); + if (1 != sscanf(argv[2], "%d%c", &y, buffer)) + usage(); + + vga_init(); + vgamode = vga_getdefaultmode(); + if (vgamode == -1) + vgamode = G320x200x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(1); + } + + vga_setmode(vgamode); + gl_setcontextvga(vgamode); + gl_enableclipping(); + gl_setfont(8, 8, gl_font8x8); + gl_setwritemode(FONT_COMPRESSED + WRITEMODE_OVERWRITE); + gl_setfontcolors(0, vga_white()); + + buffer[1] = 0; + for(;;) { + key = vga_getch(); + if (key == 4) + break; + if (key == 18) + key = '\r'; + buffer[0] = key; + gl_printf(x, y, "%s", buffer); + x = y = -1; + } + + vga_setmode(TEXT); + + exit(retval); +} diff --git a/demos/rwpage.pp b/demos/rwpage.pp new file mode 100644 index 0000000..1496cc9 --- /dev/null +++ b/demos/rwpage.pp @@ -0,0 +1,83 @@ +PROGRAM ScrollTest; + +Uses svgalib; + +type + VideoMemType = array[0..65535] of byte; + +var + i,mode,StartupMode : longint; + SeparateReadWriteWindows : boolean; + modeinfo : ^vga_modeinfo; + VideoMem : ^VideoMemType; + p : pointer; + + +Procedure DrawRectangle(x1,y1,x2,y2 : integer); +begin + vga_drawline(x1,y1,x2,y1); + vga_drawline(x1,y2,x2,y2); + vga_drawline(x1,y1,x1,y2); + vga_drawline(x2,y1,x2,y2); +end; {DrawRectangle} + + +Procedure Scroll; +{ copies first bank of screen to the last bank (for 1024x768x256 mode) } +var i : word; +begin + vga_setreadpage(0); + vga_setwritepage(11); + for i := 65535 downto 0 do VideoMem^[i] := VideoMem^[i]; +end; {Scroll} +(* +Procedure Scroll; Assembler; +{ copies first bank of screen to the last bank (for 1024x768x256 mode) } +var popreturn : longint; +asm + mov esi,SegA000 + mov edi,esi + mov eax,0 + push eax + call vga_setreadpage {set read bank} + pop popreturn {tidy stack} + mov eax,11 + push eax + call vga_setwritepage {set write bank} + pop popreturn {tidy stack} + mov ecx,16384 + rep movsd {copy all of bank 0 to bank 11} +end; {Scroll} +*) + +begin + mode := 12; {1024x768x256} + i := vga_init; + StartupMode := vga_getcurrentmode; + vga_setmode(mode); + gl_setcontextvga(mode); + p := vga_getgraphmem; + VideoMem := p; + modeinfo := vga_getmodeinfo(mode); + SeparateReadWriteWindows := (modeinfo^.flags and HAVE_RWPAGE <> 0); + if SeparateReadWriteWindows <> False then begin + vga_setcolor(14); + gl_fillbox(100,0,823,63,13); + + DrawRectangle(100,0,923,63); + vga_setcolor(3); + vga_drawline(0,0,1023,767); + vga_drawline(1023,0,0,767); + for i := 0 to 5000000 do vga_drawpixel(10,10); {delay} + + Scroll; {copy first 64 lines down to last 64 lines of screen} + + for i := 0 to 5000000 do vga_drawpixel(10,10); {delay} + + end; + + vga_setmode(StartupMode); + + writeln('SeparateReadWriteWindows = ',SeparateReadWriteWindows); + writeln('vgamode = ',mode); +end. diff --git a/demos/scrolltest.c b/demos/scrolltest.c new file mode 100644 index 0000000..2c57200 --- /dev/null +++ b/demos/scrolltest.c @@ -0,0 +1,308 @@ +/* + Animation/smooth scrolling demo, uses Mode X/page flipping and + linear virtual screen in system memory. + + First method copies window to page-flipped Mode X-style video memory + for scrolling. + Linear addressing, and page flipping (no shearing) and triple + buffering, but relatively slow. + + Second method uses Mode X-style hardware scrolling. + Limited logical screen size, page flipping if no scrolling, tricky and + slow animation, scrolling fast (page flipping with scrolling is very + tricky). + + Third method copies window to linear "Mode 13h" video memory. + Linear addressing, no page flipping (scrolling looks bad), speed + depends on bus (fast on a good ISA card; very fast on VLB). + Some SVGA cards can support page-flipping in linear 320x200x256. + + Adding animated objects is trivial with the virtual screen methods (1 + and 3). + */ + + +#include +#include +#include +#include +#include + + +/* Virtual screen size. */ +/* Limited to 256K by hardware scrolling method (automatically clipped). */ +/* Width must be multiple of 8. */ +#define VWIDTH 640 +#define VHEIGHT 400 + +/* Scrolling window size for system memory virtual screen demo. */ +#define WINWIDTH 320 +#define WINHEIGHT 200 + +/* Define this to use triple-buffering in first method. */ +#define TRIPLEBUFFERING + + +unsigned char *vbuf; + + +void boxes(void) +{ + int x, y; + for (x = 0; x <= VWIDTH - 8; x += 8) + for (y = 0; y <= VHEIGHT - 8; y += 8) { + int r, g, b; + /* Draw red tiles. */ + r = rand() & 255; + b = 0; + g = 0; + if ((rand() & 15) == 15) { /* Add occasional */ + r = 0; /* blue specks. */ + b = rand() & 127; + } + gl_fillbox(x, y, 7, 7, gl_rgbcolor(r, g, b)); + } +} + + +void demo1(void) +{ + int x, y; + int targetx, targety; + int pageoffset[3] = + { + 0, + 320 * 240 / 4, + 2 * 320 * 240 / 4 + }; + int writepage; + int count, startclock; + + /* Window coordinate initially at center. */ + x = VWIDTH / 2 - WINWIDTH / 2; + y = VHEIGHT / 2 - WINHEIGHT / 2; + targetx = x; + targety = y; + + /* Page flipping initialization. */ + vga_setdisplaystart(0); /* Display page 0, write to page 1. */ + writepage = 1; + + count = 0; + startclock = clock(); + + for (;;) { + /* Copy window to screen. */ + vga_copytoplanar256(vbuf + y * WIDTH + x, WIDTH, + pageoffset[writepage], 80, WINWIDTH, WINHEIGHT); + + /* Flip pages. */ + vga_setdisplaystart(pageoffset[writepage] * 4); + +#ifndef TRIPLEBUFFERING + /* Conventional double-buffering (page-flipping). */ + vga_waitretrace(); + writepage ^= 1; +#else + /* Triple buffering; no need to wait for vertical retrace. */ + writepage = (writepage + 1) % 3; +#endif + + if (x == targetx && y == targety) { + /* Create new target. */ + targetx = rand() % (VWIDTH - WINWIDTH); + targety = rand() % (VHEIGHT - WINHEIGHT); + } + /* Move towards target. */ + if (x < targetx) + x++; + if (x > targetx) + x--; + if (y < targety) + y++; + if (y > targety) + y--; + + /* Boundary checks. */ + if (x < 0) + x = 0; + if (x > VWIDTH - WINWIDTH) + x = VWIDTH - WINWIDTH; + if (y < 0) + y = 0; + if (y > VHEIGHT - WINHEIGHT) + y = VHEIGHT - WINHEIGHT; + + if (vga_getkey()) + break; + + count++; + } + + printf("Method 1: frame rate %ld\n", count * CLOCKS_PER_SEC + / (clock() - startclock)); +} + + +void demo2(void) +{ + int x, y; + int targetx, targety; + int vwidth, vheight; + int count, startclock; + + /* Make sure window fits in video memory. */ + vwidth = VWIDTH; + if (vwidth > 640) + vwidth = 640; + vheight = VHEIGHT; + if (vheight > 400) + vheight = 400; + + vga_setlogicalwidth(vwidth); + + /* Copy virtual screen to logical screen in video memory. */ + vga_copytoplanar256(vbuf, VWIDTH, 0, vwidth / 4, + vwidth, VHEIGHT); + + /* Window coordinates initially at center. */ + x = vwidth / 2 - WINWIDTH / 2; + y = vheight / 2 - WINHEIGHT / 2; + targetx = x; + targety = y; + count = 0; + startclock = clock(); + + for (;;) { + /* Set video memory window. */ + vga_setdisplaystart((y * vwidth / 4) * 4 + x); + vga_waitretrace(); + + if (x == targetx && y == targety) { + /* Create new target. */ + targetx = rand() % (vwidth - WINWIDTH); + targety = rand() % (vheight - WINHEIGHT); + } + /* Move towards target. */ + if (x < targetx) + x++; + if (x > targetx) + x--; + if (y < targety) + y++; + if (y > targety) + y--; + + /* Boundary checks. */ + if (x < 0) + x = 0; + if (x > vwidth - WINWIDTH) + x = vwidth - WINWIDTH; + if (y < 0) + y = 0; + if (y > vheight - WINHEIGHT) + y = vheight - WINHEIGHT; + + if (vga_getkey()) + break; + + count++; + } + printf("Method 2: frame rate %ld\n", count*CLOCKS_PER_SEC + /(clock() - startclock)); +} + + +void demo3(void) +{ + int x, y; + int targetx, targety; + int count, startclock; + GraphicsContext *virtualscreen; + GraphicsContext *physicalscreen; + + /* Window coordinate initially at center. */ + x = VWIDTH / 2 - WINWIDTH / 2; + y = VHEIGHT / 2 - WINHEIGHT / 2; + targetx = x; + targety = y; + + virtualscreen = gl_allocatecontext(); + gl_getcontext(virtualscreen); + gl_setcontextvga(G320x200x256); + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + gl_setcontext(virtualscreen); + + count = 0; + startclock = clock(); + + for (;;) { + vga_waitretrace(); + /* Copy window to screen. */ + gl_copyboxtocontext(x, y, WINWIDTH, WINHEIGHT, physicalscreen, + 0, 0); + + if (x == targetx && y == targety) { + /* Create new target. */ + targetx = rand() % (VWIDTH - WINWIDTH); + targety = rand() % (VHEIGHT - WINHEIGHT); + } + /* Move towards target. */ + if (x < targetx) + x++; + if (x > targetx) + x--; + if (y < targety) + y++; + if (y > targety) + y--; + + /* Boundary checks. */ + if (x < 0) + x = 0; + if (x > VWIDTH - WINWIDTH) + x = VWIDTH - WINWIDTH; + if (y < 0) + y = 0; + if (y > VHEIGHT - WINHEIGHT) + y = VHEIGHT - WINHEIGHT; + + if (vga_getkey()) + break; + + count++; + } + + printf("Method 3: frame rate %ld\n", count * CLOCKS_PER_SEC + / (clock() - startclock)); +} + + +int main(void) +{ + vga_init(); + + /* Create virtual screen. */ + vbuf = malloc(VWIDTH * VHEIGHT); + gl_setcontextvirtual(VWIDTH, VHEIGHT, 1, 8, vbuf); + + /* Set Mode X-style 320x240x256. */ + vga_setmode(G320x240x256); + gl_setrgbpalette(); + vga_clear(); + + boxes(); + + demo1(); + + demo2(); + + vga_setmode(G320x200x256); /* Set linear 320x200x256. */ + gl_setrgbpalette(); + + demo3(); + + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/sixbpp.xbm b/demos/sixbpp.xbm new file mode 100644 index 0000000..d3784ba --- /dev/null +++ b/demos/sixbpp.xbm @@ -0,0 +1,17 @@ +#define sixbpp_width 23 +#define sixbpp_height 66 +static char sixbpp_bits[] = { + 0x80,0x3f,0x00,0xf0,0xff,0x01,0xfc,0xff,0x01,0xfe,0xff,0x03,0x7e,0x02,0x03, + 0x0f,0x01,0x02,0x83,0x01,0x02,0x81,0x81,0x03,0x81,0xff,0x01,0x0d,0xff,0x01, + 0x1f,0xff,0x00,0x1e,0x3e,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0xff,0x01,0xf1,0xff,0x01,0xff,0xff,0x03, + 0xff,0x03,0x03,0xff,0x00,0x02,0x8f,0x00,0x02,0x40,0x00,0x03,0xc0,0xc0,0x03, + 0xc0,0xff,0x01,0x80,0xff,0x01,0x80,0xff,0x00,0x00,0x3e,0x40,0x00,0x00,0x40, + 0x00,0x00,0x78,0x40,0x80,0x7f,0x40,0xf8,0x7f,0xc0,0xff,0x7f,0xc0,0xff,0x47, + 0xc0,0xff,0x41,0xc0,0x07,0x03,0x80,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x03, + 0xc0,0xc0,0x03,0xc0,0xff,0x01,0x80,0xff,0x01,0x80,0xff,0x00,0x00,0x3e,0x40, + 0x00,0x00,0x40,0x00,0x00,0x78,0x40,0x80,0x7f,0x40,0xf8,0x7f,0xc0,0xff,0x7f, + 0xc0,0xff,0x47,0xc0,0xff,0x41,0xc0,0x07,0x03,0x80,0x00,0x02,0x40,0x00,0x02, + 0x40,0x00,0x03,0xc0,0xc0,0x03,0xc0,0xff,0x01,0x80,0xff,0x01,0x80,0xff,0x00, + 0x00,0x3e,0x00}; diff --git a/demos/speedtest.c b/demos/speedtest.c new file mode 100644 index 0000000..52e888f --- /dev/null +++ b/demos/speedtest.c @@ -0,0 +1,312 @@ + +#include +#include +#include +#include +#include +#include +#include + + +/* #define LINEAR_ADDRESSING */ + + +int VGAMODE, USEGL; +GraphicsContext *physicalscreen; +GraphicsContext *backscreen; + + +void screen1(void) +{ + int x, y; + for (y = 0; y < HEIGHT; y++) + for (x = 0; x < WIDTH; x++) + /* limited RGB palette in 256-color modes */ + /* some color information is not used in */ + /* 15-bit color modes */ + gl_setpixelrgb(x, y, + x * 256 / WIDTH, + 255 - x * 256 / WIDTH, + y * 256 / HEIGHT); +} + + +void configure(void) +{ + int allowed[GLASTMODE + 1]; + + for (;;) { + int i; + int m; + for (i = G320x200x16; i <= GLASTMODE; i++) { + allowed[i] = 0; + if (vga_hasmode(i)) { + printf("%2d %s\n", i, vga_getmodename(i)); + allowed[i] = 1; + } + } + + printf("\nWhich mode? "); + scanf("%d", &m); + getchar(); + printf("\n"); + if (m >= G320x200x16 && m <= GLASTMODE) { + VGAMODE = m; + if (vga_getmodeinfo(m)->bytesperpixel >= 1) + USEGL = 1; + else + USEGL = 0; + break; + } + } + + vga_setmode(VGAMODE); +#ifdef LINEAR_ADDRESSING + vga_setlinearaddressing(); +#endif + if (USEGL) { + gl_setcontextvga(VGAMODE); + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + } +} + + +void blit(void) +{ + gl_clearscreen(0x86); + vga_imageblt(vga_getgraphmem(), 0, WIDTH - 128, HEIGHT - 128, + WIDTH * BYTESPERPIXEL); +/* vga_bitblt(0, 100 * WIDTH * BYTESPERPIXEL, 50, 50, WIDTH * BYTESPERPIXEL); + vga_fillblt(100 * BYTESPERPIXEL, 50, 50, WIDTH * BYTESPERPIXEL, 0x86); + */ +} + + +#if 0 + +/* May help on well-designed motherboards. */ + +/* IT DOES MAKE A DIFFERENCE! REP STOSL IS SLOWER */ +/* (CL-GD5434 VLB zero-wait writes -- 2/3 cycles); rep stos takes 4 */ + +#if 1 + +static inline void * + __memset(void *s, char c, size_t count) +{ + __asm__( + "cld\n\t" + "cmpl $12,%%edx\n\t" + "jl 1f\n\t" /* if (count >= 12) */ + + "movzbl %%al,%%ax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $8,%%ecx\n\t" /* c |= c << 8 */ + "orl %%ecx,%%eax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $16,%%ecx\n\t" /* c |= c << 16 */ + "orl %%ecx,%%eax\n\t" + + "movl %%edx,%%ecx\n\t" + "negl %%ecx\n\t" + "andl $3,%%ecx\n\t" /* (-s % 4) */ + "subl %%ecx,%%edx\n\t" /* count -= (-s % 4) */ + "rep ; stosb\n\t" /* align to longword boundary */ + + "movl %%edx,%%ecx\n\t" + "shrl $2,%%ecx\n\t" + + "cmpl $32,%%ecx\n\t" /* do loop unrolling for */ + "jl 2f\n\t" /* chunks of 128 bytes */ + "jmp 3f\n\t" + ".align 4,0x90\n\t" + + "3:\n\t" + "movl %%eax,(%%edi)\n\t" + "movl %%eax,4(%%edi)\n\t" + "movl %%eax,8(%%edi)\n\t" + "movl %%eax,12(%%edi)\n\t" + "movl %%eax,16(%%edi)\n\t" + "movl %%eax,20(%%edi)\n\t" + "movl %%eax,24(%%edi)\n\t" + "movl %%eax,28(%%edi)\n\t" + "movl %%eax,32(%%edi)\n\t" + "movl %%eax,36(%%edi)\n\t" + "movl %%eax,40(%%edi)\n\t" + "movl %%eax,44(%%edi)\n\t" + "movl %%eax,48(%%edi)\n\t" + "movl %%eax,52(%%edi)\n\t" + "movl %%eax,56(%%edi)\n\t" + "movl %%eax,60(%%edi)\n\t" + "movl %%eax,64(%%edi)\n\t" + "movl %%eax,68(%%edi)\n\t" + "movl %%eax,72(%%edi)\n\t" + "movl %%eax,76(%%edi)\n\t" + "movl %%eax,80(%%edi)\n\t" + "movl %%eax,84(%%edi)\n\t" + "movl %%eax,88(%%edi)\n\t" + "movl %%eax,92(%%edi)\n\t" + "movl %%eax,96(%%edi)\n\t" + "movl %%eax,100(%%edi)\n\t" + "movl %%eax,104(%%edi)\n\t" + "movl %%eax,108(%%edi)\n\t" + "subl $32,%%ecx\n\t" + "movl %%eax,112(%%edi)\n\t" + "movl %%eax,116(%%edi)\n\t" + "movl %%eax,120(%%edi)\n\t" + "movl %%eax,124(%%edi)\n\t" + "addl $128,%%edi\n\t" + "cmpl $32,%%ecx\n\t" + "jge 3b\n\t" + + "2:\n\t" + "rep ; stosl\n\t" /* fill remaining longwords */ + + "andl $3,%%edx\n" /* fill last few bytes */ + "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ + "rep ; stosb\n\t" + : : "a"(c), "D"(s), "d"(count) + : "ax", "cx", "dx", "di"); + return s; +} + +#else /* 8-bit writes. */ + +static inline void * + __memset(void *s, char c, size_t count) +{ + __asm__( + "cld\n\t" + "cmpl $12,%%edx\n\t" + "jl 1f\n\t" /* if (count >= 12) */ + + "movzbl %%al,%%ax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $8,%%ecx\n\t" /* c |= c << 8 */ + "orl %%ecx,%%eax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $16,%%ecx\n\t" /* c |= c << 16 */ + "orl %%ecx,%%eax\n\t" + + "movl %%edx,%%ecx\n\t" + "negl %%ecx\n\t" + "andl $3,%%ecx\n\t" /* (-s % 4) */ + "subl %%ecx,%%edx\n\t" /* count -= (-s % 4) */ + "rep ; stosb\n\t" /* align to longword boundary */ + + "movl %%edx,%%ecx\n\t" + "shrl $2,%%ecx\n\t" + + "cmpl $32,%%ecx\n\t" /* do loop unrolling for */ + "jl 2f\n\t" /* chunks of 128 bytes */ + "jmp 3f\n\t" + ".align 4,0x90\n\t" + + "3:\n\t" + "movb %%al,(%%edi)\n\t" + "movb %%al,1(%%edi)\n\t" + "movb %%al,2(%%edi)\n\t" + "movl %%al,3(%%edi)\n\t" + "movl %%al,4(%%edi)\n\t" + "movl %%al,5(%%edi)\n\t" + "movl %%al,6(%%edi)\n\t" + "movl %%al,7(%%edi)\n\t" + "movl %%al,8(%%edi)\n\t" + "movl %%al,9(%%edi)\n\t" + "movl %%al,10(%%edi)\n\t" + "movl %%al,11(%%edi)\n\t" + "movl %%al,12(%%edi)\n\t" + "movl %%al,13(%%edi)\n\t" + "movl %%al,14(%%edi)\n\t" + "movl %%al,15(%%edi)\n\t" + "movl %%al,16(%%edi)\n\t" + "movl %%al,17(%%edi)\n\t" + "movl %%al,18(%%edi)\n\t" + "movl %%al,19(%%edi)\n\t" + "movl %%al,20(%%edi)\n\t" + "movl %%al,21(%%edi)\n\t" + "movl %%al,22(%%edi)\n\t" + "movl %%al,23(%%edi)\n\t" + "movl %%al,24(%%edi)\n\t" + "movl %%al,25(%%edi)\n\t" + "movl %%al,26(%%edi)\n\t" + "movl %%al,27(%%edi)\n\t" + "movl %%al,28(%%edi)\n\t" + "subl $8,%%ecx\n\t" + "movl %%al,29(%%edi)\n\t" + "movl %%al,30(%%edi)\n\t" + "movl %%al,31(%%edi)\n\t" + "addl $32,%%edi\n\t" + "cmpl $8,%%ecx\n\t" + "jge 3b\n\t" + + "2:\n\t" + "rep ; stosl\n\t" /* fill remaining longwords */ + + "andl $3,%%edx\n" /* fill last few bytes */ + "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ + "rep ; stosb\n\t" + : : "a"(c), "D"(s), "d"(count) + : "ax", "cx", "dx", "di"); + return s; +} + +#endif + +#define memset __memset + +#endif + + +void speed(void) +{ + int i; + int start_clock; + int finish_clock; + int diff_clock; + unsigned char *vgabase = vga_getgraphmem(); + +#ifndef LINEAR_ADDRESSING + if (VGAMODE >= G640x480x256) + vga_setpage(0); +#endif + + start_clock = clock(); + + for (i = 0; i < 5000; i++) { + memset(vgabase, i & 255, 65536); + } + + finish_clock = clock(); + + diff_clock = (finish_clock - start_clock)*10/CLOCKS_PER_SEC; + printf("Timing: %3d.%1ds, %dK/s\n", diff_clock / 10, + (diff_clock % 10) , 64*5000*10 / diff_clock); +} + + +int main(void) +{ + vga_init(); + + printf("This is a video memory speed tester. Note that the first " + "screen doesn't test\nanything (nor does the 3 second pause " + "that follows).\n\n"); + + configure(); + + if (COLORS == 256) + gl_setrgbpalette(); /* set RGB palette */ + + if (USEGL) + screen1(); + sleep(2); + +/* vga_screenoff(); */ + + speed(); + + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/spin.c b/demos/spin.c new file mode 100644 index 0000000..b5b894f --- /dev/null +++ b/demos/spin.c @@ -0,0 +1,391 @@ +/* + spin.c - A simple (or not quite so) app to test the SpaceOrb by rotating + a shape of a given number of sides. + + Copyright (C) 1997 Eric Sharkey, Jason Lyons, Brett Viren + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + ---- end copyleft notice ---- + + This program is FREE!!! However, if you feel that nothing is free and you + refuse to use something someone else made unless paid for, you can send a + donation to me (Jason Lyons). For information on this, E-MAIL me at + jason_l@hotmail.com. + + This graphical test program was originally written by Jason Lyons and + later hacked to bits by Eric Sharkey, but this program would not be + possible without Brett's efforts. Be sure to thank him! + + The original code for the SpaceOrb in Unix/Linux was written by Brett Viren + (Brett.Viren@sunysb.edu) on his free time (ie, not when on the pay + clock of SUNY@Stony Brook). Do with it what you will, as long as + you abide by the GPL. + + I think by now all of Brett's code has been removed from this demo + and incorporated into svgalib itself, but he's still responsible for + starting this whole thing. + +*/ +#include +#include +#include +#include +#include +#include +#include +#include "spintables.h" + +#define DONT_MANUALLY_SETUP_MOUSE +#define NODEBUG + +#define GMODE 5 +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 200 +#define SCREEN_DEPTH 100 + +#ifndef ROTATION_ONLY +/* Note: 6-D protocol assumes x is left/right, y is in/out, and z is up/down, */ +/* which is logical for a three d environment, but for this demo all plotting */ +/* is done with x/y only, so we remap y onto z and vice versa here by */ +/* defining y as coordinate 2 and z as coordinate 1 */ +#define SCR_XCTR t[0] +#define SCR_YCTR t[2] +#define SCR_ZCTR (((float) t[1])/((float) SCREEN_DEPTH)) +#else +#define SCR_XCTR (SCREEN_WIDTH/2) +#define SCR_YCTR (SCREEN_HEIGHT/2) +#define SCR_ZCTR 1 +#endif + +#define SCREEN_SIZE (SCREEN_WIDTH*SCREEN_HEIGHT) + +#define LAYERS 6 +#define MAX_NUM_SIDES 20 +#define MAX_NUM_POINTS MAX_NUM_SIDES*LAYERS + +#define HORIZONTAL 0 + +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef unsigned int DWORD; + +typedef struct { + float x, y, z; +} POINT3D; + +int CurrentColor=12; +int Depth[LAYERS] = { -45, -35, -10, +10, +35, +45 }; +int Radius[LAYERS] = { 5, 50, 75, 75, 50, 5 }; + +int InitGraph(int mode); +void InitPoints(POINT3D *Points, int sides); +void SetColor(char c); +char GetColor(void); +void SetPixel(int x, int y, char c); +void line(int x1, int y1, int x2, int y2); +void Update(void); +void Clear(void); + +void RotateX(POINT3D *dest, POINT3D src, int a); +void RotateY(POINT3D *dest, POINT3D src, int a); +void RotateZ(POINT3D *dest, POINT3D src, int a); + +GraphicsContext *screen; +char *buf; + +int main(void) +{ + int scale=100, a, b, c; + POINT3D *Points; + + int sides; + int NUM_POINTS; + + int t[3], r[3], oldbutton=0, button=0; + +#ifdef MANUALLY_SETUP_MOUSE + char orbdev[1024] = "/dev/ttyS0"; +#endif + + printf("\n\n Welcome to SPIN\n\n"); + printf(" Spin is a graphical rotation program for Linux which uses the SVGA library.\n"); + printf("It's purpose is to demonstrate the new six dimensional mouse driver support.\n"); + printf("So far this driver only supports the Spaceball series of controllers including\n"); + printf("the Spaceball Avenger and SpaceOrb 360. Spin may be used with any mouse type\n"); + printf("but two dimensional mice will only be able to move the image in two dimensions.\n\n"); + printf("Spin was originally written by Jason Lyons, based on the SpaceOrb readout code\n"); + printf("developed by Brett Viren and others. Eric Sharkey incorporated Brett's code\n"); + printf("into svgalib and adapted spin accordingly.\n\n"); + printf("Button Functions:\n"); + printf(" A - Decrease Sensitivity (Right Mouse Button)\n"); + printf(" B - Change color (Middle Mouse Button)\n"); + printf(" C - Increase Sensitivity (Left Mouse Button)\n"); + printf(" D - Increase Number of Sides\n"); + printf(" E - Decrease Number of Sides\n"); + printf(" F - Quit (CTRL-C)\n"); + printf(" Reset button toggles orientation (default is vertical) \n\n"); + printf("Warning: Default sensitivity optimized for spaceball.\n"); + printf("Most mice will need to increase this setting.\n"); + printf("\nHow many sides to start with (MAX %d) ? ",MAX_NUM_SIDES); + scanf("%d", &c); + + if(c == 0) exit(1); + else if(c < 0) printf("\nCannot draw a negative number of sides.\n"), exit(1); + else if(c > MAX_NUM_SIDES) printf("\nCannot draw with more sides than %d.\n",MAX_NUM_SIDES), exit(1); + + sides = c; + NUM_POINTS = sides*LAYERS; + + Points = (POINT3D *)calloc(MAX_NUM_POINTS, sizeof(POINT3D)); + +InitPoints(Points,sides); + +printf("Initializing mouse\n"); + +#ifdef MANUALLY_SETUP_MOUSE +if (mouse_init(orbdev,MOUSE_SPACEBALL,MOUSE_DEFAULTSAMPLERATE)) { + printf("mouse_init failed"); + return -1; +} else { + printf("mouse_init successful\n"); +} +#else + vga_setmousesupport(1); +#endif + + if(!InitGraph(GMODE)) return 0; + +mouse_setscale(scale); +mouse_setrange_6d(0,SCREEN_WIDTH,1,SCREEN_DEPTH,0,SCREEN_HEIGHT,-2,2,-2,2,-2,2,63); +mouse_setwrap(MOUSE_ROT_INFINITESIMAL); +mouse_setposition_6d(SCREEN_WIDTH/2,SCREEN_DEPTH/2,SCREEN_HEIGHT/2,0,0,0,63); + + while(1) + { + mouse_update(); + mouse_getposition_6d(&t[0],&t[1],&t[2],&r[0],&r[1],&r[2]); +#ifdef DEBUG + printf("%d %d %d\n",t[0],t[1],t[2]); +#endif + oldbutton = button; + button = mouse_getbutton(); + if ((button & MOUSE_RIGHTBUTTON)&&!(oldbutton & MOUSE_RIGHTBUTTON)) { + scale += 5; + mouse_setscale(scale); + } + if ((button & MOUSE_LEFTBUTTON)&&!(oldbutton & MOUSE_LEFTBUTTON)) { + if (scale==1) { + printf("\007"); + fflush(stdout); + } else { + if (scale>6) + scale -=5; + else + scale--; + mouse_setscale(scale); + } + } + if ((button & MOUSE_MIDDLEBUTTON)&&!(oldbutton & MOUSE_MIDDLEBUTTON)) + CurrentColor = random() % 15 + 1; + if ((button & MOUSE_FOURTHBUTTON)&&!(oldbutton & MOUSE_FOURTHBUTTON)) { + if (sides>1) { + sides--; + NUM_POINTS = sides*LAYERS; + InitPoints(Points,sides); + } else { + printf("\007"); + fflush(stdout); + } + } + if ((button & MOUSE_FIFTHBUTTON)&&!(oldbutton & MOUSE_FIFTHBUTTON)) { + if (sides= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT) + buf[y*SCREEN_WIDTH+x] = c; +} +void Clear() { memset((char *)buf, 0, SCREEN_SIZE); } +void Update() +{ + memcpy((char *)screen->vbuf, (char *)buf, SCREEN_SIZE); +} + +void InitPoints(POINT3D *Points, int sides) +{ + int a, b, c; + + for(a = 0; a < LAYERS; a++) + { + for(b = 0; b < sides; b++) + { + c=(b*360)/sides; + Points[a*sides+b].x = cosine[c] * Radius[a]; + Points[a*sides+b].y = sine[c] * Radius[a]; + Points[a*sides+b].z = Depth[a]; + } + } +} + +int InitGraph(int mode) +{ + buf = (char *)malloc(SCREEN_SIZE); + if(!buf) return 0; + + if(!vga_hasmode(mode)) return 0; + vga_setmode(mode); + + gl_setcontextvga(mode); + screen = gl_allocatecontext(); + gl_getcontext(screen); + gl_setcontextvgavirtual(mode); + gl_setcontext(screen); + + return 1; +} +void RotateX(POINT3D *dest, POINT3D src, int a) +{ + while (a<0) a+=360; + dest->x = src.x; + dest->y = src.y * cosine[a] + src.z * sine[a]; + dest->z = -1 * src.y * sine[a] + src.z * cosine[a]; +} +void RotateY(POINT3D *dest, POINT3D src, int a) +{ + while (a<0) a+=360; + dest->x = -1 * src.z * sine[a] + src.x * cosine[a]; + dest->y = src.y; + dest->z = src.z * cosine[a] + src.x * sine[a]; +} +void RotateZ(POINT3D *dest, POINT3D src, int a) +{ + while (a<0) a+=360; + dest->x = src.x * cosine[a] + src.y * sine[a]; + dest->y = -1 * src.x * sine[a] + src.y * cosine[a]; + dest->z = src.z; +} +void line(int x1, int y1, int x2, int y2) +{ + int dx, dy; + int sx, sy; + int ax, ay; + int x, y, c=CurrentColor; + + dx = x2 - x1; + dy = y2 - y1; + ax = abs(dx) << 1; + ay = abs(dy) << 1; + sx = (dx >= 0) ? 1 : -1; + sy = (dy >= 0) ? 1 : -1; + x = x1; + y = y1; + + if (ax > ay) + { + int d = ay - (ax >> 1); + while (x != x2) + { + SetPixel(x, y, c); + if (d > 0 || (d == 0 && sx == 1)) + { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } + else + { + int sy = (dy >= 0) ? 1 : -1; + int d = ax - (ay >> 1); + while (y != y2) + { + SetPixel(x, y, c); + if (d > 0 || (d == 0 && sy == 1)) + { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } + SetPixel(x, y, c); +} diff --git a/demos/spintables.h b/demos/spintables.h new file mode 100644 index 0000000..5a3e59b --- /dev/null +++ b/demos/spintables.h @@ -0,0 +1,724 @@ +float sine[360] = { +0.000000, +0.017449, +0.034893, +0.052326, +0.069743, +0.087139, +0.104509, +0.121846, +0.139147, +0.156405, +0.173616, +0.190773, +0.207873, +0.224909, +0.241877, +0.258771, +0.275587, +0.292318, +0.308961, +0.325509, +0.341958, +0.358303, +0.374539, +0.390661, +0.406664, +0.422544, +0.438294, +0.453911, +0.469390, +0.484726, +0.499914, +0.514951, +0.529830, +0.544548, +0.559100, +0.573482, +0.587689, +0.601718, +0.615563, +0.629221, +0.642687, +0.655957, +0.669028, +0.681895, +0.694554, +0.707002, +0.719235, +0.731248, +0.743039, +0.754604, +0.765939, +0.777040, +0.787905, +0.798530, +0.808912, +0.819048, +0.828934, +0.838568, +0.847947, +0.857067, +0.865927, +0.874522, +0.882852, +0.890912, +0.898702, +0.906217, +0.913457, +0.920419, +0.927100, +0.933499, +0.939614, +0.945442, +0.950983, +0.956234, +0.961195, +0.965862, +0.970235, +0.974313, +0.978094, +0.981578, +0.984762, +0.987647, +0.990230, +0.992513, +0.994493, +0.996170, +0.997544, +0.998614, +0.999381, +0.999843, +1.000000, +0.999853, +0.999401, +0.998645, +0.997586, +0.996222, +0.994555, +0.992585, +0.990313, +0.987739, +0.984865, +0.981691, +0.978217, +0.974446, +0.970379, +0.966015, +0.961358, +0.956408, +0.951166, +0.945635, +0.939816, +0.933711, +0.927322, +0.920650, +0.913698, +0.906468, +0.898961, +0.891181, +0.883130, +0.874810, +0.866223, +0.857372, +0.848261, +0.838891, +0.829266, +0.819388, +0.809261, +0.798887, +0.788270, +0.777413, +0.766320, +0.754992, +0.743436, +0.731652, +0.719646, +0.707421, +0.694980, +0.682328, +0.669468, +0.656404, +0.643141, +0.629681, +0.616030, +0.602191, +0.588169, +0.573967, +0.559591, +0.545045, +0.530332, +0.515459, +0.500428, +0.485244, +0.469913, +0.454439, +0.438827, +0.423081, +0.407206, +0.391207, +0.375089, +0.358857, +0.342515, +0.326069, +0.309524, +0.292885, +0.276156, +0.259344, +0.242452, +0.225487, +0.208453, +0.191355, +0.174199, +0.156991, +0.139734, +0.122435, +0.105098, +0.087730, +0.070335, +0.052918, +0.035485, +0.018042, +0.000593, +-0.016857, +-0.034301, +-0.051734, +-0.069152, +-0.086549, +-0.103919, +-0.121258, +-0.138560, +-0.155820, +-0.173032, +-0.190192, +-0.207293, +-0.224332, +-0.241302, +-0.258199, +-0.275017, +-0.291751, +-0.308397, +-0.324949, +-0.341401, +-0.357750, +-0.373990, +-0.390116, +-0.406123, +-0.422006, +-0.437761, +-0.453383, +-0.468867, +-0.484208, +-0.499401, +-0.514442, +-0.529327, +-0.544051, +-0.558609, +-0.572996, +-0.587210, +-0.601244, +-0.615096, +-0.628760, +-0.642233, +-0.655510, +-0.668587, +-0.681461, +-0.694128, +-0.706583, +-0.718823, +-0.730844, +-0.742642, +-0.754215, +-0.765557, +-0.776667, +-0.787540, +-0.798174, +-0.808564, +-0.818708, +-0.828603, +-0.838245, +-0.847633, +-0.856762, +-0.865630, +-0.874235, +-0.882573, +-0.890643, +-0.898442, +-0.905967, +-0.913216, +-0.920187, +-0.926878, +-0.933286, +-0.939411, +-0.945249, +-0.950800, +-0.956061, +-0.961031, +-0.965708, +-0.970091, +-0.974179, +-0.977971, +-0.981464, +-0.984659, +-0.987554, +-0.990148, +-0.992440, +-0.994431, +-0.996118, +-0.997503, +-0.998583, +-0.999360, +-0.999832, +-1.000000, +-0.999863, +-0.999422, +-0.998676, +-0.997627, +-0.996273, +-0.994616, +-0.992657, +-0.990395, +-0.987832, +-0.984967, +-0.981803, +-0.978340, +-0.974579, +-0.970522, +-0.966168, +-0.961521, +-0.956581, +-0.951349, +-0.945828, +-0.940019, +-0.933923, +-0.927544, +-0.920881, +-0.913939, +-0.906718, +-0.899221, +-0.891450, +-0.883408, +-0.875097, +-0.866519, +-0.857677, +-0.848575, +-0.839213, +-0.829597, +-0.819728, +-0.809609, +-0.799243, +-0.788635, +-0.777786, +-0.766700, +-0.755381, +-0.743832, +-0.732056, +-0.720058, +-0.707840, +-0.695406, +-0.682761, +-0.669908, +-0.656851, +-0.643594, +-0.630141, +-0.616497, +-0.602664, +-0.588648, +-0.574453, +-0.560082, +-0.545542, +-0.530835, +-0.515966, +-0.500941, +-0.485763, +-0.470436, +-0.454967, +-0.439359, +-0.423618, +-0.407747, +-0.391752, +-0.375638, +-0.359410, +-0.343072, +-0.326630, +-0.310088, +-0.293452, +-0.276726, +-0.259916, +-0.243027, +-0.226064, +-0.209032, +-0.191937, +-0.174783, +-0.157576, +-0.140321, +-0.123023, +-0.105688, +-0.088320, +-0.070926, +-0.053510, +-0.036077, +-0.018634, +}; +float cosine[360] = { +1.000000, +0.999848, +0.999391, +0.998630, +0.997565, +0.996196, +0.994524, +0.992549, +0.990272, +0.987693, +0.984813, +0.981634, +0.978156, +0.974380, +0.970307, +0.965939, +0.961276, +0.956321, +0.951075, +0.945539, +0.939715, +0.933605, +0.927211, +0.920534, +0.913578, +0.906343, +0.898832, +0.891047, +0.882991, +0.874666, +0.866075, +0.857220, +0.848104, +0.838730, +0.829100, +0.819218, +0.809087, +0.798709, +0.788088, +0.777227, +0.766129, +0.754798, +0.743237, +0.731450, +0.719440, +0.707212, +0.694767, +0.682112, +0.669248, +0.656181, +0.642914, +0.629451, +0.615796, +0.601954, +0.587929, +0.573725, +0.559346, +0.544796, +0.530081, +0.515205, +0.500171, +0.484985, +0.469652, +0.454175, +0.438561, +0.422812, +0.406935, +0.390934, +0.374814, +0.358580, +0.342237, +0.325789, +0.309242, +0.292602, +0.275872, +0.259058, +0.242165, +0.225198, +0.208163, +0.191064, +0.173908, +0.156698, +0.139440, +0.122141, +0.104804, +0.087435, +0.070039, +0.052622, +0.035189, +0.017745, +0.000296, +-0.017153, +-0.034597, +-0.052030, +-0.069448, +-0.086844, +-0.104214, +-0.121552, +-0.138854, +-0.156113, +-0.173324, +-0.190483, +-0.207583, +-0.224621, +-0.241590, +-0.258485, +-0.275302, +-0.292035, +-0.308679, +-0.325229, +-0.341680, +-0.358027, +-0.374265, +-0.390389, +-0.406394, +-0.422275, +-0.438028, +-0.453647, +-0.469128, +-0.484467, +-0.499658, +-0.514697, +-0.529579, +-0.544299, +-0.558854, +-0.573239, +-0.587450, +-0.601481, +-0.615329, +-0.628990, +-0.642460, +-0.655733, +-0.668808, +-0.681678, +-0.694341, +-0.706792, +-0.719029, +-0.731046, +-0.742841, +-0.754409, +-0.765748, +-0.776854, +-0.787723, +-0.798352, +-0.808738, +-0.818878, +-0.828769, +-0.838407, +-0.847790, +-0.856915, +-0.865778, +-0.874379, +-0.882713, +-0.890778, +-0.898572, +-0.906092, +-0.913336, +-0.920303, +-0.926989, +-0.933393, +-0.939512, +-0.945346, +-0.950892, +-0.956148, +-0.961113, +-0.965785, +-0.970163, +-0.974246, +-0.978032, +-0.981521, +-0.984710, +-0.987600, +-0.990189, +-0.992477, +-0.994462, +-0.996144, +-0.997523, +-0.998599, +-0.999370, +-0.999837, +-1.000000, +-0.999858, +-0.999412, +-0.998661, +-0.997606, +-0.996248, +-0.994586, +-0.992621, +-0.990354, +-0.987786, +-0.984916, +-0.981747, +-0.978279, +-0.974513, +-0.970450, +-0.966092, +-0.961439, +-0.956494, +-0.951258, +-0.945732, +-0.939918, +-0.933817, +-0.927433, +-0.920766, +-0.913818, +-0.906593, +-0.899091, +-0.891316, +-0.883269, +-0.874953, +-0.866371, +-0.857525, +-0.848418, +-0.839052, +-0.829431, +-0.819558, +-0.809435, +-0.799065, +-0.788452, +-0.777600, +-0.766510, +-0.755187, +-0.743634, +-0.731854, +-0.719852, +-0.707630, +-0.695193, +-0.682545, +-0.669688, +-0.656628, +-0.643368, +-0.629911, +-0.616263, +-0.602428, +-0.588408, +-0.574210, +-0.559837, +-0.545293, +-0.530584, +-0.515712, +-0.500684, +-0.485503, +-0.470175, +-0.454703, +-0.439093, +-0.423349, +-0.407476, +-0.391480, +-0.375364, +-0.359133, +-0.342794, +-0.326349, +-0.309806, +-0.293168, +-0.276441, +-0.259630, +-0.242740, +-0.225775, +-0.208743, +-0.191646, +-0.174491, +-0.157283, +-0.140027, +-0.122729, +-0.105393, +-0.088025, +-0.070630, +-0.053214, +-0.035781, +-0.018338, +-0.000889, +0.016560, +0.034004, +0.051438, +0.068856, +0.086254, +0.103625, +0.120964, +0.138267, +0.155527, +0.172740, +0.189901, +0.207003, +0.224043, +0.241014, +0.257913, +0.274732, +0.291468, +0.308115, +0.324668, +0.341123, +0.357473, +0.373715, +0.389843, +0.405852, +0.421738, +0.437495, +0.453119, +0.468605, +0.483948, +0.499144, +0.514188, +0.529076, +0.543802, +0.558363, +0.572754, +0.586970, +0.601007, +0.614862, +0.628529, +0.642005, +0.655286, +0.668367, +0.681244, +0.693914, +0.706373, +0.718617, +0.730641, +0.742444, +0.754020, +0.765367, +0.776480, +0.787358, +0.797995, +0.808389, +0.818538, +0.828437, +0.838084, +0.847475, +0.856609, +0.865482, +0.874091, +0.882434, +0.890508, +0.898311, +0.905841, +0.913095, +0.920071, +0.926766, +0.933180, +0.939309, +0.945152, +0.950708, +0.955974, +0.960949, +0.965631, +0.970020, +0.974112, +0.977909, +0.981407, +0.984607, +0.987507, +0.990106, +0.992404, +0.994399, +0.996092, +0.997482, +0.998567, +0.999349, +0.999826, +}; diff --git a/demos/svidtune.c b/demos/svidtune.c new file mode 100644 index 0000000..1d59c24 --- /dev/null +++ b/demos/svidtune.c @@ -0,0 +1,180 @@ +/* Program to test the svgalib keyboard functions. */ + +#include +#include +#include +#include +#include +#include +#include + +void usage(void) +{ + puts("Usage: svidtune [mode]\n" + ); + exit(2); +} + +int main(int argc, char **argv) +{ + int x=-1,xmax,ymax; + char buffer[2]; + int vgamode; + int key, retval = 0; + int pixelClock; + int HDisplay; + int HSyncStart; + int HSyncEnd; + int HTotal; + int VDisplay; + int VSyncStart; + int VSyncEnd; + int VTotal; + int flags; + float hsf,vsf; + char flagstring[256]; + + if (argc > 2) + usage(); + if(argc==2){ + if(!sscanf(argv[1], "%d", &x)) + usage(); + }; + + vga_init(); + if(x==-1)vgamode = vga_getdefaultmode(); else vgamode=x; + if (vgamode == -1) + vgamode = G640x480x256; + + if (!vga_hasmode(vgamode)) { + printf("Mode not available.\n"); + exit(1); + } + + vga_setmode(vgamode); + gl_setcontextvga(vgamode); + gl_enableclipping(); + gl_setfont(8, 8, gl_font8x8); + gl_setwritemode(FONT_COMPRESSED + WRITEMODE_OVERWRITE); + gl_setfontcolors(0, vga_white()); + + buffer[1] = 0; + for(;!buffer[1];) { + vga_getcurrenttiming(&pixelClock, + &HDisplay, + &HSyncStart, + &HSyncEnd, + &HTotal, + &VDisplay, + &VSyncStart, + &VSyncEnd, + &VTotal, + &flags); + + sprintf(flagstring,"%s%s%s%s%s%s", + flags&1?"+hsync ":"", + flags&2?"-hsync ":"", + flags&4?"+vsync ":"", + flags&8?"-vsync ":"", + flags&16?"interlaced ":"", + flags&32?"doublescan":""); + + hsf=pixelClock*1000.0/HTotal; + vsf=hsf/VTotal; + if(flags&32)vsf=vsf/2; + + gl_printf(500,500,"îúï æéå-àá"); + gl_printf(10,5, "Clock:%i", pixelClock); + gl_printf(10,25, "HDisplay:%i", HDisplay); + gl_printf(10,45, "HSyncStart:%i", HSyncStart); + gl_printf(10,65, "HSyncEnd:%i", HSyncEnd); + gl_printf(10,85, "HTotal:%i", HTotal); + gl_printf(10,105, "VDisplay:%i", VDisplay); + gl_printf(10,125, "VSyncStart:%i", VSyncStart); + gl_printf(10,145, "VSyncEnd:%i", VSyncEnd); + gl_printf(10,165, "VTotal:%i", VTotal); + gl_printf(10,185, "flags:%i = %s", flags,flagstring); + gl_printf(10,205, "Horz freq:%.3f kHz", hsf/1000); + gl_printf(10,215, "Vert freq:%.2f Hz", vsf); + + if(VDisplay>270){ + gl_printf(10,235, "Up, Down, Left, Right, Wider, Narrower, lOnger, Shorter"); + gl_printf(10,258, "'p' - prints current modeline to stdout, 'P' - to config file "); + }; + xmax = vga_getxdim() - 1; + ymax = vga_getydim() - 1; + + vga_setcolor(vga_white()); + vga_drawline(0, 0, xmax, 0); + vga_drawline(xmax, 0, xmax, ymax); + vga_drawline(xmax, ymax, 0, ymax); + vga_drawline(0, ymax, 0, 0); + + key = vga_getch(); + switch(key) { + case 4: + case 'q': + buffer[1]=1; + break; + case 'l': + vga_changetiming(0,0,8,8,0,0,0,0,0,0); + break; + case 'r': + vga_changetiming(0,0,-8,-8,0,0,0,0,0,0); + break; + case 'u': + vga_changetiming(0,0,0,0,0,0,1,1,0,0); + break; + case 'd': + vga_changetiming(0,0,0,0,0,0,-1,-1,0,0); + break; + case 'w': + vga_changetiming(0,0,-4,-4,-8,0,0,0,0,0); + break; + case 'n': + vga_changetiming(0,0,4,4,8,0,0,0,0,0); + break; + case 's': + vga_changetiming(0,0,0,0,0,0,1,1,2,0); + break; + case 'o': + vga_changetiming(0,0,0,0,0,0,-1,-1,-2,0); + break; + case 'p': + fprintf(stderr,"Modeline %c%ix%i@%.0f%c %.3f %i %i %i %i %i %i %i %i %s\n",'"',xmax+1,ymax+1,vsf,'"', + pixelClock/1000.0, + HDisplay, + HSyncStart, + HSyncEnd, + HTotal, + VDisplay, + VSyncStart, + VSyncEnd, + VTotal, + flagstring); + break; + case 'P':{ + FILE *f; + f=fopen("/etc/vga/libvga.config","a"); + fprintf(f,"Modeline %c%ix%i@%.0f%c %.3f %i %i %i %i %i %i %i %i %s\n",'"',xmax+1,ymax+1,vsf,'"', + pixelClock/1000.0, + HDisplay, + HSyncStart, + HSyncEnd, + HTotal, + VDisplay, + VSyncStart, + VSyncEnd, + VTotal, + flagstring); + fclose(f); + }; + break; + + }; + } + + vga_setmode(TEXT); + + exit(retval); +} diff --git a/demos/testaccel.c b/demos/testaccel.c new file mode 100644 index 0000000..ea65fa9 --- /dev/null +++ b/demos/testaccel.c @@ -0,0 +1,758 @@ +/* Program to test all accelerator functions and the 8 bit + per color color lookup functions. */ +/* written by Michael Weller (eowmob@exp-math.uni-essen.de) */ + +#include +#include +#include +#include +#include +#include +#include "vga.h" +#include "clut.xbm" +#include "sixbpp.xbm" +#include "eightbpp.xbm" +#include "fish_monster.h" + +#define RED(i) (0) +#define GREEN(i) (0) +#define BLUE(i) (i) + +#define LOGO_NAME "linuxlogo.bitmap" +#define LOGO_WIDTH 201 +#define LOGO_HEIGHT 85 + +#undef BITFRAME + +typedef struct { + int n; + int pels; + int width; + int offset; + /* + int xmin[n]; + int xmax[n]; */ +} hlinelst; + +/*Adjust hlist for new xcoord */ +inline void adj_hlilst(hlinelst * lst, register int x) +{ + register int i, *ptr; + + i = x; + x -= lst->offset; + lst->offset = i; + + i = (lst->n) << 1; + ptr = (int *) (((char *) lst) + sizeof(hlinelst)); + + while (i--) + *ptr++ += x; +} + +inline int sizhlilst(int n) +{ + return sizeof(hlinelst) + (sizeof(int) * (n < 1 ? 2 : (n << 1))); +} + +inline int isqr(int i) +{ + return i * i; +} + +int waitmode = 1; + +void my_wait(void) +{ + if (waitmode) + vga_getch(); + else + sleep(1); +} + +void setcol(vga_modeinfo * modeinfo) +{ + int i; + + if (modeinfo->colors == 256) + for (i = 0; i < 256; i++) + vga_setpalette(i, (i & 7) * 0x9, ((i >> 3) & 7) * 0x9, ((i >> 6) & 3) * 0x15); + else if (modeinfo->colors < 256) + for (i = 0; i < 16; i++) + vga_setegacolor(i); +} + +int colorcol(int column, int width, int xmax) +{ + int color; + + color = ((column << 8) - column) / xmax; + if (width != 8) + color &= 0xfc; + return color; +} + +void drawtwidth(vga_modeinfo * modeinfo, char *bits, int x, int y, int tw, int th, int width) +{ + unsigned char color; + int i, j, k, xmax, offset; + + tw = (tw + 7) >> 3; + th <<= 1; + th += x; + xmax = vga_getxdim() - 1; + y *= modeinfo->linewidth; + + for (i = x; i < th; i++) { + color = colorcol(xmax - i, width, xmax); + offset = y + i; + + if ((i - x) & 1) + bits -= tw; + j = tw; + while (j--) { + k = 1; + do { + if (*bits & k) { + vga_setpage(offset >> 16); + graph_mem[offset & 0xffff] = color; + } + offset += modeinfo->linewidth; + if (*bits & k) { + vga_setpage(offset >> 16); + graph_mem[offset & 0xffff] = color; + } + offset += modeinfo->linewidth; + k <<= 1; + } + while (k & 0xff); + bits++; + } + } +} + +void drawwidth(int mode, vga_modeinfo * modeinfo, int line, int height, int width) +{ + unsigned char color; + int i, xmax, j, offset; + + xmax = vga_getxdim() - 1; + + for (i = 0; i < xmax; i++) { + color = colorcol(i, width, xmax); + offset = line * (modeinfo->linewidth) + i; + + j = height; + while (j--) { + vga_setpage(offset >> 16); + graph_mem[offset & 0xffff] = color; + offset += modeinfo->linewidth; + } + } + + j = clut_width + sixbpp_width; + j = height - j - j; + j /= 3; + + drawtwidth(modeinfo, clut_bits, (xmax - 2 * clut_height) >> 1, j + line, clut_width, clut_height, width); + j += j + clut_width; + if (width == 6) + drawtwidth(modeinfo, sixbpp_bits, (xmax - 2 * sixbpp_height) >> 1, j + line, sixbpp_width, sixbpp_height, width); + else + drawtwidth(modeinfo, eightbpp_bits, (xmax - 2 * eightbpp_height) >> 1, j + line, eightbpp_width, eightbpp_height, width); +} + +void testwidth(int mode, vga_modeinfo * modeinfo) +{ + int ymax, i, old_flags; + + ymax = vga_getydim(); + + if (vga_getxdim() < 640) + puts(" Warning: Resolution too small, displayed text is\n" + " probably scrambled.\n"); + if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_FLAGS) & VGA_CLUT8) { + old_flags = vga_ext_set(VGA_EXT_SET, VGA_CLUT8); + + for (i = 0; i < 256; i++) + vga_setpalette(i, RED(i), GREEN(i), BLUE(i)); + + puts(" Has support for CLUT width 8 bit"); + drawwidth(mode, modeinfo, 0, ymax >> 1, 6); + drawwidth(mode, modeinfo, ymax >> 1, ymax >> 1, 8); + my_wait(); + vga_clear(); + vga_ext_set(VGA_EXT_RESET, old_flags); + } else { + + for (i = 0; i < 256; i++) + vga_setpalette(i, RED(i) >> 2, GREEN(i) >> 2, BLUE(i) >> 2); + + puts(" No support for CLUT width 8 bit"); + drawwidth(mode, modeinfo, 0, ymax, 6); + my_wait(); + } +} + +void testfill(vga_modeinfo * modeinfo) +{ + clock_t clk; + unsigned long pels = 0; + int xmax, ymax, lw, i, start, lim, x, y, w, h, mask; + + lw = modeinfo->linewidth; + setcol(modeinfo); + vga_clear(); + + ymax = vga_getydim(); + xmax = vga_getxdim(); + + srand(time(0)); + clk = clock(); + mask = modeinfo->colors - 1; + lim = ((xmax < ymax) ? xmax : ymax) >> 1; + + for (i = 0, start = 0; i < lim; i++, start += lw + modeinfo->bytesperpixel) { + vga_fillblt(start, xmax - (i << 1), ymax - (i << 1), lw, mask & i); + pels += (xmax - (i << 1)) * (ymax - (i << 1)); + } + for (i = 0; i < 10000; i++) { + x = rand() % xmax; + y = rand() % ymax; + w = rand() % (xmax - x); + h = rand() % (ymax - y); + switch (modeinfo->bytesperpixel) { + case 2: + x <<= 1; + break; + case 3: + x += (x << 1); + break; + case 4: + x <<= 2; + break; + } + + vga_fillblt(x + y * lw, w, h, lw, mask & rand()); + pels += w * h; + } + clk = clock() - clk; + printf(" Has FillBlt: %11lu Pixels in %.2f seconds -> %.2f Megapels\n", + pels, ((double) clk) / CLOCKS_PER_SEC, (pels / 1.0e6) / (((double) clk) / CLOCKS_PER_SEC)); + my_wait(); +} + +void getlogo(void *blitimage, vga_modeinfo * modeinfo) +{ + int i; + FILE *fd; + + fd = fopen(LOGO_NAME, "r"); + if (!fd) { + read_err: + perror("Problems reading linuxlogo.bitmap"); + exit(2); + } + if (1 != fread(blitimage, LOGO_WIDTH * LOGO_HEIGHT, 1, fd)) + goto read_err; + fclose(fd); + switch (modeinfo->bytesperpixel) { + /* Nothing todo for 256 colors! */ + case 2: + { + unsigned char *bmp = (void *) blitimage; + unsigned short *bmpsh = (void *) blitimage; + bmp += LOGO_WIDTH * LOGO_HEIGHT; + bmpsh += LOGO_WIDTH * LOGO_HEIGHT; + i = LOGO_WIDTH * LOGO_HEIGHT; + + if (modeinfo->colors == 32768) { + while (i--) { + bmp--; + *--bmpsh = ((((unsigned short) *bmp) & 7) << 12) | + ((((unsigned short) *bmp) & 0x38) << 4) | + ((((unsigned short) *bmp) & 0xc0) >> 3); + } + } else { + while (i--) { + bmp--; + *--bmpsh = ((((unsigned short) *bmp) & 7) << 13) | + ((((unsigned short) *bmp) & 0x38) << 5) | + ((((unsigned short) *bmp) & 0xc0) >> 3); + } + } + } + break; + case 3: + { + unsigned char *bmp = (void *) blitimage; + unsigned char *bmp3 = (void *) blitimage; + bmp += LOGO_WIDTH * LOGO_HEIGHT; + bmp3 += 3 * LOGO_WIDTH * LOGO_HEIGHT; + i = LOGO_WIDTH * LOGO_HEIGHT; + + while (i--) { + bmp--; + *--bmp3 = ((((unsigned int) *bmp) & 7) << 5); + *--bmp3 = ((((unsigned int) *bmp) & 0x38) << 2); + *--bmp3 = ((((unsigned int) *bmp) & 0xc0)); + } + } + break; + case 4: + { + unsigned char *bmp = (void *) blitimage; + unsigned int *bmpi = (void *) blitimage; + bmp += LOGO_WIDTH * LOGO_HEIGHT; + bmpi += LOGO_WIDTH * LOGO_HEIGHT; + i = LOGO_WIDTH * LOGO_HEIGHT; + + if (modeinfo->flags & RGB_MISORDERED) { + while (i--) { + bmp--; + *--bmpi = ((((unsigned int) *bmp) & 7) << 29) | + ((((unsigned int) *bmp) & 0x38) << 18) | + ((((unsigned int) *bmp) & 0xc0) << 8); + } + } else { + while (i--) { + bmp--; + *--bmpi = ((((unsigned int) *bmp) & 7) << 21) | + ((((unsigned int) *bmp) & 0x38) << 10) | + ((((unsigned int) *bmp) & 0xc0)); + } + } + } + break; + } +} + +void testbit(vga_modeinfo * modeinfo) +{ + clock_t clk; + unsigned long pels = 0, *blitimage; + int xmax, ymax, lw, i, x, y, dx, dy, nx, ny; + + if ((modeinfo->bytesperpixel != 1) && (modeinfo->bytesperpixel != 2)) { + puts(" Has BitBlt, but no test code for this pixelwidth implemented."); + return; + } + ymax = vga_getydim(); + xmax = vga_getxdim(); + lw = modeinfo->linewidth; + + if ((xmax < 210) || (ymax < 90)) { + puts(" Has BitBlt, but no test code for this small resolution implemented."); + return; + } + setcol(modeinfo); + vga_clear(); + + pels = 0; + blitimage = alloca(modeinfo->bytesperpixel * LOGO_WIDTH * LOGO_HEIGHT); + getlogo(blitimage, modeinfo); + + if (modeinfo->bytesperpixel == 1) { + unsigned char *ptr = (void *) blitimage; + for (y = 1; y <= LOGO_HEIGHT; y++) + for (x = 1; x <= LOGO_WIDTH; x++) { + vga_setcolor((int) *ptr++); + vga_drawpixel(x, y); + } + } else { + unsigned short *ptr = (void *) blitimage; + for (y = 1; y <= LOGO_HEIGHT; y++) + for (x = 1; x <= LOGO_WIDTH; x++) { + vga_setcolor((int) *ptr++); + vga_drawpixel(x, y); + } + } +#ifdef BITFRAME + vga_setcolor(200); + vga_drawline(0, 0, 0, LOGO_HEIGHT + 1); + vga_drawline(0, 0, LOGO_WIDTH + 1, 0); + vga_drawline(LOGO_WIDTH + 1, 0, LOGO_WIDTH + 1, LOGO_HEIGHT + 1); + vga_drawline(0, LOGO_HEIGHT + 1, LOGO_WIDTH + 1, LOGO_HEIGHT + 1); +#endif + + x = 0; + y = 0; + dx = 1; + dy = 1; + clk = clock(); + + for (i = 0; i < 10000; i++) { + nx = x + dx; + ny = y + dy; + if ((nx + LOGO_WIDTH + 2 > xmax) || (nx < 0)) { + dx = -dx; + nx = x + dx; + } + if ((ny + LOGO_HEIGHT + 2 > ymax) || (ny < 0)) { + dy = -dy; + ny = y + dy; + } + if (modeinfo->bytesperpixel == 2) { + vga_bitblt((x + y * (lw >> 1)) << 1, + (nx + ny * (lw >> 1)) << 1, + LOGO_WIDTH + 2, LOGO_HEIGHT + 2, lw); + } else { + vga_bitblt(x + y * lw, nx + ny * lw, LOGO_WIDTH + 2, LOGO_HEIGHT + 2, lw); + } + + pels += (LOGO_WIDTH + 2) * (LOGO_HEIGHT + 2); + x = nx; + y = ny; + } + + clk = clock() - clk; + printf(" Has BitBlt: %12lu Pixels in %.2f seconds -> %.2f Megapels\n", + pels, ((double) clk) / CLOCKS_PER_SEC, (pels / 1.0e6) / (((double) clk) / CLOCKS_PER_SEC)); + my_wait(); +} + +void testimage(vga_modeinfo * modeinfo) +{ + clock_t clk; + unsigned long pels = 0, *blitimage; + int xmax, ymax, lw, i, x, y; + + if ((modeinfo->bytesperpixel < 1) || (modeinfo->bytesperpixel > 4)) { + puts(" Has ImageBlt, but no test code for this pixelwidth implemented."); + return; + } + ymax = vga_getydim(); + xmax = vga_getxdim(); + lw = modeinfo->linewidth; + + if ((xmax < 210) || (ymax < 90)) { + puts(" Has ImageBlt, but no test code for this small resolution implemented."); + return; + } +/* Prepare a simple test pattern for testuse: */ + switch (modeinfo->bytesperpixel) { + default: + { + /* 8bpp: */ + register unsigned char *ptr, *pt_fish = fish_monster; + + blitimage = alloca(fish_monster_w * fish_monster_h); + ptr = (unsigned char *) blitimage; + + for (i = 0; i < (fish_monster_w * fish_monster_h); i++) + *ptr++ = fish_monster233[(*pt_fish++) - '`']; + } + break; + case 2: + { + register unsigned char *pt_fish = fish_monster; + register unsigned short *ptr, *coltab; + + blitimage = alloca(sizeof(unsigned short) * fish_monster_w * fish_monster_h); + ptr = (unsigned short *) blitimage; + + if (modeinfo->colors == 32768) + coltab = fish_monster555; + else + coltab = fish_monster565; + for (i = 0; i < (fish_monster_w * fish_monster_h); i++) + *ptr++ = coltab[(*pt_fish++) - '`']; + } + break; + case 3: + { + register unsigned char *pt_fish = fish_monster; + register unsigned char *ptr, *coltab; + + blitimage = alloca(3 * fish_monster_w * fish_monster_h); + ptr = (unsigned char *) blitimage; + + coltab = (unsigned char *) fish_monster888; + + for (i = 0; i < (fish_monster_w * fish_monster_h); i++) { + *ptr++ = coltab[(((*pt_fish) - '`') << 2)]; + *ptr++ = coltab[(((*pt_fish) - '`') << 2) + 1]; + *ptr++ = coltab[(((*pt_fish++) - '`') << 2) + 2]; + } + } + break; + case 4: + { + register unsigned char *pt_fish = fish_monster; + register unsigned int *ptr, *coltab; + + blitimage = alloca(sizeof(unsigned int) * fish_monster_w * fish_monster_h); + ptr = (unsigned int *) blitimage; + + coltab = fish_monster888; + if (modeinfo->flags & RGB_MISORDERED) { + for (i = 0; i < (fish_monster_w * fish_monster_h); i++) + *ptr++ = (coltab[(*pt_fish++) - '`'] << 8); + } else { + for (i = 0; i < (fish_monster_w * fish_monster_h); i++) + *ptr++ = coltab[(*pt_fish++) - '`']; + } + } + break; + } + setcol(modeinfo); + vga_clear(); + + srand(time(0)); + for (i = 0; i < 10000; i++) { + x = rand() % (xmax - fish_monster_w); + y = rand() % (ymax - fish_monster_h); + if (modeinfo->bytesperpixel > 1) + x *= modeinfo->bytesperpixel; + + vga_imageblt(blitimage, x + y * lw, fish_monster_w, fish_monster_h, lw); + pels += fish_monster_w * fish_monster_h; + } + pels = 0; + blitimage = alloca(modeinfo->bytesperpixel * LOGO_WIDTH * LOGO_HEIGHT); + getlogo(blitimage, modeinfo); + + clk = clock(); + + for (i = 0; i < 1000; i++) { + x = rand() % (xmax - LOGO_WIDTH); + y = rand() % (ymax - LOGO_HEIGHT); + if (modeinfo->bytesperpixel > 1) + x *= modeinfo->bytesperpixel; + + vga_imageblt(blitimage, x + y * lw, LOGO_WIDTH, LOGO_HEIGHT, lw); + pels += LOGO_WIDTH * LOGO_HEIGHT; + } + + clk = clock() - clk; + printf(" Has ImageBlt: %10lu Pixels in %.2f seconds -> %.2f Megapels\n", + pels, ((double) clk) / CLOCKS_PER_SEC, (pels / 1.0e6) / (((double) clk) / CLOCKS_PER_SEC)); + my_wait(); +} + +void hlinesquare(hlinelst * des, register int n) +{ + register int *xmin, *xmax; + + if (n < 1) + n = 1; + + des->n = n; + des->width = n; + des->offset = 0; + des->pels = n * n; + + xmin = (int *) ((char *) des + sizeof(hlinelst)); + xmax = xmin + n; + + while (n--) { + *xmin++ = 0; + *xmax++ = des->width - 1; + } +} + +void hlinedisk(hlinelst * des, register int n) +{ + register int *xmin, *xmax, radsq, rad, x; + + if (!(n & 1)) + n--; + if (n < 1) + n = 1; + + des->n = n; + des->width = n; + des->offset = 0; + des->pels = n * n; + rad = (n >> 1); + radsq = rad * rad; + + xmin = (int *) ((char *) des + sizeof(hlinelst)); + xmax = xmin + n; + + while (n--) { + x = sqrt(radsq - isqr(n - rad)); + *xmin++ = rad - x; + *xmax++ = rad + x; + } +} + +void hlinecaro(hlinelst * des, register int n) +{ + register int *xmin, *xmax, i, j; + + if (!(n & 1)) + n--; + if (n < 1) + n = 1; + + des->n = n; + des->width = n; + des->offset = 0; + des->pels = (n * n) / 2; + + xmin = (int *) ((char *) des + sizeof(hlinelst)); + xmax = xmin + n; + + i = 1 + (n >> 1); + j = 0; + + while (i--) { + *xmin++ = (n >> 1) - j; + *xmax++ = (n >> 1) + j; + j++; + } + i = (n >> 1); + j -= 2; + while (i--) { + *xmin++ = (n >> 1) - j; + *xmax++ = (n >> 1) + j; + j--; + } +} + +void testhline(vga_modeinfo * modeinfo) +{ +#define SHAPES 9 + clock_t clk; + unsigned long pels = 0; + hlinelst *shape[SHAPES], *curs; + int xmax, ymax, lw, i, x, y, mask; + + setcol(modeinfo); + vga_clear(); + + ymax = vga_getydim(); + xmax = vga_getxdim(); + lw = modeinfo->linewidth; + mask = modeinfo->colors - 1; + + srand(time(0)); + + i = 0; + shape[i] = alloca(sizhlilst(ymax / 2)); + hlinesquare(shape[i++], ymax / 2); + shape[i] = alloca(sizhlilst(ymax / 4)); + hlinesquare(shape[i++], ymax / 4); + shape[i] = alloca(sizhlilst(ymax / 8)); + hlinesquare(shape[i++], ymax / 8); + + shape[i] = alloca(sizhlilst(ymax / 2)); + hlinecaro(shape[i++], ymax / 2); + shape[i] = alloca(sizhlilst(ymax / 4)); + hlinecaro(shape[i++], ymax / 4); + shape[i] = alloca(sizhlilst(ymax / 8)); + hlinecaro(shape[i++], ymax / 8); + + shape[i] = alloca(sizhlilst(ymax / 2)); + hlinedisk(shape[i++], ymax / 2); + shape[i] = alloca(sizhlilst(ymax / 4)); + hlinedisk(shape[i++], ymax / 4); + shape[i] = alloca(sizhlilst(ymax / 8)); + hlinedisk(shape[i++], ymax / 8); + + + clk = clock(); + + for (i = 0; i < 1000; i++) { + curs = shape[rand() % SHAPES]; + x = rand() % (xmax - (curs->width)); + y = rand() % (ymax - (curs->n)); + adj_hlilst(curs, x); + pels += curs->pels; + vga_hlinelistblt(y, curs->n, + (int *) (((char *) curs) + sizeof(hlinelst)), + (int *) (((char *) curs) + sizeof(hlinelst) + (curs->n) * sizeof(int)), + lw, mask & rand()); + } + clk = clock() - clk; + clk++; + printf(" Has HlineLst: %10lu Pixels in %.2f seconds -> %.2f Megapels\n", + pels, ((double) clk) / CLOCKS_PER_SEC, (pels / 1.0e6) / (((double) clk) / CLOCKS_PER_SEC)); + my_wait(); +} + +void testmode(int mode) +{ + vga_modeinfo *modeinfo; + + printf("Testing mode %2d: %s...", mode, vga_getmodename(mode)); + if (!vga_hasmode(mode)) { + puts(" not available"); + return; + } + puts(""); + + vga_setmode(mode); + modeinfo = vga_getmodeinfo(mode); + + if ((modeinfo->colors == 256) && !(modeinfo->flags & IS_MODEX)) { + testwidth(mode, modeinfo); + } else + puts(" Dacwidth test not applicable."); + if (modeinfo->haveblit & HAVE_BITBLIT) + testbit(modeinfo); + if (modeinfo->haveblit & HAVE_FILLBLIT) + testfill(modeinfo); + if (modeinfo->haveblit & HAVE_IMAGEBLIT) + testimage(modeinfo); + if (modeinfo->haveblit & HAVE_HLINELISTBLIT) + testhline(modeinfo); + vga_setmode(TEXT); +} + +void usage(void) +{ + puts("Usage: testaccel [-nowait] {all|[mode [mode [mode...]]]}\n" + "\ttests accelerated features and extended options in\n" + "\tall or the given modes.\n" + "\tAll standard svgalib ways of writing modenames are understood.\n" + "\tIf no parameters are given the defaultmode or G640x480x256 is\n" + "\tused.\n" + "\tIf -nowait is given, don't wait for a keypress after each test."); + exit(2); +} + +int main(int argc, char *argv[]) +{ + int mode; + + vga_init(); + + puts( + "Note: Timings include main cpu calculations (random numbers and such\n" + " things). Thus they are esp. for lower resolutions much too slow!"); + + if ((argc > 1) && !strcmp(argv[1], "-nowait")) { + argc--; + argv++; + waitmode = 0; + } + if ((argc == 2) && !strcmp(argv[1], "all")) { + int flag = 0; + for (mode = 1; mode <= GLASTMODE; mode++) + if (vga_hasmode(mode)) { + flag = 1; + testmode(mode); + } + if (!flag) + puts("testaccel: Not any graphicsmode available!"); + } else if (argc > 1) { + for (mode = 1; mode < argc; mode++) + if (vga_getmodenumber(argv[mode]) < 0) { + printf("testaccel: Parameter %s is not a valid graphicsmode.\n", argv[mode]); + usage(); + } + for (mode = 1; mode < argc; mode++) + testmode(vga_getmodenumber(argv[mode])); + } else { + mode = vga_getdefaultmode(); + if (mode < 0) + mode = G640x480x256; + if (vga_hasmode(mode)) + testmode(mode); + else + puts("testaccel: could not set defaultmode or G640x480x256!"); + } + return 0; +} diff --git a/demos/testgl.c b/demos/testgl.c new file mode 100644 index 0000000..5ebf8ca --- /dev/null +++ b/demos/testgl.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include + +/* The logo was drawn by John Remyn. */ +/* Feel free to provide a more beautiful/official/thought provoking/cool */ +/* logo to replace it. */ +#define LOGOWIDTH 201 +#define LOGOHEIGHT 85 + +int VGAMODE; +int VIRTUAL; + +int timescale=1; + +GraphicsContext *backscreen; +GraphicsContext *physicalscreen; +void *logobitmap; + +void loadbitmap(char *filename, void *buf) +{ + FILE *f; + f = fopen(filename, "rb"); + if(f==NULL)return; + fread(buf, 1, 17085, f); + fclose(f); +} + + +void test(void) +{ + int i, j; + unsigned char *bitmap; + GraphicsContext *savedcontext; + + if (VIRTUAL) + gl_setcontext(backscreen); + + gl_clearscreen(0); + for (i = 0; i < 5; i++) { + gl_clearscreen(0); + for (j = 0; j < 20000*timescale; j++) + gl_setpixel(random() % WIDTH, random() % HEIGHT, + random() % COLORS); + } + + if (VIRTUAL) + gl_copyscreen(physicalscreen); + + gl_clearscreen(0); + for (i = 0; i < 5000*timescale; i++) { + int x, y; + x = random() % (WIDTH - 1); + y = random() % (HEIGHT - 1); + gl_fillbox(x, y, random() % (WIDTH - x), random() + % (HEIGHT - y), random() % COLORS); + } + + if (VIRTUAL) + gl_copyscreen(physicalscreen); + + gl_clearscreen(0); + for (i = 0; i < 4000*timescale; i++) + gl_line(random() % WIDTH, random() % HEIGHT, + random() % WIDTH, random() % HEIGHT, + random() % COLORS); + + if (VIRTUAL) + gl_copyscreen(physicalscreen); + + /* Create bitmap. */ + bitmap = malloc(64 * 64 * BYTESPERPIXEL); + /* Create temporary graphics context to create bitmap in. */ + savedcontext = gl_allocatecontext(); + gl_getcontext(savedcontext); + gl_setcontextvirtual(64, 64, BYTESPERPIXEL, BITSPERPIXEL, bitmap); + /* The rgb functions can be used to create nice bitmaps easily for */ + /* hicolor/truecolor modes. The 256 color 'emulated' truecolor */ + /* looks less impressive. */ + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) { + int c; + c = 255 - (i + j) * 4; + gl_setpixelrgb(31 - i, 31 - j, c, 0, 0); + gl_setpixelrgb(32 + i, 31 - j, c, c, 0); + gl_setpixelrgb(31 - i, 32 + j, c, 0, c); + gl_setpixelrgb(32 + i, 32 + j, c, c, c); + } + /* Restore previous context. */ + gl_setcontext(savedcontext); + + gl_clearscreen(0); + for (i = 0; i < 4000*timescale; i++) { + int x, y; + x = random() % (WIDTH - 64 + 1); + y = random() % (HEIGHT - 64 + 1); + gl_putbox(x, y, 64, 64, bitmap); + } + + free(bitmap); + + if (VIRTUAL) + gl_copyscreen(physicalscreen); +} + + +void setcustompalette(void) +{ + /* colors 0-31 are an RGB mix (bits 0 and 1 red, 2 green, 3 and 4 blue) */ + /* 32-63 black to red */ + /* 64-95 black to green */ + /* 96-127 black to yellow */ + /* 128-159 black to blue */ + /* 160-191 black to magenta */ + /* 192-223 black to cyan */ + /* 224-255 black to white */ + Palette pal; + int i; + for (i = 0; i < 256; i++) { + int r, g, b; + r = g = b = 0; + if ((i & 32) > 0) + r = (i & 31) << 1; + if ((i & 64) > 0) + g = (i & 31) << 1; + if ((i & 128) > 0) + b = (i & 31) << 1; + if (i < 32) { + r = (i & 3) << 4; /* 2 bits */ + g = (i & 4) << 3; /* 1 bit */ + b = (i & 24) << 1; /* 2 bits */ + } + pal.color[i].red = r; + pal.color[i].green = g; + pal.color[i].blue = b; + } + gl_setpalette(&pal); +} + + +void logotest(void) +{ + int h; + void *scaled; + /* Set logo palette. */ + setcustompalette(); + /* Create logo bitmap */ + logobitmap = alloca(LOGOWIDTH * LOGOHEIGHT); + loadbitmap("linuxlogo.bitmap", logobitmap); + /* Allocate buffer for scaled bitmap. */ + scaled = alloca(WIDTH * HEIGHT); + gl_clearscreen(0); + /* Stretch vertically. */ + for (h = 0; h <= LOGOHEIGHT; h++) { + gl_scalebox(LOGOWIDTH, LOGOHEIGHT, logobitmap, + LOGOWIDTH, h, scaled); + gl_putbox(0, 0, LOGOWIDTH, h, scaled); + if (VIRTUAL) + gl_copyscreen(physicalscreen); + usleep(10000); + } + gl_clearscreen(0); + /* Scale to screen resolution. */ + gl_scalebox(LOGOWIDTH, LOGOHEIGHT, logobitmap, WIDTH, HEIGHT, scaled); + gl_putbox(0, 0, WIDTH, HEIGHT, scaled); + gl_copyscreen(physicalscreen); +} + + +int main(int argc, char *argv[]) +{ + vga_init(); + + if(argc>=2) { + timescale=atoi(argv[1]); + if(timescale<1)timescale=1; + } + + VGAMODE = vga_getdefaultmode(); + if (VGAMODE == -1) + VGAMODE = G320x200x256; /* Default mode. */ + + if (!vga_hasmode(VGAMODE)) { + printf("Mode not available.\n"); + exit(-1); + } + VIRTUAL = 0; /* No virtual screen. */ + if (vga_getmodeinfo(VGAMODE)->colors == 16 || + (vga_getmodeinfo(VGAMODE)->flags & IS_MODEX)) + /* These modes are supported indirectly by vgagl. */ + VIRTUAL = 1; + + if (VIRTUAL) { + /* Create virtual screen. */ + gl_setcontextvgavirtual(VGAMODE); + backscreen = gl_allocatecontext(); + gl_getcontext(backscreen); + } + vga_setmode(VGAMODE); + gl_setcontextvga(VGAMODE); /* Physical screen context. */ + physicalscreen = gl_allocatecontext(); + gl_getcontext(physicalscreen); + if (COLORS == 256) + gl_setrgbpalette(); + + if(argc==3)sleep(2); + + test(); + + /* Now do the same with clipping enabled. */ + gl_clearscreen(0); + gl_setclippingwindow(WIDTH / 4, HEIGHT / 4, WIDTH - WIDTH / 4 - 1, + HEIGHT - HEIGHT / 4 - 1); + + test(); + + gl_disableclipping(); + if (COLORS == 256) + /* Show the logo if using 256 color mode. */ + logotest(); + + getchar(); + + if (VIRTUAL) + gl_freecontext(backscreen); + vga_setmode(TEXT); + exit(0); +} diff --git a/demos/testlinear.c b/demos/testlinear.c new file mode 100644 index 0000000..4b034ea --- /dev/null +++ b/demos/testlinear.c @@ -0,0 +1,124 @@ + +/* + Simple test program for Cirrus linear addressing/color expansion. + vgagl can take advantage of it (linear addressing). + */ + + +#include +#include +#include +#include +#include +#include +#include "../src/libvga.h" + + +#define USE_LINEAR_ADDRESSING +/* #define USE_BY16_ADDRESSING */ + + +unsigned char *vbuf; + +#if 0 +/* This function is Cirrus specific and has nothing to do with linear + * addressing. */ +void by8test(void) +{ + int i; + int startclock, diffclock; + + /* Enable extended write modes and BY8/16 addressing. */ + outb(0x3ce, 0x0b); + +#ifdef USE_BY16_ADDRESSING + outb(0x3cf, inb(0x3cf) | 0x16); +#else + outb(0x3cf, inb(0x3cf) | 0x06); +#endif + /* Set extended write mode 4. */ + outb(0x3ce, 0x05); + outb(0x3cf, (inb(0x3cf) & 0xf8) | 4); + + /* Set pixel mask register (coincides with VGA plane mask register). */ + outw(0x3c4, 0xff02); + + startclock = clock(); + for (i = 0; i < 248; i++) { + outw(0x3ce, 0x01 + (i << 8)); /* Set foreground color. */ +#ifdef USE_BY16_ADDRESSING + outw(0x3ce, 0x11 + (i << 8)); /* Set high byte. */ + memset(vbuf, 0xff, 640 * 480 / 16); +#else + memset(vbuf, 0xff, 640 * 480 / 8); +#endif + } + diffclock = clock() - startclock; + printf("Color expansion framebuffer fill speed: %dK/s\n", + 640 * 480 * 248 / diffclock / 10); +} +#endif + +int main(int argc, char *argv[]) +{ + int i,j; + + if (!(argc == 2 && strcmp(argv[1], "--force") == 0)) + if (!(vga_getmodeinfo(vga_getdefaultmode())->flags & CAPABLE_LINEAR)) { + printf("Linear addressing not supported for this chipset.\n"); + exit(1); + } + vga_init(); + vga_setmode(vga_getdefaultmode()); + vga_setpage(0); +#ifdef USE_LINEAR_ADDRESSING + if (vga_setlinearaddressing() == -1) { + vga_setmode(TEXT); + printf("Could not set linear addressing.\n"); + exit(-1); + } +#endif + + /* Should not mess with bank register after this. */ + + vbuf = vga_getgraphmem(); + printf("vbuf mapped at %08lx.\n", (unsigned long) vbuf); + + getchar(); + +#ifdef USE_LINEAR_ADDRESSING + memset(vbuf, 0x88, 640 * 480); + sleep(1); + + memset(vbuf, 0, 640 * 480); + for (i = 0; i < 100000; i++) + *(vbuf + (rand() & 0xfffff)) = rand(); +#endif + +#if 0 + if (vga_getcurrentchipset() == CIRRUS) + /* Show the bandwidth of the extended write modes of the */ + /* Cirrus chip. */ + by8test(); +#endif + + getchar(); + for(i = 0;i < 44;i++){ + *(vbuf + i) = 0x1c; + *(vbuf + 640*17 + i) = 0x1c; + *(vbuf + 640*480 - i) = 0x1c; + *(vbuf + 640*480 - 1 - 640*17 - i) = 0x1c; + for(j = 1;j < 17;j++){ + *(vbuf + 640*j + i) = (i == 0 || i == 43)? 0x1c:0; + *(vbuf + 640*480 - 1 - 640*j - i) = (i == 0 || i == 43)? 0x1c:0; + } + } + for(i = 3;i < 10;i++) + for(j = 4;j < 10;j++){ + *(vbuf + i + 640*j) = 0x3f; + *(vbuf + 640*480 -1 -640*j - i) = 0x3f; + } + getchar(); + vga_setmode(TEXT); + return 0; +} diff --git a/demos/vgatest.c b/demos/vgatest.c new file mode 100644 index 0000000..550c79b --- /dev/null +++ b/demos/vgatest.c @@ -0,0 +1,294 @@ +/* From VGAlib, changed for svgalib */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + + +#include +#include +#include /* for usleep( long ) */ +#include +#include "vga.h" + +static unsigned char line[2048 * 3]; + +static void +drawSquares(int const xmax, int const ymax) +{ + unsigned int const center_x = xmax/2; + /* The column just to the left of the center (assuming + even number of columns) + */ + unsigned int const center_y = ymax/2; + /* The line just above the center (assuming + even number of lines) + */ + + int x; + + for (x = 0; x < 64; x++) { + int y; + for (y = 0; y < 64; y++) { + /* Top 3 squares */ + vga_setrgbcolor(x * 4 + 3, y * 4 + 3, 0); + vga_drawpixel(center_x - 32 - 32 - 64 + x, center_y - 80 + y); + vga_setrgbcolor(x * 4 + 3, 0, y * 4 + 3); + vga_drawpixel(center_x - 32 + x, center_y - 80 + y); + vga_setrgbcolor(0, x * 4 + 3, y * 4 + 3); + vga_drawpixel(center_x + 32 + 32 + x, center_y - 80 + y); + + /* Bottom 3 squares */ + vga_setrgbcolor(x * 4 + 3, y * 4 + 3, 255); + vga_drawpixel(center_x - 32 - 32 - 64 + x, center_y + 16 + y); + vga_setrgbcolor(x * 4 + 3, 255, y * 4 + 3); + vga_drawpixel(center_x - 32 + x, center_y + 16 + y); + vga_setrgbcolor(255, x * 4 + 3, y * 4 + 3); + vga_drawpixel(center_x + 32 + 32 + x, center_y + 16 + y); + } + } +} + + + +static void testmode(int mode) +{ + int xmax, ymax, i, x, y, yw, ys, c; + vga_modeinfo *modeinfo; + + vga_setmode(mode); + + modeinfo = vga_getmodeinfo(mode); + + printf("Width: %d Height: %d Colors: %d\n", + modeinfo->width, + modeinfo->height, + modeinfo->colors); + printf("DisplayStartRange: %xh Maxpixels: %d Blit: %s\n", + modeinfo->startaddressrange, + modeinfo->maxpixels, + modeinfo->haveblit ? "YES" : "NO"); + +#ifdef TEST_MODEX + if (modeinfo->colors == 256) + printf("Switching to ModeX ... %s\n", + (vga_setmodeX()? "done" : "failed")); +#endif + + vga_screenoff(); + + xmax = vga_getxdim() - 1; + ymax = vga_getydim() - 1; + + vga_setcolor(vga_white()); + vga_drawline(0, 0, xmax, 0); + vga_drawline(xmax, 0, xmax, ymax); + vga_drawline(xmax, ymax, 0, ymax); + vga_drawline(0, ymax, 0, 0); + + /* Draw crosses */ + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(10 + i * 5, 10, 89 + i * 5, 89); + } + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(89 + i * 5, 10, 10 + i * 5, 89); + } + + vga_screenon(); + + ys = 100; + yw = (ymax - 100) / 4; + switch (vga_getcolors()) { + case 256: + /* Draw horizontal color bands using palette */ + for (i = 0; i < 60; ++i) { + c = (i * 64) / 60; + vga_setpalette(i + 16, c, c, c); + vga_setpalette(i + 16 + 60, c, 0, 0); + vga_setpalette(i + 16 + (2 * 60), 0, c, 0); + vga_setpalette(i + 16 + (3 * 60), 0, 0, c); + } + line[0] = line[xmax] = 15; + line[1] = line[xmax - 1] = 0; + for (x = 2; x < xmax - 1; ++x) + line[x] = (((x - 2) * 60) / (xmax - 3)) + 16; + for (y = ys; y < ys + yw; ++y) /* gray */ + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) /* red */ + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) /* green */ + vga_drawscanline(y, line); + for (x = 2; x < xmax - 1; ++x) + line[x] += 60; + ys += yw; + for (y = ys; y < ys + yw; ++y) /* blue */ + vga_drawscanline(y, line); + break; + + case 1 << 15: + case 1 << 16: + case 1 << 24: + /* Draw horizontal color bands in RGB */ + for (x = 2; x < xmax - 1; ++x) { + c = ((x - 2) * 255) / (xmax - 4); + y = ys; + vga_setrgbcolor(c, c, c); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(c, 0, 0); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(0, c, 0); + vga_drawline(x, y, x, y + yw - 1); + y += yw; + vga_setrgbcolor(0, 0, c); + vga_drawline(x, y, x, y + yw - 1); + } + drawSquares(xmax, ymax); + break; + default: + /* Draw vertical color bars */ + if (vga_getcolors() == 16) { + for (i = 0; i < xmax - 1; i++) + line[i] = (i + 2) % 16; + line[0] = line[xmax] = 15; + line[1] = line[xmax - 1] = 0; + } + if (vga_getcolors() == 2) { + for (i = 0; i <= xmax; i++) + line[i] = 0x11; + line[0] = 0x91; + } + for (i = 100; i < ymax - 1; i++) + vga_drawscanline(i, line); + break; + + } + + if (getchar() == 'd') + vga_dumpregs(); + +} + +int main(int argc, char *argv[]) +{ + int mode, mode2; + int i, high; + + vga_init(); /* Initialize. */ + + mode = -1; + mode2= -1; + + if(argc==2) { + mode = atoi(argv[1]); + } else if(argc==3) { + mode = atoi(argv[1]); + mode2= atoi(argv[2]); + } + + + if (mode == -1) { + printf("Choose one of the following video modes: \n"); + + high = 0; + for (i = 1; i <= vga_lastmodenumber(); i++) + if (vga_hasmode(i)) { + vga_modeinfo *info; + char expl[100]; + const char *cols = NULL; + + *expl = '\0'; + info = vga_getmodeinfo(i); + switch (info->colors) { + case 2: + cols = "2"; + strcpy(expl, "1 bitplane, monochrome"); + break; + case 16: + cols = "16"; + strcpy(expl, "4 bitplanes"); + break; + case 256: + if (i == G320x200x256) + strcpy(expl, "packed-pixel"); + else if (i == G320x240x256 + || i == G320x400x256 + || i == G360x480x256) + strcpy(expl, "Mode X"); + else + strcpy(expl, + "packed-pixel, banked"); + break; + case 1 << 15: + cols = "32K"; + strcpy(expl, "5-5-5 RGB, blue at LSB, banked"); + break; + case 1 << 16: + cols = "64K"; + strcpy(expl, "5-6-5 RGB, blue at LSB, banked"); + break; + case 1 << 24: + cols = "16M"; + if (info->bytesperpixel == 3) { + if (info->flags & RGB_MISORDERED) + strcpy(expl, "8-8-8 BGR, red byte first, banked"); + else + strcpy(expl, "8-8-8 RGB, blue byte first, banked"); + } else if (info->flags & RGB_MISORDERED) + strcpy(expl, "8-8-8 RGBX, 32-bit pixels, X byte first, banked"); + else + strcpy(expl, "8-8-8 XRGB, 32-bit pixels, blue byte first, banked"); + break; + } + if (info->flags & IS_INTERLACED) { + if (*expl != '\0') + strcat(expl, ", "); + strcat(expl, "interlaced"); + } + if (info->flags & IS_DYNAMICMODE) { + if (*expl != '\0') + strcat(expl, ", "); + strcat(expl, "dynamically loaded"); + } + high = i; + printf("%5d: %dx%d, ", + i, info->width, info->height); + if (cols == NULL) + printf("%d", info->colors); + else + printf("%s", cols); + printf(" colors "); + if (*expl != '\0') + printf("(%s)", expl); + printf("\n"); + } + printf("Enter mode number (1-%d): ", high); + scanf("%d", &mode); + getchar(); + printf("\n"); + + if (mode < 1 || mode > GLASTMODE) { + printf("Error: Mode number out of range \n"); + exit(-1); + } + } + if (vga_hasmode(mode)) { + testmode(mode); + if(mode2!=-1 && vga_hasmode(mode2)) { + testmode(mode2); + } + } else { + printf("Error: Video mode not supported by driver\n"); + exit(-1); + } + + vga_setmode(TEXT); + + return 0; +} diff --git a/demos/vgatweak.c b/demos/vgatweak.c new file mode 100644 index 0000000..a5260c7 --- /dev/null +++ b/demos/vgatweak.c @@ -0,0 +1,131 @@ +/* From VGAlib, changed for svgalib */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + + +#include +#include /* for usleep( long ) */ +#include +#include "vga.h" + +static unsigned char line[2048 * 3]; + +static void testmode(int mode) +{ + int xmax, ymax, i, yw, ys; + unsigned char buf[60]; + vga_modeinfo *modeinfo; + + vga_setmode(mode); + + modeinfo = vga_getmodeinfo(mode); + + printf("Width: %d Height: %d Colors: %d\n", + modeinfo->width, + modeinfo->height, + modeinfo->colors); + printf("DisplayStartRange: %xh Maxpixels: %d Blit: %s\n", + modeinfo->startaddressrange, + modeinfo->maxpixels, + modeinfo->haveblit ? "YES" : "NO"); + + vga_screenoff(); + + xmax = vga_getxdim() - 1; + ymax = vga_getydim() - 1; + + vga_setcolor(vga_white()); + vga_drawline(0, 0, xmax, 0); + vga_drawline(xmax, 0, xmax, ymax); + vga_drawline(xmax, ymax, 0, ymax); + vga_drawline(0, ymax, 0, 0); + + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(10 + i * 5, 10, 90 + i * 5, 90); + } + for (i = 0; i <= 15; i++) { + vga_setegacolor(i); + vga_drawline(90 + i * 5, 10, 10 + i * 5, 90); + } + + vga_screenon(); + + ys = 100; + yw = (ymax - 100) / 4; + for (i = 0; i < xmax - 1; i++) + line[i] = (i + 2) % 16; + line[0] = line[xmax] = 15; + line[1] = line[xmax - 1] = 0; + for (i = 100; i < ymax - 1; i++) + vga_drawscanline(i, line); + + if (getchar() == 'd') + vga_dumpregs(); + + + vga_getcrtcregs(buf); + + buf[0]=0x4d; + buf[1]=0x3f; + buf[2]=0x3f; + buf[3]=0x80; + buf[4]=0x41; + buf[5]=0x10; + + vga_setcrtcregs(buf); + for(i=0;i<20;i++) { + vga_setdisplaystart(i); + usleep(200000); + vga_waitretrace(); + } + + vga_getch(); + + vga_setmode(TEXT); +} + +int main(void) +{ + int mode; + int i, high; + + vga_init(); /* Initialize. */ + + mode = 4; + + if (mode == -1) { + printf("Choose one of the following video modes: \n"); + + high = 0; + for (i = 1; i <= vga_lastmodenumber(); i++) + if (vga_hasmode(i)) { + vga_modeinfo *info; + char expl[100]; + char *cols = NULL; + + *expl = '\0'; + info = vga_getmodeinfo(i); + cols = "16"; + strcpy(expl, "4 bitplanes"); + high = i; + printf("%5d: %dx%d, ", + i, info->width, info->height); + if (cols == NULL) + printf("%d", info->colors); + else + printf("%s", cols); + printf(" colors "); + if (*expl != '\0') + printf("(%s)", expl); + printf("\n"); + } + } + if (vga_hasmode(mode)) + testmode(mode); + else { + printf("Error: Video mode not supported by driver\n"); + exit(-1); + } + + return 0; +} diff --git a/demos/wizard.xbm b/demos/wizard.xbm new file mode 100644 index 0000000..73528af --- /dev/null +++ b/demos/wizard.xbm @@ -0,0 +1,45 @@ +#define wizard_width 67 +#define wizard_height 55 +static unsigned char wizard_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0x07, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0xf0, 0xfd, 0x0f, 0x00, + 0xa0, 0x24, 0x01, 0x00, 0x00, 0x78, 0xfc, 0x1f, 0x00, 0xd0, 0xb2, 0x01, + 0x00, 0x00, 0x18, 0xf8, 0x3f, 0x00, 0xc8, 0x9a, 0x00, 0x00, 0x00, 0x08, + 0xae, 0x3f, 0x00, 0x64, 0xfd, 0x00, 0x00, 0x00, 0x80, 0xff, 0x3f, 0x00, + 0xf8, 0xbf, 0x00, 0x00, 0x00, 0x40, 0xff, 0x9f, 0x1f, 0x20, 0xfe, 0x00, + 0x00, 0x80, 0xff, 0x00, 0xe0, 0x67, 0x20, 0x9c, 0x00, 0x00, 0xe0, 0xe0, + 0xff, 0xff, 0x80, 0x30, 0x4c, 0x00, 0x00, 0xd0, 0x87, 0xff, 0x07, 0x3e, + 0x39, 0x44, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x80, 0xff, 0x38, 0x23, 0x00, + 0x00, 0xf8, 0xff, 0x00, 0xf0, 0xff, 0x9c, 0x11, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0x3f, 0xdc, 0x08, 0x00, 0x00, 0x00, 0x3c, 0xdb, 0xe4, 0x0e, + 0xde, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x8c, 0x71, 0xfe, 0xdf, 0x0c, 0x00, + 0x00, 0xf0, 0xf7, 0x87, 0xbf, 0xfd, 0xee, 0x0c, 0x00, 0x00, 0xf8, 0xfb, + 0xcf, 0x3f, 0xfb, 0xee, 0x0e, 0x00, 0x00, 0xff, 0xaf, 0x7b, 0x07, 0x3e, + 0xd5, 0x1f, 0x00, 0xe0, 0x80, 0x57, 0xfd, 0x14, 0xae, 0xe7, 0x1e, 0x00, + 0x10, 0x0b, 0x3e, 0x74, 0x05, 0x9d, 0xcd, 0x1f, 0x00, 0xc8, 0x00, 0x5c, + 0x04, 0x81, 0x1f, 0x87, 0x1e, 0x00, 0x6c, 0x60, 0x18, 0x00, 0x00, 0x6e, + 0xf0, 0x1f, 0x00, 0x74, 0x30, 0x72, 0x01, 0x80, 0xbf, 0xec, 0x1e, 0x00, + 0x74, 0x00, 0x33, 0x00, 0x10, 0xff, 0xff, 0x1f, 0x00, 0xf6, 0x80, 0xb1, + 0x05, 0xa0, 0xff, 0xff, 0x1e, 0x00, 0xf6, 0xf8, 0xf9, 0x80, 0xe8, 0xff, + 0xff, 0x0f, 0x00, 0x66, 0x77, 0x7d, 0x13, 0xca, 0xff, 0x7f, 0x0f, 0x00, + 0x7e, 0x37, 0xfb, 0xbb, 0xde, 0xff, 0xff, 0x0f, 0x00, 0x76, 0x32, 0xfd, + 0xbf, 0xff, 0xff, 0xbd, 0x07, 0x00, 0x46, 0x92, 0xfe, 0xff, 0xff, 0xff, + 0xbf, 0x07, 0x00, 0x3e, 0xe4, 0xfb, 0xff, 0xff, 0xff, 0xfd, 0x03, 0x00, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x03, 0x00, 0xfc, 0xef, 0xfb, + 0xff, 0xef, 0xff, 0xfb, 0x03, 0x00, 0xfc, 0xef, 0xff, 0xff, 0xff, 0x7f, + 0xb7, 0x01, 0x00, 0xf8, 0x6f, 0xff, 0xfd, 0xff, 0xfe, 0x1f, 0x00, 0x00, + 0xf8, 0x6f, 0xff, 0xff, 0xef, 0xff, 0x02, 0x00, 0x00, 0xf8, 0xbf, 0xff, + 0xfd, 0xff, 0xfb, 0x07, 0x00, 0x00, 0xf0, 0x97, 0xff, 0xff, 0xdf, 0xef, + 0x1f, 0x00, 0x00, 0xe0, 0xe3, 0xf7, 0xde, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0xf8, 0xdf, 0xff, 0xff, 0xdf, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xef, 0xff, 0xff, 0x03, 0x00, 0xe0, 0x1f, 0xf8, 0xdf, 0xff, 0x7d, + 0xc0, 0x07, 0x00, 0xf0, 0x4f, 0xf4, 0xef, 0xf7, 0x9b, 0x90, 0x00, 0x00, + 0x00, 0x83, 0xef, 0xff, 0xfd, 0xef, 0x0b, 0x01, 0x00, 0x00, 0xd5, 0x80, + 0xff, 0xff, 0x00, 0x5e, 0x03, 0x00, 0x80, 0x38, 0x00, 0x78, 0x00, 0x00, + 0x70, 0x04, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x04, 0x00, + 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; diff --git a/demos/wizardmsk.xbm b/demos/wizardmsk.xbm new file mode 100644 index 0000000..4ae14b8 --- /dev/null +++ b/demos/wizardmsk.xbm @@ -0,0 +1,45 @@ +#define wizardmsk_width 67 +#define wizardmsk_height 55 +static unsigned char wizardmsk_bits[] = { + 0x00, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x1f, 0x00, + 0xe0, 0xff, 0x01, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x03, + 0x00, 0x00, 0xfc, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x03, 0x00, 0x00, 0xfe, + 0xff, 0x7f, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, + 0xfe, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0x03, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0xf0, 0xff, 0xc1, 0xff, 0xff, 0x01, 0xff, 0x1f, 0x00, 0xe0, 0x7f, 0x00, + 0xfc, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; diff --git a/doc/0-INSTALL b/doc/0-INSTALL new file mode 100644 index 0000000..71371f7 --- /dev/null +++ b/doc/0-INSTALL @@ -0,0 +1,255 @@ +Installation of Svgalib v1.2.12 or higher. + +Table of contents: + 0. Introduction + 1. Directories + 2. Installation + 3. SVGALib port to ALPHA AXP hardware + +0. Introduction + This is a low level graphics library for Linux, based on VGAlib 1.2 by + Tommy Frandsen. VGAlib supported a number of standard VGA graphics + modes, as well as Tseng ET4000 high resolution 256-color modes. + Nowadays support for even more hardware is given. For details on + supported chipsets, see the file 0-README which is equal to man 7 + svgalib (when svgalib is installed). + + It supports transparent virtual console switching, that is, you can + switch consoles to and from text and graphics mode consoles using + alt-[function key]. Also, svgalib corrects most of VGAlib's textmode + corruption behaviour by catching SIGSEGV, SIGFPE and SIGILL, and + ensuring that a program is running in the currently visible virtual + console before setting a graphics mode. Svgalib uses SIGUSR1 and SIGUSR2 + internally to do so. + + When the library is first used by a program at run-time, the chipset is + detected and the appropriate driver is used. This means that a graphics + program will work on any card that is supported by svgalib, if the mode + it uses is supported by the chipset driver for that card. The library + is upwardly compatible with VGAlib. + + The set of drawing functions provided by svgalib itself is limited + (mostly unchanged from VGAlib) and unoptimized; you can however use + vga_setpage and graph_mem (which points to the 64K VGA framebuffer) in + a program or graphics library. A fast external framebuffer graphics + library for linear and banked 1, 2, 3 and 4 bytes per pixel modes is + included (it also indirectly supports planar VGA modes). See 'man 7 + vgagl' for details. + + One obvious application of the library is a picture viewer. Several are + available, along with animation viewers. See the references at the end + of 0-README. + + I have added a simple VGA textmode font restoration utility + (restorefont) which may help if you suffer from XFree86 textmode font + corruption. It can also be used to change the textmode font. It's in + the utils/ directory, along with a README and some other textmode + utilities: restoretextmode (which saves/restores textmode registers), + restorepalette, and the script textmode. If you run the savetextmode + script to save textmode information to /tmp, you'll be able to restore + textmode by running the textmode script. + + If you have an ET4000 card, you should read the 0-README in the et4000/ + directory. You will probably want to replace the ET4000 registers. + +1. Directories + doc/ README's and man pages. See the 0-README in this + directory for info on how to read these man pages + without installing svgalib and how to produce nice + printouts. + demos/ Demo and test programs. + utils/ Textmode/font utilities. + src/ Main library source. + src/mouse/ Source for mouse interface. + src/keyboard/ Source for keyboard interface. + gl/ External framebuffer graphics library sources. + support/ DOS-based utility for dumping VGA registers. + et4000/ Notes, utilities and sample registers for ET4000. + mach32/ Notes and a utility for the ATI mach32 driver. + jump/ Configuration files for building DLL shared library. + sharedlib/ Shared library image and stubs. + threeDKit/ Routines to draw 3-dimensional triangles and + 3D demos using these. + lrmi-0.5m/ Linux real mode library (used for VESA driver) + including a utility for restoring text mode + + I welcome any questions, comments, suggestions, bug-reports, etc. + + The source code is rather a mess, but there's hope. The new XFree86-style + driver interface (used by the Cirrus and S3 drivers) and kernel module + graphics that some are experimenting with should provide some momentum. + + Harm Hanemaayer + hhanemaa@cs.ruu.nl + + Current maintainer is + Matan Ziv-Av + +2. Installation + If you are happy with the configuration in 'Makefile.cfg' which means + that you want to install an ELF shared library and probably an a.out + shared library for support of some old binaries (and if the svgalib tar + file you got already contains such an precompiled a.out shared library) + just running + + make install + + as root should take care of proper installation. After installation, + you MUST edit /etc/vga/libvga.config to set the monitor and mouse type. + Depending on your hardware, other setup might be required. Checkout + 'man 7 svgalib' for details after you installed svgalib (or see + doc/0-README) + + It is a good idea to read and check the configurable section of + Makefile.cfg nevertheless, even if you don't think you have to. Also, + if your are using GLIBC you have to uncomment the definition of + USEGLIBC in Makefile.cfg as glibc is not completely compatible to the + linux libc (at least at compile time). + + Let me rephrase this: YOU MUST COMPILE AND INSTALL AS ROOT. + If you don't nothing bad will happen during compilation, but certain + tools won't be able to become SETUID ROOT which is required for + proper operation. + + In case you change anything in 'Makefile.cfg' which does not just control + which parts to install and where, you *MUST* issue a 'make clean' prior to + 'make install' to remove any already compiled objects and force complete + recompilation. + + Edit Makefile.cfg to change installation paths and to select the parts + that should be installed. + + If you have an ET4000 card, read 'man 7 svgalib.et4000' and copy the + appropriate register file to et4000.regs. Remember to set the DAC type. + + The default behaviour is the following: + + Shared libraries are installed in /lib and /usr/local/lib, header files + in /usr/local/include (any old header files in /usr/include are + removed). In the Slackware distribution the linkable libraries are in + /usr/lib, and the utilities in /usr/bin; these are now removed by 'make + install'. Until now just doing make install with Slackware might have + produced duplicate binaries, but fortunately the newer version in + /usr/local/* would have taken precedence in use. + + The et4000 registers (et4000.regs) are installed as + /etc/vga/libvga.et4000, but only if this file does not exit yet. The + same goes for the configuration file, libvga.config. + + Textmode utilities are installed in /usr/local/bin. These are + restorefont, runx, restorepalette, dumpreg, restoretextmode, textmode, + savetextmode, fix132x43, and mode3. + + If you change Makefile.cfg to install the static libraries, static + libraries are compiled, and installed in /usr/local/lib. Note that you + do not need to do this; the shared library is enough. + + If you now run 'make demoprogs', the demo programs are created in the + demos/ and threeDKit/ directory. If you + + You can remove previously installed files (not the et4000 registers and + config file and manual pages) with 'make uninstall'. + + In 1.28 the makefiles were changed. With minimal effort you can compile + it from a separate (even read-only) source tree. Just make a copy of + Makefile and Makefile.cfg into a writable dir, and change srcdir (or + override from environment) to the directory where the source code is. + + This feature, as well as the code for ELF compilation was kindly + contributed by Stephen Lee . + + `make static' compiles a static version of svgalib. It is not + automatically installed by default but you can enable that from + Makefile.cfg. Note though, that if you specify installation of the static + libraries in 'Makefile.cfg' a simple 'make install' will compile the + static library first. + + If you do not configure Makefile.cfg to install the shared libs, the + demoprogs and utilities are linked against the new static lib + (regardless of one already installed). However, the static libraries are + not build automatically then. You must issue a 'make static' first. + + Building elf or a.out shared libraries can easily be configured in the + Makefile.cfg. Be sure to issue a `make clean' after changing the + TARGET_FORMAT setting. + + If you specified elf, `make install' will compile the shared libs as + they don't come pre-built. This is nothing to worry about. Compilation + is easy and will not use any user action. + + This is not true for a.out and there is a special hack in the makefiles + for this. As svgalib is distributed there is no attempt to recompile the + a.out sharedlibs. Prebuild images are already included. + + If you have the required tools-* installed and if you made patches (or + just feel like recompiling) issue a `make clean' and `make shared' to + enforce recompiling of the a.out sharedlibs (from then on even a make + install will update the shared library if sources changed). Issue `make + distclean' after a `make shared' to fall back to the distribution + behaviour. + + However, getting the right tools becomes more and more complicated as + it gets less important to give a.out support. Right now you even have to + hand patch the last tools-* release to make it usuable with current + compilers. In general I discourage trying to compile the a.out libs. + Just use the images that come with svgalib. + +3. SVGALib port to ALPHA AXP hardware + David Mosberger-Tang contributed patches to make + SVGALib run on Linux/Alpha namely APECS-based and low-cost PCI boards. + + It is known to run with #9 GXE (but all S3-based graphic cards should + work if they are supported). He wrote a patch to make SVGALib run on + Jensen boards. They own EISA slots instead of PCI slots and can not map + video memory as a continous frame buffer. Use this patch with extreme + care (do sync disks before starting compiled software for the first + time!). He also recommends using SVGATextMode in combination with + SVGALib-based software otherwise the library crunches the font + (although the system should not crash). Here is a list of what is not + supported yet: + + - vc-switching (due to lack of some signals supported by current ALPHA + kernels but this could be fixed now [He used a 1.3.28 to test]) + - font restoring without SVGATextMode (He still works on it) + - clearing screen in mode 320x200x256 + - vgagl (will never be ported by me because he thinks it is too much work + and useless in the end) + + He tested his patch with an ELSA Winner 1000 but it should even work on + other cards (He recommends to always sync disks, it saves a lot of time + and sweat :-) ). + + If you compile it on a machine where __alpha__ is defined, you should + have configured your kernel correctly once. This is due to the fact + that he saw no other possibility to determine the type of ALPHA AXP + hardware you use. During kernel configuration your are asked which + architecture you want to compile it for. + + Also important: you must have the right libc compiled for your board + hardware. This is due to the I/O functions in libc. They need to be + compiled especially for your Alpha board. Have a look at + ftp.azstarnet.com for precompiled libc's (although this is not very + reliable, most of the libc-packages are sources). + + Note that he feels __not__ responsible for damage to your hardware when + using this software. If you encounter any problems that refer to + Jensen-type hardware you can send an email to me: + + If you encounter any problems that refer to Jensen-type hardware you + can send an email to: + Stephan Kanthak + + Here are some additional comments Michael Weller wrote on the first + ALPHA patches from David Mosberger-Tang: + + No reports of other hardware working or not exist yet. This is REAL + ALPHA software. I don't know any installation details. In theory you + just recompile it out of the box (When you are using Linux/Alpha you + are a hacker and should be able to create a shared lib w/o problems). I + don't know any details, in case of problems please contact David. + + From what I saw you might have to use static libs. That's no real + problem, a simple 'make static' will create a static lib. + + The background mode is said not to work on Dec-ALPHA, so you better + disable it in Makefile.cfg diff --git a/doc/CHANGES b/doc/CHANGES new file mode 100644 index 0000000..a50cc48 --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1,1036 @@ +Changes after 1.4.1: + +Bryan Henderson: + fix vgatest for small modes and vgatest man page to describe test pattern. + +PinkFreud: + fix g400.c to accept user specified amount of memory. + +Ryan Rubley : + mode 145 (400x300x256 mode X) + Change all drivers to test for standard vga modes with a macro. + +Don Secrets: + hardware cursor support for et6000 driver. + +Michael Glickman : + cleanups in kernel/svgalib_helper/Makefile + +Chris Purnell : + fbdev driver. + Intellimouse Explorer PS/2 mouse driver. + +Hans de Goede : + fix vesa.c for modes where logical width is not the minimum necessary. + +Morris Michael Slutsky : + A new mouse driver for DR mouse with two wheels. (DRMOUSE4DS) + +Yury Starkov : + fix banshee.c setdisplaystart(). + fix gl_enablepageflipping() call in demos/fun.c + +Bartlomiej Zolnierkiewicz + remove compiler warnings from + gl/inlstring.h + src/ark.c + src/chips.c + src/et4000.c + src/joystick/joystick.c + src/mach32.c + src/mx.c + src/timing.c + src/vgacursor.c + src/vgapal.c + Other miscellaneous cleanups. + +Tijs van Bakel + added SVGALIB_HELPER_IOCSREPOUTB ioctl in kernel module, and port_rep_outb in + svgalib_helper.c in order to speed up vga_setpalvec(). + +Bart Oldeman : + vga_simple_init, vga_chipset_setregs, vga_chipset_saveregs - for dosemu. + fix sis driver to program 25 and 28MHz clocks correctly, in case + bios misporgrammed them. + +Klaus Stehle : + Fix gl_writen to behave as per the man page (not stop at nul char). + +Ben Winslow : + support for Wacom Graphire tablet/mouse. + +malekith@ikar.mps.com.pl: + support for mouse type pnp (explanation of this type in gpm). + +Krzysztof Nikiel : + move mouse_init to vga_init (before giving up root privileges), and + not closing mouse upon return to text mode. This enables svgalib + programs to use the mouse device even when the device is only readable + by root. + +Matan Ziv-Av + Banshee fixes to support high resolution modes. + nv3 fix to support nv3 (Riva128) cards again. + nv3 fix to restore memory page number. + fix gl_hline to do nothing if x1>x2 (rather than segfault) + man page. + workaround for double clock speed for some rage cards + cursor support: example in demos/cursor.c + software cursor in vgacursor.c + hardware cursor in mx.c nv3.c rage.c i740.c sis.c banshee.c, etc. + removed all BACKGROUND support. + vga_flip now saves the graphics state, and does not depend on setmode only. + third button support on ms compatible mice + laguna driver for cirrus 546X chipset. + millennium and g400 drivers for Matrox cards. + rage 128 driver. + savage driver for S3 savage cards, as well as trio and virge cards. + trident driver for PCI Trident cards. + fix memory leak in _modeavailable in some drivers (found by Robin). + + +Changes in 1.4.1: + +Shigehiro Nomura : + neomagic driver. + +Jay Link : + Functions gl_fillcircle(3) and gl_bcircle(3), for greater flexibility. + Main algorithm of gl_bcircle(3) provided by Chris Atenasio: + . + +Sergey A. Kononenko : + s3 driver update to support linear mode with Trio64 + small fixes. + +Matan Ziv-Av: + sis, banshee, i740 drivers. + nv3 updated for TNT and GeForce. + scitech's gtf in timing.c (not used yet). + vgapci can now be used to find more than one vga card. + +Robert J. Ragno : + fix compile problems with gcc-2.95 + +Greg Alexander + add support for fourth button of Trackman Marble. + + +Changes in 1.4.0: + +Matan Ziv-Av + vgapci uses /proc/bus/pci kernel interface, when available. + Rage driver. + Added static modes. + Extended dynamic mode creation with vga_addtiming(3), vga_guesstiming(3), + vga_addmode(3) and newmode config file option. + Functions vga_cetcurrenttiming(3) and vga_changetiming(3), for mode + tuning at runtime. + All mmaps of /dev/mem are done by driver initialize function and + vga_init, so /dev/mem file descriptor is closed when relinquishing root + privileges. + Moved mach64.c driver to a different directory. + vga_reset utility added to facilitate restoring textmode without + rebooting, in case svgalib fails to do it properly. + +Christian Groessler : + Chips&tech driver fixes. + Changing vga_setlinearaddressing to return error when in mode that does + support linear. + +Luke Angel : + FPC (Pascal) demo. + +Don Secrest : + Rewrite of et6000 driver to comply with newer svgalib driver interface. + +Russell Marks : + Fixed bug in console switching when in background mode (it used to + effectively disable console-switching after the first switch, which + broke zgv). + Made vga_getscansegment() and vga_drawscansegment() work correctly + for non-4-pixel-aligned x locations in mode-X modes, and made + mode-X vga_getscansegment() set page to *read*, not write. + + +Changes in v1.3.1: (16 Aug 98): + +Wichert Akkermann & Kevin Vajk : + Ensure stdin/out/err don't point to sensitive files (/dev/mem) by accident. + +David Bateman : + C&T: Added support for 65555, 68554, 69000 and 64300 chips + Some smaller fixes (65554 memory probing, max. pixel clock) + +David Grant : + Remove some egcs warnings. + +Christian Groessler : + C&T: Further 65550 enhancements, fix text-mode stretching. + C&T: does not need iopl(3) anymore. + map_framebuffer() also works for non root now. + vga_setmode() typo fixed + Increase buffers for vgapci + +Bernd Schmidt : + Lrmi.c support under egcs, nested int calls. + +Don Secrest : + Support for linear frame buffer. + +Scott Stone : + Glibc adaptions for lrmi.c. + +Brion Vibber : + Variation of lrmi glibc adaptions. + +Matan Ziv-Av : + Minor apm/nv3/vesa patches. + Vgapci enhanced (some buffer sizes changed). + MX driver added. + TextProg option added. + +Changes in v1.3.0: (11 June 98): + +Daniel Engström : + Provided an svgalib-style joystick driver. + +Harald Hoyer : + Readjust speed for certain Logitech Mousemen. + +Jan Hubicka : + Some internal additions for cards with no VGA functionality. + +Elliot Lee : + Yet another ViRGE/VX id for autodetection. + +Attila Lendvai (101) <101@kempelen.inf.bme.hu>: + Logarithmic mouse acceleration. + Mouse acceleration config by config file. + Rename GSVGAMODE to SVGALIB_DEFAULT_MODE + Parse ~/.svgalibrc and SVGALIB_CONFIG_FILE. + Mouse emulation in raw keyboard mode + Changed his email + +Lalo Martins : + Fix misinterpretation of monitor freq limits in Mach32 interlaced (fix + generalized and applied to a related code segment as well: eowmob, below) + +Marek Mintal : + Fixed gl_copyfrom/tocontext in more than 8bpp. + +Don Secrest : + ET6000 Support. + A tiny ET4000 fix. + +Trek , : + Added gl_printf. + +Brion Vibber : + Added Intellimouse support, PS/2 and serial. + Fake keyboard events for using wheel with legacy apps. + Updated mousetest demo to do something with middle button and wheel (RX axis). + Added limited keyboard layout remapping for raw keyboard. + +Michael Weller : + demos/Makefile misused $* in chown accel and others. + Makefile now robust for comments in /etc/ld.so.conf (Problem cause/fix found + by ) + Makefile failed to remove certain library stubs not removed by ldconfig on + Slack 3.3 reported by Jacek Tokarski + Various rewritings of gl_printf(). + Documentation fixes. + Mach32 lowered iopl() accidently on occasion. + Allow disabling sigint in graphicsmode. + Made apm test more grateful to VGA cards. + Mach32 proper accel bitmap (RD_MASK) in 32K colors. + Allow joystick sharing and multiple joystick support, bind joystick + interface into svgalib. + +Matan Ziv-Av : + Added apm driver for AT3D. + Added nv3 driver for Riva128. + Added a driver for 'nicely behaved' Vesa bioses. + +Changes in v1.2.13: (4 Dec 97): + +Pekka T. Alaruikka & Michael Friman : + Modified the VC switch queue & other clean up. + +Mike Chapman : + Added mouse acceleration. + +Ryan Rubley : + Added TVGA9440 support. + Provided trap-out tool. + +Frodo Looijaard : + Email changed. + +Michael Weller : + Fix the 512 chars console font fix. + +Changes in v1.2.12: (4 Sep 97): +Pekka T. Alaruikka & Michael Friman : + Fix a bug in the background mode support, introduced by Michael. + Optimizing speed of the background mode support. + +Greg Alexander: + Autodetect S3Trio64V2/DX. + New 640x480 example timing. + +Ricardas Cepas + Save 512 chars of console font (needed for newer kernels). + +Michael Talbot-Wilson : + Some more glibc modification & success reports. + +Michael Weller : + Transformed all README's in a bunch of man pages and even documented + previously unknown stuff. + Makefile modifications to allow installation of man pages. + Makefile modifications to ensure default configuration is for ELF. + Fixed accelerated gl_fillbox for more than 8bpp problem reported by + Anthony Chu + +Changes in v1.2.11: (29 Jun 97): + +Pekka T. Alaruikka & Michael Friman : + Background mode support. + +David Bateman : + Support for Chips & Technologies 655xx chipsets + +Gary Clark : + Allow S3 virge to be autodetected as S3 Trio 64 + +Jeff Epler : + Allow for coexistance of GPM and svgalib + +David Goldsmith : + Pointed out buffer overrun security flaws using saved uids and provided a fix. + +H. Hanemaayer : + Some Cirrus 5436 fixes and changes to mode timings for Cirrus + Remove lock from a few Ark registers. + +Dr Stephen Henson (former Stephen Henson + ): + Fix an ELF/gcc flaw in inlstring.h (former BugsNotFound) + +Ron Koerner : + Enhanced ALI driver. + +Jae-Hyuck Lee : + Makefile problems (probably due to new gmake, used to work b4). + +Stephen Lee : + Detects the Trio64V+. + A few patch to Trio64 RAMDAC code to make it work better on the V+. + +Robert Lupton : + Typo in vga_waitevent(). + Possible race condition releasevt_signal() when restoring signal. + +Szeredi Miklos : + Reset keystates on a VC switch in keyboard.c + +David Mosberger-Tang : + Some (more) changes for clean Linux/Alpha support. + +Tomi Sarvela : + Added support for Cirrus 5436. + +Paul Sheer : + Gl line drawing routine with inlined set_pixel. + +Lodewijk Voge : + Autodetect Hercules Stingray 64/Video as ark2000pv. + +Vernon C. Hoxie : + Solved (hopefully) the Mach32-AST problem. + +Michael Weller : + Search free console on startup as zgv did. Should also fix a problem with + /dev/tty & zgv on newer kernels (reported by Mike Castle ). + Various Makefile fixes and changes. (Most useful reports by: + Kieron Brown & + Don Secrest ) + +Oliver White : + Fix typo that broke G1024x768x32K and G640x480x16M32 and higher in ark.c + +Eric Sharkey : + Added 6-D mouse support + Added Spacetec Spaceball/Spaceorb mouse protocol (special thanks to + Brett Viren for reverse engineering + this protocol and providing many lines of code which I've included + in svgalib) + Added spin demo, adapted and expanded from the original spin program + by Jason Lyons + Added mdev config file option to set mouse device + Fixed scale bug in mouse_setposition() + +Changes in v1.2.10: (20 Mar 96) + +Andreas Arens : + Support for new S3 clockchip ICD 2061A in a new clockchip module. + Sierra SC1148X ramdac support + Sierra SC15025 ramdac support + New `DacSpeed' config option + Fix for 928 modes. + +Stefan Kanthak : + Several changes for support of Alpha _JENSEN_ system as well. + +Stephen Lee : + Makefile patches: + - LFLAGS is for lex, use LDFLAGS instead. + - Changed default target. + - Create symlinks for new binutils. + - Moved ramdac and clockchip into their own directory. + - 3dkit can now compile in a separate directory. + - use $(CC) $(INCLUDE) instead of just gcc for making dependency files. + Cleanup ATI driver (also fix for a buglet). + Partial S3 868 support. + SDAC 24bpp support (probably wouldn't work with 864, though). + Allow 1152x864 & 1600x1200 modes for drivers that can use modeline + in libvga.conf (e.g. S3). + S3 4bpp doesn't like Linear Bank Switching. + SDAC doesn't seem to do pixel multiplexing at 4/8bpp. + ramdac.c bugfix and cleanup. + okay, so some people still have pixel swapping problem on the 805. (sigh) + I've put in an experimental fix for it. + split ramdac.c into individual files. + 968/IBMRGB support. Only 256 colors for now. + Merged Trio64 patch from Moto Kawamura . + Changed handling of S3 CR34 for VGA modes at Andreas' suggestion. + Updated libvga.config and README.config. + Small fix for libvga.h macros. + Rewrote __vga_dumpregs(). + +Bill Randle : + Patches to allow compiling only some of the ramdac drivers. + Enhanced vga_drawscansegment() to remove it's limitations. + New function: vga_getscansegment(); + Allow intermixing of vga_setpalette()/vga_getpalette calls. + +Tomi Sarvela : + Some more scancodes for vgakeyboard.h + +Paul Sheer : + Routine to draw quick triangles and some 3d demos in 3dkit/ + +Erik Troan + Renamed a read[bwl] and write[bwl] for ALPHA support under latest kernels. + +Michael Weller : + Fixed security leak from linux-security@vger in restorefont -r. + Fixed Fix for vgapal.c so it started working again. Added index register sets + back to vgadrawscansegment for ATI SVGA cards. + Cleaned support to compile only few RAMDACS in (still not happy with it though) + Even more scancodes to vgakeyboard.h + New function vga_waitevent() plus eventtest demo due to request for libgrx by + Daniel Lee Jackson (although there was no such + flexible solution required) + Docs for vga_(draw/get)scansegment(), vga_waitevent(); + +Changes in v1.29: (11 Nov 95) + +Stephen Lee : + Minor Makefile patches. + 16 color modes work on the S3 805. + +Scott Snyder + Fix to have Mach32 not remap the location of some ELF libs (modified by Michael). + +Heiko Schroeder + Implemented a modeline config command for libvga.conf to userdefine + modes for all drivers using timing.c + +Andreas Arens : + ET4000 patches to avoid problems with 132 column consoles and with IOPERM + in ET4000/W32. + RAMDAC (SC15025) for S3 + +Ron Koerner : + New driver for ALI2301 (keyword: ALI) cards in all SVGA 256 colormodes. + +Peter Ekberg + Waiting for console activation could be interrupted by signals. + +Michael Weller : + Fixed fix of Oak, modifies mode timings depending on detected chipset + Minor typo in egadrv.c + Documented unavailability of SIGUSR1/2 as Peter suggested. + Fixed a problem in raw keyboard mode noticed by Stephen (matter of + seconds coz of good description) + +Changes in v1.28: (7 Oct 95) + +Koen Gadeyne : + Typo for S3 genDac (S3 SDAC, S3 Trio) made all clocks unusable. + Support for 24bpp (true-color) on S3 805 cards with GenDAC. + +Honza alias Jan Hubicka : + Possible segfault in gl/cbitmap, fixed gl_regioncode for clipping + on Dec Alpha. + +Sven Grothklags : + Bugfixes for compressed fonts in vgagl. + +Stephen Lee : + Several pixel swapping fixes on S3-805, New Dacspeed keyword for ATT20C490 + Changed monitor setup to accept seperate h/vsync values (see README.config), + Reintroduced lost (?) et3000 support in distribution shared lib. + Rejoined ELF/a.out Makefiles, in fact rewrote all Makefiles. + Again many code cleanups to pass -Wstrict-prototypes + +Michael Weller : + Fixed confusion about termios setting between keyboard.c and vga.c (console + lockup at -Enter) + Catched ALL fatal signals for gentle touch down. + Patched mach32 to accept new h/vsync monitor setup. + Some tiny a.out patches to Stephen's Makefile's + Even more code cleanups. Now EVERY sourcefile passes -Wstrict-prototypes + and even the esp. pedantic warnings of my vanilla a.out gcc 2.6.3 + (who seems to be more pecular than other compilers) + Reformatted ALL sources due to requests. + Minimal fix to allow using chipset ATI on Mach32 (doesn't give you much, + though) + vga_safety_fork() enhanced, uses iopl now. (which has its own security issues, + see README) + +Frodo Looijaard : + Fixed Oak driver to support Oak-67 again. Note: The fix might have broken + Oak-87 support by accident. + +Christopher Wiles : + Slight modifications of above Oak fix. + +Peter Ekberg : + Some more scancodes in vgakeyboard.h and doc fix for vga_getkey(); + +Changes in v1.27: (21 August 95) + +Mach32 related changes(M. Weller ): + cosmetic fixes, new config commands svgaclocks, ramdac, vendor to + help support alien (not conforming to original ATI specs) cards + (should work for dell now). Fixed several NULL ptr dereferences + that delurked under ELF. + +David Mosberger-Tang : + Patches to make svgalib work on Linux/Alpha. (Only known to work with #9 GXE + PCI, other cards may or may not work) + +Harm Haanemayer : + Change duplicate include check vgamouse.h. + Fix bug in gl_getpixel in 3-bytes-per-pixel modes. + Allow ctrl-c detection to be disabled in raw keyboard interface. + +Gregory Margo : + Support for the Logitech Mouseman mouse series. + Override mouse mode from environment (SVGA_MOUSE_OVERRIDE) (useful for doom) + +Stephen Lee : + ELF support, countless patches for code clean up, bugfixes in S3 15/16/24 bpp, + autodection for more chips (but alas, no support for them) + +Moved config files to /etc/vga due to requests, patched makefiles for automatic + reconfiguration. (M. Weller ) + +Changes in v1.26: (27 April 95) + +Really fix console-switching in raw-keyboard mode. +Fix SDAC support. +Fix Trio64 detect. Modes don't work though (use Ramdac "normal"). +Move ET4000 chiptype detection so that it works when chipset is +forced in config file. +Fix Cirrus 5420/22/24 support. +Mach32 related changes: +Minor typos in mach32info fixed. 68800-6 should now be reported correctly. +Fixed compiler warnings in mach32.c due to changed interface (no new accel +interface yet). +Newflag for red first in 24bpp returned for Mach32 with DAC 4 +Support for 24bpp red first in whole svgalib + vgagl. +Added support for 32bpp in vgadraw.c +Added detection for 24bpp red first in vgatest. +TODO: Fix raw-keyboard console switching when alt is kept pressed (e.g. +Doom). + +Changes in v1.25: (7 March 95) + +Problem with programs that don't call vga_init finally fixed. +Fix console-switching in svgalib raw-keyboard mode (vgakeyboard.h). +Working ARK driver (includes acceleration). +Linear addressing detection changed (supports partial framebuffers). +Add more RAMDAC support -- AT&T490-compatible truecolor DACs supported +for S3. +Tweak mouse/keyboard header files to fix conflict with libgrx compile. + +Changes in v1.24: + +Fix bug causing "not running in ..." messages if vga_init wasn't called. +Better structure for driver interface ("DriverSpecs"). Fields other +than the basic driver functions can be included. Type checking is also +better. Most drivers haven't been updated for the new return types; +feel free to send patches. Something might be broken, watch out. +Better acceleration inferface. +Fix ARK chiptype detection. +Untested ARK chip support. +Largely fixed S3-864 + SDAC support. +Untested clock/DAC support for the Trio64 in the S3 driver. +Unlock extended registers when forcing Cirrus in config file. +Try to avoid Cirrus hardware lock-up when switching certain modes. +Add "accel" program to test new acceleration interface. + +Changes in v1.23: (8 Feb 95) + +ET4000/W32 tweaks. +Added gl_allocatecontext. Use this instead of declaring GraphicsContext +variables statically. Demo programs changed accordingly. +Safer VC switching with blits. +Allow Cirrus SVGA modes with 512K memory. +Possible Cirrus 5422 MCLK detection fix. +Incorporate ATI 'driver' from Scott Heavner (allows VGA with 132-column +textmode). +Untested ARK driver and untested generic S3 support (640x480x256 @ 60 Hz). +Unused acceleration interface sketch (accel.h/cirrus.c). + +Changes in v1.22: + +ET4000 additions for STG170x DAC (tseng3.c and driver), linear addressing +support for W32p, better general linear addressing handling with new driver +function, 8-bit color components CLUT support for AT&T DAC (David +Etherton). +Cirrus driver tweaks. +S3 driver rewritten for S3-864 + SDAC (doesn't work yet) using new +interface. +Linear addressing probing with vga_setlinearaddressing. Console switching +is not a good idea with linear addressing enabled. +Treat Oak 077 as standard VGA (incompatible with OTI-087 mode dumps). +Fix planar getpixel (untested). +VC switching in RAW keyboard mode (e.g. Doom) (doesn't always work) +[was typo, fixed in 1.25]. + +'VGAGL' status: + Should be usable seperate from svgalib with minor changes. + GraphicsContext should be allocated dynamically (malloc) + by library for compatibility/extensibility. + Non-expanded font text write functions added (untested...). + Missing is proper direct page flipping support (double-buffering + in video memory). This would require all operations to be + performanced at a certain offset into the framebuffer. + +Changes in v1.21: (23 Dec 94) + +Partially restructured Cirrus driving using clean, XFree86-style +SVGA-generalized interface. Check out timing.*, vgaregs.* and cirrus.c. +Cirrus driver itself should now support all 542x/543x cards. +Fix MouseSystems movement overflow. +Fix PS/2 mouse support finally (sorry). +Fix (old) Logitech protocol mouse handling (hopefully - I lost the +message that contained the fix). +Fix Cirrus bitblt bug. +gvga6400 driver BIOS check changed; munmap seems to mess things up. +Add vga_getpixel() (untested). +Incorporate restorepalette patch from Charles Blake, allows custom +textmode console colors (see utils/README). + +Changes from Michael Weller: +Made GSVGAMODE parsing case insensitive, and added names for 16M32 modes. +vgatest displays info about 16M32 modes better. +mach32 - Support for 8bit clut on type 2 DACS. +Added testaccel demo. +mach32 - Support for all accelerator functions. +Added vga_hlinelist(), vga_blitwait(), vga_ext_set(), [vga_accel()] +mach32 - eeprom interpretation more robust and configurable for stupid AST + boards. +mach32 - changed 16M4 -> 16M32 for compatibility +Fix: reserve memory for one screen on EACH setmode call (as the README + states). +mach32 - Added support for AST style EEPROM checksums. +Added commands to control RTS/DTR lines for multiprotocol mice. +Fix: mach32 - VGA modes should work now even in 132 columns text modes. +Sanity check for MAX_REGS in vga.c +Fix: Raised MAX_REGS as was actually needed. +Fix: Textmode utils now give errors on problems with accessing files. +Fix: Restore of Mach32 regs after clock probe was broken (cosmetic, no + problems reported). +Fix: Mach32 Dac1&4 have to use double/triple clocks in 16/24bpp. + + +Changes in v1.20: (25 Nov 94) + +Clean up VT code a bit. +Slight ET4000/W32p detection fix. +Possible mach32 32bpp copyscreen fix. +Allow VT-switching with mouse support (it was disabled because of +interaction with an old version of selection, I take it things are +better now?). +Preliminary Cirrus 5434 support (untested, only 1280x1024x256 for now), +will be fixed soon. +New Oak driver (Christopher Wiles). +Use seteuid instead of setuid to give up setuid-root permissions. +Hack that may fix 132-column textmode/VGA mode problems on ET4000. +Fix color/mono config option (mono was broken). +Disable 320x200x256 page flipping for ET4000. +Fix Cirrus fillblt register corruption problem. +GVGA6400 driver (Arno Schaefer). +vga_init now returns -1 if not on a suitable console (0 otherwise); hard + exit can only happen in vga_setmode (David Liu). This should help + programs with multiple output devices like gnuplot. +Added mouse_init_return_fd and keyboard_init_return_fd for select() use. +Add SIGKILL catch to raw keyboard interface. +PS/2 mouse support possibly fixed. +Shared library 1.2.0 (corresponds with main svgalib version number). + + +Changes in v1.12: (17 June 1994) + +Delay console checking until actually setting a mode (should fix problems +with device-probing programs like gnuplot). +Fix planar mode getmodeinfo bug for Trident and others (should fix floating +point exceptions in zgv). +Support PS/2 mouse in config file. +Fix one-byte-per-pixel gl_putboxmask. +Shared library 1.1.8. + +Changes in v1.11: (19 May 94). + +Better fix for ET4000/W32 auto-detection. +Fix typo that prevented ET3000 auto-detection. +Clipping bug with compiled bitmaps fixed. +Shared library 1.1.7. + +Changes in v1.10: (9 May 94) + +Possible fix for ET4000/W32 auto-detection (does iopl(3) now). +Logitech mouse fix. +Repeated keyboard_init/keyboard_close fix. +vgagl fixes for mach32 'misordered' 32bpp truecolor and 32bpp paged fillbox. +mach32 - Forgot to disable write mask for VGA framebuffer (zgv2.2 screen + corruption after online help) +mach32 - Wrong assumption about BIOS enabling the mem aperture.. was actually + done by Xfree.. driver will setup linear framebuffer itself using + info from the EEPROM now. +mach32 - added mach32/mach32.std-modes info file.. +mach32 - ran a spell checker over my README's to throw away the worst errors. +mach32 - Patched vgapix for correct RGB_MISORDERED support. +mach32 - This needed an additional global for the modeinfo-flags (short cut is MODEFLAGS). +mach32 - Changed blankadjust for 32bpp modes and DAC-type 2. +mach32 - Patched mach32 autodetection code. +mach32 - Changed 32bpp setting at all by defining a new dacmode (needed for dac-types 5) +mach32 - Changed VFIFO handling and vfifo defaults for 16/24/32bpp modes. +mach32 - Added fuzz factor of 0.5KHz when obeying monitor horz restriction. +mach32 - deleted dacwidth config command (was not useful) +mach32 - Added setuplinear command for mach32 (would be useful for cirrus too) +mach32 - Changed order of restore of extended ati registers to obey locking.. + may need even more fixing..that is ensure restore of vgaregs before they are locked + again when restoring extended ATI lock registers. +mach32 - Had to change order of entries in save-/setregs array for mach32 for this. +Shared library v1.1.6. + +Changes in v1.09: (2 May 94) + +Significant mach32 driver/docs update (potentially dangerous bug fixed). +Some vga_draw primitives now support 32-bit pixel modes (better support is +in vgagl). +Cirrus 320x200x256 registers redefined to support page flipping (setmodeX +doesn't work anymore). +Trident 320x200x256 page-flipping disabled. +Shared library 1.1.5. + +Changes in v1.08: (27 Apr 94) + +Improved vgagl 24-bit physical/32-bit virtual screen support (pageflipping +really fixed, speed increase (alignment)). +S3 driver hacked (try it if you are bold). +Sierra 15025/26 DAC support should work for 32K modes now. +Added PS/2 mouse support (untested). +More vgagl 32bpp primitives. +320x200x256 vgagl page flipping fix (this is a big one). +Added ctrl-c detection to low-level keyboard interface. +vgagl copyboxfromcontext added, and more efficient copyboxtocontext. +Shared library 1.1.4. + +Changes in v1.07: (19 Apr 94) + +Moved main library source into src/. Cleaned up shared library making. +Fix permissions of utils/convfont. +Fix tty behaviour: +Open /dev/tty instead of /dev/tty0 (previously non-root users could not run +programs if /dev/tty0 was not world-readable, like in the recent slackware). +Don't kill the terminal settings when detecting a non-graphics capable +virtual console (stupid bug related to use of atexit()). +Limited support for ioperm(1) by Olaf Titz. Allows non-root users to run +svgalib binaries which are not setuid-root. +Emulated paged copybox in vgagl (untested). +Utility to read out the ATI mach32 EEPROM. +Shared library 1.1.3. + +Changes in v1.06: (11 Apr 94) + +vgagl pageflipping fix for 24-bit/32-bit virtual screen. +Fix 16 color mode availability on ATI mach32. +Possible ET4000/W32 Sierra 15025/26 64K color fix. +vgagl compiled bitmaps enhanced (not completely compatible with v1.05), +but still untested. +Possible Trident 320x200 page flipping fix. +Shared library 1.1.2 + +Changes in v1.05: (2 Apr 94) + +Some unfinished SVPMI stuff (feedback strongly encouraged). +Added vgagl compiled bitmap functions (256 color only, untested). +Added definitions for 32 bits per pixel truecolor modes (not used yet). I +don't feel like adding vga_draw* functions for these; use vgagl. +vgagl now supports VGA 16 color modes indirectly. +Added RAW mode keyboard interface (vgakeyboard.h). +Mouse driver fix. +Shared library 1.1.1. + +Changes in v1.04: (29 Mar 94) + +Support for more than 1Mbyte of memory on ET4000W32i/W32p and 24-bit Sierra +DAC (15025/6) (untested). Fixed copying 4 bytes per pixel virtual screen to +three bytes per pixel screen (e.g. '3d' in truecolor modes). Fixed missing +gl_enablepageflipping. Fixed Cirrus linear addressing. +Amazing alpha ATI mach32 driver by Michael Weller; configuration file format +extended. +Shared library version 1.1. + +Changes in v1.03: + +EGA support fixed (Kapil Paranjabe). Added vga_safety_fork. +utils/Makefile fixed. + +Changes in v1.02: + +vgagl bitmap scaling improved. vga_lockvc/unlockvc should be useful now to +avoid corruption of certain VGA registers used for drawing. + +Changes in v1.01: + +Fixed copying to planar 256 color mode in vgagl, and added page flipping +support. Setting an SVGA mode after a planar 256 color mode clears the +screen properly now. Shared library 1.0.10. + +Changes in v1.00: (Jan 94) + +[The version number doesn't say anything about stability/completeness etc.] +A number of bug fixes related to Mode X (display start, console switching, +planar 320x200x256 allowed with vga_setmodeX()). +Added vga_copytoplanar256 for Mode X-like modes. Added smooth scrolling demo +program. Demo programs moved to demos/. +Cirrus linear addressing works (if you have less than 16Mb of memory); see +demos/testlinear. Added ET3000 driver. Trident 8900 reboot-beep problem should +be fixed. +Shared library 1.0.9 + +Changes in v0.99: + +ET4000 patches by Hartmut Schirmer: ET4000 register dumps now have extra +registers, so old register dumps won't work; register dump program (tseng3, +moved to et4000/ directory) supports VESA modes. Microsoft mouse handling +bug fixed. Shared library 1.0.8. + +Changes in v0.98: + +Some minor bugfixes, low-level mouse handling rewritten (was very slow). +Added vga_runinbackground and vga_oktowrite as a kludge to allow a graphics +program to run in the background (not entirely safe). Disabled ET4000 clock +detection (wasn't used yet). +Shared library version 1.0.7. + +Changes in v0.97: + +Fixed Cirrus 1024x768x256 non-interlaced. Other modes use default (lowest) +frequencies. Fixed bad virtual screen bug in vgagl (copyscreen). +Incorporates patches from Hartmut Schirmer (et4000 clock frequency +determination). Shared library 1.0.6. + +Changes in v0.96: + +Corrected et4000/et4000.default. Cirrus 1024x768x256 non-interlaced. +Hopefully fixed Cirrus monitor settings. Cirrus blitting works again. Fixes +in vgagl truecolor framebuffer support. Shared library 1.0.5. + +Changes in v0.95: + +Avoid writing to some reserved registers on ET4000 and Trident (fixes dual +monitor setups) (David Monro). Cirrus 1024x768x256 was doing scary things if +the svgalib monitor type was set to allow non-interlaced. Added Cirrus +1024x768x16 non-interlaced and 1280x1024x16 interlaced. Shared library +1.0.4. + +Changes in v0.94: + +Added 132x43 textmode tweaking utility. Put utilities in utils/. +restoretextmode was not saving/restoring extended registers anymore. Shared +library 1.0.3. Hack to prevent standard VGA modes from failing to work after +having run XFree86 on Cirrus. gl_setcontextwidth fixed. + +Changes in v0.93: + +Oops, version 0.92 was not quite up to date. Shared library is 1.0.2. We'll +get libvga.so.1.0.99 before the end of the year at this rate :-). +gl_copybox truly fixed. + +Changes in v0.92: + +Fixed broken configuration file reading; some minor changes. +Shared library is now version 1.0.1. Source is flawed. + +Changes in v0.91: + +Various fixes. Dumpreg should work better in X now. The default dynamically +defined ET4000 registers are now in /usr/local/lib/libvga.et4000. +Added vga_getgraphmem. +Shared library support (requires tools 2.8 to build). This greatly reduces +executable size and is good for binary compatibility. +__svgalib_graph_mem is now shadowed in a read-only user-visible global +variable (graph_mem) for easier shared library building. +Fixed console switching bug when a textmode is set in between the setting +of graphics modes. + +Oak 640x480x256 should work now. + +vgalgl updates. Added 4 bytes per pixel virtual screen support. + +Added vga_init. This will detect and initialize the driver, and give up +supervisor rights, having obtained I/O permissions. This is the recommended +first line of any program that uses svgalib. + +Should do chmod a+s on restorefont. + +EGA support from egalib by Kapil Paranjabe integrated into svgalib. This +is currently untested. + +Mouse support (can also be used independently). Added vga_lockvc and +vga_unlockvc; vga_getkey (read keyboard without waiting). Using the mouse +means no console switching for now. + +Initial untested S3 driver. Goal is to provide support for truecolor modes +on the 801/805/928, in SVGA mode. Properly uses monitor type variable. +[doesn't work] + +Configuration file for mouse/monitor type. Monitor type not used by drivers +yet, except Cirrus. + + +Changes in v0.9: + +Extensive changes and restructuring, by Hartmut Schirmer. Dynamic +(run-time) register loading from a configuration file for ET4000 cards, +providing binary compatibility. High resolution 16-color modes (for ET4000 +at least). More stable virtual console switching. + +copybox, and gl_setpalettecolor bugs fixed in vgagl. + +Fixed setting of standard VGA mode after SVGA mode. + + +Changes in v0.82: + +Virtual console switching cleanup. + +The dumpreg program now also shows extended registers. + +Added Oak driver, but extended registers have not been filled in. Somebody +should run XFree86 with the Oak driver, dump the extended registers with the +dumpreg program (make sure the Oak driver is enabled in config.h), and put +them in oak.c. With some luck it'll work. + + +Changes in v0.81: + +Restorefont (write option) was broken again due to bug in vga.c; gl/text.c +was missing in v0.8. Added vga_disabledriverreport. + + +Changes in v0.8: + +Fixed major bug in vga_getmodeinfo in vgadrv.c. This may have caused +spic to fail on unsupported SVGA cards in 320x200x256. + +vga.c split, and other changes (Hartmut Schirmer). Note that mode numbers +beyond 1024x768x256 have changed. Standard VGA modes 720x350x16 and +720x480x16 added. + +Virtual console switching improved (bank/linewidth/displaystart preserved). + + +Changes in v0.7: + +Trident textmode restoration and SVGA modes should work now on 1M cards +(thanks to Scott Heavner). + +Bug fixes in vgagl. + + +Changes in v0.6: + +Trident driver bug fixed; detection cleaned up. 800x600 and 1024x768 on 1Mb +cards don't work correctly. + +Added Cirrus 800x600x16M NI (at 50 Hz), and program to set the Cirrus memory +clock to a higher value (setmclk.c). + +Added framebuffer graphics library for one, two and three byte-per-pixel +modes. Documentation improved. + +vga_setrgbcolor added. + +ET4000 Hicolor fixes (thanks to Savio Lam), and other fixes (Scott Heavner). + + +Changes in v0.5: + +Fixed palette register timing bug (caused occasional corruption of textmode +palette). + +Added function that checks the environment variable GSVGAMODE for a +default mode (vga_getdefaultmode). The environment string can either be a +mode number (compatible with VGAlib Ghostscript), or a mode name as +in (G640x480x2, G640x480x16, G640x480x256, G640x480x32K, G640x480x64K, +G640x480x16M, PROMPT (ignore)). + + +Changes in v0.4: + +restorefont.c as distributed in v0.3 missed a case line in a switch +statement which made it useless. + +Each VGA register write in the library was producing silly debugging code +(I forgot to restore the macro definition), making everything significantly +larger than neccessary. + +Added vga_getchipset function. vgatest now only lists modes that are +available. + +The ET4000 driver has been improved, including Hicolor DAC detection +(thanks to David Monro and Daniel Jackson). + +Cirrus driver: +Fixed 5420/2/4 bug, cleaned up detection, changed the 800x600 timings, and +added missing modes 1024x768x256/32K/64K, as well as 320x200x15/16/24bit. +Also, there's support for some of the accelerated features of the Cirrus +5426, the driver provides bitblt (move box), fillblt (fill box), and +imageblt (write bitmap from system memory) functions. + +Display start address can now be meaningfully changed in 16-color and planar +256 color VGA modes for page-flipping (address is expressed as number of +pixels). + +Fixed the vga_flip() functionality; if you press escape during +vga_getch() the console is switched to textmode until another key is +pressed. [note: this has been obsoleted by console switching] +The default amount of video memory saved in SVGA modes is the size +of one screen. If the program uses more (if it uses page-flipping, for +example), you must indicate it with the vga_claimvideomemory function. This +prevents 2048 or 1024K being saved when only a few hundred K is required. + +svgalib now waits until the virtual console it is running in becomes active +before setting the first graphics mode. + +Implemented transparent virtual console switching (which uses vga_flip). + diff --git a/doc/DESIGN b/doc/DESIGN new file mode 100644 index 0000000..823e511 --- /dev/null +++ b/doc/DESIGN @@ -0,0 +1,86 @@ +This file contains some talk about what is involved with a good +register-level graphics driver interface. This is an old file, +you might also consider reading 'man 7 svgalib.faq' + +Section 1: Mode Setting + +The following describes what happens during a mode set. + +A request is made for a mode with given width, height, and color +resolution. Optionally the request can specify a specific pixel size, +scanline offset (line width), and pixel size (e.g. 3 vs. 4 pixels for +24-bit color modes), otherwise the driver chooses defaults for these +properties. It is the intention that requests for resolutions that don't +match an availabe mode timing can still be honoured by choosing a higher +resolution (for example, 700x500 is requested and 800x600 timing is +programmed). The scanline offset should ensure correct drawing of +graphics. + +The user-level driver tries to match the requested mode properties with +either fixed modes defined by the selected kernel module driver, or with a +flexible mode timing if the selected kernel module driver supports mode +timing. In the case of fixed modes, the user-level driver must ask the +kernel driver about the supported fixed modes, and in the case of mode +timings, the user-level driver must ask the kernel driver about physical +limits such as the amount of video memory, maximum pixel clocks for each +pixel size, range and mapping of horizontal timing parameters, and the +available pixel clock frequencies. In both cases, modes/timings that fall +outside of the configured monitor specs (probably stored in a file in +/etc) will not be selected. In the case of flexible mode timings, the +highest refresh timing that is possible will be selected. + +Once a mode timing or fixed mode is selected, the kernel module driver is +requested to set the mode on the hardware. A mode state is defined which +is a collection of VGA and driver-specific extended register values (byte +values) that describes the mode that the video card is set to. During the +mode set proper, the following actions are performed: + +1. The registers values that make up the state are read from the video + card and stored in a state in system memory (this is the state of + the video card before the mode set). + +2. An initialization function modifies the values in the state according + to the requested mode. Nothing is written to the card; only the state + in system memory is changed. + +3. The actual mode set on the hardware is performed by writing the values + in the state to the corresponding registers on the video card. + +A special case is VGA-compatible textmode state, which would normally be +active at the time of a graphics mode set. This mode cannot be initialized +in the way of (2) above. Instead, the mode is saved using (1), and the +resulting state is restored using (3) when textmode needs to be restored. + +Another special case is the setting of a mode for which (1) and (2) have +already been performed, and the resulting state has been saved. In this +case the mode can be set accomplished by just (3), provided that certain +hardware-specific settings on the card have not been changed in the time +between (1) and (3) (this would normally be the case). + +When a VT switch away from a graphics modes happens, the current hardware +state should be saved, instead of the initialized mode state, since an +application can have changed it (banking, displaystart, accelerator state +etc.). This is subject to all the extended registers being readable, which +may be a problem with some cards (note that for simple mode setting +followed by textmode restoration, this is not a problem since the mode +initialization overwrites most of the delicate extended registers, and the +saved textmode state is largely VGA registers, and doesn't deal with +delicate extended registers). A possible solution would be to have +functions that save and restore or re-initialize the 'drawing' state, +which would include banking, displaystart and accelerator registers. Upon +VT switching back, the mode initialization function would be used followed +by the restoring of the saved drawing state. + +Section 2: What should be in the kernel driver. + +A decision that has to be made is whether all chipset specific settings +should be handled within the kernel module driver. There's a fair amount +of information required to select a suitable timing, which the user-level +driver will have to request, and it might have to do additional queries +during its evaluation. The abstractions used for this communication will +include a growing number of properties to accomodate new card/chipset +drivers. It is however desirable that the simple loading of a new module +driver is enough to make full use it, without the requirement of having an +updated user-level driver. + +Harm Hanemaayer (hhanemaa@cs.ruu.nl) diff --git a/doc/Driver-programming-HOWTO b/doc/Driver-programming-HOWTO new file mode 100644 index 0000000..9d5654c --- /dev/null +++ b/doc/Driver-programming-HOWTO @@ -0,0 +1,216 @@ +Here are some tips on writing a new chipset svgalib driver. +They don't require knowledge of direct vga programming, even though that +helps. +The instructions assume: +1- A super vga card, that is a card which is extended, but also fully +compatible to standard vga. Of the cards available today (in the mass market), +all are, with the possible exception of Permedia chipsets. +2- A PCI (or AGP) connected card. This is useful for detection of the card, +and for finding the linear aperture, as well as knowing it is always there. +3- Knowledge of the extended features of the chipset: Usually either as the +spec, or a source of a driver for the chipset (XFree86). + +as a start, get the following: +1- vgadoc4b.zip[1] (or a later version), includes information on the vga + hardware registers, as well as on many chipsets. +2- the latest svgalib[2]. +3- If the card is supported by XFree86, either the link kit (Xlkit.tgz[3]) + if the card is supported by the XF86_SVGA server, or the XFree86 source + ([4]), if it is supported by a special server. + +1. in the src subdir of the svgalib distribution, cp skeleton.c to some other + name, chipset.c, where chipset is the name of the chipset you intend to + support. + +2. now you have to fill the blanks. The functions that need to be are +sk_setpage +sk_saveregs +sk_setregs +sk_initializemode +sk_unlock +sk_test +sk_setdisplaystart +sk_setlogicalwidth +sk_init + +3. When that is done, change all sk_ in the driver to chipset_ (where + chipset is the name of the chipset you write the driver for). Then + the driver needs to be integrated into svgalib. The files that need + to be edited are: +Makefile.cfg +src/Makefile +src/driver.h +src/vga.c +src/vga.h + (It's easy to see what changes are needed in those files, by simply + seeing how its done for another driver). + +4. Now is the most interesting time - debugging. Usually (in my experience, + in all cases), the driver won't work right immediately. Here are a few + debugging tips: + +Setting modes is made of two things: setting the timings, and setting the +memory organisation. You can usually tell which is the problem, by noticing +if the wrong screen is seen as if some/all pixels are not set to the color +they should (memory organisation), or the display looks "stormy" (timings +problem). If the problem is timing problem, a digital monitor taht displays +horizontal and vertical timings helps. If the horizontal freq is right, but +vertical is wrong, then the problem is in the vertical timing. If both horiz +and vert are wrong, then either the clock frequency, or the horizontal +frequency is wrong. + +If the problem is in memory organisation, It might work in linear mode, so try +running testlinear and lineart. + +If the driver fails to restore text mode properly, then usually starting X +will work. It won't help restoring text mode, but then you might be able +to see the output of the program (using /dev/vcs?, /dev/vcsa?). + +The program mode3 (in lrmi-0.6m subdir) might be able to restore text mode, +corrupted by a bad driver. + +The same mode3 might be used for debugging as follows: if a mode, say +800x600x256 does not work properly, but mode3 does work, you might try the +following run vgatest, select 11 (for 800x600x256), and while the wrong mode +is displayed, press d (to recieve a registers dump). +then, try mode3 259 ; utils/dumpreg ; mode3, and compare the register dump +of vesa mode 259 (800x600x256), with the output from your driver. Try finding +out what do the bits that are different mean. + + +Here are some more details on writing the necessary functions: +examples given are from the banshee.c driver, written according to the spec +available from 3dfx, and the (hypotethical) milleniumII.c driver, written +according to the XFree86 source. + +_setpage: + +This is a simple function. A mistake in this function is indicated by: +all linear programs work fine, while in paged memory examples, the problem +is that blocks (full width * ??? lines) are moved. + +For millenium, from freebe (this part is unavailable in X source, +since X uses only linear mode). +{ + outw(0x3de,(page<<8)|4); +}; + +For Banshee: +{ + page<<=1; + outl(banshee_io_base+0x2c,(inl(banshee_io_base+0x2c)&0xfff00000)|(page)|(page<<10)); +} + + +_saveregs, _setregs + +This functions should save and restore the state of the svga card, such that +it can be restored to a previous state, no matter what we do. A mistake is +indicated by failure to restore text mode properly. + +We should save all registers that we change, or might be changed by other +programs (X, SVGATextMode, etc.), here's the banshee_saveregs: + +typedef struct { + unsigned int pllCtrl0, pllCtrl1, dacMode, dacAddr, + vidProcCfg, vidScreenSize, vgaInit0, + vgaInit1, vidDesktopStartAddr,vidDesktopOverlayStride; +} *HWRecPtr; + +static int banshee_saveregs(unsigned char regs[]) +{ + HWRecPtr save; + + banshee_unlock(); + + save=(HWRecPtr)(regs+62); + + regs[BANSHEEREG_SAVE(0)]=__svgalib_inCR(0x1a); + regs[BANSHEEREG_SAVE(1)]=__svgalib_inCR(0x1b); + save->pllCtrl0=inl(banshee_io_base+0x40); + save->pllCtrl1=inl(banshee_io_base+0x44); + save->dacMode=inl(banshee_io_base+0x4c); + save->dacAddr=inl(banshee_io_base+0x50); + save->vidProcCfg=inl(banshee_io_base+0x5c); + save->vidScreenSize=inl(banshee_io_base+0x98); + save->vgaInit0=inl(banshee_io_base+0x28); + save->vgaInit1=inl(banshee_io_base+0x2c); + save->vidDesktopStartAddr=inl(banshee_io_base+0xe4); + save->vidDesktopOverlayStride=inl(banshee_io_base+0xe8); + + return BANSHEE_TOTAL_REGS - VGA_TOTAL_REGS; +} + +If we use the X source, it usually in the functions XXXSave and XXXRestore. +It is only needed to translate from XFree86 notation to svgalib notation, +and to remember that while the X functions need to save the vga state (usually +by calling the vga function to do it, in svgalib the chipset_saveregs/setregs +don't need to do that, but only save extended vga info). +For MilleniumII, the interesting X functions are: MGA3026Save and +MGA3026Restore, here a translation of a part of MGA3026Restore to +mill_setregs: + +MGA3026Restore: + for (i = 0; i < 6; i++) + outw(0x3DE, (restore->ExtVga[i] << 8) | i); + + /* restore DAC regs */ + for (i = 0; i < sizeof(MGADACregs); i++) + outMGA1064(MGADACregs[i], restore->DACreg[i]); + +translates to (assuming sizeof(MGADACregs)==32) + for (i = 0; i < 6; i++) + outw(0x3DE, (restore[60+i] << 8) | i); + + /* restore DAC regs */ + for (i = 0; i < 32; i++){ + OUTREG8(RAMDAC_OFFSET + MGA1064_INDEX, MGADACregs[i]); + OUTREG8(RAMDAC_OFFSET + MGA1064_DATA, restore[66+i]); + }; + + +_initializemode - This is the trickiest function. If you use the XFree86 +source, try to translate the appropriate function from X to svgalib (in +the milleniumII case, MGA1064Init(mode)). For examples of this translation, +see how its done for nv3.c compared to nv/nv3driver.c from X, or apm.c compared +to apm/apm_driver.c. +If you are working from specs, it usually explained in the spec. + +_unlock: +simple function. The skeleton includes the vga unlocking part. If you have +specs, they usually explain how to unlock the extended features, if you use +the X source, its usually in the EnterLeave function. + +_test - If you are supporting a single chipset of a single manufacturer, +on a PCI/AGP, the skeleton driver includes a test for this, just make sure to +set VENDOR_ID and CARD_ID properly. Otherwise, either the specs explain +how to recognize that you have the right chipset, or its in the function +XXXProbe of the XFree86 source. + + +_setdisplaystart, _setlogicalwidth: +vga includes this settings, but with limited range (start<65536, +width<2048 bytes). An svga chipset either defines extra bits, for increasing +the range, or completely new registers for these values. +In the first case, the skeleton driver includes setting the vga part, and +the extra bits are either defined in the specs, or in the XXXAdjust function +in XFree86 (see mx.c for example of this). In the second case, remove the +vga setting part from the functions (see for example rage.c). +Note that none of the demo programs test this functions, so if you want to +check if they work, the only example I know of is seejpeg (try to see an image +larger than the screen) + + +_init +should not need much changes, except for checking memory size (in the spec, or +in XXXProbe), and maybe setting MMIO (if other functions use it). + + + + +1- http://home.worldonline.dk/finth +2- http://www.cs.bgu.ac.il/~zivav/svgalib +3- ftp://ftp.xfree86.org/pub/XFree86/current/binaries/Linux-ix86-libc5/Xlkit.tgz + (or mirrors) +4- ftp://ftp.xfree86.org/pub/XFree86/current/source/X333servonly.tgz + (or mirrors) diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..e757a99 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,94 @@ +include ../Makefile.cfg + +srcdir = .. +VPATH = $(srcdir)/doc + +SVGALIB1=man7/svgalib.7 man5/libvga.config.5 man5/libvga.et4000.5 \ + man5/svgalibrc.5 man7/svgalib.chips.7 \ + man7/svgalib.et4000.7 man7/svgalib.mach32.7\ + man6/mach32info.6 man3/vga_* man3/keyboard_* man3/mouse_* \ + man3/joystick_* man3/currentcontext.3 man3/graph_mem.3 \ + man1/convfont.1 man1/dumpreg.1 man1/fix132x43.1 man1/restorefont.1 \ + man1/restorepalette.1 man1/restoretextmode.1 man1/runx.1 man1/savetextmode.1 \ + man1/setmclk.1 man1/textmode.1\ + man1/svgakeymap.1 \ + man6/joytest.6 man6/mjoytest.6 man6/printftest.6 man6/svidtune.6 \ + man6/eventtest.6 man6/forktest.6 man6/fun.6 man6/keytest.6\ + man6/mousetest.6 man6/speedtest.6 man6/spin.6\ + man6/testaccel.6 man6/threed.6 man6/vgatest.6 man6/accel.6\ + man6/bg_test.6 man6/scrolltest.6 man6/testlinear.6\ + man7/svgalib.faq.7 man8/mode3.8 man8/vga_reset.8 man6/lineart.6 + +VGAGL1=man7/vgagl.7 $(shell ls man3/gl_* | grep -v tri ) man6/testgl.6 + +THREED1=man7/threedkit.7 man3/gl_*tri* man6/plane.6 man6/wrapdemo.6 + +SVGALIB=$(subst man,$(srcdir)/doc/man,$(SVGALIB1)) +VGAGL=$(subst man,$(srcdir)/doc/man,$(VGAGL1)) +THREED=$(subst man,$(srcdir)/doc/man,$(THREED1)) +COMPMANPAGES=$(shell cd $(srcdir)/doc; find man? -name "*.gz" -type f -print) + +.PHONY: clean ascii dvi ps install gunzip gzip + +gunzip: + echo gunzipping manpages + for i in $(COMPMANPAGES); do\ + gunzip $$i; \ + done + +gzip: + echo gzipping manpages + for i in $(SVGALIB1) $(VGAGL1) $(THREED1); do\ + gzip $$i; \ + done + +../0-README: man7/svgalib.7 + cat man7/svgalib.7 | nroff -man | col -b > ../0-README + +ascii: + cat $(SVGALIB) | grep -v '^\.so ' | nroff -man -T$@ \ + | col -b > svgalib.$@ + cat $(VGAGL) | grep -v '^\.so ' | nroff -man -T$@ \ + | col -b > vgagl.$@ + cat $(THREED) | grep -v '^\.so ' | nroff -man -T$@ \ + | col -b > 3d.$@ + +lpr: + cat $(SVGALIB) | grep -v '^\.so ' | nroff -man -Tascii > svgalib.lpr + cat $(VGAGL) | grep -v '^\.so ' | nroff -man -Tascii > vgagl.lpr + cat $(THREED) | grep -v '^\.so ' | nroff -man -Tascii > 3d.lpr + +ps dvi: + cat $(SVGALIB) | grep -v '^\.so ' | troff -man -T$@ > svgalib.$@ + cat $(VGAGL) | grep -v '^\.so ' | troff -man -T$@ > vgagl.$@ + cat $(THREED) | grep -v '^\.so ' | troff -man -T$@ > 3d.$@ + +install: gzip + mkdir -p $(mandir)/man1 $(mandir)/man3 $(mandir)/man5 \ + $(mandir)/man6 $(mandir)/man7 $(mandir)/man8 + for i in $(COMPMANPAGES); do\ + $(INSTALL_DATA) $(srcdir)/doc/$$i $(mandir)/$$i; \ + done + make gunzip +ifdef MAKEWHATIS + @echo "Rebuilding the whatis database (this is slow!)" + @echo "You can comment this out in Makefile.cfg!" + $(MAKEWHATIS) +endif + +uninstall: + @echo Removing all svgalib man pages. + @for dir in $(mandir) ; do \ + if [ -d $$dir ]; then \ + cd $$dir; \ + rm -f $(COMPMANPAGES) $(UNCOMANPAGES); \ + fi; \ + done;\ + +clean: +# -gzip -9 man?/* 2>/dev/null + rm -f man?/*.bak + rm -f svgalib.ascii vgagl.ascii 3d.ascii + rm -f svgalib.dvi vgagl.dvi 3d.dvi + rm -f svgalib.ps vgagl.ps 3d.ps + rm -f svgalib.lpr vgagl.lpr 3d.lpr diff --git a/doc/README.joystick b/doc/README.joystick new file mode 100644 index 0000000..7276b35 --- /dev/null +++ b/doc/README.joystick @@ -0,0 +1,83 @@ +Hi! +I wrote a set of SVGAlibish joystick routines while I played with porting +DOSDoom to SVGAlib. +It is compatible with both the older joystick driver for Linux 1.x and 2.0 +and the newer joystick driver that is in recent 2.1.x kernels. +Some of the code is ripped from the userland tools joystick-0.6.7 and +joystick-2.0.6 none of wich has any special license attaced to them. + +The files are: +joydev.h: my userland version of the kernel joystick.h +vgajoystick.h: library include file analog to vgakeyboard.h and vgamouse.h +joystick.c: the library routines. +joytest.c: a simple test program/example + +I dunno how useful these will be, but I could at least use them in doom. (Not +that joystick control in doom adds anything, I just implemented it for +completeness.) + +BUGS: +Only one joystick device at any time (but the new 2.1.x driver will let you +map 4 axis and 4 buttons to one logical device). + +The routines: + +int joystick_init(const char *joydev, int verbose, FILE *file); +This one inits the joystick routines and opens the device. Returna the +filedescriptor of the joystick device if successfull or -1 if not. +Outputs some messages to stdout id verbose is != 0. If file != NULL it will +try to recalibrate the joystick and output the recalibration instructions to +the struct file pointed to by file. +E.g. + +if (-1 == joystick_init("/dev/js0, 1, stdout)) +{ + printf("Joystick init failed\n"); + exit(1); +} + +void joystick_close(void); +Shuts down the joystick. + +int joystick_update(void); +Reads the joystick and calls the joystick handler if anything events are +availible. Should be called every now and then. + + +void joystick_sethandler(__joystick_handler jh); +Install a user supplied joystick handler. + +A user supplied joystick handler would look like this. +void joystick_handler(int event, int number, char value); +int event - event type: + JOY_EVENTAXIS an axis has moved + JOY_EVENTBUTTONDOWN a button has been pushed + JOY_EVENTBUTTONUP a button has been released +int number - the axis or button number for this event 0=x axis or button 1, etc. +char value - value for axis events (-128 .. 0 .. 127) + +void joystick_setdefaulthandler(void); +Restore the default joystick handler. + +char joystick_getnumaxes(void); +char joystick_getnumbuttons(void); +Retrun the number of axes/buttons on the joystick. + +char joystick_getaxis(int a); +char joystick_getbutton(int b); +Querys the jostick state from the default joystick handler if it is used. + +The following macros calls joystick_getaxis() or joystick_getbutton(). +joystick_getb1() - Gets button 1 +joystick_getb2() - Gets button 2 +joystick_getb3() - Gets button 3 +joystick_getb4() - Gets button 4 + +joystick_getx() - Returns the X axis +joystick_gety() - Returns the Y axis +joystick_getz() - Returns the Z axis + +That all folks, + +Daniel Engström +daniel.engstrom@riksnett.no diff --git a/doc/README.keymap b/doc/README.keymap new file mode 100644 index 0000000..f47b678 --- /dev/null +++ b/doc/README.keymap @@ -0,0 +1,172 @@ +** Svgalib keyboard scancode remapping: the Readme ** + +** Introduction + +After a poll on Slashdot.org about keyboard layouts, I decided to switch from +QWERTY to the Dvorak simplified keyboard. (Such is the power of Slashdot!) It +was easy to switch the keymaps used by the console and X and even LILO, but +svgalib programs that used raw keyboard weren't affected since they interpret +the keyboard scancodes into characters themselves - often assuming a standard +US keyboard with QWERTY layout. + +In order for my machine to present a ``unified front'' with a single consistent +keyboard layout, I added to svgalib the ability to remap scancodes. This is +done in keyboard_getevents(), before the event handler is called, so it will +work whether or not a program provides its own handler. Programs that do not +use raw keyboard are not affected, so by setting both the console and svgalib +itself to use the same keymap a consistent keyboard layout is available to all +svgalib programs. + + +** Background + +When you press or release a key on your keyboard, it sends a byte of data to +your computer. The top bit indicates whether the key was pressed or released, +and the lower seven bits hold the scancode, a number that uniquely identifies +the key. A program on the computer interprets these scancodes as representing +characters (`A', `%', etc) or actions to be taken (`Page Up', `Back Space') or +modifiers that alter the interpretation of other keys (`Shift', `Alt', etc). +Most programs do not perform this interpretation themselves, but leave it up +to some other piece of software: the system BIOS, or the operating system, +or the graphical user interface system. + +On Linux this is normally done by the kernel or by the X server for X clients, +but this doesn't meet the needs of some programs (especially games) which +care more about whether a key is up or down than what it means and treat the +modifiers the same way as other keys. These programs open the keyboard in `raw' +mode and deal directly with scancodes. + +The problem comes because these programs often do need to interpret the keys +into characters, or it is important for a certain key to be identifiable to +the user as being associated with a certain key. For instance, a game player +might need to type a description of a saved game or be directed to press a +certain key to activate a game feature. Interpretation of keyboard scancodes +can be difficult since there are many different keyboard layouts which do not +have the same associations between scancodes, modifiers, characters, and +commands. So the author of the program must choose between writing a complex +and customizable conversion routine that can handle any layout the user might +have, and a simple routine that is hard-coded to use a single layout. In the +latter case, users of other keyboard layouts will encounter numerous +discrepancies between what he or she tries to type and what the program +interprets. + + +** How it works + +Svgalib's scancode conversion is meant to at least partially fill this gap by +converting the scancodes that the keyboard produces to equivalent, or nearly +equivalent, scancodes for the keyboard layout that the program expects. The +program then (hopefully) interprets the new scancode into the intended +character. + +As an example, let us consider a US keyboard with Dvorak layout and the game +Quake, which expects a US keyboard with QWERTY layout. Both layouts have the +same scancodes for each physical key, but different characters are produced. +For intance, the first row of letters produces the scancodes 16 through 27, but +on QWERTY this produces the charaters qwertyuiop[] while Dvorak produces +',.pyfgcrl/=. Thus when the Dvorak letter `p' is pressed, the scancode 19 +is interpreted by Quake as the letter `r', which occupies scancode 19 on the +QWERTY layout. + +The solution lies in the fact that svgalib acts as an intermediary between the +keyboard and the program and has the opportunity to present a different +scancode to the program than the keyboard produced. In this case we tell Quake +that the scancode was not 19 but rather 25, which is the letter `p' in the +QWERTY layout, so when Quake interprets the scancode the correct character is +produced. + + +** The keymap files + +In order to know what scancodes to convert to what other scancodes, a keymap +file is read which lists scancodes produced by the keyboard and their +equivalents in the layout expected by the program. + +A program called svgakeymap is provided to generate these maps from the +keytable files in /usr/lib/kbd/keytables; you must have perl for it to work. +Creating a keymap file with svgakeymap is easy; to make a map to convert +scancodes from a US Dvorak keyboard to a US QWERTY keyboard as for our example +above: + + svgakeymap dvorak us > dvorak-us.keymap + +The path and .map and .gz suffixes are automatically added if necessary. If +your keytables are stored elsewhere, specify a complete path. If only one +keytable is specified, a keymap is generated that performs no conversions but +contains the correct key names so you can specify scancodes used by fake +keyboard and mouse events by name instead of by number. If none are specified, +this is done for the standard US QWERTY layout. + +dvorak-us.keymap and default.keymap (the US QWERTY layout) are provided with +the svgalib distribution and can serve as an example if you wish to make your +own keymap files manually or create an improved generator. + + +** Configuration + +You can specify a keymap to use for all svgalib programs (keeping in mind that +only those that use raw keyboard are affected) by putting a line like this into +libvga.config or ~/.svgalibrc: + + kbd_keymap /etc/vga/dvorak-us.keymap + +You must specify a complete path to the keymap file. If no keymap is specified, +no conversion is performed. + +You can also override the global keymap by setting the environment variable +SVGALIB_KEYMAP to point to the appropriate keymap file. This can be useful if +some programs support alternate keymaps directly but not others, or if +different users use their own keyboard layouts based on preference. + + +** Security issues + +It can be dangerous to let users arbitrarily reassign keyboard scancodes; for +instance all keys could be routed to an unused scancode, making the console +unusable. To prevent this, put the option kbd_only_root_keymaps into +libvga.config; only keymaps owned by root will be accepted, so the available +keymaps can be limited to safe ones. + + +** Bugs and limitations + +There are no known bugs, but there probably are some. If you find any please +let me know at brion@pobox.com. + +Limitations however we definitely have. The scancode conversion performed is +very simple, and can only achieve 100% success when the keyboard layouts being +converted between differ _only_ in arrangement of keys while producing the same +characters from each key. Example: the de facto standard Dvorak keyboard has +the left and right brackets (`[' and `]') on separate keys, with the curly +braces (`{' and `}') produced by those keys when shifted. The standard QWERTY +keyboard produces those characters the same way, the only difference is that +the keys are a row higher on Dvorak; switching the scancodes around results in +proper character interpretation. However the official ANSI standard Dvorak +layout has tho two brackets on _the same key_, one regular and one shifted. +The curly braces similarly have their own key. These cannot be properly mapped +by scancode to the QWERTY keyboard since they produce different characters +in conjunction with modifiers, and the wrong character is produced by the +program. + +This could be worked around by interpreting the modifiers in svgalib and +simulating the proper modifier/character keypress/release sequences, but it +would be very complex and would do nothing to help the situation where +characters on the physical keyboard layout do not exist on the target layout +(quite likely when dealing with national or language-specific keyboards); +they cannot be converted into any key sequence since they do not exist. + +Ultimately it might be better to set up a ``medium-rare'' keyboard mode where +keys are interpreted into characters but ``raw''-style non-interpreted key +press and release events are available. + + +** Further information + +There isn't really any further information right now unless you want to Use The +Source... More to come in the future. If it does you'll find it at: + + Brion Vibber's Svgalib Stuff - http://pobox.com/~brion/linux/svgalib.html + + +-- brion vibber (brion@pobox.com) + 3 July 1998 diff --git a/doc/README.lrmi b/doc/README.lrmi new file mode 120000 index 0000000..1b55df4 --- /dev/null +++ b/doc/README.lrmi @@ -0,0 +1 @@ +../lrmi-0.6m/README \ No newline at end of file diff --git a/doc/README.multi-monitor b/doc/README.multi-monitor new file mode 100644 index 0000000..044ce27 --- /dev/null +++ b/doc/README.multi-monitor @@ -0,0 +1,88 @@ +multi-monitor support is still very experimental, and not +very easy to setup. Here's a copy of a message I sent to +the mailing list: + + +First: only nvidia, 3dfx, sis and i740 cards can be secondary cards, +(though the primary can be anything, including vesa). +Second: as far as I can understand, once both cards are enabled, there +ought to be a resource contention (in hardware) between the cards for +the vga regions (IO 0x3c0-0x3df and MEM 0xa0000-0xbffff). I don't know +how it is supposed to be solved, but in practice, if I ignore it in my +system, it just works. + +If anybody else has successfully run svgalib on a secondary card, please +tell me, and if you had to do something different from what I did, a +detailed report to the list might help others. + +Here's my setup: + +I have two vga cards: AGP (1:0.0) nVidia TNT2 and (PCI0:0f.0) Riva128. +The AGP card is the primary (in the BIOS option "initialize AGP card +first" is selected). My boot sequence includes the following code to +initialize the secondary card: + +/usr/local/sbin/vbios.x86emu +/usr/local/sbin/vga_reset +/sbin/setpci -s 00:0f.0 COMMAND=2 + +the vbios.x86emu is the same as distributed in x86emu-0.6 (from ftp.scitechsoft.com) +except that in debug.h the line +#define CONFIG_ACTIVE_DEVICE 1 +is replaced by +#define CONFIG_ACTIVE_DEVICE 0 +(so that the active device is not initialized by x86emu). + +the setpci line enables memory access (of the drivers supporting +secondary card, nv3 and i740 use only memory mapped IO, sis and banshee +need I/O access as well, so you need COMMAND=3). The COMMAND register +might have other bits set, so you might try to see its value first, and +then set the 0,1 bits. + +I have two config files in /etc/vga: +libvga.config.0 - for the scondary card: + +novccontrol +secondary +include /etc/vga/libvga.config.common +HorizSync 30 54 +VertRefresh 40 120 + +The novccontrol and secondary options are necessary for a secondary +card. The include statement is for a card with common configurations - +mouse, keyboard, etc. + +libvga.config.1 - for the primary: + +PCIStart 1 0 +include /etc/vga/libvga.config.common +HorizSync 30 115 +VertRefresh 40 160 + +The pcistart option is necessary to make sure that svgalib skips the +first card (in PCI order), and so finds the AGP card. + +to run a program on the primary card, in the usual way, I do + +export SVGALIB_CARD=1 +/svgalib/demos/vgatest + +to run a program on the secondary card: + +export SVGALIB_CARD=0 +/svgalib/demos/vgatest + +There are a few differences for a program running on secondary card: + +- The program is not aware of VC switches, so you can switch to another + console, and the program will still run (and display). +- The program can't event system (mouse or raw keyboard). +- Standard VGA modes and paged memory modes might have problems. + +What this limitations mean is that usual svgalib program might not be +useful for a secondary card. I use the secondary display for +watching TV, movies and slideshows. Eye candy programs (such as +synaesthesia) might also work, after a few changes, but interactive +programs (zgv, games) are unusable right now. I intend to add support +for Vojtech Pavlik's input event system to svgalib-2.0, so that +interactive program will be usable as well. diff --git a/doc/README.patching b/doc/README.patching new file mode 100644 index 0000000..2abbf8c --- /dev/null +++ b/doc/README.patching @@ -0,0 +1,140 @@ +Patching svgalib + +Contents + +0. Introduction +1. Indenting +2. Structure of the chipset drivers + +0. Introduction + + Here is some info on writing patches and/or adding support for + further chipsets. The info on the chipset drivers is outdated, but + better than nothing and get you started. + + As a side note, other than a.out, ELF does not allow to have some + symbols global to svgalib which are not accessible to user + programs. + + Because of that, if possible all the symbols and functions in your + program should be static. Those which can not be static should + have a name like: "__svgalib_*" to mark them as internals s.t. + people using them get what they deserve. Please do only add a new + function to the user interface if it is really unavoidable. Better + add some new parameters to an existing function. + + Adding a new function would definitly result in loosing a.out + compatibility thus removing the chance to use new cards and such + with old a.out binaries where the source is not available (doom + comes to mind). + + A new function should be really important to outweigh this draw + back. + +1. Indenting + + Due to some request (and I heard it b4) all the sources were now + automatically indentified. + + There were some requests for indent -gnu but it looks painful. I + opted for -kr (there were requests for it as well) as it is not + only nicer but also what is done in the linux-kernel and this is + certainly a program only usable for linux. + + I dunno if emacs is confused by -kr, but to be honest this is a + big all-in-one egg-giving-wool-milk-sow (as we say in german), and + you won't tell me that this several megs beast is unable to edit + this and I can't use -kr due to some restrictions of emacs. That + would be really ridiculous. If it is the case just make emacs + better. + + The OneModeEntry macro is eaten by indent (I would say it is an + indent bug, I might send a bug report to them), please ensure (if + at all possible) that your code can be passed through indent (use + the INDENT-OFF comments as shown in some sources for + OneModeEntry). + + You can use `make indent-gnu' (if you have a recent enough (I use + 1.9.1) indent) to switch to your favorite style. But please ensure + your patches fit into this now declared as "official style" + sources. (Use `make indent' to reformat). + + Do not use it too often though as most indent's tend to add empty + lines at certain places in the source. + +2. Structure of the chipset drivers + + The chipset specific registers saving function (saveregs) is only + used directly to save the textmode registers at initialization. + + The chipset specific registers restoring function (setregs) is only + used directly to return to textmode, and when setting a VGA mode + after an SVGA mode. + + The registers for each mode are stored like the ET4000 modes in + VGAlib 1.2, i.e. the extended registers at the end. The following + functions must be provided in a driver: + + saveregs( unsigned char regs[] ) + Saves the chipset-specific registers in regs, starting at + array index EXT (after the VGA registers). + + setregs( unsigned char regs[] ) + Sets the chipset-specific registers stored in regs from + index EXT. + + modeavailable( int mode ) + Returns nonzero if mode is available (should check video + memory). + + getmodeinfo( vga_modeinfo *modeinfo ) + Fills in chipset specific field of mode information + structure: maxlogicalwidth, startaddressrange (mask of + significant bits), and maxpixels (video memory divided by + the number of bytes per pixel). haveblit indicates whether + bitblt functions are available. + Note: providing extended info and an aperture with size + >= memory and setting bits 4 and 6 in flags will + automatically enable linear addressing support. + + + setmode( int mode, int previous_mode ) + Sets all registers for a mode; returns nonzero if mode not + available. __vga_setregs can be called to set the VGA + registers. + + unlock() + Unlocks chipset-specific registers. + + lock() + Lock (protect) chipset-specific registers. Currently not + called. + + test() + Identify chipset; initialize (check memory and type) and + return nonzero if detected. + + setpage( int page ) + Set 64K page number to be mapped at 0xa0000. + + init( int force, int par1, ... ) + Initialize memory and type; called by test. If force is 1, + the chiptype or the amount of memory can be forced (this + is pretty useless). + + The following functions provide for things like page flipping + and hardware scrolling virtual desktops. + + setdisplaystart( int address ) + Sets the display start address in video memory in pixels. + + setlogicalwidth( int width ) + Sets the logical scanline length in bytes. Usually a + multiple of 8. + + The function getchipset() in vga.c must call the test routine for + the chipset. The chipsetfunctionslist must be have a pointer + to the chipsetfunctions table for the chipset (which is the only + global symbol in a chipset driver). Also, vga.h contains a magic + number for each chipset. Also driver_names[] in vga.c has to + contain a name for each driver at the correct position. diff --git a/doc/README.vesa b/doc/README.vesa new file mode 100644 index 0000000..cc5b1d5 --- /dev/null +++ b/doc/README.vesa @@ -0,0 +1,60 @@ +Notes for the VESA driver: + +The driver's autodetection is disabled by default, so in order to use it, +the line +chipset VESA +must be added to the config file (usually /etc/vga/libvga.config). + +The error: +Int 0x10 is not in rom (xxxx:xxxx) +is usually caused by running linux using loadlin, after loading a dos tsr +that changes the int 10 vector, or after windows 95, that does the same +thing. The solution, is either to use lilo, or run loadlin after a clean +dos boot. + + +There is a new config file option that affects the vesa driver: +VesaText +If this option is used, the driver sets 80x25 text mode (using vesa bios) +before setting any standard vga mode. + +This option was added in order to enable standard vga modes with the vesa +driver on Matrox Millenium, but now it has the following effect: +(read in a fixed width font) + +chipset with VesaText without VesaText + +CL-GD5446 works leaves a messy font when + returning to text mode + +Riva 128 does not restore works + previous used text + font, but reverts to + ROM font. + +Matrox +Millenium works does not set standard vga + modes properly. + +A list of cards known to work with the VESA driver is: + * Riva128 (both on a STBV128 and a Viper330) + * RivaTNT + * Matrox Millenium 2 + * Matrox Mystique + * Matrox Productiva G100 + * Matrox Millenium G200 + * Neomagic Magicgraph 128XD (in a Dell Inspiron laptop) + * S3 375 Virge/DX ( A "Trident Video Excel 3D Accelerator" ) + * S3 Trio3D + * Cirrus Logic GD5446 + * Rendition V1000 - Only modes up to 800x600 seem to work + * ATI Expression+ PC2TV 2MB (RageII chipset) - tested only modes up + to 800x600 resolution + * i740 (Diamond Stealth G460) + * Voodoo Banshee + * Alliance Technology AT24 + +Please note that some of this cards have also failed to work in some +cases, so it is _very_ configuration dependent. + +For Matrox cards, the advice is to upgrade to the latest bios from Matrox. diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 0000000..72e3819 --- /dev/null +++ b/doc/TODO @@ -0,0 +1,40 @@ +Be sure to read the svgalib.FAQ man 7 svgalib.faq + +Have to decide what exactly is G320x200x256 (VGA Mode 13h or SVGA +packed-pixel). A separate Mode X would be nice too. + +A set of functions to handle page-flipping would be nice. (e.g. a +vga_setvideopage() that returns the new video start address) + +Support for more chipsets? + +Clean up keyword parsing code. + +Kernel support for page-flipping. + +automatic console restore on device close. + +really reliable vc switching. + +There are races in the mouse code when the mouse device is closed in the +signal handler on a vc switch. Again, probably kernel support is due. + +start marking functions that will become obsolete. + +Move away from hard-coded mode numbers: + + Think what would happen if a program is compiled to call + vga_setmode(G1280x1024x256) and we change the mode number to + something else... This has happened before. The solution is either + to provide a getmodenum(xres, yres, colordepth, layout) function, or + a setmode(xres, yres, colordepth, layout) function or vow not to + change the definitions of the mode numbers (i.e. new modes can only + be added to the end of the list). + +More RamDAC support. The S3 code should have no problem with 868, Trio and +9xx chips except that boards that uses those chips usually uses +newer/unsupported RamDACs as well. + +Multiple-adaptor support. + +IBM RGB52x >8bpp support. diff --git a/doc/add_driver b/doc/add_driver new file mode 100644 index 0000000..693340a --- /dev/null +++ b/doc/add_driver @@ -0,0 +1,6 @@ +Makefile.cfg DRIVER, DRIVER_TEST +src/Makefile +src/vga.c driverspecs, config names, test +src/vga.h +src/driver.h + diff --git a/doc/dual-head-howto b/doc/dual-head-howto new file mode 100644 index 0000000..30afd5b --- /dev/null +++ b/doc/dual-head-howto @@ -0,0 +1,111 @@ +There is a new config option - "device". After you insert the module, you +see output such as (those lines are available with the command dmesg, or +in the file /var/log/messages, depending on your syslog setup): + +svgalib_helper: Initializing, version 1.9.18 +svgalib_helper: device1: vendor:1002 id:4c49 +device1: region0, base=dd000000 len=16777216 type=0 +device1: region1, base=0000d000 len=256 type=1 +device1: region2, base=e4000000 len=4096 type=0 +svgalib_helper: device2: vendor:12d2 id:0018 +device2: region0, base=df000000 len=16777216 type=0 +device2: region1, base=e0000000 len=16777216 type=8 +svgalib_helper: device3: vendor:102b id:051a +device3: region0, base=e1000000 len=16384 type=0 +device3: region1, base=e2000000 len=8388608 type=8 +device3: region2, base=e3000000 len=8388608 type=0 +svgalib_helper: device4: vendor:102b id:0525 +device4: region0, base=d8000000 len=33554432 type=8 +device4: region1, base=da000000 len=16384 type=0 +device4: region2, base=db000000 len=8388608 type=0 + +(Of course, the number of cards, and their types will be different). + +From which you can see which number each card is assigned. Then you +create a different libvga.config for each card, which contains the +device keyword. + +For example In my system I have + +/etc/vga/libvga.config.rage: +novccontrol +secondary +device 1 +BiosParams 3 29500 +include /etc/vga/libvga.config.common +mouse none +HorizSync 30 38 +VertRefresh 40 90 + +/etc/vga/libvga.config.nv3: +helper /dev/svga_helper/2 +novccontrol +secondary +include /etc/vga/libvga.config.common +Modeline "6" 14.16 640 776 840 904 240 332 337 625 -hsync -vsync tvmode tvpal +newmode 640 240 65536 1280 2 +HorizSync 24 60 +VertRefresh 55 75 + +/etc/vga/libvga.config.mystique: +helper /dev/svga3 +novccontrol +secondary +chipset g400 +include /etc/vga/libvga.config.common +Modeline "6" 14.16 640 776 840 904 240 332 337 625 -hsync -vsync tvmode +tvpal +newmode 640 240 65536 1280 2 +HorizSync 30 37 +VertRefresh 30 90 + +/etc/vga/libvga.config.mga: +Device 4 +OverRideEnable +include /etc/vga/libvga.config.common +HorizSync 30 115 +VertRefresh 40 160 + + +Some explanations: + +When the environment variable SVGALIB_CARD is set, svgalib opens the +config file /etc/vga/libvga.config.$SVGALIB_CARD, instead of the usual +/etc/vga/libvga.config. So, if I want to run zgv on the nv3 card, I do +export SVGALIB_CARD=nv3 ; zgv + +The helper keyword can be used similar to the device keyword, to tell +svgalib which device to open. + +All cards except for the primary need to use the secondary and +novccontrol keywords. Secondary tells svgalib not to try to use the +standard VGA ports when accessing this card (since only one card can be +accessed with those, and that is the primary). NoVCControl tells svgalib +not to check or try to control the VC, so you can run an svgalib program +on a secondary card, while working normally on the main head, including +switching virtual consoles. + +You should use "mouse none", or "mdev" options to make sure no two +programs open the mouse at the same time. (Though it is possible with +most mice, and can give some funny results). + +XFree86 likes to disable all PCI video cards that it does not use, +whenever it is started, or switched to, so if you switch in and out of X +on your main card, you need to patch your X server to prevent this +behavior. If you only run X on the main card, and don't return to +text mode, there is no need to patch X. + + +There are no limitations on the primary card. As you can see, I currently +use nvidia, mystique and rage (mach64) cards as secondaries. Also known to +work are sis, r128 (including radeon), laguna, trident and s3 (trio and up) +cards. + + +The main issue with secondary cards is initializing them. If your BIOS +initializes them, that's the best (I heard rumors of such BIOSes, but +never something concrete). The next option is x86emu, this almost always +works (on x86 systems). It also works on some other arches, if you use PC +video cards. If even that fails, then C code is available to initialize some +mach64 cards, and old matrox cards (before G100). + diff --git a/doc/man1/convfont.1 b/doc/man1/convfont.1 new file mode 100644 index 0000000..93713b1 --- /dev/null +++ b/doc/man1/convfont.1 @@ -0,0 +1,80 @@ +.TH convfont 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +convfont \- convert font files for svgalib +.SH SYNOPSIS + +.BI convfont " fontfile fontheight vgafontfile" + +.SH DESCRIPTION +convert the standard format binary fontfile name +.I fontfile +to the codepage format required by +.BR restorefont (1). +The converted font is written to +.IR vgafontfile . + +A binary font file of any number of characters up to 256 can be used, although +at least defining the first 128 characters is a good idea. The +.I fontheight +must be in the range +.BR 1 " - " 32 . + +The +.I fontfile +file consist of +.I fontheight +bytes stored sequentially (top to bottom) for each character in your +font, starting with the character with code 0. + +The format of +.I vgafontfile +is that required by +.BR restorefont (1) +and described there. + +This utility is part of svgalib and can be found in the +.I utils/ +subdirectory of the original svgalib distribution. However, it is not installed +by default, s.t. it is unclear where you can find it if your svgalib was install +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. You +don't need to install it. Just +.B make +in the +.I utils/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR dumpreg (1), +.BR fix132x43 (1), +.BR restorefont (1), +.BR restorepalette (1), +.BR restoretextmode (1), +.BR runx (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/dumpreg.1 b/doc/man1/dumpreg.1 new file mode 100644 index 0000000..64ac372 --- /dev/null +++ b/doc/man1/dumpreg.1 @@ -0,0 +1,54 @@ +.TH dumpreg 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +dumpreg \- dump the state of the card as the svgalib chipset driver sees it. +.SH SYNOPSIS + +.BI dumpreg +.br +.BI "dumpreg < /dev/tty" N + +.SH DESCRIPTION +The chipset drivers of svgalib inquire the mode of the graphic card when the application +is started and restore it when the svgalib application quits. +.B dumpreg +prints this information to stdout. + +This is useful for debugging or adding modes to a device driver. For example you can +use Xfree86 to setup a given mode timing, then run +.B dumpreg +and use it's stdout to make your chipset driver use exactly this timing. + +However, the recent change of svgalib to hunt an own free virtual console does not allow +this, because it will make Xfree86 return to textmode first. You can avoid this by using +the second form where +.I N +is the number of the virtual console on which Xfree86 runs (usually 7) as root. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_dumpregs (3), +.BR convfont (1), +.BR fix132x43 (1), +.BR restorefont (1), +.BR restorepalette (1), +.BR restoretextmode (1), +.BR runx (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/fix132x43.1 b/doc/man1/fix132x43.1 new file mode 100644 index 0000000..e4b7661 --- /dev/null +++ b/doc/man1/fix132x43.1 @@ -0,0 +1,91 @@ +.TH fix132x43 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +fix132x43 \- fix problems with certain (132 column) graphics modes +dump the state of the card as the svgalib chipset driver sees it. +.SH SYNOPSIS + +.BI fix132x43 " options" + +.SH DESCRIPTION +This program tries to fix problems with extended textmodes on some cards. The problem is that for +132x43 textmode, some BIOS's set the vertical display end register to 349 (350), instead of 343 +(344 = 3 * 8 scanlines). Because in Linux textmode video memory is usually filled with old text +that has already scrolled away (this includes the area below the 43rd textmode line, which changes +when the console scrolls), the top half of a constantly changing irrelevant text line is visible +at the bottom of the screen, which is very annoying. + +This program sets the VGA Vertical Display End register to the proper value. + +This problem is at least present in the BIOS of most Cirrus Logic 542x based cards, and +some WD90C03x based cards. + +The +.B LINES +environment variable is used to detect 43 or 44 line consoles. + +.SH OPTIONS +You have to specify exactly one of the following options: +.TP +.B -f +Fix problem of annoying changing line of text at bottom of screen. +.TP +.B -v +Switch to 9 line characters (400 line frame, 70 Hz). +.TP +.B -w +Switch to 11 line characters (480 line frame, 60 Hz). + +.B fix132x43 +does not usually provide this option but it can be enabled in the source of +.BR fix132x43. + +.TP +.B -r +Switch to 8 line characters again (350 line frame, 70 Hz). +.PP +This utility is part of svgalib and can be found in the +.I utils/ +subdirectory of the original svgalib distribution. However, it is not installed +by default, s.t. it is unclear where you can find it if your svgalib was install +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. You +don't need to install it. Just +.B make +in the +.I utils/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR convfont (1), +.BR dumpreg (1), +.BR restorefont (1), +.BR restorepalette (1), +.BR restoretextmode (1), +.BR runx (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/restorefont.1 b/doc/man1/restorefont.1 new file mode 100644 index 0000000..9bb47c9 --- /dev/null +++ b/doc/man1/restorefont.1 @@ -0,0 +1,125 @@ +.TH restorefont 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +restorefont \- save or restore the SVGA font for textmode. +.SH SYNOPSIS + +.BI "restorefont {-r|-w} " filename + +.SH DESCRIPTION +The font used by SVGA when in textmode is written to or restored from +.IR filename +using the +.BR vga_gettextfont "(3) and " +.BR vga_puttextfont (3) +functions. + +.SH FILE FORMAT +The VGA font file +.I filename +has the following format: + +.RS +.BR Offset: +.br +.BR " 0 - 31 " "Character 0" +.br +.BR " ... " " ..." +.br +.BR "8164 - 8195 " "Character 255" +.RE + +Each row of a character bitmap is stored as a byte (8 pixels). +The space that is left from the 32-byte buffer for each character +is ignored, e.g. a 16 line font uses only offsets 0 - 15 of each character. + +Linux textmode screen resolutions: + +.BR 80x25 " 16 line font 400 scanlines" +.br +.BR 80x28 " 14 line font 400 scanlines" +.br +.BR 80x50 " 8 line font 400 scanlines" + +The font sizes and resolutions of extended textmodes depend on the +video card type and BIOS: + +.BR 132x25 " 14 line font 350 scanlines (ugly)" +.br +.BR 132x25 " 16 line font 400 scanlines" +.br +.BR 132x43 " 8 line font 350 scanlines (use fix132x43 to fix/improve)" +.br +.BR 132x50 " 8 line font 400 scanlines" +.br + +Using a font that has less lines per character than the textmode works, but +the characters are smaller. Using a font that is bigger than the textmode +font results in the bottom part of characters being cut off. + +The svgalib distribution contains sample fonts with 8, 14 and 16 line characters +in the files +.IR utils/font8 ", " utils/font14 ", and " utils/font16 . + +The +.BR convfont +(1) program can be used to convert fonts straightforwardly stored +character-after-character (i.e. each character only uses 8/14/whatever +bytes), to the 32-byte per character format that +.B restorefont +requires. + +The purpose of this program is usually to recover from a crashed console due to an +svgalib, Xfree or other program bug. First save the state of the SVGA card when on a +text console. After the crash restore this state. The +.BR savetextmode (1) +and +.BR textmode (1) +script makes this procedure very easy. + +The national/fontpak packages, which include kernel patches, allow different +textmode fonts to be used in different virtual consoles. These have been +superseded by the kbd package (in the kernel since ages). See the +.BR setfont (8) +utility of the kbd package as a starting point. + +Recent kernels support up to 2 fonts with 512 chars each. Recent versions +of svgalib take this into account and extend the size of the datafile accordingly. + +.SH OPTIONS +.TP +.BI "-w " filename +write the font to the file +.IR filename . +.TP +.BI "-r " filename +restore the font from the file +.IR filename . + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR setfont (8), +.BR vga_gettextfont (3), +.BR vga_puttextfont (3), +.BR dumpreg (1), +.BR convfont (1), +.BR fix132x43 (1), +.BR restoretextmode (1), +.BR restorepalette (1), +.BR runx (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1). +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/restorepalette.1 b/doc/man1/restorepalette.1 new file mode 100644 index 0000000..26178e7 --- /dev/null +++ b/doc/man1/restorepalette.1 @@ -0,0 +1,107 @@ +.TH restorepalette 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +restorepalette \- set the color palette for textmode. +.SH SYNOPSIS + +.BI "restorepalette [" filename ] + +.SH DESCRIPTION +.B restorepalette +without arguments sets the standard VGA palette. This can be useful +if it is somehow messed up. + +With a +.I filename +argument a custom palette can be loaded (feature added by Charles Blake +). + +This allow a user to set up a file that looks like this one +(These color map definitions are the same as the default VGA ones. +Alter to suite personal tastes). The first column contains the number of +the color to set, then follow three integers in range 0 - 63 (lowest to +highest intensity) for red, green, blue. + +.RS +.B " 0 0 0 0 # black" +.br +.B " 1 0 0 42 # blue" +.br +.B " 2 0 42 0 # green" +.br +.B " 3 0 42 42 # cyan" +.br +.B " 4 42 0 0 # red" +.br +.B " 5 42 0 42 # magenta" +.br +.B " 6 42 21 0 # brown" +.br +.B " 7 42 42 42 # white" +.br +.B " 8 21 21 21 # bright black" +.br +.B " 9 21 21 63 # bright blue" +.br +.B "10 21 63 21 # bright green" +.br +.B "11 21 63 63 # bright cyan" +.br +.B "12 63 21 21 # bright red" +.br +.B "13 63 21 63 # bright magenta" +.br +.B "14 63 63 21 # bright brown" +.br +.B "15 63 63 63 # bright white" +.RE + +The inline comments are the +only kind of allowed, as I use a little +.BR fscanf (3) +trick to get them. Blank lines +are ok, but not pure comment lines. See the comments in my code, also. + +This allows people to set up custom palettes for use in virtual console text +modes. I use it all the time. When combined with a color-syntax editor like +jed-0.97+ or color-ls, etc., being able to choose your own text-mode palette is +quite a bonus. I set mine up via +.B restorepalette /etc/palette +in my +.IR /etc/rc . +If the program is given the correct permissions, then individual users can +have +.B restorepalette ~/.palette +or some such thing in their shell startup +files. +Of course, it shouldn't be done when starting remote shells or when +under X, so some kind of test that +.B TERM +is a virtual console is needed for that case. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_setpalvec (3), +.BR dumpreg (1), +.BR convfont (1), +.BR fix132x43 (1), +.BR restorefont (1), +.BR restoretextmode (1), +.BR runx (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1). +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/restoretextmode.1 b/doc/man1/restoretextmode.1 new file mode 100644 index 0000000..cc99b78 --- /dev/null +++ b/doc/man1/restoretextmode.1 @@ -0,0 +1,66 @@ +.TH restoretextmode 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +restoretextmode \- save or restore the SVGA registers for textmode. +.SH SYNOPSIS + +.BI "restoretextmode {-r|-w} " filename + +.SH DESCRIPTION +The state of the SVGA is written to or restored from +.IR filename +using the +.BR vga_gettextmoderegs "(3) and " +.BR vga_settextmoderegs (3) +functions. + +As of this writing this file is 385 bytes long but this might change with future versions. + +Please do not fiddle with the contents of the file except when you know what you do. It +might even result in hardware damage. Because of that, you should think twice to make +this command available to all users on your system. + +The purpose of this program is usually to recover from a crashed console due to an +svgalib, Xfree or other program bug. First save the state of the SVGA card when on a +text console. After the crash restore this state. The +.BR savetextmode (1) +and +.BR textmode (1) +script makes this procedure very easy. + +.SH OPTIONS +.TP +.BI "-w " filename +write the SVGA state to the file +.IR filename . +.TP +.BI "-r " filename +restore the SVGA state from the file +.IR filename . +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_gettextmoderegs (3), +.BR vga_settextmoderegs (3), +.BR dumpreg (1), +.BR convfont (1), +.BR fix132x43 (1), +.BR restorefont (1), +.BR restorepalette (1), +.BR runx (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1). +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/runx.1 b/doc/man1/runx.1 new file mode 100644 index 0000000..644491a --- /dev/null +++ b/doc/man1/runx.1 @@ -0,0 +1,104 @@ +.TH runx 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +runx \- try to overcome problems of Xfree96 restoring textmode using svgalib. +.SH SYNOPSIS + +.BI runx + +.SH DESCRIPTION +If XFree86 corrupts your textmode font, try putting +.BR restorefont (1) +in your path and use the shell script +.B runx +to run X. +.B runx +saves the VGA font data in +.IR /tmp/fontdata , +and restores it when you exit X. + +The +.B runx +script actually is: + +.RS +.B #!/bin/sh +.br +.B echo Saving font in /tmp/fontdata +.br +.B restorefont -w /tmp/fontdata +.br +.B startx +.br +.B echo Restoring font from /tmp/fontdata +.br +.B restorefont -r /tmp/fontdata +.RE + +Note that this doesn't help with syncing problems. + +A more rigorous alternative is to run the +.BR savetextmode (1) +script before running X, and +.BR textmode (1) +after. This will restore the textmode registers and the VGA palette in addition to the VGA font. + +Assuming that +.BR savetextmode (1) +and +.BR textmode (1) +are in your +.BR PATH +the +.B runx +script would then look like: + +.RS +.B #!/bin/sh +.br +.B echo Saving SVGA state +.br +.B savetextmode +.br +.B startx +.br +.B echo restoring SVGA state +.br +.B textmode +.RE + +.PP +This utility is part of svgalib and can be found in the +.I utils/ +subdirectory of the original svgalib distribution. However, it is not installed +by default, s.t. it is unclear where you can find it if your svgalib was install +by a linux distribution. + +However, this is no big deal as it was printed out above already ;-). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR convfont (1), +.BR dumpreg (1), +.BR restorefont (1), +.BR restorepalette (1), +.BR restoretextmode (1), +.BR fix132x43 (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/savetextmode.1 b/doc/man1/savetextmode.1 new file mode 100644 index 0000000..c2d48d9 --- /dev/null +++ b/doc/man1/savetextmode.1 @@ -0,0 +1,71 @@ +.TH savetextmode 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +savetextmode, textmode \- save or restore the complete SVGA status for textmode. +.SH SYNOPSIS + +.B savetextmode +.br +.B textmode + +.SH DESCRIPTION +These are simple scripts to save the SVGA register state when in textmode to the +files +.IR /tmp/fontdata " and " /tmp/textregs +or to restore it from these files. + +The actual utilities used are +.BR restorefont (1), +.BR restoretextmode "(1), and " +.BR restorepalette (1). + +The purpose of these scripts program is usually to recover from a crashed console due to an +svgalib, Xfree or other program bug. + +You do this by being a smart guy and running +.B savetextmode +right after booting of your machine, +.B prior +to any problems. Then, in case the SVGA state is hosed and you sit in front of a blank or +useless console, change VC (maybe login) to get to a shell. Or exist the currently running +program with +.BR -C ", " +.BR -- , +or whatever applies. Once you got a shell, run +.B textmode +and it will hopefully render your console useable again. + +To make it clear: You do all this while not seeing anything on your console screen, you +enter this information blindly or after logging in from a network. Also, if the keyboard is +left in raw mode, nothing can really help you as you cannot enter anything which a shell +will understand. + +.SH FILES +.I /tmp/fontdata +.br +.I /tmp/textregs + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR dumpreg (1), +.BR convfont (1), +.BR fix132x43 (1), +.BR restorefont (1), +.BR restoretextmode (1), +.BR restorepalette (1), +.BR runx (1), +.BR setmclk (1), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/setmclk.1 b/doc/man1/setmclk.1 new file mode 100644 index 0000000..158b6ed --- /dev/null +++ b/doc/man1/setmclk.1 @@ -0,0 +1,90 @@ +.TH setmclk 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +setmclk \- adjust the memory timing of certain Cirrus cards. +.SH SYNOPSIS + +.BI setmclk + +.SH DESCRIPTION +This program sets the +.B memory clock +of Cirrus 5424/26/28 cards. + +The first three values could be set by utility programs that +came with my card (AVGA3), but somewhat higher values seem to work (on my +card at least). It may be that better and more recent Cirrus cards use a +higher value as boot-up default. It should depend on DRAM speed, but it +seems to be more dependant on the card logic. + +I have the impression that many Cirrus 542x cards suffer from horrible +BIOS version/DRAM timing misconfigurations. Perhaps even some versions of +MS-Windows drivers change the MCLK register. In any case, the boot-up BIOS +default (0x1c) may be inappropriately low for the type of DRAM timing most +cards use. + +Using a higher memory clock gives a very significant performance improvement; +with high dot clock modes (like 640x480x16M or 1150x900x256) performance can +be more than twice that of the standard 50 MHz clock. This goes for both +(VLB) framebuffer access and accelerated features (bitblt). This also helps +XFree86 server performance, but only if the XFree86 Cirrus driver doesn't +set the memory clock register (it should work for XFree86 1.3 and 2.0). +Use at your own risk! + +Note that the +.B dot clock +is something entirely different. There does not +seem to be much correlation between the two (i.e. if a high dot clock gives +screen problems, using a high memory clock is not likely to fix it, other +than improving speed). + +The actual +.B memory clock +is hard compiled into the program. It defaults to 0x1c. You can change this value +and some suggestiong come in th source of the utility. + +This utility is part of svgalib and can be found in the +.I utils/ +subdirectory of the original svgalib distribution. However, it is not installed +by default, s.t. it is unclear where you can find it if your svgalib was install +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. You +don't need to install it. Just +.B make +in the +.I utils/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR convfont (1), +.BR dumpreg (1), +.BR restorefont (1), +.BR restorepalette (1), +.BR restoretextmode (1), +.BR runx (1), +.BR savetextmode (1), +.BR fix132x43 (1), +.BR textmode (1). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced utility as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man1/svgakeymap.1 b/doc/man1/svgakeymap.1 new file mode 100644 index 0000000..ff0fdbc --- /dev/null +++ b/doc/man1/svgakeymap.1 @@ -0,0 +1,41 @@ +.TH svgakeymap 1 "3 July 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +svgakeymap \- generates keymaps for svgalib + +.SH SYNOPSIS +.BI "svgakeymap [" "physical_table" " [" program_table "]] > " output.keymap + +.SH DESCRIPTION +Generates a keymap conversion file for +.BR svgalib (7) +from two keytable definitions. Keytables are searched for in +.I /usr/lib/kbd/keytables +and are automatically filtered through +.BR gzip (1) +if necessary. + +If only one keytable is specified, a keymap is generated that performs no +conversion but contains the proper key names for that layout. If no keytables +are specified, the standard US QWERTY keyboard is used. + +The generated keymap is sent to the standard output and may be redirected +or piped in any creative manner you wish. + +.SH FILES +.I /usr/lib/kbd/keytables/*.map[.gz] +.RS +The system keytable files used by +.BR loadkeys "(1)." +.RE + +.SH BUGS +Can get confused if there is more than one key with a given name or if names +do not match properly between keytables. Keymaps may require manual editing. + +.SH AUTHOR +Brion Vibber + +.SH SEE ALSO +.BR libvga.config (5) + +.IR README.keymap " from the svgalib distribution" diff --git a/doc/man1/textmode.1 b/doc/man1/textmode.1 new file mode 100644 index 0000000..cbe2634 --- /dev/null +++ b/doc/man1/textmode.1 @@ -0,0 +1 @@ +.so man1/savetextmode.1 diff --git a/doc/man3/currentcontext.3 b/doc/man3/currentcontext.3 new file mode 100644 index 0000000..06c6b74 --- /dev/null +++ b/doc/man3/currentcontext.3 @@ -0,0 +1 @@ +.so man3/gl_getcontext.3 diff --git a/doc/man3/gl_allocatecontext.3 b/doc/man3/gl_allocatecontext.3 new file mode 100644 index 0000000..df663a5 --- /dev/null +++ b/doc/man3/gl_allocatecontext.3 @@ -0,0 +1,48 @@ +.TH gl_allocatecontext 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_allocatecontext \- allocate a graphics context + +.SH SYNOPSIS +.B #include + +.BI "GraphicsContext *gl_allocatecontext(void);" + +.SH DESCRIPTION +Allocate a graphics context. This is preferred to +hardcoding a context variable in a program since the +latter is incompatible with a future vgagl version that +have additional context fields. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_getcontext (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_bcircle.3 b/doc/man3/gl_bcircle.3 new file mode 100644 index 0000000..c6f218d --- /dev/null +++ b/doc/man3/gl_bcircle.3 @@ -0,0 +1,66 @@ +.TH gl_bcircle 3 "4 Dec 1999" "Svgalib (>= 1.4.1)" "Svgalib User Manual" +.SH NAME +gl_bcircle \- draw a filled or unfilled Bresenham circle + +.SH SYNOPSIS +.B #include + +.BI "void gl_bcircle(int " x ", int " y ", int " r ", int " c ", int " fill ");" + +.SH DESCRIPTION +Draw a Bresenham circle of radius +.I r +in color +.I c , +centered at +.I ( x ", " y ). + +.I Fill +should be 0 for a hollow circle, or any other value for a solid color. + +This function differs from gl_circle (3) and gl_fillcircle (3) in that it +looks good in 320 x 200 screen modes. The modified algorithm was provided +by Chris Atenasio , and is based upon Bresenham's +formula. + +Note that the "circle" is technically an ellipse, and is actually wider +than it is tall. Therefore, +.I r +is equal to the circle's height, but is less than its width. This +distortion is necessary to accomodate the 8:5 aspect ratio (e.g., 320 x +200). + +I don't recommend using this function in standard 4:3 screen modes (e.g., +640 x 480 and higher). Furthermore, care must be taken so that a circle +drawn with this function isn't copied to a screen with a different aspect +ratio. Otherwise, the result may be undesirable. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_circle (3), +.BR gl_clearscreen (3), +.BR gl_colorfont (3), +.BR gl_disableclipping (3), +.BR gl_enableclipping (3), +.BR gl_fillbox (3), +.BR gl_fillcircle (3), +.BR gl_hline (3), +.BR gl_line (3), +.BR gl_setclippingwindow (3), +.BR gl_setpalette (3), +.BR gl_setpalettecolor (3), +.BR gl_setpalettecolors (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3), +.BR gl_setrgbpalette (3), +.BR gl_setwritemode (3). + +.SH AUTHOR + +This manual page was written by Jay Link . diff --git a/doc/man3/gl_circle.3 b/doc/man3/gl_circle.3 new file mode 100644 index 0000000..299a868 --- /dev/null +++ b/doc/man3/gl_circle.3 @@ -0,0 +1,53 @@ +.TH gl_circle 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_circle \- draw a circle + +.SH SYNOPSIS +.B #include + +.BI "void gl_circle(int " x ", int " y ", int " r ", int " c ); + +.SH DESCRIPTION +Draw a circle of radius +.I r +in color +.IR c , +centered at +.RI ( x ", " y ). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_clearscreen (3), +.BR gl_colorfont (3), +.BR gl_disableclipping (3), +.BR gl_enableclipping (3), +.BR gl_fillbox (3), +.BR gl_hline (3), +.BR gl_line (3), +.BR gl_setclippingwindow (3), +.BR gl_setpalette (3), +.BR gl_setpalettecolor (3), +.BR gl_setpalettecolors (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3), +.BR gl_setrgbpalette (3), +.BR gl_setwritemode (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_clearscreen.3 b/doc/man3/gl_clearscreen.3 new file mode 100644 index 0000000..815b9b3 --- /dev/null +++ b/doc/man3/gl_clearscreen.3 @@ -0,0 +1,39 @@ +.TH gl_clearscreen 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_clearscreen \- clear the screen + +.SH SYNOPSIS +.B #include + +.BI "void gl_clearscreen(int " c ); + +.SH DESCRIPTION +Fill the entire screen with color +.IR c . + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR currentcontext (3), +.BR gl_circle (3), +.BR gl_fillbox (3), +.BR gl_hline (3), +.BR gl_line (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_colorfont.3 b/doc/man3/gl_colorfont.3 new file mode 100644 index 0000000..46db13f --- /dev/null +++ b/doc/man3/gl_colorfont.3 @@ -0,0 +1,45 @@ +.TH gl_colorfont 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_colorfont \- change the color of a font + +.SH SYNOPSIS +.B #include + +.BI "void gl_colorfont(int " fw ", int " fh ", int " c ", void *" fp ); + +.SH DESCRIPTION +Set all nonzero pixels in the expanded font +.I fp +with 256 characters of size +.IR fw " and " fh +each to color +.IR c . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_colorfont (3), +.BR gl_expandfont (3), +.BR gl_font8x8 (3), +.BR gl_setfontcolors (3), +.BR gl_write (3), +.BR gl_writen (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_compileboxmask.3 b/doc/man3/gl_compileboxmask.3 new file mode 100644 index 0000000..ec4dcde --- /dev/null +++ b/doc/man3/gl_compileboxmask.3 @@ -0,0 +1,52 @@ +.TH gl_compileboxmask 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_compileboxmask \- compress a masked bitmap + +.SH SYNOPSIS +.B #include + +.BI "void gl_compileboxmask(int " w ", int " h ", void *" sdp ", void *" ddp ); + +.SH DESCRIPTION +Convert the rectangular masked bitmap of size +.RI ( w ", " h ") at " sdp +to a compressed format that allows faster drawing, which is +stored at +.IR ddp . +Allocating +.IR w " * " h +bytes for the compiled +version is usually enough; an upper limit should be +.RI ( w " + 2) * " h . + +Compiled bitmaps are only supported in linear 256 color modes. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_compileboxmask (3), +.BR gl_compiledboxmasksize (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_putboxpart (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_compiledboxmasksize.3 b/doc/man3/gl_compiledboxmasksize.3 new file mode 100644 index 0000000..afe5858 --- /dev/null +++ b/doc/man3/gl_compiledboxmasksize.3 @@ -0,0 +1,46 @@ +.TH gl_compiledboxmasksize 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_compiledboxmasksize \- compute the size of a compiled masked box + +.SH SYNOPSIS +.B #include + +.BI "int gl_compiledboxmasksize(int " w ", int " h ", void *" sdp ); + +.SH DESCRIPTION +Returns the size of the compiled version of the masked +bitmap of size +.RI ( w ", " h ) +at +.I sdp +that would be generated by +.BR compileboxmask(3). + +Compiled bitmaps are only supported in linear 256 color modes. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_compileboxmask (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_copybox.3 b/doc/man3/gl_copybox.3 new file mode 100644 index 0000000..68e79ff --- /dev/null +++ b/doc/man3/gl_copybox.3 @@ -0,0 +1,51 @@ +.TH gl_copybox 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_copybox \- copy a rectangular screen area + +.SH SYNOPSIS +.B #include + +.BI "void gl_copybox(int " x1 ", int " y1 ", int " w ", int " h +.BI ", int "x2 ", int " y2 ); + +.SH DESCRIPTION +Copy the rectangular area at +.BR (x1 ", " y1 ) +of size +.BR (w ", " h ), +to +.BR (x2 ", " y2 ) +(screencopy). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_fillbox (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3), +.BR gl_scalebox (3), + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_copyboxfromcontext.3 b/doc/man3/gl_copyboxfromcontext.3 new file mode 100644 index 0000000..3a2672d --- /dev/null +++ b/doc/man3/gl_copyboxfromcontext.3 @@ -0,0 +1,57 @@ +.TH gl_copyboxfromcontext 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_copyboxfromcontext \- copy rectangular area from another context + +.SH SYNOPSIS +.B #include + +.BI "void gl_copyboxfromcontext(GraphicsContext *" gc ", int " x1 ", int " +.IB y1 ", int " w ", int " h ", int " x2 ", int " y2 ); + +.SH DESCRIPTION +Copy the rectangular area at +.RI ( x1 ", " y1 ) +in the context +.IR gc +of size +.RI ( w ", " h ) +to position +.RI ( x2 ", " y2 ) +in the current context. + +This is more efficient than +.BR copyboxtocontext (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_copybox (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_fillbox (3), +.BR gl_getbox (3), +.BR gl_getcontext (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3), +.BR gl_rgbcolor (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_copyboxtocontext.3 b/doc/man3/gl_copyboxtocontext.3 new file mode 100644 index 0000000..2716146 --- /dev/null +++ b/doc/man3/gl_copyboxtocontext.3 @@ -0,0 +1,52 @@ +.TH gl_copyboxtocontext 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_copyboxtocontext \- copy a rectangular area to another context + +.SH SYNOPSIS +.B #include + +.BI "void gl_copyboxtocontext(int " x1 ", int " y1 ", int " w ", int " h +.BI ", GraphicsContext *" gc ", int " x2 ", int " y2 ); + +.SH DESCRIPTION +Copy the rectangular area at +.RI ( x1 ", " y1 ) +of size +.RI ( w ", " h ) +to position +.RI ( x2 ", " y2 ) +in the context +.IR gc . +If possible use +.BR copyboxfromcontext (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyscreen (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_copyscreen.3 b/doc/man3/gl_copyscreen.3 new file mode 100644 index 0000000..68dea74 --- /dev/null +++ b/doc/man3/gl_copyscreen.3 @@ -0,0 +1,45 @@ +.TH gl_copyscreen 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_copyscreen \- copy the screen contents of contexts + +.SH SYNOPSIS +.B #include + +.BI "void gl_copyscreen(GraphicsContext *" gc ); + +.SH DESCRIPTION +Copy the current graphics context contents (screen data) to +the specified graphics context (the physical screen, for +example). Contexts are assumed to be identical in size. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_clearscreen (3), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_fillbox (3), +.BR gl_getbox (3), +.BR gl_putbox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_disableclipping.3 b/doc/man3/gl_disableclipping.3 new file mode 100644 index 0000000..40533c4 --- /dev/null +++ b/doc/man3/gl_disableclipping.3 @@ -0,0 +1,36 @@ +.TH gl_disableclipping 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_disableclipping \- disables clipping + +.SH SYNOPSIS +.B #include + +.BI "void gl_disableclipping(void);" + +.SH DESCRIPTION +Disable clipping. This is the default. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_enableclipping (3), +.BR gl_setclippingwindow (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_enableclipping.3 b/doc/man3/gl_enableclipping.3 new file mode 100644 index 0000000..9a33f8e --- /dev/null +++ b/doc/man3/gl_enableclipping.3 @@ -0,0 +1,41 @@ +.TH gl_enableclipping 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_enableclipping \- enables clipping + +.SH SYNOPSIS +.B #include + +.BI "void gl_enableclipping(void);" + +.SH DESCRIPTION +Enable automatic clipping in most functions. No, I don't know +which ones. However, it works for most. +.BR gl_copybox (3) +is report to do no clipping. + +Go figure. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_disableclipping (3), +.BR gl_setclippingwindow (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_enablepageflipping.3 b/doc/man3/gl_enablepageflipping.3 new file mode 100644 index 0000000..9a8afc7 --- /dev/null +++ b/doc/man3/gl_enablepageflipping.3 @@ -0,0 +1,71 @@ +.TH gl_enablepageflipping 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_enablepageflipping \- enables automatic page flipping + +.SH SYNOPSIS +.B #include + +.BI "int gl_enablepageflipping(GraphicsContext *" gc ); + +.SH DESCRIPTION +Enable page flipping or triple buffering in +.BR gl_copyscreen (3) +if the physical context +.I gc +can do it. + +Returns 3 if triple +buffering will be used, 2 for page flipping, 0 if page +flipping is not possible (due to video memory/mode +limitations). + +When pageflipping is enabled, the +.BR gl_screenoffset (3) +is ignored in +.BR gl_copyscreen (3). + +The idea is that you draw your picture in +.I gc +and copy it to the screen by consecutive +.BR gl_copyscreen (3) +calls. Each of these will choose a free buffer in the screen and +adjust the display start accourdingly. + +The current context must by the VGA when +.BR gl_copyscreen (3) +is called in this situation. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_expandfont.3 b/doc/man3/gl_expandfont.3 new file mode 100644 index 0000000..bb1bf83 --- /dev/null +++ b/doc/man3/gl_expandfont.3 @@ -0,0 +1,53 @@ +.TH gl_expandfont 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_expandfont \- expand a packed pixel font + +.SH SYNOPSIS +.B #include + +.BI "void gl_expandfont(int " fw ", int " fh ", int " c ", void *" sfp ", void *" dfp ); + +.SH DESCRIPTION +Convert a bit-per-pixel font at +.IR sfp +with 256 characters of size +.RI ( fw ", " fh ) +to an expanded font of character pixmaps, stored at +.I dfp +(size will be 256 * +.IR fw " * " fw +.RB " * " BYTESPERPIXEL ). +All non-zero pixels are set to color +.IR c . + +It is possible to use non expanded fonts (but it is slower) when +the +.BR "FONT_COMPRESSED gl_setwritemode" (3) +flag is set. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR testgl (1), +.BR gl_colorfont (3), +.BR gl_font8x8 (3), +.BR gl_setfont (3), +.BR gl_setfontcolors (3), +.BR gl_setwritemode (3), +.BR gl_write (3), +.BR gl_writen (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_fillbox.3 b/doc/man3/gl_fillbox.3 new file mode 100644 index 0000000..82a3444 --- /dev/null +++ b/doc/man3/gl_fillbox.3 @@ -0,0 +1,44 @@ +.TH gl_fillbox 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_fillbox \- fill a rectangular area + +.SH SYNOPSIS +.B #include + +.BI "void gl_fillbox(int " x ", int " y ", int " w ", int " h ", int " c ); + +.SH DESCRIPTION +Fill a rectangular area at position +.RI ( x ", " y ) +with size +.RI ( w ", " h ) +of the screen with a single color +.IR c . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR testgl (1), +.BR currentcontext (3), +.BR gl_clearscreen (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3), +.BR gl_scalebox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_fillcircle.3 b/doc/man3/gl_fillcircle.3 new file mode 100644 index 0000000..5554f1a --- /dev/null +++ b/doc/man3/gl_fillcircle.3 @@ -0,0 +1,46 @@ +.TH gl_fillcircle 3 "4 Dec 1999" "Svgalib (>= 1.4.1)" "Svgalib User Manual" +.SH NAME +gl_fillcircle \- draw a filled circle + +.SH SYNOPSIS +.B #include + +.BI "void gl_fillcircle(int " x ", int " y ", int " r ", int " c ); + +.SH DESCRIPTION +Draw a filled circle of radius +.I r +in color +.I c , +centered at +.I ( x ", " y ). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_circle (3), +.BR gl_clearscreen (3), +.BR gl_colorfont (3), +.BR gl_disableclipping (3), +.BR gl_enableclipping (3), +.BR gl_fillbox (3), +.BR gl_hline (3), +.BR gl_line (3), +.BR gl_setclippingwindow (3), +.BR gl_setpalette (3), +.BR gl_setpalettecolor (3), +.BR gl_setpalettecolors (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3), +.BR gl_setrgbpalette (3), +.BR gl_setwritemode (3). + +.SH AUTHOR + +This manual page was written by Jay Link . The function +itself is based upon the original gl_circle (3). diff --git a/doc/man3/gl_font8x8.3 b/doc/man3/gl_font8x8.3 new file mode 100644 index 0000000..39d8995 --- /dev/null +++ b/doc/man3/gl_font8x8.3 @@ -0,0 +1,49 @@ +.TH gl_font8x8 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_font8x8 \- a packed 8x8 pixel font + +.SH SYNOPSIS +.B #include + +.BI "extern unsigned char *" gl_font8x8 ; + +.SH DESCRIPTION +.I gl_font8x8 +contains a packed pixel font with 8x8 pixels per character which you can +use in your +.B vgagl +programs. Before you can use it, you might need to expand it with +.BR gl_expandfont (3), +though. + +It is possible to use non expanded fonts (but it is slower) when +the +.BR "FONT_COMPRESSED gl_setwritemode" (3) +flag is set. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR testgl (1), +.BR gl_colorfont (3), +.BR gl_expandfont (3), +.BR gl_setfont (3), +.BR gl_setfontcolors (3), +.BR gl_setwritemode (3), +.BR gl_write (3), +.BR gl_writen (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_freecontext.3 b/doc/man3/gl_freecontext.3 new file mode 100644 index 0000000..91adc81 --- /dev/null +++ b/doc/man3/gl_freecontext.3 @@ -0,0 +1,45 @@ +.TH gl_freecontext 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_freecontext \- free a virtual screen + +.SH SYNOPSIS +.B #include + +.BI "void gl_freecontext(GraphicsContext *" gc ); + +.SH DESCRIPTION +Free the space allocated for the virtual screen in the +given context +.I gc +which should better be a virtual context. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_copyscreen (3), +.BR gl_getcontext (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_getbox.3 b/doc/man3/gl_getbox.3 new file mode 100644 index 0000000..03a2223 --- /dev/null +++ b/doc/man3/gl_getbox.3 @@ -0,0 +1,51 @@ +.TH gl_getbox 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_getbox \- copy a rectangular pixmap from the screen to a buffer + +.SH SYNOPSIS +.B #include + +.BI "void gl_getbox(int " x ", int " y ", int " w ", int " h ", void *" dp ); + +.SH DESCRIPTION +Copy a rectangular bitmap at position +.RI ( x ", " y ) +with size +.RI ( w ", " h ) +from the screen to a buffer +.IR dp . + +Pixmaps are in row-major order. The destination pixmap has the size +.IR w " * " h " * " +.BR BYTESPERPIXEL . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_compileboxmask (3), +.BR gl_compiledboxmasksize (3), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3), +.BR gl_scalebox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_getcontext.3 b/doc/man3/gl_getcontext.3 new file mode 100644 index 0000000..6f4fc8b --- /dev/null +++ b/doc/man3/gl_getcontext.3 @@ -0,0 +1,69 @@ +.TH gl_getcontext 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_getcontext, currentcontext \- get the current graphics contents. + +.SH SYNOPSIS +.B #include + +.BI "void gl_getcontext(GraphicsContext *" gc ); + +.BI "extern GraphicsContext " currentcontext ; +/* this is already in vgagl.h */ + +.SH DESCRIPTION +Save the current context in the structure variable +.IR gc . + +You can also get the current context from the global +variable +.IR currentcontext ; + +However, simply access single elements in this structure +with the macros given in +.BR vgagl (7) +but do not copy +.I currentcontext +in another structure. This is because the size of the structure +might change and your program does not know it when it will be +linked dynamically to future svgalib versions. + +Instead use +.BR gl_allocatecontext (3) +to allocate such a structure, fill it with +.B gl_getcontext +and release it with +.BR free (3) +after usage. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_allocatecontext (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_freecontext (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_getpalette.3 b/doc/man3/gl_getpalette.3 new file mode 100644 index 0000000..7077a2f --- /dev/null +++ b/doc/man3/gl_getpalette.3 @@ -0,0 +1 @@ +.so man3/gl_getpalettecolor.3 diff --git a/doc/man3/gl_getpalettecolor.3 b/doc/man3/gl_getpalettecolor.3 new file mode 100644 index 0000000..7988a4f --- /dev/null +++ b/doc/man3/gl_getpalettecolor.3 @@ -0,0 +1,62 @@ +.TH gl_getpalettecolor 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_getpalettecolor, gl_getpalettecolors, gl_getpalette \- read the color palette + +.SH SYNOPSIS +.B #include + +.BI "void gl_getpalettecolor(int " c ", int *" r ", int *" g ", int *" b ); +.br +.BI "void gl_getpalettecolors(int " s ", int " n ", void *" dp ); +.br +.BI "void gl_getpalette(void *" dp ); + +.SH DESCRIPTION +.B gl_getpalettecolor +gets red, green and blue values (in the range 0 - 63) of +color +.I c +from the color-lookup-table, and stores +them as integers in the memory locations pointed to by +.IR r ", " g " and " b . + +.B gl_getpalettecolors +gets RGB values of +.I n +colors starting at +.IR s , +which are stored +as a table of groups of three bytes each at +.IR dp . + +.B gl_getpalette +is equivalent to +.BR "getpalettecolors(0, 256, " dp ). + +.BR vga_ext_set (3) +might change the range of the colors returned to 0 - 255. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR vga_ext_set (3), +.BR gl_setpalette (3), +.BR gl_setpalettecolor (3), +.BR gl_setpalettecolors (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_getpalettecolors.3 b/doc/man3/gl_getpalettecolors.3 new file mode 100644 index 0000000..7077a2f --- /dev/null +++ b/doc/man3/gl_getpalettecolors.3 @@ -0,0 +1 @@ +.so man3/gl_getpalettecolor.3 diff --git a/doc/man3/gl_getpixel.3 b/doc/man3/gl_getpixel.3 new file mode 100644 index 0000000..5f6d926 --- /dev/null +++ b/doc/man3/gl_getpixel.3 @@ -0,0 +1,47 @@ +.TH gl_getpixel 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_getpixel \- return the color of a pixel + +.SH SYNOPSIS +.B #include + +.BI "int gl_getpixel(int " x ", int " y ); + +.SH DESCRIPTION +Returns the color of pixel at position +.RI ( x ", " y ) +in the format used in the screen memory. + +The color -1 is returned for points outside the clipping window. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_getbox (3), +.BR gl_getpalette (3), +.BR gl_getpalettecolor (3), +.BR gl_getpalettecolors (3), +.BR gl_getpixelrgb (3), +.BR gl_rgbcolor (3), +.BR gl_setpalette (3), +.BR gl_setpalettecolor (3), +.BR gl_setpalettecolors (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_getpixelrgb.3 b/doc/man3/gl_getpixelrgb.3 new file mode 100644 index 0000000..2b8340c --- /dev/null +++ b/doc/man3/gl_getpixelrgb.3 @@ -0,0 +1,41 @@ +.TH gl_getpixelrgb 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_getpixelrgb \- store color components of a pixel + +.SH SYNOPSIS +.B #include + +.BI "void gl_getpixelrgb(int " x ", int " y ", int *" r ", int *" g ", int *" b ); + +.SH DESCRIPTION +Store color components from pixel at +.RI ( x ", " y ) +ranging from 0 to 255 into integers pointed to by +.IR r ", " g " and " b . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_getpixel (3), +.BR gl_rgbcolor (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_hline.3 b/doc/man3/gl_hline.3 new file mode 100644 index 0000000..f7dc177 --- /dev/null +++ b/doc/man3/gl_hline.3 @@ -0,0 +1,47 @@ +.TH gl_hline 3 "9 Feb 2000" "Svgalib (>= 1.4.2)" "Svgalib User Manual" +.SH NAME +gl_hline \- draw a horizontal line + +.SH SYNOPSIS +.B #include + +.BI "void gl_hline(int " x1 ", int " y ", int " x2 ", int " c ); + +.SH DESCRIPTION +Draw a horizontal line from point +.RI ( x1 ", " y ) +to +.RI ( x2 ", " y ) +in color +.IR c . +x1 must not be larger than x2. If x2. The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_line.3 b/doc/man3/gl_line.3 new file mode 100644 index 0000000..a18e8b3 --- /dev/null +++ b/doc/man3/gl_line.3 @@ -0,0 +1,56 @@ +.TH gl_line 3 "21 Aug 1999" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_line \- draw a line + +.SH SYNOPSIS +.B #include + +.BI "void gl_line(int " x1 ", int " y1 ", int " x2 ", int " y2 ", int " c ); + +.SH DESCRIPTION +Draw a line from point +.RI ( x1 ", " y1 ) +to +.RI ( x2 ", " y2 ) +inclusively in color +.IR c . + +You should not assume that the same drawing trajectory is used when you exchange start and +end points. + +To use this program one first sets up a mode with a regular +vga_setmode call and vga_setpage(0), with possibly a +vga_setlinearaddressing +call. Then a call to gl_setcontextvga(mode) is made. This makes the +information about the mode available to gl_line. + +The pixels are placed directly into video memory using inline coded +commands. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_circle (3), +.BR gl_clearscreen (3), +.BR gl_hline (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3), +.BR gl_setcontextvga (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. This page was modified by Don Secrest . + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_printf.3 b/doc/man3/gl_printf.3 new file mode 100644 index 0000000..7bae617 --- /dev/null +++ b/doc/man3/gl_printf.3 @@ -0,0 +1,70 @@ +.TH gl_printf 3 "22 Feb 1997" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +gl_printf \- write formatted output in graphic mode + +.SH SYNOPSIS +.B #include + +.BI "int gl_printf(int " x ", int " y ", const char *" fmt ", ...);" + +.SH DESCRIPTION +.B gl_printf +writes, like +.B printf(3) +a formatted string to position +.RI ( x ", " y ) +using the currently selected font. If one or both of +.IR x " and " y +is negative, the text printing continues at the last position. The +special characters +.BR \eb ", " \er ", " +.BR \en ", " \ea ", " +.BR \et " and " \ev +have the usual effects. + +Printing wraps at the screen borders. Nevertheless, behaviour is undefined +if not a single characters fits on the screen or if the initial position +is outside the screen. + +The kind of text draw operation is set with +.BR gl_setwritemode (3). + +.B BEWARE! +Prior to the of use of +.BR gl_printf (3) +you must set a font. + +A good default initialization sequence is: + +.B gl_setfont(8, 8, gl_font8x8); +.br +.B gl_setwritemode(FONT_COMPRESSED + WRITEMODE_OVERWRITE); +.br +.B gl_setfontcolors(0, vga_white()); +.br + +.SH RETURN VALUE +The number of characters printed. + +.SH BUGS +For compatibility reasons this function is not contained in a.out +libraries. + +.SH SEE ALSO +.BR printf (3), +.BR svgalib (7), +.BR vgagl (7), +.BR gl_colorfont (3), +.BR gl_expandfont (3), +.BR gl_font8x8 (3), +.BR gl_setfont (3), +.BR gl_setfontcolors (3), +.BR gl_setwritemode (3), +.BR gl_write (3), +.BR gl_writechar (3), +.BR printftest (6). + +.SH AUTHOR + +This function and manual page was written by Trek +. diff --git a/doc/man3/gl_putbox.3 b/doc/man3/gl_putbox.3 new file mode 100644 index 0000000..a9599ba --- /dev/null +++ b/doc/man3/gl_putbox.3 @@ -0,0 +1,52 @@ +.TH gl_putbox 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_putbox \- copy a pixmap to a rectangular area + +.SH SYNOPSIS +.B #include + +.BI "void gl_putbox(int " x ", int " y ", int " w ", int " h ", void *" dp ); + +.SH DESCRIPTION +Copy the contents of a memory buffer +.I dp +to a rectangular bitmap at position +.RI ( x ", " y ) +with size +.RI ( w ", " h ). + +Pixmaps are in row-major order. The source pixmap memory has the size +.IR w " * " h " * " +.BR BYTESPERPIXEL . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_compileboxmask (3), +.BR gl_compiledboxmasksize (3), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_fillbox (3), +.BR gl_getbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3), +.BR gl_scalebox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_putboxmask.3 b/doc/man3/gl_putboxmask.3 new file mode 100644 index 0000000..bdfe4a9 --- /dev/null +++ b/doc/man3/gl_putboxmask.3 @@ -0,0 +1,58 @@ +.TH gl_putboxmask 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_putboxmask \- copy a masked pixmap to a rectangular area + +.SH SYNOPSIS +.B #include + +.BI "void gl_putboxmask(int " x ", int " y ", int " w ", int " h ", void *" dp ); + +.SH DESCRIPTION +Copy the contents of a memory buffer +.I dp +to a rectangular bitmap at position +.RI ( x ", " y ) +with size +.RI ( w ", " h ). + +This function works like +.BR gl_putbox , +but does not write pixmap pixels of color zero. If the same pixmap is used often +you should consider using the faster +.BR gl_putboxmaskcompiled (3). + +Pixmaps are in row-major order. The source pixmap memory has the size +.IR w " * " h " * " +.BR BYTESPERPIXEL . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_compileboxmask (3), +.BR gl_compiledboxmasksize (3), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_fillbox (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3), +.BR gl_scalebox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_putboxmaskcompiled.3 b/doc/man3/gl_putboxmaskcompiled.3 new file mode 100644 index 0000000..1dcbc88 --- /dev/null +++ b/doc/man3/gl_putboxmaskcompiled.3 @@ -0,0 +1,55 @@ +.TH gl_putboxmaskcompiled 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_putboxmaskcompiled \- copy a compiled masked pixmap to a rectangular area + +.SH SYNOPSIS +.B #include + +.BI "void gl_putboxmaskcompiled(int " x ", int " y ", int " w ", int " h ", void *" dp ); + +.SH DESCRIPTION +Copy the contents of a memory buffer +.I dp +to a rectangular bitmap at position +.RI ( x ", " y ) +with size +.RI ( w ", " h ). + +This function works like +.BR gl_putbox , +but does not write pixmap pixels of color zero. Also, for faster operation the +pixmap was compiled with +.BR gl_compileboxmask (3) +first. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_compileboxmask (3), +.BR gl_compiledboxmasksize (3), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_fillbox (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxpart (3), +.BR gl_scalebox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_putboxpart.3 b/doc/man3/gl_putboxpart.3 new file mode 100644 index 0000000..3860193 --- /dev/null +++ b/doc/man3/gl_putboxpart.3 @@ -0,0 +1,60 @@ +.TH gl_putboxpart 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_putboxpart \- copy a partial pixmap to a rectangular area + +.SH SYNOPSIS +.B #include + +.BI "void gl_putboxpart(int " x ", int " y ", int " w ", int " h +.BI ", int " bw ", int " bh ", void *" dp +.BI ", int " xo ", int " yo ); + +.SH DESCRIPTION +Copy the contents of a memory buffer +.I dp +to a rectangular bitmap at position +.RI ( x ", " y ) +with size +.RI ( w ", " h ). + +However, only a part of size +.RI ( bw ", " bh ) +starting at offset +.RI ( xo ", " yo ) +in the pixmap is copied. + +Pixmaps are in row-major order. The source pixmap memory has the size +.IR w " * " h " * " +.BR BYTESPERPIXEL . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_compileboxmask (3), +.BR gl_compiledboxmasksize (3), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_fillbox (3), +.BR gl_getbox (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_scalebox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_rgbcolor.3 b/doc/man3/gl_rgbcolor.3 new file mode 100644 index 0000000..349774d --- /dev/null +++ b/doc/man3/gl_rgbcolor.3 @@ -0,0 +1,40 @@ +.TH gl_rgbcolor 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_rgbcolor \- return pixel value corresponding to an rgb color + +.SH SYNOPSIS +.B #include + +.BI "int gl_rgbcolor(int " r ", int " g ", int " b ); + +.SH DESCRIPTION +Returns pixel value used in the current context that corresponds with the given color +components. Used by +.BR setpixelrgb (3). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_circle (3), +.BR gl_clearscreen (3), +.BR gl_fillbox (3), +.BR gl_hline (3), +.BR gl_line (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_scalebox.3 b/doc/man3/gl_scalebox.3 new file mode 100644 index 0000000..acc3b34 --- /dev/null +++ b/doc/man3/gl_scalebox.3 @@ -0,0 +1,46 @@ +.TH gl_scalebox 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_scalebox \- scale a pixmap + +.SH SYNOPSIS +.B #include + +.BI "void gl_scalebox(int " w1 ", int " h1 ", void *" sdp ", int " w2 ", int " h2 ", void *" ddp ); + +.SH DESCRIPTION +Scale the bitmap of size +.RI ( w1 ", " h1 ) +at +.I sdp +to size +.RI ( w2 ", " h2 ) +and store it at +.IR ddp , +which must be a large enough buffer. + +The pixel size of the current graphics context is used. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_getbox (3), +.BR gl_putbox (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setclippingwindow.3 b/doc/man3/gl_setclippingwindow.3 new file mode 100644 index 0000000..7bce7a6 --- /dev/null +++ b/doc/man3/gl_setclippingwindow.3 @@ -0,0 +1,38 @@ +.TH gl_setclippingwindow 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setclippingwindow \- set the clipping window + +.SH SYNOPSIS +.B #include + +.BI "void gl_setclippingwindow(int " x1 ", int " y1 ", int " x2 ", int " y2 ); + +.SH DESCRIPTION +Set the clipping window to the rectangle with top-left +corner +.RI ( x1 ", " y1 ) +and bottom-right corner +.RI ( x2 ", " y2 ) +(inclusively). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_disableclipping (3), +.BR gl_enableclipping (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setcontext.3 b/doc/man3/gl_setcontext.3 new file mode 100644 index 0000000..82a4e28 --- /dev/null +++ b/doc/man3/gl_setcontext.3 @@ -0,0 +1,43 @@ +.TH gl_setcontext 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setcontext \- set a previously saved context + +.SH SYNOPSIS +.B #include + +.BI "void gl_setcontext(GraphicsContext *" gc ); + +.SH DESCRIPTION +Restore a previously saved context (make it the current +context). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_freecontext (3), +.BR gl_getcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setcontextheight.3 b/doc/man3/gl_setcontextheight.3 new file mode 100644 index 0000000..2a1d3f6 --- /dev/null +++ b/doc/man3/gl_setcontextheight.3 @@ -0,0 +1 @@ +.so man3/gl_setcontextwidth.3 diff --git a/doc/man3/gl_setcontextvga.3 b/doc/man3/gl_setcontextvga.3 new file mode 100644 index 0000000..a9a7561 --- /dev/null +++ b/doc/man3/gl_setcontextvga.3 @@ -0,0 +1,64 @@ +.TH gl_setcontextvga 3 "21 Aug 1999" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setcontextvga \- set the context to the physical screen + +.SH SYNOPSIS +.B #include + +.BI "int gl_setcontextvga(int " mode ); + +.SH DESCRIPTION +Set the graphics context to the physical screen of a +vga mode (as defined in +.BR vga_setmode (3)). +The mode must be set with +.BR vga_setmode (3) +prior to using any of the drawing functions. +.B vgagl +does not take care of that. + +The function returns 0 for success and non-zero if the mode is not supported by the +hardware. + +The only thing you can do with a planar (mode X-like) +256 color mode is aligned +.BR gl_putbox , +and use it as a target for +.BR gl_copyscreen . + +In all of the svga modes this program makes a description of the vga +mode available to the vgagl functions. The 256 color svgamodes are +handled properly by this program. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_freecontext (3), +.BR gl_line (3), +.BR gl_getcontext (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. This page was modified by Don Secrest . + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setcontextvgavirtual.3 b/doc/man3/gl_setcontextvgavirtual.3 new file mode 100644 index 0000000..1eb901f --- /dev/null +++ b/doc/man3/gl_setcontextvgavirtual.3 @@ -0,0 +1,55 @@ +.TH gl_setcontextvgavirtual 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setcontextvgavirtual \- set the context to a virtual mode + +.SH SYNOPSIS +.B #include + +.BI "int gl_setcontextvgavirtual(int " mode ); + +.SH DESCRIPTION +Allocate a virtual screen in system memory identical to +the graphics mode (as defined in +.BR vga_setmode (3)), +and make that the current graphics context. + +The function returns 0 for success and non-zero if the mode is not supported by the +hardware. + +The only thing you can do with a planar (mode X-like) +256 color mode is aligned +.BR gl_putbox , +and use it as a target for +.BR gl_copyscreen . + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_freecontext (3), +.BR gl_getcontext (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setcontextvirtual.3 b/doc/man3/gl_setcontextvirtual.3 new file mode 100644 index 0000000..4d5ecb6 --- /dev/null +++ b/doc/man3/gl_setcontextvirtual.3 @@ -0,0 +1,54 @@ +.TH gl_setcontextvirtual 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setcontextvirtual \- define a virtual context + +.SH SYNOPSIS +.B #include + +.BI "void gl_setcontextvirtual(int " w ", int " h ", int " bpp ", int " bitspp ", void *" vbuf ); + +.SH DESCRIPTION +Define the current graphics context to have a width of +.I w +pixels, height +.IR h ", " bpp +bytes per pixel, +.I bitspp +significant +color bits per pixel (8, 15, 16 or 24), with the framebuffer +at +.IR vbuf . +A 4 bytes per pixel context, with 24 significant +color bits is also valid. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_freecontext (3), +.BR gl_getcontext (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextwidth (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setcontextwidth.3 b/doc/man3/gl_setcontextwidth.3 new file mode 100644 index 0000000..36978ed --- /dev/null +++ b/doc/man3/gl_setcontextwidth.3 @@ -0,0 +1,50 @@ +.TH gl_setcontextwidth 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setcontextwidth, gl_setcontextheight \- set the dimension of a context + +.SH SYNOPSIS +.B #include + +.BI "void gl_setcontextwidth(int " w ); +.br +.BI "void gl_setcontextheight(int " h ); + +.SH DESCRIPTION +Set the size of the current virtual context, effectively clipping everything to the +top left corner of +size +.RI ( w ", " h ). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_disableclipping (3), +.BR gl_enableclipping (3), +.BR gl_freecontext (3), +.BR gl_getcontext (3), +.BR gl_setcontext (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setdisplaystart (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setdisplaystart.3 b/doc/man3/gl_setdisplaystart.3 new file mode 100644 index 0000000..e9caede --- /dev/null +++ b/doc/man3/gl_setdisplaystart.3 @@ -0,0 +1,48 @@ +.TH gl_setdisplaystart 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setdisplaystart \- set the start of the screen are displayed + +.SH SYNOPSIS +.B #include + +.BI "vga gl_setdisplaystart(int " x ", int " y ); + +.SH DESCRIPTION +Set the physical display start address to the pixel at +.RI ( x ", " y ). + +Can be used for hardware scrolling, or for page flipping +(e.g. +.B setdisplaystart(0, HEIGHT) +displays from the second +page). Make sure the scanline width +.RB ( BYTEWIDTH ) +in bytes +of the current context corresponds with the physical +screen. + +Note also that the display start cannot be set to completely arbitrary points, see +.BR vga_setdisplaystart (3). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR vga_setdisplaystart (3), +.BR gl_copyscreen (3), +.BR gl_setscreenoffset (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setfont.3 b/doc/man3/gl_setfont.3 new file mode 100644 index 0000000..2012aac --- /dev/null +++ b/doc/man3/gl_setfont.3 @@ -0,0 +1,47 @@ +.TH gl_setfont 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setfont \- set the text font to be used + +.SH SYNOPSIS +.B #include + +.BI "void gl_setfont(int " fw ", int " fh ", void *" fp ); + +.SH DESCRIPTION +Use the font stored as character bitmaps at +.IR fp , +with characters of size +.RI ( fw ", " fh ), +as the basic font for write +operations. Note that the font included in the library must +be expanded first, because it is stored bit-per-pixel; +this is not required if the +.B FONT_COMPRESSED +.BR gl_setwritemode (3) +flag is set. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_colorfont (3), +.BR gl_expandfont (3), +.BR gl_font8x8 (3), +.BR gl_setfontcolors (3), +.BR gl_write (3), +.BR gl_writen (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setfontcolors.3 b/doc/man3/gl_setfontcolors.3 new file mode 100644 index 0000000..673f99b --- /dev/null +++ b/doc/man3/gl_setfontcolors.3 @@ -0,0 +1,43 @@ +.TH gl_setfontcolors 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setfontcolors \- set the font colors + +.SH SYNOPSIS +.B #include + +.BI "void gl_setfontcolors(int " bg ", int " fg ); + +.SH DESCRIPTION +Set the background and foreground colors for the compressed +font write mode which is set with +.BR gl_setwritemode (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_colorfont (3), +.BR gl_expandfont (3), +.BR gl_font8x8 (3), +.BR gl_setfont (3), +.BR gl_setwritemode (3), +.BR gl_write (3), +.BR gl_writen (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setpalette.3 b/doc/man3/gl_setpalette.3 new file mode 100644 index 0000000..aee44e1 --- /dev/null +++ b/doc/man3/gl_setpalette.3 @@ -0,0 +1 @@ +.so man3/gl_setpalettecolor.3 diff --git a/doc/man3/gl_setpalettecolor.3 b/doc/man3/gl_setpalettecolor.3 new file mode 100644 index 0000000..1eda303 --- /dev/null +++ b/doc/man3/gl_setpalettecolor.3 @@ -0,0 +1,61 @@ +.TH gl_setpalettecolor 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setpalettecolor, gl_setpalettecolors, gl_setpalette \- set the color palette + +.SH SYNOPSIS +.B #include + +.BI "void gl_setpalettecolor(int " c ", int " r ", int " g ", int " b ); +.br +.BI "void gl_setpalettecolors(int " s ", int " n ", void *" sp ); +.br +.BI "void gl_setpalette(void *" sp ); + +.SH DESCRIPTION +.B gl_setpalettecolor +sets red, green and blue values (in the range 0 - 63) of +color +.I c +from the color-lookup-table to +.IR r ", " g " and " b . + +.B gl_setpalettecolors +sets RGB values of +.I n +colors starting at +.IR s , +which are stored +as a table of groups of three bytes each at +.IR sp . + +.B gl_setpalette +is equivalent to +.BR "setpalettecolors(0, 256, " sp ). + +.BR vga_ext_set (3) +might change the range of the colors to be set to 0 - 255. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR vga_ext_set (3), +.BR gl_getpalette (3), +.BR gl_getpalettecolor (3), +.BR gl_getpalettecolors (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setpalettecolors.3 b/doc/man3/gl_setpalettecolors.3 new file mode 100644 index 0000000..aee44e1 --- /dev/null +++ b/doc/man3/gl_setpalettecolors.3 @@ -0,0 +1 @@ +.so man3/gl_setpalettecolor.3 diff --git a/doc/man3/gl_setpixel.3 b/doc/man3/gl_setpixel.3 new file mode 100644 index 0000000..562e4ea --- /dev/null +++ b/doc/man3/gl_setpixel.3 @@ -0,0 +1,56 @@ +.TH gl_setpixel 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setpixel, gl_setpixelrgb \- draw a pixel + +.SH SYNOPSIS +.B #include + +.BI "void gl_setpixel(int " x ", int " y ", int " c ), +.br +.BI "void gl_setpixelrgb(int " x ", int " y ", int " r ", int " g ", int " b ); + +.SH DESCRIPTION +.B gl_setpixel +draws a single pixel at position +.RI ( x ", " y ) +in color +.IR c . +The lower +8, 15, 16 or 24 bits of the color are significant, depending +on the number of colors the current mode supports. + +.B gl_setpixelrgb +draws a single pixel at position +.RI ( x ", " y ) +with color components +.IR r ", " g ", and " b , +ranging from 0 to 255. In 256 color mode, only +meaningful if the RGB palette is set +.RB ( gl_setrgbpalette (3)). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_circle (3), +.BR gl_fillbox (3), +.BR gl_hline (3), +.BR gl_line (3), +.BR gl_rgbcolor (3), +.BR gl_setrgbpalette (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setpixelrgb.3 b/doc/man3/gl_setpixelrgb.3 new file mode 100644 index 0000000..71d23c5 --- /dev/null +++ b/doc/man3/gl_setpixelrgb.3 @@ -0,0 +1 @@ +.so man3/gl_setpixel.3 diff --git a/doc/man3/gl_setrgbpalette.3 b/doc/man3/gl_setrgbpalette.3 new file mode 100644 index 0000000..6e11032 --- /dev/null +++ b/doc/man3/gl_setrgbpalette.3 @@ -0,0 +1,46 @@ +.TH gl_setrgbpalette 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setrgbpalette \- set a 256-color RGB palette + +.SH SYNOPSIS +.B #include + +.BI "void gl_setrgbpalette(void)" + +.SH DESCRIPTION +Sets 256-color RGB palette (bits 0 - 2 blue, 3 - 5 green, +6 - 7 red). + +Call this prior to using +.BR gl_getpixelrgb (3), +.BR gl_rgbcolor "(3), or " +.BR gl_setpixelrgb (3) +in 256 color modes. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR plane (1), +.BR wrapdemo (1), +.BR gl_getpixelrgb (3), +.BR gl_rgbcolor (3), +.BR gl_setpalette (3), +.BR gl_setpalettecolor (3), +.BR gl_setpalettecolors (3), +.BR gl_setpixelrgb (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setscreenoffset.3 b/doc/man3/gl_setscreenoffset.3 new file mode 100644 index 0000000..fd09d1b --- /dev/null +++ b/doc/man3/gl_setscreenoffset.3 @@ -0,0 +1,43 @@ +.TH gl_setscreenoffset 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setscreenoffset \- set a memory offset for copyscreen + +.SH SYNOPSIS +.B #include + +.BI "void gl_setscreenoffset(int " o ); + +.SH DESCRIPTION +Set the offset in pixels into video memory for +.BR copyscreen (3) +and +.BR copyboxtocontext (3), +.BR copyboxfromcontext (3) +and thus +allows for page-flipping. Must be a +multiple of the scanline width in bytes. It is reset to +zero after the completion of +.BR copyscreen (3). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_enablepageflipping (3). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_setwritemode.3 b/doc/man3/gl_setwritemode.3 new file mode 100644 index 0000000..37fc282 --- /dev/null +++ b/doc/man3/gl_setwritemode.3 @@ -0,0 +1,65 @@ +.TH gl_setwritemode 3 "22 Feb 1998" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_setwritemode \- set the font writemode flags + +.SH SYNOPSIS +.B #include + +.BI "void gl_setwritemode(int " m ); + +.SH DESCRIPTION +Sets the writemode flags for the font routines. It must be the sum of exactly +one choice out of the following two groups: + +.PD 0 +.TP +.B WRITEMODE_MASKED +.TP +.BR WRITEMODE_OVERWRITE " (default)" +.PD +If +.B WRITEMODE_MASKED +is set, only foreground pixels of the font +are used for write operations; the screen background is not +erased. + + +.PD 0 +.TP +.B FONT_COMPRESSED +.TP +.BR FONT_EXPANDED " (default)" +.PD +If +.B FONT_COMPRESSED +is set, text writes will use the compressed +bit-per-pixel font rather than the expanded font (which would be slightly faster). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_colorfont (3), +.BR gl_expandfont (3), +.BR gl_font8x8 (3), +.BR gl_hline (3), +.BR gl_line (3), +.BR gl_setfont (3), +.BR gl_setfontcolors (3), +.BR gl_write (3), +.BR gl_writen (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_striangle.3 b/doc/man3/gl_striangle.3 new file mode 100644 index 0000000..d4a9f3e --- /dev/null +++ b/doc/man3/gl_striangle.3 @@ -0,0 +1,91 @@ +.TH gl_striangle 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_striangle \- draw a solid colored triangle + +.SH SYNOPSIS +.B #include + +.BI "void gl_striangle(int " x0 ", int " y0 ", int " x1 ", int " y1 +.BI ", int "x2 ", int " y2 ", int " color ", int " bf ); + +.SH DESCRIPTION +Draws a non-interpolated (solid) triangle between the three points 0, 1 and 2 +with the color +.IR color . + +The +.I bf +value is used to tell the routine not to draw +the triangle if it is facing the other way. +.I bf +tells +which way the triangle should be facing to be drawn. +since you will more than likely require both +combinations. + +.IB bf " = 0" +disables drawing when the points are arranged clockwise, +.IB bf " = 1" +disables drawing when the points are arranged counter clockwise. +.IB bf " = -1" +will probably always draw the triangle. + +Beware, these functions are not a direct part of the svgalib library. +Instead their source is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not +installed in the system by default, s.t. it is unclear where you can find it +if your svgalib was installed by some +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. Yo +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +The functions are defined in the +.IR tri.o " and " triangl.o +files (or their resp. sources) which you must link to your program. + +.SH SEE ALSO +.BR vgagl (7), +.BR svgalib (7), +.BR threedkit (7), +.BR gl_swtriangle (3), +.BR gl_triangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_trisetdrawpoint (3), +.BR gl_wtriangle (3), +.BR plane (6), +.BR wrapdemo (6). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man3/gl_swtriangle.3 b/doc/man3/gl_swtriangle.3 new file mode 100644 index 0000000..bd5e122 --- /dev/null +++ b/doc/man3/gl_swtriangle.3 @@ -0,0 +1,116 @@ +.TH gl_swtriangle 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_swtriangle \- draw a solid pixmap mapped on a triangle + +.SH SYNOPSIS +.B #include + +.B typedef struct { +.br +.BI " unsigned char *" bitmap1 ; +.br +.BI " unsigned char *" bitmap2 ; +.br +.BI " int " bf ; +.br +.BI "} " TD_tridata ; + +.BI "void gl_swtriangle(int " x0 ", int " y0 ", int " xd0 ", int " yd0 +.BI ", int " x1 ", int " y1 ", int " xd1 ", int " yd1 +.BI ", int " x2 ", int " y2 ", int " xd2 ", int " yd2 ", int " c ", TD_tridata *" tri ); + +.SH DESCRIPTION +Draws a triangle at points 0, 1, 2 by mapping the pixmaps defined +in the +.B TD_triangle +structure into the triangle. + +The +.IR xd " and " yd +values represent the triangle on the +bitmap and the +.IR x " and " y +values represent the triangle +on the screen. + +.I bitmap1 +defines the back side of the triangle, +.I bitmap2 +the front. + +The +.I bf +value is used to tell the routine to draw the backside +if it is facing the other way. +.I bf +tells +which way the triangle should be facing to show the front, +since you will more than likely require both +combinations. + +.IB bf " = 2" +defines the back to be drawn when the points are arranged clockwise, +.IB bf " = 3" +defines the back to be drawn when the points are arranged counter clockwise, +.IB bf " = -1" +will probably always draw the front. + +Beware, these functions are not a direct part of the svgalib library. +Instead their source is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not +installed in the system by default, s.t. it is unclear where you can find it +if your svgalib was installed by some +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. Yo +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +The functions are defined in the +.IR tri.o " and " triangl.o +files (or their resp. sources) which you must link to your program. + +.SH SEE ALSO +.BR vgagl (7), +.BR svgalib (7), +.BR threedkit (7), +.BR gl_striangle (3), +.BR gl_wtriangle (3), +.BR gl_triangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_trisetdrawpoint (3), +.BR plane (6), +.BR wrapdemo (6). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man3/gl_triangle.3 b/doc/man3/gl_triangle.3 new file mode 100644 index 0000000..99a6463 --- /dev/null +++ b/doc/man3/gl_triangle.3 @@ -0,0 +1,105 @@ +.TH gl_triangle 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_triangle \- draw a triangle with interpolated colors + +.SH SYNOPSIS +.B #include + +.BI "void gl_triangle(int " x0 ", int " y0 ", int " z0 ", int " x1 ", int " y1 +.BI ", int " z1 ", int " x2 ", int " y2 ", int " z2 ", int " bf ); + +.SH DESCRIPTION +Draws a triangle between the three points 0, 1 and 2. + +.IR z0 ", " z1 " and " z2 +are the colors at those points. Hence, +if you set the palette to a grayscale, the triangle +will have an interpolated gray shade. + +If you are using +more than 8 bit color, the +.I z +values will be +interpreted as an index to a lookup table of at most +4096 entries long. Each entry is of type +.BR long . + +You can set the entries with the function +.BR gl_trisetcolorlookup (3). + +The +.I bf +value is used to tell the routine not to draw +the triangle if it is facing the other way. +.I bf +tells +which way the triangle should be facing to be drawn. +since you will more than likely require both +combinations. + +.IB bf " = 0" +disables drawing when the points are arranged clockwise, +.IB bf " = 1" +disables drawing when the points are arranged counter clockwise. +.IB bf " = -1" +will probably always draw the triangle. + +Beware, these functions are not a direct part of the svgalib library. +Instead their source is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not +installed in the system by default, s.t. it is unclear where you can find it +if your svgalib was installed by some +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. Yo +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +The functions are defined in the +.IR tri.o " and " triangl.o +files (or their resp. sources) which you must link to your program. + +.SH SEE ALSO +.BR vgagl (7), +.BR svgalib (7), +.BR threedkit (7), +.BR gl_striangle (3), +.BR gl_swtriangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_trisetdrawpoint (3), +.BR gl_wtriangle (3), +.BR plane (6), +.BR wrapdemo (6). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man3/gl_trigetcolorlookup.3 b/doc/man3/gl_trigetcolorlookup.3 new file mode 100644 index 0000000..9bd15da --- /dev/null +++ b/doc/man3/gl_trigetcolorlookup.3 @@ -0,0 +1 @@ +.so man3/gl_trisetcolorlookup.3 diff --git a/doc/man3/gl_trisetcolorlookup.3 b/doc/man3/gl_trisetcolorlookup.3 new file mode 100644 index 0000000..6a1c587 --- /dev/null +++ b/doc/man3/gl_trisetcolorlookup.3 @@ -0,0 +1,85 @@ +.TH gl_trisetcolorlookup 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_trisetcolorlookup, gl_trigetcolorlookup \- manages a color lookup table for shadowing + +.SH SYNOPSIS +.B #include + +.BI "void gl_trisetcolorlookup(int " i ", long " color ); +.br +.BI "long gl_trigetcolorlookup(int " i ); + +.SH DESCRIPTION +.B gl_trisetcolorlookup +sets the color of an index +.I i +in the table used in more than 256 color modes to interpolate tables. + +Note that it is your responsibility to set all the intermediate color values. + +You can use this function to create the index table, +but remember not to let +.I i +go over 4096. + +.B gl_trigetcolorlookup +retrieves a previously set value from the table. + +Beware, these functions are not a direct part of the svgalib library. +Instead their source is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not +installed in the system by default, s.t. it is unclear where you can find it +if your svgalib was installed by some +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. Yo +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +The functions are defined in the +.IR tri.o " and " triangl.o +files (or their resp. sources) which you must link to your program. + +.SH SEE ALSO +.BR vgagl (7), +.BR svgalib (7), +.BR threedkit (7), +.BR gl_striangle (3), +.BR gl_swtriangle (3), +.BR gl_triangle (3), +.BR gl_trisetdrawpoint (3), +.BR gl_wtriangle (3), +.BR plane (6), +.BR wrapdemo (6). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man3/gl_trisetdrawpoint.3 b/doc/man3/gl_trisetdrawpoint.3 new file mode 100644 index 0000000..6710b55 --- /dev/null +++ b/doc/man3/gl_trisetdrawpoint.3 @@ -0,0 +1,87 @@ +.TH gl_trisetdrawpoint 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_trisetdrawpoint \- set a triangle drawing function + +.SH SYNOPSIS +.B #include + +.BI "void gl_trisetdrawpoint(void (" setpixelfunc ") (int " x ", int " y ", int " color ") ); + +.SH DESCRIPTION +If this function is called with +.I setpixelfunc +non-zero, then the function +.I setpixelfunc +is used from +there after to draw each pixel (instead of the usual +direct screen buffer writes). + +This function need never +be used, except if you want to use your own pixel +drawing function for extra effects. If you use +this feature, you can be assured that none of the +triangle routines will access the hardware, +enabling portability to other environments. + +Beware, these functions are not a direct part of the svgalib library. +Instead their source is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not +installed in the system by default, s.t. it is unclear where you can find it +if your svgalib was installed by some +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. Yo +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +The functions are defined in the +.IR tri.o " and " triangl.o + +The functions are defined in the +.IR tri.o " and " triangl.o +files (or their resp. sources) which you must link to your program. + +.SH SEE ALSO +.BR vgagl (7), +.BR svgalib (7), +.BR threedkit (7), +.BR gl_striangle (3), +.BR gl_swtriangle (3), +.BR gl_triangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_wtriangle (3), +.BR plane (6), +.BR wrapdemo (6). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man3/gl_write.3 b/doc/man3/gl_write.3 new file mode 100644 index 0000000..3851b55 --- /dev/null +++ b/doc/man3/gl_write.3 @@ -0,0 +1,67 @@ +.TH gl_write 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_write, gl_writen \- write a text string + +.SH SYNOPSIS +.B #include + +.BI "void gl_write(int " x ", int " y ", char *" s ); +.br +.BI "void gl_writen(int " x ", int " y ", int " n " ,char *" s ); + +.SH DESCRIPTION +.B gl_write +writes the zero terminated string +.I s +to position +.RI ( x ", " y ) +using the currently selected font. + +.B gl_writen +works similarly, but writes exactly +.I n +characters, thus allowing to use the character 0. + +The kind of text draw operation is set with +.BR gl_setwritemode (3). + +.B BEWARE! +Prior to the of use of +.BR gl_write "(3) and " gl_writen (3) +you must set a font. + +A good default initialization sequence is: + +.B gl_setfont(8, 8, gl_font8x8); +.br +.B gl_setwritemode(FONT_COMPRESSED + WRITEMODE_OVERWRITE); +.br +.B gl_setfontcolors(0, vga_white()); +.br + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR svgalib.conf (5), +.BR threedkit (7), +.BR testgl (1), +.BR gl_printf (3), +.BR gl_colorfont (3), +.BR gl_expandfont (3), +.BR gl_font8x8 (3), +.BR gl_setfont (3), +.BR gl_setfontcolors (3), +.BR gl_setwritemode (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/gl_writen.3 b/doc/man3/gl_writen.3 new file mode 100644 index 0000000..50e087b --- /dev/null +++ b/doc/man3/gl_writen.3 @@ -0,0 +1 @@ +.so man3/gl_write.3 diff --git a/doc/man3/gl_wtriangle.3 b/doc/man3/gl_wtriangle.3 new file mode 100644 index 0000000..ea9037d --- /dev/null +++ b/doc/man3/gl_wtriangle.3 @@ -0,0 +1,131 @@ +.TH gl_wtriangle 3 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +gl_wtriangle \- draw a shadowed pixmap mapped on a triangle + +.SH SYNOPSIS +.B #include + +.B typedef struct { +.br +.BI " unsigned char *" bitmap1 ; +.br +.BI " unsigned char *" bitmap2 ; +.br +.BI " int " bf ; +.br +.BI "} " TD_tridata ; + +.BI "void gl_wtriangle(int " x0 ", int " y0 ", int " xd0 ", int " yd0 ", int " z0 +.BI ", int " x1 ", int " y1 ", int " xd1 ", int " yd1 ", int " z1 +.BI ", int " x2 ", int " y2 ", int " xd2 ", int " yd2 ", int " z2 ", TD_tridata *" tri ); + +.SH DESCRIPTION +Draws a triangle at points 0, 1, 2 by mapping the pixmaps defined +in the +.B TD_triangle +structure into the triangle. + +The +.IR xd " and " yd +values represent the triangle on the +bitmap and the +.IR x " and " y +values represent the triangle +on the screen. The +.I z +values represent an additional +value which will be added to the color that is looked +up from the pixmap data. Once again, if the +current context is more than 8 bits then the result +is interpreted as an index to the same lookup table. See +.BR gl_triangle (3) +for more details on shadowing. + +.B gl_wtriangle +is used to draw wrapped surfaces +.B with +shadowing interpolation. The function +.BR gl_swtriangle (3) +does it without shadowing. + +.I bitmap1 +defines the back side of the triangle, +.I bitmap2 +the front. + +The +.I bf +value is used to tell the routine to draw the backside +if it is facing the other way. +.I bf +tells +which way the triangle should be facing to show the front, +since you will more than likely require both +combinations. + +.IB bf " = 2" +defines the back to be drawn when the points are arranged clockwise, +.IB bf " = 3" +defines the back to be drawn when the points are arranged counter clockwise, +.IB bf " = -1" +will probably always draw the front. + +Beware, these functions are not a direct part of the svgalib library. +Instead their source is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not +installed in the system by default, s.t. it is unclear where you can find it +if your svgalib was installed by some +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. Yo +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +The functions are defined in the +.IR tri.o " and " triangl.o +files (or their resp. sources) which you must link to your program. + +.SH SEE ALSO +.BR vgagl (7), +.BR svgalib (7), +.BR threedkit (7), +.BR gl_striangle (3), +.BR gl_swtriangle (3), +.BR gl_triangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_trisetdrawpoint (3), +.BR plane (6), +.BR wrapdemo (6). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man3/graph_mem.3 b/doc/man3/graph_mem.3 new file mode 100644 index 0000000..91210ef --- /dev/null +++ b/doc/man3/graph_mem.3 @@ -0,0 +1 @@ +.so man3/vga_getgraphmem.3 diff --git a/doc/man3/joystick_button1.3 b/doc/man3/joystick_button1.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_button1.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_button2.3 b/doc/man3/joystick_button2.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_button2.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_button3.3 b/doc/man3/joystick_button3.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_button3.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_button4.3 b/doc/man3/joystick_button4.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_button4.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_close.3 b/doc/man3/joystick_close.3 new file mode 100644 index 0000000..b065cda --- /dev/null +++ b/doc/man3/joystick_close.3 @@ -0,0 +1,49 @@ +.TH joystick_close 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +joystick_close \- close a joystick +.SH SYNOPSIS + +.B "#include " + +.BI "void joystick_close(int " joydev ); + +.SH DESCRIPTION +closes the joystick +.I joydev +which was opened with +.BR joystick_init (3). + +.IB joydev " = -1" +closes all currently open joystick devices. Note that any calibration data is lost if you +close a joystick. + +.SH CAVEATS +This function is only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR joytest (6), +.BR mjoytest (6), +.BR joystick_init (3), +.BR joystick_update (3), +.BR joystick_sethandler (3), +.BR joystick_setdefaulthandler (3), +.BR joystick_getnumaxes (3), +.BR joystick_getnumbuttons (3), +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1 (3), +.BR joystick_getb1 (3), +.BR joystick_x (3), +.BR joystick_getx (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man3/joystick_getaxis.3 b/doc/man3/joystick_getaxis.3 new file mode 100644 index 0000000..a3a3dc4 --- /dev/null +++ b/doc/man3/joystick_getaxis.3 @@ -0,0 +1,139 @@ +.TH joystick_getaxis 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +joystick_getaxis, joystick_getbutton \- query the current state of a joystick. +.SH SYNOPSIS + +.B "#include " + +.BI "char joystick_getaxis(int " joydev ", int " a ); +.br +.BI "char joystick_getbutton(int " joydev ", int " b ); + +.SH DESCRIPTION +These functions query the current state of the joystick +.IR joydev . +Actually this is the state found during the last call +to +.BR joystick_update (3) +with the default joystick event handler active. + +.BI "joystick_getaxis(" joydev ", " a ) +return the current state of the given axis (usually it is +.BR "x - 0" ", " "y - 1" ", " "z - 1" ", ...)" +in range +.BR "-128 .. 127" . +Some effort is made such that the center position is close to +.BR 0 . + +Note that especially the version 0.* protocol joystick calibration is very bad. You won't usually +see the extrem values on the extreme position. Also, the center position will be close to zero but +often not be exactly zero and return values will also vary slightly from call to call even when +the user did not move the joystick. + +.BI "joystick_getbutton(" joydev ", " b ) +returns the state of a button. It returns 1 for pressed button and 0 else. Note that no hardware +checks for button clicks. The button press is only detected during a call to +.BR joystick_update (3) +(at least in the 0.* protocol). + +.B NOTE: +The functions simply return the data passed to the default joystick event handler! + +For your convenience, the following stortcuts have been established by use of the preprocessor: + +.RS +.BI joystick_button1( i ) +for +.BI joystick_getbutton( i , +.BR 0) . +.br +.BI joystick_button2( i ) +for +.BI joystick_getbutton( i , +.BR 1) . +.br +.BI joystick_button3( i ) +for +.BI joystick_getbutton( i , +.BR 2) . +.br +.BI joystick_button4( i ) +for +.BI joystick_getbutton( i , +.BR 3) . +.RE + +.RS +.BI joystick_x( i ) +for +.BI joystick_getaxis( i , +.BR 0) . +.br +.BI joystick_y( i ) +for +.BI joystick_getaxis( i , +.BR 1) . +.br +.BI joystick_z( i ) +for +.BI joystick_getaxis( i , +.BR 2) . +.RE + +.RS +.B joystick_getb1() +for +.BR "joystick_getbutton(0, 0)" . +.br +.B joystick_getb2() +for +.BR "joystick_getbutton(0, 1)" . +.br +.B joystick_getb3() +for +.BR "joystick_getbutton(0, 2)" . +.br +.B joystick_getb4() +for +.BR "joystick_getbutton(0, 3)" . +.RE + +.RS +.B joystick_getx() +for +.BR "joystick_getaxis(0, 0)" . +.br +.B joystick_gety() +for +.BR "joystick_getaxis(0, 1)" . +.br +.B joystick_getz() +for +.BR "joystick_getaxis(0, 2)" . +.RE + +.SH CAVEATS +This function is only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR joytest (6), +.BR mjoytest (6), +.BR joystick_init (3), +.BR joystick_close (3), +.BR joystick_update (3), +.BR joystick_sethandler (3), +.BR joystick_setdefaulthandler (3), +.BR joystick_getnumaxes (3), +.BR joystick_getnumbuttons (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man3/joystick_getb1.3 b/doc/man3/joystick_getb1.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_getb1.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_getb2.3 b/doc/man3/joystick_getb2.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_getb2.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_getb3.3 b/doc/man3/joystick_getb3.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_getb3.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_getb4.3 b/doc/man3/joystick_getb4.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_getb4.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_getbutton.3 b/doc/man3/joystick_getbutton.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_getbutton.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_getnumaxes.3 b/doc/man3/joystick_getnumaxes.3 new file mode 100644 index 0000000..e8a9207 --- /dev/null +++ b/doc/man3/joystick_getnumaxes.3 @@ -0,0 +1,47 @@ +.TH joystick_getnumaxes 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +joystick_getnumaxes, joystick_getnumbuttons \- query the capabilities of a joystick +.SH SYNOPSIS + +.B "#include " + +.BI "char joystick_getnumaxes(int " joydev ); +.br +.BI "char joystick_getnumbuttons(int " joydev ); + +.SH DESCRIPTION +queries the number of axes (number of continuous ranges which the joystick allows to choose +from) and buttons. The old version 0.* joystick protocol reports 2 axes (x and y) and 4 buttons +although the actual joystick will usually have less (often two) buttons. + +svgalib supports up to 127 axes and buttons, provided the underlying device driver does it. + +.SH CAVEATS +This function is only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR joytest (6), +.BR mjoytest (6), +.BR joystick_init (3), +.BR joystick_close (3), +.BR joystick_update (3), +.BR joystick_sethandler (3), +.BR joystick_setdefaulthandler (3), +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1 (3), +.BR joystick_getb1 (3), +.BR joystick_x (3), +.BR joystick_getx (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man3/joystick_getnumbuttons.3 b/doc/man3/joystick_getnumbuttons.3 new file mode 100644 index 0000000..710b124 --- /dev/null +++ b/doc/man3/joystick_getnumbuttons.3 @@ -0,0 +1 @@ +.so man3/joystick_getnumaxes.3 diff --git a/doc/man3/joystick_getx.3 b/doc/man3/joystick_getx.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_getx.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_gety.3 b/doc/man3/joystick_gety.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_gety.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_getz.3 b/doc/man3/joystick_getz.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_getz.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_init.3 b/doc/man3/joystick_init.3 new file mode 100644 index 0000000..a68460f --- /dev/null +++ b/doc/man3/joystick_init.3 @@ -0,0 +1,152 @@ +.TH joystick_init 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +joystick_init \- open a joystick +.SH SYNOPSIS + +.B "#include " +.br +.BI "typedef void (*" __joystick_output ") (const char *" msg ); + +.BI "int joystick_init(int " joydev ", __joystick_output " jo ); + +.SH DESCRIPTION +This function opens a joystick device. A negative value is returned on failure, +otherwise the joystick was initialized. +.BR svgalib (7) +supports several joysticks. The corresponding device node names can be configured in +.BR libvga.config (5). + +The +.I joydev +parameter indicates which joystick is to be initialized. As of this writing svgalib +support up to four joysticks +.IB joydev " = 0" +to +.I joydev +.BR "= 3" , +although I'm not aware of hardware and kernel drivers which handle more than joysticks +.BR 0 " and " 1 . + +It is strongly encouraged that your program allows the user to calibrate the joystick. This is +controlled by the +.I jo +parameter. If it is +.BR NULL , +no calibration is performed. Otherwise, calibration is performed and instructions are printed +to the user by calling the user supplied +.I jo +function. It is the responsibility of this function to print the +.B NUL +and +.B NL +terminated message pointed to by +.I msg +to the user. The message might contain embedded +.B NL +characters and will not extend 256 characters including the terminating +.BR NUL . + +Usually an +.BI fputs( msg ", stdout);" +followed by +.B fflush(stdout); +will do, but for your convenience you can perform the same by passing +.B JOY_CALIB_STDOUT +for +.IR jo . +.BR gl_printf (3) +is well suited for this job as well. However, it needs some font setup first, so we do not +provide a special +preprocessor constant. + +It is valid to initialize an already initialized joystick. This allows you to recalibrate the +joystick at any time. The module supports older version 0.* as well as newer version 1.* joystick +device protocols. + +.SH GENERAL CONCEPT +The joystick module is basically independent from the rest of svgalib. You can easily use it +in text mode only (but why would you do that?). If used in a graphics mode, however, it will release +the joystick devices upon a VC switch s.t. several applications can share joysticks. Unfortunately +this does not work during joystick calibration. Therefore, you should lock the VC with +.BR vga_lockvc (3) +while calibrating in graphics mode. + +Also, when using joysticks in textmode only, svgalib won't detect VC switches and joysticks cannot +be shared among applications. + +.BR joystick_close (3) +releases opened joysticks. + +.BR joystick_update (3) +queries the joysticks for position changes. Note that you must busy wait for joystick events. +At least the older version 0.* joystick devices do not allow to sleep and get informed about +new joystick events. Basically, this is a PC hardware issue in the first place. Therefore, +.BR vga_waitevent (3) +does not know about joysticks. To use it, you must make it timeout after a few ms and actively +query the joystick for updates. + +By default a handler deals with the joystick events. +.BR joystick_getaxis "(3) and " joystick_getbutton (3) +plus several convenience macros +.BR joystick_button1|2|3|4 ", " joystick_getb1|2|3|4 ", " joystick_x|y|z ", and " +.B joystick_getx|y|z +allow to query the current status of the joystick (as it was +determined during the last +.B joystick_update() +call). + +The functions +.BR joystick_getnumaxes "(3) and " joystick_getnumbuttons (3) +query the number of axes and buttons of a joystick. + +Finally, you can (un)register an own handler for the joystick events with +.BR joystick_sethandler "(3) and " joystick_setdefaulthandler (3) + +The simple text demo +.BR joytest (6) +and the more complex graphical +.BR mjoytest (6) +demo show the use of the joystick package in some more detail. + +.SH CAVEATS +This function is only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +Certain game ports seem to be unable to detect missing joysticks properly. +(This might also be a linux device driver issue). Anyway, is using the +joystick interface, allow a user of your application to specify the number +of joysticks to be used as well as to bail out the joystick calibration +(when he is not able to press a button on a missing joystick). + +Usually -C works, but you should not rely too much on it, as it can +be disabled. As a general guideline, maybe try to open and calibrate +joysticks while still in +textmode. -C will usually still work then. If this succeeds, you may +assume a joystick is there for any following recalibrations in graphics mode. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR joytest (6), +.BR mjoytest (6), +.BR joystick_close (3), +.BR joystick_update (3), +.BR joystick_sethandler (3), +.BR joystick_setdefaulthandler (3), +.BR joystick_getnumaxes (3), +.BR joystick_getnumbuttons (3), +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1 (3), +.BR joystick_getb1 (3), +.BR joystick_x (3), +.BR joystick_getx (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man3/joystick_setdefaulthandler.3 b/doc/man3/joystick_setdefaulthandler.3 new file mode 100644 index 0000000..92e6240 --- /dev/null +++ b/doc/man3/joystick_setdefaulthandler.3 @@ -0,0 +1 @@ +.so man3/joystick_sethandler.3 diff --git a/doc/man3/joystick_sethandler.3 b/doc/man3/joystick_sethandler.3 new file mode 100644 index 0000000..44f5297 --- /dev/null +++ b/doc/man3/joystick_sethandler.3 @@ -0,0 +1,97 @@ +.TH joystick_sethandler 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +joystick_sethandler, joystick_setdefaulthandler \- set the joystick event handler. +.SH SYNOPSIS + +.B "#include " +.br +.BI "typedef void (*" __joystick_handler ") (int " event ", int " number ", char" +.IB value ", int " joydev ); + +.BI "void joystick_sethandler(int " joydev ", __joystick_handler " jh ); +.br +.BI "void joystick_setdefaulthandler(int " joydev ); + +.SH DESCRIPTION +By default, each call to +.BR joystick_init (3) +enables the default handler for the opened joystick. This handler maintains a state table +which can be read by the +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1|2|3|4 (3), +.BR joystick_getb1|2|3|4 (3), +.BR joystick_x|y|z "(3) and " +.BR joystick_getx|y|z (3) +functions. + +If you define an own handler, the following parameters are passed: + +.RS +.HP +.I event +one of the following values: +.RS +.HP +.B JOY_EVENTBUTTONDOWN +a button was pressed. +.HP +.B JOY_EVENTBUTTONUP +a button was released. +.HP +.B JOY_EVENTAXIS +the joystick position was changed. +.RE + +.IP +All other values are reserved for future use. + +.HP +.I number +identifies the button or axis to which this event belongs. + +.HP +.I value +for axis events the new position in range +.BR "-128 .. 127" . See +.BR joystick_getaxis (3) +for further comments on the range. + +.HP +.I joydev +identifies the joystick affected (this allows to use one handler for many joysticks). +.RE + +.IB joydev " = -1" +modifies the event handler of +all currently open joystick devices. + +.SH CAVEATS +This function is only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR joytest (6), +.BR mjoytest (6), +.BR joystick_init (3), +.BR joystick_close (3), +.BR joystick_update (3), +.BR joystick_getnumaxes (3), +.BR joystick_getnumbuttons (3), +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1 (3), +.BR joystick_getb1 (3), +.BR joystick_x (3), +.BR joystick_getx (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man3/joystick_update.3 b/doc/man3/joystick_update.3 new file mode 100644 index 0000000..0ee7b8c --- /dev/null +++ b/doc/man3/joystick_update.3 @@ -0,0 +1,48 @@ +.TH joystick_update 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +joystick_update \- query joysticks for status changes +.SH SYNOPSIS + +.B "#include " + +.BI "int joystick_update(void); + +.SH DESCRIPTION +queries all currently opened joysticks for position changes and calls the appropriate +event handlers. + +A non-zero value is returned if and only if any joystick reported a position change. In more +detail the logical and of the return value and +.BI "(1 << " joydev ) +is non-zero if this joystick status changed. + +.SH CAVEATS +This function is only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR joytest (6), +.BR mjoytest (6), +.BR joystick_init (3), +.BR joystick_close (3), +.BR joystick_sethandler (3), +.BR joystick_setdefaulthandler (3), +.BR joystick_getnumaxes (3), +.BR joystick_getnumbuttons (3), +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1 (3), +.BR joystick_getb1 (3), +.BR joystick_x (3), +.BR joystick_getx (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man3/joystick_x.3 b/doc/man3/joystick_x.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_x.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_y.3 b/doc/man3/joystick_y.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_y.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/joystick_z.3 b/doc/man3/joystick_z.3 new file mode 100644 index 0000000..b47e073 --- /dev/null +++ b/doc/man3/joystick_z.3 @@ -0,0 +1 @@ +.so man3/joystick_getaxis.3 diff --git a/doc/man3/keyboard_clearstate.3 b/doc/man3/keyboard_clearstate.3 new file mode 100644 index 0000000..d2f6c27 --- /dev/null +++ b/doc/man3/keyboard_clearstate.3 @@ -0,0 +1,48 @@ +.TH keyboard_clearstate 3 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_clearstate \- reset the state of all keys when in raw keyboard mode +.SH SYNOPSIS + +.B "#include " + +.BI "void keyboard_clearstate(void);" + +.SH DESCRIPTION +When in raw keyboard mode, svgalib receives press and release events from the kernel and +keeps track which keys are currently pressed. Calling +.B keyboard_clearstate() +sets this information to all keys released. You can use this for cleanup at certain places +in your program. In addition svgalib resets the states of all keys when a VC switch occurs +because it does not know the current state of keys when it regains control of the console. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_seteventhandler (3), +.BR keyboard_init (3), +.BR keyboard_init_return_fd (3), +.BR keyboard_close (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_getstate (3), +.BR keyboard_keypressed (3), +.BR keyboard_translatekeys (3), +.BR keyboard_update (3), +.BR keyboard_waitforupdate (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_close.3 b/doc/man3/keyboard_close.3 new file mode 100644 index 0000000..5fcf1c5 --- /dev/null +++ b/doc/man3/keyboard_close.3 @@ -0,0 +1,46 @@ +.TH keyboard_close 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_close \- return the keyboard to normal operation from raw mode +.SH SYNOPSIS + +.B "#include " + +.BI "void keyboard_close(void); + +.SH DESCRIPTION +This routine returns the keyboard to normal operation from raw mode. If you used +one of the +.B keyboard_init_*() +routines you should call it prior to leaving your svgalib application as a keyboard in raw mode + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_seteventhandler (3), +.BR keyboard_init (3), +.BR keyboard_init_return_fd (3), +.BR keyboard_update (3), +.BR keyboard_waitforupdate (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_getstate (3), +.BR keyboard_clearstate (3), +.BR keyboard_translatekeys (3), +.BR keyboard_keypressed (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_getstate.3 b/doc/man3/keyboard_getstate.3 new file mode 100644 index 0000000..59871e3 --- /dev/null +++ b/doc/man3/keyboard_getstate.3 @@ -0,0 +1,143 @@ +.TH keyboard_getstate 3 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_getstate \- get a pointer to a buffer holding the state of all keys in raw keyboard mode +.SH SYNOPSIS + +.B "#include " + +.BI "char *keyboard_getstate(void);" + +.SH DESCRIPTION +When in raw keyboard mode this routine returns a pointer +.I buffer +to a static buffer. If the value in +.IB buffer [ scancode ] +is +.BR KEY_PRESSED " or " KEY_NOTPRESSED +the key with that +.I scancode +is pressed or not. Actually +.BR KEY_PRESSED " is 1 and " KEY_NOTPRESSED " is 0," +s.t. you can use constructs like: + +.B "if(buffer[SCANCODE_ENTER]) {" +.br +.BR " " "/* do something */" +.br +.B } + +This is more efficient than calling +.BR keyboard_keypressed (3) +if you want to check for many different keys. + +Please note that keyboard events will only be processed when you occasionally call +.BR keyboard_update "(3) or " +.BR keyboard_waitforupdate (3). + +.BR keyboard_translatekeys (3) +allows certain remap operations which make certain keys (digits, enter) which might have +several physical keys show up under the same scancodes. + +Here are the supported scancodes. The names of the +.B #defines +originate from the US keyboard layout, for other countries, they'll refer to the key +in the same physical location, but the keycap will have a different inscription. For +the list below, add +.BR SCANCODE_ +in front of the names to get the right name for your C source. That means, if it lists +.BR BACKSLASH +below, you shall use +.BR SCANCODE_BACKSLASH +as symbol in your program. In addition to the names below we also have +.BR SCANCODE_0 " - " SCANCODE_9 ", " +.BR SCANCODE_KEYPAD0 " - " SCANCODE_KEYPAD9 ", " +.BR SCANCODE_A " - " SCANCODE_Z ", and " +.BR SCANCODE_F1 " - " SCANCODE_F12 "." + +The other key names are +.BR ESCAPE ", " +.BR MINUS ", " +.BR EQUAL ", " +.BR BACKSPACE ", " +.BR TAB ", " +.BR BRACKET_LEFT ", " +.BR BRACKET_RIGHT ", " +.BR ENTER ", " +.BR LEFTCONTROL ", " +.BR SEMICOLON ", " +.BR APOSTROPHE ", " +.BR GRAVE ", " +.BR LEFTSHIFT ", " +.BR BACKSLASH ", " +.BR COMMA ", " +.BR PERIOD ", " +.BR SLASH ", " +.BR RIGHTSHIFT ", " +.BR KEYPADMULTIPLY ", " +.BR LEFTALT ", " +.BR SPACE ", " +.BR CAPSLOCK ", " +.BR NUMLOCK ", " +.BR SCROLLLOCK ", " +.BR CURSORUPLEFT ", " +.BR CURSORUP ", " +.BR CURSORUPRIGHT ", " +.BR KEYPADMINUS ", " +.BR CURSORLEFT ", " +.BR CURSORRIGHT ", " +.BR KEYPADPLUS ", " +.BR CURSORDOWNLEFT ", " +.BR CURSORDOWN ", " +.BR CURSORDOWNRIGHT ", " +.BR KEYPADPERIOD ", " +.BR LESS ", " +.BR KEYPADENTER ", " +.BR RIGHTCONTROL ", " +.BR CONTROL ", " +.BR KEYPADDIVIDE ", " +.BR PRINTSCREEN ", " +.BR RIGHTALT ", " +.BR BREAK ", " +.BR BREAK_ALTERNATIVE ", " +.BR HOME ", " +.BR CURSORBLOCKUP ", " +.BR PAGEUP ", " +.BR CURSORBLOCKLEFT ", " +.BR CURSORBLOCKRIGHT ", " +.BR END ", " +.BR CURSORBLOCKDOWN ", " +.BR PAGEDOWN ", " +.BR INSERT ", and " +.BR REMOVE "." + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_seteventhandler (3), +.BR keyboard_init (3), +.BR keyboard_init_return_fd (3), +.BR keyboard_close (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_getstate (3), +.BR keyboard_clearstate (3), +.BR keyboard_translatekeys (3), +.BR keyboard_update (3), +.BR keyboard_waitforupdate (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_init.3 b/doc/man3/keyboard_init.3 new file mode 100644 index 0000000..28d7176 --- /dev/null +++ b/doc/man3/keyboard_init.3 @@ -0,0 +1,73 @@ +.TH keyboard_init 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_init, keyboard_init_return_fd \- initialize the keyboard to raw mode +.SH SYNOPSIS + +.B "#include " + +.BI "int keyboard_init(void); +.br +.BI "int keyboard_init_return_fd(void); + +.SH DESCRIPTION +These routines initialize the keyboard to raw mode. No ASCII codes are produced, instead +svgalib keeps track of each single keypress or depress. +The +.B return_fd +version returns the file descriptor of the +console device to allow you to do further tricks with it (though it is unclear which). +The other version just returns 0 if successful. +Both return -1 on error. + +.BR keyboard_close (3) +returns to normal operation. + +When in raw keyboard mode you can no longer use +.BR vga_getch(3) +or +.BR vga_getkey(3) +but you must use +.BR keyboard_getstate (3) +or +.BR keyboard_keypressed (3). + +Depending on the setting of +.BR keyboard_translatekeys (3) +even in raw mode a +.B -C +will cause a +.BR SIGINT. +In any case svgalib will check for +.BR -F1 " - " -F10 +and perform console switches accordingly. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_seteventhandler (3), +.BR keyboard_close (3), +.BR keyboard_update (3), +.BR keyboard_waitforupdate (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_getstate (3), +.BR keyboard_clearstate (3), +.BR keyboard_translatekeys (3), +.BR keyboard_keypressed (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_init_return_fd.3 b/doc/man3/keyboard_init_return_fd.3 new file mode 100644 index 0000000..f48ce2b --- /dev/null +++ b/doc/man3/keyboard_init_return_fd.3 @@ -0,0 +1 @@ +.so man3/keyboard_init.3 diff --git a/doc/man3/keyboard_keypressed.3 b/doc/man3/keyboard_keypressed.3 new file mode 100644 index 0000000..e8a6e62 --- /dev/null +++ b/doc/man3/keyboard_keypressed.3 @@ -0,0 +1,135 @@ +.TH keyboard_keypressed 3 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_keypressed \- check if a key is pressed when in raw keyboard mode +.SH SYNOPSIS + +.B "#include " + +.BI "int keyboard_keypressed(int " scancode ); + +.SH DESCRIPTION +When in raw keyboard mode this routine checks if the key with +.I scancode +is pressed and returns +.BR KEY_PRESSED " or " KEY_NOTPRESSED +accordingly. Actually +.BR KEY_PRESSED " is 1 and " KEY_NOTPRESSED " is 0," +s.t. you can use constructs like: + +.B "if(keyboard_keypressed(SCANCODE_ENTER)) {" +.br +.BR " " "/* do something */" +.br +.B } + +Please note that keyboard events will only be processed when you occasionally call +.BR keyboard_update "(3) or " +.BR keyboard_waitforupdate (3). + +.BR keyboard_translatekeys (3) +allows certain remap operations which make certain keys (digits, enter) which might have +several physical keys show up under the same scancodes. + +Here are the supported scancodes. The names of the +.B #defines +originate from the US keyboard layout, for other countries, they'll refer to the key +in the same physical location, but the keycap will have a different inscription. For +the list below, add +.BR SCANCODE_ +in front of the names to get the right name for your C source. That means, if it lists +.BR BACKSLASH +below, you shall use +.BR SCANCODE_BACKSLASH +as symbol in your program. In addition to the names below we also have +.BR SCANCODE_0 " - " SCANCODE_9 ", " +.BR SCANCODE_KEYPAD0 " - " SCANCODE_KEYPAD9 ", " +.BR SCANCODE_A " - " SCANCODE_Z ", and " +.BR SCANCODE_F1 " - " SCANCODE_F12 "." + +The other key names are +.BR ESCAPE ", " +.BR MINUS ", " +.BR EQUAL ", " +.BR BACKSPACE ", " +.BR TAB ", " +.BR BRACKET_LEFT ", " +.BR BRACKET_RIGHT ", " +.BR ENTER ", " +.BR LEFTCONTROL ", " +.BR SEMICOLON ", " +.BR APOSTROPHE ", " +.BR GRAVE ", " +.BR LEFTSHIFT ", " +.BR BACKSLASH ", " +.BR COMMA ", " +.BR PERIOD ", " +.BR SLASH ", " +.BR RIGHTSHIFT ", " +.BR KEYPADMULTIPLY ", " +.BR LEFTALT ", " +.BR SPACE ", " +.BR CAPSLOCK ", " +.BR NUMLOCK ", " +.BR SCROLLLOCK ", " +.BR CURSORUPLEFT ", " +.BR CURSORUP ", " +.BR CURSORUPRIGHT ", " +.BR KEYPADMINUS ", " +.BR CURSORLEFT ", " +.BR CURSORRIGHT ", " +.BR KEYPADPLUS ", " +.BR CURSORDOWNLEFT ", " +.BR CURSORDOWN ", " +.BR CURSORDOWNRIGHT ", " +.BR KEYPADPERIOD ", " +.BR LESS ", " +.BR KEYPADENTER ", " +.BR RIGHTCONTROL ", " +.BR CONTROL ", " +.BR KEYPADDIVIDE ", " +.BR PRINTSCREEN ", " +.BR RIGHTALT ", " +.BR BREAK ", " +.BR BREAK_ALTERNATIVE ", " +.BR HOME ", " +.BR CURSORBLOCKUP ", " +.BR PAGEUP ", " +.BR CURSORBLOCKLEFT ", " +.BR CURSORBLOCKRIGHT ", " +.BR END ", " +.BR CURSORBLOCKDOWN ", " +.BR PAGEDOWN ", " +.BR INSERT ", and " +.BR REMOVE "." + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_seteventhandler (3), +.BR keyboard_init (3), +.BR keyboard_init_return_fd (3), +.BR keyboard_close (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_keypressed (3), +.BR keyboard_clearstate (3), +.BR keyboard_translatekeys (3), +.BR keyboard_update (3), +.BR keyboard_waitforupdate (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_setdefaulteventhandler.3 b/doc/man3/keyboard_setdefaulteventhandler.3 new file mode 100644 index 0000000..fdd7eb4 --- /dev/null +++ b/doc/man3/keyboard_setdefaulteventhandler.3 @@ -0,0 +1 @@ +.so man3/keyboard_seteventhandler.3 diff --git a/doc/man3/keyboard_seteventhandler.3 b/doc/man3/keyboard_seteventhandler.3 new file mode 100644 index 0000000..78c1d11 --- /dev/null +++ b/doc/man3/keyboard_seteventhandler.3 @@ -0,0 +1,145 @@ +.TH keyboard_seteventhandler 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_seteventhandler, keyboard_setdefaulteventhandler \- define an event handler for keyboard events in raw mode +.SH SYNOPSIS + +.B "#include " + +.BI "typedef void (*" __keyboard_handler ") (int " scancode ", int " press ");" + +.BI "void keyboard_seteventhandler(__keyboard_handler " handler ");" +.br +.BI "void keyboard_setdefaulteventhandler(void);" + +.SH DESCRIPTION +These functions allow to define a keyboard event handler which is called by +.BR keyboard_update "(3) and " +.BR keyboard_waitforupdate (3) +when a keyboard event occured. + +.I press +is +.BR KEY_EVENTRELEASE " or " KEY_EVENTPRESS +if key +.I scancode +was released or pressed. Actually the first value is 0 and the second is 1 which are +so intuitive s.t. you may use them in your program. + +Even you specify an own handler, svgalib will check for +.BR "-F*" " or " "-C" +for console switches or generation of +.BR SIGINT +if allowed by +.BR keyboard_translatekeys (3). + +Calling +.B keyboard_setdefaulteventhandler() +reinstates the default handler which maintains the tables used by +.BR keyboard_getstate "(3) and " +.BR keyboard_keypressed (3). +It is probably a good idea to call +.BR keyboard_clearstate (3) +after reenabling the default handler. + +Here are the supported scancodes. The names of the +.B #defines +originate from the US keyboard layout, for other countries, they'll refer to the key +in the same physical location, but the keycap will have a different inscription. For +the list below, add +.BR SCANCODE_ +in front of the names to get the right name for your C source. That means, if it lists +.BR BACKSLASH +below, you shall use +.BR SCANCODE_BACKSLASH +as symbol in your program. In addition to the names below we also have +.BR SCANCODE_0 " - " SCANCODE_9 ", " +.BR SCANCODE_KEYPAD0 " - " SCANCODE_KEYPAD9 ", " +.BR SCANCODE_A " - " SCANCODE_Z ", and " +.BR SCANCODE_F1 " - " SCANCODE_F12 "." + +The other key names are +.BR ESCAPE ", " +.BR MINUS ", " +.BR EQUAL ", " +.BR BACKSPACE ", " +.BR TAB ", " +.BR BRACKET_LEFT ", " +.BR BRACKET_RIGHT ", " +.BR ENTER ", " +.BR LEFTCONTROL ", " +.BR SEMICOLON ", " +.BR APOSTROPHE ", " +.BR GRAVE ", " +.BR LEFTSHIFT ", " +.BR BACKSLASH ", " +.BR COMMA ", " +.BR PERIOD ", " +.BR SLASH ", " +.BR RIGHTSHIFT ", " +.BR KEYPADMULTIPLY ", " +.BR LEFTALT ", " +.BR SPACE ", " +.BR CAPSLOCK ", " +.BR NUMLOCK ", " +.BR SCROLLLOCK ", " +.BR CURSORUPLEFT ", " +.BR CURSORUP ", " +.BR CURSORUPRIGHT ", " +.BR KEYPADMINUS ", " +.BR CURSORLEFT ", " +.BR CURSORRIGHT ", " +.BR KEYPADPLUS ", " +.BR CURSORDOWNLEFT ", " +.BR CURSORDOWN ", " +.BR CURSORDOWNRIGHT ", " +.BR KEYPADPERIOD ", " +.BR LESS ", " +.BR KEYPADENTER ", " +.BR RIGHTCONTROL ", " +.BR CONTROL ", " +.BR KEYPADDIVIDE ", " +.BR PRINTSCREEN ", " +.BR RIGHTALT ", " +.BR BREAK ", " +.BR BREAK_ALTERNATIVE ", " +.BR HOME ", " +.BR CURSORBLOCKUP ", " +.BR PAGEUP ", " +.BR CURSORBLOCKLEFT ", " +.BR CURSORBLOCKRIGHT ", " +.BR END ", " +.BR CURSORBLOCKDOWN ", " +.BR PAGEDOWN ", " +.BR INSERT ", and " +.BR REMOVE "." + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_init (3), +.BR keyboard_init_return_fd (3), +.BR keyboard_close (3), +.BR keyboard_getstate (3), +.BR keyboard_keypressed (3), +.BR keyboard_clearstate (3), +.BR keyboard_translatekeys (3), +.BR keyboard_update (3), +.BR keyboard_waitforupdate (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_translatekeys.3 b/doc/man3/keyboard_translatekeys.3 new file mode 100644 index 0000000..af8b320 --- /dev/null +++ b/doc/man3/keyboard_translatekeys.3 @@ -0,0 +1,105 @@ +.TH keyboard_translatekeys 3 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_translatekeys \- modify scancode mappings in raw keyboard mode +.SH SYNOPSIS + +.B "#include " + +.BI "void keyboard_translatekeys(int " mask ); + +.SH DESCRIPTION +This function sets several flags which control how certain scancodes are mapped. At startup +a +.I mask +value of 0 is active. + +.I mask +must be a logical or of zero or more of the following +.B #predefined +integers to turn the features listed on: + +.TP +.B TRANSLATE_CURSORKEYS +Translate the scancodes of the +.B SCANCODE_CURSORBLOCK* +keys to those of the cursor keys on the number pad, s.t. +.BR keyboard_getstate "(3) and " keyboard_keypressed (3) +report a keypress of the corresponding number pad cursor key and not the one +on the cursor block. +.TP +.B TRANSLATE_DIAGONAL +Translates the scancodes of diagonal cursor keys (keypad 7, 9, 1, 3) to presses of two +of the ordinary up, down, left, right keys. For example, instead of reporting +a press of +.B SCANCODE_CURSORUPRIGHT +.BR keyboard_getstate "(3) and " keyboard_keypressed (3) +report a simultaneous press of +.BR SCANCODE_CURSORUP " and " SCANCODE_CURSORRIGHT . +.TP +.B TRANSLATE_KEYPADENTER +The scancode of the keypad enter key is mapped to that of the ordinary enter key, s.t. +.BR keyboard_getstate "(3) and " keyboard_keypressed (3) +report a press of +.B SCANCODE_ENTER +regardless if keypad enter or ordinary enter is pressed. +.TP +.B DONT_CATCH_CTRLC +Pressing +.B -C +does +.B not +raise a +.BR SIGINT . +On contrary to the other flags this has also effect when a user defined keyboard event handler +is used. Svgalib will +.BR always " process " -F1 " - " -F10 +and perform console switches accordingly. + +.SH BUGS +The +.B TRANSLATE_* +options above do really do simple scancode translations. For example, when +.B TRANSLATE_KEYPADENTER +is active and the user presses both enter and keypad enter. Then, if he releases +one of them (say keypad enter), it's release event will clear the common keyboard state, s.t. +no keypress is reported even though enter is still pressed. + +Similarly, if +.B TRANSLATE_DIAGONAL +is active, the user holds cursor upleft (keypad 7) down and then presses and release +cursor up (keypad 8), svgalib will only report a pressed cursor left but the simulated +cursor up will be lost. You can easily try this with the +.BR keytest (6) +demo to make the effect more clear to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_seteventhandler (3), +.BR keyboard_init (3), +.BR keyboard_init_return_fd (3), +.BR keyboard_close (3), +.BR keyboard_update (3), +.BR keyboard_waitforupdate (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_getstate (3), +.BR keyboard_clearstate (3), +.BR keyboard_keypressed (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_update.3 b/doc/man3/keyboard_update.3 new file mode 100644 index 0000000..09f5638 --- /dev/null +++ b/doc/man3/keyboard_update.3 @@ -0,0 +1,57 @@ +.TH keyboard_update 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +keyboard_update, keyboard_waitforupdate \- process raw keyboard events +.SH SYNOPSIS + +.B "#include " + +.BI "int keyboard_update(void); +.br +.BI "void keyboard_waitforupdate(void); + +.SH DESCRIPTION +These routines check the keyboard buffer for any raw keyboard events and do the +necessary updates to the internal buffers of +.BR keyboard_clearstate (3) +and +.BR keyboard_keypressed (3). + +When there are no such events, +.B keyboard_update() +returns 0 immediately (non-zero else) whereas +.B keyboard_waitforupdate() +blocks and waits until an event occurs. + +.BR vga_waitevent (3) +allows to wait for keyboard and other events at the same time. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR keytest (6), +.BR eventtest (6), +.BR keyboard_seteventhandler (3), +.BR keyboard_init (3), +.BR keyboard_init_return_fd (3), +.BR keyboard_close (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_getstate (3), +.BR keyboard_clearstate (3), +.BR keyboard_translatekeys (3), +.BR keyboard_keypressed (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/keyboard_waitforupdate.3 b/doc/man3/keyboard_waitforupdate.3 new file mode 100644 index 0000000..4ec7cbf --- /dev/null +++ b/doc/man3/keyboard_waitforupdate.3 @@ -0,0 +1 @@ +.so man3/keyboard_update.3 diff --git a/doc/man3/mouse_close.3 b/doc/man3/mouse_close.3 new file mode 100644 index 0000000..7e22086 --- /dev/null +++ b/doc/man3/mouse_close.3 @@ -0,0 +1,45 @@ +.TH mouse_close 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_close \- explicitly close a mouse +.SH SYNOPSIS + +.B "#include " + +.BI "void mouse_close(void);" + +.SH DESCRIPTION +Closes the mouse device file. This should be called at +the end of the program (if a mouse is used) because it +tries to restore the original mouse state, if it has changed. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mousetest (6), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR mouse_seteventhandler (3), +.BR vga_setmousesupport (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_getbutton.3 b/doc/man3/mouse_getbutton.3 new file mode 100644 index 0000000..510d369 --- /dev/null +++ b/doc/man3/mouse_getbutton.3 @@ -0,0 +1 @@ +.so man3/mouse_getx.3 diff --git a/doc/man3/mouse_getcaps.3 b/doc/man3/mouse_getcaps.3 new file mode 100644 index 0000000..2f3f75e --- /dev/null +++ b/doc/man3/mouse_getcaps.3 @@ -0,0 +1,91 @@ +.TH vga_getmousetype 3 "5 July 1998" "Svgalib (>= 1.3.0)" "Svgalib User Manual" +.SH NAME +mouse_getcaps \- returns the capabilities of the mouse +.SH SYNOPSIS + +.B "#include " + +.BI "int mouse_getcaps(struct MouseCaps *" caps ");" + +.SH DESCRIPTION +This fills a structure with information about the capabilities of the mouse +as configured in +.IR /etc/vga/libvga.config . + +The return value is 0 on success, -1 on failure. Failure indicates that an +older version of the svgalib library is being used that does not support this +function, and the capabilities should be inferred from the mouse type as +retrieved by the function +.BR vga_getmousetype (3). + +.RI "The " MouseCaps " structure contains the following members:" + +.PD 0 +.TP +.B int key; +.RB "After a successful call of " mouse_getcaps " this should be set to " MOUSE_GOTCAPS "." +The values of this and the other members are undefined in the case of failure. +.TP +.B int buttons; +A bitmask indicating which buttons are supported by the device, composed of +.RB "the constants " MOUSE_LEFTBUTTON ", " MOUSE_MIDDLEBUTTON ", " +.BR MOUSE_RIGHTBUTTON ", " MOUSE_FOURTHBUTTON ", " MOUSE_FIFTHBUTTON ", " +.BR MOUSE_SIXTHBUTTON ", and " MOUSE_RESETBUTTON ". Note that " MOUSE_MIDDLEBUTTON +may be set when using mouse protocols that support a middle button even if there +is no button physically present on the mouse. +.TP +.B int axes; +A bitmask indicating which axes are supported by the device, composed of +.RB "the constants " MOUSE_XDIM ", " MOUSE_YDIM ", " MOUSE_ZDIM ", " +.BR MOUSE_RXDIM ", " MOUSE_RYDIM ", and " MOUSE_RZDIM "." +.TP +.B int info; +A bitmask indicating other information about the mouse. Currently the only +.RB "field defined is " MOUSE_INFO_WHEEL ", which indicates that the mouse" +is a wheel mouse. +.TP +.B int reserved0; +Reserved for future use. +.TP +.B int reserved1; +Reserved for future use. +.PD +.PP + +Your application may use this info to perform specific actions (go into a 3d pointer +device mode or make use of a wheel for scrolling for example). + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR mousetest (6), +.BR spin (6), +.BR mouse_close (3), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_init (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_getmousetype (3) +.BR vga_init (3), +.BR vga_setmousesupport (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was heavily edited by Brion Vibber +from material on another function edited by Michael Weller +. The exact source of the original +documentation is unknown. + +It is very likely that it is at least to some extent due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +ask to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_getposition_6d.3 b/doc/man3/mouse_getposition_6d.3 new file mode 100644 index 0000000..e8e8b71 --- /dev/null +++ b/doc/man3/mouse_getposition_6d.3 @@ -0,0 +1,86 @@ +.TH mouse_getposition_6d 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_getposition_6d, mouse_setposition_6d, mouse_setrange_6d \- provide an interface to 3d mice +.SH SYNOPSIS + +.B "#include " + +.BI "void mouse_getposition_6d(int *" x ", int *" y ", int *" z ", int *" rx +.BI ", int *" ry ", int *" rz ); +.br +.BI "void mouse_setposition_6d(int " x ", int " y ", int " z ", int " rx +.BI ", int " ry ", int " rz ", int " dim_mask ); +.br +.BI "void mouse_setrange_6d(int " x1 ", int " x2 ", int " y1 ", int " y2 ", int " z1 +.BI ", int " z2 ", int " rx1 ", int " rx2 ", int " ry1 ", int " ry2 +.BI ", int " rz1 ", int " rz2 ", int " dim_mask ); + +.SH DESCRIPTION +These routines provide the same function as +.BR mouse_getx (3), +.BR mouse_gety (3), +.BR mouse_setxrange (3), +.BR mouse_setyrange (3), +.BR mouse_setposition "(3), and " +.BR mouse_getx (3), +except that they work in all six dimensions, +x, y, z, and rotations about those axes. + +For +.BR mouse_getposition_6d() ", " NULL +pointers may be passed for +any coordinate you don't care to know about. Those dimensions +will be ignored. + +.BR mouse_setposition_6d() " and " mouse_setrange_6d() +take an additional +argument called +.IR dim_mask , +which should be an logical or of the +following: +.BR MOUSE_XDIM ", " MOUSE_YDIM ", " MOUSE_ZDIM ", " MOUSE_RXDIM ", " +.BR MOUSE_RYDIM ", or " MOUSE_RZDIM . +.BR MOUSE_2DIM ", " MOUSE_3DIM ", " MOUSE_6DIM +can be used as shorthand for the XY, XYZ, or +XYZRxRyRz dimensions. The position or ranges will only +be set if that dimension is included in +.IR dim_mask . + +The 6d mouse routines can be used safely with +.B any +mouse type, including standard 2D mice. + +When used with mice that support fewer than six axes, the +other coordinates will always return zero (or whatever value +you set them to). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_setposition (3), +.BR mouse_getx (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_getx.3 b/doc/man3/mouse_getx.3 new file mode 100644 index 0000000..7ca4779 --- /dev/null +++ b/doc/man3/mouse_getx.3 @@ -0,0 +1,62 @@ +.TH mouse_getx 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_getx, mouse_gety, mouse_getbutton \- query the mouse state +.SH SYNOPSIS + +.B "#include " + +.BI "int mouse_getx(void); +.br +.BI "int mouse_gety(void); +.br +.BI "int mouse_getbutton(void); + +.SH DESCRIPTION +These three routines do the obvious, namely returning current mouse pointer position and +button state. +.B mouse_getbutton() +returns an integer which can be bitwise &'d with +.BR MOUSE_LEFTBUTTON ", " MOUSE_MIDDLEBUTTON ", " MOUSE_RIGHTBUTTON ", " +.BR MOUSE_FOURTHBUTTON ", " MOUSE_FIFTHBUTTON ", " MOUSE_SIXTHBUTTON ", or " MOUSE_RESETBUTTON . + +A 1 on any of these bits means the button has been pressed, +a 0 means it hasn't. + +Please note that you need to call +.BR mouse_update (3) +or +.BR mouse_waitforupdate (3) +for the mouse state actually to change. + +For 3d pointer devices, there is actually another interface. See +.BR mouse_getposition_6d (3). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_gety.3 b/doc/man3/mouse_gety.3 new file mode 100644 index 0000000..510d369 --- /dev/null +++ b/doc/man3/mouse_gety.3 @@ -0,0 +1 @@ +.so man3/mouse_getx.3 diff --git a/doc/man3/mouse_init.3 b/doc/man3/mouse_init.3 new file mode 100644 index 0000000..2e4abec --- /dev/null +++ b/doc/man3/mouse_init.3 @@ -0,0 +1,71 @@ +.TH mouse_init 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_init, mouse_init_return_fd \- specifically initialize a mouse +.SH SYNOPSIS + +.B "#include " + +.BI "int mouse_init(char *" dev ", int " type ", int " samplerate ); +.br +.BI "int mouse_init_return_fd(char *" dev ", int " type ", int " samplerate ); + +.SH DESCRIPTION +These routines can be used to open the mouse manually, +ignoring the mouse types or devices specified in the +config file. + +.I dev +is the name of the mouse device +.RI "(defaults to " /dev_mouse ). + +.I samplerate +may be one +.BR MOUSE_DEFAULTSAMPLERATE (150) +or any other value. Probably it is in Hz. + +.I type +is one of the types which are listed already in +.BR vga_getmousetype (3). + +If these routines are used it is not necessary to call +.BR vga_setmousesupport (3), +but it's probably better to not use these and use +.BR vga_setmousesupport (3) +instead. + +The +.B return_fd +version returns the file descriptor of the +mouse device to allow you to do further tricks with the mouse (but the filehandle may change +during a VC switch). The other version just returns 0 if successful. +Both return -1 on error. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_init_return_fd.3 b/doc/man3/mouse_init_return_fd.3 new file mode 100644 index 0000000..3a83afd --- /dev/null +++ b/doc/man3/mouse_init_return_fd.3 @@ -0,0 +1 @@ +.so man3/mouse_init.3 diff --git a/doc/man3/mouse_setdefaulteventhandler.3 b/doc/man3/mouse_setdefaulteventhandler.3 new file mode 100644 index 0000000..2b3a01e --- /dev/null +++ b/doc/man3/mouse_setdefaulteventhandler.3 @@ -0,0 +1 @@ +.so man3/mouse_seteventhandler.3 diff --git a/doc/man3/mouse_seteventhandler.3 b/doc/man3/mouse_seteventhandler.3 new file mode 100644 index 0000000..126bc99 --- /dev/null +++ b/doc/man3/mouse_seteventhandler.3 @@ -0,0 +1,56 @@ +.TH mouse_seteventhandler 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_seteventhandler, mouse_setdefaulteventhandler \- set a mouse event handler +.SH SYNOPSIS + +.B "#include " + +.BI "typedef void (*" __mouse_handler ") (int " button ", int " dx ", int " dy ", int " dz +.BI ", int " drx ", int " dry ", int " drz ); +/* is already in +.B "#include " +included */ + +.BI "void mouse_seteventhandler(__mouse_handler " handler ); +.br +.BI "void mouse_setdefaulteventhandler(void);" + +.SH DESCRIPTION +.BR mouse_update (3) +and +.BR mouse_waitforupdate (3) +will call this function for each change of mouse state and you can do your own book keeping +and maybe even draw a mouse cursor. + +.B mouse_setdefaulteventhandler() +activates the default handler. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_getx (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_setposition.3 b/doc/man3/mouse_setposition.3 new file mode 100644 index 0000000..306860d --- /dev/null +++ b/doc/man3/mouse_setposition.3 @@ -0,0 +1,45 @@ +.TH mouse_setposition 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_setposition \- set the current mouse position +.SH SYNOPSIS + +.B "#include " + +.BI "void mouse_setposition(int " x ", int " y ); + +.SH DESCRIPTION +Sets the current mouse position to +.BI ( x ", " y ). + +For 3d pointer devices, there is actually another interface. See +.BR mouse_getposition_6d (3). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_setposition_6d.3 b/doc/man3/mouse_setposition_6d.3 new file mode 100644 index 0000000..80060df --- /dev/null +++ b/doc/man3/mouse_setposition_6d.3 @@ -0,0 +1 @@ +.so man3/mouse_getposition_6d.3 diff --git a/doc/man3/mouse_setrange_6d.3 b/doc/man3/mouse_setrange_6d.3 new file mode 100644 index 0000000..80060df --- /dev/null +++ b/doc/man3/mouse_setrange_6d.3 @@ -0,0 +1 @@ +.so man3/mouse_getposition_6d.3 diff --git a/doc/man3/mouse_setscale.3 b/doc/man3/mouse_setscale.3 new file mode 100644 index 0000000..1e3ddd2 --- /dev/null +++ b/doc/man3/mouse_setscale.3 @@ -0,0 +1,51 @@ +.TH mouse_setscale 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_setscale \- sets a mouse scale factor +.SH SYNOPSIS + +.B "#include " + +.BI "void mouse_setscale(int " s ); + +.SH DESCRIPTION +This routine sets the scale factor between the motion +reported by the mouse and the size of one pixel. The larger +the scale is, the slower the mouse cursor appears to move. +The scale may be set to any non-zero integer. Negative +scales result in flipped axes. Currently, there is no +support for scale factors between 0 and 1 which would make +the mouse appear faster than usual. + +If this routine is never called, +.RI scale " s" +defaults to 1. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_init (3), +.BR mouse_close (3), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_setposition (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_setwrap.3 b/doc/man3/mouse_setwrap.3 new file mode 100644 index 0000000..1d60588 --- /dev/null +++ b/doc/man3/mouse_setwrap.3 @@ -0,0 +1,85 @@ +.TH mouse_setwrap 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_setwrap \- set what happens at the mouse boundaries +.SH SYNOPSIS + +.B "#include " + +.BI "void mouse_setwrap(int " state ); + +.SH DESCRIPTION +This routine determines what to do if the mouse position +reaches a boundary. + +.I state +should be either +.BR MOUSE_WRAP ", " MOUSE_NOWRAP ", or a bitwise or of " MOUSE_WRAPX ", " +.BR MOUSE_WRAPY ", " MOUSE_WRAPZ ", " MOUSE_WRAPRX ", " MOUSE_WRAPRY ", or " +.BR MOUSE_WRAPRZ . +These define if all or the respective coordinates wrap or are clipped at the ends. + +This variable has been overloaded for the case of +multi-dimensional mice that support rotations and can be +used to select the coordinate system used to return the +current position of the mouse. + +If the above value of state is also ored with +.BR MOUSE_ROT_RX_RY_RZ , +rotational information will be returned +as the angular position as expressed by the total angle wound +around the X, Y, and Z axes. This is the simplest coordinate +system to use, but it's also the least useful, since angular +rotations about perpendicular axes don't commute. There are +situations where this system might be useful, for controlling +truly independent quantities, such as color, with each axis +being used to dial a level of red, green, or blue, but +for modeling the actual orientation of a physical object, +it's utterly hopeless. + +If state is instead ored with +.BR MOUSE_ROT_INFINITESIMAL , +the angular positions returned are expressed as differences +from the previously reported position. If the differences +are sufficiently small, the angular displacements will +commute with each other and can be used to track the motion +of a physical object. +Other coordinate systems, such as yaw, pitch, and roll, +could be defined, but haven't been done due to lack of +time. If you feel you need this feature, send mail +to Eric Sharkey +and he just might consider coding it up. + +.BR MOUSE_WRAP " and " MOUSE_ROT_COORDS +can be used to mask out the +bits used for wrap and coordinate states, respectively. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_getx (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_setxrange.3 b/doc/man3/mouse_setxrange.3 new file mode 100644 index 0000000..9a2a53e --- /dev/null +++ b/doc/man3/mouse_setxrange.3 @@ -0,0 +1,55 @@ +.TH mouse_setxrange 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_setxrange, mouse_setyrange \- define the boundaries for the mouse cursor +.SH SYNOPSIS + +.B "#include " + +.BI "void mouse_setxrange(int " x1 ", int " x2 ); +.br +.BI "void mouse_setyrange(int " y1 ", int " y2 ); + +.SH DESCRIPTION +These two define the boundaries for mouse cursor. +.IR x1 ", " x2 ", " y1 ", and " y2 +are the coordinates of the left, right, bottom, +and top edges of the screen, respectively. + +The return values of +.BR mouse_getx (3) +and +.BR mouse_gety (3) +will always stay in these boundaries. + +For 3d pointer devices, there is actually another interface. See +.BR mouse_getposition_6d (3). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_getx (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_setyrange.3 b/doc/man3/mouse_setyrange.3 new file mode 100644 index 0000000..a91c233 --- /dev/null +++ b/doc/man3/mouse_setyrange.3 @@ -0,0 +1 @@ +.so man3/mouse_setxrange.3 diff --git a/doc/man3/mouse_update.3 b/doc/man3/mouse_update.3 new file mode 100644 index 0000000..5092c0f --- /dev/null +++ b/doc/man3/mouse_update.3 @@ -0,0 +1,46 @@ +.TH mouse_update 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_update \- updates the mouse state +.SH SYNOPSIS + +.B "#include " + +.BI "int mouse_update(void);" + +.SH DESCRIPTION +This reads in mouse events from the mouse buffer and updates +the internal svgalib variables which store the current mouse +position and button states. If there are no events to be +read this routine returns immediately. + +The function returns 0 if there was no event and a non-zero value otherwise. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_getx (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/mouse_waitforupdate.3 b/doc/man3/mouse_waitforupdate.3 new file mode 100644 index 0000000..46c9888 --- /dev/null +++ b/doc/man3/mouse_waitforupdate.3 @@ -0,0 +1,45 @@ +.TH mouse_waitforupdate 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mouse_waitforupdate \- wait for an mouse update +.SH SYNOPSIS + +.B "#include " + +.BI "void mouse_waitforupdate(void);" + +.SH DESCRIPTION +This reads in mouse events from the mouse buffer and updates +the internal svgalib variables which store the current mouse +position and button states. If there are no events the function does +not return until one occurs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_close (3), +.BR mouse_init (3), +.BR mouse_getposition_6d (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_getx (3), +.BR mouse_waitforupdate (3), +.BR vga_setmousesupport (3), +.BR mouse_seteventhandler (3), +.BR vga_waitevent (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_accel.3 b/doc/man3/vga_accel.3 new file mode 100644 index 0000000..8eaa96f --- /dev/null +++ b/doc/man3/vga_accel.3 @@ -0,0 +1,602 @@ +.TH vga_accel 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_accel \- calls the graphics accelerator +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_accel(unsigned " operation ", " ... ); + +.SH DESCRIPTION +This is the major function of the new accelerator interface which was sketched in +version 1.2.3 (Michael: Hmm, it must have been later) but was implemented much later. + +The main goal is to define functions that can be used as part of +certain kinds of interesting graphical operations (not necessarily +interesting primitives on their own). Obvious useful primitives +in their own are FillBox, ScreenCopy, DrawHLineList (solid polygon), +DrawLine. + +An interesting purpose is the fast drawing of color bitmaps, both +straight and transparent (masked, certain color not written). For +masked bitmaps ("sprites"), there is a number of possible methods, +the availability of which depends on the chips. Caching in +non-visible video memory is often useful. One way is to use a +transparency color compare feature of a BITBLT chip, either +transferring the image from system memory or cached in video memory. +If transparency compare is not available, it may be possible to first +clear (zeroe) the mask in the destination area, and then use BITBLT +raster-operation to OR the image into the destination (this requires +the mask color to be 0). A higher level (library) interface should +control this kind of operation. + +.I vga.h +contains several macros which may be used for +.IR operation . +Most of them accept +several optional arguments which you may specify after them. The +.BR accel (6) +svgalib demo shows basic usage of this function. The function returns -1 if the +operation is +not available and 0 if it is (or better: wasi and could be performed). + +Currently the following parameters for +.B vga_accel() +are defined: + +.TP +.BI "vga_accel(ACCEL_FILLBOX, int " x ", int " y ", int " w ", int " h ) +Simple solid fill of a box at pixels +.IR x ", " y " with width " w " and height " h +in the current foreground color +.TP +.BI "vga_accel(ACCEL_SCREENCOPY, int " x1 ", int " y1 ", int " x2 ", int " y2 ", int " w ", int " h ) +Simple screen-to-screen blit. It copies a box of width +.IR w " and height " h +pixels from position +.IR x1 ", " y1 +to position +.IR x2 ", " y2 . +You may assume that the copy is non corrupting in case of overlapping source and destination +areas. +.TP +.BI "vga_accel(ACCEL_SCREENCOPYMONO, int " x1 ", int " y1 ", int " x2 ", int " y2 ", int " w ", int " h ) +Monochrome screen-to-screen blit. It copies a box of width +.IR w " and height " h +pixels from position +.IR x1 ", " y1 +to position +.IR x2 ", " y2 . + +However, each pixel will all bits set to 0 is drawn in the background color, each pixel with all +bits set to 1 is drawn in the foreground color. To allow many different architectures supporting +this routine, behaviour is undefined for other values. Bitmap transparency might be supported +as well. + +You should not expect +.B ACCEL_SCREENCOPYBITMAP +handling overlapping screen areas gracefully. +.TP +.BI "vga_accel(ACCEL_PUTIMAGE, int " x ", int " y ", int " w ", int " h ", void *" p ) +Straight image transfer. It fills the given box with the data in memory area +.IR p . +The memory buffer must contain the pixels in the same representation as used in the vga memory, +starting at the top left corner, from left to right, and then, line by line, from up to down, +without any gaps and interline spaces. +.TP +.BI "vga_accel(ACCEL_DRAWLINE, int " x1 ", int " y1 ", int " x2 ", int " y2 )) +General line draw. Draws a line from +.IR x1 ", " y1 +to position +.IR x2 ", " y2 " in the foreground color." +You should not expect the reverse line from +.IR x2 ", " y2 +to position +.IR x1 ", " y1 " to use the exact same pixels on the screen." +Several, esp. hardware, algorithms tend to yield to surprising results. +.TP +.BI "vga_accel(ACCEL_SETFGCOLOR, int " color ) +Sets foreground color. It is used by most other draw commands. + +.TP +.BI "vga_accel(ACCEL_SETBGCOLOR, int " color ) +Set background color. It is used by draw commands which might also + +.TP +.BI "vga_accel(ACCEL_SETTRANSPARENCY, int " mode ", " ... ) +Set transparency mode, see the table below for an explanation parameters. + +.TP +.BI "vga_accel(ACCEL_SETRASTEROP, int " mode ) +Set raster-operation, see the table below for an explanation of parameters. + +.TP +.BI "vga_accel(ACCEL_PUTBITMAP, int " x ", int " y ", int " w ", int " h ", void *" p ) +Color-expand bitmap. This works similar to +.B ACCEL_PUTIMAGE +but the bitmap +.I *p +is a one bit bitmap. +Each pixel related to a set bit in +.I *p +is drawn in the foreground color, the other pixels are drawn in the background color. + +Each byte at +.I *p +contains 8 pixels. +The lowest order bit of each byte is leftmost on the screen +(contrary to the VGA tradition), irrespective of the bitmap +bit order flag. Each scanline is aligned to a multiple of +32-bits. + +If the transparency mode is enabled (irrespective of the +transparency color), then bits that are zero in the bitmap +are not written (the background color is not used). + +.TP +.BI "vga_accel(ACCEL_SCREENCOPYBITMAP, int " x1 ", int " y1 ", int " x2 ", int " y2 ", int " w ", int " h ) +Color-expand from screen. This works similar to +.B ACCEL_PUTBITMAP +but the bitmap +lies at position +.IR x1 ", " y1 +and the destination box at +.IR x2 ", " y2. + +Alas, the sizes of the pixels in both bitmap are different. The bitmap +.I *p +must have the format corresponding to +.B ACCEL_PUTBITMAP +but will start at the screen memory location where +the pixel +.RI ( x1 ", " y1 ) +would be (probably in off screen memory). + +In modes where pixel will not start at byte boundaries (typically those with less then +256 colors), the pixel +.RI ( x1 ", " y1 ) +must start at a byte boundary (for example in a 16 color mode (4bpp rather than 8bpp for +256 colors) this means that +.I x1 +should be an even number). + +The easiest way to achieve this is probably to choose +.IB x1 " == 0" +in these situations. + +You should not expect +.B ACCEL_SCREENCOPYBITMAP +handling overlapping screen areas gracefully. +.TP +.BI "vga_accel(ACCEL_DRAWHLINELIST, int " y ", int " n ", int *" x1 ", int *" x2 ) +Draw horizontal spans. Each of the +.IR *x1 " and " *x2 +arrays contains +.I n +x-coordinate pairs. Starting with a horizontal line from +.IR *x1 , y " to " *x2 , y +consecutive horizontal lines (with increasing +.I y +values) are drawn using the start and end points in +.IR *x1 " and " *x2 . +This is usually a very quick operation and useful to draw arbitrary polygons (when the +accelerator cannot do an arbitrary polygon fill itself). +.TP +.BI "vga_accel(ACCEL_POLYLINE, int " flag ", int " n ", unsigned short *" coords ) +draws a contiguous line through the +.I n +points listed in +.IR *coords . +.I *coords +contains +.I n +pairs of shorts, the first is the x coordinate, the second is the y coordinate. + +Normally +.I +flag +should have the value +.BR "ACCEL_START | ACCEL_END" . +However, if the evaluation of the points is costly, you can mix calculations and drawings. +Your first call to +.BI "vga_accel(ACCEL_POLYLINE, " ... ) +must have +.B ACCEL_START +set. This will initialize the accelerator. If you do not specify +.BR ACCEL_END , +you can (actually you have to) follow your call with another +.BI "vga_accel(ACCEL_POLYLINE, " ... ) +call which will give additional points to connect. + +It is important that no other operations (even no color settings) take place +between a call with +.BR ACCEL_START " and the one with the corresponding " ACCEL_END . +Because of this, it is also important that you lock the console with +.BR vga_lockvc (3) +and +.BR vga_unlockvc (3), +s.t. you cannot be interrupted by a console switch. + +It is allowed not to set +.B ACCEL_END +for your last call to +.BI "vga_accel(ACCEL_POLYLINE, " ... ). This will not draw the last pixel of the last +line which is important for some raster operations when drawing closed polygons. +The accelerator will automatically deinitialize when called with another operation in +this situation. + +It is undefined what happens when you specify other values for +.I flag +and when your polyline contains only a single point. The line segments must also not +be of length zero. + +For implementors: In conjunction with raster operations +.RB ( ROP_XOR ", " ROP_INV ) +it is important that endpoints of inner line section are only drawn once. If you cannot achieve +that, you must signal that this function cannot be used in conjunction with raster operations. +In this case it is valid to always draw all points of the line segments including the endpoints +regardless of the existence of a +.B ACCEL_END +parameter. +.TP +.BI "vga_accel(ACCEL_POLYHLINE, int " flag ", int " y ", int " n ", unsigned short *" xcoords ) +This function combines the features of +.B ACCEL_POLYLINE +and +.BR ACCEL_DRAWHLINELIST . +Starting in row +.I y +horizontal lines are drawn from top to bottom. For each horizontal scanline the +.I *coords +array will contain a number +.I m +followed by +.I m +x coordinates in left to right order. Horizontal lines are drawn between the first and the +second, the third and the fourth x coordinates, and so on. If the +.I m +coordinates are exhausted, +.I y +is increased, a new number +.I m +is read from the +.I *coords +array and operation continues. + +This procedure is done for +.I n +scan lines. + +In addition there is a +.I flag parameter which works similar to +.BR ACCEL_POLYLINE . +Your first call to +.B ACCEL_DRAWHLINELIST +must have the +.B ACCEL_START +bit set for proper initialization. The +.I y +parameter is ignored when +.B ACCEL_START +is not given. + +On contrary to +.B ACCEL_POLYLINE +it is required that the last call has the +.B ACCEL_END +bit set. + +The function is intended for drawing complex filled polygons using horizontal scanlines. +By issuing small and fast calls for few scanlines only it is possible to intermix drawing and +calculations. + +The operation of +.B ACCEL_POLYHLINE +is undefined if the x coordinates are not sorted from left to right or there are zero length +segments in any scan line or if +.IR n " or one of the " m +counters are zero, or one of the +.IR m 's +is not even. +.TP +.BI "vga_accel(ACCEL_POLYFILLMODE, " onoff ) +Switches polygon fill mode on +.RI ( onoff " non-zero) +or off. + +When in polygon fill mode, +.BR ACCEL_DRAWLINE " and " ACCEL_POLYLINE +will only draw a single point on each scanline of each line segment. +.B ACCEL_SCREENCOPYMONO +will horizontally scan it's source area and start drawing in the foreground color when it +encounters a set pixel. When the next pixel is encountered, it will start using the background +color and so on. + +This can be used for hardware filled polygons: +.RS +.IP 1. +Enable polygon fill mode. +.IP 2. +Fill an offscreen rectangular area with a the color with all bits zero (usually black). +.IP 3. +Draw a (usually closed) polygon outline in this offscreen area in the color with all bits set +(usually white). To get the proper bits set for the polygon outline, it is recommended +to use +.B ROP_XOR +s.t. outlines intersecting in a single point are handled correctly. To ensure that polygon +corners are handled right, both start and end points must be drawn (in +.B ROP_XOR +mode). Thus it is best to use +.B ACCEL_DRAWLINE +instead of +.BR ACCEL_POLYLINE . +Finally, skip drawing all horizontal lines (which would confuse +.BR ACCEL_SCREENCOPYMONO ). +.IP 4. +Set fore- and background colors, raster operation, bitmap transparency to those you want for +your polygon. +.IP 5. +Use +.B ACCEL_SCREENCOPYMONO +to copy the offscreen pattern to the screen. +.RE +.IP +The rasteroperations and transparency which are signalled to be supported for +.B ACCEL_POLYFILLMODE +by +.BR vga_ext_set (3) +are actually meant to apply to the last +.B ACCEL_SCREENCOPYMONO +call. + +Because this polygon drawing uses more screen read/write operations it is probably slower +than using +.B ACCEL_DRAWHLINELIST +or +.BR ACCEL_POLYHLINE +for drawing a polygon scanline by scanline. However, it is easier to use and it will work +mostly without intervention of the CPU which can do other calculations then. See +.B BUGS +below. + +It is unspecified if the left or right end points of the scanlines are drawn, and most +probably some cards (like Mach32) will omit them on one end, at least. Because of that you +should always draw the boundary line in the fill color (or another color) after filling the +polygon. +.TP +.BI "vga_accel(ACCEL_SETMODE, " mode ) +Set blit strategy. There are two choices for +.IR mode , +namely +.BR BLITS_SYNC " and " BLITS_IN_BACKGROUND . +The first ensures that a +.B vga_accel() +call only returns when the accelerator has finished its operation. The second +allows for an immediate return and thus allows parallel operation of the CPU and the +accelerator. Consecutive accelerator operations will wait for +each other to complete (and block if necessary). However, direct screen memory +access (also when done implicitly by some call to an svgalib function) may find any intermediate +state in vga memory or even corrupt the running accelerator operation. +.TP +.BI vga_accel(ACCEL_SYNC) +Wait for accelerator to finish when in +.B vga_accel(BLITS_IN_BACKGROUND) +mode. +.TP +.BI "vga_accel(ACCEL_SETOFFSET, int " address ) +set a screen offset as +.BI vga_setdisplaystart (3) +does. The same restrictions for this function as reported by +.BI vga_getmodeinfo (3) +apply to +.RI address. + +Whenever the video screen offset is modified, the accelerator's offset will follow. However +you can modify it later with this function. + +.PP +The following +.I mode +values are defined for +.BI "vga_accel(ACCEL_SETTRANSPARENCY, int " mode ", " ... ) +.TP +.BI "vga_accel(ACCEL_SETTRANSPARENCY, ENABLE_TRANSPARENCY_COLOR, int " color ) +Whenever one of the +.B vga_accel() +operations would draw a pixel in color +.IR color , +no operation is performed and the destination pixel is left unchanged. In fact +that color is defined to be transparent. +.TP +.BI "vga_accel(ACCEL_SETTRANSPARENCY, DISABLE_TRANSPARENCY_COLOR)" +disables the previous functionality. +.TP +.BI "vga_accel(ACCEL_SETTRANSPARENCY, ENABLE_BITMAP_TRANSPARENCY)" +in the bitmap expanding operations +.BR ACCEL_PUTBITMAP " and " ACCEL_SCREENCOPYBITMAP +whenever a non set bit is encountered, to not perform any draw operation. The 0 bits +do not draw in the background color. Instead they are defined to be transparent. +.TP +.BI "vga_accel(ACCEL_SETTRANSPARENCY, DISABLE_BITMAP_TRANSPARENCY)" +disables the previous functionality. + +.PP +The following +.I mode +values are defined for +.BI "vga_accel(ACCEL_SETRASTEROP, int " mode ) +.TP +.BI "vga_accel(ACCEL_SETRASTEROP, ROP_COPY) +Straight copy. Pixels drawn by +.B vga_accel() +replace the destination. +.TP +.BI "vga_accel(ACCEL_SETRASTEROP, ROP_OR) +Logical or. Pixels drawn by +.B vga_accel() +are logical (bitwise) ored to the destination. +.TP +.BI "vga_accel(ACCEL_SETRASTEROP, ROP_AND) +Logical and. Pixels drawn by +.B vga_accel() +are logical (bitwise) anded to the destination. +.TP +.BI "vga_accel(ACCEL_SETRASTEROP, ROP_XOR) +Logical exclusive or. Pixels drawn by +.B vga_accel() +are logical (bitwise) exclusive ored to the destination (bits set in the drawn pixels +flip those pits in the destination). +.TP +.BI "vga_accel(ACCEL_SETRASTEROP, ROP_INV) +Inversion. Pixels drawn by +.B vga_accel() +are inverted. Which color is drawn is actually ignored. Any pixel which would be +overwritten is simply inverted (bitwise) instead. + +.PP +.B IMPORTANT! +Please note that a 0 returned by +.BI "vga_accel(ACCEL_SETTRANSPARENCY, int " mode ", " ... ) +and +.BI "vga_accel(ACCEL_SETRASTEROP, int " mode ) +simply means that the set function is available (and thus probably +.I some +of above features) but only partial functionality may be available. +The +.BR VGA_AVAIL_ROPMODES " and " VGA_AVAIL_TRANSMODES +subfunctions of +.BR vga_ext_set (3) +allow you to check for valid parameters. The +.BR VGA_AVAIL_ROP " and " VGA_AVAIL_TRANSPARENCY +subfunctions return which of the +.B vga_accel +operations are actually affected by these set functions. + +.PP +Instead of calling +.B vga_accel() +for each operation to find out if it is supported, you can call: + +.B "#include " + +.BI "int vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL)" + +When the logical bitwise and of the return value with one of the following predefined +(one bit set only) integer constants is non zero, the corresponding operation is available: +.BR ACCELFLAG_FILLBOX , +.BR ACCELFLAG_SCREENCOPY , +.BR ACCELFLAG_PUTIMAGE , +.BR ACCELFLAG_DRAWLINE , +.BR ACCELFLAG_SETFGCOLOR , +.BR ACCELFLAG_SETBGCOLOR , +.BR ACCELFLAG_SETTRANSPARENCY , +.BR ACCELFLAG_SETRASTEROP , +.BR ACCELFLAG_PUTBITMAP , +.BR ACCELFLAG_SCREENCOPYBITMAP , +.BR ACCELFLAG_DRAWHLINELIST , +.BR ACCELFLAG_SETMODE " and " +.BR ACCELFLAG_SYNC . + +In addition, calling + +.B "#include " + +.BI "int vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_TRANSPARENCY)" + +or + +.BI "int vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ROP)" + +does +.B not +list the supported values for raster operations and transparency but instead +returns the +.BR ACCELFLAG_ +values for the accelerator operations which respond the raster operation resp. transparency +settings. + +.PP +The availability of the operations will usually depend on the current video mode selected. +You should not try to use them or check for availability prior to selecting the mode you +want to use with +.BR set_mode (3). +.SH BUGS +I found the Mach32 buggy in that it occasionally omits drawing last pixels of lines when +in polygon fill modes (that means, a single point for the last scanline touched by a line). +Obviously this confuses the polygon fill hardware. However, screen corruption will always be +restricted to a small area as +.B ACCEL_SCREENCOPYMONO +will work only on a limited area. It is not clear if this is a driver error, but it seems +to be a hardware bug, and I don't know a clutch to avoid it yet. In case you experience problems +with certain applications, try +.B blit nopolyfillmode +in the configuration file or the SVGALIB_CONFIG +environment variable. + +You must ensure that the given screen coordinates lie in screen memory. Actually you may +not really be sure how offscreen areas are handled, you can only really trust that coordinates +which are visible are supported. For example, the Mach32 restricts the allowable x and +y coordinates to the range -512 .. 1535. However, even on a 1MB VGA memory card, the offscreen +point (0, 1599) would identify a valid screen memory location (if you could use it). + +Where supported, the +.BI "vga_accel(ACCEL_SETOFFSET, " ... ) +directive might help to ease things a bit in such situations. + +Svgalib's accelerator support is a mess. Right now, only the Ark, the Cirrus, the +Chips&Technologies, and the Mach32 svga drivers +really support this function. The Mach32 still also supports the +old style accelerator functions +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt "(3) and " +.BR vga_imageblt (3) +which were first designed for the Cirrus cards and thus the Mach32 has its problems +emulating them. The +.B gl_ +functions use the accelerator to some extend. Currently the use both +the new and the old style accelerator. You should avoid mixing calls of the new and the old +style kinds. + +These functions are not well tested. You should expect weird bugs. In any case, the +accelerator is of not much use in many typical svgalib applications. Best if you are +not using them. + +.B BEWARE! +You should not use the graphics accelerator together with the background feature of +.BR vga_runinbackground (3). +However, you can try using +.BR vga_lockvc (3) +to lock the vc prior to using the accelerator. + +The Mach32 driver does this on it's own, and even keeps the console locked while background +accelerator functions are in progress. Other drivers might not be as graceful. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR accel (6), +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_ext_set (3), +.BR vga_fillblt (3), +.BR vga_getmodeinfo (3), +.BR vga_hlinelistblt (3), +.BR vga_imageblt (3), +.BR vga_runinbackground (3), +.BR vga_runinbackground_version (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_addmode.3 b/doc/man3/vga_addmode.3 new file mode 100644 index 0000000..abb0484 --- /dev/null +++ b/doc/man3/vga_addmode.3 @@ -0,0 +1,30 @@ +.TH vga_addmode 3 "7 April 1999" "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +vga_addmode \- add a mode to svgalib modes list +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_addmode(int width, int height, int num_cols, int offset, int bytesperpixel )" + +.SH DESCRIPTION +Adds a mode to the list of modes, with the given parameters. +The function returns the mode number. If such a mode already exists on the list, +its number is returned, and no mode is added. + +.SH NOTE +Adding a mode to the list is not enough in order to use it. There must +also be a timing line that fits that mode. This can be added either as a modeline in the config file, +or with one of the functions +.BR vga_addtiming (3) +and +.BR vga_guesstiming (3). +.SH SEE ALSO + +.BR vga_addtiming (3) +.BR vga_guesstiming (3) +.BR addmodetest (6) + +.SH AUTHOR + +This manual page was written by Matan Ziv-Av diff --git a/doc/man3/vga_addtiming.3 b/doc/man3/vga_addtiming.3 new file mode 100644 index 0000000..1a08e65 --- /dev/null +++ b/doc/man3/vga_addtiming.3 @@ -0,0 +1,27 @@ +.TH vga_addtiming 3 "7 April 1999" "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +vga_addtiming \- add a timing line to svgalib user timing list +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_addtiming(int pixelClock, int HDisplay, int HSyncStart, int HSyncEnd, int HTotal, \ +int VDisplay, int VSyncStart, intVSyncEnd, int VTotal, int flags); + + +.SH DESCRIPTION +Adds the given line of mode timing to the table of user timing, as if the +line is in the config file. For a description of the parameters' meaning, see +.BR libvga.config (5) +. + +.SH SEE ALSO + +.BR vga_addmode (3) +.BR vga_guesstiming (3) +.BR addmodetest (6) +.BR libvga.config (5) + +.SH AUTHOR + +This manual page was written by Matan Ziv-Av diff --git a/doc/man3/vga_bitblt.3 b/doc/man3/vga_bitblt.3 new file mode 100644 index 0000000..b02724f --- /dev/null +++ b/doc/man3/vga_bitblt.3 @@ -0,0 +1,84 @@ +.TH vga_bitblt 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_bitblt \- copy pixmap on screen using an accelerator +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_bitblt(int " srcaddr ", int " destaddr ", int " w ", int " h ", int " pitch ); + +.SH DESCRIPTION +Bitblit (copy rectangular area in video memory), addresses +are offsets into video memory (up to 2M). The +.I pitch +is the logical width of the screen. Height +.I h +is in Pixels, Width +.I w +is in +.BR BYTES ! + +This is an old style function to access the accelerator of an SVGA card. Before calling +it you should check for availability of the function in the mode you use with +.BR vga_getmodeinfo (3). + +For new applications you might be better of trying to use +.BR vga_accel (3) +instead. + +The old +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt "(3), and " +.BR vga_imageblt (3) +interface was originally designed for the Cirrus chipsets. Then Mach32 added support too +but has problems to resemble the unintuitive Cirrus interface. Then these new ideas +were reinjected and +.BR vga_accel (3) +was designed. Now Cirrus and Chips & Technologies chipset give limited +.BR vga_accel (3) +support but no longer this old style support. +Mach32 is left to use the unintuitive Cirrus interface. At some future point the +functions might be added for Mach32 too (which should be rather simple), so new +applications should use the newer and probably more efficient interface. + +It would be fatal if the accelerator would be used while the console is switched away. +You should use +.BR vga_lockvc (3) +and +.BR vga_unlockvc (3) +to avoid this, although good implementations of the accelerator functions (like Mach32) +will already ensure that. + +The +.BR testaccel (6) +demo utilizes the old style accelerator functions. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR testaccel (6), +.BR vga_accel (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt (3), +.BR vga_imageblt (3), +.BR vga_getmodeinfo (3), +.BR vga_lockvc (3), +.BR vga_unlockvc (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_blitwait.3 b/doc/man3/vga_blitwait.3 new file mode 100644 index 0000000..ede80ce --- /dev/null +++ b/doc/man3/vga_blitwait.3 @@ -0,0 +1,81 @@ +.TH vga_blitwait 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_blitwait \- wait for any accelerator operation to finish +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_blitwait(void);" + +.SH DESCRIPTION +waits for any accelerator operation to finish. Though already +implemented not useful because these old style functions do not allow for parallel +operation of the accelerator. A limited use might be to wait for a running +operation to complete in a +.BR signal (2) +handler. + +This is an old style function to access the accelerator of an SVGA card. Before calling +it you should check for availability of the function in the mode you use with +.BR vga_getmodeinfo (3). + +For new applications you might be better of trying to use +.BR vga_accel (3) +instead. + +The old +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt "(3), and " +.BR vga_imageblt (3) +interface was originally designed for the Cirrus chipsets. Then Mach32 added support too +but has problems to resemble the unintuitive Cirrus interface. Then these new ideas +were reinjected and +.BR vga_accel (3) +was designed. Now Cirrus and Chips & Technologies chipset give limited +.BR vga_accel (3) +support but no longer this old style support. +Mach32 is left to use the unintuitive Cirrus interface. At some future point the +functions might be added for Mach32 too (which should be rather simple), so new +applications should use the newer and probably more efficient interface. + +It would be fatal if the accelerator would be used while the console is switched away. +You should use +.BR vga_lockvc (3) +and +.BR vga_unlockvc (3) +to avoid this, although good implementations of the accelerator functions (like Mach32) +will already ensure that. + +The +.BR testaccel (6) +demo utilizes the old style accelerator functions. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR testaccel (6), +.BR vga_accel (3), +.BR vga_bitblt (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt (3), +.BR vga_imageblt (3), +.BR vga_getmodeinfo (3), +.BR vga_lockvc (3), +.BR vga_unlockvc (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_changetiming.3 b/doc/man3/vga_changetiming.3 new file mode 100644 index 0000000..ecdc68e --- /dev/null +++ b/doc/man3/vga_changetiming.3 @@ -0,0 +1,25 @@ +.TH vga_addtiming 3 "7 April 1999" "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +vga_changetiming \- change the current timing parameters. +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_addtiming(int pixelClock, int HDisplay, int HSyncStart, int HSyncEnd, int HTotal, \ +int VDisplay, int VSyncStart, int VSyncEnd, int VTotal, int flags); + + +.SH DESCRIPTION +Changes the value of the current timing parameters by the given values. No checks are made to see if the new timing are within monitor or card specs. +See +.BR svidtune (6) +for an example of using this. + +.SH SEE ALSO + +.BR vga_getcurrenttiming (3) +.BR svidtune (6) + +.SH AUTHOR + +This manual page was written by Matan Ziv-Av diff --git a/doc/man3/vga_claimvideomemory.3 b/doc/man3/vga_claimvideomemory.3 new file mode 100644 index 0000000..cc90aac --- /dev/null +++ b/doc/man3/vga_claimvideomemory.3 @@ -0,0 +1,37 @@ +.TH vga_claimvideomemory 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_claimvideomemory \- declare the amount of video memory used +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_claimvideomemory(int " m ); + +.SH DESCRIPTION +Declare the amount of video memory in bytes that is to +be saved when temporarily switching to textmode. Returns +nonzero if the amount is not available. Defaults to one +screen when a mode is set. Use this if you are using more +than one screen of video memory. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_getmodeinfo (3), +.BR vga_init (3), +.BR vga_setmode (3), + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_clear.3 b/doc/man3/vga_clear.3 new file mode 100644 index 0000000..ca490bb --- /dev/null +++ b/doc/man3/vga_clear.3 @@ -0,0 +1,42 @@ +.TH vga_clear 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_clear \- clear the screen +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_clear(void);" + +.SH DESCRIPTION +Clears the screen and sets all visible pixels to 0 (which is usually black). This is +automatically done by a +.BR vga_setmode (3) +call. + +The function always returns 0 (on which you should probably not really rely). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_setmode (3), +.BR vga_setcolor (3), +.BR vga_setrgbcolor (3), +.BR vga_getpixel (3), +.BR vga_drawpixel (3), +.BR vga_drawline (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getscansegment (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_copytoplanar16.3 b/doc/man3/vga_copytoplanar16.3 new file mode 100644 index 0000000..c25b5f8 --- /dev/null +++ b/doc/man3/vga_copytoplanar16.3 @@ -0,0 +1,58 @@ +.TH vga_copytoplanar16 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_copytoplanar16 \- copy linear pixmap into VGA 16 color mode video memory +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_copytoplanar16(unsigned char *" virtual ", int " pitch ", int " voffset ", int " +.IB vpitch ", int " w ", int " h ); + +.SH DESCRIPTION +Similar to +.BR vga_copytoplanar256 (3), +but for 16 color modes (not well tested). Assumes +pixels stored in consecutive bytes ranging from 0 to 15 in +the virtual screen. + +Copies part of a linear virtual screen in system memory at +.I *virtual +to VGA 16 mode video memory. +.I pitch +is the logical width of the virtual +screen (in pixels (which are one byte large)), +.I voffset +is the address offset into video memory, +.I vpitch +is the logical scanline width of the screen. +.BI ( w ", " h ) +is the size of the area to copy in pixels +.RI ( width +must be multiple of 4). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_accel (3), +.BR vga_copytoplanar256 (3), +.BR vga_copytoplane (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getmodeinfo (3), +.BR vga_setlogicalwidth (3), +.BR vga_imageblt (3), +.BR vga_setmodeX (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_copytoplanar256.3 b/doc/man3/vga_copytoplanar256.3 new file mode 100644 index 0000000..ceff538 --- /dev/null +++ b/doc/man3/vga_copytoplanar256.3 @@ -0,0 +1,52 @@ +.TH vga_copytoplanar256 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_copytoplanar256 \- copy linear pixmap into Mode X video memory +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_copytoplanar256(unsigned char *" virtual ", int " pitch ", int " voffset ", int " +.IB vpitch ", int " w ", int " h ); + +.SH DESCRIPTION +Copy part of a linear virtual screen in system memory at +.I *virtual +to Mode X style video memory. +.I pitch +is the logical width of the virtual +screen (in pixels (which are one byte large)), +.I voffset +is the address offset into video memory, +.I vpitch +is the logical scanline width of the screen. +.BI ( w ", " h ) +is the width and height of the area to copy in pixels +.RI ( w +must be a multiple of 4). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_accel (3), +.BR vga_copytoplanar16 (3), +.BR vga_copytoplane (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getmodeinfo (3), +.BR vga_setlogicalwidth (3), +.BR vga_imageblt (3), +.BR vga_setmodeX (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_copytoplane.3 b/doc/man3/vga_copytoplane.3 new file mode 100644 index 0000000..941e96f --- /dev/null +++ b/doc/man3/vga_copytoplane.3 @@ -0,0 +1,65 @@ +.TH vga_copytoplane 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_copytoplane \- copy linear pixmap to some planes of VGA 16 color mode video memory +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_copytoplane(unsigned char *" virtual ", int " pitch ", int " voffset ", int " +.IB vpitch ", int " w ", int " h ", int " plane ); + +.SH DESCRIPTION +Similar to +.BR vga_copytoplanar16 (3), +but copies only a subset of the +four 16-color mode planes +.RI ( plane +should be in the range 0 .. 15). The bits set in +.I plane +select which of the four 16-color mode planes to modify. + +Assumes +pixels stored in consecutive bytes ranging from 0 to 15 in +the virtual screen. + +Copies part of a linear virtual screen in system memory at +.I *virtual +to VGA 16 mode video memory. +.I pitch +is the logical width of the virtual +screen (in pixels (which are one byte large)), +.I voffset +is the address offset into video memory, +.I vpitch +is the logical scanline width of the screen. +.BI ( w ", " h ) +is the size of the area to copy in pixels +.RI ( width +must be multiple of 4). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_accel (3), +.BR vga_copytoplanar16 (3), +.BR vga_copytoplanar256 (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getmodeinfo (3), +.BR vga_setlogicalwidth (3), +.BR vga_imageblt (3), +.BR vga_setmodeX (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_disabledriverreport.3 b/doc/man3/vga_disabledriverreport.3 new file mode 100644 index 0000000..02b814a --- /dev/null +++ b/doc/man3/vga_disabledriverreport.3 @@ -0,0 +1,36 @@ +.TH vga_disabledriverreport 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_disabledriverreport \- makes svgalib not emit any startup messages +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_disabledriverreport(void);" + +.SH DESCRIPTION +Usually svgalib prints the name of the hardware detected or forced to the screen during +startup. This and other informational messages are suppressed when +.B vga_disabledriverreport() +was called. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_init (3), +.BR vga_setmode (3), +.BR vga_setchipset (3), +.BR vga_setchipsetandfeatures (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_drawline.3 b/doc/man3/vga_drawline.3 new file mode 100644 index 0000000..156e5d1 --- /dev/null +++ b/doc/man3/vga_drawline.3 @@ -0,0 +1,62 @@ +.TH vga_drawline 3 "21 August 1999" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_drawline \- draw a line on the screen +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_drawline(int " x1 ", int " y1 ", int " x2 ", int " y2 ); + +.SH DESCRIPTION +draws a line from +.BI ( x1 ", " y1 ) +to +.BI ( x2 ", " y2 ) +on the screen. If you exchange start and end of the line you should not expect the +exactly identical set of pixel be covered by the line. + +This function is very inefficient +as is does a bunch +of +.BR vga_drawpixel (3) +calls, you should +consider using +.BR gl_line (3) +which is very efficient, +or doing direct screen access instead or use +.BR vga_drawscansegment (3) +to handle more than one pixel. + +The color drawn is set with +.BR vga_setcolor (3) +or +.BR vga_setrgbcolor (3) +resp. + +The function always returns 0 (on which you should probably not really rely). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR gl_line (3) +.BR vga_clear (3), +.BR vga_setcolor (3), +.BR vga_setrgbcolor (3), +.BR vga_getpixel (3), +.BR vga_drawline (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getscansegment (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. This Page was modified by Don Secrest + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_drawpixel.3 b/doc/man3/vga_drawpixel.3 new file mode 100644 index 0000000..45cac32 --- /dev/null +++ b/doc/man3/vga_drawpixel.3 @@ -0,0 +1,47 @@ +.TH vga_drawpixel 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_drawpixel \- draw a pixel on the screen +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_drawpixel(int " x ", int " y ); + +.SH DESCRIPTION +Read a pixels value from the screen. This function is very inefficient, you should +consider doing direct screen access instead or use +.BR vga_drawscansegment (3) +to handle more than one pixel. + +The color drawn is set with +.BR vga_setcolor (3) +or +.BR vga_setrgbcolor (3) +resp. + +The function always returns 0 (on which you should probably not really rely). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_clear (3), +.BR vga_setcolor (3), +.BR vga_setrgbcolor (3), +.BR vga_getpixel (3), +.BR vga_drawline (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getscansegment (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_drawscanline.3 b/doc/man3/vga_drawscanline.3 new file mode 100644 index 0000000..2dc5408 --- /dev/null +++ b/doc/man3/vga_drawscanline.3 @@ -0,0 +1,42 @@ +.TH vga_drawscanline 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_drawscanline \- draw a horizontal line of pixels +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_drawscanline(int " line " , unsigned char *" color ); + +.SH DESCRIPTION +draws a horizontal line over the whole screen in the line with y coordinate +.IR line . + +The colors drawn are taken from +.IB color "[0] .. " color [ length " - 1]." + +This is a simpler frontend to +.BR vga_drawscansegment (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_clear (3), +.BR vga_drawpixel (3), +.BR vga_drawline (3), +.BR vga_getpixel (3), +.BR vga_getscansegment (3) +.BR vga_drawscansegment (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_drawscansegment.3 b/doc/man3/vga_drawscansegment.3 new file mode 100644 index 0000000..379f9ef --- /dev/null +++ b/doc/man3/vga_drawscansegment.3 @@ -0,0 +1,43 @@ +.TH vga_drawscansegment 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_drawscansegment \- draw a horizontal line of pixels +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_drawscansegment(unsigned char *" colors ", int " x ", int " y ", int " length ); + +.SH DESCRIPTION +draws a horizontal line of +.I length pixels +starting at position +.BI ( x ", " y ). +The colors drawn are taken from +.IB color "[0] .. " color [ length " - 1]." +Svgalib versions prior to 1.2.10 required +.IR x ", " y ", and " length +to be multiples of 8. This is no longer true. +In high/truecolor modes, the length must be given in bytes, not pixels. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_clear (3), +.BR vga_drawpixel (3), +.BR vga_drawline (3), +.BR vga_getpixel (3), +.BR vga_drawscanline (3), +.BR vga_getscansegment (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_dumpregs.3 b/doc/man3/vga_dumpregs.3 new file mode 100644 index 0000000..0014d89 --- /dev/null +++ b/doc/man3/vga_dumpregs.3 @@ -0,0 +1,32 @@ +.TH vga_dumpregs 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_dumpregs \- dump the contents of the SVGA registers +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_dumpregs(void);" + +.SH DESCRIPTION +This function dumps the current values of all SVGA registers in a way which can by +copied in a source file. This is for debugging purposes only. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_init (3), +.BR vga_dumpregs (3), +.BR dumpreg (1) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_ext_set.3 b/doc/man3/vga_ext_set.3 new file mode 100644 index 0000000..fb15cc4 --- /dev/null +++ b/doc/man3/vga_ext_set.3 @@ -0,0 +1,259 @@ +.TH vga_ext_set 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_ext_set \- set and query several extended features +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_ext_set(unsigned " what ", " ... ); + +.SH DESCRIPTION +sets and several extended features. Before trying to call +.B vga_ext_set() +you should check if it is available in +.BR vga_getmodeinfo (3) +for compatibility with old svgalib versions. In addition, the availability of certain +features will depend on the current graphics mode. + +However, the +.BR VGA_EXT_PAGE_OFFSET " and " VGA_EXT_FONT_SIZE +features are features of the base module of svgalib and are always available if your +version of svgalib supports them. Actually the result of +.BR vga_getmodeinfo (3) +shows the availability of enhancements of +.BR vga_ext_set() +in the given SVGA graphics mode. Hence, these base features may be supported even if +svgalib does not admit it. Since version 1.2.13 you can check +.B vga_getmodeinfo(TEXT) +to see if basic +.BR vga_ext_set() +functionality is available. The +.BR VGA_EXT_PAGE_OFFSET " and " VGA_EXT_FONT_SIZE +calls are then available in any mode +.B even if +.BR vga_getmodeinfo (3) +states that you should not call +.B vga_ext_set() +at all. + +As of now, the following calls are defined: +.SS Query availability of features +.TP +.BI "vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_SET)" +returns an int with the +.IR i -th +bit set if +.I i +is a valid +.I what +parameter for +.BR vga_ext_set() . +.TP +.BI "vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL)" +returns an integer with the +.IR i -th +bit set if +.I i +is a valid +.I what +parameter for +.BR vga_accel (3). +For nicer code, the following integers are predefined to have a bit +set in the right position: + +.BR ACCELFLAG_FILLBOX , +.BR ACCELFLAG_SCREENCOPY , +.BR ACCELFLAG_PUTIMAGE , +.BR ACCELFLAG_DRAWLINE , +.BR ACCELFLAG_SETFGCOLOR , +.BR ACCELFLAG_SETBGCOLOR , +.BR ACCELFLAG_SETTRANSPARENCY , +.BR ACCELFLAG_SETRASTEROP , +.BR ACCELFLAG_PUTBITMAP , +.BR ACCELFLAG_SCREENCOPYBITMAP , +.BR ACCELFLAG_DRAWHLINELIST , +.BR ACCELFLAG_SETMODE ", and " +.BR ACCELFLAG_SYNC . +.TP +.BI "vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ROP)" +returns an integer as +.B VGA_AVAIL_ACCEL +does, but this time listing the +.BR vga_accel (3) +operations which obey a +.B vga_accel(ACCEL_SETRASTEROP, ...) +setting. +.TP +.BI "vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_TRANSPARENCY)" +returns an integer as +.B VGA_AVAIL_ACCEL +does, but this time listing the +.BR vga_accel (3) +operations which obey a +.B vga_accel(ACCEL_SETTRANSPARENCY, ...) +setting. +.TP +.BI "vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ROPMODES)" +returns an integer with the +.IR i -th +bit set if +.I i +is a valid +.I mode +parameter for a +.BI "vga_accel(ACCEL_SETRASTEROP, " mode ) +call. For example: + +.RS +.B if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ROPMODES) & (1 << ROP_XOR)) +.br +.B " " vga_accel(ACCEL_SETRASTEROP, ROP_XOR); +.br +.B else +.br +.B " " /* do something else */ +.RE + +.TP +.BI "vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_TRANSMODES)" +returns an integer with the +.IR i -th +bit set if +.I i +is a valid +.I mode +parameter for a +.BI "vga_accel(ACCEL_SETTRANSPARENCY, " mode ", ...)" +call. The function lists only the supported enable functions (currently +.BR ENABLE_TRANSPARENCY_COLOR " and " ENABLE_BITMAP_TRANSPARENCY ). +It is assumed the corresponding disable functions will then exist as well. +.TP +.BI "vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_FLAGS)" +returns an int with one bit on/off flags. Bits that are set are supported +refer to special features which can be enabled in the current mode. + +.SS Operations with one bit flags +A certain mode might have a special feature which can be turned on or off by the +applications. These functions allow to handle such features. + +You can always set flags, and their settings are remembered if not +supported in the current mode. This is to avoid problems when +switching VC's. + +.TP +.BI "vga_ext_set(VGA_EXT_SET, int " bitflags ) +set all flags that are set in +.IR bitflags , +do not touch any other flags. Returns previous setting of all flags. +.TP +.BI "vga_ext_set(VGA_EXT_CLEAR, int " bitflags ) +clear all flags that are set in +.IR bitflags , +do not touch any other flags. Returns previous setting of all flags. +.TP +.BI "vga_ext_set(VGA_EXT_RESET, int " bitflags ) +set all flags to the corresponding bits of +.IR bitflags . +Returns previous setting of all flags. + +.SS One bit flags for special features +As of now, we only support +.TP +.B VGA_CLUT8 +which is set by calling +.BR "vga_ext_set(VGA_EXT_SET, VGA_CLUT8)" . +This makes the color lookup table for 16 and 256 color lookup table modes work +with 8 bit per red, green, blue part instead of the ordinary 6 bits. + +As of now this feature is only availabl for Mach32 cards with type 2 DAC's. +8 bit per red, green, blue wide in all (even VGA) 256 color modes. This mean, +however, that all calls to +.BR vga_setpalette "(3) and " vga_setpalvec (3) +need to be adjuste accordingly as well as that the interpretation of the +return values of +.BR vga_getpalette "(3) and " vga_getpalvec (3) +changes. + +The +.BR testaccel (6) +demos makes use of this to show a smooth 256 blue shades scale. + +.SS Miscanellous features +.TP +.BI "vga_ext_set(VGA_EXT_PAGE_OFFSET, int " offset ) +for all following +.BI vga_set*page( n ) +calls (even those implicitly done +by svgalib drawing functions) do +.BI vga_set*page( n " + " offset ) +instead. +This is +.B very +nice for drawing in an offscreen area. However, it +requires the mode being able to use more than one page at all as well as +.B not +having called +.BR vga_setlinearaddressing (3). + +A better approach would be to just use higher +.I y +values for all +draw operations to have them end up in offscreen regions that +may be displayed later (cf. +.BR vga_setdisplaystart (3)). + +The previously set value for +.B VGA_EXT_PAGE_OFFSET +(which defaults to 0 at startup) is returned. + +.TP +.BI "vga_ext_set(VGA_EXT_FONT_SIZE, int " size ) +sets the size of the buffer which the application passes to +.BR vga_gettextfont "(3) and " +.BR vga_puttextfont (3). +Old versions of svgalib used a fixed size of 8192 which is still the default. +Newer versions of svgalib use a larger size internally to properly support the +extended font capabilities of newer kernels. + +Calling +.B vga_ext_set(VGA_EXT_FONT_SIZE, 0) +returns the size of the internal buffers of svgalib. It is recommended to use this +(or a larger size) for any font (re)storing application. If this differs from the +size of the applications buffers set +.BR vga_gettextfont "(3) and " +.BR vga_puttextfont (3) +truncate and zero-pad all buffers accordingly. + +Otherwise the previously set buffer size is returned. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR accel (6), +.BR testaccel (6), +.BR vga_setpalette (3), +.BR vga_setpalvec (3), +.BR vga_getpalette (3), +.BR vga_getpalvec (3), +.BR vga_setlinearaddressing (3), +.BR vga_setdisplaystart (3), +.BR vga_setpage (3), +.BR vga_setreadpage (3), +.BR vga_setwritepage (3), +.BR vga_gettextfont (3), +.BR vga_puttextfont (3). + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_fillblt.3 b/doc/man3/vga_fillblt.3 new file mode 100644 index 0000000..a2c59a7 --- /dev/null +++ b/doc/man3/vga_fillblt.3 @@ -0,0 +1,86 @@ +.TH vga_fillblt 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_fillblt \- file rectangular area in video memory with a single color +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_fillblt(int " destaddr ", int " w ", int " h ", int " pitch ", int " color ); + +.SH DESCRIPTION +Fill a rectangular area in video memory with a single color +.IR color . +.I destaddr +is an offset into video memory (up to 2M). The +.I pitch +is the logical width of the screen. Height +.I h +is in Pixels, Width +.I w +is in +.BR BYTES ! + +This is an old style function to access the accelerator of an SVGA card. Before calling +it you should check for availability of the function in the mode you use with +.BR vga_getmodeinfo (3). + +For new applications you might be better of trying to use +.BR vga_accel (3) +instead. + +The old +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt "(3), and " +.BR vga_imageblt (3) +interface was originally designed for the Cirrus chipsets. Then Mach32 added support too +but has problems to resemble the unintuitive Cirrus interface. Then these new ideas +were reinjected and +.BR vga_accel (3) +was designed. Now Cirrus and Chips & Technologies chipset give limited +.BR vga_accel (3) +support but no longer this old style support. +Mach32 is left to use the unintuitive Cirrus interface. At some future point the +functions might be added for Mach32 too (which should be rather simple), so new +applications should use the newer and probably more efficient interface. + +It would be fatal if the accelerator would be used while the console is switched away. +You should use +.BR vga_lockvc (3) +and +.BR vga_unlockvc (3) +to avoid this, although good implementations of the accelerator functions (like Mach32) +will already ensure that. + +The +.BR testaccel (6) +demo utilizes the old style accelerator functions. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR testaccel (6), +.BR vga_accel (3), +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_hlinelistblt (3), +.BR vga_imageblt (3), +.BR vga_getmodeinfo (3), +.BR vga_lockvc (3), +.BR vga_unlockvc (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_flip.3 b/doc/man3/vga_flip.3 new file mode 100644 index 0000000..9185f64 --- /dev/null +++ b/doc/man3/vga_flip.3 @@ -0,0 +1,73 @@ +.TH vga_flip 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_flip \- toggle between text and graphics mode +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_flip(void);" + +.SH DESCRIPTION +switches between graphics and text mode without +destroying the screen contents. This makes it possible for +your application to use both text and graphics output. + +.BR However , +This is an old vgalib function. You should really only use it for debugging as it runs +extremely unstable because svgalib now does its own virtual console management. If you +want to perform a similar action, +save the current screen contents with ordinary memory copy operation to the frame buffer +or +.BR gl_getbox (3), +set +.BR vga_setmode(TEXT) , +then call +.BR vga_setmode (3) +to return to graphics operation and restore the screen contents with memory or +.BR gl_putbox (3). + +One could also use +.BR vga_drawscansegment (3) +and +.BR vga_getscansegment (3) +calls. + +.B However, avoid any calls to vga_flip() in your applications. + +The function always returns 0, a fact on which you shouldn't rely. + +It might be useful if you are debugging one of your svgalib applications though. +If your program reaches a breakpoint while +in graphics mode, you can switch to text mode with the gdb command + +.B "print vga_flip()" + +and later restore the graphics screen contents with the same command. +It is useful to define the following alias in gdb: + +.B "define flip print vga_flip() end " + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_init (3), +.BR vga_setflipchar (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getscansegment (3), +.BR gl_getbox (3), +.BR gl_putbox (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getcardinfo.3 b/doc/man3/vga_getcardinfo.3 new file mode 100644 index 0000000..409a3c0 --- /dev/null +++ b/doc/man3/vga_getcardinfo.3 @@ -0,0 +1,72 @@ +.TH vga_getcardinfo 3 "23 June 2001" "Svgalib (>= 1.9.10)" "Svgalib User Manual" +.SH NAME +vga_getcardinfo \- returns pointer to information about the video card. +.SH SYNOPSIS + +.B "#include " + +.BI "vga_cardinfo *vga_getcardinfo(void); + +.SH DESCRIPTION +The function returns a pointer to a card information structure which is +filled out with details about the video card in use. + +.B "#include " +defines +.B vga_cardinfo +as + +.B typedef struct { +.br +.B " " int version; +.br +.B " " int size; +.br +.B " " int chipset; +.br +.B " " int physmem; +.br +.B " " int physmemsize; +.br +.B " " int linearmem; +.br +.B } vga_cardinfo; + +The fields meaning in detail: + +.SS Basic mode details +.TP +.B version +Version of the information structure. Application can use this field to make +sure the data it needs is really there. +.TP +.B size +Size of the cardinfo structure. The structure is malloc()ed, and the program should free +it when no longer needed. +.TP +.B chipset +Number of the chispet driver used to drive the card. Same list as is used in the +.B vga_setchipset +function. +.TP +.B physmem +Physical address of the linear memory aperture of the card. This is needed for example for setting +the video overlay of v4l devices. +.TP +.B physmemsize +Amount of physical memory in bytes. (Version >= 0x0200) +.TP +.B linearmem +Virtual address of the linear memory aperture. Please note that currently it is +mapped at vga_init, but in future versions of svgalib this might change. +(Version >= 0x0200) + +.SH SEE ALSO + +.BR svgalib (7), +.BR libvga.config (5), + +.SH AUTHOR + +This manual page written by Matan Ziv-Av . + diff --git a/doc/man3/vga_getch.3 b/doc/man3/vga_getch.3 new file mode 100644 index 0000000..f208ea1 --- /dev/null +++ b/doc/man3/vga_getch.3 @@ -0,0 +1,41 @@ +.TH vga_getch 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getch \- wait for a key +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getch(void);" + +.SH DESCRIPTION +waits for a key press just like +.BR getchar (3) +would. + +For a non blocking check for a keypress use +.BR vga_getkey (3) +or use +.BR vga_waitevent (3) +if you want to wait for several events to occur at once. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_getkey (3), +.BR vga_setflipchar (3), +.BR vga_waitevent (3), +.BR getchar (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getcolors.3 b/doc/man3/vga_getcolors.3 new file mode 100644 index 0000000..b5d9b6a --- /dev/null +++ b/doc/man3/vga_getcolors.3 @@ -0,0 +1 @@ +.so man3/vga_getxdim.3 diff --git a/doc/man3/vga_getcurrentchipset.3 b/doc/man3/vga_getcurrentchipset.3 new file mode 100644 index 0000000..c29dbc8 --- /dev/null +++ b/doc/man3/vga_getcurrentchipset.3 @@ -0,0 +1,34 @@ +.TH vga_getcurrentchipset 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getcurrentchipset \- returns the current SVGA chipset +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getcurrentchipset(void);" + +.SH DESCRIPTION +Returns the current SVGA chipset which was autodetected or forced. See +.BR vga_setchipset (3) +for the predefined values which may be returned. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_setchipset (3), +.BR vga_setchipsetandfeatures (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getcurrentmode.3 b/doc/man3/vga_getcurrentmode.3 new file mode 100644 index 0000000..33c4ae9 --- /dev/null +++ b/doc/man3/vga_getcurrentmode.3 @@ -0,0 +1,39 @@ +.TH vga_getcurrentmode 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getcurrentmode \- returns the current video mode +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getcurrentmode(void);" + +.SH DESCRIPTION +Returns the current video mode. +See +.BR vga_setmode (3) +for a list of predefined return values and there meaning. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_hasmode (3), +.BR vga_modeinfo (3), +.BR vga_setmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getmodename (3), +.BR vga_getmodenumber (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getcurrenttiming.3 b/doc/man3/vga_getcurrenttiming.3 new file mode 100644 index 0000000..309a2eb --- /dev/null +++ b/doc/man3/vga_getcurrenttiming.3 @@ -0,0 +1,24 @@ +.TH vga_addtiming 3 "7 April 1999" "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +vga_getcurrenttiming \- get the current timing parameters. +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_addtiming(int *pixelClock, int *HSyncStart, int *HSyncEnd, int *HTotal, int *VDisplay, int *VSyncStart, int *VSyncEnd, int *VTotal, int *flags); + + +.SH DESCRIPTION +Saves to the current timing parameters to the variables given in the function call. +See +.BR svidtune (6) +for an example of using this. + +.SH SEE ALSO + +.BR vga_changetiming (3) +.BR svidtune (6) + +.SH AUTHOR + +This manual page was written by Matan Ziv-Av diff --git a/doc/man3/vga_getdefaultmode.3 b/doc/man3/vga_getdefaultmode.3 new file mode 100644 index 0000000..dbf0f89 --- /dev/null +++ b/doc/man3/vga_getdefaultmode.3 @@ -0,0 +1,52 @@ +.TH vga_getdefaultmode 3 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +vga_getdefaultmode \- returns the default graphics mode number +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getdefaultmode(void);" + +.SH DESCRIPTION +Returns the default graphics mode number from the +.B SVGALIB_DEFAULT_MODE +environment variable. If undefined, the from the +.B default_mode +configuration file +option. If that is not available as well, returns 10 (G640x480x256). The +mode value in the environment variable or configuration file can either be a mode number or a mode name. See +.BR vga_setmode (3) +for a list of predefined return values and their meaning. The mode names which can be used +in the environment are those used by +.BR vga_getmodename (3) +and +.BR vga_getmodenumber (3). + +Whenever your application has no special need for a given mode you should always try to +honour this setting for consistency among svgalib applications. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_hasmode (3), +.BR vga_modeinfo (3), +.BR vga_setmode (3), +.BR vga_getcurrentmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getmodename (3), +.BR vga_getmodenumber (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getgraphmem.3 b/doc/man3/vga_getgraphmem.3 new file mode 100644 index 0000000..0632af5 --- /dev/null +++ b/doc/man3/vga_getgraphmem.3 @@ -0,0 +1,55 @@ +.TH vga_getgraphmem 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getgraphmem \- returns the address of the VGA memory +.SH SYNOPSIS + +.B "#include " + +.BR "unsigned char *graph_mem;" +/* This declaration is already in vga.h */ + +.BI "unsigned char *vga_getgraphmem(void);" + +.SH DESCRIPTION +returns a pointer to the 64K VGA frame buffer window. +.BR vga_setpage (3), +.BR vga_setreadpage "(3) and " +.BR vga_setwritepage (3) +allow to select which page of the VGA memory shows up at this position. +.BR vga_setlinearaddressing (3) +maps all VGA memory at a consecutive memory area (if the hardware supports it). +In this mode, +.BI "vga_getgraphmem()" +will return the location of this area too. You can also access the global variable +.BR graph_mem , +which will also contain this address. + +Most demos, esp. +.BR vgatest (6) +show the simple direct use of this function to access screen memory. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgatest (6), +.BR fun (6), +.BR testlinear (6), +.BR vga_setlinearaddressing (3), +.BR vga_claimvideomemory (3), +.BR vga_getmodeinfo (3), +.BR vga_setpage (3), +.BR vga_setreadpage (3), +.BR vga_setwritepage (3), + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getkey.3 b/doc/man3/vga_getkey.3 new file mode 100644 index 0000000..86f8f84 --- /dev/null +++ b/doc/man3/vga_getkey.3 @@ -0,0 +1,47 @@ +.TH vga_getkey 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getkey \- read a character from the keyboard without waiting +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getkey(void);" + +.SH DESCRIPTION +Read a character from the keyboard without waiting; returns +zero if no key pressed and the ASCII value otherwise. This function must not be used +in raw keyboard mode. In this situation use +.BR keyboard_getstate (3) +or +.BR keyboard_keypressed (3) +instead. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR keytest (6), +.BR keyboard_init (3), +.BR keyboard_close (3), +.BR keyboard_setdefaulteventhandler (3), +.BR keyboard_seteventhandler (3), +.BR keyboard_getstate (3), +.BR keyboard_clearstate (3), +.BR keyboard_translatekeys (3), +.BR keyboard_keypressed (3), +.BR vga_getch (3), +.BR vga_waitevent (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getmodeinfo.3 b/doc/man3/vga_getmodeinfo.3 new file mode 100644 index 0000000..e0e6d1f --- /dev/null +++ b/doc/man3/vga_getmodeinfo.3 @@ -0,0 +1,281 @@ +.TH vga_getmodeinfo 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getmodeinfo \- returns pointer to mode information structure for a mode +.SH SYNOPSIS + +.B "#include " + +.BI "vga_modeinfo *vga_getmodeinfo(int " mode " ); + +.SH DESCRIPTION +The function returns a pointer to a statical allocated mode information structure which is +filled out with details for a video mode +.IR mode . + +.B "#include " +defines +.B vga_modeinfo +as + +.B typedef struct { +.br +.B " " int width; +.br +.B " " int height; +.br +.B " " int bytesperpixel; +.br +.B " " int colors; +.br +.B " " int linewidth; +.br +.B " " int maxlogicalwidth; +.br +.B " " int startaddressrange; +.br +.B " " int maxpixels; +.br +.B " " int haveblit; +.br +.B " " int flags; +.br +/* Extended fields, not always available: */ +.br +.B " " int chiptype; +.br +.B " " int memory; +.br +.B " " int linewidth_unit; +.br +.B " " char *linear_aperture; +.br +.B " " int aperture_size; +.br +.B " " void (*set_aperture_page) (int page); +.br +.B " " void *extensions; +.br +.B } vga_modeinfo; + +If the given +.I mode +is out of range, +.B NULL +is returned. +.BR Beware , +even when +.B vga_getmodeinfo() +returns details about a certain mode, you must check if it is currently +available (may depend on memory size and other details) with +.B vga_hasmode (3). + +The fields meaning in detail: + +.SS Basic mode details +.TP +.B width +Width of mode in pixels. +.TP +.B height +Height of mode in pixel lines. +.TP +.B bytesperpixel +Bytes per pixel. This is 1, 2, 3, or 4 (for 256, 32K & 64K, 16M, 16M$ modes) and 0 for planar +VGA modes. +.TP +.B linewidth +Logical scanline width in bytes. This is the memory offset between two pixels above each other +in two adjacent screen lines. It is +.B not +valid to assume that +.BR linewidth " == " width " * " bytesperpixel +in general! +.TP +.B colors +The number of colors which you can display simultaneously 2, 16, 256, 32768, 65536, or 16777216. +Generally 16 and 256 mean that a color lookup table is used. 2 means that only black/white is +used and the others use some high/true color mode. +.SS Possible modifications of the memory layout +.TP +.B maxlogicalwidth +The maximum logical scanline width (in bytes) which you can set for this mode with +.BR vga_setlogicalwidth (3) +while still expecting a perfect screen image. +.TP +.B startaddressrange +Mask of changeable bits of start address (in pixels). All bits zero in +.B startaddressrange +must also be zero in a call to +.BR vga_setdisplaystart (3) +when you want to avoid noisy video signals. +.SS Memory size +.TP +.B maxpixels +Maximum number of pixels that will fit in a logical screen (depends on video memory). +.SS Further, advanced capabilities +.TP +.B haveblit +Indicates whether the following bitblit functions are available. It is a logical or +of the following predefined values (which each have only one bit set). +.RS +.TP +.B HAVE_BITBLIT +has +.BR vga_bitblt (3) +old style accelerator function. +.TP +.B HAVE_FILLBLIT +has +.BR vga_fillblt (3) +old style accelerator function. +.TP +.B HAVE_IMAGEBLIT +has +.BR vga_imageblt (3) +old style accelerator function. +.TP +.B HAVE_HLINELISTBLIT +has +.BR vga_hlinelistblt (3) +old style accelerator function. +.TP +.B HAVE_BLITWAIT +has +.BR vga_blitwait (3) +old style accelerator function. +.RE +.PP +.TP +.B flags +Miscellaneous flags. It is a logical or +of the following predefined values (which each have only one bit set). +.RS +.TP +.B HAVE_RWPAGE +.BR vga_setreadpage "(3) and " vga_setwritepage (3) +are available in this mode. +.TP +.B IS_INTERLACED +Mode is interlaced, which means it will tend to flicker and the user might be happier if the +application chooses another mode. +.TP +.B IS_MODEX +Mode user mode X like memory layout (planar 256 colors VGA mode). See +.BR vga_setmodeX (3) +for some explanations. +.TP +.B IS_DYNAMICMODE +Dynamically loaded mode. This mode was defined in +.I /etc/vga/libvga.conf +by the user. He will probably prefer its usage. However, usually this should +be of no interest to the user. +.TP +.B CAPABLE_LINEAR +Mode can be set to linear addressing with +.BR vga_setlinearaddressing (3). +.TP +.B IS_LINEAR +Linear addressing is already enabled for this mode. +.TP +.B EXT_INFO_AVAILABLE +The extended fields in this information structure are set to sensible information. If +EXT_INFO_AVAILABLE is not set you should even not access these fields as you might have +encountered an old version of svgalib and the fields migth actually not have been +allocated at all. +.TP +.B RGB_MISORDERED +For 16M4 modes it means that the 4 bytes per pixel actually mean 0BGR rather than +BGR0 as per default. For 16M mode it means that the 3 bytes actually mean +RGB instead of BGR. + +The first is a general limitation of Mach32, the latter one of Mach32 with a ramdac of type +4. The +.B vga_ +drawing functions takes this into account. +.TP +.B HAVE_EXT_SET +A +.BR vga_ext_set (3) +is available and can be called. +.RE +.SS Extended mode information +You must check for +.B EXT_INFO_AVAILABLE +in +.B flags +before trying to access these values. +.TP +.B chiptype +the chiptype that was detected/set. This specifies a subtype of the current +.BR vga_getcurrentchipset (3) +setting whose value depends on the chipset. It should be only used for +debugging or internally. +.TP +.B memory +memory available on the SVGA card in KB. +.TP +.B linewidth_unit +use only a multiple of this value for +.BR set_logicalwidth "(3) or " set_displaystart (3) +to ensure graceful alignment of lines onto the vga memory in this mode and for noiseless +video signals. +.TP +.B linear_aperture +ptr to a mmaped secondary linear framebuffer (not related to the use of +.BR vga_setlinearaddressing (3)) +.RB ( NULL +if unavailable) +.TP +.B aperture_size +size of the secondary framebuffer in KB. 0 if unavailable. +.TP +.B set_aperture_page +a function taking an int as parameter to select a page in the framebuffer addressed by +read/writes to this memory arey (if +.BR aperture_size " < " memory . +.TP +.B extensions +pointer to additional, internal, chipset specific info +(contents of the EEPROM for Mach32 driver.) +.PP +The +.BR vgatest (6) +demo displays most of this info for all supported modes. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_hasmode (3), +.BR vga_init (3), +.BR vga_setmode (3), +.BR vga_getcurrentmode (3), +.BR vga_getdefaultmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getmodename (3), +.BR vga_getmodenumber (3), +.BR vga_setlogicalwidth (3), +.BR vga_bitblt (3), +.BR vga_fillblt (3), +.BR vga_imageblt (3), +.BR vga_hlinelistblt (3), +.BR vga_blitwait (3), +.BR vga_setmodeX (3), +.BR vga_getcurrentchipset (3), +.BR vga_ext_set (3), +.BR vga_setlinearaddressing (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getmodename.3 b/doc/man3/vga_getmodename.3 new file mode 100644 index 0000000..7087bbc --- /dev/null +++ b/doc/man3/vga_getmodename.3 @@ -0,0 +1,61 @@ +.TH vga_getmodename 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getmodename \- return a name for the given video mode +.SH SYNOPSIS + +.B "#include " + +.BI "char *vga_getmodename(int " mode ); + +.SH DESCRIPTION +A pointer to a static memory buffer is returned. Depending on mode it consist of +a capital +.B G +followed by the +.BR "amount of x pixels" , +followed by a lower case +.BR x , +followed by the +.BR "amount of y pixels" , +followed by a lower case +.BR x . +Finally the number of different colors is appended. Here the shortcuts +.BR 32K , 64K , 16M ", and " 16M4 +are used for 32768, 65536, and 16777216 are used. The last refers also to +16777216 which are store in 4 bytes (highest address byte unused) for easier +screen access. + +For unsupported values +of +.I mode +the empty string "" is returned. In general the string resembles the corresponding +.B #define +for the videomode in +.BR "#include " . + +.SH EXAMPLE +.BR vga_getmodename(10) " returns " """G640x480x256""" . +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_hasmode (3), +.BR vga_modeinfo (3), +.BR vga_setmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getcurrentmode (3), +.BR vga_getdefaultmode (3), +.BR vga_getmodenumber (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getmodenumber.3 b/doc/man3/vga_getmodenumber.3 new file mode 100644 index 0000000..7b84108 --- /dev/null +++ b/doc/man3/vga_getmodenumber.3 @@ -0,0 +1,64 @@ +.TH vga_getmodenumber 3 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +vga_getmodenumber \- return a number for the given video mode +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getmodenumber(char *" name ); + +.SH DESCRIPTION +The function parses +.I *name +and tries to find a videomode corresponding on it. +.I *name +is parsed case insensitive and should be either an integer string just giving a +mode number or +consist of +a capital +.B G +followed by the +.BR "amount of x pixels" , +followed by a lower case +.BR x , +followed by the +.BR "amount of y pixels" , +followed by a lower case +.BR x . +Finally the number of different colors is appended. Here the shortcuts +.BR 32K , 64K , 16M ", and " 16M4 +are used for 32768, 65536, and 16777216 are used. The last refers also to +16777216 which are store in 4 bytes (highest address byte unused) for easier +screen access. + +For unsupported values or the string "PROMPT" the value -1 is returned. Also a +irritating error message is printed to stdout. This is used during parsing the +.B SVGALIB_DEFAULT_MODE +environment variable. Probably it should not be used for anything else. + +.SH EXAMPLE +.BR vga_getmodenumber("G640x480x256") " returns " 10. +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_hasmode (3), +.BR vga_modeinfo (3), +.BR vga_setmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getcurrentmode (3), +.BR vga_getdefaultmode (3), +.BR vga_getmodename (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getmonitortype.3 b/doc/man3/vga_getmonitortype.3 new file mode 100644 index 0000000..35a5ca2 --- /dev/null +++ b/doc/man3/vga_getmonitortype.3 @@ -0,0 +1,68 @@ +.TH vga_getmonitortype 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getmonitortype \- returns the monitor type configured +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getmonitortype(void);" + +.SH DESCRIPTION +This returns the monitor type configered in +.IR /etc/vga/libvga.config . +This function is really obsolete, as the result is of not much use to the application +.BR vga_getmodeinfo (3) +and +.BR vga_hasmode (3) +do already check the monitor type and there are more flexible ways to specify it too. + +The return value is one of: + +.PD 0 +.TP +.B MON640_60 +31.5 KHz (standard VGA): does 640x480 in 60Hz vsync. +.TP +.B MON800_56 +35.1 KHz (old SVGA): does 800x600 in 56Hz vsync. +.TP +.B MON1024_43I +35.5 KHz (low-end SVGA, 8514): does 1024x768 in 43Hz vsync interlaced. +.TP +.B MON800_60 +37.9 KHz (SVGA): does 800x600 in 60Hz vsync. +.TP +.B MON1024_60 +48.3 KHz (SVGA non-interlaced): does 1024x768 in 60Hz vsync, non-interlaced. +.TP +.B MON1024_70 +56.0 KHz (SVGA high frequency): does 1024x768 in 70Hz vsync. +.TP +.B MON1024_72 +does 1024x768 in 72Hz vsync or even better. +.PD +.PP + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR mousetest (6), +.BR spin (6), +.BR vga_init (3), +.BR vga_setmode (3), +.BR vga_hasmode (3), +.BR vga_getmodeinfo (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getmousetype.3 b/doc/man3/vga_getmousetype.3 new file mode 100644 index 0000000..ed2a004 --- /dev/null +++ b/doc/man3/vga_getmousetype.3 @@ -0,0 +1,110 @@ +.TH vga_getmousetype 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getmousetype \- returns the mouse type configured +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getmousetype(void);" + +.SH DESCRIPTION +This returns the mouse type configered in +.IR /etc/vga/libvga.config . + +The return value logically anded with +.B MOUSE_TYPE_MASK +is one of (defined in +.RB ( "#include " ): + +.PD 0 +.TP +.B MOUSE_NONE +There is no mouse installed. It is good style to check if there is no mouse +available first and then enable mouse support to avoid an svgalib error message if you +try to initialize a non existing mouse. +.B MOUSE_MICROSOFT +A Microsoft compatible mouse (2 buttons) (default). +.TP +.B MOUSE_MOUSESYSTEMS +A MouseSystems compatible mouse (3 buttons). +.TP +.B MOUSE_MMSERIES +A MMSeries compatible mouse. +.TP +.B MOUSE_LOGITECH +An ordinary LogiTech compatible mouse. +.TP +.B MOUSE_BUSMOUSE +A busmouse. +.TP +.B MOUSE_PS2 +A PS/2 busmouse. +.TP +.B MOUSE_LOGIMAN +An ordinary LogiTech LogiMan compatible mouse. +.TP +.B MOUSE_GPM +The GPM daemon is used. +.TP +.B MOUSE_SPACEBALL +A 3d SpaceTec Spaceball pointer device. +.TP +.B MOUSE_INTELLIMOUSE +A Microsoft IntelliMouse or Logitech MouseMan+ on serial port. +.TP +.B MOUSE_IMPS2 +A Microsoft IntelliMouse or Logitech MouseMan+ on PS/2 port. +.PD +.PP +The return value may be ored with one or more of the following flags + +.PD 0 +.TP +.B MOUSE_CHG_DTR +change the setting of DTR to force the mouse to a given mode. +.TP +.B MOUSE_DTR_HIGH +set DTR to high instead of setting it to low (default). +.TP +.B MOUSE_CHG_RTS +change the setting of RTS to force the mouse to a given mode. +.TP +.B MOUSE_RTS_HIGH +set RTS to high instead of setting it to low (default). +.PD +.PP + +Your application may use this info to perform specific actions (go into a 3d pointer +device mode for example). +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR mousetest (6), +.BR spin (6), +.BR mouse_close (3), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_init (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_init (3), +.BR vga_setmousesupport (3), +.BR vga_waitevent (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getpalette.3 b/doc/man3/vga_getpalette.3 new file mode 100644 index 0000000..7b2c8cb --- /dev/null +++ b/doc/man3/vga_getpalette.3 @@ -0,0 +1,53 @@ +.TH vga_getpalette 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getpalette \- get a color in the color lookup table +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_getpalette(int " index ", int *" r ", int *" g ", int *" b ); + +.SH DESCRIPTION +Get the color with index +.I index +and store its RGB values at +.IR *r ", " *g ", and " *b , +each in +the range 0 - 63. This function is only sensible in 16 or 256 color modes. It returns +which color all +.BI vga_setcolor( index ) +drawn pixels actually refer to. + +If the +.B VGA_CLUT8 +feature is set for the current mode with +.BR vga_ext_set (3) +the +.IR *r ", " *g ", and " *b +values are in the range 0 - 255. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_ext_set (3), +.BR vga_setpalvec (3), +.BR vga_setpalette (3), +.BR vga_getpalvec (3), +.BR vga_setrgbcolor (3), +.BR vga_setcolor (3), +.BR vga_setegacolor (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getpalvec.3 b/doc/man3/vga_getpalvec.3 new file mode 100644 index 0000000..4ee52c6 --- /dev/null +++ b/doc/man3/vga_getpalvec.3 @@ -0,0 +1,66 @@ +.TH vga_getpalvec 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getpalvec \- gets colors from the color lookup table +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getpalvec(int " start ", int " num ", int *" pal ); + +.SH DESCRIPTION +Gets the +.I num +colors starting with index +.I start +from the color lookup table and stores the RGB values in +.IR *pal ". " *pal " contains " +.BI "3 * " num +integers which are the color values from first to last palette entry in +the order red, green, blue (always three consecutive entries +in +.I *pal +built a palette entry. + +Each color entry is in range +0 - 63. This function is only sensible in 16 or 256 color modes. It shows +which color all +.BI vga_setcolor( start ) +(and +.IB num " - 1" +following colors) +drawn pixels will actually refer to. + +If the +.B VGA_CLUT8 +feature is set for the current mode with +.BR vga_ext_set (3) +the red, green, and blue values are in the range 0 - 255. + +The function returns the value of +.IR num . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_ext_set (3), +.BR vga_setpalette (3), +.BR vga_getpalette (3), +.BR vga_setpalvec (3), +.BR vga_setrgbcolor (3), +.BR vga_setcolor (3), +.BR vga_setegacolor (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getpixel.3 b/doc/man3/vga_getpixel.3 new file mode 100644 index 0000000..82e16ce --- /dev/null +++ b/doc/man3/vga_getpixel.3 @@ -0,0 +1,38 @@ +.TH vga_getpixel 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getpixel \- get a pixels value from the screen +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getpixel(int " x ", int " y ); + +.SH DESCRIPTION +Read a pixels value from the screen. This function is very inefficient, you should +consider doing direct screen access instead or use +.BR vga_getscansegment (3) +to handle more than one pixel. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_clear (3), +.BR vga_drawpixel (3), +.BR vga_drawline (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3), +.BR vga_getscansegment (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getscansegment.3 b/doc/man3/vga_getscansegment.3 new file mode 100644 index 0000000..a79ec98 --- /dev/null +++ b/doc/man3/vga_getscansegment.3 @@ -0,0 +1,35 @@ +.TH vga_getscansegment 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getscansegment \- get a list of consecutive pixel values +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getscansegment(unsigned char *" colors ", int " x ", int " y ", int " length ); + +.SH DESCRIPTION +The direct opposite of vga_drawscansegment(). The line of +.I length +pixels starting at +.BI ( x ", " y ) +is not drawn but instead the colorvalues are taken from the screen and +copied into +.IB color "[0] .. " color [ length " - 1]." +Svgalib versions was introduced in version 1.2.10. +In high/truecolor modes, the length must be given in bytes, not pixels. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_clear (3), +.BR vga_drawpixel (3), +.BR vga_drawline (3), +.BR vga_getpixel (3), +.BR vga_drawscanline (3), +.BR vga_drawscansegment (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . +The referenced function and its documentation are due to +Bill Randle . diff --git a/doc/man3/vga_gettextfont.3 b/doc/man3/vga_gettextfont.3 new file mode 100644 index 0000000..3c972e2 --- /dev/null +++ b/doc/man3/vga_gettextfont.3 @@ -0,0 +1,59 @@ +.TH vga_gettextfont 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_gettextfont, vga_puttextfont \- get/set the font used in text mode +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_gettextfont(void *font);" +.br +.BI "void vga_puttextfont(void *font);" + +.SH DESCRIPTION +The functions gives access to the buffer where svgalib saves the font used by the kernel. +This is used by the +.BR restorefont "(1), " +.BR savetextmode "(1), and " +.BR textmode "(1)" +utilities to restore a possibly screwed console font. + +The font buffer occupies 8192 bytes. However, versions 1.2.13 and later use +a larger buffer internally and the size of the buffers passed to +.BR vga_gettextfont "(3) and " vga_puttextfont (3) +can be set with +.BR vga_ext_set (3). + +The functions give access to the internal buffers of svgalib, +.B not +the font tables of the VGA card. This means that both functions must be called +in graphics mode and a newly set font takes effect only at the next +.BR vga_setmode(TEXT) +call. + +.SH SEE ALSO + +.BR vga_setmode (3), +.BR vga_ext_set (3), +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR restorefont (1), +.BR restoretextmode (1), +.BR restorepalette (1), +.BR savetextmode (1), +.BR textmode (1), +.BR vga_dumpregs (3), +.BR vga_gettextmoderegs (3), +.BR dumpreg (1) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_gettextmoderegs.3 b/doc/man3/vga_gettextmoderegs.3 new file mode 100644 index 0000000..a6e872a --- /dev/null +++ b/doc/man3/vga_gettextmoderegs.3 @@ -0,0 +1,48 @@ +.TH vga_gettextmoderegs 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_gettextmoderegs, vga_settextmoderegs \- get/set the vga state used in text mode +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_gettextmoderegs(void *state);" +.br +.BI "void vga_settextmoderegs(void *state);" + +.SH DESCRIPTION +The functions gives access to the buffer where svgalib saves the vga state which is use when +the kernel displays text on the SVGA. +This is used by the +.BR restoretextmode "(1), " +.BR savetextmode "(1), and " +.BR textmode "(1)" +utilities to restore a possibly screwed console. + +The buffer currently occupies 385 bytes. It can't do any harm to make it substantially larger +to allow for future enhancements. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR restorefont (1), +.BR restoretextmode (1), +.BR restorepalette (1), +.BR savetextmode (1), +.BR textmode (1), +.BR vga_dumpregs (3), +.BR vga_gettextfont (3), +.BR dumpreg (1) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getxdim.3 b/doc/man3/vga_getxdim.3 new file mode 100644 index 0000000..253d5e6 --- /dev/null +++ b/doc/man3/vga_getxdim.3 @@ -0,0 +1,37 @@ +.TH vga_getxdim 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_getxdim, vga_getydim, vga_getcolors \- return the current screen resolution +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_getxdim(void);" +.br +.BI "int vga_getydim(void);" +.br +.BI "int vga_getcolors(void);" + +.SH DESCRIPTION +These function return the currently selected screen resolution resp. number of +displayable colors. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_setmode (3), +.BR vga_getcurrentode (3), +.BR vga_getmodeinfo (3), +.BR vga_getgraphmem (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_getydim.3 b/doc/man3/vga_getydim.3 new file mode 100644 index 0000000..b5d9b6a --- /dev/null +++ b/doc/man3/vga_getydim.3 @@ -0,0 +1 @@ +.so man3/vga_getxdim.3 diff --git a/doc/man3/vga_guesstiming.3 b/doc/man3/vga_guesstiming.3 new file mode 100644 index 0000000..395f268 --- /dev/null +++ b/doc/man3/vga_guesstiming.3 @@ -0,0 +1,42 @@ +.TH vga_addtiming 3 "7 April 1999" "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +vga_guesstiming \- calculate a timing line for the given resolution +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_guesstiming(int x, int y, int clue, int arg); + +.SH DESCRIPTION +Calculates a timing line for a +.BR x*y +resolution, according to the value of +.BR clue. + +.SH CALCULATION METHODS +If +.BR clue +is 0, then the aspect ratio for the requested mode ( +.BR x:y +) must be 4:3. A mode with the same aspect ratio closest to the requested, while still having a higher resolution +is found, and then scaled down to the requested mode. + +If +.BR clue +is 1, then the aspect ratio for the requested mode ( +.BR x:y +) must be 4:3. A mode with the same aspect ratio closest to the requested, while still having a lower resolution +is found, and then scaled down to the requested mode. + +.SH BUGS +No guarantee that a modeline will be created, or that a created modeline will be usefull is given. + +.SH SEE ALSO + +.BR vga_addmode (3) +.BR vga_addtiming (3) +.BR addmodetest (6) + +.SH AUTHOR + +This manual page was written by Matan Ziv-Av diff --git a/doc/man3/vga_hasmode.3 b/doc/man3/vga_hasmode.3 new file mode 100644 index 0000000..eb6369e --- /dev/null +++ b/doc/man3/vga_hasmode.3 @@ -0,0 +1,44 @@ +.TH vga_hasmode 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_hasmode \- returns if a video mode is supported +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_hasmode(int " mode ); + +.SH DESCRIPTION +The function returns a non-zero value if the given +.I mode +is supported and 0 else. See +.BR vga_setmode (3) +for a list of predefined +.I mode +values and their meaning. +.BR vga_modeinfo (3) +can be used to find out details about the specific mode. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_modeinfo (3), +.BR vga_setmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getmodename (3), +.BR vga_getmodenumber (3) +.BR vga_getcurrentmode (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_hlinelistblt.3 b/doc/man3/vga_hlinelistblt.3 new file mode 100644 index 0000000..02ada08 --- /dev/null +++ b/doc/man3/vga_hlinelistblt.3 @@ -0,0 +1,97 @@ +.TH vga_hlinelistblt 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_hlinelistblt \- draw horizontal scan lines +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_hlinelistblt(int " ymin ", int " n ", int *" xmin ", int *" xmax +.BI ", int " pitch ", int " c ); + +.SH DESCRIPTION +.IR *xmin " and " *xmax " are pointers to arrays of " n " integers." +There are +.I n +horizontal lines drawn, for +.I i +in +.IB 0 " .. (" n " - 1)" +a horizontal line will be drawn from pixel +.BI ( xmin [ i "], " ymin " + " i ) +to +.BI ( xmax [ i "], " ymin " + " i ) +using color +.IR c . +Pixel +.B (0,0) +is considered +to be at the absolute beginning of the SVGA memory. +(as if +.B vga_setdisplaystart(0) +was called) + +This is an old style function to access the accelerator of an SVGA card. Before calling +it you should check for availability of the function in the mode you use with +.BR vga_getmodeinfo (3). + +For new applications you might be better of trying to use +.BR vga_accel (3) +instead. + +The old +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt "(3), and " +.BR vga_imageblt (3) +interface was originally designed for the Cirrus chipsets. Then Mach32 added support too +but has problems to resemble the unintuitive Cirrus interface. Then these new ideas +were reinjected and +.BR vga_accel (3) +was designed. Now Cirrus and Chips & Technologies chipset give limited +.BR vga_accel (3) +support but no longer this old style support. +Mach32 is left to use the unintuitive Cirrus interface. At some future point the +functions might be added for Mach32 too (which should be rather simple), so new +applications should use the newer and probably more efficient interface. + +It would be fatal if the accelerator would be used while the console is switched away. +You should use +.BR vga_lockvc (3) +and +.BR vga_unlockvc (3) +to avoid this, although good implementations of the accelerator functions (like Mach32) +will already ensure that. + +The +.BR testaccel (6) +demo utilizes the old style accelerator functions. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR testaccel (6), +.BR vga_accel (3), +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_imageblt (3), +.BR vga_getmodeinfo (3), +.BR vga_setdisplaystart (3), +.BR vga_lockvc (3), +.BR vga_unlockvc (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_imageblt.3 b/doc/man3/vga_imageblt.3 new file mode 100644 index 0000000..0d5e8bf --- /dev/null +++ b/doc/man3/vga_imageblt.3 @@ -0,0 +1,95 @@ +.TH vga_imageblt 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_imageblt \- copy a rectangular pixmap from system memory to video memory +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_imageblt(void *" srcaddr ", int " destaddr ", int " w ", int " h ", int " pitch ); + +.SH DESCRIPTION +Write a rectangular pixmap from system memory to video memory. +.I destaddr +is an offset +into video memory (up to 2M). The +.I pitch +is the logical width of the screen. Height +.I h +is in Pixels, Width +.I w +is in +.BR BYTES ! + +It fills the given box +with the data in memory area +.IR *srcaddr . +The memory buffer must contain the pixels in the same representation +as used in the vga memory, starting at the top left +corner, from left to right, and then, line by line, +from up to down, without any gaps and interline +spaces. + +This is an old style function to access the accelerator of an SVGA card. Before calling +it you should check for availability of the function in the mode you use with +.BR vga_getmodeinfo (3). + +For new applications you might be better of trying to use +.BR vga_accel (3) +instead. + +The old +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt "(3), and " +.BR vga_imageblt (3) +interface was originally designed for the Cirrus chipsets. Then Mach32 added support too +but has problems to resemble the unintuitive Cirrus interface. Then these new ideas +were reinjected and +.BR vga_accel (3) +was designed. Now Cirrus and Chips & Technologies chipset give limited +.BR vga_accel (3) +support but no longer this old style support. +Mach32 is left to use the unintuitive Cirrus interface. At some future point the +functions might be added for Mach32 too (which should be rather simple), so new +applications should use the newer and probably more efficient interface. + +It would be fatal if the accelerator would be used while the console is switched away. +You should use +.BR vga_lockvc (3) +and +.BR vga_unlockvc (3) +to avoid this, although good implementations of the accelerator functions (like Mach32) +will already ensure that. + +The +.BR testaccel (6) +demo utilizes the old style accelerator functions. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR testaccel (6), +.BR vga_accel (3), +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt (3), +.BR vga_getmodeinfo (3), +.BR vga_lockvc (3), +.BR vga_unlockvc (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_init.3 b/doc/man3/vga_init.3 new file mode 100644 index 0000000..088c851 --- /dev/null +++ b/doc/man3/vga_init.3 @@ -0,0 +1,123 @@ +.TH vga_init 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_init \- initialize svgalib library +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_init(void);" + +.SH DESCRIPTION +It detects the chipset and gives up supervisor +rights. This is the recommended first line of any program that uses +svgalib. +.BR vga_setchipset (3) +can be called before it to avoid detection. + +Svgalib catches a bunch of signals that usually kill your +program to restore textmode. If you catch signal's before +calling +.B vga_init() +svgalib will restore textmode and prepare +for shutdown and then call your handler routine. If you don't +want this, catch the signal +.B after +calling vga_init and do not daisychain to svgalib's original handler. + +.B WARNING! +svgalib needs two signals for it's own purposes +(that is managing console switches). To avoid problems it uses +the otherwise unused signals +.B SIGUSR1 +and +.BR SIGUSR2 . +However, this means that you cannot use them in your program by any +means. They are setup by +.B vga_init() +as everything else is. + +Since version 1.2.11 +.B vga_init() +includes code to hunt for a free virtual console on its own in +case you are not starting the program from one (but instead over a network or +modem login, from within 'screen' or an 'xterm'). Provided there is a free +console, this succeeds if you are root or if the svgalib calling user own +the current console. This is to avoid people not using the console being able +to fiddle with it. +On graceful exit the program returns to the console from which it was started. +Otherwise it remains in text mode at the VC which svgalib allocated to allow +you to see any error messages. In any case, any I/O the svgalib makes in +text mode (after calling vga_init) will also take place at this new console. + +Alas, some games misuse their suid root privilege and run as full root +process. svgalib cannot detect this and allows Joe Blow User to open a new +VC on the console. If this annoys you +.B ROOT_VC_SHORTCUT +in +.I Makefile.cfg +allows +you to disable allocating a new VC for root (except when he owns the current +console) when compiling svgalib. This is the default (disabling the allocation for root). + +.B vga_init() +returns a non-zero value in case of errors. As of this writing it will return +-1 if it is unable to allocate a graphical console. Otherwise, 0 is returned. + +.SH BUGS +Svgalib versions prior to 1.2.11 had a security hole where it would be possible +to regain root privileges even after a +.B vga_init() +call. This is not necessarily a problem, but if your program is vulnerable to +buffer overflows and other attacks, an attacker may exploit this. + +However, prior to your call, your program will need to run setuid root, so you should +be very careful. The ioperm library by Olaf Titz will allow svgalib programs to run +not setuid root. However, it gives all programs unlimited access to the hardware. Again, +a malicious person can exploit this (albeit a bit more difficult) too. +Thus, in general, make your svgalib programs as secure as any setuid root program. + +Some programs may (accidently) rely on the old behaviour (which was probably due to the +author not knowing about saved uids (which might actually even not have existed in Linux at that +time)). A line: + +.B "security compat" + +in the configuration file +.I /etc/vga/libvga.conf +will reinstate the old behaviour whereas + +.B "security revoke-all-privs" + +enables the (currently default) action. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vga_setmode (3), +.BR mouse_init (3), +.BR vga_claimvideomemory (3), +.BR vga_ext_set (3), +.BR vga_fillblt (3), +.BR vga_getcurrentchipset (3), +.BR vga_getdefaultmode (3), +.BR vga_getgraphmem (3), +.BR vga_runinbackground (3), +.BR vga_runinbackground_version (3), +.BR vga_safety_fork (3), +.BR vga_setchipset (3), +.BR vga_setchipsetandfeatures (3), +.BR vgagl (7), +.BR libvga.config (5), + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_initcursor.3 b/doc/man3/vga_initcursor.3 new file mode 100644 index 0000000..a3489fa --- /dev/null +++ b/doc/man3/vga_initcursor.3 @@ -0,0 +1,32 @@ +.TH vga_initcursor 3 "23 June 2001" "Svgalib (>= 1.9.6)" "Svgalib User Manual" +.SH NAME +vga_initcursor \- initialize mouse cursor +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_initcursor(int sw);" + +.SH DESCRIPTION +if +.B sw +is non-zero, this initializes the software cursor. Otherwise calls the chipset driver's +cursor init function. If the driver supports does not support a hardware cursor, a +software cursor is used. + +.SH RETURN VALUE +.BR vga_initcursor +returns zero if a software cursor is used, and non-zero if hardware cursor is used. +.SH SEE ALSO + +.BR svgalib (7), +.BR mouse_init (3), +.BR vga_selectcursor (3), +.BR vga_showcursor (3), +.BR vga_setcursorposition (3), +.BR vga_setcursorimage (3), + +.SH AUTHOR + +This manual page written by Matan Ziv-Av . + diff --git a/doc/man3/vga_lastmodenumber.3 b/doc/man3/vga_lastmodenumber.3 new file mode 100644 index 0000000..40601be --- /dev/null +++ b/doc/man3/vga_lastmodenumber.3 @@ -0,0 +1,46 @@ +.TH vga_lastmodenumber 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_lastmodenumber \- returns the last video mode number +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_lastmodenumber(void);" + +.SH DESCRIPTION +Returns the last video mode number. As video mode numbers start with 1 (0 is for textmode) +this allows an application to scan through all possible modes portable with +.BR vga_modeinfo (3). + +For example the +.BR vgatest (6) +demo does just that. + +.B "#include " +does include a +.BR "#define GLASTMODE vga_lastmodenumber()" . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_hasmode (3), +.BR vga_modeinfo (3), +.BR vga_setmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getmodename (3), +.BR vga_getmodenumber (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_lockvc.3 b/doc/man3/vga_lockvc.3 new file mode 100644 index 0000000..b6e61ee --- /dev/null +++ b/doc/man3/vga_lockvc.3 @@ -0,0 +1,35 @@ +.TH vga_lockvc 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_lockvc \- disables virtual console switching for safety +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_lockvc(void);" + +.SH DESCRIPTION +Disables virtual console switching for safety. Recommended +when doing register I/O or low-level device handling. Used +by mouse functions. Also useful in conjunction with background running. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR bg_test (6), +.BR vga_oktowrite (3), +.BR vga_runinbackground (3), +.BR vga_runinbackground_version (3), +.BR vga_unlockvc (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_norevokeprivs.3 b/doc/man3/vga_norevokeprivs.3 new file mode 100644 index 0000000..80377d0 --- /dev/null +++ b/doc/man3/vga_norevokeprivs.3 @@ -0,0 +1,22 @@ +.TH vga_norevokeprivs 3 "9 September 2004" "Svgalib (>= 1.9.20)" "Svgalib User Manual" +.SH NAME +vga_norevokeprivs \- Keep root privileges if run as suid root. +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_norevokeprivs(void);" + +.SH DESCRIPTION +Calling this function prevents svgalib from revoking root privileges and +returning to the uid of the user running the program. Usually svgalib revokes +privileges at +.BR vga_init (3) +time, so +.B vga_norevokeprivs +needs to be called before +.B vga_init . + +.SH AUTHOR + +This manual page written by Matan Ziv-Av . diff --git a/doc/man3/vga_oktowrite.3 b/doc/man3/vga_oktowrite.3 new file mode 100644 index 0000000..7d0c4d0 --- /dev/null +++ b/doc/man3/vga_oktowrite.3 @@ -0,0 +1,43 @@ +.TH vga_oktowrite 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_oktowrite \- indicates whether the program has direct access to the SVGA +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_oktowrite(void);" + +.SH DESCRIPTION +Indicates whether the program is in the console currently +visible on the screen, that is, whether it is OK to write +to video memory (if running in the background has been allowed +with the function above). Note that this is not entirely +safe, since a console switch interrupt may occur during a +video operation. It is best to avoid this function. + +Usually your program will be suspended when it has no access to the +screen but see +.BR vga_runinbackground (3) +for an alternative. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR bg_test (6), +.BR vga_runinbackground (3), +.BR vga_runinbackground_version (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_puttextfont.3 b/doc/man3/vga_puttextfont.3 new file mode 100644 index 0000000..6c7cd56 --- /dev/null +++ b/doc/man3/vga_puttextfont.3 @@ -0,0 +1 @@ +.so man3/vga_gettextfont.3 diff --git a/doc/man3/vga_runinbackground.3 b/doc/man3/vga_runinbackground.3 new file mode 100644 index 0000000..ef079f4 --- /dev/null +++ b/doc/man3/vga_runinbackground.3 @@ -0,0 +1,254 @@ +.TH vga_runinbackground 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_runinbackground \- enable running of the program while there is no VGA access +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_runinbackground(int " stat ); + +.SH DESCRIPTION +Enable/disable background running of a graphics program. +.TP +.IB stat " = 1" +enables +.TP +.IB stat " = 0" +disables +.PP +Normally, the program is suspended while +not in the current virtual console. A program can only +safely run in the background if it doesn't do any video +access during this time. + +As of version 1.2.11 this was changed by Pekka T. Alaruikka +& Michael Friman +The support for this must be enabled +in +.I Makefile.cfg +of svgalib (which it is by default). Several ways to support this may exist internally. +As of now, only one using proc-fs works. +Using +.BI "vga_runinbackground(VGA_GOTOBACK, void (*" goto )()) +and +.BI "vga_runinbackground(VGA_COMEFROMBACK, void (*" comefrom )()) +with +function pointers to functions +.BI "void " goto "(void)" +and +.BI "void " comefrom "(void)" +you can setup function to be called +when your program goes to background mode and when it comes +back to foreground. These can be changed at any time, and +passing +.B NULL +as function disables the feature. + +Both these new +features require a +.BR vga_runinbackground_version (3) +of 1 or higher. You should check and not call it when the +svgalib in use returns 0. +Also, when writing applications, check with + +.B #ifdef VGA_GOTOBACK +.br +.BR " " "/* code using " vga_runinbackground(VGA_GOTOBACK, " +.IB goto ) +*/ +.br +.B #else +.br +.BR " " "/* code using no goto or comefrom function */" +.br +.B #endif + +if you are compiling with an svgalib that supports this feature, +and try to rearrange your source to work without it when +an svgalib version prior to 1.2.11 is used. + +The function should be called right after +.BR vga_init (3). +The +.BR bg_test (6) +demos shows the principle operation. +.PP +Please note that background capabilities are in +.B VERY +early stages. Please do not expect that +.B EVERYTHING +works flawlessly when background abilities are enabled in your program. + +.SH EXAMPLE +.B vga_init(); +.br +.B vga_setmode(G320x200x256); +.br +.B "if (vga_runinbackground_version() == 1)" +.br +.B " " vga_runinbackground(1); + +.SH NOTES +Before a program is left background capable, it should be tested well. Most +programs will work just well. + +When the program is in background, it can read IO-devices (except keyboard). +This can cause harm, if the programmer does not take this int account. I.e. in games +using a joystick or/and mouse device the game continues reading joystick or/and +mouse as it would be on foreground. + +The mouse can be made working correctly also in background, but this means that +svgalib must be configured to use gpm mouse driver. + +More information about gpm-linux can be founded from latest gpm packet (by +Alessandro Rubini). + +The goto and comefrom routines provide a way to overcome this restriction. +.PP +There are so far two different methods for background running. The first method +use mmap function with FIXED option, which is not recommended by mmap's man page. +It has some probability to fail. But it allows programs to think that +graphics memory is always present. + +The second method is just let the functions to write directly graphics memory's +save-buffer. This means that the memory area where graphics information is changes +for the program. The program must always know where to write. This type of action +needs much more work and leaves probably always room for race conditions. + +Hopefully the first method proves to be good enough and second method can be +left away. + +Neither method allows the use of the graphics card's registers in background. +When registers are used, vc switching is disabled, but the request are queued. +Vc switching is done as soon as possible. +.PP +Generally, accelerated functions will probably cause problems, except when they are +implemented carefully to check for availability of the cards registers. +.PP +User programs should generally not use the graphics registers directly. But if program needs to +use the registers, it has to check if it is in background or not. In the +background state it can not use the registers. For testing the +.BR vga_oktowrite (3) +function can be used. During register access the virtual console must be +locked. A possible code fragment might look like: + +.B vga_lockvc(); +.br +.B "if (vga_oktowrite()) {" +.br +.BR " " "/* Register operations. */" +.br +.B } else { +.br +.BR " " "/* Registers can not be used. Alternative action. */" +.br +.B } +.br +.B vga_unlockvc(); + +.SH ADVANCED NOTES +.SS Installation +Background capability is enabled in svgalib by setting +.B BACKGROUND=y +and +disabled by commenting +.B #BACKGROUND=y in +.I Makefile.cfg +before compiling svgalib. Background capable +svgalib is more stable with all programs. Programs do not have to use +background abilities even when they are available. As of this writing, all +precompiled svgalib binaries are background capable by default. +.B NOTICE: proc-fs must be mounted for background capability. + +.SS Status of the background feature +Background capability in svgalib is in an early stagei of development. +There has been done lot of work for it, but probably not everything will work +perfectly. This applies only to programs which actually enabled background running +with +.BR vga_runinbackground (3). + +The +.BR vga_drawline (3), +.BR vga_drawpixel (3), +.BR vga_getclolors (3), +.BR vga_getpixel (3), +.BR vga_screenoff (3), +.BR vga_screenon (3), +.BR vga_setegacolor (3), +.BR vga_setrgbcolor (3), +.BR vga_setcolor (3), +.BR vga_setpage "(3) and " +.BR vga_clear (3) +functions appear to work and calling +.BR vga_setmode (3) +is safe too but cannot change modes while in background. The remaining +svgalib and vgagl function should work too but are not well tested. + +Calling accelerated functions will most probably cause harm though this is +worked on. + +Please report problems to Pekka (see +.B AUTHOR +section). + +.SS Programming within svgalib +When coding within svgalib, +there are same restrictions as in user programs. +SVGA registers can not be used while in background. The svgalibrary has +internal functions for locking and unlocking virtual console switching +.B __svgalib_dont_switch_vt_yet() +and +.BR __svgalib_is_vt_switching_needed() . +These +functions are not meant to be called from user program. +.BR vga_unlockvc (3) +can not +release vc switching if internal svgalib locking is used. This is for safety. +The procedure for registers are similar to the procedure for user programs: + +.B "void vga_super_new_function(void) {" +.br +.B " __svgalib_dont_switch_vt_yet();" +.br +.B " if (vga_oktowrite()) {" +.br +.BR " " "/* Register operations. */" +.br +.B " } else {" +.br +.BR " " "/* Registers can not be used. Alternative action. */" +.br +.B " }" +.br +.B " __svgalib_is_vt_switching_needed();" +.br +.B "}" + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR bg_test (6), +.BR vga_accel (3), +.BR vga_bitblt (3), +.BR vga_blitwait (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt (3), +.BR vga_imageblt (3), +.BR vga_init (3), +.BR vga_lockvc (3), +.BR vga_oktowrite (3), +.BR vga_runinbackground_version (3), +.BR vga_safety_fork (3), +.BR vga_setchipset (3), +.BR vga_setpage (3), +.BR vga_setreadpage (3), +.BR vga_setwritepage (3), +.BR vga_unlockvc (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +function was implemented and documented by Pekka T. Alaruikka +& Michael Friman . diff --git a/doc/man3/vga_runinbackground_version.3 b/doc/man3/vga_runinbackground_version.3 new file mode 100644 index 0000000..0ac47e2 --- /dev/null +++ b/doc/man3/vga_runinbackground_version.3 @@ -0,0 +1,30 @@ +.TH vga_runinbackground_version 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_runinbackground_version \- returns the version of the current background support +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_runinbackground_version(void);" + +.SH DESCRIPTION +returns the version of the current background support which is +1 (uses proc-fs). In case svgalib is compiled without background +support, 0 is returned. See +.BR vga_runinbackground (3) +for more information on background support. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR bg_test (6), +.BR vga_runinbackground (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +function was implemented and documented by Pekka T. Alaruikka +& Michael Friman . + diff --git a/doc/man3/vga_safety_fork.3 b/doc/man3/vga_safety_fork.3 new file mode 100644 index 0000000..ce20455 --- /dev/null +++ b/doc/man3/vga_safety_fork.3 @@ -0,0 +1,56 @@ +.TH vga_safety_fork 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_safety_fork \- start a parallel process to restore the console at a crash +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_safety_fork(void (*" shutdown_routine ")(void))" + +.SH DESCRIPTION +Calling this at the start of a program results in a better +chance of textmode being restored in case of a crash. +However it has to raise the iopl level to 3 to work. This is +a small security breach as it is inherited to any programs +you fork of. However, some SVGA card drivers have to use +iopl(3) anyway. +If you use it call that function as the very first +.B vga_ +function. Call it right before +.B vga_init (3). +Note that +.B vga_safety_fork() +will already enter a graphicsmode. (For font +and grafix state saving). +Don't overestimate the power of this function. Your application will continue to run +in background while a foreground application will restore a usable screen and graphics +mode in case of a crash. + +The +.BR forktest (6) +demo shows the principal operation. +.BI (* shutdown_routine )() +is called when the system crashes. However, realize that the call will take in a forked +copy of your program, you'll not have access to any globals modified after the +.B vga_safety_fork() +call! +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR forktest (6), +.BR vga_init (3), + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_screenoff.3 b/doc/man3/vga_screenoff.3 new file mode 100644 index 0000000..fb02061 --- /dev/null +++ b/doc/man3/vga_screenoff.3 @@ -0,0 +1,37 @@ +.TH vga_screenoff 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_screenoff, vga_screenon \- turn generation of the video signal on or off +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_screenoff(void);" +.br +.BI "int vga_screenon(void);" + +.SH DESCRIPTION +The functions turn the generation of the video signal on or off. On some video boards, +SVGA memory access is faster when no video signal is generated. On the other hand, not +all boards allow to disable it (at least not in all modes). + +The functions always return 0 (on which you should probably not really rely). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_init (3), +.BR vga_setmode (3), +.BR vga_clear (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_screenon.3 b/doc/man3/vga_screenon.3 new file mode 100644 index 0000000..a35158f --- /dev/null +++ b/doc/man3/vga_screenon.3 @@ -0,0 +1 @@ +.so man3/vga_screenoff.3 diff --git a/doc/man3/vga_selectcursor.3 b/doc/man3/vga_selectcursor.3 new file mode 100644 index 0000000..faf2521 --- /dev/null +++ b/doc/man3/vga_selectcursor.3 @@ -0,0 +1,25 @@ +.TH vga_selectcursor 3 "23 June 2001" "Svgalib (>= 1.9.6)" "Svgalib User Manual" +.SH NAME +vga_selectcursor \- select mouse cursor pattern +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_selectcursor(int cur);" + +.SH DESCRIPTION +Selects onr of the 16 cursor patterns to display. + +.SH SEE ALSO + +.BR svgalib (7), +.BR mouse_init (3), +.BR vga_showcursor (3), +.BR vga_initcursor (3), +.BR vga_setcursorposition (3), +.BR vga_setcursorimage (3), + +.SH AUTHOR + +This manual page written by Matan Ziv-Av . + diff --git a/doc/man3/vga_setchipset.3 b/doc/man3/vga_setchipset.3 new file mode 100644 index 0000000..d35d301 --- /dev/null +++ b/doc/man3/vga_setchipset.3 @@ -0,0 +1,99 @@ +.TH vga_setchipset 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setchipset \- force chipset +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setchipset(int " chipset ); + +.SH DESCRIPTION +Force detection of a chipset (when chipset detection fails). +.B vga_setchipset(VGA) +can be useful if the chipset specific +stuff or the SVGA detection stuff gives problems. + +However, at first the automatic detection should work well, and if not a specific +chipset can be forced from +.IR /etc/vga/libvga.config . + +Because of that, +.BI "void vga_setchipset(int " chipset ) +should probably never be used by applications. If used nevertheless, it should be called +directly before +.BR vga_init (3). + +As of now the following values are defined for +.IR chipset: +.TP +.B UNDEFINED +This is the default and specifies autodetection. +.TP +.B VGA +A plain VGA card, not that the SVGA must behave like an ordinary SVGA card then which +will probably mean it is in an ordinary (25x80) textmode. +.TP +.B ET4000 +Tseng ET4000/ET4000W32(i/p) cards. +.TP +.B CIRRUS +Cirrus Logic GD542x/3x cards. +.TP +.B TVGA8900 +Trident TVGA 8900C/9000 (and possibly also 8800CS/8900A/B) cards. +.TP +.B OAK +Oak Technologies OTI-037/67/77/87 cards. +.TP +.B EGA +An ordinary EGA card. The notes about VGA apply. +.TP +.B S3 +An S3 base card. +.TP +.B ET3000 +Tseng ET3000 cards. +.TP +.B MACH32 +A card (from ATI or not) based on the ATI Mach32 chipset. +.TP +.B GVGA6400 +A Genoa(?) GVGA6400 card. +.TP +.B ARK +ARK Logic ARK1000PV/2000PV cards. +.TP +.B ATI +An ATI SVGA (VGA Wonder and friends) card. This does not (necessarily) include +the newer cards (usually called Mach something). +.TP +.B ALI +An ALI2301 based card. +.TP +.B MACH64 +A card using the ATI Mach64 chipset. Support is not complete. +.TP +.B CHIPS +Chips and Technologies chipsets 65525, 65535, 65546, 65548, 65550, and 65554 (usually in laptops). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_getcurrentchipset (3), +.BR vga_setchipsetandfeatures (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setchipsetandfeatures.3 b/doc/man3/vga_setchipsetandfeatures.3 new file mode 100644 index 0000000..8c62e05 --- /dev/null +++ b/doc/man3/vga_setchipsetandfeatures.3 @@ -0,0 +1,39 @@ +.TH vga_setchipsetandfeatures 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setchipsetandfeatures \- force chipset and optional parameters +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setchipsetandfeatures(int " chipset ", int " par1 ", int " par2 ); + +.SH DESCRIPTION +Force chipset, and optional parameters like the exact +chipset type and the amount of video memory installed. This function works similar to +.BR vga_setchipset (3) +and allows the same values for +.IR chipset . +In addition you can pass additional parameters to the setup routine whose meaning +heavily depend on the driver. You should only use this for debugging and if you know +what you do, which is why we do not document anything more here. + +.SH SEE ALSO +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_getcurrentchipset (3), +.BR vga_setchipset (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setcolor.3 b/doc/man3/vga_setcolor.3 new file mode 100644 index 0000000..2f33fc6 --- /dev/null +++ b/doc/man3/vga_setcolor.3 @@ -0,0 +1,50 @@ +.TH vga_setcolor 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setcolor \- set the current color +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setcolor(int " color ); + +.SH DESCRIPTION +Set the current color to +.IR color . +You may only use +.B vga_setcolor() +in 256 or less color modes. For the other modes you must use +.BR vga_setrgbcolor (3) +instead. + +The color is used by +.BR vga_drawpixel (3) +and +.BR vga_drawline (3). + +The +.BR fun "(6) and " vgatest (6) +demos show the basic use of this function. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR fun (6), +.BR vgatest (6), +.BR vga_setrgbcolor (3), +.BR vga_setegacolor (3), +.BR vga_drawpixel (3), +.BR vga_drawline (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setcursorimage.3 b/doc/man3/vga_setcursorimage.3 new file mode 100644 index 0000000..ad1bc3a --- /dev/null +++ b/doc/man3/vga_setcursorimage.3 @@ -0,0 +1,37 @@ +.TH vga_setcursorimage 3 "23 June 2001" "Svgalib (>= 1.9.6)" "Svgalib User Manual" +.SH NAME +vga_setcursorimage \- set the pattern and colors of the mouse cursor +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setcursorimage(int cur, int format, int c0, int c1, unsigned char *buf);" + +.SH DESCRIPTION +Sets cursor image number +.B cur +to be the pattern pointed by +.B buf +with colors +.B c0 +and +.B c1. +The +.B format +parameter decides the format of the input pattern. + +.SH NOTES + +.SH SEE ALSO + +.BR svgalib (7), +.BR mouse_init (3), +.BR vga_selectcursor (3), +.BR vga_initcursor (3), +.BR vga_setcursorposition (3), +.BR vga_showcursor (3), + +.SH AUTHOR + +This manual page written by Matan Ziv-Av . + diff --git a/doc/man3/vga_setcursorposition.3 b/doc/man3/vga_setcursorposition.3 new file mode 100644 index 0000000..797639f --- /dev/null +++ b/doc/man3/vga_setcursorposition.3 @@ -0,0 +1,30 @@ +.TH vga_setcursorposition 3 "23 June 2001" "Svgalib (>= 1.9.6)" "Svgalib User Manual" +.SH NAME +vga_setcursorposition \- set the mouse cursor position +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_initcursor(int x, int y);" + +.SH DESCRIPTION +Sets the position of the top left corner of the mouse square to be at the pixel position +( +.B x +, +.B y +). + +.SH SEE ALSO + +.BR svgalib (7), +.BR mouse_init (3), +.BR vga_selectcursor (3), +.BR vga_showcursor (3), +.BR vga_initcursor (3), +.BR vga_setcursorimage (3), + +.SH AUTHOR + +This manual page written by Matan Ziv-Av . + diff --git a/doc/man3/vga_setdisplaystart.3 b/doc/man3/vga_setdisplaystart.3 new file mode 100644 index 0000000..06a9cd0 --- /dev/null +++ b/doc/man3/vga_setdisplaystart.3 @@ -0,0 +1,47 @@ +.TH vga_setdisplaystart 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setdisplaystart \- set the display start address +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setdisplaystart(int " a ); + +.SH DESCRIPTION +Set the display start address to +.IR a , +where the address is the +number of pixels offset from the start of video memory, +except for hicolor/truecolor modes, which use a unit of +1 byte. Can be used for page-flipping and virtual desktop +scrolling. May not work properly for 16 color modes. + +You should ensure that the memory displayed is actually available on the SVGA +card (query memory size with +.BR vga_modeinfo (3)) +and ensure that it is saved by svgalib during console switches with +.BR vga_claimvideomemory (3). + +You may only set the bits of the display start address returned by +.BR vga_modeinfo (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_modeinfo (3), +.BR vga_setlogicalwidth (3), +.BR vga_claimvideomemory (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setegacolor.3 b/doc/man3/vga_setegacolor.3 new file mode 100644 index 0000000..40cc1ad --- /dev/null +++ b/doc/man3/vga_setegacolor.3 @@ -0,0 +1,101 @@ +.TH vga_setegacolor 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setegacolor \- set the current color +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setegacolor(int " color ); + +.SH DESCRIPTION +Set the current color to be a color resembling the +.IR color -th +EGA coler. This works regardless of the depth of the current video mode. + +The color is used by +.BR vga_drawpixel (3) +and +.BR vga_drawline (3). + +Valid values for +.I color +are: +.PP +.PD 0 +.TP +.B 0 +- black. +.TP +.B 1 +- blue. +.TP +.B 2 +- green. +.TP +.B 3 +- cyan. +.TP +.B 4 +- red. +.TP +.B 5 +- magenta. +.TP +.B 6 +- brown. +.TP +.B 7 +- grey. +.TP +.B 8 +- dark grey (light black). +.TP +.B 9 +- light blue. +.TP +.B 10 +- light green. +.TP +.B 11 +- light cyan. +.TP +.B 12 +- light red. +.TP +.B 13 +- light magenta. +.TP +.B 14 +- yellow (light brown). +.TP +.B 15 +- white (light grey). +.PD +.PP +The +.BR fun "(6) and " vgatest (6) +demos show the basic use of this function. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR fun (6), +.BR vgatest (6), +.BR vga_setcolor (3), +.BR vga_setrgbcolor (3), +.BR vga_drawpixel (3), +.BR vga_drawline (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setflipchar.3 b/doc/man3/vga_setflipchar.3 new file mode 100644 index 0000000..eee3c67 --- /dev/null +++ b/doc/man3/vga_setflipchar.3 @@ -0,0 +1,43 @@ +.TH vga_setflipchar 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setflipchar \- set the character causing a vga_flip() +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_setflipchar(int " c ); + +.SH DESCRIPTION +This sets the ASCII code of the key which causes +.BR vga_getch (3) +to shortly switch between graphics and text mode +when waiting for a keypress. +.B +is the default at startup. + +Because one can now swicth directly between consoles even when in graphics modes and +the use of +.BR vga_flip (3) +is discouraged except for debugging, this function is just there for +vgalib compatibility but has no effect! + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_flip (3), +.BR vga_getkey (3), +.BR vga_waitevent (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setlinearaddressing.3 b/doc/man3/vga_setlinearaddressing.3 new file mode 100644 index 0000000..65959d2 --- /dev/null +++ b/doc/man3/vga_setlinearaddressing.3 @@ -0,0 +1,76 @@ +.TH vga_setlinearaddressing 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setlinearaddressing \- switch to linear addressing mode +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_setlinearaddressing(void);" + +.SH DESCRIPTION +Switch to linear addressing mode. This maps all (or most) of the SVGA memory at the +position returned by +.BR vga_getgraphmem (3) +(which will probably change by the call +to +.BR vga_setlinearaddressing()). +The +.BR vga_set*page (3) +calls +are no longer required. This ensures optimal performance, however, +not all cards support it (and not in all modes). + +Use +.BR vga_modeinfo (3) +to check for availability of the function in a given mode. + +Furthermore, some cards (Cirrus) just enable this buffer at a fixed hardware address. +For Cirrus it is mapped at 14MB so you should never used it if you have more than 14MB +of memory (But how does an application know?). +The Mach32 support for this is smarter. It makes this feature only available when it is safe +to be used. + +To avoid all this problems you can use + +.TP +.B nolinear +Inhibit use of a linear mmaped frame buffer. +.TP +.B linear +Allow (not enforce!) use of a linear mmaped frame buffer. +.P +in the +.I /etc/vga/libvga.config +file to disable the linear frame buffer if it cannot be used. + +Returns the size of the mapped framebuffer if successful (can +be less than total video memory), -1 if not. + +The +.BR testlinear (6) +demo shows the use of this feature (and if it works for you). +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR testlinear (6), +.BR vga_modeinfo (3), +.BR vga_getgraphmem (3), +.BR vga_setpage (3), +.BR vga_setreadpage (3), +.BR vga_setwritepage (3), +.BR vga_setlinearaddressing (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setlogicalwidth.3 b/doc/man3/vga_setlogicalwidth.3 new file mode 100644 index 0000000..d7fae3d --- /dev/null +++ b/doc/man3/vga_setlogicalwidth.3 @@ -0,0 +1,43 @@ +.TH vga_setlogicalwidth 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setlogicalwidth \- set the logical scanline width +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setlogicalwidth(int " l ); + +.SH DESCRIPTION +Set the logical scanline width to +.I l +bytes. It must be a multiple of 8. Only changes the VGA register, drawing +functions don't take it into account. The logical scan line width is the offset +between points above each other in consecutive lines. Note that for some cards and +graphics modes a +multiple of 8 will not suffice to ensure a proper video timing. You should +only set +.I l +to multiples of the value returned for that graphics mode by +.BR vga_modeinfo (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_modeinfo (3), +.BR vga_displaystart (3), +.BR vga_claimvideomemory (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setmode.3 b/doc/man3/vga_setmode.3 new file mode 100644 index 0000000..3cccc3a --- /dev/null +++ b/doc/man3/vga_setmode.3 @@ -0,0 +1,182 @@ +.TH vga_setmode 3 "28 Jul 1999" "Svgalib 1.4.1" "Svgalib User Manual" +.SH NAME +vga_setmode \- sets a video mode +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_setmode(int " mode ); + +.SH DESCRIPTION +.BI "vga_setmode(int " mode ) +selects the video +.I mode +given and clears the screen (if it was a graphics mode). +Basically this should be the first action of your application after calling +.BR vga_init (3) +and finding out which mode to use. +Prior to exiting your application should call +.B vga_setmode(TEXT). + +.B vga_setmode() +returns 0 on success and -1 if this mode is not available. + +From svgalib-1.4.1, if +.I mode +is -1 then vga_setmode() returns the current svgalib version, in BCD format, so +svgalib 1.4.1 returns 0x1410. + +.I mode +should be one of the following, predefined values, or generally a value in range +.B 1 <= +.I mode +.B <= vga_lastmodenumber() +where +.BR vga_modeinfo (3) +returned details about this mode. Instead of trying to set the mode, +.BR vga_hasmode (3) +determines if the mode would actually be supported. It is also possible to use +the numeric values given below though this is discouraged. They are commonly used as values +for the +.B SVGALIB_DEFAULT_MODE +environment variable to set the +.BR vga_getdefaultmode (3). + +Here are the predefined values for +.IR mode . +.SS Text mode +.BR TEXT (0) +restores textmode and falls back to ordinary text console handling. All other calls switch to a +graphics mode. You should set this mode prior to exiting an svgalib application. +.SS VGA compatible graphics modes +In general, for all modes following, the first number is the amount of x pixels, the second +the amount of y pixels, the third the number of colors, with shortcuts 32K, 64K, 16M, 16M4 +for 32768, 65536, and 1677721. Those with 2 or more than 256 colors use fixed color mappings +(either black and white or some RGB true/high color) the others make use of a color lookup +table. + +Memory layout for the VGA modes is weird. Too weird to be explained here, but you can check +the usual VGA literature. +.BR vga_setmodeX (3) +has a short explanation which is valid for all 256 color modes. + +.BR G320x200x16 (1), +.BR G640x200x16 (2), +.BR G640x350x16 (3), +.BR G640x480x16 (4), +.BR G320x200x256 (5), +.BR G320x240x256 (6), +.BR G320x400x256 (7), +.BR G360x480x256 "(8), and " +.BR G640x480x2 (9) + +.SS Basic SVGA modes +These use linear 256 color memory layouts similar to +.BR G320x200x256 . + +.BR G640x480x256 (10), +.BR G800x600x256 (11), +.BR G1024x768x256 "(12), and " +.BR G1280x1024x256 (13) + +.SS High color SVGA modes +These also use linear memory layouts, but for 32K & 64K each pixel occupies two bytes and +three for 16M. For 32K, each 16 bit word is divided into 555 bit portions refering to 5 +bit red, green, blue part. The most significant bit is ignored by the card. For 64K the +division is 565 allowing to specify green in a little bit more detail (Human eyes are more +sensitive to green. People joke this is because our ancestors lived in trees where light was +filtered through green leaves). + +For the 16M modes, from low to high addresses the 3 bytes are named BGR and specify the +blue, green, red parts of the pixel value. + +.BR G320x200x32K (14), +.BR G320x200x64K (15), +.BR G320x200x16M (16), +.BR G640x480x32K (17), +.BR G640x480x64K (18), +.BR G640x480x16M (19), +.BR G800x600x32K (20), +.BR G800x600x64K (21), +.BR G800x600x16M (22), +.BR G1024x768x32K (23), +.BR G1024x768x64K (24), +.BR G1024x768x16M (25), +.BR G1280x1024x32K (26), +.BR G1280x1024x64K "(27), and " +.BR G1280x1024x16M (28) + +.SS High resolutions with less color numbers. +Memory layout is probably one nibble per pixel, two pixels per byte in a linear fashion where +the most significant nibble is the left most pixel. + +.BR G800x600x16 (29), +.BR G1024x768x16 "(30), and " +.BR G1280x1024x16 (31) + +.SS Hercules emulation mode +Again check out the ordinary VGA literature for the memory layout. + +.BR G720x348x2 (32) + +.SS 32-bit per pixel modes +These are similar to 16M but each pixel uses four bytes. The first three are similar to +16M but the fourth is left empty and ignored by the VGA card (you can store own status there). + +This eases pixel address calculations on the screen and drawing operations. However, 1/3 more +data has to be moved to the screen. Experiments show that usually the higher memory bandwidth +used outweighs the effects of the simplified algorithms by far. + +.BR G320x200x16M32 (33), +.BR G640x480x16M32 (34), +.BR G800x600x16M32 (35), +.BR G1024x768x16M32 "(36), and " +.BR G1280x1024x16M32 (37) + +.SS Some more resolutions +It should by now be clear how the modes will look. + +.BR G1152x864x16 (38), +.BR G1152x864x256 (39), +.BR G1152x864x32K (40), +.BR G1152x864x64K (41), +.BR G1152x864x16M (42), +.BR G1152x864x16M32 (43), +.BR G1600x1200x16 (44), +.BR G1600x1200x256 (45), +.BR G1600x1200x32K (46), +.BR G1600x1200x64K (47), +.BR G1600x1200x16M "(48), and " +.BR G1600x1200x16M32 (49) + +.PP +The +.BR vgatest (6) +produces a list of supported modes for your hardware, prints some info on the modes and +allows you to try each of them. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_hasmode (3), +.BR vga_init (3), +.BR vga_modeinfo (3), +.BR vga_getcurrentmode (3), +.BR vga_getdefaultmode (3), +.BR vga_lastmodenumber (3), +.BR vga_getmodename (3), +.BR vga_getmodenumber (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setmodeX.3 b/doc/man3/vga_setmodeX.3 new file mode 100644 index 0000000..7c2c310 --- /dev/null +++ b/doc/man3/vga_setmodeX.3 @@ -0,0 +1,50 @@ +.TH vga_setmodeX 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setmodeX \- try to set Mode X-like memory organization +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setmodeX(void);" + +.SH DESCRIPTION +Try to enable Mode X-like memory organization for +256 color modes using up to 256K of memory like 320x200x256 +and 640x400x256. + +Modes like 320x240x256 etc. are Mode X-like by default. +.BR vga_modeinfo (3) +lists which modes have Mode X memory layout. + +A mode X like memory layout means that memory is organized in four pages +.RB ( set_page (3)) +and that the top most pixel 0,1,2,3 are the first pixel in pages 0,1,2,3. Pixels +4,5,6,7 are than the second pixels in pages 0,1,2,3. + +The other, packed pixel, mode will have pixel 0,1,2,3 as pixel 0,1,2,3 in page 0 and +so on. It will only use the next pages if the size of the first 64K page is exceeded. Most +SVGA 256 color modes work this way. + +This is not guaranteed to work. Probably a new mode should be defined +for planar 320x200x256. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_getmodeinfo (3), +.BR vga_setmode (3), +.BR vga_setpage (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setmousesupport.3 b/doc/man3/vga_setmousesupport.3 new file mode 100644 index 0000000..2f79a50 --- /dev/null +++ b/doc/man3/vga_setmousesupport.3 @@ -0,0 +1,52 @@ +.TH vga_setmousesupport 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setmousesupport \- enable mouse support +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setmousesupport(int " stat ); + +.SH DESCRIPTION +Set mouse support; 0 disables (default), 1 enabled. If +enabled, the mouse is set up for screen resolution after a +mode set and you can use the various +.B mouse_ +functions. You can also use +.BR mouse_init (3) +the mouse in more flexibility. However, usually this is not the deal of the application. +The mouse is configured in +.I /etc/vga/libvga.config +and usually the application will just want to use that. + +The +.BR mousetest "(6), " eventtest (6) ", and " spin (6) +demos make use of the mouse functions. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR mousetest (6), +.BR mouse_close (3), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_init (3), +.BR mouse_setposition (3), +.BR mouse_setscale (3), +.BR mouse_setwrap (3), +.BR mouse_setxrange (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setpage.3 b/doc/man3/vga_setpage.3 new file mode 100644 index 0000000..2a7729c --- /dev/null +++ b/doc/man3/vga_setpage.3 @@ -0,0 +1,47 @@ +.TH vga_setpage 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setpage \- set the 64K SVGA page number +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setpage(int " page ); + +.SH DESCRIPTION +Usually SVGA cards have more than the 64K memory which suffice for an ordinary VGA. +However, the memory window mapped at +.BR vga_getgraphmem (3) +is only 64K bytes large. +.BR vga_setpage() +selects the +.IR page "-th" +64K memory chunk to be visible at position +.BR vga_getgraphmem (3). + +The +.BR fun "(6) and " vgatest (6) +show the basic use of this function. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR fun (6), +.BR vgatest (6), +.BR vga_getgraphmem (3), +.BR vga_setreadpage (3), +.BR vga_setwritepage (3), +.BR vga_setlinearaddressing (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setpalette.3 b/doc/man3/vga_setpalette.3 new file mode 100644 index 0000000..a804d01 --- /dev/null +++ b/doc/man3/vga_setpalette.3 @@ -0,0 +1,61 @@ +.TH vga_setpalette 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setpalette \- set a color in the color lookup table +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setpalette(int " index ", int " r ", int " g ", int " b ); + +.SH DESCRIPTION +Set the current color with index +.I index +to RGB values +.IR r ", " g ", and " b , +each in +the range 0 - 63. This function is only sensible in 16 or 256 color modes. It selects +which color all +.BI vga_setcolor( index ) +drawn pixels will actually refer to. + +Note that setting color 0 will modify the background color and that setting any color +in range 0 .. 15 will affect the operation of +.BR vga_setegacolor (3) . + +If the +.B VGA_CLUT8 +feature is set for the current mode with +.BR vga_ext_set (3) +the +.IR r ", " g ", and " b +values are in the range 0 - 255. + +The +.BR vgatest (6) +demo shows the basic use of this function. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_ext_set (3), +.BR vga_setpalvec (3), +.BR vga_getpalette (3), +.BR vga_getpalvec (3), +.BR vga_setrgbcolor (3), +.BR vga_setcolor (3), +.BR vga_setegacolor (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setpalvec.3 b/doc/man3/vga_setpalvec.3 new file mode 100644 index 0000000..0c6a03b --- /dev/null +++ b/doc/man3/vga_setpalvec.3 @@ -0,0 +1,70 @@ +.TH vga_setpalvec 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setpalvec \- sets colors in the color lookup table +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_setpalvec(int " start ", int " num ", int *" pal ); + +.SH DESCRIPTION +Sets the +.I num +colors starting with index +.I start +to the RGB values in +.IR *pal ". " *pal " contains " +.BI "3 * " num +integers which are the color values to set from first to last palette entry in +the order red, green, blue (always three consecutive entries +in +.I *pal +built a palette entry. + +Each color entry is in range +0 - 63. This function is only sensible in 16 or 256 color modes. It selects +which color all +.BI vga_setcolor( start ) +(and +.IB num " - 1" +following colors) +drawn pixels will actually refer to. + +Note that setting color 0 will modify the background color and that setting any color +in range 0 .. 15 will affect the operation of +.BR vga_setegacolor (3) . + +If the +.B VGA_CLUT8 +feature is set for the current mode with +.BR vga_ext_set (3) +the red, green, and blue values are in the range 0 - 255. + +The function returns the value of +.IR num . + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vgatest (6), +.BR vga_ext_set (3), +.BR vga_setpalette (3), +.BR vga_getpalette (3), +.BR vga_getpalvec (3), +.BR vga_setrgbcolor (3), +.BR vga_setcolor (3), +.BR vga_setegacolor (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setreadpage.3 b/doc/man3/vga_setreadpage.3 new file mode 100644 index 0000000..df86969 --- /dev/null +++ b/doc/man3/vga_setreadpage.3 @@ -0,0 +1,57 @@ +.TH vga_setreadpage 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setreadpage \- set the 64K SVGA page number +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setreadpage(int " page ); + +.SH DESCRIPTION +Usually SVGA cards have more than the 64K memory which suffice for an ordinary VGA. +However, the memory window mapped at +.BR vga_getgraphmem (3) +is only 64K bytes large. +.BR vga_setreadpage() +selects the +.IR page "-th" +64K memory chunk to be visible for reads at position +.BR vga_getgraphmem (3). + +.BR vga_setwritepage (3) +allows a different 64K memory chunk to be modified by writes to this memory window. This +is a very useful feature for screen to screen pixmap copies. However, not all cards support +this in all graphics mode. Check +.BR vga_modeinfo (3) +for availability. Esp. as this feature can also not be used when in background mode. + +Of course, this function must be used in conjunction with +.BR vga_setwritepage (3) +but may not be used in conjunction with +.BR vga_setpage (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR fun (6), +.BR vgatest (6), +.BR vga_claimvideomemory (3), +.BR vga_getgraphmem (3), +.BR vga_modeinfo (3), +.BR vga_setpage (3), +.BR vga_setwritepage (3), +.BR vga_setlinearaddressing (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_setrgbcolor.3 b/doc/man3/vga_setrgbcolor.3 new file mode 100644 index 0000000..e4b40df --- /dev/null +++ b/doc/man3/vga_setrgbcolor.3 @@ -0,0 +1,43 @@ +.TH vga_setrgbcolor 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setrgbcolor \- set the current color +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setrgbcolor(int " r ", int " g ", int " b ); + +.SH DESCRIPTION +Set the current color to RGB values r, g, and b, each in +the range 0-255. Does not make sense in 256 or less color modes. Use +.BR vga_setcolor (3) +there. The color is used by +.BR vga_drawpixel (3) +and +.BR vga_drawline (3). + +The +.BR fun "(6) and " vgatest (6) +demos show the basic use of this function. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR fun (6), +.BR vgatest (6), +.BR vga_drawpixel (3), +.BR vga_drawline (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_settextmoderegs.3 b/doc/man3/vga_settextmoderegs.3 new file mode 100644 index 0000000..c6af4bb --- /dev/null +++ b/doc/man3/vga_settextmoderegs.3 @@ -0,0 +1 @@ +.so man3/vga_gettextmoderegs.3 diff --git a/doc/man3/vga_setwritepage.3 b/doc/man3/vga_setwritepage.3 new file mode 100644 index 0000000..0ae1797 --- /dev/null +++ b/doc/man3/vga_setwritepage.3 @@ -0,0 +1,57 @@ +.TH vga_setwritepage 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_setwritepage \- set the 64K SVGA page number +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_setwritepage(int " page ); + +.SH DESCRIPTION +Usually SVGA cards have more than the 64K memory which suffice for an ordinary VGA. +However, the memory window mapped at +.BR vga_getgraphmem (3) +is only 64K bytes large. +.BR vga_setwritepage() +selects the +.IR page "-th" +64K memory chunk to be visible for writes at position +.BR vga_getgraphmem (3). + +.BR vga_setreadpage (3) +allows a different 64K memory chunk to be modified by reads from this memory window. This +is a very useful feature for screen to screen pixmap copies. However, not all cards support +this in all graphics modes. Check +.BR vga_modeinfo (3) +for availability. Esp. as this feature can also not be used when in background mode. + +Of course, this function must be used in conjunction with +.BR vga_setreadpage (3) +but may not be used in conjunction with +.BR vga_setpage (3). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR fun (6), +.BR vgatest (6), +.BR vga_getgraphmem (3), +.BR vga_claimvideomemory (3), +.BR vga_modeinfo (3) +.BR vga_setpage (3), +.BR vga_setreadpage (3), +.BR vga_setlinearaddressing (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_showcursor.3 b/doc/man3/vga_showcursor.3 new file mode 100644 index 0000000..daf561f --- /dev/null +++ b/doc/man3/vga_showcursor.3 @@ -0,0 +1,47 @@ +.TH vga_showcursor 3 "23 June 2001" "Svgalib (>= 1.9.6)" "Svgalib User Manual" +.SH NAME +vga_showcursor \- show / hide mouse cursor +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_showcursor(int show);" + +.SH DESCRIPTION +if +.B show +== 0, hides the cursor. + +if +.B show +== 1, shows the cursor. + +if +.B show +== 2, hides the cursor only if a software cursor is in use. + +.SH NOTES +The +.B show +== 2 case is needed, since drawing over the software cursor is not allowed. This means +that when the program needs to draw and can not be sure that the cursor is not overwritten, +it needs to hide the cursor before drawing. This might cause the cursor to flicker. If the +cursor is hidden by calling +.B vga_showcursor(2) +(instead of +.B vga_showcursor(0) +), then hardware cursor will not flicker. + +.SH SEE ALSO + +.BR svgalib (7), +.BR mouse_init (3), +.BR vga_selectcursor (3), +.BR vga_initcursor (3), +.BR vga_setcursorposition (3), +.BR vga_setcursorimage (3), + +.SH AUTHOR + +This manual page written by Matan Ziv-Av . + diff --git a/doc/man3/vga_unlockvc.3 b/doc/man3/vga_unlockvc.3 new file mode 100644 index 0000000..433f5a7 --- /dev/null +++ b/doc/man3/vga_unlockvc.3 @@ -0,0 +1,34 @@ +.TH vga_unlockvc 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_unlockvc \- re-enables virtual console switching +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_unlockvc(void);" + +.SH DESCRIPTION +Re-enables virtual console switching. +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR bg_test (6), +.BR vga_lockvc (3), +.BR vga_oktowrite (3), +.BR vga_runinbackground (3), +.BR vga_runinbackground_version (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_waitevent.3 b/doc/man3/vga_waitevent.3 new file mode 100644 index 0000000..8b954af --- /dev/null +++ b/doc/man3/vga_waitevent.3 @@ -0,0 +1,161 @@ +.TH vga_waitevent 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_waitevent \- wait for various I/O events +.SH SYNOPSIS + +.B "#include " +.br +.B "#include " +.br +.B "#include " +.br +.B "#include " + +.BI "int vga_waitevent(int " which ", fd_set *" input ", fd_set *" output +.BI ", fd_set *" except ", struct timeval *" timeout) + +.SH DESCRIPTION +This is the only function allowing you to wait for keyboard +AND mouse events. It is based on the +.BR select (2) +library function, +so for deep understanding of +.B vga_waitevent() +look at +.BR select (2) +as well. + +.I which +can be 0 or logical ored together from +.BR VGA_MOUSEEVENT " and " VGA_KEYEVENT . +If you are interested in waiting for file descriptors having +input available or being ready for new write data or being +in an exceptional condition (urgent data arrived on a TCP +stream) set the corresponding bits in the +.B fd_set +structures passed (see +.BR select (3)). +If you want +.B vga_waitevent() +to return after a timeout value pass a +.B struct timeval +with the desired value. If you are not interested in the +corresponding events you may pass +.B NULL +for any of the pointers. + +If +.B NULL +is passed for +.IB "timeout " vga_waitevent() +will not time out but block until any of the other events occurs. +If the integer returned is < 0 an error occurred. Check the global +variable +.B errno +for details. If a value >= 0 is returned it is a bitmask constructed using +.BR VGA_MOUSEEVENT " and " VGA_KEYEVENT +to show which of these events occured. + +If any of these two occured the appropriate update functions +are already called by +.BR vga_waitevent() . vga_waitevent() +operates in raw as well as non-raw keyboard +mode. In the latter case use +.BR vga_getch (3) +not +.BR vga_getkey (3) +to read the newly arrived keys. + +Any of the file related conditions being met will be signalled +by setting exactly the bits for files that met the conditions +in the corresponding +.B fd_set +structures. If a +.RB non- NULL +.I timeout +is passed the remaining time is written into it on return. +If it is 0 a timeout occured. (again: cf. +.BR select (2)) +Therefore, depending on context, +.BR vga_waitkey (3) +may return 0 if only special, non svgalib, events occured. + +.SH EXAMPLES +If you want to wait blocking for a keypress OR a mouse event use: +.B vga_waitevent(VGA_MOUSEEVENT | VGA_KEYEVENT, NULL, NULL, NULL, NULL); + +If you want to wait for a keypress OR a mouse event but +non-blocking use: + +.B "#include " +.br +.B "#include " +.br +.B "#include " +.br +.B "#include " + +.B struct timeval timeout; +.br +.B timeout.tv_sec = 0; +.br +.B timeout.tv_usec = 0; +.br +.B vga_waitevent(VGA_MOUSEEVENT | VGA_KEYEVENT, NULL, NULL, NULL, &timeout); + +You could do a similar thing by just calling + +.B mouse_update(); +.br +.B keyboard_update(); + +though. There is no such counterpart for the first example. + +Finally, there is a very nice +.BR eventtest (6) +demo showing most capabilities of +.BR vga_waitevent() . + +.SH BUGS +This function was introduced in 1.2.10. Unfortunately there was a typo in the first +implementation which broke the case where +.I input +was +.BR NULL . +Though fixed in 1.2.11 for optimal portability pass an empty +.B fd_set +instead of +.B NULL +as first argument. + +When not running in background mode, that is, the svgalib applcation is suspended +while the VC is switched away, it seems +.B vga_waitevent +gets stuck and does no longer timeout. It is not clear if this is an svgalib bug, kernel +bug or general problem. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR eventtest (6), +.BR mouse_getposition_6d (3), +.BR mouse_getx (3), +.BR mouse_update (3), +.BR mouse_waitforupdate (3), +.BR vga_getkey (3), +.BR vga_getch (3) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_waitretrace.3 b/doc/man3/vga_waitretrace.3 new file mode 100644 index 0000000..d19859c --- /dev/null +++ b/doc/man3/vga_waitretrace.3 @@ -0,0 +1,37 @@ +.TH vga_waitretrace 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_waitretrace \- wait for vertical retrace. +.SH SYNOPSIS + +.B "#include " + +.BI "void vga_waitretrace(void);" + +.SH DESCRIPTION +Wait for vertical retrace, that is when the video beam goes dark and returns from the +bottom line to the top line. Useful to synchronize animation with +monitor refresh. + +However, Linux is a multiuser OS, thus some time might have passed already when the +function returns. Also, not all cards support this in all modes (or with more or +less good results). + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR scrolltest (6), + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man3/vga_white.3 b/doc/man3/vga_white.3 new file mode 100644 index 0000000..ab95f51 --- /dev/null +++ b/doc/man3/vga_white.3 @@ -0,0 +1,49 @@ +.TH vga_white 3 "27 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vga_white \- return the color white in the current screen resolution +.SH SYNOPSIS + +.B "#include " + +.BI "int vga_white(void);" + +.SH DESCRIPTION +.B vga_white() +returns the color white in the current screen resolution as it would be set with +.BR vga_setcolor (3) +or written directly into the screen. + +In high color modes it is always clear how white is set with +.BR vga_setrgbcolor (3). +In the other modes you need +.BR vga_white() . + +However, it only knows about the default palette. If you change it with one of the palette +functions the function will not know about it. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_init (3), +.BR vga_setmode (3), +.BR vga_setpalette (3), +.BR vga_setpalvec (3), +.BR vga_getpalette (3), +.BR vga_getpalvec (3), +.BR vga_setcolor (3), +.BR vga_setrgbcolor (3), +.BR vga_setegacolor (3) +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced function as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man5/libvga.config.5 b/doc/man5/libvga.config.5 new file mode 100644 index 0000000..4846367 --- /dev/null +++ b/doc/man5/libvga.config.5 @@ -0,0 +1,1332 @@ +.TH libvga.config 5 "19 December 1998" "Svgalib 1.3.1" "Svgalib User Manual" +.SH NAME +libvga.config, svgalibrc \- the svgalib configuration file +.SH DESCRIPTION +The svgalib configuration is usually located in +.I /etc/vga/libvga.config +though one can reconfigure this location when recompiling svgalib. + +In the configuration file, everything between a +.B # +and the end of the line is ignored. Empty lines are also +ignored. Since the driver you will use may not know all config options +here, unknown commands are silently ignored. Please think of that when +something does not work as you expect. I know this is a nuisance +because misformed configuration statements do not cause +errors. Multiple commands are allowed in one line, and commands can +exceed lines. + +Actually, svgalib simply reads a list of whitespace separated tokens +from the file until it finds one it knows and it then assumes the +following tokens to be arguments of that command until one is +encountered which may not be an argument. + +New style options are in general case insensitive whereas the old style +options are case sensitive. The old style options are included to +allow for old config files still being used. For completeness they +are documented in the +.B OBSOLETE COMMANDS +section. You should not use them anymore. + +In addition, +.BR svgalib (7) +parses the files +.I ~/.svgalibrc +and the file given in the environment variable +.BR SVGALIB_CONFIG_FILE . + +Finally, the contents of the environment variable +.B SVGALIB_CONFIG +are parsed like the +files before. + +Configuration commands which control hardware settings that might cause +harm to your hardware are called +.BR privileged . +By default the +.B privileged +commands can only be used in the +main configuration file +.I /etc/vga/libvga.config +for safety (s.t. a non root user can not cause any harm to your hardware by +misconfiguring +.BR svgalib (7)). + +Enable them in the other locations as well with the command +.B overrideenable +in the main config file. +.B BEWARE! +This allows every user to change the monitor and clocks (and +other configs) and thus damaging the hardware. I +.B strongly +discourage the use of +.B overrideenable +except for debugging/testing purposes. + +.SH REQUIRED CONFIGURATION +Please do not allow the vastness of options to confuse you. Generally +svgalib uses well choosen defaults and is able to autodetect +everything. Thus generally you don't need to specify much. When +installing svgalib it provides a sample +.I /etc/vga/libvga.config +file which contains most of the required configuration. Just edit +it to your needs. + +Generally you only need to use: +.TP +.B mouse +To specify if you use anything else then a Microsoft compatible mouse. +.TP +.B mdev +If the mouse device file is +.B not +.I /dev/mouse +which is generally a symbolic link to the actual mouse device +file. You will usually need to use this command if you want to use the +SpaceTec Spaceball device (which is not your usual mouse). + +.TP +.BR setRTS ", " clearRTS ", " leaveRTS ", " setDTR ", " clearDTR ", and " leaveDTR +if your mouse needs it to enter your desired mouse protocol. +.TP +.BR monitor ", or (better) " HorizSync " and " VertRefresh +to specify the capabilities of your monitor. + +.SS If you use the EGA chipset driver +.TP +.BR monotext " or " colortext +to specify if your EGA card is in monochrome or color configuration. +.SS If you use the Mach32 chipset driver +You should consider reading +.BR svgalib.mach32 (7). +.TP +.BI "Clocks " "clock1 clock2 clock3 " ... +to specify the Mach32 clocks. This is mandatory. However, if you omit it. svgalib +will autodetect clocks and modify your +.I /etc/vga/libvga.config +file and abort. After this, every svgalib application started will find the proper +.B Clocks +command. +.TP +.B mach32eeprom /etc/vga/mach32.eeprom +is recommended to avoid slowish reads of the Mach32 EEPROM which will also cause annoying +screen flickering. +.SS If you use the Mach64 chipset driver +.TP +.B Chipset Mach64 +if you want to use the experimental pre-alpha driver +.SS If you use the S3 chipset driver +I don't have much knowledge on the S3, but it seems to me that you need: + +.TP +.BI Clocks " clock1 clock2 " ... +to specify the clocks (take them from your Xfree86 configuration). +.PP +or +.TP +.BI "ClockChip icd2061a " number +if you have an Icd2061a clockchip. +.TP +.BI "Ramdac " chipname +if your Ramdac is not detected properly. +.TP +.BI "Dacspeed " speed +if the default choosen is not right (probably too restrictive). +.PP +The remaining options are really only to be used in case of problems +which you'll not generally encounter. +.SS If you use the VESA chipset driver +.TP +.BR VesaText +forces the driver to set 80x25 text mode, before any standard vga mode +setting. Fixes text mode restoring with many cards, as well as standard +VGA modes. +.TP +.BR VesaSave +selects the bitmap to save and restore, using VESA functions. see VESA +documentation for bits' meanings. The default is 1110 (=14) which is +good for most cards, but some give better results with other numbers. + +.SH GENERAL OPTIONS (HANDLED BY THE MAIN MODULE) +.SS Mouse configuration +.TP +.BI "mouse " mousetype +where +.I mousetype +is one of: +.BR Microsoft ", " MouseSystems ", " MMSeries ", " Logitech ", " Busmouse ", " PS2 ", " +.BR MouseMan ", " gpm ", " Spaceball ", " none ", " IntelliMouse ", or " IMPS2 . +.I mousetype +can also be a number +.RB ( 0 " - " 9 ") for the keywords " Microsoft " - " none . + +.B gpm +allows for (hopefully) peaceful interaction with gpm, +.B Spaceball +enables support for the 6-axes Spacetec Spaceball mouse (well, probably more like a +trackball), +.B IntelliMouse +and +.B IMPS2 +refer to the Microsoft IntelliMouse or Logitech MouseMan+, where +.B IntelliMouse +is for serial port and +.B IMPS2 +for such a mouse on the PS/2 port. + +Note that it is not possible to specify the Microsoft IntelliMouse or Logitech MouseMan+ +by a number. This is due to historical and compatibility reasons. + +.TP +.B mouse_override +This command is only available if +.B ALLOW_MOUSE_OVERRIDE +was set in +.I Makefile.cfg +when svgalib was compiled (which is the default). + +If given, svgalib ignores +any mouse type the program specifies but uses the type +configured with the +.B mouse +command. + +For example, DOOM does not recognize +.B MouseMan +as a valid +mouse type and defaults the mouse type to +.BR MouseSystems. +This command allows to make svgalib ignore whatever DOOM specifies and use +.B MouseMan +anyway. + +.TP +.BI "mdev " mousedevice +Usually +.I /dev/mouse +(the default) will be a link to the mouse device. +However, esp. with the Spacetec Spaceball you may +want to specify a different device for +.BR svgalib (7) +to use: + +.BR "mdev /dev/ttyS0 " "# mouse is at /dev/ttyS0" + +.PP +Some multiprotocol mice use the state of RTS and DTR to find out which +protocol to enable: + +.TP +.B setRTS +set the RTS wire. +.TP +.B clearRTS +clear the RTS wire. +.TP +.B leaveRTS +leave the RTS wire alone (default) (Wire is usually set) +.TP +.B setDTR +set the DTR wire. +.TP +.B clearDTR +clear the DTR wire. +.TP +.B leaveDTR +leave the DTR wire alone (default) (Wire is usually set) + +.PP + +For example my mouse can emulate Microsoft and MouseSystems. +It needs a low RTS to go into MouseSystems mode. Thus I use: + +.B mouse MouseSystems clearRTS + +Still I could just use +.B mouse Microsoft +and use the mouse with that +protocol.. But then only 2 buttons instead of 3 are supported (not +that I know many svgalib programs that uses more than 2 buttons.) + +Other mice might need +.B clearDTR +as well or one set and clear. Try yourself. + +Note: Having crtscts handshake enabled on the mouse tty may interfer with this +options. Do not do that. + +Finally, a special goodie for wheel mice: + +.TP +.BI "mouse_fake_kbd_event " upscancode " " downscancode +sends a fake keyboard event to the program when the +wheel on a Microsoft IntelliMouse, Logitech MouseMan+, or similar wheel +mouse is turned. + +The up and down scancodes are the scancodes of the keys to simulate when +the wheel is turned up and down, respectively. + +The following can be specified for the scancodes: letters +.RB ( A - Z "), numbers (" 0 - 9 ), +.RB "function keys (" F1 - F12 ), +or any of the following - +.BR ESCAPE ", " MINUS ", " +.BR EQUAL ", " BACKSPACE ", " TAB ", " BRACKET_LEFT ", " BRACKET_RIGHT ", " ENTER ", " LEFTCONTROL ", " +.BR SEMICOLON ", " APOSTROPHE ", " GRAVE ", " LEFTSHIFT ", " BACKSLASH ", " COMMA ", " PERIOD ", " SLASH ", " +.BR RIGHTSHIFT ", " KEYPADMULTIPLY ", " LEFTALT ", " SPACE ", " CAPSLOCK ", " NUMLOCK ", " SCROLLLOCK ", " +.BR KEYPAD7 ", " CURSORUPLEFT ", " KEYPAD8 ", " CURSORUP ", " KEYPAD9 ", " CURSORUPRIGHT ", " KEYPADMINUS ", " +.BR KEYPAD4 ", " CURSORLEFT ", " KEYPAD5 ", " KEYPAD6 ", " CURSORRIGHT ", " KEYPADPLUS ", " KEYPAD1 ", " +.BR CURSORDOWNLEFT ", " KEYPAD2 ", " CURSORDOWN ", " KEYPAD3 ", " CURSORDOWNRIGHT ", " KEYPAD0 ", " +.BR KEYPADPERIOD ", " KEYPADCENTER ", " RIGHTCONTROL ", " CONTROL ", " KEYPADDIVIDE ", " +.BR PRINTSCREEN ", " RIGHTALT ", " BREAK ", " BREAK_ALTERNATIVE ", " HOME ", " CURSORBLOCKUP ", " +.BR PAGEUP ", " CURSORBLOCKLEFT ", " CURSORBLOCKRIGHT ", " END ", " CURSORBLOCKDOWN ", " PAGEDOWN ", " +.BR INSERT . + +Note that this option has no effect unless the IntelliMouse or IMPS2 mouse +type is used (see above). Also note that the simulated keypresses are +instantaneous, so they cannot be used for functions that require a key to +be held down for a certain length of time. + +This example simulates a press of the left bracket ([) when the wheel is +turned up and a press of the right bracket (]) when the wheel is turned +down (good for selecting items in Quake II): + +.B mouse_fake_kbd_event BRACKET_LEFT BRACKET_RIGHT + +.PP +.SS +Mouse acceleration + +Svgalib versions 1.3.0 and later use the following commands to control the +logarithmic +mouse acceleration: +.RS +.TP +.B mouse_force +If given, force use of input parameters even if they seem strange. +.TP +.BI mouse_maxdelta " " +Set max delta BEFORE acceleration. +.TP +.BI mouse_accel_maxdelta " " +Set max delta AFTER acceleration. +.TP +.BI mouse_accel_thresh " " +Set acceleration threshold. +.TP +.BI mouse_accel_power " " +Set input variable for power mode. +.TP +.BI mouse_accel_mult " " +Set acceleration factor. +.TP +.BR mouse_accel_type " {" 0 | off | normal | power | linear "}" +Set the type of acceleration. The following strings are valid values: +.RS +.TP +.BR 0 " or " off +No acceleration. +.TP +.B normal +No acceleration while delta is less than +.B mouse_accel_thresh +but multiplied by +.B mouse_accel_mult +if more. +.br +Originally done by Mike Chapman . +.TP +.B power +The acceleration factor is a power function of delta until +it reaches +.B mouse_accel_mult +After that it's a simple +multiplication. Basically it's like the normal mode but the +acceleration factor grows as you move your mouse faster and +faster, not just turns in and out. If the acceleration factor +reaches +.B mouse_accel_mult +it turns into a plain multiplication. + +Threshold has the same meaning as in normal mode. +The one I use for *uaking... :) + +It is calculated like this: + +if (abs(dx) > 1) /* to prevent losing resolution */ +.br + dx = (abs(dx) >= +.br +.B " " mouse_accel_thresh +) ? +.br + (float)dx * +.br +.B " " mouse_accel_mult +: +.br + (float)dx * +.br + m_accel_powertable[abs(dx)]; +.TP +.B +linear +The acceleration factor grows linear with the delta until it +reaches +.BR mouse_accel_thresh . +After that it is a simple mutiplication. +(I know that it can be done with setting +.B mouse_accel_power +to 1, but +it was one minute to implement... and uses no memory... and...) + +It is calculated like this: + +if (abs(dx) > 1) +.br + dx = (abs(dx) >= +.br +.B " " mouse_accel_thresh +) ? +.br + (float)dx * +.br +.B " " mouse_accel_mult +: +.br + (float)dx * abs(dx) * +.br +.B " " mouse_accel_mult +/ +.br +.B " " mouse_accel_thresh +; +.RE + +The enhanced acceleration was done +by 101 (Attila Lendvai) <101@kempelen.inf.bme.hu> +.RE + +.SS Joystick configuration +As of now, svgalib supports up to four joystick devices. You must have joystick support in your +kernel to support this. + +.TP +.BI "joystick0 " device +sets the device name to use for joystick 0. The commands +.BR joystick1 ", " joystick2 " and " joystick3 +configure the other joysticks. By default the names +.IR /dev/js0 ", " /dev/js1 ", " /dev/js2 " and " /dev/js3 +are used. + +.SS Keyboard configuration +.TP +.BI kbd_fake_mouse_event " scancode " [ flag(s) "] " command " [" argument ] +, as it says, sends a fake mouse event to the program. +.I Scancode +is a raw scancode as you can find them in +.IR . + +.IP +Supported +.I flag(s) +are: +.RS +.TP +.B down +trigger event when the key is pressed (default). +.TP +.B up +the opposite. +.TP +.B both +trigger in both case, if pressed or released. +.TP +.B repeat +repeat events if the key is kept pressed (off by default). +.RE + +.IP +Supported commands are: +.RS +.TP +.BR delta [ xyz ] +send a fake delta event as if you have moved your +mouse. If the +.I parameter +is +.BR off " or " on +it will turn off/on the respective mouse axis (requires a +.IR parameter , +of course) +.TP +.BR button [ 123 ] +send a fake event that the mouse button is pressed +or released as given by the +.I parameter +.RB ( pressed " or " released ) +.RE + +.IP +Here are some examples: + +This is one I use in *uake: it turns around, looks down a bit and when the +key is released it does the opposite, so it gets back to the starting state. +With this one and the help of a rocket you can fly though the whole map :) +(Scancode 28 is +.BR ): + +.B " " kbd_fake_mouse_event 28 both deltax 8182 +.br +.B " " down deltay -1500 +.br +.B " " up deltay 1500 + +This one will switch off the y axis of the mouse while the key +.B +is kept pressed. + +.B " " kbd_fake_mouse_event 97 down deltay off +.br +.B " " up deltay on + +This one is the same as if you were pressing the left mouse button. (But +if you move your mouse then the button state will reset even if you keep +.B +down...) + +.B " " kbd_fake_mouse_event 97 down button1 pressed +.br +.B " " up button1 released + +.B +NOTE: +This does only work when the keyboard is in raw keyboard mode! + +Yet another feature brought to you +by 101 (Attila Lendvai) <101@kempelen.inf.bme.hu> + +.TP +.B nosigint +This command disables generation of a +.B SIGINT +signal when +.B +is pressed. + +This works regardless of ordinary or raw keyboard mode (albeit the +hot key might be different from +.B +in the first case). + +.B +Note +that this is a very dangerous option. Disabling +.B SIGINT +will lock you in programs which can only by quit by +.BR ! +However, there were request for it for +Quake playing. +.TP +.BR sigint " (default)" +Enables generation of +.BR SIGINT . + +.SS Monitor configuration + +.PD 0 +.TP +.BI "HorizSync " "min_kHz max_kHz" +.TP +.BI "VertRefresh " "min_Hz max_Hz" +.PD +specifies the range of frequencies acceptable to your monitor. They +obsolete the +.B monitor +settings below, and this shouldn't be used if +.BR HorizSync " and " VertRefresh " are defined. Examples:" + +.B HorizSync 31.5 35.5 +.br +.B VertRefresh 50 70 + +.TP +.BI monitor " monitor_class" +where +.I monitor_class +is a digit +.BR 0 " - " 6 +or the maximal horizontal frequency in kHz. Examples: + +.BR "monitor 0" " # Max horizontal sync is 31.5 kHz" +.br +.BR "monitor 1" " # Max horizontal sync is 35.1 kHz" +.br +.BR "monitor 2" " # Max horizontal sync is 35.5 kHz" +.br +.BR "monitor 3" " # Max horizontal sync is 37.9 kHz" +.br +.BR "monitor 4" " # Max horizontal sync is 48.3 kHz" +.br +.BR "monitor 5" " # Max horizontal sync is 56.0 kHz" +.br +.BR "monitor 6" " # No restrictions." + +For your convenience you may specify the max horizontal sync explicitly. The +correct class will the be chosen. You may use floats consisting of digits +and a decimal point for this too: + +.BR "monitor 40.0" " # equivalent to monitor 3" + +This command is +.BR privileged . + +.SS Mode timings +It is now possible to define modetimings for some cards (see the info on your card +in +.BR svgalib (7)). +The syntax is: + +.TP +.BI "modeline " "label pxcl HDsp HSS HSE HTot VDsp VSS VSE VTot flags +.RS +.TP +.IR "label " string +(ignored by svgalib) +mainly there to be compatible with XF86Config. +I use the format "Width x Height @ Vert.Refresh", but that's +just personal taste... +.TP +.IR "pxcl " float +the pixel clock in MHz + +.PD 0 +.TP +.IR HDsp +.TP +.IR "VDsp " integer +size of the visible area (horizontal/vertical) +.PD + +.PD 0 +.TP +.IR HSS +.TP +.IR "VSS " integer +Sync start (horizontal/vertical) +.PD + +.PD 0 +.TP +.IR HSE +.TP +.IR "VSE " integer +Sync end (horizontal/vertical) +.PD + +.PD 0 +.TP +.IR HTot +.TP +.IR "VTot " integer +Total width/height (end of back porch) +.PD + +.TP +.IB "flags " "+hsync -hsync +vsync -vsync interlace interlaced" +.B doublescan +Sync polarity, interlace mode +.RE + +Everything should be on one line. +The values for the horizontal timings must be multiples of eight. + +These are prefered over the default timings (if monitor and chipset +can handle them). +The format is identical to the one used by XFree86, but the label +following the modeline keyword is ignored by vgalib. + +Here some examples: + +.B modeline "640x480@100" 43 640 664 824 848 480 483 490 504 +.br +.B modeline "800x600@73" 50 800 856 976 1024 600 637 643 666 +.br +.B modeline "1024x768@75" 85 1024 1048 1376 1400 768 771 780 806 +.br + +.B IMPORTANT! +Not all drivers, that is SVGA cards, use the values. Only +drivers using timing.c. As of this writing, drivers using this feature are: +Ark, Cirrus, Chips & Technologies, Et6000, S3. + +The Mach32 driver provides a similar feature separately, you have to use +the +.B define +command described below. + +ET4000 (and to some extent EGA) allow one to use a binary file +created by some utility. All other chipset driver use predefined +timings that are hardcoded in register dumps within the drivers. See +.BR svgalib.et4000 (7) +for more information. + +.SS Chipset detection +Usually svgalib does a good job autodetecting your hardware. However, +if auto detection fails (or you want to fall back to a simpler driver, say VGA, +as a bug work around), you may force detection of your chipset with + +.TP +.BI "chipset " type +where +.I type +is (currently) one of: +.BR VGA ", " +.BR ET4000 ", " +.BR Cirrus ", " +.BR TVGA ", " +.BR Oak ", " +.BR EGA ", " +.BR S3 ", " +.BR ET3000 ", " +.BR Mach32 ", " +.BR GVGA6400 ", " +.BR ARK ", " +.BR ATI ", " +.BR ALI ", " +.BR Mach64 ", " +.BR C&T ", " +.BR APM ", " +.BR NV3 ", " +.BR ET6000 ", " +.BR VESA ", " +.BR MX ", " +.BR PARADISE ", and " +.BR RAGE . + +You can also specify a number in range +.B 1 " - " 22 +to specify the +.IB type "-th" +chipset type or +.B 0 +to enforce autodetection. + +Warning, incorrect settings may damage your hardware. +This command is +.BR privileged . + +.TP +.BI "chipset " "type param1 param2" +use this form if the size of memory or an additional configuration option is +misdetected. For example: + +.B chipset Mach32 0 2048 + +Note that always two integers have to be specified. Usually (Mach32) +the second parameter is the memory amount. Look at the *_init function +of the specific device driver sources or information on that type +of cards in +.BR svgalib (7). + +Note that there is a more convenient command +.B setuplinear +for enforcing specific memory-aperture configurations for Mach32 + +This command is +.BR privileged . + +.SS Specific options required for the EGA-driver. +.TP +.B monotext +Card is in monochrome emulation mode +.TP +.B colortext +Card is in color emulation mode + +This command is +.BR privileged . + +.SS RAMDAC configuration +Some chipsets (e.g. S3 and ARK) allow specifying a RAMDAC type. If +your RAMDAC is not autodetected, you can try specifying it: + +.PD 0 +.TP +.B Ramdac Sierra32K +.TP +.B Ramdac SC15025 +.TP +.B Ramdac SDAC +S3 SDAC +.TP +.B Ramdac GenDAC +S3 GenDAC +.TP +.B Ramdac ATT20C490 +AT&T 20C490, 491, 492 (and compatibles) +.TP +.B Ramdac ATT20C498 +AT&T 20C498 +.TP +.B Ramdac IBMRGB52x +IBM RGB524, 526, 528 (and compatibles) +.PD +.PP + +.B BEWARE! +The Mach32 driver features an own +.B ramdac +command (which is usually not required). If you have a Mach32, +see +.BR svgalib.mach32 (7). + +.TP +.BI "Dacspeed " speed +.I speed +is a floating point number in MHz (like in +.BR Dacspeed 40.0" ) +specifying the maximal allowable pixel clock of the Ramdac in use. Currently this +option is only supported by the S3 driver. The Mach32 driver supports +.BR maxclock8 ", " maxclock16 ", " maxclock24 ", and " maxclock32 +commands which have a similar effect. Nevertheless, the Mach32 has a very good idea +on the capabilities of the Ramdac in use. The settings are more intended to specify the +VGA memory bandwidth. + +.SS Pixel clocks +.TP +.BI "Clocks " "list of clock values as floats or ints" + +Some chipsets need a list of dot clocks for optimum operation. Some +includes or supports a programmable clock chip. You'll need to specify +them here. + +Fixed clocks example: (The following is just an example, get +the values for your card from +you X setup) + +.B Clocks 25.175 28.3 40 70 50 75 36 44.9 0 118 77 31.5 110 65 72 93.5 + +.B BEWARE! +The +.B Clocks +command for the Mach32 features only integer clocks. Please round your clocks to +the next integer data. The Mach32 only uses these values to check monitor +requirements and to compare the quality of modes. The rounding errors are of +no importance there as the difference in the resulting monitor timings is barely +measurable. See the Mach32 section below. +.TP +.B Clockchip ICD2061A +Configure for a programmable clockchip. +.B ICD2061A +is the only one supported right now. + +.SS Miscanellous options +.TP +.B security revoke-all-privs +Make sure it is impossible to regain root access +after +.BR vga_init (3) +was called. (default) +.TP +.B security compat +For compatibility to pre 1.2.11, do not close a security hole using saved uids. +.TP +.B verbose +Mach32: show messages while processing all info to build up a mode table. +.TP +.B quiet +Turn verbose messages off (default). +.TP +.B nolinear +Inhibit use of a linear mmaped frame buffer. +.TP +.B linear +Allow (not enforce!) use of a linear mmaped frame buffer. +.TP +.B overrideenable +Allow +.B privileged +commands outside the main configuration file. + +.SS Common options currently used by Mach32 only +Options that may be useful for all drivers, but currently are only supported +by Mach32 (Please read +.BR svgalib.mach32 (7) +if you use one): + +.TP +.BI "maxclock16 " maxclk +The maximum pixel clock to use for 16bpp modes. This is +used by Mach32 to find out which settings may be used for 16bpp modes. +the Mach32 default for this is 2000, thus it is effectively switched off. +.I maxclk +must be an integer. + +.TP +.BI "maxclock24 " maxclk +The maximum clock to use for 24bpp modes. (see above) +Experience showed that the Mach32 default 49 is good for my 2MB VRAM card. + +.TP +.BI "maxclock32 " maxclk +The same for 32bpp modes (24bpp with one fill byte for +faster memory access (not fully implemented (esp. for Mach32) yet). +Mach32 default (good for my VRAM card) is 39. + +.TP +.BI "maxclock8 " maxclk +Just for completeness the same for 8bpp modes (I doubt anyone needs it), default +is 2000 to disable this feature. + +.P +The +.B maxclock +commands are +.BR privileged . + +.TP +.BI "clocks " "list of clocks" +Sets the frequencies of the clocks the chips can +generate. Exactly 16 values have to be specified for mach32. +Use 0 to disable a specific clock. + +Note that the mach32 can divide clocks by 2. Thus there are actually 32 clocks +And you can also use the divided clocks in a define command. +On contrary to Xfree96 or the +.B clocks +command above only integers are allowed for Mach32. Simply round them to the nearest +integer. + +This line is mandatory for Mach32. If it is not there it will be auto detected +and added at the beginning of the config file. The program will then exit and +when you start it next, everything should be ok. + +Common clock values for Mach32: +.RS +.TP +Clock chip 18811-0: +.B clocks 43 49 92 36 50 56 0 45 +.br +.B " " 30 32 110 80 40 45 75 65 + +.TP +Clock chip 18811-1: +due to Xfree86 info valid for: Ultra pro ISA, Ultra pro EISA, +Ultra pro VLB(68800-3) + +.B clocks 100 126 92 36 50 56 0 45 +.br +.B " " 135 32 110 80 40 45 75 65 + +.TP +Clock chip 1881 (ICS2494): +due to Xfree86 info valid for: Ultra pro VLB (6880006) + +.B clocks 18 22 25 28 36 44 50 56 +.br +.B " " 30 32 37 39 40 0 75 65 +.RE +.IP +In my own correspondence with ATI they say every Mach32 would have a +18811-1, so it should be possible just to take the 18811-1 line. +However I have now reports of third party cards and motherboards with +on board Mach32 chips, so be careful. + +Please read +.BR svgalib.mach32 (7) +for additional info on clocks. + +The +.B clocks +command is +.BR privileged . + +.TP +.B variablelinelength +Sometimes a mode cannot be realized with the logical linelength = pixels in +a row * bytes per pixel. (definitely true for Mach32 800x600). The default behavior +of Mach32 is to adjust +.I xbytes +(see +.BR vga_getmodeinfo (3)) +in the info table appropriately. + +This command enforces this default operation and +adjusts +.I xbytes +appropriately, thus overriding the standard +svgalib mode. This may yield to problems with ..umm.. not well designed +applications. + +.TP +.B duplicatelinelength +Don't touch the standard mode but create an exact +copy, a dynamic mode, with the adjusted +.I xbytes +value. Expect noise at some +pixels in 800x600 for more than 256 colors on Mach32 when not using the dynamic +mode. + +.TP +.B strictlinelength +Same as above but delete the standard mode thus creating +the non conforming +.I xbytes +modes only as dynamic modes. + +.PP + +To enforce the standard linelength for non-conforming modes use +.B setlinelength +below. + +The +linelength +commands are +.BR "not privileged" . + +In the following commands a mode is specified with +.IR horz X vert X colors . +Valid settings for colors in the mach32 driver are: 256, 32K, 64K, 16M, 16M4. +16M4 is for the 16M colors with 32bpp modes. These are expected to support +slightly faster drawing. + +Examples: +.BR 640x480x256 ", " 1024x768x64K ", etc..." + +.TP +.BI "inhibit " mode1 " [" mode2 " " mode3 "...]" +Switch the specified SVGA-Modes off. For example: + +.B inhibit 800x600x32K 800x600x64K 800x600x16M + +disallows the maybe toasted mach32 800x600 modes. + +The +.B inhibit +command is +.BR "not privileged" . + +.TP +.BI "setlinelength " length " " mode1 " [" mode2 " " mode3 "...]" +Force the logical line length +.RI ( xbytes ) +in the given modes to length pixels (not bytes!). See also +.BR variablelinelength ", " strictlinelength ", and " duplicatelinelength +above. For example: + +.B setlinelength 800 800x600x32K 800x600x64K 800x600x16M + +sets the linelength, and thus +.IR xbytes , +for the +.B 800x600 +modes to the equivalent of 800 pixels. For Mach32 this will give badly +designed applications an 800x600 with which they can cope. However, +the Mach32 will generate a noisy video signal in some configurations. + +The +.B setlinelength +command is +.BR "not privileged" . + +.TP +.BI "define " mode1 " [" mode2 " " mode3 "...] " "clock horz_timing vert_timing flags" +where +.I clock +is a clock in MHz (as an integer! Has to be known by the driver. +(one of the set clocks, or the exact half of one)). Only clocks in a +.B clocks +command issued before the +.B define +can be used. + +You may use +.BI : n +to specify the +.IR n -th clock +.RI ( n " = 0 .. 31" +for mach32). + +.I horz_timing +is four integers: +.IR "hdisp h_sync_strt h_sync_wid h_total" . + +.I vert_timing +has the same format but for vertical. + +You may specify one or +more +.I flags +out of: +.BR Interlace ", " +vsync ", " -vsync ", " +hsync ", or " -hsync +to select +interlace mode and polarity of sync signals. This format is almost the same +Xfree uses, s.t. you may use their mode table and the modegen spreadsheet +package for mode creation. You simple need to round the clock to the next integer, +add the resolution instead of the timing name for Xfree and replace the +.B modeline +keyword with +.BR define . +Here is a 1024x768x256 mode as example: + +.B define 1024x768x256 80 1024 1024 1184 1312 +.br +.B " " 768 768 772 791 +vsync -hsync + +or + +.B define 1024x768x256 1024x768x32K 1024x768x64K +.br +.B " " :11 1024 1024 1184 1312 768 768 772 791 + +(yes any whitespace in a command is allowed, even a newline !) + +Both commands define the same timings (if the 11-th clock is 80) but +the first explicitly specifies the polarity of sync signals whereas +the second declares that these timings are also to be used for +a 32K and 64K mode. + +The +.B define +command is +.BR privileged . + +.PP +There is one really dangerous option (except faking clocks). Please +use it only if you are sure what you are doing. Wrong setup will +lead to multiple components accessing your bus at once and thus +to probable hardware damage: + +.TP +.BI setuplinear " address size" +Sets up a linear frame buffer at +.IR address " of size " size +(both are given in MB). If the values make sense (for example address <16MB for ISA cards) +the linear aperture is setup. Since the Mach32-driver auto detects configured +address itself, I strongly discourage use of this command. However I was +asked for it as some PCI mach32-cards didn't setup the linear aperture correctly. + +Please ensure that the address range from +.IR address " to " address " + " size +(exclusively) is not used +in your system. Obey that due to memory remapping for example 16MB Ram may +exceed the 16MB address limit. + +Valid Mach32 values for size are 1 and 4 (only 4 in PCI configurations), +.IR address " + " size +have to be below 16MB for ISA, 4GB for multiplexed PCI, +and 128MB else. Example: (my setup) + +.B setuplinear 64 4 + +for a 4MB linear frame buffer at address 0x4000000. + +It is also valid to specify +.BR "setuplinear 0 0" . +This will actually disable/de-configure any linear +frame buffer. Useful to disable mach32 aperture even if it is enabled +in the EEPROM. + +The +.B setuplinear +command is +.BR privileged . + +.TP +.BI "blit " "subcommand1 subcommand2" " ..." +This is a command to control the Mach32 support for oldstyle accelerator +functions. + +Valid +.IR subcommand s +are +.BR bit ", " fill ", " image ", and " hlinelist . +They enable support for the +corresponding blit functions. Preceed them with +.B no +to turn them off (no space after +.B no +allowed). Use +.B memimage +to emulate the +.B image +blit using a linearframebuffer, which is usually much faster for Mach32. +Use +.B nomemimage +to never use this emulation. On the Mach32 this emulation can be used in more resolutions than +the actual imageblit accelerator function. +Again order is vital! (esp. for the +.B *image +commands). + +As the Mach32 now has also new style +.BR vga_accel (3) +support there are now also the +.IR subcommand s: +.BR settrans ", " setrop ", " fillbox ", " screencopy ", " +.BR drawline ", " putimage ", " drawhlinelist ", " putbitmap ", " +.BR screencopymono ", " setmode ", " polyline ", " polyhline ", and" +.BR polyfillmode . +Which are also supported with a leading +.BR no . +They allow to control support for the subfunctions of +.BR vga_accel (3). +In addition, +.B memimage +emulation applies to +.B putimage +as well. + +Some examples: + +.RS +.TP +.B blit image nomemimage +Use IO-style imageblt where possible. Don't emulate it in any resolution. +.TP +.B +blit image memimage +Use emulated imageblt where possible. +.TP +.B +blit memimage image +Use IO-style imageblt where possible, and the emulation where possible in the remaining modes. +.TP +.B +blit noimage +Disable support for imageblt. +.RE +.IP + +Mach32 default is: + +.B blit bit fill image hlinelist settrans setrop +.br +.B " " fillbox screencopy drawline putimage +.br +.B " " drawhlinelist putbitmap screencopymono +.br +.B " " setmode polyline polyhline polyfillmode +.br +.B " " memimage + +The +.B blit +command is +.BR "not privileged" . + +.PP +The Mach32 has also a few intermediate debug options for low level timing adjust. +They are: + +.BI vfifo8 " number" +.br +.BI vfifo16 " number" +.br +.BI vfifo24 " number" +.br +.BI vfifo32 " number" +.br +.BI blank " number" +.br +.BI latch " number" + +There also options which are useful to support broken Mach32 cards or third +party hardware based on Mach32 which does not follow the ATI specifications +completely. For example: + +.B vendor ati +.br +.B misc_ctl keep-off +.br +.B svgaclocks 9 +.br +.B ramdac auto + +For details about these options see +.BR svgalib.mach32 (7). +All of them are +.BR "privileged" . + +.SH OBSOLETE COMMANDS +Very old svgalib versions used a different style configuration file. For compatibility, +svgalib can still parse these old options. Generally the options consist of one +character (case sensitive) followed by a number. Whitespace characters (space, tab, +newline) can be used after the characters +.BR m " and " M +and the number. + +The old svgalib versions actually allowed a new option character to follow a number immediately. +The current parser requires white space after the numbers. + +Of course, you should not use these cryptic forms anymore. The obsolete commands are: + +.TP +.BI m number +Specify the mouse type like +.BI mouse " number" +does. +.TP +.BI M class +Specify the monitor class like +.BI monitor " class" +does. +.TP +.BI C number +Force usage of the +.IR number -th +chipset driver from the list of supported drivers +.BR VGA "(1), " +.BR ET4000 "(2), " +.BR Cirrus "(3), " +.BR TVGA "(4), " +.BR Oak "(5), " +.BR EGA "(6), " +.BR S3 "(7), " +.BR ET3000 "(8), " +.BR Mach32 "(9), " +.BR GVGA6400 "(10), " +.BR ARK "(11), " +.BR ATI "(12), " +.BR ALI "(13), " +.BR Mach64 "(14), " +.BR C&T "(15), " +.BR APM "(16), " +.BR NV3 "(17), " +.BR ET6000 "(18), " +.BR VESA "(19), " +.BR MX "(20), " +.BR PARADISE "(21), and " +.BR RAGE (22). + +.B C0 +reenables auto detection of the chipset (default). + +.TP +.BI c flag +When using the EGA chipset driver, the card is in monochrome emulation mode for +.I flag += 0 and in color emulation mode for +.I flag += 1. +.SH FILES +.IR /etc/vga/libvga.config +.br +.IR /etc/vga/libvga.et4000 + +.SH SEE ALSO +.BR svgalib (7), +.BR svgalib.et4000 (7), +.BR svgalib.chips (7), +.BR svgalib.mach32 (7), + +.SH AUTHOR +The newstyle configuration file was first implemented and +documented by +Michael Weller . However, +other people added new features. + +Finally this page was edited by +Michael Weller . diff --git a/doc/man5/libvga.et4000.5 b/doc/man5/libvga.et4000.5 new file mode 100644 index 0000000..04b2dd2 --- /dev/null +++ b/doc/man5/libvga.et4000.5 @@ -0,0 +1 @@ +.so man7/svgalib.et4000.7 diff --git a/doc/man5/svgalibrc.5 b/doc/man5/svgalibrc.5 new file mode 100644 index 0000000..e36353a --- /dev/null +++ b/doc/man5/svgalibrc.5 @@ -0,0 +1 @@ +.so man5/libvga.config.5 diff --git a/doc/man6/accel.6 b/doc/man6/accel.6 new file mode 100644 index 0000000..43ea822 --- /dev/null +++ b/doc/man6/accel.6 @@ -0,0 +1,402 @@ +.TH accel 6 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +accel \- tests the new style svgalib accelerator interface +.SH SYNOPSIS + +.B accel + +.SH DESCRIPTION +Test new-style accelerated functions (As of this writing: Ark, Cirrus, Chips & +Technologies cards, and Mach32 only). +For other cards the demo will not work (well it will complain about missing accelerator +support). Don't worry about this. + +During the development of the Mach32 new style driver for 1.2.12, this demo was massively +extended to check the Mach32 functions. + +Upon startup it lists all supported SVGA modes and asks you to enter a number +identifying the mode to be tested. The supported subfunctions of +.BR vga_accel (3) +in this mode are listed and the demo instructs to press +.B +to start the demos. + +If supported, all drawing operations are performed in the background. + +Then the following tests are performed: +.SS Positioning tests +These tests were originally intended to check that the accelerator commands work on the +proper screen locations. The screen shows 12 (4 x 3) smaller areas with red crosses in the +corners. When everything is ok, the drawings should reach right in the corners of the crosses. + +A given card may not support all operations listed here. In that case the resp. test area +just shows the red crosses. For tests performed, the name of the test is printed below the +area. The tests are (from left to right, top to bottom): + +.IP 1. +A green box is drawn with +.BR vga_accel(ACCEL_FILLBOX) . +.IP 2. +A cross of green lines is drawn with +.BR vga_accel(ACCEL_DRAWLINE) . +.IP 3. +A linux pixmap just fitting into the crosses is drawn with +.BR vga_accel(ACCEL_PUTIMAGE) . +.IP 4. +A pixmap just fitting into the crosses is drawn into the red crosses (by +.BR vgagl (5) +which may or may not use the accelerator). The pixmap is then copied to a few lines/columns +below. Green crosses mark the intended destination position. +.IP 5. +Works like 3. but copies to an area above the origin. The accelerator must ensure that the +overlapping areas are handled non corrupting. Thus, watch that the copy operation is properly +performed. +.IP 6. +A green triangle is drawn above the top/left to bottom/right diagonal by use of +.BR vga_accel(ACCEL_DRAWHLINELIST) . +.IP 7. +Certain bitmaps are copied to the screen. In the corners you'll see the digits +.RS +.IP 0 +top/left, green on red. +.IP 1 +top/right, red on green. +.IP 2 +bottom/left, black on white. +.IP 3 +bottom/right, white on black. Note that some black border, not the digit will be aligned +to the red crosses. +.RE +.IP +Finally, a yellow wizard image is drawn into the center. + +The bit ordering for bitmaps is a bit weird. Please check that the digits are not mirrored or +flipped. +.IP 8. +This time bitmap transparency is tested by drawing wizard images onto the aforementioned +linux pixmap (left to right, top to bottom) in yellow, red, green, and cyan. The background +of the yellow wizard is masked out by a black border bitmap. +Note that the wizard will not reach into the red corners because the bitmap has some +(transparent) border. +.IP 9. +The text below this box is copied as a monochrome bitmap from the screen into the corners +listed under 7. in the same colors. +.IP 10. +Two green rectangles with an edge cut out from the bottom is drawn using +.BR vga_accel(ACCEL_POLYLINE) . There is an intended bug which draws the center of the +top line twice. If supported, the lower rectangle is drawn in cyan and with the xor +raster operation s.t. the buggy point is not drawn thus leaving a pin hole. +.IP 11. +.BR vga_accel(ACCEL_POLYHLINE) is used to draw some green lines which makes this area look +like a green box with a cut out, black M-style shape. +.IP 12. +A weird green polygon is filled in red with +.BR vga_accel(ACCEL_POLYFILLMODE) +using the techniques given in +.BR vga_accel (3). +This needs some offscreen memory. If VGA memory is tight in that resolution the test cannot +be performed. +.PP +After this screen, you'll have to hit +.B +to continue. +.SS Raster operations +Again, red cross bordered areas are drawn on the screen, this time for each of the supported +raster operations. For +.BR ROP_AND " and " ROP_XOR +the areas are filled in white first. + +Three overlapping boxes +.BR A ", " B ", " C +are drawn such that you see the following areas. + +.RB AAAAAA dddd BBBBBB +.br +.RB AAAAAA dddd BBBBBB +.br +.RB AAAAAA dddd BBBBBB +.br +.RB AAAA ee gggg ff BBBB +.br +.RB AAAA ee gggg ff BBBB +.br +.RB AAAA ee gggg ff BBBB +.br +.RB " CCCCCCCC" +.br +.RB " CCCCCCCC" +.br +.RB " CCCCCCCC" + +The pictures should show: +.IP 1. +Replace mode. A, B, C are red, green, blue. They just overlap, yielding +d - green and e, f, g - blue. +.IP 2. +The colors mix using +.B ROP_OR +(and a nice color table). The overlapping areas become the additive color mix: +d - yellow, e - magenta, f - cyan, and g - white. +.IP 3. +.B ROP_AND +is used. The background is filled white first, s.t. there is something in video memory +to and with non trivially. We have A, B, C in cyan, magenta, yellow and d, e, f, g +in blue, green, red, black. +.IP 4. +.B ROP_XOR +is used and the background filled white first too. A, B, C are red, green, blue again, but +the overlapping areas d, e, f, g become blue, green, red, white. +.IP 5. +.B ROP_INV +is used, s.t. A, B, C are all white and d, e, f, g become black, black, black, white. +Note that this is not done by using +.B ROP_XOR +and drawing A, B, C in white. Instead A, B, C are drawn in the usual + red, green, blue. However, the accelerator just inverts the memory contens. +.PP +If the accelerator supports raster operations for +.B ACCEL_DRAWHLINELIST +actually disks (well, ellipses) are drawn instead of boxes. +.PP +After this screen, you'll have to hit +.B +to continue. + +.SS Replace QuixDemo +If +.B ACCEL_DRAWLINE +is supported, a Quix like bouncing series of lines in varying colors is drawn. The lines +are removed from the screen by overdrawing them in black, thus erasing the dots and text +on the background. + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SS XOR Mode QuixDemo +As before, but this time all lines are drawn in +.B ROP_XOR +mode (if +.B ACCEL_DRAWLINE +supports raster operations). Thus the background will not be destroyed this time. + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SS FillBox Demo +The screen is +.BR ACCEL_FILLBOX +filled with a series of boxes of increasing colors. +In truei/high color modes you'll probably only see a series of varying blue tones (because these +are at the beginning of the color table and there are soo many of them). + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SS ScreenCopy Demo +Some random dots are drawn on the screen and thirds of the screen contents are moved +around using +.BR ACCEL_SCREENCOPY . + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SS Scroll Demo +Some random dots are drawn on the screen and moved one line up with +.BR ACCEL_SCREENCOPY . +In offscreen memory a new line is prepared which will be cleared by +.BR ACCEL_FILLBOX and move in from below. This test requires some offscreen and will not +be performed if video memory is very tight. + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SS FillBox with DrawHLineList Demo +Like the FillBox test, but no box fill is done but the screen is filled with a list of +horizontal lines drawn with +.BR ACCEL_DRAWHLINELIST . + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SS FillBox XOR Mode Demo +Like the FillBox test, but the XOR raster operation is used. + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SS PutBitmap Demo +The screen is filled with bitmasks consisting of tiny vertical lines alternating in red and +blue. + +The test lasts about 5 seconds and some statistics are printed to stdout. + +.SH SOME DATAPOINTS +Here is a list of speed listings for some cards. Please keep in mind that also the +calling overhead for the program is measured. This seems to be esp. true for the +QuixDemo. + +.SS "Results on a Cirrus GD5434-E with 2Mb:" +.TP +.B "640x480x256 60 Hz" +.br +FillBox: 200.3 Mpixels/s (200.3 Mbytes/s) +.br +ScreenCopy: 51.0 Mpixels/s (51.0 Mbytes/s) +.br +Scroll Demo: 50.5 Mpixels/s (50.5 Mbytes/s) +.br +FillBox XOR: 83.2 Mpixels/s (83.2 Mbytes/s) +.TP +.B "320x200x256 70 Hz" +.br +FillBox: 200.1 Mpixels/s (200.1 Mbytes/s) +.br +ScreenCopy: 52.3 Mpixels/s (52.3 Mbytes/s) +.br +Scroll Demo: 51.2 Mpixels/s (51.2 Mbytes/s) +.br +FillBox XOR: 87.1 Mpixels/s (87.1 Mbytes/s) +.TP +.B "640x480x32K 60 Hz" +.br +FillBox: 90.9 Mpixels/s (181.8 Mbytes/s) +.br +ScreenCopy: 23.1 Mpixels/s (46.3 Mbytes/s) +.br +Scroll Demo: 23.0 Mpixels/s (46.1 Mbytes/s) +.br +FillBox XOR: 37.2 Mpixels/s (74.5 Mbytes/s) +.TP +.B "640x480x16M (32-bit) 60 Hz" +.br +FillBox: 35.5 Mpixels/s (142.3 Mbytes/s) +.br +ScreenCopy: 9.3 Mpixels/s (37.3 Mbytes/s) +.br +Scroll Demo: 9.2 Mpixels/s (37.1 Mbytes/s) +.br +FillBox XOR: 14.6 Mpixels/s (58.6 Mbytes/s) + +.SS "On a Cirrus Logic 5426 VLB (50 MHz MCLK):" +.TP +.B "640x480x256 60 Hz" +.br +FillBox: 32.8 Mpixels/s (32.8 Mbytes/s) +.br +ScreenCopy: 16.4 Mpixels/s (16.4 Mbytes/s) +.br +Scroll Demo: 16.3 Mpixels/s (16.3 Mbytes/s) +.br +FillBox XOR: 16.5 Mpixels/s (16.5 Mbytes/s) +.TP +.B "640x480x32K 60 Hz" +.br +FillBox: 12.2 Mpixels/s (24.4 Mbytes/s) +.br +ScreenCopy: 6.1 Mpixels/s (12.2 Mbytes/s) +.br +Scroll Demo: 6.0 Mpixels/s (12.1 Mbytes/s) +.br +FillBox XOR: 6.1 Mpixels/s (12.2 Mbytes/s) + +.SS "Tweaked to 60 MHz MCLK:" +.TP +.B "640x480x256 60 Hz" +.br +FillBox: 42.1 Mpixels/s (42.1 Mbytes/s) +.br +ScreenCopy: 21.0 Mpixels/s (21.0 Mbytes/s) +.br +Scroll Demo: 20.9 Mpixels/s (20.9 Mbytes/s) +.br +FillBox XOR: 21.1 Mpixels/s (21.1 Mbytes/s) +.TP +.B "640x480x32K 60 Hz" +.br +FillBox: 16.7 Mpixels/s (33.5 Mbytes/s) +.br +ScreenCopy: 8.3 Mpixels/s (16.7 Mbytes/s) +.br +Scroll Demo: 8.3 Mpixels/s (16.7 Mbytes/s) +.br +FillBox XOR: 8.3 Mpixels/s (16.7 Mbytes/s) +.SS Results on a Mach32 EISA with 2Mb VRAM: +.TP +.B 1280x1024x256 60 Hz +Replace QuixDemo: 12.1 Klines/s (6.7 Mpixels/s or 6.7 Mbytes/s) +.br +Xor QuixDemo: 9.9 Klines/s (5.1 Mpixels/s or 5.1 Mbytes/s) +.br +FillBox: 75.4 Mpixels/s (75.4 Mbytes/s) +.br +ScreenCopy: 26.4 Mpixels/s (26.4 Mbytes/s) +.br +Scroll Demo: 28.7 Mpixels/s (28.7 Mbytes/s) +.br +FillBox with DrawHlineList: 73.1 Mpixels/s (73.1 Mbytes/s) +.br +FillBox XOR: 37.9 Mpixels/s (37.9 Mbytes/s) +.br +PutBitmap: 15.6 Mpixels/s (15.6 Mbytes/s) + +.TP +.B 1024x768x64K 72Hz +Replace QuixDemo: 12.3 Klines/s (5.2 Mpixels/s or 10.5 Mbytes/s) +.br +Xor QuixDemo: 9.0 Klines/s (5.1 Mpixels/s or 10.3 Mbytes/s) +.br +FillBox: 37.6 Mpixels/s (75.2 Mbytes/s) +.br +ScreenCopy: 13.2 Mpixels/s (26.4 Mbytes/s) +.br +Scroll Demo: 13.2 Mpixels/s (26.4 Mbytes/s) +.br +FillBox with DrawHlineList: 37.0 Mpixels/s (74.0 Mbytes/s) +.br +FillBox XOR: 18.9 Mpixels/s (37.8 Mbytes/s) +.br +PutBitmap: 15.2 Mpixels/s (30.5 Mbytes/s) + +.PP +You're encouraged to send in more data. +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_accel (3), +.BR threed (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +demo and most of its documentation is due to +Harm Hanemaayer . diff --git a/doc/man6/bg_test.6 b/doc/man6/bg_test.6 new file mode 100644 index 0000000..7bb6dc2 --- /dev/null +++ b/doc/man6/bg_test.6 @@ -0,0 +1,90 @@ +.TH bg_test 6 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +bg_test \- test the background mode of svgalib +.SH SYNOPSIS + +.BI "bg_test [" linear ] + +.SH DESCRIPTION +Tests the enhanced support of recent svgalibs to draw while +switched to the background. Draws a small centered white box +then waits until you switch to another vc. Draws some outer +box frame around it +.B while +background, which you can see +when you switch back to it. For obvious reasons, your version +of svgalib must have +.B BACKGROUND +support enabled (which is the +default as of this writing). +When finished, press any key to end +.BR bg_test . + +The demo uses a +.B G320x200x256 +mode or the one you set with +.BR SVGALIB_DEFAULT_MODE . + +If you specify the +.I linear +parameter the demo will use +.BR vgagl (7) +and +.BR vga_setlinearaddressing (3) +to test linear mode in background. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_runinbackground (3), +.BR threed (6), +.BR accel (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/buildcsr.6 b/doc/man6/buildcsr.6 new file mode 100644 index 0000000..3320be5 --- /dev/null +++ b/doc/man6/buildcsr.6 @@ -0,0 +1,80 @@ +.\" Process this file with +.\" groff -man -Tascii buildcsr.1 +.\" +.TH BUILDCSR "FEBRUARY 2001" Linux "User Manuals" +.SH NAME +buildcsr - builds a cursor +.SH SYNOPSIS +.B buildcsr [-p +.I name +.B -b +.I name +.B -m +.I mode +.B -s] +.SH DESCRIPTION +.B buildcsr +presents a blank screen with a cursor. One may hold down the left +mouse button and draw the color1 part of the cursor on the +screen. Typing +.B 2 +on the keyboard will cause color2 to be drawn. The cursor can be +viewed as a cursor by typing +.BR n . +To modify the cursor type +.B o +to go back to the original cursor. Pixels may be erased by clicking +on them with the right mouse button. The left mouse button will draw +either color1 or color2, depending on whether +.B 1 +or +.B 2 +was chosen from the keyboard last. The current color is displayed at +the bottom of the screen. +.SH OPTIONS +.IP -p +and +.IP -b +followed by name will produce a cursor file with the name +.BR name . +.IP -p +will produce a c language definition of the cursor suitable for +inclusion in a program as a header file. +.IP -b +will produce a binary cursor file which may be read into a user +program at execution time. +.IP -m +mode , a mode number will cause the program to run in mode +.BR mode . +This will not make a difference in the screen representation of the +cursor, but the cursor itself will be much smaller in high resolution +modes. Thus, for high resolution it is wise to construct the cursor +using the resolution at which it is intended to be used. Typing +.B n +will show the cursor as it will look at the resolution of the screen. +If no mode is given using +.B -m +the mode will be +.B SVGALIB_DEFAULT_MODE +if that has been defined in an environment variable. If no default +has been given and no +.B -m +was used, the screen mode will be mode 5, G320x200x256, which is +default for this program. The hardware cursor will be used if a +hardware cursor exists for the video card in use, otherwise the +software cursor will be used. +.IP -s +option will force the software cursor to be used even if a hardware +cursor exists. +.SH ENVIRONMENT +.IP SVGALIB_DEFAULT_MODE +will be used if it has been defined and +.B -m +was not given. If neither of these are in effect the mode will be +mode 5, G320x200x256. +.SH AUTHOR +Don Secrest +.SH "SEE ALSO" +.BR VGA_CURSOR (3) +.BR VGA_GETDEFAULTMODE (3) + diff --git a/doc/man6/eventtest.6 b/doc/man6/eventtest.6 new file mode 100644 index 0000000..c07bbd9 --- /dev/null +++ b/doc/man6/eventtest.6 @@ -0,0 +1,94 @@ +.TH eventtest 6 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +eventtest \- test the waitevent function of svgalib +.SH SYNOPSIS + +.B eventtest + +.SH DESCRIPTION +This is a kind of an upgraded +.BR keytest "(6) and " mousetest (6) +demo using the +.BR vga_waitevent (3) +function. + +Use mouse to move cursor. +.BR <1> - <9> ", " <0> +to set the cursor size. +.B +to change +the cursor color. Left button to draw. Right button or +.B +to bailout. + +The cursor goes on/off every half second by usage of a +.I timeout +passed to +.BR vga_waitevent (3). +Every 5 seconds a string from a child process (the time) +arrives asynchronously and is displayed by the frontend. This comes +in through a +.BR pipe (2) +which is monitored by +.BR vga_waitevent (2). + +You can set a videomode +to use by setting the environment variable +.B SVGALIB_DEFAULT_MODE +to a number (see vgatest +for a list) or a string like G0x1x2 where you replace 0 with desired x +resolution, 1 with the desired y rez, and 2 with the desired number of +colors (2, 16, 256, 32K, 64K, 16M, 16M4). Again, only certain choices are +available, see vgatest for a list. + +In case nothing is selected, G320x200x256 is choosen. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_waitevent (3), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +demos as well as the +.BR vga_waitevent (3) +function is due to him. diff --git a/doc/man6/forktest.6 b/doc/man6/forktest.6 new file mode 100644 index 0000000..e8d0cf0 --- /dev/null +++ b/doc/man6/forktest.6 @@ -0,0 +1,87 @@ +.TH forktest 6 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +forktest \- tests the vga_safety_fork() function. +.SH SYNOPSIS + +.B forktest + +.SH DESCRIPTION +This is a copy of the +.BR keytest (6) +demo (look there). However, it uses +.BR vga_safety_fork (3) +to start a background process to restore the +console in case the fore ground process crashes. It removes all +automatic restore functions of svgalib. Thus, in case you kill +this program with +.BR kill (1) +or +.BR -C , +only the background process will +save your system from being hosed up. + +You can set a videomode +to use by setting the environment variable +.B SVGALIB_DEFAULT_MODE +to a number (see vgatest +for a list) or a string like G0x1x2 where you replace 0 with desired x +resolution, 1 with the desired y rez, and 2 with the desired number of +colors (2, 16, 256, 32K, 64K, 16M, 16M4). Again, only certain choices are +available, see vgatest for a list. + +In case nothing is selected, G320x200x256 is choosen. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_safety_fork (3), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/fun.6 b/doc/man6/fun.6 new file mode 100644 index 0000000..faec2b3 --- /dev/null +++ b/doc/man6/fun.6 @@ -0,0 +1,73 @@ +.TH fun 6 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +fun \- draw pixels accumulating in clusters +.SH SYNOPSIS + +.B fun + +.SH DESCRIPTION +Random moving pixels accumulate in clusters. Uses virtual screens +for frame animation. This uses basic VGA functionality and works +only in 320x200x256. + +Hit +.B -C +to abort. The bottom row shows all +'clustered' pixels (on the screen a blue circle marks the seed of the +largest cluster and its size), frames drawn, and (after some time) +average frames per second. Once the screen is filled, a new random +setup is run. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/joytest.6 b/doc/man6/joytest.6 new file mode 100644 index 0000000..627fc3d --- /dev/null +++ b/doc/man6/joytest.6 @@ -0,0 +1,81 @@ +.TH joytest 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +joytest \- test the svgalib joystick package in text mode +.SH SYNOPSIS + +.BI "joytest " number + +.SH DESCRIPTION +This demo program tries to open the joystick with the given +.I number +and calibrates it. The user is prompted to press +.B +after which any state change of the joystick is reported until the program is killed. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.3.0.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH CAVEATS +The functions used by this demo are only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6), +.BR vgatest (6), +.BR mjoytest (6), +.BR joystick_init (3), +.BR joystick_close (3), +.BR joystick_update (3), +.BR joystick_sethandler (3), +.BR joystick_setdefaulthandler (3), +.BR joystick_getnumaxes (3), +.BR joystick_getnumbuttons (3), +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1 (3), +.BR joystick_getb1 (3), +.BR joystick_x (3), +.BR joystick_getx (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man6/keytest.6 b/doc/man6/keytest.6 new file mode 100644 index 0000000..ae5d8a4 --- /dev/null +++ b/doc/man6/keytest.6 @@ -0,0 +1,107 @@ +.TH keytest 6 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +keytest \- tests the svgalib raw keyboard functions +.SH SYNOPSIS + +.B keytest + +.SH DESCRIPTION +A program to test the low-level keyboard interface. This uses basic +VGA functionality (or an svga mode you specify). Works only in 256 +color modes. + +Cursor keys or keypad +.BR <1> ", " +.BR <2> ", " +.BR <3> ", " +.BR <4> ", " +.BR <5> ", " +.BR <6> ", " +.BR <7> ", " +.BR <8> ", and " +.BR <9> +move the cursor. +Keypad +.BR <0> " or " +changes color. +.BR " or " -C +quits. (autoquit after 60 +seconds). + +Note that the svgalib diagonal +.BR <7> ", " +.BR <9> ", " +.BR <1> ", and " +.BR <3> +keypad keys +emulation is flawed in that it emulates the vertical/horizontal +keys. If one of these is pressed too, it's release confuses svgalib. + +The top pixel line shows a blue pixel for each key which is reported +to be pressed. + +You can set a videomode +to use by setting the environment variable +.B SVGALIB_DEFAULT_MODE +to a number (see vgatest +for a list) or a string like G0x1x2 where you replace 0 with desired x +resolution, 1 with the desired y rez, and 2 with the desired number of +colors (2, 16, 256, 32K, 64K, 16M, 16M4). Again, only certain choices are +available, see vgatest for a list. + +In case nothing is selected, G320x200x256 is choosen. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/lineart.6 b/doc/man6/lineart.6 new file mode 100644 index 0000000..1ff86dd --- /dev/null +++ b/doc/man6/lineart.6 @@ -0,0 +1 @@ +.so man6/testlinear.6 diff --git a/doc/man6/mach32info.6 b/doc/man6/mach32info.6 new file mode 100644 index 0000000..5a3cc8c --- /dev/null +++ b/doc/man6/mach32info.6 @@ -0,0 +1,97 @@ +.TH mach32info 1 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +mach32info \- read out configuration information of a Mach32 +.SH SYNOPSIS + +.B mach32info {info|force} + +.SH DESCRIPTION +.B mach32info +prints out almost all the info about your mach32 card from configuration +registers and Mach32 EEPROM. It also measures the Mach32 clocks. A +completely idle system is required when these measurements are being +performed. During these measurements, the video signals will be screwed up +for about 3-4 seconds. + +If your monitor does not switch off when getting a video signal it can't +stand (fixed freq. monitors) better switch it off before starting +mach32info. Your computer will beep when it is finished probing. +You can redirect the 'stdout' of +.B mach32info +to some file for viewing the results easier or mailing them. + +Do not redirect 'stderr' as you won't hear the beep. + +This tool is part of svgalib. Although it's output maybe useful to debug +Xfree86 Mach32 Servers, I am +.B NOT +related to Xfree86! +.B Please do not send me (Michael Weller) any Xfree86 bug reports! +Thanx in advance. + +Note that this tool comes +.B without any warranty! +Use it at your +.B own +risk! + +.BR Warning , +this tool does not check for VC changes etc.. Just let it run in +its own virtual console as root and don't try to fool it. +Actually this is due to it not using svgalib at all but simply accessing the +Mach32. + +Please report any problems with running +.B mach32info +or with configuring the +.BR svgalib (7)'s +Mach32 driver to Michael Weller . +Include the results from running this test with your report. + +.SH OPTIONS +.TP +.B info +print out the configuration information. Without +.B info +.B mach32info +prints a usage message (looking almost like this manpage ;-)). +.TP +.B force +The +.B force +option disables the sanity check that tries to detect the +presence of the mach32 prior to printing the information. + +Do not use this option unless you are really, +really sure that you have a Mach32 compatible vga card installed. +.PP +This utility is part of svgalib and can be found in the +.I mach32/ +subdirectory of the original svgalib distribution. However, it is not installed +by default, s.t. it is unclear where you can find it if your svgalib was install +by a linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. You +don't need to install it. Just +.B make +in the +.I mach32/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR svgalib.mach32 (7), +.BR vgagl (7), +.BR libvga.config (5). + +.SH AUTHOR + +This manual page was edited by Michael Weller . +He also wrote the referenced utility as well as of the original documentation. diff --git a/doc/man6/mjoytest.6 b/doc/man6/mjoytest.6 new file mode 100644 index 0000000..19d9bdd --- /dev/null +++ b/doc/man6/mjoytest.6 @@ -0,0 +1,111 @@ +.TH mjoytest 3 "14 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +mjoytest \- test the svgalib joystick package in graphics mode +.SH SYNOPSIS + +.BI "mjoytest [-j " joystick "] [[-m] " "video mode" ] + +.SH DESCRIPTION +This demo program utilizes joysticks +.BR 0 " and " 1 +in graphics mode. + +If you specify a +.I joystick +number, only this is used. The demo separates the screen in two parts where you +can move a cursor around with the resp. joystick. Pressing button +2 changes the color, pressing button 1 draws. + +It also prints the current joystick position to the screen. + +Internally the demo also shows the use of custom joystick handlers and how to +recalibrate a joystick in graphics mode (press key +.BR <1> " and " <2> +respectively. + +After the demo runs and the joysticks are initialized it is possible to share the +joysticks with another application (as long as it releases the joysticks upon a VC +switch as well). + +Pressing +.BR +exits. + +.SH BUGS +After a vc switch the demo occasionally hangs in +.BR vga_waitevent (3) +not timing out (hence the joysticks block). It is +not clear if it is a conceptional problem or bug in +.BR vga_waitevent (3) +or the kernel. +Simply press any key to revive the demo. + +.SH NOTES + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.3.0.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH CAVEATS +The functions used by this demo are only available in ELF versions of svgalib. Due to backwards +compatibility issues it cannot be used with shared a.out libs. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6), +.BR vgatest (6), +.BR joytest (6), +.BR joystick_init (3), +.BR joystick_close (3), +.BR joystick_update (3), +.BR joystick_sethandler (3), +.BR joystick_setdefaulthandler (3), +.BR joystick_getnumaxes (3), +.BR joystick_getnumbuttons (3), +.BR joystick_getaxis (3), +.BR joystick_getbutton (3), +.BR joystick_button1 (3), +.BR joystick_getb1 (3), +.BR joystick_x (3), +.BR joystick_getx (3). + +.SH AUTHOR + +The svgalib joystick handler was mostly done by Daniel Engstr\\"om . +Multiple joystick, VC switching support and code to glue it into svgalib by Michael Weller +. Part of the code is based on code from C. Smith and +Vojtech Pavlik. diff --git a/doc/man6/mousetest.6 b/doc/man6/mousetest.6 new file mode 100644 index 0000000..6e9aef0 --- /dev/null +++ b/doc/man6/mousetest.6 @@ -0,0 +1,82 @@ +.TH mousetest 6 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +mousetest \- tests the svgalib mouse driver +.SH SYNOPSIS + +.B mousetest + +.SH DESCRIPTION +A simple program to test mouse functionality. +This uses basic VGA functionality (or an +svga mode you specify, you should stick to 256 color modes). + +The proper setup mouse should move the cursor (drawing spots in the +current color). Left button changes color, right button (or +.BR -C) +aborts. + +You can set a videomode +to use by setting the environment variable +.B SVGALIB_DEFAULT_MODE +to a number (see vgatest +for a list) or a string like G0x1x2 where you replace 0 with desired x +resolution, 1 with the desired y rez, and 2 with the desired number of +colors (2, 16, 256, 32K, 64K, 16M, 16M4). Again, only certain choices are +available, see vgatest for a list. + +In case nothing is selected, G320x200x256 is choosen. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/plane.6 b/doc/man6/plane.6 new file mode 100644 index 0000000..e8440d3 --- /dev/null +++ b/doc/man6/plane.6 @@ -0,0 +1,116 @@ +.TH plane 6 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +plane \- draw a 3 dimensional plane +.SH SYNOPSIS + +.B plane + +.SH DESCRIPTION +A greyscale-shaded rendered-on-the-fly turbo-prop that you can rotate +and scale however you like. + +The demo prompts your for a mode to be used and several details. Just +follow the instructions on the screen and make your selections. + +Once the program runs you can use the following keys: + +.TP +.BR " and " ", " " and " ", " " and "

+to rotate the plane around the space axes. +.TP +.BR " and " ", " " and " ", " " and " +to move up, down, north, south, east, west. (world view only) +.TP +.B + +to toggle rendering vs. wire frame. +.TP +.BR " and " +to scale in non-world view compilation -- see plane.h +.TP +.BR <1> " and " <2> +to change rotation increment. +.TP +.BR <3> " through " <9> +to change surface density. +.TP +.BR +to change shading method. +.TP +.BR +to quit the program. +.TP +.BR +to reset the rotation to the startup values. +.PP +This demo is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR triangle (3), +.BR striangle (3), +.BR wtriangle (3), +.BR swtriangle (3), +.BR trisetcolorlookup (3), +.BR trigetcolorlookup (3), +.BR trisetdrawpoint (3), +.BR threedkit (7), +.BR vgatest (6), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR wrapdemo (6) + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man6/printftest.6 b/doc/man6/printftest.6 new file mode 100644 index 0000000..537d42f --- /dev/null +++ b/doc/man6/printftest.6 @@ -0,0 +1,80 @@ +.TH printftest 6 "8 April 1997" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +printftest \- tests the vgagl gl_printf function +.SH SYNOPSIS + +.BI "printftest " x " " y + +.SH DESCRIPTION +This test utility reads keys from the keyboard and displays them on the +screen at pixel position +.RI ( x ", " y ) +using +.BR gl_printf (3). +It must be linked with the ELF svgalib libraries. + +You can set a videomode +to use by setting the environment variable +.B SVGALIB_DEFAULT_MODE +to a number (see vgatest +for a list) or a string like G0x1x2 where you replace 0 with desired x +resolution, 1 with the desired y rez, and 2 with the desired number of +colors (2, 16, 256, 32K, 64K, 16M, 16M4). Again, only certain choices are +available, see vgatest for a list. + +In case nothing is selected, G320x200x256 is choosen. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/scrolltest.6 b/doc/man6/scrolltest.6 new file mode 100644 index 0000000..eed3ab9 --- /dev/null +++ b/doc/man6/scrolltest.6 @@ -0,0 +1,76 @@ +.TH scrolltest 6 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +scrolltest \- tests some scrolling algorithms with svgalib +.SH SYNOPSIS + +.B scrolltest + +.SH DESCRIPTION +Smooth scrolling demo. Uses three different techniques. Useful for +testing Mode X functionality (not that I would recommend it over +320x240x256 linear). Press +.B +to cycle through the demos. + +The demos works only in 320x240x256 for the first 2 tests +and with 320x200x256 in the last. Demos 1 & 3 use a virtual screen +buffer, mode 2 (jumpy) works on screen. This is more a skeleton if +you want to write some animation program, rather than a nice demo. + +Shows frames per second (multiplied by 10) for method 1 & 3. Thus +works also a kind of memory speed tester + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/speedtest.6 b/doc/man6/speedtest.6 new file mode 100644 index 0000000..8cf0628 --- /dev/null +++ b/doc/man6/speedtest.6 @@ -0,0 +1,70 @@ +.TH speedtest 6 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +speedtest \- tests the speed of memory access under svgalib +.SH SYNOPSIS + +.B speedtest + +.SH DESCRIPTION +Video memory speed tester. Selects the given mode and makes linear +screen accesses. Prints the overall run time of the test and +deduces the speed with which the CPU can transfer data to the cards +memory. + +The demo gives a list of modes supported and prompts your for an integer +indentifying the mode to test. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/spin.6 b/doc/man6/spin.6 new file mode 100644 index 0000000..10ea372 --- /dev/null +++ b/doc/man6/spin.6 @@ -0,0 +1,98 @@ +.TH spin 6 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +spin \- test a 6-dimension mouse or pointer device with svgalib +.SH SYNOPSIS + +.B spin + +.SH DESCRIPTION +Another mouse test program. This is the first svgalib program to +use the 6-dimensional mouse routines. It draws a wireframe spheroid +on the screen which can be moved left/right, up/down, in/out, or +rotated along the x, y, or z axes. + +.B Button bindings are: +.br +.PD 0 +.TP +.BR A " - Decrease Sensitivity (Right Mouse Button)" +.TP +.BR B " - Change color (Middle Mouse Button)" +.TP +.BR C " - Increase Sensitivity (Left Mouse Button)" +.TP +.BR D " - Increase Number of Sides" +.TP +.BR E " - Decrease Number of Sides" +.TP +.BR F " - Quit (" -C ) +.PD +.P +If you only have a two dimensional mouse with three or fewer buttons +you will only be able to move the mouse in two dimensions +(left/right and in/out) and will not be able to move up/down or +spin the spheroid. +Note: the initial mouse sensitivity is optimised for the Spacetec +series of controllers, which are much more sensitive than the usual +mouse. Increasing the sensitivity is advised for users of other +types of devices. + +The demo works always in mode 320x200x256. It prompts your for an +integer, the number of sides the sphere has (the higher the smoother +looks the spere). + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR mouse_setposition_6d (3), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/svidtune.6 b/doc/man6/svidtune.6 new file mode 100644 index 0000000..0c816eb --- /dev/null +++ b/doc/man6/svidtune.6 @@ -0,0 +1,55 @@ +.TH vgatest 6 "10 June 1999" "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +svidtune - tunes svgalib modes +.SH SYNOPSIS + +.B svidtune mode + +.SH DESCRIPTION + +.I mode +is an svgalib mode number for the mode to be tuned. The number of colours +is irrelevant, but the mode must be supported by the hardware. + +svidtune displays the mode timing parameters, and a rectangle around the +screen. You can then adjust the parameters to have the display tuned +properly. + +Please note that modelines (and this program) only affects display when +the driver uses the timing.c interface. Specifically, it has no affect on +the VESA driver. + +.SH KEYS + +.IR l,r,d,u +move the displayed portion of the screen left, right, down or up. + +.IR w,n +increase or decrease the screens horizontal size. + +.I s,o +increase or decrease the screens vertical size. + +.I p +print the current modeline to the standard error. + +.I P +print the current modeline to the config file, so it will be used by +svgalib from now on. + +.I q +quit + +.SH BUGS + +The program does not test that the modes remain within the monitor limits. + +.SH SEE ALSO + +.BR vga_getcurrenttiming (3), +.BR vga_changecurrenttiming (3), +.BR libvga.config (5) + +.SH AUTHOR + +This man page was written by Matan Ziv-Av. diff --git a/doc/man6/testaccel.6 b/doc/man6/testaccel.6 new file mode 100644 index 0000000..2d269b3 --- /dev/null +++ b/doc/man6/testaccel.6 @@ -0,0 +1,397 @@ +.TH testaccel 6 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +testaccel \- test the old style blitter functions and vga_ext_set() +.SH SYNOPSIS + +.BI "testaccel [ -nowait ] [ { all | " videomodes "... } ] + +.SH DESCRIPTION +Program to test the old blitter functions in a screen mode. Checks +the 8-bit wide color lookup tables on Mach32's with type 2 DACs +as well. +[I think '6bpp' and '8bpp' are silly names for the 8-bit +LUT thing -- bpp is bits per pixel, in the framebuffer - HH :-)] + +After each test it waits for a key press except when +.B -nowait +is +given. + +You can specify names of modes to test on the command line +or specify +.B all +to loop over all svgalib modes. + +The program will run on any card, however, most of the tests can +only be performed on a Mach32. + +The subtest are in turn: + +.TP +.B 1 - +For each 256 color mode the program sees if it is possible to +enable a special mode with 8 bits per color in the RGB lookup +table. If so, for example 256 different shades of blue can +be implemented. +The program displays as much blue shades as possible in a shade +from dark (left) to bright (right) and some text in an +opposite direction on top of it. In case 56 different shades +are supported, the screen is divided and shows a rough 64 shades +scale (ordinary vga) on top and the smooth shade below. +Right now 256 different shades are only possible on a Mach32 with +RAMDAC of type 2. +For modes with few pixels only, the program might fail to print +the text properly and will 'wrap' it around the screen edges. +.TP +.B 2 - +Draws a bouncing 'linux' logo stopping after a fixed amount of +1 pixel steps. Uses +.BR vga_bitblt (3) +on the image plus a one pixel +outline in border color to move the pixel around the screen. +The Mach32 is +.B very +fast in this discipline. +.TP +.B 3 - +Draws filled rectangles using +.BR vga_fillblt (3). +At first a series +of larger to smaller centered rectangles is drawn to fill the +screen. +For 256 or less color modes these will use a sequence of 256 +random colors. For 32K or more color modes it will use colors +0 up too, however, you'll usually just see a repeating series +of blues (limitations of monitor/human eye, the blue's differ +not enough for the eye to see). Then a bunch of random boxes +in random places is drawn overwriting each other. +The Mach32 is +.B very +fast in this discipline. +.TP +.B 4 - +Draws small fish bitmaps and then larger linux logos in random +positions using +.BR vga_imageblt (3). +They just overlap each other +The Mach32 is poor in this discipline. If you have a linear +frame buffer enabled, it is used instead to perform this function +(even if the program does not use a linear frame buffer otherwise). +Usually this is twice as fast for Mach32. +.TP +.B 5 - +Use +.BR vga_hlinelistblt (3) +o do some simple polygon fills: squares, +circles, diamonds of random sizes, positions and colors. Again, +the Mach32 is +.B very +fast in this discipline, but somehow slowed +down by the imperfect prototype of this function. Again, +the polygons just overlap each other. + +The resp. tests will only be performed where supported by the +hardware. For Mach32 this means only SVGA 256, 32K, 64K color modes. +The linear frame buffer emulated +.BR vga_imageblt (3) +works for all SVGA modes +though. +.P + +The program prints the number of pixels drawn and the time required +plus the resulting rate of pixels per second. For Mach32 the rate +depends on the amount of screen accesses (2 per pixel move for +.BR vga_bitblt (3), +1 per pixel move for +.BR vga_fillblt "(3) and " +.BR vga_hlinelistblt (3); +also twice bytes +are affected for 32K, 64K color modes). On a non VRAM card you'll +also note the effect of the memory access caused by the generation +of the video frames (more colors/rez/sync rates => less speed). +Also, higher modes draw more pixels per call, thus less call and +setup overhead. + +Here are the rates for my card on an almost idle 486 EISA system +which should be fairly optimal (2MB VRAM EISA Mach32) except maybe +the linear frame buffer emulated imageblt which might be faster on +PCI card: + +.br +.B Testing mode 1: G320x200x16... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 2: G640x200x16... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 3: G640x350x16... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 4: G640x480x16... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 5: G320x200x256... +.br +.B Warning: Resolution too small, displayed text is +.br +.B probably scrambled. +.br +.B " " +.br +.B Has support for CLUT width 8 bit +.br +.B Testing mode 6: G320x240x256... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 7: G320x400x256... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 8: G360x480x256... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 9: G640x480x2... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 10: G640x480x256... +.br +.B Has support for CLUT width 8 bit +.br +.B Has BitBlt: 176610000 Pixels in 6.49 seconds -> 27.21 Megapels +.br +.B Has FillBlt: 217884171 Pixels in 4.55 seconds -> 47.89 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 3.07 seconds -> 5.57 Megapels +.br +.B Has HlineLst: 20192124 Pixels in 0.57 seconds -> 35.42 Megapels +.br +.B Testing mode 11: G800x600x256... +.br +.B Has support for CLUT width 8 bit +.br +.B Has BitBlt: 176610000 Pixels in 6.65 seconds -> 26.56 Megapels +.br +.B Has FillBlt: 343102613 Pixels in 6.23 seconds -> 55.07 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 3.06 seconds -> 5.58 Megapels +.br +.B Has HlineLst: 33166399 Pixels in 0.78 seconds -> 42.52 Megapels +.br +.B Testing mode 12: G1024x768x256... +.br +.B Has support for CLUT width 8 bit +.br +.B Has BitBlt: 176610000 Pixels in 6.88 seconds -> 25.67 Megapels +.br +.B Has FillBlt: 603141286 Pixels in 9.78 seconds -> 61.67 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 3.07 seconds -> 5.57 Megapels +.br +.B Has HlineLst: 52958845 Pixels in 1.08 seconds -> 49.04 Megapels +.br +.B Testing mode 13: G1280x1024x256... +.br +.B Has support for CLUT width 8 bit +.br +.B Has BitBlt: 176610000 Pixels in 7.10 seconds -> 24.87 Megapels +.br +.B Has FillBlt: 1063820849 Pixels in 16.16 seconds -> 65.83 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 3.07 seconds -> 5.57 Megapels +.br +.B Has HlineLst: 95798478 Pixels in 1.75 seconds -> 54.74 Megapels +.br +.B Testing mode 14: G320x200x32K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 12.30 seconds -> 14.36 Megapels +.br +.B Has FillBlt: 41317334 Pixels in 3.61 seconds -> 11.45 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.93 seconds -> 2.88 Megapels +.br +.B Has HlineLst: 3411068 Pixels in 0.23 seconds -> 14.83 Megapels +.br +.B Testing mode 15: G320x200x64K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 12.29 seconds -> 14.37 Megapels +.br +.B Has FillBlt: 42351016 Pixels in 4.12 seconds -> 10.28 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.93 seconds -> 2.88 Megapels +.br +.B Has HlineLst: 3561694 Pixels in 0.23 seconds -> 15.49 Megapels +.br +.B Testing mode 16: G320x200x16M... +.br +.B Dacwidth test not applicable. +.br +.B Has ImageBlt: 17085000 Pixels in 8.83 seconds -> 1.93 Megapels +.br +.B Testing mode 17: G640x480x32K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 13.38 seconds -> 13.20 Megapels +.br +.B Has FillBlt: 217723964 Pixels in 7.95 seconds -> 27.39 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.94 seconds -> 2.88 Megapels +.br +.B Has HlineLst: 19579110 Pixels in 0.74 seconds -> 26.46 Megapels +.br +.B Testing mode 18: G640x480x64K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 13.37 seconds -> 13.21 Megapels +.br +.B Has FillBlt: 221608034 Pixels in 8.28 seconds -> 26.76 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.93 seconds -> 2.88 Megapels +.br +.B Has HlineLst: 21048202 Pixels in 0.79 seconds -> 26.64 Megapels +.br +.B Testing mode 19: G640x480x16M... +.br +.B Dacwidth test not applicable. +.br +.B Has ImageBlt: 17085000 Pixels in 8.82 seconds -> 1.94 Megapels +.br +.B Testing mode 20: G800x600x32K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 13.97 seconds -> 12.64 Megapels +.br +.B Has FillBlt: 357205415 Pixels in 12.22 seconds -> 29.23 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.92 seconds -> 2.89 Megapels +.br +.B Has HlineLst: 34391335 Pixels in 1.16 seconds -> 29.65 Megapels +.br +.B Testing mode 21: G800x600x64K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 13.97 seconds -> 12.64 Megapels +.br +.B Has FillBlt: 348943970 Pixels in 11.87 seconds -> 29.40 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.93 seconds -> 2.88 Megapels +.br +.B Has HlineLst: 34510200 Pixels in 1.17 seconds -> 29.50 Megapels +.br +.B Testing mode 22: G800x600x16M... +.br +.B Dacwidth test not applicable. +.br +.B Has ImageBlt: 17085000 Pixels in 8.83 seconds -> 1.93 Megapels +.br +.B Testing mode 23: G1024x768x32K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 14.60 seconds -> 12.10 Megapels +.br +.B Has FillBlt: 608000981 Pixels in 18.62 seconds -> 32.65 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.93 seconds -> 2.88 Megapels +.br +.B Has HlineLst: 53767429 Pixels in 1.72 seconds -> 31.26 Megapels +.br +.B Testing mode 24: G1024x768x64K... +.br +.B Dacwidth test not applicable. +.br +.B Has BitBlt: 176610000 Pixels in 14.60 seconds -> 12.10 Megapels +.br +.B Has FillBlt: 601666798 Pixels in 18.80 seconds -> 32.00 Megapels +.br +.B Has ImageBlt: 17085000 Pixels in 5.92 seconds -> 2.89 Megapels +.br +.B Has HlineLst: 52037798 Pixels in 1.67 seconds -> 31.16 Megapels +.br +.B Testing mode 32: G720x348x2... +.br +.B Dacwidth test not applicable. +.br +.B Testing mode 33: G320x200x16M32... +.br +.B Dacwidth test not applicable. +.br +.B Has ImageBlt: 17085000 Pixels in 11.60 seconds -> 1.47 Megapels +.br +.B Testing mode 34: G640x480x16M32... +.br +.B Dacwidth test not applicable. +.br +.B Has ImageBlt: 17085000 Pixels in 11.62 seconds -> 1.47 Megapels +.br +.B Testing mode 35: G800x600x16M32... +.br +.B Dacwidth test not applicable. +.br +.B Has ImageBlt: 17085000 Pixels in 11.62 seconds -> 1.47 Megapels + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_ext_set (3), +.BR vga_bitblt (3), +.BR vga_fillblt (3), +.BR vga_hlinelistblt (3), +.BR vga_imageblt.3 +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . He +also wrote thise demo and it's documentation. diff --git a/doc/man6/testgl.6 b/doc/man6/testgl.6 new file mode 100644 index 0000000..992dd64 --- /dev/null +++ b/doc/man6/testgl.6 @@ -0,0 +1,92 @@ +.TH testgl 6 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +testgl \- test the vgagl library +.SH SYNOPSIS + +.B testgl + +.SH DESCRIPTION +Demo program for +.BR vgagl (7) +framebuffer library. Runs in any mode preset +from the environment. + +First draws pixels in random locations, then +random boxes, then random lines and finally some bit image in random +locations (all just over the previous drawings). + +Then the +test is repeated clipping the screen output to a smaller screen +portion (using a +.BR vgagl (7) +function). Finally a (lousy) 'rotating' +linux logo is shown in the top left quadrant and then is drawn +over the whole screen. +Depending on internal development state of svgalib, it may use an +accelerator for some of the functions. + +You can set a videomode +to use by setting the environment variable +.B SVGALIB_DEFAULT_MODE +to a number (see vgatest +for a list) or a string like G0x1x2 where you replace 0 with desired x +resolution, 1 with the desired y rez, and 2 with the desired number of +colors (2, 16, 256, 32K, 64K, 16M, 16M4). Again, only certain choices are +available, see vgatest for a list. + +In case nothing is selected, G320x200x256 is choosen. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/testlinear.6 b/doc/man6/testlinear.6 new file mode 100644 index 0000000..d4ac399 --- /dev/null +++ b/doc/man6/testlinear.6 @@ -0,0 +1,96 @@ +.TH testlinear 6 "29 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +testlinear, lineart \- test a linear frame buffer +.SH SYNOPSIS + +.B testlinear + +.SH DESCRIPTION +Program to test linear addressing on Cirrus cards and on Mach32 (and other cards which +may support it). + +Selects 640x480x256 and tries to enable a linear frame buffer +(its virtual address is printed). Fills the screen in some color, +then draws pixels in random positions. + +For Cirrus cards some +direct hardware access is then made for highspeed screen access. +Except for the last (Cirrus only) test no speeds are printed, but +you are welcome to use 'time' to measure it. The program draws +714400 one byte pixels plus a forced 1s delay and various rand() +calls for the pixels. + +The +.B testlinear +demo needs a few presses of +.B +after each +minimal demo step. Even when it does not prompt for it. When it +appears to be stuck, just press +.BR . + +The +.B lineart +demo is the same, but it accepts a command line with an arbitrary +number of modes. The modes may be either mode numbers or names, or +both. For example, + +.I lineart 11 17 "G800x600x32k" 22 + +will give a display of mode 11. If a key is pressed mode 17 will +appear, followed by mode 20 and 22 as succesive keys are pressed. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/threed.6 b/doc/man6/threed.6 new file mode 100644 index 0000000..f769c7e --- /dev/null +++ b/doc/man6/threed.6 @@ -0,0 +1,128 @@ +.TH threed 6 "8 April 1998" "Svgalib 1.3.0" "Svgalib User Manual" +.SH NAME +threed \- The svgalib 3d demo +.SH SYNOPSIS + +.B 3d + +.SH DESCRIPTION +Well, the 3d demo... + +I, Michael, the current svgalib maintainer, do not have any source for it. + +Thus, you may experience weird problems with new svgalib versions +and you need installed a.out libc and svgalib versions. +Also the demo is known to be buggy in several aspects. Thus, do not +panic if it appears not to work for you. + +If it works in a certain mode for you be happy and +play around with it. For example, with recent svgalibs, +.B 3d +is +unable to initialize the mouse if not started directly in a linux +console for unknown reasons. + +Otherwise: +.B "Don't worry at all." + +.SS "Here's the author's (Harm's) info about it:" + +There's also a +.B 3d +demo binary included in this directory. It has been +in a similar state for several months now, but I'm planning to get +some work done (although it probably won't be the amazing multi-player +networked 3D lightsource-shaded real-time VGA virtual reality +simulation). I'll release the source code at some point (when it has +some degree of flexibility). I'm sorry that there's no scene +description file; it will come. So now you know you can do this kind +of thing in Linux. And it's practically 100% C code. + +You can set the graphics mode to be used with the +.B SVGALIB_DEFAULT_MODE +environment +variable (e.g. G640x480x256). All linear 256 color, 32K color and 16M +color modes are supported, with page flipping used if available. Planar +256 color VGA modes also work. This should do 800x600 full screen 3D +animation at near 10 fps with a good system. +Request: Please report if page flipping goes wrong on a particular +chipset (e.g. ET4000, Trident) in 320x200x256. Also 32-bit pixel +truecolor modes don't work correctly, this will be fixed. +The user interface is somewhat primitive at this point: + +- Use the mouse to rotate. +.br +- Left button accelerates, right decelerates. +.br +- Press +.B +to move upwards, +.B +to go down again. +.br +- Use +.B +and +.B +to control the zoom factor. +.br +- +.BR " or " -C +exits. + +Note that the light source rotates quickly at an infinite distance. +This is not something that will easily occur naturally (as far as I +know)... + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH BUGS +Countless. +.br +In addition, source is still not available. Sorry, I just don't have it. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +demo and most of it's documentation is due to +Harm Hanemaayer . diff --git a/doc/man6/vgatest.6 b/doc/man6/vgatest.6 new file mode 100644 index 0000000..44856f4 --- /dev/null +++ b/doc/man6/vgatest.6 @@ -0,0 +1,157 @@ +.TH vgatest 6 "01 January 2001" "Svgalib (>= 1.9.13)" "Svgalib User Manual" +.SH NAME +vgatest \- makes basic tests on any svgalib graphics mode +.SH SYNOPSIS + +.B vgatest + +.SH DESCRIPTION +Mode test program. First the program gives a list of the supported +modes, then you enter a number and +.B vgatest +displays a test pattern in that mode. + +The test pattern consists of a sequence of crosses (in different colors, +if the mode support has different colors) in the top left corner. + +Below you see either four horizontal color bars (white, red, green, +and blue with increasing intensity from left to right) or vertical +stripes. + +If the mode has 32K or more colors, six squares will appear on top of +that, each showing some different smooth color shades + +The whole pattern is enclosed in a white border around the edge of the +screen. + +See below for details of the test pattern in case you need to verify that +it is being displayed correctly or diagnose a problem with the display. + +It also shows some details from +.BR vga_getmodeinfo (3). + +To terminate the display and exit the program, hit any key. If that key +is 'd', +.B vgatest +dumps the values of all the SVGA registers to Standard Output, in the +manner of vga_dumpregs() before exiting. + +This demo is part of svgalib and can be found in the +.I demos/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I demos/ +subdirecty. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SS The Test Pattern +Here are the details of the test pattern that +.B vgatest +displays. + +The screen is surrounded by a white frame which is at the very edges of +the screen and one pixel thick. + +At the top of the screen is a set of 16 overlapping crosses, lined up +horizontally 5 pixels apart. Each cross is composed of a one pixel +thick line sloping down at 45 degrees and one sloping up at 45 degrees +meeting in the center. The top of each of these lines is at the 11th +raster line on the screen and the bottom is at the 90th, so the +crosses are 80 lines high. The leftmost pixel of the crosses is in +the 11th column of the screen and the rightmost is in the 165th +column. The lines are in multiple colors, but each line is one color +(except where it intersects another line). + +Below the crosses are either 4 horizontal bands of color or vertical +bars. If the mode has 2 or 16 colors, you get the vertical bars. If +the mode has 256, 32K, 64K, or 16M colors, you get the horizontal +bands of color. + +For a 2 color mode, the vertical bars are are one pixel wide white +bars, spaced 4 pixels apart all the way across the screen on a black +background. The first white bar is in the 3rd column. (But don't +forget the white border described above). + +For a 16 color mode, the vertical bars are one pixel wide and +contiguous, filling the 3rd column from the left through the 3rd +column from the right. The bars cycle through each of the 16 colors +from left to right. + +The vertical bars start in the 101st raster line and end in the 3rd +line from the bottom of the screen. + +For a higher color mode, the color bands fill the 3rd column from the +left through the 3rd column from the right. (leaving a column of +black and the aforementioned white border at the edges). The bands +are all the same height with nothing between them. They are as large +as will fit starting in the 101st line of the screen and ending at or +before the 3rd line from the bottom. So depending on the number of +lines on the screen, there are 1, 2, 3, or 4 black lines between the +lowest bar and the white bottom border. + +The hues of the bands are, from top to bottom, white, red, +green, and blue. Each band goes from zero to maximal brightness from +left to right. + +In addition to the color bands, for a mode with 32K or more colors, +six squares, 64 pixels on a side are arranged in a matrix centered on +the screen, spaced 32 pixels apart. They replace any other part of +the test pattern. These are actual squares only if your monitor +displays square pixels in this mode, i.e. 64 columns is the same +length as 64 lines. Normal monitors, properly adjusted, display +square pixels for 1024 x 768 modes, but may not for other geometries. + +Each square contains 4096 different colors, one pixel per color, in +smooth transition. In each top square, one color component (red, +green, or blue) is zero another varies linearly in the vertical +direction and the other varies linearly in the Y direction. The +bottom squares are the same except that one color component is maximum +instead of zero. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR vga_getmodeinfo (3), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR plane (6), +.BR wrapdemo (6) + +.SH AUTHOR + +This manual page was edited by Michael Weller . The +exact source of the referenced demo as well as of the original documentation is +unknown. + +It is very likely that both are at least to some extent are due to +Harm Hanemaayer . + +Occasionally this might be wrong. I hereby +asked to be excused by the original author and will happily accept any additions or corrections +to this first version of the svgalib manual. diff --git a/doc/man6/wrapdemo.6 b/doc/man6/wrapdemo.6 new file mode 100644 index 0000000..2200aae --- /dev/null +++ b/doc/man6/wrapdemo.6 @@ -0,0 +1,116 @@ +.TH wrapdemo 6 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +wrapdemo \- demonstrates surface wrapping of pixmaps +.SH SYNOPSIS + +.B wrapdemo + +.SH DESCRIPTION +Demonstrates surface wrapping of pixmaps by wrapping a picture or +Susanna Rubens around a 3-dimensional ball. + +The demo prompts your for a mode to be used and several details. Just +follow the instructions on the screen and make your selections. + +Once the program runs you can use the following keys: + +.TP +.BR " and " ", " " and " ", " " and "

+to rotate the plane around the space axes. +.TP +.BR " and " ", " " and " ", " " and " +to move up, down, north, south, east, west. (world view only) +.TP +.B + +to toggle rendering vs. wire frame. +.TP +.BR " and " +to scale in non-world view compilation -- see plane.h +.TP +.BR <1> " and " <2> +to change rotation increment. +.TP +.BR <3> " through " <9> +to change surface density. +.TP +.BR +to change shading method. +.TP +.BR +to quit the program. +.TP +.BR +to reset the rotation to the startup values. +.PP +This demo is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not installed in the system +by default, s.t. it is unclear where you can find it if your svgalib was installed by some +linux distribution. Even then, when you have the demo on your system, you probably won't have +the sources s.t. it is only of limited use for you. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +.SH SEE ALSO + +.BR svgalib (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR triangle (3), +.BR striangle (3), +.BR wtriangle (3), +.BR swtriangle (3), +.BR trisetcolorlookup (3), +.BR trigetcolorlookup (3), +.BR trisetdrawpoint (3), +.BR threedkit (7), +.BR vgatest (6), +.BR threed (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR mousetest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR plane (6) + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man7/svgalib.7 b/doc/man7/svgalib.7 new file mode 100644 index 0000000..9a382c0 --- /dev/null +++ b/doc/man7/svgalib.7 @@ -0,0 +1,1266 @@ +.TH svgalib 7 "16 December 1999" "Svgalib 1.4.1" "Svgalib User Manual" +.SH NAME +svgalib \- a low level graphics library for linux +.SH TABLE OF CONTENTS + +.BR 0. " Introduction" +.br +.BR 1. " Installation" +.br +.BR 2. " How to use svgalib" +.br +.BR 3. " Description of svgalib functions" +.br +.BR 4. " Overview of supported SVGA chipsets and modes" +.br +.BR 5. " Detailed comments on certain device drivers" +.br +.BR 6. " Goals" +.br +.BR 7. " References (location of latest version, apps etc.)" +.br +.BR 8. " Known bugs" + +.SH 0. INTRODUCTION + +This is a low level graphics library for Linux, originally based on VGAlib 1.2 by +Tommy Frandsen. VGAlib supported a number of standard VGA graphics modes, as +well as Tseng ET4000 high resolution 256-color modes. As of now, support for many +more chipsets has been added. See section +.B 4 Overview of supported SVGA chipsets and modes + +It supports transparent virtual console switching, that is, you can switch +consoles to and from text and graphics mode consoles using alt-[function +key]. Also, svgalib corrects most of VGAlib's textmode corruption behaviour +by catching +.BR SIGSEGV ", " SIGFPE ", " SIGILL , +and other fatal signals and ensuring that a program is running +in the currently visible virtual console before setting a graphics mode. + +Note right here that +.BR SIGUSR1 " and " SIGUSR2 +are used to manage console switching internally in +.BR svgalib . +You can not use them in your programs. If your program needs to use one of +those signals, svgalib can be compiled to use other signals, by editing +libvga.h + +This version includes code to hunt for a free virtual console on its own in +case you are not starting the program from one (but instead over a network or +modem login, from within +.BR screen (1) +or an +.BR xterm (1)). +Provided there is a free +console, this succeeds if you are root or if the svgalib calling user own +the current console. This is to avoid people not using the console being able +to fiddle with it. +On graceful exit the program returns to the console from which it was started. +Otherwise it remains in text mode at the VC which svgalib allocated to allow +you to see any error messages. In any case, any I/O the svgalib makes in +text mode (after calling +.BR vga_init (3)) +will also take place at this new console. + +Alas, some games misuse their suid root privilege and run as full root +process. svgalib cannot detect this and allows Joe Blow User to open a new +VC on the console. If this annoys you, +.B ROOT_VC_SHORTCUT +in +.I Makefile.cfg +allows +you to disable allocating a new VC for root (except when he owns the current +console) when you compile svgalib. This is the default. + +When the library is used by a program at run-time, first the chipset is +detected and the appropriate driver is used. This means that a graphics +program will work on any card that is supported by svgalib, if the mode it +uses is supported by the chipset driver for that card. The library is +upwardly compatible with VGAlib. + +The set of drawing functions provided by svgalib itself is limited (unchanged +from VGAlib) and unoptimized; you can however use +.BR vga_setpage (3) +and +.BR vga_getgraphmem (3) +(which points to the 64K VGA framebuffer) in a program or graphics library. +A fast external framebuffer graphics library for linear and banked 1, 2, 3 +and 4 bytes per pixel modes is included (it also indirectly supports planar +VGA modes). It is documented in +.BR vgagl (7). + +One obvious application of the library is a picture viewer. Several are +available, along with animation viewers. See the +.B 7. References +at the end of this document. + +I have added a simple VGA textmode font restoration utility +.RB ( restorefont (1)) +which may help if you suffer from XFree86 textmode font corruption. It can +also be used to change the textmode font. It comes with some other textmode utilities: +.BR restoretextmode (1) +(which saves/restores textmode registers), +.BR restorepalette (1), +and the script +.BR textmode (1). +If you run the +.BR savetextmode (1) +script to save textmode information to +.IR /tmp , +you'll be able to restore textmode by running the +.BR textmode (1) +script. + +.SH 1. INSTALLATION +Installation is easy in general but there are many options and things +you should keep in mind. This document however assumes that +.B svgalib +is already installed. + +If you need information on installation see +.I 0-INSTALL +which comes with the svgalib distribution. + +However, even after installation of the library you might need to configure +svgalib using the file +.IR /etc/vga/libvga.config . +Checkout section +.B 4 Overview of supported SVGA chipsets and modes +and +.BR libvga.config (5) +for information. + +.SH 2. HOW TO USE SVGALIB + +For basic svgalib usage (no mouse, no raw keyboard) add +.B #include +at the beginning your program. +Use +.BR vga_init (3) +as your first +.B svgalib +call. This will give up root privileges right +after initialization, making setuid-root binaries relatively safe. + +The function +.BR vga_getdefaultmode (3) +checks the environment variable +.B SVGALIB_DEFAULT_MODE +for a default mode, and returns the corresponding mode number. The +environment string can either be a mode number or a mode name as in +.RB ( "G640x480x2" ", " "G640x480x16" ", " "G640x480x256 ", " +.BR G640x480x32K ", " G640x480x64K ", " G640x480x16M ). +As an example, to set the default +graphics mode to 640x480, 256 colors, use: + +.B export SVGALIB_DEFAULT_MODE=G640x480x256 + +on the +.BR bash(1) +command line. If a program needs just a linear VGA/SVGA resolution (as required by +.BR vgagl (7)), +only modes where +.B bytesperpixel +in the +.B vga_modeinfo +structure returned by +.BR vga_getmodeinfo (3) +is greater or equal to 1 should be accepted (this is 0 for tweaked +planar 256-color VGA modes). + +Use +.BI vga_setmode( graphicsmode ) +to set a graphics mode. Use +.B vga_setmode(TEXT) +to restore textmode before program exit. + +Programs that use svgalib must +.BR #include ; +if they also use the external graphics library +.BR vgagl (7), +you must also +.BR #include . +Linking must be done +with +.B -lvga +(and +.BR -lvgagl " before " -lvga , +if +.BR vgagl (7) +is used). You can save binary space by removing the unused chipset drivers in +.I Makefile.cfg +if you only use specific chipsets. However this reduces the flexibility of svgalib +and has a significant effect only when you use the static libraries. You should better +use the shared libraries and these will load only the really used parts anyway. + +Functions in the +.BR vgagl (7) +library have the prefix +.BR gl_ . +Please see +.BR vgagl (7) +for details. + +There are demos with sources available which will also help to get you started, in +recomended order of interest: +.BR vgatest (6), +.BR keytest (6), +.BR mousetest (6), +.BR eventtest (6), +.BR forktest (6), +.BR bg_test (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR fun (6), +.BR spin (6), +.BR testlinear (6), +.BR lineart (6), +.BR testgl (6), +.BR accel (6), +.BR testaccel (6), +.BR plane "(6), and " +.BR wrapdemo (6). + +Debugging your programs will turn out to be rather difficult, because the svgalib +application can not restore textmode when it returns to the debugger. + +Happy are the users with a serial terminal, X-station, or another way to log into the machine +from network. These can use + +.BI "textmode . + +Supports 640x480x256, 800x600x256, 1024x768x256 (interlaced and non-interlaced) +Might be useful to add 16-color modes (for those equipped with a 512K TVGA9000) +for the 8900 and 9000 cards. + +320x200x{32K, 64K, 16M}, 640x480x{256, 32K, 64K, +16M}, 800x600x{256, 32K, 64K, 16M}, 1024x768x{16, 256}, 800x600x{16, 256, 32K, +64K} modes are supported for the TVGA 9440. + +Autodetection can be forced with a: + +.RS +.B chipset TVGA +.I memory flags +.RE + +line in the config file. + +.I memory +is the amount of VGA memory in KB, +.I flags +is composed of three bits: +.RS +.TP +.B bit2 = false, bit1 = false +force 8900. +.TP +.B bit2 = false, bit1 = true +force 9440. +.TP +.B bit2 = true, bit1 = false +force 9680. +.TP +.B bit0 = true +force noninterlaced. +.TP +.B bit0 = false +force interlaced which only matters on 8900's with at least 1M +since there is no 512K interlaced mode on the 8900 or any of the other cards. +.RH + +.SS Tseng ET4000/ET4000W32(i/p) + +Derived from VGAlib; not the same register values. +ET4000 register values are not compatible; see +.BR svgalib.et4000 (7). + +Make sure the colors are right in hicolor mode; the vgatest +program should draw the same color bars for 256 and hicolor +modes (the DAC type is defined at compilation in +.I et4000.regs +or the dynamic +registers file). +ET4000/W32 based cards usually have an AT&T or Sierra +15025/6 DAC. With recent W32p based cards, you might have +some luck with the AT&T DAC type. +If the high resolution modes don't work, you can try +dumping the registers in DOS using the program in the +.I et4000/ +directory and putting them in a file +.RI ( /etc/vga/libvga.et4000 +is parsed at runtime if +.B DYNAMIC +is defined in +.IR Makefile.cfg +at compilation (this is default)). + +Supported modes are +640x480x256, 800x600x256, 1024x768x256, +640x480x32K, 800x600x32K, 640x480x16M, etc. + +Reports of ET4000/W32i/p functionality are welcome. + +There may be a problem with the way the hicolor DAC register +is handled; dumped registers may use one of two timing +methods, with the value written to the register for a +particular DAC for a hicolor mode (in vgahico.c) being +correct for just one of the these methods. As a consequence +some dumped resolutions may work while others don't. + +.SS Tseng ET6000 + +Most modes of which the card is capable are supported. The 8 15 +16 24 and 32 bit modes are supported. + +The ET6000 has a built in DAC and there is no problem coming from +that area. The ET6000 is capable of acceleration, but this as well as +sprites are not yet implemented in the driver. + +The driver now uses modelines in libvga.config for user defined modes. +It is sometimes useful to add a modeline for a resolution which does +not display well. For example, the G400x600 is too far to the right +of the screen using standard modes. This is corrected by including +in +.B libvga.config +the line + +Modeline "400x600@72" 25.000 400 440 488 520 600 639 644 666 + +More examples are given below. + +This driver was provided by Don Secrest. + +.SS VESA + +Please read README.vesa and README.lrmi in doc subdirectory of the standard +distribution. + +Go figure! I turned off autodetection in the release, +as a broken bios will be called too, maybe crashing the machine. Enforce +.B VESA +mode by putting a +.B chipset VESA +in the end of your +.IR libvga.config (5). + +Note that it will leave protected mode and call the cards bios opening the door to +many hazards. + +.SH 5. DETAILED COMMENTS ON CERTAIN DEVICE DRIVERS +This section contains detailed information by the authors on certain +chipsets. + +.SS AT3D (AT25) +Also known as Promotion at25. Popular as the 2D part of a voodoo rush +card. + +I have written a driver for this chipset, based on the XF86 driver for +this chipset. + +The programs that work with this driver include all the programs in +the demos directory, zgv and dvisvga (tmview). + +I believe it should be easy to make it work on AT24, AT6422. + +.SS ATI Mach32 +Please see +.BR svgalib.mach32 (7). + +.SS ATI Mach64 +The rage.c driver works only on mach64 based cards with internal DAC. +The driver might misdetect the base frequency the card uses, so if when setting +any svgalib modes the screen blanks, or complains about out of bound freqencies, +or the display is unsynced, then try adding the option +.BR RageDoubleClock +to the config file. + +.SS Chips and Technologies chipsets 65525, 65535, 65546, 65548, 65550, and 65554 (usually in laptops). +Please see +.BR svgalib.chips (7). + +.SS Tseng ET4000/ET4000W32(i/p) +Please see +.BR svgalib.et4000 (7). + +.SS Tseng ET6000 +I have only 2 Mbytes of memory on my ET6000 card, so I am not able to +get all possible modes running. I haven't even tried to do all of the +modes which I am capable of doing, but I am confident that I can +manage more modes when I have time. I have enough modes working to +make the card useful, so I felt it was worth while to add the driver +to svgalib now. + +Linear graphics is working on this card, both with and without +BACKGROUND enabled, and vga_runinbackground works. + +I decided it was best to quit working on more modes and try to get +acceleration and sprites working. + +My et6000 card is on a PCI bus. The card will run on a vesa bus, but +since I don't have one on my machine I couldn't develop vesa bus +handling. I quit if the bus is a vesa bus. + +I check for an et6000 card, which can be unequivocally identified. The +et4000 driver does not properly identify et4000 cards. It thinks the +et6000 card is an et4000, but can only run it in vga modes. + +I have found the following four modelines to be useful in +.B libvga.config +or in +.B ~/.svgalibrc +for proper display of some modes. + +.br +Modeline "512x384@79" 25.175 512 560 592 640 384 428 436 494 +.br +Modeline "400x300@72" 25.000 400 456 472 520 300 319 332 350 DOUBLESCAN +.br +Modeline "512x480@71" 25.175 512 584 600 656 480 500 510 550 +.br +Modeline "400x600@72" 25.000 400 440 488 520 600 639 644 666 + +Don Secrest Aug 21, 1999 + + +.SS Oak Technologies OTI-037/67/77/87 +First a few comments of me (Michael Weller ): + +As of this writing (1.2.8) fixes were made to the oak driver by +Frodo Looijaard to reenable OTI-067 support. It is unknown +right now if they might have broken OTI-087 support. The author of the '87 +support Christopher Wiles owns no longer an OTI-087 card and +can thus no longer give optimal support to this driver. Thus you might be +better off contacting me or Frodo for questions. If you are a knowledgable +OTI-087 user and experience problems you are welcome to provide fixes. +No user of a OTI-087 is currently +known to me, so if you are able to fix problems with the driver please do so +(and contact me) as noone else can. + +Michael. + +Now back to the original Oak information: + +The original OTI driver, which supported the OTI-067/77 at 640x480x256, +has been augmented with the following features: + +.TP +.B 1) +Supported resolutions/colors have been expanded to 640x480x32K, +800x600x256/32K, 1024x768x256, and 1280x1024x16. +.TP +.B 2) +The OTI-087 (all variants) is now supported. Video memory is +correctly recognized. +.PP + +The driver as it exists now is somewhat schizoid. As the '87 +incorporates a completely different set of extended registers, I found it +necessary to split its routines from the others. Further, I did not have +access to either a '67 or a '77 for testing the new resolutions. If +using them causes your monitor/video card to fry, your dog to bite you, +and so forth, I warned you. The driver works on my '87, and that's all I +guarantee. Period. + +Heh. Now, if someone wants to try them out ... let me know if they work. + +New from last release: + +32K modes now work for 640x480 and 800x600. I found that the Sierra DAC +information in VGADOC3.ZIP is, well, wrong. But, then again, the +information for the '87 was wrong also. + +64K modes +.B do not +work. I can't even get Oak's BIOS to enter those modes. + +I have included a 1280x1024x16 mode, but I haven't tested it. My monitor +can't handle that resolution. According to the documentation, with 2 +megs the '87 should be able to do an interlaced 1280x1024x256 ... again, +I couldn't get the BIOS to do the mode. I haven't 2 megs anyway, so +there it sits. + +I have included routines for entering and leaving linear mode. They +.B should +work, but they don't. It looks like a pointer to the frame +buffer is not being passed to SVGALIB. I've been fighting with this one +for a month. If anyone wants to play with this, let me know if it can be +make to work. I've got exams that I need to pass. + +Tidbit: I pulled the extended register info out of the video BIOS. When +the information thus obtained failed to work, I procured the OTI-087 data +book. It appears that Oak's video BIOS sets various modes incorrectly +(e.g. setting 8-bit color as 4, wrong dot clock frequencies, etc.). Sort +of makes me wonder ... + +Christopher M. Wiles (a0017097@wsuaix.csc.wsu.edu) +.br +12 September 1994 + +.SH 6. GOALS + +I think the ability to use a VGA/SVGA graphics resolution in one +virtual console, and being able to switch to any other virtual console +and back makes a fairly useful implementation of graphics modes in +the Linux console. + +Programs that use +.B svgalib +must be setuid root. I don't know how +desirable it is to have this changed; direct port access can hardly +be done without. Root privileges can now be given up right after +initialization. I noticed some unimplemented stuff in the kernel +header files that may be useful, although doing all register I/O via +the kernel would incur a significant context-switching overhead. An +alternative might be to have a pseudo +.I /dev/vga +device that yields +the required permissions when opened, the device being readable by +programs in group vga. + +It is important that textmode is restored properly and reliably; it +is fairly reliable at the moment, but fast console switching back +and forth between two consoles running graphics can give problems. +Wild virtual console switching also sometimes corrupts the contents +of the textmode screen buffer (not the textmode registers or font). +Also if a program crashes it may write into the area where the saved +textmode registers are stored, causing textmode not be restored +correctly. It would be a good idea to somehow store this information +in a 'safe' area (say a kernel buffer). Note that the +.BR vga_safety_fork (3) +thing has the same idea. + +Currently, programs that are in graphics mode are suspended while +not in the current virtual console. Would it be a good idea to let +them run in the background, virtualizing framebuffer actions (this +should not be too hard for linear banked SVGA modes)? It would be +nice to have, say, a raytracer with a real-time display run in the +background (although just using a separate real-time viewing +program is much more elegant). + +Anyone wanting to rewrite it all in a cleaner way (something with +loadable kernel modules shouldn't hurt performance with linear +framebuffer/vgagl type applications) is encouraged. + +Also, if anyone feels really strongly about a low-resource and +truecolor supporting graphical window environment with cut-and-paste, +I believe it would be surprisingly little work to come up with a +simple but very useful client-server system with shmem, the most +useful applications being fairly trivial to write (e.g. shell +window, bitmap viewer). And many X apps would port trivially. + +This is old information, please be sure to read +.BR svgalib.faq (7) +if you are interested in further goals. + +.SH 7. REFERENCES + +The latest version of svgalib can be found on +.IR sunsite.unc.edu " in " /pub/Linux/libs/graphics +or +.IR tsx-11.mit.edu " in " /pub/linux/sources/libs +as +.IR svgalib-X.X.X.tar.gz . +As of this writing the latest version is +.IR svgalib-1.4.1.tar.gz . +There are countless mirrors of these ftp servers in the world. Certainly +a server close to you will carry it. + +The original VGAlib is on +.IR tsx-11.mit.edu ", " pub/linux/sources/libs/vgalib12.tar.Z . +.I tvgalib-1.0.tar.Z +is in the same directory. + +SLS has long been distributing an old version of VGAlib. +Slackware keeps a fairly up-to-date version of svgalib, but it +may be installed in different directories from what svgalib likes +to do by default. The current svgalib install tries to remove most +of this. It also removes +.IR /usr/bin/setmclk " and " /usr/bin/convfont , +which is a security risk if setuid-root. Actually the recent makefiles try to do +a really good job to cleanup the mess which some distributions make. + +If you want to recompile the a.out shared library, you will need the +DLL 'tools' package (found on +.IR tsx-11.mit.edu ", " GCC " dir)." +To make it work with recent ELF compiler's you actually need to hand patch it. You +should probably not try to compile it. Compiling the ELF library is deadly simple. + +And here is a list of other references which is horribly outdated. +There are many more svgalib applications as well as the directories might have changed. +However, these will give you a start point and names to hunt for on CD's or in +ftp archives. + +.SS Viewers (in /pub/Linux/apps/graphics/viewers on sunsite.unc.edu): + +.PD 0 +.TP +.B spic +Picture viewer; JPG/PPM/GIF; truecolor; scrolling. +.TP +.B zgv +Full-featured viewer with nice file selector. +.TP +.B see-jpeg +Shows picture as it is being built up. +.TP +.B mpeg-linux +svgalib port of the Berkeley MPEG decoder (mpeg_play); it also includes an X binary. +.TP +.B flip +FLI/FLC player (supports SVGA-resolution). +.PD +.PP +.SS Games (in /pub/Linux/games on sunsite.unc.edu): + +.PD 0 +.TP +.B bdash +B*lderdash clone with sound. +.TP +.B sasteroids +Very smooth arcade asteroids game. +.TP +.B yatzy +Neat mouse controlled dice game. +.TP +.B vga_cardgames +Collection of graphical card games. +.TP +.B vga_gamespack +Connect4, othello and mines. +.TP +.B wt +Free state-of-the-art Doom-like engine. +.TP +.B Maelstrom +A very nice asteroids style game port from Mac. +.TP +.B Koules +A game. (I've no idea what it looks like) +.PD +.PP +.SS Docs +In the vga directory of the +.B SIMTEL MSDOS +collection, there is a +package called +.I vgadoc3 +which is a collection of VGA/SVGA register +information. + +The XFree86 driver sources distributed with the link-kit may be +helpful. + +.SS Miscellaneous + +There's an alternative RAW-mode keyboard library by Russell Marks for +use with +.B svgalib +on +.IR sunsite.unc.edu . + +.BR LIBGRX , +the extensive framebuffer library by Csaba Biegl distributed +with +.BR DJGPP , +has been ported to Linux. Contact Hartmut Schirmer +(phc27@rz.uni-kiel.d400.de, subject prefix "HARTMUT:"). A more +up-to-date port by Daniel Jackson (djackson@icomp.intel.com) is on +.IR sunsite.unc.edu . + +The vgalib ghostscript device driver sources can be found on +.IR sunsite.unc.edu ", " /pub/Linux/apps/graphics . +Ghostscript patches from Slackware: +.IR ftp.cdrom.com ", " /pub/linux/misc . +.B gnuplot +patches are on +.IR sunsite.unc.edu . + +Mitch D'Souza has written font functions that work in 16 color modes +and can use VGA textmode (codepage format) fonts; these can be found +in his +.B g3fax +package in +.IR sunsite.unc.edu . +These functions may go into a later +version of +.BR svgalib . + +.SH 8. KNOWN BUGS +This section is most probably outdated, none of these problems are no longer +reported. + +Using a 132 column textmode may cause graphics modes to fail. Try +using something like 80x28. + +The console switching doesn't preserve some registers that may be +used to draw in planar VGA modes. + +Wild console switching can cause the text screen to be corrupted, +especially when switching between two graphics consoles. + +On ET4000, having run XFree86 may cause high resolution modes to +fail (this is more XFree86's fault). + +The Trident probing routine in the XFree86 server may cause standard +VGA modes to fail after exiting X on a Cirrus. Try putting a 'Chipset' +line in your Xconfig to avoid the Trident probe, or use the link kit +to build a server without the Trident driver. Saving and restoring +the textmode registers with savetextmode/textmode (restoretextmode) +should also work. [Note: svgalib now resets the particular extended +register, but only if the Cirrus driver is used (i.e. the chipset +is not forced to VGA)] [This is fixed in XFree86 v2.1] + +Some Paradise VGA cards may not work even in standard VGA modes. Can +anyone confirm this? + +Piping data into a graphics program has problems. I am not +sure why. A pity, since zcatting a 5Mb FLC file into flip on a 4Mb +machine would be fun. + +The +.B tseng3.exe +DOS program include as source in the svgalib distribution doesn't recognize any modes on +some ET4000 cards. +Also ET4000 cards with a Acumos/Cirrus DAC may only work correctly +in 64K color mode. + +.SH FILES +.IR /etc/vga/libvga.config +.br +.IR /etc/vga/libvga.et4000 + +.SH SEE ALSO +.BR svgalib.et4000 (7), +.BR svgalib.chips (7), +.BR svgalib.mach32 (7), +.BR vgagl (7), +.BR libvga.config (5), +.BR 3d (6), +.BR accel (6), +.BR bg_test (6), +.BR eventtest (6), +.BR forktest (6), +.BR fun (6), +.BR keytest (6), +.BR lineart (5), +.BR mousetest (6), +.BR joytest (6), +.BR mjoytest (6), +.BR scrolltest (6), +.BR speedtest (6), +.BR spin (6), +.BR testaccel (6), +.BR testgl (6), +.BR testlinear (6), +.BR vgatest (6), +.BR plane (6), +.BR wrapdemo (6), +.BR convfont (1), +.BR dumpreg (1), +.BR fix132x43 (1), +.BR restorefont (1), +.BR restorepalette (1), +.BR restoretextmode (1), +.BR runx (1), +.BR savetextmode (1), +.BR setmclk (1), +.BR textmode (1), +.BR mach32info (1). + +.SH AUTHOR +There are many authors of svgalib. This page was edited by +Michael Weller . +The original documentation and most of +.B svgalib +was done by Harm Hanemaayer though. diff --git a/doc/man7/svgalib.chips.7 b/doc/man7/svgalib.chips.7 new file mode 100644 index 0000000..b149596 --- /dev/null +++ b/doc/man7/svgalib.chips.7 @@ -0,0 +1,249 @@ +.TH svgalib.chips 7 "31 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +svgalib.chips \- Information for Chips and Technologies Users + +.SH TABLE OF CONTENTS + +Information for Chips and Technologies Users +.br +David Bateman +.br +23nd May 1997 + +.BR 0. " Introduction" +.br +.BR 1. " ""libvga.config"" options" +.br +.BR 2. " Unsupported Chips and Technologies chipsets" +.br +.BR 3. " Known bugs" +.br + +.SH 0. INTRODUCTION + +This is the really only my first attempt to get a working fully +featured driver for the Chips and Technologies chipset to work +with +.BR svgalib (7). +As such the only machine that I know it will work +on is my own. If you use this software then at this point I'm still +very interested in hearing from you by e-mail. Include full details +of your chipset, amount of videoram and whether you have a VL-Bus +or PCI bus machine. + +This server was written using the +.BR svgalib (7) +patch from Sergio and +Angelo Masci as a starting point. This version of the code resembled +the XFree server code that was used up to XFree 3.1.2. As such it was +incapable of programming the clocks, using linear addressing, Hi-Color, +True-Color modes or the hardware acceleration. All of these features +have since been added to the code. In addition support for the 65525, +65535, 65546, 65548, 65550 and 65554 have been included. The 64200 and +64300 chips are unsupported, however these chips are very similar to +the 6554x chips which are supported. + +At this point this code is only confirmed to work correctly on a +65545 VL-Bus machine. However as much of the code was stolen from +my experiences with writing code for XFree I hope not to have too +many problems with other machines. However if you run this code +on a 65545/48 PCI machine or a 65550/54 machine then I am particularly +interested in hearing of any success or failure stories. + +.SH 1. """libvga.config""" OPTIONS + +The first thing to note is that the option parser for +.BR svgalib (7) +is not +very robust. Hence if you make some typing mistakes, you can have +some very strange effects. I've set out below the +.BR libvga.config (5) +options +that are of particular interest to Chips and Technologies users. Normally +this configuration file can be found at +.IR /etc/vga/libvga.config. + +.TP +.B HorizSync MIN MAX +Often LCD panels has very different specifications for the +horizontal sync than CRT's do. Hence often you'll need this option, +particularly if you are using the XFree like modelines described +below. The two floating point numbers specified will set the minimum +and maximum allowed horizontal sync in kHz. + +.TP +.B VertRefresh MIN MAX +Similar to the above, but this sets the LCD or CRT's vertical refresh +rate in Hz. + +.TP +.B modeline "640x480" 20.00 640 688 704 776 480 480 481 486 +This option allows you to specify XFree like modelines to use +in preference to the in built modelines. Often LCD panels will +need very different pixel clocks and timings than CRT's. Hence +this option allows you to specify these. Note that the LCD panel +timings are related to the panel size and not the mode size. +Therefore by default the BIOS setting already uploaded into the +registers are used by default. See the "UseModeline" option +below if you wish to override these. + +.TP +.B chipset C&T 5 1024 +These option allows the user to specify the chipset to use and +the amount of installed memory in kBytes. Currently supported +chipsets are + + 0 65520 + 1 65525 + 2 65530 + 3 65535 + 4 65540 + 5 65545 + 6 65546 + 7 65548 + 8 65550 + 9 65554 + +.TP +.B TextClockFreq 25.175 +One major difference between this code and the previously available +support for the Chips and Technologies chipsets is that it supports +the use of programmable clocks. Because of the way that the Chips +and Technologies chips program the VCO from the registers, there is +no way to be sure to recover the previously programmed clock value. +Hence the driver assumes that the console clock is 25.175MHz. This +will be wrong for many machines. However I have supplied this option +to use a different value that might be more suitable for your machine. + +.TP +.B nolinear +This option disables the use of the linear framebuffer. This might +be useful for machines that have broken linear framebuffers. In +lar the linear framebuffer doesn't seem to work with the +achines. + +.TP +.B linear +Allow, but don't enforce the use of the linear framebuffer. As this +is the default anyway, I don't see that this option is much use. + +.TP +.B setuplinear 0xC0000000 +For VL-Bus machines I expect that the linear framebuffer starting +address will be setup correctly. However to get the starting address +for PCI machines requires access to the MEMBASE register in the PCI +address space. Code to do this doesn't currently exist with +.BR svgalib (7), +and so I've taken the easy option of just testing a few known PCI +starting addresses. For now these are just 0xFE000000, 0xFD000000, +0x41000000 and 0xC0000000. If you have a different starting address +then the linear framebuffer will be unusable. You might like to report +your starting address to me so that I can include it in the probing +code, but till then this option can be used to set up the correct +address. This option just forces the given address to be the only one +probed. It doesn't force the linear framebuffer to be used. + +.TP +.B LCDPanelSize 800 600 +For some machines the LCD panel size is incorrectly probed from +the registers. This option forces the LCD panel size to be +as specified. If you have a black band down one side of your +LCD display you might very well need this option. Also if you +are using the option "fix_panel_size" in XFree then this option +has a similar effect. This option can be used in conjunction with +the option "UseModeline" to program all the panel timings using +the modeline values. Two machines that are known to need this +option are the HP Omnibook 5000CTS and the NEC Versa 4080 +800x600 TFT machines. + +.TP +.B UseModeline +The flat panel timings are related to the panel size and not the +size of the mode specified. For this reason the default behaviour +of the +.BR svgalib (7) +is to use the panel timings already installed in the +chip. The user can force the panel timings to be recalculated from +the modeline with this option. However the panel size will still be +probed. Two machines that are known to need this option are the +HP Omnibook 5000CTS and the Prostar 8200. You are advised to check +the README.chips that come with XFree for more details. + +.TP +.B NoBitBlt +This option disables the use of H/W acceleration. As far as I know +the only thing that currently uses the H/W acceleration is libvgagl, +so this might not be a problem anyway. However if you see corruption +of the graphics on the screen try this option and see if it goes +away. + +.TP +.B Use18BitBus +For 24bpp on TFT screens, the server assumes that a 24bit bus is +being used. This can result in a reddish tint to 24bpp mode for +machines that actually have a 18 bit bus. This option, selects an +18 bit TFT bus. Note that using this option with a 24 bit bus machine +will similarly discolour the screen. For other depths this option +has no effect. + +.TP +.BR "Center ENABLE/DISABLE" " or " "Stretch ENABLE/DISABLE" +The default behaviour of +.BR svgalib (7) +is to leave the stretching and +centring registers completely alone. However for some machines +this might result in poorly placed modes, or modes that don't +fill the whole screen. These two options can be used to centre +and stretch the mode on the screen. Note that for instance a +.B Center DISABLE +might follow a +.B Center ENABLE +in the config file. Only the last option takes effect. + +.SH 2. UNSUPPORTED CHIPS AND TECHNOLOGIES CHIPSETS + +The 64200 and 64300 chips are unsupported. However by specifying the +chipset in your +.I libvga.config +as either a + +.TP +.B chipset C&T 3 2048 +Use 65535 for a 64200 assuming 2M of video ram, or +.TP +.B chipset C&T 7 2048 +Use 65548 for a 64300 assuming 2Mb of video ram +.PP + +then svgalib can be made to give limited support to these chipsets. Note +that the paged addressing mode of the 65548 chip and earlier can only +address upto 1Mb of video ram. If the additional memory is needed then +linear addressing must be used!! Note that support of the 64xxx chips +has not been tested at all, and the above is just a suggestion that I +believe will work. + +.SH 3. KNOWN BUGS + +One persistent and annoying bug is that the text mode stretching on +LCD displays is not always restored correctly for 65550 and 65554 +machines. This is to do with the manner in which the extended registers +are restored and what is being done with the synchronous reset while +the registers are restored. As I don't have a 65550 or 65554 machine +of my own on which to test this code, I have been unable to fix this +problem. In most circumstances an LCD-CRT switch will restore the +LCD stretching to the desired state. + +David. + +.SH FILES +.I /etc/vga/libvga.config + +.SH SEE ALSO +.BR svgalib (7), +.BR libvga.config (5). + +.SH AUTHOR +of the driver and this documentation is +David Bateman . +However, it was slightly reformatted by Michael Weller +. diff --git a/doc/man7/svgalib.et4000.7 b/doc/man7/svgalib.et4000.7 new file mode 100644 index 0000000..5c8af9e --- /dev/null +++ b/doc/man7/svgalib.et4000.7 @@ -0,0 +1,312 @@ +.TH svgalib.et4000 7 "31 July 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +svgalib.et4000, libvga.et4000 \- Information for Tseng ET4000 users + +.SH TABLE OF CONTENTS +.B NOTE: The ET4000 register layout changed stepping from +.B svgalib 0.98 to 0.99. See 8. Problems below first + + +.BR 1. " Basics of ET4000 cards" +.br +.BR 2. " How to configure " svgalib (7) +.br +.BR 3. " Creating card dependent register values" +.br +.BR 4. " Defining new modes" +.br +.BR 5. " Redefining standard modes" +.br +.BR 6. " Available examples" +.br +.BR 7. " ET4000/W32 support" +.br +.BR 8. " Problems" +.br +.BR 9. " Using dynamic loading with other cards" + +.SH 1. BASICS OF ET4000 CARDS + +Basicly all ET4000 cards are equal, some are even more equal ... + +The Chipset is well documented (by Tseng Labs and eg. the vgadoc2.zip) +and all graphics functions can be used the same way on different cards +(including the ET4000/W32 based ones). There are three important points +to be kept in mind: + +.TP +.B a.) +amount of available, the organisation and timing of video memory +.TP +.B b.) +type and capabilities of the DAC +.TP +.B c.) +available oscillator frequencies +.P + +.BR svgalib (7) +will check the available video memory during startup. This +should work on all DRAM cards. If there are any problems concerning +VRAM equipped cards, please tell us about. + +By now we found is no reliable way to detect the memory organisation/ +timing and the DAC type/capabilities. Most modern card use a frequency +synthizier and provide the following pixel frequencies (in MHz): + +.RS +.B 50.350 56.644 65.0 72.0 80.0 89.8 63.0 75.0 +.RE + +Checking older ET4000 cards we found a wide spread range of available +frequencies. Since the video timing is based on the pixel frequency, +the required register values are card dependent. + +.SH 2. HOW TO CONFIGURE SVGALIB + +.BR svgalib (7) +has a somewhat 'standard' registers set that may work with +modern ET4000 cards. If +.BR svgalib (7) +fails on your machine or you have +a HiColor dac, you need to configure your +.BR svgalib (7). + +The +.BR svgalib (7) +may use hard linked or dynamical linked register values. +If you use hard linked values, the binary will be smaller and start +up faster but might fail on other machines. + +Compiling the +.BR svgalib (7) +with DYNAMIC defined (see +.IR Makefile.cfg ) +will set up dynamic register loading. Otherwise the value from +.I svgalib/et4000.regs +will be hard linked. + +The dynamic configuration will be read from +.I /etc/vga/libvga.et4000 +which is an ASCII file (see +.I Makefile.cfg +for exact naming). If you have +a working et4000.regs for your system just copy this file to +.IR /etc/vga/libvga.et4000 " or link " /etc/vga/libvga.et4000 +to your +.I svgalib/et4000.regs +file. + +The actual scanner/parser will handle the following entries: + +.TP +.B #define DAC_TYPE +Overwrite the DAC detection +.TP +.B #define +Enable MODE1 using MODE2 registers, eg. 64K modes like 32K modes +.TP +.B #define DISABLE_MODE +do not use MODE (eg. from vgadrv) +.TP +.B char [..] = {, , ... }; +register definition +.PP +with + +.B " ::= 'g'xx" +.br +.B " ::= |" +.br +.B " ::= '0x'{}" +.br +.B " ::= ['+'|'-']{}" +.br +.B "::= |'a..f'|'A..F'" +.br +.B " ::= '0..9'" +.br +.B " ::= '2'|'16'|'256'|'32k'|'32K'|'64k'|'64K'|'16M'" +.br +.B " ::= |[(|'_'){||'_'}]" +.br +.B " ::= 'a..z'|'A..Z'" + +C style comments will be skipped. See the +.I et4000/ +subdirectory of the svgalib distribution for examples. + +.SH 3. CREATING CARD DEPENDENT REGISTER VALUES + +You may create a +.I et4000.regs on your own with the +.IR tseng3.exe +program. This DOS program and its source is included in the svgalib +distribution. + +Just boot MS-DOS and start + +.B tseng3 et4000.reg + +The +.I tseng3.exe +will measure the video timing for each available mode. +Check the +.I et4000.regs +file against your monitor documentation and +disable all non conformant modes, eg. + +.B #define g1024x768x256_regs DISABLE_MODE +.br +.B /* +.br +.B static unsigned char g1024x768x256_regs[71] = { +.br +.B ... +.br +.B }; +.br +.B */ + +will disable the 1024x768x256 mode. You +.B mustn't +disable the 640x480x256 mode! + +Your +.I et4000.regs +.I must define the following symbols (register values +or +.BR "#define ... DISABLE_MODE" ) +for hard linking: + +.BR g320x200x32K_regs ", " g640x400x256_regs ", " g640x480x256_regs ", " +.BR g640x480x32K_regs ", " g640x480x16M_regs ", " g800x600x16_regs ", " +.BR g800x600x256_regs ", " g800x600x32K_regs ", " g1024x768x16_regs ", " +.BR g1024x768x256_regs ", and " g1280x1024x16_regs . + +and all 64K modes handled like 32K modes by the driver: + +.B #define g320x200x64K_regs g320x200x32K_regs +.br +.B #define g640x480x64K_regs g640x480x32K_regs +.br +.B #define g800x600x64K_regs g800x600x32K_regs + +You may omit every unusable mode in +.IR /usr/lib/libvga.et4000 . + +.SH 4. DEFINING NEW MODES + +All standard +.BR svgalib (7) +modes may be selected by the mode constants +defined in +.B #include +(eg. +.BR G320x200x16 ). +You may define new modes on +your own. Just use dynamic register loading and add the register +definition of the new mode. Your program may determine the related +modenumber by checking the vga_getmodeinfo(1..vga_lastmodenumber()). + +Most ET4000 cards provide 640x350 and 640x400 graphics modes. The +.I tseng3.exe +generates the related register sets. You may also use +.BR dumpreg (1) +from an X window to grab you favourite X graphics mode. +The X mode normaly isn't usable directly. See +.I cardex.w32 +for an example and +.I et4000.c +for a brief description of et4000 registers (both files are included in the +svgalib distribution). + +.SH 5. REDEFINING STANDARD MODES + +Using dynamic register loading you may redefine any standard VGA +mode except of TEXT and 640x480x16. Just add the ET4000 specific +register set to +.IR /etc/vga/et4000.regs . + +.SH 6. AVAILABLE EXAMPLES + +In the +.I et4000/ +subdir of teh svgalib distribution you'll find some sample register sets: + +.TP +.B cardex.w32 +Cardex ET4000/W32 card, Music TrueColor DAC +.TP +.B speedstar+ +SpeedSTAR PLUS card, Normal DAC +.TP +.B orchid.pdII +Orchid Prodesigner II +.PP + +.SH 7. ET4000/W32 SUPPORT + +The actual driver seems to be ET4000/W32 compatible. Tell us about +any problems (and solutions). If you've got any information about +the ET4000/W32 blitter, we would be pleased to receive it. + +.SH 8. PROBLEMS + +As mentioned before, the DAC detection isn't very reliable. +.BR vgatest (6) +should print equal screens in 256 color and HiColor/TrueColor modes. +You may have to edit your +.I libvga.et4000 +register file by hand to setup the correct DAC. + +The +.I tseng3.exe +may fail due to incompatible mode numbering. You might use +a VESA driver (eg. tlivesa.com from VPIC 6.0) or edit and recompile +the +.IR tseng3.exe . + +Newer ET4000 chipsets (eg. W32 and W32i) allow up to 32 clock +frequencies. Two additional register values were added just before the +old extened register value. The new registers are CRTC/30h and CRTC/31h. +The old register set had 71 values, the new growed to 73. +You may update your old register set by hand: + +.IP - +run the dumpreg program, remember the first two values from last +data line. +.IP - +edit your libvga: +.RS +for each mode +.RS +change the number of register values from 71 to 73 +.br +add the values from dumreg output at front of last data line +.RE +.RE +.IP - +run .BR vgatest (6) +to check the new register set + +.SH 9. USING DYNAMIC LOADING WITH OTHER CARDS + +The dynamical register loading may be used in other drivers. +Since hard linked register values work fine for Cirrus and Trident +cards, we didn't include this feature. + + +.SH FILES +.I /etc/vga/libvga.config +.br +.I /etc/vga/libvga.et4000 + +.SH SEE ALSO +.BR svgalib (7), +.BR libvga.config (5). + +.SH AUTHOR +This documentation for the ET4000 registers was provided by Hartmut Schirmer. +However, it was slightly reformatted by Michael Weller +. diff --git a/doc/man7/svgalib.faq.7 b/doc/man7/svgalib.faq.7 new file mode 100644 index 0000000..6abef52 --- /dev/null +++ b/doc/man7/svgalib.faq.7 @@ -0,0 +1,336 @@ +.TH svgalib.faq 7 "10 Jun 1999" "Svgalib 1.4.1" "Svgalib User Manual" +.SH NAME +svgalib.faq \- frequently asked questions about svgalib + +.SH INTRODUCTION +I (Matan Ziv-Av), added/changed some of the answers in this file, so some +answers are mine, and some are Michael's. + +List of (recently) frequently asked questions about svgalib. Esp. about +it's status and future. Please note that as of now all answers are just +written by me, Michael Weller . I'd like +this to change. So email your suggestion (best of all: question and the +answer). + +Also, most questions deal with the status and future and my ideas about +it. Necessarily they contain my own private opinions on this. People may +disagree and I'm sure I don't have the best ideas about it or may even +be completely wrong. I don't want to force anyone to agree with me. + +Also, I was asked about MY opinions, so I'm just presenting them here. + +.SH CONTENTS +.TP +.B Q 1) +I want to write some svgalib application. Where is the documentation? +.TP +.B Q 2) +My board is not supported. What now? +.TP +.B Q 3) +I get: + +.B You must be the owner of the current console to use svgalib. +.br +.B Not running in a graphics capable console, and unable to find one. + +However, though logged in not directly from the linux console, I +am the owner of the console. +.TP +.B Q 4) +Is svgalib dead? +.TP +.B Q 5) +There are so many Xfree drivers, why not just use them. +.TP +.B Q 6) +Why not just use the VGA BIOS?. +.TP +.B Q 7) +What about GGI? +.TP +.B Q 8) +Why not just use X11? +.TP +.B Q 9) +Now, again, what about the future of svgalib? +.TP +.B Q 10) +Ok, just for completeness, what are your plans about svgalib anyway? +.TP +.B Q 11) +Nice plan. But will it become true? +.PP + +.SH THE QUESTIONS +.SS Q 1) +I want to write some svgalib application. Where is the documentation? + +.SS A a) +Well, did you really look at everything? The +.I 0-README +file in the top +level directory contains all function prototypes and explanations on +how to call them. + +Yes, the documentation is short and/or confusing. Sorry, English is +not my native tongue. Many people complain and want to write some +better documentation. You are welcome to do so! However, up to now, +either people found the documentation sufficient once they looked at +the correct files or they just gave up. At least, I never heard from +these people again. + +Also, svgalib comes with source. If in doubt: read it. + +Finally: Linux distributions include svgalib, but not the source and +README's (or hide them so good noone finds them). Well, no problem, +get full svgalib source, demos, readme's from svgalib-*.tar.gz on +any Linux FTP server in your vicinity. Even if you don't dare to install +or compile it, it contains the readme's. + +Oh yes, there are some simple demos in the +.I demos/ subdir. They should +get you started. + +When someone writes +.BR man (1) +manual pages, a distribution might just install +them. Please do not complain, write them, mail them to me. + +.SS A b) +Finally, I, Michael Weller wrote the manpages. Looking at +.BR svgalib (7) +should get you started. Additions and corrections are still welcome, of course. + +.SS Q 2) +My board is not supported. What now? + +.SS A) +Simple: + +.TP +.B a) +Contact the maintainers (see other README's) and check out if +someone is working on a driver. + +.TP +.B b) +If so, contact them if you like and announce you'd be willing to +test things or even help coding. + +.TP +.B c) +If not, write a driver. Get as many docs on your card as you can, +then read and understand the internals of svgalib (again read the +README's carefully!). +.PP + +Please understand that this is a free project. I will not go and buy +a similar card and write a driver for you. I already wrote support for +the hardware I have! I just do this as a hobby. Because I don't get +paid for this I can not just buy card & docu and spend much much time +supporting whatever graphics card on earth exists. + +Also read below on the future of svgalib. + +If you don't feel able to write a driver for whatever reason, please +do not complain if other people don't do it for you (because you are +not better than they are). + +.SS Q 3) +I get: + +.B You must be the owner of the current console to use svgalib. +.br +.B Not running in a graphics capable console, and unable to find one. + +However, though logged in not directly from the linux console, I +am the owner of the console. + +.SS A) +Alas, some programs use their suid root privilege and become a full +root owned process. svgalib thinks they are run by root which does +not own the current console. +Defining +.B ROOT_VC_SHORTCUT +in +.I Makefile.cfg +and recompiling will allow +svgalib to allocate a new VC. However, it will allow any person which +is able to exec that program to start in on a new console. Even if not +logged in from the console at all. Thus, for security, you need to +explicitly enable that root feature. + +.SS Q 4) +Is svgalib dead? + +.SS A) +This question comes up frequently esp. in recent times. + +The answer is, of course, no. + +.SS Q 5) +There are so many Xfree drivers, why not just use them. + +.SS A) +Well, actually much of the code in there is actually already used by +svgalib. Xfree coders worked on svgalib and vice versa. But honestly, do +not expect that a driver from Xfree can just be used for svgalib. The +internal structures of Xfree and svgalib (and GGI) are just too +different. As a source of knowledge and for one or the other subroutine, +the Xfree sources are invaluable however. + +.SS Q 6) +Why not just use the VGA BIOS?. + +.SS A) +Actually, we do. There is now, thanks to Josh Vanderhoof, a VESA driver. +The VESA driver does not work on all cards, even though it should. +It does not even work on all cards where vbetest works. If vbetest does +not work it means the bios writers assumed it would always run in DOS, and +used tricks (for delay, etc.) that can't work under Linux. If vbetest works, +but the VESA driver does not, I (Matan Ziv-Av) believe it is due to the +following reason: +The driver use VESA function 4 (save/restore video state). This function +can't be used in a singletasking environment (DOS) and as such, some bios +writers failed to implement it properly, and all the tests (which are run +under DOS) failed to discover this. + +The VESA driver does work with many cards though. + +.SS Q 7) +What about GGI? + +.SS A) +Yes, GGI. Another long story. At first: Yes, I like the idea of an +in kernel graphics driver. I like it very much. And, yes, this is a +bit weird because I am the svgalib maintainer and a working GGI will make +svgalib obsolete. Again, I already said above: I did not invent svgalib +nor do I promote it as +.B the +solution (now compare this to GGI). It just +does what it does and works for me and some other people. + +I liked this idea so much, I even started coding a frame buffer device +once. After a short time, other people came out with the GGI idea. Right +from their beginning they claimed to be the only source of wisdom. I +tried to join our efforts, but failed. In general we have the same +goals (read the GGI project pages for that). + +Anyhow, at that time a flame war started. I don't really know why. I +don't see I did anything else than offering my opinions, work and +experience. But that should be judged by others. + +Well, after some time I stopped bothering them. I was satisfied to learn +later though that they actually came up with some conclusions I proposed +first but weeks or months later. But let us leave the past alone. + +.PP +When intending to contribute to svgalib, you should think about what you +really want. I don't see that GGI is becoming available soon. GGI people +told me the opposite again and again, ok, I still don't see it. Still +out of a sudden, everything might be GGI infested, so you might consider +contributing to GGI instead. + +With svgalib you might be able to use your fruits earlier. And anyone +(with supported hardware) can just use it right away without reinstalling kernel/X11 +what else (maybe being unable to use something he did before). + +.SS Q 8) +Why not just use X11? + +Yes, this is what many people say. This is the common Unix way to do it. +X does it. + +But X has some drawbacks: + +.IP i) +It uses many resources. Admittedly this is becoming of lesser +importance now, where you can run a sensible X11 Linux system on +8MB (16 MB for heaven like performance) which is the absolute minimum +to get a simple text editor running under M$ windows. + +Still, an advantage of Linux is the ability to use old hardware for +mission critical background jobs on the net +(servers/routers/firewalls) on low price or otherwise even unusable +hardware. + +.IP ii) +X has a nice API with draw commands for any kind of 'command oriented' +screen output. I mean with that: Select a color, draw a line, polygon, +etc. + +This imposes a bunch of overhead. If you just want access to the +screen memory, it slows things down as hell. If you want just to use +above's draw commands, it is ok! + +.IP iii) +One can now circumvent the API restrictions by getting direct +screen access using a special Xfree extension. Basically Xfree just +setups the screen and gives you shared memory access to the screen +memory. IMHO, this is not much different from the shared memory X11 +extension by MIT (which is probably why it was added so easily). +Still it needs quite some overhead, at least when the card does not +allow for a linear frame buffer. + +However, you cannot change screen modes and rez as easily. This is +IMHO THE drawback of X. For a picture viewer, you want 256 color +high/true color modes on a per picture basis (also, insert any other +application you like: movie viewers, a special game, a drawing +program). Also, you want a small picture use a low rez s.t. it does +not appear as a thumbnail, maybe use a high rez mode for a huge +picture which you don't want to use on a permanent basis because +it flickers like hell (and you don't want to use a panning virtual +desktop too, I hated them at best). + +This latter restriction can of course be circumvented by enlarging +the picture. But this will need much time for a picture viewer +already and certainly too much for smooth video or game animations. + +.IP iv) +Finally, the problem how X11 itself accesses the screen is not solved. +Security is usually no concern because X11 does it, is a trusted +executable and a firewall between applications and the hardware. + +Alas, there might be security holes, also the stability and +performance issues (IRQ driven accelerator queue, CPU support for +VGA memory paging) still exist, though one can expect an Xserver +to be a generally well coded application. + +.SS Q 9) +Now, again, what about the future of svgalib? + +For console graphics, svgalib is still the only solution for most people, +and as such it should go on for a while. Compared to the other console +graphics options (kgi and kernel fb device), writing svgalib driver is the +simplest (at least, this is my experience), and so it makes sense to believe +that svgalib will work on all cards where there is someone interested enough +in that support. + +.SS Q 10) +Ok, just for completeness, what are your plans about svgalib anyway? + +First, make svgalib cooperate nicely with kernel fb device. Then (and it should +be very similiar) make svgalib work on a secondary vga card. + +A rewrite of the code for memory handling and virtual console handling is necessary +for the previous goals, but is also necessary in itself, and so will be done +also. + +I do intend to maintain complete binary compatibility, so that older programs +will go on working. + +As internal changes are made, the drivers have to be changed as well. For some +of the older drivers (ali, ark, ati, et3000, et4000, gvga, oak), I no longer get +any reports, so I don't know if they still work. Some features are also lost, +for example, linear frame buffer on non-PCI cards. This should not be a very +big problem, as users with such cards can go on using 1.3.1, as most changes +are not applicable for older machines. + +.SH SEE ALSO +.BR svgalib (7), +.BR libvga.config (5). + +.SH AUTHOR +This file was written by Michael Weller , +And later changed by Matan Ziv-Av. diff --git a/doc/man7/svgalib.mach32.7 b/doc/man7/svgalib.mach32.7 new file mode 100644 index 0000000..b02c9e7 --- /dev/null +++ b/doc/man7/svgalib.mach32.7 @@ -0,0 +1,876 @@ +.TH svgalib.mach32 7 "1 August 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +svgalib.mach32 \- Information on the Mach32 chipset driver + +.SH TABLE OF CONTENTS +.BR " 0. " "Introduction" +.br +.BR " 1. " "Specifying pixel clocks" +.br +.BR " 2. " "Copyrights" +.br +.BR " 3. " "The mach32info utility" +.br +.BR " 4. " "Third party cards" +.br +.BR " 5. " "Logical linewidth" +.br +.BR " 6. " "Noisy video signals" +.br +.BR " 7. " "The configuration EEPROM" +.br +.BR " 8. " "EEPROM woes" +.br +.BR " 9. " "The Mach32Eeprom command" +.br +.BR "10. " "Setup of the memory aperture (linear framebuffer)" +.br +.BR "11. " "Accelerator support and other weird features" +.br +.BR "12. " "Ramdacs" +.br +.BR "13. " "Meaning of the detection message from svgalib" +.br +.BR "14. " "Conclusions" + +.SH 0. INTRODUCTION +The driver should allow you to use any of the graph-modes +your Mach32 card supports. Note that there is no support for +<8bpp modes and that I won't ever implement that because I don't see +any reason for doing so. All standard VGA-modes are supported, of course +(by using the standard VGA driver routines). + +If you configured your Mach32 for a memory aperture and it is +at least as big as the memory of your card (that is, not a 1MB +memory aperture for a 2MB card) support for linear frame buffer +access of svgalib is given. + +Auto detection of the Mach32 seems not to work on all cards. That's +really strange since I got the code from the X people. It should be OK +regardless of my docs. Well, I fixed that (hopefully). Actually +the bug was found by Daniel Lee Jackson (djackson@ichips.intel.com). +(Thanks again.. It was so silly... I would have never found it) +If you still have problems just put a chipset Mach32 in your config file. + +.SH 1. SPECIFYING PIXEL CLOCKS +.B WARNING! +The Mach32 driver needs to know correct clock frequencies for graceful +DAC configuration. Wrong clocks may damage your card! However, this version +contains code for automatic clock detection. Since clock detection is time +critical, please do it on a completely idle system. Then put the printed +out +.B clocks +line in your +.BR libvga.config (5) +file. + +The driver tries to do this for you. +After that, you can restart whatever svgalib program you used and you are +set. If you already put a +.B clocks +line in your config by hand, comment it +out to have the driver check your clocks. + +Since clock probing is time critical, values differ from time to time, you +may try it multiple times and see which values seem to be most exact. You +can also compare them with the standard clock chips for Mach32 cards in +.BR libvga.config (5)). + +The clock probing relies on the 7th clock being 44.9MHz as this is what Xfree does. +If this is not true (and it is not always), probing is hosed. See +.BR libvga.config (5) +for a list of the +.B clocks +used by common svgalib cards. + +.SH 2. COPYRIGHTS +Some tiny routines are copied from Xfree86. The clock detection code is almost +just copied. So I repeat the copyright statements for these parts here: + +Copyright 1992 by Orest Zborowski +.br +Copyright 1993 by David Wexelblat + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the names of Orest Zborowski and David Wexelblat +not be used in advertising or publicity pertaining to distribution of +the software without specific, written prior permission. Orest Zborowski +and David Wexelblat make no representations about the suitability of this +software for any purpose. It is provided "as is" without express or +implied warranty. + +.B Orest Zborowski and David Wexelblat disclaim all warranties with regard +.B to this software, including all implied warranties of merchantability and +.B fitness, in no event shall Orest Zborowski or David Wexelblat be liable +.B for any special, indirect or consequential damages or any damages +.B whatsoever resulting from loss of use, data or profits, whether in an +.B action of contract, negligence or other tortious action, arising out of +.B or in connection with the use or performance of this software. + +Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. +.br +Copyright 1993 by Kevin E. Martin, Chapel Hill, North Carolina. + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Thomas Roell not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. Thomas Roell makes no representations +about the suitability of this software for any purpose. It is provided +"as is" without express or implied warranty. + +.B Thomas Roell, Kevin E. Martin, and Rickard E. Faith disclaim all +.B warranties with regard to this software, including all implied +.B warranties of merchantability and fitness, in no event shall the authors +.B be liable for any special, indirect or consequential damages or any +.B damages whatsoever resulting from loss of use, data or profits, whether +.B in an action of contract, negligence or other tortious action, arising +.B out of or in connection with the use or performance of this software. + +Author: Thomas Roell, roell@informatik.tu-muenchen.de + +Rewritten for the 8514/A by Kevin E. Martin (martin@cs.unc.edu) +.br +Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu) +.br +Rewritten for the Mach32 by Kevin E. Martin (martin@cs.unc.edu) + +And here is my own copyright: + +This driver is free software; you can redistribute it and/or +modify it without any restrictions. This library is distributed +in the hope that it will be useful, but without any warranty. + +Copyright 1994 by Michael Weller + +Email addresses as of this writing: + +eowmob@exp-math.uni-essen.de mat42b@spi.power.uni-essen.de + +.B Michael Weller disclaims all warranties with regard +.B to this software, including all implied warranties of merchantability and +.B fitness, in no event shall Michael Weller be liable +.B for any special, indirect or consequential damages or any damages +.B whatsoever resulting from loss of use, data or profits, whether in an +.B action of contract, negligence or other tortious action, arising out of +.B or in connection with the use or performance of this software. + +.SH 3. THE MACH32INFO UTILITY +The +.BR mach32info (6) +utility or demo reads out all configuration registers and the configuration +EEPROM of your Mach32 card. If +there is a problem with the particular card you have, compile +and run the utility in the +.I mach32/ +directory of the svgalib distribution and send it's stdout to me +This might also be useful if you need a lot of options (e.g. clocks on new models?) to +get it to work so that this can be done automatically in future versions. + +.SH 4. THIRD PARTY CARDS +I got a few reports about AST systems with onboard Mach32. +They do feature an incompatible EEPROM setup, but I think I got around +that. Nevertheless the Mach32 chipset driver doesn't work out of the box +on any AST system I heard of. + +Since original ATI Mach32 demos and tools don't work as well, I've to claim +that the Mach32 on these AST systems does not conform to ATI's Mach32 docs. +Fortunately, Vernon C. Hoxie found a work around +after years (really!) of investigating. AST Mach32 seems to work now. The work around was +also submitted to Xfree and will be incorporated to allow running it on the +AST hardware too in recent versions. Please read on the +.B misc_ctl +command below. + +Dell users should have a look at the +.BR "vendor" ", " ramdac ", and " svgaclocks +commands below (if they have problems with the default settings). + +.SS Commands to support third party cards +I had to learn that those cards seem +to use not only non standard clocks for the Mach32, but also for the included +SVGA. However, since people often like to use proprietary, non standard VGA +(read 80x25) textmodes, the Mach32 driver has to set the included SVGA to +a VGA compatible clock frequency. Otherwise svgalib has problems using plain VGA +modes. This screws VGA modes up if these clocks have different values on third +party Mach32 cards. + +.TP +.BI "svgaclocks " n +with +.I n +a number between +.BR 0 " and " 31 +to select the svga clocks to be used in vga +modes. The bits of +.I n +refer to specific ATI register bits to complicated to +explain here. Even if I would, I can't tell which clocks they would select +on your third party card (which is the actual problem) + +.B svgaclocks 9 +is the default setting and correct for original ATI cards. + +Often +.B svgaclocks 0 +(Dell cards) works. +.TP +.B svgaclocks keep +is special in that the +driver will not touch any SVGA timings. This requires the Mach32 SVGA part to +be in a VGA compatible mode when the svgalib application is started, that is, +you must use 80x25 (maybe 80x50) console textmodes. +.PP + +As I mentioned already, +Vernon C. Hoxie really seems to have located the reason +for the Mach32 AST problems. Any access to +.B MISC_CTL +locks up the card & system. Fortunately +.B MISC_CTL +is only used for some DAC fine tuning (actually the setting you can +fine tune with the +.B blank +command) which is only of barely noticable effect to the screen. + +The following configuration commands exist to support AST cards: + +.TP +.B misc_ctl keep-off +Do not dare to touch MISC_CTL. +.TP +.B misc_ctl use +Use it for fine tuning of the Ramdac setup (default). +.PP + +Finally, for your convenience there exist: + +.PD 0 +.TP +.B vendor ati +.TP +.B vendor dell +.TP +.B vendor ast +.PD +These are macros that expand to settings for +.BR svgaclocks ", " ramdac ", " misc_ctl ", and " mach32eeprom +that are usually correct for ATI, Dell, AST cards. Be aware +that they really work like macros. That is, they override any setting +of +.BR svgaclocks ", " ramdac ", " misc_ctl ", and " mach32eeprom +made before them and individual aspects will be changed by a following +.BR svgaclocks ", " ramdac ", " misc_ctl ", and " mach32eeprom +command. + +Note that the +.B mach32eeprom ignore +required for some Dell cards requires +you to include explicit timings for Mach32 modes other than 640x480x256. +The +.I mach32/mach32.std-modes +file in the svgalib distribution contains recommendations for modes from ATI. + +I heard about a bug in some ATI chipsets returning wrong memory amounts +configs. (But cannot confirm that) + +You can enforce correct chipset identification from the configuration file: + +.TP +.BI "chipset Mach32 " "chiptype memory" +where +.I chiptype +is the sum of at exactly one value from each of the following two groups + +.PD 0 +.RS +.TP +.B 128 +use no memory aperture. +.TP +.B 160 +use a 1MB memory aperture. +.TP +.B 192 +use a 4MB memory aperture. +.TP +.B 0 +choose size for the memory aperture automatically. +.PD +.PP +and + +.PD 0 +.TP +.B 16 +Ramdac is of type 0 (ATI68830) +.TP +.B 17 +Ramdac is of type 1 (IMS-G173, SC11486) +.TP +.B 18 +Ramdac is of type 2 (ATI68875, TLC34075) +.TP +.B 19 +Ramdac is of type 3 (INMOS176, INMOS178) +.TP +.B 20 +Ramdac is of type 4 (Bt481, Bt482) +.TP +.B 21 +Ramdac is of type 5 (ATI68860) +.TP +.B 0 +Ramdac type is queried from Mach32 chip. +.PD 1 +.RE + +.IP +.I memory +is the amount of videomemory in KB. +.PP +Note that the type of the ramdac can be set more conveniently with the +.B ramdac +command. + +.SH 5. LOGICAL LINEWIDTH +At least my VRAM card seems to be very peculiar about logical +linewidths. From my experience a multiple of 64 pels is needed. +Your mileage may vary. Use the config file options to adjust it +and tell me if your card needs a different value. Include the name and +model number of the card and what the correct numbers should be. This +is so that I can correct the auto configuration of the driver. + +If some svgalib application has problems, note that you can +force the logical linewidth to the default value from the +configfile. Probably this will lead to glitches in some 800x600 +resolutions. You can +.B inhibit +these resolutions from the configfile +as well. Apropos glitches, I found no guidelines as to what clockrates +to use due to memory restrictions. I adjusted the driver, such that +I get a stable pic in all resolutions. However sometimes the screen +is disturbed by heavy video memory accesses. If you don't like that, +reduce the clocks used with the maxclock16 or maxclock24 command, resp. +This may of course lead to none of the predefined modes being used. +Then you can try to define your own mode via the define command. + +.SH 6. NOISY VIDEO SIGNALS +If you get some flicker or heavy noise on your screen, some fine tuning may +be needed. My docs didn't give me hints as to what each card can stand. +Especially DRAM cards may give problems (I've VRAM). In that case, use the +fine tuning config commands and send me your results along with the output +of +.BR mach32info (6). +Then I can include them in my next release. + +.SS Fine-tuning configuration commands + +First you should think about the +.B maxclock* +configuration commands to reduce pixel clocks used for each color depth. + +Especially important for DRAM cards is the video FIFO depth used to queue +memory values for writing to the screen. Here is a command to set this +value for the 8bpp modes: + +.TP +.BI "vfifo8 " number +where +.I number is in range +.BR 0 " - " 15 . +The default is now 6. + +Since vfifo is of some impact to the speed of the card, tell me the +lowest setting that satisfies your card. + +For 16/24/32 modes, there are non-zero values preset from internal tables and +the EEPROM, however you can enforce minimal vfifo values with: +.PP +.BI "vfifo16 " number +.br +.BI "vfifo24 " number +.br +.BI "vfifo32 " number + +.TP +.BI "blank " number +where +.I number +is +.BI "4 * " pixel_delay " + " blank_adjust +where +.IR pixel_delay " and " blank_adjust +are in range +.BR 0 " .. " 3 . +.I pixel_delay +delays pixels before they are sent to the DAC and +.I blank_adjust +adjusts the blank pulse for type 2 DAC's. +.B blank +should be set correctly for each DAC type automatically. +So use it only as a last resort. + +.TP +.BI "latch " number +where +.I number +is the sum of zero or more of the following numbers: +.RS +.TP +.B 128 +VRAM serial delay latch enable, DRAM latch bits 63 - 0 enable. +.TP +.B 4096 +Latch video memory data. +.TP +.B 8192 +Memory data delay latch enable for data bits 63 - 0. +.TP +.B 16384 +Memory full clock pulse enable. +.RE +.IP +Default is to switch all settings on (they are on on my card by default anyway). +.PP + +Note that these commands may vanish again once they are no longer needed for +debugging purposes. + +There is no 320x200 mode in the EEPROM of the Mach32 at all, however +I defined one in the default configuration file for you. This is the best +thing I could get up on my card/screen. Note that it will probably +have big borders on your screen, and black lines in between the pixel lines. +This is because of the lack of low clocks < 16MHz on the Mach32 and the +lack of a line doubling mode as VGA has. The Mach32 is not intended +for such low resolutions. If you find a better mode or have an idea, +please let me know. You can also just remove my timings from the +default configuration file. + +.SH 7. THE CONFIGURATION EEPROM +Ah yes, about the EEPROM, I figured out how to read out the Mach32 +EEPROM. I did it by disassembling the BIOS routine mentioned in the +docs. I then redid it in C. The driver will use everything it finds +there. + +Use the Mach32 install tools (they should have reached you together with +your Mach32 VGA card) to setup your card/monitor combo correctly. +The +.B monitors +setting from the config file (or default of 35kHz or something) +will be obeyed by the driver nevertheless (for safety!). + +As you probably know already, accessing the EEPROM causes some screen +flickering. If this annoys you (or even worse your monitor) have a look +at the +.B mach32eeprom +command described below. This allows you to put the data from the +EEPROM into a file and which can be read whenever it is required. + +Don't even think about changing the contents of the file. (There is +an easily faked checksum in it.). Anyway the driver ensures (hopefully) +that no damage can be caused. + +Also, if some mode is not well aligned on your screen or you don't like +it's sync frequency, consider using the Mach32 install utility (setup for +custom monitor) and set one up interactively. If there is no valid faster +(higher VSYNC) standard mode given in the EEPROM the driver will use +that mode. You will find that this is fun compared with calculating video +timings for +.IR /etc/XF86Config " or " /etc/vga/libvga.config . + +However the install utility does restrict the maximum pixel depth for +custom modes sometimes unneeded hard and the driver obeys that. +(Hmm.. actually it should be smart enough to decide itself which pixel +depth it can use in that mode.) +Since the standard modes are usually only slightly shifted to one side +a file with the configuration commands representing the standard modes is given +in +.I mach32/mach32.std-modes +in the svgalib distribution. You can use these as a starting point. + +But here are some real problems: + +.SH 8. EEPROM WOES +I got 2 reports of people having problems with incorrect EEPROM checksums. +Both had motherboards with onboard Mach32 VGA's from AST. I guessed a checksum +algorithm from those reports and put this in the code in addition to the +standard ATI style. Still I got a report of someone whose EEPROM was completely +empty. If you have problems with checksums send me the output of +.BR mach32info (6) +and I'll see what I can do. + +By default svgalib writes a complaining message and ignores the contents. +You can have svgalib ignore the checksum and contents with the configuration command + +.B mach32eeprom ignore + +Then you can decide to use the partial info that is still in it. Use + +.B mach32eeprom ignore usetimings + +to use the videomodes that are defined in the EEPROM (if no better modes are +known by the driver). This is usually safe, because the driver knows +which modes are safe for your hardware (if +.BR clocks ", " monitor " and " ramdac +are configured correctly). You can also allow the driver to use the +configuration for the linear frame buffer in the EEPROM: + +.B mach32eeprom ignore useaperture + +or + +.B mach32eeprom ignore usetimings useaperture + +However I discourage this because the driver will just enable what the EEPROM +says about the aperture. Use +.BR mach32info (6) +to check the address it will choose is safe. It might be +better to use +.B setuplinear +to set up a 4MB aperture at a free address range. + +.SH 9. THE MACH32EEPROM COMMAND +The +.B mach32eeprom +allows to work around these problems. Here is the complete description for this +configuration command. + +.TP +.BI "mach32eeprom " filename +The +.I filename +has to begin with a "/". + +Unfortunately reading the EEPROM causes annoying +screen flickering and is slow. +To avoid this, specify a +.I filename +from which to read the contents of the +EEPROM. + +If the file cannot be read, the EEPROM is read out and the file +is created. There is a very simple checksum put into this file. Although +it can easily be fooled, don't change the file except you know +.B very, very +well what you are doing. + +Also, as long as the file exists, changes in the +Mach32's EEPROM are ignored. Delete the file to recreate an updated +version on next use of svgalib. You should ensure that the permissions of +the file don't allow normal users to change it. (This may happen if umask +has a bad value when svgalib creates the file). + +Example: + +.B mach32eeprom /etc/vga/mach32.eeprom + +.PP + +Due to problems with some boards this command got +heavily expanded: + +.TP +.BI "mach32eeprom " subcommand1 " [" subcommand2 "...]" +At least one +.I subcommand +is needed. Valid +.I subcommands +are: + +.RS +.TP +.B ignore +Don't complain about checksum and don't use any EEPROM contents. +.TP +.B useaperture +Use the configuration for the memoryaperture given in the EEPROM. +.TP +.B usetimings +Use videomodes found in the EEPROM of the board. +.TP +.B nofile +Forget about any filename that maybe was already configured. +Don't read a file, don't create one. +.TP +.BI "file " filename +Newstyle form to specify the +.IR filename ; +On contrary to the +.BI "mach32eeprom " filename +form it can be mixed with any other +mach32eeprom subcommand. +.TP +.B updatefile +Don't read the file, always read the EEPROM (except when +.B ignore +is given) and create an +uptodate image of the EEPROM. +.TP +.B keepfile +Disable all previous updatefile commands. +.TP +.B compatible +Fall back to default behavior: If checksum on the EEPROM data is not ok, use nothing of the +configuration data. If it is ok, configure everything as specified in the EEPROM. +.RE +.IP +The subcommands are intended to be used together and are performed in the order +specified. For example: + +.B mach32eeprom ignore useaperture usetimings + +will ignore the checksum of your EEPROM, but use its contents. +Order is vital! So: + +.B mach32eeprom useaperture usetimings ignore + +won't use any configuration from your EEPROM. Be careful with the +.B useaperture +subcommand. Please see the +.B EEPROM WOES +section. Note that any non +understood +.I subcommand +will terminate the +.B mach32eeprom +command silently! Use only one +.I subcommand +per +.B mach32eeprom +command to avoid this. + +The +.B mach32eeprom +command is usually not allowed in the environment variable +.BR SVGALIB_CONFIG . + +.SH 10. SETUP OF THE MEMORY APERTURE (LINEAR FRAMEBUFFER) + +Due to poor design, Xfree86 insists on setting up the aperture itself. It +doesn't reset the original settings at a VC switch once it runs. You +should not start X for the first time after a boot as long as an svgalib +application is running. This will result in pre X values being restored at a VC +switch by svgalib. If you use svgalib and XF86_Mach32 together, run X first or +at least do not start it while any svgalib appl. is still running. After X was +started once you can use svgalib and X in all combinations w/o any problems. Xfree +uses whatever address is given in +the +.B MEM_CFG +Mach32 register for a 4MB aperture, even if the aperture is not already enabled and +the value in this register is pointless garbage. This is IMHO +a dangerous bug as some systems may work only with a 1MB aperture. + +However, usage of a correct EEPROM circumvents any such problems. If you +cannot use that, use +.B mach32info (6) +to find the address in +.B MEM_CFG. +Then, +.BR "if it is a senseable setting for your system" , +enable a 4MB aperture at that address with +.BR setuplinear . +Ensure that no other card or memory uses the address range you choose. + +.SH 11. ACCELERATOR SUPPORT AND OTHER WEIRD FEATURES +This version now has support for all accelerator functions of svgalib. +However they were intended for use with the cirrus chips. It may happen +that at runtime they find they cannot emulate the function actually +requested. Then you should disable the corresponding blit function +(at least for that application) with the blit config command. + +Data transfer between the host and the Mach32 is normally via I/O. This +proved to be pretty slow. If a big enough aperture is available, a simple +memory copy is used instead. This is usually much faster. You can change +which method is used with the blit command. This I/O option affects only +.BR vga_imageblt (3). +The other functions are incredible fast. + +For type 2 DACS, there is support for 8 bit per color (instead of the normal 6) +in the RGB triple in the color lookup table of the 256 color modes. This +can be enabled by an application, if it supports it. The +.BR testaccel (6) +demo uses it if supported by your hardware. +You can use +.BR vga_ext_set (3) +to use it from your programs. + +.SH 12. RAMDACS +Mach32 Ramdacs are specified by a type in range 1 .. 5. This type can be +queried from the Mach32 and then specifies how to set up the ramdac. A list +of actual hardware chips used for each type exists, but is not of much use. The +Mach32 will return a type and the ramdac will be completely hardware compatible to +one of the given type. + +Type 1 and 4 Dacs need different clock frequencies for high colormodes. +For 32K/64K colormodes the frequencies have to be doubled and for +16M colors (type 4 only) they have to be tripled. I followed the ATI scheme +and did this internally. However this means that for 32K/64K you can use +only clocks for which the doubled frequencies can be generated as well. + +This is no hard restriction as the 16 clocks of the Mach32 can be divided by 2. +Thus if you setup some mode yourself try to use one of the divided clocks in +your timings and I can use the undivided clocks internally. + +It is a real restriction for 16M colors. ATI themself only supports 25MHz +(640x480) here by use of a 75MHz clock. Depending on your clock chip other +values may be usable as well. Even the doubled/tripled clocks have to be less +than the magic 80 MHz. However the driver does all this itself. It may just +happen that some of the predefined or one of your handmade mode-timings +can't be used because the clock that is used cannot be doubled/tripled. +Even though there is already some tolerance in the driver you may fix that by +slighty changing the clock values that you set with the +.B clocks +command. But +note that this will as well affect the ability of the driver to calculate +video timings and thus it ability to check the monitor and DAC safety +restrictions. + +In addition (in complete contrast to my original ATI docs) RAMDAC 4 does not support +RGB with blue byte first but only with red first. This required special handling and me +adding a bunch of functions to all modules of svgalib and vgagl. The added functions are +of lower performance than the usual functions. However most data has to be completely +mangled, so I doubt that it can be done much faster. Sorry. + +Of course, I might have +forgotten to port some parts or even confused things. About bugs in the gl and drawing +libs, please ask Harm. +But then, I'm able to emulate a BGR ramdac on my card, so I should +even be able to reproduce your problems. + +Recently I hear often about type 6 ramdacs in non ATI Mach32 cards. There exists +no info about these dacs, thus I cannot support them. The driver assumes unknown +DACs can stand up to 80MHz in 256 color clut modes and does not touch the +ramdac (that is, assumes it is in the 256 color mode already) + +To get rid of the warning message you can use the + +.TP +.BI "ramdac " n +configuration command. It allows to explicitly set the type of the dac to +.I n +(in range +.BR 0 " to " 5). +.B Ramdac 3 +is the most dumbest ramdac possible, s.t. you can use +it without any fear for your hardware. +.TP +.B ramdac dumb +is equivalent to +.BR "ramdac 3" . +.TP +.B ramdac auto +switches back to the default autodetection. +.SH 13. MEANING OF THE DETECTION MESSAGE FROM SVGALIB +Some programs (which do not switch it off) will show a + +.BI "Using Mach32 " version " (" size "M at " adr "M (" how "), " mem "K mem, DAC " dactype ) + +line. This will show up in +.BR testlinear (6) +etc but will probably scroll away when you use +.BR vgatest (6). +In this line: + +.TP +.I version +is the version of the driver (as of my counting, not the svgalib +version). +.TP +.I size +is the size of the memory aperture. It can be +.BR 1 " or " 4 " (" 1 +will lead to not using the linear aperture if your card has more than 1MB +memory, however applications can still use the 1MB aperture and page +the video memory through it in 1MB steps). +.I size +can also be +.B no +if no aperture is setup at all. +.TP +.I adr +is the base address of the aperture in MB. +.TP +.I how +is +.B autodetect +if the aperture was setup this way already when the +program started. It is +.B setup +when the the setting was enforced with a +.B setuplinear +configuration command. It is +.B EEPROM +when no aperture was detected, +but parameters to set it up were found in the EEPROM. +.TP +.I mem +is the amount of memory the card reported to have. +.TP +.I dactype +is the type of the DAC that was detected. + +If a special ramdac type was set with the +.B ramdac +command a +.B (set) +will be displayed after +.IR dactype . +.PP + +If +.IR mem ", " dactype +and/or the chipset were enforced with +.B chipset from the configuration file +or +.BR vga_setchipsetandfeatures (3) +a +.B forced +will be appended to the line. + +.SH 14. CONCLUSIONS +A final word: I have an ATI ULTRA PRO/2MB/EISA with a Type 2 DAC. +My monitor is an EIZO F550i-M. Everything I tried works on it like +a charm. However, I couldn't try it with other machines myself and esp. +other DAC's. Fortunately the Type 2 DAC is the worst to code. So I +will probably have gotten the other DAC's right. But please be warned! + +I did my very best to code the driver to support the other DAC's by +just reading the docs. +.B But i can't give any definitive guarantee for +.B it to work or even not damaging your hardware. So please be careful! + +Note that you will have to set the environment variable +.B SVGALIB_MACH32 +to +.B ILLTRYIT +if your DAC is not type 0, 2, 3 or 4. This will of course change +if no one with a DAC equal to 1 or 5 has serious problems. If you have +a different DAC, making patches to support your card will be much more +helpful instead of just complaining. +If you have a different DAC that works well tell me as well such that I +can remove the need for SVGALIB_MACH32 in the next release. Still, even +now, after years, I got no reports of a Mach32 card with a type 1 or 5 +ramdac. Go figure. + +Thank you for your audience and wishes you will enjoy this driver, +.br +Michael. +.SH FILES +.I /etc/vga/libvga.config +.br +.I /etc/vga/mach32.eeprom + +.SH SEE ALSO +.BR svgalib (7), +.BR libvga.config (5), +.BR mach32info (6). + +.SH AUTHOR +The Mach32 driver and this documentation was written by +Michael Weller . diff --git a/doc/man7/threedkit.7 b/doc/man7/threedkit.7 new file mode 100644 index 0000000..674344f --- /dev/null +++ b/doc/man7/threedkit.7 @@ -0,0 +1,267 @@ +.TH threedkit 7 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +threedkit \- a set of functions for 3D support. + +.SH DESCRIPTION +The 3dkit consists mainly of the following triangle functions +.BR gl_striangle (3), +.BR gl_swtriangle (3), +.BR gl_triangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_trisetdrawpoint (3), +.BR gl_wtriangle (3). + +Beware, these functions are not a direct part of the svgalib library. +Instead their source is part of svgalib and can be found in the +.I threeDkit/ +subdirectory of the original svgalib distribution. However, it is not +installed in the system by default, s.t. it is unclear where you can find it +if your svgalib was installed by some +linux distribution. + +In case of any such problem, simply get an svgalib distribution from the net. You even +don't need to install it. Just +.B make +in the +.I threeDkit/ +subdirectory. As of this writing, +.I svgalib-1.2.12.tar.gz +is the latest version and can be retrieved by ftp from +.IR "sunsite.unc.edu" " at " "/pub/Linux/libs/graphics" +and +.IR "tsx-11.mit.edu" " at " "/pub/linux/sources/libs" +which will most probably be mirrored by a site close to you. + +The functions are defined in the +.IR tri.o " and " triangl.o +files (or their resp. sources) which you must link to your program. + +.SH EXPLANATION ON 3DKIT.C +This is main engine for 3D rendering. + +Program flow: + +.TP +.B 1. +The function called from outside of +.I 3dkit.c +is +.BR TD_drawsolid . +This first calculates the rotation matrix from the camera +rotation angles (see below for more details). +It then allocates memory for the temporary array +.Itemp +for +holding temporary coords in subsequently called functions. +It also sorts the surfaces from furthest to closest; according +to the distance of the centre grid-point of each surface from +the camera. + +It also establishes whether +.B ROTATE_OBJECT +option is on +and zero's the camera position if so --- this is for displaying the +object at the screen centre like in a 3D CAD package, as +apposed to virtual reality where the object can be anywhere +and the actual camera position can move. + +In the case of +.B ROTATE_OBJECT +being on, although the camera position +is zero, some distance has to be placed between the camera and the +object (or else it would appear to be infinitely large on the +screen). This is done using the variable +.I s_cam +which is +initialized to +.I distance +which is set by the calling application. +It then loops through each surface (ordering them in the way they +were just sorted --- i.e. according to +.I sortarray +indexing) and +calls one of five graphic routines to write the 3D surface to the +hardware. + +.TP +.B 2. +Assume that +.B TD_drawsolid +then calls +.BR TD_drawmesh . +Here, each surface +grid point is first +.BR TD_translate 'd +into a 2D screen point and stored in +the +.I temp +array. There are obviously w(idth)*h(eight) points in the +grid. + +Following, each line from the 2D temp array is drawn on the screen. +To draw the surface, the corner wishbone (two lines) from each grid +square is drawn while advancing across and the down. After completing +the scan, the furthest two edges of the surface must then be filled +in, vis.: + _ _ _ _ _ _ +.br +|_|_|_|_|_|_ +.br +|_|_|_|_|_|_ +.br +|_|_|_|_|_|_ +.br +|_|_|_|_|_|_ +.br +|_|_|_|_|_|_ +.br +| | | | | | + +To understand the object rotation, a knowledge of matrix +multiplication is required. I once derived a camera rotation +before I learned matrix computation. It amounted to the same +thing, but was unnecessarily complicated to optimise. + +.TP +.B 3. +.B TD_translate +called from +.B TD_drawmesh +(and others) converts from +the 3D grid point coordinate to the 2D screen coordinate using: +.B (a) +the three camera position coordinates, (or the single camera +distance value, +.IR s_cam , +if +.B ROTATE_OBJECT +is set), and +.B (b) +the three camera rotation angles. However, the three camera rotation +angles have already been converted into a rotation matrix when +.B TD_calc_rotation_matrix +was called by +.BR TD_draw_solid . + +To convert from a 3D coordinate to a 2D screen coordinate, +the camera position (or more correctly, the position of the object +from the camera) must first be added to each of the 3D grid coordinates. +If the user has chosen to use 32 bit values for the discription +of the surface, then these must be right shifted to the same size +as the 16 bit case. + +.IR x ", " y " and " z +now hold the 3D position of the +object relative to the camera centre (or in these terms, the +centre of the video screen +.B RIGHT ON +the screen). The vector +.BI [ "x y z" ] +must +now be multiplied by the rotation matrix. The +.I xt +value must also have the camera distance, +.IR s_cam , +added to it in case the +.B ROTATE_CAMERA +is set (in which case +.IR x_cam ", " y_cam " and " z_cam +(the camera position) +will be zero and instead +.I s_cam +will have a value to provide the necessary object-camera distance). A test is +also made as to whether this +value is zero or negative. In the case, the point is too close to the +camera, or behind the camera, and must not be drawn. + +After the multiplication, the resulting vector +.BI [ "xt yt zt" ] +has been rotated +to be aligned with screen. The vector is now adjusted for perspective +by dividing the +.IR yt " and " zt +values (horizontal and vertical +respectively) by the +.I xt +value (into the screen). Division is done +by +.B muldiv64 +because the intermediate product is larger +than 32 bits. +.IR xscale " and " yscale +are factors that scale the image to size. +.IR posx " and " posy +is just the centre of the screen, or more precisely: + +The exact position of the pinhole camera viewing the object. + +.TP +.B 4. +.B TD_calc_rotation_matrix +calculates the nine entries of the 3 by 3 +matrix used in +.BR TD_translate . +In order that only integer arithmetic +is performed, these values are stored and used as integers. Since this +matrix's entries are always between -1 and +1, they have to be +integer left shifted to give them accuracy. +.B TD_MULCONSTANT +scales them +to sufficient bits of accuracy before they are converted to integers. + +This also means that results (of multiplications with them) have +to be scaled down by the same amount. This scaling is inherent in the +final multiplication and division +.RB ( muldiv64 ) +done in the +.B TD_translate +function, so an extra division is not consumed. + +The rotation matrix effectively rotates the vector by the Eulerian angles +.IR alpha ", " beta " and " gamma . +These angles represent successive rotations about +each of the 3D axes. You can test which angles do what by looking at +the calling application. Their precise definitions are not +all that important since you can get the keyboard to do the right thing +with a little trial and error. + +.PP +Intrisics of drawing non-transparent surfaces... + +to be continued ?! + +.SH SEE ALSO +.BR vgagl (7), +.BR svgalib (7), +.BR gl_striangle (3), +.BR gl_swtriangle (3), +.BR gl_triangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_trisetdrawpoint (3), +.BR gl_wtriangle (3), +.BR plane (6), +.BR wrapdemo (6). + +.SH AUTHOR +This manual page was edited by Michael Weller . The +demos, the initial documentation and the whole threedkit stuff was done by +Paul Sheer . + +Paper mail: +.RS +Paul Sheer +.br +P O BOX 890507 +.br +Lyndhurst +.br +Johannesburg 2106 +.br +South Africa +.RE + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/doc/man7/vgagl.7 b/doc/man7/vgagl.7 new file mode 100644 index 0000000..e08f6f0 --- /dev/null +++ b/doc/man7/vgagl.7 @@ -0,0 +1,401 @@ +.TH vgagl 7 "2 Aug 1997" "Svgalib (>= 1.2.11)" "Svgalib User Manual" +.SH NAME +vgagl \- a fast framebuffer-level graphics library based ion svgalib +.SH TABLE OF CONTENTS + +.BR 0. " Introduction" +.br +.BR 1. " How to use vgagl" +.br +.BR 2. " Description of vgagl functions" +.br +.BR 3. " Macros defined in vgagl.h" + +.SH 0. INTRODUCTION + +This is a fast framebuffer-level graphics library for linear 1, 2, 3 and 4 +byte-per-pixel modes (256-color, hicolor, truecolor). It uses a limited +number of functions from svgalib (libvga) for low-level hardware +communication (the library is included in the svgalib shared image). + +In particular, +.BR svgalib (7) +maps the 64K VGA frame buffer window, and this library +directly addresses the buffer. For SVGA modes that use more than 64K of +screen memory, SVGA paging is required when writing to the physical screen; +this is done automatically for most functions (at a certain cost). + +Alternatively, any number of virtual screens of any type in system memory can +be used, which can then be copied to the physical screen. There is also +support for 4 bytes per pixel framebuffers (and copying them to a 3 bytes per +pixel context), and limited planar 256 color mode support (copyscreen, +aligned putbox). + +The planar 256 color modes (available on all VGA cards) can now be used +with a virtual screen, which is copied to the physical screen (with optional +page-flipping). + +Bitmaps are raw, with one (or more) bytes per pixel (like pixmaps in X), +stored in row-major order. They are usually manipulated with the getbox +and putbox functions. + +.B vgagl +does also make use of the graphic cards accelerator +(if it is supported) +in some situations. + +A graphics context is just a structure that holds the size of the associated +graphics screen, how it is organized, clipping status etc. You can define a +custom virtual (system memory) graphics context of any size with the +setcontextvirtual function. All operations work on the current context. + +Any questions, bug-reports, additions, suggestions etc. are welcome. + +.SH 1. HOW TO USE VGAGL +Programs that use +.B vgagl +must +.BR "#include " . +Linking must be done with +.BR "-lvgagl -lvga" . + +Functions in the +.B vgagl +library have the prefix +.BR gl_* . +To initialize +.BR vgagl , +the graphics context must be set. Example: + +.RS +.B vga_setmode(G320x200x256); +.br +.B gl_setcontextvga(G320x200x256); +.RE + +In this example, the context is set to the physical screen. The context can +be saved (only the screen type, not the contents) into a variable, e.g. + +.RS +.B GraphicsContext physicalscreen; +.br +.B gl_getcontext(&physicalscreen). +.RE + +To define a virtual screen in system memory, use +.BR gl_setcontextvgavirtual (3): + +.RS +.B gl_setcontextvgavirtual(G320x200x256) +.RE + +which allocates space for a screen identical to 320x200x256 graphics mode, +and makes this virtual screen the current graphics context. + +The virtual screen can now be copied to the physical screen as follows: + +.RS +.B gl_copyscreen(&physicalscreen); +.RE + +Note that with a virtual screen in system memory, it is possible to add +fast X-Window support to a program, using MITSHM to copy the framebuffer +to the screen window. + +.SH 2. DESCRIPTION OF VGAGL FUNCTIONS +.PD 0 +.SS Context management +.TP +.BR gl_getcontext "(3), " currentcontext (3) +get the current graphics contents.. +.TP +.BR gl_setcontext (3) +set a previously saved context. +.TP +.BR gl_setcontextvga (3) +set the context to the physical screen. +.TP +.BR gl_setcontextvgavirtual (3) +set the context to a virtual mode. +.TP +.BR gl_setcontextvirtual (3) +define a virtual context. +.TP +.BR gl_allocatecontext (3) +allocate a graphics context. +.TP +.BR gl_freecontext (3) +free a virtual screen. +.TP +.BR gl_setcontextwidth "(3), " gl_setcontextheight (3) +set the dimension of a context. + +.SS Drawing primitives +.TP +.BR gl_clearscreen (3) +clear the screen. +.TP +.BR gl_rgbcolor (3) +return pixel value corresponding to an rgb color. +.TP +.BR gl_setpixel "(3), " gl_setpixelrgb (3) +draw a pixel. +.TP +.BR gl_getpixel (3) +return the color of a pixel. +.TP +.BR gl_getpixelrgb (3) +store color components of a pixel. +.TP +.BR gl_hline (3) +draw a horizontal line. +.TP +.BR gl_line (3) +draw a line. +.TP +.BR gl_circle (3) +draw a circle. +.TP +.BR gl_fillbox (3) +fill a rectangular area. + +.SS Copying of screen buffers and page flipping +.TP +.BR gl_copyscreen (3) +copy the screen contents of contexts. +.TP +.BR gl_setscreenoffset (3) +set a memory offset for copyscreen. +.TP +.BR gl_setdisplaystart (3) +set the start of the screen are displayed. +.TP +.BR gl_enablepageflipping (3) +enables automatic page flipping. + +.SS Clipping +.TP +.BR gl_disableclipping (3) +disables clipping. +.TP +.BR gl_enableclipping (3) +enables clipping. +.TP +.BR gl_setclippingwindow (3) +set the clipping window. + +.SS Text drawing primitives +.TP +.BR gl_setfont (3) +set the text font to be used. +.TP +.BR gl_setfontcolors (3) +set the font colors. +.TP +.BR gl_expandfont (3) +expand a packed pixel font. +.TP +.BR gl_colorfont (3) +change the color of a font. +.TP +.BR gl_setwritemode (3) +set the font writemode flags. +.TP +.BR gl_write "(3), " gl_writen (3) +write a text string. +.TP +.BR gl_printf (3) +formatted output to the graphics screen. +.TP +.BR gl_font8x8 (3) +a packed 8x8 pixel font. + +.SS Pix- and Bitmap drawing +.TP +.BR gl_getbox (3) +copy a rectangular pixmap from the screen to a buffer. +.TP +.BR gl_copybox (3) +copy a rectangular screen area. +.TP +.BR gl_copyboxfromcontext (3) +copy rectangular area from another context. +.TP +.BR gl_copyboxtocontext (3) +copy a rectangular area to another context. +.TP +.BR gl_putbox (3) +copy a pixmap to a rectangular area. +.TP +.BR gl_putboxpart (3) +copy a partial pixmap to a rectangular area. +.TP +.BR gl_putboxmask (3) +copy a masked pixmap to a rectangular area. +.TP +.BR gl_putboxmaskcompiled (3) +copy a compiled masked pixmap to a rectangular area. +.TP +.BR gl_compileboxmask (3) +compress a masked bitmap. +.TP +.BR gl_compiledboxmasksize (3) +compute the size of a compiled masked box. +.TP +.BR gl_scalebox (3) +scale a pixmap. + +.SS Palette handling +.TP +.BR gl_getpalettecolor "(3), " gl_getpalettecolors "(3), " gl_getpalette (3) +read the color palette. +.TP +.BR gl_setpalettecolor "(3), " gl_setpalettecolors "(3), " gl_setpalette (3) +set the color palette. +.TP +.BR gl_setrgbpalette (3) +set a 256-color RGB palette. + +.SS Triangle primitives from threeDkit +.TP +.BR gl_striangle (3) +draw a solid colored triangle. +.TP +.BR gl_triangle (3) +draw a triangle with interpolated colors. +.TP +.BR gl_swtriangle (3) +draw a solid pixmap mapped on a triangle. +.TP +.BR gl_wtriangle (3) +draw a shadowed pixmap mapped on a triangle. +.TP +.BR gl_trisetcolorlookup "(3), " gl_trigetcolorlookup (3) +manages a color lookup table for shadowing. +.TP +.BR gl_trisetdrawpoint (3) +set a triangle drawing function. +.PD +.SH 3. MACROS DEFINED IN VGAGL.H: +.TP +.B WIDTH +The width in pixels of the current graphics context. +.TP +.B HEIGHT +Height in pixels. +.TP +.B BYTESPERPIXEL +Number of bytes per pixel (1, 2, 3 or 4). +.TP +.B BYTEWIDTH +Width of a scanline in bytes. +.TP +.B COLORS +Number of colors. +.TP +.B BITSPERPIXEL +Number of significant color bits. +.TP +.B VBUF +Address of the framebuffer. +.TP +.B __clip +Clipping flag. + +.PD 0 +.TP +.B __clipx1 +.TP +.B __clipy1 +Top-left corner of clipping window. +.PD + +.PD 0 +.TP +.B __clipx2 +.TP +.B __clipy2 +.PD +Bottom-right corner of clipping window. + +.SH BUGS +For three bytes per pixel (true color) modes, it is possible that +pixels cross a SVGA segment boundary. This should be correctly +handled by most functions, but you never know. It can be avoided by using a logical +scanline length that is a divisor of 65536 (a power of 2), like 1024 +(as opposed to 960) for 320x200 and 2048 (1920) for 640x480. For +800x600, this is impractical (4096 as opposed to 2400 doesn't fit in +2MB). Alternatively, avoid those functions by using a virtual screen. + +.SH SEE ALSO +.BR svgalib (7), +.BR libvga.config (5), +.BR testgl (6), +.BR threedkit (7), +.BR currentcontext (3), +.BR gl_allocatecontext (3), +.BR gl_circle (3), +.BR gl_clearscreen (3), +.BR gl_colorfont (3), +.BR gl_compileboxmask (3), +.BR gl_compiledboxmasksize (3), +.BR gl_copybox (3), +.BR gl_copyboxfromcontext (3), +.BR gl_copyboxtocontext (3), +.BR gl_copyscreen (3), +.BR gl_disableclipping (3), +.BR gl_enableclipping (3), +.BR gl_enablepageflipping (3), +.BR gl_expandfont (3), +.BR gl_fillbox (3), +.BR gl_font8x8 (3), +.BR gl_freecontext (3), +.BR gl_getbox (3), +.BR gl_getcontext (3), +.BR gl_getpalette (3), +.BR gl_getpalettecolor (3), +.BR gl_getpalettecolors (3), +.BR gl_getpixel (3), +.BR gl_getpixelrgb (3), +.BR gl_hline (3), +.BR gl_line (3), +.BR gl_putbox (3), +.BR gl_putboxmask (3), +.BR gl_putboxmaskcompiled (3), +.BR gl_putboxpart (3), +.BR gl_rgbcolor (3), +.BR gl_scalebox (3), +.BR gl_setclippingwindow (3), +.BR gl_setcontext (3), +.BR gl_setcontextheight (3), +.BR gl_setcontextvga (3), +.BR gl_setcontextvgavirtual (3), +.BR gl_setcontextvirtual (3), +.BR gl_setcontextwidth (3), +.BR gl_setdisplaystart (3), +.BR gl_setfont (3), +.BR gl_setfontcolors (3), +.BR gl_setpalette (3), +.BR gl_setpalettecolor (3), +.BR gl_setpalettecolors (3), +.BR gl_setpixel (3), +.BR gl_setpixelrgb (3), +.BR gl_setrgbpalette (3), +.BR gl_setscreenoffset (3), +.BR gl_setwritemode (3), +.BR gl_striangle (3), +.BR gl_swtriangle (3), +.BR gl_triangle (3), +.BR gl_trigetcolorlookup (3), +.BR gl_trisetcolorlookup (3), +.BR gl_trisetdrawpoint (3), +.BR gl_write (3), +.BR gl_writen (3), +.BR gl_wtriangle (3). + +.SH AUTHOR +There are many authors of svgalib. This page was edited by +Michael Weller . +The original documentation and most of +.B vgagl +was done by Harm Hanemaayer though. diff --git a/doc/man8/mode3.8 b/doc/man8/mode3.8 new file mode 100644 index 0000000..5219d1d --- /dev/null +++ b/doc/man8/mode3.8 @@ -0,0 +1,16 @@ +.TH mode3 8 "11 Mar 1999" "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +mode3 \- set a vesa mode. +.SH SYNOPSIS + +.BI "mode3 [modenum] " + +.SH DESCRIPTION +The video card is set to vesa mode +.IR modenum +(or 3 by default) using the (real mode) vesa bios calls. + +.SH BUGS +Using this program is unsafe, and might (depending on the bios) result in +a video card in a state that requires a hard reset to restore to normal, +or even a hung computer. diff --git a/doc/man8/vga_reset.8 b/doc/man8/vga_reset.8 new file mode 100644 index 0000000..87ad4bb --- /dev/null +++ b/doc/man8/vga_reset.8 @@ -0,0 +1,17 @@ +.TH vga_reset 8 2004-01-26 "Svgalib (>= 1.4.0)" "Svgalib User Manual" +.SH NAME +vga_reset \- reset video graphic board +.SH SYNOPSIS +.B vga_reset +.SH DESCRIPTION +Call real mode c000:0003, which should be the video card's initialization +routine. Should work in some cases when mode3 fails to restore text mode. +.SH BUGS +Using this program is unsafe, and might (depending on the bios) result in +a video card in a state that requires a hard reset to restore to normal, +or even a hung computer. +.SH SEE ALSO +.BR mode3 (8). +.SH AUTHOR +This manual page was written by Guillem Jover . + diff --git a/doc/svgalib.lsm b/doc/svgalib.lsm new file mode 100644 index 0000000..8d5318d --- /dev/null +++ b/doc/svgalib.lsm @@ -0,0 +1,18 @@ +Begin3 +Title: svgalib +Version: 1.4.1 +Entered-date: 17DEC99 +Description: Low-level graphics library that provides VGA and SVGA + modes in a console. It is not intended as an alternative + to X for apps, but rather a set of tools for things like + VGA games, image viewing in modes that X cannot support, etc. +Keywords: graphics, VGA, SVGA, library, console +Author: hhanemaa@cs.ruu.nl (Harm Hanemaayer) et al. +Maintained-by: Matan Ziv-Av +Primary-site: sunsite.unc.edu /pub/Linux/libs/graphics + 938K svgalib-1.4.1.tar.gz +Platforms: Linux/Intel (too many vgacards to list here); Linux/Alpha (up + to now only #9 GXE PCI KNOWN to work, other cards may/should + work). +Copying-policy: Freely distributable. +End diff --git a/doc/tman b/doc/tman new file mode 100755 index 0000000..df0baec --- /dev/null +++ b/doc/tman @@ -0,0 +1,12 @@ +#!/bin/sh +for i in "$@" +do + for j in 1 3 5 6 7 + do + FILE=man$j/$i.$j.gz + if [ -f $FILE ] + then + gunzip < $FILE | nroff -man | more + fi + done +done diff --git a/fixldsoconf b/fixldsoconf new file mode 100755 index 0000000..fa4d453 --- /dev/null +++ b/fixldsoconf @@ -0,0 +1,8 @@ +#!/bin/sh +if [ `whoami` != root ] ; then exit 0 ; fi +if grep -q /usr/local/lib /etc/ld.so.conf + then + echo > /dev/null + else + echo /usr/local/lib >> /etc/ld.so.conf + fi diff --git a/gl/Makefile b/gl/Makefile new file mode 100644 index 0000000..e102291 --- /dev/null +++ b/gl/Makefile @@ -0,0 +1,73 @@ +#---------------------------------------------------------------------- +# Makefile for SVGAlib GL routines. +#---------------------------------------------------------------------- + +# *** NO SERVICIBLE PARTS HERE! +# All options are in Makefile.cfg. + +include ../Makefile.cfg + +srcdir = .. +VPATH = $(srcdir)/gl + +ifeq (a.out, $(TARGET_FORMAT)) + DEFINES += -DSVGA_AOUT +endif + +ifeq (y, $(NO_ASM)) + DEFINES += -DNO_ASSEMBLY +endif + +#---------------------------------------------------------------------- +# Rules Section +#---------------------------------------------------------------------- + +MODULES = grlib.o driver.o line.o palette.o scale.o text.o font8x8.o \ + cbitmap.o mem.o + +all: libvgagl.a +.PHONY: all clean dep + +libvgagl.so.$(VERSION): $(MODULES) + $(CC) -s -shared -Wl,-soname,libvgagl.so.$(MAJOR_VER) -o libvgagl.so.$(VERSION) \ + $(MODULES) + +libvgagl.a: $(MODULES) + rm -f libvgagl.a + $(AR) rcs libvgagl.a $(MODULES) + +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.S.s: + $(CC) $(CFLAGS) -E $< >$@ + +.s.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.c.s: + $(CC) $(CFLAGS) -S -o $*.s $< + +.o: + $(CC) $(CFLAGS) $(LDFLAGS) -o $* $*.o $(LIBS) + chmod 4755 $* + +$(MODULES): .depend.gl + +dep: + rm -f .depend.gl + make depend + +.depend.gl: + echo '# GL Module dependencies' >>.depend.gl + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/gl/%.c,$(MODULES)) >>.depend.gl + +clean: + rm -f .depend.gl *.bak *.o *~ libvgagl.a libvgagl.so.$(VERSION) + +# +# include a dependency file if one exists +# +ifeq (.depend.gl,$(wildcard .depend.gl)) +include .depend.gl +endif diff --git a/gl/cbitmap.c b/gl/cbitmap.c new file mode 100644 index 0000000..4826bd9 --- /dev/null +++ b/gl/cbitmap.c @@ -0,0 +1,186 @@ +/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ +/* cbitmap.c Compiled bitmaps */ + + +#include +#include +#include +#include "inlstring.h" /* include inline string operations */ + +#include "vgagl.h" +#include "def.h" + + + +void gl_compileboxmask(int w, int h, void *_dp1, void *_dp2) +{ +/* Compiled format: */ +/* []... */ + uchar *dp1 = _dp1; + uchar *dp2 = _dp2; + int i; + for (i = 0; i < h; i++) { + int x = 0; + while (x < w) { + int count; + /* count zeroes */ + count = 0; + while (x < w && *(dp1 + count) == 0 && count < 254) { + count++; + x++; + } + dp1 += count; + if (x < w) { + *dp2++ = count; + /* count nonzeroes */ + count = 0; + while (x < w && *(dp1 + count) != 0 && count < 255) { + *(dp2 + count + 1) = *(dp1 + count); + count++; + x++; + } + *dp2 = count; + dp2 += count + 1; + dp1 += count; + } + } + *dp2++ = 0xff; + } +} + +int gl_compiledboxmasksize(int w, int h, void *_dp1) +{ +/* Compiled format: */ +/* []... */ + uchar *dp1 = _dp1; + int size = 0; + int i; + for (i = 0; i < h; i++) { + int x = 0; + while (x < w) { + int count; + /* count zeroes */ + count = 0; + while (x < w && *(dp1 + count) == 0 && count < 254) { + count++; + x++; + } + size++; + dp1 += count; + /* count nonzeroes */ + if (x < w) { + count = 0; + while (x < w && *(dp1 + count) != 0 && count < 255) { + count++; + x++; + } + size += count + 1; + dp1 += count; + } + } + size++; + } + return size; +} + +static void gl_putboxmaskcompiledclip(int nx, int ny, int nw, int nh, int _x, + int _y, int w, int h, void *_dp) +{ +/* Special case costly clipping */ + uchar *dp = _dp; + uchar *vp, *vpline; + int y; + vpline = VBUF + _y * BYTEWIDTH + _x; + for (y = _y; y < ny + nh; y++) { + int x = _x; + vp = vpline; + for (;;) { + int count = *dp++; + if (count == 0xff) + break; /* end of line */ + vp += count; + x += count; + count = *dp++; + /* __memcpy gives severe bug here */ + if (y >= ny) { + if (x >= nx) + if (x + count > __clipx2 + 1) { + if (x <= __clipx2) + __memcpyb(vp, dp, __clipx2 - x + 1); + } else + __memcpyb(vp, dp, count); + else if (x + count > __clipx1) { + if (x + count > __clipx2 + 1) + __memcpyb(vp + __clipx1 - x, + dp + __clipx1 - x, + __clipx2 - __clipx1 + 1); + else + __memcpy(vp + __clipx1 - x, + dp + __clipx1 - x, + count - __clipx1 + x); + }; + }; + x += count; + vp += count; + dp += count; + } + vpline += BYTEWIDTH; + } +} + +#define ADJUSTBITMAPBOX() \ + nw = w; nh = h; nx = x; ny = y; \ + if (nx + nw < __clipx1 || nx > __clipx2) \ + return; \ + if (ny + nh < __clipy1 || ny > __clipy2) \ + return; \ + if (nx < __clipx1) { /* left adjust */ \ + nw += nx - __clipx1; \ + nx = __clipx1; \ + } \ + if (ny < __clipy1) { /* top adjust */ \ + nh += ny - __clipy1; \ + ny = __clipy1; \ + } \ + if (nx + nw > __clipx2) /* right adjust */ \ + nw = __clipx2 - nx + 1; \ + if (ny + nh > __clipy2) /* bottom adjust */ \ + nh = __clipy2 - ny + 1; \ + + +void gl_putboxmaskcompiled(int x, int y, int w, int h, void *_dp) +{ +/* no clipping */ + uchar *dp = _dp; + uchar *vp, *vpline; + int i; + if (MODETYPE != CONTEXT_LINEAR && MODETYPE != CONTEXT_VIRTUAL) { + printf("vgagl: putboxmaskcompiled only supported in linear framebuffer\n"); + return; + } + if (__clip) { + int nx, ny, nw, nh; + ADJUSTBITMAPBOX(); + if (nw != w || nh != h) { + gl_putboxmaskcompiledclip(nx, ny, nw, nh, x, y, w, h, + dp); + return; + } + } + vpline = VBUF + y * BYTEWIDTH + x; + for (i = 0; i < h; i++) { + vp = vpline; + for (;;) { + int count = *dp++; + if (count == 0xff) + break; /* end of line */ + vp += count; + count = *dp++; + /* __memcpy gives severe bug here */ + __memcpyb(vp, dp, count); + vp += count; + dp += count; + } + vpline += BYTEWIDTH; + } +} diff --git a/gl/def.h b/gl/def.h new file mode 100644 index 0000000..e3540f0 --- /dev/null +++ b/gl/def.h @@ -0,0 +1,72 @@ + + +#define uchar unsigned char +#define swap(x, y) { int temp = x; x = y; y = temp; } +#define swapb(x, y) { uchar temp = x; x = y; y = temp; } +#define max(x, y) ((x > y) ? x : y) +#define min(x, y) ((x > y) ? y : x) +#define outside(x, y) (x < __clipx1 || x > __clipx2 || y < __clipy1 \ + || y > __clipy2) +#define x_outside(x) (x < __clipx1 || x > __clipx2) +#define y_outside(y) (y < __clipy1 || y > __clipy2) +#define clipxleft(x) if (x < __clipx1) x = __clipx1; +#define clipxright(x) if (x > __clipx2) x = __clipx2; +#define clipytop(y) if (y < __clipy1) y = __clipy1; +#define clipybottom(y) if (y > __clipy2) y = __clipy2; + + +#define setpixel (*(__currentcontext.ff.driver_setpixel_func)) +#define getpixel (*(__currentcontext.ff.driver_getpixel_func)) +#define hline (*(__currentcontext.ff.driver_hline_func)) +#define fillbox (*(__currentcontext.ff.driver_fillbox_func)) +#define putbox (*(__currentcontext.ff.driver_putbox_func)) +#define getbox (*(__currentcontext.ff.driver_getbox_func)) +#define putboxmask (*(__currentcontext.ff.driver_putboxmask_func)) +#define putboxpart (*(__currentcontext.ff.driver_putboxpart_func)) +#define getboxpart (*(__currentcontext.ff.driver_getboxpart_func)) +#define copybox (*(__currentcontext.ff.driver_copybox_func)) + +#define TEXT_TABSIZE 8 + +#ifdef DLL_CONTEXT_SHADOW + +/* Library uses internal currentcontext for faster DLL library. */ + +#undef BYTESPERPIXEL +#undef BYTEWIDTH +#undef WIDTH +#undef HEIGHT +#undef VBUF +#undef MODETYPE +#undef MODEFLAGS +#undef BITSPERPIXEL +#undef COLORS +#undef __clip +#undef __clipx1 +#undef __clipy1 +#undef __clipx2 +#undef __clipy2 + +extern GraphicsContext __currentcontext; + +#define BYTESPERPIXEL (__currentcontext.bytesperpixel) +#define BYTEWIDTH (__currentcontext.bytewidth) +#define WIDTH (__currentcontext.width) +#define HEIGHT (__currentcontext.height) +#define VBUF (__currentcontext.vbuf) +#define MODETYPE (__currentcontext.modetype) +#define MODEFLAGS (__currentcontext.modeflags) +#define BITSPERPIXEL (__currentcontext.bitsperpixel) +#define COLORS (__currentcontext.colors) + +#define __clip (__currentcontext.clip) +#define __clipx1 (__currentcontext.clipx1) +#define __clipy1 (__currentcontext.clipy1) +#define __clipx2 (__currentcontext.clipx2) +#define __clipy2 (__currentcontext.clipy2) + +#else + +#define __currentcontext currentcontext + +#endif diff --git a/gl/driver.c b/gl/driver.c new file mode 100644 index 0000000..421928e --- /dev/null +++ b/gl/driver.c @@ -0,0 +1,1376 @@ +/* driver.c Framebuffer primitives */ + + +#include +#include +#include +#include + +#include "inlstring.h" /* include inline string operations */ +#include "vgagl.h" +#include "def.h" +#include "driver.h" + + +#define MAXBYTEWIDTH 4096 /* used in bitblt emulation */ + +/* All functions that simply call another function with slightly different + * parameter values are declared inline. */ +#define INLINE inline + +#define NOTIMPL(s) { notimplemented(s); return; } + +/* in: vp = video offset; out: rvp = video pointer, chunksize, page */ +#define SETWRITEPAGED(vp, rvp, chunksize, page) \ + page = vp >> 16; \ + vga_setpage(page); \ + rvp = (vp & 0xffff) + VBUF; \ + chunksize = 0x10000 - (vp & 0xffff); + +static inline int RGB2BGR(int c) +{ +/* a bswap would do the same as the first 3 but in only ONE! cycle. */ +/* However bswap is not supported by 386 */ + + if (MODEFLAGS & MODEFLAG_24BPP_REVERSED) +#ifdef NO_ASSEMBLY + c = ((c >> 0) & 0xff) << 16 | + ((c >> 8) & 0xff) << 8 | + ((c >> 16) & 0xff) << 0; +#else + asm("rorw $8, %0\n" /* 0RGB -> 0RBG */ + "rorl $16, %0\n" /* 0RBG -> BG0R */ + "rorw $8, %0\n" /* BG0R -> BGR0 */ + "shrl $8, %0\n" /* 0BGR -> 0BGR */ + : "=q"(c):"0"(c)); +#endif + return c; +} + +/* RGB_swapped_memcopy returns the amount of bytes unhandled */ +static inline int RGB_swapped_memcpy(char *dest, char *source, int len) +{ + int rest, tmp; + + tmp = len / 3; + rest = len - 3 * tmp; + len = tmp; + + while (len--) { + *dest++ = source[2]; + *dest++ = source[1]; + *dest++ = source[0]; + source += 3; + } + + return rest; +} + +static void notimplemented(char *s) +{ + printf("vgagl: %s not implemented.\n", s); +} + + + +/* One byte per pixel frame buffer primitives */ + +#define ASSIGNVP8(x, y, vp) vp = VBUF + (y) * BYTEWIDTH + (x); +#define ASSIGNVPOFFSET8(x, y, vp) vp = (y) * BYTEWIDTH + (x); + +void __svgalib_driver8_setpixel(int x, int y, int c) +{ + char *vp; + ASSIGNVP8(x, y, vp); + *vp = c; +} + +void __svgalib_driver8p_setpixel(int x, int y, int c) +{ + int vp; + ASSIGNVPOFFSET8(x, y, vp); + vga_setpage(vp >> 16); + *(VBUF + (vp & 0xffff)) = c; +} + +int __svgalib_driver8_getpixel(int x, int y) +{ + char *vp; + ASSIGNVP8(x, y, vp); + return *vp; +} + +int __svgalib_driver8p_getpixel(int x, int y) +{ + int vp; + ASSIGNVPOFFSET8(x, y, vp); + vga_setpage(vp >> 16); + return *(VBUF + (vp & 0xffff)); +} + +void __svgalib_driver8_hline(int x1, int y, int x2, int c) +{ + char *vp; + ASSIGNVP8(x1, y, vp); + __memset(vp, c, x2 - x1 + 1); +} + +void __svgalib_driver8p_hline(int x1, int y, int x2, int c) +{ + int vp; + char *rvp; + int l; + int chunksize, page; + ASSIGNVPOFFSET8(x1, y, vp); + SETWRITEPAGED(vp, rvp, chunksize, page); + l = x2 - x1 + 1; + if (l <= chunksize) + __memset(rvp, c, l); + else { + __memset(rvp, c, chunksize); + vga_setpage(page + 1); + __memset(VBUF, c, l - chunksize); + } +} + +void __svgalib_driver8_fillbox(int x, int y, int w, int h, int c) +{ + char *vp; + int i; + ASSIGNVP8(x, y, vp); + for (i = 0; i < h; i++) { + __memset(vp, c, w); + vp += BYTEWIDTH; + } +} + +void __svgalib_driver8a_fillbox(int x, int y, int w, int h, int c) +{ + if (w * h < 128) + (*__svgalib_nonaccel_fillbox)(x, y, w, h, c); + else { + vga_accel(ACCEL_SETFGCOLOR, c); + vga_accel(ACCEL_FILLBOX, x, y, w, h); + } +} + +void __svgalib_driver8p_fillbox(int x, int y, int w, int h, int c) +{ + int vp; + int page; + int i; + ASSIGNVPOFFSET8(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (i = 0; i < h; i++) { + if (vp + w > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* page break within line */ + __memset(VBUF + vp, c, 0x10000 - vp); + page++; + vga_setpage(page); + __memset(VBUF, c, (vp + w) & 0xffff); + vp = (vp + BYTEWIDTH) & 0xffff; + continue; + } + }; + __memset(VBUF + vp, c, w); + vp += BYTEWIDTH; + } +} + +void __svgalib_driver8_putbox(int x, int y, int w, int h, void *b, int bw) +{ + char *vp; /* screen pointer */ + char *bp; /* bitmap pointer */ + int i; + ASSIGNVP8(x, y, vp); + bp = b; + for (i = 0; i < h; i++) { + __memcpy(vp, bp, w); + bp += bw; + vp += BYTEWIDTH; + } +} + +void __svgalib_driver8p_putbox(int x, int y, int w, int h, void *b, int bw) +{ +/* extra argument width of source bitmap, so that putboxpart can use this */ + int vp; + int page; + char *bp = b; + int i; + ASSIGNVPOFFSET8(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (i = 0; i < h; i++) { + if (vp + w > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* page break within line */ + __memcpy(VBUF + vp, bp, 0x10000 - vp); + page++; + vga_setpage(page); + __memcpy(VBUF, bp + 0x10000 - vp, + (vp + w) & 0xffff); + vp = (vp + BYTEWIDTH) & 0xffff; + bp += bw; + continue; + } + }; + __memcpy(VBUF + vp, bp, w); + bp += bw; + vp += BYTEWIDTH; + } +} + +void __svgalib_driver8_getbox(int x, int y, int w, int h, void *b, int bw) +{ + char *vp; /* screen pointer */ + char *bp; /* bitmap pointer */ + int i; + ASSIGNVP8(x, y, vp); + bp = b; + for (i = 0; i < h; i++) { + __memcpy(bp, vp, w); + bp += bw; + vp += BYTEWIDTH; + } +} + +void __svgalib_driver8p_getbox(int x, int y, int w, int h, void *b, int bw) +{ + int vp; + int page; + char *bp = b; + int i; + ASSIGNVPOFFSET8(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (i = 0; i < h; i++) { + if (vp + w > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* page break within line */ + __memcpy(bp, VBUF + vp, 0x10000 - vp); + page++; + vga_setpage(page); + __memcpy(bp + 0x10000 - vp, VBUF, + (vp + w) & 0xffff); + vp = (vp + BYTEWIDTH) & 0xffff; + bp += bw; + continue; + } + }; + __memcpy(bp, VBUF + vp, w); + bp += bw; + vp += BYTEWIDTH; + } +} + +void __svgalib_driver8_putboxmask(int x, int y, int w, int h, void *b) +{ + uchar *bp = b; + uchar *vp; + int i; + ASSIGNVP8(x, y, vp); + for (i = 0; i < h; i++) { + uchar *endoflinebp = bp + w; + while (bp < endoflinebp - 3) { + unsigned int c4 = *(unsigned int *) bp; + if (c4 & 0xff) + *vp = (uchar) c4; + c4 >>= 8; + if (c4 & 0xff) + *(vp + 1) = (uchar) c4; + c4 >>= 8; + if (c4 & 0xff) + *(vp + 2) = (uchar) c4; + c4 >>= 8; + if (c4 & 0xff) + *(vp + 3) = (uchar) c4; + bp += 4; + vp += 4; + } + while (bp < endoflinebp) { + uchar c = *bp; + if (c) + *vp = c; + bp++; + vp++; + } + vp += BYTEWIDTH - w; + } +} + +void __svgalib_driver8_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver8_putbox(x, y, w, h, b + yo * ow + xo, ow); /* inlined */ +} + +void __svgalib_driver8p_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver8p_putbox(x, y, w, h, b + yo * ow + xo, ow); /* inlined */ +} + +void __svgalib_driver8_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver8_getbox(x, y, w, h, b + yo * ow + xo, ow); +} + +void __svgalib_driver8p_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver8p_getbox(x, y, w, h, b + yo * ow + xo, ow); +} + +void __svgalib_driver8_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + char *svp, *dvp; + /* I hope this works now. */ + if (y1 >= y2) { + if (y1 == y2 && x2 >= x1) { /* tricky */ + int i; + if (x1 == x2) + return; + /* use a temporary buffer to store a line */ + /* using reversed movs would be much faster */ + ASSIGNVP8(x1, y1, svp); + ASSIGNVP8(x2, y2, dvp); + for (i = 0; i < h; i++) { + uchar linebuf[MAXBYTEWIDTH]; + __memcpy(linebuf, svp, w); + __memcpy(dvp, linebuf, w); + svp += BYTEWIDTH; + dvp += BYTEWIDTH; + } + } else { /* copy from top to bottom */ + int i; + ASSIGNVP8(x1, y1, svp); + ASSIGNVP8(x2, y2, dvp); + for (i = 0; i < h; i++) { + __memcpy(dvp, svp, w); + svp += BYTEWIDTH; + dvp += BYTEWIDTH; + } + } + } else { /* copy from bottom to top */ + int i; + ASSIGNVP8(x1, y1 + h, svp); + ASSIGNVP8(x2, y2 + h, dvp); + for (i = 0; i < h; i++) { + svp -= BYTEWIDTH; + dvp -= BYTEWIDTH; + __memcpy(dvp, svp, w); + } + } +} + +void __svgalib_driver8a_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + vga_accel(ACCEL_SCREENCOPY, x1, y1, x2, y2, w, h); +} + + + +/* Two bytes per pixel graphics primitives */ + +#define ASSIGNVP16(x, y, vp) vp = VBUF + (y) * BYTEWIDTH + (x) * 2; +#define ASSIGNVPOFFSET16(x, y, vp) vp = (y) * BYTEWIDTH + (x) * 2; + +void __svgalib_driver16_setpixel(int x, int y, int c) +{ + char *vp; + ASSIGNVP16(x, y, vp); + *(unsigned short *) vp = c; +} + +void __svgalib_driver16p_setpixel(int x, int y, int c) +{ + int vp; + ASSIGNVPOFFSET16(x, y, vp); + vga_setpage(vp >> 16); + *(unsigned short *) (VBUF + (vp & 0xffff)) = c; +} + +int __svgalib_driver16_getpixel(int x, int y) +{ + char *vp; + ASSIGNVP16(x, y, vp); + return *(unsigned short *) vp; +} + +int __svgalib_driver16p_getpixel(int x, int y) +{ + int vp; + ASSIGNVPOFFSET16(x, y, vp); + vga_setpage(vp >> 16); + return *(unsigned short *) (VBUF + (vp & 0xffff)); +} + +void __svgalib_driver16_hline(int x1, int y, int x2, int c) +{ + char *vp; + ASSIGNVP16(x1, y, vp); + __memset2(vp, c, x2 - x1 + 1); +} + +void __svgalib_driver16p_hline(int x1, int y, int x2, int c) +{ + int vp; + char *rvp; + int l; + int chunksize, page; + ASSIGNVPOFFSET16(x1, y, vp); + SETWRITEPAGED(vp, rvp, chunksize, page); + l = (x2 - x1 + 1) * 2; + if (l <= chunksize) + __memset2(rvp, c, l / 2); + else { + __memset2(rvp, c, chunksize / 2); + vga_setpage(page + 1); + __memset2(VBUF, c, (l - chunksize) / 2); + } +} + +void __svgalib_driver16_fillbox(int x, int y, int w, int h, int c) +{ + char *vp; + int i; + ASSIGNVP16(x, y, vp); + for (i = 0; i < h; i++) { + __memset2(vp, c, w); + vp += BYTEWIDTH; + } +} + +void __svgalib_driver16p_fillbox(int x, int y, int w, int h, int c) +{ + int vp; + int page; + int i; + ASSIGNVPOFFSET16(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (i = 0; i < h; i++) { + if (vp + w * 2 > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* page break within line */ + __memset2(VBUF + vp, c, (0x10000 - vp) / 2); + page++; + vga_setpage(page); + __memset2(VBUF, c, ((vp + w * 2) & 0xffff) / 2); + vp = (vp + BYTEWIDTH) & 0xffff; + continue; + } + }; + __memset2(VBUF + vp, c, w); + vp += BYTEWIDTH; + } +} + +void __svgalib_driver16_putbox(int x, int y, int w, int h, void *b, int bw) +{ + char *vp; /* screen pointer */ + char *bp; /* bitmap pointer */ + int i; + ASSIGNVP16(x, y, vp); + bp = b; + for (i = 0; i < h; i++) { + __memcpy(vp, bp, w * 2); + bp += bw * 2; + vp += BYTEWIDTH; + } +} + +void __svgalib_driver16p_putbox(int x, int y, int w, int h, void *b, int bw) +{ + __svgalib_driver8p_putbox(x * 2, y, w * 2, h, b, bw * 2); +} + +void __svgalib_driver16_getbox(int x, int y, int w, int h, void *b, int bw) +{ + char *vp; /* screen pointer */ + char *bp; /* bitmap pointer */ + int i; + ASSIGNVP16(x, y, vp); + bp = b; + for (i = 0; i < h; i++) { + __memcpy(bp, vp, w * 2); + bp += bw * 2; + vp += BYTEWIDTH; + } +} + +INLINE void __svgalib_driver16p_getbox(int x, int y, int w, int h, void *b, int bw) +{ + __svgalib_driver8p_getbox(x * 2, y, w * 2, h, b, bw * 2); +} + +void __svgalib_driver16_putboxmask(int x, int y, int w, int h, void *b) +{ + uchar *bp = b; + uchar *vp; + int i; + ASSIGNVP16(x, y, vp); + for (i = 0; i < h; i++) { + uchar *endoflinebp = bp + w * 2; + while (bp < endoflinebp - 7) { + unsigned c2 = *(unsigned *) bp; + if (c2 & 0xffff) + *(ushort *) vp = (ushort) c2; + c2 >>= 16; + if (c2 & 0xffff) + *(ushort *) (vp + 2) = (ushort) c2; + c2 = *(unsigned *) (bp + 4); + if (c2 & 0xffff) + *(ushort *) (vp + 4) = (ushort) c2; + c2 >>= 16; + if (c2 & 0xffff) + *(ushort *) (vp + 6) = (ushort) c2; + bp += 8; + vp += 8; + } + while (bp < endoflinebp) { + ushort c = *(ushort *) bp; + if (c) + *(ushort *) vp = c; + bp += 2; + vp += 2; + } + vp += BYTEWIDTH - w * 2; + } +} + +INLINE void __svgalib_driver16_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver8_putbox(x * 2, y, w * 2, h, b + yo * ow * 2 + xo * 2, ow * 2); + /* inlined */ +} + +INLINE void __svgalib_driver16p_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver8p_putbox(x * 2, y, w * 2, h, b + yo * ow * 2 + xo * 2, ow * 2); +} + +INLINE void __svgalib_driver16_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver16_getbox(x, y, w, h, b + yo * ow + xo, ow); +} + +INLINE void __svgalib_driver16p_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver16p_getbox(x, y, w, h, b + yo * ow + xo, ow); +} + +INLINE void __svgalib_driver16_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + __svgalib_driver8_copybox(x1 * 2, y1, w * 2, h, x2 * 2, y2); +} + +void __svgalib_driver16a_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + int svp, dvp; + ASSIGNVPOFFSET16(x1, y1, svp); + ASSIGNVPOFFSET16(x2, y2, dvp); + vga_bitblt(svp, dvp, w * 2, h, BYTEWIDTH); +} + + + +/* Three bytes per pixel graphics primitives */ + +#define ASSIGNVP24(x, y, vp) vp = VBUF + (y) * BYTEWIDTH + (x) * 3; +#define ASSIGNVPOFFSET24(x, y, vp) vp = (y) * BYTEWIDTH + (x) * 3; +#define RGBEQUAL(c) ((c & 0xff) == ((c >> 8) & 0xff) && \ + (c & 0xff) == ((c >> 16) & 0xff)) + +void __svgalib_driver24_setpixel(int x, int y, int c) +{ + char *vp; + c = RGB2BGR(c); + ASSIGNVP24(x, y, vp); + *(unsigned short *) vp = c; + *(unsigned char *) (vp + 2) = c >> 16; +} + +void __svgalib_driver24p_setpixel(int x, int y, int c) +{ + int vp, vpo; + char *vbuf; + int page; + c = RGB2BGR(c); + ASSIGNVPOFFSET24(x, y, vp); + vbuf = VBUF; + page = vp >> 16; + vga_setpage(page); + vpo = vp & 0xffff; + if (vpo <= 0xfffd) { + *(unsigned short *) (vbuf + vpo) = c; + *(unsigned char *) (vbuf + vpo + 2) = c >> 16; + } else if (vpo == 0xfffe) { + *(unsigned short *) (vbuf + 0xfffe) = c; + vga_setpage(page + 1); + *(unsigned char *) vbuf = c >> 16; + } else { /* vpo == 0xffff */ + *(unsigned char *) (vbuf + 0xffff) = c; + vga_setpage(page + 1); + *(unsigned short *) vbuf = c >> 8; + } +} + +int __svgalib_driver24_getpixel(int x, int y) +{ + char *vp; + ASSIGNVP24(x, y, vp); + return RGB2BGR(*(unsigned short *) vp + (*(unsigned char *) (vp + 2) << 16)); +} + +int __svgalib_driver24p_getpixel(int x, int y) +{ + int vp, vpo; + char *vbuf; + int page; + ASSIGNVPOFFSET24(x, y, vp); + vbuf = VBUF; + page = vp >> 16; + vga_setpage(page); + vpo = vp & 0xffff; + if (vpo <= 0xfffd) + return RGB2BGR(*(unsigned short *) (vbuf + vpo) + + (*(unsigned char *) (vbuf + vpo + 2) << 16)); + else if (vpo == 0xfffe) { + int c; + c = *(unsigned short *) (vbuf + 0xfffe); + vga_setpage(page + 1); + return RGB2BGR((*(unsigned char *) vbuf << 16) + c); + } else { /* vpo == 0xffff */ + int c; + c = *(unsigned char *) (vbuf + 0xffff); + vga_setpage(page + 1); + return RGB2BGR((*(unsigned short *) vbuf << 8) + c); + } +} + +void __svgalib_driver24_hline(int x1, int y, int x2, int c) +{ + char *vp; + c = RGB2BGR(c); + ASSIGNVP24(x1, y, vp); + if (RGBEQUAL(c)) + __memset(vp, c, (x2 - x1 + 1) * 3); + else + __memset3(vp, c, x2 - x1 + 1); +} + +void __svgalib_driver24p_hline(int x1, int y, int x2, int c) +{ + int vp; + char *rvp; + int l; + int chunksize, page; + c = RGB2BGR(c); + ASSIGNVPOFFSET24(x1, y, vp); + SETWRITEPAGED(vp, rvp, chunksize, page); + l = (x2 - x1 + 1) * 3; + if (l <= chunksize) + __memset3(rvp, c, l / 3); + else { + int n, m, o; + n = chunksize / 3; + m = chunksize % 3; + __memset3(rvp, c, n); + /* Handle page break within pixel. */ + if (m >= 1) + *(rvp + n * 3) = c; + if (m == 2) + *(rvp + n * 3 + 1) = c >> 8; + vga_setpage(page + 1); + o = 0; + if (m == 2) { + *(VBUF) = c >> 16; + o = 1; + } + if (m == 1) { + *(unsigned short *) (VBUF) = c >> 8; + o = 2; + } + __memset3(VBUF + o, c, (l - chunksize) / 3); + } +} + +void __svgalib_driver24_fillbox(int x, int y, int w, int h, int c) +{ + char *vp; + int i, j; + c = RGB2BGR(c); + ASSIGNVP24(x, y, vp); + if (RGBEQUAL(c)) + for (i = 0; i < h; i++) { + __memset(vp, c, w * 3); + vp += BYTEWIDTH; + } else + for (j = 0; j < h; j++) { + __memset3(vp, c, w); + vp += BYTEWIDTH; + } +} + +void __svgalib_driver24p_fillbox(int x, int y, int w, int h, int c) +{ + int vp; + int page; + int i; + c = RGB2BGR(c); + ASSIGNVPOFFSET24(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + if (RGBEQUAL(c)) { + for (i = 0; i < h; i++) { + if (vp + w * 3 > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* Page break within line. */ + __memset(VBUF + vp, c, 0x10000 - vp); + page++; + vga_setpage(page); + __memset(VBUF, c, (vp + w * 3) & 0xffff); + vp = (vp + BYTEWIDTH) & 0xffff; + continue; + } + }; + __memset(VBUF + vp, c, w * 3); + vp += BYTEWIDTH; + } + } else + for (i = 0; i < h; i++) { + if (vp + w * 3 > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* Page break within line. */ + int n, m, o; + n = (0x10000 - vp) / 3; + m = (0x10000 - vp) % 3; + __memset3(VBUF + vp, c, n); + /* Handle page break within pixel. */ + if (m >= 1) + *(VBUF + vp + n * 3) = c; + if (m == 2) + *(VBUF + vp + n * 3 + 1) = c >> 8; + page++; + vga_setpage(page); + o = 0; + if (m == 2) { + *(VBUF) = c >> 16; + o = 1; + } + if (m == 1) { + *(unsigned short *) (VBUF) = c >> 8; + o = 2; + } + __memset3(VBUF + o, c, ((vp + w * 3) & 0xffff) / 3); + vp = (vp + BYTEWIDTH) & 0xffff; + continue; + } + }; + __memset3(VBUF + vp, c, w); + vp += BYTEWIDTH; + } +} + +void __svgalib_driver24_putbox(int x, int y, int w, int h, void *b, int bw) +{ + char *vp; /* screen pointer */ + char *bp; /* bitmap pointer */ + int i; + ASSIGNVP24(x, y, vp); + bp = b; + if (MODEFLAGS & MODEFLAG_24BPP_REVERSED) { + for (i = 0; i < h; i++) { + RGB_swapped_memcpy(vp, bp, w * 3); + bp += bw * 3; + vp += BYTEWIDTH; + } + } else { + for (i = 0; i < h; i++) { + __memcpy(vp, bp, w * 3); + bp += bw * 3; + vp += BYTEWIDTH; + } + } +} + +static void driver24_rev_putbox(int x, int y, int w, int h, void *b, int bw) +{ +/* extra argument width of source bitmap, so that putboxpart can use this */ + int vp; + int page; + char *bp = b, *bp2; + int i, left; + + ASSIGNVPOFFSET8(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (i = 0; i < h; i++) { + if (vp + w > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* page break within line */ + left = RGB_swapped_memcpy(VBUF + vp, bp, 0x10000 - vp); + bp2 = bp + (0x10000 - vp - left); + switch (left) { + case 2: + *(VBUF + 0xFFFE) = bp2[2]; + *(VBUF + 0xFFFF) = bp2[1]; + break; + case 1: + *(VBUF + 0xFFFF) = bp2[2]; + break; + } + + page++; + vga_setpage(page); + + switch (left) { + case 1: + *(VBUF) = bp2[1]; + *(VBUF + 1) = bp2[0]; + left = 3 - left; + bp2 += 3; + break; + case 2: + *(VBUF) = bp2[0]; + left = 3 - left; + bp2 += 3; + break; + } + + RGB_swapped_memcpy(VBUF + left, bp2, ((vp + w) & 0xffff) - left); + vp = (vp + BYTEWIDTH) & 0xffff; + bp += bw; + continue; + } + }; + RGB_swapped_memcpy(VBUF + vp, bp, w); + bp += bw; + vp += BYTEWIDTH; + } +} + +INLINE void __svgalib_driver24p_putbox(int x, int y, int w, int h, void *b, int bw) +{ + if (MODEFLAGS & MODEFLAG_24BPP_REVERSED) { + driver24_rev_putbox(x * 3, y, w * 3, h, b, bw * 3); + } else { + __svgalib_driver8p_putbox(x * 3, y, w * 3, h, b, bw * 3); + } +} + +void __svgalib_driver24_putbox32(int x, int y, int w, int h, void *b, int bw) +{ + char *vp; /* screen pointer */ + char *bp; /* bitmap pointer */ + int i; + ASSIGNVP24(x, y, vp); + bp = b; + for (i = 0; i < h; i++) { + __svgalib_memcpy4to3(vp, bp, w); + bp += bw * 4; + vp += BYTEWIDTH; + } +} + +void __svgalib_driver24_getbox(int x, int y, int w, int h, void *b, int bw) +{ + char *vp; /* screen pointer */ + char *bp; /* bitmap pointer */ + int i; + ASSIGNVP24(x, y, vp); + bp = b; + if (MODEFLAGS & MODEFLAG_24BPP_REVERSED) { + for (i = 0; i < h; i++) { + RGB_swapped_memcpy(bp, vp, w * 3); + bp += bw * 3; + vp += BYTEWIDTH; + } + } else { + for (i = 0; i < h; i++) { + __memcpy(bp, vp, w * 3); + bp += bw * 3; + vp += BYTEWIDTH; + } + } +} + +static void driver24_rev_getbox(int x, int y, int w, int h, void *b, int bw) +{ +/* extra argument width of source bitmap, so that putboxpart can use this */ + int vp; + int page; + char *bp = b, *bp2; + int i, left; + + ASSIGNVPOFFSET8(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (i = 0; i < h; i++) { + if (vp + w > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* page break within line */ + left = RGB_swapped_memcpy(bp, VBUF + vp, 0x10000 - vp); + bp2 = bp + (0x10000 - vp - left); + switch (left) { + case 2: + bp2[2] = *(VBUF + 0xFFFE); + bp2[1] = *(VBUF + 0xFFFF); + break; + case 1: + bp2[2] = *(VBUF + 0xFFFF); + break; + } + + page++; + vga_setpage(page); + + switch (left) { + case 1: + bp2[1] = *(VBUF); + bp2[0] = *(VBUF + 1); + left = 3 - left; + bp2 += 3; + break; + case 2: + bp2[0] = *(VBUF); + left = 3 - left; + bp2 += 3; + break; + } + + RGB_swapped_memcpy(bp2, VBUF + left, ((vp + w) & 0xffff) - left); + vp = (vp + BYTEWIDTH) & 0xffff; + bp += bw; + continue; + } + }; + RGB_swapped_memcpy(bp, VBUF + vp, w); + bp += bw; + vp += BYTEWIDTH; + } +} + +INLINE void __svgalib_driver24p_getbox(int x, int y, int w, int h, void *b, int bw) +{ + if (MODEFLAGS & MODEFLAG_24BPP_REVERSED) { + driver24_rev_getbox(x * 3, y, w * 3, h, b, bw * 3); + } else { + __svgalib_driver8p_getbox(x * 3, y, w * 3, h, b, bw * 3); + } +} + +void __svgalib_driver24_putboxmask(int x, int y, int w, int h, void *b) +{ + uchar *bp = b; + uchar *vp; + int i; + ASSIGNVP24(x, y, vp); + for (i = 0; i < h; i++) { + uchar *endoflinebp = bp + w * 3; + while (bp < endoflinebp - 11) { + unsigned c = RGB2BGR(*(unsigned *) bp); + if (c & 0xffffff) { + *(ushort *) vp = (ushort) c; + *(vp + 2) = c >> 16; + } + c = RGB2BGR(*(unsigned *) (bp + 3)); + if (c & 0xffffff) { + *(ushort *) (vp + 3) = (ushort) c; + *(vp + 5) = c >> 16; + } + c = RGB2BGR(*(unsigned *) (bp + 6)); + if (c & 0xffffff) { + *(ushort *) (vp + 6) = (ushort) c; + *(vp + 8) = c >> 16; + } + c = RGB2BGR(*(unsigned *) (bp + 9)); + if (c & 0xffffff) { + *(ushort *) (vp + 9) = (ushort) c; + *(vp + 11) = c >> 16; + } + bp += 12; + vp += 12; + } + while (bp < endoflinebp) { + uint c = RGB2BGR(*(uint *) bp); + if (c & 0xffffff) { + *(ushort *) vp = (ushort) c; + *(vp + 2) = c >> 16; + } + bp += 3; + vp += 3; + } + vp += BYTEWIDTH - w * 3; + } +} + +INLINE void __svgalib_driver24_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + /* + * Actually I think all this could be done by just calling __svgalib_driver24_putbox + * with correct args. But I'm too fearful. - Michael. + */ + if (MODEFLAGS & MODEFLAG_24BPP_REVERSED) { + __svgalib_driver24_putbox(x, y, w, h, b + yo * ow + xo, ow); + } else { + __svgalib_driver8_putbox(x * 3, y, w * 3, h, b + yo * ow * 3 + xo * 3, ow * 3); + } +} + +INLINE void __svgalib_driver24p_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + if (MODEFLAGS & MODEFLAG_24BPP_REVERSED) { + driver24_rev_putbox(x * 3, y, w * 3, h, b + yo * ow * 3 + xo * 3, ow * 3); + } else { + __svgalib_driver8p_putbox(x * 3, y, w * 3, h, b + yo * ow * 3 + xo * 3, ow * 3); + } +} + +INLINE void __svgalib_driver24_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver24_getbox(x, y, w, h, b + yo * ow + xo, ow); +} + +INLINE void __svgalib_driver24p_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver24p_getbox(x, y, w, h, b + yo * ow + xo, ow); +} + +void __svgalib_driver24_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + __svgalib_driver8_copybox(x1 * 3, y1, w * 3, h, x2 * 3, y2); +} + +void __svgalib_driver24a_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + int svp, dvp; + ASSIGNVPOFFSET24(x1, y1, svp); + ASSIGNVPOFFSET24(x2, y2, dvp); + vga_bitblt(svp, dvp, w * 3, h, BYTEWIDTH); +} + + + +/* Four bytes per pixel graphics primitives */ + +#define ASSIGNVP32(x, y, vp) vp = VBUF + (y) * BYTEWIDTH + (x) * 4; +#define ASSIGNVPOFFSET32(x, y, vp) vp = (y) * BYTEWIDTH + (x) * 4; + +void __svgalib_driver32_setpixel(int x, int y, int c) +{ + char *vp; + ASSIGNVP32(x, y, vp); + *(unsigned *) vp = c; +} + +void __svgalib_driver32p_setpixel(int x, int y, int c) +{ + int vp; + ASSIGNVPOFFSET32(x, y, vp); + vga_setpage(vp >> 16); + *(unsigned *) (VBUF + (vp & 0xffff)) = c; +} + +int __svgalib_driver32_getpixel(int x, int y) +{ + char *vp; + ASSIGNVP32(x, y, vp); + return *(unsigned *) vp; +} + +int __svgalib_driver32p_getpixel(int x, int y) +{ + int vp; + ASSIGNVPOFFSET32(x, y, vp); + vga_setpage(vp >> 16); + return *(unsigned *) (VBUF + (vp & 0xffff)); +} + +void __svgalib_driver32_hline(int x1, int y, int x2, int c) +{ + char *vp; + ASSIGNVP32(x1, y, vp); + __memset4(vp, c, x2 - x1 + 1); +} + +void __svgalib_driver32p_hline(int x1, int y, int x2, int c) +{ + int vp; + char *rvp; + int l; + int chunksize, page; + ASSIGNVPOFFSET32(x1, y, vp); + SETWRITEPAGED(vp, rvp, chunksize, page); + l = (x2 - x1 + 1) * 4; + if (l <= chunksize) + __memset4(rvp, c, l / 4); + else { + __memset4(rvp, c, chunksize / 4); + vga_setpage(page + 1); + __memset4(VBUF, c, (l - chunksize) / 4); + } +} + +void __svgalib_driver32_fillbox(int x, int y, int w, int h, int c) +{ + char *vp; + int i; + ASSIGNVP32(x, y, vp); + for (i = 0; i < h; i++) { + __memset4(vp, c, w); + vp += BYTEWIDTH; + } +} + +void __svgalib_driver32p_fillbox(int x, int y, int w, int h, int c) +{ + int vp; + int page; + int i; + ASSIGNVPOFFSET32(x, y, vp); + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (i = 0; i < h; i++) { + if (vp + w * 4 > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { /* page break within line */ + __memset4(VBUF + vp, c, (0x10000 - vp) / 4); + page++; + vga_setpage(page); + __memset4(VBUF, c, ((vp + w * 4) & 0xffff) / 4); + vp = (vp + BYTEWIDTH) & 0xffff; + continue; + } + }; + __memset4(VBUF + vp, c, w); + vp += BYTEWIDTH; + } +} + +INLINE void __svgalib_driver32_putbox(int x, int y, int w, int h, void *b, int bw) +{ + __svgalib_driver8_putbox(x * 4, y, w * 4, h, b, bw * 4); +} + +INLINE void __svgalib_driver32p_putbox(int x, int y, int w, int h, void *b, int bw) +{ + __svgalib_driver8p_putbox(x * 4, y, w * 4, h, b, bw * 4); +} + +INLINE void __svgalib_driver32_getbox(int x, int y, int w, int h, void *b, int bw) +{ + __svgalib_driver8_getbox(x * 4, y, w * 4, h, b, bw * 4); +} + +INLINE void __svgalib_driver32p_getbox(int x, int y, int w, int h, void *b, int bw) +{ + __svgalib_driver8p_getbox(x * 4, y, w * 4, h, b, bw * 4); +} + +void __svgalib_driver32_putboxmask(int x, int y, int w, int h, void *b) +{ + uchar *bp = b; + uchar *vp; + int i; + ASSIGNVP32(x, y, vp); + for (i = 0; i < h; i++) { + uchar *endoflinebp = bp + w * 4; + while (bp < endoflinebp - 15) { + unsigned c = *(unsigned *) bp; + if (c) + *(unsigned *) vp = c; + c = *(unsigned *) (bp + 4); + if (c) + *(unsigned *) (vp + 4) = c; + c = *(unsigned *) (bp + 8); + if (c) + *(unsigned *) (vp + 8) = c; + c = *(unsigned *) (bp + 12); + if (c) + *(unsigned *) (vp + 12) = c; + bp += 16; + vp += 16; + } + while (bp < endoflinebp) { + unsigned c = *(unsigned *) bp; + if (c) + *(unsigned *) vp = c; + bp += 4; + vp += 4; + } + vp += BYTEWIDTH - w * 4; + } +} + +INLINE void __svgalib_driver32_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver32_putbox(x, y, w, h, b + yo * ow * 4 + xo * 4 , ow ); + /* inlined */ +} + +INLINE void __svgalib_driver32p_putboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver32p_putbox(x, y, w, h, b + yo * ow * 4 + xo * 4, ow ); + /* inlined */ +} + +INLINE void __svgalib_driver32_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver32_getbox(x, y, w, h, b + yo * ow * 4 + xo * 4 , ow ); +} + +INLINE void __svgalib_driver32p_getboxpart(int x, int y, int w, int h, int ow, int oh, + void *b, int xo, int yo) +{ + __svgalib_driver32p_getbox(x, y, w, h, b + yo * ow * 4 + xo * 4 , ow ); +} + +INLINE void __svgalib_driver32_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + __svgalib_driver8_copybox(x1 * 4, y1, w * 4, h, x2 * 4, y2); +} + + + +/* Planar 256 color mode graphics primitives (only putbox) */ + +void __svgalib_driverplanar256_nothing(void) +{ + NOTIMPL("planar 256 color mode primitive"); +} + +void __svgalib_driverplanar256_putbox(int x, int y, int w, int h, void *b, int bw) +{ + if ((w & 3) != 0 || (x & 3) != 0) + NOTIMPL("planar 256 color mode unaligned putbox"); + vga_copytoplanar256(b, bw, y * BYTEWIDTH + x / 4, BYTEWIDTH, + w, h); +} + +void __svgalib_driverplanar16_nothing(void) +{ + NOTIMPL("planar 16 color mode primitive"); +} + + +/* Memory primitives */ + +int __svgalib_driver_setread(GraphicsContext * gc, int i, void **vp) +{ + if (gc->modetype == CONTEXT_PAGED) { + vga_setpage(i >> 16); + *vp = (i & 0xffff) + gc->vbuf; + return 0x10000 - (i & 0xffff); + } else { + *vp = gc->vbuf + i; + return 0x10000; + } +} + +int __svgalib_driver_setwrite(GraphicsContext * gc, int i, void **vp) +{ + if (gc->modetype == CONTEXT_PAGED) { + vga_setpage(i >> 16); + *vp = (i & 0xffff) + gc->vbuf; + return 0x10000 - (i & 0xffff); + } else { + *vp = gc->vbuf + i; + return 0x10000; + } +} + + + +/* Functions that are not yet implemented */ + +void __svgalib_driver8p_putboxmask(int x, int y, int w, int h, void *b) +{ + NOTIMPL("8-bit paged putboxmask"); +} + +void __svgalib_driver8p_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + NOTIMPL("8-bit paged copybox (bitblt)"); +} + +void __svgalib_driver16p_putboxmask(int x, int y, int w, int h, void *b) +{ + NOTIMPL("16-bit paged putboxmask"); +} + +void __svgalib_driver16p_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + NOTIMPL("16-bit paged copybox"); +} + +void __svgalib_driver24p_putboxmask(int x, int y, int w, int h, void *b) +{ + NOTIMPL("24-bit paged putboxmask"); +} + +void __svgalib_driver24p_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + NOTIMPL("24-bit paged copybox"); +} + +void __svgalib_driver32p_putboxmask(int x, int y, int w, int h, void *b) +{ + NOTIMPL("32-bit paged putboxmask"); +} + +void __svgalib_driver32p_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ + NOTIMPL("32-bit paged copybox"); +} diff --git a/gl/driver.h b/gl/driver.h new file mode 100644 index 0000000..77e79a3 --- /dev/null +++ b/gl/driver.h @@ -0,0 +1,104 @@ +void __svgalib_driver8_setpixel(int, int, int); +int __svgalib_driver8_getpixel(int, int); +void __svgalib_driver8_hline(int, int, int, int); +void __svgalib_driver8_fillbox(int, int, int, int, int); +void __svgalib_driver8_putbox(int, int, int, int, void *, int); +void __svgalib_driver8_getbox(int, int, int, int, void *, int); +void __svgalib_driver8_putboxmask(int, int, int, int, void *); +void __svgalib_driver8_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver8_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver8_copybox(int, int, int, int, int, int); + +void __svgalib_driver16_setpixel(int, int, int); +int __svgalib_driver16_getpixel(int, int); +void __svgalib_driver16_hline(int, int, int, int); +void __svgalib_driver16_fillbox(int, int, int, int, int); +void __svgalib_driver16_putbox(int, int, int, int, void *, int); +void __svgalib_driver16_getbox(int, int, int, int, void *, int); +void __svgalib_driver16_putboxmask(int, int, int, int, void *); +void __svgalib_driver16_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver16_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver16_copybox(int, int, int, int, int, int); + +void __svgalib_driver24_setpixel(int, int, int); +int __svgalib_driver24_getpixel(int, int); +void __svgalib_driver24_hline(int, int, int, int); +void __svgalib_driver24_fillbox(int, int, int, int, int); +void __svgalib_driver24_putbox(int, int, int, int, void *, int); +void __svgalib_driver24_getbox(int, int, int, int, void *, int); +void __svgalib_driver24_putboxmask(int, int, int, int, void *); +void __svgalib_driver24_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver24_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver24_copybox(int, int, int, int, int, int); +void __svgalib_driver24_putbox32(int, int, int, int, void *, int); + +void __svgalib_driver32_setpixel(int, int, int); +int __svgalib_driver32_getpixel(int, int); +void __svgalib_driver32_hline(int, int, int, int); +void __svgalib_driver32_fillbox(int, int, int, int, int); +void __svgalib_driver32_putbox(int, int, int, int, void *, int); +void __svgalib_driver32_getbox(int, int, int, int, void *, int); +void __svgalib_driver32_putboxmask(int, int, int, int, void *); +void __svgalib_driver32_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver32_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver32_copybox(int, int, int, int, int, int); + +void __svgalib_driver8p_setpixel(int, int, int); +int __svgalib_driver8p_getpixel(int, int); +void __svgalib_driver8p_hline(int, int, int, int); +void __svgalib_driver8p_fillbox(int, int, int, int, int); +void __svgalib_driver8p_putbox(int, int, int, int, void *, int); +void __svgalib_driver8p_getbox(int, int, int, int, void *, int); +void __svgalib_driver8p_putboxmask(int, int, int, int, void *); +void __svgalib_driver8p_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver8p_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver8p_copybox(int, int, int, int, int, int); + +void __svgalib_driver16p_setpixel(int, int, int); +int __svgalib_driver16p_getpixel(int, int); +void __svgalib_driver16p_hline(int, int, int, int); +void __svgalib_driver16p_fillbox(int, int, int, int, int); +void __svgalib_driver16p_putbox(int, int, int, int, void *, int); +void __svgalib_driver16p_getbox(int, int, int, int, void *, int); +void __svgalib_driver16p_putboxmask(int, int, int, int, void *); +void __svgalib_driver16p_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver16p_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver16p_copybox(int, int, int, int, int, int); + +void __svgalib_driver24p_setpixel(int, int, int); +int __svgalib_driver24p_getpixel(int, int); +void __svgalib_driver24p_hline(int, int, int, int); +void __svgalib_driver24p_fillbox(int, int, int, int, int); +void __svgalib_driver24p_putbox(int, int, int, int, void *, int); +void __svgalib_driver24p_getbox(int, int, int, int, void *, int); +void __svgalib_driver24p_putboxmask(int, int, int, int, void *); +void __svgalib_driver24p_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver24p_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver24p_copybox(int, int, int, int, int, int); + +void __svgalib_driver32p_setpixel(int, int, int); +int __svgalib_driver32p_getpixel(int, int); +void __svgalib_driver32p_hline(int, int, int, int); +void __svgalib_driver32p_fillbox(int, int, int, int, int); +void __svgalib_driver32p_putbox(int, int, int, int, void *, int); +void __svgalib_driver32p_getbox(int, int, int, int, void *, int); +void __svgalib_driver32p_putboxmask(int, int, int, int, void *); +void __svgalib_driver32p_putboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver32p_getboxpart(int, int, int, int, int, int, void *, int, int); +void __svgalib_driver32p_copybox(int, int, int, int, int, int); + +void __svgalib_driver8a_fillbox(int, int, int, int, int); +void __svgalib_driver8a_copybox(int, int, int, int, int, int); + +void __svgalib_driverplanar256_nothing(void); +void __svgalib_driverplanar256_putbox(int, int, int, int, void *, int); + +void __svgalib_driverplanar16_nothing(void); + +/* Generic functions */ + +int __svgalib_driver_setread(GraphicsContext * gc, int i, void **vp); +int __svgalib_driver_setwrite(GraphicsContext * gc, int i, void **vp); + +/* internal globals: */ +extern void (*__svgalib_nonaccel_fillbox)(int, int, int, int, int); diff --git a/gl/font8x8.c b/gl/font8x8.c new file mode 100644 index 0000000..b98c12c --- /dev/null +++ b/gl/font8x8.c @@ -0,0 +1,137 @@ + +/* binary image of font8x8 follows */ + + +static unsigned char __font8x8[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 126, 129, 165, 129, 189, 129, 126, 0, /* 0 to 15 */ + 126, 255, 219, 255, 195, 255, 126, 0, 54, 127, 127, 127, 62, 28, 8, 0, /* 16 to 31 */ + 8, 28, 62, 127, 62, 28, 8, 0, 28, 28, 8, 107, 127, 107, 8, 28, /* 32 to 47 */ + 8, 28, 62, 127, 62, 8, 28, 62, 0, 0, 24, 60, 60, 24, 0, 0, /* 48 to 63 */ + 255, 255, 231, 195, 195, 231, 255, 255, 0, 60, 102, 66, 66, 102, 60, 0, /* 64 to 79 */ +255, 195, 153, 189, 189, 153, 195, 255, 15, 7, 13, 60, 102, 102, 102, 60, /* 80 to 95 */ + 60, 102, 102, 102, 60, 24, 126, 24, 48, 56, 60, 54, 52, 112, 240, 224, /* 96 to 111 */ +127, 99, 127, 99, 99, 103, 230, 192, 24, 219, 126, 102, 102, 126, 219, 24, /* 112 to 127 */ + 64, 112, 124, 127, 124, 112, 64, 0, 1, 7, 31, 127, 31, 7, 1, 0, /* 128 to 143 */ + 24, 60, 126, 24, 24, 126, 60, 24, 102, 102, 102, 102, 102, 0, 102, 0, /* 144 to 159 */ + 63, 122, 122, 58, 10, 10, 10, 0, 30, 51, 28, 54, 54, 28, 102, 60, /* 160 to 175 */ + 0, 0, 0, 0, 126, 126, 126, 0, 24, 60, 126, 24, 126, 60, 24, 126, /* 176 to 191 */ + 24, 60, 126, 24, 24, 24, 24, 0, 24, 24, 24, 24, 126, 60, 24, 0, /* 192 to 207 */ + 0, 12, 14, 127, 14, 12, 0, 0, 0, 24, 56, 127, 56, 24, 0, 0, /* 208 to 223 */ + 0, 0, 96, 96, 96, 127, 0, 0, 0, 36, 102, 255, 102, 36, 0, 0, /* 224 to 239 */ + 0, 24, 60, 126, 255, 255, 0, 0, 0, 255, 255, 126, 60, 24, 0, 0, /* 240 to 255 */ + 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 0, 24, 0, /* 256 to 271 */ + 102, 102, 102, 0, 0, 0, 0, 0, 108, 108, 254, 108, 254, 108, 108, 0, /* 272 to 287 */ + 16, 124, 208, 124, 22, 124, 16, 0, 0, 198, 204, 24, 48, 102, 198, 0, /* 288 to 303 */ + 56, 108, 56, 118, 220, 204, 118, 0, 24, 24, 48, 0, 0, 0, 0, 0, /* 304 to 319 */ + 12, 24, 48, 48, 48, 24, 12, 0, 48, 24, 12, 12, 12, 24, 48, 0, /* 320 to 335 */ + 0, 108, 56, 254, 56, 108, 0, 0, 0, 24, 24, 126, 24, 24, 0, 0, /* 336 to 351 */ + 0, 0, 0, 0, 0, 24, 24, 48, 0, 0, 0, 126, 0, 0, 0, 0, /* 352 to 367 */ + 0, 0, 0, 0, 0, 48, 48, 0, 0, 6, 12, 24, 48, 96, 192, 0, /* 368 to 383 */ + 60, 102, 110, 126, 118, 102, 60, 0, 12, 28, 60, 12, 12, 12, 12, 0, /* 384 to 399 */ + 60, 102, 6, 28, 48, 96, 126, 0, 60, 102, 6, 28, 6, 102, 60, 0, /* 400 to 415 */ + 28, 60, 108, 204, 254, 12, 12, 0, 126, 96, 96, 124, 6, 102, 60, 0, /* 416 to 431 */ + 60, 96, 96, 124, 102, 102, 60, 0, 126, 6, 6, 12, 24, 48, 48, 0, /* 432 to 447 */ + 60, 102, 102, 60, 102, 102, 60, 0, 60, 102, 102, 62, 6, 6, 60, 0, /* 448 to 463 */ + 0, 48, 48, 0, 0, 48, 48, 0, 0, 24, 24, 0, 0, 24, 24, 48, /* 464 to 479 */ + 12, 24, 48, 96, 48, 24, 12, 0, 0, 0, 126, 0, 0, 126, 0, 0, /* 480 to 495 */ + 48, 24, 12, 6, 12, 24, 48, 0, 60, 102, 6, 12, 24, 0, 24, 0, /* 496 to 511 */ + 60, 102, 110, 110, 108, 96, 60, 0, 24, 60, 102, 102, 126, 102, 102, 0, /* 512 to 527 */ + 124, 102, 102, 124, 102, 102, 124, 0, 60, 102, 96, 96, 96, 102, 60, 0, /* 528 to 543 */ + 124, 102, 102, 102, 102, 102, 124, 0, 126, 96, 96, 124, 96, 96, 126, 0, /* 544 to 559 */ + 126, 96, 96, 124, 96, 96, 96, 0, 60, 102, 96, 110, 102, 102, 60, 0, /* 560 to 575 */ + 102, 102, 102, 126, 102, 102, 102, 0, 60, 24, 24, 24, 24, 24, 60, 0, /* 576 to 591 */ + 6, 6, 6, 6, 102, 102, 60, 0, 102, 108, 120, 112, 120, 108, 102, 0, /* 592 to 607 */ + 96, 96, 96, 96, 96, 96, 126, 0, 198, 238, 254, 214, 198, 198, 198, 0, /* 608 to 623 */ +102, 118, 126, 110, 102, 102, 102, 0, 60, 102, 102, 102, 102, 102, 60, 0, /* 624 to 639 */ + 124, 102, 102, 124, 96, 96, 96, 0, 60, 102, 102, 102, 102, 110, 60, 6, /* 640 to 655 */ + 124, 102, 102, 124, 102, 102, 102, 0, 60, 102, 96, 60, 6, 102, 60, 0, /* 656 to 671 */ + 126, 24, 24, 24, 24, 24, 24, 0, 102, 102, 102, 102, 102, 102, 60, 0, /* 672 to 687 */ +102, 102, 102, 102, 102, 60, 24, 0, 198, 198, 198, 214, 254, 238, 198, 0, /* 688 to 703 */ + 102, 102, 60, 24, 60, 102, 102, 0, 102, 102, 102, 60, 24, 24, 24, 0, /* 704 to 719 */ + 126, 6, 12, 24, 48, 96, 126, 0, 60, 48, 48, 48, 48, 48, 60, 0, /* 720 to 735 */ + 0, 192, 96, 48, 24, 12, 6, 0, 60, 12, 12, 12, 12, 12, 60, 0, /* 736 to 751 */ + 24, 60, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, /* 752 to 767 */ + 24, 24, 12, 0, 0, 0, 0, 0, 0, 0, 60, 6, 62, 102, 62, 0, /* 768 to 783 */ + 96, 96, 96, 124, 102, 102, 124, 0, 0, 0, 60, 102, 96, 102, 60, 0, /* 784 to 799 */ + 6, 6, 6, 62, 102, 102, 62, 0, 0, 0, 60, 102, 126, 96, 62, 0, /* 800 to 815 */ + 28, 54, 48, 124, 48, 48, 48, 0, 0, 0, 62, 102, 102, 62, 6, 60, /* 816 to 831 */ + 96, 96, 124, 102, 102, 102, 102, 0, 24, 0, 24, 24, 24, 24, 24, 0, /* 832 to 847 */ + 12, 0, 12, 12, 12, 12, 108, 56, 96, 96, 102, 108, 120, 108, 102, 0, /* 848 to 863 */ + 48, 48, 48, 48, 48, 48, 24, 0, 0, 0, 236, 254, 214, 214, 198, 0, /* 864 to 879 */ + 0, 0, 124, 102, 102, 102, 102, 0, 0, 0, 60, 102, 102, 102, 60, 0, /* 880 to 895 */ + 0, 0, 124, 102, 102, 124, 96, 96, 0, 0, 62, 102, 102, 62, 6, 6, /* 896 to 911 */ + 0, 0, 124, 102, 96, 96, 96, 0, 0, 0, 62, 96, 60, 6, 124, 0, /* 912 to 927 */ + 48, 48, 124, 48, 48, 54, 28, 0, 0, 0, 102, 102, 102, 102, 62, 0, /* 928 to 943 */ + 0, 0, 102, 102, 102, 60, 24, 0, 0, 0, 198, 214, 254, 238, 68, 0, /* 944 to 959 */ + 0, 0, 102, 60, 24, 60, 102, 0, 0, 0, 102, 102, 102, 62, 6, 60, /* 960 to 975 */ + 0, 0, 126, 12, 24, 48, 126, 0, 28, 48, 48, 96, 48, 48, 28, 0, /* 976 to 991 */ + 24, 24, 24, 24, 24, 24, 24, 0, 56, 12, 12, 6, 12, 12, 56, 0, /* 992 to 1007 */ + 118, 220, 0, 0, 0, 0, 0, 0, 0, 0, 24, 60, 102, 102, 126, 0, /* 1008 to 1023 */ + 60, 102, 96, 96, 102, 60, 24, 48, 102, 0, 102, 102, 102, 102, 62, 0, /* 1024 to 1039 */ + 14, 0, 60, 102, 126, 96, 60, 0, 60, 102, 60, 6, 62, 102, 62, 0, /* 1040 to 1055 */ + 102, 0, 60, 6, 62, 102, 62, 0, 112, 0, 60, 6, 62, 102, 62, 0, /* 1056 to 1071 */ + 24, 24, 60, 6, 62, 102, 62, 0, 0, 0, 62, 96, 96, 62, 24, 48, /* 1072 to 1087 */ + 60, 102, 60, 102, 126, 96, 60, 0, 102, 0, 60, 102, 126, 96, 60, 0, /* 1088 to 1103 */ + 112, 0, 60, 102, 126, 96, 60, 0, 102, 0, 24, 24, 24, 24, 24, 0, /* 1104 to 1119 */ + 60, 102, 24, 24, 24, 24, 24, 0, 112, 0, 24, 24, 24, 24, 24, 0, /* 1120 to 1135 */ + 198, 56, 108, 198, 254, 198, 198, 0, 24, 24, 0, 60, 102, 126, 102, 0, /* 1136 to 1151 */ + 14, 0, 124, 96, 120, 96, 124, 0, 0, 0, 126, 26, 126, 216, 126, 0, /* 1152 to 1167 */ + 62, 120, 216, 222, 248, 216, 222, 0, 60, 102, 60, 102, 102, 102, 60, 0, /* 1168 to 1183 */ + 102, 0, 60, 102, 102, 102, 60, 0, 112, 0, 60, 102, 102, 102, 60, 0, /* 1184 to 1199 */ + 60, 102, 0, 102, 102, 102, 62, 0, 112, 0, 102, 102, 102, 102, 62, 0, /* 1200 to 1215 */ + 102, 0, 102, 102, 102, 62, 6, 60, 102, 60, 102, 102, 102, 102, 60, 0, /* 1216 to 1231 */ + 102, 0, 102, 102, 102, 102, 60, 0, 12, 12, 62, 96, 96, 62, 12, 12, /* 1232 to 1247 */ + 56, 108, 96, 240, 96, 102, 252, 0, 102, 102, 60, 24, 126, 24, 126, 24, /* 1248 to 1263 */ + 124, 102, 102, 124, 102, 111, 102, 99, 14, 27, 24, 60, 24, 24, 120, 48, /* 1264 to 1279 */ + 14, 0, 60, 6, 62, 102, 62, 0, 14, 0, 24, 24, 24, 24, 24, 0, /* 1280 to 1295 */ + 14, 0, 60, 102, 102, 102, 60, 0, 14, 0, 102, 102, 102, 102, 62, 0, /* 1296 to 1311 */ + 118, 220, 0, 124, 102, 102, 102, 0, 126, 0, 102, 118, 126, 110, 102, 0, /* 1312 to 1327 */ + 62, 102, 102, 62, 0, 126, 0, 0, 60, 102, 102, 60, 0, 126, 0, 0, /* 1328 to 1343 */ + 24, 0, 24, 48, 96, 102, 60, 0, 0, 0, 0, 126, 96, 96, 0, 0, /* 1344 to 1359 */ + 0, 0, 0, 126, 6, 6, 0, 0, 198, 204, 216, 62, 99, 198, 12, 31, /* 1360 to 1375 */ + 198, 204, 216, 54, 110, 214, 31, 6, 24, 0, 24, 24, 24, 24, 24, 0, /* 1376 to 1391 */ + 0, 54, 108, 216, 108, 54, 0, 0, 0, 216, 108, 54, 108, 216, 0, 0, /* 1392 to 1407 */ + 34, 136, 34, 136, 34, 136, 34, 136, 85, 170, 85, 170, 85, 170, 85, 170, /* 1408 to 1423 */ + 221, 119, 221, 119, 221, 119, 221, 119, 8, 8, 8, 8, 8, 8, 8, 8, /* 1424 to 1439 */ + 8, 8, 8, 8, 248, 8, 8, 8, 8, 8, 8, 248, 248, 8, 8, 8, /* 1440 to 1455 */ + 28, 28, 28, 28, 252, 28, 28, 28, 0, 0, 0, 0, 252, 28, 28, 28, /* 1456 to 1471 */ + 0, 0, 0, 248, 248, 8, 8, 8, 28, 28, 28, 252, 252, 28, 28, 28, /* 1472 to 1487 */ + 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, 0, 252, 252, 28, 28, 28, /* 1488 to 1503 */ + 28, 28, 28, 252, 252, 0, 0, 0, 28, 28, 28, 28, 252, 0, 0, 0, /* 1504 to 1519 */ + 8, 8, 8, 248, 248, 0, 0, 0, 0, 0, 0, 0, 248, 8, 8, 8, /* 1520 to 1535 */ + 8, 8, 8, 8, 15, 0, 0, 0, 8, 8, 8, 8, 255, 0, 0, 0, /* 1536 to 1551 */ + 0, 0, 0, 0, 255, 8, 8, 8, 8, 8, 8, 8, 15, 8, 8, 8, /* 1552 to 1567 */ + 0, 0, 0, 0, 255, 0, 0, 0, 8, 8, 8, 8, 255, 8, 8, 8, /* 1568 to 1583 */ + 8, 8, 8, 15, 15, 8, 8, 8, 28, 28, 28, 28, 31, 28, 28, 28, /* 1584 to 1599 */ + 28, 28, 28, 31, 31, 0, 0, 0, 0, 0, 0, 31, 31, 28, 28, 28, /* 1600 to 1615 */ + 28, 28, 28, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 28, 28, 28, /* 1616 to 1631 */ + 28, 28, 28, 31, 31, 28, 28, 28, 0, 0, 0, 255, 255, 0, 0, 0, /* 1632 to 1647 */ + 28, 28, 28, 255, 255, 28, 28, 28, 8, 8, 8, 255, 255, 0, 0, 0, /* 1648 to 1663 */ + 28, 28, 28, 28, 255, 0, 0, 0, 0, 0, 0, 255, 255, 8, 8, 8, /* 1664 to 1679 */ + 0, 0, 0, 0, 255, 28, 28, 28, 28, 28, 28, 28, 31, 0, 0, 0, /* 1680 to 1695 */ + 8, 8, 8, 15, 15, 0, 0, 0, 0, 0, 0, 15, 15, 8, 8, 8, /* 1696 to 1711 */ + 0, 0, 0, 0, 31, 28, 28, 28, 28, 28, 28, 28, 255, 28, 28, 28, /* 1712 to 1727 */ + 8, 8, 8, 255, 255, 8, 8, 8, 8, 8, 8, 8, 248, 0, 0, 0, /* 1728 to 1743 */ + 0, 0, 0, 0, 15, 8, 8, 8, 255, 255, 255, 255, 255, 255, 255, 255, /* 1744 to 1759 */ + 0, 0, 0, 0, 255, 255, 255, 255, 240, 240, 240, 240, 240, 240, 240, 240, /* 1760 to 1775 */ + 15, 15, 15, 15, 15, 15, 15, 15, 255, 255, 255, 255, 0, 0, 0, 0, /* 1776 to 1791 */ + 0, 0, 118, 204, 204, 204, 118, 0, 60, 102, 102, 124, 102, 102, 124, 96, /* 1792 to 1807 */ + 126, 102, 96, 96, 96, 96, 96, 0, 0, 0, 254, 108, 108, 108, 102, 0, /* 1808 to 1823 */ + 126, 102, 48, 24, 48, 102, 126, 0, 0, 0, 62, 108, 108, 108, 56, 0, /* 1824 to 1839 */ + 0, 0, 102, 102, 102, 102, 127, 192, 0, 0, 126, 216, 24, 24, 12, 0, /* 1840 to 1855 */ + 124, 56, 124, 214, 214, 124, 56, 124, 124, 198, 198, 254, 198, 198, 124, 0, /* 1856 to 1871 */ + 124, 198, 198, 198, 108, 108, 238, 0, 30, 48, 24, 60, 102, 102, 60, 0, /* 1872 to 1887 */ + 0, 0, 126, 219, 219, 126, 0, 0, 3, 6, 62, 107, 115, 62, 96, 192, /* 1888 to 1903 */ + 30, 48, 96, 126, 96, 48, 30, 0, 124, 198, 198, 198, 198, 198, 198, 0, /* 1904 to 1919 */ + 0, 126, 0, 126, 0, 126, 0, 0, 24, 24, 126, 24, 24, 0, 126, 0, /* 1920 to 1935 */ + 48, 24, 12, 24, 48, 0, 126, 0, 12, 24, 48, 24, 12, 0, 126, 0, /* 1936 to 1951 */ + 14, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 216, 216, 112, /* 1952 to 1967 */ + 24, 24, 0, 126, 0, 24, 24, 0, 0, 118, 220, 0, 118, 220, 0, 0, /* 1968 to 1983 */ + 60, 102, 102, 60, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, /* 1984 to 1999 */ + 0, 0, 0, 0, 24, 0, 0, 0, 30, 24, 24, 24, 24, 216, 120, 56, /* 2000 to 2015 */ + 120, 108, 108, 108, 108, 0, 0, 0, 56, 12, 24, 48, 60, 0, 0, 0, /* 2016 to 2031 */ + 0, 0, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 2032 to 2047 */ +}; + +unsigned char *gl_font8x8 = __font8x8; diff --git a/gl/grlib.c b/gl/grlib.c new file mode 100644 index 0000000..5c66fd8 --- /dev/null +++ b/gl/grlib.c @@ -0,0 +1,994 @@ +/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ +/* grlib.c Main module */ + + +#include +#include +#include +#include "inlstring.h" /* include inline string operations */ + +#include "vgagl.h" +#include "def.h" +#include "driver.h" + + +/* Global variables */ + +#ifdef DLL_CONTEXT_SHADOW + +/* The current context variable is shadowed in a read-only variable for */ +/* external use. */ + +GraphicsContext __currentcontext; /* Internal current context. */ +GraphicsContext currentcontext; /* Copy for external use. */ + +#else + +GraphicsContext currentcontext; + +#endif + +void (*__svgalib_nonaccel_fillbox)(int, int, int, int, int); +static int screenoffset = 0; /* Used by copy(box)toscreen. */ + + +/* Framebuffer function pointers */ + +static framebufferfunctions ff8 = +{ + __svgalib_driver8_setpixel, + __svgalib_driver8_getpixel, + __svgalib_driver8_hline, + __svgalib_driver8_fillbox, + __svgalib_driver8_putbox, + __svgalib_driver8_getbox, + __svgalib_driver8_putboxmask, + __svgalib_driver8_putboxpart, + __svgalib_driver8_getboxpart, + __svgalib_driver8_copybox +}; + +static framebufferfunctions ff16 = +{ + __svgalib_driver16_setpixel, + __svgalib_driver16_getpixel, + __svgalib_driver16_hline, + __svgalib_driver16_fillbox, + __svgalib_driver16_putbox, + __svgalib_driver16_getbox, + __svgalib_driver16_putboxmask, + __svgalib_driver16_putboxpart, + __svgalib_driver16_getboxpart, + __svgalib_driver16_copybox +}; + +static framebufferfunctions ff24 = +{ + __svgalib_driver24_setpixel, + __svgalib_driver24_getpixel, + __svgalib_driver24_hline, + __svgalib_driver24_fillbox, + __svgalib_driver24_putbox, + __svgalib_driver24_getbox, + __svgalib_driver24_putboxmask, + __svgalib_driver24_putboxpart, + __svgalib_driver24_getboxpart, + __svgalib_driver24_copybox +}; + +static framebufferfunctions ff32 = +{ + __svgalib_driver32_setpixel, + __svgalib_driver32_getpixel, + __svgalib_driver32_hline, + __svgalib_driver32_fillbox, + __svgalib_driver32_putbox, + __svgalib_driver32_getbox, + __svgalib_driver32_putboxmask, + __svgalib_driver32_putboxpart, + __svgalib_driver32_getboxpart, + __svgalib_driver32_copybox +}; + +static framebufferfunctions ff8paged = +{ + __svgalib_driver8p_setpixel, + __svgalib_driver8p_getpixel, + __svgalib_driver8p_hline, + __svgalib_driver8p_fillbox, + __svgalib_driver8p_putbox, + __svgalib_driver8p_getbox, + __svgalib_driver8p_putboxmask, + __svgalib_driver8p_putboxpart, + __svgalib_driver8p_getboxpart, + __svgalib_driver8p_copybox +}; + +static framebufferfunctions ff16paged = +{ + __svgalib_driver16p_setpixel, + __svgalib_driver16p_getpixel, + __svgalib_driver16p_hline, + __svgalib_driver16p_fillbox, + __svgalib_driver16p_putbox, + __svgalib_driver16p_getbox, + __svgalib_driver16p_putboxmask, + __svgalib_driver16p_putboxpart, + __svgalib_driver16p_getboxpart, + __svgalib_driver16p_copybox +}; + +static framebufferfunctions ff24paged = +{ + __svgalib_driver24p_setpixel, + __svgalib_driver24p_getpixel, + __svgalib_driver24p_hline, + __svgalib_driver24p_fillbox, + __svgalib_driver24p_putbox, + __svgalib_driver24p_getbox, + __svgalib_driver24p_putboxmask, + __svgalib_driver24p_putboxpart, + __svgalib_driver24p_getboxpart, + __svgalib_driver24p_copybox +}; + +static framebufferfunctions ff32paged = +{ + __svgalib_driver32p_setpixel, + __svgalib_driver32p_getpixel, + __svgalib_driver32p_hline, + __svgalib_driver32p_fillbox, + __svgalib_driver32p_putbox, + __svgalib_driver32p_getbox, + __svgalib_driver32p_putboxmask, + __svgalib_driver32p_putboxpart, + __svgalib_driver32p_getboxpart, + __svgalib_driver32p_copybox +}; + +static framebufferfunctions ffplanar256 = +{ + (void *) __svgalib_driverplanar256_nothing, + (void *) __svgalib_driverplanar256_nothing, + (void *) __svgalib_driverplanar256_nothing, + (void *) __svgalib_driverplanar256_nothing, + __svgalib_driverplanar256_putbox, + (void *) __svgalib_driverplanar256_nothing, + (void *) __svgalib_driverplanar256_nothing, + (void *) __svgalib_driverplanar256_nothing, + (void *) __svgalib_driverplanar256_nothing, + (void *) __svgalib_driverplanar256_nothing, +}; + +#if 0 /* Not yet used */ +static framebufferfunctions ffplanar16 = +{ + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, + (void *) __svgalib_driverplanar16_nothing, +}; +#endif + + +/* Initialization and graphics contexts */ + +#define SCREENSIZE(gc) ((gc).bytewidth * (gc).height) + +static int colorbits(int c) +{ + switch (c) { + default: + case 256: + return 8; + case 32768: + return 15; + case 65536: + return 16; + case 256 * 65536: + return 24; + } +} + +int gl_setcontextvga(int m) +{ + framebufferfunctions *ff; + vga_modeinfo *modeinfo; + int accelfuncs; + if (!vga_hasmode(m)) + return -1; + modeinfo = vga_getmodeinfo(m); + /* Set graphics context */ + WIDTH = modeinfo->width; + HEIGHT = modeinfo->height; + BYTESPERPIXEL = modeinfo->bytesperpixel; + COLORS = modeinfo->colors; + BITSPERPIXEL = colorbits(COLORS); + BYTEWIDTH = modeinfo->linewidth; + VBUF = vga_getgraphmem(); + MODEFLAGS = 0; + __clip = 0; + ff = &(__currentcontext.ff); + if (modeinfo->flags & IS_MODEX) { + /* Pretend it's a regular (linear) context. */ + BYTESPERPIXEL = 1; + BYTEWIDTH *= 4; + MODETYPE = CONTEXT_MODEX; + if (BYTEWIDTH * HEIGHT * 2 <= 256 * 1024) + MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; + if (BYTEWIDTH * HEIGHT * 3 <= 256 * 1024) + MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; + __currentcontext.ff = ffplanar256; + } else if (modeinfo->colors == 16) { + /* Pretend it's a regular one byte per pixel context. */ + BYTESPERPIXEL = 1; + BYTEWIDTH *= 8; + MODETYPE = CONTEXT_PLANAR16; + if (BYTEWIDTH * HEIGHT <= 256 * 1024) + MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; + if (BYTEWIDTH * HEIGHT * 3 / 2 <= 256 * 1024) + MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; + } else if ((m == G320x200x256 && modeinfo->maxpixels <= 65536) || + (modeinfo->flags & IS_LINEAR) +#if 1 /* svgalib doesn't VT-switch correctly with linear addressing. */ + || ((modeinfo->flags & CAPABLE_LINEAR) + /* Creepy. Try linear addressing only if the mode is set. */ + && vga_getcurrentmode() == m && (vga_setlinearaddressing() != -1)) +#endif + ) { + /* No banking. */ + /* Get get the fb address in case we set linear addressing. */ + VBUF = vga_getgraphmem(); + MODETYPE = CONTEXT_LINEAR; + if (modeinfo->maxpixels >= WIDTH * HEIGHT * 2) + MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; + if (modeinfo->maxpixels >= WIDTH * HEIGHT * 3) + MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; + switch (BYTESPERPIXEL) { + case 1: + __currentcontext.ff = ff8; + break; + case 2: + __currentcontext.ff = ff16; + break; + case 3: + __currentcontext.ff = ff24; + break; + case 4: + __currentcontext.ff = ff32; + break; + } + if (modeinfo->flags & RGB_MISORDERED) + MODEFLAGS |= MODEFLAG_32BPP_SHIFT8; + } else { + /* Banked mode. */ + MODETYPE = CONTEXT_PAGED; + if (modeinfo->maxpixels >= WIDTH * HEIGHT * 2) + MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; + if (modeinfo->maxpixels >= WIDTH * HEIGHT * 3) + MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; + if ((modeinfo->startaddressrange & 0x1ffff) == 0x10000) { + /* This hack is required for 320x200x256 page flipping */ + /* on Trident, which doesn't work with bank boundary */ + /* within the second page. */ + MODEFLAGS |= MODEFLAG_FLIPPAGE_BANKALIGNED; + } + switch (BYTESPERPIXEL) { + case 1: + __currentcontext.ff = ff8paged; + break; + case 2: + __currentcontext.ff = ff16paged; + break; + case 3: + __currentcontext.ff = ff24paged; + break; + case 4: + __currentcontext.ff = ff32paged; + break; + } + if (modeinfo->flags & RGB_MISORDERED) + MODEFLAGS |= MODEFLAG_32BPP_SHIFT8; + } + if (vga_getcurrentmode() == m) { + accelfuncs = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL); + __svgalib_nonaccel_fillbox = __currentcontext.ff.driver_fillbox_func; + if (accelfuncs & ACCELFLAG_FILLBOX) + __currentcontext.ff.driver_fillbox_func = + __svgalib_driver8a_fillbox; + if (accelfuncs & ACCELFLAG_SCREENCOPY) + __currentcontext.ff.driver_copybox_func = + __svgalib_driver8a_copybox; + } +#ifdef DLL_CONTEXT_SHADOW + currentcontext = __currentcontext; +#endif + return 0; +} + +int gl_setcontextvgavirtual(int m) +{ + vga_modeinfo *modeinfo; + if (!vga_hasmode(m)) + return -1; + modeinfo = vga_getmodeinfo(m); + /* Set graphics context */ + WIDTH = modeinfo->width; + HEIGHT = modeinfo->height; + if (modeinfo->flags & IS_MODEX) { + /* Use a regular virtual screen for planar 256 color modes. */ + BYTESPERPIXEL = 1; + BYTEWIDTH = modeinfo->linewidth * 4; + } else if (modeinfo->colors == 16) { + /* Use a regular one byte per pixel virtual screen for */ + /* planar 16 color modes. */ + BYTESPERPIXEL = 1; + BYTEWIDTH = modeinfo->linewidth * 8; + } else { + BYTESPERPIXEL = modeinfo->bytesperpixel; + BYTEWIDTH = modeinfo->linewidth; + } + COLORS = modeinfo->colors; + BITSPERPIXEL = colorbits(COLORS); + VBUF = malloc(SCREENSIZE(__currentcontext)); + MODETYPE = CONTEXT_VIRTUAL; + MODEFLAGS = 0; + __clip = 0; + switch (BYTESPERPIXEL) { + case 1: + __currentcontext.ff = ff8; + break; + case 2: + __currentcontext.ff = ff16; + break; + case 3: + __currentcontext.ff = ff24; + break; + case 4: + __currentcontext.ff = ff32; + break; + } +#ifdef DLL_CONTEXT_SHADOW + currentcontext = __currentcontext; +#endif + return 0; +} + +void gl_setcontextvirtual(int w, int h, int bpp, int bitspp, void *v) +{ + WIDTH = w; + HEIGHT = h; + BYTESPERPIXEL = bpp; + BITSPERPIXEL = bitspp; + COLORS = 1 << bitspp; + BYTEWIDTH = WIDTH * BYTESPERPIXEL; + VBUF = v; + MODETYPE = CONTEXT_VIRTUAL; + MODEFLAGS = 0; + switch (BYTESPERPIXEL) { + case 1: + __currentcontext.ff = ff8; + break; + case 2: + __currentcontext.ff = ff16; + break; + case 3: + __currentcontext.ff = ff24; + break; + case 4: + __currentcontext.ff = ff32; + break; + } + __clip = 0; +#ifdef DLL_CONTEXT_SHADOW + currentcontext = __currentcontext; +#endif +} + +GraphicsContext * + gl_allocatecontext() +{ + return malloc(sizeof(GraphicsContext)); +} + +void gl_setcontext(GraphicsContext * gc) +{ + __currentcontext = *gc; +#ifdef DLL_CONTEXT_SHADOW + currentcontext = *gc; +#endif +} + +void gl_getcontext(GraphicsContext * gc) +{ + *gc = __currentcontext; +} + +void gl_freecontext(GraphicsContext * gc) +{ + if (gc->modetype == CONTEXT_VIRTUAL) + free(gc->vbuf); +} + +void gl_setcontextwidth(int w) +{ + __currentcontext.width = currentcontext.width = w; + __currentcontext.bytewidth = currentcontext.bytewidth = + w * BYTESPERPIXEL; +} + +void gl_setcontextheight(int h) +{ + __currentcontext.height = currentcontext.height = h; +} + + +/* Clipping */ + +void gl_setclippingwindow(int x1, int y1, int x2, int y2) +{ + __clip = 1; + __clipx1 = x1; + __clipy1 = y1; + __clipx2 = x2; + __clipy2 = y2; +} + +void gl_enableclipping() +{ + __clip = 1; + __clipx1 = 0; + __clipy1 = 0; + __clipx2 = WIDTH - 1; + __clipy2 = HEIGHT - 1; +} + +void gl_disableclipping() +{ + __clip = 0; +} + + +/* Primitive functions */ + +void gl_setpixel(int x, int y, int c) +{ + if (__clip && outside(x, y)) + return; + setpixel(x, y, c); +} + +int gl_getpixel(int x, int y) +{ + if (__clip && outside(x, y)) + return -1; + return getpixel(x, y); +} + +void gl_hline(int x1, int y, int x2, int c) +{ + if (__clip) { + if (y_outside(y)) + return; + clipxleft(x1); + clipxright(x2); + } + if (x1 > x2) + return; + hline(x1, y, x2, c); +} + +#define ADJUSTBITMAPBOX() \ + nw = w; nh = h; nx = x; ny = y; \ + if (nx + nw < __clipx1 || nx > __clipx2) \ + return; \ + if (ny + nh < __clipy1 || ny > __clipy2) \ + return; \ + if (nx < __clipx1) { /* left adjust */ \ + nw += nx - __clipx1; \ + nx = __clipx1; \ + } \ + if (ny < __clipy1) { /* top adjust */ \ + nh += ny - __clipy1; \ + ny = __clipy1; \ + } \ + if (nx + nw > __clipx2) /* right adjust */ \ + nw = __clipx2 - nx + 1; \ + if (ny + nh > __clipy2) /* bottom adjust */ \ + nh = __clipy2 - ny + 1; \ + +void gl_fillbox(int x, int y, int w, int h, int c) +{ + if (__clip) { + if (x + w < __clipx1 || x > __clipx2) + return; + if (y + h < __clipy1 || y > __clipy2) + return; + if (x < __clipx1) { + w -= __clipx1 - x; + x = __clipx1; + } + if (y < __clipy1) { + h -= __clipy1 - y; + y = __clipy1; + } + if (x + w > __clipx2 + 1) + w = __clipx2 - x + 1; + if (y + h > __clipy2 + 1) + h = __clipy2 - y + 1; + } + if (w <= 0 || h <= 0) + return; + fillbox(x, y, w, h, c); +} + +void gl_putboxpart(int x, int y, int w, int h, int ow, int oh, void *b, + int ox, int oy) +{ + putboxpart(x, y, w, h, ow, oh, b, ox, oy); +} + +void gl_putbox(int x, int y, int w, int h, void *b) +{ + uchar *bp = b; + if (w <= 0 || h <= 0) + return; + if (__clip) { + int nx, ny, nw, nh; + ADJUSTBITMAPBOX(); + if (nw <= 0 || nh <= 0) + return; + if (nw != w || nh != h) { + putboxpart(nx, ny, nw, nh, w, h, bp, nx - x, ny - y); + return; + } + } + putbox(x, y, w, h, bp, w); +} + +static void emulate_putboxmask(int x, int y, int w, int h, void *b) +{ + void *box; + GraphicsContext gc; + box = alloca(w * h * BYTESPERPIXEL); + gl_getbox(x, y, w, h, box); /* does clipping */ + + gl_getcontext(&gc); /* save context */ + + /* create context that is only the box */ + gl_setcontextvirtual(w, h, BYTESPERPIXEL, BITSPERPIXEL, box); + gl_putboxmask(0, 0, w, h, b); + + gl_setcontext(&gc); /* restore context */ + gl_putbox(x, y, w, h, box); +} + +void gl_putboxmask(int x, int y, int w, int h, void *b) +{ + if (w <= 0 || h <= 0) + return; + if (__clip) { + if (x + w < __clipx1 || x > __clipx2) + return; + if (y + h < __clipy1 || y > __clipy2) + return; + if (x < __clipx1 || y < __clipy1 + || x + w > __clipx2 + 1 || y + h > __clipy2 + 1) { + /* clipping is not directly implemented */ + emulate_putboxmask(x, y, w, h, b); + return; + } + } + if (MODETYPE == CONTEXT_PAGED) + /* paged primitive is not implemented */ + emulate_putboxmask(x, y, w, h, b); + else + putboxmask(x, y, w, h, b); +} + +void gl_getbox(int x, int y, int w, int h, void *b) +{ + if (__clip) { + int nx, ny, nw, nh; + ADJUSTBITMAPBOX(); + if (nw <= 0 || nh <= 0) + return; + if (nw != w || nh != h) { + getboxpart(nx, ny, nw, nh, w, h, b, nx - x, ny - y); + return; + } + } + getbox(x, y, w, h, b, w); +} + +void gl_copybox(int x1, int y1, int w, int h, int x2, int y2) +{ +/* Doesn't handle clipping. */ + if (MODETYPE == CONTEXT_PAGED) { + /* Paged primitive is not implemented. */ + void *box; + box = alloca(w * h * BYTESPERPIXEL); + getbox(x1, y1, w, h, box, w); + putbox(x2, y2, w, h, box, w); + return; + } + copybox(x1, y1, w, h, x2, y2); +} + + +/* Miscellaneous functions */ + +void gl_clearscreen(int c) +{ + gl_fillbox(0, 0, WIDTH, HEIGHT, c); +} + +int gl_rgbcolor(int r, int g, int b) +{ + unsigned v; + switch (BITSPERPIXEL) { + case 8: + /* assumes RGB palette at index 0-255 */ + /* bits 0-2 = blue (3 bits) */ + /* 3-5 = green (3 bits) */ + /* 6-7 = red (2 bits) */ + return (r & 0xc0) + ((g & 0xe0) >> 2) + (b >> 5); + case 24: + case 32: + v = (r << 16) + (g << 8) + b; + if (MODEFLAGS & MODEFLAG_32BPP_SHIFT8) + return v << 8; + return v; + case 15: + return ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + (b >> 3); + case 16: + return ((r & 0xf8) << 8) + ((g & 0xfc) << 3) + (b >> 3); + case 4: + /* Now this is real fun. Map to standard EGA palette. */ + v = 0; + if (b >= 64) + v += 1; + if (g >= 64) + v += 2; + if (r >= 64) + v += 4; + if (b >= 192 || g >= 192 || r >= 192) + v += 8; + return v; + } + return -1; +} + +void gl_setpixelrgb(int x, int y, int r, int g, int b) +{ +/* Color components range from 0 to 255 */ + if (__clip && outside(x, y)) + return; + setpixel(x, y, gl_rgbcolor(r, g, b)); +} + +void gl_getpixelrgb(int x, int y, int *r, int *g, int *b) +{ + unsigned c; + if (__clip && outside(x, y)) { + *r = *g = *b = -1; + return; + } + c = getpixel(x, y); + switch (BITSPERPIXEL) { + case 8: + *b = (c & (1 + 2 + 4)) << 5; /* bits 0-2 */ + *g = (c & (8 + 16 + 32)) << 2; /* bits 3-5 */ + *r = (c & (64 + 128)); /* bits 6-7 */ + break; + case 32: + if (MODEFLAGS & MODEFLAG_32BPP_SHIFT8) { + *b = (c & 0xff00) >> 8; + *g = (c & 0xff0000) >> 16; + *r = c >> 24; + break; + } + case 24: + *b = c & 0xff; + *g = (c & 0xff00) >> 8; + *r = c >> 16; + break; + case 15: + *b = (c & (1 + 2 + 4 + 8 + 16)) << 3; + *g = (c & (32 + 64 + 128 + 256 + 512)) >> 2; + *r = (c & (1024 + 2048 + 4096 + 8192 + 16384)) >> 7; + break; + case 16: + *b = (c & (1 + 2 + 4 + 8 + 16)) << 3; + *g = (c & (32 + 64 + 128 + 256 + 512 + 1024)) >> 3; + *r = (c & (2048 + 4096 + 8192 + 16384 + 32768)) >> 8; + break; + case 4: + *b = (c & 1) * ((c & 8) ? 255 : 128); + *g = (c & 2) * ((c & 8) ? 255 : 128); + *r = (c & 4) * ((c & 8) ? 255 : 128); + break; + } +} + +void gl_setdisplaystart(int x, int y) +{ + vga_setdisplaystart(y * BYTEWIDTH + x * BYTESPERPIXEL); +} + + +/* Screen copying */ + +void gl_setscreenoffset(int o) +{ + screenoffset = o; +} + +int gl_enablepageflipping(GraphicsContext * gc) +{ + if (gc->modeflags & MODEFLAG_PAGEFLIPPING_CAPABLE) { + gc->modeflags |= MODEFLAG_PAGEFLIPPING_ENABLED; + } + if (gc->modeflags & MODEFLAG_TRIPLEBUFFERING_CAPABLE) { + gc->modeflags &= ~(MODEFLAG_PAGEFLIPPING_ENABLED); + gc->modeflags |= MODEFLAG_TRIPLEBUFFERING_ENABLED; + } + gc->flippage = 0; + if (gc->modeflags & MODEFLAG_TRIPLEBUFFERING_ENABLED) + return 3; + if (gc->modeflags & MODEFLAG_PAGEFLIPPING_ENABLED) + return 2; + return 0; +} + +void gl_copyscreen(GraphicsContext * gc) +{ + int size; + void *svp, *dvp; + + if (gc->modeflags & MODEFLAG_PAGEFLIPPING_ENABLED) + gc->flippage ^= 1; + if (gc->modeflags & MODEFLAG_TRIPLEBUFFERING_ENABLED) + gc->flippage = (gc->flippage + 1) % 3; + if (gc->modeflags & (MODEFLAG_PAGEFLIPPING_ENABLED | + MODEFLAG_TRIPLEBUFFERING_ENABLED)) { + /* Calculate screen offset in bytes. */ + screenoffset = gc->bytewidth * HEIGHT * gc->flippage; + if (gc->modeflags & MODEFLAG_FLIPPAGE_BANKALIGNED) + screenoffset = ((screenoffset + 0xffff) & ~0xffff); + } + if (gc->modetype == CONTEXT_MODEX) { + vga_copytoplanar256(VBUF, BYTEWIDTH, screenoffset / 4, + gc->bytewidth / 4, WIDTH, HEIGHT); + goto end; + } + if (gc->modetype == CONTEXT_PLANAR16) { + if (WIDTH == 1024 && HEIGHT >= 512 && + ((screenoffset / 8) & 0xffff) == 0) { + /* Kludge to allow 1024x768x16 with page flipping. */ + int page; + page = (screenoffset / 8) >> 16; + vga_setpage(page); + vga_copytoplanar16(VBUF, BYTEWIDTH, 0, + gc->bytewidth / 8, WIDTH, 512); + vga_setpage(page + 1); + vga_copytoplanar16(VBUF + WIDTH * 512, BYTEWIDTH, + 0, gc->bytewidth / 8, WIDTH, HEIGHT - 512); + return; + } + if (WIDTH * HEIGHT >= 512 * 1024) + /* We don't handle banking. */ + return; + + vga_copytoplanar16(VBUF, BYTEWIDTH, screenoffset / 8, + gc->bytewidth / 8, WIDTH, HEIGHT); + goto end; + } + if (BYTESPERPIXEL == 4 && gc->bytesperpixel == 3) { + /* Special case. */ + int soffset, doffset; + if (BYTEWIDTH / 4 != gc->bytewidth / 3) { + /* Even more special case for physical truecolor */ + /* modes that have extra scanline padding. */ + /* This has the effect of slowing down */ + /* '3d' in some truecolor modes on ATI mach32. */ + gl_copyboxtocontext(0, 0, WIDTH, HEIGHT, gc, 0, 0); + goto end; + } + soffset = 0; + doffset = screenoffset; + size = WIDTH * HEIGHT; + while (soffset / 4 < size) { + int schunk, dchunk; + int count; + schunk = __svgalib_driver_setread(&__currentcontext, soffset, &svp); + dchunk = __svgalib_driver_setwrite(gc, doffset, &dvp); + if (dchunk == 1) { + /* One byte left in segment. */ + int pix; + pix = *(unsigned *) svp; /* 32-bit pixel */ + *(unsigned char *) dvp = pix; + dchunk = __svgalib_driver_setwrite(gc, doffset + 1, &dvp); + *(unsigned short *) dvp = pix >> 8; + count = 1; /* 1 pixel handled. */ + } else if (dchunk == 2) { + /* Two bytes left. */ + int pix; + pix = *(unsigned *) svp; /* 32-bit pixel */ + *(unsigned short *) dvp = pix; + dchunk = __svgalib_driver_setwrite(gc, doffset + 2, &dvp); + *(unsigned char *) dvp = pix >> 16; + count = 1; /* 1 pixel handled. */ + } else { + count = min(min(schunk / 4, dchunk / 3), + size - (soffset / 4)); + __svgalib_memcpy4to3(dvp, svp, count); + } + soffset += count * 4; + doffset += count * 3; + } + goto end; + } + if (BYTESPERPIXEL == 4 && gc->bytesperpixel == 4 && + (gc->modeflags & MODEFLAG_32BPP_SHIFT8)) { + int soffset = 0; + int doffset = screenoffset; + size = SCREENSIZE(__currentcontext); + while (soffset < size) { + int schunk, dchunk; + int count; + schunk = __svgalib_driver_setread(&__currentcontext, soffset, &svp); + dchunk = __svgalib_driver_setwrite(gc, doffset, &dvp); + count = min(min(schunk, dchunk), (size - soffset)); + __svgalib_memcpy32shift8(dvp, svp, count / 4); + soffset += count; + doffset += count; + } + } else { + int soffset = 0; + int doffset = screenoffset; + size = SCREENSIZE(__currentcontext); + while (soffset < size) { + int schunk, dchunk; + int count; + schunk = __svgalib_driver_setread(&__currentcontext, soffset, &svp); + dchunk = __svgalib_driver_setwrite(gc, doffset, &dvp); + count = min(min(schunk, dchunk), (size - soffset)); + __memcpy(dvp, svp, count); + soffset += count; + doffset += count; + } + } + + end: + if (gc->modeflags & (MODEFLAG_PAGEFLIPPING_ENABLED | + MODEFLAG_TRIPLEBUFFERING_ENABLED)) { + GraphicsContext save; + /* setdisplaystart will use BYTEWIDTH of the virtual screen, */ + /* which is what we want since vga_setdisplaystart is */ + /* defined in terms of pixel offset (except for hicolor */ + /* modes, which are defined in terms of bytes). */ + gl_getcontext(&save); + gl_setcontext(gc); + if (gc->modeflags & MODEFLAG_FLIPPAGE_BANKALIGNED) + vga_setdisplaystart(screenoffset); + else + gl_setdisplaystart(0, gc->height * gc->flippage); + gl_setcontext(&save); + /* For page flipping, it might be appropriate to add a */ + /* waitverticalretrace here. */ + } + screenoffset = 0; +} + +void gl_copyboxtocontext(int x1, int y1, int w, int h, GraphicsContext * gc, + int x2, int y2) +{ +/* This is now reasonably efficient if clipping is not enabled. */ + void *buf; + GraphicsContext save; + gl_getcontext(&save); + if ((MODETYPE == CONTEXT_LINEAR || MODETYPE == CONTEXT_VIRTUAL) && + (BYTESPERPIXEL == gc->bytesperpixel) && + !__clip && !gc->clip) { +#ifdef DLL_CONTEXT_SHADOW + __currentcontext = *gc; +#else + gl_setcontext(gc); +#endif +/* + * Note: Using save.bytewidth / BYTESPERPIXEL is probably not an optimal hack here. + * it would be better to transfer save.bytewidth to putbox as it is what is really + * used there. However, putbox is used all over interpreting the last entry as a + * pixel count, so we keep it this way to avoid problems if some other place not + * updated by accident. + */ + putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, save.vbuf + + y1 * save.bytewidth + x1 * BYTESPERPIXEL, + save.bytewidth / BYTESPERPIXEL); + goto end; + } + buf = alloca(w * h * BYTESPERPIXEL); + gl_getbox(x1, y1, w, h, buf); +#ifdef DLL_CONTEXT_SHADOW + __currentcontext = *gc; +#else + gl_setcontext(gc); +#endif + + if (save.bytesperpixel == 4 && gc->bytesperpixel == 3) { + /* Special case conversion from 32-bit virtual screen to */ + /* 24-bit truecolor framebuffer. */ + if (gc->modetype == CONTEXT_PAGED || gc->clip) { + /* For paged modes or clipping, use another buffer. */ + void *buf2; + buf2 = alloca(w * h * 3); + __svgalib_memcpy4to3(buf2, buf, w * h); + gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, + buf2); + } else + /* No clipping, linear. */ + __svgalib_driver24_putbox32(x2, y2, w, h, buf, w); + } else /* Contexts assumed to have same pixel size. */ + gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, buf); + + end: +#ifdef DLL_CONTEXT_SHADOW + __currentcontext = save; +#else + gl_setcontext(&save); +#endif +} + +void gl_copyboxfromcontext(GraphicsContext * gc, int x1, int y1, int w, int h, + int x2, int y2) +{ + void *buf; + GraphicsContext save; + if ((gc->modetype == CONTEXT_LINEAR || gc->modetype == CONTEXT_VIRTUAL) && + (BYTESPERPIXEL == gc->bytesperpixel) && + !__clip && !gc->clip) { +/* + * see above on gc->bytewidth / BYTESPERPIXEL. + */ + putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, gc->vbuf + + y1 * gc->bytewidth + x1 * BYTESPERPIXEL, + gc->bytewidth / BYTESPERPIXEL); + return; + } + gl_getcontext(&save); +#ifdef DLL_CONTEXT_SHADOW + __currentcontext = *gc; +#else + gl_setcontext(gc); +#endif + buf = alloca(w * h * BYTESPERPIXEL); + gl_getbox(x1, y1, w, h, buf); +#ifdef DLL_CONTEXT_SHADOW + __currentcontext = save; +#else + gl_setcontext(&save); +#endif + + if (gc->bytesperpixel == 4 && save.bytesperpixel == 3) { + /* Special case conversion from 32-bit virtual screen to */ + /* 24-bit truecolor framebuffer. */ + if (save.modetype == CONTEXT_PAGED || save.clip) { + /* For paged modes or clipping, use another buffer. */ + void *buf2; + buf2 = alloca(w * h * 3); + __svgalib_memcpy4to3(buf2, buf, w * h); + gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, + buf2); + } else + /* No clipping, linear. */ + __svgalib_driver24_putbox32(x2, y2, w, h, buf, w); + } else /* Contexts assumed to have same pixel size. */ + gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, buf); +} diff --git a/gl/inlstring.h b/gl/inlstring.h new file mode 100644 index 0000000..5c76606 --- /dev/null +++ b/gl/inlstring.h @@ -0,0 +1,344 @@ +/* Based on functions in linux/string.h */ + +#include /* for size_t */ +#include "../src/ppcmemset.h" + +#if defined (NO_ASSEMBLY) + +#define __memcpy(dst,src,n) memcpy((dst),(src),(n)) +#define __memcpy_conventional(dst,src,n) memcpy((dst),(src),(n)) +#define __memcpyb(dst,src,n) memcpy((dst),(src),(n)) +#define __memsetb(dst,c,n) memset((dst),(c),(n)) +#define __memset(dst,c,n) memset((dst),(c),(n)) + +static inline void *__memset4(void *s, int c, size_t count) { + int i, *p=s; + for(i=0;i>8)&0xff; + *p++=(c>>16)&0xff; + } + return s; +} + +#else + +static inline void * + __memcpy_conventional(void *to, const void *from, size_t n) +{ + int dummy1; + long dummy2, dummy3; + __asm__ __volatile__("cld\n\t" + "cmpl $0,%%edx\n\t" + "jle 2f\n\t" + "movl %%edi,%%ecx\n\t" + "andl $1,%%ecx\n\t" + "subl %%ecx,%%edx\n\t" + "rep ; movsb\n\t" /* 16-bit align destination */ + "movl %%edx,%%ecx\n\t" + "shrl $2,%%ecx\n\t" + "jz 3f\n\t" + "rep ; movsl\n\t" + "3:\n\t" + "testb $1,%%dl\n\t" + "je 1f\n\t" + "movsb\n" + "1:\ttestb $2,%%dl\n\t" + "je 2f\n\t" + "movsw\n" + "2:\n" + : "=d"(dummy1), "=D"(dummy2), "=S"(dummy3) /* fake output */ + : "0"(n), "1"((long) to), "2"((long) from) + : "cx"/***rjr***, "dx", "di", "si"***/ + ); + return (to); +} + + +static inline void * + __memcpyb(void *to, const void *from, size_t n) +{ + int dummy1; + long dummy2, dummy3; + __asm__ __volatile__("cld\n\t" + "rep ; movsb\n\t" + : "=c"(dummy1), "=D"(dummy2), "=S"(dummy3) /* fake output */ + : "0"(n), "1"((long) to), "2"((long) from) + /***rjr***: "cx", "di", "si"***/ + ); + return (to); +} + +static inline void * + __memsetb(void *s, char c, size_t count) +{ + __asm__("cld\n\t" + "rep\n\t" + "stosb" + : : "a"(c), "D"(s), "c"(count) + : "cx", "di"); + return s; +} + +static inline void * + __memset4(void *s, unsigned c, size_t count) +{ + long dummy1; + int dummy2; + __asm__ __volatile__("cld\n\t" + "rep\n\t" + "stosl" + : "=D"(dummy1), "=c"(dummy2) /* fake outputs */ + : "a"(c), "0"(s), "1"(count) + /***rjr***: "cx", "di"***/ + ); + return s; +} + +static inline void * + __memset(void *s, char c, size_t count) +{ + int dummy1; + long dummy2; + int dummy3; + __asm__ __volatile__( + "cld\n\t" + "cmpl $12,%%edx\n\t" + "jl 1f\n\t" /* if (count >= 12) */ + + "movzbl %%al,%%eax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $8,%%ecx\n\t" /* c |= c << 8 */ + "orl %%ecx,%%eax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $16,%%ecx\n\t" /* c |= c << 16 */ + "orl %%ecx,%%eax\n\t" + + "movl %%edx,%%ecx\n\t" + "negl %%ecx\n\t" + "andl $3,%%ecx\n\t" /* (-s % 4) */ + "subl %%ecx,%%edx\n\t" /* count -= (-s % 4) */ + "rep ; stosb\n\t" /* align to longword boundary */ + + "movl %%edx,%%ecx\n\t" + "shrl $2,%%ecx\n\t" + "rep ; stosl\n\t" /* fill longwords */ + + "andl $3,%%edx\n" /* fill last few bytes */ + "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ + "rep ; stosb\n\t" + : "=a"(dummy1), "=D"(dummy2), "=d"(dummy3) /* fake outputs */ + : "0"(c), "1"(s), "2"(count) + : /***rjr***"ax",*/ "cx"/*, "dx", "di"*/ + ); + return s; +} + +static inline void * + __memset2(void *s, short c, size_t count) +/* count is in 16-bit pixels */ +/* s is assumed to be 16-bit aligned */ +{ + int dummy1; + long dummy2; + int dummy3; + __asm__ __volatile__( + "cld\n\t" + "cmpl $12,%%edx\n\t" + "jl 1f\n\t" /* if (count >= 12) */ + + "movzwl %%ax,%%eax\n\t" + "movl %%eax,%%ecx\n\t" + "shll $16,%%ecx\n\t" /* c |= c << 16 */ + "orl %%ecx,%%eax\n\t" + + "movl %%edi,%%ecx\n\t" + "andl $2,%%ecx\n\t" /* s & 2 */ + "jz 2f\n\t" + "decl %%edx\n\t" /* count -= 1 */ + "movw %%ax,(%%edi)\n\t" /* align to longword boundary */ + "addl $2,%%edi\n\t" + + "2:\n\t" + "movl %%edx,%%ecx\n\t" + "shrl $1,%%ecx\n\t" + "rep ; stosl\n\t" /* fill longwords */ + + "andl $1,%%edx\n" /* one 16-bit word left? */ + "jz 3f\n\t" /* no, finished */ + "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ + "rep ; stosw\n\t" + "3:\n\t" + : "=a"(dummy1), "=D"(dummy2), "=d"(dummy3) /* fake outputs */ + : "0"(c), "1"(s), "2"(count) + : /***rjr***"ax",*/ "cx"/*, "dx", "di"*/ + ); + return s; +} + +static inline void * + __memset3(void *s, int c, size_t count) +/* count is in 24-bit pixels (3 bytes per pixel) */ +{ + int dummy1; + long dummy2; + int dummy3; + __asm__ __volatile__( + "cmpl $8,%%edx\n\t" + /* "jmp 2f\n\t" *//* debug */ + "jl 2f\n\t" + + "movl %%eax,%%esi\n\t" /* esi = (low) BGR0 (high) */ + "shll $24,%%eax\n\t" /* eax = 000B */ + "orl %%eax,%%esi\n\t" /* esi = BGRB */ + + "movl %%esi,%%eax\n\t" + "shrl $8,%%eax\n\t" /* eax = GRB0 */ + "movl %%eax,%%ecx\n\t" + "shll $24,%%ecx\n\t" /* ecx = 000G */ + "orl %%ecx,%%eax\n\t" /* eax = GRBG */ + + "movl %%esi,%%ecx\n\t" + "shll $8,%%ecx\n\t" /* ecx = 0BGR */ + "movb %%ah,%%cl\n\t" /* ecx = RBGR */ + + "cmpl $16,%%edx\n\t" + "jl 1f\n\t" + "jmp 5f\n\t" + ".align 4,0x90\n\t" + + "5:\n\t" /* loop unrolling */ + "movl %%esi,(%%edi)\n\t" /* write BGRB */ + "movl %%eax,4(%%edi)\n\t" /* write GRBG */ + "movl %%ecx,8(%%edi)\n\t" /* write RBGR */ + "movl %%esi,12(%%edi)\n\t" + "movl %%eax,16(%%edi)\n\t" + "movl %%ecx,20(%%edi)\n\t" + "movl %%esi,24(%%edi)\n\t" + "movl %%eax,28(%%edi)\n\t" + "movl %%ecx,32(%%edi)\n\t" + "movl %%esi,36(%%edi)\n\t" + "subl $16,%%edx\n\t" /* blend end-of-loop instr. */ + "movl %%eax,40(%%edi)\n\t" + "movl %%ecx,44(%%edi)\n\t" + "addl $48,%%edi\n\t" + "cmpl $16,%%edx\n\t" + "jge 5b\n\t" + "andl %%edx,%%edx\n\t" + "jz 4f\n\t" /* finished */ + "cmpl $4,%%edx\n\t" + "jl 2f\n\t" /* less than 4 pixels left */ + "jmp 1f\n\t" + ".align 4,0x90\n\t" + + "1:\n\t" + "movl %%esi,(%%edi)\n\t" /* write BGRB */ + "movl %%eax,4(%%edi)\n\t" /* write GRBG */ + "movl %%ecx,8(%%edi)\n\t" /* write RBGR */ + "addl $12,%%edi\n\t" + "subl $4,%%edx\n\t" + "cmpl $4,%%edx\n\t" + "jge 1b\n\t" + + "2:\n\t" + "cmpl $0,%%edx\n\t" /* none left? */ + "jle 4f\n\t" /* finished */ + + "mov %%ecx,%%eax\n\t" + "shrl $8,%%ecx\n\t" /* R in cl */ + + "3:\n\t" /* write last few pixels */ + "movw %%cx,(%%edi)\n\t" /* write BG */ + "movb %%al,2(%%edi)\n\t" /* write R */ + "addl $3,%%edi\n\t" + "decl %%edx\n\t" + "jnz 3b\n\t" + + "4:\n\t" + : "=a"(dummy1), "=D"(dummy2), "=d"(dummy3) /* fake outputs */ + : "0"(c), "1"(s), "2"(count) + : /***rjr***"ax",*/ "cx", /*"dx",*/ "si"/*, "di"*/ + ); + return s; +} + +/* Functions for which arguments must be passed in %ebx, %edx, and %ecx. */ +#if 0 /* Why declare 'em? Just confuses the compiler and can't be called from C + anyway */ +extern __memcpyasm_regargs(); /* nu_bytes >= 3 */ +extern __memcpyasm_regargs_aligned(); /* nu_bytes >= 32 */ +#endif + + +/* Always 32-bit align destination, even for a small number of bytes. */ +static inline void * + __memcpy_aligndest(void *dest, const void *src, int n) +{ + __asm__ __volatile__("cmpl $3, %%ecx\n\t" + "ja 1f\n\t" + "call * __memcpy_jumptable (, %%ecx, 4)\n\t" + "jmp 2f\n\t" + "1:call __memcpyasm_regargs\n\t" + "2:": + :"S"(dest), "d"(src), "c"(n) + :"ax", "0", "1", "2"); + return dest; +} + + +/* Optimized version for 32-bit aligned destination. */ +static inline void * + __memcpy_destaligned(void *dest, const void *src, int n) +{ + __asm__ __volatile__("cmpl $32, %%ecx\n\t" + "ja 1f\n\t" + "call * __memcpy_jumptable (, %%ecx, 4)\n\t" + "jmp 2f\n\t" + "1:call __memcpyasm_regargs_aligned\n\t" + "2:\n\t": + :"S"(dest), "d"(src), "c"(n) + :"ax", "0", "1", "2"); + return dest; +} + + +/* Balanced inline memcpy; 32-bit align destination if nu_bytes >= 20. */ +static inline void * + __memcpy_balanced(void *dest, const void *src, int n) +{ + __asm__ __volatile__("cmpl $19, %%ecx\n\t" + "ja 1f\n\t" + "call * __memcpy_jumptable (, %%ecx, 4)\n\t" + "jmp 2f\n\t" + "1:call __memcpyasm_regargs\n\t" + "2:\n\t" + : + :"S"((long) dest), "d"((long) src), "c"((long) n) + :"ax", "0", "1", "2"); + return dest; +} + + +#define __memcpy __memcpy_conventional + +#endif + +/* Functions defined in mem.S or mem.c */ + +extern void __svgalib_memcpy4to3(void *dest, void *src, int n); +extern void __svgalib_memcpy32shift8(void *dest, void *src, int n); + diff --git a/gl/line.c b/gl/line.c new file mode 100644 index 0000000..271589f --- /dev/null +++ b/gl/line.c @@ -0,0 +1,546 @@ +/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ +/* line.c Line drawing */ + + +#include + +#ifndef DO_NOT_USE_VGALIB +#include +#endif + +#include "inlstring.h" /* include inline string operations */ + +#include "vgagl.h" +#include "def.h" +#include "driver.h" + +static inline int muldiv64(int m1, int m2, int d) +{ + return (float) m1 * (float) m2 / ((float) d); +} + +#ifdef NO_ASSEMBLY + +static inline int gl_regioncode (int x, int y) +{ + int result = 0; + if (x < __clipx1) + result |= 1; + else if (x > __clipx2) + result |= 2; + if (y < __clipy1) + result |= 4; + else if (y > __clipy2) + result |= 8; + return result; +} + +#else + +#define INC_IF_NEG(y, result) \ +{ \ + __asm__("btl $31,%1\n\t" \ + "adcl $0,%0" \ + : "=r" ((int) result) \ + : "rm" ((int) (y)), "0" ((int) result) \ + ); \ +} + +static inline int gl_regioncode (int x, int y) +{ + int dx1, dx2, dy1, dy2; + int result; + result = 0; + dy2 = __clipy2 - y; + INC_IF_NEG (dy2, result); + result <<= 1; + dy1 = y - __clipy1; + INC_IF_NEG (dy1, result); + result <<= 1; + dx2 = __clipx2 - x; + INC_IF_NEG (dx2, result); + result <<= 1; + dx1 = x - __clipx1; + INC_IF_NEG (dx1, result); + return result; +} + +#endif /* ! NO_ASSEMBLY */ + + +#define line_start_paged(s) \ + fp = y * bytesperrow + x * s; \ + vga_setpage (fpp = (fp >> 16)); \ + fp &= 0xFFFF; + +#define line_start_linear(s) \ + vp = (unsigned char *)VBUF + y * bytesperrow + x * s; + + +#define line_loop_paged_a(m,i,u,v) \ + { \ + int d = ay - (ax >> 1); \ + if ((x = abs (dx))) \ + do { \ + i; \ + if (d m 0) { \ + fp v; \ + d -= ax; \ + } \ + fp u; \ + d += ay; \ + if (fp & 0xFFFF0000) { /* has it cross a page boundary ? */ \ + fpp += fp >> 16; \ + vga_setpage (fpp); \ + } \ + fp &= 0x0000FFFF; \ + } while (--x); \ + } + +#define line_loop_linear_a(m,i,u,v) \ + { \ + int d = ay - (ax >> 1); \ + if ((x = abs (dx))) \ + do { \ + i; \ + if (d m 0) { \ + vp v; \ + d -= ax; \ + } \ + vp u; \ + d += ay; \ + } while (--x); \ + } + + +#define line_loop_paged_b(m,i,u,v) \ + { \ + int d = ax - (ay >> 1); \ + if ((y = abs (dy))) \ + do { \ + i; \ + if (d m 0) { \ + fp u; \ + d -= ay; \ + } \ + fp v; \ + d += ax; \ + if (fp & 0xFFFF0000) { \ + fpp += fp >> 16; \ + vga_setpage (fpp); \ + } \ + fp &= 0x0000FFFF; \ + } while (--y); \ + } + + +#define line_loop_linear_b(m,i,u,v) \ + { \ + int d = ax - (ay >> 1); \ + if ((y = abs (dy))) \ + do { \ + i; \ + if (d m 0) { \ + vp u; \ + d -= ay; \ + } \ + vp v; \ + d += ax; \ + } while (--y); \ + } + + + +/* Partly based on the work which was partly based on vgalib by Tommy Frandsen */ +/* This is a lot faster now that setpixel is inlined */ + +void gl_line (int x1, int y1, int x2, int y2, int c) +{ + int dx, dy, ax, ay, sx, sy, x, y; + int bytesperrow; + unsigned char *vp = NULL; + + if (__clip) + /* Cohen & Sutherland algorithm */ + for (;;) { + int r1 = gl_regioncode (x1, y1); + int r2 = gl_regioncode (x2, y2); + if (!(r1 | r2)) + break; /* completely inside */ + if (r1 & r2) + return; /* completely outside */ + if (r1 == 0) { + swap (x1, x2); /* make sure first */ + swap (y1, y2); /* point is outside */ + r1 = r2; + } + if (r1 & 1) { /* left */ + y1 += muldiv64 (__clipx1 - x1, y2 - y1, x2 - x1); + x1 = __clipx1; + } else if (r1 & 2) { /* right */ + y1 += muldiv64 (__clipx2 - x1, y2 - y1, x2 - x1); + x1 = __clipx2; + } else if (r1 & 4) { /* top */ + x1 += muldiv64 (__clipy1 - y1, x2 - x1, y2 - y1); + y1 = __clipy1; + } else if (r1 & 8) { /* bottom */ + x1 += muldiv64 (__clipy2 - y1, x2 - x1, y2 - y1); + y1 = __clipy2; + } + } + dx = x2 - x1; + dy = y2 - y1; + ax = abs (dx) << 1; + ay = abs (dy) << 1; + sx = (dx >= 0) ? 1 : -1; + sy = (dy >= 0) ? 1 : -1; + x = x1; + y = y1; + +#define insert_pixel_1 *((unsigned char *) vp) = c; +#define insert_pixel_2 *((unsigned short *) vp) = c; + +#define insert_pixel_3 *((unsigned char *) vp) = c; \ + *((unsigned char *) (vp + 1)) = (c>>8); \ + *((unsigned char *) (vp + 2)) = (c>>16); + +#define insert_pixel_4 *((unsigned int *) vp) = c; + + bytesperrow = BYTEWIDTH; + + if (MODETYPE == CONTEXT_VIRTUAL || MODETYPE == CONTEXT_LINEAR) { + switch BYTESPERPIXEL { + case 1: + line_start_linear(1); + if (ax > ay) { + if(sx > 0) { + line_loop_linear_a(>=,insert_pixel_1,++,+=bytesperrow*sy); + } else { + line_loop_linear_a(>,insert_pixel_1,--,+=bytesperrow*sy); + } + } else { + if(sy > 0) { + line_loop_linear_b(>=,insert_pixel_1,+=sx,+=bytesperrow); + } else { + line_loop_linear_b(>,insert_pixel_1,+=sx,-=bytesperrow); + } + } + insert_pixel_1; + break; + case 2: + line_start_linear(2); + if (ax > ay) { + if(sx > 0) { + line_loop_linear_a(>=,insert_pixel_2,+=2,+=bytesperrow*sy); + } else { + line_loop_linear_a(>,insert_pixel_2,-=2,+=bytesperrow*sy); + } + } else { + sx <<= 1; + if(sy > 0) { + line_loop_linear_b(>=,insert_pixel_2,+=sx,+=bytesperrow); + } else { + line_loop_linear_b(>,insert_pixel_2,+=sx,-=bytesperrow); + } + } + insert_pixel_2; + break; + case 3: + line_start_linear(3); + if (ax > ay) { + if(sx > 0) { + line_loop_linear_a(>=,insert_pixel_3,+=3,+=bytesperrow*sy); + } else { + line_loop_linear_a(>,insert_pixel_3,-=3,+=bytesperrow*sy); + } + } else { + sx *= 3; + if(sy > 0) { + line_loop_linear_b(>=,insert_pixel_3,+=sx,+=bytesperrow); + } else { + line_loop_linear_b(>,insert_pixel_3,+=sx,-=bytesperrow); + } + } + insert_pixel_3; + break; + case 4: + line_start_linear(4); + if (ax > ay) { + if(sx > 0) { + line_loop_linear_a(>=,insert_pixel_4,+=4,+=bytesperrow*sy); + } else { + line_loop_linear_a(>,insert_pixel_4,-=4,+=bytesperrow*sy); + } + } else { + sx <<= 2; + if(sy > 0) { + line_loop_linear_b(>=,insert_pixel_4,+=sx,+=bytesperrow); + } else { + line_loop_linear_b(>,insert_pixel_4,+=sx,-=bytesperrow); + } + } + insert_pixel_4; + break; + } + } + + + + +#ifndef DO_NOT_USE_VGALIB + +#undef insert_pixel_1 +#undef insert_pixel_2 +#undef insert_pixel_3 +#undef insert_pixel_4 + +#define insert_pixel_1 *((unsigned char *) (vp + fp)) = c; +#define insert_pixel_2 *((unsigned short *) (vp + fp)) = c; + +#define insert_pixel_3 *((unsigned char *) (vp + fp)) = c; \ + *((unsigned char *) (vp + fp + 1)) = (c>>8); \ + *((unsigned char *) (vp + fp + 2)) = (c>>16); + +#define insert_pixel_4 *((unsigned int *) (vp + fp)) = c; + + + if (MODETYPE == CONTEXT_PAGED) { + vp = (unsigned char *)VBUF; + switch BYTESPERPIXEL { + int fpp; + int fp; + case 1: + line_start_paged(1); + if (ax > ay) { + if(sx > 0) { + line_loop_paged_a(>=,insert_pixel_1,++,+=bytesperrow*sy); + } else { + line_loop_paged_a(>,insert_pixel_1,--,+=bytesperrow*sy); + } + } else { + if(sy > 0) { + line_loop_paged_b(>=,insert_pixel_1,+=sx,+=bytesperrow); + } else { + line_loop_paged_b(>,insert_pixel_1,+=sx,-=bytesperrow); + } + } + insert_pixel_1; + break; + case 2: + line_start_paged(2); + if (ax > ay) { + if(sx > 0) { + line_loop_paged_a(>=,insert_pixel_2,+=2,+=bytesperrow*sy); + } else { + line_loop_paged_a(>,insert_pixel_2,-=2,+=bytesperrow*sy); + } + } else { + sx <<= 1; + if(sy > 0) { + line_loop_paged_b(>=,insert_pixel_2,+=sx,+=bytesperrow); + } else { + line_loop_paged_b(>,insert_pixel_2,+=sx,-=bytesperrow); + } + } + insert_pixel_2; + break; + case 3: + line_start_paged(3); + if (ax > ay) { + if(sx > 0) { + line_loop_paged_a(>=,insert_pixel_3,+=3,+=bytesperrow*sy); + } else { + line_loop_paged_a(>,insert_pixel_3,-=3,+=bytesperrow*sy); + } + } else { + sx *= 3; + if(sy > 0) { + line_loop_paged_b(>=,insert_pixel_3,+=sx,+=bytesperrow); + } else { + line_loop_paged_b(>,insert_pixel_3,+=sx,-=bytesperrow); + } + } + insert_pixel_3; + break; + case 4: + line_start_paged(4); + if (ax > ay) { + if(sx > 0) { + line_loop_paged_a(>=,insert_pixel_4,+=4,+=bytesperrow*sy); + } else { + line_loop_paged_a(>,insert_pixel_4,-=4,+=bytesperrow*sy); + } + } else { + sx <<= 2; + if(sy > 0) { + line_loop_paged_b(>=,insert_pixel_4,+=sx,+=bytesperrow); + } else { + line_loop_paged_b(>,insert_pixel_4,+=sx,-=bytesperrow); + } + } + insert_pixel_4; + break; + } + } + + if (!vp) { + + if (ax > ay) { + int d = ay - (ax >> 1); + while (x != x2) { + setpixel (x, y, c); + + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } else { + int d = ax - (ay >> 1); + while (y != y2) { + setpixel (x, y, c); + + if (d > 0 || (d == 0 && sy == 1)) { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } + setpixel (x, y, c); + } +#endif +} + + +static void gl_setcirclepixels(int x, int y, int sx, int sy, int c) +{ + if (__clip) { + int z = max(x, y); + if (sx - z < __clipx1 || sx + z > __clipx2 + || sy - z < __clipy1 || sy + z > __clipy2) { + /* use setpixel clipping */ + gl_setpixel(sx + x, sy + y, c); + gl_setpixel(sx - x, sy + y, c); + gl_setpixel(sx + x, sy - y, c); + gl_setpixel(sx - x, sy - y, c); + gl_setpixel(sx + y, sy + x, c); + gl_setpixel(sx - y, sy + x, c); + gl_setpixel(sx + y, sy - x, c); + gl_setpixel(sx - y, sy - x, c); + return; + } + } + setpixel(sx + x, sy + y, c); + setpixel(sx - x, sy + y, c); + setpixel(sx + x, sy - y, c); + setpixel(sx - x, sy - y, c); + setpixel(sx + y, sy + x, c); + setpixel(sx - y, sy + x, c); + setpixel(sx + y, sy - x, c); + setpixel(sx - y, sy - x, c); +} + +void gl_circle(int sx, int sy, int r, int c) +{ + int x, y, d; + if (r < 1) { + gl_setpixel(sx, sy, c); + return; + } + if (__clip) + if (sx + r < __clipx1 || sx - r > __clipx2 + || sy + r < __clipy1 || sy - r > __clipy2) + return; + x = 0; + y = r; + d = 1 - r; + gl_setcirclepixels(x, y, sx, sy, c); + while (x < y) { + if (d < 0) + d += x * 2 + 3; + else { + d += x * 2 - y * 2 + 5; + y--; + } + x++; + gl_setcirclepixels(x, y, sx, sy, c); + } +} + +void gl_fillcircle(int sx, int sy, int r, int c) +{ + int x = 0, + y = r, + d = 1 - r; + + if (r < 1) { + gl_setpixel(sx, sy, c); + return; + } + if (__clip) + if (sx + r < __clipx1 || sx - r > __clipx2 + || sy + r < __clipy1 || sy - r > __clipy2) + return; + gl_hline(sx - x, sy + y, sx + x, c); + gl_hline(sx - x, sy - y, sx + x, c); + gl_hline(sx - y, sy + x, sx + y, c); + gl_hline(sx - y, sy - x, sx + y, c); + while (x < y) + { + if (d < 0) + { + d += x * 2 + 3; + } else { + d += x * 2 - y * 2 + 5; + y--; + } + x++; + gl_hline(sx - x, sy + y, sx + x, c); + gl_hline(sx - x, sy - y, sx + x, c); + gl_hline(sx - y, sy + x, sx + y, c); + gl_hline(sx - y, sy - x, sx + y, c); + } +} + +void gl_bcircle(int sx, int sy, int r, int c, int fill) +{ + int x = 0, + y = r, + d = 2 * (1 - r); + + if (r < 1) { + gl_setpixel(sx, sy, c); + return; + } + if (__clip) + if (sx + r < __clipx1 || sx - r > __clipx2 + || sy + r < __clipy1 || sy - r > __clipy2) + return; + while (y >= 0) + { + if (fill == 0) + { + gl_setpixel(sx + x, sy + y, c); + gl_setpixel(sx + x, sy - y, c); + gl_setpixel(sx - x, sy + y, c); + gl_setpixel(sx - x, sy - y, c); + } else { + gl_hline(sx - x, sy + y, sx + x, c); + gl_hline(sx - x, sy - y, sx + x, c); + } + if ((d + y) > 0) + { + y--; + d -= (2 * y * WIDTH / HEIGHT) - 1; + } + if (x > d) + { + x++; + d += (2 * x) + 1; + } + } +} diff --git a/gl/mem.S b/gl/mem.S new file mode 100644 index 0000000..8893da0 --- /dev/null +++ b/gl/mem.S @@ -0,0 +1,481 @@ +#define __ASSEMBLY__ +#include + +#ifndef SYMBOL_NAME +#define SYMBOL_NAME(name) _ ## name +#endif +#ifndef ENTRY +#define ENTRY(name) .align 4; .globl _ ## name ## ; _ ## name ## : +#endif + + .file "mem.S" + + /* This file contains unrolled memcpy functions. */ + + + /* Prototype: memcpy4to3( void *dest, void *src, int n ) */ + /* Copies pixels from 4-byte-per-pixel screen to 3-byte-per-pixel screen, +*/ + /* discarding the last byte of each pixel. */ + /* Only uses 32-bit aligned word accesses. */ + /* Instructions have been shuffled a bit for possible avoidance of */ + /* pipeline hazards. */ + +.text +ENTRY(memcpy4to3) + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + pushl %ebx + pushl %ecx + movl 8(%ebp),%edi /* destination address */ + movl 12(%ebp),%esi /* source address */ + movl 16(%ebp),%ecx /* number of pixels */ + + /* Handle chunks of 8 pixels. */ +1: cmpl $8,%ecx + jl 2f + + movl (%esi),%eax /* pixel 0 */ + movl 4(%esi),%ebx /* pixel 1 */ + shll $8,%eax /* BGR0 in 8-31 */ + shrd $8,%ebx,%eax /* BGR0 in 0-23, B1 in 24-31 */ + movl %eax,(%edi) /* write word */ + shll $8,%ebx /* GR1 in 16-31 */ + movl 8(%esi),%eax /* pixel 2 */ + shrd $16,%eax,%ebx /* GR1 in 0-15, BG2 in 16-31 */ + movl %ebx,4(%edi) /* write word */ + shll $8,%eax /* move R2 into 24-31 */ + movl 12(%esi),%ebx /* pixel 3 */ + shrd $24,%ebx,%eax /* R2 in 0-7, BGR3 in 8-31 */ + movl %eax,8(%edi) /* write word */ + + movl 16(%esi),%eax /* pixel 4 */ + shll $8,%eax /* BGR4 in 8-31 */ + movl 20(%esi),%ebx /* pixel 5 */ + shrd $8,%ebx,%eax /* BGR4 in 0-23, B5 in 24-31 */ + movl %eax,12(%edi) /* write word */ + shll $8,%ebx /* GR5 in 16-31 */ + movl 24(%esi),%eax /* pixel 6 */ + shrd $16,%eax,%ebx /* GR5 in 0-15, BG6 in 16-31 */ + movl %ebx,16(%edi) /* write word */ + subl $8,%ecx /* blended end-of-loop instruction */ + shll $8,%eax /* move R6 into 24-31 */ + movl 28(%esi),%ebx /* pixel 7 */ + shrd $24,%ebx,%eax /* R6 in 0-7, BGR7 in 8-31 */ + addl $32,%esi /* blended end-of-loop instruction */ + movl %eax,20(%edi) /* write word */ + + addl $24,%edi + jmp 1b + +2: /* Do the remaining pixels. */ + + andl %ecx,%ecx + jz 4f /* none left */ + +3: movl (%esi),%eax + movw %eax,(%edi) + shrl $16,%eax + movb %al,2(%edi) + addl $4,%esi + addl $3,%edi + decl %ecx + jnz 3b + +4: + popl %ecx + popl %ebx + popl %esi + popl %edi + popl %ebp + ret + + /* Prototype: memcpy32shift8( void *dest, void *src, int n ) */ + /* Copies pixels from 4-byte-per-pixel screen organized as BGR0 to */ + /* 0BGR 4-byte-per-pixel screen. */ + /* Used by copyscreen for ATI mach32 32-bit truecolor modes. */ + +.text +ENTRY(memcpy32shift8) + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + pushl %ecx + pushl %ebx + movl 8(%ebp),%edi /* destination address */ + movl 12(%ebp),%esi /* source address */ + movl 16(%ebp),%ecx /* number of pixels */ + + /* Handle chunks of 8 pixels. */ +1: cmpl $8,%ecx + jl 2f + + movl (%esi),%eax + shll $8,%eax + movl %eax,(%edi) + movl 4(%esi),%edx + shll $8,%edx + movl %edx,4(%edi) + movl 8(%esi),%eax + shll $8,%eax + movl %eax,8(%edi) + movl 12(%esi),%edx + shll $8,%edx + movl %edx,12(%edi) + movl 16(%esi),%eax + shll $8,%eax + movl %eax,16(%edi) + movl 20(%esi),%edx + shll $8,%edx + movl %edx,20(%edi) + movl 24(%esi),%eax + subl $8,%ecx + shll $8,%eax + movl %eax,24(%edi) + movl 28(%esi),%edx + addl $32,%esi + shll $8,%edx + movl %edx,28(%edi) + addl $32,%edi + jmp 1b + +2: andl %ecx,%ecx + jz 4f + +3: movl (%esi),%eax + shll $8,%eax + movl %eax,(%edi) + addl $4,%esi + addl $4,%edi + decl %ecx + jnz 3b + +4: + popl %ebx + popl %ecx + popl %esi + popl %edi + popl %ebp + ret + + +/* Optimized memcpy. */ +/* Performance on par with inlined 32-bit aligned rep movsl on slow */ +/* motherboard. */ +/* Hypothesized to be fast on motherboards that handle writes efficiently */ +/* and suffer with slow rep movsl microcode in 486/Pentium. */ +/* (esp. Cyrix 486DX WB, Headland HTK 486 chipset, Pentium). */ + +/* Arguments passed in registers: */ +/* destination address in %esi */ +/* source address in %edx */ +/* count in %ecx */ + +#define MOVEBYTE(n) movb n(%edx),%al; movb %al,n(%esi) + +#define MOVESHORT(n) movw n(%edx),%ax; movw %ax,n(%esi) + +#define MOVEWORD(n) movl n(%edx),%eax; movl %eax,n(%esi) + +ENTRY(_memcpy_jumptable) + .long copy0 + .long copy1, copy2, copy3, copy4 + .long copy5, copy6, copy7, copy8 + .long copy9, copy10, copy11, copy12 + .long copy13, copy14, copy15, copy16 + .long copy17, copy18, copy19, copy20 + .long copy21, copy22, copy23, copy24 + .long copy25, copy26, copy27, copy28 + .long copy29, copy30, copy31, copy32 + +jumptable2: + .long align0, align1, align2, align3 + +ENTRY(_memcpyasm_regargs) + + /* This is only valid if nu_bytes >= 3. */ + + /* Align destination to 32-bit boundary */ + movl %esi,%eax + andl $3,%eax + jmp *jumptable2(,%eax,4) + +align1: MOVESHORT(0) + MOVEBYTE(2) + addl $3,%edx + addl $3,%esi + subl $3,%ecx + jmp copyaligned + +align3: MOVEBYTE(0) + incl %edx + incl %esi + decl %ecx + jmp copyaligned + +align2: MOVESHORT(0) + addl $2,%edx + addl $2,%esi + subl $2,%ecx +align0: + +copyaligned: + cmpl $32,%ecx + ja copyunrolled + /* <= 32 bytes. */ + /* Copy remaining bytes (0-32). */ + jmp *SYMBOL_NAME(_memcpy_jumptable)(,%ecx,4) + .align 4,0x90 + +/* memcpyasm_regargs_aligned is only called if nu_bytes > 32. */ +ENTRY(_memcpyasm_regargs_aligned) + +copyunrolled: + /* Copy chunks of 32 bytes. */ + /* End-of-loop increment instructions blended in. */ + addl $32,%esi /*P ok */ + movl (%edx),%eax + movl %eax,(0-32)(%esi) /*P ok */ + movl 4(%edx),%eax + movl %eax,(4-32)(%esi) /*P ok */ + movl 8(%edx),%eax + movl %eax,(8-32)(%esi) /*P ok */ + movl 12(%edx),%eax + movl %eax,(12-32)(%esi) /*P ok */ + movl 16(%edx),%eax + addl $32,%edx /*P ok */ + movl %eax,(16-32)(%esi) + subl $32,%ecx /*P ok */ + movl (20-32)(%edx),%eax + movl %eax,(20-32)(%esi) /*P ok */ + movl (24-32)(%edx),%eax + movl %eax,(24-32)(%esi) /*P ok */ + movl (28-32)(%edx),%eax + movl %eax,(28-32)(%esi) /*P ok */ + cmpl $32,%ecx + jge copyunrolled /*P fail */ + /* Copy remaining bytes (less than 32). */ + jmp *SYMBOL_NAME(_memcpy_jumptable)(,%ecx,4) + +#define END ret + +copy0: END + +copy1: MOVEBYTE(0) + END + +copy2: MOVESHORT(0) + END + +copy3: MOVESHORT(0) + MOVEBYTE(2) + END + +copy4: MOVEWORD(0) + END + +copy5: MOVEWORD(0) + MOVEBYTE(4) + END + +copy6: MOVEWORD(0) + MOVESHORT(4) + END + +copy7: MOVEWORD(0) + MOVESHORT(4) + MOVEBYTE(6) + END + +copy8: MOVEWORD(0) + MOVEWORD(4) + END + +copy9: MOVEWORD(0) + MOVEWORD(4) + MOVEBYTE(8) + END + +copy10: MOVEWORD(0) + MOVEWORD(4) + MOVESHORT(8) + END + +copy11: MOVEWORD(0) + MOVEWORD(4) + MOVESHORT(8) + MOVEBYTE(10) + END + +copy12: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + END + +copy13: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEBYTE(12) + END + +copy14: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVESHORT(12) + END + +copy15: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVESHORT(12) + MOVEBYTE(14) + END + +copy16: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + END + +copy17: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEBYTE(16) + END + +copy18: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVESHORT(16) + END + +copy19: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVESHORT(16) + MOVEBYTE(18) + END + +copy20: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + END + +copy21: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEBYTE(20) + END + +copy22: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVESHORT(20) + END + +copy23: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVESHORT(20) + MOVEBYTE(22) + END + +copy24: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + END + +copy25: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVEBYTE(24) + END + +copy26: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVESHORT(24) + END + +copy27: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVESHORT(24) + MOVEBYTE(26) + END + +copy28: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVEWORD(24) + END + +copy29: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVEWORD(24) + MOVEBYTE(28) + END + +copy30: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVEWORD(24) + MOVESHORT(28) + END + +copy31: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVEWORD(24) + MOVESHORT(28) + MOVEBYTE(30) + END + +copy32: MOVEWORD(0) + MOVEWORD(4) + MOVEWORD(8) + MOVEWORD(12) + MOVEWORD(16) + MOVEWORD(20) + MOVEWORD(24) + MOVEWORD(28) + END diff --git a/gl/mem.c b/gl/mem.c new file mode 100644 index 0000000..79bec46 --- /dev/null +++ b/gl/mem.c @@ -0,0 +1,23 @@ +#include + + /* + * Copies pixels from 4-byte-per-pixel screen to 3-byte-per-pixel screen, + * + * discarding the last byte of each pixel. Only uses 32-bit aligned word + * accesses. Instructions have been shuffled a bit for possible + * avoidance of pipeline hazards. + */ +void __svgalib_memcpy4to3(void *dest, void *src, int n) +{ + printf("libgl: __svgalib_memcpy4to3 not done yet\n"); +} + +/* + * Copies pixels from 4-byte-per-pixel screen organized as BGR0 to + * 0BGR 4-byte-per-pixel screen. + * Used by copyscreen for ATI mach32 32-bit truecolor modes. + */ +void __svgalib_memcpy32shift8(void *dest, void *src, int n) +{ + printf("libgl: __svgalib_memcpy32shift8 not done yet\n"); +} diff --git a/gl/palette.c b/gl/palette.c new file mode 100644 index 0000000..b20bb18 --- /dev/null +++ b/gl/palette.c @@ -0,0 +1,71 @@ +/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ +/* palette.c Palette functions (wrapper over vgalib) */ + + +#include +#include + +#include "vgagl.h" +#include "def.h" + + +/* 256-color palette functions */ + +/* There was a horrible bug here in 0.8x -- green and blue were swapped... */ +void gl_getpalettecolor(int c, int *r, int *g, int *b) +{ + vga_getpalette(c, r, g, b); +} + +void gl_setpalettecolor(int c, int r, int g, int b) +{ + vga_setpalette(c, r, g, b); +} + +void gl_setpalettecolors(int s, int n, void *_dp) +{ + uchar *dp = _dp; + int i; + for (i = s; i < s + n; i++) { + unsigned char r, g, b; + r = *(dp++); + g = *(dp++); + b = *(dp++); + vga_setpalette(i, r, g, b); + } +} + +void gl_getpalettecolors(int s, int n, void *_dp) +{ + uchar *dp = _dp; + int i; + for (i = s; i < s + n; i++) { + int r, g, b; + vga_getpalette(i, &r, &g, &b); + *(dp++) = (unsigned char) r; + *(dp++) = (unsigned char) g; + *(dp++) = (unsigned char) b; + } +} + +void gl_getpalette(void *p) +{ + gl_getpalettecolors(0, 256, p); +} + +void gl_setpalette(void *p) +{ + gl_setpalettecolors(0, 256, p); +} + +void gl_setrgbpalette() +{ + int i; + Palette pal; + for (i = 0; i < 256; i++) { + pal.color[i].blue = (i & 7) * (64 / 8); /* 3 bits */ + pal.color[i].green = ((i & 56) >> 3) * (64 / 8); /* 3 bits */ + pal.color[i].red = ((i & 192) >> 6) * (64 / 4); /* 2 bits */ + } + gl_setpalette(&pal); +} diff --git a/gl/scale.c b/gl/scale.c new file mode 100644 index 0000000..e3bec32 --- /dev/null +++ b/gl/scale.c @@ -0,0 +1,197 @@ +/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ +/* scale.c Scaling routine */ + + +#include +#include +#include "inlstring.h" /* include inline string operations */ + +#include "vgagl.h" +#include "def.h" + +static inline int muldiv64(float m1, float m2, float d) +{ + return m1 * m2 / d; +} + +/* This is a DDA-based algorithm. */ +/* Iteration over target bitmap. */ + +void gl_scalebox(int w1, int h1, void *_dp1, int w2, int h2, void *_dp2) +{ + uchar *dp1 = _dp1; + uchar *dp2 = _dp2; + int xfactor; + int yfactor; + + if (w2 == 0 || h2 == 0) + return; + + xfactor = muldiv64(w1, 65536, w2); /* scaled by 65536 */ + yfactor = muldiv64(h1, 65536, h2); /* scaled by 65536 */ + + switch (BYTESPERPIXEL) { + case 1: + { + int y, sy; + sy = 0; + for (y = 0; y < h2;) { + int sx = 0; + uchar *dp2old = dp2; + int x; + x = 0; + while (x < w2 - 8) { + *(dp2 + x) = *(dp1 + (sx >> 16)); + sx += xfactor; + *(dp2 + x + 1) = *(dp1 + (sx >> 16)); + sx += xfactor; + *(dp2 + x + 2) = *(dp1 + (sx >> 16)); + sx += xfactor; + *(dp2 + x + 3) = *(dp1 + (sx >> 16)); + sx += xfactor; + *(dp2 + x + 4) = *(dp1 + (sx >> 16)); + sx += xfactor; + *(dp2 + x + 5) = *(dp1 + (sx >> 16)); + sx += xfactor; + *(dp2 + x + 6) = *(dp1 + (sx >> 16)); + sx += xfactor; + *(dp2 + x + 7) = *(dp1 + (sx >> 16)); + sx += xfactor; + x += 8; + } + while (x < w2) { + *(dp2 + x) = *(dp1 + (sx >> 16)); + sx += xfactor; + x++; + } + dp2 += w2; + y++; + while (y < h2) { + int l; + int syint = sy >> 16; + sy += yfactor; + if ((sy >> 16) != syint) + break; + /* Copy identical lines. */ + l = dp2 - dp2old; + __memcpy(dp2, dp2old, l); + dp2old = dp2; + dp2 += l; + y++; + } + dp1 = _dp1 + (sy >> 16) * w1; + } + } + break; + case 2: + { + int y, sy; + sy = 0; + for (y = 0; y < h2;) { + int sx = 0; + uchar *dp2old = dp2; + int x; + x = 0; + /* This can be greatly optimized with loop */ + /* unrolling; omitted to save space. */ + while (x < w2) { + *(unsigned short *) (dp2 + x * 2) = + *(unsigned short *) (dp1 + (sx >> 16) * 2); + sx += xfactor; + x++; + } + dp2 += w2 * 2; + y++; + while (y < h2) { + int l; + int syint = sy >> 16; + sy += yfactor; + if ((sy >> 16) != syint) + break; + /* Copy identical lines. */ + l = dp2 - dp2old; + __memcpy(dp2, dp2old, l); + dp2old = dp2; + dp2 += l; + y++; + } + dp1 = _dp1 + (sy >> 16) * w1 * 2; + } + } + break; + case 3: + { + int y, sy; + sy = 0; + for (y = 0; y < h2;) { + int sx = 0; + uchar *dp2old = dp2; + int x; + x = 0; + /* This can be greatly optimized with loop */ + /* unrolling; omitted to save space. */ + while (x < w2) { + *(unsigned short *) (dp2 + x * 3) = + *(unsigned short *) (dp1 + (sx >> 16) * 3); + *(unsigned char *) (dp2 + x * 3 + 2) = + *(unsigned char *) (dp1 + (sx >> 16) * 3 + 2); + sx += xfactor; + x++; + } + dp2 += w2 * 3; + y++; + while (y < h2) { + int l; + int syint = sy >> 16; + sy += yfactor; + if ((sy >> 16) != syint) + break; + /* Copy identical lines. */ + l = dp2 - dp2old; + __memcpy(dp2, dp2old, l); + dp2old = dp2; + dp2 += l; + y++; + } + dp1 = _dp1 + (sy >> 16) * w1 * 3; + } + } + break; + case 4: + { + int y, sy; + sy = 0; + for (y = 0; y < h2;) { + int sx = 0; + uchar *dp2old = dp2; + int x; + x = 0; + /* This can be greatly optimized with loop */ + /* unrolling; omitted to save space. */ + while (x < w2) { + *(unsigned *) (dp2 + x * 4) = + *(unsigned *) (dp1 + (sx >> 16) * 4); + sx += xfactor; + x++; + } + dp2 += w2 * 4; + y++; + while (y < h2) { + int l; + int syint = sy >> 16; + sy += yfactor; + if ((sy >> 16) != syint) + break; + /* Copy identical lines. */ + l = dp2 - dp2old; + __memcpy(dp2, dp2old, l); + dp2old = dp2; + dp2 += l; + y++; + } + dp1 = _dp1 + (sy >> 16) * w1 * 4; + } + } + break; + } +} diff --git a/gl/text.c b/gl/text.c new file mode 100644 index 0000000..83d7055 --- /dev/null +++ b/gl/text.c @@ -0,0 +1,328 @@ +/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ +/* text.c Text writing and fonts */ + + +#include +#include +#include +#include +#include "inlstring.h" /* include inline string operations */ + +#include "vgagl.h" +#include "def.h" + + + +/* Text/font functions */ + +static int font_width = 8; +static int font_height = 8; +static char *font_address; +static int font_charactersize = 64; +static int font_writemode = WRITEMODE_OVERWRITE; +static int compressed_font_bg = 0; +static int compressed_font_fg = 15; + +static void writecompressed(int x, int y, int n, unsigned char *s); + + +void gl_colorfont(int fw, int fh, int fg, void *_dp) +{ + uchar *dp = _dp; + int i; + i = fw * fh * 256; + switch (BYTESPERPIXEL) { + case 1: + while (i > 0) { + if (*dp) + *dp = fg; + dp++; + i--; + } + break; + case 2: + while (i > 0) { + if (*(ushort *) dp) + *(ushort *) dp = fg; + dp += 2; + i--; + } + break; + case 3: + while (i > 0) { + if (*(ushort *) dp || *(dp + 2)) { + *(ushort *) dp = fg; + *(dp + 2) = fg >> 16; + } + dp += 3; + i--; + } + break; + case 4: + while (i > 0) { + if (*(int *) dp) + *(int *) dp = fg; + dp += 4; + i--; + } + break; + + } +} + +void gl_setfont(int fw, int fh, void *font) +{ + font_width = fw; + font_height = fh; + font_charactersize = font_width * font_height * BYTESPERPIXEL; + font_address = font; +} + +void gl_setwritemode(int m) +{ + font_writemode = m; +} + +void gl_writen(int x, int y, int n, char *s) +{ +/* clipping in putbox */ + int i; + if (font_writemode & FONT_COMPRESSED) { + writecompressed(x, y, n, s); + return; + } + if (!(font_writemode & WRITEMODE_MASKED)) { + for (i=0; i= 0) && (sy >= 0)) { + x = x_start = sx; + y = sy; + } + + for (; *buf; buf++) + switch (*buf) { + case '\a': /* badly implemented */ + fputc('\a', stdout); + fflush(stdout); + break; + case '\b': + x -= font_width; + if (x < x_start) { + x = WIDTH + (x_start % font_width); + while(x + font_width > WIDTH) + x -= font_width; + if (y >= font_height) + y -= font_height; + } + break; + case '\n': + newline: + y += font_height; + if (y + font_height > HEIGHT) + y %= font_height; + case '\r': + x = x_start; + break; + case '\t': + x += ((TEXT_TABSIZE - ((x - x_start) / font_width) % TEXT_TABSIZE) * font_width); + goto chk_wrap; + break; + case '\v': + y += font_height; + if (y + font_height > HEIGHT) + y %= font_height; + break; + default: + gl_writen(x, y, 1, buf); + x += font_width; + chk_wrap: + if (x + font_width > WIDTH) + goto newline; + } + return n; +} + +int gl_printf(int x, int y, const char *fmt, ...) +{ + size_t bufs = BUFSIZ; + int result; + va_list args; + + va_start(args, fmt); + + /* Loop until buffer size suffices */ + do { + result = gl_nprintf(x, y, bufs, fmt, args); + bufs <<= 1; + } while(result < 0); + + va_end(args); + return result; +} + +#endif +void gl_expandfont(int fw, int fh, int fg, void *_f1, void *_f2) +{ +/* Convert bit-per-pixel font to byte(s)-per-pixel font */ + uchar *f1 = _f1; + uchar *f2 = _f2; + int i, x, y, b = 0; /* keep gcc happy with b = 0 - MW */ + + for (i = 0; i < 256; i++) { + for (y = 0; y < fh; y++) + for (x = 0; x < fw; x++) { + if (x % 8 == 0) + b = *f1++; + if (b & (128 >> (x % 8))) /* pixel */ + switch (BYTESPERPIXEL) { + case 1: + *f2 = fg; + f2++; + break; + case 2: + *(ushort *) f2 = fg; + f2 += 2; + break; + case 3: + *(ushort *) f2 = fg; + *(f2 + 2) = fg >> 16; + f2 += 3; + break; + case 4: + *(uint *) f2 = fg; + f2 += 4; + } else /* no pixel */ + switch (BYTESPERPIXEL) { + case 1: + *f2 = 0; + f2++; + break; + case 2: + *(ushort *) f2 = 0; + f2 += 2; + break; + case 3: + *(ushort *) f2 = 0; + *(f2 + 2) = 0; + f2 += 3; + break; + case 4: + *(uint *) f2 = 0; + f2 += 4; + } + } + } +} + +static void expandcharacter(int bg, int fg, int c, unsigned char *bitmap) +{ + int x, y; + unsigned char *font; + int b = 0; /* keep gcc happy with b = 0 - MW */ + + font = font_address + c * (font_height * ((font_width + 7) / 8)); + + for (y = 0; y < font_height; y++) + for (x = 0; x < font_width; x++) { + if (x % 8 == 0) + b = *font++; + if (b & (128 >> (x % 8))) /* pixel */ + switch (BYTESPERPIXEL) { + case 1: + *bitmap = fg; + bitmap++; + break; + case 2: + *(ushort *) bitmap = fg; + bitmap += 2; + break; + case 3: + *(ushort *) bitmap = fg; + *(bitmap + 2) = fg >> 16; + bitmap += 3; + break; + case 4: + *(uint *) bitmap = fg; + bitmap += 4; + } else /* background pixel */ + switch (BYTESPERPIXEL) { + case 1: + *bitmap = bg; + bitmap++; + break; + case 2: + *(ushort *) bitmap = bg; + bitmap += 2; + break; + case 3: + *(ushort *) bitmap = bg; + *(bitmap + 2) = bg >> 16; + bitmap += 3; + break; + case 4: + *(uint *) bitmap = bg; + bitmap += 4; + } + } +} + +/* Write using compressed font. */ + +static void writecompressed(int x, int y, int n, unsigned char *s) +{ + unsigned char *bitmap; + int i; + bitmap = alloca(font_width * font_height * BYTESPERPIXEL); + if (!(font_writemode & WRITEMODE_MASKED)) { + for (i=0; i +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SVGALIB_VER 0x010922 + +#define TEXT 0 /* Compatible with VGAlib v1.2 */ +#define G320x200x16 1 +#define G640x200x16 2 +#define G640x350x16 3 +#define G640x480x16 4 +#define G320x200x256 5 +#define G320x240x256 6 +#define G320x400x256 7 +#define G360x480x256 8 +#define G640x480x2 9 + +#define G640x480x256 10 +#define G800x600x256 11 +#define G1024x768x256 12 + +#define G1280x1024x256 13 /* Additional modes. */ + +#define G320x200x32K 14 +#define G320x200x64K 15 +#define G320x200x16M 16 +#define G640x480x32K 17 +#define G640x480x64K 18 +#define G640x480x16M 19 +#define G800x600x32K 20 +#define G800x600x64K 21 +#define G800x600x16M 22 +#define G1024x768x32K 23 +#define G1024x768x64K 24 +#define G1024x768x16M 25 +#define G1280x1024x32K 26 +#define G1280x1024x64K 27 +#define G1280x1024x16M 28 + +#define G800x600x16 29 +#define G1024x768x16 30 +#define G1280x1024x16 31 + +#define G720x348x2 32 /* Hercules emulation mode */ + +#define G320x200x16M32 33 /* 32-bit per pixel modes. */ +#define G640x480x16M32 34 +#define G800x600x16M32 35 +#define G1024x768x16M32 36 +#define G1280x1024x16M32 37 + +/* additional resolutions */ +#define G1152x864x16 38 +#define G1152x864x256 39 +#define G1152x864x32K 40 +#define G1152x864x64K 41 +#define G1152x864x16M 42 +#define G1152x864x16M32 43 + +#define G1600x1200x16 44 +#define G1600x1200x256 45 +#define G1600x1200x32K 46 +#define G1600x1200x64K 47 +#define G1600x1200x16M 48 +#define G1600x1200x16M32 49 + +#define G320x240x256V 50 +#define G320x240x32K 51 +#define G320x240x64K 52 +#define G320x240x16M 53 +#define G320x240x16M32 54 + +#define G400x300x256 55 +#define G400x300x32K 56 +#define G400x300x64K 57 +#define G400x300x16M 58 +#define G400x300x16M32 59 + +#define G512x384x256 60 +#define G512x384x32K 61 +#define G512x384x64K 62 +#define G512x384x16M 63 +#define G512x384x16M32 64 + +#define G960x720x256 65 +#define G960x720x32K 66 +#define G960x720x64K 67 +#define G960x720x16M 68 +#define G960x720x16M32 69 + +#define G1920x1440x256 70 +#define G1920x1440x32K 71 +#define G1920x1440x64K 72 +#define G1920x1440x16M 73 +#define G1920x1440x16M32 74 + +/* The following modes have been introduced by SciTech Display Doctor */ + +#define G320x400x256V 75 +#define G320x400x32K 76 +#define G320x400x64K 77 +#define G320x400x16M 78 +#define G320x400x16M32 79 + +#define G640x400x256 80 +#define G640x400x32K 81 +#define G640x400x64K 82 +#define G640x400x16M 83 +#define G640x400x16M32 84 + +#define G320x480x256 85 +#define G320x480x32K 86 +#define G320x480x64K 87 +#define G320x480x16M 88 +#define G320x480x16M32 89 + +#define G720x540x256 90 +#define G720x540x32K 91 +#define G720x540x64K 92 +#define G720x540x16M 93 +#define G720x540x16M32 94 + +#define G848x480x256 95 +#define G848x480x32K 96 +#define G848x480x64K 97 +#define G848x480x16M 98 +#define G848x480x16M32 99 + +#define G1072x600x256 100 +#define G1072x600x32K 101 +#define G1072x600x64K 102 +#define G1072x600x16M 103 +#define G1072x600x16M32 104 + +#define G1280x720x256 105 +#define G1280x720x32K 106 +#define G1280x720x64K 107 +#define G1280x720x16M 108 +#define G1280x720x16M32 109 + +#define G1360x768x256 110 +#define G1360x768x32K 111 +#define G1360x768x64K 112 +#define G1360x768x16M 113 +#define G1360x768x16M32 114 + +#define G1800x1012x256 115 +#define G1800x1012x32K 116 +#define G1800x1012x64K 117 +#define G1800x1012x16M 118 +#define G1800x1012x16M32 119 + +#define G1920x1080x256 120 +#define G1920x1080x32K 121 +#define G1920x1080x64K 122 +#define G1920x1080x16M 123 +#define G1920x1080x16M32 124 + +#define G2048x1152x256 125 +#define G2048x1152x32K 126 +#define G2048x1152x64K 127 +#define G2048x1152x16M 128 +#define G2048x1152x16M32 129 + +#define G2048x1536x256 130 +#define G2048x1536x32K 131 +#define G2048x1536x64K 132 +#define G2048x1536x16M 133 +#define G2048x1536x16M32 134 + +#define G512x480x256 135 +#define G512x480x32K 136 +#define G512x480x64K 137 +#define G512x480x16M 138 +#define G512x480x16M32 139 + +#define G400x600x256 140 +#define G400x600x32K 141 +#define G400x600x64K 142 +#define G400x600x16M 143 +#define G400x600x16M32 144 + +#define G400x300x256X 145 + +#define G320x200x256V 146 + +#define __GLASTMODE G320x200x256V +#define GLASTMODE vga_lastmodenumber() + +#define IS_IN_STANDARD_VGA_DRIVER(mode) ( \ + ((mode) < G640x480x256) || ((mode) == G720x348x2) || \ + ( ((mode) >= G400x300x256X) && ((mode) <= G400x300x256X) ) ) + + extern int vga_version; + + extern int vga_setmode(int mode); + extern int vga_hasmode(int mode); + extern int vga_setflipchar(int c); + + extern int vga_clear(void); + extern int vga_flip(void); + + extern int vga_getxdim(void); + extern int vga_getydim(void); + extern int vga_getcolors(void); + + extern int vga_setpalette(int index, int red, int green, int blue); + extern int vga_getpalette(int index, int *red, int *green, int *blue); + extern int vga_setpalvec(int start, int num, int *pal); + extern int vga_getpalvec(int start, int num, int *pal); + + extern int vga_screenoff(void); + extern int vga_screenon(void); + + extern int vga_setcolor(int color); + extern int vga_drawpixel(int x, int y); + extern int vga_drawline(int x1, int y1, int x2, int y2); + extern int vga_drawscanline(int line, unsigned char *colors); + extern int vga_drawscansegment(unsigned char *colors, int x, int y, int length); + extern int vga_getpixel(int x, int y); /* Added. */ + extern int vga_getscansegment(unsigned char *colors, int x, int y, int length); + + extern int vga_getch(void); + + extern int vga_dumpregs(void); + + +/* Extensions to VGAlib v1.2: */ + +/* blit flags */ +#define HAVE_BITBLIT 1 +#define HAVE_FILLBLIT 2 +#define HAVE_IMAGEBLIT 4 +#define HAVE_HLINELISTBLIT 8 +#define HAVE_BLITWAIT 16 + +/* other flags */ +#define HAVE_RWPAGE 1 /* vga_setreadpage() / vga_setwritepage() available */ +#define IS_INTERLACED 2 /* mode is interlaced */ +#define IS_MODEX 4 /* ModeX style 256 colors */ +#define IS_DYNAMICMODE 8 /* Dynamic defined mode */ +#define CAPABLE_LINEAR 16 /* Can go to linear addressing mode. */ +#define IS_LINEAR 32 /* Linear addressing has been set by vga_setlinearaddressing. */ +#define EXT_INFO_AVAILABLE 64 /* Returned modeinfo contains valid extended fields */ +#define RGB_MISORDERED 128 /* Mach32 32bpp uses 0BGR instead of BGR0. */ +#define HAVE_EXT_SET 256 /* vga_ext_set() available */ +#define LINEAR_CAN 512 /* Linear mode can be used (even if not set). */ +#define IOCTL_SETDISPLAY 1024 /* The card supports ioctl method for setting display + start at next vertical blank time */ +#define LINEAR_USE (IS_LINEAR|LINEAR_CAN) + + typedef struct { + int width; + int height; + int bytesperpixel; + int colors; + int linewidth; /* scanline width in bytes */ + int maxlogicalwidth; /* maximum logical scanline width */ + int startaddressrange; /* changeable bits set */ + int maxpixels; /* video memory / bytesperpixel */ + int haveblit; /* mask of blit functions available */ + int flags; /* other flags */ + + /* Extended fields: */ + + int chiptype; /* Chiptype detected */ + int memory; /* videomemory in KB */ + int linewidth_unit; /* Use only a multiple of this as parameter for set_logicalwidth and + set_displaystart */ + char *linear_aperture; /* points to mmap secondary mem aperture of card (NULL if unavailable) */ + int aperture_size; /* size of aperture in KB if size>=videomemory. 0 if unavail */ + void (*set_aperture_page) (int page); + /* if aperture_size= has bits set for mouse/keyboard events detected. + * mouse and raw keyboard events are already handled and their bits removed + * from *in when vga_waitevent returns. + * VGA_KEYEVENT relates to vga_getch NOT vga_getkey. + * return values < 0 signal errors. In this case check errno. + */ + +/* Background running */ +extern void vga_runinbackground(int stat, ...); +#define VGA_GOTOBACK -1 +#define VGA_COMEFROMBACK -2 +extern int vga_runinbackground_version(void); +extern void vga_waitvtactive(void); + +#ifdef _SVGALIB_LRMI +typedef struct { + int (*rm_init)(void); + int (*rm_call)(struct LRMI_regs *r); + int (*rm_int)(int interrupt, struct LRMI_regs *r); + void * (*rm_alloc_real)(int size); + void (*rm_free_real)(void *m); +} LRMI_callbacks; +extern int vga_set_LRMI_callbacks(LRMI_callbacks * LRMI); +#endif + +#ifdef __cplusplus +} + +#endif +#endif /* VGA_H */ diff --git a/include/vgajoystick.h b/include/vgajoystick.h new file mode 120000 index 0000000..547d39e --- /dev/null +++ b/include/vgajoystick.h @@ -0,0 +1 @@ +../src/joystick/vgajoystick.h \ No newline at end of file diff --git a/include/vgakeyboard.h b/include/vgakeyboard.h new file mode 120000 index 0000000..72afd95 --- /dev/null +++ b/include/vgakeyboard.h @@ -0,0 +1 @@ +../src/keyboard/vgakeyboard.h \ No newline at end of file diff --git a/include/vgamouse.h b/include/vgamouse.h new file mode 100644 index 0000000..1c58d4c --- /dev/null +++ b/include/vgamouse.h @@ -0,0 +1,186 @@ +/* Mouse interface for svgalib. */ +/* Can be used independently. */ + +#ifndef VGAMOUSE_H +#define VGAMOUSE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MOUSE_MICROSOFT 0 +#define MOUSE_MOUSESYSTEMS 1 +#define MOUSE_MMSERIES 2 +#define MOUSE_LOGITECH 3 +#define MOUSE_BUSMOUSE 4 +#define MOUSE_PS2 5 +#define MOUSE_LOGIMAN 6 +#define MOUSE_GPM 7 +#define MOUSE_SPACEBALL 8 +#define MOUSE_NONE 9 /* Some special number for a non supported/existing mouse */ +#define MOUSE_INTELLIMOUSE 10 +#define MOUSE_IMPS2 11 +#define MOUSE_PNP 12 +#define MOUSE_WACOM_GRAPHIRE 13 +#define MOUSE_DRMOUSE4DS 14 +#define MOUSE_EXPPS2 15 +#define MOUSE_LAST MOUSE_EXPPS2 + +#define MOUSE_ORIENTATION_VERTICAL 0 +#define MOUSE_ORIENTATION_HORIZONTAL 1 + +#define MOUSE_ACCEL_TYPE_NORMAL 1 +#define MOUSE_ACCEL_TYPE_POWER 2 + +#define DEFAULT_ACCEL_THRESH 5 +#define DEFAULT_ACCEL_POWER 1.2 +#define DEFAULT_ACCEL_OFFSET 1 +#define DEFAULT_ACCEL_MULT 10 +#define DEFAULT_MAXDELTA 0 +#define DEFAULT_ACCEL_MAXDELTA 0 +#define DEFAULT_ACCEL_TYPE 0 /* MOUSE_ACCEL_TYPE_POWER */ + +/* MS IntelliMouse has 18 steps, Logitech FirstMouse+ has 24 */ +#define DEFAULT_WHEEL_STEPS 18 +#define DEFAULT_WHEEL_DELTA (360 / DEFAULT_WHEEL_STEPS) + +/* Logical or the following values to one of the above at will and give that for + type in mouse_init (still they make only sense for serial mice) */ + +#define MOUSE_CHG_DTR 0x80000000 /* CLEAR (!) the DTR line */ +#define MOUSE_DTR_HIGH 0x40000000 /* when used with MOUSE_CHG_DTR set DTR not clear it */ +#define MOUSE_CHG_RTS 0x20000000 /* CLEAR (!) the RTS line */ +#define MOUSE_RTS_HIGH 0x10000000 /* when used with MOUSE_CHG_RTS set RTS not clear it */ + +/* If MOUSE_CHG_DTR is not given the DTR state is not touched.. same with RTS resp. */ +/* So I use MOUSE_MOUSESYSTEMS|MOUSE_CHG_RTS to force my + multiprotocol mouse to MOUSESYSTEMS and use init the driver to MOUSESYSTEMS */ + +#define MOUSE_TYPE_MASK 0xffff /* the upper 16bit are reserved for future flags */ + +#define MOUSE_LEFTBUTTON 4 +#define MOUSE_MIDDLEBUTTON 2 +#define MOUSE_RIGHTBUTTON 1 +#define MOUSE_FOURTHBUTTON 8 +#define MOUSE_FIFTHBUTTON 16 +#define MOUSE_SIXTHBUTTON 32 +#define MOUSE_RESETBUTTON 64 + +#define MOUSE_XDIM 1 +#define MOUSE_YDIM 2 +#define MOUSE_ZDIM 4 +#define MOUSE_RXDIM 8 +#define MOUSE_RYDIM 16 +#define MOUSE_RZDIM 32 +#define MOUSE_2DIM 3 +#define MOUSE_3DIM 7 +#define MOUSE_6DIM 63 + +#define MOUSE_DEFAULTSAMPLERATE 150 + +/* Initialize mouse device. Returns 0 if succesful, -1 otherwise. */ +/* (Get the svgalib configured type with vga_getmousetype()). */ + int mouse_init(char *dev, int type, int samplerate); +/* Similar but returns the mouse fd if succesful. */ + int mouse_init_return_fd(char *dev, int type, int samplerate); +/* Set event handler invoked by mouse_update(). */ +#if 0 /* This is the actual definition */ + typedef void (*__mouse_handler) (int button, int dx, int dy, int dz, + int drx, int dry, int drz); +#else /* For backwards compatibility with: + typedef void (*__mouse_handler) (int button, int dx, int dy) we use: */ + typedef void *__mouse_handler; +#endif + void mouse_seteventhandler(__mouse_handler handler); +/* Close mouse device. */ + void mouse_close(void); +/* Read mouse and handle events. Returns 0 if no event. */ + int mouse_update(void); +/* Similar to mouse_update, but wait for an event to happen. */ + void mouse_waitforupdate(void); + +/* mouse_init sets default event handler that keeps track of absolute */ +/* coordinates: */ + +#define MOUSE_NOWRAP 0 +#define MOUSE_WRAPX 1 +#define MOUSE_WRAPY 2 +#define MOUSE_WRAPZ 4 +#define MOUSE_WRAPRX 8 +#define MOUSE_WRAPRY 16 +#define MOUSE_WRAPRZ 32 +#define MOUSE_WRAP 63 +#define MOUSE_ROT_COORDS 196 +#define MOUSE_ROT_INFINITESIMAL 0 /* report changes in angle about axes */ +#define MOUSE_ROT_RX_RY_RZ 64 /* report angle about axes */ + +/* Warning! Next two not yet supported! */ +#define MOUSE_ROT_ZXZ 128 /* use x convention Euler angles */ +#define MOUSE_ROT_YPR 196 /* use yaw, pitch, and roll */ + +/* Revert to default handler. */ + void mouse_setdefaulteventhandler(void); +/* Set position of mouse. */ + void mouse_setposition(int x, int y); +/* Set position of mouse in all 6 dimensions. */ + void mouse_setposition_6d(int x, int y, int z, + int rx, int ry, int rz, int dim_mask); +/* Set horizontal range of mouse to [x1, x2] incl. */ + void mouse_setxrange(int x1, int x2); +/* Set vertical range of mouse to [y1, y2] incl. */ + void mouse_setyrange(int y1, int y2); +/* Set all ranges of mouse in 6 dimensions. */ + void mouse_setrange_6d(int x1, int x2, int y1, int y2, int z1, int z2, + int rx1, int rx2, int ry1, int ry2, int rz1, int rz2, int dim_mask); +/* Set scale factor by which raw mouse coordinates are divided. */ + void mouse_setscale(int s); +/* Enable/disable wrapping of mouse in horizontal and/or vertical range. */ + void mouse_setwrap(int w); + +/* Get current mouse x-coordinate. */ + int mouse_getx(void); +/* Get current mouse y-coordinate. */ + int mouse_gety(void); +/* Get position of mouse in all 6 dimensions. */ + void mouse_getposition_6d(int *x, int *y, int *z, + int *rx, int *ry, int *rz); +/* Get current mouse button status. */ + int mouse_getbutton(void); + + +#define MOUSE_CAPS 1024 +#define MOUSE_WANTCAPS 0x002b0042 +#define MOUSE_GOTCAPS 0x0042ffd4 + +#define MOUSE_INFO_WHEEL 0x00000001 /* The mouse has a wheel */ + + struct MouseCaps { + int key; /* MOUSE_GOTCAPS */ + int buttons; /* MOUSE_*BUTTON */ + int axes; /* MOUSE_*DIM */ + int info; /* MOUSE_INFO_* */ + int reserved0; /* Don't use these! */ + int reserved1; /* The names may change in the future... */ + }; + +/* Use this function to get information about the mouse without depending on + mouse types known when your app was made. The weirdness is so that you + don't need to depend on having svgalib 1.3.0; as long as you don't depend + on other features your app should be able to work with older versions too, + just without this info... In a future version this will be made a real + function. Returns 0 on success or -1 on failure. */ + + static inline int mouse_getcaps(struct MouseCaps *caps) + { + mouse_setposition_6d(MOUSE_WANTCAPS,0,0, 0,0,0, MOUSE_CAPS); + mouse_getposition_6d(&(caps->key), &(caps->buttons), &(caps->axes), + &(caps->info), &(caps->reserved0), &(caps->reserved1)); + return ((caps->key == MOUSE_GOTCAPS) ? (0) : (-1)); + } + +#ifdef __cplusplus +} + +#endif +#endif diff --git a/kernel/patch.mtrr.2.2.15 b/kernel/patch.mtrr.2.2.15 new file mode 100644 index 0000000..cf9335d --- /dev/null +++ b/kernel/patch.mtrr.2.2.15 @@ -0,0 +1,364 @@ +--- mtrr.c.orig Thu May 4 10:59:14 2000 ++++ linux/arch/i386/kernel/mtrr.c Thu May 4 11:06:10 2000 +@@ -464,11 +464,113 @@ + return 0; + } /* End Function have_wrcomb */ + ++static void intel_get_fixed_mtrr (unsigned int reg, unsigned long *base, ++ unsigned long *size, mtrr_type *type) ++{ ++ unsigned long lo, hi, calc_base, calc_size; ++ unsigned long msr_num; ++ ++ reg-=get_num_var_ranges(); ++ ++ if (reg>=NUM_FIXED_RANGES) { ++ /* Invalid num. */ ++ *base = 0; ++ *size = 0; ++ *type = 0; ++ return; ++ } ++ ++ switch(reg>>3){ ++ case 0: ++ msr_num=MTRRfix64K_00000_MSR; ++ calc_base=0; ++ calc_size=65536; ++ break; ++ case 1: ++ msr_num=MTRRfix16K_80000_MSR; ++ calc_base=0x80000; ++ calc_size=16384; ++ break; ++ case 2: ++ msr_num=MTRRfix16K_A0000_MSR; ++ calc_base=0xA0000; ++ calc_size=16384; ++ break; ++ case 3: ++ msr_num=MTRRfix4K_C0000_MSR; ++ calc_base=0xC0000; ++ calc_size=4096; ++ break; ++ case 4: ++ msr_num=MTRRfix4K_C8000_MSR; ++ calc_base=0xC8000; ++ calc_size=4096; ++ break; ++ case 5: ++ msr_num=MTRRfix4K_D0000_MSR; ++ calc_base=0xD0000; ++ calc_size=4096; ++ break; ++ case 6: ++ msr_num=MTRRfix4K_D8000_MSR; ++ calc_base=0xD8000; ++ calc_size=4096; ++ break; ++ case 7: ++ msr_num=MTRRfix4K_E0000_MSR; ++ calc_base=0xE0000; ++ calc_size=4096; ++ break; ++ case 8: ++ msr_num=MTRRfix4K_E8000_MSR; ++ calc_base=0xE8000; ++ calc_size=4096; ++ break; ++ case 9: ++ msr_num=MTRRfix4K_F0000_MSR; ++ calc_base=0xF0000; ++ calc_size=4096; ++ break; ++ case 10: ++ msr_num=MTRRfix4K_F8000_MSR; ++ calc_base=0xF8000; ++ calc_size=4096; ++ break; ++ default: ++ msr_num=0; ++ calc_base=0; ++ calc_size=0; ++ break; ++ }; ++ ++ if (msr_num==0) { ++ /* Invalid num. */ ++ *base = 0; ++ *size = 0; ++ *type = 0; ++ return; ++ } ++ ++ rdmsr(msr_num, lo, hi); ++ ++ if(reg&4)lo=hi; ++ lo>>=8*(reg&3); ++ ++ *type = (lo & 0xff); ++ *size=calc_size; ++ *base=calc_base+(reg&7)*calc_size; ++} ++ + static void intel_get_mtrr (unsigned int reg, unsigned long *base, + unsigned long *size, mtrr_type *type) + { + unsigned long dummy, mask_lo, base_lo; + ++ if(reg>=get_num_var_ranges()){ ++ intel_get_fixed_mtrr(reg,base,size,type); ++ return; ++ }; ++ + rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy); + if ((mask_lo & 0x800) == 0) { + /* Invalid (i.e. free) range. */ +@@ -614,6 +716,71 @@ + static void (*get_mtrr) (unsigned int reg, unsigned long *base, + unsigned long *size, mtrr_type *type) = NULL; + ++static int intel_set_fixed_mtrr (unsigned int reg, unsigned long base, ++ unsigned long size, mtrr_type type) ++/* currently, ignore size, only set the fixed mtrr that includes base */ ++{ ++ unsigned long lo, hi, mask, calc_size; ++ unsigned long msr_num, tmp_base; ++ int place; ++ ++ if((size==0)&&(base==0)&&(type==0)) { ++ int max=get_num_var_ranges (); ++ intel_get_fixed_mtrr(reg,&base,&size,&type); ++ if(reg=max+16)type=0; ++ }; ++ ++ if(size==0) { ++ size=0x1000; ++ type=0; ++ }; ++ ++ while(size>0) ++ { ++ if (base>=0x100000) return -EFAULT; ++ tmp_base = base >> 12 ; ++ ++ if(tmp_base<128) { ++ msr_num=MTRRfix64K_00000_MSR; ++ place=tmp_base>>4; ++ calc_size=65536; ++ } else ++ if(tmp_base<192) { ++ msr_num=MTRRfix16K_80000_MSR+(tmp_base>=160); ++ place=(tmp_base>>2)&7l; ++ calc_size=16384; ++ } else { ++ msr_num=MTRRfix4K_C0000_MSR+((tmp_base&0x3f)>>3); ++ place=tmp_base&7; ++ calc_size=4096; ++ }; ++ ++ rdmsr(msr_num, lo, hi); ++ ++ mask=0xff<<((place&3)<<3); ++ ++ if(place&4) { ++ hi&=~mask; ++ hi|=type<<((place&3)<<3); ++ } else { ++ lo &=~mask; ++ lo|=type<<(place<<3); ++ }; ++ ++ wrmsr(msr_num, lo, hi); ++ ++ if(size= MTRR_NUM_TYPES) +@@ -1126,6 +1291,11 @@ + printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base); + return -EINVAL; + } ++ if (base + size < 0x100000) ++ { ++ fixed=1; ++ i=get_num_var_ranges (); ++ }; + /* Fall through */ + case X86_VENDOR_CYRIX: + case X86_VENDOR_CENTAUR: +@@ -1142,7 +1312,7 @@ + return -EINVAL; + } + } +- else if (base + size < 0x100000) /* Cyrix */ ++ else if ((!fixed) && (base + size < 0x100000)) + { + printk ("mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n", + base, size); +@@ -1174,6 +1344,8 @@ + max = get_num_var_ranges (); + /* Search for existing MTRR */ + spin_lock_reschedule (&main_lock); ++ if(!fixed) ++ { + for (i = 0; i < max; ++i) + { + (*get_mtrr) (i, &lbase, &lsize, <ype); +@@ -1210,9 +1382,12 @@ + printk ("mtrr: no more MTRRs available\n"); + return i; + } ++ } + set_mtrr (i, base, size, type); ++ if(!fixed) ++ { + usage_table[i] = 1; +- compute_ascii (); ++ }; + spin_unlock (&main_lock); + return i; + } /* End Function mtrr_add */ +@@ -1274,7 +1449,6 @@ + return -EINVAL; + } + if (--usage_table[reg] < 1) set_mtrr (reg, 0, 0, 0); +- compute_ascii (); + spin_unlock (&main_lock); + return reg; + } /* End Function mtrr_del */ +@@ -1319,11 +1493,30 @@ + + static ssize_t mtrr_read (struct file *file, char *buf, size_t len, + loff_t *ppos) +-{ +- if (*ppos >= ascii_buf_bytes) return 0; ++{ int size; ++ ++ size=get_num_var_ranges()+NUM_FIXED_RANGES; ++ if ( ( ascii_buffer = kmalloc (size * LINE_SIZE, GFP_KERNEL) ) == NULL ) ++ { ++ printk ("mtrr: could not allocate\n"); ++ return 0; ++ } ++ ascii_buf_bytes = 0; ++ compute_ascii (); ++ ++ if (*ppos >= ascii_buf_bytes) ++ { ++ kfree(ascii_buffer); ++ return 0; ++ }; + if (*ppos + len > ascii_buf_bytes) len = ascii_buf_bytes - *ppos; +- if ( copy_to_user (buf, ascii_buffer + *ppos, len) ) return -EFAULT; ++ if ( copy_to_user (buf, ascii_buffer + *ppos, len) ) ++ { ++ kfree(ascii_buffer); ++ return -EFAULT; ++ }; + *ppos += len; ++ kfree(ascii_buffer); + return len; + } /* End Function mtrr_read */ + +@@ -1429,7 +1622,9 @@ + case MTRRIOC_GET_ENTRY: + if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) ) + return -EFAULT; ++#if 0 /* this should be done by the called function */ + if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL; ++#endif + (*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type); + gentry.type = type; + if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) ) +@@ -1542,6 +1737,19 @@ + "reg%02i: base=0x%08lx (%4liMB), size=%4li%cB: %s, count=%d\n", + i, base, base>>20, size, factor, + attrib_to_str (type), usage_table[i]); ++ ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes); ++ } ++ } ++ if(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) ++ for (i = max; i < max+NUM_FIXED_RANGES; i++) ++ { ++ (*get_mtrr) (i, &base, &size, &type); ++ if(((i=max+16)&&(type!=0))) ++ { ++ sprintf ++ (ascii_buffer + ascii_buf_bytes, ++ "reg%02i: base=0x%08lx (%4likB), size=%4likB: %s, count=%d\n", ++ i, base, base>>10, size>>10, attrib_to_str (type), 1); + ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes); + } + } diff --git a/kernel/patch.mtrr.2.3.99 b/kernel/patch.mtrr.2.3.99 new file mode 100644 index 0000000..4709da0 --- /dev/null +++ b/kernel/patch.mtrr.2.3.99 @@ -0,0 +1,289 @@ +--- mtrr.c.org Fri Apr 21 15:15:24 2000 ++++ mtrr.c Fri Apr 21 15:18:59 2000 +@@ -482,11 +482,113 @@ + return 0; + } /* End Function have_wrcomb */ + ++static void intel_get_fixed_mtrr (unsigned int reg, unsigned long *base, ++ unsigned long *size, mtrr_type *type) ++{ ++ unsigned long lo, hi, calc_base, calc_size; ++ unsigned long msr_num; ++ ++ reg-=get_num_var_ranges(); ++ ++ if (reg>=NUM_FIXED_RANGES) { ++ /* Invalid num. */ ++ *base = 0; ++ *size = 0; ++ *type = 0; ++ return; ++ } ++ ++ switch(reg>>3){ ++ case 0: ++ msr_num=MTRRfix64K_00000_MSR; ++ calc_base=0; ++ calc_size=65536; ++ break; ++ case 1: ++ msr_num=MTRRfix16K_80000_MSR; ++ calc_base=0x80000; ++ calc_size=16384; ++ break; ++ case 2: ++ msr_num=MTRRfix16K_A0000_MSR; ++ calc_base=0xA0000; ++ calc_size=16384; ++ break; ++ case 3: ++ msr_num=MTRRfix4K_C0000_MSR; ++ calc_base=0xC0000; ++ calc_size=4096; ++ break; ++ case 4: ++ msr_num=MTRRfix4K_C8000_MSR; ++ calc_base=0xC8000; ++ calc_size=4096; ++ break; ++ case 5: ++ msr_num=MTRRfix4K_D0000_MSR; ++ calc_base=0xD0000; ++ calc_size=4096; ++ break; ++ case 6: ++ msr_num=MTRRfix4K_D8000_MSR; ++ calc_base=0xD8000; ++ calc_size=4096; ++ break; ++ case 7: ++ msr_num=MTRRfix4K_E0000_MSR; ++ calc_base=0xE0000; ++ calc_size=4096; ++ break; ++ case 8: ++ msr_num=MTRRfix4K_E8000_MSR; ++ calc_base=0xE8000; ++ calc_size=4096; ++ break; ++ case 9: ++ msr_num=MTRRfix4K_F0000_MSR; ++ calc_base=0xF0000; ++ calc_size=4096; ++ break; ++ case 10: ++ msr_num=MTRRfix4K_F8000_MSR; ++ calc_base=0xF8000; ++ calc_size=4096; ++ break; ++ default: ++ msr_num=0; ++ calc_base=0; ++ calc_size=0; ++ break; ++ }; ++ ++ if (msr_num==0) { ++ /* Invalid num. */ ++ *base = 0; ++ *size = 0; ++ *type = 0; ++ return; ++ } ++ ++ rdmsr(msr_num, lo, hi); ++ ++ if(reg&4)lo=hi; ++ lo>>=8*(reg&3); ++ ++ *type = (lo & 0xff); ++ *size=calc_size; ++ *base=calc_base+(reg&7)*calc_size; ++} ++ + static void intel_get_mtrr (unsigned int reg, unsigned long *base, + unsigned long *size, mtrr_type *type) + { + unsigned long dummy, mask_lo, base_lo; + ++ if(reg>=get_num_var_ranges()){ ++ intel_get_fixed_mtrr(reg,base,size,type); ++ return; ++ }; ++ + rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy); + if ( (mask_lo & 0x800) == 0 ) + { +@@ -624,6 +726,71 @@ + static void (*get_mtrr) (unsigned int reg, unsigned long *base, + unsigned long *size, mtrr_type *type) = NULL; + ++static int intel_set_fixed_mtrr (unsigned int reg, unsigned long base, ++ unsigned long size, mtrr_type type) ++/* currently, ignore size, only set the fixed mtrr that includes base */ ++{ ++ unsigned long lo, hi, mask, calc_size; ++ unsigned long msr_num, tmp_base; ++ int place; ++ ++ if((size==0)&&(base==0)&&(type==0)) { ++ int max=get_num_var_ranges (); ++ intel_get_fixed_mtrr(reg,&base,&size,&type); ++ if(reg=max+16)type=0; ++ }; ++ ++ if(size==0) { ++ size=0x1000; ++ type=0; ++ }; ++ ++ while(size>0) ++ { ++ if (base>=0x100000) return -EFAULT; ++ tmp_base = base >> 12 ; ++ ++ if(tmp_base<128) { ++ msr_num=MTRRfix64K_00000_MSR; ++ place=tmp_base>>4; ++ calc_size=65536; ++ } else ++ if(tmp_base<192) { ++ msr_num=MTRRfix16K_80000_MSR+(tmp_base>=160); ++ place=(tmp_base>>2)&7l; ++ calc_size=16384; ++ } else { ++ msr_num=MTRRfix4K_C0000_MSR+((tmp_base&0x3f)>>3); ++ place=tmp_base&7; ++ calc_size=4096; ++ }; ++ ++ rdmsr(msr_num, lo, hi); ++ ++ mask=0xff<<((place&3)<<3); ++ ++ if(place&4) { ++ hi&=~mask; ++ hi|=type<<((place&3)<<3); ++ } else { ++ lo &=~mask; ++ lo|=type<<(place<<3); ++ }; ++ ++ wrmsr(msr_num, lo, hi); ++ ++ if(size= get_num_var_ranges () ) return -EINVAL; ++*/ + (*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type); + gentry.type = type; + if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) ) +@@ -1597,6 +1781,19 @@ + ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes); + } + } ++ if(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) ++ for (i = max; i < max+NUM_FIXED_RANGES; i++) ++ { ++ (*get_mtrr) (i, &base, &size, &type); ++ if(((i=max+16)&&(type!=0))) ++ { ++ sprintf ++ (ascii_buffer + ascii_buf_bytes, ++ "reg%02i: base=0x%08lx (%4likB), size=%4likB: %s, count=%d\n", ++ i, base, base>>10, size>>10, attrib_to_str (type), 1); ++ ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes); ++ } ++ } + devfs_set_file_size (devfs_handle, ascii_buf_bytes); + # ifdef CONFIG_PROC_FS + proc_root_mtrr->size = ascii_buf_bytes; diff --git a/kernel/svgalib_helper/Makefile b/kernel/svgalib_helper/Makefile new file mode 100644 index 0000000..f81511e --- /dev/null +++ b/kernel/svgalib_helper/Makefile @@ -0,0 +1,66 @@ + +SVGALIB_HELPER_MAJOR=209 + +svgalib_helper-objs := main.o i810.o interrupt.o virtual.o displaystart.o +obj-m := svgalib_helper.o + +ifneq ($(KERNELRELEASE),) + + VER ?= $(KERNELRELEASE) + KDIR := /lib/modules/$(VER)/build + PWD := $(shell pwd) + TARGET := svgalib_helper + + ifeq ($(PATCHLEVEL),4) + include $(TOPDIR)/Rules.make + endif + +else + + VER ?= $(shell uname -r) + KDIR := /lib/modules/$(VER)/build + PWD := $(shell pwd) + TARGET := svgalib_helper + +endif + + +CLASS_SIMPLE := $(shell grep class_simple_create $(KDIR)/include/linux/device.h) + +ifneq ($(CLASS_SIMPLE),) + CLASS_CFLAGS = -DCLASS_SIMPLE=1 +endif + +EXTRA_CFLAGS := -DSVGALIB_HELPER_MAJOR=$(SVGALIB_HELPER_MAJOR) $(CLASS_CFLAGS) + + +default: + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) CLASS_CFLAGS=$(CLASS_CFLAGS) modules + +depend: + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) depend + + +clean: + rm -f svgalib_helper.{o,ko,mod.{o,c}} .*.{cmd,flags} + rm -f *.o *~ core .depend *.bak *.orig + rm -fr .tmp_versions + +svgalib_helper.o: $(svgalib_helper-objs) + $(LD) -r -o $@ $(svgalib_helper-objs) + +device: + rm -f /dev/svga /dev/svga? + mknod -m 666 /dev/svga c $(SVGALIB_HELPER_MAJOR) 0 + mknod -m 666 /dev/svga1 c $(SVGALIB_HELPER_MAJOR) 1 + mknod -m 666 /dev/svga2 c $(SVGALIB_HELPER_MAJOR) 2 + mknod -m 666 /dev/svga3 c $(SVGALIB_HELPER_MAJOR) 3 + mknod -m 666 /dev/svga4 c $(SVGALIB_HELPER_MAJOR) 4 + +install: device modules_install + +modules_install: $(MODNAME) + mkdir -p /lib/modules/$(VER)/kernel/misc + install -m 0644 -c $(TARGET).ko /lib/modules/$(VER)/kernel/misc || install -m 0644 -c $(TARGET).o /lib/modules/$(VER)/kernel/misc + depmod -a $(VER) + diff --git a/kernel/svgalib_helper/Makefile.alt b/kernel/svgalib_helper/Makefile.alt new file mode 100644 index 0000000..c78c169 --- /dev/null +++ b/kernel/svgalib_helper/Makefile.alt @@ -0,0 +1,84 @@ +include ../../Makefile.cfg + + +ifndef INCLUDEDIR +INCLUDEDIR = /lib/modules/$(shell uname -r)/build/include +endif + +MODVER = $(shell grep CONFIG_MODVERSIONS $(INCLUDEDIR)/linux/autoconf.h) + +ifeq ($(MODVER),) + @echo INCLUDEDIR is not set up correctly + exit 1 +endif + +# Extract version number from headers. +VER = $(shell awk -F\" '/REL/ {print $$2}' $(INCLUDEDIR)/linux/version.h 2>/dev/null) + +# Use version of current running kernel +ifeq ($(VER),) + VER = $(shell uname -r) +endif + +VER_MAJOR = $(shell echo $(VER) | cut -d. -f1) +VER_MINOR = $(shell echo $(VER) | cut -d. -f2) + +INCLUDES += -I$(INCLUDEDIR) +INCLUDES += -I$(INCLUDEDIR)/asm/mach-default + +CFLAGS = -O2 -DLINUX -Dlinux -D__KERNEL__ -DMODULE $(DEBFLAGS) +ifeq (2,$(VER_MAJOR)) + ifeq (6,$(VER_MINOR)) + CFLAGS += -DKBUILD_MODNAME="svgalib_helper" + endif +endif + +CFLAGS += $(INCLUDES) +CFLAGS += -DSVGALIB_HELPER_MAJOR=$(SVGALIB_HELPER_MAJOR) + +ifeq (1,$(findstring 1,$(MODVER))) + CFLAGS += -DMODVERSIONS -include $(INCLUDEDIR)/linux/modversions.h +endif + +TARGET = svgalib_helper +OBJS = $(TARGET).o +SRC = main.c interrupt.c i810.c virtual.c displaystart.c + +ifeq (2,$(VER_MAJOR)) + ifeq (6,$(VER_MINOR)) + OBJS = $(TARGET).ko + endif +endif + +all: .depend $(OBJS) + +$(TARGET).o: $(SRC:.c=.o) + $(LD) -r $^ -o $@ + +$(TARGET).ko: $(TARGET).o + $(LD) -d -r $^ -o $@ + +install: device modules_install + +modules_install: $(OBJS) + mkdir -p /lib/modules/$(VER)/kernel/misc + install -m 0644 -c $(OBJS) /lib/modules/$(VER)/kernel/misc + +device: + rm -f /dev/svgalib_helper* /dev/svga_helper* /dev/svga /dev/svga? + mknod -m 666 /dev/svga c $(SVGALIB_HELPER_MAJOR) 0 + mknod -m 666 /dev/svga1 c $(SVGALIB_HELPER_MAJOR) 1 + mknod -m 666 /dev/svga2 c $(SVGALIB_HELPER_MAJOR) 2 + mknod -m 666 /dev/svga3 c $(SVGALIB_HELPER_MAJOR) 3 + mknod -m 666 /dev/svga4 c $(SVGALIB_HELPER_MAJOR) 4 + +clean: + rm -f *.ko *.o *~ core .depend *.bak *.orig + +depend .depend dep: + $(CC) $(CFLAGS) -M *.c > $@ + + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/kernel/svgalib_helper/displaystart.c b/kernel/svgalib_helper/displaystart.c new file mode 100644 index 0000000..0ef78f1 --- /dev/null +++ b/kernel/svgalib_helper/displaystart.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include "kernel26compat.h" +#include "svgalib_helper.h" + +#ifndef NO_TASK +void set_displaystart(struct sh_pci_device *dev) { + int i, id; + long ad; + + switch(dev->vendor) { + case PCI_VENDOR_ID_MATROX: + ad=dev->startad>>3; + writeb(0x0c, dev->membase+0x3D4); + writeb((ad & 0xFF00)>>8, dev->membase+0x3D5); + writeb(0x0d, dev->membase+0x3D4); + writeb(ad & 0xFF, dev->membase+0x3D5); + writeb(0x00, dev->membase+0x3DE); + i=readb(dev->membase+0x3DF) & 0xb0; + i|=(ad & 0xf0000)>>16; + i|=(ad & 0x100000)>>14; + writeb(i, dev->membase+0x3DF); + break; +#if 0 + case PCI_VENDOR_ID_SI: /* SiS */ + dev->iobase = dev->mem[2]-0x380; + dev->test_vsync = io_test_vsync; + dev->ack_vsync = io_ack_vsync; + dev->enable_vsync = io_enable_vsync; + break; +#endif + case PCI_VENDOR_ID_NVIDIA_SGS: + if(dev->id<0x20) { + ad=dev->startad>>2; + writeb(0x0c, dev->membase+0x6013D4); + writeb((ad & 0xFF00)>>8, dev->membase+0x6013D5); + writeb(0x0d, dev->membase+0x6013D4); + writeb(ad & 0xFF, dev->membase+0x6013D5); + + writeb(0x19, dev->membase+0x6013D4); + i=readb(dev->membase+0x6013D5) & 0xe0; + i|=(ad & 0x1f0000)>>16; + writeb(i, dev->membase+0x6013D5); + + writeb(0x2D, dev->membase+0x6013D4); + i=readb(dev->membase+0x6013D5) & 0x9f; + i|=(ad & 0x600000)>>16; + writeb(i, dev->membase+0x6013D5); + } else { + } + break; +#if 0 + case PCI_VENDOR_ID_NVIDIA: + dev->iobase = (unsigned long)ioremap(dev->mem[0],0x800000); + dev->test_vsync = nv4_test_vsync; + dev->ack_vsync = nv4_ack_vsync; + dev->enable_vsync = nv4_enable_vsync; + break; + case PCI_VENDOR_ID_ATI: + id=dev->id; + + if( (id==0x4c45) || + (id==0x4c46) || + (id==0x4c57) || + (id==0x4c59) || + (id==0x4c5a) || + (id==0x4d46) || + (id==0x4d4c) || + (id==0x4242) || + ((id>>8)==0x50) || + ((id>>8)==0x51) || + ((id>>8)==0x52) || + ((id>>8)==0x53) || + ((id>>8)==0x54)) { + dev->iobase = (unsigned long)ioremap(dev->mem[2], 16384); + dev->test_vsync = r128_test_vsync; + dev->ack_vsync = r128_ack_vsync; + dev->enable_vsync = r128_enable_vsync; + } else { + dev->iobase = dev->mem[1]; + dev->test_vsync = rage_test_vsync; + dev->ack_vsync = rage_ack_vsync; + dev->enable_vsync = rage_enable_vsync; + } + break; + case PCI_VENDOR_ID_RENDITION: + dev->iobase = dev->mem[1]; + dev->test_vsync = rendition_test_vsync; + dev->ack_vsync = rendition_ack_vsync; + dev->enable_vsync = rendition_enable_vsync; + break; + case PCI_VENDOR_ID_S3: + dev->iobase = (unsigned long)ioremap(dev->mem[0]+0x1000000, 0x10000); + dev->test_vsync = s3_test_vsync; + dev->ack_vsync = s3_ack_vsync; + dev->enable_vsync = s3_enable_vsync; + break; + default: + dev->test_vsync = vga_test_vsync; + dev->ack_vsync = vga_ack_vsync; + dev->enable_vsync = vga_enable_vsync; + dev->iobase = 0; +#endif + } + +} +#endif diff --git a/kernel/svgalib_helper/displaystart.h b/kernel/svgalib_helper/displaystart.h new file mode 100644 index 0000000..eddd702 --- /dev/null +++ b/kernel/svgalib_helper/displaystart.h @@ -0,0 +1,2 @@ +void set_displaystart(struct sh_pci_device *); + diff --git a/kernel/svgalib_helper/dkms.conf b/kernel/svgalib_helper/dkms.conf new file mode 100644 index 0000000..59be111 --- /dev/null +++ b/kernel/svgalib_helper/dkms.conf @@ -0,0 +1,9 @@ +MAKE="make" +DEST_MODULE_LOCATION="/kernel/misc" +CLEAN="make clean" +MODULE_NAME="svgalib_helper.o" + +BUILT_MODULE_NAME="svgalib_helper" +PACKAGE_NAME="svgalib_helper" +PACKAGE_VERSION="1.9.25" +AUTOINSTALL="yes" diff --git a/kernel/svgalib_helper/i810.c b/kernel/svgalib_helper/i810.c new file mode 100644 index 0000000..ddffee6 --- /dev/null +++ b/kernel/svgalib_helper/i810.c @@ -0,0 +1,66 @@ +/* vram size in pages */ + +#ifdef __386__ + +#include +#include +#include /* cli(), *_flags */ +#include /* memcpy and such */ +#include +#include + +#define I810_SIZE 1024 + +unsigned long i810_alloc_page() +{ + unsigned long address; + + address = __get_free_page(GFP_KERNEL); + if(address == 0UL) + return 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + atomic_inc(&virt_to_page(address)->count); + set_bit(PG_locked, &virt_to_page(address)->flags); +#endif + return address; +} + +#if 0 +static void i810_free_page(unsigned long page) +{ + if(page == 0UL) + return; + + atomic_dec(&virt_to_page(page)->count); + clear_bit(PG_locked, &virt_to_page(page)->flags); + wake_up(&virt_to_page(page)->wait); + free_page(page); + return; +} +#endif + +static unsigned long i810_pages[I810_SIZE]; +unsigned long i810_gttes[I810_SIZE]; +static unsigned long i810_gttpage=0; + +unsigned int i810_make_gtt() { + int i; + + if(i810_gttpage) return virt_to_bus((void *)i810_gttpage); + + i810_gttpage=i810_alloc_page(); + + for(i=0;i +#include +#include +#include "kernel26compat.h" +#include "svgalib_helper.h" + +int vga_test_vsync(struct sh_pci_device *dev) { + return inb(0x3c2)&0x80; +} + +void vga_ack_vsync(struct sh_pci_device *dev) { + int pb; + +/* clear pending */ + outb(0x11, 0x3d4); + pb = inb(0x3d5); + outb(0x11, 0x3d4); + outb((pb&0xef) | 0x20, 0x3d5); + +/* disable interrupts */ + outb(0x11, 0x3d4); + pb = inb(0x3d5); + outb(0x11, 0x3d4); + outb(pb | 0x20 , 0x3d5); +} + +void vga_enable_vsync(struct sh_pci_device *dev) { + int pb; + +/* enable interrupt, clear pending */ + outb(0x11, 0x3d4); + pb = inb(0x3d5); + outb(0x11, 0x3d4); + outb((pb&0xcf) , 0x3d5); + +/* Allow interrupts */ + outb(0x11, 0x3d4); + pb = inb(0x3d5); + outb(0x11, 0x3d4); + outb(pb | 0x10 , 0x3d5); +} + +int io_test_vsync(struct sh_pci_device *dev) { + return inb(dev->iobase+0x3c2)&0x80; +} + +void io_ack_vsync(struct sh_pci_device *dev) { + int pb; + +/* clear pending */ + outb(0x11, dev->iobase+0x3d4); + pb = inb(dev->iobase+0x3d5); + outb(0x11, dev->iobase+0x3d4); + outb((pb&0xef) | 0x20, dev->iobase+0x3d5); + +/* disable interrupts */ + outb(0x11, dev->iobase+0x3d4); + pb = inb(dev->iobase+0x3d5); + outb(0x11, dev->iobase+0x3d4); + outb(pb | 0x20 , dev->iobase+0x3d5); +} + +void io_enable_vsync(struct sh_pci_device *dev) { + int pb; + +/* enable interrupt, clear pending */ + outb(0x11, dev->iobase+0x3d4); + pb = inb(dev->iobase+0x3d5); + outb(0x11, dev->iobase+0x3d4); + outb((pb&0xcf) , dev->iobase+0x3d5); + +/* Allow interrupts */ + outb(0x11, dev->iobase+0x3d4); + pb = inb(dev->iobase+0x3d5); + outb(0x11, dev->iobase+0x3d4); + outb(pb | 0x10 , dev->iobase+0x3d5); +} + +int mm_test_vsync(struct sh_pci_device *dev) { + return readb(dev->membase+0x3c2)&0x80; +} + +void mm_ack_vsync(struct sh_pci_device *dev) { + int pb; + +/* clear pending */ + writeb(0x11, dev->membase+0x3d4); + pb = readb(dev->membase+0x3d5); + writeb(0x11, dev->membase+0x3d4); + writeb((pb&0xef) | 0x20, dev->membase+0x3d5); + +/* disable interrupts */ + writeb(0x11, dev->membase+0x3d4); + pb = readb(dev->membase+0x3d5); + writeb(0x11, dev->membase+0x3d4); + writeb(pb | 0x20 , dev->membase+0x3d5); +} + +void mm_enable_vsync(struct sh_pci_device *dev) { + int pb; + +/* enable interrupt, clear pending */ + writeb(0x11, dev->membase+0x3d4); + pb = readb(dev->membase+0x3d5); + writeb(0x11, dev->membase+0x3d4); + writeb((pb&0xcf) , dev->membase+0x3d5); + +/* Allow interrupts */ + writeb(0x11, dev->membase+0x3d4); + pb = readb(dev->membase+0x3d5); + writeb(0x11, dev->membase+0x3d4); + writeb(pb | 0x10 , dev->membase+0x3d5); +} + +int s3_test_vsync(struct sh_pci_device *dev) { + return readl(dev->membase+0x8504) & 1; +} + +void s3_enable_vsync(struct sh_pci_device *dev) { + writel(0x101, dev->membase+0x8504); +} + +void s3_ack_vsync(struct sh_pci_device *dev) { + writel(0x001, dev->membase+0x8504); +} + +static uint32_t saved_pmc=0xffffffff; + +int nv3_test_vsync(struct sh_pci_device *dev) { + return readl(dev->membase+0x400100)&0x100; +} + +void nv3_ack_vsync(struct sh_pci_device *dev) { + +/* disable interrupt, clear pending */ + writel(0xffffffff, dev->membase + 0x000100); + writel(0x100, dev->membase + 0x400100); + writel(0, dev->membase + 0x000140); + writel(0, dev->membase + 0x400140); + if(saved_pmc!=0xffffffff) + writel(saved_pmc, dev->membase + 0x000200); + +} + +void nv3_enable_vsync(struct sh_pci_device *dev) { + saved_pmc = inl(dev->iobase + 0x200); + writel(saved_pmc|0x1000, dev->membase+0x200); + writel(0x1, dev->membase + 0x000140); + writel(0x100, dev->membase + 0x400140); + writel(0xffffffff, dev->membase + 0x000100); + writel(0xffffffff, dev->membase + 0x400100); +} + +int nv4_test_vsync(struct sh_pci_device *dev) { + return readl(dev->membase+0x600100)&0x1; +} + +void nv4_ack_vsync(struct sh_pci_device *dev) { + +/* disable interrupt, clear pending */ + writel(0xffffffff, dev->membase + 0x000100); + writel(0x1, dev->membase + 0x600100); + writel(0, dev->membase + 0x000140); + writel(0, dev->membase + 0x600140); + writel(saved_pmc, dev->membase + 0x000200); +} + +void nv4_enable_vsync(struct sh_pci_device *dev) { + saved_pmc = inl(dev->iobase + 0x200); + writel(saved_pmc|(1<<24),dev->membase+0x200); + writel(0x1, dev->membase + 0x000140); + writel(0x1, dev->membase + 0x600140); + writel(0xffffffff, dev->membase + 0x000100); + writel(0xffffffff, dev->membase + 0x600100); +} + +int r128_test_vsync(struct sh_pci_device *dev) { + return readl(dev->membase + 0x44) &1; +} + +void r128_ack_vsync(struct sh_pci_device *dev) { + writel(1, dev->membase + 0x44); + writel(readl(dev->membase + 0x40) & 0xfffffffe, dev->membase + 0x40); +} + +void r128_enable_vsync(struct sh_pci_device *dev) { + writel(1, dev->membase + 0x44); + writel(readl(dev->membase + 0x40) | 1, dev->membase + 0x40); +} + +int rage_test_vsync(struct sh_pci_device *dev) { + return inl(dev->iobase + 0x18) &4; +} + +void rage_ack_vsync(struct sh_pci_device *dev) { + outl((inl(dev->iobase + 0x18) & 0xfffffff8) | 12, dev->iobase + 0x18); +} + +void rage_enable_vsync(struct sh_pci_device *dev) { + outl((inl(dev->iobase + 0x18) & 0xfffffff8) | 14, dev->iobase + 0x18); +} + +int rendition_test_vsync(struct sh_pci_device *dev) { + return inw(dev->iobase + 0x44) & 1; +} + +void rendition_ack_vsync(struct sh_pci_device *dev) { + outw(1, dev->iobase + 0x44); + outw(0, dev->iobase + 0x46); +} + +void rendition_enable_vsync(struct sh_pci_device *dev) { + outw(1, dev->iobase + 0x44); + outw(1, dev->iobase + 0x46); +} + +void vga_init_vsync(struct sh_pci_device *dev) { + int i, id; + switch(dev->vendor) { + case PCI_VENDOR_ID_MATROX: + i=0; + if(dev->len[0]>=1048576)i=1; + dev->membase = ioremap(dev->mem[i],0x2000) + 0x1c00; + dev->test_vsync = mm_test_vsync; + dev->ack_vsync = mm_ack_vsync; + dev->enable_vsync = mm_enable_vsync; + dev->disable_vsync = mm_ack_vsync; + break; + case PCI_VENDOR_ID_SI: /* SiS */ + dev->iobase = dev->mem[2]-0x380; + dev->test_vsync = io_test_vsync; + dev->ack_vsync = io_ack_vsync; + dev->enable_vsync = io_enable_vsync; + dev->disable_vsync = io_ack_vsync; + break; + case PCI_VENDOR_ID_NVIDIA_SGS: + dev->membase = ioremap(dev->mem[0],0x800000); + if(dev->id<0x20) { + dev->test_vsync = nv3_test_vsync; + dev->ack_vsync = nv3_ack_vsync; + dev->enable_vsync = nv3_enable_vsync; + dev->disable_vsync = nv3_ack_vsync; + } else { + dev->test_vsync = nv4_test_vsync; + dev->ack_vsync = nv4_ack_vsync; + dev->enable_vsync = nv4_enable_vsync; + dev->disable_vsync = nv4_ack_vsync; + } + break; + case PCI_VENDOR_ID_NVIDIA: + dev->membase = ioremap(dev->mem[0],0x800000); + dev->test_vsync = nv4_test_vsync; + dev->ack_vsync = nv4_ack_vsync; + dev->enable_vsync = nv4_enable_vsync; + dev->disable_vsync = nv4_ack_vsync; + break; + case PCI_VENDOR_ID_ATI: + id=dev->id; + + if( (id==0x4c45) || + (id==0x4c46) || + (id==0x4c57) || + (id==0x4c59) || + (id==0x4c5a) || + (id==0x4d46) || + (id==0x4d4c) || + (id==0x4242) || + ((id>>8)==0x50) || + ((id>>8)==0x51) || + ((id>>8)==0x52) || + ((id>>8)==0x53) || + ((id>>8)==0x54)) { + dev->membase = ioremap(dev->mem[2], 16384); + dev->test_vsync = r128_test_vsync; + dev->ack_vsync = r128_ack_vsync; + dev->enable_vsync = r128_enable_vsync; + dev->disable_vsync = r128_ack_vsync; + } else { + dev->iobase = dev->mem[1]; + dev->test_vsync = rage_test_vsync; + dev->ack_vsync = rage_ack_vsync; + dev->enable_vsync = rage_enable_vsync; + dev->disable_vsync = rage_ack_vsync; + } + break; + case PCI_VENDOR_ID_RENDITION: + dev->iobase = dev->mem[1]; + dev->test_vsync = rendition_test_vsync; + dev->ack_vsync = rendition_ack_vsync; + dev->enable_vsync = rendition_enable_vsync; + dev->disable_vsync = rendition_ack_vsync; + break; + case PCI_VENDOR_ID_S3: + dev->membase = ioremap(dev->mem[0]+0x1000000, 0x10000); + dev->test_vsync = s3_test_vsync; + dev->ack_vsync = s3_ack_vsync; + dev->enable_vsync = s3_enable_vsync; + dev->disable_vsync = s3_ack_vsync; + break; + default: + dev->test_vsync = vga_test_vsync; + dev->ack_vsync = vga_ack_vsync; + dev->enable_vsync = vga_enable_vsync; + dev->disable_vsync = vga_ack_vsync; + dev->iobase = 0; + } + +} + diff --git a/kernel/svgalib_helper/interrupt.h b/kernel/svgalib_helper/interrupt.h new file mode 100644 index 0000000..5626c93 --- /dev/null +++ b/kernel/svgalib_helper/interrupt.h @@ -0,0 +1,5 @@ +void vga_init_vsync(struct sh_pci_device *); +int vga_test_vsync(struct sh_pci_device *); +void vga_ack_vsync(struct sh_pci_device *); +void vga_enable_vsync(struct sh_pci_device *); + diff --git a/kernel/svgalib_helper/kernel26compat.h b/kernel/svgalib_helper/kernel26compat.h new file mode 100644 index 0000000..01c3ab7 --- /dev/null +++ b/kernel/svgalib_helper/kernel26compat.h @@ -0,0 +1,163 @@ +#ifndef KERNEL_VERSION +# include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + +# ifdef KERNEL_2_6 +# undef KERNEL_2_6 +# endif + +# define PCI_GET_CLASS pci_find_class +# define PCI_GET_DEVICE pci_find_device + +# if defined (PG_chainlock) +# define my_io_remap_page_range(vma, start, ofs, len, prot) \ + io_remap_page_range(vma,start,ofs,len,prot) +# else +# ifdef __alpha__ /* Is alpha really the issue here ??? */ +# define my_io_remap_page_range(vma, start, ofs, len, prot) \ + remap_page_range(start,ofs,len,prot) +# else +# define my_io_remap_page_range(vma, start, ofs, len, prot) \ + io_remap_page_range(start,ofs,len,prot) +# endif +# endif +# ifndef IRQ_HANDLED +typedef void irqreturn_t; +# define IRQ_NONE +# define IRQ_HANDLED +# endif + +#else /* Kernel 2.6 */ + +#define NO_TASK + +# ifndef KERNEL_2_6 +# define KERNEL_2_6 +# endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +# undef MODULE_PARM +# define MODULE_PARM(x,y) module_param(x, int, 0) +#endif + +/* WHY ? */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +# define PCI_GET_CLASS pci_find_class +# define PCI_GET_DEVICE pci_find_device +# define DEVFS_MK_SYMLINK(a,b) devfs_mk_symlink(a,b) +#else +# define PCI_GET_CLASS pci_get_class +# define PCI_GET_DEVICE pci_get_device +# define DEVFS_MK_SYMLINK(a,b) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) +# define io_remap_page_range(vma, vaddr, paddr, size, prot) \ + remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot) +#endif + +# define my_io_remap_page_range(vma, start, ofs, len, prot) \ + io_remap_page_range(vma,start,ofs,len,prot) + +# define pci_present() 1 + +# ifdef CONFIG_DEVFS_FS +typedef void* devfs_handle_t; +# endif + +#endif + +/* These are also not present in 2.6 kernels ... */ +#if (!defined _LINUX_DEVFS_FS_KERNEL_H) || (defined KERNEL_2_6) +static inline int devfs_register_chrdev (unsigned int major, const char *name, + struct file_operations *fops) +{ + return register_chrdev (major, name, fops); +} +static inline int devfs_unregister_chrdev (unsigned int major,const char *name) +{ + return unregister_chrdev (major, name); +} +#endif + +#if defined(KERNEL_2_6) && !defined(CONFIG_DEVFS_FS) + +# if !defined(CLASS_SIMPLE) /* no class_simple */ + +# define K_CLASS class +# define SLH_SYSFS_REGISTER \ + svgalib_helper_class = class_create(THIS_MODULE, "svgalib_helper"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +# define SLH_SYSFS_ADD_CONTROL \ + class_device_create(svgalib_helper_class, \ + MKDEV(SVGALIB_HELPER_MAJOR, 0), \ + NULL, "svga"); + +# define SLH_SYSFS_ADD_DEVICE(_name, _minor) \ + class_device_create(svgalib_helper_class, \ + MKDEV(SVGALIB_HELPER_MAJOR, _minor), \ + &sh_pci_devs[_minor]->dev->dev, _name); +#else /* 2.6.15 changed class_device_create */ +# define SLH_SYSFS_ADD_CONTROL \ + class_device_create(svgalib_helper_class, NULL, \ + MKDEV(SVGALIB_HELPER_MAJOR, 0), \ + NULL, "svga"); + +# define SLH_SYSFS_ADD_DEVICE(_name, _minor) \ + class_device_create(svgalib_helper_class, NULL, \ + MKDEV(SVGALIB_HELPER_MAJOR, _minor), \ + &sh_pci_devs[_minor]->dev->dev, _name); +#endif /* 2.6.15 */ + +# define SLH_SYSFS_REMOVE_DEVICE(i) \ + class_destroy(svgalib_helper_class); + +# define SLH_SYSFS_UNREGISTER \ + class_destroy(svgalib_helper_class); + +# else /* class_simple */ + +# define K_CLASS class_simple +# define SLH_SYSFS_REGISTER \ + svgalib_helper_class = class_simple_create(THIS_MODULE, "svgalib_helper"); + +# define SLH_SYSFS_ADD_CONTROL \ + class_simple_device_add(svgalib_helper_class, \ + MKDEV(SVGALIB_HELPER_MAJOR, 0), \ + NULL, "svga"); + +# define SLH_SYSFS_ADD_DEVICE(_name, _minor) \ + class_simple_device_add(svgalib_helper_class, \ + MKDEV(SVGALIB_HELPER_MAJOR, _minor), \ + &sh_pci_devs[_minor]->dev->dev, _name); + +# define SLH_SYSFS_REMOVE_DEVICE(i) \ + class_simple_device_remove(MKDEV(SVGALIB_HELPER_MAJOR, i)); + +# define SLH_SYSFS_UNREGISTER \ + class_simple_destroy(svgalib_helper_class); +# endif /* class_simple */ + +#else +# define SLH_SYSFS_REGISTER +# define SLH_SYSFS_ADD_CONTROL +# define SLH_SYSFS_ADD_DEVICE(_name, _minor) +# define SLH_SYSFS_REMOVE_DEVICE(i) +# define SLH_SYSFS_UNREGISTER +#endif + +#if (defined MINOR) +# define my_minor(x) MINOR(x) +#else +# define my_minor(x) minor(x) +#endif + +#if !defined(MODULE_VERSION) +# define MODULE_VERSION(x) +#endif + +#ifndef PCI_VENDOR_ID_RENDITION +#define PCI_VENDOR_ID_RENDITION 0x1163 +#endif diff --git a/kernel/svgalib_helper/main.c b/kernel/svgalib_helper/main.c new file mode 100644 index 0000000..1a7cdf1 --- /dev/null +++ b/kernel/svgalib_helper/main.c @@ -0,0 +1,778 @@ +#include + +#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) +# define MODVERSIONS +#endif + +#include /* printk() */ +#include + +#include +#include /* everything... */ +#include /* error codes */ +#include /* size_t */ +#include +#include +#include /* O_ACCMODE */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define __KERNEL_SYSCALLS__ +#include +asmlinkage long (*s_ioperm)(unsigned long from, unsigned long num, int turn_on); + +#include +#include +#include /* cli(), *_flags */ +#include /* memcpy and such */ +#include +#include +#include + +#include "kernel26compat.h" + +#include "svgalib_helper.h" + +#include "vgaversion.h" + +#include "i810.h" +#include "interrupt.h" +#include "displaystart.h" + +int debug=0; +static int all_devices=0; +int num_devices=0; + +static char *sdev_id="svgalib_helper"; + +static struct sh_pci_device *sh_pci_devs[MAX_NR_DEVICES]; + +static int irqs[MAX_NR_DEVICES]; + +#if (defined CONFIG_DEVFS_FS) && (!defined KERNEL_2_6) +static devfs_handle_t devfs_handle; +#endif + +#if defined(KERNEL_2_6) && !defined(CONFIG_DEVFS_FS) +struct K_CLASS *svgalib_helper_class; +#endif + +static int check_io_range(int port, int device) { + return 1; +} + +static struct pci_dev *get_pci_dev(int pcipos, int minor) { + + if(minor>=num_devices) return NULL; + if(minor>0) { + return sh_pci_devs[minor]->dev; + } else { + if(pcipos>0 && pciposdev; + } + return NULL; + +} + +static int get_dev(int pcipos, int minor) { + + if(minor>=num_devices) return 0; + if(minor>0) { + return minor; + } else { + if(pcipos>=num_devices || pcipos<1) return 0; + return pcipos; + } +} + +static volatile int vsync=0; +static wait_queue_head_t vsync_wait; + +static irqreturn_t vsync_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct sh_pci_device *dev = (struct sh_pci_device *)dev_id; + + if((char *)dev==sdev_id) { + if(!vga_test_vsync(dev)) { + return IRQ_NONE; + } + vga_ack_vsync(dev); + vsync=0; + wake_up_interruptible(&vsync_wait); + } else { + if(!dev->test_vsync(dev)) { + return IRQ_NONE; + } + dev->ack_vsync(dev); + dev->vsync=0; + wake_up_interruptible(&dev->vsync_wait); + +#ifndef NO_TASK + wake_up_interruptible(&dev->startad_wait); +#endif + } + + return IRQ_HANDLED; +} + +#ifndef NO_TASK +static void task_startad(void *data) { + struct sh_pci_device *dev = (struct sh_pci_device *)data; + int i; + + i=dev->dev->irq; + dev->enable_vsync(dev); + interruptible_sleep_on(&dev->vsync_wait); + dev->ack_vsync(dev); + set_displaystart(dev); + dev->startad=-1; +} +#endif + +#define GET_IOSTR \ + get_user(iostr.port, &user_iostr->port); \ + get_user(iostr.length, &user_iostr->length); \ + get_user(iostr.string, &user_iostr->string); +#define GET_IOV \ + get_user(iov.port, &user_iov->port); \ + get_user(iov.val, &user_iov->val); +#define PUT_IOV \ + put_user(iov.val, &user_iov->val); +#define GET_PCIV \ + get_user(pciv.pcipos, &user_pciv->pcipos); \ + get_user(pciv.address, &user_pciv->address); \ + get_user(pciv.val, &user_pciv->val); +#define PUT_PCIV \ + put_user(pciv.val, &user_pciv->val); +static int svgalib_helper_ioctl( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { + + io_t iov, *user_iov=(io_t *)arg; + pcic_t pciv, *user_pciv=(pcic_t *)arg; + int minor = my_minor(inode->i_rdev); + struct pci_dev *pdev; + io_string_t iostr, *user_iostr=(io_string_t *)arg; + int i=0, ret; + u8 pb; + u16 pw; + u32 pl; + unsigned char *outb_str; + + if(_IOC_TYPE(cmd)!=SVGAHELPER_MAGIC) { + return -EINVAL; + } + + ret=0; + + switch(_IOC_NR(cmd)) { + + case _IOC_NR(SVGAHELPER_REPOUTB): + GET_IOSTR; + if (iostr.length>4096) return -EINVAL; + if ( (outb_str = kmalloc(iostr.length, GFP_KERNEL )) == NULL ) return -ENOMEM; + if(copy_from_user(outb_str,iostr.string,iostr.length)) return -EPERM; + if(check_io_range(iostr.port,minor)) { + for(i=0; i5)) return -EINVAL; + pciv.val=sh_pci_devs[i]->len[pciv.address]; + PUT_PCIV; + break; + + case _IOC_NR(SVGAHELPER_PCIOUTB): + GET_PCIV; + pdev = get_pci_dev(pciv.pcipos, minor); + if(!pdev) return -EINVAL; + pb=pciv.val; + pci_write_config_byte(pdev, pciv.address, pb); + break; + + case _IOC_NR(SVGAHELPER_PCIOUTW): + GET_PCIV; + pdev = get_pci_dev(pciv.pcipos, minor); + if(!pdev) return -EINVAL; + pw=pciv.val; + pci_write_config_word(pdev, pciv.address, pw); + break; + + case _IOC_NR(SVGAHELPER_PCIOUTL): + GET_PCIV; + pdev = get_pci_dev(pciv.pcipos, minor); + if(!pdev) return -EINVAL; + pl=pciv.val; + pci_write_config_dword(pdev, pciv.address, pl); + break; +#ifdef __386__ + case _IOC_NR(SVGAHELPER_I810GTT): + i=i810_make_gtt(); + copy_to_user((char *)arg, &i, sizeof(unsigned int)); + break; + case _IOC_NR(SVGAHELPER_I810GTTE): + copy_from_user(&i, (char *)arg, sizeof(unsigned int)); + if(idev->irq; + if(i==0 || i==-1 || i==255) return -EINVAL; + sh_pci_devs[minor]->vsync=1; + sh_pci_devs[minor]->enable_vsync(sh_pci_devs[minor]); + wait_event_interruptible(sh_pci_devs[minor]->vsync_wait, + !sh_pci_devs[minor]->vsync); + if(sh_pci_devs[minor]->vsync) sh_pci_devs[minor]->ack_vsync(sh_pci_devs[minor]); + if(sh_pci_devs[minor]->vsync) return -ERESTARTSYS; + } else { + int i; + vsync=1; + i=0; + while(irqs[i]!=-1) + request_irq(irqs[i++], vsync_interrupt, SA_SHIRQ, "svgalib_helper", sdev_id); + vga_enable_vsync((void *)sdev_id); + wait_event_interruptible(vsync_wait, !vsync); + i=0; + if(vsync) vga_ack_vsync((void *)sdev_id); + while(irqs[i]!=-1) + free_irq(irqs[i++], sdev_id); + if(vsync) return -ERESTARTSYS; + } + + break; +#if 0 + case _IOC_NR(SVGAHELPER_IOPERM): + if(minor) return -EPERM; +#if 1 + i=0; + if(!capable(CAP_SYS_RAWIO)) { + i=1; + cap_raise(current->cap_effective, CAP_SYS_RAWIO); + } + s_ioperm=sys_call_table[__NR_ioperm]; + s_ioperm(0,0x400,1); + if(i) { + cap_lower(current->cap_effective, CAP_SYS_RAWIO); + } +#else + if(!ioperm) { + struct thread_struct * t = ¤t->thread; + struct tss_struct * tss; + unsigned long *bitmap; + + ioperm=1; + bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); + if (!bitmap) + return -ENOMEM; + + memset(bitmap, 0, IO_BITMAP_BYTES); + t->io_bitmap_ptr = bitmap; + tss = &per_cpu(init_tss, get_cpu()); + t->io_bitmap_max = IO_BITMAP_BYTES; + tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; + put_cpu(); + } +#endif + + break; +#endif +#ifndef NO_TASK + case _IOC_NR(SVGAHELPER_SETDISPLAYSTART): + if(minor) { + if(sh_pci_devs[minor]->startad==-1) + schedule_task(&sh_pci_devs[minor]->tq_startad); + sh_pci_devs[minor]->startad=arg; + } + break; +#endif + +#ifdef SVGA_HELPER_VIRTUAL + case _IOC_NR(SVGAHELPER_VIRT_TO_PHYS): + return dhahelper_virt_to_phys((dhahelper_vmi_t *)arg); + case _IOC_NR(SVGAHELPER_VIRT_TO_BUS): + return dhahelper_virt_to_bus((dhahelper_vmi_t *)arg); + case _IOC_NR(SVGAHELPER_ALLOC_PA): + return dhahelper_alloc_pa((dhahelper_mem_t *)arg); + case _IOC_NR(SVGAHELPER_FREE_PA): + return dhahelper_free_pa((dhahelper_mem_t *)arg); + case _IOC_NR(SVGAHELPER_LOCK_MEM): + return dhahelper_lock_mem((dhahelper_mem_t *)arg); + case _IOC_NR(SVGAHELPER_UNLOCK_MEM): + return dhahelper_unlock_mem((dhahelper_mem_t *)arg); + default: +#endif + return -EINVAL; + } + return ret; +} + + +static int svgalib_helper_open( struct inode *inode, struct file * filp) { + + int minor = my_minor(inode->i_rdev); + + if(minor>=num_devices) return -ENODEV; + + if(minor) { + int i=sh_pci_devs[minor]->dev->irq; + sh_pci_devs[minor]->opencount++; + if(sh_pci_devs[minor]->opencount==1 && i!=0 && i!=-1 && i!=255) + request_irq(i, vsync_interrupt, SA_SHIRQ, "svgalib_helper", sh_pci_devs[minor]); + } + +#ifndef KERNEL_2_6 + MOD_INC_USE_COUNT; +#else + try_module_get(THIS_MODULE); +#endif + + return 0; +} + +static int svgalib_helper_release( struct inode *inode, struct file *filp) { + + int minor = my_minor(inode->i_rdev); + + if(minor) { + int i=sh_pci_devs[minor]->dev->irq; + sh_pci_devs[minor]->opencount--; + if(sh_pci_devs[minor]->opencount==0 && i!=0 && i!=-1 && i!=255) { + sh_pci_devs[minor]->disable_vsync(sh_pci_devs[minor]); + free_irq(i, sh_pci_devs[minor]); + } + } +#ifndef KERNEL_2_6 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + + return 0; +} + +int remap_cache(struct vm_area_struct *vma, unsigned long off) { + + vma->vm_pgoff = off >> PAGE_SHIFT; + /* This is an IO map - tell maydump to skip this VMA */ + vma->vm_flags |= VM_IO; +#if defined(__sparc_v9__) + vma->vm_flags |= (VM_SHM | VM_LOCKED); + if (my_io_remap_page_range(vma, vma->vm_start, off, + vma->vm_end - vma->vm_start, vma->vm_page_prot, 0)) + return -EAGAIN; +#else +#if defined(__mc68000__) +#if defined(CONFIG_SUN3) + pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE; +#else + if (CPU_IS_020_OR_030) + pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030; + if (CPU_IS_040_OR_060) { + pgprot_val(vma->vm_page_prot) &= _CACHEMASK040; + /* Use no-cache mode, serialized */ + pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S; + } +#endif +#elif defined(__powerpc__) + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED; +#elif defined(__alpha__) + /* Caching is off in the I/O space quadrant by design. */ +#elif defined(__i386__) || defined(__x86_64__) + if (boot_cpu_data.x86 > 3) + pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; +#elif defined(__arm__) || defined(__mips__) + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +#elif defined(__sh__) + pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE; +#elif defined(__hppa__) + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; +#elif defined(__ia64__) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#else +#warning What do we have to do here?? +#endif + if (my_io_remap_page_range(vma, vma->vm_start, off, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; +#endif /* !__sparc_v9__ */ + return 0; + +} + +int check_mem(int card, unsigned long start, unsigned long len) { + int j; + unsigned long rstart, rlen; +#ifdef __alpha__ + int type; +#endif + + if (start+len < start || len >= 0x40000000) return -3; + + rstart=start; + rlen=len; + +#ifdef __alpha__ + type = start>>32; + switch(type) { + case 2: + start = start & 0xffffffff; + start = start >> 5; + len = len >> 5; + break; + case 3: + start = start & 0xffffffff; + break; + default: + return -1; + } +#endif + + if(!card) { + if( (start<0x110000) && (start+len<0x110000) ) return 0; + for(j=1;jmem[j]) + if((start>=sh_pci_devs[card]->mem[j])&& + (start+len<=sh_pci_devs[card]->mem[j]+sh_pci_devs[card]->len[j])) { + return 0; + } + } + return -2; +} + +static int svgalib_helper_mmap(struct file *filp, struct vm_area_struct *vma) { + unsigned long start=vma->vm_start; + unsigned long end=vma->vm_end; + unsigned long minor = my_minor(filp->f_dentry->d_inode->i_rdev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + unsigned long ofs=vma->vm_pgoff*PAGE_SIZE; +#else + unsigned long ofs=vma->vm_offset; +#endif + + if(check_mem(minor, ofs, end-start)) return -EPERM; + if(remap_cache(vma, ofs)) return -EAGAIN; + return 0; +} + +struct file_operations svgalib_helper_fops = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + .owner = THIS_MODULE, +#endif + .ioctl = svgalib_helper_ioctl, + .mmap = svgalib_helper_mmap, + .open = svgalib_helper_open, + .release = svgalib_helper_release, +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#define base_address(i) dev->resource[i].start +#else +#define base_address(i) (dev->base_address[i]&PCI_BASE_ADDRESS_MEM_MASK) +#endif + +int init_module(void) +{ + int result, i, j; + struct pci_dev *dev=NULL; + char name[255]; +#ifdef CONFIG_DEVFS_FS +# ifndef KERNEL_2_6 + devfs_handle_t slave_handle; +# endif +#endif + /* + * Register your major, and accept a dynamic number + */ + + printk(KERN_INFO "svgalib_helper: Initializing, version %s\n", versionstr); + + result = devfs_register_chrdev(SVGALIB_HELPER_MAJOR, "svgalib_helper", &svgalib_helper_fops); + + if (result < 0) { + printk(KERN_WARNING "svgalib_helper: can't get major %d\n",SVGALIB_HELPER_MAJOR); + return result; + } + + if((sh_pci_devs[0]=kmalloc(sizeof(struct sh_pci_device),GFP_KERNEL))==NULL) { + goto nomem_error; + } + + memset(sh_pci_devs[0],0,sizeof(struct sh_pci_device)); + num_devices=1; + for(i=1;idev=dev; + pci_read_config_word(dev,0,&sh_pci_devs[num_devices]->vendor); + pci_read_config_word(dev,2,&sh_pci_devs[num_devices]->id); + pci_read_config_byte(dev,8,&sh_pci_devs[num_devices]->revision); + printk(KERN_DEBUG "svgalib_helper: device%d: vendor:%.4x id:%.4x\n",num_devices, + sh_pci_devs[num_devices]->vendor,sh_pci_devs[num_devices]->id); + for(i=0;i<6;i++){ + unsigned int t; + int len; + pci_read_config_dword(dev,16+4*i,&result); + if(result) { + pci_write_config_dword(dev,16+4*i,0xffffffff); + pci_read_config_dword(dev,16+4*i,&t); + pci_write_config_dword(dev,16+4*i,result); + len = ~(t&~0xf)+1; + if (len){ + sh_pci_devs[num_devices]->mem[i]=result&~0xf; + sh_pci_devs[num_devices]->flags[i]=0x80 | (result&0xf); + sh_pci_devs[num_devices]->len[i]=len; + sh_pci_devs[num_devices]->mask[i]=t&~0xf; + printk(KERN_DEBUG "device%d: region%d, base=%.8x len=%d type=%d\n", + num_devices,i, result&(~0xf), len, result&0xf); + } + } + } + vga_init_vsync(sh_pci_devs[num_devices]); + init_waitqueue_head(&sh_pci_devs[num_devices]->vsync_wait); +#ifndef NO_TASK + init_waitqueue_head(&sh_pci_devs[num_devices]->startad_wait); + sh_pci_devs[num_devices]->tq_startad.routine=task_startad; + sh_pci_devs[num_devices]->tq_startad.data=sh_pci_devs[num_devices]; + sh_pci_devs[num_devices]->tq_startad.sync=0; + sh_pci_devs[num_devices]->startad=-1; +#endif + sh_pci_devs[num_devices]->opencount=0; + + sprintf(name, "svga%d", num_devices); + SLH_SYSFS_ADD_DEVICE(name, num_devices); + + num_devices++; + } + } + + j=0; + for(i=1; idev->irq; + if(k>0 && k<255) { + for(l=0;l0) { + irqs[j]=k; + j++; + } + } + } + irqs[j]=-1; + + init_waitqueue_head(&vsync_wait); + +#ifndef KERNEL_2_6 + EXPORT_NO_SYMBOLS; +#endif + + return 0; /* succeed */ + +nomem_error: + for(i=0;i"); +MODULE_DESCRIPTION("Generic hardware access to vga cards"); diff --git a/kernel/svgalib_helper/svgalib_helper.h b/kernel/svgalib_helper/svgalib_helper.h new file mode 100644 index 0000000..0852b09 --- /dev/null +++ b/kernel/svgalib_helper/svgalib_helper.h @@ -0,0 +1,117 @@ +#ifndef SVGALIB_HELPER_H +#define SVGALIB_HELPER_H + +#ifdef __KERNEL__ + +#define MAX_NR_DEVICES 15 + +#define address_t unsigned long + +struct sh_pci_device { + unsigned short vendor; + unsigned short id; + unsigned char revision; + struct pci_dev *dev; + address_t mem[6]; + address_t len[6]; + address_t mask[6]; + int flags[6]; + unsigned long iobase; + u8 * membase; + int (*test_vsync)(struct sh_pci_device *); + void (*ack_vsync)(struct sh_pci_device *); + void (*enable_vsync)(struct sh_pci_device *); + void (*disable_vsync)(struct sh_pci_device *); + int opencount; + int vsync; + wait_queue_head_t vsync_wait; +#ifndef NO_TASK + wait_queue_head_t startad_wait; + long startad; + struct tq_struct tq_startad; +#endif +}; + +extern int debug; + +#endif + +typedef struct { + int port; + int length; + unsigned char* string; +} io_string_t; + +typedef struct { + int port; + unsigned int val; +} io_t; + +typedef struct { + int pcipos; + unsigned int address; + unsigned long val; +} pcic_t; + +typedef struct { + void *win; + void *lfb; +} windowing_t; + +typedef struct dhahelper_vmi_s +{ + void * virtaddr; + unsigned long length; + unsigned long *realaddr; +}dhahelper_vmi_t; + +typedef struct dhahelper_mem_s +{ + void * addr; + unsigned long length; +}dhahelper_mem_t; + +#define SVGAHELPER_MAGIC 0xB3 + +#define SVGAHELPER_OUTB _IOR(SVGAHELPER_MAGIC,1,io_t) +#define SVGAHELPER_OUTW _IOR(SVGAHELPER_MAGIC,2,io_t) +#define SVGAHELPER_OUTL _IOR(SVGAHELPER_MAGIC,3,io_t) +#define SVGAHELPER_INB _IOW(SVGAHELPER_MAGIC,4,io_t) +#define SVGAHELPER_INW _IOW(SVGAHELPER_MAGIC,5,io_t) +#define SVGAHELPER_INL _IOW(SVGAHELPER_MAGIC,6,io_t) + +#define SVGAHELPER_PCIOUTB _IOR(SVGAHELPER_MAGIC,11,pcic_t) +#define SVGAHELPER_PCIOUTW _IOR(SVGAHELPER_MAGIC,12,pcic_t) +#define SVGAHELPER_PCIOUTL _IOR(SVGAHELPER_MAGIC,13,pcic_t) +#define SVGAHELPER_PCIINB _IOW(SVGAHELPER_MAGIC,14,pcic_t) +#define SVGAHELPER_PCIINW _IOW(SVGAHELPER_MAGIC,15,pcic_t) +#define SVGAHELPER_PCIINL _IOW(SVGAHELPER_MAGIC,16,pcic_t) +#define SVGAHELPER_PCIAPLEN _IOW(SVGAHELPER_MAGIC,17,pcic_t) + +#define SVGAHELPER_DVMA _IO(SVGAHELPER_MAGIC,7) +#define SVGAHELPER_WIND _IOR(SVGAHELPER_MAGIC,8,windowing_t) + +#define SVGAHELPER_IOPERM _IO(SVGAHELPER_MAGIC,9) +#define SVGAHELPER_REPOUTB _IOR(SVGAHELPER_MAGIC,10,io_t) + +#define SVGAHELPER_I810GTT _IOW(SVGAHELPER_MAGIC,128,unsigned int *) +#define SVGAHELPER_I810GTTE _IOW(SVGAHELPER_MAGIC,129,unsigned int *) + +#define SVGAHELPER_WRITEB _IOR(SVGAHELPER_MAGIC,21,io_t) +#define SVGAHELPER_WRITEW _IOR(SVGAHELPER_MAGIC,22,io_t) +#define SVGAHELPER_WRITEL _IOR(SVGAHELPER_MAGIC,23,io_t) +#define SVGAHELPER_READB _IOW(SVGAHELPER_MAGIC,24,io_t) +#define SVGAHELPER_READW _IOW(SVGAHELPER_MAGIC,25,io_t) +#define SVGAHELPER_READL _IOW(SVGAHELPER_MAGIC,26,io_t) + +#define SVGAHELPER_WAITRETRACE _IO(SVGAHELPER_MAGIC,31) +#define SVGAHELPER_SETDISPLAYSTART _IOR(SVGAHELPER_MAGIC,32, int) + +#define SVGAHELPER_VIRT_TO_PHYS _IOWR(SVGAHELPER_MAGIC, 40, dhahelper_vmi_t) +#define SVGAHELPER_VIRT_TO_BUS _IOWR(SVGAHELPER_MAGIC, 41, dhahelper_vmi_t) +#define SVGAHELPER_ALLOC_PA _IOWR(SVGAHELPER_MAGIC, 42, dhahelper_mem_t) +#define SVGAHELPER_FREE_PA _IOWR(SVGAHELPER_MAGIC, 43, dhahelper_mem_t) +#define SVGAHELPER_LOCK_MEM _IOWR(SVGAHELPER_MAGIC, 44, dhahelper_mem_t) +#define SVGAHELPER_UNLOCK_MEM _IOWR(SVGAHELPER_MAGIC, 45, dhahelper_mem_t) + +#endif /* SVGALIB_HELPER_H */ diff --git a/kernel/svgalib_helper/vgaversion.h b/kernel/svgalib_helper/vgaversion.h new file mode 100644 index 0000000..144211d --- /dev/null +++ b/kernel/svgalib_helper/vgaversion.h @@ -0,0 +1,2 @@ +int vga_version=0x1925; +static char versionstr[32]="1.9.25"; diff --git a/kernel/svgalib_helper/virtual.c b/kernel/svgalib_helper/virtual.c new file mode 100644 index 0000000..0a29866 --- /dev/null +++ b/kernel/svgalib_helper/virtual.c @@ -0,0 +1,358 @@ +#ifdef SVGA_HELPER_VIRTUAL + +#include +#include +#include /* cli(), *_flags */ +#include /* memcpy and such */ +#include +#include +#include +#include +#include "svgalib_helper.h" + +/*******************************/ +/* Memory management functions */ +/* from kernel:/drivers/media/video/bttv-driver.c */ +/*******************************/ + +#define MDEBUG(x) do { } while(0) /* Debug memory management */ + +/* [DaveM] I've recoded most of this so that: + * 1) It's easier to tell what is happening + * 2) It's more portable, especially for translating things + * out of vmalloc mapped areas in the kernel. + * 3) Less unnecessary translations happen. + * + * The code used to assume that the kernel vmalloc mappings + * existed in the page tables of every process, this is simply + * not guarenteed. We now use pgd_offset_k which is the + * defined way to get at the kernel page tables. + */ + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) +{ + unsigned long ret = 0UL; + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if(pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + + } + } + } + MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long uvirt_to_bus(unsigned long adr) +{ + unsigned long kva, ret; + + kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long uvirt_to_pa(unsigned long adr) +{ + unsigned long kva, ret; + + kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); + ret = virt_to_phys((void *)kva); + MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long kvirt_to_bus(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); + return ret; +} + +static void * rvmalloc(signed long size) +{ + void * mem; + unsigned long adr, page; + + mem=vmalloc_32(size); + if (mem) + { + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_reserve(virt_to_page(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + } + return mem; +} + +static int pag_lock(unsigned long addr) +{ + unsigned long page; + unsigned long kva; + + kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr); + if(kva) + { + lock_it: + page = uvirt_to_pa((unsigned long)addr); + LockPage(virt_to_page(__va(page))); + SetPageReserved(virt_to_page(__va(page))); + } + else + { + copy_from_user(&page,(char *)addr,1); /* try access it */ + kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr); + if(kva) goto lock_it; + else return EPERM; + } + return 0; +} + +static int pag_unlock(unsigned long addr) +{ + unsigned long page; + unsigned long kva; + + kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr); + if(kva) + { + page = uvirt_to_pa((unsigned long)addr); + UnlockPage(virt_to_page(__va(page))); + ClearPageReserved(virt_to_page(__va(page))); + return 0; + } + return EPERM; +} + + +static void rvfree(void * mem, signed long size) +{ + unsigned long adr, page; + + if (mem) + { + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_unreserve(virt_to_page(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + vfree(mem); + } +} + + +int dhahelper_virt_to_phys(dhahelper_vmi_t *arg) +{ + dhahelper_vmi_t mem; + unsigned long i,nitems; + char *addr; + if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t))) + { + if (debug > 0) + printk(KERN_ERR "dhahelper: failed copy from userspace\n"); + return -EFAULT; + } + nitems = mem.length / PAGE_SIZE; + if(mem.length % PAGE_SIZE) nitems++; + addr = mem.virtaddr; + for(i=0;i 0) + printk(KERN_ERR "dhahelper: failed copy to userspace\n"); + return -EFAULT; + } + addr += PAGE_SIZE; + } + return 0; +} + +int dhahelper_virt_to_bus(dhahelper_vmi_t *arg) +{ + dhahelper_vmi_t mem; + unsigned long i,nitems; + char *addr; + if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t))) + { + if (debug > 0) + printk(KERN_ERR "dhahelper: failed copy from userspace\n"); + return -EFAULT; + } + nitems = mem.length / PAGE_SIZE; + if(mem.length % PAGE_SIZE) nitems++; + addr = mem.virtaddr; + for(i=0;i 0) + printk(KERN_ERR "dhahelper: failed copy to userspace\n"); + return -EFAULT; + } + addr += PAGE_SIZE; + } + return 0; +} + + +int dhahelper_alloc_pa(dhahelper_mem_t *arg) +{ + dhahelper_mem_t mem; + if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t))) + { + if (debug > 0) + printk(KERN_ERR "dhahelper: failed copy from userspace\n"); + return -EFAULT; + } + mem.addr = rvmalloc(mem.length); + if (copy_to_user(arg, &mem, sizeof(dhahelper_mem_t))) + { + if (debug > 0) + printk(KERN_ERR "dhahelper: failed copy to userspace\n"); + return -EFAULT; + } + return 0; +} + +int dhahelper_free_pa(dhahelper_mem_t *arg) +{ + dhahelper_mem_t mem; + if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t))) + { + if (debug > 0) + printk(KERN_ERR "dhahelper: failed copy from userspace\n"); + return -EFAULT; + } + rvfree(mem.addr,mem.length); + return 0; +} + +int dhahelper_lock_mem(dhahelper_mem_t *arg) +{ + dhahelper_mem_t mem; + int retval; + unsigned long i,nitems,addr; + if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t))) + { + if (debug > 0) + printk(KERN_ERR "dhahelper: failed copy from userspace\n"); + return -EFAULT; + } + nitems = mem.length / PAGE_SIZE; + if(mem.length % PAGE_SIZE) nitems++; + addr = (unsigned long)mem.addr; + for(i=0;i 0) + printk(KERN_ERR "dhahelper: failed copy from userspace\n"); + return -EFAULT; + } + nitems = mem.length / PAGE_SIZE; + if(mem.length % PAGE_SIZE) nitems++; + addr = (unsigned long)mem.addr; + for(i=0;i 1) + printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n", + cmd, arg); + + if (MINOR(inode->i_rdev) != 0) + return -ENXIO; + + switch(cmd) + { + case DHAHELPER_GET_VERSION: return dhahelper_get_version((int *)arg); + case DHAHELPER_PORT: return dhahelper_port((dhahelper_port_t *)arg); + case DHAHELPER_VIRT_TO_PHYS:return dhahelper_virt_to_phys((dhahelper_vmi_t *)arg); + case DHAHELPER_VIRT_TO_BUS: return dhahelper_virt_to_bus((dhahelper_vmi_t *)arg); + case DHAHELPER_ALLOC_PA:return dhahelper_alloc_pa((dhahelper_mem_t *)arg); + case DHAHELPER_FREE_PA: return dhahelper_free_pa((dhahelper_mem_t *)arg); + case DHAHELPER_LOCK_MEM: return dhahelper_lock_mem((dhahelper_mem_t *)arg); + case DHAHELPER_UNLOCK_MEM: return dhahelper_unlock_mem((dhahelper_mem_t *)arg); + default: + if (debug > 0) + printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd); + return -EINVAL; + } + return 0; +} + +#endif diff --git a/lrmi-0.6m/Makefile b/lrmi-0.6m/Makefile new file mode 100644 index 0000000..d286cc4 --- /dev/null +++ b/lrmi-0.6m/Makefile @@ -0,0 +1,41 @@ +CFLAGS ?= -g -Wall + +sources = lrmi.c +objects = lrmi.o +all = vbetest mode3 vga_reset vbemodeinfo dosint + +%.o: %.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +all: $(all) + +vbetest: vbetest.c lrmi.o + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ + +mode3: mode3.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +dosint: dosint.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +vbemodeinfo: vbemodeinfo.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +vga_reset: vga_reset.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +install: mode3 vga_reset + install mode3 /sbin + install vga_reset /sbin + +.PHONY: clean +clean: + rm -f $(objects) $(all) core regs-out *.bak + +.PHONY: distclean +distclean: clean + rm -f .depend + +.PHONY: depend +depend: $(sources) + -$(CC) -M $(CPPFLAGS) $^ >.depend diff --git a/lrmi-0.6m/README b/lrmi-0.6m/README new file mode 100644 index 0000000..cf11f11 --- /dev/null +++ b/lrmi-0.6m/README @@ -0,0 +1,13 @@ +This is a modified version of Josh Vanderhoof's lrmi-0.5 package +The original is available at http://www.planet.net/pjoshv/ + + + +vbetest - show available modes, and test a mode + +mode3 - set mode using vesa bios. It can usually restore text mode after + svgalib leaves a non-working text-mode. + +vga_reset - call real mode c000:0003, which should be the video card's + initialization routine. Should work in some cases when mode3 fails to + restore text mode. diff --git a/lrmi-0.6m/dosint.c b/lrmi-0.6m/dosint.c new file mode 100644 index 0000000..1462c96 --- /dev/null +++ b/lrmi-0.6m/dosint.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include "lrmi.h" + +unsigned char * edid = NULL; + +int read_edid() +{ + int i; + struct LRMI_regs regs; + + if (!LRMI_init()) { + return -1; + } + + edid = LRMI_alloc_real(128); + + if ( edid == NULL ) + { + return -1; + } + + memset(edid, 0xed, 128); + memset(®s, 0, sizeof(regs)); + + regs.es = (unsigned int)edid >> 4; + regs.edi = 0; + + regs.eax = 0x4f15; + regs.ebx = 0x01; + + ioperm(0,0x400,1); + iopl(3); + LRMI_int( 0x10, ®s ); + iopl(0); + ioperm(0,0x400,0); + + if(*edid || *(edid+7)) return -2; + for(i=1;i<=6;i++) if(*(edid+i)!=0xff) return -2; + + return regs.eax; +} + + +int main ( int argc, char *argv[]) +{ +read_edid(); +fwrite(edid,128,1,stdout); +} diff --git a/lrmi-0.6m/get-edid b/lrmi-0.6m/get-edid new file mode 100755 index 0000000..7956716 --- /dev/null +++ b/lrmi-0.6m/get-edid @@ -0,0 +1,2 @@ +#!/bin/sh +./dosint 0x10 0x4f15 0x0001 0x80 diff --git a/lrmi-0.6m/lrmi.c b/lrmi-0.6m/lrmi.c new file mode 100644 index 0000000..8ed72f6 --- /dev/null +++ b/lrmi-0.6m/lrmi.c @@ -0,0 +1,945 @@ +#define DEBUG 0 +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +You are free to distribute and modify this file, as long as you +do not remove this copyright notice and clearly label modified +versions as being modified. + +This software has NO WARRANTY. Use it at your own risk. +*/ + +#include +#include +#include + +#ifdef USE_LIBC_VM86 +#include +#endif + +#include +#include +#include +#include +#include + +#include "lrmi.h" + +#define REAL_MEM_BASE ((void *)0x10000) +#define REAL_MEM_SIZE 0x10000 +#define REAL_MEM_BLOCKS 0x100 + +struct mem_block + { + unsigned int size : 20; + unsigned int free : 1; + }; + +static struct + { + int ready; + int count; + struct mem_block blocks[REAL_MEM_BLOCKS]; + } mem_info = { 0 }; + +static int +real_mem_init(void) + { + void *m; + int fd_zero; + + if (mem_info.ready) + return 1; + + fd_zero = open("/dev/zero", O_RDONLY); + if (fd_zero == -1) + { + perror("open /dev/zero"); + return 0; + } + + m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_zero, 0); + + if (m == (void *)-1) + { + perror("mmap /dev/zero"); + close(fd_zero); + return 0; + } + + mem_info.ready = 1; + mem_info.count = 1; + mem_info.blocks[0].size = REAL_MEM_SIZE; + mem_info.blocks[0].free = 1; + + return 1; + } + + +static void +insert_block(int i) + { + memmove( + mem_info.blocks + i + 1, + mem_info.blocks + i, + (mem_info.count - i) * sizeof(struct mem_block)); + + mem_info.count++; + } + +static void +delete_block(int i) + { + mem_info.count--; + + memmove( + mem_info.blocks + i, + mem_info.blocks + i + 1, + (mem_info.count - i) * sizeof(struct mem_block)); + } + +void * +LRMI_alloc_real(int size) + { + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return NULL; + + if (mem_info.count == REAL_MEM_BLOCKS) + return NULL; + + size = (size + 15) & ~15; + + for (i = 0; i < mem_info.count; i++) + { + if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) + { + insert_block(i); + + mem_info.blocks[i].size = size; + mem_info.blocks[i].free = 0; + mem_info.blocks[i + 1].size -= size; + + return (void *)r; + } + + r += mem_info.blocks[i].size; + } + + return NULL; + } + + +void +LRMI_free_real(void *m) + { + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return; + + i = 0; + while (m != (void *)r) + { + r += mem_info.blocks[i].size; + i++; + if (i == mem_info.count) + return; + } + + mem_info.blocks[i].free = 1; + + if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) + { + mem_info.blocks[i].size += mem_info.blocks[i + 1].size; + delete_block(i + 1); + } + + if (i - 1 >= 0 && mem_info.blocks[i - 1].free) + { + mem_info.blocks[i - 1].size += mem_info.blocks[i].size; + delete_block(i); + } + } + + +#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK) +#define DEFAULT_STACK_SIZE 0x1000 +#define RETURN_TO_32_INT 255 + +static struct + { + int ready; + unsigned short ret_seg, ret_off; + unsigned short stack_seg, stack_off; + struct vm86_struct vm; + } context = { 0 }; + + +static inline void +set_bit(unsigned int bit, void *array) + { + unsigned char *a = array; + + a[bit / 8] |= (1 << (bit % 8)); + } + + +static inline unsigned int +get_int_seg(int i) + { + return *(unsigned short *)(i * 4 + 2); + } + + +static inline unsigned int +get_int_off(int i) + { + return *(unsigned short *)(i * 4); + } + + +static inline void +pushw(unsigned short i) + { + struct vm86_regs *r = &context.vm.regs; + r->esp -= 2; + *(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i; + } + + +int +LRMI_init(void) + { + void *m; + int fd_mem; + + if (context.ready) + return 1; + + if (!real_mem_init()) + return 0; + + /* + Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) + and the ROM (0xa0000 - 0x100000) + */ + fd_mem = open("/dev/mem", O_RDWR); + + if (fd_mem == -1) + { + perror("open /dev/mem"); + return 0; + } + + m = mmap((void *)0, 0x502, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_mem, 0); + + if (m == (void *)-1) + { + perror("mmap /dev/mem"); + return 0; + } + + m = mmap((void *)0xa0000, 0x100000 - 0xa0000, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); + + if (m == (void *)-1) + { + perror("mmap /dev/mem"); + return 0; + } + + + /* + Allocate a stack + */ + m = LRMI_alloc_real(DEFAULT_STACK_SIZE); + + context.stack_seg = (unsigned int)m >> 4; + context.stack_off = DEFAULT_STACK_SIZE; + + /* + Allocate the return to 32 bit routine + */ + m = LRMI_alloc_real(2); + + context.ret_seg = (unsigned int)m >> 4; + context.ret_off = (unsigned int)m & 0xf; + + ((unsigned char *)m)[0] = 0xcd; /* int opcode */ + ((unsigned char *)m)[1] = RETURN_TO_32_INT; + + memset(&context.vm, 0, sizeof(context.vm)); + + context.vm.cpu_type=CPU_386; + + /* + Enable kernel emulation of all ints except RETURN_TO_32_INT + */ + memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); + set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); + + context.ready = 1; + + return 1; + } + + +static void +set_regs(struct LRMI_regs *r) + { + context.vm.regs.edi = r->edi; + context.vm.regs.esi = r->esi; + context.vm.regs.ebp = r->ebp; + context.vm.regs.ebx = r->ebx; + context.vm.regs.edx = r->edx; + context.vm.regs.ecx = r->ecx; + context.vm.regs.eax = r->eax; + context.vm.regs.eflags = DEFAULT_VM86_FLAGS; + context.vm.regs.es = r->es; + context.vm.regs.ds = r->ds; + context.vm.regs.fs = r->fs; + context.vm.regs.gs = r->gs; + } + + +static void +get_regs(struct LRMI_regs *r) + { + r->edi = context.vm.regs.edi; + r->esi = context.vm.regs.esi; + r->ebp = context.vm.regs.ebp; + r->ebx = context.vm.regs.ebx; + r->edx = context.vm.regs.edx; + r->ecx = context.vm.regs.ecx; + r->eax = context.vm.regs.eax; + r->flags = context.vm.regs.eflags; + r->es = context.vm.regs.es; + r->ds = context.vm.regs.ds; + r->fs = context.vm.regs.fs; + r->gs = context.vm.regs.gs; + } + +#define DIRECTION_FLAG (1 << 10) + +static void +em_ins(int size) + { + unsigned int edx, edi; + + edx = context.vm.regs.edx & 0xffff; + edi = context.vm.regs.edi & 0xffff; + edi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; insl; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("std; insw; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("std; insb; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + } + else + { + if (size == 4) + asm volatile ("cld; insl" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("cld; insw" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("cld; insb" + : "=D" (edi) : "d" (edx), "0" (edi)); + } + + edi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.edi &= 0xffff0000; + context.vm.regs.edi |= edi & 0xffff; + } + +static void +em_rep_ins(int size) + { + unsigned int ecx, edx, edi; + + ecx = context.vm.regs.ecx & 0xffff; + edx = context.vm.regs.edx & 0xffff; + edi = context.vm.regs.edi & 0xffff; + edi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; rep; insl; cld" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else if (size == 2) + asm volatile ("std; rep; insw; cld" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else + asm volatile ("std; rep; insb; cld" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + } + else + { + if (size == 4) + asm volatile ("cld; rep; insl" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else if (size == 2) + asm volatile ("cld; rep; insw" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else + asm volatile ("cld; rep; insb" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + } + + edi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.edi &= 0xffff0000; + context.vm.regs.edi |= edi & 0xffff; + + context.vm.regs.ecx &= 0xffff0000; + context.vm.regs.ecx |= ecx & 0xffff; + } + +static void +em_outs(int size) + { + unsigned int edx, esi; + + edx = context.vm.regs.edx & 0xffff; + esi = context.vm.regs.esi & 0xffff; + esi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; outsl; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("std; outsw; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("std; outsb; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + } + else + { + if (size == 4) + asm volatile ("cld; outsl" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("cld; outsw" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("cld; outsb" + : "=S" (esi) : "d" (edx), "0" (esi)); + } + + esi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.esi &= 0xffff0000; + context.vm.regs.esi |= esi & 0xffff; + } + +static void +em_rep_outs(int size) + { + unsigned int ecx, edx, esi; + + ecx = context.vm.regs.ecx & 0xffff; + edx = context.vm.regs.edx & 0xffff; + esi = context.vm.regs.esi & 0xffff; + esi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; rep; outsl; cld" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else if (size == 2) + asm volatile ("std; rep; outsw; cld" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else + asm volatile ("std; rep; outsb; cld" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + } + else + { + if (size == 4) + asm volatile ("cld; rep; outsl" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else if (size == 2) + asm volatile ("cld; rep; outsw" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else + asm volatile ("cld; rep; outsb" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + } + + esi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.esi &= 0xffff0000; + context.vm.regs.esi |= esi & 0xffff; + + context.vm.regs.ecx &= 0xffff0000; + context.vm.regs.ecx |= ecx & 0xffff; + } + +static void +em_inb(int port) + { + asm volatile ("inb (%w1), %b0" + : "=a" (context.vm.regs.eax) + : "d" (port)); +#if DEBUG +printf("inb %04x %02x\n",context.vm.regs.edx,context.vm.regs.eax); +#endif + } + +static void +em_inw(int port) + { + asm volatile ("inw (%w1), %w0" + : "=a" (context.vm.regs.eax) + : "d" (port)); +#if DEBUG +printf("inw %04x %04x\n",context.vm.regs.edx,context.vm.regs.eax); +#endif + } + +static void +em_inl(int port) + { + asm volatile ("inl (%w1), %0" + : "=a" (context.vm.regs.eax) + : "d" (port)); +#if DEBUG +printf("inl %04x %08x\n",context.vm.regs.edx,context.vm.regs.eax); +#endif + } + +static void +em_outb(int port) + { + asm volatile ("outb %b0, (%w1)" + : : "a" (context.vm.regs.eax), + "d" (port)); +#if DEBUG +printf("outb %04x %02x\n",context.vm.regs.edx,context.vm.regs.eax); +#endif + } + +static void +em_outw(int port) + { + asm volatile ("outw %w0, (%w1)" + : : "a" (context.vm.regs.eax), + "d" (port)); +#if DEBUG +printf("outw %04x %02x\n",context.vm.regs.edx,context.vm.regs.eax); +#endif + } + +static void +em_outl(int port) + { + asm volatile ("outl %0, (%w1)" + : : "a" (context.vm.regs.eax), + "d" (port)); +#if DEBUG +printf("outl %04x %08x\n",context.vm.regs.edx,context.vm.regs.eax); +#endif + } + +static int +emulate(void) + { + unsigned char *insn; + struct + { + unsigned int size : 1; + unsigned int rep : 1; + } prefix = { 0, 0 }; + int i = 0; + + insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4); + insn += context.vm.regs.eip; + + while (1) + { + if (insn[i] == 0x66) + { + prefix.size = 1 - prefix.size; + i++; + } + else if (insn[i] == 0xf3) + { + prefix.rep = 1; + i++; + } + else if (insn[i] == 0xf0 || insn[i] == 0xf2 + || insn[i] == 0x26 || insn[i] == 0x2e + || insn[i] == 0x36 || insn[i] == 0x3e + || insn[i] == 0x64 || insn[i] == 0x65 + || insn[i] == 0x67) + { + /* these prefixes are just ignored */ + i++; + } + else if (insn[i] == 0x6c) + { + if (prefix.rep) + em_rep_ins(1); + else + em_ins(1); + i++; + break; + } + else if (insn[i] == 0x6d) + { + if (prefix.rep) + { + if (prefix.size) + em_rep_ins(4); + else + em_rep_ins(2); + } + else + { + if (prefix.size) + em_ins(4); + else + em_ins(2); + } + i++; + break; + } + else if (insn[i] == 0x6e) + { + if (prefix.rep) + em_rep_outs(1); + else + em_outs(1); + i++; + break; + } + else if (insn[i] == 0x6f) + { + if (prefix.rep) + { + if (prefix.size) + em_rep_outs(4); + else + em_rep_outs(2); + } + else + { + if (prefix.size) + em_outs(4); + else + em_outs(2); + } + i++; + break; + } + else if (insn[i] == 0xe4) + { + i++; + em_inb(insn[i]); + i++; + break; + } + else if (insn[i] == 0xe5) + { + i++; + if (prefix.size) + em_inl(insn[i]); + else + em_inw(insn[i]); + i++; + break; + } + else if (insn[i] == 0xe6) + { + i++; + em_outb(insn[i]); + i++; + break; + } + else if (insn[i] == 0xe7) + { + i++; + if (prefix.size) + em_outl(insn[i]); + else + em_outw(insn[i]); + i++; + break; + } + else if (insn[i] == 0xec) + { + em_inb(context.vm.regs.edx); + i++; + break; + } + else if (insn[i] == 0xed) + { + if (prefix.size) + em_inl(context.vm.regs.edx); + else + em_inw(context.vm.regs.edx); + i++; + break; + } + else if (insn[i] == 0xee) + { + em_outb(context.vm.regs.edx); + i++; + break; + } + else if (insn[i] == 0xef) + { + if (prefix.size) + em_outl(context.vm.regs.edx); + else + em_outw(context.vm.regs.edx); + + i++; + break; + } + else + return 0; + } + + context.vm.regs.eip += i; + return 1; + } + + +/* + I don't know how to make sure I get the right vm86() from libc. + The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) + which should be declared as "int vm86(struct vm86_struct *);" in + . + + This just does syscall 113 with inline asm, which should work + for both libc's (I hope). +*/ +#if !defined(USE_LIBC_VM86) +static int +lrmi_vm86(struct vm86_struct *vm) + { + int r; +#ifdef __PIC__ + asm volatile ( + "pushl %%ebx\n\t" + "movl %2, %%ebx\n\t" + "int $0x80\n\t" + "popl %%ebx" + : "=a" (r) + : "0" (113), "r" (vm)); +#else + asm volatile ( + "int $0x80" + : "=a" (r) + : "0" (113), "b" (vm)); +#endif + return r; + } +#else +#define lrmi_vm86 vm86 +#endif + + +static void +debug_info(int vret) + { + int i; + unsigned char *p; + + fputs("vm86() failed\n", stderr); + fprintf(stderr, "return = 0x%x\n", vret); + fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax); + fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx); + fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx); + fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx); + fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi); + fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi); + fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp); + fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip); + fprintf(stderr, "cs = 0x%04x\n", context.vm.regs.cs); + fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp); + fprintf(stderr, "ss = 0x%04x\n", context.vm.regs.ss); + fprintf(stderr, "ds = 0x%04x\n", context.vm.regs.ds); + fprintf(stderr, "es = 0x%04x\n", context.vm.regs.es); + fprintf(stderr, "fs = 0x%04x\n", context.vm.regs.fs); + fprintf(stderr, "gs = 0x%04x\n", context.vm.regs.gs); + fprintf(stderr, "eflags = 0x%08lx\n", context.vm.regs.eflags); + + fputs("cs:ip = [ ", stderr); + + p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff)); + + for (i = 0; i < 16; ++i) + fprintf(stderr, "%02x ", (unsigned int)p[i]); + + fputs("]\n", stderr); + } + + +static int +run_vm86(void) + { + unsigned int vret; + + while (1) + { + vret = lrmi_vm86(&context.vm); + + if (VM86_TYPE(vret) == VM86_SIGNAL || + VM86_TYPE(vret) == VM86_STI || + VM86_TYPE(vret) == VM86_PICRETURN) { + context.vm.regs.eflags &= ~VIP_MASK; + continue; + } + + if (VM86_TYPE(vret) == VM86_INTx) + { + unsigned int v = VM86_ARG(vret); + + if (v == RETURN_TO_32_INT) + return 1; + + pushw(context.vm.regs.eflags); + pushw(context.vm.regs.cs); + pushw(context.vm.regs.eip); + + context.vm.regs.cs = get_int_seg(v); + context.vm.regs.eip = get_int_off(v); + context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK); + + continue; + } + + if (VM86_TYPE(vret) != VM86_UNKNOWN) + break; + + if (!emulate()) + break; + } + + debug_info(vret); + + return 0; + } + + +int +LRMI_call(struct LRMI_regs *r) + { + unsigned int vret; + + memset(&context.vm.regs, 0, sizeof(context.vm.regs)); + + set_regs(r); + + context.vm.regs.cs = r->cs; + context.vm.regs.eip = r->ip; + + if (r->ss == 0 && r->sp == 0) + { + context.vm.regs.ss = context.stack_seg; + context.vm.regs.esp = context.stack_off; + } + else + { + context.vm.regs.ss = r->ss; + context.vm.regs.esp = r->sp; + } + + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; + } + + +int +LRMI_int(int i, struct LRMI_regs *r) + { + unsigned int vret; + unsigned int seg, off; + + seg = get_int_seg(i); + off = get_int_off(i); + + /* + If the interrupt is in regular memory, it's probably + still pointing at a dos TSR (which is now gone). + */ + if (seg < 0xa000 || (seg << 4) + off >= 0x100000) + { + fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); + return 0; + } + + memset(&context.vm.regs, 0, sizeof(context.vm.regs)); + + set_regs(r); + + context.vm.regs.cs = seg; + context.vm.regs.eip = off; + + if (r->ss == 0 && r->sp == 0) + { + context.vm.regs.ss = context.stack_seg; + context.vm.regs.esp = context.stack_off; + } + else + { + context.vm.regs.ss = r->ss; + context.vm.regs.esp = r->sp; + } + + pushw(DEFAULT_VM86_FLAGS); + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; + } + diff --git a/lrmi-0.6m/lrmi.h b/lrmi-0.6m/lrmi.h new file mode 100644 index 0000000..a299b40 --- /dev/null +++ b/lrmi-0.6m/lrmi.h @@ -0,0 +1,75 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +You are free to distribute and modify this file, as long as you +do not remove this copyright notice and clearly label modified +versions as being modified. + +This software has NO WARRANTY. Use it at your own risk. + +*/ + +#ifndef LRMI_H +#define LRMI_H +#if defined __GLIBC__ && __GLIBC__ >= 2 +#include +#endif + +struct LRMI_regs + { + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int reserved; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + unsigned short int flags; + unsigned short int es; + unsigned short int ds; + unsigned short int fs; + unsigned short int gs; + unsigned short int ip; + unsigned short int cs; + unsigned short int sp; + unsigned short int ss; + }; + +/* + Initialize + returns 1 if sucessful, 0 for failure +*/ +int +LRMI_init(void); + +/* + Simulate a 16 bit far call + returns 1 if sucessful, 0 for failure +*/ +int +LRMI_call(struct LRMI_regs *r); + +/* + Simulate a 16 bit interrupt + returns 1 if sucessful, 0 for failure +*/ +int +LRMI_int(int interrupt, struct LRMI_regs *r); + +/* + Allocate real mode memory + The returned block is paragraph (16 byte) aligned +*/ +void * +LRMI_alloc_real(int size); + +/* + Free real mode memory +*/ +void +LRMI_free_real(void *m); + +#endif diff --git a/lrmi-0.6m/mode3.c b/lrmi-0.6m/mode3.c new file mode 100644 index 0000000..8c7c46c --- /dev/null +++ b/lrmi-0.6m/mode3.c @@ -0,0 +1,52 @@ +/* +Set mode to VESA mode 3 (80x25 text mode) +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "lrmi.h" + +void set_vesa_mode(int mode){ + struct LRMI_regs r; + memset(&r, 0, sizeof(r)); + r.eax = 0x4f02; + r.ebx = mode; + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't set video mode (vm86 failure)\n"); + } + } + +int main(int argc, char *argv[]){ + int i; + + + if((argc>1)&&(!strcmp(argv[1],"-h"))){ + printf("Usage: mode3 [ modenum [ font ] ]\n" + "\n" + "uses VESA bios to set video mode to modenum (3 by default)\n" + "if font is given, uses setfont to change the screen font\n\n"); + return 0; + }; + if (!LRMI_init()) + return 1; + ioperm(0, 0x400, 1); + iopl(3); + i=3; + if(argc>1){ + sscanf(argv[1],"%i",&i); + if((i<=0))i=3; + }; + set_vesa_mode(i); + if(argc>2){ + execlp("setfont",argv[2],NULL); + return 1; + }; + return 0; +} diff --git a/lrmi-0.6m/vbe.h b/lrmi-0.6m/vbe.h new file mode 100644 index 0000000..265d373 --- /dev/null +++ b/lrmi-0.6m/vbe.h @@ -0,0 +1,104 @@ +/* +Copyright (C) 1996 by Josh Vanderhoof + +You are free to distribute and modify this file, as long as you +do not remove this copyright notice and clearly label modified +versions as being modified. + +This software has NO WARRANTY. Use it at your own risk. +*/ + +#ifndef _VBE_H +#define _VBE_H + +/* structures for vbe 2.0 */ + +struct vbe_info_block + { + char vbe_signature[4]; + short vbe_version; + unsigned short oem_string_off; + unsigned short oem_string_seg; + int capabilities; + unsigned short video_mode_list_off; + unsigned short video_mode_list_seg; + short total_memory; + short oem_software_rev; + unsigned short oem_vendor_name_off; + unsigned short oem_vendor_name_seg; + unsigned short oem_product_name_off; + unsigned short oem_product_name_seg; + unsigned short oem_product_rev_off; + unsigned short oem_product_rev_seg; + char reserved[222]; + char oem_data[256]; + } __attribute__ ((packed)); + +#define VBE_ATTR_MODE_SUPPORTED (1 << 0) +#define VBE_ATTR_TTY (1 << 2) +#define VBE_ATTR_COLOR (1 << 3) +#define VBE_ATTR_GRAPHICS (1 << 4) +#define VBE_ATTR_NOT_VGA (1 << 5) +#define VBE_ATTR_NOT_WINDOWED (1 << 6) +#define VBE_ATTR_LINEAR (1 << 7) + +#define VBE_WIN_RELOCATABLE (1 << 0) +#define VBE_WIN_READABLE (1 << 1) +#define VBE_WIN_WRITEABLE (1 << 2) + +#define VBE_MODEL_TEXT 0 +#define VBE_MODEL_CGA 1 +#define VBE_MODEL_HERCULES 2 +#define VBE_MODEL_PLANAR 3 +#define VBE_MODEL_PACKED 4 +#define VBE_MODEL_256 5 +#define VBE_MODEL_RGB 6 +#define VBE_MODEL_YUV 7 + +struct vbe_mode_info_block + { + unsigned short mode_attributes; + unsigned char win_a_attributes; + unsigned char win_b_attributes; + unsigned short win_granularity; + unsigned short win_size; + unsigned short win_a_segment; + unsigned short win_b_segment; + unsigned short win_func_ptr_off; + unsigned short win_func_ptr_seg; + unsigned short bytes_per_scanline; + unsigned short x_resolution; + unsigned short y_resolution; + unsigned char x_char_size; + unsigned char y_char_size; + unsigned char number_of_planes; + unsigned char bits_per_pixel; + unsigned char number_of_banks; + unsigned char memory_model; + unsigned char bank_size; + unsigned char number_of_image_pages; + unsigned char res1; + unsigned char red_mask_size; + unsigned char red_field_position; + unsigned char green_mask_size; + unsigned char green_field_position; + unsigned char blue_mask_size; + unsigned char blue_field_position; + unsigned char rsvd_mask_size; + unsigned char rsvd_field_position; + unsigned char direct_color_mode_info; + unsigned int phys_base_ptr; + unsigned int offscreen_mem_offset; + unsigned short offscreen_mem_size; + unsigned char res2[206]; + } __attribute__ ((packed)); + +struct vbe_palette_entry + { + unsigned char blue; + unsigned char green; + unsigned char red; + unsigned char align; + } __attribute__ ((packed)); + +#endif diff --git a/lrmi-0.6m/vbemodeinfo.c b/lrmi-0.6m/vbemodeinfo.c new file mode 100644 index 0000000..1888b97 --- /dev/null +++ b/lrmi-0.6m/vbemodeinfo.c @@ -0,0 +1,132 @@ +/* +List the available VESA graphics and text modes. + +This program is in the public domain. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "lrmi.h" +#include "vbe.h" + +struct + { + struct vbe_info_block *info; + struct vbe_mode_info_block *mode; + } vbe; + +int +main(int argc, char *argv[]) { + struct LRMI_regs r; + int mode; + + if((argc!=2)||((mode=atoi(argv[1]))==0)){ + printf("usage: vbemodeinfo \n" + "where is a vesa mode numder.\n" + "use vbetest to list available modes\n\n"); + return 0; + }; + + if (!LRMI_init()) + return 1; + + vbe.info = LRMI_alloc_real(sizeof(struct vbe_info_block) + + sizeof(struct vbe_mode_info_block)); + + if (vbe.info == NULL) { + fprintf(stderr, "Can't alloc real mode memory\n"); + return 1; + } + + vbe.mode = (struct vbe_mode_info_block *)(vbe.info + 1); + + /* + Allow read/write to all IO ports + */ + ioperm(0, 0x400 , 1); + iopl(3); + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f00; + r.es = (unsigned int)vbe.info >> 4; + r.edi = 0; + + memcpy(vbe.info->vbe_signature, "VBE2", 4); + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get VESA info (vm86 failure)\n"); + return 1; + } + + if ((r.eax & 0xffff) != 0x4f || strncmp(vbe.info->vbe_signature, "VESA", 4) != 0) { + fprintf(stderr, "No VESA bios\n"); + return 1; + } + + printf("VBE Version %x.%x\n", + (int)(vbe.info->vbe_version >> 8) & 0xff, + (int)vbe.info->vbe_version & 0xff); + + printf("%s\n", + (char *)(vbe.info->oem_string_seg * 16 + vbe.info->oem_string_off)); + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f01; + r.ecx = mode; + r.es = (unsigned int)vbe.mode >> 4; + r.edi = (unsigned int)vbe.mode & 0xf; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return 1; + } + + printf("mode %i\n",mode); + + printf ("mode_attributes = %i\n", vbe.mode->mode_attributes); + printf ("win_a_attributes = %i\n", vbe.mode->win_a_attributes); + printf ("win_b_attributes = %i\n", vbe.mode->win_b_attributes); + printf ("win_granularity = %i\n", vbe.mode->win_granularity); + printf ("win_size = %i\n", vbe.mode->win_size); + printf ("win_a_segment = %i\n", vbe.mode->win_a_segment); + printf ("win_b_segment = %i\n", vbe.mode->win_b_segment); + printf ("win_func_ptr_off = %i\n", vbe.mode->win_func_ptr_off); + printf ("win_func_ptr_seg = %i\n", vbe.mode->win_func_ptr_seg); + printf ("bytes_per_scanline = %i\n", vbe.mode->bytes_per_scanline); + printf ("x_resolution = %i\n", vbe.mode->x_resolution); + printf ("y_resolution = %i\n", vbe.mode->y_resolution); + printf ("x_char_size = %i\n", vbe.mode->x_char_size); + printf ("y_char_size = %i\n", vbe.mode->y_char_size); + printf ("number_of_planes = %i\n", vbe.mode->number_of_planes); + printf ("bits_per_pixel = %i\n", vbe.mode->bits_per_pixel); + printf ("number_of_banks = %i\n", vbe.mode->number_of_banks); + printf ("memory_model = %i\n", vbe.mode->memory_model); + printf ("bank_size = %i\n", vbe.mode->bank_size); + printf ("number_of_image_pages = %i\n", vbe.mode->number_of_image_pages); + printf ("res1 = %i\n", vbe.mode->res1); + printf ("red_mask_size = %i\n", vbe.mode->red_mask_size); + printf ("red_field_position = %i\n", vbe.mode->red_field_position); + printf ("green_mask_size = %i\n", vbe.mode->green_mask_size); + printf ("green_field_position = %i\n", vbe.mode->green_field_position); + printf ("blue_mask_size = %i\n", vbe.mode->blue_mask_size); + printf ("blue_field_position = %i\n", vbe.mode->blue_field_position); + printf ("rsvd_mask_size = %i\n", vbe.mode->rsvd_mask_size); + printf ("rsvd_field_position = %i\n", vbe.mode->rsvd_field_position); + printf ("direct_color_mode_info = %i\n", vbe.mode->direct_color_mode_info); + printf ("phys_base_ptr = %i\n", vbe.mode->phys_base_ptr); + printf ("offscreen_mem_offset = %i\n", vbe.mode->offscreen_mem_offset); + printf ("offscreen_mem_size = %i\n", vbe.mode->offscreen_mem_size); + + + LRMI_free_real(vbe.info); + + return 0; +} diff --git a/lrmi-0.6m/vbetest.c b/lrmi-0.6m/vbetest.c new file mode 100644 index 0000000..594fd0b --- /dev/null +++ b/lrmi-0.6m/vbetest.c @@ -0,0 +1,333 @@ +/* +List the available VESA graphics and text modes. + +This program is in the public domain. +*/ + +#include +#include +#include +#include +#include +#include + +#include "lrmi.h" +#include "vbe.h" + +struct + { + struct vbe_info_block *info; + struct vbe_mode_info_block *mode; + } vbe; + +void * +save_state(void) + { + struct LRMI_regs r; + void *buffer; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 0; /* get buffer size */ + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't get video state buffer size (vm86 failure)\n"); + return NULL; + } + + if ((r.eax & 0xffff) != 0x4f) + { + fprintf(stderr, "Get video state buffer size failed\n"); + return NULL; + } + + buffer = LRMI_alloc_real((r.ebx & 0xffff) * 64); + + if (buffer == NULL) + { + fprintf(stderr, "Can't allocate video state buffer\n"); + return NULL; + } + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 1; /* save state */ + r.es = (unsigned int)buffer >> 4; + r.ebx = (unsigned int)buffer & 0xf; + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't save video state (vm86 failure)\n"); + return NULL; + } + + if ((r.eax & 0xffff) != 0x4f) + { + fprintf(stderr, "Save video state failed\n"); + return NULL; + } + + return buffer; + } + +void +restore_state(void *buffer) + { + struct LRMI_regs r; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 2; /* restore state */ + r.es = (unsigned int)buffer >> 4; + r.ebx = (unsigned int)buffer & 0xf; + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't restore video state (vm86 failure)\n"); + } + else if ((r.eax & 0xffff) != 0x4f) + { + fprintf(stderr, "Restore video state failed\n"); + } + + LRMI_free_real(buffer); + } + +void +text_mode(void) + { + struct LRMI_regs r; + + memset(&r, 0, sizeof(r)); + + r.eax = 3; + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't set text mode (vm86 failure)\n"); + } + } + +void +set_mode(int n) + { + struct LRMI_regs r; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f02; + r.ebx = n; + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't set video mode (vm86 failure)\n"); + } + else if ((r.eax & 0xffff) != 0x4f) + { + fprintf(stderr, "Set video mode failed\n"); + } + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f01; + r.ecx = n; + r.es = (unsigned int)vbe.mode >> 4; + r.edi = (unsigned int)vbe.mode & 0xf; + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return; + } + + if ((r.eax & 0xffff) != 0x4f) + { + fprintf(stderr, "Get mode info failed\n"); + return; + } + + /* + Draw a blue/red fade on top line + */ + if (vbe.mode->memory_model == VBE_MODEL_RGB) + { + char *p = (char *)(vbe.mode->win_a_segment << 4); + int pixel_size = (vbe.mode->bits_per_pixel + 7) / 8; + int x_res = vbe.mode->x_resolution; + int max_r = (1 << vbe.mode->red_mask_size) - 1; + int max_b = (1 << vbe.mode->blue_mask_size) - 1; + int shift_r = vbe.mode->red_field_position; + int shift_b = vbe.mode->blue_field_position; + int i; + + for (i = 0; i < x_res; i++) + { + int c; + c = (i * max_r / x_res) << shift_r; + c |= ((x_res - i) * max_b / x_res) << shift_b; + + memcpy(p + i * pixel_size, &c, pixel_size); + } + for (i=2048;i<0x7fff;i++)*(p+i)=(i&0xff); + for(i=0x8000;i<0xffff;i++)*(p+i)=85; + } + } + +void +interactive_set_mode(void) + { + int n; + void *state; + struct stat stat; + + if (fstat(0, &stat) != 0) + { + fprintf(stderr, "Can't stat() stdin\n"); + return; + } + + if ((stat.st_rdev & 0xff00) != 0x400 + || (stat.st_rdev & 0xff) > 63) + { + fprintf(stderr, "To switch video modes, " + "this program must be run from the console\n"); + return; + } + + printf("mode? "); + scanf("%d", &n); + + printf("setting mode %d\n", n); + + ioctl(0, KDSETMODE, KD_GRAPHICS); + + state = save_state(); + + if (state == NULL) + return; + + set_mode(n); + + sleep(5); + + text_mode(); + restore_state(state); + + ioctl(0, KDSETMODE, KD_TEXT); + } + +int +main(void) + { + struct LRMI_regs r; + short int *mode_list; + + if (!LRMI_init()) + return 1; + + vbe.info = LRMI_alloc_real(sizeof(struct vbe_info_block) + + sizeof(struct vbe_mode_info_block)); + + if (vbe.info == NULL) + { + fprintf(stderr, "Can't alloc real mode memory\n"); + return 1; + } + + vbe.mode = (struct vbe_mode_info_block *)(vbe.info + 1); + + /* + Allow read/write to all IO ports + */ + ioperm(0, 0x400 , 1); + iopl(3); + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f00; + r.es = (unsigned int)vbe.info >> 4; + r.edi = 0; + + memcpy(vbe.info->vbe_signature, "VBE2", 4); + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't get VESA info (vm86 failure)\n"); + return 1; + } + + if ((r.eax & 0xffff) != 0x4f || strncmp(vbe.info->vbe_signature, "VESA", 4) != 0) + { + fprintf(stderr, "No VESA bios\n"); + return 1; + } + + printf("VBE Version %x.%x\n", + (int)(vbe.info->vbe_version >> 8) & 0xff, + (int)vbe.info->vbe_version & 0xff); + + printf("%s\n", + (char *)(vbe.info->oem_string_seg * 16 + vbe.info->oem_string_off)); + + mode_list = (short int *)(vbe.info->video_mode_list_seg * 16 + vbe.info->video_mode_list_off); + + while (*mode_list != -1) + { + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f01; + r.ecx = *mode_list; + r.es = (unsigned int)vbe.mode >> 4; + r.edi = (unsigned int)vbe.mode & 0xf; + + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return 1; + } + + if (vbe.mode->memory_model == VBE_MODEL_RGB) + printf("[%3d] %dx%d (%d:%d:%d)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution, + vbe.mode->red_mask_size, + vbe.mode->green_mask_size, + vbe.mode->blue_mask_size); + else if (vbe.mode->memory_model == VBE_MODEL_256) + printf("[%3d] %dx%d (256 color palette)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution); + else if (vbe.mode->memory_model == VBE_MODEL_PACKED) + printf("[%3d] %dx%d (%d color palette)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution, + 1 << vbe.mode->bits_per_pixel); + else if (vbe.mode->memory_model == VBE_MODEL_TEXT) + printf("[%3d] %dx%d (TEXT)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution); + else printf("[%3d] %dx%d (model=%d)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution, + vbe.mode->memory_model); + mode_list++; + } + + LRMI_free_real(vbe.info); + + interactive_set_mode(); + + return 0; + } diff --git a/lrmi-0.6m/vga_reset.c b/lrmi-0.6m/vga_reset.c new file mode 100644 index 0000000..eae7f6d --- /dev/null +++ b/lrmi-0.6m/vga_reset.c @@ -0,0 +1,24 @@ +/* +Call real mode c0003 +*/ + +#include +#include +#include +#include + +#include "lrmi.h" + +int main(int argc, char *argv[]){ + struct LRMI_regs r; + + if (!LRMI_init()) + return 1; + ioperm(0, 0x400, 1); + iopl(3); + memset(&r,0,sizeof(r)); + r.ip=3; + r.cs=0xc000; + LRMI_call(&r); + return 0; +} diff --git a/lrmi-0.9/Makefile b/lrmi-0.9/Makefile new file mode 100644 index 0000000..d286cc4 --- /dev/null +++ b/lrmi-0.9/Makefile @@ -0,0 +1,41 @@ +CFLAGS ?= -g -Wall + +sources = lrmi.c +objects = lrmi.o +all = vbetest mode3 vga_reset vbemodeinfo dosint + +%.o: %.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +all: $(all) + +vbetest: vbetest.c lrmi.o + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ + +mode3: mode3.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +dosint: dosint.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +vbemodeinfo: vbemodeinfo.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +vga_reset: vga_reset.c lrmi.o + $(CC) $(CFLAGS) -o $@ $^ + +install: mode3 vga_reset + install mode3 /sbin + install vga_reset /sbin + +.PHONY: clean +clean: + rm -f $(objects) $(all) core regs-out *.bak + +.PHONY: distclean +distclean: clean + rm -f .depend + +.PHONY: depend +depend: $(sources) + -$(CC) -M $(CPPFLAGS) $^ >.depend diff --git a/lrmi-0.9/Makefile.bsd b/lrmi-0.9/Makefile.bsd new file mode 100644 index 0000000..afaee3b --- /dev/null +++ b/lrmi-0.9/Makefile.bsd @@ -0,0 +1,34 @@ +CFLAGS = -g -Wall +RANLIB = ranlib +OS != uname -s + +sources = lrmi.c lrmi.h +objects = lrmi.o +pic_objects = lrmi.lo +all = liblrmi.a liblrmi.so vbetest +.if ${OS}=="NetBSD" || ${OS}=="OpenBSD" +libs= -li386 +.endif + +all: $(all) + +.c.o: + $(CC) -c $(CPPFLAGS) $(CFLAGS) -o ${.TARGET} ${.IMPSRC} + +.SUFFIXES: .lo +.c.lo: + $(CC) -c $(CPPFLAGS) $(CFLAGS) -fPIC -o ${.TARGET} ${.IMPSRC} + +liblrmi.a: $(objects) + $(AR) -r ${.TARGET} ${.ALLSRC} + $(RANLIB) ${.TARGET} + +liblrmi.so: $(pic_objects) + $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -shared -o ${.TARGET} ${.ALLSRC} ${libs} + +vbetest: vbetest.o liblrmi.a + $(CC) $(CPPFLAGS) $(CFLAGS) -o ${.TARGET} ${.ALLSRC} ${libs} + +.PHONY: clean +clean: + rm -f $(objects) $(pic_objects) vbetest.o $(all) *.core diff --git a/lrmi-0.9/Makefile.lrmi b/lrmi-0.9/Makefile.lrmi new file mode 100644 index 0000000..28ec944 --- /dev/null +++ b/lrmi-0.9/Makefile.lrmi @@ -0,0 +1,56 @@ +LIBDIR ?= /usr/local/lib +INCDIR ?= /usr/local/include + +CFLAGS = -g -Wall + +sources = lrmi.c +objects = lrmi.o +pic_objects = lrmi.lo +all = liblrmi.a liblrmi.so vbetest + +MAJOR = 0 +MINOR = 9 +VERSION = $(MAJOR).$(MINOR) +LIBNAME = liblrmi + +%.o: %.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< + +%.lo: %.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ $< + +all: $(all) + +liblrmi.a: $(objects) + $(AR) -rs $@ $^ + +liblrmi.so: $(pic_objects) +# $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -shared -o $@ $^ + $(CC) $(CPPFLAGS) $(CFLAGS) -Wl,-soname,$(LIBNAME).so.$(MAJOR) -fPIC -shared -o $(LIBNAME).so.$(VERSION) $^ + ln -sf $(LIBNAME).so.$(VERSION) $(LIBNAME).so.$(MAJOR) + ln -sf $(LIBNAME).so.$(MAJOR) $(LIBNAME).so + +vbetest: vbetest.c liblrmi.a + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ + +install: + mkdir -p $(LIBDIR) + install -m 755 -s -p $(LIBNAME).so.$(VERSION) $(LIBDIR)/$(LIBNAME).so.$(VERSION) + rm -f $(LIBDIR)/$(LIBNAME).so + ln -sf $(LIBNAME).so.$(VERSION) $(LIBDIR)/$(LIBNAME).so.$(MAJOR) + ln -sf $(LIBNAME).so.$(MAJOR) $(LIBDIR)/$(LIBNAME).so + install -m 644 -s -p lrmi.h $(INCDIR)/lrmi.h + -ldconfig + +.PHONY: clean +clean: + rm -f $(objects) $(pic_objects) $(all) core + rm -f liblrmi.so liblrmi.so.$(MAJOR) liblrmi.so.$(VERSION) + +.PHONY: distclean +distclean: clean + rm -f .depend + +.PHONY: depend +depend: $(sources) + -$(CC) -M $(CPPFLAGS) $^ >.depend diff --git a/lrmi-0.9/README b/lrmi-0.9/README new file mode 100644 index 0000000..36426c8 --- /dev/null +++ b/lrmi-0.9/README @@ -0,0 +1,19 @@ +This is a modified version of lrmi-0.9 package. +The original is available at http://sourceforge.net/projects/lrmi + + +Programs included are: + +vbetest - show available modes, and test a mode. + +vbegetmodeinfo - show information about a vbe mode. + +mode3 - set mode using vesa bios. It can usually restore text mode after + svgalib leaves a non-working text-mode. + +vga_reset - call real mode c000:0003, which should be the video card's + initialization routine. Should work in some cases when mode3 fails to + restore text mode. + +get-edid - Use vbe call to get monitor's edid information. + diff --git a/lrmi-0.9/README.lrmi b/lrmi-0.9/README.lrmi new file mode 100644 index 0000000..5e53cde --- /dev/null +++ b/lrmi-0.9/README.lrmi @@ -0,0 +1,39 @@ +Linux Real Mode Interface +========================= + +1, Goal + +This library provides a DPMI like interface under Linux and *BSD systems +using vm86. There is also some VBE (VESA Bios Extension) interface utility +called vbetest. + +2, Supported systems + +Only under x86: + +* Linux 2.2 and above +* FreeBSD +* NetBSD +* OpenBSD + +3, License + +Look into the individual source files. + +4, Authors + +Josh Vanderhoof +* original author + +Dmitry Frolov +* FreeBSD/NetBSD support + +Alex Beregszaszi +* merged MPlayer, MPlayerXP, svgalib and LRMI versions +* OpenBSD support + +Oleg I. Vdovikin +* pthread fixes + +Peter Kosinar +* pthread fixes diff --git a/lrmi-0.9/dosint.c b/lrmi-0.9/dosint.c new file mode 100644 index 0000000..dc929f6 --- /dev/null +++ b/lrmi-0.9/dosint.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + +#include "lrmi.h" + +unsigned char * edid = NULL; + +int read_edid() +{ + int i; + struct LRMI_regs regs; + + if (!LRMI_init()) { + return -1; + } + + edid = LRMI_alloc_real(128); + + if ( edid == NULL ) + { + return -1; + } + + memset(edid, 0xed, 128); + memset(®s, 0, sizeof(regs)); + + regs.es = (unsigned int)edid >> 4; + regs.edi = 0; + + regs.eax = 0x4f15; + regs.ebx = 0x01; + + ioperm(0,0x400,1); + iopl(3); + LRMI_int( 0x10, ®s ); + iopl(0); + ioperm(0,0x400,0); + + if(*edid || *(edid+7)) return -2; + for(i=1;i<=6;i++) if(*(edid+i)!=0xff) return -2; + + return regs.eax; +} + + +int main ( int argc, char *argv[]) +{ +read_edid(); +fwrite(edid,128,1,stdout); +return 0; +} diff --git a/lrmi-0.9/get-edid b/lrmi-0.9/get-edid new file mode 100755 index 0000000..7956716 --- /dev/null +++ b/lrmi-0.9/get-edid @@ -0,0 +1,2 @@ +#!/bin/sh +./dosint 0x10 0x4f15 0x0001 0x80 diff --git a/lrmi-0.9/lrmi.c b/lrmi-0.9/lrmi.c new file mode 100644 index 0000000..892a63a --- /dev/null +++ b/lrmi-0.9/lrmi.c @@ -0,0 +1,1043 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined(__OpenBSD__)) + +#include +#include + +#if defined(__linux__) + +#include +#include + +#ifdef USE_LIBC_VM86 +#include +#endif + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + +#include +#include +#include +#include +#include +#include + +#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ + +#include +#include +#include +#include +#include + +#include "lrmi.h" + +#define REAL_MEM_BASE ((void *)0x10000) +#define REAL_MEM_SIZE 0x40000 +#define REAL_MEM_BLOCKS 0x100 + +struct mem_block { + unsigned int size : 20; + unsigned int free : 1; +}; + +static struct { + int ready; + int count; + struct mem_block blocks[REAL_MEM_BLOCKS]; +} mem_info = { 0 }; + +static int +real_mem_init(void) +{ + void *m; + int fd_zero; + + if (mem_info.ready) + return 1; + + fd_zero = open("/dev/zero", O_RDONLY); + if (fd_zero == -1) { + perror("open /dev/zero"); + return 0; + } + + m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_zero, 0); + + if (m == (void *)-1) { + perror("mmap /dev/zero"); + close(fd_zero); + return 0; + } + + close(fd_zero); + + mem_info.ready = 1; + mem_info.count = 1; + mem_info.blocks[0].size = REAL_MEM_SIZE; + mem_info.blocks[0].free = 1; + + return 1; +} + +static void +real_mem_deinit(void) +{ + if (mem_info.ready) { + munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE); + mem_info.ready = 0; + } +} + + +static void +insert_block(int i) +{ + memmove( + mem_info.blocks + i + 1, + mem_info.blocks + i, + (mem_info.count - i) * sizeof(struct mem_block)); + + mem_info.count++; +} + +static void +delete_block(int i) +{ + mem_info.count--; + + memmove( + mem_info.blocks + i, + mem_info.blocks + i + 1, + (mem_info.count - i) * sizeof(struct mem_block)); +} + +void * +LRMI_alloc_real(int size) +{ + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return NULL; + + if (mem_info.count == REAL_MEM_BLOCKS) + return NULL; + + size = (size + 15) & ~15; + + for (i = 0; i < mem_info.count; i++) { + if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) { + insert_block(i); + + mem_info.blocks[i].size = size; + mem_info.blocks[i].free = 0; + mem_info.blocks[i + 1].size -= size; + + return (void *)r; + } + + r += mem_info.blocks[i].size; + } + + return NULL; +} + + +void +LRMI_free_real(void *m) +{ + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return; + + i = 0; + while (m != (void *)r) { + r += mem_info.blocks[i].size; + i++; + if (i == mem_info.count) + return; + } + + mem_info.blocks[i].free = 1; + + if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) { + mem_info.blocks[i].size += mem_info.blocks[i + 1].size; + delete_block(i + 1); + } + + if (i - 1 >= 0 && mem_info.blocks[i - 1].free) { + mem_info.blocks[i - 1].size += mem_info.blocks[i].size; + delete_block(i); + } +} + + +#if defined(__linux__) +#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK) +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#define DEFAULT_VM86_FLAGS (PSL_I | PSL_IOPL) +#define TF_MASK PSL_T +#define VIF_MASK PSL_VIF +#endif +#define DEFAULT_STACK_SIZE 0x1000 +#define RETURN_TO_32_INT 255 + +#if defined(__linux__) +#define CONTEXT_REGS context.vm.regs +#define REG(x) x +#elif defined(__NetBSD__) || defined(__OpenBSD__) +#define CONTEXT_REGS context.vm.substr.regs +#define REG(x) vmsc.sc_ ## x +#elif defined(__FreeBSD__) +#define CONTEXT_REGS context.vm.uc +#define REG(x) uc_mcontext.mc_ ## x +#endif + +static struct { + int ready; + unsigned short ret_seg, ret_off; + unsigned short stack_seg, stack_off; +#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) + struct vm86_struct vm; +#elif defined(__FreeBSD__) + struct { + struct vm86_init_args init; + ucontext_t uc; + } vm; +#endif +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + int success; + jmp_buf env; + void *old_sighandler; + int vret; +#endif +} context = { 0 }; + + +static inline void +set_bit(unsigned int bit, void *array) +{ + unsigned char *a = array; + + a[bit / 8] |= (1 << (bit % 8)); +} + + +static inline unsigned int +get_int_seg(int i) +{ + return *(unsigned short *)(i * 4 + 2); +} + + +static inline unsigned int +get_int_off(int i) +{ + return *(unsigned short *)(i * 4); +} + + +static inline void +pushw(unsigned short i) +{ + CONTEXT_REGS.REG(esp) -= 2; + *(unsigned short *)(((unsigned int)CONTEXT_REGS.REG(ss) << 4) + + CONTEXT_REGS.REG(esp)) = i; +} + + +int +LRMI_init(void) +{ + void *m; + int fd_mem; + + if (context.ready) + return 1; + + if (!real_mem_init()) + return 0; + + /* + Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) + and the ROM (0xa0000 - 0x100000) + */ + fd_mem = open("/dev/mem", O_RDWR); + + if (fd_mem == -1) { + real_mem_deinit(); + perror("open /dev/mem"); + return 0; + } + + m = mmap((void *)0, 0x502, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_mem, 0); + + if (m == (void *)-1) { + close(fd_mem); + real_mem_deinit(); + perror("mmap /dev/mem"); + return 0; + } + + m = mmap((void *)0xa0000, 0x100000 - 0xa0000, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); + + if (m == (void *)-1) { + munmap((void *)0, 0x502); + close(fd_mem); + real_mem_deinit(); + perror("mmap /dev/mem"); + return 0; + } + + close(fd_mem); + + + /* + Allocate a stack + */ + m = LRMI_alloc_real(DEFAULT_STACK_SIZE); + + context.stack_seg = (unsigned int)m >> 4; + context.stack_off = DEFAULT_STACK_SIZE; + + /* + Allocate the return to 32 bit routine + */ + m = LRMI_alloc_real(2); + + context.ret_seg = (unsigned int)m >> 4; + context.ret_off = (unsigned int)m & 0xf; + + ((unsigned char *)m)[0] = 0xcd; /* int opcode */ + ((unsigned char *)m)[1] = RETURN_TO_32_INT; + + memset(&context.vm, 0, sizeof(context.vm)); + + /* + Enable kernel emulation of all ints except RETURN_TO_32_INT + */ +#if defined(__linux__) + memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); + set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + set_bit(RETURN_TO_32_INT, &context.vm.int_byuser); +#elif defined(__FreeBSD__) + set_bit(RETURN_TO_32_INT, &context.vm.init.int_map); +#endif + + context.ready = 1; + + return 1; +} + + +static void +set_regs(struct LRMI_regs *r) +{ + CONTEXT_REGS.REG(edi) = r->edi; + CONTEXT_REGS.REG(esi) = r->esi; + CONTEXT_REGS.REG(ebp) = r->ebp; + CONTEXT_REGS.REG(ebx) = r->ebx; + CONTEXT_REGS.REG(edx) = r->edx; + CONTEXT_REGS.REG(ecx) = r->ecx; + CONTEXT_REGS.REG(eax) = r->eax; + CONTEXT_REGS.REG(eflags) = DEFAULT_VM86_FLAGS; + CONTEXT_REGS.REG(es) = r->es; + CONTEXT_REGS.REG(ds) = r->ds; + CONTEXT_REGS.REG(fs) = r->fs; + CONTEXT_REGS.REG(gs) = r->gs; +} + + +static void +get_regs(struct LRMI_regs *r) +{ + r->edi = CONTEXT_REGS.REG(edi); + r->esi = CONTEXT_REGS.REG(esi); + r->ebp = CONTEXT_REGS.REG(ebp); + r->ebx = CONTEXT_REGS.REG(ebx); + r->edx = CONTEXT_REGS.REG(edx); + r->ecx = CONTEXT_REGS.REG(ecx); + r->eax = CONTEXT_REGS.REG(eax); + r->flags = CONTEXT_REGS.REG(eflags); + r->es = CONTEXT_REGS.REG(es); + r->ds = CONTEXT_REGS.REG(ds); + r->fs = CONTEXT_REGS.REG(fs); + r->gs = CONTEXT_REGS.REG(gs); +} + +#define DIRECTION_FLAG (1 << 10) + +enum { + CSEG = 0x2e, SSEG = 0x36, DSEG = 0x3e, + ESEG = 0x26, FSEG = 0x64, GSEG = 0x65, +}; + +static void +em_ins(int size) +{ + unsigned int edx, edi; + + edx = CONTEXT_REGS.REG(edx) & 0xffff; + edi = CONTEXT_REGS.REG(edi) & 0xffff; + edi += (unsigned int)CONTEXT_REGS.REG(es) << 4; + + if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) { + if (size == 4) + asm volatile ("std; insl; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("std; insw; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("std; insb; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + } else { + if (size == 4) + asm volatile ("cld; insl" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("cld; insw" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("cld; insb" + : "=D" (edi) : "d" (edx), "0" (edi)); + } + + edi -= (unsigned int)CONTEXT_REGS.REG(es) << 4; + + CONTEXT_REGS.REG(edi) &= 0xffff0000; + CONTEXT_REGS.REG(edi) |= edi & 0xffff; +} + +static void +em_rep_ins(int size) +{ + unsigned int cx; + + cx = CONTEXT_REGS.REG(ecx) & 0xffff; + + while (cx--) + em_ins(size); + + CONTEXT_REGS.REG(ecx) &= 0xffff0000; +} + +static void +em_outs(int size, int seg) +{ + unsigned int edx, esi, base; + + edx = CONTEXT_REGS.REG(edx) & 0xffff; + esi = CONTEXT_REGS.REG(esi) & 0xffff; + + switch (seg) { + case CSEG: base = CONTEXT_REGS.REG(cs); break; + case SSEG: base = CONTEXT_REGS.REG(ss); break; + case ESEG: base = CONTEXT_REGS.REG(es); break; + case FSEG: base = CONTEXT_REGS.REG(fs); break; + case GSEG: base = CONTEXT_REGS.REG(gs); break; + default: + case DSEG: base = CONTEXT_REGS.REG(ds); break; + } + + esi += base << 4; + + if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) { + if (size == 4) + asm volatile ("std; outsl; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("std; outsw; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("std; outsb; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + } else { + if (size == 4) + asm volatile ("cld; outsl" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("cld; outsw" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("cld; outsb" + : "=S" (esi) : "d" (edx), "0" (esi)); + } + + esi -= base << 4; + + CONTEXT_REGS.REG(esi) &= 0xffff0000; + CONTEXT_REGS.REG(esi) |= esi & 0xffff; +} + +static void +em_rep_outs(int size, int seg) +{ + unsigned int cx; + + cx = CONTEXT_REGS.REG(ecx) & 0xffff; + + while (cx--) + em_outs(size, seg); + + CONTEXT_REGS.REG(ecx) &= 0xffff0000; +} + +static void +em_inbl(unsigned char literal) +{ + asm volatile ("inb %w1, %b0" + : "=a" (CONTEXT_REGS.REG(eax)) + : "d" (literal), "0" (CONTEXT_REGS.REG(eax))); +} + +static void +em_inb(void) +{ + asm volatile ("inb %w1, %b0" + : "=a" (CONTEXT_REGS.REG(eax)) + : "d" (CONTEXT_REGS.REG(edx)), "0" (CONTEXT_REGS.REG(eax))); +} + +static void +em_inw(void) +{ + asm volatile ("inw %w1, %w0" + : "=a" (CONTEXT_REGS.REG(eax)) + : "d" (CONTEXT_REGS.REG(edx)), "0" (CONTEXT_REGS.REG(eax))); +} + +static void +em_inl(void) +{ + asm volatile ("inl %w1, %0" + : "=a" (CONTEXT_REGS.REG(eax)) + : "d" (CONTEXT_REGS.REG(edx))); +} + +static void +em_outbl(unsigned char literal) +{ + asm volatile ("outb %b0, %w1" + : : "a" (CONTEXT_REGS.REG(eax)), + "d" (literal)); +} + +static void +em_outb(void) +{ + asm volatile ("outb %b0, %w1" + : : "a" (CONTEXT_REGS.REG(eax)), + "d" (CONTEXT_REGS.REG(edx))); +} + +static void +em_outw(void) +{ + asm volatile ("outw %w0, %w1" + : : "a" (CONTEXT_REGS.REG(eax)), + "d" (CONTEXT_REGS.REG(edx))); +} + +static void +em_outl(void) +{ + asm volatile ("outl %0, %w1" + : : "a" (CONTEXT_REGS.REG(eax)), + "d" (CONTEXT_REGS.REG(edx))); +} + +static int +emulate(void) +{ + unsigned char *insn; + struct { + unsigned char seg; + unsigned int size : 1; + unsigned int rep : 1; + } prefix = { DSEG, 0, 0 }; + int i = 0; + + insn = (unsigned char *)((unsigned int)CONTEXT_REGS.REG(cs) << 4); + insn += CONTEXT_REGS.REG(eip); + + while (1) { + if (insn[i] == 0x66) { + prefix.size = 1 - prefix.size; + i++; + } else if (insn[i] == 0xf3) { + prefix.rep = 1; + i++; + } else if (insn[i] == CSEG || insn[i] == SSEG + || insn[i] == DSEG || insn[i] == ESEG + || insn[i] == FSEG || insn[i] == GSEG) { + prefix.seg = insn[i]; + i++; + } else if (insn[i] == 0xf0 || insn[i] == 0xf2 + || insn[i] == 0x67) { + /* these prefixes are just ignored */ + i++; + } else if (insn[i] == 0x6c) { + if (prefix.rep) + em_rep_ins(1); + else + em_ins(1); + i++; + break; + } else if (insn[i] == 0x6d) { + if (prefix.rep) { + if (prefix.size) + em_rep_ins(4); + else + em_rep_ins(2); + } else { + if (prefix.size) + em_ins(4); + else + em_ins(2); + } + i++; + break; + } else if (insn[i] == 0x6e) { + if (prefix.rep) + em_rep_outs(1, prefix.seg); + else + em_outs(1, prefix.seg); + i++; + break; + } else if (insn[i] == 0x6f) { + if (prefix.rep) { + if (prefix.size) + em_rep_outs(4, prefix.seg); + else + em_rep_outs(2, prefix.seg); + } else { + if (prefix.size) + em_outs(4, prefix.seg); + else + em_outs(2, prefix.seg); + } + i++; + break; + } else if (insn[i] == 0xe4) { + em_inbl(insn[i + 1]); + i += 2; + break; + } else if (insn[i] == 0xec) { + em_inb(); + i++; + break; + } else if (insn[i] == 0xed) { + if (prefix.size) + em_inl(); + else + em_inw(); + i++; + break; + } else if (insn[i] == 0xe6) { + em_outbl(insn[i + 1]); + i += 2; + break; + } else if (insn[i] == 0xee) { + em_outb(); + i++; + break; + } else if (insn[i] == 0xef) { + if (prefix.size) + em_outl(); + else + em_outw(); + + i++; + break; + } else + return 0; + } + + CONTEXT_REGS.REG(eip) += i; + return 1; +} + + +#if defined(__linux__) +/* + I don't know how to make sure I get the right vm86() from libc. + The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) + which should be declared as "int vm86(struct vm86_struct *);" in + . + + This just does syscall 113 with inline asm, which should work + for both libc's (I hope). +*/ +#if !defined(USE_LIBC_VM86) +static int +lrmi_vm86(struct vm86_struct *vm) +{ + int r; +#ifdef __PIC__ + asm volatile ( + "pushl %%ebx\n\t" + "movl %2, %%ebx\n\t" + "int $0x80\n\t" + "popl %%ebx" + : "=a" (r) + : "0" (113), "r" (vm)); +#else + asm volatile ( + "int $0x80" + : "=a" (r) + : "0" (113), "b" (vm)); +#endif + return r; +} +#else +#define lrmi_vm86 vm86 +#endif +#endif /* __linux__ */ + + +static void +debug_info(int vret) +{ +#ifdef LRMI_DEBUG + int i; + unsigned char *p; + + fputs("vm86() failed\n", stderr); + fprintf(stderr, "return = 0x%x\n", vret); + fprintf(stderr, "eax = 0x%08x\n", CONTEXT_REGS.REG(eax)); + fprintf(stderr, "ebx = 0x%08x\n", CONTEXT_REGS.REG(ebx)); + fprintf(stderr, "ecx = 0x%08x\n", CONTEXT_REGS.REG(ecx)); + fprintf(stderr, "edx = 0x%08x\n", CONTEXT_REGS.REG(edx)); + fprintf(stderr, "esi = 0x%08x\n", CONTEXT_REGS.REG(esi)); + fprintf(stderr, "edi = 0x%08x\n", CONTEXT_REGS.REG(edi)); + fprintf(stderr, "ebp = 0x%08x\n", CONTEXT_REGS.REG(ebp)); + fprintf(stderr, "eip = 0x%08x\n", CONTEXT_REGS.REG(eip)); + fprintf(stderr, "cs = 0x%04x\n", CONTEXT_REGS.REG(cs)); + fprintf(stderr, "esp = 0x%08x\n", CONTEXT_REGS.REG(esp)); + fprintf(stderr, "ss = 0x%04x\n", CONTEXT_REGS.REG(ss)); + fprintf(stderr, "ds = 0x%04x\n", CONTEXT_REGS.REG(ds)); + fprintf(stderr, "es = 0x%04x\n", CONTEXT_REGS.REG(es)); + fprintf(stderr, "fs = 0x%04x\n", CONTEXT_REGS.REG(fs)); + fprintf(stderr, "gs = 0x%04x\n", CONTEXT_REGS.REG(gs)); + fprintf(stderr, "eflags = 0x%08x\n", CONTEXT_REGS.REG(eflags)); + + fputs("cs:ip = [ ", stderr); + + p = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) + (CONTEXT_REGS.REG(eip) & 0xffff)); + + for (i = 0; i < 16; ++i) + fprintf(stderr, "%02x ", (unsigned int)p[i]); + + fputs("]\n", stderr); +#endif +} + + +#if defined(__linux__) +static int +run_vm86(void) +{ + unsigned int vret; + sigset_t all_sigs, old_sigs; + unsigned long old_gs, old_fs; + + while (1) { + // FIXME: may apply this to BSD equivalents? + sigfillset(&all_sigs); + sigprocmask(SIG_SETMASK, &all_sigs, &old_sigs); + asm volatile ("movl %%gs, %0" : "=rm" (old_gs)); + asm volatile ("movl %%fs, %0" : "=rm" (old_fs)); + vret = lrmi_vm86(&context.vm); + asm volatile ("movl %0, %%gs" :: "rm" (old_gs)); + asm volatile ("movl %0, %%fs" :: "rm" (old_fs)); + sigprocmask(SIG_SETMASK, &old_sigs, NULL); + + if (VM86_TYPE(vret) == VM86_INTx) { + unsigned int v = VM86_ARG(vret); + + if (v == RETURN_TO_32_INT) + return 1; + + pushw(CONTEXT_REGS.REG(eflags)); + pushw(CONTEXT_REGS.REG(cs)); + pushw(CONTEXT_REGS.REG(eip)); + + CONTEXT_REGS.REG(cs) = get_int_seg(v); + CONTEXT_REGS.REG(eip) = get_int_off(v); + CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); + + continue; + } + + if (VM86_TYPE(vret) != VM86_UNKNOWN) + break; + + if (!emulate()) + break; + } + + debug_info(vret); + + return 0; +} +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__NetBSD__) || defined(__OpenBSD__) +static void +vm86_callback(int sig, int code, struct sigcontext *sc) +{ + /* Sync our context with what the kernel develivered to us. */ + memcpy(&CONTEXT_REGS, sc, sizeof(*sc)); + + switch (VM86_TYPE(code)) { + case VM86_INTx: + { + unsigned int v = VM86_ARG(code); + + if (v == RETURN_TO_32_INT) { + context.success = 1; + longjmp(context.env, 1); + } + + pushw(CONTEXT_REGS.REG(eflags)); + pushw(CONTEXT_REGS.REG(cs)); + pushw(CONTEXT_REGS.REG(eip)); + + CONTEXT_REGS.REG(cs) = get_int_seg(v); + CONTEXT_REGS.REG(eip) = get_int_off(v); + CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); + + break; + } + + case VM86_UNKNOWN: + if (emulate() == 0) { + context.success = 0; + context.vret = code; + longjmp(context.env, 1); + } + break; + + default: + context.success = 0; + context.vret = code; + longjmp(context.env, 1); + return; + } + + /* ...and sync our context back to the kernel. */ + memcpy(sc, &CONTEXT_REGS, sizeof(*sc)); +} +#elif defined(__FreeBSD__) +static void +vm86_callback(int sig, int code, struct sigcontext *sc) +{ + unsigned char *addr; + + /* Sync our context with what the kernel develivered to us. */ + memcpy(&CONTEXT_REGS, sc, sizeof(*sc)); + + if (code) { + /* XXX probably need to call original signal handler here */ + context.success = 0; + context.vret = code; + longjmp(context.env, 1); + } + + addr = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) + + CONTEXT_REGS.REG(eip)); + + if (addr[0] == 0xcd) { /* int opcode */ + if (addr[1] == RETURN_TO_32_INT) { + context.success = 1; + longjmp(context.env, 1); + } + + pushw(CONTEXT_REGS.REG(eflags)); + pushw(CONTEXT_REGS.REG(cs)); + pushw(CONTEXT_REGS.REG(eip)); + + CONTEXT_REGS.REG(cs) = get_int_seg(addr[1]); + CONTEXT_REGS.REG(eip) = get_int_off(addr[1]); + CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); + } else { + if (emulate() == 0) { + context.success = 0; + longjmp(context.env, 1); + } + } + + /* ...and sync our context back to the kernel. */ + memcpy(sc, &CONTEXT_REGS, sizeof(*sc)); +} +#endif /* __FreeBSD__ */ + +static int +run_vm86(void) +{ + if (context.old_sighandler) { +#ifdef LRMI_DEBUG + fprintf(stderr, "run_vm86: callback already installed\n"); +#endif + return (0); + } + +#if defined(__NetBSD__) || defined(__OpenBSD__) + context.old_sighandler = signal(SIGURG, (void (*)(int))vm86_callback); +#elif defined(__FreeBSD__) + context.old_sighandler = signal(SIGBUS, (void (*)(int))vm86_callback); +#endif + + if (context.old_sighandler == (void *)-1) { + context.old_sighandler = NULL; +#ifdef LRMI_DEBUG + fprintf(stderr, "run_vm86: cannot install callback\n"); +#endif + return (0); + } + + if (setjmp(context.env)) { +#if defined(__NetBSD__) || defined(__OpenBSD__) + (void) signal(SIGURG, context.old_sighandler); +#elif defined(__FreeBSD__) + (void) signal(SIGBUS, context.old_sighandler); +#endif + context.old_sighandler = NULL; + + if (context.success) + return (1); + debug_info(context.vret); + return (0); + } + +#if defined(__NetBSD__) || defined(__OpenBSD__) + if (i386_vm86(&context.vm) == -1) + return (0); +#elif defined(__FreeBSD__) + if (i386_vm86(VM86_INIT, &context.vm.init)) + return 0; + + CONTEXT_REGS.REG(eflags) |= PSL_VM | PSL_VIF; + sigreturn(&context.vm.uc); +#endif /* __FreeBSD__ */ + + /* NOTREACHED */ + return (0); +} +#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ + +int +LRMI_call(struct LRMI_regs *r) +{ + unsigned int vret; + + memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS)); + + set_regs(r); + + CONTEXT_REGS.REG(cs) = r->cs; + CONTEXT_REGS.REG(eip) = r->ip; + + if (r->ss == 0 && r->sp == 0) { + CONTEXT_REGS.REG(ss) = context.stack_seg; + CONTEXT_REGS.REG(esp) = context.stack_off; + } else { + CONTEXT_REGS.REG(ss) = r->ss; + CONTEXT_REGS.REG(esp) = r->sp; + } + + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; +} + + +int +LRMI_int(int i, struct LRMI_regs *r) +{ + unsigned int vret; + unsigned int seg, off; + + seg = get_int_seg(i); + off = get_int_off(i); + + /* + If the interrupt is in regular memory, it's probably + still pointing at a dos TSR (which is now gone). + */ + if (seg < 0xa000 || (seg << 4) + off >= 0x100000) { +#ifdef LRMI_DEBUG + fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); +#endif + return 0; + } + + memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS)); + + set_regs(r); + + CONTEXT_REGS.REG(cs) = seg; + CONTEXT_REGS.REG(eip) = off; + + if (r->ss == 0 && r->sp == 0) { + CONTEXT_REGS.REG(ss) = context.stack_seg; + CONTEXT_REGS.REG(esp) = context.stack_off; + } else { + CONTEXT_REGS.REG(ss) = r->ss; + CONTEXT_REGS.REG(esp) = r->sp; + } + + pushw(DEFAULT_VM86_FLAGS); + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; +} + +#else /* (__linux__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__) && __i386__ */ +#warning "LRMI is not supported on your system!" +#endif diff --git a/lrmi-0.9/lrmi.h b/lrmi-0.9/lrmi.h new file mode 100644 index 0000000..1f7f0ee --- /dev/null +++ b/lrmi-0.9/lrmi.h @@ -0,0 +1,108 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef LRMI_H +#define LRMI_H + +#if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined(__OpenBSD__)) + +struct LRMI_regs { + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int reserved; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + unsigned short int flags; + unsigned short int es; + unsigned short int ds; + unsigned short int fs; + unsigned short int gs; + unsigned short int ip; + unsigned short int cs; + unsigned short int sp; + unsigned short int ss; +}; + +#ifndef LRMI_PREFIX +#define LRMI_PREFIX LRMI_ +#endif + +#define LRMI_CONCAT2(a, b) a ## b +#define LRMI_CONCAT(a, b) LRMI_CONCAT2(a, b) +#define LRMI_MAKENAME(a) LRMI_CONCAT(LRMI_PREFIX, a) + +/* + Package version (high 16bit = major, low 16bit minor) +*/ +#define LRMI_version 0x0009 /* 0.9 */ + +/* + Initialize + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_init LRMI_MAKENAME(init) +int +LRMI_init(void); + +/* + Simulate a 16 bit far call + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_call LRMI_MAKENAME(call) +int +LRMI_call(struct LRMI_regs *r); + +/* + Simulate a 16 bit interrupt + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_int LRMI_MAKENAME(int) +int +LRMI_int(int interrupt, struct LRMI_regs *r); + +/* + Allocate real mode memory + The returned block is paragraph (16 byte) aligned +*/ +#define LRMI_alloc_real LRMI_MAKENAME(alloc_real) +void * +LRMI_alloc_real(int size); + +/* + Free real mode memory +*/ +#define LRMI_free_real LRMI_MAKENAME(free_real) +void +LRMI_free_real(void *m); + +#else /* (__linux__ || __NetBSD__ || __FreeBSD__) && __i386__ */ +#warning "LRMI is not supported on your system!" +#endif + +#endif diff --git a/lrmi-0.9/mode3.c b/lrmi-0.9/mode3.c new file mode 100644 index 0000000..48db622 --- /dev/null +++ b/lrmi-0.9/mode3.c @@ -0,0 +1,53 @@ +/* +Set mode to VESA mode 3 (80x25 text mode) +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lrmi.h" + +void set_vesa_mode(int mode){ + struct LRMI_regs r; + memset(&r, 0, sizeof(r)); + r.eax = 0x4f02; + r.ebx = mode; + if (!LRMI_int(0x10, &r)) + { + fprintf(stderr, "Can't set video mode (vm86 failure)\n"); + } + } + +int main(int argc, char *argv[]){ + int i; + + + if((argc>1)&&(!strcmp(argv[1],"-h"))){ + printf("Usage: mode3 [ modenum [ font ] ]\n" + "\n" + "uses VESA bios to set video mode to modenum (3 by default)\n" + "if font is given, uses setfont to change the screen font\n\n"); + return 0; + }; + if (!LRMI_init()) + return 1; + ioperm(0, 0x400, 1); + iopl(3); + i=3; + if(argc>1){ + sscanf(argv[1],"%i",&i); + if((i<=0))i=3; + }; + set_vesa_mode(i); + if(argc>2){ + execlp("setfont",argv[2],NULL); + return 1; + }; + return 0; +} diff --git a/lrmi-0.9/vbe.h b/lrmi-0.9/vbe.h new file mode 100644 index 0000000..83efa4c --- /dev/null +++ b/lrmi-0.9/vbe.h @@ -0,0 +1,95 @@ +/* +This file is in the public domain. +*/ + +#ifndef _VBE_H +#define _VBE_H + +/* structures for vbe 2.0 */ + +struct vbe_info_block { + char vbe_signature[4]; + short vbe_version; + unsigned short oem_string_off; + unsigned short oem_string_seg; + int capabilities; + unsigned short video_mode_list_off; + unsigned short video_mode_list_seg; + short total_memory; + short oem_software_rev; + unsigned short oem_vendor_name_off; + unsigned short oem_vendor_name_seg; + unsigned short oem_product_name_off; + unsigned short oem_product_name_seg; + unsigned short oem_product_rev_off; + unsigned short oem_product_rev_seg; + char reserved[222]; + char oem_data[256]; +} __attribute__ ((packed)); + +#define VBE_ATTR_MODE_SUPPORTED (1 << 0) +#define VBE_ATTR_TTY (1 << 2) +#define VBE_ATTR_COLOR (1 << 3) +#define VBE_ATTR_GRAPHICS (1 << 4) +#define VBE_ATTR_NOT_VGA (1 << 5) +#define VBE_ATTR_NOT_WINDOWED (1 << 6) +#define VBE_ATTR_LINEAR (1 << 7) + +#define VBE_WIN_RELOCATABLE (1 << 0) +#define VBE_WIN_READABLE (1 << 1) +#define VBE_WIN_WRITEABLE (1 << 2) + +#define VBE_MODEL_TEXT 0 +#define VBE_MODEL_CGA 1 +#define VBE_MODEL_HERCULES 2 +#define VBE_MODEL_PLANAR 3 +#define VBE_MODEL_PACKED 4 +#define VBE_MODEL_256 5 +#define VBE_MODEL_RGB 6 +#define VBE_MODEL_YUV 7 + +struct vbe_mode_info_block { + unsigned short mode_attributes; + unsigned char win_a_attributes; + unsigned char win_b_attributes; + unsigned short win_granularity; + unsigned short win_size; + unsigned short win_a_segment; + unsigned short win_b_segment; + unsigned short win_func_ptr_off; + unsigned short win_func_ptr_seg; + unsigned short bytes_per_scanline; + unsigned short x_resolution; + unsigned short y_resolution; + unsigned char x_char_size; + unsigned char y_char_size; + unsigned char number_of_planes; + unsigned char bits_per_pixel; + unsigned char number_of_banks; + unsigned char memory_model; + unsigned char bank_size; + unsigned char number_of_image_pages; + unsigned char res1; + unsigned char red_mask_size; + unsigned char red_field_position; + unsigned char green_mask_size; + unsigned char green_field_position; + unsigned char blue_mask_size; + unsigned char blue_field_position; + unsigned char rsvd_mask_size; + unsigned char rsvd_field_position; + unsigned char direct_color_mode_info; + unsigned int phys_base_ptr; + unsigned int offscreen_mem_offset; + unsigned short offscreen_mem_size; + unsigned char res2[206]; +} __attribute__ ((packed)); + +struct vbe_palette_entry { + unsigned char blue; + unsigned char green; + unsigned char red; + unsigned char align; +} __attribute__ ((packed)); + +#endif diff --git a/lrmi-0.9/vbemodeinfo.c b/lrmi-0.9/vbemodeinfo.c new file mode 100644 index 0000000..66c19c1 --- /dev/null +++ b/lrmi-0.9/vbemodeinfo.c @@ -0,0 +1,133 @@ +/* +List the available VESA graphics and text modes. + +This program is in the public domain. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lrmi.h" +#include "vbe.h" + +struct + { + struct vbe_info_block *info; + struct vbe_mode_info_block *mode; + } vbe; + +int +main(int argc, char *argv[]) { + struct LRMI_regs r; + int mode; + + if((argc!=2)||((mode=atoi(argv[1]))==0)){ + printf("usage: vbemodeinfo \n" + "where is a vesa mode numder.\n" + "use vbetest to list available modes\n\n"); + return 0; + }; + + if (!LRMI_init()) + return 1; + + vbe.info = LRMI_alloc_real(sizeof(struct vbe_info_block) + + sizeof(struct vbe_mode_info_block)); + + if (vbe.info == NULL) { + fprintf(stderr, "Can't alloc real mode memory\n"); + return 1; + } + + vbe.mode = (struct vbe_mode_info_block *)(vbe.info + 1); + + /* + Allow read/write to all IO ports + */ + ioperm(0, 0x400 , 1); + iopl(3); + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f00; + r.es = (unsigned int)vbe.info >> 4; + r.edi = 0; + + memcpy(vbe.info->vbe_signature, "VBE2", 4); + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get VESA info (vm86 failure)\n"); + return 1; + } + + if ((r.eax & 0xffff) != 0x4f || strncmp(vbe.info->vbe_signature, "VESA", 4) != 0) { + fprintf(stderr, "No VESA bios\n"); + return 1; + } + + printf("VBE Version %x.%x\n", + (int)(vbe.info->vbe_version >> 8) & 0xff, + (int)vbe.info->vbe_version & 0xff); + + printf("%s\n", + (char *)(vbe.info->oem_string_seg * 16 + vbe.info->oem_string_off)); + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f01; + r.ecx = mode; + r.es = (unsigned int)vbe.mode >> 4; + r.edi = (unsigned int)vbe.mode & 0xf; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return 1; + } + + printf("mode %i\n",mode); + + printf ("mode_attributes = %i\n", vbe.mode->mode_attributes); + printf ("win_a_attributes = %i\n", vbe.mode->win_a_attributes); + printf ("win_b_attributes = %i\n", vbe.mode->win_b_attributes); + printf ("win_granularity = %i\n", vbe.mode->win_granularity); + printf ("win_size = %i\n", vbe.mode->win_size); + printf ("win_a_segment = %i\n", vbe.mode->win_a_segment); + printf ("win_b_segment = %i\n", vbe.mode->win_b_segment); + printf ("win_func_ptr_off = %i\n", vbe.mode->win_func_ptr_off); + printf ("win_func_ptr_seg = %i\n", vbe.mode->win_func_ptr_seg); + printf ("bytes_per_scanline = %i\n", vbe.mode->bytes_per_scanline); + printf ("x_resolution = %i\n", vbe.mode->x_resolution); + printf ("y_resolution = %i\n", vbe.mode->y_resolution); + printf ("x_char_size = %i\n", vbe.mode->x_char_size); + printf ("y_char_size = %i\n", vbe.mode->y_char_size); + printf ("number_of_planes = %i\n", vbe.mode->number_of_planes); + printf ("bits_per_pixel = %i\n", vbe.mode->bits_per_pixel); + printf ("number_of_banks = %i\n", vbe.mode->number_of_banks); + printf ("memory_model = %i\n", vbe.mode->memory_model); + printf ("bank_size = %i\n", vbe.mode->bank_size); + printf ("number_of_image_pages = %i\n", vbe.mode->number_of_image_pages); + printf ("res1 = %i\n", vbe.mode->res1); + printf ("red_mask_size = %i\n", vbe.mode->red_mask_size); + printf ("red_field_position = %i\n", vbe.mode->red_field_position); + printf ("green_mask_size = %i\n", vbe.mode->green_mask_size); + printf ("green_field_position = %i\n", vbe.mode->green_field_position); + printf ("blue_mask_size = %i\n", vbe.mode->blue_mask_size); + printf ("blue_field_position = %i\n", vbe.mode->blue_field_position); + printf ("rsvd_mask_size = %i\n", vbe.mode->rsvd_mask_size); + printf ("rsvd_field_position = %i\n", vbe.mode->rsvd_field_position); + printf ("direct_color_mode_info = %i\n", vbe.mode->direct_color_mode_info); + printf ("phys_base_ptr = %i\n", vbe.mode->phys_base_ptr); + printf ("offscreen_mem_offset = %i\n", vbe.mode->offscreen_mem_offset); + printf ("offscreen_mem_size = %i\n", vbe.mode->offscreen_mem_size); + + + LRMI_free_real(vbe.info); + + return 0; +} diff --git a/lrmi-0.9/vbetest.c b/lrmi-0.9/vbetest.c new file mode 100644 index 0000000..3d6dd1f --- /dev/null +++ b/lrmi-0.9/vbetest.c @@ -0,0 +1,450 @@ +/* +List the available VESA graphics modes. + +This program is in the public domain. +*/ + +#include +#include +#include +#include +#include +#if defined(__linux__) +#include +#include +#include +#elif defined(__NetBSD__) || defined(__OpenBSD__) +#include +#include +#include +#elif defined(__FreeBSD__) +#include +#include +#endif + +#include "lrmi.h" +#include "vbe.h" + +struct { + struct vbe_info_block *info; + struct vbe_mode_info_block *mode; + char *win; /* this doesn't point directly at the window, see update_window() */ + int win_low, win_high; +} vbe; + +static char *run_command = NULL; + +void * +save_state(void) +{ + struct LRMI_regs r; + void *buffer; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 0; /* get buffer size */ + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get video state buffer size (vm86 failure)\n"); + return NULL; + } + + if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Get video state buffer size failed\n"); + return NULL; + } + + buffer = LRMI_alloc_real((r.ebx & 0xffff) * 64); + + if (buffer == NULL) { + fprintf(stderr, "Can't allocate video state buffer\n"); + return NULL; + } + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 1; /* save state */ + r.es = (unsigned int)buffer >> 4; + r.ebx = (unsigned int)buffer & 0xf; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't save video state (vm86 failure)\n"); + return NULL; + } + + if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Save video state failed\n"); + return NULL; + } + + return buffer; +} + +void +restore_state(void *buffer) +{ + struct LRMI_regs r; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 2; /* restore state */ + r.es = (unsigned int)buffer >> 4; + r.ebx = (unsigned int)buffer & 0xf; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't restore video state (vm86 failure)\n"); + } else if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Restore video state failed\n"); + } + + LRMI_free_real(buffer); +} + +void +text_mode(void) +{ + struct LRMI_regs r; + + memset(&r, 0, sizeof(r)); + + r.eax = 3; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't set text mode (vm86 failure)\n"); + } +} + +int +update_window(int address) +{ + struct LRMI_regs r; + int w, g; + + if (address >= vbe.win_low && address < vbe.win_high) + return 0; + + g = vbe.mode->win_granularity * 1024; + w = address / g; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f05; + r.ebx = 0; + r.edx = w; + + LRMI_int(0x10, &r); + + vbe.win_low = w * g; + vbe.win_high = vbe.win_low + vbe.mode->win_size * 1024; + + vbe.win = (char *)(vbe.mode->win_a_segment << 4); + vbe.win -= vbe.win_low; + + return 1; +} + +void +set_pixel(int x, int y, int r, int g, int b) +{ + int x_res = vbe.mode->x_resolution; + int y_res = vbe.mode->y_resolution; + int shift_r = vbe.mode->red_field_position; + int shift_g = vbe.mode->green_field_position; + int shift_b = vbe.mode->blue_field_position; + int pixel_size = (vbe.mode->bits_per_pixel + 7) / 8; + int bpl = vbe.mode->bytes_per_scanline; + int c, addr; + + if (x < 0 || x >= x_res || y < 0 || y >= y_res) + return; + + r >>= 8 - vbe.mode->red_mask_size; + g >>= 8 - vbe.mode->green_mask_size; + b >>= 8 - vbe.mode->blue_mask_size; + + c = (r << shift_r) | (g << shift_g) | (b << shift_b); + + addr = y * bpl + (x * pixel_size); + + update_window(addr); + + memcpy(vbe.win + addr, &c, pixel_size); +} + +void +set_mode(int n) +{ + struct LRMI_regs r; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f02; + r.ebx = n; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't set video mode (vm86 failure)\n"); + } else if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Set video mode failed\n"); + } + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f01; + r.ecx = n; + r.es = (unsigned int)vbe.mode >> 4; + r.edi = (unsigned int)vbe.mode & 0xf; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return; + } + + if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Get mode info failed\n"); + return; + } + + vbe.win_low = vbe.win_high = -1; + + /* + Draw a colorful checkerboard + */ + if (vbe.mode->memory_model == VBE_MODEL_RGB) { + int x_res = vbe.mode->x_resolution; + int y_res = vbe.mode->y_resolution; + int x, y; + + for (y = 0; y < y_res; ++y) { + for (x = 0; x < x_res; ++x) { + int r, g, b; + if ((x & 16) ^ (y & 16)) { + r = x * 255 / x_res; + g = y * 255 / y_res; + b = 255 - x * 255 / x_res; + } else { + r = 255 - x * 255 / x_res; + g = y * 255 / y_res; + b = 255 - y * 255 / y_res; + } + + set_pixel(x, y, r, g, b); + } + } + } +} + +void +interactive_set_mode(int n) +{ + void *state; +#if defined(__linux__) + struct stat stat; +#elif defined(__NetBSD__) || defined(__OpenBSD__) + struct wsdisplay_fbinfo wsi; +#elif defined(__FreeBSD__) + struct vid_info vi; +#endif + + if (n == -1) { + printf("Type a mode number, or 'q' to quit - "); + + if (scanf("%d", &n) != 1) + return; + } + +#if defined(__linux__) + if (fstat(0, &stat) != 0) { + fprintf(stderr, "Can't stat() stdin\n"); + return; + } + + if ((stat.st_rdev & 0xff00) != 0x400 + || (stat.st_rdev & 0xff) > 63) +#elif defined(__NetBSD__) || defined(__OpenBSD__) + if (ioctl(0, WSDISPLAYIO_GINFO, &wsi) == -1) +#elif defined(__FreeBSD__) + memset(&vi, 0, sizeof(vi)); + vi.size = sizeof(vi); + if (ioctl(0, CONS_GETINFO, &vi) == -1) +#endif + { + fprintf(stderr, "To switch video modes, " + "this program must be run from the console\n"); + return; + } + + printf("setting mode %d\n", n); + +#if defined(__linux__) || defined(__FreeBSD__) + ioctl(0, KDSETMODE, KD_GRAPHICS); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + ioctl(0, WSDISPLAYIO_SMODE, WSDISPLAYIO_MODE_MAPPED); +#endif + + state = save_state(); + + if (state == NULL) + return; + + set_mode(n); + + system(run_command); + + sleep(5); + + text_mode(); + restore_state(state); + +#if defined(__linux__) || defined(__FreeBSD__) + ioctl(0, KDSETMODE, KD_TEXT); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + ioctl(0, WSDISPLAYIO_SMODE, WSDISPLAYIO_MODE_EMUL); +#endif +} + +void +usage_and_quit(int error) +{ + fputs("Usage: vbetest [-m mode] [-c command]\n", + error ? stderr : stdout); + exit(error); +} + +int +main(int argc, char *argv[]) +{ + struct LRMI_regs r; + short int *mode_list; + int i, mode = -1; +#if defined(__NetBSD__) || defined(__OpenBSD__) + unsigned long iomap[32]; +#endif + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-c") == 0) { + i++; + if (i == argc) + usage_and_quit(1); + run_command = argv[i]; + } else if (strcmp(argv[i], "-m") == 0) { + char *e; + i++; + if (i == argc) + usage_and_quit(1); + mode = strtol(argv[i], &e, 10); + if (e == argv[i]) + usage_and_quit(1); + } else + usage_and_quit(1); + } + + if (!LRMI_init()) + return 1; + + vbe.info = LRMI_alloc_real(sizeof(struct vbe_info_block) + + sizeof(struct vbe_mode_info_block)); + + if (vbe.info == NULL) { + fprintf(stderr, "Can't alloc real mode memory\n"); + return 1; + } + + vbe.mode = (struct vbe_mode_info_block *)(vbe.info + 1); + +#if 0 + /* + Allow read/write to video IO ports + */ + ioperm(0x2b0, 0x2df - 0x2b0, 1); + ioperm(0x3b0, 0x3df - 0x3b0, 1); +#else + /* + Allow read/write to ALL io ports + */ +#if defined(__linux__) + ioperm(0, 1024, 1); + iopl(3); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + memset(&iomap[0], 0xff, sizeof(iomap)); + i386_set_ioperm(iomap); + i386_iopl(3); +#elif defined(__FreeBSD__) + i386_set_ioperm(0, 0x10000, 1); +#endif +#endif + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f00; + r.es = (unsigned int)vbe.info >> 4; + r.edi = 0; + + memcpy(vbe.info->vbe_signature, "VBE2", 4); + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get VESA info (vm86 failure)\n"); + return 1; + } + + if ((r.eax & 0xffff) != 0x4f || strncmp(vbe.info->vbe_signature, "VESA", 4) != 0) { + fprintf(stderr, "No VESA bios\n"); + return 1; + } + + printf("VBE Version %x.%x\n", + (int)(vbe.info->vbe_version >> 8) & 0xff, + (int)vbe.info->vbe_version & 0xff); + + printf("%s\n", + (char *)(vbe.info->oem_string_seg * 16 + vbe.info->oem_string_off)); + + mode_list = (short int *)(vbe.info->video_mode_list_seg * 16 + vbe.info->video_mode_list_off); + + while (*mode_list != -1) { + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f01; + r.ecx = *mode_list; + r.es = (unsigned int)vbe.mode >> 4; + r.edi = (unsigned int)vbe.mode & 0xf; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return 1; + } + + if (vbe.mode->memory_model == VBE_MODEL_RGB) + printf("[%3d] %dx%d (%d:%d:%d)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution, + vbe.mode->red_mask_size, + vbe.mode->green_mask_size, + vbe.mode->blue_mask_size); + else if (vbe.mode->memory_model == VBE_MODEL_256) + printf("[%3d] %dx%d (256 color palette)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution); + else if (vbe.mode->memory_model == VBE_MODEL_PACKED) + printf("[%3d] %dx%d (%d color palette)\n", + *mode_list, + vbe.mode->x_resolution, + vbe.mode->y_resolution, + 1 << vbe.mode->bits_per_pixel); + + mode_list++; + } + + LRMI_free_real(vbe.info); + + interactive_set_mode(mode); + + return 0; +} diff --git a/lrmi-0.9/vga_reset.c b/lrmi-0.9/vga_reset.c new file mode 100644 index 0000000..7b887da --- /dev/null +++ b/lrmi-0.9/vga_reset.c @@ -0,0 +1,25 @@ +/* +Call real mode c0003 +*/ + +#include +#include +#include +#include +#include + +#include "lrmi.h" + +int main(int argc, char *argv[]){ + struct LRMI_regs r; + + if (!LRMI_init()) + return 1; + ioperm(0, 0x400, 1); + iopl(3); + memset(&r,0,sizeof(r)); + r.ip=3; + r.cs=0xc000; + LRMI_call(&r); + return 0; +} diff --git a/obsolete/et4000/0-README b/obsolete/et4000/0-README new file mode 100644 index 0000000..acf8201 --- /dev/null +++ b/obsolete/et4000/0-README @@ -0,0 +1 @@ +Please read 'man 7 svgalib.et4000' diff --git a/obsolete/et4000/cardex.w32 b/obsolete/et4000/cardex.w32 new file mode 100644 index 0000000..2cd36a7 --- /dev/null +++ b/obsolete/et4000/cardex.w32 @@ -0,0 +1,316 @@ + +/* + This is for a Cardex ET4000/W32, with a high-end monitor (it uses + 58 kHz horizontal sync for 1024x768 non-int at 70 Hz). + --HH +*/ + +/* + ( File generated by tseng3.exe ) + +tseng3 v1.2, Copyright (C) 1993 Tommy Frandsen, Harm Hanemaayer +and Hartmut Schirmer + +Permission is granted to any individual or institution to use, copy, or +redistribute this executable so long as it is not modified and that it is +not sold for profit. + +LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND COMES WITH +NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL +THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF +THIS SOFTWARE. +*/ + +/* Music 15/16/24 bit dac (AT&T compatible) detected */ +#define DAC_TYPE 9 + +#define CLOCK_VALUES { \ + /* 0 */ 50350, \ + /* 1 */ 56644, \ + /* 2 */ 65293, \ + /* 3 */ 72364, \ + /* 4 */ 80429, \ + /* 5 */ 90155, \ + /* 6 */ 63300, \ + /* 7 */ 75379 \ + } + +/* VESA HiColor mode 0x10D -- 320x200x32K */ +/* Video timing: Vertical frequency : 69.8Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g320x200x32K_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x41,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x50,0x60,0x96,0xB9,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x63, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xFC,0x00,0x00, + 0x80 +}; + +/* VESA HiColor mode 0x10E -- 320x200x64K */ +#define g320x200x64K_regs g320x200x32K_regs + +/* ET4000 TrueColor BIOS mode 0x13 -- 320x200x16M : NOT SUPPORTED */ +#define g320x200x16M_regs DISABLE_MODE + +/* VESA mode 0x101 -- 640x480x256 */ +/* Video timing: Vertical frequency : 59.7Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x480x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x50,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xFC,0x00,0x00, + 0x00 +}; + +/* VESA HiColor mode 0x110 -- 640x480x32K */ +/* Video timing: Vertical frequency : 59.7Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x480x32K_regs[73] = { + 0xC3,0x9F,0xA1,0x85,0xA7,0x1F,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0xA0,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x80 +}; + +/* VESA HiColor mode 0x111 -- 640x480x64K */ +#define g640x480x64K_regs g640x480x32K_regs + +/* VESA TrueColor mode 0x112 -- 640x480x16M */ +/* Video timing: Vertical frequency : 59.6Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x480x16M_regs[73] = { + 0x27,0xEF,0xF2,0x88,0xF8,0x98,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x0C,0xDF,0xF0,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xEF, + 0x1C,0x00,0x28,0x00,0x0A,0x00,0x2B,0x0F,0x01,0xBC,0x00,0x00, + 0x80 +}; + +/* VESA mode 0x102 -- 800x600x16 */ +/* Video timing: Vertical frequency : 72.4Hz + Horizontal frequency : 48.2KHz */ +static unsigned char g800x600x16_regs[73] = { + 0x7D,0x63,0x63,0x81,0x6D,0x1C,0x98,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7C,0x82,0x57,0x32,0x00,0x57,0x99,0xC3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x0F,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x06, + 0x23, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* VESA mode 0x103 -- 800x600x256 */ +/* Video timing: Vertical frequency : 72.4Hz + Horizontal frequency : 48.2KHz */ +static unsigned char g800x600x256_regs[73] = { + 0x7D,0x63,0x64,0x80,0x6D,0x1C,0x98,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7C,0x82,0x57,0x64,0x60,0x5D,0x93,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x23, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* VESA HiColor mode 0x113 -- 800x600x32K */ +/* Video timing: Vertical frequency : 60.8Hz + Horizontal frequency : 38.5KHz */ +static unsigned char g800x600x32K_regs[73] = { + 0xFF,0xC7,0xC9,0x81,0xD1,0x11,0x77,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5D,0x8F,0x57,0xC8,0x60,0x5B,0x74,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x1C,0x00,0x28,0x00,0x0A,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x80 +}; + +/* VESA HiColor mode 0x114 -- 800x600x64K */ +#define g800x600x64K_regs g800x600x32K_regs + +/* ET4000 TrueColor BIOS mode 0x30 -- 800x600x16M : NOT SUPPORTED */ + +/* VESA mode 0x104 -- 1024x768x16 */ +/* Video timing: Vertical frequency : 71.8Hz + Horizontal frequency : 57.8KHz */ +static unsigned char g1024x768x16_regs[73] = { + 0xA8,0x7F,0x7F,0x8C,0x87,0x98,0x24,0xF5,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x88,0xFF,0x40,0x00,0xFF,0x25,0xC3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x0F,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x06, + 0xE3, + 0x1C,0x00,0x28,0x00,0x0A,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* VESA mode 0x105 -- 1024x768x256 */ +/* Video timing: Vertical frequency : 71.8Hz + Horizontal frequency : 57.8KHz */ +static unsigned char g1024x768x256_regs[73] = { + 0xA8,0x7F,0x7F,0x8C,0x87,0x98,0x24,0xF5,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x88,0xFF,0x80,0x60,0xFF,0x25,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x1C,0x00,0x28,0x00,0x0A,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x38 -- 1024x768x32K : NOT SUPPORTED */ + +/* ET4000 HiColor BIOS mode 0x38 -- 1024x768x64K : NOT SUPPORTED */ + +/* ET4000 TrueColor BIOS mode 0x38 -- 1024x768x16M : NOT SUPPORTED */ + +/* VESA mode 0x106 -- 1280x1024x16 */ +/* Video timing: Vertical frequency : 43.5Hz (interlaced) + Horizontal frequency : 48.1KHz */ +static unsigned char g1280x1024x16_regs[73] = { + 0xCB,0x9F,0xA0,0x8E,0xA9,0x04,0x4F,0x52,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x11,0x89,0xFF,0x50,0x00,0x09,0x46,0xC3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x0F,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x06, + 0x23, + 0x1C,0x00,0x28,0x00,0x0A,0x9B,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* VESA mode 0x107 -- 1280x1024x256 : NOT SUPPORTED */ + +/* VESA HiColor mode 0x119 -- 1280x1024x32K : NOT SUPPORTED */ + +/* VESA HiColor mode 0x11A -- 1280x1024x64K : NOT SUPPORTED */ + +/* VESA TrueColor mode 0x11B -- 1280x1024x16M : NOT SUPPORTED */ + +/* --- ET4000 specific modes */ +#ifdef _DYNAMIC_ONLY_ + +/* ET4000 BIOS mode 0x2D -- 640x350x256 */ +/* Video timing: Vertical frequency : 69.8Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x350x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x83,0x85,0x5D,0x50,0x60,0x63,0xBA,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xA3, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xFC,0x00,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2D -- 640x350x32K */ +/* Video timing: Vertical frequency : 69.8Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x350x32K_regs[73] = { + 0xC3,0x9F,0xA1,0x85,0xA7,0x1F,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x83,0x85,0x5D,0xA0,0x60,0x63,0xBA,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xA3, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x80 +}; + +/* ET4000 HiColor BIOS mode 0x2D -- 640x350x64K */ +#define g640x350x64K_regs g640x350x32K_regs + +/* ET4000 TrueColor BIOS mode 0x2D -- 640x350x16M */ +/* Video timing: Vertical frequency : 69.6Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x350x16M_regs[73] = { + 0x27,0xEF,0xF2,0x88,0xF8,0x98,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x83,0x05,0x5D,0xF0,0x60,0x63,0xBA,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xAF, + 0x1C,0x00,0x28,0x00,0x0A,0x00,0x2B,0x0F,0x01,0xBC,0x00,0x00, + 0x80 +}; + +/* VESA mode 0x100 -- 640x400x256 */ +/* Video timing: Vertical frequency : 69.8Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x400x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x50,0x60,0x96,0xB9,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x63, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xFC,0x00,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2F -- 640x400x32K */ +/* Video timing: Vertical frequency : 69.8Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x400x32K_regs[73] = { + 0xC3,0x9F,0xA1,0x85,0xA7,0x1F,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0xA0,0x60,0x96,0xB9,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x63, + 0x1C,0x00,0x28,0x00,0x08,0x00,0x2B,0x0F,0x00,0xBC,0x00,0x00, + 0x80 +}; + +/* ET4000 HiColor BIOS mode 0x2F -- 640x400x64K */ +#define g640x400x64K_regs g640x400x32K_regs + +/* ET4000 TrueColor BIOS mode 0x2F -- 640x400x16M */ +/* Video timing: Vertical frequency : 69.6Hz + Horizontal frequency : 31.3KHz */ +static unsigned char g640x400x16M_regs[73] = { + 0x27,0xEF,0xF2,0x88,0xF8,0x98,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9C,0x0E,0x8F,0xF0,0x60,0x96,0xB9,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x6F, + 0x1C,0x00,0x28,0x00,0x0A,0x00,0x2B,0x0F,0x01,0xBC,0x00,0x00, + 0x80 +}; + +#endif /* defined(_DYNAMIC_ONLY_ALL_) */ + diff --git a/obsolete/et4000/et4000.default b/obsolete/et4000/et4000.default new file mode 100644 index 0000000..8d10f74 --- /dev/null +++ b/obsolete/et4000/et4000.default @@ -0,0 +1,119 @@ +/* ET4000 registers from SVGALIB 0.81 */ + +/* Define DAC_TYPE to force the DAC type used in the ET4000 driver. If it */ +/* is not defined, the driver tries to autodetect the DAC type which may go */ +/* wrong. */ + +/* Use the following values: + 0: Ordinary DAC + 1: Sierra SC11486 (32k) + 3: Sierra 32k/64k + 5: SS2410 15/24bit DAC + 9: AT&T 20c491/2 (32k/64k/24bit) + 17: Acumos ADAC (Cirrus Logic DAC) + 33: Sierra 15025/6 24-bit DAC +*/ + +#define DAC_TYPE 0 + +/* unsupported modes */ +#define g320x200x64K_regs DISABLE_MODE +#define g320x200x16M_regs DISABLE_MODE +#define g800x600x16_regs DISABLE_MODE +#define g1024x768x16_regs DISABLE_MODE +#define g1280x1024x16_regs DISABLE_MODE + + +/* Got this mode from someone's tseng3.exe dump. */ +/* ET4000 HiColor BIOS mode 0x13 -- 320x200x32K */ +/* Video timing: Vertical frequency : 70.3Hz + Horizontal frequency : 31.6KHz */ +static unsigned char g320x200x32K_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x41,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x50,0x60,0x96,0xB9,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x63, + 0x00,0x00,0x28,0x00,0x08,0x00,0x43,0x0F,0x00,0xFC,0x00,0x00, + 0x00 +}; + +/* ET4000 BIOS mode 2Eh - 640x480x256 */ +static unsigned char g640x480x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x50,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x00,0x00,0x28,0x00,0x08,0x00,0x03,0x0F,0x00,0xFC,0x00,0x00, + 0x00 +}; + +/* ET4000 BIOS mode 30h - 800x600x256 */ +static unsigned char g800x600x256_regs[73] = { + 0x7F,0x63,0x64,0x02,0x6A,0x1D,0x77,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5D,0x8F,0x57,0x64,0x60,0x5B,0x74,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x00,0x00,0x28,0x00,0x0A,0x00,0x03,0x0F,0x00,0xFC,0x00,0x00, + 0x00 +}; + +/* ET4000 BIOS mode 38h - 1024x768x256 */ +static unsigned char g1024x768x256_regs[73] = { + 0xA1,0x7F,0x80,0x04,0x89,0x99,0x26,0xFD,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x08,0x8A,0xFF,0x80,0x60,0x04,0x22,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xEB, + 0x00,0x00,0x28,0x00,0x08,0x00,0x03,0x0F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +static unsigned char g800x600x32K_regs[73] = { + 0xF9,0xC7,0xC9,0x9B,0xCF,0x8F,0x78,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5C,0x8E,0x57,0xC8,0x60,0x5B,0x75,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xEF, + 0x00,0x00,0x28,0x00,0x08,0x00,0x03,0x0F,0x00,0xBC,0x00,0x00, + 0x06 +}; +#define g800x600x64K_regs g800x600x32K_regs + +static unsigned char g640x480x16M_regs[73] = { + 0x27,0xEF,0xF2,0x88,0xF8,0x98,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x0C,0xDF,0xF0,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xEF, + 0x00,0x00,0x28,0x00,0x0A,0x00,0x03,0x0F,0x01,0xBC,0x00,0x00, + 0x00 +}; + +static unsigned char g640x480x32K_regs[73] = { + 0xC3,0x9F,0xA1,0x85,0xA7,0x1F,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0xA0,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x00,0x00,0x28,0x00,0x08,0x00,0x03,0x0F,0x00,0xBC,0x00,0x00, + 0x00 +}; +#define g640x480x64K_regs g640x480x32K_regs + diff --git a/obsolete/et4000/orchid.pdII b/obsolete/et4000/orchid.pdII new file mode 100644 index 0000000..6a960a4 --- /dev/null +++ b/obsolete/et4000/orchid.pdII @@ -0,0 +1,212 @@ + +/* + + This is for an Orchid Prodesigner II. + The 640x480 and 800x600 modes are low-end (hor. sync 35.5 kHz) + The 1024x768 modes are 60 Hz non-interlaced (hsync 48.3 kHz); be + sure to disable these if your monitor can't handle them. + + (file provided by Kayvan Sylvan ) +*/ + +/* + ( File generated by tseng3.exe ) + +tseng3 v1.2, Copyright (C) 1993 Tommy Frandsen, Harm Hanemaayer +and Hartmut Schirmer + +Permission is granted to any individual or institution to use, copy, or +redistribute this executable so long as it is not modified and that it is +not sold for profit. + +LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND COMES WITH +NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL +THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF +THIS SOFTWARE. +*/ + +/* Dac detection BIOS call returned an error */ + +#define CLOCK_VALUES { \ + /* 0 */ 25175, \ + /* 1 */ 28322, \ + /* 2 */ 39999, \ + /* 3 */ 36000, \ + /* 4 */ 25177, \ + /* 5 */ 28320, \ + /* 6 */ 44899, \ + /* 7 */ 62006 \ + } + +/* ET4000 HiColor BIOS mode 0x13 -- 320x200x32K : NOT SUPPORTED */ +#define g320x200x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x13 -- 320x200x64K : NOT SUPPORTED */ +#define g320x200x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x13 -- 320x200x16M : NOT SUPPORTED */ +#define g320x200x16M_regs DISABLE_MODE + +/* ET4000 BIOS mode 0x2E -- 640x480x256 */ +/* Video timing: Vertical frequency : 59.9Hz + Horizontal frequency : 31.5KHz */ +static unsigned char g640x480x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x50,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xE3, + 0x00,0x00,0x08,0x00,0x08,0x00,0x43,0x1F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2E -- 640x480x32K : NOT SUPPORTED */ +#define g640x480x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x2E -- 640x480x64K : NOT SUPPORTED */ +#define g640x480x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x2E -- 640x480x16M : NOT SUPPORTED */ +#define g640x480x16M_regs DISABLE_MODE + +/* ET4000 BIOS mode 0x29 -- 800x600x16 */ +/* Video timing: Vertical frequency : 55.9Hz + Horizontal frequency : 35.4KHz */ +static unsigned char g800x600x16_regs[73] = { + 0x7A,0x63,0x64,0x1D,0x68,0x9A,0x78,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5C,0x8E,0x57,0x32,0x00,0x5B,0x75,0xC3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x0F,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x06, + 0xEF, + 0x00,0x00,0x08,0x00,0x08,0x00,0x43,0x1F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* ET4000 BIOS mode 0x30 -- 800x600x256 */ +/* Video timing: Vertical frequency : 55.9Hz + Horizontal frequency : 35.4KHz */ +static unsigned char g800x600x256_regs[73] = { + 0x7A,0x63,0x64,0x1D,0x68,0x9A,0x78,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5C,0x8E,0x57,0x64,0x60,0x5B,0x75,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xEF, + 0x00,0x00,0x08,0x00,0x08,0x00,0x43,0x1F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x30 -- 800x600x32K : NOT SUPPORTED */ +#define g800x600x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x30 -- 800x600x64K : NOT SUPPORTED */ +#define g800x600x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x30 -- 800x600x16M : NOT SUPPORTED */ + +/* ET4000 BIOS mode 0x37 -- 1024x768x16 */ +/* Video timing: Vertical frequency : 59.9Hz + Horizontal frequency : 48.4KHz */ +static unsigned char g1024x768x16_regs[73] = { + 0x9B,0x7F,0x7F,0x1F,0x85,0x1B,0x26,0xF5,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x06,0x88,0xFF,0x40,0x00,0xFF,0x27,0xC3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x0F,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x06, + 0x2F, + 0x00,0x00,0x08,0x00,0x0A,0x00,0x43,0x1F,0x00,0xFC,0x00,0x00, + 0x90 +}; + +/* ET4000 BIOS mode 0x38 -- 1024x768x256 */ +/* Video timing: Vertical frequency : 60.0Hz + Horizontal frequency : 48.4KHz */ +static unsigned char g1024x768x256_regs[73] = { + 0x9B,0x7F,0x7F,0x1F,0x85,0x1B,0x26,0xF5,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x06,0x88,0xFF,0x80,0x60,0xFF,0x27,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x2F, + 0x00,0x00,0x08,0x00,0x0A,0x00,0x43,0x1F,0x00,0xFC,0x00,0x00, + 0x90 +}; + +/* ET4000 HiColor BIOS mode 0x38 -- 1024x768x32K : NOT SUPPORTED */ + +/* ET4000 HiColor BIOS mode 0x38 -- 1024x768x64K : NOT SUPPORTED */ + +/* ET4000 TrueColor BIOS mode 0x38 -- 1024x768x16M : NOT SUPPORTED */ + +/* ET4000 BIOS mode 0x3D -- 1280x1024x16 : NOT SUPPORTED */ +#define g1280x1024x16_regs DISABLE_MODE + +/* VESA mode 0x107 -- 1280x1024x256 : NOT SUPPORTED */ + +/* VESA HiColor mode 0x119 -- 1280x1024x32K : NOT SUPPORTED */ + +/* VESA HiColor mode 0x11A -- 1280x1024x64K : NOT SUPPORTED */ + +/* VESA TrueColor mode 0x11B -- 1280x1024x16M : NOT SUPPORTED */ + +/* --- ET4000 specific modes */ +#ifdef _DYNAMIC_ONLY_ + +/* ET4000 BIOS mode 0x2D -- 640x350x256 */ +/* Video timing: Vertical frequency : 70.1Hz + Horizontal frequency : 31.5KHz */ +static unsigned char g640x350x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x83,0x85,0x5D,0x50,0x60,0x63,0xBA,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xA3, + 0x00,0x00,0x08,0x00,0x08,0x00,0x43,0x1F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2D -- 640x350x32K : NOT SUPPORTED */ +#define g640x350x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x2D -- 640x350x64K : NOT SUPPORTED */ +#define g640x350x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x2D -- 640x350x16M : NOT SUPPORTED */ +#define g640x350x16M_regs DISABLE_MODE + +/* ET4000 BIOS mode 0x2F -- 640x400x256 */ +/* Video timing: Vertical frequency : 70.1Hz + Horizontal frequency : 31.5KHz */ +static unsigned char g640x400x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x50,0x60,0x96,0xB9,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x63, + 0x00,0x00,0x08,0x00,0x08,0x00,0x43,0x1F,0x00,0xBC,0x00,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2F -- 640x400x32K : NOT SUPPORTED */ +#define g640x400x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x2F -- 640x400x64K : NOT SUPPORTED */ +#define g640x400x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x2F -- 640x400x16M : NOT SUPPORTED */ +#define g640x400x16M_regs DISABLE_MODE + +#endif /* defined(_DYNAMIC_ONLY_ALL_) */ + + diff --git a/obsolete/et4000/speedstar+ b/obsolete/et4000/speedstar+ new file mode 100644 index 0000000..573512b --- /dev/null +++ b/obsolete/et4000/speedstar+ @@ -0,0 +1,216 @@ + +/* + + Max hor. sync: 56 Hz (1024x768 NI at 70 Hz) --HH +*/ + +/********************************************************* +** These register value are from a SpeedSTAR Plus V4.23 ** +** ** +** Oscillator frequencies (from dmode.com) : ** +** ** +** 25.175 28.322 75.0 72.0 80.0 44.9 50.0 65.0 ** +**********************************************************/ + +/* + ( File generated by tseng3.exe ) + +tseng3 v1.2, Copyright (C) 1993 Tommy Frandsen, Harm Hanemaayer +and Hartmut Schirmer + +Permission is granted to any individual or institution to use, copy, or +redistribute this executable so long as it is not modified and that it is +not sold for profit. + +LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND COMES WITH +NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL +THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF +THIS SOFTWARE. +*/ + +/* Standard VGA dac detected */ +#ifndef alt +#define DAC_TYPE 0 + +#define CLOCK_VALUES { \ + /* 0 */ 25175, \ + /* 1 */ 28322, \ + /* 2 */ 50181, \ + /* 3 */ 61231, \ + /* 4 */ 67684, \ + /* 5 */ 62300, \ + /* 6 */ 51760, \ + /* 7 */ 59149 \ + } + +/* ET4000 HiColor BIOS mode 0x13 -- 320x200x32K : NOT SUPPORTED */ +#define g320x200x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x13 -- 320x200x64K : NOT SUPPORTED */ +#define g320x200x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x13 -- 320x200x16M : NOT SUPPORTED */ +#define g320x200x16M_regs DISABLE_MODE + +/* ET4000 BIOS mode 0x2E -- 640x480x256 */ +/* Video timing: Vertical frequency : 72.3Hz + Horizontal frequency : 38.0KHz */ +static unsigned char g640x480x256_regs[73] = { + 0x66,0x4F,0x50,0x89,0x58,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEC,0x8C,0xDF,0x50,0x60,0xE7,0x04,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xEF, + 0x00,0x00,0x28,0x00,0x02,0x00,0x41,0x1F,0x00,0xFC,0x01,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2E -- 640x480x32K : NOT SUPPORTED */ +#define g640x480x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x2E -- 640x480x64K : NOT SUPPORTED */ +#define g640x480x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x2E -- 640x480x16M : NOT SUPPORTED */ +#define g640x480x16M_regs DISABLE_MODE + +/* ET4000 BIOS mode 0x29 -- 800x600x16 */ +/* Video timing: Vertical frequency : 72.2Hz + Horizontal frequency : 48.1KHz */ +static unsigned char g800x600x16_regs[73] = { + 0x7D,0x63,0x64,0x01,0x6C,0x1A,0x98,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x69,0x80,0x57,0x32,0x00,0x59,0x7D,0xC3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x0F,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x06, + 0xAB, + 0x00,0x00,0x28,0x00,0x02,0x00,0x41,0x0F,0x00,0xBC,0x01,0x00, + 0x00 +}; + +/* ET4000 BIOS mode 0x30 -- 800x600x256 */ +/* Video timing: Vertical frequency : 72.2Hz + Horizontal frequency : 48.1KHz */ +static unsigned char g800x600x256_regs[73] = { + 0x7D,0x63,0x64,0x01,0x6C,0x1A,0x98,0xF0,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x69,0x80,0x57,0x64,0x60,0x59,0x7D,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xAB, + 0x00,0x00,0x28,0x00,0x02,0x00,0x41,0x0F,0x00,0xBC,0x01,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x30 -- 800x600x32K : NOT SUPPORTED */ +#define g800x600x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x30 -- 800x600x64K : NOT SUPPORTED */ +#define g800x600x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x30 -- 800x600x16M : NOT SUPPORTED */ + +/* ET4000 BIOS mode 0x37 -- 1024x768x16 */ +/* Video timing: Vertical frequency : 70.0Hz + Horizontal frequency : 56.5KHz */ +static unsigned char g1024x768x16_regs[73] = { + 0xA1,0x7F,0x80,0x04,0x84,0x94,0x24,0xFD,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x89,0xFF,0x40,0x00,0x01,0x24,0xC3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x0F,0x00,0x00,0x00,0x00,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x06, + 0x2B, + 0x00,0x00,0x28,0x00,0x00,0x00,0x41,0x0F,0x00,0xBC,0x01,0x00, + 0x00 +}; + +/* ET4000 BIOS mode 0x38 -- 1024x768x256 */ +/* Video timing: Vertical frequency : 70.0Hz + Horizontal frequency : 56.4KHz */ +static unsigned char g1024x768x256_regs[73] = { + 0xA1,0x7F,0x80,0x04,0x84,0x94,0x24,0xFD,0x00,0x60,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x89,0xFF,0x80,0x60,0x01,0x24,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x2B, + 0x00,0x00,0x28,0x00,0x00,0x00,0x41,0x0F,0x00,0xBC,0x01,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x38 -- 1024x768x32K : NOT SUPPORTED */ + +/* ET4000 HiColor BIOS mode 0x38 -- 1024x768x64K : NOT SUPPORTED */ + +/* ET4000 TrueColor BIOS mode 0x38 -- 1024x768x16M : NOT SUPPORTED */ + +/* ET4000 BIOS mode 0x3D -- 1280x1024x16 : NOT SUPPORTED */ +#define g1280x1024x16_regs DISABLE_MODE + +/* VESA mode 0x107 -- 1280x1024x256 : NOT SUPPORTED */ + +/* VESA HiColor mode 0x119 -- 1280x1024x32K : NOT SUPPORTED */ + +/* VESA HiColor mode 0x11A -- 1280x1024x64K : NOT SUPPORTED */ + +/* VESA TrueColor mode 0x11B -- 1280x1024x16M : NOT SUPPORTED */ + +/* --- ET4000 specific modes */ +#ifdef _DYNAMIC_ONLY_ + +/* ET4000 BIOS mode 0x2D -- 640x350x256 */ +/* Video timing: Vertical frequency : 70.1Hz + Horizontal frequency : 31.5KHz */ +static unsigned char g640x350x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x83,0x85,0x5D,0x50,0x60,0x63,0xBA,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0xA3, + 0x00,0x00,0x28,0x00,0x00,0x00,0x41,0x0F,0x00,0xBC,0x01,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2D -- 640x350x32K : NOT SUPPORTED */ +#define g640x350x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x2D -- 640x350x64K : NOT SUPPORTED */ +#define g640x350x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x2D -- 640x350x16M : NOT SUPPORTED */ +#define g640x350x16M_regs DISABLE_MODE + +/* ET4000 BIOS mode 0x2F -- 640x400x256 */ +/* Video timing: Vertical frequency : 70.1Hz + Horizontal frequency : 31.5KHz */ +static unsigned char g640x400x256_regs[73] = { + 0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x50,0x60,0x96,0xB9,0xAB, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, + 0x03,0x01,0x0F,0x00,0x0E, + 0x63, + 0x00,0x00,0x28,0x00,0x00,0x00,0x41,0x0F,0x00,0xBC,0x01,0x00, + 0x00 +}; + +/* ET4000 HiColor BIOS mode 0x2F-- 640x400x32K : NOT SUPPORTED */ +#define g640x400x32K_regs DISABLE_MODE + +/* ET4000 HiColor BIOS mode 0x2F-- 640x400x64K : NOT SUPPORTED */ +#define g640x400x64K_regs DISABLE_MODE + +/* ET4000 TrueColor BIOS mode 0x2F-- 640x400x16M : NOT SUPPORTED */ +#define g640x400x16M_regs DISABLE_MODE + +#endif /* defined(_DYNAMIC_ONLY_ALL_) */ + diff --git a/obsolete/et4000/tseng3.c b/obsolete/et4000/tseng3.c new file mode 100644 index 0000000..4bbd07e --- /dev/null +++ b/obsolete/et4000/tseng3.c @@ -0,0 +1,645 @@ +/* +** tseng3.c - get ET4000 graphics register values +** Copyright (C) 1993 Tommy Frandsen, Harm Hanemaayer, Hartmut Schirmer +** +** This program is free software; +** +** Permission is granted to any individual or institution to use, copy, +** or redistribute this executable so long as it is not modified and +** that it is not sold for profit. +** +** LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND +** COMEs WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. +** IN NO EVENT WILL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES +** RESULTING FROM THE USE OF THIS SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include + +/* VGA index register ports */ +#define CRT_I 0x3D4 /* CRT Controller Index (mono: 0x3B4) */ +#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define PEL_IW 0x3C8 /* PEL Write Index */ + +/* VGA data register ports */ +#define CRT_D 0x3D5 /* CRT Controller Data Register (mono: 0x3B5) */ +#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ +#define MIS_R 0x3CC /* Misc Output Read Register */ +#define MIS_W 0x3C2 /* Misc Output Write Register */ +#define IS1_R 0x3DA /* Input Status Register 1 (mono: 0x3BA) */ +#define PEL_D 0x3C9 /* PEL Data Register */ + +/* VGA indexes max counts */ +#define CRT_C 24 /* 24 CRT Controller Registers */ +#define ATT_C 21 /* 21 Attribute Controller Registers */ +#define GRA_C 9 /* 9 Graphics Controller Registers */ +#define SEQ_C 5 /* 5 Sequencer Registers */ +#define MIS_C 1 /* 1 Misc Output Register */ +#define EXT_C 17 /* 11 SVGA Extended Registers */ + +/* VGA registers saving indexes */ +#define CRT 0 /* CRT Controller Registers start */ +#define ATT CRT+CRT_C /* Attribute Controller Registers start */ +#define GRA ATT+ATT_C /* Graphics Controller Registers start */ +#define SEQ GRA+GRA_C /* Sequencer Registers */ +#define MIS SEQ+SEQ_C /* General Registers */ +#define EXT MIS+MIS_C /* SVGA Extended Registers */ +#define TOTAL EXT+EXT_C /* # or registers values */ + +unsigned char vga_regs[TOTAL]; +static int do_all = 0; +FILE *output = NULL; + +static int save_extregs; + +void port_out(unsigned char value, unsigned short port) +{ + asm mov dx,port + asm mov al,value + asm out dx,al +} + + +unsigned char port_in(unsigned short port) +{ + asm mov dx,port + asm in al,dx + return (_AL); +} + +int dactype(void) +{ + union REGS cpu_regs; + + cpu_regs.x.ax=0x10F1; + cpu_regs.x.bx=0x2EFF; + + int86(0x10, &cpu_regs, &cpu_regs); + if (cpu_regs.x.ax != 0x0010) + return (-1); + else + return (cpu_regs.h.bl); +} + +int read_dac(int addr) +{ + inp(0x3c8); + inp(0x3c6); + inp(0x3c6); + inp(0x3c6); + inp(0x3c6); + while (addr) + --addr,inp(0x3c6); + addr = inp(0x3c6); + return addr; +} + +int write_dac(int addr,int value) +{ + inp(0x3c8); + inp(0x3c6); + inp(0x3c6); + inp(0x3c6); + inp(0x3c6); + while (addr) + --addr,inp(0x3c6); + outp(0x3c6,value); + return read_dac(addr); +} + +int read_ext_dac(int addr) +{ + write_dac(1,addr); + write_dac(2,0); + return read_dac(3); +} + +void puts2(char *s) { + if (output != NULL) + fprintf(output, "%s\n", s); + while (*s != '\0') { + if (*s == '\n') putch('\r'); + putch (*(s++)); + } + putch('\r'); putch('\n'); +} + +int printf2(char *fmt, ...) +{ + va_list argptr; + char str[140], *s; + int cnt; + + va_start( argptr, fmt ); + + if (output != NULL) + vfprintf(output, fmt, argptr); + cnt = vsprintf( str, fmt, argptr ); + s = str; + while (*s) { + switch (*s) { + case '\n' : putch('\r'); + break; + case '\t' : cprintf("%*s", 8-((wherex()-1)&7), ""); + ++s; + continue; + } + putch(*(s++)); + } + va_end( argptr ); + return( cnt ); +} + +void get_dac(void) +{ + int dac; + + dac = dactype(); + switch (dac) + { + case -1: + printf2 ("/* Dac detection BIOS call returned an error */\n"); + break; + case 0: + printf2 ("/* Standard VGA dac detected */\n"); + printf2 ("#define DAC_TYPE 0\n"); + break; + case 1: + printf2 ("/* Sierra SC1148x HiColor dac detected */\n"); + printf2 ("#define DAC_TYPE 1\n"); + break; + case 2: + printf2 ("/* Diamond Speedstar 24 24bit dac or Sierra Mark2/Mark3 dac detected */\n"); + break; + case 3: + printf2 ("/* AT&T ATT20c491/2 15/16/24 bit dac detected */\n"); + printf2 ("#define DAC_TYPE 9\n"); + break; + case 4: + printf2 ("/* AcuMos ADAC1 15/16/24 bit dac detected */\n"); + break; + case 8: + printf2 ("/* Music 15/16/24 bit dac (AT&T compatible) detected */\n"); + printf2 ("#define DAC_TYPE 9\n"); + break; + default: { /* use alternate method */ + int cmd = read_dac(0); + write_dac(0,cmd | 0x10); + if (read_ext_dac(0) == 0x44) { + printf2 ("/* SGS-Thomson STG170x 15/16/24 dac detected */\n"); + save_extregs = 1; + } + else + printf2 ("/* Unknown HiColor dac (%d) detected */\n", dac); + break; + } + } +} + +#define TickTime (1.0/1193182.0) + +#define init_timer() do { \ + asm mov al, 034h; \ + asm out 043h, al; \ + asm xor al, al; \ + asm out 040h, al; \ + asm out 040h, al; \ +} while(0) + +#define ReadTimer(dst) do { \ + asm { mov al, 4; \ + out 43h, al; \ + in al, 40h; \ + mov bl, al; \ + in al, 40h; \ + mov ah, al; \ + mov al, bl; \ + not ax } \ + (dst) = _AX; \ + } while (0); + +#define _wait_(ID,VAL) \ +w_##ID##1: \ + asm in al, dx; \ + asm test al, VAL; \ + asm jne w_##ID##1; \ +w_##ID##2: \ + asm in al, dx; \ + asm test al, VAL; \ + asm je w_##ID##2 + +#define wait_horizontal(ID,port) do { _DX=(port); _wait_(ID##ch,8);} while(0) +#define wait_vertical(ID,port) do { _DX=(port); _wait_(ID##cv,1);} while(0) +#define __loop__(ID,port,loops,msk) do { \ + register int cnt = (loops); \ + _DX=(port); \ + do { \ + _wait_(ID,msk); \ + } while (--cnt > 0); \ + } while(0) +#define loop_vertical(ID,port,loops) __loop__(ID##cv,(port),(loops),1) + + +int interlaced(void) { + return (vga_regs[EXT+5] & 0x80) ? 1 : 0; +} + +int calc_vtotal(void) { + int total; + + total = (vga_regs[EXT+5]&2) ? 1024 : 0; + switch (vga_regs[CRT+7]&0x21) { + case 0x01 : total += 256; break; + case 0x20 : total += 512; break; + case 0x21 : total += 768; break; + } + total += vga_regs[CRT+6]; + return total + 2; +} + +double measure_horizontal(void) +{ + short start, stop; + long diff; + + disable(); + init_timer(); + wait_horizontal(mv0,0x3da); + wait_vertical(mv0,0x3da); + ReadTimer(start); + loop_vertical(mv, 0x3da, 200); + ReadTimer(stop); + enable(); + diff = stop-start; + if (diff < 0) diff += 65536L; + return 200/(TickTime*((double)diff)); +} + +#define ASK_CONT 0 +#define ASK_SKIP 1 +#define ASK_ALL 2 + +int ask(char *expl) +{ + int ch; + + cprintf("\r\n\n" + "ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r\n" + "º WARNING: Improper use of this program may destroy your monitor º\r\n" + "ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\r\n\n" + "%s\r\n\n" + "Type SPACE to skip, ESC to cancel program, RETURN to continue ... ", + expl); + do { + ch = getch(); + if (ch == 27) exit(1); + switch (ch) { + case 27 : exit(1); + case ' ' : return ASK_SKIP; + case 'A' : return ASK_ALL; + case '\r': return ASK_CONT; + } + } while (1); +} + + +void get_clocks(void) +{ + union REGS cpu_regs; + unsigned char temp; + int i; + double clock[8], horzbase, baseosc; + + if (!do_all) + switch (ask("Measure clock frequencies")) { + case ASK_SKIP : return; + case ASK_ALL : do_all = 1; break; + default : break; + } + + cpu_regs.h.ah = 0x00; + cpu_regs.h.al = 0x13; + int86(0x10, &cpu_regs, &cpu_regs); + port_out(0x03, 0x3BF); /* Unprotect ET4000 registers */ + port_out(0xA0, 0x3D8); + port_out(0x00, ATT_IW); /* disable video */ + port_out(7, SEQ_I); /* devide by 4 */ + temp = port_in(SEQ_D); + port_out(temp | 0x41, SEQ_D); + + baseosc = 25175; /* Base frequency */ + switch (temp & 0x41) { + case 0x41 : baseosc *= 4; break; + case 0x40 : baseosc *= 2; break; + } + clock[0] = baseosc; + clock[1] = baseosc * 28322.0 / 25175.0; + horzbase = measure_horizontal(); + for (i=2; i < 8; ++i) { + temp = (port_in(MIS_R) & 0xF3) | ((i&3)<<2); + port_out(temp, MIS_W); + port_out(0x34, CRT_I); + temp = (port_in(CRT_D) & 0xFD) | ((i&4)>>1); + port_out(temp, CRT_D); + clock[i] = baseosc*measure_horizontal()/horzbase; + } + + cpu_regs.h.ah = 0x00; + cpu_regs.h.al = 0x03; + int86(0x10, &cpu_regs, &cpu_regs); + + printf2("\n#define CLOCK_VALUES {\t\\\n"); + for (i = 0; i < 8; ++i) + printf2("\t/* %d */ %5.0f%s\t\\\n", i, clock[i],(i==7?"":",")); + printf2("\t}\n"); +} + +void one_mode(int vesa_mode, int mode, int colbits, int funny_card) +{ + union REGS cpu_regs; + int i, skip = 0, modeok = 0; + int x=0, y, col, size; + char resol[100], colors[100], *desc; + char *verttxt; + double vertical, horizontal; + + switch (mode) { + case 0x13: x = 320; y = 200; break; + case 0x25: x = 640; y = 480; break; + case 0x29: x = 800; y = 600; break; + case 0x2d: x = 640; y = 350; break; + case 0x2e: x = 640; y = 480; break; + case 0x2f: x = 640; y = 400; break; + case 0x30: x = 800; y = 600; break; + case 0x37: x = 1024; y = 768; break; + case 0x38: x = 1024; y = 768; break; + case 0x3d: x = 1280; y = 1024; break; + default : switch (vesa_mode) { + case 0x107: + case 0x119: + case 0x11a: + case 0x11b: x = 1280; y = 1024; break; + default : return; + } + break; + } + col = (1<> 10); + if (col == 16) size >>= 2; + + switch (colbits) { + case 15: size*=2; strcpy(colors, "32K"); desc = "HiColor "; break; + case 16: size*=2; strcpy(colors, "64K"); desc = "HiColor "; break; + case 24: size*=3; strcpy(colors, "16M"); desc = "TrueColor "; break; + default: sprintf(colors, "%d", col); desc = ""; break; + } + sprintf(resol, "%dx%dx%s", x, y, colors); + + if (!do_all) { + char expl[100]; + sprintf(expl, "BIOS mode 0x%2X : %s", mode, resol); + switch(ask(expl)) { + case ASK_SKIP : skip = 1; break; + case ASK_ALL : do_all = 1; break; + default : break; + } + } + + if (!skip) { + /* First try VESA mode */ + if (vesa_mode != 0) { + cpu_regs.x.ax = 0x4f02; + cpu_regs.x.bx = vesa_mode; + int86(0x10, &cpu_regs, &cpu_regs); + modeok = (cpu_regs.x.ax == 0x004f); + } + /* Try std ET4000 mode numbers if VESA failed */ + if (!modeok && mode != 0) { + switch (colbits) + { + case 15: + case 16: + cpu_regs.x.ax=0x10F0; + cpu_regs.h.bl=mode; + break; + case 24: + switch (funny_card) + { + case 1: + cpu_regs.x.ax=0x10E0; + cpu_regs.h.bl=0x2e; + break; + case 2: + cpu_regs.x.ax=0x10f0; + cpu_regs.h.bl=0x3e; + break; + case 0: + default: + cpu_regs.x.ax=0x10F0; + cpu_regs.h.bh=mode; + cpu_regs.h.bl=0xFF; + break; + } + break; + case 0: + default: + cpu_regs.h.ah = 0x00; + cpu_regs.h.al = mode; + break; + } + + int86(0x10, &cpu_regs, &cpu_regs); + modeok = !( (colbits > 8 && cpu_regs.x.ax != 0x0010) + ||(colbits <=8 && cpu_regs.x.ax == mode ) ); + vesa_mode = 0; + } + + if (modeok) { + /* get VGA register values */ + for (i = 0; i < CRT_C; i++) { + port_out(i, CRT_I); + vga_regs[CRT+i] = port_in(CRT_D); + } + for (i = 0; i < ATT_C; i++) { + if (col == 16 && i < 16) + vga_regs[ATT+i] = i; + else { + port_in(IS1_R); + port_out(i, ATT_IW); + vga_regs[ATT+i] = port_in(ATT_R); + } + } + for (i = 0; i < GRA_C; i++) { + if (i==1 && col == 16) + vga_regs[GRA+i] = 0x0F; + else { + port_out(i, GRA_I); + vga_regs[GRA+i] = port_in(GRA_D); + } + } + for (i = 0; i < SEQ_C; i++) { + port_out(i, SEQ_I); + vga_regs[SEQ+i] = port_in(SEQ_D); + } + vga_regs[MIS] = port_in(MIS_R); + + /* get extended CRT registers */ + for (i = 0; i < 8; i++) { + port_out(0x30+i, CRT_I); + vga_regs[EXT+i] = port_in(CRT_D); + } + port_out(0x3f , CRT_I); + vga_regs[EXT+8] = port_in(CRT_D); + + /* get extended sequencer register */ + port_out(7, SEQ_I); + vga_regs[EXT+9] = port_in(SEQ_D); + + /* get some other ET4000 specific registers */ + vga_regs[EXT+10] = port_in(0x3c3); + vga_regs[EXT+11] = port_in(0x3cd); + + /* get extended attribute register */ + port_in(IS1_R); /* reset flip flop */ + port_out(0x16, ATT_IW); + vga_regs[EXT+12] = port_in(ATT_R); + + if (save_extregs) { /* copy stg170x extended info */ + vga_regs[EXT+13] = read_dac(0); + write_dac(0,vga_regs[EXT+13] | 0x10); + vga_regs[EXT+14] = read_ext_dac(3); + vga_regs[EXT+15] = read_ext_dac(4); + vga_regs[EXT+16] = read_ext_dac(5); + } + + /* Measure video timing */ + horizontal = measure_horizontal(); + /* switch back to text mode */ + cpu_regs.h.ah = 0x00; + cpu_regs.h.al = 0x03; + int86(0x10, &cpu_regs, &cpu_regs); + } + } + + if (vesa_mode) + printf2("\n/* VESA %smode 0x%03X", desc, vesa_mode); + else + printf2("\n/* ET4000 %sBIOS mode 0x%02X", desc, mode); + printf2(" -- %s", resol); + if ( skip || !modeok) { + printf2(" : NOT SUPPORTED */\n"); + if (size <= 1024) + printf2("#define g%s_regs DISABLE_MODE\n", resol); + return; + } + printf2(" */\n"); + + /* can't always treat 15 and 16 bit modes the same! */ + if (colbits == 16 && !save_extregs) { + printf2("#define g%s_regs g%dx%dx32K_regs\n", resol, x, y); + return; + } + + verttxt = interlaced() ? " (interlaced)" : ""; + vertical = horizontal / calc_vtotal(); + printf2("/* Video timing:\tVertical frequency : %4.1fHz%s\n", + vertical, verttxt); + printf2("\t\t\tHorizontal frequency : %4.1fKHz */\n", horizontal/1000.0); + printf2("static unsigned char g%s_regs[%d] = {\n ", resol, TOTAL); + for (i = 0; i < CRT_C; i++) + printf2("%s0x%02X,", (i==12?"\n ":""), vga_regs[CRT+i]); + printf2("\n "); + for (i = 0; i < ATT_C; i++) + printf2("%s0x%02X,", (i==12?"\n ":""), vga_regs[ATT+i]); + printf2("\n "); + for (i = 0; i < GRA_C; i++) + printf2("0x%02X,",vga_regs[GRA+i]); + printf2("\n "); + for (i = 0; i < SEQ_C; i++) + printf2("0x%02X,",vga_regs[SEQ+i]); + printf2("\n 0x%02X,",vga_regs[MIS]); + printf2("\n 0x%02X",vga_regs[EXT]); + for (i = 1; i < EXT_C; i++) + printf2(",%s0x%02X", (i==12?"\n ":""), vga_regs[i+EXT]); + printf2("\n};\n"); +} + +void usage(void) { + cputs("tseng3 [SS24]"); + exit(1); +} + +void main(int argc, char* argv[]) +{ + int funny_card = 0; + + if (argc >= 2) + output = fopen(argv[1], "w"); + + if (output != NULL) + fputs("/*\n ( File generated by tseng3.exe )\n\n", output); + puts2("tseng3 v1.2, Copyright (C) 1993 Tommy Frandsen, Harm Hanemaayer"); + puts2("and Hartmut Schirmer\n"); + puts2("Permission is granted to any individual or institution to use, copy, or"); + puts2("redistribute this executable so long as it is not modified and that it is"); + puts2("not sold for profit.\n"); + puts2("LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND COMES WITH"); + puts2("NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL"); + puts2("THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF"); + puts2("THIS SOFTWARE."); + if (output != NULL) + fputs("*/\n", output); + puts2(""); + + if (argc >= 2 && output == NULL) + usage(); + + if (argc>=3) + funny_card = (strcmp("SS24", argv[2]) == 0) ? 1 : 2; + + get_dac(); + get_clocks(); + + one_mode(0x10d, 0x13, 15, funny_card); /* 320x200x32K */ + one_mode(0x10e, 0x13, 16, funny_card); /* 320x200x64K */ + one_mode(0x10f, 0x13, 24, funny_card); /* 320x200x16M */ + one_mode(0x101, 0x2e, 8, funny_card); /* 640x480x256 */ + one_mode(0x110, 0x2e, 15, funny_card); /* 640x480x32K */ + one_mode(0x111, 0x2e, 16, funny_card); /* 640x480x64K */ + one_mode(0x112, 0x2e, 24, funny_card); /* 640x480x16M */ + one_mode(0x102, 0x29, 4, funny_card); /* 800x600x16 */ + one_mode(0x103, 0x30, 8, funny_card); /* 800x600x256 */ + one_mode(0x113, 0x30, 15, funny_card); /* 800x600x32K */ + one_mode(0x114, 0x30, 16, funny_card); /* 800x600x64K */ + one_mode(0x115, 0x30, 24, funny_card); /* 800x600x16M */ + one_mode(0x104, 0x37, 4, funny_card); /* 1024x768x16 */ + one_mode(0x105, 0x38, 8, funny_card); /* 1024x768x256 */ + one_mode(0x116, 0x38, 15, funny_card); /* 1024x768x32K */ + one_mode(0x117, 0x38, 16, funny_card); /* 1024x768x64K */ + one_mode(0x118, 0x38, 24, funny_card); /* 1024x768x16M */ + one_mode(0x106, 0x3D, 4, funny_card); /* 1280x1024x16 */ + one_mode(0x107, 0x00, 8, funny_card); /* 1280x1024x256 */ + one_mode(0x119, 0x00, 15, funny_card); /* 1280x1024x32K */ + one_mode(0x11a, 0x00, 16, funny_card); /* 1280x1024x64K */ + one_mode(0x11b, 0x00, 24, funny_card); /* 1280x1024x16M */ + puts2("\n/* --- ET4000 specific modes */\n#ifdef _DYNAMIC_ONLY_"); + one_mode(0x000, 0x2d, 8, funny_card); /* 640x350x256 */ + one_mode(0x000, 0x2d, 15, funny_card); /* 640x350x32K */ + one_mode(0x000, 0x2d, 16, funny_card); /* 640x350x64K */ + one_mode(0x000, 0x2d, 24, funny_card); /* 640x350x16M */ + one_mode(0x100, 0x2f, 8, funny_card); /* 640x400x256 */ + one_mode(0x000, 0x2f, 15, funny_card); /* 640x400x32K */ + one_mode(0x000, 0x2f, 16, funny_card); /* 640x400x64K */ + one_mode(0x000, 0x2f, 24, funny_card); /* 640x400x16M */ + puts2("\n#endif /* defined(_DYNAMIC_ONLY_ALL_) */\n"); +} + diff --git a/obsolete/et4000/tseng3.exe b/obsolete/et4000/tseng3.exe new file mode 100644 index 0000000..74454aa Binary files /dev/null and b/obsolete/et4000/tseng3.exe differ diff --git a/obsolete/jump/jump.funcs b/obsolete/jump/jump.funcs new file mode 100644 index 0000000..0829844 --- /dev/null +++ b/obsolete/jump/jump.funcs @@ -0,0 +1,152 @@ +00000000 T _vga_setchipset libvga vga +00000000 T _vga_setchipsetandfeatures libvga vga +00000000 T _vga_setpage libvga vga +00000000 T _vga_setreadpage libvga vga +00000000 T _vga_setwritepage libvga vga +00000000 T _vga_setmode libvga vga +00000000 T _vga_gettextfont libvga vga +00000000 T _vga_puttextfont libvga vga +00000000 T _vga_gettextmoderegs libvga vga +00000000 T _vga_settextmoderegs libvga vga +00000000 T _vga_getcurrentmode libvga vga +00000000 T _vga_getcurrentchipset libvga vga +00000000 T _vga_disabledriverreport libvga vga +00000000 T _vga_getmodeinfo libvga vga +00000000 T _vga_hasmode libvga vga +00000000 T _vga_lastmodenumber libvga vga +00000000 T _vga_setcolor libvga vga +00000000 T _vga_screenoff libvga vga +00000000 T _vga_screenon libvga vga +00000000 T _vga_getxdim libvga vga +00000000 T _vga_getydim libvga vga +00000000 T _vga_getcolors libvga vga +00000000 T _vga_white libvga vga +00000000 T _vga_claimvideomemory libvga vga +00000000 T _vga_getch libvga vga +00000000 T _vga_flip libvga vga +00000000 T _vga_setflipchar libvga vga +00000000 T _vga_setlogicalwidth libvga vga +00000000 T _vga_setdisplaystart libvga vga +00000000 T _vga_bitblt libvga vga +00000000 T _vga_imageblt libvga vga +00000000 T _vga_fillblt libvga vga +00000000 T _vga_hlinelistblt libvga vga +00000000 T _vga_drawscanline libvga vgadraw +00000000 T _vga_drawscansegment libvga vgadraw +00000000 T _vga_clear libvga vgaclear +00000000 T _vga_drawline libvga vgaline +00000000 T _vga_drawpixel libvga vgapix +00000000 T _vga_setpalette libvga vgapal +00000000 T _vga_getpalette libvga vgapal +00000000 T _vga_setpalvec libvga vgapal +00000000 T _vga_getpalvec libvga vgapal +00000000 T _vga_setrgbcolor libvga vgacol +00000000 T _vga_setegacolor libvga vgacol +00000000 T _vga_getmodenumber libvga vgamodesel +00000000 T _vga_getmodename libvga vgamodesel +00000000 T _vga_getdefaultmode libvga vgamodesel +00000000 T _vga_getgraphmem libvga vgamisc +00000000 T _vga_dumpregs libvga vgadump +00000000 T _vga_waitretrace libvga vgamisc +00000000 T _vga_init libvga vga +00000000 T _vga_getmousetype libvga vga +00000000 T _vga_getmonitortype libvga vga +00000000 T _vga_setmousesupport libvga vga +00000000 T _vga_setmodeX libvga vga +00000000 T _vga_lockvc libvga vga +00000000 T _vga_unlockvc libvga vga +00000000 T _vga_getkey libvga vgamisc +00000000 T _gl_setcontextvga libvgagl grlib +00000000 T _gl_setcontextvgavirtual libvgagl grlib +00000000 T _gl_setcontextvirtual libvgagl grlib +00000000 T _gl_setcontext libvgagl grlib +00000000 T _gl_getcontext libvgagl grlib +00000000 T _gl_freecontext libvgagl grlib +00000000 T _gl_setclippingwindow libvgagl grlib +00000000 T _gl_enableclipping libvgagl grlib +00000000 T _gl_disableclipping libvgagl grlib +00000000 T _gl_setpixel libvgagl grlib +00000000 T _gl_getpixel libvgagl grlib +00000000 T _gl_hline libvgagl grlib +00000000 T _gl_fillbox libvgagl grlib +00000000 T _gl_putboxpart libvgagl grlib +00000000 T _gl_putbox libvgagl grlib +00000000 T _gl_putboxmask libvgagl grlib +00000000 T _gl_getbox libvgagl grlib +00000000 T _gl_copybox libvgagl grlib +00000000 T _gl_clearscreen libvgagl grlib +00000000 T _gl_rgbcolor libvgagl grlib +00000000 T _gl_setpixelrgb libvgagl grlib +00000000 T _gl_getpixelrgb libvgagl grlib +00000000 T _gl_setdisplaystart libvgagl grlib +00000000 T _gl_copyscreen libvgagl grlib +00000000 T _gl_copyboxtocontext libvgagl grlib +00000000 T _gl_line libvgagl line +00000000 T _gl_circle libvgagl line +00000000 T _gl_getpalettecolor libvgagl palette +00000000 T _gl_setpalettecolor libvgagl palette +00000000 T _gl_setpalettecolors libvgagl palette +00000000 T _gl_getpalettecolors libvgagl palette +00000000 T _gl_getpalette libvgagl palette +00000000 T _gl_setpalette libvgagl palette +00000000 T _gl_setrgbpalette libvgagl palette +00000000 T _gl_scalebox libvgagl scale +00000000 T _gl_colorfont libvgagl text +00000000 T _gl_setfont libvgagl text +00000000 T _gl_setwritemode libvgagl text +00000000 T _gl_write libvgagl text +00000000 T _gl_writen libvgagl text +00000000 T _gl_expandfont libvgagl text +00000000 T _mouse_init libvga mouse/mouse +00000000 T _mouse_update libvga mouse/mouse +00000000 T _mouse_waitforupdate libvga mouse/mouse +00000000 T _mouse_seteventhandler libvga mouse/mouse +00000000 T _mouse_close libvga mouse/mouse +00000000 T _mouse_setdefaulteventhandler libvga mouse/mouse +00000000 T _mouse_setwrap libvga mouse/mouse +00000000 T _mouse_setposition libvga mouse/mouse +00000000 T _mouse_setxrange libvga mouse/mouse +00000000 T _mouse_setyrange libvga mouse/mouse +00000000 T _mouse_setscale libvga mouse/mouse +00000000 T _mouse_getx libvga mouse/mouse +00000000 T _mouse_gety libvga mouse/mouse +00000000 T _mouse_getbutton libvga mouse/mouse +00000000 T _gl_setcontextwidth libvgagl grlib +00000000 T _gl_setcontextheight libvgagl grlib +00000000 T _vga_runinbackground libvga vga +00000000 T _vga_oktowrite libvga vga +00000000 T _vga_copytoplanar256 libvga vgaconvplanar +00000000 T _vga_copytoplanar16 libvga vgaconvplanar +00000000 T _vga_setlinearaddressing libvga vgamisc +00000000 T _gl_setscreenoffset libvga vgamisc +00000000 T _vga_safety_fork libvga vgamisc +00000000 T _gl_enablepageflipping libvgagl grlib +00000000 T _gl_compileboxmask libvgagl cbitmap +00000000 T _gl_compiledboxmasksize libvgagl cbitmap +00000000 T _gl_putboxmaskcompiled libvgagl cbitmap +00000000 T _keyboard_init libvga keyboard/keyboard +00000000 T _keyboard_seteventhandler libvga keyboard/keyboard +00000000 T _keyboard_close libvga keyboard/keyboard +00000000 T _keyboard_update libvga keyboard/keyboard +00000000 T _keyboard_waitforupdate libvga keyboard/keyboard +00000000 T _keyboard_setdefaulteventhandler libvga keyboard/keyboard +00000000 T _keyboard_getstate libvga keyboard/keyboard +00000000 T _keyboard_clearstate libvga keyboard/keyboard +00000000 T _keyboard_translatekeys libvga keyboard/keyboard +00000000 T _keyboard_keypressed libvga keyboard/keyboard +00000000 T _gl_copyboxfromcontext libvgagl grlib +00000000 T _vga_copytoplane libvga vgaconvplanar +00000000 T _mouse_init_return_fd libvga mouse/mouse +00000000 T _keyboard_init_return_fd libvga keyboard/keyboard +00000000 T _vga_blitwait libvga vga +00000000 T _vga_ext_set libvga vga +00000000 T _vga_accel libvga vgamisc +00000000 T _vga_getpixel libvga vgamisc +00000000 T _gl_setfontcolors libvgagl text +00000000 T _gl_allocatecontext libvgagl grlib +00000000 T _vga_getscansegment libvga vgadraw +00000000 T _vga_waitevent libvga vgamisc +00000000 T _mouse_setposition_6d libvga vgamisc +00000000 T _mouse_setrange_6d libvga vgamisc +00000000 T _mouse_getposition_6d libvga vgamisc +00000000 T _vga_runinbackground_version libvga vga diff --git a/obsolete/jump/jump.ignore b/obsolete/jump/jump.ignore new file mode 100644 index 0000000..aac6e1e --- /dev/null +++ b/obsolete/jump/jump.ignore @@ -0,0 +1,294 @@ +00000000 D ___svgalib_infotable libvga vga +00000000 D ___svgalib_cur_mode libvga vga +00000000 D ___svgalib_chipset libvga vga +00000000 D ___svgalib_driver_report libvga vga +00000000 D ___svgalib_videomemoryused libvga vga +00000000 D ___svgalib_modeX libvga vga +00000000 D ___svgalib_modeflags libvga vga +00000000 D ___svgalib_critical libvga vga +00000000 D ___svgalib_screenon libvga vga +00000000 D ___svgalib_horizsync libvga vga +00000000 D ___svgalib_vertrefresh libvga vga +00000000 D ___svgalib_grayscale libvga vga +00000000 D ___svgalib_modeinfo_linearset libvga vga +00000000 K ___svgalib_max_modes libvga vga +00000000 D ___svgalib_mem_fd libvga vga +00000000 D ___svgalib_tty_fd libvga vga +00000000 D ___svgalib_oktowrite libvga vga +00000000 D ___svgalib_flipchar libvga vga +00000000 D ___svgalib_driverspecs libvga vga +00000000 D ___svgalib_driverspecslist libvga vga +00000000 T ___svgalib_waitvtactive libvga vga +00000000 T ___svgalib_open_devconsole libvga vga +00000000 T ___svgalib_get_perm libvga vga +00000000 T ___svgalib_delay libvga vga +00000000 T ___svgalib_saveregs libvga vga +00000000 T ___svgalib_setregs libvga vga +00000000 T ___svgalib_getchipset libvga vga +00000000 T ___svgalib_map_virtual_screen libvga vga +00000000 T ___svgalib_addmode libvga vga +00000000 T ___svgalib_flip_status libvga vga +00000000 T ___svgalib_flipaway libvga vga +00000000 T ___svgalib_flipback libvga vga +00000000 T ___svgalib_read_options libvga vga +00000000 T ___svgalib_give_graph_red libvga vga +00000000 T ___svgalib_give_graph_green libvga vga +00000000 T ___svgalib_give_graph_blue libvga vga +00000000 C ___svgalib_CRT_I libvga vga +00000000 C ___svgalib_CRT_D libvga vga +00000000 C ___svgalib_IS1_R libvga vga +00000000 C ___svgalib_cur_info libvga vga +00000000 C ___svgalib_cur_color libvga vga +00000000 C ___svgalib_graph_mem libvga vga +00000000 C ___svgalib_currentpage libvga vga +00000000 C ___svgalib_setpage libvga vga +00000000 C ___svgalib_setrdpage libvga vga +00000000 C ___svgalib_setwrpage libvga vga +00000000 T ___svgalib_fast_drawpixel libvga vgapix +00000000 T ___svgalib_fast_getpixel libvga vgapix +00000000 C ___svgalib_green_backup libvga vgapal +00000000 T ___svgalib_name2number libvga vgamodesel +00000000 T ___svgalib_physmem libvga vgamisc +00000000 T ___svgalib_dumpregs libvga vgadump +00000000 D ___svgalib_standard_timings libvga timing +00000000 T ___svgalib_addusertiming libvga timing +00000000 T ___svgalib_getmodetiming libvga timing +00000000 T ___svgalib_setup_VGA_registers libvga vgaregs +00000000 T ___svgalib_outGR libvga vgaregs +00000000 T ___svgalib_outbGR libvga vgaregs +00000000 T ___svgalib_outCR libvga vgaregs +00000000 T ___svgalib_outbCR libvga vgaregs +00000000 T ___svgalib_outSR libvga vgaregs +00000000 T ___svgalib_outbSR libvga vgaregs +00000000 T ___svgalib_inGR libvga vgaregs +00000000 T ___svgalib_inCR libvga vgaregs +00000000 T ___svgalib_inSR libvga vgaregs +00000000 T ___svgalib_createModeInfoStructureForSvgalibMode libvga interface +00000000 T ___svgalib_colorbits_to_colormode libvga interface +00000000 T ___svgalib_clear_accelspecs libvga interface +00000000 T ___svgalib_InitializeAcceleratorInterface libvga accel +00000000 C ___svgalib_accel_screenpitch libvga accel +00000000 C ___svgalib_accel_bytesperpixel libvga accel +00000000 C ___svgalib_accel_screenpitchinbytes libvga accel +00000000 C ___svgalib_accel_mode libvga accel +00000000 C ___svgalib_accel_bitmaptransparency libvga accel +00000000 T ___svgalib_fast_setpage libvga vgabgpage +00000000 T ___svgalib_setpage_fg libvga vgabgpage +00000000 T ___svgalib_setpage_bg libvga vgabgpage +00000000 D ___svgalib_ignore_vt_switching libvga vgabgvt +00000000 D ___svgalib_go_to_background libvga vgabgvt +00000000 D ___svgalib_come_from_background libvga vgabgvt +00000000 T ___svgalib_dont_switch_vt_yet libvga vgabgvt +00000000 T ___svgalib_is_vt_switching_needed libvga vgabgvt +00000000 T ___svgalib_takevtcontrol libvga vgabgvt +00000000 D ___svgalib_mouse_fd libvga mouse/mouse +00000000 D ___svgalib_kbd_fd libvga keyboard/keyboard +00000000 T ___svgalib_probeDacs libvga ramdac/ramdac +00000000 T ___svgalib_setDacSpeed libvga ramdac/ramdac +00000000 D ___svgalib_all_dacs libvga ramdac/ramdac +00000000 D ___svgalib_normal_dac_methods libvga ramdac/normal +00000000 T ___svgalib_att20c490_map_clock libvga ramdac/attdacs +00000000 T ___svgalib_att20c490_map_horizontal_crtc libvga ramdac/attdacs +00000000 D ___svgalib_ATT20C490_methods libvga ramdac/attdacs +00000000 D ___svgalib_ATT20C498_methods libvga ramdac/attdacs +00000000 T ___svgalib_Sierra_32K_savestate libvga ramdac/sierra +00000000 T ___svgalib_Sierra_32K_restorestate libvga ramdac/sierra +00000000 D ___svgalib_Sierra_32K_methods libvga ramdac/sierra +00000000 D ___svgalib_SC15025_methods libvga ramdac/sierra +00000000 D ___svgalib_SC1148X_methods libvga ramdac/sierra +00000000 D ___svgalib_ICW_methods libvga ramdac/icw +00000000 D ___svgalib_S3_SDAC_methods libvga ramdac/s3dacs +00000000 D ___svgalib_S3_GENDAC_methods libvga ramdac/s3dacs +00000000 D ___svgalib_Trio64_methods libvga ramdac/s3dacs +00000000 D ___svgalib_IBMRGB52x_methods libvga ramdac/IBMRGB52x +00000000 D ___svgalib_I2061A_clockchip_methods libvga clockchip/icd2061a +00000000 D ___svgalib_vga_driverspecs libvga vgadrv +00000000 T ___svgalib_readmodes libvga regextr +00000000 T ___svgalib_mode_in_table libvga modetab +00000000 D ___svgalib_et4000_driverspecs libvga et4000 +00000000 T ___svgalib_hicolor libvga vgahico +00000000 T ___svgalib_cirrus_inlinearmode libvga cirrus +00000000 D ___svgalib_cirrus_driverspecs libvga cirrus +00000000 T ___svgalib_cirrusaccel_init libvga cirrus +00000000 T ___svgalib_cirrusaccel_FillBox libvga cirrus +00000000 T ___svgalib_cirrusaccel_mmio_FillBox libvga cirrus +00000000 T ___svgalib_cirrusaccel_ScreenCopy libvga cirrus +00000000 T ___svgalib_cirrusaccel_mmio_ScreenCopy libvga cirrus +00000000 T ___svgalib_cirrusaccel_SetFGColor libvga cirrus +00000000 T ___svgalib_cirrusaccel_mmio_SetFGColor libvga cirrus +00000000 T ___svgalib_cirrusaccel_SetRasterOp libvga cirrus +00000000 T ___svgalib_cirrusaccel_mmio_SetRasterOp libvga cirrus +00000000 T ___svgalib_cirrusaccel_SetTransparency libvga cirrus +00000000 K ___svgalib_cirrusaccel_Sync libvga cirrus +00000000 T ___svgalib_cirrusaccel_mmio_Sync libvga cirrus +00000000 D ___svgalib_tvga8900_driverspecs libvga tvga8900 +00000000 D ___svgalib_oak_driverspecs libvga oak +00000000 D ___svgalib_ega_driverspecs libvga egadrv +00000000 D ___svgalib_mach32_driverspecs libvga mach32 +00000000 D ___svgalib_s3_driverspecs libvga s3 +00000000 D ___svgalib_et3000_driverspecs libvga et3000 +00000000 D ___svgalib_gvga6400_driverspecs libvga gvga6400 +00000000 D ___svgalib_ark_driverspecs libvga ark +00000000 T ___svgalib_arkaccel_FillBox libvga ark +00000000 T ___svgalib_arkaccel_coords_FillBox libvga ark +00000000 T ___svgalib_arkaccel_ScreenCopy libvga ark +00000000 T ___svgalib_arkaccel_coords_ScreenCopy libvga ark +00000000 T ___svgalib_arkaccel_DrawHLineList libvga ark +00000000 T ___svgalib_arkaccel_coords_DrawHLineList libvga ark +00000000 T ___svgalib_arkaccel_SetFGColor libvga ark +00000000 T ___svgalib_arkaccel_SetBGColor libvga ark +00000000 T ___svgalib_arkaccel_PutBitmap libvga ark +00000000 T ___svgalib_arkaccel_SetRasterOp libvga ark +00000000 K ___svgalib_arkaccel_Sync libvga ark +00000000 D ___svgalib_ati_driverspecs libvga ati +00000000 D ___svgalib_ali_driverspecs libvga ali +00000000 D ___svgalib_mach64_driverspecs libvga mach64 +00000000 D ___svgalib_ctPanelType libvga chips +00000000 D ___svgalib_ctMMIOBase libvga chips +00000000 D ___svgalib_ctMMIOPage libvga chips +00000000 D ___svgalib_CHIPS_LinearBase libvga chips +00000000 D ___svgalib_ctBltDataWindow libvga chips +00000000 D ___svgalib_byte_reversed libvga chips +00000000 D ___svgalib_XRregs libvga chips +00000000 D ___svgalib_HiQVXRregs libvga chips +00000000 D ___svgalib_HiQVCRregs libvga chips +00000000 D ___svgalib_HiQVFRregs libvga chips +00000000 D ___svgalib_chips_driverspecs libvga chips +00000000 T ___svgalib_CHIPS_FillBox libvga chips +00000000 T ___svgalib_CHIPS_mmio_FillBox libvga chips +00000000 T ___svgalib_CHIPS_hiqv_FillBox libvga chips +00000000 T ___svgalib_CHIPS_FillBox24 libvga chips +00000000 T ___svgalib_CHIPS_mmio_FillBox24 libvga chips +00000000 T ___svgalib_CHIPS_PutBitmap libvga chips +00000000 T ___svgalib_CHIPS_mmio_PutBitmap libvga chips +00000000 T ___svgalib_CHIPS_hiqv_PutBitmap libvga chips +00000000 T ___svgalib_CHIPS_SetFGColor libvga chips +00000000 T ___svgalib_CHIPS_SetBGColor libvga chips +00000000 T ___svgalib_CHIPS_SetRasterOp libvga chips +00000000 T ___svgalib_CHIPS_SetTransparency libvga chips +00000000 C ___svgalib_ctSize libvga chips +00000000 T ___svgalib_driver8_setpixel libvga driver +00000000 T ___svgalib_driver8p_setpixel libvga driver +00000000 T ___svgalib_driver8_getpixel libvga driver +00000000 T ___svgalib_driver8p_getpixel libvga driver +00000000 T ___svgalib_driver8_hline libvga driver +00000000 T ___svgalib_driver8p_hline libvga driver +00000000 T ___svgalib_driver8_fillbox libvga driver +00000000 T ___svgalib_driver8a_fillbox libvga driver +00000000 T ___svgalib_driver8p_fillbox libvga driver +00000000 T ___svgalib_driver8_putbox libvga driver +00000000 T ___svgalib_driver8p_putbox libvga driver +00000000 T ___svgalib_driver8_getbox libvga driver +00000000 T ___svgalib_driver8p_getbox libvga driver +00000000 T ___svgalib_driver8_putboxmask libvga driver +00000000 T ___svgalib_driver8_putboxpart libvga driver +00000000 T ___svgalib_driver8p_putboxpart libvga driver +00000000 T ___svgalib_driver8_getboxpart libvga driver +00000000 T ___svgalib_driver8p_getboxpart libvga driver +00000000 T ___svgalib_driver8_copybox libvga driver +00000000 T ___svgalib_driver8a_copybox libvga driver +00000000 T ___svgalib_driver16_setpixel libvga driver +00000000 T ___svgalib_driver16p_setpixel libvga driver +00000000 T ___svgalib_driver16_getpixel libvga driver +00000000 T ___svgalib_driver16p_getpixel libvga driver +00000000 T ___svgalib_driver16_hline libvga driver +00000000 T ___svgalib_driver16p_hline libvga driver +00000000 T ___svgalib_driver16_fillbox libvga driver +00000000 T ___svgalib_driver16p_fillbox libvga driver +00000000 T ___svgalib_driver16_putbox libvga driver +00000000 T ___svgalib_driver16p_putbox libvga driver +00000000 T ___svgalib_driver16_getbox libvga driver +00000000 T ___svgalib_driver16p_getbox libvga driver +00000000 T ___svgalib_driver16_putboxmask libvga driver +00000000 T ___svgalib_driver16_putboxpart libvga driver +00000000 T ___svgalib_driver16p_putboxpart libvga driver +00000000 T ___svgalib_driver16_getboxpart libvga driver +00000000 T ___svgalib_driver16p_getboxpart libvga driver +00000000 T ___svgalib_driver16_copybox libvga driver +00000000 T ___svgalib_driver16a_copybox libvga driver +00000000 T ___svgalib_driver24_setpixel libvga driver +00000000 T ___svgalib_driver24p_setpixel libvga driver +00000000 T ___svgalib_driver24_getpixel libvga driver +00000000 T ___svgalib_driver24p_getpixel libvga driver +00000000 T ___svgalib_driver24_hline libvga driver +00000000 T ___svgalib_driver24p_hline libvga driver +00000000 T ___svgalib_driver24_fillbox libvga driver +00000000 T ___svgalib_driver24p_fillbox libvga driver +00000000 T ___svgalib_driver24_putbox libvga driver +00000000 T ___svgalib_driver24p_putbox libvga driver +00000000 T ___svgalib_driver24_putbox32 libvga driver +00000000 T ___svgalib_driver24_getbox libvga driver +00000000 T ___svgalib_driver24p_getbox libvga driver +00000000 T ___svgalib_driver24_putboxmask libvga driver +00000000 T ___svgalib_driver24_putboxpart libvga driver +00000000 T ___svgalib_driver24p_putboxpart libvga driver +00000000 T ___svgalib_driver24_getboxpart libvga driver +00000000 T ___svgalib_driver24p_getboxpart libvga driver +00000000 T ___svgalib_driver24_copybox libvga driver +00000000 T ___svgalib_driver24a_copybox libvga driver +00000000 T ___svgalib_driver32_setpixel libvga driver +00000000 T ___svgalib_driver32p_setpixel libvga driver +00000000 T ___svgalib_driver32_getpixel libvga driver +00000000 T ___svgalib_driver32p_getpixel libvga driver +00000000 T ___svgalib_driver32_hline libvga driver +00000000 T ___svgalib_driver32p_hline libvga driver +00000000 T ___svgalib_driver32_fillbox libvga driver +00000000 T ___svgalib_driver32p_fillbox libvga driver +00000000 T ___svgalib_driver32_putbox libvga driver +00000000 T ___svgalib_driver32p_putbox libvga driver +00000000 T ___svgalib_driver32_getbox libvga driver +00000000 T ___svgalib_driver32p_getbox libvga driver +00000000 T ___svgalib_driver32_putboxmask libvga driver +00000000 T ___svgalib_driver32_putboxpart libvga driver +00000000 T ___svgalib_driver32p_putboxpart libvga driver +00000000 T ___svgalib_driver32_getboxpart libvga driver +00000000 T ___svgalib_driver32p_getboxpart libvga driver +00000000 T ___svgalib_driver32_copybox libvga driver +00000000 T ___svgalib_driverplanar256_nothing libvga driver +00000000 T ___svgalib_driverplanar256_putbox libvga driver +00000000 T ___svgalib_driverplanar16_nothing libvga driver +00000000 T ___svgalib_driver_setread libvga driver +00000000 T ___svgalib_driver_setwrite libvga driver +00000000 T ___svgalib_driver8p_putboxmask libvga driver +00000000 T ___svgalib_driver8p_copybox libvga driver +00000000 T ___svgalib_driver16p_putboxmask libvga driver +00000000 T ___svgalib_driver16p_copybox libvga driver +00000000 T ___svgalib_driver24p_putboxmask libvga driver +00000000 T ___svgalib_driver24p_copybox libvga driver +00000000 T ___svgalib_driver32p_putboxmask libvga driver +00000000 T ___svgalib_driver32p_copybox libvga driver +00000000 T ___svgalib_memcpy4to3 libvga mem +00000000 T ___svgalib_memcpy32shift8 libvga mem +00000000 C ___svgalib_oldvtmode libvga vga +00000000 C ___svgalib_runinbackground libvga vga +00000000 C ___svgalib_graph_mem_linear_orginal libvga vga +00000000 C ___svgalib_graph_mem_linear_check libvga vga +00000000 C ___svgalib_linear_memory_size libvga vga +00000000 C ___svgalib_linearframebuffer libvga vgamisc +00000000 C ___svgalib_nonaccel_fillbox libvga grlib +00000000 D ___svgalib_apm_driverspecs libvga apm +00000000 D ___svgalib_default_mode libvga vga +00000000 D ___svgalib_nosigint libvga vga +00000000 D ___svgalib_m_ignore_dx libvga mouse/mouse +00000000 D ___svgalib_m_ignore_dy libvga mouse/mouse +00000000 D ___svgalib_m_ignore_dz libvga mouse/mouse +00000000 C ___svgalib_mouse_eventhandler libvga mouse/mouse +00000000 D ___svgalib_graph_base libvga vga +00000000 D ___svgalib_novga libvga vga +00000000 D ___svgalib_secondary libvga vga +00000000 T ___svgalib_pci_find_vendor_vga libvga vgapci +00000000 D ___svgalib_nv3_driverspecs libvga nv3 +00000000 D ___svgalib_et6000_driverspecs libvga et6000 +00000000 C ___svgalib_keyboard_eventhandler libvga keyboard/keyboard +00000000 D ___svgalib_vesa_driverspecs libvga vesa +00000000 T ___svgalib_vm86old libvga lrmi +00000000 T ___svgalib_LRMI_alloc_real libvga lrmi +00000000 T ___svgalib_LRMI_free_real libvga lrmi +00000000 K ___svgalib_LRMI__inline_asm libvga lrmi +00000000 T ___svgalib_LRMI_init libvga lrmi +00000000 T ___svgalib_LRMI_call libvga lrmi +00000000 T ___svgalib_LRMI_int libvga lrmi +00000000 D ___svgalib_textprog libvga vga +00000000 C ___svgalib_TextProg_argv libvga vga +00000000 C ___svgalib_TextProg libvga vga +00000000 D ___svgalib_mx_driverspecs libvga mx diff --git a/obsolete/jump/jump.vars b/obsolete/jump/jump.vars new file mode 100644 index 0000000..aebc868 --- /dev/null +++ b/obsolete/jump/jump.vars @@ -0,0 +1,3 @@ +00000004 C _graph_mem libvga vga +0000005C C _currentcontext libvgagl grlib +00000004 D _gl_font8x8 libvgagl font8x8 diff --git a/obsolete/mach/0-README b/obsolete/mach/0-README new file mode 100644 index 0000000..e2f41bb --- /dev/null +++ b/obsolete/mach/0-README @@ -0,0 +1 @@ +Please read 'man 7 svgalib.mach32' diff --git a/obsolete/mach/CHANGES.mach64 b/obsolete/mach/CHANGES.mach64 new file mode 100644 index 0000000..b274a28 --- /dev/null +++ b/obsolete/mach/CHANGES.mach64 @@ -0,0 +1,74 @@ +Mach64 driver changes log: +-------------------------- +April 11, 1998 (Michael Weller) + VGA Emulation should be used to avoid MACH64 code in get_lut + (and elsewhere?) + +March 17, 1996 (Asad Hanif) + +NON FUNCTIONAL DRIVER sent for inclusion in 1.2.10 + +It doesn't seem to quite work. Its hardcoded to 640x480x256@60hz for +a WINTURBO 2mbVRAM and 68860 ramdac - with the 18818 clock. +The screen has vertical bars thru it... each 64k chunk is a little offset +and its full of crap. I can't seem to track the problem down. I checked +the CRTC registers, and dac programming. They are similar to what I got +from ATI and based on what I yanked from XFree86. + +Help. + +Added dac handling code to vgapal.c. + +Didn't work so I stripped it clean. Removed clock programming... +fixed the dac to 68860 and clock to 8 - the default clock setting. +Based code on combination of ATI's SDK and the mach64 x server. + +Went from a.out to elf. +Discovered a hell of a lof of segfaults. Due to my attempts to be nice +and unmap and free any mapped/allocated ram... uncommented worked fine. + +Nov 18, 1995 (Asad Hanif) + +Re-synced to pre 1.2.9 from 1.2.7 + +Sept 25, 1995 (Asad Hanif) + +So I'm lazy (actually busy) + +Well... I got the updated SDK from ATI. Updated the autodetect function +to reflect the SDK recommendations. I'm gonna avoid using the Extended +vga registers to try and maintain compatability with the CT/ET. So all +work will be done with the Mach64 controller thingy. + +It now downloads all the necessary data from the rom. + + +Sept 2, 1995 (Asad Hanif) + +Stuck in a register dumper so I know what I see. + +It's still a vga driver. + + + +Aug 30, 1995 (Asad Hanif) + +This files was created to log all the changes made to svgalib-1.2.7 in +order to incorporate an ATI Mach 64 driver. + +libvga.h: The Mach64 has 32 bit registers. The libvga.h doesn't + have code for inl and outl. These were added. +vga.h: Well.. gotta tell it there's a new driver. + Mach64 = 13 ooohh.. lucky number. But its actually + the 14th driver-- if you count from 0. :) +vga.c: Added the driver to the list. +config.h: Added some INCLUDE_MACH64_... +driver.h: Added the extern driver specs thingy. +Makefile.aout: stuck a line in their about mach64.c + +mach64.regs: Named register list. +mach64.h: Header file. +mach64.c: Driver. +mach64.CHANGES: You're look at it. + +Genesis diff --git a/obsolete/mach/Makefile b/obsolete/mach/Makefile new file mode 100644 index 0000000..a05483b --- /dev/null +++ b/obsolete/mach/Makefile @@ -0,0 +1,4 @@ +mach32info: mach32info.c + cc -Wall -O2 -s mach32info.c -o mach32info +clean: + rm -f mach32info *.o diff --git a/obsolete/mach/mach32.std-modes b/obsolete/mach/mach32.std-modes new file mode 100644 index 0000000..a265ecd --- /dev/null +++ b/obsolete/mach/mach32.std-modes @@ -0,0 +1,64 @@ +# These are the definitions for the standard modes that the driver uses +# as they are allowed in the EEPROM. If one mode is slightly shifted +# on your screen, you can take the info here and slightly adjust sync +# timing for correct alignment. + +# 640x480 31.406kHz 59.82Hz +define 640x480x256 640x480x32K 640x480x64K 640x480x16M 640x480x16M32 + :20 640 664 675 800 480 491 493 524 -hsync -vsync + +# 640x480 37.736kHz 72.57Hz +define 640x480x256 640x480x32K 640x480x64K 640x480x16M 640x480x16M32 + :9 640 664 668 848 480 489 491 519 -hsync -vsync + +# 800x600 31.492kHz 89.72Hz Interlaced +define 800x600x256 800x600x32K 800x600x64K 800x600x16M 800x600x16M32 + :31 800 888 903 1064 600 611 629 704 interlace +hsync -vsync + +# 800x600 33.835kHz 96.39Hz Interlaced +define 800x600x256 800x600x32K 800x600x64K 800x600x16M 800x600x16M32 + :3 800 880 895 1064 600 611 629 704 interlace +hsync +vsync + +# 800x600 35.156kHz 56.25Hz +define 800x600x256 800x600x32K 800x600x64K 800x600x16M 800x600x16M32 + :3 800 824 832 1024 600 601 603 624 -hsync +vsync + +# 800x600 37.879kHz 60.32Hz +define 800x600x256 800x600x32K 800x600x64K 800x600x16M 800x600x16M32 + :12 800 840 855 1056 600 604 606 627 +hsync +vsync + +# 800x600 44.544kHz 70.04Hz +define 800x600x256 800x600x32K 800x600x64K 800x600x16M 800x600x16M32 + :7 800 808 825 1008 600 609 611 635 -hsync -vsync + +# 800x600 48.044kHz 72.14Hz +define 800x600x256 800x600x32K 800x600x64K 800x600x16M 800x600x16M32 + :4 800 856 870 1048 600 637 639 665 +hsync +vsync + +# 1024x768 35.522kHz 86.64Hz Interlaced +define 1024x768x256 1024x768x32K 1024x768x64K 1024x768x16M 1024x768x16M32 + :7 1024 1040 1061 1264 768 769 787 820 interlace +hsync +vsync + +# 1024x768 48.363kHz 60.00Hz +define 1024x768x256 1024x768x32K 1024x768x64K 1024x768x16M 1024x768x16M32 + :15 1024 1048 1064 1344 768 771 773 805 -hsync -vsync + +# 1024x768 56.476kHz 70.07Hz +define 1024x768x256 1024x768x32K 1024x768x64K 1024x768x16M 1024x768x16M32 + :14 1024 1072 1093 1392 768 776 778 815 -hsync +vsync + +# 1024x768 58.230kHz 72.245Hz +define 1024x768x256 1024x768x32K 1024x768x64K 1024x768x16M 1024x768x16M32 + :14 1024 1056 1072 1328 768 771 773 805 -hsync -vsync + +# 1024x768 53.879kHz 66.03Hz +define 1024x768x256 1024x768x32K 1024x768x64K 1024x768x16M 1024x768x16M32 + :14 1024 1048 1064 1288 768 771 773 805 -hsync -vsync + +# 1280x1024 50.000kHz 87.03Hz Interlaced +define 1280x1024x256 1280x1024x32K 1280x1024x64K 1280x1024x16M 1280x1024x16M32 + :11 1280 1360 1369 1600 1024 1074 1092 1148 interlace +hsync +vsync + +# 1280x1024 50.000kHz 94.97Hz Interlaced +define 1280x1024x256 1280x1024x32K 1280x1024x64K 1280x1024x16M 1280x1024x16M32 + :11 1280 1360 1369 1600 1024 1034 1052 1052 interlace +hsync +vsync diff --git a/obsolete/mach/mach32info.c b/obsolete/mach/mach32info.c new file mode 100644 index 0000000..d7c38d6 --- /dev/null +++ b/obsolete/mach/mach32info.c @@ -0,0 +1,1122 @@ +/* mach32info.c prints out some info about your mach32card */ + +/* Please report the info it produces if the mach32driver of svgalib */ +/* works not like expected. */ + +/* This tool is part of svgalib. Although it's output maybe useful to */ +/* debug Xfree86 Mach32 Servers, I am NOT related to Xfree86!! */ +/* PLEASE DO NOT SEND ME (MICHAEL WELLER) ANY XFREE86 BUG REPORTS!!! */ +/* Thanx in advance. */ + +/* This tool is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This tool is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Copyright 1994 by Michael Weller */ +/* eowmob@exp-math.uni-essen.de mat42b@aixrs1.hrz.uni-essen.de */ +/* eowmob@pollux.exp-math.uni-essen.de */ + +/* + + * MICHAEL WELLER DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL MICHAEL WELLER BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* This tool contains one routine out of Xfree86, therefore I repeat */ +/* its copyright here: (Actually it is longer than the copied code) */ + +/* + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Orest Zborowski and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * Copyright 1993 by Kevin E. Martin, Chapel Hill, North Carolina. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL, KEVIN E. MARTIN, AND RICKARD E. FAITH DISCLAIM ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY + * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Thomas Roell, roell@informatik.tu-muenchen.de + * + * Rewritten for the 8514/A by Kevin E. Martin (martin@cs.unc.edu) + * Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu) + * Rewritten for the Mach32 by Kevin E. Martin (martin@cs.unc.edu) + * + */ + +#include +#include +#include +#include + +/* Some stuff for the ATI VGA */ +#define ATIPORT 0x1ce +#define ATIOFF 0x80 +#define ATISEL(reg) (ATIOFF+reg) +/* Ports we use: */ +#define SUBSYS_CNTL 0x42E8 +#define GE_STAT 0x9AE8 +#define CONF_STAT1 0x12EE +#define CONF_STAT2 0x16EE +#define MISC_OPTIONS 0x36EE +#define MEM_CFG 0x5EEE +#define MEM_BNDRY 0x42EE +#define SCRATCH_PAD_0 0x52EE +#define DESTX_DIASTP 0x8EE8 +#define R_SRC_X 0xDAEE +#define R_EXT_GE_CONF 0x8EEE +#define CHIP_ID 0xFAEE +#define MAX_WAITSTATES 0x6AEE +#define LOCAL_CNTL 0x32EE +#define R_MISC_CNTL 0x92EE +#define PCI_CNTL 0x22EE +#define DISP_STATUS 0x2E8 +#define DISP_CNTL 0x22E8 +#define CLOCK_SEL 0x4AEE +#define H_DISP 0x06E8 +#define H_TOTAL 0x02E8 +#define H_SYNC_WID 0x0EE8 +#define H_SYNC_STRT 0x0AE8 +#define V_DISP 0x16E8 +#define V_SYNC_STRT 0x1AE8 +#define V_SYNC_WID 0x1EE8 +#define V_TOTAL 0x12E8 +#define R_H_TOTAL 0xB2EE +#define R_H_SYNC_STRT 0xB6EE +#define R_H_SYNC_WID 0xBAEE +#define R_V_TOTAL 0xC2EE +#define R_V_DISP 0xC6EE +#define R_V_SYNC_STRT 0xCAEE +#define R_V_SYNC_WID 0xD2EE + + + +/* Bit masks: */ +#define GE_BUSY 0x0200 + +/* Chip_id's */ +#define ATI68800_3 ('A'*256+'A') +#define ATI68800_6 ('X'*256+'X') +#define ATI68800_6HX ('H'*256+'X') +#define ATI68800LX ('L'*256+'X') +#define ATI68800AX ('A'*256+'X') + +static inline void port_out(int value, int port) +{ + __asm__ volatile ("outb %0,%1" + ::"a" ((unsigned char) value), "d"((unsigned short) port)); +} + +static inline void port_outw(int value, int port) +{ + __asm__ volatile ("outw %0,%1" + ::"a" ((unsigned short) value), "d"((unsigned short) port)); +} + +static inline int port_in(int port) +{ + unsigned char value; + __asm__ volatile ("inb %1,%0" + :"=a" (value) + :"d"((unsigned short) port)); + return value; +} + +static inline int port_inw(int port) +{ + unsigned short value; + __asm__ volatile ("inw %1,%0" + :"=a" (value) + :"d"((unsigned short) port)); + return value; +} + +#define inb port_in +#define inw port_inw +#define outb(port, value) port_out(value, port) +#define outw(port, value) port_outw(value, port) + +int force = 0, chip_id, bus; +unsigned short eeprom[128]; +char *pel_width[] = +{" 4bpp", " 8bpp", " 16bpp", " 24bpp"}; +char *bpp16mode[] = +{" 5-5-5", " 5-6-5", " 6-5-5", " 6-6-4"}; +char *bpp24mode[] = +{" RGB", " RGBa", " BGR", " aBGR"}; +char *bustype[] = +{" 16-bit ISA", " EISA", " 16-bit MicroChannel", + " 32-bit MicroChannel", " LocalBus SX, 386SX", + " LocalBus 1/2, 386DX", + " LocalBus 1/2, 486DX", " PCI"}; +char *memtype3[] = +{" 256Kx4 DRAM", " 256Kx4 VRAM, 512 bit serial transfer", + " 256Kx4 VRAM, 256 bit serial transfer", " 256Kx16 DRAM", + " invalid", " invalid", " invalid", " invalid"}; +char *memtype6[] = +{" 256Kx4 DRAM", " 256Kx4 VRAM, 512 bit serial transfer", + " 256Kx16 VRAM, 256 bit serial transfer", " 256Kx16 DRAM", + " 256Kx4 Graphics DRAM", + " 256Kx4 VRAM, 512 bit split transfer", + " 256Kx16 VRAM, 256 bit split transfer", + " invalid"}; +char *dactype[] = +{" ATI-68830 (Type 0)", " SC-11483 (Type 1)", + " ATI-68875 (Type 2)", " Bt-476 (Type 3)", + " Bt-481 (Type 4)", " ATI-68860 (Type 5)", + " Unknown type 6", " Unknown type 7"}; +char *localbus[] = +{" reserved", " LOCAL#2", " LOCAL#3", " LOCAL#1"}; +char *aperture[] = +{" memory aperture disabled", " 1 MB memory aperture", + " 4 MB memory aperture", " reserved"}; +char *mono_color[] = +{" white", " green", " amber", " reserved"}; +char *videomonames[] = +{"lores color - secondary", + "(hires) color - secondary", + "monochrome - secondary", + "lores color - primary", + "hires color - primary", + "monochrome - primary"}; +char *clockdiv[] = +{" 1", " 2", " reserved", " reserved"}; +char *transwid[] = +{" auto select", " 16 bit", " 8 bit", " 8 bit hostdata/16 bit other"}; +char *vgabound[] = +{" shared", " 256 KB", " 512 KB", " 1 MB"}; +char *maxpix[] = +{" 8 bpp", " 16 bpp", " 24 bpp", " reserved"}; +static int mach32_clocks[16]; + +void puttable(int table); + +void usage(void) +{ + fputs("Usage: mach32info {info|force}\n" + " prints out almost all the info about your mach32 card from configuration\n" + " registers and Mach32 EEPROM. It also measures the Mach32 clocks. A\n" + " completely idle system is required when these measurements are being\n" + " performed. During these measurements, the video signals will be screwed up\n" + " for about 3-4 seconds.\n" + "* If your monitor does not switch off when getting a video signal it can't\n" + " stand (fixed freq. monitors) better switch it off before starting\n" + " mach32info. Your computer will beep when it is finished probing.\n" + " You can redirect the 'stdout' of 'mach32info' to some file for viewing\n" + " the results easier. Do not redirect 'stderr' as you won't hear the beep.\n" + "* The 'force' option disables the sanity check that tries to detect the\n" + " presence of the mach32. Do not use this option unless you are really,\n" + " really sure that you have a Mach32 compatible vga card installed.\n" + "* This tool is part of svgalib. Although it's output maybe useful to debug\n" + " Xfree86 Mach32 Servers, I am NOT related to Xfree86! PLEASE DO NOT SEND\n" + " ME (MICHAEL WELLER) ANY XFREE86 BUG REPORTS! Thanx in advance.\n" + "* Note that this tool comes WITHOUT ANY WARRANTY! Use it at your OWN risk!\n" + "* Warning, this tool does not check for VC changes etc.. Just let it run in\n" + " its own virtual console and don't try to fool it.\n" + "Please report any problems with running 'mach32info' or with config-\n" + "uring the 'svgalib' mach32 driver to 'eowmob@exp-math.uni-essen.de'.\n" + "Include the results from running this test with your report.\n", + stderr); + exit(2); +} + +static void mach32_i_bltwait() +{ + int i; + + for (i = 0; i < 100000; i++) + if (!(inw(GE_STAT) & (GE_BUSY | 1))) + break; + if (i >= 100000) + puts("GE idled out"); +} + +static int mach32_test() +{ + int result = 0; + short tmp; + + tmp = inw(SCRATCH_PAD_0); + outw(SCRATCH_PAD_0, 0x5555); + mach32_i_bltwait(); + if (inw(SCRATCH_PAD_0) == 0x5555) { + outw(SCRATCH_PAD_0, 0x2a2a); + mach32_i_bltwait(); + if (inw(SCRATCH_PAD_0) == 0x2a2a) { + /* Aha.. 8514/a detected.. */ + result = 1; + } + } + outw(SCRATCH_PAD_0, tmp); + if (!result) + goto quit; +/* Now ensure it is not a plain 8514/a: */ + result = 0; + outw(DESTX_DIASTP, 0xaaaa); + mach32_i_bltwait(); + if (inw(R_SRC_X) == 0x02aa) { + outw(DESTX_DIASTP, 0x5555); + mach32_i_bltwait(); + if (inw(R_SRC_X) == 0x0555) + result = 1; + } + quit: + return result; +} + +static void mach32_wait() +{ +/* Wait for at least 22 us.. (got that out of a BIOS disassemble on my 486/50 ;-) ) ... */ + register int i; + volatile dummy; + + for (i = 0; i < 16; i++) + dummy++; /*Dummy is volatile.. */ +} + +static int mach32_eeclock(register int ati33) +{ + outw(ATIPORT, ati33 |= 0x200); /* clock on */ + mach32_wait(); + outw(ATIPORT, ati33 &= ~0x200); /* clock off */ + mach32_wait(); + return ati33; +} + +static void mach32_eekeyout(register int ati33, register int offset, register int mask) +{ + do { + if (mask & offset) + ati33 |= 0x100; + else + ati33 &= ~0x100; + outw(ATIPORT, ati33); + mach32_eeclock(ati33); + } + while (mask >>= 1); +} + +static int mach32_eeget(int offset) +{ + register int ati33; + register int result, i; + +/* get current ATI33 */ + outb(ATIPORT, ATISEL(0x33)); + ati33 = ((int) inw(ATIPORT + 1)) << 8; + ati33 |= ATISEL(0x33); +/* prepare offset.. cut and add header and trailer */ + offset = (0x600 | (offset & 0x7f)) << 1; + +/* enable eeprom sequence */ + ati33 = mach32_eeclock(ati33); +/*input to zero.. */ + outw(ATIPORT, ati33 &= ~0x100); +/*enable to one */ + outw(ATIPORT, ati33 |= 0x400); + mach32_eeclock(ati33); +/*select to one */ + outw(ATIPORT, ati33 |= 0x800); + mach32_eeclock(ati33); + mach32_eekeyout(ati33, offset, 0x800); + for (i = 0, result = 0; i < 16; i++) { + result <<= 1; + outb(ATIPORT, ATISEL(0x37)); + if (inb(ATIPORT + 1) & 0x8) + result |= 1; + mach32_eeclock(ati33); + } +/*deselect... */ + outw(ATIPORT, ati33 &= ~0x800); + mach32_eeclock(ati33); +/*disable... */ + outw(ATIPORT, ati33 &= ~0x400); + mach32_eeclock(ati33); + return result; +} + +void putflag(char *str, int flag) +{ + int i; + + i = 72 - strlen(str) - 10; + printf(" %s ", str); + while (i-- > 0) + putchar('.'); + puts(flag ? ". enabled" : " disabled"); +} + +void putint(char *str, char *format, int value) +{ + char buffer[128]; + int i; + + sprintf(buffer, format, value); + i = 72 - strlen(str) - strlen(buffer); + printf(" %s ", str); + while (i-- > 0) + putchar('.'); + puts(buffer); +} + +void putstr(char *str, char *strval) +{ + putint(str, strval, 0); +} + +unsigned short putword(int word) +{ + printf("\n EEPROM Word %02xh:\t%04x\n", word, eeprom[word]); + return eeprom[word]; +} + +char * + offset(char *buffer, int word) +{ + int tab; + + word >>= 8; + if ((word < 0x0d) || (word > 0x67)) { + illegal: + sprintf(buffer, " %02xh words (no table there)", word); + } else { + tab = word - 0x0d; + if (tab % (0x1c - 0x0d)) + goto illegal; + sprintf(buffer, " %02xh words (table %d)", word, tab / (0x1c - 0x0d) + 1); + } + return buffer; +} + +char * + hsyncstr(int pixels, int clock, double fclock) +{ + static char buffer[50]; + + if (!clock) + sprintf(buffer, " %d pixels", pixels); + else + sprintf(buffer, " %d pixels, %.3f us", + pixels, pixels / fclock); + return buffer; +} + +char * + vsyncstr(int lines, int clock, double lilen) +{ + static char buffer[50]; + + if (!clock) + sprintf(buffer, " %d lines", lines); + else + sprintf(buffer, " %d lines, %.3f ms", + lines, lines / lilen); + return buffer; +} + +/* Shamelessly ripped out of Xfree2.1 (with slight changes) : */ + +static void mach32_scan_clocks(void) +{ + const int knownind = 7; + const double knownfreq = 44.9; + + char hstrt, hsync; + int htotndisp, vdisp, vtotal, vstrt, vsync, clck, i; + + int count, saved_nice, loop; + double scale; + + saved_nice = nice(0); + nice(-20 - saved_nice); + + puts( + "Warning, about to measure clocks. Wait until system is completely idle!\n" + "Any activity will disturb measuring, and therefor hinder correct driver\n" + "function. Test will need about 3-4 seconds."); +#if 0 + puts("\n(Enter Y to continue, any other text to bail out)"); + + if (getchar() != 'Y') + exit(0); + if (getchar() != '\n') + exit(0); +#endif + + htotndisp = inw(R_H_TOTAL); + hstrt = inb(R_H_SYNC_STRT); + hsync = inb(R_H_SYNC_WID); + vdisp = inw(R_V_DISP); + vtotal = inw(R_V_TOTAL); + vstrt = inw(R_V_SYNC_STRT); + vsync = inw(R_V_SYNC_WID); + clck = inw(CLOCK_SEL); + + outb(DISP_CNTL, 0x63); + + outb(H_TOTAL, 0x63); + outb(H_DISP, 0x4f); + outb(H_SYNC_STRT, 0x52); + outb(H_SYNC_WID, 0x2c); + outw(V_TOTAL, 0x418); + outw(V_DISP, 0x3bf); + outw(V_SYNC_STRT, 0x3d6); + outw(V_SYNC_WID, 0x22); + + for (i = 0; i < 16; i++) { + outw(CLOCK_SEL, (i << 2) | 0xac1); + outb(DISP_CNTL, 0x23); + + usleep(50000); + + count = 0; + loop = 200000; + + while (!(inb(DISP_STATUS) & 2)) + if (loop-- == 0) + goto done; + while (inb(DISP_STATUS) & 2) + if (loop-- == 0) + goto done; + while (!(inb(DISP_STATUS) & 2)) + if (loop-- == 0) + goto done; + + for (loop = 0; loop < 5; loop++) { + while (!(inb(DISP_STATUS) & 2)) + count++; + while ((inb(DISP_STATUS) & 2)) + count++; + } + done: + mach32_clocks[i] = count; + + outb(DISP_CNTL, 0x63); + } + + outw(CLOCK_SEL, clck); + + outw(H_DISP, htotndisp); + outb(H_SYNC_STRT, hstrt); + outb(H_SYNC_WID, hsync); + outw(V_DISP, vdisp); + outw(V_TOTAL, vtotal); + outw(V_SYNC_STRT, vstrt); + outw(V_SYNC_WID, vsync); + nice(20 + saved_nice); + +/*Recalculation: */ + scale = ((double) mach32_clocks[knownind]) * knownfreq; + for (i = 0; i < 16; i++) { + if (i == knownind) + continue; + if (mach32_clocks[i]) + mach32_clocks[i] = 0.5 + scale / ((double) mach32_clocks[i]); + } + mach32_clocks[knownind] = knownfreq + 0.5; +} + +int main(int argc, char *argv[]) +{ + char *ptr, buffer[40]; + int i, j, lastfound, mask, index, flag; + + memset(eeprom, 0, sizeof(unsigned short) * (size_t) 256); + + if (argc != 2) + usage(); + if (strcmp(argv[1], "info")) { + if (strcmp(argv[1], "force")) + usage(); + force = 1; + } + if (iopl(3) < 0) { + fputs("mach32info needs to be run as root!\n", stderr); + exit(1); + } + if (!force) { + if (mach32_test()) + puts("Mach32 succesful detected."); + else { + fputs("Sorry, no Mach32 detected.\n", stderr); + exit(1); + } + } else + puts("Mach32 autodetection skipped."); + + puts("\nThis tool is part of svgalib. Although this output maybe useful\n" + "to debug Xfree86 Mach32 Servers, I am NOT related to Xfree86!!\n" + "PLEASE DO NOT SEND ME (MICHAEL WELLER) ANY XFREE86 BUG REPORTS!!!\n" + "Thanx in advance.\n"); + + mach32_scan_clocks(); + + puts("\nResulting clocks command for your libvga.config should be:\n"); + fputs("clocks", stdout); + for (i = 0; i < 16; i++) + printf(" %3d", mach32_clocks[i]); + + fputs("\a", stderr); + fflush(stderr); + puts("\n\nParsing for chip id..."); + lastfound = inw(CHIP_ID) & 0x3ff; + flag = 0; + for (i = 0; i < 10240; i++) { + j = inw(CHIP_ID) & 0x3ff; + index = (j >> 4); + mask = 1 << (j & 15); + if (!(eeprom[index] & mask)) + printf("\tfound id: %c%c\n", + 0x41 + ((j >> 5) & 0x1f), 0x41 + (j & 0x1f)); + eeprom[index] |= mask; + if (lastfound != j) + flag = 1; + } +/* Build chip_id from last found id: */ + chip_id = (j & 0x1f) + ((j << 3) & 0x1f00); + chip_id += ATI68800_3; + + switch (chip_id) { + case ATI68800_3: + ptr = "ATI68800-3 (guessed)"; + break; + case ATI68800_6: + ptr = "ATI68800-6"; + break; + case ATI68800_6HX: + ptr = "ATI68800-6 (HX-id)"; + break; + case ATI68800LX: + ptr = "ATI68800LX"; + break; + case ATI68800AX: + ptr = "ATI68800AX"; + break; + default: + ptr = "Unknown (assuming ATI68800-3)"; + chip_id = ATI68800_3; + flag = 1; + break; + } + printf("Chipset: %s, Class: %d, Revision: %d\n", + ptr, (j >> 10) & 3, (j >> 12) & 15); + if (flag) { + puts( + "WARNING! Strange chipset id! Please report all output of this utility\n" + "together with exact type of your card / type printed on your videochips\n" + "to me, Michael Weller, eowmob@exp-math.uni-essen.de. Alternate\n" + "email-addresses are in the source of this utility and in 'README.mach32'.\n" + ); + } + j = inw(MAX_WAITSTATES); + if (chip_id == ATI68800AX) { + printf("\nAPERTURE_CNTL:\t\t%04x\n", j); + putflag("Zero waitstates for PCI aperture", j & 0x400); + putflag("Fifo read ahead for PCI aperture", j & 0x800); + putflag("Pixel stream 1 SCLK delay", j & 0x1000); + putflag("Decrement burst", j & 0x2000); + putstr("Direction of burst", (j & 0x4000) ? + "Increments burst" : "Decrements burst"); + putflag("Bus timeout on burst read/writes", !(j & 0x8000)); + } else { + printf("\nMAX_WAITSTATES:\t\t%04x\n", j); + putint("Max. I/O waitstates", " %d", 4 * (j & 15)); + putint("BIOS-ROM waitstates", " %d", (j >> 4) & 15); + putflag("Linedraw optimizations", j & 0x100); + } + j = inw(MISC_OPTIONS); + printf("\nMISC_OPTIONS:\t\t%04x\n", j); + putflag("Waitstates if FIFO is half full", j & 0x0001); + putstr("Host data I/O size", (j & 0x0002) ? "8-bit" : "16-bit"); + putint("Memory size", " %d KB", (1 << ((j >> 2) & 3)) * 512); + putflag("VGA-controller", !(j & 0x0010)); + putflag("16-bit 8514 I/O cycles", j & 0x0020); + putflag("Local RAMDAC", !(j & 0x0040)); + putflag("VRAM-serial/DRAM-memory(bits 63:0) data delay latch", j & 0x0080); + putflag("Test-mode", j & 0x0100); + putflag("Non ATI68800-3: Block-write", j & 0x0400); + putflag("Non ATI68800-3: 64-bit Draw", j & 0x0800); + putflag("Latch video memory read data", j & 0x1000); + putflag("Memory data delay latch(bits 63:0)", j & 0x2000); + putflag("Memory data latch full clock pulse", j & 0x4000); + + + j = inw(R_EXT_GE_CONF); + printf("\nR_EXT_GE_CONF:\t\t%04x\n", j); + putint("Monitor alias id", " %d", j & 7); + putflag("Monitor alias", j & 0x0008); + putstr("Pixel width", pel_width[(j >> 4) & 3]); + putstr("16 bit per plane organization", bpp16mode[(j >> 6) & 3]); + putflag("Multiplex pixels", j & 0x0100); + putstr("24 bit per plane organization", bpp24mode[(j >> 9) & 3]); + putstr("Reserved (11)", (j & 0x0800) ? " 1" : " 0"); + putint("Extended RAMDAC address", " %d", (j >> 12) & 3); + putflag("8 bit RAMDAC operation", j & 0x4000); + putstr("Reserved (15)", (j & 0x8000) ? " 1" : " 0"); + + j = inw(CONF_STAT1); + printf("\nCONF_STAT1:\t\t%04x\n", j); + putflag("VGA circuitry", !(j & 0x0001)); + putstr("Bus Type", bustype[bus = ((j >> 1) & 7)]); + putstr("Memory Type", (chip_id == ATI68800_3) ? memtype3[(j >> 4) & 7] : + memtype6[(j >> 4) & 7]); + putflag("Chip", !(j & 0x0080)); + putflag("Delay memory write for tests", (j & 0x0100)); + putstr("RAMDAC Type", dactype[(j >> 9) & 7]); + putflag("Internal MicroChannel address decode", !(j & 0x1000)); + putint("Controller id (0 if unsupported)", " %d", (j >> 13) & 7); + + j = inw(CONF_STAT2); + printf("\nCONF_STAT2:\t\t%04x\n", j); + if (chip_id == ATI68800_3) + putflag("ATI68800-3: 2 clock sequencer timing", j & 0x0001); + else + putstr("Reserved (0)", (j & 0x0001) ? " 1" : " 0"); + putflag("Memory address range FE0000-FFFFFF", !(j & 0x0002)); + if (!bus) + putflag("16-bit ISA Bus (ISA cards only)", (j & 0x0004)); + else + putstr("Reserved (2)", (j & 0x0004) ? " 1" : " 0"); + putflag("Korean character font support", (j & 0x0008)); + putstr("Local Bus signal (Local Bus only)", localbus[(j >> 4) & 3]); + putflag("Local Bus 2 (non multiplexed) configuration", (j & 0x0040)); + putflag("Read data 1 clk after RDY (Local Bus only)", (j & 0x0080)); + putflag("Local decode of RAMDAC write (Local Bus only)", !(j & 0x0100)); + putflag("1 clk RDY delay for write (Local Bus only)", !(j & 0x0200)); + putstr("BIOS EPROM at", (j & 0x0400) ? " C000:0-C7FF:F" : " E000:0-E7FF:F"); + switch (bus) { + case 1: + putflag("Enable POS register function (EISA)", (j & 0x0800)); + break; + case 4: + case 5: + case 6: + putflag("Local decode of 102h register (Local Bus only)", + !(j & 0x0800)); + break; + default: + putstr("Reserved (11)", (j & 0x0800) ? " 1" : " 0"); + break; + } + putflag("VESA compliant RDY format (Local Bus only)", !(j & 0x1000)); + putflag("Non ATI68800-3: 4 GB aperture address", (j & 0x2000)); + putstr("Non ATI68800-3: Memory support in LBus 2 config", + (j & 0x4000) ? " 2MB DRAM" : " 1MB DRAM"); + putstr("Reserved (15)", (j & 0x8000) ? " 1" : " 0"); + + j = inw(MEM_BNDRY); + printf("\nMEM_BNDRY:\t\t%04x\n", j); + putint("Video memory partition (VGA <, Mach32 >=)", " %d KB", (j & 15) * 256); + putflag("Video memory partition write protection", j & 0x0010); + putint("Reserved (15:5)", " %03xh", (j >> 5)); + + + j = inw(MEM_CFG); + printf("\nMEM_CFG:\t\t%04x\n", j); + putstr("Memory aperture", aperture[j & 3]); + putint("Memory aperture page (for 1MB aperture)", " %d", (j >> 2) & 3); + if ((bus == 7) || (((bus == 5) || (bus == 6)) && (inw(CONF_STAT2) & 0x2000))) + putint("Memory aperture location (0-4 GB)", " %d MB", j >> 4); + else { + putint("Reserved (7:4)", " %x", (j >> 4) & 0xf); + putint("Memory aperture location (0-128 MB)", " %d MB", j >> 8); + } + + j = inw(LOCAL_CNTL); + printf("\nLOCAL_CNTL:\t\t%04x\n", j); + putflag("6 clock non page cycle", j & 0x0001); + putflag("7 clock non page cycle", j & 0x0002); + putflag("1/2 memory clock CAS precharge time", j & 0x0004); + putflag("RAMDAC clocked on positive clock edge", j & 0x0008); + putflag("FIFO testing", j & 0x0010); + if (chip_id == ATI68800_3) + putint("Filtering of 1 clock IOW low or high pulse", " %d", (j >> 5) & 3); + else { + putflag("Memory mapped registers", j & 0x0020); + putflag("Local Bus BIOS ROM decode", j & 0x0040); + } + putint("ROM wait states", " %d", (j >> 7) & 7); + putint("Memory read wait states", " %d", (j >> 10) & 3); + if (chip_id == ATI68800AX) + putint("Additional I/O waitstates", " %d", (j >> 12) & 15); + else + putint("Minimum Local Bus waistates", " %d", (j >> 12) & 15); + + j = inw(R_MISC_CNTL); + printf("\nR_MISC_CNTL:\t\t%04x\n", j); + putint("Reserved (3:0)", " %x", j & 15); + putint("ROM page select", " %d KB", (j >> 3) & 0x1e); + putint("Blank adjust (delays BLANK_1_PCLK for RAMDAC type 2)", " %d", (j >> 8) & 3); + putint("Pixel data skew from PCLK (pixel delay)", " %d", (j >> 10) & 3); + putint("Reserved (15:12)", " %x", (j >> 12) & 15); + + j = inw(PCI_CNTL); + printf("\nPCI_CNTL:\t\t%04x\n", j); + putint("RAMDAC read/write waitstates", " %d", j & 7); + putflag("Target abort cycle", j & 0x0004); + putflag("PCI RAMDAC delay", j & 0x0010); + putflag("Snooping on DAC read", j & 0x0020); + putflag("0 waitstates on aperture burst write", j & 0x0040); + putflag("Fast memory mapped I/O read/write", j & 0x0080); + putint("Reserved (15:8)", " %02x", (j >> 8) & 0xff); + + fputs("\nReading in EEPROM... (some screen flicker will occur)", stdout); + fflush(stdout); + for (i = 0; i < 128; i++) + eeprom[i] = mach32_eeget(i); + puts(" ...done.\n"); + fputs("EEPROM contents:", stdout); + for (i = 0; i < 128; i++) { + if (i & 7) + putchar(' '); + else + fputs("\n ", stdout); + printf(" %02x-%04x", i, eeprom[i]); + } + puts("\n\nDecoded info out of EEPROM:"); + putword(0); + putint("EEPROM write counter", " %d", eeprom[0]); + putword(1); + switch (eeprom[1] & 0xff) { + case 0x00: + ptr = " disabled"; + break; + case 0x08: + ptr = " secondary address"; + break; + case 0x18: + ptr = " primary address"; + break; + default: + ptr = " reserved"; + } + putstr("Mouse address select", ptr); + switch ((eeprom[1] >> 8) & 0xff) { + case 0x20: + ptr = " IRQ 5"; + break; + case 0x28: + ptr = " IRQ 4"; + break; + case 0x30: + ptr = " IRQ 3"; + break; + case 0x38: + ptr = " IRQ 2"; + break; + default: + ptr = " reserved"; + } + putstr("Mouse interrupt handler select", ptr); + j = putword(2); + switch ((j >> 8) & 0xff) { + case 0x03: + case 0x05: + case 0x07: + case 0x09: + case 0x0b: + case 0x12: + case 0x13: + case 0x15: + case 0x17: + case 0x19: + case 0x1b: + sprintf(ptr = buffer, " %cGA %s", (j & 0x1000) ? 'E' : 'V', + videomonames[(((j >> 8) & 0xf) - 1) >> 1]); + break; + case 0x20: + ptr = " CGA"; + break; + case 0x30: + ptr = " Hercules 720x348"; + break; + case 0x40: + ptr = " Hercules 640x400"; + break; + default: + ptr = " reserved"; + } + putstr("Power up video mode", ptr); + putstr("Monochrome color", mono_color[(j >> 6) & 3]); + putflag("Dual monitor", j & 0x0020); + putstr("Power up font", (j & 0x0010) ? " 8x16 or 9x16" : " 8x14 or 9x14"); + putint("VGA Bus I/O", " %d bits", (j & 0x0008) + 8); + putflag("0 waitstates RAM read/write", j & 0x0004); + putflag("0 waitstates ROM read", j & 0x0002); + putflag("ROM 16 bit", j & 0x0001); + j = putword(3); + putflag("Scrolling fix", j & 0x8000); + putflag("Korean BIOS support", j & 0x4000); + putint("Reserved (13:4)", " %03xh", (j >> 4) & 0x3ff); + putint("EEPROM table revision", " %d", j & 15); + j = putword(4); + putint("Custom monitor indices", " %04x", j); + j = putword(5); + putstr("Host data transfer width", transwid[(j >> 14) & 3]); + putint("Monitor code", " %02xh", (j >> 8) & 0x3f); + putint("Reserved (7)", " %d", (j >> 7) & 1); + putstr("VGA boundary", vgabound[(j >> 4) & 3]); + putflag("Monitor alias", j & 0x0008); + putint("Monitor alias setting", " %d", j & 0x0007); + j = putword(6); + putint("Memory aperture location", " %d MB", (j >> 4)); + j &= 15; + putstr("Memory aperture size", aperture[(j > 3) ? 3 : j]); + j = putword(7); + putstr("Offset to 640x480 mode table", offset(buffer, j)); + putint("Reserved (7:2)", " %02xh", (j >> 2) & 0x3f); + putflag("Use stored params for 640x480", j & 2); + putflag("640x480 72Hz", j & 1); + j = putword(8); + putstr("Offset to 800x600 mode table", offset(buffer, j)); + putflag("Use stored params for 800x600", j & 0x80); + putint("Reserved (6)", " %d", (j >> 6) & 1); + putflag("800x600 72Hz", j & 0x20); + putflag("800x600 70Hz", j & 0x10); + putflag("800x600 60Hz", j & 8); + putflag("800x600 56Hz", j & 4); + putflag("800x600 89Hz Interlaced", j & 2); + putflag("800x600 95Hz Interlaced", j & 1); + j = putword(9); + putstr("Offset to 1024x768 mode table", offset(buffer, j)); + putflag("Use stored params for 1024x768", j & 0x80); + putint("Reserved (6:5)", " %d", (j >> 5) & 3); + putflag("1024x768 66Hz", j & 0x10); + putflag("1024x768 72Hz", j & 8); + putflag("1024x768 70Hz", j & 4); + putflag("1024x768 60Hz", j & 2); + putflag("1024x768 87Hz Interlaced", j & 1); + j = putword(10); + putstr("Offset to 1280x1024 mode table", offset(buffer, j)); + putflag("Use stored params for 1280x1024", j & 0x80); + putint("Reserved (6:2)", " %02xh", (j >> 2) & 0x1f); + putflag("1280x1024 95Hz Interlaced", j & 2); + putflag("1280x1024 87Hz Interlaced", j & 1); + j = putword(11); + putstr("Offset to alternate mode table", offset(buffer, j)); + putflag("Use stored params for alternate", j & 0x80); + putint("Reserved (6:2)", " %02xh", (j >> 2) & 0x1f); + putflag("1152x900", j & 2); + putflag("1120x760", j & 1); + for (j = 0; j < 7; j++) + puttable(j); + puts("\n EEPROM Words 76h-7dh: reserved."); + j = putword(0x7e); + putint("Reserved (15)", " %d", j >> 15); + putflag("VGA circuitry", j & 0x4000); + putint("Memory size", " %d KB", 1 << (((j >> 11) & 7) + 8)); + putstr("DAC type", dactype[(j >> 8) & 7]); + putint("Reserved (7:0)", " %02xh", j & 0xff); + j = putword(0x7f); + putint("EEPROM Checksum", " %04x", j); + j = 0; + for (i = 0; i <= 0x7f;) + j += eeprom[i++]; + printf("\nEEPROM contents sum up to %04x:%04x.\n", j >> 16, j & 0xffff); + if (!(j & 0xffff)) { + puts("ATI style checksum."); + } else { + j -= (eeprom[0x7f] << 1) - 1; + if (!(j & 0xffff)) + puts("AST style checksum."); + else + puts( + "WARNING! Strange EEPROM checksum!\n" + "Be sure that:\n" + "1. You installed the Mach32 correctly with the ATI install tool from\n" + " DOS (yuck!).\n" + "2. Wrote the proper config to the EEPROM with it.\n" + "3. DOS bios reads out the Mach32 EEPROM with out problems and obeys\n" + " all settings (for example, power up video mode).\n" + "If you can't get a correct checksum, read the section \"EEPROM woes\"\n" + "in \"README.mach32\" of your svgalib distribution.\n" + ); + } + return 0; +} + +void puttable(int table) +{ + int i; + int clock; + char buffer[80]; + + unsigned short *tab; + + tab = eeprom + (table * 15 + 0xd); + printf("\n EEPROM Words %02xh-%02xh:\tCRT Parameter table %d", table * 15 + 0xd, + (table + 1) * 15 + 0xc, table + 1); + if (tab[10] & 0x3f00) + puts(":"); + else { + puts(" ..................... invalid"); + return; + } + table = tab[0]; + putstr("Vertical sync polarity", (table & 0x8000) ? " -" : " +"); + putstr("Horizontal sync polarity", (table & 0x4000) ? " -" : " +"); + putflag("Interlace", table & 0x2000); + putflag("Multiplex pixels", table & 0x1000); + i = (table >> 9) & 7; + putstr("Maximum pixel depth", maxpix[(i > 3) ? 3 : i]); + putstr("Parameter type", (table & 0x0100) ? " 8514/Mach32" : " VGA"); + putstr("Dotclock select", (table & 0x0080) ? " user supplied" : " default"); + putstr("Usage of CRTC parameters", (table & 0x0040) ? " all" + : " sync polarities only"); + putint("Dotclock chip select", " #%d", table & 15); + clock = mach32_clocks[table & 15]; + putstr("Dotclock divide by", clockdiv[(table >> 4) & 3]); + if (!(table & 0x20)) + if (table & 0x10) + clock /= 2; + if (clock) + putint("Pixel clock (approximate value)", " %d MHz", (int) (clock + 0.5)); + else + putstr("Pixel clock", " (sorry, don't know the frequency)"); + if (table & 0x0100) { /*8514/Mach32 */ + double fclock, lilen; + int xpels = ((tab[3] & 0xff) + 1) << 3, ypels = tab[6], xtotal = ((tab[3] >> 8) + 1) << 3, + ytotal = tab[5], xstart = ((tab[4] >> 8) + 1) << 3, ystart = tab[7], + xsync = (tab[4] & 0x1f) * 8, ysync = (tab[8] >> 8) & 0x1f; + puts(" Mach32 / 8514/A CRT parameters:"); + putint("Video fifo 16bpp", " %d", tab[2] & 0xff); + putint("Video fifo 24bpp", " %d", tab[2] >> 8); + putint("H_TOTAL", " %d", tab[3] >> 8); + putint("H_DISP", " %d", tab[3] & 0xff); + putint("H_SYNC_STRT", " %d", tab[4] >> 8); + putint("H_SYNC_WID", " %02xh", tab[4] & 0xff); + putint("V_TOTAL", " %xh", tab[5]); + putint("V_DISP", " %xh", tab[6]); + putint("V_SYNC_STRT", " %xh", tab[7]); + putint("V_SYNC_WID", " %02xh", tab[8] >> 8); + putint("DISP_CNTL", " %02xh", tab[8] & 0xff); + putint("CLOCK_SEL", " %xh", tab[9]); + clock = mach32_clocks[(tab[9] >> 2) & 15]; + if (!(tab[9] & 0x40)) + clock *= 2; + puts(" Resulting video timings:"); + if (clock) { + sprintf(buffer, " %.1f MHz", fclock = ((double) clock) / 2); + } else { + sprintf(buffer, " #%d, don't know clock frequency, so no timings", + (tab[9] >> 2) & 15); + fclock = 0; + } + putstr("Pixel clock", buffer); + switch (tab[8] & 0x6) { + case 0: + ypels = ((ypels >> 2) & ~1) | (ypels & 1); + ytotal = ((ytotal >> 2) & ~1) | (ytotal & 1); + ystart = ((ystart >> 2) & ~1) | (ystart & 1); + break; + case 2: + ypels = ((ypels >> 1) & 0xFFFC) | (ypels & 3); + ytotal = ((ytotal >> 1) & 0xFFFC) | (ytotal & 3); + ystart = ((ystart >> 1) & 0xFFFC) | (ystart & 3); + break; + default: + puts(" Unknown DISP_CNTL, vertical values are probably wrong."); + } + ypels++; + ytotal++; + ystart++; + sprintf(buffer, " %d x %d%s", xpels, ypels, (tab[8] & 0x10) ? ", Interlaced" : + ""); + putstr("Resolution", buffer); + if (clock) { + sprintf(buffer, " %.3f KHz", lilen = (fclock * 1e3) / xtotal); + putstr("Horizontal frequency", buffer); + sprintf(buffer, " %.2f Hz", (lilen * 1000) / ytotal); + putstr("Vertical frequency", buffer); + } else + lilen = 0; + putstr("Horizontal sync polarity", (tab[4] & 0x20) ? " -" : " +"); + putstr("Horizontal sync width", hsyncstr(xsync, clock, fclock)); + putstr("Horizontal front porch", hsyncstr(xstart - xpels, clock, fclock)); + putstr("Horizontal back porch", hsyncstr(xtotal - xsync - xstart, + clock, fclock)); + putstr("Horizontal active time", hsyncstr(xpels, clock, fclock)); + putstr("Horizontal blank time", hsyncstr(xtotal - xpels, clock, fclock)); + putstr("Vertical sync polarity", (tab[8] & 0x2000) ? " -" : " +"); + putstr("Vertical sync width", vsyncstr(ysync, clock, lilen)); + putstr("Vertical front porch", vsyncstr(ystart - ypels, clock, lilen)); + putstr("Vertical back porch", vsyncstr(ytotal - ysync - ystart, + clock, lilen)); + putstr("Vertical active time", vsyncstr(ypels, clock, lilen)); + putstr("Vertical blank time", vsyncstr(ytotal - ypels, clock, lilen)); + } else { /*VGA mode */ + puts(" VGA CRT parameters:"); + putint("VIDEO_MODE_SEL_1", " %02xh", tab[1] >> 8); + putint("VIDEO_MODE_SEL_2", " %02xh", tab[1] & 0xff); + putint("VIDEO_MODE_SEL_3", " %02xh", tab[2] >> 8); + putint("VIDEO_MODE_SEL_4", " %02xh", tab[2] & 0xff); + putint("H_TOTAL (CRT00)", " %02xh", tab[3] >> 8); + putint("V_TOTAL (CRT06)", " %02xh", tab[3] & 0xff); + putint("H_RETRACE_START (CRT04)", " %02xh", tab[4] >> 8); + putint("H_RETRACE_END (CRT05)", " %02xh", tab[4] & 0xff); + putint("V_RETRACE_START (CRT10)", " %02xh", tab[5] >> 8); + putint("V_RETRACE_END (CRT11)", " %02xh", tab[5] & 0xff); + putint("H_BLANK_START (CRT02)", " %02xh", tab[6] >> 8); + putint("H_BLANK_END (CRT03)", " %02xh", tab[6] & 0xff); + putint("V_BLANK_START (CRT15)", " %02xh", tab[7] >> 8); + putint("V_BLANK_END (CRT16)", " %02xh", tab[7] & 0xff); + putint("CRT_OVERFLOW (CRT07)", " %02xh", tab[8] >> 8); + putint("MAX_SCANLINE (CRT09)", " %02xh", tab[8] & 0xff); + putint("V_DISPLAYED (CRT12)", " %02xh", tab[9] >> 8); + putint("CRT_MODE (CRT17)", " %02xh", tab[9] & 0xff); + puts( + " Resulting video timings ......................... not implemented for VGA" + ); + } + table = tab[10]; + puts(" Additional mode flags:"); + putflag("Pixel clock divide by 2", table & 0x8000); + putflag("Multiplex (MUX flag)", table & 0x4000); + putint("Size of mode table", " %d words", (table >> 8) & 0x3f); + putstr("Offset to alternate table", offset(buffer, (table << 8) & 0xff00)); + putint("Horizontal overscan", " %d", tab[11]); + putint("Vertival overscan", " %d", tab[12]); + putint("Overscan color blue", " %d", tab[13] >> 8); + putint("Overscan color index 8bpp", " %d", tab[13] & 0xff); + putint("Overscan color red", " %d", tab[14] >> 8); + putint("Overscan color green", " %d", tab[14] & 0xff); +} diff --git a/obsolete/mach/mach64.c b/obsolete/mach/mach64.c new file mode 100644 index 0000000..0548b95 --- /dev/null +++ b/obsolete/mach/mach64.c @@ -0,0 +1,1091 @@ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ +/* THIS DRIVER DOES NOT WORK */ + + + +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright (C) 1993 Harm Hanemaayer */ + +/* + Initial ATI Mach64 Driver. + August 1995. + Asad F. Hanif (w81h@unb.ca) + Copyright (C) 1995 Asad F. Hanif (w81h@unb.ca) + */ + +/* + Note: This code is based on the material provided to me by + the folks at ATI. As well portions are based on + the Mach64 XFree86 Server code. + + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#include "mach64.h" + +/* globals */ +static int DUMPINDEX; +static char DUMPOUT[33]; +static US ioBaseAddress, PciIOLocation; +static UB cTabSize, *RomLocation; +static UL *mreg; + +static M64_ClockInfo ClockInfo; +static M64_MaxColorDepth MaxCDT1[50], MaxCDT2[50], FreqCDT1[50], FreqCDT2[50]; +static M64_StartUpInfo StartupInfo; +/*static CRTC_Table *pcrtc; */ + +/* prototypes */ +/* svgalib - driverspec functions */ +static void nothing(void); +static int mach64_init(int, int, int); +static int mach64_test(void); +static int mach64_saveregs(UB *); +static void mach64_setregs(const UB *, int); +static void mach64_getmodeinfo(int, vga_modeinfo *); +static int mach64_modeavailable(int); +static int mach64_setmode(int, int); +static void mach64_setdisplaystart(int); +static void mach64_setlogicalwidth(int); +static void mach64_setpage(int); + +/* misc. functions */ +static UB *mach64_rom_base(void); +static UB *mach64_map_vbios(UB *); + +/*static void mach64_unmap_vbios(UB *,UB *); */ + +static void mach64_get_alot_of_info(UB *); +static void mach64_report(void); + +/* dac control and programming */ +#define DAC_TYPE StartupInfo.Dac_Type +#define DAC_SUBTYPE StartupInfo.Dac_Subtype + +static int mach64_dac_ati68860(US, US); +static void mach64_dac_program(US, US, US); +static void mach64_crtc_programming(US, US, US); + +static void mach64_small_aperature(void); + +/* regs to save */ +static int sr_accel[13] = +{ioCRTC_GEN_CNTL, + ioCRTC_H_SYNC_STRT_WID, + ioCRTC_H_TOTAL_DISP, + ioCRTC_V_SYNC_STRT_WID, + ioCRTC_V_TOTAL_DISP, + ioCRTC_OFF_PITCH, + ioCLOCK_SEL_CNTL, + ioOVR_CLR, + ioOVR_WID_LEFT_RIGHT, + ioOVR_WID_TOP_BOTTOM, + ioMEM_CNTL, + ioMEM_VGA_RP_SEL, + ioMEM_VGA_WP_SEL}; + +/* Driverspecs function table (exported) */ +DriverSpecs __svgalib_mach64_driverspecs = +{ + mach64_saveregs, + mach64_setregs, + (void (*)(void)) nothing, /* unlock */ + (void (*)(void)) nothing, /* lock */ + mach64_test, + mach64_init, + mach64_setpage, /* __svgalib_setpage */ + (void (*)(int)) nothing, /* __svgalib_setrdpage */ + (void (*)(int)) nothing, /* __svgalib_setwrpage */ + mach64_setmode, + mach64_modeavailable, + mach64_setdisplaystart, + mach64_setlogicalwidth, + mach64_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + +/* empty function */ +static void nothing(void) +{ +} + +/***************************************************************************/ + +/* Initialize chipset */ +static int mach64_init(int force, int par1, int par2) +{ + UB *atibios; + + if (__svgalib_driver_report) + fprintf(stdout, "Using ATI Mach64 driver.\n"); + + __svgalib_driverspecs = &__svgalib_mach64_driverspecs; + + /* Make sure we are operating at IO priveleges are level 3 */ + if (iopl(3) < 0) { + fprintf(stdout, "iopl(3) failed in Mach64\n"); + exit(-1); + } + /* download configuration data */ + atibios = mach64_map_vbios(RomLocation); + mach64_get_alot_of_info(atibios); +/* + This seems to be a cause of segfaults. + mach64_unmap_vbios(RomLocation,atibios); + */ + mach64_report(); + +#ifdef BAILOUT + fprintf(stdout, "\n*** WARNING ALPHA DRIVER ***\n" \ + "*** If the above diagnostics look ok then press 'Y' to" \ + "continue.\n\n"); + if (getchar() != 'Y') { + fprintf(stdout, "\n*** Bailing out! ***\n"); + exit(-1); + } +#endif + return 1; +} + +/* test for presence of mach64 */ +static int mach64_test(void) +{ + UB *atibios; + UB ati_sig1[] = "761295520"; + UB ati_sig2[] = "GXCX"; + UB ati_sig3[] = "MACH64"; + int ati_found, i; + UL sv; + US romtabptr, *romoff; + + /* Make sure we are operating at IO privlege level 3 */ + if (iopl(3) < 0) { + fprintf(stdout, "iopl(3) failed in Mach64\n"); + exit(-1); + } + /* !!should loop through the relocatable bios areas - instead */ + /* !!should read the address cause it may be relocateable */ + RomLocation = mach64_rom_base(); + + /* map the vga bios */ + atibios = mach64_map_vbios(RomLocation); + + /* scan for the signature */ + ati_found = 0; + for (i = 0; i < 128; i++) { + if (strncmp(ati_sig1, atibios + i, sizeof(ati_sig1) - 1) == 0) { + ati_found = 1; + break; + } + } + + /* scan for either GXCX or MACH64 */ + for (i = 0; i < 1024; i++) { + if (strncmp(ati_sig2, atibios + i, sizeof(ati_sig2) - 1) == 0) { + ati_found++; + break; + } + if (strncmp(ati_sig3, atibios + i, sizeof(ati_sig3) - 1) == 0) { + ati_found++; + break; + } + } + + + /* grab the address for io access - fixed and relocatable from bios + I can't tell if its VLB or PCI yet. If the ioBaseAddress is not + 0x2EC, 0x1CC, or 0x1C8 then its obviosly relocatable (we hope). + If its relocatable then we pray its PCI. */ + + romoff = (US *) atibios; + romtabptr = romoff[0x48 >> 1]; + ioBaseAddress = romoff[(romtabptr >> 1) + 2]; + PciIOLocation = romoff[(romtabptr >> 1) + 13]; + switch (ioBaseAddress) { + case 0x2ec: + break; + case 0x1cc: + case 0x1c8: + default: + fprintf(stdout, "M64: Can't handle io address yet.\n"); + exit(-1); + } +#ifdef DEBUG + fprintf(stdout, "M64: IO Base Address: %x\n", ioBaseAddress); +#endif + /* unmap the bios */ +/* This seems to be the cause of segfaults + mach64_unmap_vbios(RomLocation,atibios); + */ + /* if its not even ati return a failure */ + if (ati_found < 2) + return 0; + + /* do the scratch register io confirmation test */ + /* assume not mach64 */ + ati_found = 0; + + /* save scratch value */ + sv = inl(ioSCRATCH_REG0); + + /* test odd bits for readability */ + outl(ioSCRATCH_REG0, 0x55555555); + if (inl(ioSCRATCH_REG0) == 0x55555555) { + /* test even bits for readability */ + outl(ioSCRATCH_REG0, 0xaaaaaaaa); + if (inl(ioSCRATCH_REG0) == 0xaaaaaaaa) { + ati_found = 1; + } + } + /* restore */ + outl(ioSCRATCH_REG0, sv); + + return (ati_found) ? mach64_init(0, 0, 0) : ati_found; +} + +/**************************************************************************/ +/* locate rom locatation */ +static UB *mach64_rom_base(void) +{ + US a; + UB *b; + + a = inw(ioSCRATCH_REG1); + a &= 0x7f; + a += 0xc000; + b = (UB *) (a * 0x10); + + return (b); +} + +/* map the vga bios - pretty much lifted from ati.c */ +static UB *mach64_map_vbios(UB * map_me) +{ + UB *vga_bios; + + /* allocate 32k for bios map */ + if ((vga_bios = valloc(M64_BIOS_SIZE)) == NULL) { + fprintf(stdout, "SVGALIB valloc failure\n"); + exit(-1); + } + vga_bios = (UB *) mmap((caddr_t) vga_bios, + M64_BIOS_SIZE, + PROT_READ, + MAP_SHARED | MAP_FIXED, + __svgalib_mem_fd, + (off_t) map_me); + + if ((long) vga_bios < 0) { + fprintf(stdout, "SVGALIB mmap failure\n"); + exit(-1); + } + return (UB *) vga_bios; +} + +/* + static void mach64_unmap_vbios(UB *unmap_me,UB *free_me) + { + if (munmap((caddr_t)unmap_me,M64_BIOS_SIZE)) { + fprintf(stdout,"SVGALIB munmap failure\n"); + exit(-1); + } + free((void *)free_me); + } + */ + +/****************************************************************************/ + +/* collect information from rom and registers */ +static void mach64_get_alot_of_info(UB * mapped_area) +{ + UB *bbios; + US *sbios; + int i, j; + US RomTableOff, FreqTablePtr, CdepthTablePtr; + UL RegL; + UB RegB; + UB mask; + + /* setup bios area mappings and initial offsets */ + sbios = (US *) mapped_area; + bbios = (UB *) mapped_area; + + RomTableOff = sbios[0x48 >> 1]; + FreqTablePtr = sbios[(RomTableOff >> 1) + 8]; + + /* grab the CONFIG_CHIP_ID information */ + RegL = inl(ioCONFIG_CHIP_ID); + StartupInfo.Chip_Type = (US) (RegL & 0xffff); + StartupInfo.Chip_Class = (UB) ((RegL >> 16) && 0xff); + StartupInfo.Chip_Rev = (UB) ((RegL >> 24) && 0xff); + + switch (StartupInfo.Chip_Type) { + case 0xd7: + if (StartupInfo.Chip_Rev <= 0x03) + StartupInfo.Chip_ID_Index = StartupInfo.Chip_Rev; + else + StartupInfo.Chip_ID_Index = 0x04; + break; + case 0x57: + if (StartupInfo.Chip_Rev == 0x01) + StartupInfo.Chip_ID_Index = 0x05; + else + StartupInfo.Chip_ID_Index = 0x06; + break; + case 0x4354: + StartupInfo.Chip_ID_Index = 0x07; + break; + case 0x4554: + StartupInfo.Chip_ID_Index = 0x08; + break; + default: + StartupInfo.Chip_ID_Index = 0x09; + } + +#ifdef REPORT + if (StartupInfo.Chip_ID_Index < 0x07) + fprintf(stdout, "M64: ATI Mach64 88800 %s detected.\n", + M64_Chip_Name[StartupInfo.Chip_ID_Index]); + else + fprintf(stdout, "M64: ATI Mach64 88800 %s Rev. %x detected.\n", + M64_Chip_Name[StartupInfo.Chip_ID_Index], + StartupInfo.Chip_Rev); +#endif + + /* read the CONFIG_STAT0 and CONFIG_STAT1 */ + RegL = inl(ioCONFIG_STAT0); + StartupInfo.Cfg_Bus_type = (UB) (RegL & 0x07); + StartupInfo.Cfg_Ram_type = (UB) ((RegL >> 3) & 0x7); + RegL = inl(ioCONFIG_STAT1); + +#ifdef REPORT + fprintf(stdout, "M64: Bus Type: %s\n", + M64_Bus_Name[StartupInfo.Cfg_Bus_type]); + fprintf(stdout, "M64: Memory Type: %s\n", + M64_Ram_Name[StartupInfo.Cfg_Ram_type]); +#endif + + /* read memory configurations stuff */ + RegL = inl(ioMEM_CNTL); + StartupInfo.Mem_Size = (UB) (RegL & 0x07); + +#ifdef REPORT + fprintf(stdout, "M64: Memory Installed: %d Kilobytes\n", + M64_Mem_Size[StartupInfo.Mem_Size]); +#endif + + /* read the dac type and sub type */ + RegB = inb(ioDAC_CNTL + 2); + StartupInfo.Dac_Type = RegB & 0x07; + RegB = inb(ioSCRATCH_REG1 + 1); + StartupInfo.Dac_Subtype = (RegB & 0xf0) | StartupInfo.Dac_Type; + +#ifdef REPORT + fprintf(stdout, "M64: Dac Type: %d %s Sub Type: %d\n", + StartupInfo.Dac_Type, + M64_Dac_Name[StartupInfo.Dac_Type], + StartupInfo.Dac_Subtype); +#endif + + /* grab a pile of clock info */ + ClockInfo.ClockType = bbios[FreqTablePtr + 0]; + ClockInfo.MinFreq = sbios[(FreqTablePtr >> 1) + 1]; + ClockInfo.MaxFreq = sbios[(FreqTablePtr >> 1) + 2]; + ClockInfo.RefFreq = sbios[(FreqTablePtr >> 1) + 4]; + ClockInfo.RefDivdr = sbios[(FreqTablePtr >> 1) + 5]; + ClockInfo.N_adj = sbios[(FreqTablePtr >> 1) + 6]; + ClockInfo.Dram_Mem_Clk = sbios[(FreqTablePtr >> 1) + 8]; + ClockInfo.Vram_Mem_Clk = sbios[(FreqTablePtr >> 1) + 9]; + ClockInfo.Coproc_Mem_Clk = sbios[(FreqTablePtr >> 1) + 12]; + ClockInfo.CX_Clk = bbios[FreqTablePtr + 6]; + ClockInfo.VGA_Clk = bbios[FreqTablePtr + 7]; + ClockInfo.Mem_Clk_Entry = bbios[FreqTablePtr + 22]; + ClockInfo.SClk_Entry = bbios[FreqTablePtr + 23]; + ClockInfo.CX_DMcycle = bbios[RomTableOff + 0]; + ClockInfo.VGA_DMcycle = bbios[RomTableOff + 0]; + ClockInfo.CX_VMcycle = bbios[RomTableOff + 0]; + ClockInfo.VGA_VMcycle = bbios[RomTableOff + 0]; + CdepthTablePtr = sbios[(FreqTablePtr >> 1) - 3]; + FreqTablePtr = sbios[(FreqTablePtr >> 1) - 1]; + FreqTablePtr >>= 1; + + /* Read the default clocks */ + for (i = 0; i <= M64_CLOCK_MAX; i++) + ClockInfo.ClkFreqTable[i] = sbios[FreqTablePtr + i]; + + /* grab the color depth tables */ + cTabSize = bbios[CdepthTablePtr - 1]; + +#ifdef REPORT + fprintf(stdout, "M64: ClockType: %d %s\n", ClockInfo.ClockType, + M64_Clock_Name[ClockInfo.ClockType]); + fprintf(stdout, "M64: MinFreq: %d\n", ClockInfo.MinFreq); + fprintf(stdout, "M64: MaxFreq: %d\n", ClockInfo.MaxFreq); + fprintf(stdout, "M64: RefFreq: %d\n", ClockInfo.RefFreq); + fprintf(stdout, "M64: RefDivdr: %d\n", ClockInfo.RefDivdr); + fprintf(stdout, "M64: N_adj: %d\n", ClockInfo.N_adj); + fprintf(stdout, "M64: DramMemClk: %d\n", ClockInfo.Dram_Mem_Clk); + fprintf(stdout, "M64: VramMemClk: %d\n", ClockInfo.Vram_Mem_Clk); + fprintf(stdout, "M64: CoprocMemClk: %d\n", ClockInfo.Coproc_Mem_Clk); + fprintf(stdout, "M64: CX_Clk: %d\n", ClockInfo.CX_Clk); + fprintf(stdout, "M64: VGA_Clk: %d\n", ClockInfo.VGA_Clk); + fprintf(stdout, "M64: Mem_Clk_Entry: %d\n", ClockInfo.Mem_Clk_Entry); + fprintf(stdout, "M64: SClk_Entry: %d\n", ClockInfo.SClk_Entry); + fprintf(stdout, "M64: V/D_MCycle: %d\n", ClockInfo.CX_DMcycle); + + for (i = 0; i <= M64_CLOCK_MAX; i++) { + if (i % 8 == 0) + fprintf(stdout, "\nM64: Clocks: "); + fprintf(stdout, "%d.%d ", ClockInfo.ClkFreqTable[i] / 100, + ClockInfo.ClkFreqTable[i] % 100); + } + fprintf(stdout, "\n"); +#endif + + /* Get color depth tables that are valid for current dac */ + mask = 1 << StartupInfo.Dac_Type; + + for (j = i = 0; bbios[CdepthTablePtr + i] != 0; i += cTabSize) { + if (bbios[CdepthTablePtr + i + 1] & mask) { + MaxCDT1[j].h_disp = bbios[CdepthTablePtr + i]; + MaxCDT1[j].dacmask = bbios[CdepthTablePtr + i + 1]; + MaxCDT1[j].ram_req = bbios[CdepthTablePtr + i + 2]; + MaxCDT1[j].max_dot_clk = bbios[CdepthTablePtr + i + 3]; + MaxCDT1[j].color_depth = bbios[CdepthTablePtr + i + 4]; + ++j; + } + } + MaxCDT1[j].h_disp = 0; + + /* Get second color depth table if exists that are valid subtype */ + CdepthTablePtr += i + 2; + cTabSize = bbios[CdepthTablePtr - 1]; + for (j = i = 0; bbios[CdepthTablePtr + i] != 0; i += cTabSize) { + if (bbios[CdepthTablePtr + i + 1] == StartupInfo.Dac_Subtype) { + MaxCDT2[j].h_disp = bbios[CdepthTablePtr + i]; + MaxCDT2[j].dacmask = bbios[CdepthTablePtr + i + 1]; + MaxCDT2[j].ram_req = bbios[CdepthTablePtr + i + 2]; + MaxCDT2[j].max_dot_clk = bbios[CdepthTablePtr + i + 3]; + MaxCDT2[j].color_depth = bbios[CdepthTablePtr + i + 4]; + ++j; + fprintf(stdout, "%d\n", j); + } + } + MaxCDT2[j].h_disp = 0; + + /* Filter out the useless entries based on bpp and memory */ + mask = StartupInfo.Cfg_Ram_type & VRAM_MASK; + mask = (mask) ? 4 : 0; + + + /* table 1 */ + for (i = 0, j = 0; MaxCDT1[i].h_disp != 0; i++) { + /* pick out 8 bpp modes for now */ + switch (MaxCDT1[i].color_depth) { + case BPP_8: + if ((MaxCDT1[i].ram_req >> mask) > + StartupInfo.Mem_Size) + break; + + FreqCDT1[j].h_disp = MaxCDT1[i].h_disp; + FreqCDT1[j].dacmask = MaxCDT1[i].dacmask; + FreqCDT1[j].ram_req = MaxCDT1[i].ram_req; + FreqCDT1[j].max_dot_clk = MaxCDT1[i].max_dot_clk; + FreqCDT1[j].color_depth = MaxCDT1[i].color_depth; + j++; + break; + case BPP_32: + case BPP_16: + case BPP_15: + case BPP_4: + default: + break; + } + FreqCDT1[j].h_disp = 0; + } + /* table 2 */ + for (i = 0, j = 0; MaxCDT2[i].h_disp != 0; i++) { + /* pick out 8 bpp modes for now */ + switch (MaxCDT2[i].color_depth) { + case BPP_8: + if ((MaxCDT2[i].ram_req >> mask) > + StartupInfo.Mem_Size) + break; + + FreqCDT2[j].h_disp = MaxCDT2[i].h_disp; + FreqCDT2[j].dacmask = MaxCDT2[i].dacmask; + FreqCDT2[j].ram_req = MaxCDT2[i].ram_req; + FreqCDT2[j].max_dot_clk = MaxCDT2[i].max_dot_clk; + FreqCDT2[j].color_depth = MaxCDT2[i].color_depth; + j++; + break; + case BPP_32: + case BPP_16: + case BPP_15: + case BPP_4: + default: + break; + } + FreqCDT2[j].h_disp = 0; + } + +#ifdef REPORT_CLKTAB + fprintf(stdout, "Color Depth Table 1\n"); + for (i = 0; MaxCDT1[i].h_disp != 0; i++) { + fprintf(stdout, "%d %d %d %d %d\n", MaxCDT1[i].h_disp, + MaxCDT1[i].dacmask, MaxCDT1[i].ram_req, + MaxCDT1[i].max_dot_clk, MaxCDT1[i].color_depth); + } + fprintf(stdout, "Color Depth Table 2 - if present\n"); + for (i = 0; MaxCDT2[i].h_disp != 0; i++) { + fprintf(stdout, "%d %d %d %d %d\n", MaxCDT2[i].h_disp, + MaxCDT2[i].dacmask, MaxCDT2[i].ram_req, + MaxCDT2[i].max_dot_clk, MaxCDT2[i].color_depth); + } +#endif +#ifdef REPORT + fprintf(stdout, "Valid Color Depth Table 1\n"); + for (i = 0; FreqCDT1[i].h_disp != 0; i++) { +#ifdef REPORT_CLKTAB + fprintf(stdout, "%d %d %d %d %d\n", FreqCDT1[i].h_disp, + FreqCDT1[i].dacmask, FreqCDT1[i].ram_req, + FreqCDT1[i].max_dot_clk, FreqCDT1[i].color_depth); +#endif + fprintf(stdout, "Width: %d, MaxDotClk: %dMHz, Depth: %d bpp\n", + FreqCDT1[i].h_disp * 8, FreqCDT1[i].max_dot_clk, + M64_BPP[FreqCDT1[i].color_depth]); + } + fprintf(stdout, "Valid Color Depth Table 2 - if present\n"); + for (i = 0; FreqCDT2[i].h_disp != 0; i++) { +#ifdef REPORT_CLKTAB + fprintf(stdout, "%d %d %d %d %d\n", FreqCDT2[i].h_disp, + FreqCDT2[i].dacmask, FreqCDT2[i].ram_req, + FreqCDT2[i].max_dot_clk, FreqCDT2[i].color_depth); +#endif + fprintf(stdout, "Width: %d, MaxDotClk: %dMHz, Depth: %d bpp\n", + FreqCDT2[i].h_disp * 8, FreqCDT2[i].max_dot_clk, + M64_BPP[FreqCDT2[i].color_depth]); + } +#endif +} + +/*************************************************************************/ + +/* generates a quick register dump */ +static void mach64_report(void) +{ + UL reg; + + reg = inl(ioBUS_CNTL); + printf("BUS_CNTL: %lx ", reg); + DUMP(reg); + + reg = inl(ioCONFIG_CHIP_ID); + printf("CONFIG_CHIP_ID: %lx ", reg); + DUMP(reg); + + + reg = inl(ioCONFIG_CNTL); + printf("CONFIG_CNTL: %lx ", reg); + DUMP(reg); + + reg = inl(ioCONFIG_STAT0); + printf("CONFIG_STAT0: %lx ", reg); + DUMP(reg); + + reg = inl(ioCONFIG_STAT1); + printf("CONFIG_STAT1: %lx ", reg); + DUMP(reg); + + reg = inl(ioGEN_TEST_CNTL); + printf("GEN_TEST_CNTL: %lx ", reg); + DUMP(reg); + + reg = inl(ioMEM_CNTL); + printf("MEM_CNTL: %lx ", reg); + DUMP(reg); + + reg = inl(ioMEM_VGA_RP_SEL); + printf("MEM_VGA_RP_SEL: %lx ", reg); + DUMP(reg); + + reg = inl(ioMEM_VGA_WP_SEL); + printf("MEM_VGA_WP_SEL: %lx ", reg); + DUMP(reg); + + reg = inl(ioDAC_CNTL); + printf("DAC_CNTL: %lx ", reg); + DUMP(reg); + + reg = inl(ioCLOCK_SEL_CNTL); + printf("CLOCK_CNTL: %lx ", reg); + DUMP(reg); + + reg = inl(ioCRTC_GEN_CNTL); + printf("CRTC_GEN: %lx ", reg); + DUMP(reg); + + reg = inl(ioSCRATCH_REG0); + printf("SCRATCH 0: %lx ", reg); + DUMP(reg); + + reg = inl(ioSCRATCH_REG1); + printf("SCRATCH 1: %lx ", reg); + DUMP(reg); + + reg = inl(ioCRTC_H_SYNC_STRT_WID); + printf("H_S_S_W: %lx ", reg); + DUMP(reg); +} + +/*************************************************************************/ + +/* program the ati68860 ramdac -- standard on old mach64's */ +static int mach64_dac_ati68860(US c_depth, US accelmode) +{ + US gmode, dsetup, temp, mask; + + /* filter pixel depth */ + if (c_depth == BPP_8) { + gmode = 0x83; + dsetup = 0x61; + } else { + printf("unsupported bpp\n"); + exit(1); + } + + /* if we are in vga mode */ + if (!accelmode) { + gmode = 0x80; + dsetup = 0x60; + } + temp = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3); + + outb(ioDAC_REGS + 2, 0x1d); + outb(ioDAC_REGS + 3, gmode); + outb(ioDAC_REGS, 0x02); + + temp = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3); + + if (M64_Mem_Size[StartupInfo.Mem_Size] < 1024) + mask = 0x04; + else if (M64_Mem_Size[StartupInfo.Mem_Size] == 1024) + mask = 0x08; + else + mask = 0x0c; + + temp = inb(ioDAC_REGS); + outb(ioDAC_REGS, (dsetup | mask) | (temp & 0x80)); + temp = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3))); + + /* pixel delay from ati */ + temp = inb(ioCRTC_H_SYNC_STRT_WID + 1); + temp = 0x1c; /*was temp+= */ + outb(ioCRTC_H_SYNC_STRT_WID + 1, temp & 0x07); + temp >>= 3; + temp = temp + inb(ioCRTC_H_SYNC_STRT_WID); + outb(ioCRTC_H_SYNC_STRT_WID, temp); + + return 0; +} + +/* general ramdac program */ +static void mach64_dac_program(US c_depth, US accelmode, US dotclock) +{ + US temp, mux; + + /* check to see if we are using an accelerator mode and turn on + the extended mode display and crtc */ + if (accelmode) { + temp = inb(CRTC_GEN_CNTL) & ~CRTC_PIX_BY_2_EN; + outb(ioCRTC_GEN_CNTL, temp); + outb(ioCRTC_GEN_CNTL + 3, CRTC_EXT_DISP_EN | CRTC_EXT_EN); + } else { + outb(ioCRTC_GEN_CNTL + 3, 0); + } + + temp = inb(ioCRTC_GEN_CNTL + 3); + outb(ioCRTC_GEN_CNTL + 3, temp | CRTC_EXT_DISP_EN); + + /* switch on the dac type */ + mux = mach64_dac_ati68860(c_depth, accelmode); + + inb(ioDAC_REGS); + outb(ioCRTC_GEN_CNTL + 3, temp); + + temp = inb(ioCRTC_GEN_CNTL) & ~CRTC_PIX_BY_2_EN; + if (mux) + temp = temp | CRTC_PIX_BY_2_EN; + outb(ioCRTC_GEN_CNTL, temp); +} + +/* setup the crtc registers */ +static void mach64_crtc_programming(US mode, US c_depth, US refrate) +{ + CRTC_Table *pcrtc; + UB temp3, temp0; + + /* fix to mode 640x480 */ + pcrtc = &CRTC_tinfo[0]; + + /* determine the fifo value and dot clock */ + pcrtc->fifo_vl = 0x02; + pcrtc->pdot_clock = pcrtc->dot_clock; + + temp3 = inb(ioCRTC_GEN_CNTL + 3); + temp0 = inb(ioCRTC_GEN_CNTL + 0); + outb(ioCRTC_GEN_CNTL + 3, temp3 & ~CRTC_EXT_EN); + + /* here would would program the clock... but we won't */ + + /* horizontal */ + outb(CRTC_H_TOTAL, pcrtc->h_total); + outb(CRTC_H_DISP, pcrtc->h_disp); + outb(CRTC_H_SYNC_STRT, pcrtc->h_sync_strt); + outb(CRTC_H_SYNC_WID, pcrtc->h_sync_wid); + + printf("CRTC_H_TD: %x\n", inl(ioCRTC_H_TOTAL_DISP)); + printf("CRTC_H_SN: %x\n", inl(ioCRTC_H_SYNC_STRT_WID)); + + /* vertical */ + outw(CRTC_V_TOTAL, pcrtc->v_total); + outw(CRTC_V_DISP, pcrtc->v_disp); + outw(CRTC_V_SYNC_STRT, pcrtc->v_sync_strt); + outb(CRTC_V_SYNC_WID, pcrtc->v_sync_wid); + + printf("CRTC_V_TD: %lx\n", (UL) inl(ioCRTC_V_TOTAL_DISP)); + printf("CRTC_V_SN: %lx\n", (UL) inl(ioCRTC_V_SYNC_STRT_WID)); + + /* clock stuff */ + /* 50/2 */ + pcrtc->clock_cntl = 0x00 | 0x10; + /* CX clock */ + pcrtc->clock_cntl = 0x08; + /*outb(CLOCK_CNTL,pcrtc->clock_cntl|CLOCK_STROBE); */ + outb(CLOCK_CNTL, pcrtc->clock_cntl); + printf("CLK: %lx\n", (UL) inl(ioCLOCK_SEL_CNTL)); + + /* overscan */ + outb(OVR_WID_LEFT, 0); + outb(OVR_WID_RIGHT, 0); + outb(OVR_WID_BOTTOM, 0); + outb(OVR_WID_TOP, 0); + outb(OVR_CLR_8, 0); + outb(OVR_CLR_B, 0); + outb(OVR_CLR_G, 0); + outb(OVR_CLR_R, 0); + + /* pitch */ + outl(ioCRTC_OFF_PITCH, (UL) 80 << 22); + mreg[mSRC_OFF_PITCH / 4 + 0xC00 / 4] = (UL) 80 << 22; + mreg[mDST_OFF_PITCH / 4 + 0xC00 / 4] = (UL) 80 << 22; + + /* turn on display */ + outb(ioCRTC_GEN_CNTL + 0, temp0 & + ~(CRTC_PIX_BY_2_EN | CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN)); + outb(ioCRTC_GEN_CNTL + 1, c_depth); + outb(ioCRTC_GEN_CNTL + 2, pcrtc->fifo_vl); + outb(ioCRTC_GEN_CNTL + 3, temp3 | CRTC_EXT_DISP_EN | CRTC_EXT_EN); + + mreg[mDP_PIX_WIDTH / 4 + 0xC00 / 4] = (UL) 0x01020202; + mreg[mDP_CHAIN_MASK / 4 + 0xC00 / 4] = (UL) 0x8080; + mreg[mCONTEXT_MASK / 4 + 0xC00 / 4] = (UL) 0xffffffff; + /* woudn't a macro be nice */ + mreg[mDST_CNTL / 4 + 0xC00 / 4] = (UL) 0x00; + + printf("CRTC_GEN_IN_CRTC: %x\n", inl(ioCRTC_GEN_CNTL)); + /* configure ramdac */ + mach64_dac_program(c_depth, 1, pcrtc->pdot_clock); + + mach64_report(); +} + +/*************************************************************************/ +static int mach64_saveregs(UB * regs) +{ + int i, retval; + UL temp; + UB tb; + + /* store all the crtc, clock, memory registers */ + retval = EXT; + for (i = 0; i < 13; i++) { + temp = inl(sr_accel[i]); + printf("Saved: %d %lx\n", i, temp); + regs[retval++] = (UB) temp & 0x000000ff; + temp = temp >> 8; + regs[retval++] = (UB) temp & 0x000000ff; + temp = temp >> 8; + regs[retval++] = (UB) temp & 0x000000ff; + temp = temp >> 8; + regs[retval++] = (UB) temp & 0x000000ff; + + } + + /* store the dac --68860 */ + tb = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, (tb & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3); + regs[retval++] = (UB) inb(ioDAC_REGS + 2); + regs[retval++] = (UB) inb(ioDAC_REGS + 3); + regs[retval++] = (UB) inb(ioDAC_REGS); + tb = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, tb | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3); + regs[retval++] = (UB) inb(ioDAC_REGS); + tb = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, (tb & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3))); + + return retval - EXT + 1; +} + +static void mach64_setregs(const UB * regs, int mode) +{ + int i, retval; + UL temp; + UB tb; + + outb(0x3ce, 6); + outb(0x3cf, 0); + outb(ioCONFIG_CNTL, (inb(ioCONFIG_CNTL) & 0xfb)); + outb(ioCRTC_GEN_CNTL + 3, 0); + + return; + /* restore all the crtc, clock, memory registers */ + retval = EXT; + for (i = 0; i < 13; i++) { + temp = (UL) 0; + temp = temp | (regs[retval++] << 24); + temp = temp | (regs[retval++] << 16); + temp = temp | (regs[retval++] << 8); + temp = temp | regs[retval++]; + outl(sr_accel[i], temp); + + } + + /* store the dac --68860 */ + tb = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, (tb & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3); + outb(ioDAC_REGS + 2, regs[retval++]); + outb(ioDAC_REGS + 3, regs[retval++]); + outb(ioDAC_REGS, regs[retval++]); + tb = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, tb | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3); + outb(ioDAC_REGS, regs[retval++]); + tb = inb(ioDAC_CNTL); + outb(ioDAC_CNTL, (tb & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3))); + +} + +static void mach64_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + /*__svgalib_vga_driverspecs.getmodeinfo(mode, modeinfo); */ + modeinfo->startaddressrange = 0xfffff; +/* modeinfo->startaddressrange=0xfffffffc&(2048*1024-1); + */ + + modeinfo->maxpixels = 640 * 480; +/* modeinfo->bytesperpixel=infotable[mode].bytesperpixel; + modeinfo->linewidth_unit=8; + modeinfo->linewidth=infotable[mode].xbytes; + modeinfo->maxlogicalwidth=0xff*8*modeinfo->bytesperpixel; + modeinfo->startaddressrange=0xffc00000; + */ +} + +static int mach64_modeavailable(int mode) +{ +/* + if (mode>__svgalib_max_modes) + */ + if (mode > __GLASTMODE) + return 0; + if (mode < G640x480x256 || mode == G720x348x2) + return __svgalib_vga_driverspecs.modeavailable(mode); + else if (mode != G640x480x256) + return 0; + + return SVGADRV; +} + +static int mach64_setmode(int mode, int prv_mode) +{ + const UB *regs = NULL; + UB di; + + mach64_setregs(regs, mode); + + if (mode < G640x480x256 || mode == G720x348x2) + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + + if (mode == G640x480x256) { + + /* I don't think this is necessary since I dont even + use the vga */ + /* set packed pixel register */ + outb(ATIPORT, ATISEL(0x30)); + di = inb(ATIPORT); + printf("pre ext: %d\n", di); + outb(ATIPORT, ATISEL(0x30)); + outb(ATIPORT, di | 0x20); + + /* all maps */ + outb(0x3c4, 2); + outb(0x3c5, 0x0f); + + /* linear */ + outb(ATIPORT, ATISEL(0x36)); + di = inb(ATIPORT); + outb(ATIPORT, ATISEL(0x36)); + outb(ATIPORT, di | 0x04); + + /* turn off memory boundary */ + outl(ioMEM_CNTL, inl(ioMEM_CNTL) & 0xfff8ffff); + + /* disable interrups */ + outl(ioCRTC_INT_CNTL, 0); + + /* 8 bit dac */ + outb(ioDAC_CNTL + 1, inb(ioDAC_CNTL + 1) | 0x01); + outb(ioCRTC_GEN_CNTL + 3, 3); + /* setup small aperature */ + mach64_small_aperature(); + + + mach64_setpage(0); +#ifdef DEBUG + printf("About to call crtc programming...\n"); +#endif + mach64_crtc_programming(0, BPP_8, 60); + di = 0; +/* for (di=0;di<32;di++){ + mach64_setpage(di);usleep(10000); + for (i=0;i<64*1024;i++){ + graph_mem[i]=i%16;} + } + *//* for (j=0;j<1024*2048/8;j+=640){ + usleep(1); + outw(ioCRTC_OFF_PITCH,j/8); + } + *//* outw(ioCRTC_OFF_PITCH,4000); + outb(ioCRTC_OFF_PITCH+2,inb(ioCRTC_OFF_PITCH+2)|0x10); + outw(ioCRTC_OFF_PITCH,80*480); + */ outw(ioCRTC_OFF_PITCH, 0); + mach64_setpage(0); +/* for(j=0;j<64000;j++){ + graph_mem[j]=0x0c; + } + sleep(2); + */ mach64_setpage(0); + mach64_report(); + return 0; + } + return 1; + + +} + +static void mach64_setdisplaystart(int address) +{ + /*__svgalib_vga_driverspecs.setdisplaystart(address); */ +} + +static void mach64_setlogicalwidth(int width) +{ + /*__svgalib_vga_driverspecs.setlogicalwidth(width); */ +} + +static void mach64_setpage(int page) +{ + printf("PAGE: %d\n", page); + outb(ioMEM_VGA_WP_SEL, 255 - (page * 2)); + outb(ioMEM_VGA_WP_SEL + 2, 255 - ((page * 2) + 1)); + outb(ioMEM_VGA_RP_SEL, 255 - (page * 2)); + outb(ioMEM_VGA_RP_SEL + 2, 255 - ((page * 2) + 1)); +} + +static void mach64_small_aperature(void) +{ + int i; + + /* 256 color mode */ + outb(0x3ce, 5); + printf("pre 5:%d\n", inb(0x3cf)); + outb(0x3ce, 5); + outb(0x3cf, 0x60); + outb(0x3ce, 5); + printf("afe 5:%d\n", inb(0x3cf)); + /* APA mode with 128K at A0000 */ + outb(0x3ce, 6); + printf("pre 6:%d\n", inb(0x3cf)); + outb(0x3ce, 6); + outb(0x3cf, 1); + outb(0x3ce, 6); + printf("afe 6:%d\n", inb(0x3cf)); + + /* setup small aperature */ + outb(ioCONFIG_CNTL, (inb(ioCONFIG_CNTL) | 0x04) & 0xff); + /* map ram */ + mreg = (UL *) mmap((caddr_t) 0, + 4 * 1024, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, + __svgalib_mem_fd, + (off_t) ((UB *) 0xbf000)); + if (mreg < 0) { + printf("Mapping failed\n"); + exit(1); + } + printf("IOPORT: %x\n", inl(ioCONFIG_STAT0)); + for (i = 0; i <= 0xce; i++) { + printf("MEMA: %x %lx\n", i, mreg[i + 0xc00 / 4]); + } +} diff --git a/obsolete/mach/mach64.h b/obsolete/mach/mach64.h new file mode 100644 index 0000000..9ffa338 --- /dev/null +++ b/obsolete/mach/mach64.h @@ -0,0 +1,481 @@ +/* ATI Mach64 Driver for SVGALIB - (Driver (C) 1996 Asad F. Hanif) + Ye olde defines +*/ + + +/* Mach64 io and memory mapped registers */ +/* ripped from ati sdk */ +/* NON-GUI IO MAPPED Registers */ + +#define ioCRTC_H_TOTAL_DISP 0x02EC +#define ioCRTC_H_SYNC_STRT_WID 0x06EC +#define ioCRTC_V_TOTAL_DISP 0x0AEC +#define ioCRTC_V_SYNC_STRT_WID 0x0EEC +#define ioCRTC_VLINE_CRNT_VLINE 0x12EC +#define ioCRTC_OFF_PITCH 0x16EC +#define ioCRTC_INT_CNTL 0x1AEC +#define ioCRTC_GEN_CNTL 0x1EEC + +#define ioOVR_CLR 0x22EC +#define ioOVR_WID_LEFT_RIGHT 0x26EC +#define ioOVR_WID_TOP_BOTTOM 0x2AEC + +#define ioCUR_CLR0 0x2EEC +#define ioCUR_CLR1 0x32EC +#define ioCUR_OFFSET 0x36EC +#define ioCUR_HORZ_VERT_POSN 0x3AEC +#define ioCUR_HORZ_VERT_OFF 0x3EEC + +#define ioSCRATCH_REG0 0x42EC +#define ioSCRATCH_REG1 0x46EC + +#define ioCLOCK_SEL_CNTL 0x4AEC + +#define ioBUS_CNTL 0x4EEC + +#define ioMEM_CNTL 0x52EC +#define ioMEM_VGA_WP_SEL 0x56EC +#define ioMEM_VGA_RP_SEL 0x5AEC + +#define ioDAC_REGS 0x5EEC +#define ioDAC_CNTL 0x62EC + +#define ioGEN_TEST_CNTL 0x66EC + +#define ioCONFIG_CNTL 0x6AEC +#define ioCONFIG_CHIP_ID 0x6EEC +#define ioCONFIG_STAT0 0x72EC +#define ioCONFIG_STAT1 0x76EC + + +/* NON-GUI MEMORY MAPPED Registers - expressed in BYTE offsets */ + +#define mCRTC_H_TOTAL_DISP 0x0000 +#define mCRTC_H_SYNC_STRT_WID 0x0004 +#define mCRTC_V_TOTAL_DISP 0x0008 +#define mCRTC_V_SYNC_STRT_WID 0x000C +#define mCRTC_VLINE_CRNT_VLINE 0x0010 +#define mCRTC_OFF_PITCH 0x0014 +#define mCRTC_INT_CNTL 0x0018 +#define mCRTC_GEN_CNTL 0x001C + +#define mOVR_CLR 0x0040 +#define mOVR_WID_LEFT_RIGHT 0x0044 +#define mOVR_WID_TOP_BOTTOM 0x0048 + +#define mCUR_CLR0 0x0060 +#define mCUR_CLR1 0x0064 +#define mCUR_OFFSET 0x0068 +#define mCUR_HORZ_VERT_POSN 0x006C +#define mCUR_HORZ_VERT_OFF 0x0070 + +#define mSCRATCH_REG0 0x0080 +#define mSCRATCH_REG1 0x0084 + +#define mCLOCK_SEL_CNTL 0x0090 + +#define mBUS_CNTL 0x00A0 + +#define mMEM_CNTL 0x00B0 + +#define mMEM_VGA_WP_SEL 0x00B4 +#define mMEM_VGA_RP_SEL 0x00B8 + +#define mDAC_REGS 0x00C0 +#define mDAC_CNTL 0x00C4 + +#define mGEN_TEST_CNTL 0x00D0 + +#define mCONFIG_CHIP_ID 0x00E0 +#define mCONFIG_STAT0 0x00E4 +#define mCONFIG_STAT1 0x00E8 + + +/* GUI MEMORY MAPPED Registers */ + +#define mDST_OFF_PITCH 0x0100 +#define mDST_X 0x0104 +#define mDST_Y 0x0108 +#define mDST_Y_X 0x010C +#define mDST_WIDTH 0x0110 +#define mDST_HEIGHT 0x0114 +#define mDST_HEIGHT_WIDTH 0x0118 +#define mDST_X_WIDTH 0x011C +#define mDST_BRES_LNTH 0x0120 +#define mDST_BRES_ERR 0x0124 +#define mDST_BRES_INC 0x0128 +#define mDST_BRES_DEC 0x012C +#define mDST_CNTL 0x0130 + +#define mSRC_OFF_PITCH 0x0180 +#define mSRC_X 0x0184 +#define mSRC_Y 0x0188 +#define mSRC_Y_X 0x018C +#define mSRC_WIDTH1 0x0190 +#define mSRC_HEIGHT1 0x0194 +#define mSRC_HEIGHT1_WIDTH1 0x0198 +#define mSRC_X_START 0x019C +#define mSRC_Y_START 0x01A0 +#define mSRC_Y_X_START 0x01A4 +#define mSRC_WIDTH2 0x01A8 +#define mSRC_HEIGHT2 0x01AC +#define mSRC_HEIGHT2_WIDTH2 0x01B0 +#define mSRC_CNTL 0x01B4 + +#define mHOST_DATA0 0x0200 +#define mHOST_DATA1 0x0204 +#define mHOST_DATA2 0x0208 +#define mHOST_DATA3 0x020C +#define mHOST_DATA4 0x0210 +#define mHOST_DATA5 0x0214 +#define mHOST_DATA6 0x0218 +#define mHOST_DATA7 0x021C +#define mHOST_DATA8 0x0220 +#define mHOST_DATA9 0x0224 +#define mHOST_DATAA 0x0228 +#define mHOST_DATAB 0x022C +#define mHOST_DATAC 0x0230 +#define mHOST_DATAD 0x0234 +#define mHOST_DATAE 0x0238 +#define mHOST_DATAF 0x023C +#define mHOST_CNTL 0x0240 + +#define mPAT_REG0 0x0280 +#define mPAT_REG1 0x0284 +#define mPAT_CNTL 0x0288 + +#define mSC_LEFT 0x02A0 +#define mSC_RIGHT 0x02A4 +#define mSC_LEFT_RIGHT 0x02A8 +#define mSC_TOP 0x02AC +#define mSC_BOTTOM 0x02B0 +#define mSC_TOP_BOTTOM 0x02B4 + +#define mDP_BKGD_CLR 0x02C0 +#define mDP_FRGD_CLR 0x02C4 +#define mDP_WRITE_MASK 0x02C8 +#define mDP_CHAIN_MASK 0x02CC +#define mDP_PIX_WIDTH 0x02D0 +#define mDP_MIX 0x02D4 +#define mDP_SRC 0x02D8 + +#define mCLR_CMP_CLR 0x0300 +#define mCLR_CMP_MASK 0x0304 +#define mCLR_CMP_CNTL 0x0308 + +#define mFIFO_STAT 0x0310 + +#define mCONTEXT_MASK 0x0320 +#define mCONTEXT_LOAD_CNTL 0x0324 + +#define mGUI_TRAJ_CNTL 0x0330 +#define mGUI_STAT 0x0338 + +/* + +Shortened register names + +*/ + +#define IOBASE_ADDRESS 0x02ec +#define IOB IOBASE_ADDRESS + +#define CRTC_H_TOTAL ( IOB + 0x0000 ) +#define CRTC_H_DISP ( IOB + 0x0002 ) + +#define CRTC_H_SYNC_STRT ( IOB + 0x0400 ) +#define CRTC_H_SYNC_DLY ( IOB + 0x0401 ) +#define CRTC_H_SYNC_WID ( IOB + 0x0402 ) + +#define CRTC_V_TOTAL ( IOB + 0x0800 ) +#define CRTC_V_DISP ( IOB + 0x0802 ) + +#define CRTC_V_SYNC_STRT ( IOB + 0x0c00 ) +#define CRTC_V_SYNC_WID ( IOB + 0x0c02 ) + +#define CRTC_OFFSET ( IOB + 0x1400 ) +#define CRTC_PITCH ( IOB + 0x1402 ) + +#define CRTC_INT_CNTL ( IOB + 0x1800 ) + +#define CRTC_GEN_CNTL ( IOB + 0x1c00 ) +#define CRTC_DBL_SCAN_EN 0x01 +#define CRTC_INTERLACE_EN 0x02 +#define CRTC_HSYNC_DIS 0x04 +#define CRTC_VSYNC_DIS 0x08 +#define CRTC_CSYNC_EN 0x10 +#define CRTC_PIX_BY_2_EN 0x20 +#define CRTC_BLANK 0x40 + +#define CRTC_PIX_WIDTH ( IOB + 0x1c01 ) +#define PIX_WIDTH8 0x02 + +#define CRTC_FIFO ( IOB + 0x1c02 ) + +#define CRTC_EXT_DISP ( IOB + 0x1c03 ) +#define CRTC_EXT_DISP_EN 0x01 +#define CRTC_EXT_EN 0x02 + +#define OVR_CLR_8 ( IOB + 0x2000 ) +#define OVR_CLR_B ( IOB + 0x2001 ) +#define OVR_CLR_G ( IOB + 0x2002 ) +#define OVR_CLR_R ( IOB + 0x2003 ) + +#define OVR_WID_LEFT ( IOB + 0x2400 ) +#define OVR_WID_RIGHT ( IOB + 0x2402 ) +#define OVR_WID_TOP ( IOB + 0x2800 ) +#define OVR_WID_BOTTOM ( IOB + 0x2802 ) + +#define SCRATCH_REG0 ( IOB + 0x4000 ) +#define TEST_MEM_ADDR ( IOB + 0x4000 ) +#define SCRATCH_REG1 ( IOB + 0x4400 ) +#define TEST_MEM_DATA ( IOB + 0x4400 ) + +#define CLOCK_CNTL ( IOB + 0x4800 ) +#define FS2_bit 0x04 +#define FS3_bit 0x08 +#define CLOCK_SEL 0x0f +#define CLOCK_DIV 0x30 +#define CLOCK_DIV1 0x00 +#define CLOCK_DIV2 0x10 +#define CLOCK_DIV4 0x20 +#define CLOCK_STROBE 0x40 +#define CLOCK_SERIAL_DATA 0x80 + +#define BUS_CNTL1_16 ( IOB + 0x4c00 ) + +#define BUS_CNTL2_16 ( IOB + 0x4c02 ) + +#define MEM_CNTL8 ( IOB + 0x5000 ) + +#define MEM_VGA_WP_SEL ( IOB + 0x5400 ) +#define MEM_VGA_RP_SEL ( IOB + 0x5800 ) + +#define MEM_BNDRY ( IOB + 0x5002 ) +#define MEM_BNDRY_256K 0x01 +#define MEM_BNDRY_512K 0x02 +#define MEM_BNDRY_1M 0x03 +#define MEM_BNDRY_EN 0x04 + +#define DAC_W_INDEX ( IOB + 0x5c00 ) +#define DAC_DATA ( IOB + 0x5c01 ) +#define DAC_MASK ( IOB + 0x5c02 ) +#define DAC_R_INDEX ( IOB + 0x5c03 ) +#define DAC8_W_INDEX ( DAC_W_INDEX & 0xff ) +#define DAC8_DATA ( DAC_DATA & 0xff ) +#define DAC8_MASK ( DAC_MASK & 0xff ) +#define DAC8_R_INDEX ( DAC_R_INDEX & 0xff ) + +#define DAC_CNTL1 ( IOB + 0x6000 ) +#define DAC_EXT_SEL_RS2 0x01 +#define DAC_EXT_SEL_RS3 0x02 +#define DAC_CNTL2 ( IOB + 0x6001 ) +#define DAC_8BIT_EN 0x01 +#define DAC_PIX_DLY_MASK 0x06 +#define DAC_PIX_DLY_0NS 0x00 +#define DAC_PIX_DLY_2NS 0x02 +#define DAC_PIX_DLY_4NS 0x04 +#define DAC_BLANK_ADJ_MASK 0x18 +#define DAC_BLANK_ADJ_0 0x00 +#define DAC_BLANK_ADJ_1 0x08 +#define DAC_BLANK_ADJ_2 0x10 + +#define DAC_TYPE_ ( IOB + 0x6002 ) + +#define GEN_TEST_CNTL ( IOB + 0x6400 ) + +#define CONFIG_CNTL ( IOB + 0x6800 ) + +#define CONFIG_CHIP_ID ( IOB + 0x6c00 ) + +#define CONFIG_STAT ( IOB + 0x7000 ) + +#define GEN_TEST_CNTL ( IOB + 0x6400 ) + +#define GEN_TEST_CNTL2 ( IOB + 0x6402 ) + +#define PIXEL_DELAY_ON 0x0800 + +#define PITCH_INFO (SCRATCH_REG1 + 2) +#define DAC_VGA_MODE 0x80 +#define SET_VGA_MODE 0x02 +#define PITCH_INFO_PSIZE 0xc0 +#define PITCH_INFO_DAC 0x10 +#define PITCH_INFO_MUX2 0x20 +#define PITCH_INFO_TIOCLK 0x08 +#define PITCH_INFO_DAC0 0x01 + +#define VGA_MODE 1 +#define ACCELERATOR_MODE 0 + +#define DOTCLK_TOLERANCE 25 + +#define REPORT +#define DEBUG +#define BAILOUT + +#define TRUE 1 +#define FALSE 0 + +#define ATIPORT 0x1ce +#define ATIOFF 0x80 +#define ATISEL(reg) (ATIOFF+reg) + +#define M64_BIOS_SIZE 0x8000 +#define M64_CLOCK_MAX 0x0f + +#define BPP_4 1 +#define BPP_8 2 +#define BPP_15 3 +#define BPP_16 4 +#define BPP_24 5 +#define BPP_32 6 + +#define VRAM_MASK 0x66 + +#define C_ISC2595 1 +#define C_STG1703 2 +#define C_CH8398 3 +#define C_BEDROCK 4 +#define C_ATT20C408 5 +#define C_RGB514 6 + +#define D_ATI68860 5 + +#define SAY(x) fprintf(stderr,#x"\n");fflush(stderr); +#define DUMP(x) for (DUMPINDEX=0;DUMPINDEX<32;DUMPINDEX++) \ + DUMPOUT[31-DUMPINDEX]=(((x)>>DUMPINDEX)&0x1)? \ + '1':'0'; \ + DUMPOUT[32]='\0'; \ + printf("%s\n",DUMPOUT); + +typedef unsigned char UB; +typedef unsigned short US; +typedef unsigned long UL; + +typedef struct { + UB h_disp; /* horizontal res in chars */ + UB dacmask; /* supported dacs */ + UB ram_req; /* ram required */ + UB max_dot_clk; /* max dot clock */ + UB color_depth; /* mac color depth */ + UB FILLER; /* make even #bytes */ +} M64_MaxColorDepth; + +typedef struct { + UB ClockType; /* clock type */ + US MinFreq; /* min clock freq */ + US MaxFreq; /* max clock freq */ + US RefFreq; /* reference freq */ + US RefDivdr; /* reference freq divider */ + US N_adj; /* adjust */ + US Dram_Mem_Clk; + US Vram_Mem_Clk; + US Coproc_Mem_Clk; + UB CX_Clk; + UB VGA_Clk; + UB Mem_Clk_Entry; + UB SClk_Entry; + US ClkFreqTable[M64_CLOCK_MAX*2]; /* clock frequency table */ + UB DefaultDivdr; + UB DefaultFS2; + UB CX_DMcycle; + UB VGA_DMcycle; + UB CX_VMcycle; + UB VGA_VMcycle; +} M64_ClockInfo; + +typedef struct { + US Chip_Type; /* ASIC Chip type */ + UB Chip_Class; /* ASIC Chip class */ + UB Chip_Rev; /* ASIC Chip Revision */ + UB Chip_ID_Index; /* Name offset */ + UB Cfg_Bus_type; /* Bus type */ + UB Cfg_Ram_type; /* Ram type */ + UB Mem_Size; /* Memory installed */ + UB Dac_Type; /* Dac type */ + UB Dac_Subtype; /* Dac sub type */ +} M64_StartUpInfo; + + +static UB *M64_Chip_Name[]={"GX-C","GX-D","GX-E","GX-F","GX-?", + "CX","CX-?", + "CT","ET", + "?"}; + +static UB *M64_Bus_Name[]={"ISA","EISA","","","","","VLB","PCI"}; +static UB *M64_Dac_Name[]={"","TVP3020, RGB514","ATI68875","BT476/BT478", + "BT481, ATT490, ATT491","ATI68860/ATI68880", + "STG1700","SC15021, STF1702"}; +static UB *M64_Ram_Name[]={"DRAM (256Kx4)","VRAM (256x4,x8,x16)", + "VRAM (256Kx16 short shift register)", + "DRAM (256Kx16)","Graphics DRAM (256Kx16)", + "Enhanced VRAM (256Kx4,x8,x16)", + "Enhanced VRAM (256Kx16 short shift register)", + ""}; +static US M64_Mem_Size[]={512,1024,2048,4096,6144,8192,0,0}; +static UB *M64_Clock_Name[]={"","ISC2595","STG1703","CH8398", + "BEDROCK","ATT20C408","RGB514"}; + +static UB M64_BPP[]={-1,4,8,15,16,24,32,-1}; + +/* + +Some misc. structures + +*/ + +typedef struct { + US VRes; + US HRes; + UB max_cdepth; + UB req_cdepth; + US fifo_vl; + + US pdot_clock; + UB refresh_mask; + UB vmode; + US misc; + + UB h_total; + UB h_disp; + UB h_sync_strt; + UB h_sync_wid; + + US v_total; + US v_disp; + US v_sync_strt; + UB v_sync_wid; + + UB clock_cntl; + US dot_clock; + + UB h_overscan_a; + UB h_overscan_b; + + UB v_overscan_a; + UB v_overscan_b; + + UB overscan_8; + UB overscan_B; + UB overscan_G; + UB overscan_R; +} CRTC_Table; + +#define MAX_CRTC_TABLE 1 + +static CRTC_Table CRTC_tinfo[MAX_CRTC_TABLE]={ + /* 640x480 60 Hz NI */ + { 0, 0, 0, 0, 0, + 0, 60, 0x12, PIXEL_DELAY_ON, +/* 0x63, 0x4f, 0x52, 0x2c, + 0x020c, 0x01df, 0x01ea, 0x22, +*/ 0x64, 0x50, 0x53, 0x02, + 0x20d, 0x1e0, 0x1eb, 0x02, + 0x00, 2518, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + } +}; + + diff --git a/obsolete/support/0-README b/obsolete/support/0-README new file mode 100644 index 0000000..232b6d8 --- /dev/null +++ b/obsolete/support/0-README @@ -0,0 +1,23 @@ +This contains the source for a Borland C++ program that allows you to dump +the register contents for any BIOS video mode. 'vga.exe' should work with +any VGA/SVGA adapter. It takes a hexadecimal mode number as argument and +writes the (VGA) register contents to the console. + +These printout can be used to write a new driver. Please read also 'man 7 +svgalib.et4000' about the tseng3.exe program. + +trap-out.asm / .com is a DOS program which traces all I/O calls made when a +given video mode is set by the BIOS. It was used for the TVGA driver and should +be useful for other drivers too, esp. if no documentation is available. + +It spits out a long list of "T DX/I AX/L" strings where T is "I" for IN or +"O" for OUT, DX/I is the value of DX or the immediate given value for +ports <256, and AX/L is the value of AX or AL before the call to IN or OUT +(yeah, the value of AX is pretty worthless before a call to IN, but oh +well) + +This output is very very easily parsed into a simple C routine that calls +port_in and port_out many many times, but will set the same mode the BIOS +did. + +The trap-out program is courtesy of Ryan Rubley diff --git a/obsolete/support/trap-out.asm b/obsolete/support/trap-out.asm new file mode 100644 index 0000000..025448d --- /dev/null +++ b/obsolete/support/trap-out.asm @@ -0,0 +1,344 @@ +; TRAPOUT2.ASM v2.0 by ARK (ark@lhq.com, root@ark.dyn.ml.org) 11-28-97 +; Traps IN and OUT instructions in INT 10h and displays DX and AX/AL values. +; +; In the header "T DX/I AX/L", T is the Type of instruction (I=IN, O=OUT), +; DX/I is the value of DX or the Immediate value if port<256, and AX/L +; is the value of AX or AL depending on if an 8 or 16 bit value is listed. +; AX/L is meaningless for IN's since it is the value if AX/L *before* the +; call to IN. +; +; This is very useful to find information about how your video card works. +; I wrote this to get register dumps for my Trident TVGA9440AGi card so +; that I could use it under Linux. +; +; NOTE: Pipe the output or you won't see anything! +; (ex: TRAP-OUT 4F02 0101 > 640x480.256) +; +; New in v2.0: +; * Traces into INT 10 calls that are called from inside INT 10! +; * Allows AX and BX values to be specified! +; * Command line accepts trailing spaces now. +; x Code to trap INT's also! (T column='N', DX/I=INT ##, AX/L=AX value) +; (Its commented out - but you can recompile with it if you want) +; +; How to assemble with Borland: +; tasm /ml /zd ncr.asm (case sensitive, line number debug info only) +; tlink /x /t ncr.obj (no map, make com file) +; + +.model tiny ; Tiny memory model, all segments point to the same 64K +.286 ; This code will run on a 286... actually, it +.code ; Everything is in the code segment(cs) will probably +.startup ; Startup run on anything + +jmp Start ; Go to beginning of progam +realINT1 dd 52411A3Eh ; Address of original INT 01h routine offset +realINT10 dd 3C1B214Bh ; Memory for [es:bx] of the real INT 10h + ; (defaults are '>-ARK!-<' just for looks in the .COM) + +; strings +no_command_line db 'Use: TRAPOUT2 [AX] [BX]',13,10 +db ' Traces all IN/OUT calls inside INT 10h',13,10,36 +tracing db 'Tracing INT 10h with AX:',36 +bx_msg db ' BX:',36 +header db 13,10,'T DX/I AX/L',13,10,36 + +INT1 proc ; Interrupt Service Routine for Single Step Debugging + push ax ; save registers + push dx + push es + push di + push bp + + mov bp,sp ; set bp to the stack + push word ptr cs:[bp+12] ; put the real cs + pop es ; into es + push word ptr cs:[bp+10] ; put the real ip + pop di ; into di + mov al,byte ptr es:[di] ; set al to the next instruction that will + ; be executed after this INT 01 is done. + +; This code will trap INT's also... +; cmp al,0CDh ; If al is not CD (INT) keep going +; jne not_int ; If it is, display some stuff... +;; This will skip doing the INT's... +;; add word ptr cs:[bp+10],2 ; Add 2 to the real ip, to skip the INT +; mov dl,4Eh ; Display an N +; mov ah,02h ; The immediate value/DX is the INT ## +; int 21h ; that is called. AX is the value before +; mov dl,20h ; Display a space +; mov ah,02h ; +; int 21h ; Display the immediate value which is +; jmp is_imm ; reallly the interrupt number called. + + not_int: + and al,0F4h ; If al is E4-E7 or EC-EF (all IN/OUT's) + cmp al,0E4h ; Then we display our stuff + jne not_io ; Otherwise, do nothing + ; note: 1 more byte of code after this + ; jmp will make it out of range... + + mov al,byte ptr es:[di] ; Set al to next instruction + test al,02h ; If bit 1 is set then we have an OUT + jz is_in ; If bit 1 is 0, we have an IN + + mov dl,4Fh ; Display an O + mov ah,02h + int 21h + jmp dx_or_imd + + is_in: ; Display an I + mov dl,49h + mov ah,02h + int 21h + + dx_or_imd: ; Display a space + mov dl,20h + mov ah,02h + int 21h + + mov al,byte ptr es:[di] ; Set al to next instruction + test al,08h ; If bit 3 is set then we are using DX + jz is_imm ; If bit 3 is 0, we are using an immediate + + mov ax,[bp+6] ; restore dx to ax + call ShowHex ; Display dx + call ShowHex + call ShowHex + call ShowHex + jmp ax_or_al + + is_imm: + mov dl,20h ; Display 2 spaces + mov ah,02h + int 21h + mov dl,20h + mov ah,02h + int 21h + + mov ah,byte ptr es:[di+1] ; Set ah to byte after the next instruction + call ShowHex ; Display the immediate value + call ShowHex + + ax_or_al: + mov dl,2Ch ; Display a comma + mov ah,02h + int 21h + + mov al,byte ptr es:[di] ; Set al to next instruction + test al,01h ; If bit 0 is set then we are using AX + jz is_al ; If bit 0 is 0, we are using AL + + mov ax,[bp+8] ; Restore ax + call ShowHex ; Display ax + call ShowHex + call ShowHex + call ShowHex + jmp print_next_line + + is_al: + mov ah,[bp+8] ; Restore al to ah + call ShowHex ; Display al + call ShowHex + + print_next_line: + mov dl,0Dh ; print a newline + mov ah,02h + int 21h + mov dl,0Ah + mov ah,02h + int 21h + + not_io: + pop bp ; restore registers + pop di + pop es + pop dx + pop ax + iret ; end interrupt +INT1 endp + +; INT 10h that fakes the real INT 10 and sets the trap flag. +INT10 proc ; Interrupt Service Routine for Tracing INT 10h + push ax ; Save AX + pushf ; Put flags on the stack + pop ax ; Then into AX + or ax,0100h ; Set the trap flag + push ax ; Trap Flag calls INT 01h between every instruction + popf ; Stuff new flags back into the flags register + pop ax ; Restore AX + + cli ; Fake INT call: clear interrupt flag, skip clearing + pushf ; trap flag, push flags, call to location. + call cs:[realINT10] ; This call to INT 10h is be trapped for + ; IN/OUT/INT Normal INT calls would clear + ; the trap flag and then INT 01h would never + ; be called. + iret ; end interrupt +INT10 endp + +; function that prints the highest 4 bits of ax as text {0-9,A-F} to stdout +; ax will be shifted left 4 bits on return. +ShowHex proc + push ax ; save registers + push dx + + shr ax,0Ch ; move the highest 4 bits to the lowest 4 + and al,0Fh ; limit to lowest 4 bits + or al,30h ; change range to 30h-3Fh {0-9:;<=>?} + cmp al,39h ; if it is 30h-39h + jbe is_0_thru_9 ; then its already set + add al,07h ; otherwise change :;<=>? to A-F + is_0_thru_9: + mov dl,al + mov ah,02h + int 21h + + pop dx ; restore dx + pop ax ; restore ax + shl ax,4 ; set up ax for next call + ret ; return +ShowHex endp + +Start: ; Program begins here + mov si,0080h ; CS:0080h is the command line + cmp byte ptr [si],10 ; I want it to be at least 10 bytes long + jae process_command_line ; if not, abort + + mov dx,offset no_command_line ; ds is preset + mov ah,09h ; Dos function 09h + int 21h ; Display no command line string + ret ; Exit program + + process_command_line: + inc si ; move si to start of actual string + mov ax,[si+1] ; copy first 2 chrs to ax, skipping the space + mov bx,[si+3] ; copy 2nd two characters to bx + sub al,30h ; subtract 30h so chrs 0-9 have value 0-9 + cmp al,09h ; if its 0-9, its ok. + jbe al_is_ok ; if its not, its probably A-F or a-f + sub al,07h ; so subtract 7 more + and al,0Fh ; and limit to 0-F + al_is_ok: + sub ah,30h ; do the same to ah + cmp ah,09h + jbe ah_is_ok + sub ah,07h + and ah,0Fh + ah_is_ok: + sub bl,30h ; do the same to bl + cmp bl,09h + jbe bl_is_ok + sub bl,07h + and bl,0Fh + bl_is_ok: + sub bh,30h ; do the same to bh + cmp bh,09h + jbe bh_is_ok + sub bh,07h + and bh,0Fh + bh_is_ok: + shl al,04h ; Combine the values so that AL-AH-BL-BH + or ah,al ; Goes into --AH- --AL- + mov al,bl ; <----AX---> + shl al,04h + or al,bh + mov word ptr [si],ax ; store the value over the string + + mov ax,[si+6] ; copy 3rd 2 chrs to ax, skip the 2nd space + mov bx,[si+8] ; copy 4th two characters to bx + sub al,30h ; subtract 30h so chrs 0-9 have value 0-9 + cmp al,09h ; if its 0-9, its ok. + jbe al_is_ok2 ; if its not, its probably A-F or a-f + sub al,07h ; so subtract 7 more + and al,0Fh ; and limit to 0-F + al_is_ok2: + sub ah,30h ; do the same to ah + cmp ah,09h + jbe ah_is_ok2 + sub ah,07h + and ah,0Fh + ah_is_ok2: + sub bl,30h ; do the same to bl + cmp bl,09h + jbe bl_is_ok2 + sub bl,07h + and bl,0Fh + bl_is_ok2: + sub bh,30h ; do the same to bh + cmp bh,09h + jbe bh_is_ok2 + sub bh,07h + and bh,0Fh + bh_is_ok2: + shl al,04h ; Combine the values so that AL-AH-BL-BH + or ah,al ; Goes into --AH- --AL- + mov al,bl ; <----AX---> + shl al,04h + or al,bh + mov word ptr [si+2],ax ; store the value over the string + ; Now [si] contains the real values of AX and BX + + mov dx,offset tracing ; ds is preset + mov ah,09h ; Dos function 09h + int 21h ; Display tracing string + mov ax,word ptr [si] ; Restore ax + call ShowHex ; Display command line + call ShowHex ; ax value back to user + call ShowHex ; by placing it in ax + call ShowHex ; and calling ShowHex + mov dx,offset bx_msg ; ds is preset + mov ah,09h ; Dos function 09h + int 21h ; Display bx message + mov ax,word ptr [si+2] ; Restore bx into ax + call ShowHex ; Display command line + call ShowHex ; bx value back to user + call ShowHex ; by placing it in ax + call ShowHex ; and calling ShowHex + mov dx,offset header ; ds is preset + mov ah,09h ; Dos function 09h + int 21h ; Display header to output + + mov ax,3501h ; Dos function 35h, Get vector of INT 01h + int 21h ; Store it in es:bx + mov word ptr [realINT1],bx ; Store address of original INT 01h + mov word ptr [realINT1+2],es ; into realINT1 + + mov ax,3510h ; Dos function 35h, Get vector of INT 10h + int 21h ; Store it in es:bx + mov word ptr [realINT10],bx ; Store address of original INT 10h + mov word ptr [realINT10+2],es ; into realINT10 so we can fake an INT + + mov ax,2501h ; Dos function 25h, Store DS:DX to INT 01h + mov dx,offset INT1 ; ds is preset, dx is the handler's offset + int 21h ; Set new Single Step handler + + mov ax,2510h ; Dos function 25h, Store DS:DX to INT 10h + mov dx,offset INT10 ; ds is preset, dx is the handler's offset + int 21h ; Set new Video Interrupt + + mov ax,word ptr [si] ; We will use the command line ax/bx + mov bx,word ptr [si+2] ; values for the fake int call + int 10h ; Call my int 10 which fakes the + ; real int 10 and traps it. + + mov ax,2501h ; Dos function 25h, Store DS:DX to INT 01h + mov dx,word ptr [realINT1] ; ds/dx are in realINT1 + push ds ; Save old ds + push word ptr [realINT1+2] ; Put segment on stack + pop ds ; Set ds to the segment + int 21h ; Reset old Single Step handler + pop ds ; Restore old ds + + mov ax,2510h ; Dos function 25h, Store DS:DX to INT 10h + mov dx,word ptr [realINT10] ; ds/dx are in realINT10 + push ds ; Save old ds + push word ptr [realINT10+2] ; Put segment on stack + pop ds ; Set ds to the segment + int 21h ; Reset old Video Interrupt + pop ds ; Restore old ds + + mov ax,0003h ; Set ax to 3 + int 10h ; Set 80x25 Text mode + ret ; End of program +end ; End of file diff --git a/obsolete/support/trap-out.com b/obsolete/support/trap-out.com new file mode 100644 index 0000000..150dcf4 Binary files /dev/null and b/obsolete/support/trap-out.com differ diff --git a/obsolete/support/vga.c b/obsolete/support/vga.c new file mode 100644 index 0000000..16e4745 --- /dev/null +++ b/obsolete/support/vga.c @@ -0,0 +1,146 @@ +#include +#include +#include + +/* January 1995, Scott Heavner (sdh@po.cwru.edu) + + * Changes to allow anyone to compile vga.c under the go32 Linux->dos cross compiler. + * It should also work with DJGPP (the gcc port to msdos). The cross compiler is + * available at ftp://sunsite.unc.edu/pub/Linux/devel/msdos/go32crs.tar.gz. + * + * I compiled it with: + * + * go32gcc vga.c -lpc + * cat /usr/local/go32/bin/go32.exe a.out > vga.exe + */ +#ifdef GO32 +#include +#endif + +/* VGA index register ports */ +#define CRT_I 0x3D4 /* CRT Controller Index (mono: 0x3B4) */ +#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define PEL_IW 0x3C8 /* PEL Write Index */ + +/* VGA data register ports */ +#define CRT_D 0x3D5 /* CRT Controller Data Register (mono: 0x3B5) */ +#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ +#define MIS_R 0x3CC /* Misc Output Read Register */ +#define MIS_W 0x3C2 /* Misc Output Write Register */ +#define IS1_R 0x3DA /* Input Status Register 1 (mono: 0x3BA) */ +#define PEL_D 0x3C9 /* PEL Data Register */ + +/* VGA indexes max counts */ +#define CRT_C 24 /* 24 CRT Controller Registers */ +#define ATT_C 21 /* 21 Attribute Controller Registers */ +#define GRA_C 9 /* 9 Graphics Controller Registers */ +#define SEQ_C 5 /* 5 Sequencer Registers */ +#define MIS_C 1 /* 1 Misc Output Register */ + +/* VGA registers saving indexes */ +#define CRT 0 /* CRT Controller Registers start */ +#define ATT CRT+CRT_C /* Attribute Controller Registers start */ +#define GRA ATT+ATT_C /* Graphics Controller Registers start */ +#define SEQ GRA+GRA_C /* Sequencer Registers */ +#define MIS SEQ+SEQ_C /* General Registers */ +#define END MIS+MIS_C /* last */ + + +unsigned char vga_regs[60]; + +#ifdef GO32 + +#define port_out(v,p) outportb(p,v) +#define port_in(p) inportb(p) + +#else + +void port_out(unsigned char value, unsigned short port) +{ + asm + { + mov dx, port + mov al, value + out dx, al + } +} unsigned char port_in(unsigned short port) +{ + asm + { + mov dx, port + in al, dx + } return (_AL); +} + +#endif + +main(int argc, char *argv[]) +{ + union REGS cpu_regs; + int i; + unsigned char mode; + + if (argc != 2) { + printf("Usage: getregs mode (mode must be hexadecimal)\n"); + exit(-1); + } + if (!sscanf(argv[1], "%x", &mode)) { + printf("Usage: getregs mode (mode must be hexadecimal)\n"); + exit(-1); + } + cpu_regs.h.ah = 0x00; + cpu_regs.h.al = mode; + int86(0x10, &cpu_regs, &cpu_regs); + + /* get VGA register values */ + for (i = 0; i < CRT_C; i++) { + port_out(i, CRT_I); + vga_regs[CRT + i] = port_in(CRT_D); + } + for (i = 0; i < ATT_C; i++) { + port_in(IS1_R); + port_out(i, ATT_IW); + vga_regs[ATT + i] = port_in(ATT_R); + } + for (i = 0; i < GRA_C; i++) { + port_out(i, GRA_I); + vga_regs[GRA + i] = port_in(GRA_D); + } + for (i = 0; i < SEQ_C; i++) { + port_out(i, SEQ_I); + vga_regs[SEQ + i] = port_in(SEQ_D); + } + vga_regs[MIS] = port_in(MIS_R); + + cpu_regs.h.ah = 0x00; + cpu_regs.h.al = 0x03; + int86(0x10, &cpu_regs, &cpu_regs); + + printf("/* BIOS mode 0x%02X */\n", mode); + printf("static char regs[60] = {\n "); + for (i = 0; i < 12; i++) + printf("0x%02X,", vga_regs[CRT + i]); + printf("\n "); + for (i = 12; i < CRT_C; i++) + printf("0x%02X,", vga_regs[CRT + i]); + printf("\n "); + for (i = 0; i < 12; i++) + printf("0x%02X,", vga_regs[ATT + i]); + printf("\n "); + for (i = 12; i < ATT_C; i++) + printf("0x%02X,", vga_regs[ATT + i]); + printf("\n "); + for (i = 0; i < GRA_C; i++) + printf("0x%02X,", vga_regs[GRA + i]); + printf("\n "); + for (i = 0; i < SEQ_C; i++) + printf("0x%02X,", vga_regs[SEQ + i]); + printf("\n "); + printf("0x%02X", vga_regs[MIS]); + printf("\n};\n"); + +} diff --git a/obsolete/svpmi/parse.c b/obsolete/svpmi/parse.c new file mode 100644 index 0000000..905c513 --- /dev/null +++ b/obsolete/svpmi/parse.c @@ -0,0 +1,253 @@ + +/* + * This is a quickly hacked program to convert an SVPMI (Super VGA Protected + * Mode Interface) data file to an svgalib driver. Feedback is + * very welcome. + * + * Initial version (Mar 94 HH). Doesn't do much yet. + * Assumes textmode is last defined mode. + * End with ctrl-c. Correct resulting files by hand. + * (add "}" to modetable.svpmi) + */ + + +#include +#include +#include + + +void parse (); + + +void +main () +{ + parse (); +} + + +/* Return pointer to line red from stdin, end marked by CR or CR/LF. + * Initial spaces are removed. */ + +char * +getline () +{ + static char linebuf[128]; + int i, length, spaces; + i = 0; + for (;;) + { + int c; + c = fgetc (stdin); + if (feof (stdin)) + return NULL; + if (c == 13) + continue; /* Skip. */ + if (c == 10) + break; + linebuf[i] = c; + i++; + } + length = i; + linebuf[i] = 0; + /* Remove initial spaces. */ + spaces = 0; + i = 0; + while (i < length) + { + if (linebuf[i] != ' ') + break; + i++; + spaces++; + } + return linebuf + spaces; +} + + +/* Skip lines until left side of line matches string s. */ + +char * +getthisline (char *s) +{ + char buf[128]; + int n; + n = strlen (s); + for (;;) + { + char *line; + line = getline (); + if (strncmp (line, s, n) == 0) + return line; + } +} + + +/* Get the (n + 1)th word delimited by ' ' and ';' in string s. */ + +char * +getword (char *s, int n) +{ + int i; + char *word; + int mode, wcount; + word = s; + mode = 0; /* Whitespace. */ + wcount = 0; + i = 0; + for (i = 0; s[i] != 0; i++) + { + if (s[i] == ' ' || s[i] == ';') + if (mode == 0) + continue; + else + { + s[i] = 0; + if (wcount == n) + return word; + wcount++; + mode = 0; + } + else if (mode == 1) + continue; + else + { + word = &s[i]; + mode = 1; + } + } + return NULL; +} + + +/* Write lines to file until left part matches string s. */ + +void +writetofileuntilthisline (char *s, FILE * f) +{ + int n; + n = strlen (s); + for (;;) + { + char *line; + line = getline (); + if (strncmp (line, s, n) == 0) + break; + fprintf (f, "%s\n", line); + } +} + + +void +writetofileuntilend (FILE * f) +{ + for (;;) + { + char *line; + line = getline (); + if (line == NULL) + return; + fprintf (f, "%s\n", line); + } +} + + +void +parse () +{ + char *line; + char s[128]; + char modename[40]; + int modenumber; + FILE *f, *g; + printf ("SVPMI to svgalib driver converter.\n\n"); + + /* Read header. */ + getthisline ("[ADAPTER]"); + line = getline (); + printf ("Graphics Adapter string: %s\n", line); + + /* Read modes. */ + modenumber = 0; + g = fopen ("modetable.svpmi", "wb"); + f = fopen ("modes.svpmi", "wb"); + fprintf (g, "/* svgalib SVPMI mode table. */\n\n"); + fprintf (g, "static svpmi_modeentry svpmi_modes[] = {\n"); + + for (;;) + { + int XResolution; /* SVPMI modeinfo fields. */ + int YResolution; + int BitsPerPixel; + int BytesPerScanline; + int WinAGranularity; + int WinASize; + int WinABase; + int ModeAttributes; + getthisline ("[MODEINFO]"); + line = getthisline ("ModeAttributes"); + ModeAttributes = atoi (getword (line, 2)); + line = getthisline ("WinAGranularity"); + WinAGranularity = atoi (getword (line, 2)); + line = getthisline ("WinASize"); + WinASize = atoi (getword (line, 2)); + line = getthisline ("WinABase"); + WinABase = atoi (getword (line, 2)); +#if 0 + if (WinABase != 0xa0000) + { + printf ("Window is not at 0xa0000.\n"); + exit (-1); + } +#endif + line = getthisline ("BytesPerScanline"); + BytesPerScanline = atoi (getword (line, 2)); + line = getthisline ("XResolution"); + XResolution = atoi (getword (line, 2)); + line = getthisline ("YResolution"); + YResolution = atoi (getword (line, 2)); + line = getthisline ("BitsPerPixel"); + BitsPerPixel = atoi (getword (line, 2)); + + if (ModeAttributes == 0x07) + { + /* Text mode. */ + printf ("Textmode found.\n"); + getthisline ("[SETMODE]"); + fprintf (f, "static void svpmi_setmode_text() {\n"); + writetofileuntilend (f); + fprintf (f, "}\n\n\n"); + fprintf (g, "}\n"); + fclose (f); + fclose (g); + exit (0); + } + + printf ("Mode found: %d x %d, %dbpp %d bpl gran A %d\n", + XResolution, YResolution, BitsPerPixel, + BytesPerScanline, WinAGranularity); + + sprintf (modename, "%dx%dx%d", XResolution, YResolution, + 1 << BitsPerPixel); + + getthisline ("[SETMODE]"); + fprintf (f, "static void svpmi_setmode_%s() {\n", modename); + writetofileuntilthisline ("[SETCOLOR]", f); + fprintf (f, "}\n\n\n"); + getthisline ("[SETWINDOW]"); + fprintf (f, "static void svpmi_setwindow_%s( int r0 ) {\n", modename); + writetofileuntilthisline ("[MODE]", f); + fprintf (f, "}\n\n\n"); + + fprintf (g, "{ %d, %d, %d, %d, %d, svpmi_setmode_%s, svpmi_setwindow_%s },\n", + XResolution, YResolution, BitsPerPixel, + BytesPerScanline, WinAGranularity, modename, modename); + + fflush (f); + fflush (g); + + modenumber++; + } + fprintf (g, "}\n"); + fclose (f); + fclose (g); +} diff --git a/obsolete/svpmi/svpmi.c b/obsolete/svpmi/svpmi.c new file mode 100644 index 0000000..825f5b9 --- /dev/null +++ b/obsolete/svpmi/svpmi.c @@ -0,0 +1,185 @@ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Copyright (C) 1994 Harm Hanemaayer */ + +/* + Basic initial untested SVPMI skeleton driver. + Includes computer-generated mode setting/bank switching + routines and mode information table. + + Untested, may not be finished. + + A better way to do this would be to have a seperate svpmi server + program set modes. This way there would be no need to recompile + the shared library. For performance it would be nice to move the + bank-switching over to svgalib. I imagine one way to do this would + be to encode the SVPMI procedure code (simple as it is, just a few + outs and a few basic bit operations) and have the svgalib driver + interpret that. This could also be used for mode setting. + */ + + +#include +#include "../vga.h" +#include "../libvga.h" +#include "../driver.h" + +#include "svpmi.h" +#include "modes.svpmi" +#include "modetable.svpmi" + + + +static svpmi_currentmode = NULL; + +static svpmi_modeentry * +svpmi_lookupmode (int w, int h, int colors) +{ + int i; + for (i = 0; i < sizeof (svpmi_modes); i++) + if (w == svpmi_modes[i].width && h == svpmi_modes[i].height && + colors = (1 << svpmi_mode[i].bitsperpixel)) + return &svpmi_modes[i]; + return NULL; +} + + +static int +svpmi_getmodeinfo (int mode, vga_modeinfo * modeinfo) +{ + modeinfo->maxlogicalwidth = modeinfo->width; + modeinfo->startaddressrange = 0; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + return 0; +} + + +/* Return non-zero if mode is available */ + +static int +svpmi_modeavailable (int mode) +{ + struct info *info; + svpmi_modeentry *sm; + + if (mode < 10) + return vga_chipsetfunctions[CHIPSET_MODEAVAILABLE] (mode); + if (mode == 32) + return 0; + + sm = svpmi_lookupmode (modeinfo->width, modeinfo->height, + modeinfo->colors); + return (sm != NULL) +} + + +/* Set a mode */ + +static int +svpmi_setmode (int mode, int prv_mode) +{ + svpmi_modeentry *sm; + + if (mode == TEXT) + { + svpmi_setmode_text (); + return 0; + } + + if (!SVGAMODE (mode)) + /* Let the standard VGA driver set standard VGA modes. */ + return vga_chipsetfunctions[CHIPSET_SETMODE] (mode); + + sm = svpmi_lookupmode (infotable[mode].width, infotable[mode].height, + infotable[mode].colors); + if (sm == NULL) + return 1; /* No match. */ + + sm->setmode (); /* Call the SVPMI mode setting code. */ + svpmi_currentmode = sm; + + /* Hack similar to what the ATI mach32 driver does for some */ + /* truecolor modes. I think S3 uses only a few fixed scanline */ + /* widths (e.g. 1024, 1280) so may happen a lot. */ + infotable[mode].xbytes = sm->bytesperscanline; +} + + +/* Indentify chipset; return non-zero if detected */ + +static int +svpmi_test () +{ + /* Detection with environment variable -- better change into */ + /* config file option. */ + if (getenv ("SVGALIB_SVPMI")) + return 1; + return 0; +} + + +/* Bank switching function - set 64K bank number */ + +static void +svpmi_setpage (int page) +{ + svpmi_currentmode->setwindow (page * + (64 / svpmi_currentmode->windowgranularity)); +} + + +/* Set display start address (not for 16 color modes) */ + +static int +svpmi_setdisplaystart (int address) +{ +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Multiples of 8 to 2040 */ + +static int +svpmi_setlogicalwidth (int width) +{ + outw (0x3d4, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ + return 0; +} + +static int +nothing () +{ +} + + +/* Function table (exported) */ + +int (*svpmi_chipsetfunctions[]) () = +{ + (int (*)()) nothing, /* saveregs */ + (int (*)()) nothing, /* setregs */ + (int (*)()) nothing, /* unlock */ + (int (*)()) nothing, /* lock */ + svpmi_test, + svpmi_init, + (int (*)()) svpmi_setpage, + (int (*)()) nothing, + (int (*)()) nothing, + svpmi_setmode, + svpmi_modeavailable, + nothing, /* setdisplaystart */ + svmi_setlogicalwidth, + svpmi_getmodeinfo +}; + + +/* Initialize chipset (called after detection) */ + +static int +svpmi_init (int force, int par1, int par2) +{ + /* Not required. */ +} diff --git a/obsolete/svpmi/svpmi.h b/obsolete/svpmi/svpmi.h new file mode 100644 index 0000000..8027386 --- /dev/null +++ b/obsolete/svpmi/svpmi.h @@ -0,0 +1,40 @@ + +typdef struct + { + int width; + int height; + int bitsperpixel; + int bytesperscanline; + int windowgranularity; + void *setmode (); + void *setwindow (int); + } +svpmi_modeentry; + + +static void +wait (int x) +{ + int i; + for (i = 0; i < 10; i++); +} + +static unsigned char r0, r1, r2, r3, r4, r5, r6, r7; +static unsigned char r8, r9, r10, r11, r12, r13, r14, r15; +static unsigned char r16, r17, r18, r19, r20, r21, r22, r23; +static unsigned char r24, r25, r26, r27, r28, r29, r30, r31; + +#define boutb(n, p1, p2) __boutb(0, n, p1 p2) +#define __boutp(i, n, p1, p2) \ + #if n != 0 \ + outb(p1, i); outb(p2, r##i); \ + boutb((i + 1), (n - 1), p1, p2); \ + #endif + +#define inb(r, p) port_in(p) + +#define and(r, v) r &= v; +#define or(r, v) r |= v; +#define xor(r, v) r ^= v; +#define shr(r, v) r >>= v; +#define shl(r, v) r <<= v; diff --git a/src/8514a.h b/src/8514a.h new file mode 100644 index 0000000..d71ea8a --- /dev/null +++ b/src/8514a.h @@ -0,0 +1,92 @@ +/* + * 8514a.h: common header for 8514/A-like (S3, Mach) graphic engines + * + * Extracted from: + * + * ATI Mach32 driver Copyright 1995 Michael Weller + * eowmob@exp-math.uni-essen.de mat42b@aixrs1.hrz.uni-essen.de + * eowmob@pollux.exp-math.uni-essen.de + */ + +#ifndef _8514A_H +#define _8514A_H + +#define CMD 0x9AE8 +#define ALU_FG_FN 0xBAEE +#define ALU_BG_FN 0xB6EE +#define EXT_SCISSOR_B 0xE6EE +#define EXT_SCISSOR_L 0xD2EE +#define EXT_SCISSOR_R 0xE2EE +#define EXT_SCISSOR_T 0xDEEE +#define DP_CONFIG 0xCEEE +#define FRGD_MIX 0xBAE8 +#define BKGD_MIX 0xB6E8 +#define FRGD_COLOR 0xA6E8 +#define BKGD_COLOR 0xA2E8 +#define CUR_X 0x86E8 +#define CUR_Y 0x82E8 +#define MAJ_AXIS_PCNT 0x96E8 +#define MULTI_FUNC_CNTL 0xBEE8 +#define EXT_FIFO_STATUS 0x9AEE +#define ADVFUNC_CNTL 0x4AE8 /* S3 */ +#define SUBSYS_CNTL 0x42E8 +#define SUBSYS_STAT 0x42E8 +#define SCRATCH_PAD_0 0x52EE +#define DESTX_DIASTP 0x8EE8 +#define DESTY_AXSTP 0x8AE8 +#define R_SRC_X 0xDAEE +#define SRC_X 0x8EE8 +#define SRC_Y 0x8AE8 +#define SRC_X_START 0xB2EE +#define SRC_X_END 0xBEEE +#define SRC_Y_DIR 0xC2EE +#define SCAN_TO_X 0xCAEE +#define DEST_X_START 0xA6EE +#define DEST_X_END 0xAAEE +#define DEST_Y_END 0xAEEE +#define GE_STAT 0x9AE8 +#define CONF_STAT1 0x12EE +#define CONF_STAT2 0x16EE +#define MISC_OPTIONS 0x36EE +#define MEM_CFG 0x5EEE +#define MEM_BNDRY 0x42EE +#define LOCAL_CNTL 0x32EE +#define CHIP_ID 0xFAEE +#define EXT_GE_CONF 0x7AEE +#define R_EXT_GE_CONF 0x8EEE +#define DISP_CNTL 0x22E8 +#define CLOCK_SEL 0x4AEE +#define GE_PITCH 0x76EE +#define GE_OFFSET_HI 0x72EE +#define GE_OFFSET_LO 0x6EEE +#define CRT_PITCH 0x26EE +#define CRT_OFFSET_HI 0x2EEE +#define CRT_OFFSET_LO 0x2AEE +#define H_DISP 0x06E8 +#define H_TOTAL 0x02E8 +#define H_SYNC_WID 0x0EE8 +#define H_SYNC_STRT 0x0AE8 +#define V_DISP 0x16E8 +#define V_SYNC_STRT 0x1AE8 +#define V_SYNC_WID 0x1EE8 +#define V_TOTAL 0x12E8 +#define R_H_TOTAL 0xB2EE +#define R_H_SYNC_STRT 0xB6EE +#define R_H_SYNC_WID 0xBAEE +#define R_V_TOTAL 0xC2EE +#define R_V_DISP 0xC6EE +#define R_V_SYNC_STRT 0xCAEE +#define R_V_SYNC_WID 0xD2EE +#define SHADOW_SET 0x5AEE +#define SHADOW_CTL 0x46EE +#define MISC_CTL 0x7EEE +#define R_MISC_CTL 0x92EE +#define LINEDRAW 0xFEEE +#define LINEDRAW_INDEX 0x9AEE +#define LINEDRAW_OPT 0xA2EE +#define PIX_TRANS 0xE2E8 +#define DEST_CMP_FN 0xEEEE +#define CMP_COLOR 0xB2E8 +#define RD_MASK 0xAEE8 + +#endif /* _8514A_H */ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..fbe6660 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,534 @@ +#---------------------------------------------------------------------- +# Makefile for the main svgalib source. +#---------------------------------------------------------------------- + +# *** NO SERVICIBLE PARTS HERE! +# All options are in Makefile.cfg. + +include ../Makefile.cfg + +srcdir = .. +VPATH = $(srcdir)/src + +#---------------------------------------------------------------------- +# Compiler Section (overrides Makefile.cfg) +#---------------------------------------------------------------------- + +INCLUDES += -I$(srcdir)/src + +#---------------------------------------------------------------------- +# Rules Section +#---------------------------------------------------------------------- + +DRIVERS = vgadrv.o regextr.o modetab.o +MODULES = vga.o vgaio.o \ + vgadraw.o vgaclear.o vgaline.o vgapix.o \ + vgapal.o vgacol.o vgamodesel.o vgamisc.o \ + vgadump.o vgaconvplanar.o vgaaccel.o \ + timing.o vgaregs.o interface.o accel.o \ + vgapci.o vga_helper.o \ + vga_console.o vgarelvgaio.o vgammvgaio.o vgacursor.o \ + vganullio.o +MOUSE = mouse/mouse.o +KEYBOARD = keyboard/keyboard.o +JOYSTICK = joystick/joystick.o +RAMDAC = ramdac/ramdac.o ramdac/normal.o ramdac/attdacs.o ramdac/sierra.o \ + ramdac/icw.o ramdac/s3dacs.o ramdac/IBMRGB52x.o ramdac/ics_gendac.o +CLOCKCHIP = clockchip/icd2061a.o + +# defines for all files. +ifeq (y, $(USE_LRMI_9)) + DEFINES += -DUSE_LRMI_9 +endif +ifeq (y, $(NO_ASM)) + DEFINES += -DNO_ASSEMBLY +endif +ifdef SVGALIB_CONFIG_FILE + DEFINES += -DSVGALIB_CONFIG_FILE=\"$(SVGALIB_CONFIG_FILE)\" +endif +ifdef ALLOW_MOUSE_OVERRIDE + DEFINES += -DALLOW_MOUSE_OVERRIDE +endif +ifdef DEBUG + DEFINES += -DDEBUG + CFLAGS += -ggdb3 +endif +ifdef DEBUG_ACCEL + DEFINES += -DDEBUG_ACCEL +endif +ifdef DEBUG_KEYBOARD + DEFINES += -DDEBUG_KEYBOARD +endif +ifdef NO_DELAY + DEFINES += -DNO_DELAY +endif +ifdef LIBC_MEMCPY + DEFINES += -DLIBC_MEMCPY +endif + +# defines for vga.c only. +ifdef ROOT_VC_SHORTCUT + VGA_DEFINES += -DROOT_VC_SHORTCUT +endif + +ifdef DEBUG_CONF + DEFINES += -DDEBUG_CONF +endif + +ifdef INCLUDE_ET4000_DRIVER + VGA_DEFINES += -DINCLUDE_ET4000_DRIVER + DRIVERS += drivers/et4000.o drivers/et4000hico.o + ifdef INCLUDE_ET4000_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_ET4000_DRIVER_TEST + endif + ifdef ET4000_REGS + DEFINES += -DET4000_REGS=\"$(ET4000_REGS)\" + endif + ifdef USE_CLOCKS + DEFINES += -DUSE_CLOCKS + endif +endif +ifdef INCLUDE_CIRRUS_DRIVER + VGA_DEFINES += -DINCLUDE_CIRRUS_DRIVER + DRIVERS += drivers/cirrus.o + ifdef INCLUDE_CIRRUS_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_CIRRUS_DRIVER_TEST + endif +endif +ifdef INCLUDE_TVGA_DRIVER + VGA_DEFINES += -DINCLUDE_TVGA_DRIVER + DRIVERS += drivers/tvga8900.o + ifdef INCLUDE_TVGA_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_TVGA_DRIVER_TEST + endif +endif +ifdef INCLUDE_TRIDENT_DRIVER + VGA_DEFINES += -DINCLUDE_TRIDENT_DRIVER + DRIVERS += drivers/trident.o + ifdef INCLUDE_TRIDENT_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_TRIDENT_DRIVER_TEST + endif +endif +ifdef INCLUDE_OAK_DRIVER + VGA_DEFINES += -DINCLUDE_OAK_DRIVER + DRIVERS += drivers/oak.o + ifdef INCLUDE_OAK_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_OAK_DRIVER_TEST + endif +endif +ifdef INCLUDE_EGA_DRIVER + VGA_DEFINES += -DINCLUDE_EGA_DRIVER + DRIVERS += drivers/egadrv.o + ifdef INCLUDE_EGA_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_EGA_DRIVER_TEST + endif + ifdef EGA_REGS + DEFINES += -DEGA_REGS=\"$(EGA_REGS)\" + endif +endif +ifdef INCLUDE_MACH32_DRIVER + VGA_DEFINES += -DINCLUDE_MACH32_DRIVER + DRIVERS += drivers/mach32.o + ifdef INCLUDE_MACH32_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_MACH32_DRIVER_TEST + endif +endif +ifdef INCLUDE_S3_DRIVER + VGA_DEFINES += -DINCLUDE_S3_DRIVER + DRIVERS += drivers/s3.o + ifdef INCLUDE_S3_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_S3_DRIVER_TEST + endif +endif +ifdef INCLUDE_ET3000_DRIVER + VGA_DEFINES += -DINCLUDE_ET3000_DRIVER + DRIVERS += drivers/et3000.o + ifdef INCLUDE_ET3000_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_ET3000_DRIVER_TEST + endif +endif +ifdef INCLUDE_GVGA6400_DRIVER + VGA_DEFINES += -DINCLUDE_GVGA6400_DRIVER + DRIVERS += drivers/gvga6400.o + ifdef INCLUDE_GVGA6400_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_GVGA6400_DRIVER_TEST + endif +endif +ifdef INCLUDE_ARK_DRIVER + VGA_DEFINES += -DINCLUDE_ARK_DRIVER + DRIVERS += drivers/ark.o + ifdef INCLUDE_ARK_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_ARK_DRIVER_TEST + endif +endif +ifdef INCLUDE_ATI_DRIVER + VGA_DEFINES += -DINCLUDE_ATI_DRIVER + DRIVERS += drivers/ati.o + ifdef INCLUDE_ATI_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_ATI_DRIVER_TEST + endif +endif +ifdef INCLUDE_ALI_DRIVER + VGA_DEFINES += -DINCLUDE_ALI_DRIVER + DRIVERS += drivers/ali.o + ifdef INCLUDE_ALI_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_ALI_DRIVER_TEST + endif +endif +ifdef INCLUDE_MACH64_DRIVER + VGA_DEFINES +=-DINCLUDE_MACH64_DRIVER + DRIVERS += drivers/mach64.o + ifdef INCLUDE_MACH64_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_MACH64_DRIVER_TEST + endif +endif +ifdef INCLUDE_CHIPS_DRIVER + VGA_DEFINES +=-DINCLUDE_CHIPS_DRIVER + DRIVERS += drivers/chips.o + ifdef INCLUDE_CHIPS_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_CHIPS_DRIVER_TEST + endif +endif +ifdef INCLUDE_APM_DRIVER + VGA_DEFINES +=-DINCLUDE_APM_DRIVER + DRIVERS += drivers/apm.o + ifdef INCLUDE_APM_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_APM_DRIVER_TEST + endif +endif +ifdef INCLUDE_VESA_DRIVER + VGA_DEFINES +=-DINCLUDE_VESA_DRIVER + DRIVERS += drivers/vesa.o lrmi.o + ifdef INCLUDE_VESA_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_VESA_DRIVER_TEST + endif +endif +ifdef INCLUDE_NV3_DRIVER + VGA_DEFINES +=-DINCLUDE_NV3_DRIVER + DRIVERS += drivers/nv3.o + ifdef INCLUDE_NV3_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_NV3_DRIVER_TEST + endif +endif +ifdef INCLUDE_SAVAGE_DRIVER + VGA_DEFINES +=-DINCLUDE_SAVAGE_DRIVER + DRIVERS += drivers/savage.o + ifdef INCLUDE_SAVAGE_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_SAVAGE_DRIVER_TEST + endif +endif +ifdef INCLUDE_G400_DRIVER + VGA_DEFINES +=-DINCLUDE_G400_DRIVER + DRIVERS += drivers/g400.o + ifdef INCLUDE_G400_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_G400_DRIVER_TEST + endif +endif +ifdef INCLUDE_PM2_DRIVER + VGA_DEFINES +=-DINCLUDE_PM2_DRIVER + DRIVERS += drivers/pm2.o + ifdef INCLUDE_PM2_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_PM2_DRIVER_TEST + endif +endif +ifdef INCLUDE_UNICHROME_DRIVER + VGA_DEFINES +=-DINCLUDE_UNICHROME_DRIVER + DRIVERS += drivers/unichrome.o + ifdef INCLUDE_UNICHROME_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_UNICHROME_DRIVER_TEST + endif +endif +ifdef INCLUDE_G450C2_DRIVER + VGA_DEFINES +=-DINCLUDE_G450C2_DRIVER + DRIVERS += drivers/g450c2.o + ifdef INCLUDE_G450C2_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_G450C2_DRIVER_TEST + endif +endif +ifdef INCLUDE_MILLENNIUM_DRIVER + VGA_DEFINES +=-DINCLUDE_MILLENNIUM_DRIVER + DRIVERS += drivers/millennium.o + ifdef INCLUDE_MILLENNIUM_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_MILLENNIUM_DRIVER_TEST + endif +endif +ifdef INCLUDE_R128_DRIVER + VGA_DEFINES +=-DINCLUDE_R128_DRIVER + DRIVERS += drivers/r128.o + ifdef INCLUDE_R128_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_R128_DRIVER_TEST + endif +endif +ifdef INCLUDE_MX_DRIVER + VGA_DEFINES +=-DINCLUDE_MX_DRIVER + DRIVERS += drivers/mx.o + ifdef INCLUDE_MX_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_MX_DRIVER_TEST + endif +endif +ifdef INCLUDE_PARADISE_DRIVER + VGA_DEFINES +=-DINCLUDE_PARADISE_DRIVER + DRIVERS += drivers/paradise.o + ifdef INCLUDE_PARADISE_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_PARADISE_DRIVER_TEST + endif +endif +ifdef INCLUDE_RAGE_DRIVER + VGA_DEFINES +=-DINCLUDE_RAGE_DRIVER + DRIVERS += drivers/rage.o + ifdef INCLUDE_RAGE_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_RAGE_DRIVER_TEST + endif +endif +ifdef INCLUDE_BANSHEE_DRIVER + VGA_DEFINES +=-DINCLUDE_BANSHEE_DRIVER + DRIVERS += drivers/banshee.o + ifdef INCLUDE_BANSHEE_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_BANSHEE_DRIVER_TEST + endif +endif +ifdef INCLUDE_SIS_DRIVER + VGA_DEFINES +=-DINCLUDE_SIS_DRIVER + DRIVERS += drivers/sis.o + ifdef INCLUDE_SIS_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_SIS_DRIVER_TEST + endif +endif +ifdef INCLUDE_I740_DRIVER + VGA_DEFINES +=-DINCLUDE_I740_DRIVER + DRIVERS += drivers/i740.o + ifdef INCLUDE_I740_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_I740_DRIVER_TEST + endif +endif +ifdef INCLUDE_I810_DRIVER + VGA_DEFINES +=-DINCLUDE_I810_DRIVER + DRIVERS += drivers/i810.o + ifdef INCLUDE_I810_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_I810_DRIVER_TEST + endif +endif +ifdef INCLUDE_LAGUNA_DRIVER + VGA_DEFINES +=-DINCLUDE_LAGUNA_DRIVER + DRIVERS += drivers/laguna.o + ifdef INCLUDE_LAGUNA_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_LAGUNA_DRIVER_TEST + endif +endif +ifdef INCLUDE_ET6000_DRIVER + VGA_DEFINES += -DINCLUDE_ET6000_DRIVER + DRIVERS += drivers/et6000.o + ifdef INCLUDE_ET6000_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_ET6000_DRIVER_TEST + endif +endif +ifdef INCLUDE_NEO_DRIVER + VGA_DEFINES += -DINCLUDE_NEO_DRIVER + DRIVERS += drivers/neo.o + ifdef INCLUDE_NEO_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_NEO_DRIVER_TEST + endif +endif +ifdef INCLUDE_FBDEV_DRIVER + VGA_DEFINES += -DINCLUDE_FBDEV_DRIVER + DRIVERS += drivers/fbdev.o + ifdef INCLUDE_FBDEV_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_FBDEV_DRIVER_TEST + endif +endif +ifdef INCLUDE_RENDITION_DRIVER + VGA_DEFINES += -DINCLUDE_RENDITION_DRIVER + DRIVERS += drivers/rendition.o + ifdef INCLUDE_RENDITION_DRIVER_TEST + VGA_DEFINES += -DINCLUDE_RENDITION_DRIVER_TEST + endif +endif + +# DYNAMIC is used by both ET drivers. +ifdef DYNAMIC + ifdef INCLUDE_ET4000_DRIVER + DEFINES += -DDYNAMIC + endif +endif + +# defines for ramdac.c, ramdac.h (and files including it) only. +ifdef INCLUDE_NORMAL_DAC + RAMDAC_DEFINES += -DINCLUDE_NORMAL_DAC + ifdef INCLUDE_NORMAL_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_NORMAL_DAC_TEST + endif +endif +ifdef INCLUDE_S3_SDAC_DAC + RAMDAC_DEFINES += -DINCLUDE_S3_SDAC_DAC + ifdef INCLUDE_S3_SDAC_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_S3_SDAC_DAC_TEST + endif +endif +ifdef INCLUDE_S3_GENDAC_DAC + RAMDAC_DEFINES += -DINCLUDE_S3_GENDAC_DAC + ifdef INCLUDE_S3_GENDAC_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_S3_GENDAC_DAC_TEST + endif +endif +ifdef INCLUDE_S3_TRIO64_DAC + RAMDAC_DEFINES += -DINCLUDE_S3_TRIO64_DAC + ifdef INCLUDE_S3_TRIO64_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_S3_TRIO64_DAC_TEST + endif +endif +ifdef INCLUDE_SIERRA_DAC + RAMDAC_DEFINES += -DINCLUDE_SIERRA_DAC + ifdef INCLUDE_SIERRA_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_SIERRA_DAC_TEST + endif +endif +ifdef INCLUDE_SC15025_DAC + RAMDAC_DEFINES += -DINCLUDE_SC15025_DAC + ifdef INCLUDE_SC15025_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_SC15025_DAC_TEST + endif +endif +ifdef INCLUDE_ATT20C490_DAC + RAMDAC_DEFINES += -DINCLUDE_ATT20C490_DAC + ifdef INCLUDE_ATT20C490_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_ATT20C490_DAC_TEST + endif +endif +ifdef INCLUDE_ATT20C498_DAC + RAMDAC_DEFINES += -DINCLUDE_ATT20C498_DAC + ifdef INCLUDE_ATT20C498_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_ATT20C498_DAC_TEST + endif +endif +ifdef INCLUDE_ICW_DAC + RAMDAC_DEFINES += -DINCLUDE_ICW_DAC + ifdef INCLUDE_ICW_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_ICW_DAC_TEST + endif +endif +ifdef INCLUDE_IBMRGB52x_DAC + RAMDAC_DEFINES += -DINCLUDE_IBMRGB52x_DAC + ifdef INCLUDE_IBMRGB52x_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_IBMRGB52x_DAC_TEST + endif +endif +ifdef INCLUDE_SC1148X_DAC + RAMDAC_DEFINES += -DINCLUDE_SC1148X_DAC + ifdef INCLUDE_SC1148X_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_SC1148X_DAC_TEST + endif +endif +ifdef INCLUDE_ICS_GENDAC_DAC + RAMDAC_DEFINES += -DINCLUDE_ICS_GENDAC_DAC + ifdef INCLUDE_ICS_GENDAC_DAC_TEST + RAMDAC_DEFINES += -DINCLUDE_ICS_GENDAC_DAC_TEST + endif +endif + +ALLOBJS = $(MODULES) $(MOUSE) $(JOYSTICK) $(KEYBOARD) $(RAMDAC) $(CLOCKCHIP) $(DRIVERS) + +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.c.s: + $(CC) $(CFLAGS) -S -o $*.s $< + +.PHONY: all dep depadd clean install FORCE + + + +ifeq (a.out, $(TARGET_FORMAT)) + +all: libvga.a + +else + +all: libvga.so.$(VERSION) + +# These rules are for ELF only. +libvga.so.$(VERSION): $(ALLOBJS) + $(CC) -shared -Wl,-soname,libvga.so.$(MAJOR_VER) \ + -Xlinker --retain-symbols-file -Xlinker ../src/exports \ + -Wl,-Bsymbolic -o libvga.so.$(VERSION) $(ALLOBJS) -lm + +$(sharedlibdir)/libvga.so.$(VERSION): libvga.so.$(VERSION) + $(INSTALL_SHLIB) $< $(sharedlibdir)/$< + -ldconfig + +install: $(sharedlibdir)/libvga.so.$(VERSION) + +endif + +libvga.a: $(ALLOBJS) + rm -f libvga.a + $(AR) rcs libvga.a $(ALLOBJS) + +libvgagl.a: FORCE + make -f $(srcdir)/gl/Makefile $@ srcdir="$(srcdir)" DLLFLAGS="$(DLLFLAGS)" + +svgalib_helper.h: + @ln -sf ../kernel/svgalib_helper/svgalib_helper.h ../src + +vga.o: vga.c + $(CC) $(CFLAGS) $(VGA_DEFINES) -c -o $@ $< + +#lrmi must NOT be compiled as -fPIC +lrmi.o: lrmi.c + $(CC) $(CFLAGS:-fPIC=) -c -o $@ $< + +$(RAMDAC): %.o: %.c + $(CC) $(CFLAGS) $(RAMDAC_DEFINES) -c -o $@ $< + +drivers/s3.o drivers/ark.o: %.o: %.c + $(CC) $(CFLAGS) $(RAMDAC_DEFINES) -c -o $@ $< + +nucleus.o: %.o: %.c + $(CC) $(CFLAGS) $(RAMDAC_DEFINES) -c -o $@ $< scitech.o + +$(MODULES): .depend.src + +dep: + rm -f .depend.src + make .depend.src + +.depend.src: + @ln -sf ../kernel/svgalib_helper/svgalib_helper.h ../src + echo '# Module dependencies' >>.depend.src + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/src/%.c,$(MODULES)) >>.depend.src + echo '# Mouse dependencies' >>.depend.src + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/src/%.c,$(MOUSE)) >.depend.src.mouse + sed 's#^\(.*\.o\):#mouse/\1:#g' <.depend.src.mouse >>.depend.src + rm -f .depend.src.mouse + echo '# Joystick dependencies' >>.depend.src + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/src/%.c,$(JOYSTICK)) >.depend.src.joystick + sed 's#^\(.*\.o\):#joystick/\1:#g' <.depend.src.joystick >>.depend.src + rm -f .depend.src.joystick + echo '# Keyboard dependencies' >>.depend.src + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/src/%.c,$(KEYBOARD)) >.depend.src.keyboard + sed 's#^\(.*\.o\):#keyboard/\1:#g' <.depend.src.keyboard >>.depend.src + rm -f .depend.src.keyboard + echo '# Driver dependencies' >>.depend.src + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/src/%.c,$(DRIVERS)) >>.depend.src + echo '# Ramdac dependencies' >>.depend.src + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/src/%.c,$(RAMDAC)) >.depend.src.ramdac + sed 's#^\(.*\.o\):#ramdac/\1:#g' <.depend.src.ramdac >>.depend.src + rm -f .depend.src.ramdac + echo '# Clockchip dependencies' >>.depend.src + $(CC) $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/src/%.c,$(CLOCKCHIP)) >.depend.src.clockchip + sed 's#^\(.*\.o\):#clockchip/\1:#g' <.depend.src.clockchip >>.depend.src + rm -f .depend.src.clockchip + +clean: + rm -f .depend.src *~ *.o mouse/*.o keyboard/*.o mouse/*~ keyboard/*~ \ + ramdac/*.o clockchip/*.o ramdac/*~ clockchip/*~ \ + libvga.a libvga.so.$(VERSION) *.bak */*.bak */*.orig *.orig \ + svgalib_helper.h + +FORCE: # dummy target. + +# +# include a dependency file if one exists +# +ifeq (.depend.src,$(wildcard .depend.src)) +include .depend.src +endif diff --git a/src/accel.c b/src/accel.c new file mode 100644 index 0000000..7a416bb --- /dev/null +++ b/src/accel.c @@ -0,0 +1,20 @@ + +#include "vga.h" +#include "timing.h" +#include "accel.h" + + +int __svgalib_accel_screenpitch; +int __svgalib_accel_bytesperpixel; +int __svgalib_accel_screenpitchinbytes; +int __svgalib_accel_mode; +int __svgalib_accel_bitmaptransparency; + +void __svgalib_InitializeAcceleratorInterface(ModeInfo * modeinfo) +{ + __svgalib_accel_screenpitch = modeinfo->lineWidth / modeinfo->bytesPerPixel; + __svgalib_accel_bytesperpixel = modeinfo->bytesPerPixel; + __svgalib_accel_screenpitchinbytes = modeinfo->lineWidth; + __svgalib_accel_mode = BLITS_SYNC; + __svgalib_accel_bitmaptransparency = 0; +} diff --git a/src/accel.h b/src/accel.h new file mode 100644 index 0000000..e2d2310 --- /dev/null +++ b/src/accel.h @@ -0,0 +1,204 @@ + +#ifndef ACCEL_H +#define ACCEL_H + +/* + * New accelerator interface sketch. + * As of svgalib 1.23, this isn't used yet. + * + * The main goal is to define functions that can be used as part of + * certain kinds of interesting graphical operations (not necessarily + * interesting primitives on their own). Obvious useful primitives + * in their own are FillBox, ScreenCopy, DrawHLineList (solid polygon), + * DrawLine. + * + * An interesting purpose is the fast drawing of color bitmaps, both + * straight and transparent (masked, certain color not written). For + * masked bitmaps ("sprites"), there is a number of possible methods, + * the availability of which depends on the chips. Caching in + * non-visible video memory is often useful. One way is to use a + * transparency color compare feature of a BITBLT chip, either + * transferring the image from system memory or cached in video memory. + * If transparency compare is not available, it may be possible to first + * clear (zeroes) the mask in the destination area, and then use BITBLT + * raster-operation to OR the image into the destination (this requires + * the mask color to be 0). A higher level (library) interface should + * control this kind of operation. + */ + + +typedef struct { +/* Graphics mode-independent fields. */ + int flags; + /* + * The following fields define lists of linewidths in pixel + * units that the accelerator supports for each depth. Each + * list is terminated by 0. These fields are only relevant + * if the ACCELERATE_ANY_LINEWIDTH flag is not set. + */ + int *supportedLineWidths8bpp; + int *supportedLineWidths16bpp; + int *supportedLineWidths24bpp; + int *supportedLineWidths32bpp; + /* + * The following function sets up the accelerator interface for + * pixels of size bpp and scanline width of width_in_pixels. + */ + void (*initAccelerator) (int bpp, int width_in_pixels); +/* Fields that are initialized after setting a graphics mode. */ + /* + * The following field defines which accelerated primitives are + * available in the selected graphics mode. + */ + int operations; + /* + * The following field defines which accelerated primitives are + * available with special raster-ops in the selected graphics mode. + */ + int ropOperations; + /* + * The following field defines which special raster operations are + * available in the selected graphics mode. + */ + int ropModes; + /* + * The following field defines which accelerated primitives are + * available with transparency in the selected graphics mode. + */ + int transparencyOperations; + /* + * The following field defines which special transparency modes are + * available in the selected graphics mode. + */ + int transparencyModes; +/* Acceleration primitive functions. */ + void (*FillBox) (int x, int y, int width, int height); + void (*ScreenCopy) (int x1, int y1, int x2, int y2, int width, + int height); + void (*PutImage) (int x, int y, int width, int height, void *image); + void (*DrawLine) (int x1, int y1, int x2, int y2); + void (*SetFGColor) (int c); + void (*SetBGColor) (int c); + void (*SetRasterOp) (int rop); + void (*SetTransparency) (int mode, int color); + void (*PutBitmap) (int x, int y, int w, int h, void *bitmap); + void (*ScreenCopyBitmap) (int x1, int y1, int x2, int y2, int width, + int height); + void (*DrawHLineList) (int ymin, int n, int *xmin, int *xmax); + void (*SetMode) (void); + void (*Sync) (void); +} AccelSpecs; + +/* Flags: */ +/* Every programmable scanline width is supported by the accelerator. */ +#define ACCELERATE_ANY_LINEWIDTH 0x1 +/* Bitmap (1-bit-per-pixel) operations support transparency (bit = 0). */ +#define BITMAP_TRANSPARENCY 0x2 +/* For bitmaps (1 bpp) stored in video memory, the most-significant bit */ +/* within a byte is the leftmost pixel. */ +#define BITMAP_ORDER_MSB_FIRST 0x4 + +/* Operation flags: see vga.h. */ + +/* + * Acceleration primitive description: + * + * FillBox Simple solid fill of rectangle with a single color. + * ScreenCopy Screen-to-screen BLT (BitBlt), handles overlapping areas. + * PutImage Straight image transfer (PutImage). Advantage over + * framebuffer writes is mainly in alignment handling. + * DrawLine Draw general line ("zero-pixel wide"). + * SetFGColor Set foreground color for some operations (FillBox, DrawLine, + * PutBitmap). + * SetBGColor Set background color for some operations (PutBitmap). + * SetRasterOp Set the raster operation for drawing operations that support + * raster ops as defined in ropOperations. + * SetTransparency + * Set the transparency mode for some operations (enable/disable, + * and the transparency pixel value). Source pixels equal to + * the transparency color are not written. Operations supported + * are ScreenCopy and PutImage, subject to their flags being set + * in the transparencyOperations field. + * PutBitmap Color-expand a bit-wise (bit-per-pixel, each byte is 8 pixels) + * image to the screen with the foreground and background color. + * The lowest order bit of each byte is leftmost on the screen + * (contrary to the VGA tradition), irrespective of the bitmap + * bit order flag. Each scanline is aligned to a multiple of + * 32-bits. + * If the transparency mode is enabled (irrespective of the + * transparency color), then bits that are zero in the bitmap + * are not written (the background color is not used). + * ScreenCopyBitmap + * Color-expand bit-wise bitmap stored in video memory + * (may also support transparency). + * DrawHLineList + * Draw a set of horizontal line segments from top to bottom + * in the foreground color. + * SetMode Set the acceleration mode, e.g. let blits go + * on in the background (program must not access video memory + * when blits can be running). + * Sync Wait for any background blits to finish. + * + * It is not the intention to have alternative non-accelerated routines + * available for each possible operation (library functions should + * take advantage of accelerator functions, rather than the accelerator + * functions being primitives on their own right). If something like + * bit-order reversal is required to implement an accelerated primitive, + * it's still worthwhile if it's still much quicker than similar + * unaccelerated functionality would be. + * + * Strategy for accelerator registers in accelerated functions: + * Foreground color, background color, raster operation and transparency + * compare setting are preserved, source and destination pitch is always + * set to screen pitch (may be temporarily changed and then restored). + */ + + +/* Macros. */ + +#define BLTBYTEADDRESS(x, y) \ + (y * __svgalib_accel_screenpitchinbytes + x * __svgalib_accel_bytesperpixel) + +#define BLTPIXADDRESS(x, y) \ + (y * __svgalib_accel_screenpitch + x) + +#define SIGNALBLOCK \ + { \ + sigset_t sig2block; \ + sigemptyset(&sig2block); \ + sigaddset(&sig2block,SIGINT); \ + sigprocmask(SIG_BLOCK, &sig2block, (sigset_t *)NULL); \ + } + +#define SIGNALUNBLOCK \ + { \ + sigset_t sig2block; \ + sigemptyset(&sig2block); \ + sigaddset(&sig2block,SIGINT); \ + sigprocmask(SIG_UNBLOCK, &sig2block, (sigset_t *)NULL);\ + } + +/* Variables defined in accel.c */ + +extern int __svgalib_accel_screenpitch; +extern int __svgalib_accel_bytesperpixel; +extern int __svgalib_accel_screenpitchinbytes; +extern int __svgalib_accel_mode; +extern int __svgalib_accel_bitmaptransparency; + +/* + * The following function should be called when the mode is set. + * This is currently done in the setmode driver functions. + */ + +void __svgalib_InitializeAcceleratorInterface(ModeInfo * modeinfo); + +/* + * The following driver function fills in available accelerator + * primitives for a graphics mode (operations etc.). It could be part + * of the setmode driver function. + * + * void initOperations( AccelSpecs *accelspecs, int bpp, int width_in_pixels ); + */ + +#endif diff --git a/src/clockchip/clockchip.h b/src/clockchip/clockchip.h new file mode 100644 index 0000000..0d13899 --- /dev/null +++ b/src/clockchip/clockchip.h @@ -0,0 +1,32 @@ +/* + * clockchip.h + */ + +/* ClockChipMethods type. */ + +typedef struct { + /* + * The following function initializes the ClockChip; it is usually + * called once after detection. + */ + void (*initialize) (CardSpecs * cardspecs, DacMethods * DAC); + /* + * ClockChip functions that override DAC methods. + */ + void (*saveState) (unsigned char *regs); + void (*restoreState) (const unsigned char *regs); + void (*initializeState) (unsigned char *regs, int bpp, int colormode, + int pixelclock); + /* + * Original DAC save and restore functions, + * to be called before clock manipulation. + */ + void (*DAC_saveState) (unsigned char *regs); + void (*DAC_restoreState) (const unsigned char *regs); + void (*DAC_initializeState) (unsigned char *regs, int bpp, int colormode, + int pixelclock); + int TextFrequency; + int DAC_stateSize; +} ClockChipMethods; + +extern ClockChipMethods __svgalib_I2061A_clockchip_methods; diff --git a/src/clockchip/icd2061a.c b/src/clockchip/icd2061a.c new file mode 100644 index 0000000..f095df3 --- /dev/null +++ b/src/clockchip/icd2061a.c @@ -0,0 +1,283 @@ +/* + * icd2061a.c + * + * support for the ICD 2061A programmable clockchip and compatibles + * outside of the DAC + * + * Rev history: + * Andreas Arens Dec 95: Created + * + * Andreas Arens Feb 15 1996: A few minor fixes + */ + +#include "timing.h" +#include "libvga.h" +#include "ramdac/ramdac.h" +#include "clockchip.h" +#include "driver.h" +#include "vga.h" + +/* + * ATTENTION: The ICD 2061A does not support reading of the currently selected + * pixelclock. XFree86 also fails to restore this value correctly, but always + * estores a 45 MHz pixelclock. My standard text mode (132x25) uses 40 MHz, + * which is the value selected here. + * You can use the SVGATextMode-1.0 'clockprobe' tool right after boot to + * determine the value used with your card and modify here, but since 40 MHz + * is the VESA suggested pixelclock for a 70 Hz 132x25 mode, the value here + * seems fine. Note that 80xXX modes use 25 or 28 MHz clocks, which are fixed + * and not affected by this. This might not be true for Diamond boards using + * the DCS2824-0 clockchip, which is an ICD 2061A clone. + */ +#define I2061A_DEFAULT_TEXT_FREQUENCY (40000L) /* kHz */ + +/* + * Clockchip code is derived from I2051Aalt.c in XFree86/common_hw which + * in turn is derived from code available from the STB bulletin board. + * A number of modifications have been made to fit this into SVGAlib. + */ + +#define I2061A_CRYSTAL_FREQUENCY (14.31818 * 2.0) + +static double I2061A_range[15] = +{50.0, 51.0, 53.2, 58.5, 60.7, 64.4, 66.8, 73.5, + 75.6, 80.9, 83.2, 91.5, 100.0, 120.0, 120.0000001}; + +static int I2061A_SelectClock(int frequency) + /* in KHz */ +{ + unsigned int m; + int i; + double freq, fvco; + double dev, devx; + double delta, deltax; + double f0; + unsigned int p, q; + unsigned int bestp = 0, bestq = 0, bestm = 0, besti = 0; + + freq = ((double) frequency) / 1000.0; + if (freq > I2061A_range[13]) + freq = I2061A_range[13]; + else if (freq < 7.0) + freq = 7.0; + + /* + * Calculate values to load into ICD 2061A clock chip to set frequency + */ + delta = 999.0; + dev = 999.0; + + for (m = 0; m < 8; m++) { + fvco = freq * (1 << m); + if (fvco < 50.0 || fvco > 120.0) + continue; + + f0 = fvco / I2061A_CRYSTAL_FREQUENCY; + + for (q = 14; q <= 71; q++) { /* q={15..71}:Constraint 2 on page 14 */ + p = (int) (f0 * q + 0.5); + if (p < 4 || p > 130) /* p={4..130}:Constraint 5 on page 14 */ + continue; + deltax = (double) (p) / (double) (q) - f0; + if (deltax < 0) + deltax = -deltax; + if (deltax <= delta) { + for (i = 13; i >= 0; i--) + if (fvco >= I2061A_range[i]) + break; + devx = (fvco - (I2061A_range[i] + I2061A_range[i + 1]) / 2) / fvco; + if (devx < 0) + devx = -devx; + if (deltax < delta || devx < dev) { + delta = deltax; + dev = devx; + bestp = p; + bestq = q; + bestm = m; + besti = i; + } + } + } + } + return ((((((int) besti << 7) | (bestp - 3)) << 3) | bestm) << 7) | (bestq - 2); +} + +static int I2061A_GetClock(int dwv) +{ + int clock_q = (dwv & 0x7f) + 2; + int clock_m = (dwv >> 7) & 7; + int clock_p = ((dwv >> 10) & 0x7f) + 3; + double fvco; + + fvco = I2061A_CRYSTAL_FREQUENCY / (1 << clock_m); + return (int) (((fvco * clock_p) / clock_q) * 1000); +} + +/* needs some delay for really fast cpus */ +#define wrt_clk_bit(v) port_out_r(MIS_W, v), (void)port_in(crtcaddr), (void)port_in(crtcaddr) + +/* ATTENTION: This assumes CRTC registers and S3 registers to be UNLOCKED! */ +static void I2061A_init_clock(unsigned int setup) +{ + unsigned char nclk[2], clk[2]; + unsigned short restore42; + unsigned short oldclk; + unsigned short bitval; + int i; + unsigned char c; + unsigned short crtcaddr = (port_in(MIS_R) & 0x01) ? CRT_IC : CRT_IM; + + oldclk = port_in(MIS_R); + + port_out_r(crtcaddr, 0x42); + restore42 = port_in(crtcaddr + 1); + + port_outw_r(SEQ_I, 0x0100); + + port_out_r(SEQ_I, 1); + c = port_in(SEQ_D); + port_out_r(SEQ_D, 0x20 | c); + + port_out_r(crtcaddr, 0x42); + port_out_r(crtcaddr + 1, 0x03); + + port_outw_r(SEQ_I, 0x0300); + + nclk[0] = oldclk & 0xF3; + nclk[1] = nclk[0] | 0x08; + clk[0] = nclk[0] | 0x04; + clk[1] = nclk[0] | 0x0C; + + port_out_r(crtcaddr, 0x42); + (void) port_in(crtcaddr + 1); + + port_outw_r(SEQ_I, 0x0100); + + wrt_clk_bit(oldclk | 0x08); + wrt_clk_bit(oldclk | 0x0C); + for (i = 0; i < 5; i++) { + wrt_clk_bit(nclk[1]); + wrt_clk_bit(clk[1]); + } + wrt_clk_bit(nclk[1]); + wrt_clk_bit(nclk[0]); + wrt_clk_bit(clk[0]); + wrt_clk_bit(nclk[0]); + wrt_clk_bit(clk[0]); + for (i = 0; i < 24; i++) { + bitval = setup & 0x01; + setup >>= 1; + wrt_clk_bit(clk[1 - bitval]); + wrt_clk_bit(nclk[1 - bitval]); + wrt_clk_bit(nclk[bitval]); + wrt_clk_bit(clk[bitval]); + } + wrt_clk_bit(clk[1]); + wrt_clk_bit(nclk[1]); + wrt_clk_bit(clk[1]); + + port_out_r(SEQ_I, 1); + c = port_in(SEQ_D); + port_out_r(SEQ_D, 0xDF & c); + + port_out_r(crtcaddr, 0x42); + port_out_r(crtcaddr + 1, restore42); + + port_out_r(MIS_W, oldclk); + + port_outw_r(SEQ_I, 0x0300); + + vga_waitretrace(); + vga_waitretrace(); + vga_waitretrace(); + vga_waitretrace(); + vga_waitretrace(); + vga_waitretrace(); + vga_waitretrace(); /* 0.10 second delay... */ +} + +static int I2061A_match_programmable_clock(int desiredclock) +{ + int dvw; + + dvw = I2061A_SelectClock(desiredclock); + if (dvw) + return I2061A_GetClock(dvw); + return 0; +} + +static void I2061A_saveState(unsigned char *regs) +{ + int *dvwp; + + if (__svgalib_I2061A_clockchip_methods.DAC_saveState) + __svgalib_I2061A_clockchip_methods.DAC_saveState(regs); + + dvwp = (int *) (regs + __svgalib_I2061A_clockchip_methods.DAC_stateSize); + *dvwp = I2061A_SelectClock(__svgalib_I2061A_clockchip_methods.TextFrequency); +} + +static void I2061A_restoreState(const unsigned char *regs) +{ + unsigned int clknum = 2; + int *dvwp; + + if (__svgalib_I2061A_clockchip_methods.DAC_restoreState) + __svgalib_I2061A_clockchip_methods.DAC_restoreState(regs); + dvwp = (int *) (regs + __svgalib_I2061A_clockchip_methods.DAC_stateSize); + if (*dvwp) { + /* + * Write ICD 2061A clock chip - assumes S3 to be unlocked! + */ + I2061A_init_clock(((unsigned int) *dvwp) | (((int) clknum) << 21)); + } +} + +static void I2061A_initializeState(unsigned char *regs, int bpp, int colormode, int pixelclock) +{ + int *dvwp; + + if (__svgalib_I2061A_clockchip_methods.DAC_initializeState) + __svgalib_I2061A_clockchip_methods.DAC_initializeState(regs, bpp, colormode, pixelclock); + + dvwp = (int *) (regs + __svgalib_I2061A_clockchip_methods.DAC_stateSize); + + if (bpp > 16) + pixelclock *= 4; + else if (bpp > 8) + pixelclock *= 2; + + *dvwp = I2061A_SelectClock((int) pixelclock); +} + +/* This functions patches the DacMethod to route through the ClockChip Method */ +static void I2061A_init(CardSpecs * cardspecs, DacMethods * DAC) +{ + if (DAC && !__svgalib_I2061A_clockchip_methods.DAC_initializeState) { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using ICD2061A or compatible clockchip.\n"); + __svgalib_I2061A_clockchip_methods.DAC_initializeState = DAC->initializeState; + __svgalib_I2061A_clockchip_methods.DAC_saveState = DAC->saveState; + __svgalib_I2061A_clockchip_methods.DAC_restoreState = DAC->restoreState; + __svgalib_I2061A_clockchip_methods.DAC_stateSize = DAC->stateSize; + DAC->initializeState = I2061A_initializeState; + DAC->saveState = I2061A_saveState; + DAC->restoreState = I2061A_restoreState; + DAC->stateSize += sizeof(int); + cardspecs->matchProgrammableClock = I2061A_match_programmable_clock; + cardspecs->flags |= CLOCK_PROGRAMMABLE; + } +} + +ClockChipMethods __svgalib_I2061A_clockchip_methods = +{ + I2061A_init, + I2061A_saveState, + I2061A_restoreState, + I2061A_initializeState, + NULL, /* DAC function save area */ + NULL, + NULL, + I2061A_DEFAULT_TEXT_FREQUENCY, + 0, +}; diff --git a/src/config/default.keymap b/src/config/default.keymap new file mode 100644 index 0000000..16fb41c --- /dev/null +++ b/src/config/default.keymap @@ -0,0 +1,110 @@ +# This is a svgalib scancode conversion map generated by svgakeymap. +# Read the file README.keymap from the svgalib distribution for more info. +# +# Physical keyboard layout: /usr/lib/kbd/keytables/us.map.gz +# Program's expected keyboard layout: /usr/lib/kbd/keytables/us.map.gz +# +# physical_scancode program_scancode key_name +1 1 Escape +2 2 one +3 3 two +4 4 three +5 5 four +6 6 five +7 7 six +8 8 seven +9 9 eight +10 10 nine +11 11 zero +12 12 minus +13 13 equal +14 14 Delete +15 15 Tab +16 16 q +17 17 w +18 18 e +19 19 r +20 20 t +21 21 y +22 22 u +23 23 i +24 24 o +25 25 p +26 26 bracketleft +27 27 bracketright +28 28 Return +29 97 Control +30 30 a +31 31 s +32 32 d +33 33 f +34 34 g +35 35 h +36 36 j +37 37 k +38 38 l +39 39 semicolon +40 40 apostrophe +41 41 grave +42 54 Shift +43 43 backslash +44 44 z +45 45 x +46 46 c +47 47 v +48 48 b +49 49 n +50 50 m +51 51 comma +52 52 period +53 53 slash +54 54 Shift +55 55 KP_Multiply +56 56 Alt +57 57 space +58 58 Caps_Lock +59 59 F1 +60 60 F2 +61 61 F3 +62 62 F4 +63 63 F5 +64 64 F6 +65 65 F7 +66 66 F8 +67 67 F9 +68 68 F10 +69 69 Num_Lock +70 70 Scroll_Lock +71 71 KP_7 +72 72 KP_8 +73 73 KP_9 +74 74 KP_Subtract +75 75 KP_4 +76 76 KP_5 +77 77 KP_6 +78 78 KP_Add +79 79 KP_1 +80 80 KP_2 +81 81 KP_3 +82 82 KP_0 +83 83 KP_Period +84 84 Last_Console +86 86 less +87 87 F11 +88 88 F12 +96 96 KP_Enter +97 97 Control +98 98 KP_Divide +99 99 Control_backslash +100 100 AltGr +101 101 Break +102 102 Find +103 103 Up +104 104 Prior +105 105 Left +106 106 Right +107 107 Select +108 108 Down +109 109 Next +110 110 Insert +111 111 Remove diff --git a/src/config/dvorak-us.keymap b/src/config/dvorak-us.keymap new file mode 100644 index 0000000..ed32e1c --- /dev/null +++ b/src/config/dvorak-us.keymap @@ -0,0 +1,110 @@ +# This is a svgalib scancode conversion map generated by svgakeymap. +# Read the file README.keymap from the svgalib distribution for more info. +# +# Physical keyboard layout: /usr/lib/kbd/keytables/dvorak.map.gz +# Program's expected keyboard layout: /usr/lib/kbd/keytables/us.map.gz +# +# physical_scancode program_scancode key_name +1 1 Escape +2 2 one +3 3 two +4 4 three +5 5 four +6 6 five +7 7 six +8 8 seven +9 9 eight +10 10 nine +11 11 zero +12 26 bracketleft +13 27 bracketright +14 14 Delete +15 15 Tab +16 40 apostrophe +17 51 comma +18 52 period +19 25 p +20 21 y +21 33 f +22 34 g +23 46 c +24 19 r +25 38 l +26 53 slash +27 13 equal +28 28 Return +29 97 Control +30 30 a +31 24 o +32 18 e +33 22 u +34 23 i +35 32 d +36 35 h +37 20 t +38 49 n +39 31 s +40 12 minus +41 41 grave +42 54 Shift +43 43 backslash +44 39 semicolon +45 16 q +46 36 j +47 37 k +48 45 x +49 48 b +50 50 m +51 17 w +52 47 v +53 44 z +54 54 Shift +55 55 KP_Multiply +56 56 Alt +57 57 space +58 58 Caps_Lock +59 59 F1 +60 60 F2 +61 61 F3 +62 62 F4 +63 63 F5 +64 64 F6 +65 65 F7 +66 66 F8 +67 67 F9 +68 68 F10 +69 69 Num_Lock +70 70 Scroll_Lock +71 71 KP_7 +72 72 KP_8 +73 73 KP_9 +74 74 KP_Subtract +75 75 KP_4 +76 76 KP_5 +77 77 KP_6 +78 78 KP_Add +79 79 KP_1 +80 80 KP_2 +81 81 KP_3 +82 82 KP_0 +83 83 KP_Period +84 84 Last_Console +86 86 less +87 87 F11 +88 88 F12 +96 96 KP_Enter +97 97 Control +98 98 KP_Divide +99 99 Control_backslash +100 100 AltGr +101 101 Break +102 102 Find +103 103 Up +104 104 Prior +105 105 Left +106 106 Right +107 107 Select +108 108 Down +109 109 Next +110 110 Insert +111 111 Remove diff --git a/src/config/et4000.regs b/src/config/et4000.regs new file mode 100644 index 0000000..51a2550 --- /dev/null +++ b/src/config/et4000.regs @@ -0,0 +1,126 @@ + +/* ET4000 registers from SVGALIB 0.81 */ + +/* Define DAC_TYPE to force the DAC type used in the ET4000 driver. If it */ +/* is not defined, the driver tries to autodetect the DAC type which may go */ +/* wrong. */ + +/* Use the following values: + 0: Ordinary DAC + 1: Sierra SC11486 (32k) + 3: Sierra 32k/64k + 5: SS2410 15/24bit DAC + 9: AT&T 20c491/2 (32k/64k/24bit) + 17: Acumos ADAC (Cirrus Logic DAC) + 33: Sierra 15025/6 24-bit DAC + */ + +#define DAC_TYPE 0 + +/* unsupported modes */ +#define g320x200x64K_regs DISABLE_MODE +#define g320x200x16M_regs DISABLE_MODE +#define g800x600x16_regs DISABLE_MODE +#define g1024x768x16_regs DISABLE_MODE +#define g1280x1024x16_regs DISABLE_MODE + + +/* Got this mode from someone's tseng3.exe dump. */ +/* ET4000 HiColor BIOS mode 0x13 -- 320x200x32K */ +/* Video timing: Vertical frequency : 70.3Hz + Horizontal frequency : 31.6KHz */ +static unsigned char g320x200x32K_regs[73] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x50, 0x60, 0x96, 0xB9, 0xAB, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x00, 0x00, 0x28, 0x00, 0x08, 0x00, 0x43, 0x0F, 0x00, 0xFC, 0x00, 0x00, + 0x00 +}; + +/* ET4000 BIOS mode 2Eh - 640x480x256 */ +static unsigned char g640x480x256_regs[73] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x50, 0x60, 0xE7, 0x04, 0xAB, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x00, 0x00, 0x28, 0x00, 0x08, 0x00, 0x03, 0x0F, 0x00, 0xFC, 0x00, 0x00, + 0x00 +}; + +/* ET4000 BIOS mode 30h - 800x600x256 */ +static unsigned char g800x600x256_regs[73] = +{ + 0x7F, 0x63, 0x64, 0x02, 0x6A, 0x1D, 0x77, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5D, 0x8F, 0x57, 0x64, 0x60, 0x5B, 0x74, 0xAB, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x00, 0x00, 0x28, 0x00, 0x0A, 0x00, 0x03, 0x0F, 0x00, 0xFC, 0x00, 0x00, + 0x00 +}; + +/* ET4000 BIOS mode 38h - 1024x768x256 */ +static unsigned char g1024x768x256_regs[73] = +{ + 0xA1, 0x7F, 0x80, 0x04, 0x89, 0x99, 0x26, 0xFD, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x8A, 0xFF, 0x80, 0x60, 0x04, 0x22, 0xAB, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xEB, + 0x00, 0x00, 0x28, 0x00, 0x08, 0x00, 0x03, 0x0F, 0x00, 0xBC, 0x00, 0x00, + 0x00 +}; + +static unsigned char g800x600x32K_regs[73] = +{ + 0xF9, 0xC7, 0xC9, 0x9B, 0xCF, 0x8F, 0x78, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5C, 0x8E, 0x57, 0xC8, 0x60, 0x5B, 0x75, 0xAB, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xEF, + 0x00, 0x00, 0x28, 0x00, 0x08, 0x00, 0x03, 0x0F, 0x00, 0xBC, 0x00, 0x00, + 0x06 +}; +#define g800x600x64K_regs g800x600x32K_regs + +static unsigned char g640x480x16M_regs[73] = +{ + 0x27, 0xEF, 0xF2, 0x88, 0xF8, 0x98, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x0C, 0xDF, 0xF0, 0x60, 0xE7, 0x04, 0xAB, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xEF, + 0x00, 0x00, 0x28, 0x00, 0x0A, 0x00, 0x03, 0x0F, 0x01, 0xBC, 0x00, 0x00, + 0x00 +}; + +static unsigned char g640x480x32K_regs[73] = +{ + 0xC3, 0x9F, 0xA1, 0x85, 0xA7, 0x1F, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0xA0, 0x60, 0xE7, 0x04, 0xAB, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x00, 0x00, 0x28, 0x00, 0x08, 0x00, 0x03, 0x0F, 0x00, 0xBC, 0x00, 0x00, + 0x00 +}; +#define g640x480x64K_regs g640x480x32K_regs diff --git a/src/config/libvga.config b/src/config/libvga.config new file mode 100644 index 0000000..5c28f6d --- /dev/null +++ b/src/config/libvga.config @@ -0,0 +1,449 @@ +# Configuration file for svgalib. Default location is /etc/vga. +# Other config file locations: ~/.svgalibrc +# where SVGALIB_CONFIG_FILE points +# Lines starting with '#' are ignored. + +# These needs to be before "chipset" line, since chipset option open +# the device. + +# Specify the device file for the svgalib kernel helper +# /dev/svga is the default. + +Helper /dev/svga + +# NoHelper # Disable use of the helper-kernelmodule (/dev/svga) and + # fallback to old ioperm/iopl and /dev/mem use. + +# If you have two vga cards with the same pci vendor id, svgalib will try +# to use the first one, even if the second one is active. In that case, +# in NoHelper mode use PCIStart to force starting the search for a vga card +# only at a specific bus and device number. For example, an AGP card is +# usually on bus 1, while pci is on bus 0, so to use the AGP card, uncomment: + +# PCIStart 1 0 + +# The helper-kernelmodule numbers videocards 1 till 16, in this case you can +# use Device to force using a specific card. For example, to force using +# the second card (as numbered by the helper-kernelmodule) uncomment: + +# Device 2 + + +# Have a deep look at README.config to see what can do here (especially +# for mach32). + +# Mouse type: + +# mouse Microsoft # Microsoft +# mouse MouseSystems # Mouse Systems +# mouse MMSeries # Logitech MM Series +# mouse Logitech # Logitech protocol (old, newer mice use Microsoft protocol) +# mouse Busmouse # Bus mouse +# mouse PS2 # PS/2 mouse +# mouse MouseMan # Logitech MouseMan +# mouse Spaceball # Spacetec Spaceball +# mouse IntelliMouse # Microsoft IntelliMouse or Logitech MouseMan+ on serial port +# mouse IMPS2 # Microsoft IntelliMouse or Logitech MouseMan+ on PS/2 port +# mouse pnp # plug'n'pray +# mouse WacomGraphire # Wacom Graphire tablet/mouse +# mouse DRMOUSE4DS # Digital Research double-wheeled mouse +# mouse ExplorerPS2 # Microsoft Intellimouse Explorer PS/2 +# mouse none # None + +mouse unconfigured + +# (DEBIAN NOTE: the mouse used to default to microsoft, but this was changed +# to fix bug #13458. If your mouse used to work fine, you can simply change +# it back to read "microsoft" again. If you are careful to change *only that +# one word*, and not to add or remove extra whitespace, the package +# installation will continue to update this file without requiring user +# intervention because of a modified config file. +# This applies to all mouse types, not just microsoft.) + +# Mouse/keyboard customisation by 101 (Attila Lendvai). If you have any good +# ideas you can reach me at 101@kempelen.inf.bme.hu + +# mouse_accel_type normal # No acceleration while delta is less then + # threshold but delta is multiplied by + # mouse_accel_mult if more. Originally done by + # Mike Chapman mike@paranoia.com + +# mouse_accel_type power # The acceleration factor is a power function + # of delta until it reaches m_accel_mult. It + # starts from the coordinate + # [1, 1 + m_accel_offset] and goes to + # [m_accel_thresh, m_accel_mult]. If delta + # is bigger then m_accel_thresh it is a plain + # constant (m_accel_mult). It is the f(delta) + # function with which the delta itself will be + # multiplied. m_accel_offset is 1 by default, + # so for delta = 1 the accelerated delta will + # remain 1 (You don't lose resolution). The + # starting point of the f(delta) function + # might be moved along the Y axis up/down with + # m_accel_offset thus defining the initial + # minimum acceleration (for delta = 1). + # Basically it's like the normal mode but the + # acceleration factor grows as you move your + # mouse faster and faster, not just turns in + # and out. Threshold is the point from where + # the f(delta) function gets linear. + # This is the one I use for *uaking... =) + +mouse_accel_type off # No comment... + + +mouse_accel_mult 60 # This is the number with which delta will + # be multiplied. Basically it's the number + # that defines how big the acceleration will + # be + +mouse_accel_thresh 4 # This is the threshold. See description by + # power + +mouse_accel_power 0.8 # This is the second parameter of the power + # function used in power mode. Used only by + # the power mode + +mouse_accel_offset 30 # This is the offset of the starting point + # on the Y axis. With this you can define the + # number that will multiply delta = 1 so it's + # the initial acceleration. + +# mouse_accel_maxdelta 600 # This is an upper limit for delta after + # the acceleration was applied + +# mouse_maxdelta 30 # This is an upper limit for the delta + # before the acceleration. With this one you + # can limit the biggest valid delta that + # comes from the mouse. + +# mouse_force # Force parameters even if they seem strange + # By default svgalib prints an error if any + # of the numbers are somhow out of the + # reasonable limit, (Like a negative mult :) + # and uses the default that's in vgamouse.h + +# Usually /dev/mouse will be a link to the mouse device. +# However, esp. with the Spacetec Spaceball you may +# want to specify a different device for svgalib to use + +# mdev /dev/ttyS0 # mouse is at /dev/ttyS0 + +# Some multiprotocol mice will need one of the following: + +# setRTS # set the RTS wire. +# clearRTS # clear the RTS wire. +# leaveRTS # leave the RTS wire alone (default) (Wire is usually set) +# setDTR # set the DTR wire. +# clearDTR # clear the DTR wire. +# leaveDTR # leave the DTR wire alone (default) (Wire is usually set) + +# On mice such as the Microsoft IntelliMouse and Logitech MouseMan+, turning +# the wheel rotates the mouse around the X axis. mouse_wheel_steps controls +# how many steps make up a full 360-degree turn and thus how much rotation +# occurs with each step. The default is 18 steps (20 degrees per step), the +# real-world value for the IntelliMouse. Adjust it to match your mouse or to +# suit your preferences; a negative number reverses the direction and zero +# disables rotation. + +mouse_wheel_steps 18 # For MS IntelliMouse (default) +# mouse_wheel_steps 24 # For Logitech FirstMouse+ +# mouse_wheel_steps -18 # Reverses direction +# mouse_wheel_steps 0 # Disables rotation + +# mouse_fake_kbd_event sends a fake keyboard event to the program when the +# wheel on a Microsoft IntelliMouse, Logitech MouseMan+, or similar wheel +# mouse is turned. This can be useful for programs that do not recognize the +# Z axis, but only works with some programs that use raw keyboard. +# The format is: +# +# mouse_fake_kbd_event upscancode downscancode +# +# The up and down scancodes are the scancodes of the keys to simulate when +# the wheel is turned up and down, respectively. +# +# Scancodes can be specified numerically or symbolically; the symbolic names +# are determined by the keymap (see below), if no keymap is loaded the default +# is the standard US QWERTY keyboard with the following names available: +# letters (a-z), numbers (zero-nine), function keys (F1-F12), the keypad +# numbers (KP_0-KP_9) and other keys (KP_Multiply, KP_Subtract, KP_Add, +# KP_Period, KP_Enter, and KP_Divide), and the following - minus, equal, +# Delete, Tab, bracketleft, bracketright, Return, Control, semicolon, +# apostrophe, grave, Shift, backslash, comma, period, slash, Shift, Alt, space, +# Caps_Lock, Num_Lock, Scroll_Lock, Last_Console, less, Control_backslash, +# AltGr, Break, Find, Up, Prior, Left, Right, Select, Down, Next, Insert, +# and Remove. +# +# Note that this option has no effect unless the IntelliMouse or IMPS2 mouse +# type is used (see above). Also note that the simulated keypresses are +# instantaneous, so they cannot be used for functions that require a key to +# be held down for a certain length of time. + +# This example simulates a press of the left bracket ([) when the wheel is +# turned up and a press of the right bracket (]) when the wheel is turned +# down (good for selecting items in Quake II): +# mouse_fake_kbd_event bracketleft bracketright + +# Keyboard config: + +# kbd_keymap allows you to use an alternate keyboard layout with programs that +# use raw keyboard support by translating scancodes from the desired layout to +# their equivalents in the layout expected by the program. This option has no +# affect on programs that do not use raw keyboard. +# +# Keymap files to convert between any two arbitrary keyboard layouts can be +# generated with the svgakeymap utility, but there are limitations to the +# translations that can be performed. Read the file README.keymap in the +# svgalib documentation directory for more in-depth information. +# +# You must specify the full path to the keymap file; it is recommended that +# keymaps be kept in the same directory as libvga.config, normally /etc/vga. +# The keymap specified in the configuration file can be overriden by setting +# the environment variable SVGALIB_KEYMAP to point to another keymap file; +# this can be useful for setting keymaps on a per-program basis. +# +# This example will use the provided US-Dvorak to US-QWERTY map to allow a +# Dvorak keyboard layout to be used with a program that expects a standard US +# QWERTY keyboard, for instance Quake: +# kbd_keymap /etc/vga/dvorak-us.keymap + +# There is a potential security risk in allowing users to remap keyboard +# scancodes at will; with this option enabled only keymap files owned by +# root can be used. Normally you should leave this on, but if you have a +# single-user box or you really trust your users you may find it convenient +# to run without it and allow users to load arbitrary keymaps. + +kbd_only_root_keymaps + +# kbd_fake_mouse_event, as it says, sends a fake mouse event to the program. +# The format is: kbd_fake_mouse_event scancode [flag(s)] command [argument] +# Scancode is a raw scancode or a descriptive name, the same as with fake +# keyboard events (see above). If you use keymap conversion, specify +# scancodes for the keyboard layout the program will receive. +# Flags: down - trigger event when the key is pressed (default) +# up - the opposite +# both - trigger in both case, if pressed/released +# repeat - repeat events if the key is kept pressed (off by default) +# commands: delta[xyz] - send a fake delta event as if you have moved your +# mouse. If the parameter is 'off' / 'on' it will turn +# off/on the respective mouse axis (requires a +# parameter, of course) +# button[123] - send a fake event that the mouse button is pressed +# or released that's given by the parameter. +# ('pressed' or 'released') +# Here are some examples: + +# This is one I use in *uake: it turns around, looks down a bit and when the +# key is released it does the opposite, so it gets back to the starting state. +# With this one and the help of a rocket you can fly though the whole map :) +# (Scancode 28 is enter) +# kbd_fake_mouse_event 28 both deltax 8182 down deltay -1500 up deltay 1500 + +# This one will switch off the y axis of the mouse while the key (right ctrl) +# is kept pressed. +# kbd_fake_mouse_event 97 down deltay off up deltay on + +# This one is the same as if you were pressing the left mouse button. (But +# if you move your mouse then the button state will reset even if you keep +# right ctrl down...) +# kbd_fake_mouse_event 97 down button1 pressed up button1 released + +# Monitor type: + +# Only one range can be specified for the moment. Format: +# HorizSync min_kHz max_kHz +# VertRefresh min_Hz max_Hz + +# Typical Horizontal sync ranges +# (Consult your monitor manual for Vertical sync ranges) +# +# 31.5 - 31.5 kHz (Standard VGA monitor, 640x480 @ 60 Hz) +# 31.5 - 35.1 kHz (Old SVGA monitor, 800x600 @ 56 Hz) +# 31.5 - 35.5 kHz (Low-end SVGA, 8514, 1024x768 @ 43 Hz interlaced) +# 31.5 - 37.9 kHz (SVGA monitor, 800x600 @ 60 Hz, 640x480 @ 72 Hz) +# 31.5 - 48.3 kHz (SVGA non-interlaced, 800x600 @ 72 Hz, 1024x768 @ 60 Hz) +# 31.5 - 56.0 kHz (high frequency, 1024x768 @ 70 Hz) +# 31.5 - ???? kHz (1024x768 @ 72 Hz) +# 31.5 - 64.3 kHz (1280x1024 @ 60 Hz) + +HorizSync 31.5 35.5 +VertRefresh 50 90 + +# If you have a NeoMagic card on a Toshiba Libretto 100, 110 use this instead + +# HorizSync 31.5 70 +# VertRefresh 50 100 +# Modeline "800x480" 50 800 856 976 1024 480 483 490 504 +hsync +vsy +# newmode 800 480 256 800 1 +# newmode 800 480 32768 1600 2 +# newmode 800 480 65536 1600 2 +# newmode 800 480 16777216 2400 3 + +# Monitor timings +# +# These are prefered over the default timings (if monitor and chipset +# can handle them). Not all drivers use them at the moment, and Mach32 +# has its own syntax (see below). +# The format is identical to the one used by XFree86, but the label +# following the modeline keyword is ignored by svgalib. +# +# Here some examples: + +# modeline "640x480@100" 43 640 664 780 848 480 483 490 504 +# modeline "800x600@73" 50 800 856 976 1024 600 637 643 666 +# modeline "1024x768@75" 85 1024 1048 1376 1400 768 771 780 806 + +# It seems there is a need for a 512x384 mode, this timing was donated +# by Simon Hosie : (it is 39kHz horz by 79Hz vert) + +# Modeline "512x384@79" 25.175 512 522 598 646 384 428 436 494 + +# Here's a 400x300 Modeline (created by svidtune). Note that for +# doublescan modes, the Vertical values are half the real one (so XFree86 +# modelines can be used). + +# Modeline "400x300@72" 25.000 400 440 504 520 300 319 322 333 doublescan + +# Here is a mode for a ZX Spectrum emulator: +# Modeline "256x192@73" 12.588 256 269 312 360 192 208 212 240 doublescan +# newmode 256 192 256 256 1 + +# the width must be divisible by 8. Some cards require even divisiblity by +# 16, so that's preferable, since there are no standard modes where the +# width is not divisible by 16. + +# The following modes are defined in svgalib, but have no timings in +# timing.c, so you'll have to add a modeline in order to use them: +# 1280x720, 1360x768, 1800x1012, 1920x1080, 1920x1440, 2048x1152 +# and 2048x1536 + +# Mach32 timings: + +# e.g. Setup a 320x200 mode for the mach32: + +#define 320x200x32K 320x200x64K 320x200x16M 320x200x16M32 +# 16 320 392 464 552 200 245 265 310 + +# These are REQUIRED for above mode, please edit to suit your monitor. +# (No, I won't pay for a new one) +# HorizSync 29 65 +# VertRefresh 42 93.5 + +# Chipset type: +# +# Use one of the following force chipset type. +# Autodetects if no chipset is specified. +# +# If you have a PCI or AGP card, don't use chipset type forcing. +# If the card is not autodetected, its a bug, and it will probably +# not work even with forcing. Try running vgatest (with no chipset +# line), and send to me (matan@svgalib.org) the output, a copy of +# /proc/pci (or lspci -n -vv) and whatever info you have on the card. +# +# If a chipset driver gives trouble, try forcing VGA. + +# chipset VGA # Standard VGA +# chipset EGA # EGA +# chipset ET3000 # Tseng ET3000 +# chipset ET4000 # Tseng ET4000 +# chipset Cirrus # Cirrus Logic GD542x/543x/544x +# chipset TVGA # Trident TVGA8900/9000 +# chipset Oak # Oak Technologies 037/067/077 +# chipset S3 # S3 chipsets +# chipset GVGA6400 # Genoa 6400 +# chipset ARK # ARK Logic +# chipset ATI # old ATI VGA +# chipset Mach32 # ATI Mach32 +# chipset ALI # ALI2301 +# chipset Mach64 # ATI Mach64 - deprecated, use RAGE driver +# chipset ET6000 # Tseng ET6000 +# chipset APM # Alliance Technology AT 24/25/3D +# chipset NV3 # nVidia Riva 128 +# chipset VESA # nicely behaved Vesa Bioses +# chipset MX # MX86251 (some Voodoo Rush boards) +# chipset PARADISE # WD90C31 +# chipset RAGE # RagePro (and might work with some older mach64) +# chipset BANSHEE # Banshee/V3. +# chipset SIS # SiS 5597/6326/620/530 cards / integrated vga. +# chipset I740 # Intel i740 based cards. +# chipset NEOMAGIC +# chipset LAGUNA # Cirrus Logic Laguna series (546X) +# chipset FBDEV # Use kernel fbdev, instead of direct hardware. +# chipset G400 # Matrox Mystique/G100/G200/G400/G450 +# chipset R128 # Ati Rage128 and Radeon +# chipset SAVAGE # S3 chipsets Savage, Virge, and some Trio64 +# chipset MILLENNIUM # Matrox Millennium and Millennium II +# chipset I810 # Intel i810/815 integrated video +# chipset TRIDENT # Trident PCI and AGP chipsets +# chipset RENDITION # Rendition V2100/V2200 +# chipset G450C2 +# chipset C&T # Chips and Technologies +# chipset PM2 +# chipset UNICHROME + +# EGA Color/mono mode: +# Required if chipset is EGA. +# +# Use one of the following digits to force color/mono: + +# monotext # Card is in monochrome emulation mode +# colortext # Card is in color emulation mode +colortext + +# RAMDAC support: +# Some chipsets (e.g. S3 and ARK) allows specifying a RAMDAC type. +# If your RAMDAC is not autodetected, you can try specifying it. +# Do NOT specify a RAMDAC if you card uses the S3 Trio chipset +# (the RAMDAC is built in). + +# Ramdac Sierra32K +# Ramdac SC15025 +# Ramdac SDAC # S3 SDAC +# Ramdac GenDAC # S3 GenDAC +# Ramdac ATT20C490 # AT&T 20C490, 491, 492 (and compatibles) +# Ramdac ATT20C498 # AT&T 20C498 +# Ramdac IBMRGB52x # IBM RGB524, 526, 528 (and compatibles) + +# Dotclocks: +# Some chipsets needs a list of dot clocks for optimum operation. Some +# includes or supports a programmable clock chip. You'll need to specify +# them here. + +# Fixed clocks example: +# (The following is just an example, get the values for your card from +# you XF86Config) + +# Clocks 25.175 28.3 40 70 50 75 36 44.9 0 118 77 31.5 110 65 72 93.5 + +# Programmable clockchip example: + +# Clockchip ICD2061A # The only one supported right now + + +# VesaText # Helps the VESA driver with text mode restoration + # problems. + +# VesaSave 14 # changing value might help text mode restoring + # problems with VESA driver. Legal values: 0-15 + +# NoVCControl # Disables svgalib's finding a new VC if run + # from X, also disables svgalib restoring textmode when + # switching VC's (bad). Good fo using dumpreg under X, + # but probably bad for standard usage. + +# RageDoubleClock # If your card is based on ATI's rage card, and + # the pixel clock is double what it should be + # (main symptom is some modes are out of sync), + # try enabling this. If it helps, please report to + # me (matan@svgalib.org) + +# NeoMagicLibretto100 # Enable if you have a NeoMagic card on a Toshiba + # Libretto 100, 110, etc + +# FbdevNoVga # When this is set the FBDEV chipset drivers doesn't + # (try to) use standardvga modes through the vga driver. + # this means that no special rights other then access to + # /dev/fb0 are nescesarry for svgalib programs. This can + # also be used when using the FBDEV driver with cards + # which are not VGA compatible. diff --git a/src/driver.h b/src/driver.h new file mode 100644 index 0000000..3bbf4ae --- /dev/null +++ b/src/driver.h @@ -0,0 +1,197 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright (c) 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +#ifndef _DRIVER_H +#define _DRIVER_H + +#include +#include +#include "vga.h" +#include "libvga.h" +#include "timing.h" +#include "accel.h" +#include "io.h" + +#define MAX_REGS 65000 /* VESA needs a lot of storage space */ + +extern int inrestore; + +typedef struct { + void (*savepalette)(unsigned char *red, unsigned char *green, unsigned char *blue); + void (*restorepalette)(const unsigned char *red, + const unsigned char *green, const unsigned char *blue); + int (*setpalette)(int index, int red, int green, int blue); + void (*getpalette)(int index, int *red, int *green, int *blue); + void (*savefont)(void); + void (*restorefont)(void); + int (*screenoff)(void); + int (*screenon)(void); + void (*waitretrace)(void); + } Emulation; + +typedef struct { +/* Basic functions. */ + int (*saveregs) (unsigned char regs[]); + void (*setregs) (const unsigned char regs[], int mode); + void (*unlock) (void); + void (*lock) (void); + int (*test) (void); + int (*init) (int force, int par1, int par2); + void (*__svgalib_setpage) (int page); + void (*__svgalib_setrdpage) (int page); + void (*__svgalib_setwrpage) (int page); + int (*setmode) (int mode, int prv_mode); + int (*modeavailable) (int mode); + void (*setdisplaystart) (int address); + void (*setlogicalwidth) (int width); + void (*getmodeinfo) (int mode, vga_modeinfo * modeinfo); +/* Obsolete blit functions. */ + void (*bitblt) (int srcaddr, int destaddr, int w, int h, int pitch); + void (*imageblt) (void *srcaddr, int destaddr, int w, int h, int pitch); + void (*fillblt) (int destaddr, int w, int h, int pitch, int c); + void (*hlinelistblt) (int ymin, int n, int *xmin, int *xmax, int pitch, int c); + void (*bltwait) (void); +/* Other functions. */ + int (*ext_set) (unsigned what, va_list params); + int (*accel) (unsigned operation, va_list params); + int (*linear) (int op, int param); + AccelSpecs *accelspecs; + Emulation *emul; + int (*cursor)(int cmd, int p1, int p2, int p3, int p4, void *p5); + int disabled; +} DriverSpecs; + +extern DriverSpecs __svgalib_vga_driverspecs; +extern DriverSpecs __svgalib_neo_driverspecs; +extern DriverSpecs __svgalib_cirrus_driverspecs; +extern DriverSpecs __svgalib_et4000_driverspecs; +extern DriverSpecs __svgalib_tvga8900_driverspecs; +extern DriverSpecs __svgalib_oak_driverspecs; +extern DriverSpecs __svgalib_ega_driverspecs; +extern DriverSpecs __svgalib_s3_driverspecs; +extern DriverSpecs __svgalib_r128_driverspecs; +extern DriverSpecs __svgalib_mach32_driverspecs; +extern DriverSpecs __svgalib_et3000_driverspecs; +extern DriverSpecs __svgalib_gvga6400_driverspecs; +extern DriverSpecs __svgalib_ark_driverspecs; +extern DriverSpecs __svgalib_ati_driverspecs; +extern DriverSpecs __svgalib_ali_driverspecs; +extern DriverSpecs __svgalib_mach64_driverspecs; +extern DriverSpecs __svgalib_chips_driverspecs; +extern DriverSpecs __svgalib_apm_driverspecs; +extern DriverSpecs __svgalib_nv3_driverspecs; +extern DriverSpecs __svgalib_et6000_driverspecs; +extern DriverSpecs __svgalib_vesa_driverspecs; +extern DriverSpecs __svgalib_mx_driverspecs; +extern DriverSpecs __svgalib_paradise_driverspecs; +extern DriverSpecs __svgalib_rage_driverspecs; +extern DriverSpecs __svgalib_banshee_driverspecs; +extern DriverSpecs __svgalib_sis_driverspecs; +extern DriverSpecs __svgalib_i740_driverspecs; +extern DriverSpecs __svgalib_i810_driverspecs; +extern DriverSpecs __svgalib_laguna_driverspecs; +extern DriverSpecs __svgalib_fbdev_driverspecs; +extern DriverSpecs __svgalib_r128_driverspecs; +extern DriverSpecs __svgalib_g400_driverspecs; +extern DriverSpecs __svgalib_savage_driverspecs; +extern DriverSpecs __svgalib_mil_driverspecs; +extern DriverSpecs __svgalib_trident_driverspecs; +extern DriverSpecs __svgalib_rendition_driverspecs; +extern DriverSpecs __svgalib_g450c2_driverspecs; +extern DriverSpecs __svgalib_pm2_driverspecs; +extern DriverSpecs __svgalib_unichrome_driverspecs; + +extern DriverSpecs *__svgalib_driverspecs; +extern DriverSpecs *__svgalib_driverspecslist[]; + +enum { + CHIPSET_SAVEREGS = 0, CHIPSET_SETREGS, CHIPSET_UNLOCK, CHIPSET_LOCK, + CHIPSET_TEST, CHIPSET_INIT, CHIPSET_SETPAGE, CHIPSET_SETRDPAGE, + CHIPSET_SETWRPAGE, CHIPSET_SETMODE, + CHIPSET_MODEAVAILABLE, CHIPSET_SETDISPLAYSTART, + CHIPSET_SETLOGICALWIDTH, CHIPSET_GETMODEINFO, + CHIPSET_BITBLT, CHIPSET_IMAGEBLT, CHIPSET_FILLBLT, + CHIPSET_HLINELISTBLT, CHIPSET_BLTWAIT, + CHIPSET_EXT_SET, CHIPSET_ACCEL, CHIPSET_LINEAR +}; + +enum { + LINEAR_QUERY_BASE, LINEAR_QUERY_GRANULARITY, LINEAR_QUERY_RANGE, + LINEAR_ENABLE, LINEAR_DISABLE +}; + +enum { CURSOR_INIT, CURSOR_HIDE, CURSOR_SHOW, CURSOR_POSITION, + CURSOR_SELECT, CURSOR_IMAGE, CURSOR_SAVE +}; + +typedef struct { +/* refresh ranges in Hz */ + unsigned min; + unsigned max; +} RefreshRange; + +extern int __svgalib_CRT_I; +extern int __svgalib_CRT_D; +extern int __svgalib_IS1_R; +extern int __svgalib_driver_report; /* driverreport */ +extern int __svgalib_videomemoryused; /* videomemoryused */ +extern int __svgalib_critical; +extern int __svgalib_chipset; +extern RefreshRange __svgalib_horizsync; +extern RefreshRange __svgalib_vertrefresh; +extern int __svgalib_bandwidth; +extern int __svgalib_grayscale; +extern int __svgalib_modeinfo_linearset; +extern const int __svgalib_max_modes; + +void __svgalib_read_options(char **commands, char *(*func) (int ind, int mode, char **nptr)); +char *__svgalib_token(char **nptr); +/* ---------------------------------------------------------------------- + ** A modetable holds a pair of values + ** for each mode : + ** + ** + ** + ** the last entry is marked by + ** + ** +*/ + +typedef struct { + unsigned short mode_number; + const unsigned char *regs; +} ModeTable; + +#define DISABLE_MODE ((unsigned char *)1) +#define OneModeEntry(res) {G##res,g##res##_regs} +#define DisableEntry(res) {G##res,DISABLE_MODE} +#define END_OF_MODE_TABLE { 0, NULL } + +extern const unsigned char *__svgalib_mode_in_table(const ModeTable * modes, int mode); +#define LOOKUPMODE __svgalib_mode_in_table + +/* ---------------------------------------------------------------------- */ + +extern int __svgalib_hicolor(int dac_type, int mode); +/* Enters hicolor mode - 0 for no hi, 1 for 15 bit, 2 for 16, 3 for 24 */ +/* For any modes it doesn't know about, etc, it attempts to turn hicolor off. */ + +#define STD_DAC 0 +#define HI15_DAC 1 +#define HI16_DAC 2 +#define TC24_DAC 3 + +/* ---------------------------------------------------------------------- + ** regextr.h - extract graphics modes and register information + ** from C source file + */ + +extern void __svgalib_readmodes(FILE * inp, ModeTable ** modes, int *dac, unsigned *clocks); + +#endif diff --git a/src/drivers/ali.c b/src/drivers/ali.c new file mode 100644 index 0000000..f213edb --- /dev/null +++ b/src/drivers/ali.c @@ -0,0 +1,478 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen + * + * This library is free software; you can redistribute it and/or + * modify it without any restrictions. This library is distributed + * in the hope that it will be useful, but without any warranty. + * + * Multi-chipset support Copyright 1993 Harm Hanemaayer + * partially copyrighted (C) 1993 by Hartmut Schirmer + * + * ALI2301 driver release 2.0 released 1996 by Ron Koerner + * (koerne00@marvin.informatik.uni-dortmund.de) + * + * initialization stuff is based on X server routines + * lots of information were from VGADOC4b.ZIP by Finn Thoegersen + * (very good source for (S)VGA-hardware-related stuff) + * + * + * Features in this release: + * * all modes, that is + * * XxYxC mode + * * with (X,Y) from {(320,200),(640,480),(800,600),(1024,768),(1280,1024)} + * * and C from {256,32K,64K,16M} (no(!) 16-color modes, sorry) + * * well, umm, that is, the mode is only available, if it fits in 1MB :) + * * + * * and even more, which do not fit into SVGALIBs pattern + * * actually all modes supported by UNIVBE 5.1 (at least I hope) + * + * Todo: + * * add 16 color modes + * * add accelerator functions + * + */ + +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include +#include "regs/ali.regs" + +static int ali_memory; +static unsigned char last_page = 0; + +static int ali_init(int, int, int); +static int ali_memorydetect(void); +static int GETB(int, int); + +static void ali_unlock(void); +static void ali_setpage(int page); +static void SETB(int, int, int); + +/* Mode table */ + +static ModeTable ali_modes[] = +{ +/* *INDENT-OFF* */ + OneModeEntry(640x480x256), + OneModeEntry(800x600x256), + OneModeEntry(1024x768x256), + + OneModeEntry(640x480x64K), + OneModeEntry(640x480x16M), + OneModeEntry(800x600x64K), + + OneModeEntry(320x200x32K), + OneModeEntry(320x200x64K), + OneModeEntry(320x200x16M), + + OneModeEntry(640x480x32K), + OneModeEntry(640x480x64K), + OneModeEntry(640x480x16M), + + OneModeEntry(800x600x32K), + OneModeEntry(800x600x64K), +/* OneModeEntry(800x600x16M), */ + +/* OneModeEntry(1024x768x32K), */ +/* OneModeEntry(1024x768x64K), */ +/* OneModeEntry(1024x768x16M), */ + +/* OneModeEntry(800x600x16), */ +/* OneModeEntry(1024x768x16), */ +/* OneModeEntry(1280x1024x16), */ + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +/* ali_getmodeinfo( int mode, vga_modeinfo *modeinfo) Tell SVGALIB stuff + + * Return mode information (blityes/no, start address, interlace, linear + */ + +static void ali_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + if (modeinfo->bytesperpixel > 0) { + modeinfo->maxpixels = ali_memory * 1024 / modeinfo->bytesperpixel; + } else { + modeinfo->maxpixels = ali_memory * 1024; /* any val */ + } + + if (modeinfo->height) + modeinfo->maxlogicalwidth = ali_memory * 1024 / modeinfo->height; + else + modeinfo->maxlogicalwidth = 2048; + + modeinfo->startaddressrange = 0xfffff; + switch (mode) { + case G320x200x256: + modeinfo->maxpixels = 65535; + modeinfo->maxlogicalwidth = 320; + modeinfo->startaddressrange = 0x0; + break; + case G640x480x16M: + modeinfo->linewidth = 2048; + break; + } + + modeinfo->haveblit = 0; + modeinfo->flags |= HAVE_RWPAGE; +} + +/* ali_saveregs( unsigned char regs[] ) Save extended regs + + * Save extended registers into regs[]. + */ + +static int ali_saveregs(unsigned char regs[]) +{ + int tmp; + ali_unlock(); + tmp = GETB(GRA_I, 0x0c); + regs[EXT + 7] = port_in(0x3d6); + regs[EXT + 8] = port_in(0x3d7); + port_out_r(0x3d6, 0); + regs[EXT + 0] = GETB(__svgalib_CRT_I, 0x19); + regs[EXT + 1] = GETB(__svgalib_CRT_I, 0x1a); + regs[EXT + 2] = GETB(__svgalib_CRT_I, 0x28); + regs[EXT + 3] = GETB(__svgalib_CRT_I, 0x2a); + regs[EXT + 4] = GETB(GRA_I, 0x0b); + regs[EXT + 5] = tmp; + port_in(0x3c8); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + regs[EXT + 6] = port_in(0x3c6); + return 9; /* 9 additional registers */ +} + +/* ali_setregs( unsigned char regs[], int mode ) + + * Set extended registers for specified graphics mode + */ + +static void ali_setregs(const unsigned char regs[], int mode) +{ + int tmp; + ali_unlock(); + tmp = GETB(GRA_I, 0x0f); + port_out_r(GRA_D, tmp | 4); + port_out_r(0x3d6, 0); + port_out_r(0x3d7, 0); + SETB(__svgalib_CRT_I, 0x19, regs[EXT + 0]); + SETB(__svgalib_CRT_I, 0x1a, regs[EXT + 1] | 0x10); /* |0x10 to prevent locking */ + SETB(GRA_I, 0x0b, regs[EXT + 4]); + SETB(GRA_I, 0x0c, regs[EXT + 5]); + SETB(__svgalib_CRT_I, 0x28, regs[EXT + 2]); + SETB(__svgalib_CRT_I, 0x2a, regs[EXT + 3]); + port_in(0x3c8); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + port_out_r(0x3c6, regs[EXT + 6]); + port_out_r(0x3d6, regs[EXT + 7]); + port_out_r(0x3d7, regs[EXT + 8]); +} + +/* ali_modeavailable( int mode ) Check if mode supported + + * Verify that desired graphics mode can be displayed by chip/memory combo + * Returns SVGADRV flag if SVGA, vga_chipsetfunctions if VGA, 0 otherwise + */ + +static int ali_modeavailable(int mode) +{ + const unsigned char *regs; + struct vgainfo *info; + + regs = LOOKUPMODE(ali_modes, mode); + if (regs == NULL || mode == GPLANE16) { + return __svgalib_vga_driverspecs.modeavailable(mode); + } + if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE) { + return 0; + } + info = &__svgalib_infotable[mode]; + if (ali_memory * 1024 < info->ydim * info->xbytes) { + return 0; + } + return SVGADRV; +} + + + +/* ali_setmode( int mode, int prv_mode ) Set graphics mode + + * Attempts to set a graphics mode. + * Returns 0 if successful, 1 if unsuccessful + * + * Calls vga_chipsetfunctions if VGA mode) + */ + +static int ali_setmode(int mode, int prv_mode) +{ + const unsigned char *rp; + unsigned char regs[sizeof(g640x480x256_regs)]; + + rp = LOOKUPMODE(ali_modes, mode); + if (rp == NULL || mode == GPLANE16) + return (int) (__svgalib_vga_driverspecs.setmode(mode, prv_mode)); + if (!ali_modeavailable(mode)) + return 1; /* mode not available */ + + /* Update the register information */ + memcpy(regs, rp, sizeof(regs)); + + if (__svgalib_infotable[mode].colors == 16) { + /* switch from 256 to 16 color mode (from XFree86) */ + regs[SEQ + 4] &= 0xf7; /* Switch off chain 4 mode */ + } + __svgalib_setregs(regs); + ali_setregs(regs, mode); + + return 0; +} + +/* ali_unlock() Unlock ALI registers + + * Enable register changes + * + */ + +static void ali_unlock(void) +{ + int temp; + temp = GETB(__svgalib_CRT_I, 0x1a); + port_out_r(__svgalib_CRT_D, temp | 0x10); + /* Unprotect CRTC[0-7] */ + temp = GETB(__svgalib_CRT_I, 0x11); + port_out_r(__svgalib_CRT_D, temp & 0x7f); + +} + +/* ali_lock() Lock Ali registers + + * Prevents registers from accidental change + * + */ + +static void ali_lock(void) +{ + int tmp; + /* Protect CRTC[0-7] */ + tmp = GETB(__svgalib_CRT_I, 0x11); + port_out_r(__svgalib_CRT_D, tmp | 0x80); + tmp = GETB(__svgalib_CRT_I, 0x1a); + port_out_r(__svgalib_CRT_D, tmp & 0xef); +} + +static int cwg(void) +{ + int t, t1, t2, t3; + + t = port_in(GRA_I); + t1 = GETB(GRA_I, 0x0b); + t2 = t1 & 0x30; + port_out_r(GRA_D, t2 ^ 0x30); + t3 = ((port_in(GRA_D) & 0x30) ^ 0x30); + port_out_r(GRA_D, t1); + port_out_r(GRA_I, t); + return (t2 == t3); +} + +/* ali_test() Probe for Ali card + + * Checks for Ali segment register, then chip type and memory size. + * + * Returns 1 for Ali, 0 otherwise. + */ + +static int ali_test(void) +{ + int tmp, ov; + + ali_unlock(); + + tmp = port_in(__svgalib_CRT_I); + ov = GETB(__svgalib_CRT_I, 0x1a); + port_out_r(__svgalib_CRT_D, ov & 0xef); + if (cwg()) { + ali_lock(); + return 0; + } + port_out_r(__svgalib_CRT_D, ov | 0x10); + if (!cwg()) { + ali_lock(); + return 0; + } + return ali_init(0, 0, 0); +} + +/* ali_setpage( int page ) Set read/write pages + + * Sets both read and write extended segments (64k bank number) + */ + +static void ali_setpage(int page) +{ + port_outw_r(0x3d6, (last_page = page) | (page << 8)); +} + +/* ali_setrdpage( int page ) Set read page + + * Sets read extended segment (64k bank number) + */ + +static void ali_setrdpage(int page) +{ + last_page = page; + port_out_r(0x3d6, page); +} + +/* ali_setwrpage( int page ) Set write page + + * Sets write extended segment (64k bank number) + */ + +static void ali_setwrpage(int page) +{ + last_page = page; + port_out_r(0x3d7, page); +} + +/* ali_setdisplaystart( int address ) Set display address + + * Sets display start address. + */ + +static void ali_setdisplaystart(int address) +{ + address >>= 3; + port_outw_r(__svgalib_CRT_I, 0x0c | (address & 0x00ff00)); + port_outw_r(__svgalib_CRT_I, 0x0d | ((address & 0x00ff) << 8)); + port_outw_r(__svgalib_CRT_I, 0x20 | ((address & 0x070000) >> 8)); +} + +/* ali_setlogicalwidth( int width ) Set scanline length + + * Set logical scanline length (usually multiple of 8) + * Multiples of 8 to 2040 + */ + +static void ali_setlogicalwidth(int width) +{ + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ +} + +/* ali_init ( int force, int par1, int par2) Initialize chipset + + * Detects ALI chipset type and installed video memory. + * Returns 1 if chipset is supported, 0 otherwise + */ + +static int ali_init(int force, int par1, int par2) +{ + if (force) { + ali_memory = par2; + } else { + ali_memory = ali_memorydetect(); + } + if (__svgalib_driver_report) { + fprintf(stderr,"Using ALI driver (ALI2301, %dK).\n", ali_memory); + } + __svgalib_driverspecs = &__svgalib_ali_driverspecs; + + /* fix infotable entry */ + infotable[G640x480x16M].xbytes = 2048; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + + return 1; +} + +/* ali_memorydetect() Report installed video RAM + + * Returns size (in Kb) of installed video memory + * Defined values are 256, 512, 1024, and 2048 + */ + +static int ali_memorydetect(void) +{ + int tmp; + + tmp = GETB(__svgalib_CRT_I, 0x1e); + + switch (tmp & 3) { + case 0: + return 256; + case 1: + return 512; + case 2: + return 1024; + case 3: + return 2048; + default: + fprintf(stderr,"ALI driver: More than 2MB installed. Using 2MB.\n"); + return 2048; + } +} + +/* SETB (port,index,value) Set extended register + + * Puts a specified value in a specified extended register. + * Splitting this commonly used instruction sequence into its own subroutine + * saves about 100 bytes of code overall ... + */ + +static void SETB(int port, int idx, int value) +{ + if (idx != -1) + port_out_r(port, idx); + port_out_r(port + (idx != -1), value); +} + +/* GETB (port,index) Returns ext. register + + * Returns value from specified extended register. + * As with SETB, this tightens the code considerably. + */ + +static int GETB(int port, int idx) +{ + if (idx != -1) + port_out_r(port, idx); + return port_in(port + (idx != -1)); +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_ali_driverspecs = +{ + ali_saveregs, + ali_setregs, + ali_unlock, + ali_lock, + ali_test, + ali_init, + ali_setpage, + ali_setrdpage, + ali_setwrpage, + ali_setmode, + ali_modeavailable, + ali_setdisplaystart, + ali_setlogicalwidth, + ali_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* accelspecs */ + NULL, /* Emulation */ +}; diff --git a/src/drivers/apm.c b/src/drivers/apm.c new file mode 100644 index 0000000..4da5c6a --- /dev/null +++ b/src/drivers/apm.c @@ -0,0 +1,672 @@ +/* +At3d (at25) driver - Matan Ziv-Av, matan@svgalib.org +please report problems to me, + +If you have an alliance promotion 6422, it should +be easy to make the driver work on it. + +This driver is based on the XFREE86 apm driver, developed by +Kent Hamilton and by Henrik Harmsen. + +I used the file cirrus.c in this directory as a skeleton. + +there are still the following problems: + * pageflipping (in threeDKit) does not work. + * no acceleration (is there a program that uses it anyway?). + * The clocks for 320x200 modes are _not easy_ for the driver. + if you have a problem with those modes, please contact me. + * 24 bits modes don't work on AT24. + +*/ + + +#include +#include /* for printf */ +#include /* for memset */ +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "vgapci.h" + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "vgammvgaio.h" +#include "interface.h" + +#define APMREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define APM_TOTAL_REGS (VGA_TOTAL_REGS + 38) + +static int apm_init(int, int, int); +static void apm_unlock(void); + +static int apm_memory,apm_chiptype; +static int apm_xbase; + +static CardSpecs *cardspecs; + +static void outXR(int index,unsigned char d) +{ + __svgalib_outseq(0x1d,index>>2); + port_out_r(apm_xbase,d); +} + +static void outwXR(int index,unsigned short d) +{ + __svgalib_outseq(0x1d,index>>2); + port_outw_r(apm_xbase,d); +} + +static void outlXR(int index,unsigned int d) +{ + __svgalib_outseq(0x1d,index>>2); + port_outl_r(apm_xbase,d); +} + +static unsigned char inXR(int index) +{ + __svgalib_outseq(0x1d,index>>2); + return port_in(apm_xbase); +} + +#if 0 +/* currently not used */ +static unsigned short inwXR(int index) +{ + __svgalib_outseq(0x1d,index>>2); + return inw(apm_xbase); +} +#endif + +static unsigned int inlXR(int index) +{ + __svgalib_outseq(0x1d,index>>2); + return port_inl(apm_xbase); +} + +enum { + AT6420 = 0, AT6422, AT24, AT3D +}; + +static void apm_setpage(int page) +{ + /* default 4K granularity */ + outwXR(0xc0,page << 4); +} + +/* Fill in chipset specific mode information */ +static void apm_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = apm_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = apm_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int apm_saveregs(unsigned char regs[]) +{ + unsigned int k; + unsigned int *p; + unsigned short *q; + + apm_unlock(); /* May be locked again by other programs (e.g. X) */ + regs[APMREG_SAVE(2)] = __svgalib_incrtc(0x19); + regs[APMREG_SAVE(3)] = __svgalib_incrtc(0x1A); + regs[APMREG_SAVE(4)] = __svgalib_incrtc(0x1B); + regs[APMREG_SAVE(5)] = __svgalib_incrtc(0x1C); + regs[APMREG_SAVE(6)] = __svgalib_incrtc(0x1D); + regs[APMREG_SAVE(7)] = __svgalib_incrtc(0x1E); + + regs[APMREG_SAVE(0)] = __svgalib_inseq(0x1B); + regs[APMREG_SAVE(1)] = __svgalib_inseq(0x1C); + + regs[APMREG_SAVE(8)] = inXR(0x80) ; + regs[APMREG_SAVE(9)] = inXR(0xc0) ; + k = inlXR(0xe8) ; + regs[APMREG_SAVE(10)] = k&0xff; + regs[APMREG_SAVE(11)] = (k >> 8)&0xff; + regs[APMREG_SAVE(12)] = (k >> 16) & 0xff ; + regs[APMREG_SAVE(13)] = ( k >> 24 ) & 0xff ; + k = inlXR(0xec) ; + regs[APMREG_SAVE(14)] = k&0xff; + regs[APMREG_SAVE(15)] = (k >> 8)&0xff; + regs[APMREG_SAVE(16)] = (k >> 16) & 0xff ; + regs[APMREG_SAVE(17)] = ( k >> 24 ) & 0xff ; + p=(unsigned int *) ®s[APMREG_SAVE(18)]; + *p = inlXR(0xf0); + p=(unsigned int *) ®s[APMREG_SAVE(22)]; + *p = inlXR(0xf4); + p=(unsigned int *) ®s[APMREG_SAVE(26)]; + *p = inlXR(0x140); + q=(unsigned short *) ®s[APMREG_SAVE(30)]; + *q = inlXR(0x144); + p=(unsigned int *) ®s[APMREG_SAVE(32)]; + *p = inXR(0x148); + q=(unsigned short *) ®s[APMREG_SAVE(36)]; + *q = inXR(0x14c); + + return APM_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void apm_setregs(const unsigned char regs[], int mode) +{ unsigned int k ; + + apm_unlock(); /* May be locked again by other programs (eg. X) */ + apm_setpage(0); + + __svgalib_outseq(0x1b,regs[APMREG_SAVE(0)]); + __svgalib_outseq(0x1c,regs[APMREG_SAVE(1)]); + __svgalib_outcrtc(0x19,regs[APMREG_SAVE(2)]); + __svgalib_outcrtc(0x1a,regs[APMREG_SAVE(3)]); + __svgalib_outcrtc(0x1b,regs[APMREG_SAVE(4)]); + __svgalib_outcrtc(0x1c,regs[APMREG_SAVE(5)]); + __svgalib_outcrtc(0x1d,regs[APMREG_SAVE(6)]); + __svgalib_outcrtc(0x1e,regs[APMREG_SAVE(7)]); + + if(apm_chiptype==AT3D) { + k=regs[APMREG_SAVE(10)]+(regs[APMREG_SAVE(11)] << 8)+(regs[APMREG_SAVE(12)] << 16)+(regs[APMREG_SAVE(13)] << 24); + outlXR(0xe8,k) ; + }; + + k=regs[APMREG_SAVE(14)]+(regs[APMREG_SAVE(15)] << 8)+(regs[APMREG_SAVE(16)] << 16)+(regs[APMREG_SAVE(17)] << 24); + outlXR(0xec,k & ~(1 << 7)) ; + outlXR(0xec,k | (1 << 7)) ; + + outXR(0x80,regs[APMREG_SAVE(8)]) ; + +} + + +/* Return nonzero if mode is available */ + +static int apm_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (apm_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if((modeinfo->bitsPerPixel==24)&&(apm_chiptype==AT24)) { + free(modeinfo); + return 0; + } + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +static unsigned comp_lmn(unsigned clock) ; +/* Set a mode */ + +/* Local, called by apm_setmode(). */ + +static void apm_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + int k; + + apm_saveregs(moderegs); + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + { + int offset; + offset = modeinfo->lineWidth >> 3; + moderegs[0x13] = offset; + /* Bit 8 resides at CR1C bits 7:4. */ + moderegs[APMREG_SAVE(5)] = (offset & 0xf00) >> 4; + } + + /* Set pixel depth. */ + switch(modeinfo->bitsPerPixel) + { + case 8: + moderegs[APMREG_SAVE(8)] = 0x42; + break; + case 16: + moderegs[APMREG_SAVE(8)] = modeinfo->greenWeight+7; + break; + case 24: + moderegs[APMREG_SAVE(8)] = 0xe; + break; + case 32: + moderegs[APMREG_SAVE(8)] = 0x0f; + break; + default: + break; + } + + /* + * Enable VESA Super VGA memory organisation. + * Also enable Linear Addressing. + */ + moderegs[APMREG_SAVE(0)] = 0; + moderegs[APMREG_SAVE(1)] = 21; + /* Set banking register to zero. */ + moderegs[APMREG_SAVE(9)] = 0; + + /* Handle the CRTC overflow bits. */ + { + unsigned char val; + /* Vertical Overflow. */ + val = 0; + if ((modetiming->CrtcVTotal - 2) & 0x400) + val |= 0x01; + if ((modetiming->CrtcVDisplay - 1) & 0x400) + val |= 0x02; + /* VBlankStart is equal to VSyncStart + 1. */ + if (modetiming->CrtcVSyncStart & 0x400) + val |= 0x04; + /* VRetraceStart is equal to VSyncStart + 1. */ + if (modetiming->CrtcVSyncStart & 0x400) + val |= 0x08; + moderegs[APMREG_SAVE(3)] = val; + + /* Horizontal Overflow. */ + val = 0; + if ((modetiming->CrtcHTotal / 8 - 5) & 0x100) + val |= 1; + if ((modetiming->CrtcHDisplay / 8 - 1) & 0x100) + val |= 2; + /* HBlankStart is equal to HSyncStart - 1. */ + if ((modetiming->CrtcHSyncStart / 8 - 1) & 0x100) + val |= 4; + /* HRetraceStart is equal to HSyncStart. */ + if ((modetiming->CrtcHSyncStart / 8) & 0x100) + val |= 8; + moderegs[APMREG_SAVE(4)] = val; + } + moderegs[APMREG_SAVE(7)]= 1; /* disable autoreset feature */ + + k = comp_lmn(modetiming->pixelClock); + if (k==0){ + k = comp_lmn(modetiming->pixelClock*2); + if(k>0)moderegs[VGA_SR1] |= 8 ; /* Sequencer1 - clock halving */ + }; + moderegs[APMREG_SAVE(14)]=k&0xff; + moderegs[APMREG_SAVE(15)]=(k >> 8)&0xff; + moderegs[APMREG_SAVE(16)]=(k >> 16)&0xff; + moderegs[APMREG_SAVE(17)]=(k >> 24)&0xff; + moderegs[MIS] |= 0xc; + moderegs[MIS]=0xef; + /* Set up the RAMDAC registers. */ + + if (modeinfo->bitsPerPixel > 8) { + /* Get rid of white border. */ + moderegs[VGA_AR11] = 0; + } else { + int p,q,r; + + moderegs[VGA_AR11]=0xff; + p=moderegs[1]+((moderegs[APMREG_SAVE(4)]&2)<<7); + moderegs[2]=p&0xff; + moderegs[APMREG_SAVE(4)]&=0xfd; + moderegs[APMREG_SAVE(4)]|=(p&0x100)>>7; + q=moderegs[4]+((moderegs[APMREG_SAVE(4)]&8)<<5); + r=moderegs[0]+4; + moderegs[3]&=0xe0; + moderegs[3]|=(r&0x1f); + moderegs[5]&=0x7f; + moderegs[5]|=(r&0x20)<<2; + + p=moderegs[0x12]+((moderegs[0x7]&2)<<7)+((moderegs[7]&0x40)<<3)+((moderegs[APMREG_SAVE(3)]&2)<<9); + moderegs[0x15]=p&0xff; + moderegs[0x7]&=0xf7; + moderegs[0x7]|=(p&0x100)>>5; + moderegs[0x9]&=0xdf; + moderegs[0x9]|=(p&0x200)>>4; + moderegs[APMREG_SAVE(3)]&=0xfb; + moderegs[APMREG_SAVE(3)]|=(p&0x400)>>7; + moderegs[0x16]=moderegs[6]+1; + } + + moderegs[APMREG_SAVE(10)] = 0xe8; + moderegs[APMREG_SAVE(11)] = 0x01; + moderegs[APMREG_SAVE(12)] = 0x1f; + moderegs[APMREG_SAVE(13)] = 0x07; + + return ; +} + + + +static int apm_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + /* Let the standard VGA driver set standard VGA modes */ + /* But first reset an Cirrus extended register that */ + /* an old XFree86 Trident probe corrupts. */ + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!apm_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(APM_TOTAL_REGS); + + apm_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + apm_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void apm_unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + __svgalib_outseq(0x10, 0x12); +} + + +/* Relock chipset-specific registers */ +/* (currently not used) */ + +static void apm_lock(void) +{ +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int apm_test(void) +{ +#ifdef OLD_TEST + int i; + int oldSEQ10; + +/* To remove annoying "unused..." warning + char id_ap6420[] = "Pro6420"; + char id_ap6422[] = "Pro6422"; +*/ + char id_at24[] = "Pro6424"; + char id_at3d[] = "ProAT3D"; /* Yeah, the manual could have been + correct... */ + char idstring[] = " "; + + /* + * Warning! A fully compliant VGA will most probably interprete this as + * __svgalib_outbSR(0x00, 0x02), hence stop the sequencer, to play safe + * we keep the old setting. + */ + + oldSEQ10 = __svgalib_inSR(0x10); + __svgalib_outSR(0x10, 0x12); + + for (i = 0; i < 7; i++) + idstring[i] = __svgalib_inSR(0x11+i); + + /* + * Just in case, restore any old setting & select SEQ00: + */ + __svgalib_outSR(0x10, oldSEQ10); + __svgalib_inSR(0); + + if (!memcmp(id_at3d, idstring, 7) || !memcmp(id_at24,idstring,7)) + { apm_init(0,0,0) ; return 1; } + return 0; +#else /* use PCI test */ + int found=0; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(0x1142,buf); + if(!found)return 0; + if ((((buf[0]>>16)&0xffff)!=0x6424)&& + (((buf[0]>>16)&0xffff)!=0x643d) + ) return 0; + apm_init(0,0,0); + return 1; +#endif + +} + + +/* No r/w paging */ +static void apm_setrdpage(int page) +{ +} +static void apm_setwrpage(int page) +{ +} + + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void apm_setdisplaystart(int address) +{ int i; + port_outw_r(0x3d4, (address & 0x00FF00) | 0x0C); + port_outw_r(0x3d4, ((address & 0x00FF) << 8) | 0x0D); + + /* + * Here the high-order bits are masked and shifted, and put into + * the appropriate extended registers. + */ + port_out_r(0x3d4,0x1c); + i=(port_in(0x3d5)&0xf0)|((address & 0x0f0000) >> 16); + __svgalib_outCR(0x1c,i); +/* modinx(vgaIOBase + 4, 0x1c, 0x0f, (address & 0x0f0000) >> 16); */ + +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void apm_setlogicalwidth(int width) +{ +} + +static int apm_linear(int op, int param) +{ + if (op==LINEAR_ENABLE) { return 0;} + if (op==LINEAR_DISABLE){ return 0;} + if (op==LINEAR_QUERY_BASE) { + __svgalib_outSR(0x1d,0x193>>2); + return port_in(apm_xbase+3)<<24; + } + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int apm_match_programmable_clock(int clock) +{ +return clock ; +} +static int apm_map_clock(int bpp, int clock) +{ +return clock ; +} +static int apm_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} +/* Function table (exported) */ + +DriverSpecs __svgalib_apm_driverspecs = +{ + apm_saveregs, + apm_setregs, + apm_unlock, + apm_lock, + apm_test, + apm_init, + apm_setpage, + apm_setrdpage, + apm_setwrpage, + apm_setmode, + apm_modeavailable, + apm_setdisplaystart, + apm_setlogicalwidth, + apm_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + apm_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int apm_init(int force, int par1, int par2) +{ + char idstring[] = " "; + int found=0; + unsigned int buf[64]; + int db, d9; + + apm_unlock(); + + found=__svgalib_pci_find_vendor_vga_pos(0x1142,buf); + if(!found)return 1; + switch((buf[0]>>16)&0xffff) { + case 0x6424: strcpy(idstring,"AT24"); break; + case 0x643d: strcpy(idstring,"AT25/3D"); break; + default: return 1; break; + }; + + __svgalib_linear_mem_base=buf[4]&0xffffff00; + + __svgalib_mmio_base=__svgalib_linear_mem_base+0xffc000; + __svgalib_mmio_size=0x4000; + map_mmio(); + db=v_readb(0x2cdb); + d9=v_readb(0x2cd9); + v_writeb((db & 0xf4) | 0x0a, 0x2cdb); + v_writeb((d9 & 0xcf) | 0x20, 0x2cd9); + __svgalib_vgammbase = 0x3000; + __svgalib_mm_io_mapio(); + + apm_memory=__svgalib_inseq(0x20)*64-34; /* maybe will support accel some day */ + if (__svgalib_driver_report) { + fprintf(stderr,"Using Alliance driver, %.7s, %iKB.\n",idstring, apm_memory); + } + + apm_xbase= (__svgalib_inseq(0x1f) << 8 ) + __svgalib_inseq(0x1e); + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = apm_memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 175500; + if(apm_chiptype==AT24)cardspecs->maxPixelClock8bpp = 160000; + cardspecs->maxPixelClock16bpp = 144000; + cardspecs->maxPixelClock24bpp = 75000; + cardspecs->maxPixelClock32bpp = 94500; + cardspecs->flags = CLOCK_PROGRAMMABLE | INTERLACE_DIVIDE_VERT; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->clocks = NULL; + cardspecs->mapClock = apm_map_clock; + cardspecs->mapHorizontalCrtc = apm_map_horizontal_crtc; + cardspecs->matchProgrammableClock=apm_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_apm_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_size=apm_memory*1024; + return 0; +} + +#define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2))) + +static unsigned +comp_lmn(unsigned clock) +{ + int n, m, l, f; + int fvco; + int fout; + int fmax; + int fref; + int fvco_goal; + int c; + + if(apm_chiptype==AT3D) + fmax = 400000; else fmax=265000; +/* The XFree86 driver says the max for AT24 is 250000, + but there is a much used clock (65MHZ), that uses 260000 fvco, + and the VESA bios on the card uses this clock, upped the max */ + + fref = 14318; + + for (m = 1; m <= 5; m++) + { + for (l = 3; l >= 0; l--) + { + for (n = 8; n <= 127; n++) + { + fout = ((n+1) * fref / (m+1) + (1<<(l-1))) >> l; + fvco_goal = clock << l; + fvco = (n+1) * fref / (m+1); + if (!WITHIN(fvco, 125000, fmax)) + continue; + if (!WITHIN(fvco, 995*fvco_goal/1000, 1005*fvco_goal/1000)) + continue; + + c=1000*(380*7)/(380-175); + f = (c+ 500 - 34*fvco/1000)/1000; + if (f > 7) f = 7; + if (f < 0) f = 0; +/*fprintf(stderr,"clock=%i l=%i f=%i m=%i n=%i\n",clock,l,f,m,n);*/ + return (n << 16) | (m << 8) | (l << 2) | (f << 4); + } + } + } +/*fprintf(stderr,"Can't do clock=%i\n",clock);*/ + return 0; +} + + diff --git a/src/drivers/ark.c b/src/drivers/ark.c new file mode 100644 index 0000000..c39fa08 --- /dev/null +++ b/src/drivers/ark.c @@ -0,0 +1,1429 @@ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* ARK driver written by Harm Hanemaayer. */ + +/* + * Jan 1995: + * Initial ARK driver. Should at least provide 25.175 and 28.322 MHz + * dot clocks. + * Sep 1996: Support 24bpp, but colors are wrong on ARK1000PV with AT&T + * DAC. Recognize ARK2000MT. + */ + +/* #define INCLUDE_HALVED_CLOCKS */ + +#ifdef INCLUDE_HALVED_CLOCKS +#define SVGA_STYLE_320x200x256 +#endif + +/* Use the COP in coordinate mode. */ +/* #define COORDINATES */ + + +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#include "timing.h" +#include "ramdac/ramdac.h" +#include "vgaregs.h" +#include "interface.h" +#include "accel.h" + + +/* Extended registers. */ + +#define ARK_SR10 VGA_TOTAL_REGS + 0 +#define ARK_SR11 VGA_TOTAL_REGS + 1 +#define ARK_SR12 VGA_TOTAL_REGS + 2 +#define ARK_SR13 VGA_TOTAL_REGS + 3 +#define ARK_SR14 VGA_TOTAL_REGS + 4 +#define ARK_SR15 VGA_TOTAL_REGS + 5 +#define ARK_SR16 VGA_TOTAL_REGS + 6 +#define ARK_SR17 VGA_TOTAL_REGS + 7 +#define ARK_SR18 VGA_TOTAL_REGS + 8 +#define ARK_SR19 VGA_TOTAL_REGS + 9 +#define ARK_SR1C VGA_TOTAL_REGS + 10 +#define ARK_SR1D VGA_TOTAL_REGS + 11 +#define ARK_CR40 VGA_TOTAL_REGS + 12 +#define ARK_CR41 VGA_TOTAL_REGS + 13 +#define ARK_CR42 VGA_TOTAL_REGS + 14 +#define ARK_CR44 VGA_TOTAL_REGS + 15 +#define ARK_CR46 VGA_TOTAL_REGS + 16 +#define ARK_CR50 VGA_TOTAL_REGS + 17 +#define ARK_PELMASK VGA_TOTAL_REGS + 18 + +#define ARK_MEMORY_CONTROL ARK_SR10 +#define ARK_VIDEO_CLOCK_SELECT ARK_SR11 +#define ARK_VLBUS_CONTROL ARK_SR12 +#define ARK_PAGE_ADDRESS_LOW ARK_SR13 +#define ARK_PAGE_ADDRESS_HIGH ARK_SR14 +#define ARK_APERTURE_WRITE_INDEX ARK_SR15 +#define ARK_APERTURE_READ_INDEX ARK_SR16 +#define ARK_COP_FRAMEBUFFER_PITCH ARK_SR17 /* Unused */ +#define ARK_DISPLAY_FIFO_CONTROL ARK_SR18 +#define ARK_HOST_INTERFACE_TYPE ARK_SR19 /* Read */ +#define ARK_DPMS_CONTROL ARK_SR1C +#define ARK_LOCK_REGISTER ARK_SR1D +#define ARK_CRTC_VERTICAL_OVERFLOW ARK_CR40 +#define ARK_CRTC_HORIZONTAL_OVERFLOW ARK_CR41 +#define ARK_INTERLACE_RETRACE ARK_CR42 +#define ARK_VGA_ENHANCEMENT ARK_CR44 +#define ARK_PIXEL_CLOCK_CONTROL ARK_CR46 +#define ARK_CHIP_ID ARK_CR50 /* Read */ + +#define ARK_DAC_OFFSET VGA_TOTAL_REGS + 19 +#define ARK_TOTAL_REGS VGA_TOTAL_REGS + 19 + 10 + + +#define ARK1000PV 0 +#define ARK2000PV 1 + +#define VL 0 +#define PCI 1 + +static int ark_chip; +static int ark_memory; +static int ark_bus; +static int ark_baseaddress, is_linear; /* PCI base address. */ +static CardSpecs *cardspecs; +static DacMethods *dac_used; +static int dac_speed = 0; + +static int ark_init(int, int, int); + + +static void nothing(void) +{ +} + + +/* Unlock. */ + +static void ark_unlock(void) +{ + /* Set bit 0 of SR1D. */ + __svgalib_outSR(0x1D, __svgalib_inSR(0x1D) | 0x01); + /* + * Also enable writing to CRTC 0-7. This lock seems to have side effects + * on some extended registers on the ARK1000PV! + */ + __svgalib_outCR(0x11, __svgalib_inCR(0x11) & ~0x80); +} + +/* Fill in chipset specific mode information */ + +static void ark_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ +#ifdef SVGA_STYLE_320x200x256 + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + && mode != G320x200x256) { +#else + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { +#endif + __svgalib_vga_driverspecs.getmodeinfo(mode, modeinfo); + return; + } + switch (modeinfo->colors) { + case 16: /* 4-plane 16 color mode */ + modeinfo->maxpixels = 65536 * 8; + break; + default: + modeinfo->maxpixels = ark_memory * 1024 / + modeinfo->bytesperpixel; + break; + } + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = 0x1fffff; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + modeinfo->flags |= CAPABLE_LINEAR; +} + + +/* Return non-zero if mode is available */ + +static int ark_modeavailable(int mode) +{ + struct vgainfo *info; + ModeInfo *modeinfo; + ModeTiming *modetiming; + +#ifdef SVGA_STYLE_320x200x256 + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + && mode != G320x200x256) +#else + if (IS_IN_STANDARD_VGA_DRIVER(mode)) +#endif + return __svgalib_vga_driverspecs.modeavailable(mode); + + /* Enough memory? */ + info = &__svgalib_infotable[mode]; + if (ark_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + + +static int ark_saveregs(unsigned char regs[]) +{ + ark_unlock(); + + /* Save extended registers. */ + regs[ARK_SR10] = __svgalib_inSR(0x10); + regs[ARK_SR11] = __svgalib_inSR(0x11); + regs[ARK_SR12] = __svgalib_inSR(0x12); + regs[ARK_SR13] = __svgalib_inSR(0x13); + regs[ARK_SR14] = __svgalib_inSR(0x14); + regs[ARK_SR15] = __svgalib_inSR(0x15); + regs[ARK_SR16] = __svgalib_inSR(0x16); + regs[ARK_SR18] = __svgalib_inSR(0x18); + regs[ARK_SR19] = __svgalib_inSR(0x19); + regs[ARK_SR1C] = __svgalib_inSR(0x1C); + regs[ARK_SR1D] = __svgalib_inSR(0x1D); + + regs[ARK_CR40] = __svgalib_inCR(0x40); + regs[ARK_CR41] = __svgalib_inCR(0x41); + regs[ARK_CR42] = __svgalib_inCR(0x42); + regs[ARK_CR44] = __svgalib_inCR(0x44); + regs[ARK_CR46] = __svgalib_inCR(0x46); + regs[ARK_CR50] = __svgalib_inCR(0x50); + + port_in(0x3C8); + regs[ARK_PELMASK] = port_in(0x3C6); + + dac_used->saveState(regs + ARK_DAC_OFFSET); + return ARK_DAC_OFFSET - VGA_TOTAL_REGS + dac_used->stateSize; +} + + +/* Set chipset-specific registers */ + +static void ark_setregs(const unsigned char regs[], int mode) +{ + ark_unlock(); + + /* Write extended registers. */ + + __svgalib_outCR(0x46, __svgalib_inCR(0x46) | 0x20); /* Disable Clock Select Latch. */ + + __svgalib_outSR(0x10, regs[ARK_SR10]); + __svgalib_outSR(0x11, regs[ARK_SR11]); + __svgalib_outSR(0x12, regs[ARK_SR12]); + __svgalib_outSR(0x13, regs[ARK_SR13]); + __svgalib_outSR(0x14, regs[ARK_SR14]); + __svgalib_outSR(0x15, regs[ARK_SR15]); + __svgalib_outSR(0x16, regs[ARK_SR16]); + __svgalib_outSR(0x18, regs[ARK_SR18]); + __svgalib_outSR(0x1C, regs[ARK_SR1C]); + __svgalib_outSR(0x1D, regs[ARK_SR1D]); + + __svgalib_outCR(0x40, regs[ARK_CR40]); + __svgalib_outCR(0x41, regs[ARK_CR41]); + __svgalib_outCR(0x42, regs[ARK_CR42]); + __svgalib_outCR(0x44, regs[ARK_CR44]); + + port_in(0x3C8); + port_out_r(0x3C6, regs[ARK_PELMASK]); + dac_used->restoreState(regs + ARK_DAC_OFFSET); + + __svgalib_outCR(0x46, regs[ARK_CR46]); +} + + +/* + * Initialize register state for a mode. + */ + +static void ark_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo) +{ + + /* Get current values. */ + + + is_linear=0; + ark_saveregs(moderegs); + + /* Set up the standard VGA registers for a generic SVGA. */ + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + /* Set up the extended register values, including modifications */ + /* of standard VGA registers. */ + + moderegs[VGA_CR13] = modeinfo->lineWidth >> 3; +/* moderegs[VGA_CR14] = 0x40; */ +/* moderegs[VGA_CR17] = 0xA3; */ +/* moderegs[VGA_AR10] = 0x01; */ + moderegs[VGA_AR11] = 0x00; + /* The following is actually a RAMDAC register. */ + moderegs[ARK_PELMASK] = 0xFF; + + moderegs[ARK_VIDEO_CLOCK_SELECT] &= ~0x0F; + /* Set COP and Giant Shift pixel depth. */ + if (modeinfo->bytesPerPixel == 1) + moderegs[ARK_VIDEO_CLOCK_SELECT] |= 0x6; + if (modeinfo->bytesPerPixel == 2) + moderegs[ARK_VIDEO_CLOCK_SELECT] |= 0xA; + if (modeinfo->bytesPerPixel == 3) { + moderegs[ARK_VIDEO_CLOCK_SELECT] |= 0x6; +// moderegs[ARK_DPMS_CONTROL] &=0xe7; +// moderegs[ARK_DPMS_CONTROL] |=0x18; + + } + if (modeinfo->bytesPerPixel == 4) + moderegs[ARK_VIDEO_CLOCK_SELECT] |= 0xE; + +/* Framebuffer control. */ + /* Enable VESA Super VGA memory organisation. */ + /* Also enable Linear Addressing and COP (seems to be required). */ + moderegs[ARK_MEMORY_CONTROL] &= ~0x1F; + moderegs[ARK_MEMORY_CONTROL] |= 0x1F; + /* Map aperture at 0xA0000. */ + moderegs[ARK_PAGE_ADDRESS_LOW] = 0x0A; + moderegs[ARK_PAGE_ADDRESS_HIGH] = 0x00; + /* The following register is not VLB-specific, despite its name. */ + /* Set 64K aperture. */ + moderegs[ARK_VLBUS_CONTROL] &= ~0x03; + moderegs[ARK_APERTURE_WRITE_INDEX] = 0; + moderegs[ARK_APERTURE_READ_INDEX] = 0; + +/* Display FIFO. */ + { + int threshold; + unsigned char val; + threshold = 4; /* A guess. */ + val = moderegs[ARK_DISPLAY_FIFO_CONTROL]; + if (ark_chip == ARK1000PV) { + val |= 0x08; /* Enable full FIFO. */ + val &= ~0x07; + val |= threshold; + } + if (ark_chip == ARK2000PV) { + threshold=12; + val &= 0x40; + val |= 0x10; /* 32-deep FIFO. */ + val |= (threshold & 0x0E) >> 1; + if (threshold & 0x01) + val |= 0x80; + if (threshold & 0x10) + val |= 0x20; + } + moderegs[ARK_DISPLAY_FIFO_CONTROL] = val; + } + +/* CRTC timing. */ + { + unsigned char val; + /* Vertical Overflow. */ + val = 0; + if ((modetiming->CrtcVTotal - 2) & 0x400) + val |= 0x80; + if ((modetiming->CrtcVDisplay - 1) & 0x400) + val |= 0x40; + /* VBlankStart is equal to VSyncStart + 1. */ + if (modetiming->CrtcVSyncStart & 0x400) + val |= 0x20; + /* VRetraceStart is equal to VSyncStart + 1. */ + if (modetiming->CrtcVSyncStart & 0x400) + val |= 0x10; + moderegs[ARK_CRTC_VERTICAL_OVERFLOW] = val; + + /* Horizontal Overflow. */ + val = moderegs[ARK_CRTC_HORIZONTAL_OVERFLOW]; + val &= 0x07; + if ((modetiming->CrtcHTotal / 8 - 5) & 0x100) + val |= 0x80; + if ((modetiming->CrtcHDisplay / 8 - 1) & 0x100) + val |= 0x40; + /* HBlankStart is equal to HSyncStart - 1. */ + if ((modetiming->CrtcHSyncStart / 8 - 1) & 0x100) + val |= 0x20; + /* HRetraceStart is equal to HSyncStart. */ + if ((modetiming->CrtcHSyncStart / 8) & 0x100) + val |= 0x10; + if ((modeinfo->lineWidth / 8) & 0x100) + val |= 0x08; + moderegs[ARK_CRTC_HORIZONTAL_OVERFLOW] = val; + } + /* No interlace, standard character clock. */ + moderegs[ARK_VGA_ENHANCEMENT] &= ~0x34; + /* Enable RAMDAC access. */ + moderegs[ARK_VGA_ENHANCEMENT] &= ~0x01; + if (modetiming->flags & INTERLACED) { + /* Set mid-scan vertical retrace start. */ + moderegs[ARK_INTERLACE_RETRACE] = + (modetiming->CrtcHTotal / 8 - 5) / 2; + moderegs[ARK_VGA_ENHANCEMENT] |= 0x04; /* Interlaced. */ + } +/* Clocking. */ + /* Select 8 or 16-bit video output to RAMDAC on 2000PV. */ + if (ark_chip == ARK2000PV) { + int dac16; + moderegs[ARK_PIXEL_CLOCK_CONTROL] &= ~0x04; /* 8-bit */ + dac16 = 0; + if (modeinfo->bitsPerPixel == 8 && + cardspecs->mapClock(8, modetiming->pixelClock) + == modetiming->pixelClock / 2) + /* Typically high resolution 8bpp (> 110 MHz). */ + dac16 = 1; + if (modeinfo->bitsPerPixel == 16 && + cardspecs->mapClock(16, modetiming->pixelClock) + == modetiming->pixelClock) + /* 16bpp at pixel rate. */ + dac16 = 1; + /* Note: with an 8-bit DAC, 16bpp is Clock * 2. */ + /* 24bpp is always Clock * 3. */ + if (modeinfo->bitsPerPixel == 32 && + cardspecs->mapClock(32, modetiming->pixelClock) + == modetiming->pixelClock * 2) + /* 32bpp at Clock * 2. */ + dac16 = 1; + /* Note: with an 8-bit dac, 32bpp is Clock * 4. */ + if (dac16) + moderegs[ARK_PIXEL_CLOCK_CONTROL] |= 0x04; /* 16-bit */ + } + if (modetiming->flags & USEPROGRCLOCK) + if(dac_used==&__svgalib_ICS_GENDAC_methods) { + moderegs[VGA_MISCOUTPUT] &= ~0x0C; + moderegs[VGA_MISCOUTPUT] |= 0x08; + } else moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */ + else { + /* Program clock select. */ + moderegs[VGA_MISCOUTPUT] &= ~0x0C; + moderegs[VGA_MISCOUTPUT] |= + (modetiming->selectedClockNo & 3) << 2; + moderegs[ARK_VIDEO_CLOCK_SELECT] &= ~0xC0; + moderegs[ARK_VIDEO_CLOCK_SELECT] |= + (modetiming->selectedClockNo & 0xC) << 4; +#ifdef INCLUDE_HALVED_CLOCKS + if (modetiming->selectedClockNo & 0x10) + /* Set VGA divide clock by 2 bit. */ + moderegs[VGA_SR1] |= 0x08; +#endif + } + + if (dac_used->id != NORMAL_DAC) { + dac_used->initializeState(&moderegs[ARK_DAC_OFFSET], + modeinfo->bitsPerPixel, + __svgalib_colorbits_to_colormode(modeinfo->bitsPerPixel, + modeinfo->colorBits), + modetiming->pixelClock); + } +} + + +/* Set a mode */ + +static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp, + int width_in_pixels); + +static void arkaccel_init(AccelSpecs * accelspecs, int bpp, + int width_in_pixels); + +static int ark_setmode(int mode, int prv_mode) +{ + ModeInfo *modeinfo; + ModeTiming *modetiming; + unsigned char *moderegs; + +#ifdef SVGA_STYLE_320x200x256 + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + && mode != G320x200x256) +#else + if (IS_IN_STANDARD_VGA_DRIVER(mode)) +#endif + /* Let the standard VGA driver set standard VGA modes. */ + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + if (!ark_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + moderegs = malloc(ARK_TOTAL_REGS); + + ark_initializemode(moderegs, modetiming, modeinfo); + free(modetiming); + + ark_setregs(moderegs, mode); /* Set extended regs. */ + __svgalib_setregs(moderegs); /* Set standard regs. */ + free(moderegs); + + __svgalib_InitializeAcceleratorInterface(modeinfo); + + init_acceleration_specs_for_mode(__svgalib_driverspecs->accelspecs, + modeinfo->bitsPerPixel, + modeinfo->lineWidth / modeinfo->bytesPerPixel); + + arkaccel_init(__svgalib_driverspecs->accelspecs, + modeinfo->bitsPerPixel, + modeinfo->lineWidth / modeinfo->bytesPerPixel); + + free(modeinfo); + return 0; +} + + +/* Indentify chipset; return non-zero if detected */ + +static int ark_test(void) +{ + if (ark_init(0, 0, 0)) + return 0; + return 1; +} + + +/* Bank switching function - set 64K bank number */ + +static void ark_setpage(int page) +{ + __svgalib_outseq(0x15, page); + __svgalib_outseq(0x16, page); +} + + +/* Set display start address (not for 16 color modes) */ + +static void ark_setdisplaystart(int address) +{ + __svgalib_outcrtc(0x0d, (address >> 2) & 0xff); + __svgalib_outcrtc(0x0c, (address >> 10) & 0xff); + port_in(0x3da); /* set ATC to addressing mode */ + port_out_r(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); + /* write sa0-1 to bits 1-2 */ + __svgalib_outcrtc(0x40, (address >> 18) & 0x07); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Multiples of 8 to 2040 */ + +static void ark_setlogicalwidth(int width) +{ + __svgalib_outcrtc(0x13, (width >> 3)); + port_out_r(__svgalib_CRT_I, 0x41); + port_out_r(__svgalib_CRT_D, (port_in(__svgalib_CRT_D) & ~0x08) | ((width >> 3) & 0x100)); +} + +static int ark_linear(int op, int param) +{ + if (op == LINEAR_ENABLE) { + int size; + __svgalib_outSR(0x13, param >> 16); + __svgalib_outSR(0x14, param >> 24); + switch (ark_memory) { + case 1024: + size = 1; + break; + case 2048: + size = 2; + break; + case 4096: + default: + size = 3; + } + __svgalib_outSR(0x12, (__svgalib_inSR(0x12) & ~0x03) | size); + is_linear=1; + return 0; + } + if (op == LINEAR_DISABLE) { + __svgalib_outSR(0x12, __svgalib_inSR(0x12) & ~0x03); /* 64K map. */ + __svgalib_outSR(0x13, 0xA0); /* Revert to 0xA0000. */ + __svgalib_outSR(0x14, 0x00); + is_linear=0; + return 0; + } + if (op == LINEAR_QUERY_BASE) { + if (ark_bus == PCI && param == 0) + /* Return PCI base address. */ + return ark_baseaddress; + if (ark_bus == VL) { + if (param == 0) + return 0x08000000; /* 128MB */ + if (param == 1) + return 0x04000000; /* 64MB */ + if (param == 2) + return 0x80000000; /* 2048MB */ + if (param == 3) + return 0x02000000; /* 32MB */ + } + return -1; + } + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + else + return -1; /* Unknown function. */ +} + +static struct { + unsigned char c8; + unsigned short c15; + unsigned short c16; + unsigned int c32; +} cursor_colors[16*2]; + +static int pal=1, palette[768]; + +static int findcolor(int rgb) { + int i,j,k,l=0; + + if(pal)vga_getpalvec(0,256,palette); + pal=0; + k=0xffffff; + for(i=0;i<256;i++) { + j=((rgb&0xff)-(palette[i*3+2]<<2))*((rgb&0xff)-(palette[i*3+2]<<2))+ + (((rgb>>8)&0xff)-(palette[i*3+1]<<2))*(((rgb>>8)&0xff)-(palette[i*3+1]<<2))+ + (((rgb>>16)&0xff)-(palette[i*3]<<2))*(((rgb>>16)&0xff)-(palette[i*3]<<2)); + if(j==0) { + return i; + } + if(j>8)&0xff); + __svgalib_outseq(0x24, p2&0xff); + __svgalib_outseq(0x23, (p2>>8)&0xff); + break; + case CURSOR_SELECT: + i=ark_memory-(p1+1); + switch(CI.colors) { + case 256: + __svgalib_outseq(0x26,cursor_colors[p1*2+1].c8); + __svgalib_outseq(0x29,cursor_colors[p1*2].c8); + break; + case 32768: + __svgalib_outseq(0x27,cursor_colors[p1*2+1].c15>>8); + __svgalib_outseq(0x26,cursor_colors[p1*2+1].c15&0xff); + __svgalib_outseq(0x2a,cursor_colors[p1*2].c15>>8); + __svgalib_outseq(0x29,cursor_colors[p1*2].c15&0xff); + break; + case 65536: + __svgalib_outseq(0x27,cursor_colors[p1*2+1].c16>>8); + __svgalib_outseq(0x26,cursor_colors[p1*2+1].c16&0xff); + __svgalib_outseq(0x2a,cursor_colors[p1*2].c16>>8); + __svgalib_outseq(0x29,cursor_colors[p1*2].c16&0xff); + break; + case (1<<24): + __svgalib_outseq(0x28,cursor_colors[p1*2+1].c32>>16); + __svgalib_outseq(0x27,(cursor_colors[p1*2+1].c32>>8)&0xff); + __svgalib_outseq(0x26,cursor_colors[p1*2+1].c32&0xff); + __svgalib_outseq(0x2b,cursor_colors[p1*2].c32>>16); + __svgalib_outseq(0x2a,(cursor_colors[p1*2].c32>>8)&0xff); + __svgalib_outseq(0x29,cursor_colors[p1*2].c32&0xff); + break; + } + __svgalib_outseq(0x25, (i>>8)&0x3f); + __svgalib_outseq(0x25, 63); + break; + case CURSOR_IMAGE: + i=ark_memory*1024-(p1+1)*1024; + i=2048*1024-256; + b3=(unsigned char *)p5; + b4=LINEAR_POINTER+i; + if (!is_linear){ + int size; + __svgalib_outSR(0x13, ark_baseaddress >> 16); + __svgalib_outSR(0x14, ark_baseaddress >> 24); + switch (ark_memory) { + case 1024: + size = 1; + break; + case 2048: + size = 2; + break; + case 4096: + default: + size = 3; + } + __svgalib_outSR(0x12, (__svgalib_inSR(0x12) & ~0x03) | size); + }; + cursor_colors[p1*2].c8=findcolor(p3); + cursor_colors[p1*2].c32=p3; + cursor_colors[p1*2].c16=((p3&0xf80000)>>8)|((p3&0xfc00)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2].c15=((p3&0xf80000)>>9)|((p3&0xf800)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2+1].c8=findcolor(p4); + cursor_colors[p1*2+1].c32=p4; + cursor_colors[p1*2+1].c16=((p4&0xf80000)>>8)|((p4&0xfc00)>>5)|((p4&0xf8)>>3); + cursor_colors[p1*2+1].c15=((p4&0xf80000)>>9)|((p4&0xf800)>>5)|((p4&0xf8)>>3); + switch(p2) { + case 0: + for(j=0;j<32;j++) for(i=0;i<4;i++){ + *b4=*b3; + b4++; + *b4=*(b3+32); + b4++; + b3++; + } + break; + } + if (!is_linear){ + __svgalib_outseq(0x12, __svgalib_inseq(0x12) & ~0x03); /* 64K map. */ + __svgalib_outseq(0x13, 0xA0); /* Revert to 0xA0000. */ + __svgalib_outseq(0x14, 0x00); + }; + break; + } + return 0; +} + +/* Function table (exported) */ +DriverSpecs __svgalib_ark_driverspecs = +{ + ark_saveregs, /* saveregs */ + ark_setregs, /* setregs */ + ark_unlock, /* unlock */ + nothing, /* lock */ + ark_test, + ark_init, + ark_setpage, + (void (*)(int)) nothing, + (void (*)(int)) nothing, + ark_setmode, + ark_modeavailable, + ark_setdisplaystart, + ark_setlogicalwidth, + ark_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + ark_linear, + NULL, /* accelspecs */ + NULL, /* Emulation */ + cursor, +}; + +/* ARK-specific config file options. */ + +/* + * Currently this only handles Clocks. It would a good idea to have + * higher-level code process options like Clocks that are valid for + * more than one driver driver (with better error detection etc.). + */ + +static char *ark_config_options[] = +{ + "clocks", "ramdac", "dacspeed", NULL +}; + +static char *ark_process_option(int option, int mode, char** dummy) +{ +/* + * option is the number of the option string in ark_config_options, + * mode seems to be a security indicator. + */ + if (option == 0) { /* "Clocks" */ + /* Process at most 16 specified clocks. */ + cardspecs->clocks = malloc(sizeof(int) * 16); + /* cardspecs->nClocks should already be 0. */ + for (;;) { + char *ptr; + int freq; + ptr = strtok(NULL, " "); + if (ptr == NULL) + break; + /* + * This doesn't protect against bad characters + * (atof() doesn't detect errors). + */ + freq = atof(ptr) * 1000; + cardspecs->clocks[cardspecs->nClocks] = freq; + cardspecs->nClocks++; + if (cardspecs->nClocks == 16) + break; + } + } + if (option == 1) { /* "Ramdac" */ + char *ptr; + DacMethods *old_dac_used; + ptr = strtok(NULL, " "); + old_dac_used = dac_used; +#ifdef INCLUDE_ICS_GENDAC_DAC + if (strcasecmp(ptr, "ICSgendac") == 0) + dac_used = &__svgalib_ICS_GENDAC_methods; +#endif +#ifdef INCLUDE_SIERRA_DAC + if (strcasecmp(ptr, "Sierra32K") == 0) + dac_used = &__svgalib_Sierra_32K_methods; +#endif +#ifdef INCLUDE_ATT20C490_DAC + if (strcasecmp(ptr, "ATT20C490") == 0) + dac_used = &__svgalib_ATT20C490_methods; +#endif +#ifdef INCLUDE_ATT20C498_DAC + if (strcasecmp(ptr, "ATT20C498") == 0) + dac_used = &__svgalib_ATT20C498_methods; +#endif +#ifdef INCLUDE_NORMAL_DAC + if (strcasecmp(ptr, "Normal") == 0) /* force normal VGA dac */ + dac_used = &__svgalib_normal_dac_methods; +#endif + if (old_dac_used != dac_used) + dac_used->initialize(); + } + if (option == 2) { /* "Dacspeed" */ + char *ptr; + ptr = strtok(NULL, " "); + /* + * This doesn't protect against bad characters + * (atoi() doesn't detect errors). + */ + dac_speed = atoi(ptr) * 1000; + } + return strtok(NULL, " "); +} + + +/* Initialize driver (called after detection) */ + +static DacMethods *dacs_to_probe[] = +{ +#ifdef INCLUDE_ICS_GENDAC_DAC_TEST + &__svgalib_ICS_GENDAC_methods, +#endif +#ifdef INCLUDE_ATT20C490_DAC_TEST + &__svgalib_ATT20C490_methods, +#endif +#ifdef INCLUDE_ATT20C498_DAC_TEST + &__svgalib_ATT20C498_methods, +#endif +#ifdef INCLUDE_SIERRA_DAC_TEST + &__svgalib_Sierra_32K_methods, +#endif + NULL}; + +static char *ark_chipname[] = +{"ARK1000PV", "ARK2000PV"}; + +static int ark_init(int force, int par1, int par2) +{ + ark_unlock(); + + if (force) { + ark_chip = par1; /* we already know the type */ + ark_memory = par2; + } else { + unsigned char id, val; + id = __svgalib_inCR(0x50) >> 3; + if (id == 0x12) + ark_chip = ARK1000PV; + else if ((id == 0x13) || (id == 0x14) || (id == 0x20)) + ark_chip = ARK2000PV; + else { + fprintf(stderr,"svgalib: ark: Unknown chiptype %d.\n", + id); + return -1; + } + val = __svgalib_inSR(0x10); + if (ark_chip == ARK1000PV) + if ((val & 0x40) == 0) + ark_memory = 1024; + else + ark_memory = 2048; + else if ((val & 0xC0) == 0) + ark_memory = 1024; + else if ((val & 0xC0) == 0x40) + ark_memory = 2048; + else + ark_memory = 4096; + } + + +/* begin: Initialize cardspecs. */ + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = ark_memory; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->nClocks = 0; + cardspecs->flags = INTERLACE_DIVIDE_VERT; + + /* Process ARK-specific config file options. */ + __svgalib_read_options(ark_config_options, ark_process_option); + + + if (dac_used == NULL) { + dac_used=__svgalib_probeDacs(dacs_to_probe); + } + + if (dac_used == NULL) { + /* Not supported. */ + fprintf(stderr,"svgalib: ark: Assuming normal VGA DAC.\n"); + +#ifdef INCLUDE_NORMAL_DAC + dac_used = &__svgalib_normal_dac_methods; +#else + fprintf(stderr,"svgalib: Alas, normal VGA DAC support is not compiled in, goodbye.\n"); + return 1; +#endif + } + dac_used->qualifyCardSpecs(cardspecs, dac_speed); + + /* Initialize standard clocks for unknown clock device. */ + if (!(dac_used->flags & CLOCK_PROGRAMMABLE) + && cardspecs->nClocks == 0) { +#ifdef INCLUDE_HALVED_CLOCKS + int i; + cardspecs->nClocks = 32; + cardspecs->clocks = malloc(sizeof(int) * 32); +#else + cardspecs->nClocks = 2; + cardspecs->clocks = malloc(sizeof(int) * 2); +#endif + cardspecs->clocks[0] = 25175; + cardspecs->clocks[1] = 28322; +#ifdef INCLUDE_HALVED_CLOCKS + for (i = 2; i < 16; i++) + cardspecs->clocks[i] = 0; + for (i = 16; i < 32; i++) + cardspecs->clocks[i] = cardspecs->clocks[i - 16] / 2; +#endif + } + /* Limit pixel clocks according to chip specifications. */ + if (ark_chip == ARK1000PV) { + /* Limit max clocks according to 120 MHz DCLK spec. */ + /* 8-bit DAC. */ + LIMIT(cardspecs->maxPixelClock4bpp, 120000); + LIMIT(cardspecs->maxPixelClock8bpp, 120000); + LIMIT(cardspecs->maxPixelClock16bpp, 120000 / 2); + LIMIT(cardspecs->maxPixelClock24bpp, 120000 / 3); + LIMIT(cardspecs->maxPixelClock32bpp, 120000 / 4); + } + if (ark_chip == ARK2000PV) { + /* Limit max clocks according to 120 MHz DCLK spec. */ + /* Assume 16-bit DAC. */ + LIMIT(cardspecs->maxPixelClock4bpp, 120000); + LIMIT(cardspecs->maxPixelClock8bpp, 120000 * 2); + LIMIT(cardspecs->maxPixelClock16bpp, 120000); + LIMIT(cardspecs->maxPixelClock24bpp, 120000 / 3); + LIMIT(cardspecs->maxPixelClock32bpp, 120000 / 2); + } + cardspecs->maxPixelClock4bpp = 0; /* 16-color modes don't work. */ +/* end: Initialize cardspecs. */ + +/* Initialize accelspecs structure. */ + __svgalib_ark_driverspecs.accelspecs = malloc(sizeof(AccelSpecs)); + __svgalib_clear_accelspecs(__svgalib_ark_driverspecs.accelspecs); + __svgalib_ark_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH; + /* Map memory-mapped I/O register space. */ + + if (__svgalib_driver_report) { + char *bustype; + if (__svgalib_inSR(0x19) & 0x80) { + ark_bus = VL; + bustype = "VL bus"; + } else { + ark_bus = PCI; + bustype = "PCI"; + ark_baseaddress = (__svgalib_inSR(0x13) << 16) + + (__svgalib_inSR(0x14) << 24); + } + fprintf(stderr,"svgalib: Using ARK driver (%s, %dK, %s).", + ark_chipname[ark_chip], ark_memory, bustype); +#if 0 + if (ark_bus == PCI) + fprintf(stderr," Base address = 0x%08X.", ark_baseaddress); +#endif + fprintf(stderr,"\n"); + } + __svgalib_driverspecs = &__svgalib_ark_driverspecs; + __svgalib_mmio_base = 0xb8000; + __svgalib_mmio_size = 4096; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + if (ark_bus == PCI)__svgalib_linear_mem_base=ark_baseaddress; + __svgalib_linear_mem_size=ark_memory*0x400; + + return 0; +} + + +/* ARK Logic acceleration functions implementation. */ + +/* We use linear COP addresses (no coordinates) to allow acceleration */ +/* in any linewidth. */ + +/* Macros for memory-mapped I/O COP register access. */ + +/* MMIO addresses (offset from 0xb8000). */ + +#define BACKGROUNDCOLOR 0x00 +#define FOREGROUNDCOLOR 0x02 +#define COLORMIXSELECT 0x18 +#define WRITEPLANEMASK 0x1A +#define STENCILPITCH 0x60 +#define SOURCEPITCH 0x62 +#define DESTPITCH 0x64 +#define STENCILADDR 0x68 +#define STENCILX 0x68 +#define STENCILY 0x6A +#define SOURCEADDR 0x6C +#define SOURCEX 0x6C +#define SOURCEY 0x6E +#define DESTADDR 0x70 +#define DESTX 0x70 +#define DESTY 0x72 +#define WIDTH 0x74 +#define HEIGHT 0x76 +#define BITMAPCONFIG 0x7C +#define COMMAND 0x7E + +/* Flags for COMMAND register. */ + +#define DRAWNSTEP 0x0000 +#define LINEDRAW 0x1000 +#define BITBLT 0x2000 +#define TEXTBITBLT 0x3000 +#define USEPLANEMASK 0x0000 +#define DISABLEPLANEMASK 0x0800 +#define PATTERN8X8 0x0400 +#define SELECTBGCOLOR 0x0000 +#define BACKGROUNDBITMAP 0x0200 +#define SELECTFGCOLOR 0x0000 +#define FOREGROUNDBITMAP 0x0100 +#define STENCILONES 0x0000 +#define STENCILGENERATED 0x0040 +#define STENCILBITMAP 0x0080 +#define LINEDRAWALL 0x0000 +#define LINESKIPFIRST 0x0010 +#define LINESKIPLAST 0x0020 +#define ENABLECLIPPING 0x0000 +#define DISABLECLIPPING 0x0008 +#define RIGHTANDDOWN 0x0000 +#define RIGHTANDUP 0x0002 +#define LEFTANDDOWN 0x0004 +#define LEFTANDUP 0x0006 + +/* Flags for Bitmap Configuration register. */ + +#define SWAPNIBLES 0x2000 +#define SWAPBITS 0x1000 +#define SYSTEMSTENCIL 0x0200 +#define LINEARSTENCILADDR 0x0100 +#define SYSTEMSOURCE 0x0020 +#define LINEARSOURCEADDR 0x0010 +#define SYSTEMDEST 0x0002 +#define LINEARDESTADDR 0x0001 + +#define SETBACKGROUNDCOLOR(c) \ + *(unsigned short *)(MMIO_POINTER + BACKGROUNDCOLOR) = c; + +#define SETFOREGROUNDCOLOR(c) \ + *(unsigned short *)(MMIO_POINTER + FOREGROUNDCOLOR) = c; + +#define SETCOLORMIXSELECT(m) \ + *(unsigned short *)(MMIO_POINTER + COLORMIXSELECT) = m; + +#define SETWRITEPLANEMASK(m) \ + *(unsigned short *)(MMIO_POINTER + WRITEPLANEMASK) = m; + +#define SETSTENCILPITCH(p) \ + *(unsigned short *)(MMIO_POINTER + STENCILPITCH) = p; + +#define SETSOURCEPITCH(p) \ + *(unsigned short *)(MMIO_POINTER + SOURCEPITCH) = p; + +#define SETDESTPITCH(p) \ + *(unsigned short *)(MMIO_POINTER + DESTPITCH) = p; + +#define SETSTENCILADDR(p) \ + *(unsigned int *)(MMIO_POINTER + STENCILADDR) = p; + +#define SETSOURCEADDR(p) \ + *(unsigned int *)(MMIO_POINTER + SOURCEADDR) = p; + +#define SETSOURCEXY(x, y) \ + *(unsigned int *)(MMIO_POINTER + SOURCEADDR) = (y << 16) + x; + +#define SETSOURCEX(x) \ + *(unsigned short *)(MMIO_POINTER + SOURCEX) = x; + +#define SETSOURCEY(y) \ + *(unsigned short *)(MMIO_POINTER + SOURCEY) = y; + +#define SETDESTADDR(p) \ + *(unsigned int *)(MMIO_POINTER + DESTADDR) = p; + +#define SETDESTXY(x, y) \ + *(unsigned int *)(MMIO_POINTER + DESTADDR) = (y << 16) + x; + +#define SETDESTX(x) \ + *(unsigned short *)(MMIO_POINTER + DESTX) = x; + +#define SETDESTY(y) \ + *(unsigned short *)(MMIO_POINTER + DESTY) = y; + +#define SETWIDTH(p) \ + *(unsigned short *)(MMIO_POINTER + WIDTH) = p - 1; + +#define SETHEIGHT(p) \ + *(unsigned short *)(MMIO_POINTER + HEIGHT) = p - 1; + +#define SETBITMAPCONFIG(p) \ + *(unsigned short *)(MMIO_POINTER + BITMAPCONFIG) = p; + +#define SETCOMMAND(p) \ + *(unsigned short *)(MMIO_POINTER + COMMAND) = p; + +#define COPISBUSY() (port_in(0x3CB) & 0x40) + +#define WAITUNTILFINISHED() \ + for (;;) { \ + if (!COPISBUSY()) \ + break; \ + } + +static void arkaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels) +{ +#ifdef COORDINATES + int pitch; +#endif + SETCOLORMIXSELECT(0x0303); /* Copy source. */ + SETWRITEPLANEMASK(0xFFFF); + SETSTENCILPITCH(width_in_pixels); + SETSOURCEPITCH(width_in_pixels); + SETDESTPITCH(width_in_pixels); +#ifdef COORDINATES + SETBITMAPCONFIG(0); + switch (width_in_pixels) { + case 640: + pitch = 0; + break; + case 800: + pitch = 1; + break; + case 1024: + pitch = 2; + break; + case 1280: + pitch = 4; + break; + case 1600: + pitch = 5; + break; + case 2048: + pitch = 6; + break; + } + __svgalib_outSR(0x17, (__svgalib_inSR(0x17) & ~0x07) | pitch); +#else + SETBITMAPCONFIG(LINEARSTENCILADDR | LINEARSOURCEADDR | + LINEARDESTADDR); +#endif +} + +#define FINISHBACKGROUNDBLITS() \ + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) \ + WAITUNTILFINISHED(); + +void __svgalib_arkaccel_FillBox(int x, int y, int width, int height) +{ + int destaddr; + destaddr = BLTPIXADDRESS(x, y); + FINISHBACKGROUNDBLITS(); + SETDESTADDR(destaddr); + SETWIDTH(width); + SETHEIGHT(height); + SETCOMMAND(SELECTBGCOLOR | SELECTFGCOLOR | STENCILONES | + DISABLEPLANEMASK | DISABLECLIPPING | BITBLT); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + WAITUNTILFINISHED(); +} + +void __svgalib_arkaccel_coords_FillBox(int x, int y, int width, int height) +{ + FINISHBACKGROUNDBLITS(); + SETDESTXY(x, y); + SETWIDTH(width); + SETHEIGHT(height); + SETCOMMAND(SELECTBGCOLOR | SELECTFGCOLOR | STENCILONES | + DISABLEPLANEMASK | DISABLECLIPPING | BITBLT); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + WAITUNTILFINISHED(); +} + +void __svgalib_arkaccel_ScreenCopy(int x1, int y1, int x2, int y2, int width, + int height) +{ + int srcaddr, destaddr, dir; + srcaddr = BLTPIXADDRESS(x1, y1); + destaddr = BLTPIXADDRESS(x2, y2); + dir = RIGHTANDDOWN; + if ((y1 < y2 || (y1 == y2 && x1 < x2)) + && y1 + height > y2) { + srcaddr += (height - 1) * __svgalib_accel_screenpitch + width - 1; + destaddr += (height - 1) * __svgalib_accel_screenpitch + width - 1; + dir = LEFTANDUP; + } + FINISHBACKGROUNDBLITS(); + SETSOURCEADDR(srcaddr); + SETDESTADDR(destaddr); + SETWIDTH(width); + SETHEIGHT(height); + SETCOMMAND(BACKGROUNDBITMAP | FOREGROUNDBITMAP | + STENCILONES | DISABLEPLANEMASK | DISABLECLIPPING | + BITBLT | dir); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + WAITUNTILFINISHED(); +} + +void __svgalib_arkaccel_coords_ScreenCopy(int x1, int y1, int x2, int y2, int width, + int height) +{ + int dir; + dir = RIGHTANDDOWN; + if ((y1 < y2 || (y1 == y2 && x1 < x2)) + && y1 + height > y2) { + y1 += height - 1; + y2 += height - 1; + x1 += width - 1; + x2 += width - 1; + dir = LEFTANDUP; + } + FINISHBACKGROUNDBLITS(); + SETSOURCEXY(x1, y1); + SETDESTXY(x2, y2); + SETWIDTH(width); + SETHEIGHT(height); + SETCOMMAND(BACKGROUNDBITMAP | FOREGROUNDBITMAP | + STENCILONES | DISABLEPLANEMASK | DISABLECLIPPING | + BITBLT | dir); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + WAITUNTILFINISHED(); +} + +void __svgalib_arkaccel_DrawHLineList(int ymin, int n, int *xmin, int *xmax) +{ + int y, destaddr; + FINISHBACKGROUNDBLITS(); + SETHEIGHT(1); + y = ymin; + destaddr = BLTPIXADDRESS(0, ymin); + while (n > 0) { + /* + * We don't wait for previous commands to finish. + * The ARK databook isn't specific on this, but + * I assume the chip will correctly force waits when + * the command FIFO is full. + */ + int x, w; + x = *xmin; + SETDESTADDR(destaddr + x); + w = *xmax - x; + if (w > 0) { + SETWIDTH(w); + SETCOMMAND(SELECTBGCOLOR | SELECTFGCOLOR | STENCILONES + | DISABLEPLANEMASK | DISABLECLIPPING | BITBLT); + } + xmin++; + xmax++; + destaddr += __svgalib_accel_screenpitch; + n--; + } + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + WAITUNTILFINISHED(); +} + +void __svgalib_arkaccel_coords_DrawHLineList(int ymin, int n, int *xmin, int *xmax) +{ + int y; + FINISHBACKGROUNDBLITS(); + SETHEIGHT(1); + y = ymin; + while (n > 0) { + /* + * We don't wait for previous commands to finish. + * The ARK databook isn't specific on this, but + * I assume the chip will correctly force waits when + * the command FIFO is full. + */ + int x, w; + x = *xmin; + SETDESTXY(x, y); + w = *xmax - x; + if (w > 0) { + SETWIDTH(w); + SETCOMMAND(SELECTBGCOLOR | SELECTFGCOLOR | STENCILONES + | DISABLEPLANEMASK | DISABLECLIPPING | BITBLT); + } + xmin++; + xmax++; + n--; + } + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + WAITUNTILFINISHED(); +} + + +void __svgalib_arkaccel_SetFGColor(int fg) +{ + SETFOREGROUNDCOLOR(fg); +} + +void __svgalib_arkaccel_SetBGColor(int fg) +{ + SETBACKGROUNDCOLOR(fg); +} + +void __svgalib_arkaccel_PutBitmap(int x, int y, int w, int h, void *bitmap) +{ + int destaddr, count; +#ifndef COORDINATES + destaddr = BLTPIXADDRESS(x, y); +#endif + /* + * Calculate number of bytes to transfer. + * The ARK chip requires the bitmap scanlines to be aligned + * to 32-bit words, with correct bit order, so no conversion + * is required. + */ + count = (((w + 31) & ~0x1F) / 8) * h; + FINISHBACKGROUNDBLITS(); +#ifdef COORDINATES + SETDESTXY(x, y); +#else + SETDESTADDR(destaddr); +#endif + SETWIDTH(w); + SETHEIGHT(h); + SETBITMAPCONFIG(LINEARSTENCILADDR | LINEARSOURCEADDR | + LINEARDESTADDR | SYSTEMSTENCIL); + SIGNALBLOCK; + SETCOMMAND(SELECTBGCOLOR | SELECTFGCOLOR | STENCILBITMAP + | DISABLEPLANEMASK | DISABLECLIPPING | BITBLT); + while (count >= 65536) { + memcpy(__svgalib_graph_mem, bitmap, 65536); + count -= 65536; + bitmap += 65536; + } + if (count > 0) + memcpy(__svgalib_graph_mem, bitmap, count); + SIGNALUNBLOCK; + WAITUNTILFINISHED(); +} + +static unsigned char ark_rop_map[] = +{ + 0x3, /* COPY */ + 0x7, /* OR */ + 0x1, /* AND */ + 0x6, /* XOR */ + 0xA /* INVERT */ +}; + +void __svgalib_arkaccel_SetRasterOp(int r) +{ + /* Write rop at bits 0-3 and 8-11. */ + SETCOLORMIXSELECT((int) ark_rop_map[r] * 0x0101); +} + +void __svgalib_arkaccel_Sync(void) +{ + WAITUNTILFINISHED(); +} + +/* + * Set up accelerator interface for pixels of size bpp and scanline width + * of width_in_pixels. + */ + +static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp, + int width_in_pixels) +{ + accelspecs->operations = 0; + accelspecs->ropOperations = 0; + accelspecs->transparencyOperations = 0; + accelspecs->ropModes = (1<transparencyModes = 0; +#ifdef COORDINATES + if (width_in_pixels != 640 && width_in_pixels != 800 + && width_in_pixels != 1024 && width_in_pixels != 1280 + && width_in_pixels != 1600 && width_in_pixels != 2048) + return; +#endif + accelspecs->operations |= ACCELFLAG_SETMODE | ACCELFLAG_SYNC + | ACCELFLAG_SETRASTEROP; + if (bpp == 8 || bpp == 16) { + accelspecs->operations |= + ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | + ACCELFLAG_SCREENCOPY | + ACCELFLAG_SETBGCOLOR | ACCELFLAG_PUTBITMAP; + accelspecs->ropOperations |= + ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY; + } + /* Set the function pointers; availability is handled by flags. */ +#ifdef COORDINATES + accelspecs->FillBox = __svgalib_arkaccel_coords_FillBox; + accelspecs->ScreenCopy = __svgalib_arkaccel_coords_ScreenCopy; +#else + accelspecs->FillBox = __svgalib_arkaccel_FillBox; + accelspecs->ScreenCopy = __svgalib_arkaccel_ScreenCopy; +#endif + accelspecs->SetFGColor = __svgalib_arkaccel_SetFGColor; + accelspecs->SetRasterOp = __svgalib_arkaccel_SetRasterOp; + accelspecs->Sync = __svgalib_arkaccel_Sync; + accelspecs->SetBGColor = __svgalib_arkaccel_SetBGColor; + accelspecs->PutBitmap = __svgalib_arkaccel_PutBitmap; +} diff --git a/src/drivers/ati.c b/src/drivers/ati.c new file mode 100644 index 0000000..c7017e2 --- /dev/null +++ b/src/drivers/ati.c @@ -0,0 +1,341 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright (C) 1993 Harm Hanemaayer */ + +/* + * Initial ATI Driver January 1995, Scott D. Heavner (sdh@po.cwru.edu) + */ + +/* ==== SO FAR THE ONLY SPECIAL THING THIS ATI DRIVER DOES IS ALLOW + * ==== GRAPHICS MODES TO FUNCTION WITH A 132col TERMINAL, THERE ARE NO + * ==== NEW MODES YET (there will be). No the XF86 driver won't help as + * ==== XF863.1 doesn't work properly with my ATI Graphics Ultra, + * ==== I will be having a look at the XF86 drivers now that I've found + * ==== the problem an implemented a fix here. + * + * ---- If this driver detects a mach32 chip, it does not init the ATI + * ---- driver, hopefully, the autodetect will find the Mach32 driver. + * ---- We should probably change this to run the Mach32 as an ATI SVGA + * ---- board, but probe for the Mach32 first, this would allow the user + * ---- to force ATI mode in a config file. + */ + +#include +#include /* for NULL */ +#include +#include +#include +#include +#include + +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "vgaregs.h" + +#define ATI_UNKNOWN 0 +#define ATI_18800 1 +#define ATI_18800_1 2 +#define ATI_28800_2 3 +#define ATI_28800_4 4 +#define ATI_28800_5 5 +#define ATI_68800 6 + +#define ATIREG(s) (EXT+(s)-0xa0) + +#define ATI_TOTAL_REGS (VGA_TOTAL_REGS + 0xbf - 0xa0) + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define ABS(a) (((a)<0)?(-(a)):(a)) + +#define ATIGETEXT(index) (port_out_r(ati_base, (index)), port_in(1 + ati_base)) +#define ATISETEXT(index, value) port_outw_r(ati_base, ((value) << 8 | (index))) + +static unsigned char ati_flags_42, ati_flags_44; +static int ati_chiptype; +static int ati_memory; +static short ati_base = 0; +static char *ati_name[] = +{"unknown", "18800", "18800-1", "28800-2", "28800-4", "28800-5", "68800"}; + +static void nothing(void) +{ +} + +/* Initialize chipset (called after detection) */ +static int ati_init(int force, int par1, int par2) +{ + __svgalib_driverspecs = &__svgalib_ati_driverspecs; + + /* + * Find out how much video memory the VGA Wonder side thinks it has. + */ + if (ati_chiptype < ATI_28800_2) { + if (ATIGETEXT(0xbb) & 0x20) + ati_memory = 512; + else + ati_memory = 256; + } else { + unsigned char b = ATIGETEXT(0xB0); + + if (b & 0x08) + ati_memory = 1024; + else if (b & 0x10) + ati_memory = 512; + else + ati_memory = 256; + } + + if (__svgalib_driver_report) + fprintf(stderr,"Using ATI (mostly VGA) driver, (%s, %dK).\n", ati_name[ati_chiptype], ati_memory); + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + + return 1; +} + +/* Read and store chipset-specific registers */ +static int ati_saveregs(unsigned char regs[]) +{ + regs[ATIREG(0xb2)] = ATIGETEXT(0xb2); + + if (ati_chiptype > ATI_18800) { + regs[ATIREG(0xbe)] = ATIGETEXT(0xbe); + if (ati_chiptype >= ATI_28800_2) { + regs[ATIREG(0xbf)] = ATIGETEXT(0xbf); + regs[ATIREG(0xa3)] = ATIGETEXT(0xa3); + regs[ATIREG(0xa6)] = ATIGETEXT(0xa6); + regs[ATIREG(0xa7)] = ATIGETEXT(0xa7); + regs[ATIREG(0xab)] = ATIGETEXT(0xab); + regs[ATIREG(0xac)] = ATIGETEXT(0xac); + regs[ATIREG(0xad)] = ATIGETEXT(0xad); + regs[ATIREG(0xae)] = ATIGETEXT(0xae); + } + } + regs[ATIREG(0xb0)] = ATIGETEXT(0xb0); + regs[ATIREG(0xb1)] = ATIGETEXT(0xb1); + regs[ATIREG(0xb3)] = ATIGETEXT(0xb3); + regs[ATIREG(0xb5)] = ATIGETEXT(0xb5); + regs[ATIREG(0xb6)] = ATIGETEXT(0xb6); + regs[ATIREG(0xb8)] = ATIGETEXT(0xb8); + regs[ATIREG(0xb9)] = ATIGETEXT(0xb9); + regs[ATIREG(0xba)] = ATIGETEXT(0xba); + regs[ATIREG(0xbd)] = ATIGETEXT(0xbd); + + return ATI_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ +static void ati_setregs(const unsigned char regs[], int mode) +{ + ATISETEXT(0xb2, regs[ATIREG(0xb2)]); + + if (ati_chiptype > ATI_18800) { + ATISETEXT(0xbe, regs[ATIREG(0xbe)]); + if (ati_chiptype >= ATI_28800_2) { + ATISETEXT(0xbf, regs[ATIREG(0xbf)]); + ATISETEXT(0xa3, regs[ATIREG(0xa3)]); + ATISETEXT(0xa6, regs[ATIREG(0xa6)]); + ATISETEXT(0xa7, regs[ATIREG(0xa7)]); + ATISETEXT(0xab, regs[ATIREG(0xab)]); + ATISETEXT(0xac, regs[ATIREG(0xac)]); + ATISETEXT(0xad, regs[ATIREG(0xad)]); + ATISETEXT(0xae, regs[ATIREG(0xae)]); + } + } + ATISETEXT(0xb0, regs[ATIREG(0xb0)]); + ATISETEXT(0xb1, regs[ATIREG(0xb1)]); + ATISETEXT(0xb3, regs[ATIREG(0xb3)]); + ATISETEXT(0xb5, regs[ATIREG(0xb5)]); + ATISETEXT(0xb6, regs[ATIREG(0xb6)]); + ATISETEXT(0xb8, regs[ATIREG(0xb8)]); + ATISETEXT(0xb9, regs[ATIREG(0xb9)]); + ATISETEXT(0xba, regs[ATIREG(0xba)]); + ATISETEXT(0xbd, regs[ATIREG(0xbd)]); +} + +/* Fill in chipset specific mode information */ +static void ati_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + __svgalib_vga_driverspecs.getmodeinfo(mode, modeinfo); +} + +/* Return non-zero if mode is available */ +static int ati_modeavailable(int mode) +{ + return __svgalib_vga_driverspecs.modeavailable(mode); +} + +/* Set a mode */ +static int ati_setmode(int mode, int prv_mode) +{ + unsigned char regs[ATI_TOTAL_REGS]; + + if (mode != TEXT) { + /* Mess with the timings before passing it off to the vga driver */ + ati_saveregs(regs); + regs[ATIREG(0xb8)] |= 0x40; + regs[ATIREG(0xbe)] |= 0x10; + ati_setregs(regs, mode); + } + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); +} + +/* + * Lifted from the genoa driver, maybe we should let everyone do the checks + * while we have the vbios mmapped. + */ +static unsigned char *map_vbios(void) +{ + unsigned char *vga_bios; + + /* Changed to use valloc(). */ + if ((vga_bios = valloc(4096)) == NULL) { + fprintf(stderr, "svgalib: malloc error\n"); + exit(-1); + } + vga_bios = (unsigned char *) mmap + ( + (caddr_t) vga_bios, + 4096, + PROT_READ, + MAP_SHARED | MAP_FIXED, + __svgalib_mem_fd, + 0xc0000 + ); + + if (vga_bios == MAP_FAILED) { + fprintf(stderr, "svgalib: mmap error\n"); + exit(-1); + } + return vga_bios; +} + +static int ati_test(void) +{ + int result; + unsigned char *vga_bios; + + vga_bios = map_vbios(); + + if (strncmp("761295520", (vga_bios + 0x31), 9) || /* Identify as an ATI product */ + strncmp("31", (vga_bios + 0x40), 2)) { /* Identify as an ATI super vga (vs EGA/Basic-16) */ + result = 0; + } else { + result = 1; + + memcpy(&ati_base, (vga_bios + 0x10), 2); + + switch (vga_bios[0x43]) { /* Identify Gate revision */ + case '1': + ati_chiptype = ATI_18800; + break; + case '2': + ati_chiptype = ATI_18800_1; + break; + case '3': + ati_chiptype = ATI_28800_2; + break; + case '4': + ati_chiptype = ATI_28800_4; + break; + case '5': + ati_chiptype = ATI_28800_5; + break; + case 'a': + ati_chiptype = ATI_68800; /* Mach 32, should someone else handle this ? * + * * + * On Mach32 we come here only if chipset ATI * + * was EXPLICITLY set (what we support) - MW */ + break; + default: + ati_chiptype = ATI_UNKNOWN; + } + + ati_flags_42 = vga_bios[0x42]; + ati_flags_44 = vga_bios[0x44]; + + } + + if (result) + result = ati_init(0, 0, 0); + + munmap((caddr_t) vga_bios, 4096); + + return (result); + +} + +#if 0 +/* Set 64k bank (r/w) number */ +static void ati_setpage(int bank) +{ + unsigned char b, mask; + + mask = (ati_chiptype > ATI_18800_1) ? 0x0f : 0x07; + + b = ((bank & mask) << 4) | (bank & mask); + ATISETEXT(0xb2, b); +} + +static void ati_setrdpage(int bank) +{ +} + +static void ati_setwrpage(int bank) +{ +} + +#endif + +/* Set display start */ +static void ati_setdisplaystart(int address) +{ +#if 0 + unsigned char b; + + b = ((address >> 10) & ~0x3f) | (ATIGETEXT(0xb0) & 0x3f); + ATISETEXT(0xb0, b); +#endif + __svgalib_vga_driverspecs.setdisplaystart(address); +} + +/* Set logical scanline length (usually multiple of 8) */ +static void ati_setlogicalwidth(int width) +{ + __svgalib_vga_driverspecs.setlogicalwidth(width); +} + +/* Function table (exported) */ +DriverSpecs __svgalib_ati_driverspecs = +{ + ati_saveregs, + ati_setregs, + nothing, /* unlock */ + nothing, /* lock */ + ati_test, + ati_init, + (void (*)(int)) nothing, /* __svgalib_setpage */ + (void (*)(int)) nothing, /* __svgalib_setrdpage */ + (void (*)(int)) nothing, /* __svgalib_setwrpage */ + ati_setmode, + ati_modeavailable, + ati_setdisplaystart, + ati_setlogicalwidth, + ati_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; diff --git a/src/drivers/banshee.c b/src/drivers/banshee.c new file mode 100644 index 0000000..dc362bd --- /dev/null +++ b/src/drivers/banshee.c @@ -0,0 +1,602 @@ +/* +3dfx Voodoo Banshee driver +*/ + +#include +#include /* for printf */ +#include /* for memset */ +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "vgarelvgaio.h" + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" + +#define BANSHEEREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define BANSHEE_TOTAL_REGS (VGA_TOTAL_REGS + 2 + 56) + +static int banshee_init(int, int, int); +static void banshee_unlock(void); +static void banshee_lock(void); + +static int banshee_memory, chiptype, banshee_io_base; +static unsigned int banshee_linear_base; + +static CardSpecs *cardspecs; + +static void banshee_setpage(int page) +{ + page<<=1; + port_outl_r(banshee_io_base+0x2c,(port_inl(banshee_io_base+0x2c)&0xfff00000)|(page)|(page<<10)); +} + +/* Fill in chipset specific mode information */ +static void banshee_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = banshee_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = banshee_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(banshee_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +typedef struct { + unsigned int pllCtrl0, pllCtrl1, dacMode, dacAddr, + vidProcCfg, vidScreenSize, vgaInit0, + vgaInit1, vidDesktopStartAddr,vidDesktopOverlayStride, + hwCurPatAddr, hwCurLoc, hwCurC0, hwCurC1; +} *HWRecPtr; + +static int banshee_saveregs(uint8_t regs[]) +{ + HWRecPtr save; + + banshee_unlock(); /* May be locked again by other programs (e.g. X) */ + + save=(HWRecPtr)(regs+62); + + regs[BANSHEEREG_SAVE(0)]=__svgalib_incrtc(0x1a); + regs[BANSHEEREG_SAVE(1)]=__svgalib_incrtc(0x1b); + save->pllCtrl0=port_inl(banshee_io_base+0x40); + save->pllCtrl1=port_inl(banshee_io_base+0x44); + save->dacMode=port_inl(banshee_io_base+0x4c); + save->dacAddr=port_inl(banshee_io_base+0x50); + save->vidProcCfg=port_inl(banshee_io_base+0x5c); + save->vidScreenSize=port_inl(banshee_io_base+0x98); + save->vgaInit0=port_inl(banshee_io_base+0x28); + save->vgaInit1=port_inl(banshee_io_base+0x2c); + save->vidDesktopStartAddr=port_inl(banshee_io_base+0xe4); + save->vidDesktopOverlayStride=port_inl(banshee_io_base+0xe8); + save->hwCurPatAddr=port_inl(banshee_io_base+0x60); + save->hwCurLoc=port_inl(banshee_io_base+0x64); + save->hwCurC0=port_inl(banshee_io_base+0x68); + save->hwCurC1=port_inl(banshee_io_base+0x6c); + + return BANSHEE_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void banshee_setregs(const uint8_t regs[], int mode) +{ + HWRecPtr restore; + + banshee_unlock(); /* May be locked again by other programs (eg. X) */ + + restore=(HWRecPtr)(regs+62); + + __svgalib_outcrtc(0x1a,regs[BANSHEEREG_SAVE(0)]); + __svgalib_outcrtc(0x1b,regs[BANSHEEREG_SAVE(1)]); + port_outl_r(banshee_io_base+0x40,restore->pllCtrl0); + port_outl_r(banshee_io_base+0x44,restore->pllCtrl1); + port_outl_r(banshee_io_base+0x4c,restore->dacMode); + port_outl_r(banshee_io_base+0x50,restore->dacAddr); + port_outl_r(banshee_io_base+0x5c,restore->vidProcCfg); + port_outl_r(banshee_io_base+0x98,restore->vidScreenSize); + port_outl_r(banshee_io_base+0x28,restore->vgaInit0); + port_outl_r(banshee_io_base+0x2c,restore->vgaInit1); + port_outl_r(banshee_io_base+0xe4,restore->vidDesktopStartAddr); + port_outl_r(banshee_io_base+0xe8,restore->vidDesktopOverlayStride); + port_outl_r(banshee_io_base+0x60,restore->hwCurPatAddr); + port_outl_r(banshee_io_base+0x64,restore->hwCurLoc); + port_outl_r(banshee_io_base+0x68,restore->hwCurC0); + port_outl_r(banshee_io_base+0x6c,restore->hwCurC1); + port_outl_r(banshee_io_base+0x5c,restore->vidProcCfg&0xfffffffe); + port_outl_r(banshee_io_base+0x5c,restore->vidProcCfg|1); + port_outl_r(banshee_io_base+0x5c,restore->vidProcCfg); + +} + + +/* Return nonzero if mode is available */ + +static int banshee_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (banshee_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if((modeinfo->bitsPerPixel==16)&&(modeinfo->greenWeight==5)) { + free(modeinfo); + return 0; + } + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +static int CalcPLL(int freq, int isBanshee); +/* Set a mode */ + +/* Local, called by banshee_setmode(). */ + +static void banshee_initializemode(uint8_t *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ /* int k; */ + + int vd,vt,vbs,vbe,ht,hd,hss,hse; + + HWRecPtr banshee_regs; + + banshee_regs=(HWRecPtr)(moderegs+62); + + banshee_saveregs(moderegs); + + if(modetiming->pixelClock > 135000) { + modetiming->CrtcHDisplay>>=1; + modetiming->CrtcHTotal>>=1; + modetiming->CrtcHSyncStart>>=1; + modetiming->CrtcHSyncEnd>>=1; + } + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + hd = (modetiming->CrtcHDisplay>>3)-1; + hss = (modetiming->CrtcHSyncStart>>3); + hse = (modetiming->CrtcHSyncEnd>>3); + ht = (modetiming->CrtcHTotal>>3)-5; + moderegs[BANSHEEREG_SAVE(0)]=((ht&0x100)>>8) | + ((hd&0x100)>>6) | + ((hd&0x100)>>4) | + ((ht&0x40)>>1) | + ((hss&0x100)>>2) | + ((hse&0x20)<<2) ; + + + vd = modetiming->CrtcVDisplay - 1; + vt = modetiming->CrtcVTotal - 2; + vbs = vd; + vbe = vt; + moderegs[BANSHEEREG_SAVE(1)]=((vt & 0x400)>>10) | + ((vd & 0x400)>>8) | + ((vbs & 0x400)>>6) | + ((vbe & 0x400)>>4); + + banshee_regs->vidProcCfg&=0xf7e30000; /* disable HW cursor, scalling etc. */ + banshee_regs->vidProcCfg|=0x00000c81; /* bypass CLUT, disable VGA mode */ + banshee_regs->vidProcCfg |= 0x02; /* cursor in X11 mode */ + + if(modeinfo->bitsPerPixel==8){ + banshee_regs->vidProcCfg &= ~0xc00; /* disable CLUT bypass */ + }; + + if (modetiming->flags & INTERLACED) { + banshee_regs->vidProcCfg |= 0x8; + } + + if (modetiming->flags & DOUBLESCAN) { + banshee_regs->vidProcCfg |= 0x10; + banshee_regs->vidScreenSize=modeinfo->width|(modeinfo->height<<13); + } else { + banshee_regs->vidScreenSize=modeinfo->width|(modeinfo->height<<12); + } + + switch (modeinfo->bitsPerPixel) + { + case 8: + banshee_regs->vidProcCfg|=0<<18; + break; + case 15: + case 16:if(modeinfo->greenWeight==5){ + banshee_regs->vidProcCfg|=1<<18; + } else banshee_regs->vidProcCfg|=1<<18; + break; + case 24: + banshee_regs->vidProcCfg|=2<<18; + break; + case 32: + banshee_regs->vidProcCfg|=3<<18; + break; + default: + break; + } + + if(modetiming->pixelClock <= 135000) { + banshee_regs->dacMode &= ~1; + banshee_regs->vidProcCfg &= ~(1<<26); + } else { + banshee_regs->dacMode |= 1; + banshee_regs->vidProcCfg |= 1<<26; + } + + banshee_regs->pllCtrl0=CalcPLL(modetiming->pixelClock, 0); + moderegs[VGA_MISCOUTPUT]|=0x0c; /* pixel clock = pllCtrl0 */ + + banshee_regs->vidDesktopStartAddr=0; + banshee_regs->vidDesktopOverlayStride=modeinfo->lineWidth; + + banshee_regs->vgaInit0=0x1140; + banshee_regs->vgaInit1=0x00100000; + + if(modetiming->pixelClock > 135000) { + modetiming->CrtcHDisplay<<=1; + modetiming->CrtcHTotal<<=1; + modetiming->CrtcHSyncStart<<=1; + modetiming->CrtcHSyncEnd<<=1; + } + + return ; +} + +static int banshee_setmode(int mode, int prv_mode) +{ + uint8_t *moderegs; + ModeTiming modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + banshee_unlock(); + __svgalib_outcrtc(0x1a,0x00); + __svgalib_outcrtc(0x1b,0x00); + port_outl_r(banshee_io_base+0x28, port_inl(banshee_io_base+0x28) & ~0x1245 ); + port_outl_r(banshee_io_base+0x2c, port_inl(banshee_io_base+0x2c) & ~0x100000 ); + port_outl_r(banshee_io_base+0x5c, port_inl(banshee_io_base+0x5c) & ~1 ); /* VGA */ + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!banshee_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if (__svgalib_getmodetiming(&modetiming, modeinfo, cardspecs)) { + free(modeinfo); + return 1; + } + + moderegs = malloc(BANSHEE_TOTAL_REGS); + + banshee_initializemode(moderegs, &modetiming, modeinfo, mode); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + banshee_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + + return 0; +} + +/* Unlock chipset-specific registers */ + +static void banshee_unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + port_outl_r(banshee_io_base+0x28,(port_inl(banshee_io_base+0x28)&0xffffffbf)|(1<<6)); +} + +static void banshee_lock(void) +{ + port_outl_r(banshee_io_base+0x28,(port_inl(banshee_io_base+0x28)&0xffffffbf)); +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int banshee_test(void) +{ + int found; + unsigned int buf[64]; + + found=(__svgalib_pci_find_vendor_vga_pos(0x121a,buf))&& + (((buf[0]>>16)==0x0003)|| + ((buf[0]>>16)==0x0009)|| + ((buf[0]>>16)==0x0005)); + + if(found) return !banshee_init(0,0,0); + return found; +} + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void banshee_setdisplaystart(int address) +{ + __svgalib_outcrtc(0x0c,((address>>2) & 0x00FF00)>>8); + __svgalib_outcrtc(0x0d,(address>>2) & 0x00FF); + port_outl_r(banshee_io_base+0xe4,address); +} + + +/* Set logical scanline length (usually multiple of 8) */ + +static void banshee_setlogicalwidth(int width) +{ + int offset = width >> 3; + + __svgalib_outcrtc(0x13,offset&0xff); + port_outl_r(banshee_io_base+0xe8,width); +} + +static int banshee_linear(int op, int param) +{ + if (op==LINEAR_DISABLE) { return 0;} + if (op==LINEAR_ENABLE) { return 0;} + if (op==LINEAR_QUERY_BASE) return banshee_linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int banshee_match_programmable_clock(int clock) +{ +return clock ; +} + +static int banshee_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int banshee_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +static unsigned int cur_colors[16*2]; + +static int banshee_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j; + unsigned int *b3; + unsigned int l1, l2; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + port_outl_r(banshee_io_base+0x5c,port_inl(banshee_io_base+0x5c)&~(1<<27)); + break; + case CURSOR_SHOW: + port_outl_r(banshee_io_base+0x5c,port_inl(banshee_io_base+0x5c)|(1<<27)); + break; + case CURSOR_POSITION: + port_outl_r(banshee_io_base+0x64,((p2+64)<<16)|(p1+64)); + break; + case CURSOR_SELECT: + i=banshee_memory*1024-(p1+1)*4096; + port_outl_r(banshee_io_base+0x68,cur_colors[p1*2]); + port_outl_r(banshee_io_base+0x6c,cur_colors[p1*2+1]); + port_outl_r(banshee_io_base+0x60,i); + break; + case CURSOR_IMAGE: + i=banshee_memory*1024-(p1+1)*4096; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*2]=p3; + cur_colors[p1*2+1]=p4; + for(j=0;j<32;j++) { + l2=*(b3+j); + l1=*(b3+32+j); + /*change endianess */ + l1=(l1<<24)|(l1>>24)|((l1>>8)&0xff00)|((l1<<8)&0xff0000); + l2=(l2<<24)|(l2>>24)|((l2>>8)&0xff00)|((l2<<8)&0xff0000); + *(unsigned int *)(LINEAR_POINTER+i+16*j)=l1; + *(unsigned int *)(LINEAR_POINTER+i+16*j+4)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+8)=l2; + *(unsigned int *)(LINEAR_POINTER+i+16*j+12)=0; + } + for(j=32;j<64;j++) { + *(unsigned int *)(LINEAR_POINTER+i+16*j)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+4)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+8)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+12)=0; + } + break; + } + break; + } + return 0; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_banshee_driverspecs = +{ + banshee_saveregs, + banshee_setregs, + banshee_unlock, + banshee_lock, + banshee_test, + banshee_init, + banshee_setpage, + NULL, + NULL, + banshee_setmode, + banshee_modeavailable, + banshee_setdisplaystart, + banshee_setlogicalwidth, + banshee_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + banshee_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + banshee_cursor +}; + +/* Initialize chipset (called after detection) */ + +static int banshee_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + + if (force) { + banshee_memory = par1; + chiptype = par2; + } else { + + }; + + found=(__svgalib_pci_find_vendor_vga_pos(0x121a,buf))&& + (((buf[0]>>16)==0x0003)|| + ((buf[0]>>16)==0x0009)|| + ((buf[0]>>16)==0x0005)); + + chiptype = buf[0]>>16; + + if (found){ + banshee_linear_base=buf[5]&0xffffff00; + banshee_io_base=buf[6]&0xff00; + __svgalib_io_reloc=banshee_io_base-0x300; + __svgalib_rel_io_mapio(); + } else return 1; + + if(banshee_memory==0) { + unsigned int draminit0,draminit1; + + draminit0=port_inl(banshee_io_base+0x18); + draminit1=port_inl(banshee_io_base+0x1c); + if(chiptype == 9) { + banshee_memory = 1024* + 4*(1+((draminit0>>26)&1))* /* chips */ + (1<<((draminit0 & 0x38000000) >> 28))* /* psize */ + 2*(1+((draminit0>>30)&1)); /* banks */ + } else { + if(draminit1&0x40000000) { + /* SDRAM */ + banshee_memory=16*1024; + } else { + /* SGRAM */ + banshee_memory=1024*4* + (1+((draminit0>>27)&1))* /* SGRAM type - 8MBIT or 16MBIT */ + (1+((draminit0>>26)&1)); /* Number of sgram chips (4 or 8) */ + } + } + } + + banshee_unlock(); + + if (__svgalib_driver_report) { + fprintf(stderr,"Using Banshee / Voodoo3 driver, %iKB.\n",banshee_memory); + } + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = banshee_memory; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = 270000; + cardspecs->maxPixelClock16bpp = 270000; + cardspecs->maxPixelClock24bpp = 270000; + cardspecs->maxPixelClock32bpp = 270000; + cardspecs->flags = CLOCK_PROGRAMMABLE | ((chiptype==0x03)?NO_INTERLACE:0); + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->nClocks =0; + cardspecs->mapClock = banshee_map_clock; + cardspecs->mapHorizontalCrtc = banshee_map_horizontal_crtc; + cardspecs->matchProgrammableClock=banshee_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_banshee_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=banshee_linear_base; + __svgalib_linear_mem_size=banshee_memory*0x400; + return 0; +} + +#define REFFREQ 14318.18 + +static int +CalcPLL(int freq, int isBanshee) { + int m, n, k, best_m, best_n, best_k, f_cur, best_error; + int minm, maxm; + + best_error=freq; + best_n=best_m=best_k=0; + if (isBanshee) { + minm=24; + maxm=25; + } else { + minm=1; + maxm=57; /* This used to be 64, alas it seems the last 8 (funny that ?) + * values cause jittering at lower resolutions. I've not done + * any calculations to what the adjustment affects clock ranges, + * but I can still run at 1600x1200@75Hz */ + } + for (n=1; n<256; n++) { + f_cur=REFFREQ*(n+2); + if (f_cur */ +/* Added Linear Addressing */ +/* Added BitBLT support */ +/* Added support for the HiQV chips */ +/* Programmable Clocks and XFree like modelines */ +/* 15/16 and 24bpp support */ +/* MODIFIED 1998: */ +/* Added support for 65555, 68554, 69000 and 64300 chips */ +/* Some smaller fixes (65554 memory probing, max. pixel */ +/* clock) */ +/* */ +/* Note that although this is a fully featured driver, it is still */ +/* considered to be experimental. It hasn't been exhaustively tested at */ +/* all with much code written from the specification sheets for chipset */ +/* and architectures that the author did have available. So sucess or */ +/* failure reports are most welcome. Please e-mail to "David Bateman */ +/* " */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Fixes 1998 for ct65550 by Christian Groessler */ +/* - modelines work now */ +/* - some smaller bugs fixed */ +/* - set XRE2 to BIOS video mode */ +/* - in vga.c: no usleep(MODESWITCHDELAY) when restoring */ +/* textmode -> textmode streching is restored correctly. */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* By default the text clock frequency is assumed to be 25.175MHz. */ +/* at the LCD and 28.322MHz at a CRT. This can be forced to be probed */ +/* by defining CHIPS_PROBE_TEXT_CLOCK below. Note that the probing */ +/* process can be unreliable. Alternatively the text clock can be */ +/* overridden from the libvga.config file with the TextClockFreq */ +/* option. */ +/*----------------------------------------------------------------------*/ +/* +#define CHIPS_PROBE_TEXT_CLOCK +*/ + +/*----------------------------------------------------------------------*/ +/* Normaly there is a 64K page at 0xA0000 that acts as a window */ +/* into video RAM located on the video adaptor. This window can */ +/* be moved around to allow all the video RAM to be accessed by */ +/* the CPU. Some chip sets allow two different windows to share */ +/* the same 64K page. The video adaptor differentiates between */ +/* the two windows by using the read/write signal provided by the */ +/* CPU, so that when it is reading from any location within the */ +/* 64K page at 0xA0000 it is reading through the read window */ +/* (often refered to as the read bank) and when it is writing to */ +/* any location within the 64K page at 0xA0000 it is writing */ +/* through the write window (often refered to as the write bank). */ +/* This allows the CPU to move data around the video RAM without */ +/* the overhead of continually changing the address of the window */ +/* between reads and writes. The Chips & Technologies chip set */ +/* does thing slightly differently. It allows the 64K page at */ +/* 0xA0000 to be split into two 32K pages, one at 0xA0000 and the */ +/* other at 0xA8000. These two pages provide two seperate windows */ +/* each of which can be accessed for both reading and writing data. */ +/*----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include /* sigprocmask */ +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +/* New style driver interface */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "accel.h" +#include "vgapci.h" + +#define FALSE 0 +#define TRUE (!FALSE) + +#define ENTER TRUE +#define LEAVE FALSE +typedef int Bool; + +static int CHIPSchipset; +static int video_memory; /* amount of video memory in K */ +static unsigned char ctVgaIOBaseFlag; +struct { + int HDisplay; + int HRetraceStart; + int HRetraceEnd; + int HTotal; + int VDisplay; + int VRetraceStart; + int VTotal; +} __svgalib_ctSize; +static Bool ctLCD=FALSE, ctCRT=TRUE; +/* Panel Types */ +unsigned char __svgalib_ctPanelType = 0; +#define TFT 1 +#define SS 2 /* STN Types */ +#define DS 4 +#define DD 6 +#define IS_STN(X) X&6 + +/* Masks for which option flags have been set */ +static int ctFlagsSet = 0; +#define ctFlags_LCDPanelSize 0x1 +#define ctFlags_UseModeline 0x2 +#define ctFlags_NoBitBlt 0x4 +#define ctFlags_Use18BitBus 0x8 +#define ctFlags_SetLinear 0x10 +#define ctFlags_StretchEnable 0x20 +#define ctFlags_StretchDisable 0x40 +#define ctFlags_CenterEnable 0x80 +#define ctFlags_CenterDisable 0x100 + +/* Global variables for acceleration support */ +static unsigned int ctROP = 0; /* Default to GXcopy */ +static unsigned int ctFGCOLOR; +static unsigned int ctBGCOLOR; +static unsigned int ctTRANSMODE = 0; /* Default to non transparency */ +static Bool ctMMIO=FALSE; /* Is the chip using MMIO */ +unsigned char *__svgalib_ctMMIOBase = NULL; /* MMIO base address */ +unsigned int __svgalib_ctMMIOPage = -1; /* MMIO paged base address */ +unsigned int __svgalib_CHIPS_LinearBase = -1; /* Linear FrameBuffer address */ +unsigned char *__svgalib_ctBltDataWindow = NULL; /* Window for Monochrome src data */ + +static void * MMIO_mem1, * MMIO_mem2; + +static int ct_video_mode(int bpp, int weight_green, int display_size); + +/* Forward definitions for accelerated support */ +static void CHIPS_ScreenCopy(int x1, int y1, int x2, int y2, int w, int h); +static void CHIPS_mmio_ScreenCopy(int x1, int y1, int x2, int y2, int w, + int h); +static void CHIPS_hiqv_ScreenCopy(int x1, int y1, int x2, int y2, int w, + int h); +void __svgalib_CHIPS_FillBox(int x, int y, int width, int height); +void __svgalib_CHIPS_mmio_FillBox(int x, int y, int width, int height); +void __svgalib_CHIPS_hiqv_FillBox(int x, int y, int width, int height); +void __svgalib_CHIPS_FillBox24(int x, int y, int width, int height); +void __svgalib_CHIPS_mmio_FillBox24(int x, int y, int width, int height); +void __svgalib_CHIPS_PutBitmap(int x, int y, int w, int h, void *bitmap); +void __svgalib_CHIPS_mmio_PutBitmap(int x, int y, int w, int h, void *bitmap); +void __svgalib_CHIPS_hiqv_PutBitmap(int x, int y, int w, int h, void *bitmap); +void __svgalib_CHIPS_SetRasterOp(int rop); +void __svgalib_CHIPS_SetBGColor(int fg); +void __svgalib_CHIPS_SetFGColor(int fg); +static void CHIPS_Sync(void); +static void CHIPS_mmio_Sync(void); +static void CHIPS_hiqv_Sync(void); +void __svgalib_CHIPS_SetTransparency(int mode, int color); + +/* alu to C&T conversion for use with source data */ +static unsigned int ctAluConv[] = +{ + 0xCC, /* ROP_COPY : dest = src; GXcopy */ + 0xEE, /* ROP_OR : dest |= src; GXor */ + 0x88, /* ROP_AND : dest &= src; GXand */ + 0x66, /* ROP_XOR : dest = ^src; GXxor */ + 0x55, /* ROP_INVERT : dest = ~dest; GXInvert */ +}; +/* alu to C&T conversion for use with pattern data */ +static unsigned int ctAluConv2[] = +{ + 0xF0, /* ROP_COPY : dest = src; GXcopy */ + 0xFC, /* ROP_OR : dest |= src; GXor */ + 0xA0, /* ROP_AND : dest &= src; GXand */ + 0x5A, /* ROP_XOR : dest = ^src; GXxor */ + 0x55, /* ROP_INVERT : dest = ~dest; GXInvert */ +}; + +/* Bitwise reversal of bytes, required for monochrome source expansion */ +unsigned char __svgalib_byte_reversed[256] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +/* Registers to save */ +unsigned char __svgalib_XRregs[] = +{ +0x02, 0x03, 0x04, 0x06, 0x07, 0x0B, 0x0D, 0x0F, 0x17, 0x19, +0x1A, 0x1B, 0x1C, 0x1E, 0x21, 0x22, 0x23, 0x28, 0x2C, 0x2D, +0x2F, 0x33, 0x40, 0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, +0x58, 0x5A, 0x64, 0x65, 0x66, 0x67, 0x68, 0x6F, +}; +unsigned char __svgalib_HiQVXRregs[] = +{ +0x09, 0x0A, 0x0E, 0x20, 0x40, 0x80, 0x81, 0xE2, +}; +unsigned char __svgalib_HiQVCRregs[] = +{ +0x30, 0x31, 0x32, 0x33, 0x38, 0x3C, 0x41, +}; +unsigned char __svgalib_HiQVFRregs[] = +{ +0x03, 0x08, 0x10, 0x11, 0x12, 0x20, 0x21, 0x22, 0x23, 0x24, +0x25, 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, +0x37, 0x40, 0x48, 0x73, +}; + +static int NUM_XRregs = (sizeof(__svgalib_XRregs) / sizeof(__svgalib_XRregs[0])); +static int NUM_HiQVXRregs = (sizeof(__svgalib_HiQVXRregs) / sizeof(__svgalib_HiQVXRregs[0])); +static int NUM_HiQVFRregs = (sizeof(__svgalib_HiQVFRregs) / sizeof(__svgalib_HiQVFRregs[0])); +static int NUM_HiQVCRregs = (sizeof(__svgalib_HiQVCRregs) / sizeof(__svgalib_HiQVCRregs[0])); +static int NUM_Clock = 5; +#define CHIPSREG_XR(i) (VGA_TOTAL_REGS + i) +#define CHIPSREG_HiQVXR(i) (VGA_TOTAL_REGS + NUM_XRregs + i) +#define CHIPSREG_HiQVFR(i) (VGA_TOTAL_REGS + NUM_XRregs + NUM_HiQVXRregs + i) +#define CHIPSREG_HiQVCR(i) (VGA_TOTAL_REGS + NUM_XRregs + NUM_HiQVXRregs + \ + NUM_HiQVFRregs + i) +#define CHIPS_CLOCK(i) (VGA_TOTAL_REGS + NUM_XRregs + NUM_HiQVXRregs + \ + NUM_HiQVFRregs + NUM_HiQVCRregs + i) +#define CHIPS_TOTAL_REGS (VGA_TOTAL_REGS + NUM_XRregs + NUM_HiQVXRregs + \ + NUM_HiQVFRregs + NUM_HiQVCRregs + NUM_Clock) +#define MSR CHIPS_CLOCK(0) +#define VCLK(i) CHIPS_CLOCK(1 + i) +#define XR02 CHIPSREG_XR(0) +#define XR03 CHIPSREG_XR(1) +#define XR04 CHIPSREG_XR(2) +#define XR06 CHIPSREG_XR(3) +#define XR07 CHIPSREG_XR(4) +#define XR0B CHIPSREG_XR(5) +#define XR0D CHIPSREG_XR(6) +#define XR0F CHIPSREG_XR(7) +#define XR17 CHIPSREG_XR(8) +#define XR19 CHIPSREG_XR(9) +#define XR1A CHIPSREG_XR(10) +#define XR1B CHIPSREG_XR(11) +#define XR1C CHIPSREG_XR(12) +#define XR1E CHIPSREG_XR(13) +#define XR21 CHIPSREG_XR(14) +#define XR22 CHIPSREG_XR(15) +#define XR23 CHIPSREG_XR(16) +#define XR28 CHIPSREG_XR(17) +#define XR2C CHIPSREG_XR(18) +#define XR2D CHIPSREG_XR(19) +#define XR2F CHIPSREG_XR(20) +#define XR33 CHIPSREG_XR(21) +#define XR40 CHIPSREG_XR(22) +#define XR50 CHIPSREG_XR(23) +#define XR51 CHIPSREG_XR(24) +#define XR52 CHIPSREG_XR(25) +#define XR54 CHIPSREG_XR(26) +#define XR55 CHIPSREG_XR(27) +#define XR56 CHIPSREG_XR(28) +#define XR57 CHIPSREG_XR(29) +#define XR58 CHIPSREG_XR(30) +#define XR5A CHIPSREG_XR(31) +#define XR64 CHIPSREG_XR(32) +#define XR65 CHIPSREG_XR(33) +#define XR66 CHIPSREG_XR(34) +#define XR67 CHIPSREG_XR(35) +#define XR68 CHIPSREG_XR(36) +#define XR6F CHIPSREG_XR(37) +#define HiQVXR09 CHIPSREG_HiQVXR(0) +#define HiQVXR0A CHIPSREG_HiQVXR(1) +#define HiQVXR0E CHIPSREG_HiQVXR(2) +#define HiQVXR20 CHIPSREG_HiQVXR(3) +#define HiQVXR40 CHIPSREG_HiQVXR(4) +#define HiQVXR80 CHIPSREG_HiQVXR(5) +#define HiQVXR81 CHIPSREG_HiQVXR(6) +#define HiQVXRE2 CHIPSREG_HiQVXR(7) + +#define HiQVFR03 CHIPSREG_HiQVFR(0) +#define HiQVFR08 CHIPSREG_HiQVFR(1) +#define HiQVFR10 CHIPSREG_HiQVFR(2) +#define HiQVFR11 CHIPSREG_HiQVFR(3) +#define HiQVFR12 CHIPSREG_HiQVFR(4) +#define HiQVFR20 CHIPSREG_HiQVFR(5) +#define HiQVFR21 CHIPSREG_HiQVFR(6) +#define HiQVFR22 CHIPSREG_HiQVFR(7) +#define HiQVFR23 CHIPSREG_HiQVFR(8) +#define HiQVFR24 CHIPSREG_HiQVFR(9) +#define HiQVFR25 CHIPSREG_HiQVFR(10) +#define HiQVFR26 CHIPSREG_HiQVFR(11) +#define HiQVFR27 CHIPSREG_HiQVFR(12) +#define HiQVFR30 CHIPSREG_HiQVFR(13) +#define HiQVFR31 CHIPSREG_HiQVFR(14) +#define HiQVFR32 CHIPSREG_HiQVFR(15) +#define HiQVFR33 CHIPSREG_HiQVFR(16) +#define HiQVFR34 CHIPSREG_HiQVFR(17) +#define HiQVFR35 CHIPSREG_HiQVFR(18) +#define HiQVFR36 CHIPSREG_HiQVFR(19) +#define HiQVFR37 CHIPSREG_HiQVFR(20) +#define HiQVFR40 CHIPSREG_HiQVFR(21) +#define HiQVFR48 CHIPSREG_HiQVFR(22) +#define HiQVFR73 CHIPSREG_HiQVFR(23) + +#define HiQVCR30 CHIPSREG_HiQVCR(0) +#define HiQVCR31 CHIPSREG_HiQVCR(1) +#define HiQVCR32 CHIPSREG_HiQVCR(2) +#define HiQVCR33 CHIPSREG_HiQVCR(3) +#define HiQVCR38 CHIPSREG_HiQVCR(4) +#define HiQVCR3C CHIPSREG_HiQVCR(5) +#define HiQVCR41 CHIPSREG_HiQVCR(6) + +/* Define the set of fixed H/W clocks used by those chips that don't + * support programmable clocks */ +#define CHIPS_NUM_CLOCKS 4 +static int chips_fixed_clocks[CHIPS_NUM_CLOCKS] = +{ + 25175, 28322, 31500, 35500 +}; +#ifndef CHIPS_PROBE_TEXT_CLOCK +#define LCD_TXT_CLOCK_FREQ 25175 +#define CRT_TXT_CLOCK_FREQ 28322 +#endif +static int ctTextClock = 0; +static int ctDacSpeed = 0; + +static int CHIPS_init(int, int, int); +static int CHIPS_interlaced(int mode); +static void CHIPS_EnterLeave(Bool enter); +static void CHIPS_setlinear(int addr); +static int vgaIOBase = 0; +static Bool ctisHiQV = FALSE; +static Bool PCIcard = FALSE; +static unsigned int chips_pcilinearbase = -1; + +#define CT_520 0 +#define CT_525 1 +#define CT_530 2 +#define CT_535 3 +#define CT_540 4 +#define CT_545 5 +#define CT_546 6 +#define CT_548 7 +#define CT_550 8 +#define CT_554 9 +#define CT_555 10 +#define CT_8554 11 +#define CT_9000 12 +#define CT_4300 13 + +static CardSpecs *cardspecs; + +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ +static void nothing(void) +{ +} + + +/*----------------------------------------------------------------------*/ +/* Fill in chipset specific mode information */ +/*----------------------------------------------------------------------*/ +static void CHIPS_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_getmodeinfo(%d, *)\n", mode); +#endif + if (modeinfo->bytesperpixel > 0) + { modeinfo->maxpixels = video_memory * 1024 / + modeinfo->bytesperpixel; + } + else + { modeinfo->maxpixels = video_memory * 1024; + } + + modeinfo->maxlogicalwidth = 2040; + modeinfo->linewidth_unit = 8; + modeinfo->startaddressrange = 0xfffff; + modeinfo->memory = video_memory; + + if (mode == G320x200x256) + { + /* Special case: bank boundary may not fall within display. */ + modeinfo->startaddressrange = 0xf0000; + + /* Hack: disable page flipping capability for the moment. */ + modeinfo->startaddressrange = 0xffff; + modeinfo->maxpixels = 65536; + } + + modeinfo->haveblit = 0; + if (CHIPS_interlaced(mode)) + { modeinfo->flags |= IS_INTERLACED; + } + if (CHIPSchipset != CT_520) + { + modeinfo->flags |= EXT_INFO_AVAILABLE | CAPABLE_LINEAR; + } + +#if defined(seperated_read_write_bank) + if (ctisHiQV) { + /* HiQV doesn't have seperate Read/Write pages */ + modeinfo->flags &= ~HAVE_RWPAGE; + } else { + modeinfo->flags |= HAVE_RWPAGE; + } +#else + modeinfo->flags &= ~HAVE_RWPAGE; +#endif +} + +static void ctHWCalcClock(unsigned char *vclk, unsigned int Clock) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: ctHWCalcClock(*, %d)\n", Clock); +#endif + vclk[MSR] = (Clock << 2) & 0xC; + vclk[XR54] = vclk[MSR]; + vclk[XR33] = 0; +} + +#define Fref 14318180 + +/* + * This is Ken Raeburn's clock + * calculation code just modified a little bit to fit in here. + */ + +static void ctCalcClock(unsigned char *vclk, unsigned int Clock) +{ + int M, N, P, PSN, PSNx; + + int bestM=0, bestN=0, bestP=0, bestPSN=0; + double bestError, abest = 42, bestFout=0; + double target; + + double Fvco, Fout; + double error, aerror; + + int M_min = 3; + + /* Hack to deal with problem of Toshiba 720CDT clock */ + int M_max = ctisHiQV ? 63 : 127; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: ctCalcClock(*, %d)\n", Clock); +#endif + + /* Other parameters available on the 65548 but not the 65545, and + * not documented in the Clock Synthesizer doc in rev 1.0 of the + * 65548 datasheet: + * + * + XR30[4] = 0, VCO divider loop uses divide by 4 (same as 65545) + * 1, VCO divider loop uses divide by 16 + * + * + XR30[5] = 1, reference clock is divided by 5 + * + * Other parameters available on the 65550 and not on the 65545 + * + * + XRCB[2] = 0, VCO divider loop uses divide by 4 (same as 65545) + * 1, VCO divider loop uses divide by 16 + * + * + XRCB[1] = 1, reference clock is divided by 5 + * + * + XRCB[7] = Vclk = Mclk + * + * + XRCA[0:1] = 2 MSB of a 10 bit M-Divisor + * + * + XRCA[4:5] = 2 MSB of a 10 bit N-Divisor + * + * I haven't put in any support for those here. For simplicity, + * they should be set to 0 on the 65548, and left untouched on + * earlier chips. */ + + target = Clock * 1000; + + for (PSNx = 0; PSNx <= 1; PSNx++) { + int low_N, high_N; + double Fref4PSN; + + PSN = PSNx ? 1 : 4; + + low_N = 3; + high_N = 127; + + while (Fref / (PSN * low_N) > 2.0e6) + low_N++; + while (Fref / (PSN * high_N) < 150.0e3) + high_N--; + + Fref4PSN = Fref * 4 / PSN; + for (N = low_N; N <= high_N; N++) { + double tmp = Fref4PSN / N; + + for (P = ctisHiQV ? 1 : 0; P <= 5; P++) { + /* to force post divisor on Toshiba 720CDT */ + double Fvco_desired = target * (1 << P); + double M_desired = Fvco_desired / tmp; + + /* Which way will M_desired be rounded? Do all three just to + * be safe. */ + int M_low = M_desired - 1; + int M_hi = M_desired + 1; + + if (M_hi < M_min || M_low > M_max) + continue; + + if (M_low < M_min) + M_low = M_min; + if (M_hi > M_max) + M_hi = M_max; + + for (M = M_low; M <= M_hi; M++) { + Fvco = tmp * M; + if (Fvco <= 48.0e6) + continue; + if (Fvco > 220.0e6) + break; + + Fout = Fvco / (1 << P); + + error = (target - Fout) / target; + + aerror = (error < 0) ? -error : error; + if (aerror < abest) { + abest = aerror; + bestError = error; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; + bestFout = Fout; + } + } + } + } + } + + if (ctisHiQV) { + vclk[MSR] = 3 << 2; + /* Leave non-clock bits of FR03 alone */ + vclk[HiQVFR03] = (vclk[HiQVFR03] & 0xF3) | vclk[MSR]; + vclk[VCLK(0)] = bestM - 2; + vclk[VCLK(1)] = bestN - 2; + vclk[VCLK(2)] = 0; + vclk[VCLK(3)] = (bestP << 4) + (bestPSN == 1); +#ifdef DEBUG + if (__svgalib_driver_report) { + fprintf(stderr,"Probed Freq: %.2f MHz", (float)(Clock / 1000.)); + fprintf(stderr,"VCLK(0) = %x, ",VCLK(0)); + fprintf(stderr,"VCLK(1) = %x, ",VCLK(1)); + fprintf(stderr,"VCLK(2) = %x, ",VCLK(2)); + fprintf(stderr,"VCLK(3) = %x\n",VCLK(3)); + fprintf(stderr,", vclk[0]=%X, vclk[1]=%X, vclk[2]=%X, vlck[3]=%X\n", + vclk[VCLK(0)], vclk[VCLK(1)], vclk[VCLK(2)], vclk[VCLK(3)]); + fprintf(stderr,"Freq used: %.2f MHz\n", bestFout / 1.0e6); + } +#endif + return; + } else { + vclk[MSR] = 3 << 2; + /* Leave non-clock bits of XR54 alone */ + vclk[XR54] = (vclk[XR54] & 0xF3) | vclk[MSR]; + vclk[VCLK(0)] = (bestP << 1) + (bestPSN == 1); + vclk[VCLK(1)] = bestM - 2; + vclk[VCLK(2)] = bestN - 2; +#ifdef DEBUG + if (__svgalib_driver_report) { + fprintf(stderr,"Probed Freq: %.2f MHz", (float)(Clock / 1000.)); + fprintf(stderr,", vclk[0]=%X, vclk[1]=%X, vclk[2]=%X\n", + vclk[VCLK(0)], vclk[VCLK(1)], vclk[VCLK(2)]); + fprintf(stderr,"Freq used: %.2f MHz\n", bestFout / 1.0e6); + } +#endif + return; + } + +} + +static void ctClockSave(unsigned char regs[]) +{ + unsigned char xr54, msr, temp; + int i; + unsigned int Clk; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: ctClockSave\n"); +#endif + + msr = port_in(0x3CC); /* save the standard VGA clock registers */ + regs[MSR] = msr; + + if (ctisHiQV) { + port_out_r(0x3D0,0x03); + regs[HiQVFR03] = port_in(0x3D1);/* save alternate clock select reg. */ + temp = (regs[HiQVFR03] & 0xC) >> 2; + if (temp == 3) + temp = 2; + temp = temp << 2; + for (i = 0; i < 4; i++) { + port_out_r(0x3D6,0xC0 + i + temp); + regs[VCLK(i)] = port_in(0x3D7); + } + } else { + port_out_r(0x3D6,0x33); /* get status of MCLK/VCLK select reg.*/ + regs[XR33] = port_in(0x3D7); + port_out_r(0x3D6,0x54); /* save alternate clock select reg. */ + xr54 = port_in(0x3D7); + regs[XR54] = xr54; + if ((CHIPSchipset == CT_535 || CHIPSchipset == CT_540 || + CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || + CHIPSchipset == CT_548 || CHIPSchipset == CT_4300) && + (((xr54 & 0xC) == 0xC) || ((xr54 & 0xC) == 0x8))) { + if (ctTextClock) { + Clk = ctTextClock; + } else { +#ifdef CHIPS_PROBE_TEXT_CLOCK + register int status = vgaIOBase + 0xA; + int maskval = 0x08; + int cnt, rcnt, sync; + int Clk1, Clk2; + sigset_t sig2block; + + /* If we are using a programmable clock, then there + * is no way to be sure that the register values + * correspond to those currently uploaded to the VCO. + * Hence we use the same ugly hack XFree uses to probe + * the value of the clock */ + + /* Disable the interrupts */ + sigfillset(&sig2block); + sigprocmask(SIG_BLOCK, &sig2block, (sigset_t *)NULL); + + /* Select Clk1 */ + port_out_r(0x3C2, (msr & 0xF2) | 0x4 | ctVgaIOBaseFlag); + port_out_r(0x3D6,0x54); + port_out_r(0x3D7,((xr54 & 0xF3) | 0x4)); + + usleep(50000); /* let VCO stabilise */ + + cnt = 0; + sync = 200000; + + while ((port_in(status) & maskval) == 0x00) + if (sync-- == 0) goto finishClk1; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((port_in(status) & maskval) == maskval) + if (sync-- == 0) goto finishClk1; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((port_in(status) & maskval) == 0x00) + if (sync-- == 0) goto finishClk1; + + for (rcnt = 0; rcnt < 5; rcnt++) + { + while (!(port_in(status) & maskval)) + cnt++; + while ((port_in(status) & maskval)) + cnt++; + } + + finishClk1: + Clk1 = cnt; + + /* Select Clk2 or Clk3 */ + port_out_r(0x3C2, (msr & 0xFE) | ctVgaIOBaseFlag); + port_out_r(0x3D6,0x54); + port_out_r(0x3D7,xr54); + + usleep(50000); /* let VCO stabilise */ + + cnt = 0; + sync = 200000; + + while ((port_in(status) & maskval) == 0x00) + if (sync-- == 0) goto finishClk2; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((port_in(status) & maskval) == maskval) + if (sync-- == 0) goto finishClk2; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((port_in(status) & maskval) == 0x00) + if (sync-- == 0) goto finishClk2; + + for (rcnt = 0; rcnt < 5; rcnt++) + { + while (!(port_in(status) & maskval)) + cnt++; + while ((port_in(status) & maskval)) + cnt++; + } + + finishClk2: + Clk2 = cnt; + + /* Re-enable the interrupts */ + sigprocmask(SIG_UNBLOCK, &sig2block, (sigset_t *)NULL); + + Clk = (int)(0.5 + (((float)28322) * Clk1) / Clk2); +#else /* CHIPS_PROBE_TEXT_CLOCK */ + if (ctLCD) { + Clk = LCD_TXT_CLOCK_FREQ; + } else { + Clk = CRT_TXT_CLOCK_FREQ; + } +#endif + } + /* Find a set of register settings that will give this + * clock */ + ctCalcClock(regs, Clk); + } + } + return; +} + +static void ctClockRestore(const unsigned char regs[]) +{ + unsigned char temp, msr; + int i; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: ctClockRestore\n"); +#endif + + msr = port_in(0x3CC); /* Select fixed clock */ + port_out_r(0x3C2, (msr & 0xFE) | ctVgaIOBaseFlag); + + if (ctisHiQV) { + port_out_r(0x3D0,0x03); + temp = port_in(0x3D1); + port_out_r(0x3D1, ((temp & ~0xC) | 0x04)); /* Select alt fixed clk */ + temp = (regs[HiQVFR03] & 0xC) >> 2; + if (temp == 3) + temp = 2; + temp = temp << 2; + for (i = 0; i < 4; i++) { + port_out_r(0x3D6,0xC0 + i + temp); + port_out_r(0x3D7,regs[VCLK(i)]); + } + port_out_r(0x3D0,0x03); + temp = port_in(0x3D1); + /* restore alternate clock select reg. */ + port_out_r(0x3D1,((regs[HiQVFR03]&0xC) | (temp&~0xC))); + } else { + port_out_r(0x3D6,0x54); /* Select alt fixed clk */ + temp = port_in(0x3D7); + port_out_r(0x3D7,((temp & 0xF3) | 0x4)); + + if ((CHIPSchipset == CT_535 || CHIPSchipset == CT_540 || + CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || + CHIPSchipset == CT_548 || CHIPSchipset == CT_4300) && + (((regs[XR54] & 0xC) == 0xC) || ((regs[XR54] & 0xC) == 0x8))) { + port_out_r(0x3D6,0x33); + temp = port_in(0x3D7); + port_out_r(0x3D7,(temp & ~0x20)); /* Select Vclk */ + port_out_r(0x3D6,0x30); + port_out_r(0x3D7,regs[VCLK(0)]); + port_out_r(0x3D6,0x31); + port_out_r(0x3D7,regs[VCLK(1)]); + port_out_r(0x3D6,0x32); + port_out_r(0x3D7,regs[VCLK(2)]); + } + port_out_r(0x3D6,0x33); /* restore status of MCLK/VCLK select reg.*/ + temp = port_in(0x3D7); + port_out_r(0x3D7,((regs[XR33] & 0x20) | (temp & ~0x20))); + port_out_r(0x3D6,0x54); /* restore alternate clock select reg. */ + temp = port_in(0x3D7); + port_out_r(0x3D7,((regs[XR54] & 0xC) | (temp & ~0xC))); + } + usleep(10000); + port_out_r(0x3C2, (regs[MSR] & 0xC) | (msr & 0xFE) | ctVgaIOBaseFlag); + usleep(10000); +} + +static int CHIPS_matchProgrammableClock(int clock) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_matchProgrammableClock(%d)\n",clock); +#endif + /* Basically we can program any valid clock */ + return clock; +} + +static int CHIPS_mapClock(int bpp, int pixelclock) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_mapClock(%d, %d)\n",bpp, pixelclock); +#endif + if (ctisHiQV) { + return pixelclock; + } else { + switch (bpp) { + case 24: + return pixelclock*3; + break; + case 16: + return pixelclock*2; + break; + case 15: + return pixelclock*2; + break; + default: + return pixelclock; + break; + } + } +} + +static int CHIPS_mapHorizontalCrtc(int bpp, int pixelclock, int htiming) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_mapHorizontalCrtc(%d, %d, %d)\n",bpp, pixelclock, + htiming); +#endif + if (ctisHiQV) { + return htiming; + } else { + switch (bpp) { + case 24: + return htiming*3; + break; + case 16: + return htiming*2; + break; + case 15: + return htiming*2; + break; + default: + return htiming; + break; + } + } +} + +static void CHIPS_unlock(void) +{ + unsigned char tmp; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_unlock\n"); +#endif + + /* set registers so that we can program the controller */ + if (ctisHiQV) { + port_outw_r(0x3D6, 0x0E); + } else { + port_outw_r(0x3D6, 0x10); +#if defined(seperated_read_write_bank) + port_outw_r(0x3D6, (1 << 11) | 0x11); +#endif + port_outw_r(0x3D6, 0x15); /* unprotect all registers */ + port_out_r(0x3D6, 0x14); + tmp = port_in(0x3D7); + port_out_r(0x3D7, (tmp & ~0x20)); /* enable vsync on ST01 */ + } + port_out_r(vgaIOBase + 4, 0x11); + tmp = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 5, (tmp & 0x7F)); /*group 0 protection off */ + +} + +/*----------------------------------------------------------------------*/ +/* Read and store chipset-specific registers */ +/*----------------------------------------------------------------------*/ +static int CHIPS_saveregs(unsigned char regs[]) +{ + int i; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_saveregs\n"); +#endif + + CHIPS_unlock(); + + if (ctisHiQV) { + for (i = 0; i < NUM_HiQVXRregs; i++) { + port_out_r(0x3D6,__svgalib_HiQVXRregs[i]); + regs[CHIPSREG_HiQVXR(i)] = port_in(0x3D7); + } + + for (i = 0; i < NUM_HiQVFRregs; i++) { + port_out_r(0x3D0,__svgalib_HiQVFRregs[i]); + regs[CHIPSREG_HiQVFR(i)] = port_in(0x3D1); + } + + for (i = 0; i < NUM_HiQVCRregs; i++) { + port_out_r(vgaIOBase + 4,__svgalib_HiQVCRregs[i]); + regs[CHIPSREG_HiQVCR(i)] = port_in(vgaIOBase + 5); + } + } else { + for (i = 0; i < NUM_XRregs; i++) { + port_out_r(0x3D6,__svgalib_XRregs[i]); + regs[CHIPSREG_XR(i)] = port_in(0x3D7); + } + } + ctClockSave(regs); + return CHIPS_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/*----------------------------------------------------------------------*/ +/* Set chipset-specific registers */ +/*----------------------------------------------------------------------*/ +static void CHIPS_setregs(const unsigned char regs[], int mode) +{ + int i,tmp; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setregs(*, %d)\n", mode); +#endif + + CHIPS_unlock(); + + while (((port_in(0x3DA)) & 0x08) == 0x08 );/* wait VSync off */ + while (((port_in(0x3DA)) & 0x08) == 0 ); /* wait VSync on */ + port_outw_r(SEQ_I,0x07); /* reset hsync - just in case... */ + + if (ctisHiQV) { + for (i = 0; i < NUM_HiQVXRregs; i++) { + port_out_r(0x3D6,__svgalib_HiQVXRregs[i]); + if (port_in(0x3D7) != regs[CHIPSREG_HiQVXR(i)]) + port_out_r(0x3D7,regs[CHIPSREG_HiQVXR(i)]); + } + + for (i = 0; i < NUM_HiQVFRregs; i++) { + if ((__svgalib_HiQVFRregs[i] == 0x40) || (__svgalib_HiQVFRregs[i] == 0x48)) { + /* Be careful to leave stretching off */ + port_out_r(0x3D0,__svgalib_HiQVFRregs[i]); + port_out_r(0x3D1,(regs[CHIPSREG_HiQVFR(i)]&0xFE)); + } else if (__svgalib_HiQVFRregs[i] == 0x3) { + /* Leave clock bits alone */ + port_out_r(0x3D0,3); + tmp = port_in(0x3D1); + port_out_r(0x3D0,3); + port_out_r(0x3D1,(regs[CHIPSREG_HiQVFR(i)] & 0xC3) | (tmp & ~0xC3)); + } else { + port_out_r(0x3D0,__svgalib_HiQVFRregs[i]); + if (port_in(0x3D1) != regs[CHIPSREG_HiQVFR(i)]) + port_out_r(0x3D1,regs[CHIPSREG_HiQVFR(i)]); + } + } + + for (i = 0; i < NUM_HiQVCRregs; i++) { + port_out_r(vgaIOBase + 4,__svgalib_HiQVCRregs[i]); + port_out_r(vgaIOBase + 5,regs[CHIPSREG_HiQVCR(i)]); + } + + } else { + for (i = 0; i < NUM_XRregs; i++) { + if ((__svgalib_XRregs[i] == 0x55) || (__svgalib_XRregs[i] == 0x57)) { + /* Be careful to leave stretching off */ + port_out_r(0x3D6,__svgalib_XRregs[i]); + port_out_r(0x3D7,(regs[CHIPSREG_XR(i)]&0xFE)); + } else if (__svgalib_XRregs[i] == 0x54) { + port_out_r(0x3D6, 0x54); + tmp = port_in(0x3D7); /* restore the non clock bits */ + port_out_r(0x3D6, 0x54); /* Don't touch alternate clock sel. reg. */ + port_out_r(0x3D7, ((regs[CHIPSREG_XR(i)] & 0xF3) | (tmp & ~0xF3))); + } else { + port_out_r(0x3D6,__svgalib_XRregs[i]); + port_out_r(0x3D7,regs[CHIPSREG_XR(i)]); + } + } + } + ctClockRestore(regs); + + /* Turn the stretching back on if needed. */ + if (ctisHiQV) { + /* Why Twice? It seems that strecthing on the text console is not + * always restored well even though the register contain the right + * values. Restoring them twice is a work around. */ + port_out_r(0x3D0, 0x40); + port_out_r(0x3D1, regs[HiQVFR40]); + port_out_r(0x3D0, 0x48); + port_out_r(0x3D1, regs[HiQVFR48]); + usleep(10000); + port_out_r(0x3D0, 0x40); + port_out_r(0x3D1, regs[HiQVFR40]); + port_out_r(0x3D0, 0x48); + port_out_r(0x3D1, regs[HiQVFR48]); + } else { + port_out_r(0x3D6, 0x55); + port_out_r(0x3D7, regs[XR55]); + port_out_r(0x3D6, 0x57); + port_out_r(0x3D7, regs[XR57]); + } + usleep(10000); +} + + + +/*----------------------------------------------------------------------*/ +/* Return nonzero if mode is available */ +/*----------------------------------------------------------------------*/ +static int CHIPS_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_modeavailable(%d)\n", mode); +#endif + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (video_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +/* Set a mode */ + +/* Local, called by CHIPS_setmode(). */ + +static void CHIPS_initializemode(unsigned char * moderegs, + ModeTiming * mode, ModeInfo * modeinfo) +{ + unsigned char tmp; + static int HSyncStart, HDisplay; + int lcdHTotal, lcdHDisplay; + int lcdVTotal, lcdVDisplay; + int lcdHRetraceStart, lcdHRetraceEnd; + int lcdVRetraceStart, lcdVRetraceEnd; + int CrtcHDisplay; + int temp; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_initializemode\n"); +#endif + + /* Get current values. Must be called before CalcClock */ + CHIPS_saveregs(moderegs); + + /* Set up the standard VGA registers for a generic SVGA. */ + __svgalib_setup_VGA_registers(moderegs, mode, modeinfo); + + /* store orig. HSyncStart needed for flat panel mode */ + HSyncStart = mode->CrtcHSyncStart / modeinfo->bytesPerPixel - 16; + HDisplay = (mode->CrtcHDisplay + 1) / modeinfo->bytesPerPixel; + + /* init clock */ + if ((CHIPSchipset == CT_520) || (CHIPSchipset == CT_525) || + (CHIPSchipset == CT_530)) { + ctHWCalcClock(moderegs,mode->selectedClockNo); + } else { + ctCalcClock(moderegs,mode->programmedClock); + } + + moderegs[VGA_AR10] = 0x01; /* mode */ + moderegs[VGA_AR11] = 0x00; /* overscan (border) color */ + moderegs[VGA_AR12] = 0x0F; /* enable all color planes */ + moderegs[VGA_AR13] = 0x00; /* horiz pixel panning 0 */ + moderegs[VGA_GR5] = 0x00; /* normal read/write mode */ + moderegs[VGA_CR13] = ((mode->CrtcHDisplay) >> 3) & 0xFF ; + moderegs[XR1E] = ((mode->CrtcHDisplay) >> 3) & 0xFF ; + moderegs[XR0D] = (((mode->CrtcHDisplay) >> 11) & 0x1) | + (((mode->CrtcHDisplay) >> 10) & 0x2); + + moderegs[XR04] |= 4; /* enable addr counter bits 16-17 */ +#if defined(seperated_read_write_bank) + moderegs[XR0B] = moderegs[XR0B] | 0x7; /* extended mode, dual maps */ +#else + moderegs[XR0B] = (moderegs[XR0B] & 0xF8) | 0x5; /* single maps */ +#endif + moderegs[XR28] |= 0x10; /* 256-colour video */ + + /* Setup extended display timings */ + if (ctCRT) { + /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */ + moderegs[XR17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) + | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) + | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) + | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2) + | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 4) + | (((mode->CrtcHSyncEnd >> 3) & 0x40) >> 1); + } else { + /* horizontal timing registers */ + /* in LCD/dual mode use saved bios values to derive timing values if + * not told otherwise*/ + if (!(ctFlagsSet & ctFlags_UseModeline)) { + lcdHTotal = __svgalib_ctSize.HTotal; + lcdHRetraceStart = __svgalib_ctSize.HRetraceStart; + lcdHRetraceEnd = __svgalib_ctSize.HRetraceEnd; + if (modeinfo->bitsPerPixel == 16) { + lcdHRetraceStart <<= 1; + lcdHRetraceEnd <<= 1; + lcdHTotal <<= 1; + } else if (modeinfo->bitsPerPixel == 24) { + lcdHRetraceStart += (lcdHRetraceStart << 1); + lcdHRetraceEnd += (lcdHRetraceEnd << 1); + lcdHTotal += (lcdHTotal << 1); + } + lcdHRetraceStart -=8; /* HBlank = HRetrace - 1: for */ + lcdHRetraceEnd -=8; /* compatibility with vgaHW.c */ + } else { + /* use modeline values if bios values don't work */ + lcdHTotal = mode->CrtcHTotal; + lcdHRetraceStart = mode->CrtcHSyncStart; + lcdHRetraceEnd = mode->CrtcHSyncEnd; + } + /* The chip takes the size of the visible display area from the + * CRTC values. We use bios screensize for LCD in LCD/dual mode + * wether or not we use modeline for LCD. This way we can specify + * always specify a smaller than default display size on LCD + * by writing it to the CRTC registers. */ + lcdHDisplay = __svgalib_ctSize.HDisplay; + if (modeinfo->bitsPerPixel == 16) { + lcdHDisplay++; + lcdHDisplay <<= 1; + lcdHDisplay--; + } else if (modeinfo->bitsPerPixel == 24) { + lcdHDisplay++; + lcdHDisplay += (lcdHDisplay << 1); + lcdHDisplay--; + } + lcdHTotal = (lcdHTotal >> 3) - 5; + lcdHDisplay = (lcdHDisplay >> 3) - 1; + lcdHRetraceStart = (lcdHRetraceStart >> 3); + lcdHRetraceEnd = (lcdHRetraceEnd >> 3); + /* This ugly hack is needed because CR01 and XR1C share the 8th bit!*/ + CrtcHDisplay = ((mode->CrtcHDisplay >> 3) - 1); + if((lcdHDisplay & 0x100) != ( CrtcHDisplay & 0x100)){ + fprintf(stderr,"This display configuration might cause problems !\n"); + lcdHDisplay = 255;} + + /* now init register values */ + moderegs[XR17] = (((lcdHTotal) & 0x100) >> 8) + | ((lcdHDisplay & 0x100) >> 7) + | ((lcdHRetraceStart & 0x100) >> 6) + | (((lcdHRetraceEnd) & 0x20) >> 2); + moderegs[XR19] = lcdHRetraceStart & 0xFF; + moderegs[XR1A] = lcdHRetraceEnd & 0x1F; + moderegs[XR1B] = lcdHTotal & 0xFF; + moderegs[XR1C] = lcdHDisplay & 0xFF; + + if (ctFlagsSet & ctFlags_UseModeline) { + /* for ext. packed pixel mode on 64520/64530 */ + /* no need to rescale: used only in 65530 */ + moderegs[XR21] = lcdHRetraceStart & 0xFF; + moderegs[XR22] = lcdHRetraceEnd & 0x1F; + moderegs[XR23] = lcdHTotal & 0xFF; + + /* vertical timing registers */ + lcdVTotal = mode->CrtcVTotal - 2; + lcdVDisplay = __svgalib_ctSize.VDisplay - 1; + lcdVRetraceStart = mode->CrtcVSyncStart; + lcdVRetraceEnd = mode->CrtcVSyncEnd; + + moderegs[XR64] = lcdVTotal & 0xFF; + moderegs[XR66] = lcdVRetraceStart & 0xFF; + moderegs[XR67] = lcdVRetraceEnd & 0x0F; + moderegs[XR68] = lcdVDisplay & 0xFF; + moderegs[XR65] = ((lcdVTotal & 0x100) >> 8) + | ((lcdVDisplay & 0x100) >> 7) + | ((lcdVRetraceStart & 0x100) >> 6) + | ((lcdVRetraceStart & 0x400) >> 7) + | ((lcdVTotal & 0x400) >> 6) + | ((lcdVTotal & 0x200) >> 4) + | ((lcdVDisplay & 0x200) >> 3) + | ((lcdVRetraceStart & 0x200) >> 2); + + /* + * These are important: 0x2C specifies the numbers of lines + * (hsync pulses) between vertical blank start and vertical + * line total, 0x2D specifies the number of clock ticks? to + * horiz. blank start ( caution ! 16bpp/24bpp modes: that's + * why we need HSyncStart - can't use mode->CrtcHSyncStart) + */ + tmp = ((__svgalib_ctPanelType == DD) && !(moderegs[XR6F] & 0x02)) + ? 1 : 0; /* double LP delay, FLM: 2 lines iff DD+no acc*/ + /* Currently we support 2 FLM scemes: #1: FLM coincides with + * VTotal ie. the delay is programmed to the difference bet- + * ween lctVTotal and lcdVRetraceStart. #2: FLM coincides + * lcdVRetraceStart - in this case FLM delay will be turned + * off. To decide which sceme to use we compare the value of + * XR2C set by the bios to the two scemes. The one that fits + * better will be used. + */ + if (moderegs[XR2C] + < abs((__svgalib_ctSize.VTotal - __svgalib_ctSize.VRetraceStart + - tmp - 1) - moderegs[XR2C])) + moderegs[XR2F] |= 0x80; /* turn FLM delay off */ + moderegs[XR2C] = lcdVTotal - lcdVRetraceStart - tmp; + /*moderegs[XR2D] = (HSyncStart >> (3 - tmp)) & 0xFF;*/ + moderegs[XR2D] = (HDisplay >> (3 - tmp)) & 0xFF; + moderegs[XR2F] = (moderegs[XR2F] & 0xDF) + | (((HSyncStart >> (3 - tmp)) & 0x100) >> 3); + } + + if ((ctFlagsSet & ctFlags_StretchEnable) || + (ctFlagsSet & ctFlags_StretchDisable) || + (ctFlagsSet & ctFlags_CenterEnable) || + (ctFlagsSet & ctFlags_CenterDisable)) { + moderegs[XR51] |= 0x40; /* enable FP compensation */ + moderegs[XR55] |= 0x01; /* enable horiz compensation */ + moderegs[XR57] |= 0x01; /* enable vert compensation */ + moderegs[XR57] &= 0x7F; /* disable fast-centre */ + moderegs[XR58] = 0; + } + + /* Screen Centering */ + moderegs[XR57]|=0x01; + if (ctFlagsSet & ctFlags_CenterEnable) { + moderegs[XR57] |= 0x02; /* enable v-centring */ + if (mode->CrtcHDisplay < 1489) /* HWBug */ + moderegs[XR55] |= 0x02; /* enable h-centring */ + else if (modeinfo->bitsPerPixel == 24) { + moderegs[XR55] &= ~0x02; + moderegs[XR56] = (lcdHDisplay - CrtcHDisplay) >> 1; + } + } else if (ctFlagsSet & ctFlags_CenterDisable) { + moderegs[XR55] &= 0xFD; /* disable h-centering */ + moderegs[XR56] = 0; + moderegs[XR57] &= 0xFD; /* disable v-centering */ + } + + /* Screen Stretching */ + if (ctFlagsSet & ctFlags_StretchEnable) { + moderegs[XR55] |= 0x20; /* h-comp on, h-double off */ + moderegs[XR57] |= 0x60; /* vertical stretching on */ + fprintf(stderr,"0x%X, 0x%X\n", mode->flags, DOUBLESCAN); + fprintf(stderr,"%d, %d\n", mode->CrtcVDisplay, __svgalib_ctSize.VDisplay); + if (2*mode->CrtcVDisplay <= __svgalib_ctSize.VDisplay) + { + /* We assume that automatic double scanning occurs */ + if (2 * mode->CrtcVDisplay == __svgalib_ctSize.VDisplay) + temp = 0; + else + temp = (( 2 * mode->CrtcVDisplay) / (__svgalib_ctSize.VDisplay - + (2 * mode->CrtcVDisplay))); + } else { + if (mode->CrtcVDisplay == __svgalib_ctSize.VDisplay) + temp = 0; + else + temp = (mode->CrtcVDisplay / (__svgalib_ctSize.VDisplay - + mode->CrtcVDisplay)); + } + moderegs[XR5A] = temp > 0x0F ? 0 : (unsigned char)temp; + } else if (ctFlagsSet & ctFlags_StretchDisable) { + moderegs[XR55] &= 0xDF; + moderegs[XR57] &= 0x9F; + } + } + + moderegs[XR03] |= 0x02; /* 32 bit I/O enable etc. */ + moderegs[XR07] = 0xF4; /* 32 bit I/O port selection */ + moderegs[XR03] |= 0x08; /* High bandwidth on 65548 */ + moderegs[XR40] = 0x01; /*BitBLT Draw Mode for 8 and 24 bpp*/ + + moderegs[XR52] |= 0x01; /* Refresh count */ + moderegs[XR0F] &= 0xEF; /* not Hi-/True-Colour */ + moderegs[XR02] |= 0x01; /* 16bit CPU Memory Access */ + moderegs[XR02] &= 0xE3; /* Attr. Cont. default access */ + /* use ext. regs. for hor. in dual */ + moderegs[XR06] &= 0xF3; /* bpp clear */ + + if (PCIcard) + moderegs[XR03] |= 0x40; /* PCI Burst for 65548 */ + + /* sync. polarities */ + if ((mode->flags & (PHSYNC | NHSYNC)) + && (mode->flags & (PVSYNC | NVSYNC))) { + if (mode->flags & (PHSYNC | NHSYNC)) { + if (mode->flags & PHSYNC) { + moderegs[XR55] &= 0xBF; /* CRT Hsync positive */ + } else { + moderegs[XR55] |= 0x40; /* CRT Hsync negative */ + } + } + if (mode->flags & (PVSYNC | NVSYNC)) { + if (mode->flags & PVSYNC) { + moderegs[XR55] &= 0x7F; /* CRT Vsync positive */ + } else { + moderegs[XR55] |= 0x80; /* CRT Vsync negative */ + } + } + } + + if (modeinfo->bitsPerPixel == 16) { + moderegs[XR06] |= 0xC4; /*15 or 16 bpp colour */ + moderegs[XR0F] |= 0x10; /*Hi-/True-Colour */ + moderegs[XR40] = 0x02; /*BitBLT Draw Mode for 16 bpp */ + if (modeinfo->greenWeight != 5) + moderegs[XR06] |= 0x08; /*16bpp */ + } else if (modeinfo->bitsPerPixel == 24) { + moderegs[XR06] |= 0xC8; /*24 bpp colour */ + moderegs[XR0F] |= 0x10; /*Hi-/True-Colour */ + if (ctFlagsSet & ctFlags_Use18BitBus) { + moderegs[XR50] &= 0x7F; /*18 bit TFT data width */ + } else { + moderegs[XR50] |= 0x80; /*24 bit TFT data width */ + } + } + + /* STN specific */ + if (IS_STN(__svgalib_ctPanelType)) { + moderegs[XR50] &= ~0x03; /* FRC clear */ + moderegs[XR50] |= 0x01; /* 16 frame FRC */ + moderegs[XR50] &= ~0x0C; /* Dither clear */ + moderegs[XR50] |= 0x08; /* Dither all modes */ + if (CHIPSchipset == CT_548) { + moderegs[XR03] |= 0x20; /* CRT I/F priority */ + moderegs[XR04] |= 0x10; /* RAS precharge 65548 */ + } + } +} + +static void CHIPS_HiQV_initializemode(unsigned char *moderegs, + ModeTiming * mode, ModeInfo * modeinfo) +{ + int lcdHTotal, lcdHDisplay; + int lcdVTotal, lcdVDisplay; + int lcdHRetraceStart, lcdHRetraceEnd; + int lcdVRetraceStart, lcdVRetraceEnd; + int lcdHSyncStart; + unsigned int temp; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_HiQV_initializemode\n"); +#endif + + /* Get current values. Must be called before CalcClock */ + CHIPS_saveregs(moderegs); + + /* Set up the standard VGA registers for a generic SVGA. */ + __svgalib_setup_VGA_registers(moderegs, mode, modeinfo); + + /* init clock */ +#ifdef DEBUG + fprintf(stderr,"CHIPS: pixelclock used: %d\n",mode->pixelClock); +#endif + ctCalcClock(moderegs,mode->pixelClock); + + moderegs[VGA_AR10] = 0x01; /* mode */ + moderegs[VGA_AR11] = 0x00; /* overscan (border) color */ + moderegs[VGA_AR12] = 0x0F; /* enable all color planes */ + moderegs[VGA_AR13] = 0x00; /* horiz pixel panning 0 */ + moderegs[VGA_GR5] = 0x00; /* normal read/write mode */ + + temp = mode->CrtcHDisplay >> 3; /* bytes per scan line, 256 color mode */ + if (modeinfo->bitsPerPixel == 24) { + temp += temp << 1; /* -> x3 in 16M color mode */ + } else if (modeinfo->bitsPerPixel == 16) { + temp <<= 1; /* or x2 in 64K color mode */ + } + moderegs[VGA_CR13] = (temp) & 0xFF; /* bytes of fb memory per scan line */ + moderegs[HiQVCR41] = (temp >> 8) & 0xF; /* upper 4 bits of it, as HiQVXR09[0] is set to 1 */ + + moderegs[HiQVXR0A] |= 0x1; /* Paging mode enabled, nolinear */ + moderegs[HiQVXR09] |= 0x1; /* Enable extended CRT registers */ + moderegs[HiQVXR0E] = 0; /* Single map */ + moderegs[HiQVXR40] |= 0x3; /* High Resolution. XR40[1] reserved? */ + moderegs[HiQVXR81] &= 0xF8; /* 256 Color Video */ + moderegs[HiQVXR81] |= 0x2; + moderegs[HiQVXR80] |= 0x10; /* Enable cursor output on P0 and P1 */ + moderegs[HiQVXR20] = 0x0; /* BitBLT Draw mode for 8bpp */ + + /* panel timing */ + /* By default don't set panel timings, but allow it as an option */ + if (ctFlagsSet & ctFlags_UseModeline) { + lcdHTotal = (mode->CrtcHTotal >> 3) - 5; + lcdHDisplay = (__svgalib_ctSize.HDisplay >> 3) - 1; + lcdHRetraceStart = (mode->CrtcHSyncStart >> 3); + lcdHRetraceEnd = (mode->CrtcHSyncEnd >> 3); + lcdHSyncStart = lcdHRetraceStart - 2; + + lcdVTotal = mode->CrtcVTotal - 2; + lcdVDisplay = __svgalib_ctSize.VDisplay - 1; + lcdVRetraceStart = mode->CrtcVSyncStart; + lcdVRetraceEnd = mode->CrtcVSyncEnd; + +#ifdef MODELINE_DEBUG + fprintf(stderr,"lcdHTotal = %d, lcdHDisplay = %d, lcdHRetraceStart = %d\n", + lcdHTotal,lcdHDisplay,lcdHRetraceStart); + fprintf(stderr,"lcdHRetraceEnd = %d, lcdHSyncStart = %d\n",lcdHRetraceEnd,lcdHSyncStart); + fprintf(stderr,"lcdVTotal = %d, lcdVDisplay = %d, lcdVretraceStart = %d\n", + lcdVTotal,lcdVDisplay,lcdVRetraceStart); + + fprintf(stderr,"before:\n"); + fprintf(stderr,"#20 = %02X, #21 = %02X, #22 = %02X, #23 = %02X, #24 = %02X, #25 = %02X\n", + moderegs[HiQVFR20],moderegs[HiQVFR21],moderegs[HiQVFR22],moderegs[HiQVFR23], + moderegs[HiQVFR24],moderegs[HiQVFR25]); + fprintf(stderr,"#26 = %02X, #27 = %02X\n", + moderegs[HiQVFR26],moderegs[HiQVFR27]); + fprintf(stderr,"#30 = %02X, #31 = %02X, #32 = %02X, #33 = %02X, #34 = %02X, #35 = %02X\n", + moderegs[HiQVFR30],moderegs[HiQVFR31],moderegs[HiQVFR32],moderegs[HiQVFR33], + moderegs[HiQVFR34],moderegs[HiQVFR35]); + fprintf(stderr,"#36 = %02X, #37 = %02X\n", + moderegs[HiQVFR36],moderegs[HiQVFR37]); +#endif + + moderegs[HiQVFR20] = lcdHDisplay & 0xFF; + moderegs[HiQVFR21] = lcdHRetraceStart & 0xFF; + moderegs[HiQVFR25] = ((lcdHRetraceStart & 0xF00) >> 4) | + ((lcdHDisplay & 0xF00) >> 8); + moderegs[HiQVFR22] = lcdHRetraceEnd & 0x1F; + moderegs[HiQVFR23] = lcdHTotal & 0xFF; + moderegs[HiQVFR24] = (lcdHSyncStart >> 3) & 0xFF; + moderegs[HiQVFR26] = (moderegs[HiQVFR26] & ~0x1F) + | ((lcdHTotal & 0xF00) >> 8) + | (((lcdHSyncStart >> 3) & 0x100) >> 4); + moderegs[HiQVFR27] &= 0x7F; + + moderegs[HiQVFR30] = lcdVDisplay & 0xFF; + moderegs[HiQVFR31] = lcdVRetraceStart & 0xFF; + moderegs[HiQVFR35] = ((lcdVRetraceStart & 0xF00) >> 4) + | ((lcdVDisplay & 0xF00) >> 8); + moderegs[HiQVFR32] = lcdVRetraceEnd & 0x0F; + moderegs[HiQVFR33] = lcdVTotal & 0xFF; + moderegs[HiQVFR34] = (lcdVTotal - lcdVRetraceStart) & 0xFF; + moderegs[HiQVFR36] = ((lcdVTotal & 0xF00) >> 8) | + (((lcdVTotal - lcdVRetraceStart) & 0x700) >> 4); + moderegs[HiQVFR37] |= 0x80; + +#ifdef MODELINE_DEBUG + fprintf(stderr,"after:\n"); + fprintf(stderr,"#20 = %02X, #21 = %02X, #22 = %02X, #23 = %02X, #24 = %02X, #25 = %02X\n", + moderegs[HiQVFR20],moderegs[HiQVFR21],moderegs[HiQVFR22],moderegs[HiQVFR23], + moderegs[HiQVFR24],moderegs[HiQVFR25]); + fprintf(stderr,"#26 = %02X, #27 = %02X\n", + moderegs[HiQVFR26],moderegs[HiQVFR27]); + fprintf(stderr,"#30 = %02X, #31 = %02X, #32 = %02X, #33 = %02X, #34 = %02X, #35 = %02X\n", + moderegs[HiQVFR30],moderegs[HiQVFR31],moderegs[HiQVFR32],moderegs[HiQVFR33], + moderegs[HiQVFR34],moderegs[HiQVFR35]); + fprintf(stderr,"#36 = %02X, #37 = %02X\n", + moderegs[HiQVFR36],moderegs[HiQVFR37]); +#endif + } + + /* Set up the extended CRT registers of the HiQV32 chips */ + moderegs[HiQVCR30] = ((mode->CrtcVTotal - 2) & 0xF00) >> 8; + moderegs[HiQVCR31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8; + moderegs[HiQVCR32] = (mode->CrtcVSyncStart & 0xF00) >> 8; + moderegs[HiQVCR33] = (mode->CrtcVSyncStart & 0xF00) >> 8; + if (CHIPSchipset == CT_9000) { + /* The 69000 has overflow bits for the horizontal values as well */ + moderegs[HiQVCR38] = (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8; + moderegs[HiQVCR3C] = ((mode->CrtcHSyncEnd >> 3) & 0xC0); + } + + /* Screen Centring */ + if (ctFlagsSet & ctFlags_CenterEnable) { + moderegs[HiQVFR40] |= 0x3; /* Enable Horizontal centering */ + moderegs[HiQVFR48] |= 0x3; /* Enable Vertical centering */ + } else if (ctFlagsSet & ctFlags_CenterDisable) { + moderegs[HiQVFR40] &= 0xFD; /* Disable Horizontal centering */ + moderegs[HiQVFR48] &= 0xFD; /* Disable Vertical centering */ + } + + /* Screen Stretching */ + if (ctFlagsSet & ctFlags_StretchEnable) { + moderegs[HiQVFR40] |= 0x21; /* Enable Horizontal stretching */ + moderegs[HiQVFR48] |= 0x05; /* Enable Vertical stretching */ + } else if (ctFlagsSet & ctFlags_StretchDisable) { + moderegs[HiQVFR40] &= 0xDF; /* Disable Horizontal stretching */ + moderegs[HiQVFR48] &= 0xFB; /* Disable Vertical stretching */ + } + + moderegs[HiQVXRE2] = ct_video_mode(modeinfo->bitsPerPixel, + modeinfo->greenWeight, + __svgalib_ctSize.HDisplay); + + /* sync. polarities */ + if ((mode->flags & (PHSYNC | NHSYNC)) + && (mode->flags & (PVSYNC | NVSYNC))) { + if (mode->flags & (PHSYNC | NHSYNC)) { + if (mode->flags & PHSYNC) + moderegs[HiQVFR08] &= 0xBF; /* Alt. CRT Hsync positive */ + else + moderegs[HiQVFR08] |= 0x40; /* Alt. CRT Hsync negative */ + } + if (mode->flags & (PVSYNC | NVSYNC)) { + if (mode->flags & PVSYNC) + moderegs[HiQVFR08] &= 0x7F; /* Alt. CRT Vsync positive */ + else + moderegs[HiQVFR08] |= 0x80; /* Alt. CRT Vsync negative */ + } + } + + if (modeinfo->bitsPerPixel == 16) { + moderegs[HiQVXR81] = (moderegs[HiQVXR81] & 0xF0) | 0x4; /* 15bpp */ + moderegs[HiQVFR10] |= 0x0C; /*Colour Panel */ + moderegs[HiQVXR20] = 0x10; /*BitBLT Draw Mode for 16 bpp */ + if (modeinfo->greenWeight != 5) + moderegs[HiQVXR81] |= 0x01; /*16bpp */ + } else if (modeinfo->bitsPerPixel == 24) { + moderegs[HiQVXR81] = (moderegs[HiQVXR81] & 0xF0) | 0x6; /* 24bpp */ + moderegs[HiQVXR20] = 0x20; /*BitBLT Draw Mode for 24 bpp */ + } + + /* STN specific */ + if (IS_STN(__svgalib_ctPanelType)) { + moderegs[HiQVFR11] &= ~0x03;/* FRC clear */ + moderegs[HiQVFR11] &= ~0x8C;/* Dither clear */ + moderegs[HiQVFR11] |= 0x01; /* 16 frame FRC */ + moderegs[HiQVFR11] |= 0x84; /* Dither */ + if (CHIPSchipset == CT_555 || CHIPSchipset == CT_8554 || + CHIPSchipset == CT_9000) { + moderegs[HiQVFR73] &= 0x4f; + moderegs[HiQVFR73] |= 0x80; + moderegs[HiQVFR73] |= 0x30; + } + + if (__svgalib_ctPanelType == DD) /* Shift Clock Mask. Use to get */ + moderegs[HiQVFR12] |= 0x4;/* rid of line in DSTN screens */ + } + +} + + +/*----------------------------------------------------------------------*/ +/* Check if mode is interlaced */ +/*----------------------------------------------------------------------*/ +static int CHIPS_interlaced(int mode) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_interlaced(%d)\n",mode); +#endif + /* This driver does not support interlaced mode */ + return FALSE; +} + + +/*----------------------------------------------------------------------*/ +/* Set a mode */ +/*----------------------------------------------------------------------*/ +static int CHIPS_setmode(int mode, int prv_mode) +{ + unsigned char *regs; + ModeInfo *modeinfo; + ModeTiming *modetiming; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setmode(%d, %d)\n", mode, prv_mode); +#endif + + if (CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || + CHIPSchipset == CT_548 || CHIPSchipset == CT_550 || + CHIPSchipset == CT_554 || CHIPSchipset == CT_555 || + CHIPSchipset == CT_8554 || CHIPSchipset == CT_9000 || + CHIPSchipset == CT_4300) { + __svgalib_driverspecs->accelspecs->operations = 0; + __svgalib_driverspecs->accelspecs->ropOperations = 0; + __svgalib_driverspecs->accelspecs->transparencyOperations = 0; + __svgalib_driverspecs->accelspecs->ropModes = 0; + __svgalib_driverspecs->accelspecs->transparencyModes = 0; + } + + if (!CHIPS_modeavailable(mode)) + { return 1; + } + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return (int) (__svgalib_vga_driverspecs.setmode(mode, prv_mode)); + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + +#ifdef MODELINE_DEBUG + /*------------------------------------*/ + fprintf(stderr,"Modetiming:\n"); + fprintf(stderr,"pixelclock - %d, HDisplay - %d, HSyncStart - %d, HSyncEnd - %d, HTotal - %d\n", + modetiming->pixelClock,modetiming->HDisplay,modetiming->HSyncStart, + modetiming->HSyncEnd,modetiming->HTotal); + fprintf(stderr,"VDisplay - %d, VSyncStart - %d, VSyncEnd - %d, VTotal - %d, flags - %d\n", + modetiming->VDisplay,modetiming->VSyncStart,modetiming->VSyncEnd, + modetiming->VTotal,modetiming->flags); + fprintf(stderr,"programmedClock - %d, selectedClockNo - %d, CrtcHDisplay - %d\n", + modetiming->programmedClock,modetiming->selectedClockNo,modetiming->CrtcHDisplay); + fprintf(stderr,"CrtcHSyncStart - %d, CrtcHSyncEnd - %d, CrtcHDisplay - %d, CrtcHTotal - %d\n", + modetiming->CrtcHSyncStart,modetiming->CrtcHSyncEnd,modetiming->CrtcHDisplay, + modetiming->CrtcHTotal); + fprintf(stderr,"CrtcVSyncStart - %d, CrtcVSyncEnd - %d, CrtcVTotal - %d\n\n", + modetiming->CrtcVSyncStart,modetiming->CrtcVSyncEnd,modetiming->CrtcVTotal); + + fprintf(stderr,"ModeInfo:\n"); + fprintf(stderr,"width - %d, height - %d, bytesPerPixel - %d, bitsPerPixel - %d\n", + (int)modeinfo->width,(int)modeinfo->height,(int)modeinfo->bytesPerPixel, + (int)modeinfo->bitsPerPixel); + fprintf(stderr,"colorBits - %d, redWeight - %d, greenWeight - %d, blueWeight - %d\n", + (int)modeinfo->colorBits,(int)modeinfo->redWeight,(int)modeinfo->greenWeight, + (int)modeinfo->blueWeight); + fprintf(stderr,"redOffset - %d, blueOffset - %d, greenOffset - %d\n", + (int)modeinfo->redOffset,(int)modeinfo->blueOffset, + (int)modeinfo->greenOffset); + fprintf(stderr,"redMask - %d, blueMask - %d, greenMask - %d, lineWidth - %d\n", + (int)modeinfo->redMask,(int)modeinfo->blueMask,(int)modeinfo->greenMask, + modeinfo->lineWidth); + fprintf(stderr,"realWidth - %d, realHeight - %d, flags - %d\n\n", + (int)modeinfo->realWidth,(int)modeinfo->realHeight,modeinfo->flags); + + fprintf(stderr,"CardSpecs:\n"); + fprintf(stderr,"videoMemory - %d, maxPixelClock8bpp - %d, flags - %d\n", + cardspecs->videoMemory,cardspecs->maxPixelClock8bpp, + cardspecs->flags); + fprintf(stderr,"nClocks - %d, maxHorizontalCrtc - %d, mapClock - %p\n", + cardspecs->nClocks,cardspecs->maxHorizontalCrtc, + cardspecs->mapClock); + fprintf(stderr,"matchProgrammableClock - %p, mapHorizontalCrtc - %p\n", + cardspecs->matchProgrammableClock,cardspecs->mapHorizontalCrtc); + + /*------------------------------------*/ +#endif + + regs = malloc(CHIPS_TOTAL_REGS); + if (ctisHiQV) { + CHIPS_HiQV_initializemode(regs, modetiming, modeinfo); + } else { + CHIPS_initializemode(regs, modetiming, modeinfo); + } + free(modetiming); + + __svgalib_setregs(regs); + CHIPS_setregs(regs, mode); + + if (ctFlagsSet & ctFlags_NoBitBlt) return 0; + + if (CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || + CHIPSchipset == CT_548) { + if (PCIcard) { + /* We are a PCI machine */ + if (__svgalib_modeinfo_linearset & IS_LINEAR) { + /* Linear addressing is enabled. So we can use + * MMIO with linear addressing. Map the required + * memory space + */ + ctMMIO = TRUE; + __svgalib_ctMMIOPage = -1; + if (__svgalib_ctMMIOBase == NULL) { + __svgalib_ctMMIOBase = MMIO_mem1; + } + } else { + if (CHIPSchipset == CT_545 || CHIPSchipset == CT_546) { + /* We are a 65545 or 65546 PCI machine. We only + * support acceleration on these machines with MMIO. + * Hence we have to use page mode to access the + * MMIO registers. + */ + ctMMIO = TRUE; + __svgalib_ctMMIOPage = 32; /* MMIO starts at 2MBytes */ + __svgalib_ctMMIOBase = __svgalib_graph_mem; + } else { + /* Let the register address acceleration handle this */ + ctMMIO = FALSE; + } + } + } + } + + if (ctisHiQV) { + if (__svgalib_modeinfo_linearset & IS_LINEAR) { + /* Linear addressing is enabled. So we can use + * MMIO with linear addressing. Map the required + * memory space + */ + ctMMIO = TRUE; + __svgalib_ctMMIOPage = -1; + if (__svgalib_ctMMIOBase == NULL) { + __svgalib_ctMMIOBase=MMIO_mem2; + } + __svgalib_ctBltDataWindow = __svgalib_ctMMIOBase + 0x10000; + } else { + /* Use paged addressing mode to program the MMIO registers */ + ctMMIO = TRUE; + __svgalib_ctMMIOPage = 64; /* MMIO starts at 4MBytes */ + __svgalib_ctMMIOBase = __svgalib_graph_mem; + __svgalib_ctBltDataWindow = __svgalib_graph_mem; + } + } + + if (CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || + CHIPSchipset == CT_548 || CHIPSchipset == CT_550 || + CHIPSchipset == CT_554 || CHIPSchipset == CT_555 || + CHIPSchipset == CT_8554 || CHIPSchipset == CT_9000 || + CHIPSchipset == CT_4300) { + __svgalib_InitializeAcceleratorInterface(modeinfo); + + __svgalib_driverspecs->accelspecs->operations = + ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | + ACCELFLAG_SETBGCOLOR | ACCELFLAG_SCREENCOPY | + ACCELFLAG_SETRASTEROP | ACCELFLAG_SETTRANSPARENCY | + ACCELFLAG_SYNC; + __svgalib_driverspecs->accelspecs->ropModes = (1<accelspecs->transparencyModes = + (1<bitsPerPixel == 24)) { + __svgalib_driverspecs->accelspecs->ropOperations = + ACCELFLAG_SCREENCOPY; + } else { + __svgalib_driverspecs->accelspecs->ropOperations = + ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY; + } + + if ((CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || + CHIPSchipset == CT_548 || CHIPSchipset == CT_4300) + && (modeinfo->bitsPerPixel == 24)) { + /* For now PutBitmap is only supported on 6554x's. I + * don't have a 65550 machine to debug it on */ + __svgalib_driverspecs->accelspecs->operations |= + ACCELFLAG_PUTBITMAP; + __svgalib_driverspecs->accelspecs->ropOperations |= + ACCELFLAG_PUTBITMAP; + __svgalib_driverspecs->accelspecs->transparencyOperations |= + ACCELFLAG_PUTBITMAP; + } + + /* Set the function pointers; availability is handled by flags. */ + __svgalib_driverspecs->accelspecs->SetFGColor = __svgalib_CHIPS_SetFGColor; + __svgalib_driverspecs->accelspecs->SetBGColor = __svgalib_CHIPS_SetBGColor; + __svgalib_driverspecs->accelspecs->SetRasterOp = __svgalib_CHIPS_SetRasterOp; + __svgalib_driverspecs->accelspecs->SetTransparency = __svgalib_CHIPS_SetTransparency; + if (ctMMIO) { + if (ctisHiQV) { + __svgalib_driverspecs->accelspecs->FillBox = __svgalib_CHIPS_hiqv_FillBox; + __svgalib_driverspecs->accelspecs->ScreenCopy = CHIPS_hiqv_ScreenCopy; + __svgalib_driverspecs->accelspecs->Sync = CHIPS_hiqv_Sync; + } else { + if (modeinfo->bitsPerPixel == 24) { + __svgalib_driverspecs->accelspecs->FillBox = __svgalib_CHIPS_mmio_FillBox24; + } else { + __svgalib_driverspecs->accelspecs->FillBox = __svgalib_CHIPS_mmio_FillBox; + __svgalib_driverspecs->accelspecs->PutBitmap = __svgalib_CHIPS_mmio_PutBitmap; + } + __svgalib_driverspecs->accelspecs->ScreenCopy = CHIPS_mmio_ScreenCopy; + __svgalib_driverspecs->accelspecs->Sync = CHIPS_mmio_Sync; + } + } else { + if (modeinfo->bitsPerPixel == 24) { + __svgalib_driverspecs->accelspecs->FillBox = __svgalib_CHIPS_FillBox24; + } else { + __svgalib_driverspecs->accelspecs->FillBox = __svgalib_CHIPS_FillBox; + __svgalib_driverspecs->accelspecs->PutBitmap = __svgalib_CHIPS_PutBitmap; + } + __svgalib_driverspecs->accelspecs->ScreenCopy = CHIPS_ScreenCopy; + __svgalib_driverspecs->accelspecs->Sync = CHIPS_Sync; + } + } + return 0; +} + +/* Enable linear mode (0 to turn off) */ + +static void CHIPS_setlinear(int addr) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setlinear(0x%X)\n", addr); +#endif + + if (ctisHiQV) { + port_out_r(0x3D6, 0x0A); + if (addr) + port_out_r(0x3D7, port_in(0x3D7) | 0x02); /* enable linear mode */ + else + port_out_r(0x3D7, port_in(0x3D7) & ~0x02); /* disable linear mode */ + } else { + port_out_r(0x3D6, 0x0B); + if (addr) + port_out_r(0x3D7, port_in(0x3D7) | 0x10); /* enable linear mode */ + else + port_out_r(0x3D7, port_in(0x3D7) & ~0x10); /* disable linear mode */ + } +} + +static int CHIPS_linear(int op, int param) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_linear(%d, %d)\n", op, param); +#endif + + if (CHIPSchipset != CT_520) { /* The 65520 doesn't support it */ + if (op == LINEAR_ENABLE) { + CHIPS_setlinear(1); + return 0; + } + if (op == LINEAR_DISABLE) { + CHIPS_setlinear(0); + return 0; + } + if (op == LINEAR_QUERY_BASE) { + + /* First deal with the user set MEMBASE */ + if (ctFlagsSet & ctFlags_SetLinear) { + switch (param) { + case 0: + return __svgalib_CHIPS_LinearBase; + break; + default: + return -1; + break; + } + } + + __svgalib_CHIPS_LinearBase = -1; + + if (PCIcard) { + if (param == 0) { + __svgalib_CHIPS_LinearBase = chips_pcilinearbase; +#ifdef DEBUG + fprintf(stderr,"CHIPS_linear: base = %08X\n",__svgalib_CHIPS_LinearBase); +#endif + } else { + /* As the above PCI membase probing code is new + * keep the old code around too as a fallback + */ + switch (param) { + case 1: + __svgalib_CHIPS_LinearBase = 0xFE000000; + break; + case 2: + __svgalib_CHIPS_LinearBase = 0xC0000000; + break; + case 3: + __svgalib_CHIPS_LinearBase = 0xFD000000; + break; + case 4: + __svgalib_CHIPS_LinearBase = 0x41000000; + break; + default: + __svgalib_CHIPS_LinearBase = -1; + break; + } + } + } else { + if (param == 0) { + if (ctisHiQV) { + port_out_r(0x3D6, 0x6); + __svgalib_CHIPS_LinearBase = ((0xFF & port_in(0x3D7)) << 24); + port_out_r(0x3D6, 0x5); + __svgalib_CHIPS_LinearBase |= ((0x80 & port_in(0x3D7)) << 16); + } else { + port_out_r(0x3D6, 0x8); + __svgalib_CHIPS_LinearBase = ((0xFF & port_in(0x3D7)) << 20); + } + } + } + return __svgalib_CHIPS_LinearBase; + } + } + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + else + return -1; /* Unknown function. */ +} + + +/*----------------------------------------------------------------------*/ +/* Indentify chipset; return non-zero if detected */ +/*----------------------------------------------------------------------*/ +static int CHIPS_test(void) +{ + unsigned char temp; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_test\n"); +#endif + + /* + * OK. We have to actually test the hardware. The + * EnterLeave() function (described below) unlocks access + * to registers that may be locked, and for OSs that require + * it, enables I/O access. So we do this before we probe, + * even though we don't know for sure that this chipset + * is present. + */ + CHIPS_EnterLeave(ENTER); + + /* + * Here is where all of the probing code should be placed. + * The best advice is to look at what the other drivers are + * doing. If you are lucky, the chipset reference will tell + * how to do this. Other resources include SuperProbe/vgadoc2, + * and the Ferraro book. + */ + port_out_r(0x3D6, 0x00); + temp = port_in(0x3D6+1); + +/* + * Reading 0x103 causes segmentation violation, like 46E8 ??? + * So for now just force what I want! + * + * Need to look at ioctl(console_fd, PCCONIOCMAPPORT, &ior) + * for bsdi! + */ + CHIPSchipset = 99; + + if (temp != 0xA5) + { + if ((temp & 0xF0) == 0x70) + { CHIPSchipset = CT_520; + } + else + if ((temp & 0xF0) == 0x80) /* Could also be a 65525 */ + { CHIPSchipset = CT_530; + } + else + if ((temp & 0xF8) == 0xC0) + { CHIPSchipset = CT_535; + } + else + if ((temp & 0xF8) == 0xD0) + { CHIPSchipset = CT_540; + } + else + if ((temp & 0xF8) == 0xD8) + { + switch (temp&0x7) { + case 3: + CHIPSchipset = CT_546; + break; + case 4: + CHIPSchipset = CT_548; + break; + default: + CHIPSchipset = CT_545; + } + } + } + + /* At this point the chip could still be a ct65550, so check */ + if ((temp != 0) && (CHIPSchipset == 99)) { + port_out_r(0x3D6, 0x02); + temp = port_in(0x03D7); + if (temp == 0xE0) { + CHIPSchipset = CT_550; + ctisHiQV = TRUE; + } + if (temp == 0xE4) { + CHIPSchipset = CT_554; + ctisHiQV = TRUE; + } + if (temp == 0xE5) { + CHIPSchipset = CT_555; + ctisHiQV = TRUE; + } + if (temp == 0xF4) { + CHIPSchipset = CT_8554; + ctisHiQV = TRUE; + } + if ((temp == 0xC0) || (temp == 0x30)) { /* 0x30 is for 69030 */ + CHIPSchipset = CT_9000; + ctisHiQV = TRUE; + } + } + + if (CHIPSchipset == 99) + { /* failure, if no good, then leave */ + + /* + * Turn things back off if the probe is going to fail. + * Returning FALSE implies failure, and the server + * will go on to the next driver. + */ + CHIPS_EnterLeave(LEAVE); + + return(FALSE); + } + + + CHIPS_init(0, 0, 0); + + return TRUE; +} + + +/*----------------------------------------------------------------------*/ +/* CHIPS_EnterLeave -- */ +/* */ +/* This function is called when the virtual terminal on which the */ +/* server is running is entered or left, as well as when the server */ +/* starts up and is shut down. Its function is to obtain and */ +/* relinquish I/O permissions for the SVGA device. This includes */ +/* unlocking access to any registers that may be protected on the */ +/* chipset, and locking those registers again on exit. */ +/* */ +/*----------------------------------------------------------------------*/ +static void CHIPS_EnterLeave(Bool enter) +{ + unsigned char temp; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_EnterLeave(%d)\n", enter); +#endif + + /* (taken from XFree86) */ + + if (enter) + { + /* + * This is a global. The CRTC base address depends on + * whether the VGA is functioning in color or mono mode. + * This is just a convenient place to initialize this + * variable. + */ + vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; + + /* + * Here we deal with register-level access locks. This + * is a generic VGA protection; most SVGA chipsets have + * similar register locks for their extended registers + * as well. + */ + /* Unprotect CRTC[0-7] */ + port_out_r(vgaIOBase + 4, 0x11); temp = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 5, temp & 0x7F); + + /* Enters Setup Mode */ +/* port_out_r(0x46E8, port_in(0x46E8) | 16); */ + + /* Extension registers access enable */ +/* port_out_r(0x103, port_in(0x103) | 0x80); */ + } + else + { + /* + * Here undo what was done above. + */ + /* Exits Setup Mode */ +/* port_out_r(0x46E8, port_in(0x46E8) & 0xEF); */ + + /* Extension registers access disable */ +/* port_out_r(0x103, port_in(0x103) & 0x7F); */ + + /* Protect CRTC[0-7] */ + port_out_r(vgaIOBase + 4, 0x11); temp = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 5, (temp & 0x7F) | 0x80); + } +} + + +/*----------------------------------------------------------------------*/ +/* Bank switching function - set 64K bank number */ +/*----------------------------------------------------------------------*/ +static void CHIPS_setpage(int page) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setpage(%d)\n",page); +#endif + + if (ctisHiQV) { + port_outw_r(0x3D6, ((page&0x7F) << 8) | 0x0E); + } else { +#if !defined(seperated_read_write_bank) + port_outw_r(0x3D6, (page << 12) | 0x10); /* bank 0 ( 64k window at 0xA0000 )*/ + if (CHIPSchipset == CT_4300) { + unsigned char tmp; + port_out_r(0x3D6, 0x0C); + tmp = port_in(0x3D7) & 0xEF; + port_outw_r(0x3D6, ((((page & 0x10) | tmp) << 8) | 0x0C)); + } +#else + int temp; + temp = (page << 12); + port_outw_r(0x3D6, temp | 0x10); /* bank 0 ( 32k window at 0xA0000 ) */ + port_outw_r(0x3D6, temp + ((1 << 11) | 0x11)); /* bank 1 ( 32k window at 0xA8000 ) */ + if (CHIPSchipset == CT_4300) { + unsigned char tmp; + port_out_r(0x3D6, 0x0C); + tmp = port_in(0x3D7) & 0xAF; + port_outw_r(0x3D6, ((((page & 0x10) | (( ((page << 2) + 2) & 0x40) | + tmp) << 8) | 0x0C)); + } +#endif + } + +} + +/*----------------------------------------------------------------------*/ +/* W A R N I N G : */ +/* when using seperate banks, each bank can only access a maximum */ +/* of 32k. bank0 is accessed at 0xA0000 .. 0xA7FFF and bank1 */ +/* is accessed at 0xA8000 .. 0xAFFFF */ +/* The GL library shipped with SVGALIB expects to be able to */ +/* access a 64k contiguoius window at 0xA0000 .. 0xAFFFF */ +/*----------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------*/ +/* Bank switching function - set 32K bank number */ +/* WARNING: this function uses a granularity or 32k not 64k */ +/*----------------------------------------------------------------------*/ +static void CHIPS_setreadpage(int page) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setreadpage(%d)\n",page); +#endif + if (CHIPSchipset == CT_4300) { + unsigned char tmp; + port_outw_r(0x3D6, (page << 11) | 0x10); /* bank 0 */ + port_out_r(0x3D6, 0x0C); + tmp = port_in(0x3D7) & 0xEF; + port_outw_r(0x3D6, (((((page >> 1) & 0x10) | tmp) << 8) | 0x0C)); + } else { + port_outw_r(0x3D6, (page << 11) | 0x10); /* bank 0 */ + } +} + +/*----------------------------------------------------------------------*/ +/* Bank switching function - set 32K bank number */ +/* WARNING: this function uses a granularity or 32k not 64k */ +/*----------------------------------------------------------------------*/ +static void CHIPS_setwritepage(int page) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setwritepage(%d)\n",page); +#endif + if (CHIPSchipset == CT_4300) { + unsigned char tmp; + port_outw_r(0x3D6, (page << 11) | 0x11); /* bank 1 */ + port_out_r(0x3D6, 0x0C); + tmp = port_in(0x3D7) & 0xBF; + port_outw_r(0x3D6, (((((page << 1) & 0x40) | tmp) << 8) | 0x0C)); + } else { + port_outw_r(0x3D6, (page << 11) | 0x11); /* bank 1 */ + } +} + + +/*----------------------------------------------------------------------*/ +/* Set display start address (not for 16 color modes) */ +/*----------------------------------------------------------------------*/ +static void CHIPS_setdisplaystart(int addr) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setdisplaystart(%d)\n",addr); +#endif + + addr >>= 2; + + /* + * These are the generic starting address registers. + * (taken from XFree86) + */ + port_outw_r(vgaIOBase + 4, (addr & 0x00FF00) | 0x0C); + port_outw_r(vgaIOBase + 4, ((addr & 0x00FF) << 8) | 0x0D); + + /* + * Here the high-order bits are masked and shifted, and put into + * the appropriate extended registers. + */ + /* MH - plug in the high order starting address bits */ + if (ctisHiQV) { + port_out_r(0x3D6, 0x09); + if ((port_in(0x3D7) & 0x1) == 0x1) + port_outw_r(vgaIOBase + 4, ((addr & 0x0F0000) >> 8) | 0x8000 | 0x40); + } else { + port_out_r(0x3D6, 0x0C); + port_out_r(0x3D7, ((addr & 0xFF0000) >> 16)); + } +} + +/*----------------------------------------------------------------------*/ +/* Set logical scanline length (usually multiple of 8) */ +/*----------------------------------------------------------------------*/ +static void CHIPS_setlogicalwidth(int width) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_setlogicalwidth(%d)\n",width); +#endif + + port_outw_r(vgaIOBase + 4, 0x13 | (((width >> 3) << 8) & 0xFF00)); + if (ctisHiQV) { + port_outw_r(vgaIOBase + 4, 0x41 | ((width >>3) & 0xF00)); + } else { + port_out_r(0x3D6,0x1E); + port_out_r(0x3D7,((width>>3)&0xFF)); + port_out_r(0x3D6,0x0D); + port_out_r(0x3D7,(((width>>11)&0x1)|((width>>10)&0x2))); + } +} + + +/*----------------------------------------------------------------------*/ +/* Function table */ +/*----------------------------------------------------------------------*/ +DriverSpecs __svgalib_chips_driverspecs = +{ + CHIPS_saveregs, + CHIPS_setregs, + nothing, /* unlock */ + nothing, /* lock */ + CHIPS_test, + CHIPS_init, + CHIPS_setpage, + CHIPS_setreadpage, + CHIPS_setwritepage, + CHIPS_setmode, + CHIPS_modeavailable, + CHIPS_setdisplaystart, + CHIPS_setlogicalwidth, + CHIPS_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + CHIPS_linear, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + +/* Chips and Technologies specific config file options. + * Currently this only handles setting the text clock frequency. + */ + +static char *CHIPS_config_options[] = +{ + "TextClockFreq", "LCDPanelSize", "UseModeline", "NoBitBlt", + "Use18BitBus", "setuplinear", "Stretch", "Center", "DacSpeed", NULL +}; + +static char *CHIPS_process_option(int option, int mode, char** dummy) +{ +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_process_option(%d, %d)\n",option, mode); +#endif +/* + * option is the number of the option string in CHIPS_config_options, + * mode seems to be a security indicator. + */ + if (option == 0) { /* TextClockFreq */ + char *ptr; + ptr = strtok(NULL, " "); + /* + * This doesn't protect against bad characters + * (atof() doesn't detect errors). + */ + ctTextClock = (int)(atof(ptr) * 1000.); + } + if (option == 1) { /* LCDPanelSize */ + char *ptr; + ptr = strtok(NULL, " "); + /* + * This doesn't protect against bad characters + * (atoi() doesn't detect errors). + */ + __svgalib_ctSize.HDisplay = atoi(ptr); + ptr = strtok(NULL, " "); + __svgalib_ctSize.VDisplay = atoi(ptr); + ctFlagsSet |= ctFlags_LCDPanelSize; + } + if (option == 2) { /* UseModeline */ + ctFlagsSet |= ctFlags_UseModeline; + } + if (option == 3) { /* NoBitBlt */ + ctFlagsSet |= ctFlags_NoBitBlt; + } + if (option == 4) { /* Use18bitBus */ + ctFlagsSet |= ctFlags_Use18BitBus; + } + if (option == 5) { /* setuplinear */ + char c; + unsigned int value; + char *ptr; + + ptr = strtok(NULL, " "); + c = *ptr++; + c = *ptr++; + value = 0; + while ((c = *ptr++)) { /* Double brackets to stop gcc warning */ + if(c >= '0' && c <= '9') + value = (value << 4) | (c - '0'); /*ASCII assumed*/ + else if(c >= 'A' && c < 'G') + value = (value << 4) | (c - 'A'+10); /*ASCII assumed*/ + else if(c >= 'a' && c < 'g') + value = (value << 4) | (c - 'a'+10); /*ASCII assumed*/ + } + __svgalib_CHIPS_LinearBase = value; + ptr = strtok(NULL, " "); + ctFlagsSet |= ctFlags_SetLinear; + } + if (option == 6) { /* Stretch */ + /* Enable or disable stretching in horizontal and vertical + * directions. Note that the default is to leave this stuff + * alone */ + char *ptr; + ptr = strtok(NULL, " "); + if (!(strcasecmp(ptr, "ENABLE"))) { + ctFlagsSet |= ctFlags_StretchEnable; + ctFlagsSet &= ~ctFlags_StretchDisable; + } else if (!(strcasecmp(ptr, "DISABLE"))) { + ctFlagsSet |= ctFlags_StretchDisable; + ctFlagsSet &= ~ctFlags_StretchEnable; + } + } + if (option == 7) { /* Center */ + /* Enable or disable centring of the mode in horizontal and + * vertical directions. Note that the default is to leave + * this stuff alone */ + char *ptr; + ptr = strtok(NULL, " "); + if (!(strcasecmp(ptr, "ENABLE"))) { + ctFlagsSet |= ctFlags_CenterEnable; + ctFlagsSet &= ~ctFlags_CenterDisable; + } else if (!(strcasecmp(ptr, "DISABLE"))) { + ctFlagsSet |= ctFlags_CenterDisable; + ctFlagsSet &= ~ctFlags_CenterEnable; + } + } + if (option == 8) { /* DacSpeed */ + char *ptr; + ptr = strtok(NULL, " "); + /* + * This doesn't protect against bad characters + * (atof() doesn't detect errors). + */ + ctDacSpeed = (int)(atof(ptr) * 1000.); + } + return strtok(NULL, " "); +} + +/*----------------------------------------------------------------------*/ +/* Initialize chipset (called after detection) */ +/*----------------------------------------------------------------------*/ +static int CHIPS_init(int force, int par1, int par2) +{ + int temp; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: CHIPS_init(%d, %d, %d)\n", force, par1, par2); +#endif + + if (force) { + CHIPS_EnterLeave(ENTER); + CHIPSchipset = par1; + video_memory = par2; + if (CHIPSchipset == CT_550 || CHIPSchipset == CT_554 || + CHIPSchipset == CT_555 || CHIPSchipset == CT_8554 || + CHIPSchipset == CT_9000) + ctisHiQV = TRUE; + } else { + /* + * do whatever chipset-specific things are necessary + * to figure out how much memory (in kBytes) is + * available. + */ + if (ctisHiQV) { + switch (CHIPSchipset) { + case CT_9000: + /* The ct69000 has 2Mb of SGRAM integrated */ + /* 69030 has 4MB, needs to be fixed */ + video_memory = 2048; + break; + case CT_550: + port_out_r(0x3D6, 0x43); + switch ((port_in(0x3D7) & 0x06) >> 1) { + case 0: + video_memory = 1024; + break; + case 1: + video_memory = 2048; + break; + case 2: + case 3: + video_memory = 4096; + break; + } + default: + port_out_r(0x3D6, 0xE0); + switch (port_in(0x3D7) & 0xF) { + case 0: + video_memory = 512; + break; + case 1: + video_memory = 1024; + break; + case 2: + video_memory = 1536; + break; + case 3: + video_memory = 2048; + break; + case 7: + video_memory = 4096; + break; + default: + video_memory = 1024; + break; + } + } + } else { + port_out_r(0x3D6, 0x0F); + temp = port_in(0x3D7); + switch (temp & 3) { + case 0: + video_memory = 256; + break; + case 1: + video_memory = 512; + break; + case 2: + video_memory = 1024; + break; + case 3: + if (CHIPSchipset == CT_4300) + video_memory = 2048; + else + video_memory = 1024; + break; + } + } + } + + /* check whether this is a PCI card */ + if (ctisHiQV) { + port_out_r(0x3D6,0x08); + PCIcard = (((port_in(0x3D7) & 1) == 1) ? TRUE : FALSE); + } else { + port_out_r(0x3D6,0x01); + PCIcard = (((port_in(0x3D7) & 7) == 6) ? TRUE : FALSE); + } + + /* get linear base address from PCI config space */ + if (PCIcard) { + unsigned int buf[64]; + + /* Find PCI config with C&T vendor ID 0x102C */ + if (__svgalib_pci_find_vendor_vga_pos(0x102C,buf)) { + chips_pcilinearbase = buf[4] & 0xFF800000; + } + } + + /* Process the chips and technologies specific config file options */ + __svgalib_read_options(CHIPS_config_options, CHIPS_process_option); + + if (ctisHiQV) { + /*test STN / TFT */ + port_out_r(0x3D0, 0x10); + temp = port_in(0x3D1); + + /* FR10[1:0]: PanelType, */ + /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ + switch (temp & 0x3) { + case 0: + __svgalib_ctPanelType = TFT; + break; + case 2: + __svgalib_ctPanelType = DS; + break; + case 3: + __svgalib_ctPanelType = DD; + break; + default: + break; + } + + /* test LCD */ + /* FR01[1:0]: Display Type, 01 = CRT, 10 = FlatPanel */ + /* LCD */ + port_out_r(0x3D0, 0x01); + temp = port_in(0x3D1); + if ((temp & 0x03) == 0x02) { + ctLCD = TRUE; + ctCRT = FALSE; + } else { + ctLCD = FALSE; + ctCRT = TRUE; + } + if (ctLCD) { + /* get H/VDisplay values for screen size */ + + unsigned char fr25,tmp1; + + if (!(ctFlagsSet & ctFlags_LCDPanelSize)) { /* read only if necessary */ + port_out_r(0x3D0,0x25); + fr25=port_in(0x3D1); + port_out_r(0x3D0,0x20); + temp=port_in(0x3D1); + __svgalib_ctSize.HDisplay = ((temp + ((fr25 & 0x0F) << 8)) + 1) << 3; + port_out_r(0x3D0,0x30); + temp=port_in(0x3D1); + port_out_r(0x3D0,0x35); + tmp1=port_in(0x3D1); + __svgalib_ctSize.VDisplay = ((tmp1 & 0x0F) << 8) + temp + 1; + } + } + } else if (CHIPSchipset != CT_4300) { + + /*test STN / TFT */ + port_out_r(0x3D6, 0x51); + temp = port_in(0x3D7); + /* XR51[1-0]: PanelType, */ + /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ + switch (temp & 0x3) { + case 0: + __svgalib_ctPanelType = TFT; + break; + case 2: + __svgalib_ctPanelType = DS; + break; + case 3: + __svgalib_ctPanelType = DD; + break; + default: + break; + } + + /* test LCD */ + if (temp & 0x4) { + /* XR51[2]: Display Type, 0 = CRT, 1 = FlatPanel */ + /* LCD */ + ctLCD = TRUE; + ctCRT = FALSE; + } else { + ctLCD = FALSE; + ctCRT = TRUE; + } + + /* screen size */ + /* + * In LCD mode / dual mode we want to derive the timing + * values from the ones preset by bios + */ + if (ctLCD) { + unsigned char xr17, tmp1; + char tmp2; + + port_out_r(0x3D6,0x17); + xr17=port_in(0x3D7); + port_out_r(0x3D6,0x1B); + temp=port_in(0x3D7); + __svgalib_ctSize.HTotal = ((temp + ((xr17 & 0x01) << 8)) + 5) << 3; + if (!(ctFlagsSet & ctFlags_LCDPanelSize)) { + port_out_r(0x3D6,0x1C); + temp=port_in(0x3D7); + __svgalib_ctSize.HDisplay = ((temp + ((xr17 & 0x02) << 7)) + 1) << 3; + } + port_out_r(0x3D6,0x19); + temp=port_in(0x3D7); + __svgalib_ctSize.HRetraceStart = ((temp + ((xr17 & 0x04) << 9)) + + 1) << 3; + port_out_r(0x3D6,0x1A); + tmp1=port_in(0x3D7); + tmp2 = (tmp1 & 0x1F) + ((xr17 & 0x08) << 2) - (temp & 0x3F); + __svgalib_ctSize.HRetraceEnd = ((((tmp2 < 0) ? (tmp2 + 0x40) : tmp2) + << 3) + __svgalib_ctSize.HRetraceStart); + port_out_r(0x3D6,0x65); + tmp1=port_in(0x3D7); + if (!(ctFlagsSet & ctFlags_LCDPanelSize)) { + port_out_r(0x3D6,0x68); + temp=port_in(0x3D7); + __svgalib_ctSize.VDisplay = ((tmp1 & 0x02) << 7) + + ((tmp1 & 0x40) << 3) + temp + 1; + } + port_out_r(0x3D6,0x66); + temp=port_in(0x3D7); + __svgalib_ctSize.VRetraceStart = ((tmp1 & 0x04) << 6) + + ((tmp1 & 0x80) << 2) + temp + 1; + port_out_r(0x3D6,0x64); + temp=port_in(0x3D7); + __svgalib_ctSize.VTotal = ((tmp1 & 0x01) << 8) + + ((tmp1 & 0x20) << 4) + temp + 2; +#ifdef DEBUG + fprintf(stderr,"__svgalib_ctSize.VDisplay = %d, __svgalib_ctSize.HDisplay = %d\n", + __svgalib_ctSize.VDisplay,__svgalib_ctSize.HDisplay); +#endif + } + } else { + ctCRT = TRUE; + ctLCD = FALSE; + } + + + ctVgaIOBaseFlag = (port_in(0x3CC) & 0x01); + + /* Initialize accelspecs structure. */ + if (CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || + CHIPSchipset == CT_548 || CHIPSchipset == CT_550 || + CHIPSchipset == CT_554 || CHIPSchipset == CT_555 || + CHIPSchipset == CT_8554 || CHIPSchipset == CT_9000 || + CHIPSchipset == CT_4300) { + __svgalib_chips_driverspecs.accelspecs = malloc(sizeof(AccelSpecs)); + __svgalib_clear_accelspecs(__svgalib_chips_driverspecs.accelspecs); + __svgalib_chips_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH; + } + + if (__svgalib_driver_report) + { + fprintf(stderr,"Using C&T 655xx driver (%dK) [%d].\n", + video_memory, CHIPSchipset); + } + + __svgalib_driverspecs = &__svgalib_chips_driverspecs; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = video_memory; + + if (ctDacSpeed) { + switch(CHIPSchipset) { + case CT_520: + case CT_525: + case CT_530: + case CT_535: + cardspecs->maxPixelClock8bpp = ctDacSpeed; + cardspecs->maxPixelClock16bpp = 0; + cardspecs->maxPixelClock24bpp = 0; + break; + default: + cardspecs->maxPixelClock8bpp = ctDacSpeed; + cardspecs->maxPixelClock16bpp = ctDacSpeed; + cardspecs->maxPixelClock24bpp = ctDacSpeed; + break; + } + } else { + switch(CHIPSchipset) { + case CT_520: + case CT_525: + case CT_530: + case CT_535: + port_out_r(0x3D6,0x6C); + if (port_in(0x3D7) & 2) { + cardspecs->maxPixelClock8bpp = 68000; /* 5V Vcc */ + } else { + cardspecs->maxPixelClock8bpp = 56000; /* 3.3V Vcc */ + } + cardspecs->maxPixelClock16bpp = 0; + cardspecs->maxPixelClock24bpp = 0; + break; + case CT_540: + case CT_545: + port_out_r(0x3D6,0x6C); + if (port_in(0x3D7) & 2) { + cardspecs->maxPixelClock8bpp = 68000; /* 5V Vcc */ + cardspecs->maxPixelClock16bpp = 34000; + cardspecs->maxPixelClock24bpp = 22667; + } else { + cardspecs->maxPixelClock8bpp = 56000; /* 3.3V Vcc */ + cardspecs->maxPixelClock16bpp = 28322; + cardspecs->maxPixelClock24bpp = 18667; + } + break; + case CT_546: + case CT_548: + cardspecs->maxPixelClock8bpp = 80000; + cardspecs->maxPixelClock16bpp = 40000; + cardspecs->maxPixelClock24bpp = 26667; + break; + case CT_4300: + cardspecs->maxPixelClock8bpp = 85000; + cardspecs->maxPixelClock16bpp = 42500; + cardspecs->maxPixelClock24bpp = 28333; + break; + case CT_9000: + cardspecs->maxPixelClock8bpp = 220000; + cardspecs->maxPixelClock16bpp = 220000; + cardspecs->maxPixelClock24bpp = 220000; + break; + case CT_8554: + case CT_555: + cardspecs->maxPixelClock8bpp = 110000; + cardspecs->maxPixelClock16bpp = 110000; + cardspecs->maxPixelClock24bpp = 110000; + break; + case CT_554: + cardspecs->maxPixelClock8bpp = 95000; + cardspecs->maxPixelClock16bpp = 95000; + cardspecs->maxPixelClock24bpp = 95000; + break; + case CT_550: + port_out_r(0x3D6, 0x04); + if ((port_in(0x3D7) & 0xF) < 6) { + port_out_r(0x3D0,0x0A); + if (port_in(0x3D1) & 2) { + cardspecs->maxPixelClock8bpp = 110000; /* 5V Vcc */ + cardspecs->maxPixelClock16bpp = 110000; + cardspecs->maxPixelClock24bpp = 110000; + } else { + cardspecs->maxPixelClock8bpp = 80000; /* 3.3V Vcc */ + cardspecs->maxPixelClock16bpp = 80000; + cardspecs->maxPixelClock24bpp = 80000; + } + } else { + cardspecs->maxPixelClock8bpp = 95000; /* Revision B */ + cardspecs->maxPixelClock16bpp = 95000; + cardspecs->maxPixelClock24bpp = 95000; + } + break; + } + + /* Adjust HiQV maximum clocks to meet limits in spec */ + if (ctisHiQV) { + unsigned char tmp, M, N, P, PSN; + unsigned int MemClk; + + /* Probe the memory clock currently in use */ + port_out_r(0x3D6,0xCC); + M = (port_in(0x3D7) & 0x7F) + 2; + port_out_r(0x3D6,0xCD); + N = (port_in(0x3D7) & 0x7F) + 2; + port_out_r(0x3D6,0xCE); + tmp = port_in(0x3D7); + PSN = (tmp & 0x1) ? 1 : 4; + P = ((tmp & 0x70) >> 4); + /* Be careful with the calculation of MemClk as it can overflow */ + MemClk = 4 * Fref / N / 1000; + MemClk = MemClk * M / (PSN * (1 << P)); + + port_out_r(0x3D0, 0x1A); + tmp = port_in(0x3D1); + if ((tmp & 1) && (!(tmp & 0x80))) { + /* Extra byte per clock cycle for embedded DSTN framebuffer */ + cardspecs->maxPixelClock8bpp = min(cardspecs->maxPixelClock8bpp, + MemClk * 4 * 0.7 / 2); + cardspecs->maxPixelClock16bpp = min( + cardspecs->maxPixelClock16bpp, MemClk * 4 * 0.7 / 3); + cardspecs->maxPixelClock24bpp = min( + cardspecs->maxPixelClock24bpp, MemClk * 4 * 0.7 / 4); + } else { + cardspecs->maxPixelClock8bpp = min(cardspecs->maxPixelClock8bpp, + MemClk * 4 * 0.7 / 1); + cardspecs->maxPixelClock16bpp = min( + cardspecs->maxPixelClock16bpp, MemClk * 4 * 0.7 / 2); + cardspecs->maxPixelClock24bpp = min( + cardspecs->maxPixelClock24bpp, MemClk * 4 * 0.7 / 3); + } + } + } + cardspecs->maxPixelClock4bpp = 0; /* Handled by Generic VGA */ + cardspecs->maxPixelClock32bpp = 0; /* Not available at all */ + + if ((CHIPSchipset == CT_520) || (CHIPSchipset == CT_525) || + (CHIPSchipset == CT_530)) { + cardspecs->flags = 0; + cardspecs->nClocks = CHIPS_NUM_CLOCKS; + cardspecs->clocks = chips_fixed_clocks; + } else { + cardspecs->flags = CLOCK_PROGRAMMABLE; + cardspecs->nClocks = 0; + cardspecs->clocks = NULL; + cardspecs->matchProgrammableClock = CHIPS_matchProgrammableClock; + } + if (ctisHiQV) { + cardspecs->maxHorizontalCrtc = 4096; + } else { + cardspecs->maxHorizontalCrtc = 2048; + } + cardspecs->mapClock = CHIPS_mapClock; + cardspecs->mapHorizontalCrtc = CHIPS_mapHorizontalCrtc; + + + __svgalib_CHIPS_LinearBase=chips_pcilinearbase; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=__svgalib_CHIPS_LinearBase; + __svgalib_linear_mem_size=video_memory*0x400; + + MMIO_mem1= + mmap(__svgalib_ctMMIOBase, 0x10000, PROT_WRITE, MAP_FIXED | + MAP_SHARED, __svgalib_mem_fd, + __svgalib_CHIPS_LinearBase + 0x200000L); + MMIO_mem2= + mmap(__svgalib_ctMMIOBase, 0x20000, PROT_WRITE, MAP_FIXED | + MAP_SHARED, __svgalib_mem_fd, + __svgalib_CHIPS_LinearBase + 0x400000L); + + return 0; +} + +/* These are the macro's for setting the ROP's with the 6554x's */ +#define ctTOP2BOTTOM 0x100 +#define ctBOTTOM2TOP 0x000 +#define ctLEFT2RIGHT 0x200 +#define ctRIGHT2LEFT 0x000 +#define ctSRCMONO 0x800 +#define ctPATMONO 0x1000 +#define ctBGTRANSPARENT 0x2000 +#define ctSRCSYSTEM 0x4000 +#define ctPATSOLID 0x80000L + +/* These are the macro's for setting the ROP's with the 6555x's */ +#define ctHIQVTOP2BOTTOM 0x000 +#define ctHIQVBOTTOM2TOP 0x200 +#define ctHIQVLEFT2RIGHT 0x000 +#define ctHIQVRIGHT2LEFT 0x100 +#define ctHIQVSRCSYSTEM 0x400 +#define ctHIQVSRCMONO 0x1000 +#define ctHIQVPATMONO 0x40000L +#define ctHIQVBGTRANSPARENT 0x22000L +#define ctHIQVPATSOLID 0x80000L + +/* These are the macro's for setting the monochrome source + * expansion with the 6555x's */ +#define ctHIQVCLIPLEFT(clip) (clip&0x3F) +#define ctHIQVCLIPRIGHT(clip) ((clip&0x3F) << 8) +#define ctHIQVSRCDISCARD(clip) ((clip&0x3F) << 16) +#define ctHIQVBITALIGN 0x1000000L +#define ctHIQVBYTEALIGN 0x2000000L +#define ctHIQVWORDALIGN 0x3000000L +#define ctHIQVDWORDALIGN 0x4000000L +#define ctHIQVQWORDALIGN 0x5000000L + +/* These are the macro functions for programming the Register + * addressed blitter for the 6554x's */ +#define ctBLTWAIT while(port_inw(0x93D2)&0x10){} +#define ctSETROP(op) port_outl_r(0x93D0,op) +#define ctSETSRCADDR(srcAddr) port_outl_r(0x97D0,(srcAddr&0x1FFFFFL)) +#define ctSETDSTADDR(dstAddr) port_outl_r(0x9BD0,(dstAddr&0x1FFFFFL)) +#define ctSETPITCH(srcPitch,dstPitch) port_outl_r(0x83D0,((dstPitch<<16)|srcPitch)) +#define ctSETHEIGHTWIDTHGO(Height,Width) port_outl_r(0x9FD0,((Height<<16)|Width)) +#define ctSETBGCOLOR(bgColor) port_outl_r(0x8BD0,(bgColor)) +#define ctSETFGCOLOR(fgColor) port_outl_r(0x8FD0,(fgColor)) + +/* These are the macro functions for programming the MMIO + * addressed blitter for the 6554x's */ +#define ctMMIOBLTWAIT while(*(volatile unsigned int *)(__svgalib_ctMMIOBase + 0x93D0) & \ + 0x00100000){} +#define ctMMIOSETROP(op) *(unsigned int *)(__svgalib_ctMMIOBase + 0x93D0) = op +#define ctMMIOSETSRCADDR(srcAddr) *(unsigned int *)(__svgalib_ctMMIOBase + 0x97D0) = \ + srcAddr&0x7FFFFFL +#define ctMMIOSETDSTADDR(dstAddr) *(unsigned int *)(__svgalib_ctMMIOBase + 0x9BD0) = \ + dstAddr&0x7FFFFFL +#define ctMMIOSETPITCH(srcPitch,dstPitch) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x83D0) = ((dstPitch&0xFFFF)<<16)| \ + (srcPitch&0xFFFF) +#define ctMMIOSETHEIGHTWIDTHGO(Height,Width) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x9FD0) = ((Height&0xFFFF)<<16)| \ + (Width&0xFFFF) +#define ctMMIOSETBGCOLOR(bgColor) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x8BD0) = (bgColor) +#define ctMMIOSETFGCOLOR(fgColor) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x8FD0) = (fgColor) + +/* These are the macro functions for programming the MMIO + * addressed blitter for the 6555x's */ +#if 0 +/* Chips and technologies released an application note saying that + * with certain batches of chips you couldn't read the blitter registers + * properly. This could cause some drawing anolomies, use XR20[0] instead + */ +#define ctHIQVBLTWAIT while(*(volatile unsigned int *)(__svgalib_ctMMIOBase + 0x10) & \ + 0x80000000){} +#else +#define ctHIQVBLTWAIT port_out_r(0x3D6,0x20); while(port_in(0x3D7)&0x1){} +#endif +#define ctHIQVSETROP(op) *(unsigned int *)(__svgalib_ctMMIOBase + 0x10) = op +#define ctHIQVSETSRCADDR(srcAddr) *(unsigned int *)(__svgalib_ctMMIOBase + 0x18) = \ + srcAddr&0x7FFFFFL +#define ctHIQVSETDSTADDR(dstAddr) *(unsigned int *)(__svgalib_ctMMIOBase + 0x1C) = \ + dstAddr&0x7FFFFFL +#define ctHIQVSETPITCH(srcPitch,dstPitch) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x0) = ((dstPitch&0xFFFF)<<16)| \ + (srcPitch&0xFFFF) +#define ctHIQVSETHEIGHTWIDTHGO(Height,Width) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x20) = ((Height&0xFFFF)<<16)| \ + (Width&0xFFFF) +#define ctHIQVSETMONOCTL(op) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0xC) = op +#define ctHIQVSETBGCOLOR(bgColor) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x4) = (bgColor) +#define ctHIQVSETFGCOLOR(fgColor) \ + *(unsigned int *)(__svgalib_ctMMIOBase + 0x8) = (fgColor) + + +static void CHIPS_ScreenCopy(int x1, int y1, int x2, int y2, int w, int h) +{ + int srcaddr, destaddr, op; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: ScreenCopy(%d, %d, %d, %d, %d, %d)\n", x1, y1, x1, y2, w, h); +#endif + + srcaddr = BLTBYTEADDRESS(x1, y1); + destaddr = BLTBYTEADDRESS(x2, y2); + op = ctAluConv[ctROP&0xF]; + if (x1 < x2) { + op |= ctRIGHT2LEFT; + } else { + op |= ctLEFT2RIGHT; + } + if (y1 < y2) { + op |= ctBOTTOM2TOP; + } else { + op |= ctTOP2BOTTOM; + } + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctBLTWAIT; + ctSETROP(op); + ctSETSRCADDR(srcaddr); + ctSETDSTADDR(destaddr); + ctSETPITCH(__svgalib_accel_screenpitchinbytes, __svgalib_accel_screenpitchinbytes); + ctSETHEIGHTWIDTHGO(h, w * __svgalib_accel_bytesperpixel); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctBLTWAIT; +} + +static void CHIPS_mmio_ScreenCopy(int x1, int y1, int x2, int y2, int w, int h) +{ + int srcaddr, destaddr, op; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: mmio_ScreenCopy(%d, %d, %d, %d, %d, %d)\n", x1, y1, x1, y2, w, h); +#endif + + srcaddr = BLTBYTEADDRESS(x1, y1); + destaddr = BLTBYTEADDRESS(x2, y2); + op = ctAluConv[ctROP&0xF]; + if (x1 < x2) { + op |= ctRIGHT2LEFT; + } else { + op |= ctLEFT2RIGHT; + } + if (y1 < y2) { + op |= ctBOTTOM2TOP; + } else { + op |= ctTOP2BOTTOM; + } + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctMMIOBLTWAIT; + ctMMIOSETROP(op); + ctMMIOSETSRCADDR(srcaddr); + ctMMIOSETDSTADDR(destaddr); + ctMMIOSETPITCH(__svgalib_accel_screenpitchinbytes, __svgalib_accel_screenpitchinbytes); + ctMMIOSETHEIGHTWIDTHGO(h, w*__svgalib_accel_bytesperpixel); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctMMIOBLTWAIT; +} + +static void CHIPS_hiqv_ScreenCopy(int x1, int y1, int x2, int y2, int w, int h) +{ + int srcaddr, destaddr, op; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: hiqv_ScreenCopy(%d, %d, %d, %d, %d, %d)\n", x1, y1, x1, y2, w, h); +#endif + + srcaddr = BLTBYTEADDRESS(x1, y1); + destaddr = BLTBYTEADDRESS(x2, y2); + op = ctAluConv[ctROP&0xF]; + if (x1 < x2) { + op |= ctHIQVRIGHT2LEFT; + } else { + op |= ctHIQVLEFT2RIGHT; + } + if (y1 < y2) { + op |= ctHIQVBOTTOM2TOP; + } else { + op |= ctHIQVTOP2BOTTOM; + } + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctHIQVBLTWAIT; + ctHIQVSETROP(op); + ctHIQVSETSRCADDR(srcaddr); + ctHIQVSETDSTADDR(destaddr); + ctHIQVSETPITCH(__svgalib_accel_screenpitchinbytes, __svgalib_accel_screenpitchinbytes); + ctHIQVSETHEIGHTWIDTHGO(h, w*__svgalib_accel_bytesperpixel); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctHIQVBLTWAIT; +} + + +void __svgalib_CHIPS_FillBox(int x, int y, int width, int height) +{ + int destaddr; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: FillBox(%d, %d, %d, %d)\n", x, y, width, height); +#endif + + destaddr = BLTBYTEADDRESS(x, y); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctBLTWAIT; + ctSETDSTADDR(destaddr); + ctSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctSETROP(ctAluConv2[ctROP&0xF] | ctTOP2BOTTOM | ctLEFT2RIGHT | ctPATSOLID + | ctPATMONO); + ctSETFGCOLOR(ctFGCOLOR); + ctSETBGCOLOR(ctFGCOLOR); + ctSETHEIGHTWIDTHGO(height,width*__svgalib_accel_bytesperpixel); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctBLTWAIT; +} + +void __svgalib_CHIPS_mmio_FillBox(int x, int y, int width, int height) +{ + int destaddr; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: mmio_FillBox(%d, %d, %d, %d)\n", x, y, width, height); +#endif + + destaddr = BLTBYTEADDRESS(x, y); + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctMMIOBLTWAIT; + ctMMIOSETDSTADDR(destaddr); + ctMMIOSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctMMIOSETROP(ctAluConv2[ctROP&0xF] | ctTOP2BOTTOM | ctLEFT2RIGHT | + ctPATSOLID | ctPATMONO); + ctMMIOSETFGCOLOR(ctFGCOLOR); + ctMMIOSETBGCOLOR(ctFGCOLOR); + ctMMIOSETHEIGHTWIDTHGO(height,width*__svgalib_accel_bytesperpixel); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctMMIOBLTWAIT; +} + +void __svgalib_CHIPS_hiqv_FillBox(int x, int y, int width, int height) +{ + int destaddr; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: hiqv_FillBox(%d, %d, %d, %d)\n", x, y, width, height); +#endif + + destaddr = BLTBYTEADDRESS(x, y); + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctHIQVBLTWAIT; + ctHIQVSETDSTADDR(destaddr); + ctHIQVSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctHIQVSETROP(ctAluConv2[ctROP&0xF] | ctHIQVTOP2BOTTOM | ctHIQVLEFT2RIGHT | + ctHIQVPATSOLID | ctHIQVPATMONO); + ctHIQVSETFGCOLOR(ctFGCOLOR); + ctHIQVSETBGCOLOR(ctFGCOLOR); + ctHIQVSETHEIGHTWIDTHGO(height,width*__svgalib_accel_bytesperpixel); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctHIQVBLTWAIT; +} + +void __svgalib_CHIPS_FillBox24(int x, int y, int width, int height) +{ + static unsigned int dwords[3] = { 0x24499224, 0x92244992, 0x49922449}; + unsigned char pixel1, pixel2, pixel3, fgpixel, bgpixel, xorpixel; + unsigned int i, op, index, line, destaddr; + Bool fastfill; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: FillBox24(%d, %d, %d, %d)\n", x, y, width, height); +#endif + + pixel3 = ctFGCOLOR & 0xFF; + pixel2 = (ctFGCOLOR >> 8) & 0xFF; + pixel1 = (ctFGCOLOR >> 16) & 0xFF; + fgpixel = pixel1; + bgpixel = pixel2; + xorpixel = 0; + index = 0; + fastfill = FALSE; + + /* Test for the special case where two of the byte of the + * 24bpp colour are the same. This can double the speed + */ + if (pixel1 == pixel2) { + fgpixel = pixel3; + bgpixel = pixel1; + fastfill = TRUE; + index = 1; + } else if (pixel1 == pixel3) { + fgpixel = pixel2; + bgpixel = pixel1; + fastfill = TRUE; + index = 2; + } else if (pixel2 == pixel3) { + fastfill = TRUE; + } else { + xorpixel = pixel2 ^ pixel3; + } + + /* Set up the invariant BitBLT parameters. */ + op = ctSRCMONO | ctSRCSYSTEM | ctTOP2BOTTOM | ctLEFT2RIGHT; + + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctBLTWAIT; + ctSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctSETSRCADDR(0); + ctSETFGCOLOR(((((fgpixel&0xFF)<<8)|(fgpixel&0xFF))<<16)| + (((fgpixel&0xFF)<<8)|(fgpixel&0xFF))); + ctSETBGCOLOR(((((bgpixel&0xFF)<<8)|(bgpixel&0xFF))<<16)| + (((bgpixel&0xFF)<<8)|(bgpixel&0xFF))); + destaddr = BLTBYTEADDRESS(x, y); + ctSETDSTADDR(destaddr); + ctSETROP(op | ctAluConv[ROP_COPY & 0xf]); + SIGNALBLOCK; + ctSETHEIGHTWIDTHGO(height, 3 * width); + line = 0; + while (line < height) { + for (i = 0; i < (((3 * width + 31) & ~31) >> 5); i++) { + *(unsigned int *)__svgalib_graph_mem = dwords[((index + i) % 3)]; + } + line++; + } + if (!fastfill) { + ctBLTWAIT; + ctSETFGCOLOR(((((xorpixel&0xFF)<<8)|(xorpixel&0xFF))<<16)| + (((xorpixel&0xFF)<<8)|(xorpixel&0xFF))); + ctSETROP(op | ctAluConv[ROP_XOR & 0xf] | ctBGTRANSPARENT); + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(height, 3 * width); + line = 0; + while (line < height) { + for (i = 0; i < (((3 * width + 31) & ~31) >> 5); i++) { + *(unsigned int *)__svgalib_graph_mem = dwords[((1 + i) % 3)]; + } + line++; + } + } + SIGNALUNBLOCK; + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctBLTWAIT; +} + +void __svgalib_CHIPS_mmio_FillBox24(int x, int y, int width, int height) +{ + static unsigned int dwords[3] = { 0x24499224, 0x92244992, 0x49922449}; + unsigned char pixel1, pixel2, pixel3, fgpixel, bgpixel, xorpixel; + unsigned int i, op, index, line, destaddr; + Bool fastfill; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: mmio_FillBox24(%d, %d, %d, %d)\n", x, y, width, height); +#endif + + pixel3 = ctFGCOLOR & 0xFF; + pixel2 = (ctFGCOLOR >> 8) & 0xFF; + pixel1 = (ctFGCOLOR >> 16) & 0xFF; + fgpixel = pixel1; + bgpixel = pixel2; + xorpixel = 0; + index = 0; + fastfill = FALSE; + + /* Test for the special case where two of the byte of the + * 24bpp colour are the same. This can double the speed + */ + if (pixel1 == pixel2) { + fgpixel = pixel3; + bgpixel = pixel1; + fastfill = TRUE; + index = 1; + } else if (pixel1 == pixel3) { + fgpixel = pixel2; + bgpixel = pixel1; + fastfill = TRUE; + index = 2; + } else if (pixel2 == pixel3) { + fastfill = TRUE; + } else { + xorpixel = pixel2 ^ pixel3; + } + + /* Set up the invariant BitBLT parameters. */ + op = ctSRCMONO | ctSRCSYSTEM | ctTOP2BOTTOM | ctLEFT2RIGHT; + + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctMMIOBLTWAIT; + ctMMIOSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctMMIOSETSRCADDR(0); + ctMMIOSETFGCOLOR(((((fgpixel&0xFF)<<8)|(fgpixel&0xFF))<<16)| + (((fgpixel&0xFF)<<8)|(fgpixel&0xFF))); + ctMMIOSETBGCOLOR(((((bgpixel&0xFF)<<8)|(bgpixel&0xFF))<<16)| + (((bgpixel&0xFF)<<8)|(bgpixel&0xFF))); + destaddr = BLTBYTEADDRESS(x, y); + ctMMIOSETDSTADDR(destaddr); + ctMMIOSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctMMIOSETROP(op | ctAluConv[ROP_COPY & 0xf]); + SIGNALBLOCK; + ctMMIOSETHEIGHTWIDTHGO(height, 3 * width); + line = 0; + while (line < height) { + for (i = 0; i < (((3 * width + 31) & ~31) >> 5); i++) { + *(unsigned int *)__svgalib_graph_mem = dwords[((index + i) % 3)]; + } + line++; + } + if (!fastfill) { + ctMMIOBLTWAIT; + ctMMIOSETFGCOLOR(((((xorpixel&0xFF)<<8)|(xorpixel&0xFF))<<16)| + (((xorpixel&0xFF)<<8)|(xorpixel&0xFF))); + ctMMIOSETROP(op | ctAluConv[ROP_XOR & 0xf] | ctBGTRANSPARENT); + ctMMIOSETDSTADDR(destaddr); + ctMMIOSETHEIGHTWIDTHGO(height, 3 * width); + line = 0; + while (line < height) { + for (i = 0; i < (((3 * width + 31) & ~31) >> 5); i++) { + *(unsigned int *)__svgalib_graph_mem = dwords[((1 + i) % 3)]; + } + line++; + } + } + SIGNALUNBLOCK; + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctMMIOBLTWAIT; +} + + +void __svgalib_CHIPS_PutBitmap(int x, int y, int w, int h, void *bitmap) +{ + int destaddr, line; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: PutBitMap(%d, %d, %d, %d)\n", x, y, w, h); +#endif + + destaddr = BLTBYTEADDRESS(x, y); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctBLTWAIT; + ctSETSRCADDR(0); + ctSETFGCOLOR(ctFGCOLOR); + ctSETBGCOLOR(ctBGCOLOR); + ctSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctSETDSTADDR(destaddr); + ctSETROP(ctAluConv[ctROP & 0xf] | ctSRCMONO | ctSRCSYSTEM | + ctTRANSMODE | ctTOP2BOTTOM | ctLEFT2RIGHT); + SIGNALBLOCK; + ctSETHEIGHTWIDTHGO(h,w*__svgalib_accel_bytesperpixel); + line = 0; + while (line < h) { + unsigned int i; + for (i = 0; i < (((w + 31) & ~31) >> 5); i++) { + *(unsigned int *)__svgalib_graph_mem = + __svgalib_byte_reversed[*(unsigned char *)bitmap] + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 1)]) << 8) + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 2)]) << 16) + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 3)]) << 24); + bitmap += 4; + } + line++; + } + SIGNALUNBLOCK; + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctBLTWAIT; +} + + +void __svgalib_CHIPS_mmio_PutBitmap(int x, int y, int w, int h, void *bitmap) +{ + int destaddr, line; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: mmio_PutBitMap(%d, %d, %d, %d)\n", x, y, w, h); +#endif + + destaddr = BLTBYTEADDRESS(x, y); + + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctMMIOBLTWAIT; + ctMMIOSETSRCADDR(0); + ctMMIOSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctMMIOSETDSTADDR(destaddr); + ctMMIOSETFGCOLOR(ctFGCOLOR); + ctMMIOSETBGCOLOR(ctBGCOLOR); + ctMMIOSETROP(ctAluConv[ctROP & 0xf] | ctSRCMONO | ctSRCSYSTEM | + ctTRANSMODE | ctTOP2BOTTOM | ctLEFT2RIGHT); + SIGNALBLOCK; + ctMMIOSETHEIGHTWIDTHGO(h,w*__svgalib_accel_bytesperpixel); + if (__svgalib_ctMMIOPage != -1) vga_setpage(0); + line = 0; + while (line < h) { + unsigned int i; + for (i = 0; i < (((w + 31) & ~31) >> 5); i++) { + *(unsigned int *)__svgalib_graph_mem = + __svgalib_byte_reversed[*(unsigned char *)bitmap] + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 1)]) << 8) + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 2)]) << 16) + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 3)]) << 24); + bitmap += 4; + } + line++; + } + SIGNALUNBLOCK; + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctMMIOBLTWAIT; +} + +/* This routine is completely untested. I have no idea if this might + * work. I don't have a 6555x machine to test it on + */ +void __svgalib_CHIPS_hiqv_PutBitmap(int x, int y, int w, int h, void *bitmap) +{ + int destaddr, line; + +#ifdef DEBUG + fprintf(stderr,"CHIPS: hiqv_PutBitMap(%d, %d, %d, %d)\n", x, y, w, h); +#endif + + destaddr = BLTBYTEADDRESS(x, y); + + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) + ctHIQVBLTWAIT; + ctHIQVSETMONOCTL(ctHIQVDWORDALIGN); + ctHIQVSETSRCADDR(0); + ctHIQVSETPITCH(0, __svgalib_accel_screenpitchinbytes); + ctHIQVSETDSTADDR(destaddr); + ctHIQVSETFGCOLOR(ctFGCOLOR); + ctHIQVSETBGCOLOR(ctBGCOLOR); + ctHIQVSETROP(ctAluConv[ctROP & 0xf] | ctHIQVSRCMONO | ctHIQVSRCSYSTEM | + ctTRANSMODE | ctHIQVTOP2BOTTOM | ctHIQVLEFT2RIGHT); + + SIGNALBLOCK; + ctHIQVSETHEIGHTWIDTHGO(h,w*__svgalib_accel_bytesperpixel); + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage + 1); + line = 0; + while (line < h) { + unsigned int i; + for (i = 0; i < (((w + 31) & ~31) >> 5); i++) { + *(unsigned int *)__svgalib_ctBltDataWindow = + __svgalib_byte_reversed[*(unsigned char *)bitmap] + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 1)]) << 8) + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 2)]) << 16) + + ((__svgalib_byte_reversed[*(unsigned char *)(bitmap + 3)]) << 24); + bitmap += 4; + } + line++; + } + + /* HiQV architecture needs a multiple of Quad-words in total */ + if (((((w + 31) & ~31) >> 5) * h) & 0x1) + *(unsigned int *)__svgalib_ctBltDataWindow = 0; + + SIGNALUNBLOCK; + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + ctHIQVBLTWAIT; +} + +static void CHIPS_Sync(void) +{ + ctBLTWAIT; +} + +static void CHIPS_mmio_Sync(void) +{ + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + ctMMIOBLTWAIT; +} + +static void CHIPS_hiqv_Sync(void) +{ + if (__svgalib_ctMMIOPage != -1) vga_setpage(__svgalib_ctMMIOPage); + ctHIQVBLTWAIT; +} + +void __svgalib_CHIPS_SetFGColor(int fg) +{ + if (ctisHiQV) { + switch(__svgalib_accel_bytesperpixel) { + case 1: + ctFGCOLOR = fg&0xFF; + break; + case 2: + ctFGCOLOR = fg&0xFFFF; + break; + case 3: + ctFGCOLOR = fg&0xFFFFFF; + break; + } + } else { + switch (__svgalib_accel_bytesperpixel) { + case 1: + ctFGCOLOR = ((((fg&0xFF)<<8) | (fg&0xFF)) << 16) | + (((fg&0xFF)<<8) | (fg&0xFF)); + break; + case 2: + ctFGCOLOR = ((fg&0xFFFF) << 16) | (fg&0xFFFF); + break; + case 3: + /* We don't have 24bpp colour expansion. The 8bpp engine + * can be used to simulate this though. + */ + ctFGCOLOR = fg; + break; + } + } +} + +void __svgalib_CHIPS_SetBGColor(int bg) +{ + if (ctisHiQV) { + switch(__svgalib_accel_bytesperpixel) { + case 1: + ctBGCOLOR = bg&0xFF; + break; + case 2: + ctBGCOLOR = bg&0xFFFF; + break; + case 3: + ctBGCOLOR = bg&0xFFFFFF; + break; + } + } else { + switch (__svgalib_accel_bytesperpixel) { + case 1: + ctBGCOLOR = ((((bg&0xFF)<<8) | (bg&0xFF)) << 16) | + (((bg&0xFF)<<8) | (bg&0xFF)); + break; + case 2: + ctBGCOLOR = ((bg&0xFFFF) << 16) | (bg&0xFFFF); + break; + case 3: + /* We don't have 24bpp colour expansion. The 8bpp engine + * can be used to simulate this though. + */ + ctBGCOLOR = bg; + break; + } + } +} + +void __svgalib_CHIPS_SetRasterOp(int rop) +{ + ctROP = rop; +} + + +void __svgalib_CHIPS_SetTransparency(int mode, int color) +{ + if (mode == DISABLE_BITMAP_TRANSPARENCY) { + ctTRANSMODE = 0; + return; + } + if (ctisHiQV) + ctTRANSMODE = ctHIQVBGTRANSPARENT; + else + ctTRANSMODE = ctBGTRANSPARENT; +} + +static int ct_video_mode(int bpp, int weight_green, int display_size) +{ /* table+code from XFree86 ct_driver.c */ + /* 4 bpp 8 bpp 16 bpp 18 bpp 24 bpp 32 bpp */ + /* 640 0x20 0x30 0x40 - 0x50 - */ + /* 800 0x22 0x32 0x42 - 0x52 - */ + /*1024 0x24 0x34 0x44 - 0x54 - */ + /*1152 0x27 0x37 0x47 - 0x57 - */ + /*1280 0x28 0x38 0x49 - - - */ + /*1600 0x2C 0x3C 0x4C 0x5D - - */ + /*This value is only for BIOS.... */ + int video_mode = 0; + + switch (bpp) { + case 4: + video_mode = 0x20; + break; + case 8: + video_mode = 0x30; + break; + case 16: + video_mode = 0x40; + if (weight_green != 5) + video_mode |= 0x01; + break; + default: + video_mode = 0x50; + break; + } + + switch (display_size) { + case 800: + video_mode |= 0x02; + break; + case 1024: + video_mode |= 0x04; + break; + case 1152: + video_mode |= 0x07; + break; + case 1280: + video_mode |= 0x08; + if (bpp == 16) + video_mode |= 0x01; + break; + case 1600: + video_mode |= 0x0C; + if (bpp == 16) + video_mode |= 0x01; + break; + } + + return(video_mode); +} diff --git a/src/drivers/cirrus.c b/src/drivers/cirrus.c new file mode 100644 index 0000000..6196734 --- /dev/null +++ b/src/drivers/cirrus.c @@ -0,0 +1,1864 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Cirrus support Copyright (C) 1993 Harm Hanemaayer */ + +/* + * Dec 1994: + * + * Mode setting rewritten with more SVGA generalization and increased + * flexibility. Supports 542x/543x. + * Uses interfaces in timing.h and vgaregs.h. Only saves/restores + * extended registers that are actually changed for SVGA modes. + */ + + +#include +#include /* for printf */ +#include +#include /* for memset */ +#include "vga.h" +#include "libvga.h" +#include "driver.h" + + +/* Enable support for > 85 MHz dot clocks on the 5434. */ +#define SUPPORT_5434_PALETTE_CLOCK_DOUBLING +/* Use the special clocking mode for all dot clocks at 256 colors, not */ +/* just those > 85 MHz, for debugging. */ +/* #define ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING */ + + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "accel.h" +#include "vgapci.h" + + +#define CIRRUSREG_GR(i) (VGA_TOTAL_REGS + i - VGA_GRAPHICS_COUNT) +#define CIRRUSREG_SR(i) (VGA_TOTAL_REGS + 5 + i - VGA_SEQUENCER_COUNT) +#define CIRRUSREG_CR(i) (VGA_TOTAL_REGS + 5 + 27 + i - VGA_CRTC_COUNT) +#define CIRRUSREG_DAC (VGA_TOTAL_REGS + 5 + 27 + 15) +#define CIRRUS_TOTAL_REGS (VGA_TOTAL_REGS + 5 + 27 + 15 + 1) + +/* Indices into mode register array. */ +#define CIRRUS_GRAPHICSOFFSET1 CIRRUSREG_GR(0x09) +#define CIRRUS_GRAPHICSOFFSET2 CIRRUSREG_GR(0x0A) +#define CIRRUS_GRB CIRRUSREG_GR(0x0B) +#define CIRRUS_SR7 CIRRUSREG_SR(0x07) +#define CIRRUS_VCLK3NUMERATOR CIRRUSREG_SR(0x0E) +#define CIRRUS_DRAMCONTROL CIRRUSREG_SR(0x0F) +#define CIRRUS_PERFTUNING CIRRUSREG_SR(0x16) +#define CIRRUS_SR17 CIRRUSREG_SR(0x17) +#define CIRRUS_VCLK3DENOMINATOR CIRRUSREG_SR(0x1E) +#define CIRRUS_MCLKREGISTER CIRRUSREG_SR(0x1F) +#define CIRRUS_CR19 CIRRUSREG_CR(0x19) +#define CIRRUS_CR1A CIRRUSREG_CR(0x1A) +#define CIRRUS_CR1B CIRRUSREG_CR(0x1B) +#define CIRRUS_CR1D CIRRUSREG_CR(0x1D) +#define CIRRUS_HIDDENDAC CIRRUSREG_DAC + + +/* Efficient chip type checks. */ + +#define CHECKCHIP1(c1) ((1 << cirrus_chiptype) & (1 << c1)) +#define CHECKCHIP2(c1, c2) ((1 << cirrus_chiptype) & ((1 << c1) | (1 << c2))) +#define CHECKCHIP3(c1, c2, c3) ((1 << cirrus_chiptype) & ((1 << c1) \ + | (1 << c2) | (1 << c3))) +#define CHECKCHIP4(c1, c2, c3, c4) ((1 << cirrus_chiptype) & ((1 << c1) \ + | (1 << c2) | (1 << c3) | (1 << c4))) +#define CHECKCHIP5(c1, c2, c3, c4, c5) ((1 << cirrus_chiptype) & \ + ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5))) +#define CHECKCHIP6(c1, c2, c3, c4, c5, c6) ((1 << cirrus_chiptype) & \ + ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ + | (1 << c6))) +#define CHECKCHIP7(c1, c2, c3, c4, c5, c6, c7) ((1 << cirrus_chiptype) & \ + ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ + | (1 << c6) | (1 << c7))) +#define CHECKCHIP8(c1, c2, c3, c4, c5, c6, c7, c8) ((1 << cirrus_chiptype) & \ + ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ + | (1 << c6) | (1 << c7) | (1 << c8))) +#define CHECKCHIP9(c1, c2, c3, c4, c5, c6, c7, c8, c9) ((1 << cirrus_chiptype) & \ + ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ + | (1 << c6) | (1 << c7) | (1 << c8) | (1 << c9))) +#define CHECKCHIPGREATEREQUAL(c) (cirrus_chiptype >= c) +#define CHECKCHIPNOTEQUAL(c) (cirrus_chiptype != c) + +#define CHIP_HAS_CR1D() \ + CHECKCHIP4(CLGD5429, CLGD5430, CLGD5434, CLGD5436) +#define CHIP_HAS_GRC_AND_GRD() \ + CHECKCHIP4(CLGD5424, CLGD5426, CLGD5428, CLGD5429) +#define CHIP_HAS_GRE() \ + CHECKCHIP5(CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436) +#define CHIP_HAS_GR10_AND_GR11() \ + CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436) +#define CHIP_HAS_BLTTRANSPARENTCOLOR() \ + CHECKCHIP2(CLGD5426, CLGD5428) +#define CHIP_HAS_PERFTUNINGREGISTER() \ + CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436) +#define CHIP_HAS_MCLK_REGISTER() \ + CHECKCHIP9(CLGD5420B, CLGD5422C, CLGD5424, CLGD5426, CLGD5428, \ + CLGD5429, CLGD5430, CLGD5434, CLGD5436) +#define CHIP_HAS_32BIT_DRAM_BUS() \ + CHECKCHIPGREATEREQUAL(CLGD5420B) +#define CHIP_HAS_64BIT_DRAM_BUS() \ + CHECKCHIP3(CLGD5434, CLGD5436, CLGD7548) +#define CHIP_HAS_HIDDENDAC() \ + CHECKCHIPGREATEREQUAL(CLGD5420B) +#define CHIP_HAS_ACCELERATION() \ + CHECKCHIPNOTEQUAL(CLGD5420B) +#define CHIP_HAS_SR17() \ + CHECKCHIPGREATEREQUAL(CLGD5422) +#define CHIP_USE_SR17() \ + CHECKCHIPGREATEREQUAL(CLGD5429) + + +/* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */ +#define CLOCK_FACTOR 28636 + +/* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */ +#define CLOCKVAL(n, d) \ + ((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) >> ((d) & 1)) + + +static int cirrus_init(int, int, int); +static void cirrus_unlock(void); + +static void __svgalib_cirrusaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels); + +static int cirrus_memory; +static int cirrus_chiptype; +static int cirrus_chiprev; +static unsigned int cirrus_pci_linear = 0; +static unsigned char actualMCLK, programmedMCLK; +static int DRAMbandwidth, DRAMbandwidthLimit; + + +static CardSpecs *cardspecs; + +#define NU_FIXED_CLOCKS 21 + +/* 12.588 clock (0x33, 0x3B) replaced with 12.599 (0x2C, 0x33). */ + +static int cirrus_fixed_clocks[NU_FIXED_CLOCKS] = +{ + 12599, 18000, 19600, + 25227, 28325, 31500, 36025, 37747, 39992, 41164, + 45076, 49867, 64983, 72163, 75000, 80013, 85226, 89998, + 95019, 100226, 108035 +}; + +static unsigned char fixed_clock_numerator[NU_FIXED_CLOCKS] = +{ + 0x2C, 0x27, 0x28, + 0x4A, 0x5B, 0x42, 0x4E, 0x3A, 0x51, 0x45, + 0x55, 0x65, 0x76, 0x7E, 0x6E, 0x5F, 0x7D, 0x58, + 0x49, 0x46, 0x53 +}; + +static unsigned char fixed_clock_denominator[NU_FIXED_CLOCKS] = +{ + 0x33, 0x3e, 0x3a, + 0x2B, 0x2F, 0x1F, 0x3E, 0x17, 0x3A, 0x30, + 0x36, 0x3A, 0x34, 0x32, 0x2A, 0x22, 0x2A, 0x1C, + 0x16, 0x14, 0x16 +}; + +/* + * It looks like the 5434 palette clock doubling mode doensn't like + * clocks like (0x7B, 0x20), whereas (0x53, 0x16) is OK. + */ + +enum { + CLGD5420 = 0, CLGD7548, CLGD5420B, CLGD5422, CLGD5422C, CLGD5424, CLGD5426, + CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436 +}; + + +int __svgalib_cirrus_inlinearmode(void) +{ + port_out_r(SEQ_I, 0x07); + return (port_in(SEQ_D) & 0xf0) != 0; +} + +/* Fill in chipset specific mode information */ + +static void cirrus_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + if (modeinfo->bytesperpixel > 0) + modeinfo->maxpixels = cirrus_memory * 1024 / modeinfo->bytesperpixel; + else + /* 16-color SVGA mode */ + /* Value taken from the air. */ + modeinfo->maxpixels = cirrus_memory * 2048; + modeinfo->maxlogicalwidth = 4088; +#if 0 + if (mode != G320x200x256) { + /* No need to check for 320x200x256, we now have a special */ + /* SVGA-derived 320x200x256 mode that fully supports page */ + /* flipping etc. */ +#endif + modeinfo->startaddressrange = cirrus_memory * 1024 - 1; + modeinfo->haveblit = 0; +#if 0 + } else { + modeinfo->startaddressrange = 0xffff; + modeinfo->maxpixels = 65536; + modeinfo->haveblit = 0; + } +#endif +#if 0 /* Who cares. */ + if (cirrus_interlaced(mode)) + modeinfo->flags |= IS_INTERLACED; +#endif + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + modeinfo->flags |= CAPABLE_LINEAR; + } +} + + +/* Read and save chipset-specific registers */ + +static int cirrus_saveregs(unsigned char regs[]) +{ +/* int i; */ + +/* #ifdef DEBUG + fprintf(stderr,"Saving Cirrus extended registers.\n"); + #endif + */ + cirrus_unlock(); /* May be locked again by other programs (e.g. X) */ + +#if 0 + /* Save extended CRTC registers. */ + for (i = 0; i < 15; i++) { /* was 4 */ + port_out(0x18 + i, __svgalib_CRT_I); + regs[CIRRUSREG_CR(i)] = port_in(__svgalib_CRT_D); + } + + /* Save extended graphics registers */ + for (i = 0; i < 5; i++) { /* was 3 */ + port_out(0x09 + i, GRA_I); + regs[CIRRUSREG_GR(i)] = port_in(GRA_D); + } + + /* Save extended sequencer registers. */ + for (i = 0; i < 27; i++) { + port_out(0x05 + i, SEQ_I); + regs[CIRRUSREG_SR(i)] = port_in(SEQ_D); + } +#endif + + /* Save extended CRTC registers. */ + regs[CIRRUSREG_CR(0x19)] = __svgalib_inCR(0x19); + regs[CIRRUSREG_CR(0x1A)] = __svgalib_inCR(0x1A); + regs[CIRRUSREG_CR(0x1B)] = __svgalib_inCR(0x1B); + if (CHIP_HAS_CR1D()) + regs[CIRRUSREG_CR(0x1D)] = __svgalib_inCR(0x1D); + + /* Save extended graphics registers. */ + regs[CIRRUSREG_GR(0x09)] = __svgalib_inGR(0x09); + regs[CIRRUSREG_GR(0x0A)] = __svgalib_inGR(0x0A); + regs[CIRRUSREG_GR(0x0B)] = __svgalib_inGR(0x0B); + + /* Save extended sequencer registers. */ + regs[CIRRUS_SR7] = __svgalib_inSR(0x07); + regs[CIRRUS_VCLK3NUMERATOR] = __svgalib_inSR(0x0E); + regs[CIRRUS_DRAMCONTROL] = __svgalib_inSR(0x0F); + if (CHIP_HAS_PERFTUNINGREGISTER()) + regs[CIRRUS_PERFTUNING] = __svgalib_inSR(0x16); + if (CHIP_HAS_SR17()) + regs[CIRRUS_SR17] = __svgalib_inSR(0x17); + regs[CIRRUS_VCLK3DENOMINATOR] = __svgalib_inSR(0x1E); + if (CHIP_HAS_MCLK_REGISTER()) + regs[CIRRUS_MCLKREGISTER] = __svgalib_inSR(0x1F); + + /* Save Hicolor DAC register. */ + /* My 5446 works without this. With this 8 bpp and text modes do not work. - MZ */ + if (CHIP_HAS_HIDDENDAC() && CHECKCHIPNOTEQUAL(CLGD5436)) { + port_out_r(0x3c6, 0); + port_out_r(0x3c6, 0xff); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + regs[CIRRUSREG_DAC] = port_in(0x3c6); + } + return CIRRUS_TOTAL_REGS - VGA_TOTAL_REGS; +} + +static void writehicolordac(unsigned char c) +{ + port_out_r(0x3c6, 0); + port_out_r(0x3c6, 0xff); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + port_out_r(0x3c6, c); + port_in(0x3c8); +} + + +/* Set chipset-specific registers */ + +static void cirrus_setregs(const unsigned char regs[], int mode) +{ +/* #ifdef DEBUG + fprintf(stderr,"Setting Cirrus extended registers.\n"); + #endif + */ + cirrus_unlock(); /* May be locked again by other programs (eg. X) */ + + /* Write extended CRTC registers. */ + __svgalib_outCR(0x19, regs[CIRRUSREG_CR(0x19)]); + __svgalib_outCR(0x1A, regs[CIRRUSREG_CR(0x1A)]); + __svgalib_outCR(0x1B, regs[CIRRUSREG_CR(0x1B)]); + if (CHIP_HAS_CR1D()) + __svgalib_outCR(0x1D, regs[CIRRUSREG_CR(0x1D)]); + + /* Write extended graphics registers. */ + __svgalib_outGR(0x09, regs[CIRRUSREG_GR(0x09)]); + __svgalib_outGR(0x0A, regs[CIRRUSREG_GR(0x0A)]); + __svgalib_outGR(0x0B, regs[CIRRUSREG_GR(0x0B)]); +#ifdef SET_ALL + if (CHIP_HAS_GRC_AND_GRD()) { + __svgalib_outGR(0x0C, regs[CIRRUSREG_GR(0x0C)]); + __svgalib_outGR(0x0D, regs[CIRRUSREG_GR(0x0D)]); + } + if (CHIP_HAS_GRE()) + __svgalib_outGR(0x0E, regs[CIRRUSREG_GR(0x0E)]); + if (CHIP_HAS_GR10_AND_GR11()) { + __svgalib_outGR(0x10, regs[CIRRUSREG_GR(0x10)]); + __svgalib_outGR(0x11, regs[CIRRUSREG_GR(0x11)]); + } + if (CHIP_HAS_BLT_REGISTERS()) { + int i; + + for (i = 0x20; i <= 0x2A; i++) + __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]); + for (i = 0x2C; i < 0x2E; i++) + __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]); + if (CHIP_HAS_BLTWRITEMASK()) + __svgalib_outGR(0x2D, regs[CIRRUSREG_GR(0x2D)]); + __svgalib_outGR(0x30, regs[CIRRUSREG_GR(0x30)]); + __svgalib_outGR(0x32, regs[CIRRUSREG_GR(0x32)]); + if (CHIP_HAS_BLTTRANSPARENTCOLOR()) { + __svgalib_outGR(0x34, regs[CIRRUSREG_GR(0x34)]); + __svgalib_outGR(0x35, regs[CIRRUSREG_GR(0x35)]); + __svgalib_outGR(0x38, regs[CIRRUSREG_GR(0x38)]); + __svgalib_outGR(0x39, regs[CIRRUSREG_GR(0x39)]); + } + } +#endif + + /* Write Truecolor DAC register. */ + if (CHIP_HAS_HIDDENDAC()) + writehicolordac(regs[CIRRUS_HIDDENDAC]); + + /* Write extended sequencer registers. */ + + /* Be careful to put the sequencer clocking mode in a safe state. */ + __svgalib_outSR(0x07, (regs[CIRRUS_SR7] & ~0x0F) | 0x01); + + __svgalib_outSR(0x0E, regs[CIRRUS_VCLK3NUMERATOR]); + __svgalib_outSR(0x1E, regs[CIRRUS_VCLK3DENOMINATOR]); + __svgalib_outSR(0x07, regs[CIRRUS_SR7]); + __svgalib_outSR(0x0F, regs[CIRRUS_DRAMCONTROL]); + if (CHIP_HAS_PERFTUNINGREGISTER()) + __svgalib_outSR(0x16, regs[CIRRUS_PERFTUNING]); + if (CHIP_USE_SR17()) + __svgalib_outSR(0x17, regs[CIRRUS_SR17]); + if (CHIP_HAS_MCLK_REGISTER()) + __svgalib_outSR(0x1F, regs[CIRRUS_MCLKREGISTER]); +} + + +/* Return nonzero if mode is available */ + +static int cirrus_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + /* CLGD7548 mode 13 is broken. Remove this if when supported */ + if (mode == G320x200x256 && cirrus_chiptype == CLGD7548) return 0; + + if (IS_IN_STANDARD_VGA_DRIVER(mode) && mode != G320x200x256) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (cirrus_memory * 1024 < info->ydim * info->xbytes) { + return 0; + } + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + + +/* Set a mode */ + +/* Local, called by cirrus_setmode(). */ + +static void cirrus_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo) +{ + + /* Get current values. */ + cirrus_saveregs(moderegs); + + /* Set up the standard VGA registers for a generic SVGA. */ + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + /* Set up the extended register values, including modifications */ + /* of standard VGA registers. */ + +/* Graphics */ + moderegs[CIRRUS_GRAPHICSOFFSET1] = 0; /* Reset banks. */ + moderegs[CIRRUS_GRAPHICSOFFSET2] = 0; + moderegs[CIRRUS_GRB] = 0; /* 0x01 enables dual banking. */ + if (cirrus_memory > 1024) + /* Enable 16K granularity. */ + moderegs[CIRRUS_GRB] |= 0x20; + moderegs[VGA_SR2] = 0xFF; /* Plane mask */ + +/* CRTC */ + if (modetiming->VTotal >= 1024 && !(modetiming->flags & INTERLACED)) + /* + * Double the vertical timing. Used for 1280x1024 NI. + * The CrtcVTimings have already been adjusted + * by __svgalib_getmodetiming() because of the GREATER_1024_DIVIDE_VERT + * flag. + */ + moderegs[VGA_CR17] |= 0x04; + moderegs[CIRRUS_CR1B] = 0x22; + if (cirrus_chiptype >= CLGD5434) + /* Clear display start bit 19. */ + SETBITS(moderegs[CIRRUS_CR1D], 0x80, 0); + /* CRTC timing overflows. */ + moderegs[CIRRUS_CR1A] = 0; + SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0xC0, + modetiming->CrtcVSyncStart + 1, 0x300); + SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0x30, + modetiming->CrtcHSyncEnd, (0xC0 << 3)); + moderegs[CIRRUS_CR19] = 0; /* Interlaced end. */ + if (modetiming->flags & INTERLACED) { + moderegs[CIRRUS_CR19] = + ((modetiming->CrtcHTotal / 8) - 5) / 2; + moderegs[CIRRUS_CR1A] |= 0x01; + } + moderegs[CIRRUS_CR1A] |= 0x02; +/* Scanline offset */ + if (modeinfo->bytesPerPixel == 4) { + /* At 32bpp the chip does an extra multiplication by two. */ + if (cirrus_chiptype >= CLGD5436) { + /* Do these chipsets multiply by 4? */ + moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 5; + SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10, + modeinfo->lineWidth, 0x2000); + } + else { + moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 4; + SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10, + modeinfo->lineWidth, 0x1000); + } + } else if (modeinfo->bitsPerPixel == 4) + /* 16 color mode (planar). */ + moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 1; + else { + moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 3; + SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10, + modeinfo->lineWidth, 0x800); + } + +/* Clocking */ + moderegs[VGA_MISCOUTPUT] |= 0x0C; /* Use VCLK3. */ + moderegs[CIRRUS_VCLK3NUMERATOR] = + fixed_clock_numerator[modetiming->selectedClockNo]; + moderegs[CIRRUS_VCLK3DENOMINATOR] = + fixed_clock_denominator[modetiming->selectedClockNo]; + +/* DAC register and Sequencer Mode */ + { + unsigned char DAC, SR7; + DAC = 0x00; + SR7 = 0x00; + if (modeinfo->bytesPerPixel > 0) + SR7 = 0x01; /* Packed-pixel mode. */ + if (modeinfo->bytesPerPixel == 2) { + int rgbmode; + rgbmode = 0; /* 5-5-5 RGB. */ + if (modeinfo->colorBits == 16) + rgbmode = 1; /* Add one for 5-6-5 RGB. */ + if (cirrus_chiptype >= CLGD5426) { + /* Pixel clock (double edge) mode. */ + DAC = 0xD0 + rgbmode; + SR7 = 0x07; + } else { + /* Single-edge (double VCLK). */ + DAC = 0xF0 + rgbmode; + SR7 = 0x03; + } + } + if (modeinfo->bytesPerPixel >= 3) { + /* Set 8-8-8 RGB mode. */ + DAC = 0xE5; + SR7 = 0x05; + if (modeinfo->bytesPerPixel == 4) + SR7 = 0x09; + } +#ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING + if (modeinfo->bytesPerPixel == 1 && (modetiming->flags & HADJUSTED)) { + /* Palette clock doubling mode on 5434 8bpp. */ + DAC = 0x4A; + SR7 = 0x07; + } +#endif + moderegs[CIRRUS_HIDDENDAC] = DAC; + moderegs[CIRRUS_SR7] = SR7; + } + +/* DRAM control and CRT FIFO */ + if (cirrus_chiptype >= CLGD5422) + /* Enable large CRT FIFO. */ + moderegs[CIRRUS_DRAMCONTROL] |= 0x20; + if (cirrus_memory == 2048 && cirrus_chiptype <= CLGD5429) + /* Enable DRAM Bank Select. */ + moderegs[CIRRUS_DRAMCONTROL] |= 0x80; + if (cirrus_chiptype >= CLGD5424) { + /* CRT FIFO threshold setting. */ + unsigned char threshold; + threshold = 8; +/* if (cirrus_chiptype >= CLGD5434) + threshold = 1;*/ + /* XXX Needs more elaborate setting. */ + SETBITS(moderegs[CIRRUS_PERFTUNING], 0x0F, threshold); + } + if (CHIP_HAS_MCLK_REGISTER()) + if (programmedMCLK != actualMCLK + && modeinfo->bytesPerPixel > 0) + /* Program higher MCLK for packed-pixel modes. */ + moderegs[CIRRUS_MCLKREGISTER] = programmedMCLK; +} + + +/* This is the clock mapping function that is put in the CardSpecs. */ + +static int cirrus_map_clock(int bpp, int pixelclock) +{ + if (bpp == 24 && cirrus_chiptype < CLGD5436) + /* Most chips need a tripled clock for 24bpp. */ + return pixelclock * 3; + if (bpp == 16 && cirrus_chiptype <= CLGD5424) + /* The 5422/24 need to use a doubled clock. */ + return pixelclock * 2; + return pixelclock; +} + +/* This is the horizontal CRTC mapping function in the CardSpecs. */ + +static int cirrus_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +#ifdef ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING + if (bpp == 8 && cirrus_chiptype >= CLGD5434) +#else + if (bpp == 8 && cirrus_chiptype >= CLGD5434 && pixelclock > 86000) +#endif + /* 5434 palette clock doubling mode; divide CRTC by 2. */ + return htiming / 2; + /* Otherwise, don't change. */ + return htiming; +} + +static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp, + int width_in_pixels); + +static int cirrus_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode) && mode != G320x200x256) { + __svgalib_clear_accelspecs(__svgalib_driverspecs->accelspecs); + /* Let the standard VGA driver set standard VGA modes */ + /* But first reset an Cirrus extended register that */ + /* an old XFree86 Trident probe corrupts. */ + port_outw_r(CRT_IC, 0x4a0b); + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!cirrus_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + moderegs = malloc(CIRRUS_TOTAL_REGS); + + cirrus_initializemode(moderegs, modetiming, modeinfo); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + cirrus_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + __svgalib_InitializeAcceleratorInterface(modeinfo); + + init_acceleration_specs_for_mode(__svgalib_driverspecs->accelspecs, + modeinfo->bitsPerPixel, + modeinfo->lineWidth / modeinfo->bytesPerPixel); + + __svgalib_cirrusaccel_init(__svgalib_driverspecs->accelspecs, + modeinfo->bitsPerPixel, + modeinfo->lineWidth / modeinfo->bytesPerPixel); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void cirrus_unlock(void) +{ + int vgaIOBase, temp; + + /* Are we Mono or Color? */ + vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; + + port_out_r(SEQ_I, 0x06); + port_out_r(SEQ_D, 0x12); /* unlock cirrus special */ + + /* Put the Vert. Retrace End Reg in temp */ + + port_out_r(vgaIOBase + 4, 0x11); + temp = port_in(vgaIOBase + 5); + + /* Put it back with PR bit set to 0 */ + /* This unprotects the 0-7 CRTC regs so */ + /* they can be modified, i.e. we can set */ + /* the timing. */ + + port_out_r(vgaIOBase + 5, temp & 0x7F); +} + + +/* Relock chipset-specific registers */ +/* (currently not used) */ + +static void cirrus_lock(void) +{ + port_out_r(SEQ_I, 0x06); + port_out_r(SEQ_D, 0x0F); /* relock cirrus special */ +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int cirrus_test(void) +{ + int oldlockreg; + int lockreg; + + port_out_r(SEQ_I, 0x06); + oldlockreg = port_in(SEQ_D); + + cirrus_unlock(); + + /* If it's a Cirrus at all, we should be */ + /* able to read back the lock register */ + + port_out_r(SEQ_I, 0x06); + lockreg = port_in(SEQ_D); + + /* Ok, if it's not 0x12, we're not a Cirrus542X. */ + if (lockreg != 0x12) { + port_out_r(SEQ_I, 0x06); + port_out_r(SEQ_D, oldlockreg); + return 0; + } + /* The above check seems to be weak, so we also check the chip ID. */ + + port_out_r(__svgalib_CRT_I, 0x27); + switch (port_in(__svgalib_CRT_D) >> 2) { + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: /* 5429 */ + case 0x28: /* 5430 */ + case 0x2A: /* 5434 */ + case 0x2B: /* 5436 */ + case 0x2E: /* 5446 */ + case 0x0E: /* 7548 */ + break; + default: + port_out_r(SEQ_I, 0x06); + port_out_r(SEQ_D, oldlockreg); + return 0; + } + + if (cirrus_init(0, 0, 0)) + return 0; /* failure */ + return 1; +} + + +/* Bank switching function -- set 64K page number */ + +static void cirrus_setpage_2M(int page) +{ + /* Cirrus banking register has been set to 16K granularity */ + port_outw_r(GRA_I, (page << 10) + 0x09); +} + +static void cirrus_setpage(int page) +{ + /* default 4K granularity */ + port_outw_r(GRA_I, (page << 12) + 0x09); +} + + +/* No r/w paging */ +static void cirrus_setrdpage(int page) +{ +} +static void cirrus_setwrpage(int page) +{ +} + + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void cirrus_setdisplaystart(int address) +{ + port_outw_r(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */ + port_outw_r(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */ + port_in(0x3da); /* set ATC to addressing mode */ + port_out_r(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ + /* Cirrus specific bits 0,1 and 18,19,20: */ + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | (address & 3)); + /* write sa0-1 to bits 0-1; other cards use bits 1-2 */ + port_out_r(CRT_IC, 0x1b); + port_out_r(CRT_DC, (port_in(CRT_DC) & 0xf2) + | ((address & 0x40000) >> 18) /* sa18: write to bit 0 */ + |((address & 0x80000) >> 17) /* sa19: write to bit 2 */ + |((address & 0x100000) >> 17)); /* sa20: write to bit 3 */ + port_out_r(CRT_IC, 0x1d); + if (cirrus_memory > 2048) + port_out_r(CRT_DC, (port_in(CRT_DC) & 0x7f) + | ((address & 0x200000) >> 14)); /* sa21: write to bit 7 */ +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void cirrus_setlogicalwidth(int width) +{ + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ + port_out_r(CRT_IC, 0x1b); + port_out_r(CRT_DC, (port_in(CRT_DC) & 0xef) | ((width & 0x800) >> 7)); + /* write lw12 to bit 4 of Sequencer reg. 0x1b */ +} + +static void cirrus_setlinear(int addr) +{ + int val; + port_out_r(SEQ_I, 0x07); + val = port_in(SEQ_D); + port_out_r(SEQ_D, (val & 0x0f) | (addr << 4)); +} + +static int cirrus_linear(int op, int param) +{ + if (op == LINEAR_ENABLE) { + cirrus_setlinear(0xE); + return 0; + } + if (op == LINEAR_DISABLE) { + cirrus_setlinear(0); + return 0; + } + if (cirrus_chiptype >= CLGD5424 && cirrus_chiptype <= CLGD5429) { + if (op == LINEAR_QUERY_BASE) { + if (param == 0) + return 0xE00000; /* 14MB */ + /* + * Trying 64MB on a system with 16MB of memory is unsafe if the + * card maps at 14MB. 14 MB was not attempted because of the + * system memory check in vga_setlinearaddressing(). However, + * linear addressing is enabled when looking at 64MB, causing a + * clash between video card and system memory at 14MB. + */ +#if 0 + if (__svgalib_physmem() <= 13 * 1024 * 1024) { + if (param == 1) + return 0x4000000; /* 64MB */ + if (param == 2) + return 0x4E00000; /* 78MB */ + if (param == 3) + return 0x2000000; /* 32MB */ + if (param == 4) + return 0x3E00000; /* 62MB */ + } +#endif + return -1; + } + } + if (cirrus_chiptype >= CLGD5430) { + if (op == LINEAR_QUERY_BASE) { + if(cirrus_pci_linear)return cirrus_pci_linear; + if (param == 0) + return 0x04000000; /* 64MB */ + if (param == 1) + return 0x80000000; /* 2048MB */ + if (param == 2) + return 0x02000000; /* 32MB */ + if (param == 3) + return 0x08000000; /* 128MB */ + /* While we're busy, try some common PCI */ + /* motherboard-configured addresses as well. */ + /* We only read, so should be safe. */ + if (param == 4) + return 0xA0000000; + if (param == 5) + return 0xA8000000; + if (param == 6) + return 0xE0000000; + if (param == 7) + return 0XFE000000; + /* + * Some PCI/VL motherboards only seem to let the + * VL slave slot respond at addresses >= 2048MB. + */ + if (param == 8) + return 0x84000000; + if (param == 9) + return 0x88000000; + return -1; + } + } + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + else + return -1; /* Unknown function. */ +} + + +/* Function table (exported) */ + +DriverSpecs __svgalib_cirrus_driverspecs = +{ + cirrus_saveregs, + cirrus_setregs, + cirrus_unlock, + cirrus_lock, + cirrus_test, + cirrus_init, + cirrus_setpage, + cirrus_setrdpage, + cirrus_setwrpage, + cirrus_setmode, + cirrus_modeavailable, + cirrus_setdisplaystart, + cirrus_setlogicalwidth, + cirrus_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + cirrus_linear, + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + + +/* Initialize chipset (called after detection) */ + +static char *cirrus_chipname[] = +{ + "5420", "7548", "5420-75QC-B", "5422", "5422-80QC-C", "5424", "5426", + "5428", "5429", "5430", "5434", "5436" +}; + +static unsigned char fixedMCLK[4] = +{0x1c, 0x19, 0x17, 0x15}; + +static int cirrus_init(int force, int par1, int par2) +{ + unsigned char v; + cirrus_unlock(); + if (force) { + cirrus_memory = par1; + cirrus_chiptype = par2; + } else { + unsigned char partstatus; + port_out_r(__svgalib_CRT_I, 0x27); + cirrus_chiptype = port_in(__svgalib_CRT_D) >> 2; + cirrus_chiprev = 0; + partstatus = __svgalib_inCR(0x25); + switch (cirrus_chiptype) { + case 0x22: + cirrus_chiptype = CLGD5420; +#if 0 + /* Check for CL-GD5420-75QC-B. */ + /* It has a Hidden-DAC register. */ + port_out_r(0x3C6, 0x00); + port_out_r(0x3C6, 0xFF); + port_in(0x3C6); + port_in(0x3c6); + port_in(0x3C6); + port_in(0x3C6); + if (port_in(0x3C6) != 0xFF) + cirrus_chiptype = CLGD5420B; +#endif + break; + case 0x23: + cirrus_chiptype = CLGD5422; + break; + case 0x24: + cirrus_chiptype = CLGD5426; + break; + case 0x25: + cirrus_chiptype = CLGD5424; + /* + * Some CL-GD5422's ID as CL-GD5424. + * Check for writability of GRC. + */ + v = __svgalib_inGR(0x0C); + __svgalib_outGR(0x0C, 0x55); + if (__svgalib_inGR(0x0C) != 0x55) + cirrus_chiptype = CLGD5422; + __svgalib_outGR(0x0C, v); + break; + case 0x26: + cirrus_chiptype = CLGD5428; + break; + case 0x27: + cirrus_chiptype = CLGD5429; + break; + case 0x28: + cirrus_chiptype = CLGD5430; + break; + case 0x2A: + cirrus_chiptype = CLGD5434; + if ((partstatus & 0xC0) == 0xC0) + /* Rev. E, can do 60 MHz MCLK. */ + cirrus_chiprev = 1; + break; + case 0x2B: + cirrus_chiptype = CLGD5436; + break; + case 0x2E: + /* Treat 5446 as 5436. */ + cirrus_chiptype = CLGD5436; + break; + case 0x0E: + cirrus_chiptype = CLGD7548; + break; + default: + fprintf(stderr,"Unknown Cirrus chip %2x.\n", + cirrus_chiptype); + return -1; + } + +#if 0 + if (cirrus_chiptype == CLGD5422) { + /* Rev. C has programmable MCLK register; */ + /* check for it. */ + /* This check is wrong. */ + if (__svgalib_inSR(0x1F) != 0xFF) + cirrus_chiptype = CLGD5422C; + } +#endif + + /* Now determine the amount of memory. */ + port_out_r(SEQ_I, 0x0a); /* read memory register */ + /* This depends on the BIOS having set a scratch register. */ + v = port_in(SEQ_D); + cirrus_memory = 256 << ((v >> 3) & 3); + + /* Determine memory the correct way for the 543x, and + * for the 542x if the amount seems incorrect. */ + if (cirrus_chiptype >= CLGD5430 || (cirrus_memory <= 256 + && cirrus_chiptype != CLGD5420)) { + unsigned char SRF; + cirrus_memory = 512; + port_out_r(SEQ_I, 0x0f); + SRF = port_in(SEQ_D); + if (SRF & 0x10) + /* 32-bit DRAM bus. */ + cirrus_memory *= 2; + if ((SRF & 0x18) == 0x18) + /* 64-bit DRAM data bus width; assume 2MB. */ + /* Also indicates 2MB memory on the 5430. */ + cirrus_memory *= 2; + if (cirrus_chiptype != CLGD5430 && (SRF & 0x80)) + /* If DRAM bank switching is enabled, there */ + /* must be twice as much memory installed. */ + /* (4MB on the 5434) */ + cirrus_memory *= 2; + } + } + if (__svgalib_driver_report) { + fprintf(stderr,"Using Cirrus Logic GD542x/3x driver (%s, %dK).\n", + cirrus_chipname[cirrus_chiptype], cirrus_memory); + } + if (CHIP_HAS_MCLK_REGISTER()) + actualMCLK = __svgalib_inSR(0x1F) & 0x3F; + else { + actualMCLK = fixedMCLK[__svgalib_inSR(0x0F) & 3]; + } + programmedMCLK = actualMCLK; + if (cirrus_chiptype == CLGD5434 && cirrus_chiprev > 0) + /* 5434 rev. E+ supports 60 MHz in graphics modes. */ + programmedMCLK = 0x22; + DRAMbandwidth = 14318 * (int) programmedMCLK / 16; + if (cirrus_memory >= 512) + /* At least 16-bit DRAM bus. */ + DRAMbandwidth *= 2; + if (cirrus_memory >= 1024 && CHIP_HAS_32BIT_DRAM_BUS()) + /* At least 32-bit DRAM bus. */ + DRAMbandwidth *= 2; + if (cirrus_memory >= 2048 && CHIP_HAS_64BIT_DRAM_BUS()) + /* 64-bit DRAM bus. */ + DRAMbandwidth *= 2; + /* + * Calculate highest acceptable DRAM bandwidth to be taken up + * by screen refresh. Satisfies + * total bandwidth >= refresh bandwidth * 1.1 + */ + DRAMbandwidthLimit = (DRAMbandwidth * 10) / 11; + + if(cirrus_chiptype>=CLGD5430) { + int i; + + i=(__svgalib_inSR(0x17)>>3)&7; + if(i==4) { + unsigned int buf[64]; + + if(__svgalib_pci_find_vendor_vga_pos(0x1013,buf)) + cirrus_pci_linear=buf[4]&0xffff0000; + }; + }; +/* begin: Initialize card specs. */ + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = cirrus_memory; + /* + * First determine clock limits for the chip (DAC), then + * adjust them according to the available DRAM bandwidth. + * For 32-bit DRAM cards the 16bpp clock limit is initially + * set very high, but they are cut down by the DRAM bandwidth + * check. + */ + cardspecs->maxPixelClock4bpp = 75000; /* 5420 */ + cardspecs->maxPixelClock8bpp = 45000; /* 5420 */ + cardspecs->maxPixelClock16bpp = 0; /* 5420 */ + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 0; + if (cirrus_chiptype == CLGD5420B) { + /* + * CL-GD5420-75QC-B + * Deviating chip, may be used in cheap ISA cards. + * 32-bit DRAM bus and Truecolor DAC but cannot do + * LUT > 45 MHz, and maybe has less acceleration. + */ + cardspecs->maxPixelClock16bpp = 75000 / 2; + cardspecs->maxPixelClock24bpp = 25175; + } + if (cirrus_chiptype >= CLGD5422) { + /* 5422/24/26/28 have VCLK spec of 80 MHz. */ + cardspecs->maxPixelClock4bpp = 80000; + cardspecs->maxPixelClock8bpp = 80000; + if (cirrus_chiptype >= CLGD5426) + /* DRAM bandwidth will be limiting factor. */ + cardspecs->maxPixelClock16bpp = 80000; + else + /* Clock / 2 16bpp requires 32-bit DRAM bus. */ + if (cirrus_memory >= 1024) + cardspecs->maxPixelClock16bpp = 80000 / 2; + /* Clock / 3 24bpp requires 32-bit DRAM bus. */ + if (cirrus_memory >= 1024) + cardspecs->maxPixelClock24bpp = 80000 / 3; + } + if (cirrus_chiptype >= CLGD5429) { + /* 5429, 5430, 5434 have VCLK spec of 86 MHz. */ + cardspecs->maxPixelClock4bpp = 86000; + cardspecs->maxPixelClock8bpp = 86000; + cardspecs->maxPixelClock16bpp = 86000; + if (cirrus_memory >= 1024) + cardspecs->maxPixelClock24bpp = 86000 / 3; + } + if (cirrus_chiptype == CLGD5434) { +#ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING + cardspecs->maxPixelClock8bpp = 108300; + if (cirrus_chiprev > 0) + /* 5434 rev E+ */ + cardspecs->maxPixelClock8bpp = 135300; +#endif + if (cirrus_memory >= 2048) + /* 32bpp requires 64-bit DRAM bus. */ + cardspecs->maxPixelClock32bpp = 86000; + } + if (cirrus_chiptype >=CLGD5436) { +#ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING + cardspecs->maxPixelClock8bpp = 135300; +#endif + if (cirrus_memory >= 2048) + /* 32bpp requires 64-bit DRAM bus. */ + cardspecs->maxPixelClock32bpp = 86000; + } + + cardspecs->maxPixelClock8bpp = min(cardspecs->maxPixelClock8bpp, + DRAMbandwidthLimit); + cardspecs->maxPixelClock16bpp = min(cardspecs->maxPixelClock16bpp, + DRAMbandwidthLimit / 2); + cardspecs->maxPixelClock24bpp = min(cardspecs->maxPixelClock24bpp, + DRAMbandwidthLimit / 3); + cardspecs->maxPixelClock32bpp = min(cardspecs->maxPixelClock32bpp, + DRAMbandwidthLimit / 4); + cardspecs->flags = INTERLACE_DIVIDE_VERT | GREATER_1024_DIVIDE_VERT; + /* Initialize clocks (only fixed set for now). */ + cardspecs->nClocks = NU_FIXED_CLOCKS; + cardspecs->clocks = cirrus_fixed_clocks; + cardspecs->mapClock = cirrus_map_clock; + cardspecs->mapHorizontalCrtc = cirrus_map_horizontal_crtc; + cardspecs->maxHorizontalCrtc = 2040; + /* Disable 16-color SVGA modes (don't work correctly). */ + cardspecs->maxPixelClock4bpp = 0; +/* end: Initialize card specs. */ + +#if 0 +/* begin: Initialize driver options. */ + register_option(5434 _VLB_ZERO_WAITSTATE); + register_option(50 MHZ_MCLK); + register_option(55 MHZ_MCLK); + register_option(60 MHZ_MCLK); + register_option(542 X_VLB_NORMAL_WAITSTATES); + register_option(CRT_FIFO_CONSERVATIVE); + register_option(CRT_FIFO_AGGRESSIVE); + register_option(NO_ACCELERATION); + register_option(NO_MMIO); +/* end: Initialize driver options. */ +#endif + +/* Initialize accelspecs structure. */ + __svgalib_cirrus_driverspecs.accelspecs = malloc(sizeof(AccelSpecs)); + __svgalib_clear_accelspecs(__svgalib_cirrus_driverspecs.accelspecs); + __svgalib_cirrus_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH; + /* Set up the correct paging routine */ + if (cirrus_memory >= 2048) + __svgalib_cirrus_driverspecs.__svgalib_setpage = + cirrus_setpage_2M; + + __svgalib_driverspecs = &__svgalib_cirrus_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=cirrus_pci_linear; + __svgalib_linear_mem_size=cirrus_memory*0x400; + __svgalib_mmio_size=32768; + __svgalib_mmio_base=0xb8000; + return 0; +} + + + +/* Some information on the accelerated features of the 5426, + derived from the Databook. + + port index + + Addresses have 21 bits (2Mb of memory). + GRA_I, 0x28 bits 0-7 of the destination address + GRA_I, 0x29 bits 8-15 + GRA_I, 0x2a bits 16-20 + + GRA_I, 0x2c bits 0-7 of the source address + GRA_I, 0x2d bits 8-15 + GRA_I, 0x2e bits 16-20 + + Maximum pitch is 4095. + GRA_I, 0x24 bits 0-7 of the destination pitch (screen width) + GRA_I, 0x25 bits 8-11 + + GRA_I, 0x26 bits 0-7 of the source pitch (screen width) + GRA_I, 0x27 bits 8-11 + + Maximum width is 2047. + GRA_I, 0x20 bits 0-7 of the box width - 1 + GRA_I, 0x21 bits 8-10 + + Maximum height is 1023. + GRA_I, 0x22 bits 0-7 of the box height - 1 + GRA_I, 0x23 bits 8-9 + + GRA_I, 0x30 BLT mode + bit 0: direction (0 = down, 1 = up) + bit 1: destination + bit 2: source (0 = video memory, 1 = system memory) + bit 3: enable transparency compare + bit 4: 16-bit color expand/transparency + bit 6: 8x8 pattern copy + bit 7: enable color expand + + 0x31 BLT status + bit 0: busy + bit 1: start operation (1)/suspend (0) + bit 2: reset + bit 3: set while blit busy/suspended + + 0x32 BLT raster operation + 0x00 black + 0x01 white + 0x0d copy source + 0xd0 copy inverted source + 0x0b invert destination + 0x05 logical AND + 0x6d logical OR (paint) + 0x59 XOR + + 0x34 BLT transparent color + 0x35 high byte + + GRA_I, 0x00 background color (for color expansion) + GRA_I, 0x01 foreground color + GRA_I, 0x10 high byte of background color for 16-bit pixels + GRA_I, 0x11 high byte of foreground color + + GRA_I, 0x0b bit 1: enable BY8 addressing + SEQ_I, 0x02 8-bit plane mask for BY8 (corresponds to 8 pixels) + (write mode 1, 4, 5) + SEQ_D, 0x05 bits 0-2: VGA write mode + extended write mode 4: write up to 8 pixels in + foreground color (BY8) + extended write mode 5: write 8 pixels in foreground/ + background color (BY8) + This may also work in normal non-BY8 packed-pixel mode. + + When doing blits from system memory to video memory, pixel data + can apparently be written to any video address in 16-bit words, with + the each scanline padded to 4-byte alignment. This is handy because + the chip handles line transitions and alignment automatically (and + can do, for example, masking). + + The pattern copy requires an 8x8 pattern (64 pixels) at the source + address in video memory, and fills a box with specified size and + destination address with the pattern. This is in fact the way to do + solid fills. + + mode pattern + Color Expansion 8 bytes (monochrome bitmap) + 8-bit pixels 64 bytes + 16-bit pixels 128 bytes + + */ + + + +/* Cirrus Logic acceleration functions implementation. */ + +/* BitBLT modes. */ + +#define FORWARDS 0x00 +#define BACKWARDS 0x01 +#define SYSTEMDEST 0x02 +#define SYSTEMSRC 0x04 +#define TRANSPARENCYCOMPARE 0x08 +#define PIXELWIDTH16 0x10 +#define PIXELWIDTH32 0x30 /* 543x only. */ +#define PATTERNCOPY 0x40 +#define COLOREXPAND 0x80 + +/* Macros for normal I/O BitBLT register access. */ + +#define SETSRCADDR(addr) \ + port_outw_r(GRA_I, (((addr) & 0x000000FF) << 8) | 0x2C); \ + port_outw_r(GRA_I, (((addr) & 0x0000FF00)) | 0x2D); \ + port_outw_r(GRA_I, (((addr) & 0x003F0000) >> 8) | 0x2E); + +#define SETDESTADDR(addr) \ + port_outw_r(GRA_I, (((addr) & 0x000000FF) << 8) | 0x28); \ + port_outw_r(GRA_I, (((addr) & 0x0000FF00)) | 0x29); \ + port_outw_r(GRA_I, (((addr) & 0x003F0000) >> 8) | 0x2A); + +/* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */ + +#define SETDESTPITCH(pitch) \ + port_outw_r(GRA_I, (((pitch) & 0x000000FF) << 8) | 0x24); \ + port_outw_r(GRA_I, (((pitch) & 0x00001F00)) | 0x25); + +#define SETSRCPITCH(pitch) \ + port_outw_r(GRA_I, (((pitch) & 0x000000FF) << 8) | 0x26); \ + port_outw_r(GRA_I, (((pitch) & 0x00001F00)) | 0x27); + +/* Width: the 5426 goes up to 2048, the 5434 can do 8192. */ + +#define SETWIDTH(width) \ + port_outw_r(GRA_I, ((((width) - 1) & 0x000000FF) << 8) | 0x20); \ + port_outw_r(GRA_I, ((((width) - 1) & 0x00001F00)) | 0x21); + +/* Height: the 5426 goes up to 1024, the 5434 can do 2048. */ +/* It appears many 5434's only go up to 1024. */ + +#define SETHEIGHT(height) \ + port_outw_r(GRA_I, ((((height) - 1) & 0x000000FF) << 8) | 0x22); \ + port_outw_r(GRA_I, (((height) - 1) & 0x00000700) | 0x23); + +#define SETBLTMODE(m) \ + port_outw_r(GRA_I, ((m) << 8) | 0x30); + +#define SETBLTWRITEMASK(m) \ + port_outw_r(GRA_I, ((m) << 8) | 0x2F); + +#define SETTRANSPARENCYCOLOR(c) \ + port_outw_r(GRA_I, ((c) << 8) | 0x34); + +#define SETTRANSPARENCYCOLOR16(c) \ + port_outw_r(GRA_I, ((c) << 8) | 0x34); \ + port_outw_r(GRA_I, (c & 0xFF00) | 0x35); + +#define SETTRANSPARENCYCOLORMASK16(m) \ + port_outw_r(GRA_I, ((m) << 8) | 0x38); \ + port_outw_r(GRA_I, ((m) & 0xFF00) | 0x39); + +#define SETROP(rop) \ + port_outw_r(GRA_I, ((rop) << 8) | 0x32); + +#define SETFOREGROUNDCOLOR(c) \ + port_outw_r(GRA_I, 0x01 + ((c) << 8)); + +#define SETBACKGROUNDCOLOR(c) \ + port_outw_r(GRA_I, 0x00 + ((c) << 8)); + +#define SETFOREGROUNDCOLOR16(c) \ + port_outw_r(GRA_I, 0x01 + ((c) << 8)); \ + port_outw_r(GRA_I, 0x11 + ((c) & 0xFF00)); + +#define SETBACKGROUNDCOLOR16(c) \ + port_outw_r(GRA_I, 0x00 + ((c) << 8)); \ + port_outw_r(GRA_I, 0x10 + ((c) & 0xFF00)); \ + +#define SETFOREGROUNDCOLOR32(c) \ + port_outw_r(GRA_I, 0x01 + ((c) << 8)); \ + port_outw_r(GRA_I, 0x11 + ((c) & 0xFF00)); \ + port_outw_r(GRA_I, 0x13 + (((c) & 0xFf0000) >> 8)); \ + port_outw_r(GRA_I, 0x15 + (((unsigned int)(c) & 0xFF000000) >> 16)); + +#define SETBACKGROUNDCOLOR32(c) \ + port_outw_r(GRA_I, 0x00 + ((c) << 8)); \ + port_outw_r(GRA_I, 0x10 + ((c) & 0xFF00)); \ + port_outw_r(GRA_I, 0x12 + (((c) & 0xFF0000) >> 8)); \ + port_outw_r(GRA_I, 0x14 + (((unsigned int)(c) & 0xFF000000) >> 16)); + +#define STARTBLT() { \ + unsigned char tmp; \ + port_out_r(GRA_I, 0x31); \ + tmp = port_in(GRA_D); \ + port_out_r(GRA_D, tmp | 0x02); \ + } + +#define BLTBUSY(s) { \ + port_out_r(GRA_I, 0x31); \ + s = port_in(GRA_D) & 1; \ + } + +#define WAITUNTILFINISHED() \ + for (;;) { \ + int busy; \ + BLTBUSY(busy); \ + if (!busy) \ + break; \ + } + + +/* Macros for memory-mapped I/O BitBLT register access. */ + +/* MMIO addresses (offset from 0xb8000). */ + +#define MMIOBACKGROUNDCOLOR 0x00 +#define MMIOFOREGROUNDCOLOR 0x04 +#define MMIOWIDTH 0x08 +#define MMIOHEIGHT 0x0A +#define MMIODESTPITCH 0x0C +#define MMIOSRCPITCH 0x0E +#define MMIODESTADDR 0x10 +#define MMIOSRCADDR 0x14 +#define MMIOBLTWRITEMASK 0x17 +#define MMIOBLTMODE 0x18 +#define MMIOROP 0x1A +#define MMIOBLTSTATUS 0x40 + +#define MMIOSETDESTADDR(addr) v_writel(addr, MMIODESTADDR); + +#define MMIOSETSRCADDR(addr) v_writel(addr, MMIOSRCADDR); + +/* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */ + +#define MMIOSETDESTPITCH(pitch) v_writel(pitch, MMIODESTPITCH); + +#define MMIOSETSRCPITCH(pitch) v_writel(pitch, MMIOSRCPITCH); + +/* Width: the 5426 goes up to 2048, the 5434 can do 8192. */ + +#define MMIOSETWIDTH(width) \ + *(unsigned short *)(MMIO_POINTER + MMIOWIDTH) = (width) - 1; + +/* Height: the 5426 goes up to 1024, the 5434 can do 2048. */ + +#define MMIOSETHEIGHT(height) \ + *(unsigned short *)(MMIO_POINTER + MMIOHEIGHT) = (height) - 1; + +#define MMIOSETBLTMODE(m) \ + *(unsigned char *)(MMIO_POINTER + MMIOBLTMODE) = m; + +#define MMIOSETBLTWRITEMASK(m) \ + *(unsigned char *)(MMIO_POINTER + MMIOBLTWRITEMASK) = m; + +#define MMIOSETROP(rop) \ + *(unsigned char *)(MMIO_POINTER + MMIOROP) = rop; + +#define MMIOSTARTBLT() \ + *(unsigned char *)(MMIO_POINTER + MMIOBLTSTATUS) |= 0x02; + +#define MMIOBLTBUSY(s) \ + s = v_readb(MMIOBLTSTATUS) & 1; + +#define MMIOSETBACKGROUNDCOLOR(c) \ + *(unsigned char *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c; + +#define MMIOSETFOREGROUNDCOLOR(c) \ + *(unsigned char *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c; + +#define MMIOSETBACKGROUNDCOLOR16(c) \ + *(unsigned short *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c; + +#define MMIOSETFOREGROUNDCOLOR16(c) \ + *(unsigned short *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c; + +#define MMIOSETBACKGROUNDCOLOR32(c) \ + *(unsigned int *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c; + +#define MMIOSETFOREGROUNDCOLOR32(c) \ + *(unsigned int *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c; + +#define MMIOWAITUNTILFINISHED() \ + for (;;) { \ + int busy; \ + MMIOBLTBUSY(busy); \ + if (!busy) \ + break; \ + } + +static int cirrus_pattern_address; /* Pattern with 1's (8 bytes) */ +static int cirrus_bitblt_pixelwidth; +/* Foreground color is not preserved on 5420/2/4/6/8. */ +static int cirrus_accel_foreground_color; + +static void __svgalib_cirrusaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels) +{ + /* [Setup accelerator screen pitch] */ + /* [Prepare any required off-screen space] */ + if (cirrus_chiptype < CLGD5426) + /* No BitBLT engine. */ + return; + if (bpp == 8) + cirrus_bitblt_pixelwidth = 0; + if (bpp == 16) + cirrus_bitblt_pixelwidth = PIXELWIDTH16; + if (bpp == 32) + cirrus_bitblt_pixelwidth = PIXELWIDTH32; + SETSRCPITCH(__svgalib_accel_screenpitchinbytes); + SETDESTPITCH(__svgalib_accel_screenpitchinbytes); + SETROP(0x0D); + cirrus_pattern_address = cirrus_memory * 1024 - 8; + (*__svgalib_driverspecs->__svgalib_setpage) (cirrus_pattern_address / 65536); + gr_writel(0xffffffff, cirrus_pattern_address & 0xffff); + gr_writel(0xffffffff, (cirrus_pattern_address & 0xffff) + 4); + (*__svgalib_driverspecs->__svgalib_setpage) (0); + if (cirrus_chiptype >= CLGD5429) + /* Enable memory-mapped I/O. */ + __svgalib_outSR(0x17, __svgalib_inSR(0x17) | 0x04); +} + + +/* + * Note: The foreground color register must always be reset to 0 + * on the 542x to avoid problems in normal framebuffer operation. + * This is not the case on chips that support memory-mapped I/O. + */ + +/* + * These are two auxilliary functions to program the foreground + * color depending on the current depth. + */ + +static void set_foreground_color(int fg) +{ + if (__svgalib_accel_bytesperpixel == 1) { + SETFOREGROUNDCOLOR(fg); + return; + } + if (__svgalib_accel_bytesperpixel == 2) { + SETFOREGROUNDCOLOR16(fg); + return; + } + SETFOREGROUNDCOLOR32(fg); +} + +static void mmio_set_foreground_color(int fg) +{ + if (__svgalib_accel_bytesperpixel == 1) { + MMIOSETFOREGROUNDCOLOR(fg); + return; + } + if (__svgalib_accel_bytesperpixel == 2) { + MMIOSETFOREGROUNDCOLOR16(fg); + return; + } + MMIOSETFOREGROUNDCOLOR32(fg); +} + +#define FINISHBACKGROUNDBLITS() \ + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) \ + WAITUNTILFINISHED(); + +#define MMIOFINISHBACKGROUNDBLITS() \ + if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) \ + MMIOWAITUNTILFINISHED(); + +static void __svgalib_cirrusaccel_FillBox(int x, int y, int width, int height) +{ + int destaddr; + destaddr = BLTBYTEADDRESS(x, y); + width *= __svgalib_accel_bytesperpixel; + FINISHBACKGROUNDBLITS(); + SETSRCADDR(cirrus_pattern_address); + SETDESTADDR(destaddr); + SETWIDTH(width); + SETHEIGHT(height); + set_foreground_color(cirrus_accel_foreground_color); + SETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth); + STARTBLT(); + WAITUNTILFINISHED(); + /* Can't easily run in background because foreground color has */ + /* to be restored. */ + SETFOREGROUNDCOLOR(0x00); +} + +static void __svgalib_cirrusaccel_mmio_FillBox(int x, int y, int width, int height) +{ + int destaddr; + destaddr = BLTBYTEADDRESS(x, y); + width *= __svgalib_accel_bytesperpixel; + MMIOFINISHBACKGROUNDBLITS(); + MMIOSETSRCADDR(cirrus_pattern_address); + MMIOSETDESTADDR(destaddr); + MMIOSETWIDTH(width); + MMIOSETHEIGHT(height); + MMIOSETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth); + MMIOSTARTBLT(); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + MMIOWAITUNTILFINISHED(); +} + +static void __svgalib_cirrusaccel_ScreenCopy(int x1, int y1, int x2, int y2, int width, + int height) +{ + int srcaddr, destaddr, dir; + width *= __svgalib_accel_bytesperpixel; + srcaddr = BLTBYTEADDRESS(x1, y1); + destaddr = BLTBYTEADDRESS(x2, y2); + dir = FORWARDS; + if ((y1 < y2 || (y1 == y2 && x1 < x2)) + && y1 + height > y2) { + srcaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1; + destaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1; + dir = BACKWARDS; + } + FINISHBACKGROUNDBLITS(); + SETSRCADDR(srcaddr); + SETDESTADDR(destaddr); + SETWIDTH(width); + SETHEIGHT(height); + SETBLTMODE(dir); + STARTBLT(); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + WAITUNTILFINISHED(); +} + +static void __svgalib_cirrusaccel_mmio_ScreenCopy(int x1, int y1, int x2, int y2, int width, + int height) +{ + int srcaddr, destaddr, dir; + width *= __svgalib_accel_bytesperpixel; + srcaddr = BLTBYTEADDRESS(x1, y1); + destaddr = BLTBYTEADDRESS(x2, y2); + dir = FORWARDS; + if ((y1 < y2 || (y1 == y2 && x1 < x2)) + && y1 + height > y2) { + srcaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1; + destaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1; + dir = BACKWARDS; + } + MMIOFINISHBACKGROUNDBLITS(); + MMIOSETSRCADDR(srcaddr); + MMIOSETDESTADDR(destaddr); + MMIOSETWIDTH(width); + MMIOSETHEIGHT(height); + MMIOSETBLTMODE(dir); + MMIOSTARTBLT(); + if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND)) + MMIOWAITUNTILFINISHED(); +} + +static void __svgalib_cirrusaccel_SetFGColor(int fg) +{ + cirrus_accel_foreground_color = fg; +} + +static void __svgalib_cirrusaccel_mmio_SetFGColor(int fg) +{ + MMIOFINISHBACKGROUNDBLITS(); + mmio_set_foreground_color(fg); +} + +static unsigned char cirrus_rop_map[] = +{ + 0x0D, /* ROP_COPY */ + 0x6D, /* ROP_OR */ + 0x05, /* ROP_AND */ + 0x59, /* ROP_XOR */ + 0x0B /* ROP_INVERT */ +}; + +static void __svgalib_cirrusaccel_SetRasterOp(int rop) +{ + FINISHBACKGROUNDBLITS(); + SETROP(cirrus_rop_map[rop]); +} + +static void __svgalib_cirrusaccel_mmio_SetRasterOp(int rop) +{ + MMIOFINISHBACKGROUNDBLITS(); + MMIOSETROP(cirrus_rop_map[rop]); +} + +static void __svgalib_cirrusaccel_SetTransparency(int mode, int color) +{ + FINISHBACKGROUNDBLITS(); + if (mode == DISABLE_TRANSPARENCY_COLOR) { + /* Disable. */ + SETTRANSPARENCYCOLORMASK16(0xFFFF); + return; + } + if (mode == ENABLE_TRANSPARENCY_COLOR) { + if (__svgalib_accel_bytesperpixel == 1) + color += color << 8; + SETTRANSPARENCYCOLORMASK16(0x0000); + SETTRANSPARENCYCOLOR16(color); + return; + } + if (mode == DISABLE_BITMAP_TRANSPARENCY) { + __svgalib_accel_bitmaptransparency = 0; + return; + } + /* mode == ENABLE_BITMAP_TRANSPARENCY */ + __svgalib_accel_bitmaptransparency = 1; +} + +static void __svgalib_cirrusaccel_Sync(void) +{ + WAITUNTILFINISHED(); +} + +void __svgalib_cirrusaccel_mmio_Sync(void) +{ + MMIOWAITUNTILFINISHED(); +} + + +/* + * Set up accelerator interface for pixels of size bpp and scanline width + * of width_in_pixels. + */ + +static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp, + int width_in_pixels) +{ + accelspecs->operations = 0; + accelspecs->ropOperations = 0; + accelspecs->transparencyOperations = 0; + accelspecs->ropModes = 0; + accelspecs->transparencyModes = 0; + accelspecs->flags = ACCELERATE_ANY_LINEWIDTH; + + if (cirrus_chiptype >= CLGD5426) { + accelspecs->operations |= ACCELFLAG_SETMODE | ACCELFLAG_SYNC; + if (bpp == 8 || bpp == 16) { + /* BitBLT engine available. */ + accelspecs->operations |= + ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | + ACCELFLAG_SCREENCOPY | + ACCELFLAG_SETRASTEROP | + ACCELFLAG_SETTRANSPARENCY; + accelspecs->ropOperations = + ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY; + accelspecs->transparencyOperations = + ACCELFLAG_SCREENCOPY; + accelspecs->ropModes |= (1<transparencyModes |= + (1<operations |= + ACCELFLAG_SCREENCOPY; + accelspecs->ropOperations = + ACCELFLAG_SCREENCOPY; + accelspecs->ropModes |= (1<= CLGD5429) + if (bpp == 8 || bpp == 16) { + /* Newer chips don't have true color-compare. */ + accelspecs->operations &= ~ACCELFLAG_SETTRANSPARENCY; + accelspecs->transparencyOperations = 0; + accelspecs->ropModes = 0; + accelspecs->transparencyModes = 0; + } + if (cirrus_chiptype >= CLGD5434) + if (bpp == 32) { + /* BitBLT engine available for 32bpp. */ + accelspecs->operations |= + ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | + ACCELFLAG_SCREENCOPY | + ACCELFLAG_SETRASTEROP | + ACCELFLAG_SETTRANSPARENCY; + accelspecs->ropOperations = + ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY; + accelspecs->ropModes |= (1<operations = + ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | ACCELFLAG_DRAWHLINE | + ACCELFLAG_DRAWHLINELIST; + if (cirrus_chiptype >= CLGD5422) + if (bpp == 16) + /* Also for 16bpp. */ + accelspecs->operations = + ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | + ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST; + if (cirrus_chiptype >= CLGD5426 && cirrus_memory >= 1024) { + if (bpp == 8 || bpp == 16) { + /* BitBLT engine available. */ + accelspecs->operations |= + ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE | + ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP | + ACCELFLAG_SETTRANSPARENCY | + ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP + ACCELFLAG_SCREENCOPYBITMAP; + accelspecs->ropOperations = + ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY | + ACCELFLAG_PUTIMAGE; + accelspecs->transparencyOperations = + ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE | + ACCELFLAG_PUTBITMAP; + accelspecs->ropModes |= (1<transparencyModes |= + (1<operations |= + ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE; + accelspecs->ropOperations = + ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE; + accelspecs->ropModes |= (1<= CLGD5429) + if (bpp == 8 || bpp == 16) { + /* Newer chips don't have true color-compare. */ + accelspecs->transparencyOperations = ACCELFLAG_BITMAP; + } + if (cirrus_chiptype >= CLGD5434) + if (bpp == 32) { + /* BitBLT engine available for 32bpp. */ + accelspecs->operations |= + ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE | + ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP | + ACCELFLAG_SETTRANSPARENCY | + ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP + ACCELFLAG_SCREENCOPYBITMAP | + ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST; + accelspecs->ropOperations = + ACCELFLAG_FILLBOX | + ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE; + accelspecs->transparencyOperations = + ACCELFLAG_PUTBITMAP; + accelspecs->ropModes |= (1<transparencyModes |= + (1<FillBox = __svgalib_cirrusaccel_FillBox; + accelspecs->ScreenCopy = __svgalib_cirrusaccel_ScreenCopy; + accelspecs->SetFGColor = __svgalib_cirrusaccel_SetFGColor; + accelspecs->SetTransparency = __svgalib_cirrusaccel_SetTransparency; + accelspecs->SetRasterOp = __svgalib_cirrusaccel_SetRasterOp; + accelspecs->Sync = __svgalib_cirrusaccel_Sync; + if (cirrus_chiptype >= CLGD5429) { + accelspecs->FillBox = __svgalib_cirrusaccel_mmio_FillBox; + accelspecs->ScreenCopy = __svgalib_cirrusaccel_mmio_ScreenCopy; + accelspecs->SetFGColor = __svgalib_cirrusaccel_mmio_SetFGColor; + /* No mmio-version of SetTransparency. */ + accelspecs->SetRasterOp = __svgalib_cirrusaccel_mmio_SetRasterOp; + accelspecs->Sync = __svgalib_cirrusaccel_mmio_Sync; + } +} diff --git a/src/drivers/drivers b/src/drivers/drivers new file mode 100644 index 0000000..1714d51 --- /dev/null +++ b/src/drivers/drivers @@ -0,0 +1,45 @@ +driver linear + +et3000 +tvga8900 +vgadrv + +egadrv +mach64 + +ali +ark +cirrus +s3 + +et4000 +gvga6400 +mach32 +oak +paradise +ati +chips + +neomagic +et6000 +fbdev + +vesa + +apm +banshee +g400 +i740 +i810 +laguna +millennium +mx +nv3 +pm2 +r128 +rage +rendition +savage +sis +trident + diff --git a/src/drivers/et3000.c b/src/drivers/et3000.c new file mode 100644 index 0000000..12f8117 --- /dev/null +++ b/src/drivers/et3000.c @@ -0,0 +1,371 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright (c) 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* + ** Used extended ET3000 registers (EXT+xx) : + ** + ** 00 : CRT (3d4) index 23 + ** 01 : CRT (3d4) index 24 + ** 02 : CRT (3d4) index 25 + ** 03 : SEQ (3c4) index 06 + ** 04 : SEQ (3c4) index 07 + ** 05 : Segment select (3cd) + ** 06 : ATT (3c0) index 16 + ** + */ + +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#define SEG_SELECT 0x3CD + +static int et3000_memory; + +static int et3000_init(int, int, int); +static int et3000_interlaced(int mode); +static void et3000_unlock(void); + + +/* Mode table */ +#include "regs/et3000.regs" + +static ModeTable et3000_modes[] = +{ +/* *INDENT-OFF* */ + OneModeEntry(640x480x256), + OneModeEntry(800x600x16), + OneModeEntry(800x600x256), + OneModeEntry(1024x768x16), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +/*#endif *//* !defined(DYNAMIC) */ + +/* Fill in chipset specific mode information */ + +static void et3000_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + switch (modeinfo->colors) { + case 16: /* 4-plane 16 color mode */ + modeinfo->maxpixels = 65536 * 8; + break; + default: + if (modeinfo->bytesperpixel > 0) + modeinfo->maxpixels = et3000_memory * 1024 / + modeinfo->bytesperpixel; + else + modeinfo->maxpixels = et3000_memory * 1024; + break; + } + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = 0x7ffff; + modeinfo->haveblit = 0; + modeinfo->flags |= HAVE_RWPAGE; + if (et3000_interlaced(mode)) + modeinfo->flags |= IS_INTERLACED; +} + + +/* Read and store chipset-specific registers */ + +static int et3000_saveregs(unsigned char regs[]) +{ + int i; + + et3000_unlock(); + /* save extended CRT registers */ + for (i = 0; i < 3; i++) { + port_out(0x23 + i, __svgalib_CRT_I); + regs[EXT + i] = port_in(__svgalib_CRT_D); + } + + /* save extended sequencer register */ + for (i = 0; i < 2; ++i) { + port_out(6 + i, SEQ_I); + regs[EXT + 3 + i] = port_in(SEQ_D); + } + + /* save some other ET3000 specific registers */ + regs[EXT + 5] = port_in(0x3cd); + + /* save extended attribute register */ + port_in(__svgalib_IS1_R); /* reset flip flop */ + port_out(0x16, ATT_IW); + regs[EXT + 6] = port_in(ATT_R); + + return 7; /* ET3000 requires 7 additional registers */ +} + + +/* Set chipset-specific registers */ + +static void et3000_setregs(const unsigned char regs[], int mode) +{ + int i; + unsigned char save; + + et3000_unlock(); + /* write some ET3000 specific registers */ + port_out(regs[EXT + 5], 0x3cd); + + /* write extended sequencer register */ + for (i = 0; i < 2; ++i) { + port_out(6 + i, SEQ_I); + port_out(regs[EXT + 3 + i], SEQ_D); + } + + /* deprotect CRT register 0x25 */ + port_out(0x11, __svgalib_CRT_I); + save = port_in(__svgalib_CRT_D); + port_out(save & 0x7F, __svgalib_CRT_D); + + /* write extended CRT registers */ + for (i = 0; i < 3; i++) { + port_out(0x23 + i, __svgalib_CRT_I); + port_out(regs[EXT + i], __svgalib_CRT_D); + } + + /* set original CRTC 0x11 */ + port_out(0x11, __svgalib_CRT_I); + port_out(save, __svgalib_CRT_D); + + /* write extended attribute register */ + port_in(__svgalib_IS1_R); /* reset flip flop */ + port_out(0x16, ATT_IW); + port_out(regs[EXT + 6], ATT_IW); +} + + +/* Return non-zero if mode is available */ + +static int et3000_modeavailable(int mode) +{ + const unsigned char *regs; + struct vgainfo *info; + + regs = LOOKUPMODE(et3000_modes, mode); + if (regs == NULL || mode == GPLANE16) + return __svgalib_vga_driverspecs.modeavailable(mode); + if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE) + return 0; + + info = &__svgalib_infotable[mode]; + if (et3000_memory * 1024 < info->ydim * info->xbytes) + return 0; + + return SVGADRV; +} + + +/* Check if mode is interlaced */ + +static int et3000_interlaced(int mode) +{ + const unsigned char *regs; + + if (et3000_modeavailable(mode) != SVGADRV) + return 0; + regs = LOOKUPMODE(et3000_modes, mode); + if (regs == NULL || regs == DISABLE_MODE) + return 0; + return (regs[EXT + 2] & 0x80) != 0; /* CRTC 25H */ +} + + +/* Set a mode */ + +static int et3000_setmode(int mode, int prv_mode) +{ + const unsigned char *regs; + + switch (et3000_modeavailable(mode)) { + case STDVGADRV: + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + case SVGADRV: + regs = LOOKUPMODE(et3000_modes, mode); + if (regs != NULL) + break; + default: + return 1; /* mode not available */ + } + + et3000_unlock(); + __svgalib_setregs(regs); + et3000_setregs(regs, mode); + return 0; +} + +/* Unlock chipset-specific registers */ + +static void et3000_unlock(void) +{ + /* get access to extended registers */ + int base; + + base = (port_in(0x3cc) & 1 ? 0x3d0 : 0x3b0); + port_out(3, 0x3bf); + port_out(0xa0, base + 8); + port_out(0x24, base + 4); + port_out(port_in(base + 5) & 0xDF, base + 5); +} + + +/* Relock chipset-specific registers */ + +static void et3000_lock(void) +{ +} + + +/* Indentify chipset; return non-zero if detected */ + +static int et3000_test(void) +{ + unsigned char old, val; + int base; + + /* test for Tseng clues */ + old = port_in(0x3cd); + port_out(old ^ 0x3f, 0x3cd); + val = port_in(0x3cd); + port_out(old, 0x3cd); + + /* return false if not Tseng */ + if (val != (old ^ 0x3f)) + return 0; + + /* test for ET3000 clues */ + if (port_in(0x3cc) & 1) + base = CRT_IC; + else + base = 0x3b4; + port_out(0x1b, base); + old = port_in(base + 1); + port_out(old ^ 0xff, base + 1); + val = port_in(base + 1); + port_out(old, base + 1); + + /* return false if not ET3000 */ + if (val != (old ^ 0xff)) + return 0; + + /* Found ET3000 */ + et3000_init(0, 0, 0); + return 1; +} + + + +static unsigned char last_page = 0x40; + +/* Bank switching function - set 64K bank number */ +static void et3000_setpage(int page) +{ + last_page = page | (page << 3) | 0x40; + port_out(last_page, SEG_SELECT); +} + + +/* Bank switching function - set 64K read bank number */ +static void et3000_setrdpage(int page) +{ + last_page &= 0xC7; + last_page |= (page << 3); + port_out(last_page, SEG_SELECT); +} + +/* Bank switching function - set 64K write bank number */ +static void et3000_setwrpage(int page) +{ + last_page &= 0xF8; + last_page |= page; + port_out(last_page, SEG_SELECT); +} + + +/* Set display start address (not for 16 color modes) */ +/* ET4000 supports any address in video memory (up to 1Mb) */ + +static void et3000_setdisplaystart(int address) +{ + port_outw_r(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */ + port_outw_r(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */ + port_in(0x3da); /* set ATC to addressing mode */ + port_out_r(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); + /* write sa0-1 to bits 1-2 */ + port_out_r(CRT_IC, 0x23); + port_out_r(CRT_DC, (port_in(CRT_DC) & 0xfd) + | ((address & 0x40000) >> 17)); /* write sa18 to bit 1 */ +} + + +/* Set logical scanline length (usually multiple of 8) */ + +static void et3000_setlogicalwidth(int width) +{ + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ +} + + +/* Function table (exported) */ + +DriverSpecs __svgalib_et3000_driverspecs = +{ + et3000_saveregs, + et3000_setregs, + et3000_unlock, + et3000_lock, + et3000_test, + et3000_init, + et3000_setpage, + et3000_setrdpage, + et3000_setwrpage, + et3000_setmode, + et3000_modeavailable, + et3000_setdisplaystart, + et3000_setlogicalwidth, + et3000_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + + +/* Initialize chipset (called after detection) */ + +static int et3000_init(int force, int par1, int par2) +{ + if (force) + et3000_memory = par1; + else { + et3000_memory = 512; + /* Any way to check this ?? */ + } + + if (__svgalib_driver_report) + fprintf(stderr,"Using Tseng ET3000 driver (%d).\n", et3000_memory); + __svgalib_driverspecs = &__svgalib_et3000_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + + return 0; +} diff --git a/src/drivers/et4000.c b/src/drivers/et4000.c new file mode 100644 index 0000000..6fe7a35 --- /dev/null +++ b/src/drivers/et4000.c @@ -0,0 +1,1136 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright (c) 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* ET4000 code taken from VGAlib + * ET4000 code modified to handle HiColor modes better by David Monro + * Dynamic register loading by Hartmut Schirmer + * HH: ET4000/W32 detection added and support for more than 1Mb (based on + * vgadoc3) (untested). + * HH: Detect newer ET4000/W32p. + */ + + +/* Note that the clock detection stuff is currently not used. */ + +/* ET4000 registers description (from vgadoc2) + ** + ** + ** + ** 102h: Microchannel Setup Control + ** bit 0 Disable Card if set + ** + ** 3BFh (R/W): Hercules Compatability register + ** + ** 3C0h index 16h: ATC Miscellaneous + ** (Write data to 3C0h, Read from 3C1h (May not be needed)) + ** bit 4,5 High resolution timings. + ** 7 Bypass the internal palette if set + ** + ** 3C3h (R/W): Microchannel Video Subsystem Enable Register: + ** bit 0 Enable Microchannel VGA if set + ** + ** 3C4h index 6 (R/W): TS State Control + ** bit 1-2 dots per characters in text mode + ** (bit 0: 3c4 index 1, bit 0) + ** bit <2:0> ! dots/char + ** 111 ! 16 + ** 100 ! 12 + ** 011 ! 11 + ** 010 ! 10 + ** 001 ! 8 + ** 000 ! 9 + ** + ** 3C4h index 7 (R/W): TS Auxiliary Mode + ** bit 0 If set select MCLK/4 (if bit 6 is also set to 1) + ** 1 If set select SCLK input from MCLK + ** 3,5 Rom Bios Enable/Disable: + ** 0 0 C000-C3FF Enabled + ** 0 1 Rom disabled + ** 1 0 C000-C5FF,C680-C7FF Enabled + ** 1 1 C000-C7FF Enabled + ** 6 MCLK/2 if set + ** 7 VGA compatible if set EGA else. + ** + ** 3CBh (R/W): PEL Address/Data Wd + ** + ** 3CDh (R/W): Segment Select + ** 0-3 64k Write bank nr (0..15) + ** 4-7 64k Read bank nr (0..15) + ** + ** 3CEh index Dh (R/W): Microsequencer Mode + ** + ** 3CEh index Eh (R/W): Microsequencer Reset + ** + ** 3d4h index 24h (R/W): Compatibility Control + ** bit 0 Enable Clock Translate + ** 1 Additional Master Clock Select + ** 2 Enable tri-state for all output pins + ** 3 Enable input A8 of 1MB DRAMs + ** 4 Reserved + ** 5 Enable external ROM CRTC translation + ** 6 Enable Double Scan and Underline Attribute + ** 7 CGA/MDA/Hercules + ** + ** 3d4h index 32h (R/W): RAS/CAS Video Config + ** Ram timing, System clock and Ram type. Sample values: + ** 00h VRAM 80nsec + ** 09h VRAM 100nsec + ** 00h VRAM 28MHz + ** 08h VRAM 36MHz + ** 70h DRAM 40MHz + ** + ** 3d4h index 33h (R/W): Extended start ET4000 + ** bit 0-1 Display start address bits 16-17 + ** 2-3 Cursor start address bits 16-17 + ** Can be used to ID ET4000 + ** + ** 3d4h index 34h (R/W): Compatibility Control Register + ** bit 2 bit 3 of clock select (bit 1-0 in misc output) + ** 3 if set Video Subsystem Enable Register at 46E8h + ** else at 3C3h. + ** + ** 3d4h index 35h (R/W): Overflow High ET4000 + ** bit 0 Vertical Blank Start Bit 10 + ** 1 Vertical Total Bit 10 + ** 2 Vertical Display End Bit 10 + ** 3 Vertical Sync Start Bit 10 + ** 4 Line Compare Bit 10 + ** 5 Gen-Lock Enabled if set (External sync) + ** 6 Read/Modify/Write Enabled if set. Currently not implemented. + ** 7 Vertical interlace if set + ** + ** 3d4h index 36h (R/W): Video System Configuration 1 + ** bit 0-2 Refresh count per line - 1 + ** 3 16 bit wide fonts if set, else 8 bit wide + ** 4 Linear addressing if set. Video Memory is + ** mapped as a 1 Meg block above 1MB. (set + ** GDC index 6 bits 3,2 to zero (128k)) + ** 5 TLI addressing mode if set + ** 6 16 bit data path (video memory) if set + ** 7 16 bit data (I/O operations) if set + ** + ** 3d4h index 37h (R/W): Video System Configuration 2 + ** bit 0-1 Display memory data bus width + ** 0,1=8bit, 2=16bit, 3=32bit; may be + ** read as number of memory banks (1,2,4) + ** 2 Bus read data latch control. If set latches + ** databus at end of CAS cycle else one clock delay + ** 3 Clear if 64kx4 RAMs ??? + ** if set RAM size = (bit 0-1)*256k + ** else RAM size = (bit 0-1)* 64k + ** 4 16 bit ROM access if set + ** 5 Memory bandwidth (0 better than 1) ??? + ** 6 TLI internal test mode if set + ** 7 VRAM installed if set DRAM else. + ** + ** 3d4h index 3Fh (R/W): + ** bit 7 This bit seems to be bit 8 of the CRTC offset register (3d4h index 13h). + ** + ** 3d8h (R/W): Display Mode Control + ** + ** 46E8h (R): Video Subsystem Enable Register + ** bit 3 Enable VGA if set + ** + ** + ** 3C4h index 05 used. + ** + ** + ** Bank Switching: + ** + ** 64k banks are selected by the Segment Select Register at 3CDh. + ** Both a Read and a Write segment can be selected. + ** + ** The sequence: + ** + ** port[$3BF]:=3; + ** port[$3D8]:=$A0; + ** + ** is apparently needed to enable the extensions in the Tseng 4000. + ** + ** + ** Used extended ET4000 registers (EXT+xx) : + ** + ** 00 : CRT (3d4) index 30 + ** 01 : CRT (3d4) index 31 + ** 02 : CRT (3d4) index 32 + ** 03 : CRT (3d4) index 33 + ** 04 : CRT (3d4) index 34 + ** 05 : CRT (3d4) index 35 + ** 06 : CRT (3d4) index 36 + ** 07 : CRT (3d4) index 37 + ** 08 : CRT (3d4) index 3f + ** 09 : SEQ (3c4) index 07 + ** 0A : Microchannel register (3c3) + ** 0B : Segment select (3cd) + ** 0C : ATT (3c0) index 16 + ** + */ + +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "ramdac/ramdac.h" + +#define SEG_SELECT 0x3CD + +#define CHIP_ET4000 0 /* Chip types. */ +#define CHIP_ET4000W32 1 +#define CHIP_ET4000W32i 2 +#define CHIP_ET4000W32p 3 + +static char *chipname[] = +{ + "ET4000", + "ET4000/W32", + "ET4000/W32i", + "ET4000/W32p" +}; + +static int et4000_memory; +static int et4000_chiptype; + +static int et4000_init(int, int, int); +static int et4000_interlaced(int mode); +static void et4000_unlock(void); + +static void et4000_setlinear(int addr); + +static int et4000_extdac; +static int pos_ext_settings, ext_settings; + +/* Mode table */ +#if defined(DYNAMIC) + +static ModeTable *et4000_modes = NULL; +static ModeTable No_Modes = END_OF_MODE_TABLE; + +#else /* !defined(DYNAMIC) */ + +#include "config/et4000.regs" + +#ifdef DAC_TYPE +static int et4000_dac = DAC_TYPE; +#endif + +static ModeTable et4000_modes[] = +{ +/* *INDENT-OFF* */ + OneModeEntry(320x200x32K), + OneModeEntry(320x200x64K), + OneModeEntry(320x200x16M), + OneModeEntry(640x480x256), + OneModeEntry(640x480x32K), + OneModeEntry(640x480x64K), + OneModeEntry(640x480x16M), + OneModeEntry(800x600x16), + OneModeEntry(800x600x256), + OneModeEntry(800x600x32K), + OneModeEntry(800x600x64K), + OneModeEntry(1024x768x16), + OneModeEntry(1024x768x256), + OneModeEntry(1280x1024x16), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +#endif /* !defined(DYNAMIC) */ + +#ifndef DAC_TYPE +static int et4000_dac = -1; +#endif + +/* Fill in chipset specific mode information */ + +static void et4000_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + switch (modeinfo->colors) { + case 16: /* 4-plane 16 color mode */ + modeinfo->maxpixels = 65536 * 8; + break; + default: + if (modeinfo->bytesperpixel > 0) + modeinfo->maxpixels = et4000_memory * 1024 / + modeinfo->bytesperpixel; + else + modeinfo->maxpixels = et4000_memory * 1024; + break; + } + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = 0xfffff; + if (mode == G320x200x256) + modeinfo->startaddressrange = 0; + modeinfo->haveblit = 0; + modeinfo->memory = et4000_memory * 1024; + modeinfo->flags |= HAVE_RWPAGE | HAVE_EXT_SET; + if (et4000_interlaced(mode)) + modeinfo->flags |= IS_INTERLACED; + if (et4000_chiptype != CHIP_ET4000) + modeinfo->flags |= EXT_INFO_AVAILABLE | CAPABLE_LINEAR; +} + + +/* ----------------------------------------------------------------- */ +/* Set/get the actual clock frequency */ + +#if defined(USE_CLOCKS) || defined(DYNAMIC) +#ifndef CLOCKS +#define CLOCKS 24 +#endif +#ifndef CLOCK_VALUES +#define CLOCK_VALUES { 0 } +#endif + +static unsigned clocks[CLOCKS] = CLOCK_VALUES; +#endif + + +#ifdef USE_CLOCKS + +/* Only include the rest of the clock stuff if USE_CLOCKS is defined. */ + +static int et4000_clocks(int clk) +{ + unsigned char temp; + int res; + + /* get actual clock */ + res = (port_in(MIS_R) >> 2) & 3; /* bit 0..1 */ + port_out_r(__svgalib_CRT_I, 0x34); + res |= (port_in(__svgalib_CRT_D) & 2) << 1; /* bit 2 */ + port_out_r(SEQ_I, 0x07); + temp = port_in(SEQ_D); + if (temp & 0x41 == 0x41) + res |= 0x10; /* bit 3..4 */ + else + res |= (temp & 0x40) >> 3; /* bit 3 */ + + if (clk >= CLOCKS) + clk = CLOCKS - 1; + if (clk >= 0) { + /* Set clock */ + temp = port_in(MIS_R) & 0xF3; + port_out_r(MIS_W, temp | ((clk & 3) << 2)); + port_out_r(__svgalib_CRT_I, 0x34); + temp = port_in(__svgalib_CRT_D) & 0xFD; + port_out_r(__svgalib_CRT_D, temp | ((clk & 4) >> 1)); + port_out_r(SEQ_I, 0x07); + temp = port_in(SEQ_D) & 0xBE; + temp |= (clk & 0x10 ? 0x41 : 0x00); + temp |= (clk & 0x08) << 3; + port_out_r(SEQ_D, temp); + usleep(5000); + } + return res; +} + +#define FRAMES 2 + +/* I think the Xfree86 uses a similar BAD HACK ... */ +static int measure(int frames) +{ + unsigned counter; + __asm__ volatile ( + " xorl %0,%0 \n" + "__W1: port_in %1,%%al \n" + " testb $8,%%al \n" + " jne __W1 \n" + "__W2: port_in %1,%%al \n" + " testb $8,%%al \n" + " je __W2 \n" + "__L1: port_in %1,%%al \n" + " incl %0 \n" + " testb $8,%%al \n" + " jne __L1 \n" + "__L2: port_in %1,%%al \n" + " incl %0 \n" + " testb $8,%%al \n" + " je __L2 \n" + "__L3: decl %2 \n" + " jns __L1 \n" + :"=b" (counter) + :"d"((unsigned short) (0x3da)), "c"(frames) + :"ax", "cx" + ); + return counter; +} + +#define BASIS_FREQUENCY 28322 + +static int measure_clk(int clk) +{ + unsigned new; + int old_clk, state; + static unsigned act = 0; + + old_clk = et4000_clocks(-1); + if ((state = SCREENON)) + vga_screenoff(); + if (act == 0) { + unsigned char save = port_in(MIS_R); + port_out_r(MIS_W, (save & 0xF3) | 0x04); + act = measure(FRAMES); + port_out_r(MIS_W, save); + } + et4000_clocks(clk); + new = measure(FRAMES); + et4000_clocks(old_clk); + if (state) + vga_screenon(); + + return (((long long) BASIS_FREQUENCY) * act) / new; +} + +#define set1(f,v) ({ if ((f)==0) (f)=(v); }) + +static void set3(unsigned *f, int clk, unsigned base) +{ + if (clk - 16 >= 0) + set1(f[clk - 16], 4 * base); + if (clk - 8 >= 0) + set1(f[clk - 8], 2 * base); + set1(f[clk], base); + if (clk + 8 < CLOCKS) + set1(f[clk + 8], base / 2); + if (clk + 16 < CLOCKS) + set1(f[clk + 16], base / 4); +} + +static int get_clock(int clk) +{ + static int first = 1; + + if (clk < 0 || clk >= CLOCKS) + return 0; + if (first) { + int act_clk; + first = 0; + act_clk = et4000_clocks(-1); + act_clk &= 0xFC; + set3(clocks, act_clk, 25175); /* act_clk : 25175 KHz */ + set3(clocks, act_clk + 1, 28322); /* act_clk+1: 28322 KHz */ + for (act_clk = 0; act_clk < CLOCKS; ++act_clk) + if (clocks[act_clk] != 0) + set3(clocks, act_clk, clocks[act_clk]); + } + if (clocks[clk] == 0) { + int c = clk & 7; + clocks[16 + c] = measure_clk(16 + c); + clocks[8 + c] = 2 * clocks[16 + c]; + clocks[c] = 2 * clocks[8 + c]; + } + return clocks[clk]; +} + +#endif /* defined(USE_CLOCKS) */ + +/* ----------------------------------------------------------------- */ + + +/* Read and store chipset-specific registers */ + +static int et4000_saveregs(unsigned char regs[]) +{ + int i; + + et4000_unlock(); + /* save extended CRT registers */ + for (i = 0; i < 8; i++) { + port_out(0x30 + i, __svgalib_CRT_I); + regs[EXT + i] = port_in(__svgalib_CRT_D); + } + port_out(0x3f, __svgalib_CRT_I); + regs[EXT + 8] = port_in(__svgalib_CRT_D); + + /* save extended sequencer register */ + port_out(7, SEQ_I); + regs[EXT + 9] = port_in(SEQ_D); + + /* save some other ET4000 specific registers */ + regs[EXT + 10] = port_in(0x3c3); + regs[EXT + 11] = port_in(0x3cd); + + /* save extended attribute register */ + port_in(__svgalib_IS1_R); /* reset flip flop */ + port_out(0x16, ATT_IW); + regs[EXT + 12] = port_in(ATT_R); + + if (et4000_extdac) { + _ramdac_dactocomm(); + regs[EXT + 13] = port_in(PEL_MSK); + _ramdac_dactocomm(); + port_out_r(PEL_MSK, regs[EXT + 13] | 0x10); + _ramdac_dactocomm(); + port_in(PEL_MSK); + port_out_r(PEL_MSK, 3); /* write index low */ + port_out_r(PEL_MSK, 0); /* write index high */ + regs[EXT + 14] = port_in(PEL_MSK); /* primary ext. pixel select */ + regs[EXT + 15] = port_in(PEL_MSK); /* secondary ext. pixel select */ + regs[EXT + 16] = port_in(PEL_MSK); /* PLL control register */ + _ramdac_dactocomm(); + port_out_r(PEL_MSK, regs[EXT + 13]); + return 17; + } + return 13; /* ET4000 requires 13 additional registers */ +} + + +/* Set chipset-specific registers */ + +static void et4000_setregs(const unsigned char regs[], int mode) +{ + int i; + unsigned char save; + + /* make sure linear mode is forced off */ + et4000_setlinear(0); + + et4000_unlock(); + /* write some ET4000 specific registers */ + port_out(regs[EXT + 10], 0x3c3); + port_out(regs[EXT + 11], 0x3cd); + + /* write extended sequencer register */ + port_out(7, SEQ_I); + port_out(regs[EXT + 9], SEQ_D); + +#if 0 /* This writes to registers we shouldn't write to. */ + /* write extended CRT registers */ + for (i = 0; i < 6; i++) { + port_out(0x32 + i, __svgalib_CRT_I); + port_out(regs[EXT + i], __svgalib_CRT_D); + } + port_out(0x3f, __svgalib_CRT_I); + port_out(regs[EXT + 6], __svgalib_CRT_D); +#endif + + /* deprotect CRT register 0x35 */ + port_out(0x11, __svgalib_CRT_I); + save = port_in(__svgalib_CRT_D); + port_out(save & 0x7F, __svgalib_CRT_D); + + /* write extended CRT registers */ + for (i = 0; i < 6; i++) { + port_out(0x30 + i, __svgalib_CRT_I); + port_out(regs[EXT + i], __svgalib_CRT_D); + } + port_out(0x36, __svgalib_CRT_I); + port_out((port_in(__svgalib_CRT_D) & 0x40) | (regs[EXT + 6] & 0xbf), __svgalib_CRT_D); + port_out(0x37, __svgalib_CRT_I); + port_out((port_in(__svgalib_CRT_D) & 0xbb) | (regs[EXT + 7] & 0x44), __svgalib_CRT_D); + port_out(0x3f, __svgalib_CRT_I); + port_out(regs[EXT + 8], __svgalib_CRT_D); + + /* set original CRTC 0x11 */ + port_out(0x11, __svgalib_CRT_I); + port_out(save, __svgalib_CRT_D); + + /* write extended attribute register */ + port_in(__svgalib_IS1_R); /* reset flip flop */ + port_out(0x16, ATT_IW); + port_out(regs[EXT + 12], ATT_IW); + + if (et4000_extdac) { + _ramdac_dactocomm(); + port_out_r(PEL_MSK, regs[EXT + 13] | 0x10); + _ramdac_dactocomm(); + port_in(PEL_MSK); + port_out_r(PEL_MSK, 3); /* write index low */ + port_out_r(PEL_MSK, 0); /* write index high */ + port_out_r(PEL_MSK, regs[EXT + 14]); /* primary ext. pixel select */ + port_out_r(PEL_MSK, regs[EXT + 15]); /* secondary ext. pixel select */ + port_out_r(PEL_MSK, regs[EXT + 16]); /* PLL control register */ + _ramdac_dactocomm(); + port_out_r(PEL_MSK, regs[EXT + 13]); + } +} + + +/* Return non-zero if mode is available */ + +static int et4000_modeavailable(int mode) +{ + const unsigned char *regs; + struct vgainfo *info; + + regs = LOOKUPMODE(et4000_modes, mode); + if (regs == NULL || mode == GPLANE16) + return __svgalib_vga_driverspecs.modeavailable(mode); + if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE) + return 0; + + info = &__svgalib_infotable[mode]; + if (et4000_memory * 1024 < info->ydim * info->xbytes) + return 0; + + switch (info->colors) { + case 1 << 15: + /* All HiColor dacs handle 15 bit */ + if ((et4000_dac & 1) == 0) + return 0; + break; + case 1 << 16: + /* Unfortunately, we can't tell the difference between a Sierra Mark 2 */ + /* and a Mark 3, and the mark 2 is only 15 bit. If this gives you trouble */ + /* change it to (8|16) rather than (2|8|16) */ + /* Currently allow Sierra Mark2/3, AT&T, STG-170x and AcuMos */ + if ((et4000_dac & (2 | 8 | 16 | 32 | 64)) == 0) + return 0; + break; + case 1 << 24: + /* Don't know how to set dac command register for Diamond SS2410 Dac */ + /* Only allow AT&T, STG-170x and AcuMos */ + if ((et4000_dac & (8 | 16 | 32 | 64)) == 0) + return 0; + break; + } + return SVGADRV; +} + + +/* Check if mode is interlaced */ + +static int et4000_interlaced(int mode) +{ + const unsigned char *regs; + + if (et4000_modeavailable(mode) != SVGADRV) + return 0; + regs = LOOKUPMODE(et4000_modes, mode); + if (regs == NULL || regs == DISABLE_MODE) + return 0; + return (regs[EXT + 5] & 0x80) != 0; /* CRTC 35H */ +} + + +/* Set a mode */ + +static int et4000_setmode(int mode, int prv_mode) +{ + const unsigned char *regs; + unsigned char i; + + if (et4000_dac) + /* Standard dac behaviour */ + __svgalib_hicolor(et4000_dac, STD_DAC); + switch (et4000_modeavailable(mode)) { + case STDVGADRV: + /* Reset extended register that is set to non-VGA */ + /* compatible value for 132-column textmodes (at */ + /* least on some cards). */ + et4000_unlock(); + port_out_r(__svgalib_CRT_I, 0x34); + i = port_in(__svgalib_CRT_D); + if ((i & 0x02) == 0x02) + port_out_r(__svgalib_CRT_D, (i & 0xfd)); /* DS */ + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + case SVGADRV: + regs = LOOKUPMODE(et4000_modes, mode); + if (regs != NULL) + break; + default: + return 1; /* mode not available */ + } + + if (et4000_dac && !et4000_extdac) + switch (vga_getmodeinfo(mode)->colors) { + case 1 << 15: + __svgalib_hicolor(et4000_dac, HI15_DAC); + break; + case 1 << 16: + __svgalib_hicolor(et4000_dac, HI16_DAC); + break; + case 1 << 24: + __svgalib_hicolor(et4000_dac, TC24_DAC); + break; + } + __svgalib_setregs(regs); + et4000_setregs(regs, mode); + return 0; +} + +/* Unlock chipset-specific registers */ + +static void et4000_unlock(void) +{ + /* get access to extended registers */ + port_out(3, 0x3bf); + if (port_in(0x3cc) & 1) + port_out(0xa0, 0x3d8); + else + port_out(0xa0, 0x3b8); +} + + +/* Relock chipset-specific registers */ + +static void et4000_lock(void) +{ +} + +/* Enable linear mode at a particular 4M page (0 to turn off) */ + +static void et4000_setlinear(int addr) +{ + et4000_unlock(); + port_out_r(CRT_IC, 0x36); + if (addr) + port_out_r(CRT_DC, port_in(CRT_DC) | 16); /* enable linear mode */ + else + port_out_r(CRT_DC, port_in(CRT_DC) & ~16); /* disable linear mode */ + port_out_r(CRT_IC, 0x30); + port_out_r(CRT_DC, addr); + et4000_lock(); +} + + +/* Indentify chipset; return non-zero if detected */ + +static int et4000_test(void) +{ + unsigned char new, old, val; + int base; + + et4000_unlock(); + + /* test for Tseng clues */ + old = port_in(0x3cd); + port_out(0x55, 0x3cd); + new = port_in(0x3cd); + port_out(old, 0x3cd); + + /* return false if not Tseng */ + if (new != 0x55) + return 0; + + /* test for ET4000 clues */ + if (port_in(0x3cc) & 1) + base = CRT_IC; + else + base = 0x3b4; + port_out(0x33, base); + old = port_in(base + 1); + new = old ^ 0xf; + port_out(new, base + 1); + val = port_in(base + 1); + port_out(old, base + 1); + + /* return true if ET4000 */ + if (val == new) { + et4000_init(0, 0, 0); + return 1; + } + return 0; +} + + + +static unsigned char last_page = 0; + +/* Bank switching function - set 64K bank number */ +static void et4000_setpage(int page) +{ + /* Set both read and write bank. */ + port_out(last_page = (page | ((page & 15) << 4)), SEG_SELECT); + if (et4000_chiptype >= CHIP_ET4000W32i) { + /* Write page4-5 to bits 0-1 of ext. bank register, */ + /* and to bits 4-5. */ + port_out_r(0x3cb, (port_in(0x3cb) & ~0x33) | (page >> 4) | (page & 0x30)); + } +} + + +/* Bank switching function - set 64K read bank number */ +static void et4000_setrdpage(int page) +{ + last_page &= 0x0F; + last_page |= (page << 4); + port_out(last_page, SEG_SELECT); + if (et4000_chiptype >= CHIP_ET4000W32i) { + /* Write page4-5 to bits 4-5 of ext. bank register. */ + port_out_r(0x3cb, (port_in(0x3cb) & ~0x30) | (page & 0x30)); + } +} + +/* Bank switching function - set 64K write bank number */ +static void et4000_setwrpage(int page) +{ + last_page &= 0xF0; + last_page |= page; + port_out(last_page, SEG_SELECT); + if (et4000_chiptype >= CHIP_ET4000W32i) { + /* Write page4-5 to bits 0-1 of ext. bank register. */ + port_out_r(0x3cb, (port_in(0x3cb) & ~0x03) | (page >> 4)); + } +} + + +/* Set display start address (not for 16 color modes) */ +/* ET4000 supports any address in video memory (up to 1Mb) */ +/* ET4000/W32i/p supports up to 4Mb */ + +static void et4000_setdisplaystart(int address) +{ + port_outw_r(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */ + port_outw_r(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */ + port_in(0x3da); /* set ATC to addressing mode */ + port_out_r(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); + /* write sa0-1 to bits 1-2 */ + port_out_r(CRT_IC, 0x33); + if (et4000_chiptype >= CHIP_ET4000W32i) + /* write sa18-21 to bit 0-3 */ + port_out_r(CRT_DC, (port_in(CRT_DC) & 0xf0) | ((address & 0x3c0000) >> 18)); + else + /* write sa18-19 to bit 0-3 */ + port_out_r(CRT_DC, (port_in(CRT_DC) & 0xfc) | ((address & 0xc0000) >> 18)); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* ET4000 supports multiples of 8 to 4088 */ + +static void et4000_setlogicalwidth(int width) +{ + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ + port_out_r(CRT_IC, 0x3f); + port_out_r(CRT_DC, (port_in(CRT_DC) & 0x7f) + | ((width & 0x800) >> 5)); /* write lw12 to bit 7 */ +} + +static int et4000_ext_set(unsigned what, va_list params) +{ + int param2, old_values; + + switch (what) { + case VGA_EXT_AVAILABLE: + param2 = va_arg(params, int); + switch (param2) { + case VGA_AVAIL_SET: + return VGA_EXT_AVAILABLE | VGA_EXT_SET | VGA_EXT_CLEAR | VGA_EXT_RESET; + case VGA_AVAIL_ACCEL: + return 0; + case VGA_AVAIL_FLAGS: + return pos_ext_settings; + } + return 0; + case VGA_EXT_SET: + old_values = ext_settings; + ext_settings |= (va_arg(params, int)) & pos_ext_settings; + params_changed: + if (((old_values ^ ext_settings) & pos_ext_settings)) { + int cmd; + CRITICAL = 1; + vga_lockvc(); + _ramdac_dactocomm(); + cmd = port_in(PEL_MSK); + _ramdac_dactocomm(); + if (ext_settings & VGA_CLUT8) + cmd |= 2; + else + cmd &= ~2; + port_out_r(PEL_MSK, cmd); + vga_unlockvc(); + CRITICAL = 0; + } + return old_values; + case VGA_EXT_CLEAR: + old_values = ext_settings; + ext_settings &= ~((va_arg(params, int)) & pos_ext_settings); + goto params_changed; + case VGA_EXT_RESET: + old_values = ext_settings; + ext_settings = (va_arg(params, int)) & pos_ext_settings; + goto params_changed; + default: + return 0; + } +} + +static int et4000_linear(int op, int param) +{ + /* linear mode not supported on original chipset */ + if (et4000_chiptype == CHIP_ET4000) + return -1; + else if (op == LINEAR_QUERY_GRANULARITY) + return 4 * 1024 * 1024; + else if (op == LINEAR_QUERY_RANGE) + return 256; + else if (op == LINEAR_ENABLE) { + et4000_setlinear(param / (4 * 1024 * 1024)); + return 0; + } else if (op == LINEAR_DISABLE) { + et4000_setlinear(0); + return 0; + } else + return -1; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_et4000_driverspecs = +{ + et4000_saveregs, + et4000_setregs, + et4000_unlock, + et4000_lock, + et4000_test, + et4000_init, + et4000_setpage, + et4000_setrdpage, + et4000_setwrpage, + et4000_setmode, + et4000_modeavailable, + et4000_setdisplaystart, + et4000_setlogicalwidth, + et4000_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + et4000_ext_set, + 0, + et4000_linear, + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + + +/* Hicolor DAC detection derived from vgadoc (looks tricky) */ + + +#ifndef DAC_TYPE +static int testdac(void) +{ + int x, y, z, v, oldcommreg, oldpelreg, retval; + + /* Use the following return values: + * 0: Ordinary DAC + * 1: Sierra SC11486 (32k) + * 3: Sierra 32k/64k + * 5: SS2410 15/24bit DAC + * 9: AT&T 20c491/2 + * 10: STG-170x + */ + + retval = 0; /* default to no fancy dac */ + _ramdac_dactopel(); + x = port_in(PEL_MSK); + do { /* wait for repeat of value */ + y = x; + x = port_in(PEL_MSK); + } while (x != y); + z = x; + port_in(PEL_IW); + port_in(PEL_MSK); + port_in(PEL_MSK); + port_in(PEL_MSK); + x = port_in(PEL_MSK); + y = 8; + while ((x != 0x8e) && (y > 0)) { + x = port_in(PEL_MSK); + y--; + } + if (x == 0x8e) { + /* We have an SS2410 */ + retval = 1 | 4; + _ramdac_dactopel(); + } else { + _ramdac_dactocomm(); + oldcommreg = port_in(PEL_MSK); + _ramdac_dactopel(); + oldpelreg = port_in(PEL_MSK); + x = oldcommreg ^ 0xFF; + port_out_r(PEL_MSK, x); + _ramdac_dactocomm(); + v = port_in(PEL_MSK); + if (v != x) { + v = _ramdac_setcomm(x = oldcommreg ^ 0x60); + /* We have a Sierra SC11486 */ + retval = 1; + + if ((x & 0xe0) == (v & 0xe0)) { + /* We have a Sierra 32k/64k */ + x = port_in(PEL_MSK); + _ramdac_dactopel(); + retval = 1 | 2; + + if (x == port_in(PEL_MSK)) { + /* We have an ATT 20c491 or 20c492 */ + retval = 1 | 8; + if (_ramdac_setcomm(0xFF) != 0xFF) { + /* We have a weird dac, AcuMos ADAC1 */ + retval = 1 | 16; + } else { /* maybe an STG-170x */ + /* try to enable ext. registers */ + _ramdac_setcomm(oldcommreg | 0x10); + port_out_r(PEL_MSK, 0); + port_out_r(PEL_MSK, 0); + if (port_in(PEL_MSK) == 0x44) { + /* it's a 170x */ + /* Another read from PEL_MSK gets the chiptype, 0x02 == 1702. */ + retval = 1 | 64; + et4000_extdac = 1; + } + } + } + } + _ramdac_dactocomm(); + port_out_r(PEL_MSK, oldcommreg); + } + _ramdac_dactopel(); + port_out_r(PEL_MSK, oldpelreg); + } + return retval; +} +#endif /* !defined(DAC_TYPE) */ + + +/* Initialize chipset (called after detection) */ + +static int et4000_init(int force, int par1, int par2) +{ + int value; + int old, new, val; +#ifdef USE_CLOCKS + int i; +#endif + +#ifdef DYNAMIC + if (et4000_modes == NULL) { + FILE *regs; + + regs = fopen(ET4000_REGS, "r"); + if (regs != 0) { + et4000_modes = NULL; + __svgalib_readmodes(regs, &et4000_modes, &et4000_dac, &clocks[0]); + fclose(regs); + } else + et4000_modes = &No_Modes; + } +#endif + + /* Determine the ET4000 chip type. */ + + /* Test for ET4000/W32. */ + old = port_in(0x3cb); + port_out_r(0x3cb, 0x33); + new = port_in(0x3cb); + port_out_r(0x3cb, old); + if (new != 0x33) + et4000_chiptype = CHIP_ET4000; + else { + port_out_r(0x217a, 0xec); + val = port_in(0x217b) >> 4; + switch (val) { + case 0: + et4000_chiptype = CHIP_ET4000W32; + break; + case 1: + case 3: + et4000_chiptype = CHIP_ET4000W32i; + break; + case 2: + case 5: + default: + et4000_chiptype = CHIP_ET4000W32p; + } + } + + if (force) + et4000_memory = par1; + else { + port_out_r(CRT_IC, 0x37); + value = port_in(CRT_DC); + et4000_memory = (value & 0x08) ? 256 : 64; + switch (value & 3) { + case 2: + et4000_memory *= 2; + break; + case 3: + et4000_memory *= 4; + break; + } + if (value & 0x80) + et4000_memory *= 2; + port_out_r(CRT_IC, 0x32); + if (port_in(CRT_DC) & 0x80) { + /* Interleaved memory on ET4000/W32i/p: */ + /* Multiply by 2. */ + et4000_memory *= 2; + } + } +#ifndef DAC_TYPE + if (et4000_dac < 0) + et4000_dac = testdac(); +#endif + +#ifdef USE_CLOCKS + /* Measure clock frequencies */ + for (i = 0; i < CLOCKS; ++i) + get_clock(i); +#endif + + if (__svgalib_driver_report) { + char dacname[60]; + switch (et4000_dac & ~1) { + case 0: + strcpy(dacname, ", Hicolor Dac: Sierra SC11486"); + break; + case 2: + strcpy(dacname, ", Hicolor Dac: Sierra 32k/64k"); + break; + case 4: + strcpy(dacname, ", Hicolor Dac: SS2410"); + break; + case 8: + strcpy(dacname, ", Hicolor Dac: ATT20c491/2"); + break; + case 16: + strcpy(dacname, ", Hicolor Dac: ACUMOS ADAC1"); + break; + case 32: + strcpy(dacname, ", Hicolor Dac: Sierra 15025/6 (24-bit)"); + break; + case 64: + strcpy(dacname, ", Hicolor Dac: STG-170x (24-bit)"); + break; + default: + strcpy(dacname, ", Hicolor Dac: Unknown"); + break; + } + + fprintf(stderr,"Using Tseng ET4000 driver (%s %d%s).", + chipname[et4000_chiptype], et4000_memory, + et4000_dac & 1 ? dacname : ""); +#ifdef USE_CLOCKS + fprintf(stderr," Clocks:"); + for (i = 0; i < 8; ++i) + fprintf(stderr," %d", (clocks[i] + 500) / 1000); +#endif + fprintf(stderr,"\n"); + } + __svgalib_driverspecs = &__svgalib_et4000_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; +/* __svgalib_linear_mem_base=LINEARBASE; + __svgalib_linear_mem_size=nv3_memory*0x400; */ + + pos_ext_settings = 0; + if (et4000_dac & (8 | 16 | 32 | 64)) + pos_ext_settings = VGA_CLUT8; + + return 0; +} diff --git a/src/drivers/et4000hico.c b/src/drivers/et4000hico.c new file mode 100644 index 0000000..c708342 --- /dev/null +++ b/src/drivers/et4000hico.c @@ -0,0 +1,109 @@ +/* vgahico.c - used by ET4000 driver. */ +/* Set Hicolor RAMDAC mode. + + * HH: Added support for 24-bit Sierra RAMDAC (15025/6) (untested). + */ + + +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "ramdac/ramdac.h" + +int __svgalib_hicolor(int dac_type, int mode) +/* Enters hicolor mode - 0 for no hi, 1 for 15 bit, 2 for 16, 3 for 24 */ +/* For any modes it doesn't know about, etc, it attempts to turn hicolor off. */ +{ + int x; + + _ramdac_dactocomm(); + x = port_in(PEL_MSK); + _ramdac_dactocomm(); + switch (dac_type & ~1) { + case 0: /* Sierra SC11486 */ + if (mode == HI15_DAC) + port_out(x | 0x80, PEL_MSK); + else + port_out(x & ~0x80, PEL_MSK); + break; + case 2: /* Sierra Mark2/Mark3 */ + switch (mode) { + case HI15_DAC: + /* port_out( (x | 0x80) & ~0x40, PEL_MSK); */ + port_out((x & 0x1f) | 0xa0, PEL_MSK); + break; + case HI16_DAC: + /* port_out( x | 0xC0, PEL_MSK); */ + port_out((x & 0x1f) | 0xe0, PEL_MSK); + break; + default: + port_out(x & ~0xC0, PEL_MSK); + break; + } + break; + case 4: /* Diamond SS2410 */ + if (mode == HI15_DAC) + port_out(x | 0x80, PEL_MSK); + else + port_out(x & ~0x80, PEL_MSK); + break; + case 8: /* AT&T 20c491/2 */ + switch (mode) { + case HI15_DAC: + port_out((x & 0x1f) | 0xA0, PEL_MSK); + break; + case HI16_DAC: + port_out((x & 0x1f) | 0xC0, PEL_MSK); + break; + case TC24_DAC: + port_out((x & 0x1f) | 0xE0, PEL_MSK); + break; + default: + port_out(x & 0x1F, PEL_MSK); + break; + } + break; + case 16: /* AcuMos ADAC1 */ + switch (mode) { + case HI15_DAC: + port_out(0xF0, PEL_MSK); + break; + case HI16_DAC: + port_out(0xE1, PEL_MSK); + break; + case TC24_DAC: + port_out(0xE5, PEL_MSK); + break; + default: + port_out(0, PEL_MSK); + break; + } + break; + case 32: /* Sierra 15025/6 24-bit DAC */ + switch (mode) { + case HI15_DAC: + port_out((x & 0x1f) | 0xa0, PEL_MSK); + /* 0xa0 is also a 15-bit mode. */ + break; + case HI16_DAC: + port_out((x & 0x1f) | 0xe0, PEL_MSK); + /* 0xc0 is also a 16-bit mode. */ + /* 0xc0 doesn't seem to work, so use 0xe0. */ + break; + case TC24_DAC: + port_out((x & 0x1f) | 0x60, PEL_MSK); + break; + default: + port_out(x & 0x1f, PEL_MSK); + break; + } + break; + default: + /* Normal VGA mode. */ + port_out(x & 0x1F, PEL_MSK); + break; + } + _ramdac_dactopel(); + + return 0; +} diff --git a/src/drivers/et6000.c b/src/drivers/et6000.c new file mode 100644 index 0000000..1047b5e --- /dev/null +++ b/src/drivers/et6000.c @@ -0,0 +1,1223 @@ + /* ET6000 driver Don Secrest version 1.4 */ + /* version using svgalib_pci_find Feb 10, 2001 */ +#include /* Testing modeline update. Works for linux-2.2.15 */ +#include +#include +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "interface.h" +#include "vgaregs.h" +#include "vgapci.h" + +#ifdef DB6K +#include +FILE *outf; +static int compareregs(void); +static int textset = 0; +static void prtmodeinfo(vga_modeinfo *m); +/* static char *not_written = "ET6000 subroutine %s is not written yet.\n"; */ +static unsigned char *textstore = 0; +static unsigned char *vgatextstore = 0; +void fdumpregs(FILE *fd,unsigned char regs[],int n); +/* #define DNOTW(a) fprintf(outf,not_written,a) */ +#define DPRT(a) fprintf(outf,a) +#else +/* #define DNOTW(a) */ +#define DPRT(a) +#endif /* DB6K */ + +#ifdef DBG /* DBG is for debugging the code to use modelines. */ +FILE *fdm; +#endif + +#define SEG_SELECT 0x3CD + +static int base1; +/* The following are set by init so that they may be restored to their */ +/* state in setmode. */ +static unsigned char pci40std,pci42std,pci57std,pci58std,pci59std=0; + +#define LMODEMIN 9 /* No mode below this has been tested for linear */ +#define LMODEMAX 146 /* No mode above this tested. These should change. */ + +static CardSpecs *cardspecs; +static int et6ksav = VGA_MISCOUTPUT + 1; +static int ET6000_TOTAL_REGS = VGA_MISCOUTPUT + 14; +static char mem_type; +static int et6000_memory; +static unsigned int et6000_linear_base; +static int et6000_interlaced(int mode); +static unsigned comp_lmn(unsigned clock,float fac); +static int et6000_chiptype = 0; +static int x3_4,x3_5,x3_8 = 0,x3_a; /* On init these get set according */ + /* to color */ +union longword { + unsigned char b[4]; + unsigned short w[2]; + unsigned int l; +}; + +static unsigned int cursor_colors[16*2]; +static unsigned int *cursors[16]; +static int cursor_loaded[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static int cursor_format[16]; +static int active_cursor = -1; +static int cursor_doublescan = 0; /* Used by et6000_cursor */ + +/* The following are in the order of apearance in struct DriverSpecs as are */ +/* the program entries. */ + +static int et6000_saveregs(unsigned char regs[]); +static void et6000_setregs(const unsigned char regs[], int mode); +static void et6000_unlock(void); +static void et6000_lock(void); +static int et6000_test(void); +static int et6000_init(int force, int par1, int par2); +static void et6000_setpage(int page); +static void et6000_setrdpage(int page); +static void et6000_setwrpage(int page); +static int et6000_setmode(int mode, int prv_mode); +static int et6000_modeavailable(int mode); +static void et6000_setdisplaystart(int address); +static void et6000_setlogicalwidth(int width); +static void et6000_getmodeinfo(int mode,vga_modeinfo *modeinfo); +/* Obsolete blit functions left out here. */ +/* static int et6000_ext_set(unsigned what, va_list params); */ +/* static int et6000_accel(unsigned operation, va_list params); */ +static int et6000_linear(int op, int param); +/* Two empty spaces here */ +static int et6000_cursor(int cmd,int p1,int p2,int p3,int p4,void *p5); + +/* +** End of the DriverSpecs function declarations +*/ + +/* Function table (exported) */ + +DriverSpecs __svgalib_et6000_driverspecs = +{ + et6000_saveregs, + et6000_setregs, + et6000_unlock, + et6000_lock, + et6000_test, + et6000_init, + et6000_setpage, + et6000_setrdpage, + et6000_setwrpage, + et6000_setmode, + et6000_modeavailable, + et6000_setdisplaystart, + et6000_setlogicalwidth, + et6000_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + NULL, /* et6000_ext_set */ + NULL, /* et6000_accel */ + et6000_linear, + NULL, /* accelspecs */ + NULL, /* emulation */ + et6000_cursor, /* cursor */ +}; +#ifdef DBG +/* programs to debug the modeline stuff. */ +static void pmodeinfo(ModeInfo *In) +{ + fprintf(fdm,"Modeinfo\nWidth %d height %d\n",In->width,In->height); + fprintf(fdm,"Bpp %d, bpp %d, cB %d\n",In->bytesPerPixel,In->bitsPerPixel, + In->colorBits); + fprintf(fdm,"RGB %d, %d, %d\n",In->redWeight,In->greenWeight, + In->blueWeight); + fprintf(fdm,"Offset RGB %d, %d, %d\n",In->redOffset,In->greenOffset, + In->blueOffset); + fprintf(fdm,"Line width %d, real width %d, real height %d\n",In->lineWidth, + In->realWidth,In->realHeight); +} +static void pmodetiming(ModeTiming *Tg) +{ + int i,*mt; + mt = (int *) Tg; + fprintf(fdm,"Mode timing\n"); + for(i = 0;i < 20;i++) + { + fprintf(fdm,"0x%04x ",*(mt + i)); + if((i+1)%5 == 0) fprintf(fdm,"\n"); + } +} +#endif /* Modeline routine debug. */ + +/* Called from setmode */ +static void et6000_initializemode(unsigned char *moderegs, + ModeTiming *modetiming,ModeInfo *modeinfo, + int mode) +{ + int tmp,tmptot,tmpss,tmpse,tmpbs,tmpbe,offset,i; + float fac; + + fac = 1.0; + __svgalib_setup_VGA_registers(moderegs,modetiming,modeinfo); + offset = modeinfo->lineWidth >>3; + if(modetiming->flags & DOUBLESCAN) + moderegs[VGA_CR17] = 0xa3; + else + moderegs[VGA_CR17] = 0xab; + if((modeinfo->bytesPerPixel == 2) || (modetiming->flags & DOUBLESCAN)) + moderegs[VGA_CR14] = 0x40; + else + moderegs[VGA_CR14] = 0x60; + moderegs[VGA_CR13] = offset & 0xff; + moderegs[VGA_AR10] = 0x01; /* This is correct. May 20 1999 */ + moderegs[VGA_AR11] = 0x00; + for(i = 0;i < 13;i++) + moderegs[et6ksav + i] = 0x00; + + tmp = (modetiming->CrtcHDisplay >> 3) - 1; + tmptot = (modetiming->CrtcHTotal >> 3) -5; + tmpss = (modetiming->CrtcHSyncStart >> 3); + tmpbs = (modetiming->CrtcHSyncStart >> 3) - 1; + tmpse = offset; /* 3F */ + moderegs[et6ksav+8] = ((tmptot & 0x100) >> 8) | /* 0 Htot (8) */ + ((tmp & 0x100) >> 7) | /* 1 HDsp (8) */ + ((tmpbs & 0x100) >> 6) | /* 2 HBs (8) */ + ((tmpss & 0x100) >> 4) | /* 4 HSs (8) */ + ((tmpse & 0x200) >> 3) | /* 6 offs (9) */ + ((tmpse & 0x100) >> 1); /* 7 ofss (8) */ + tmp = modetiming->CrtcVDisplay -1; + tmptot = modetiming->CrtcVTotal - 2; + tmpbs = modetiming->CrtcVSyncStart -1; + tmpss = modetiming->CrtcVSyncStart; + tmpbe = 0x00; /* (10) */ /* 35 */ + moderegs[et6ksav+5] = ((tmpbs & 0x400) >> 10) | /* 0 VBs (10) */ + ((tmptot & 0x400) >> 9 ) | /* 1 Vtot (10) */ + ((tmp & 0x400) >> 8 ) | /* 2 VDsp (10) */ + ((tmpss & 0x400) >> 7 ) | /* 3 Vsst (10) */ + ( tmpbe >> 6); /* 4 splt (10) */ + if(modetiming->flags & INTERLACED) + moderegs[et6ksav + 5] |= 0xa0; /* bit 7 of cr35 and bit 1 of 57 */ + + switch(modeinfo->bitsPerPixel) + { + case 8: + moderegs[et6ksav + 12] = 0x00; /* et6ksav Reg */ + moderegs[et6ksav + 6] = 0x04; /* 0 PCI 58 */ + moderegs[et6ksav] &= 0xfe; /* 1 PCI 42 */ + break; /* 2 CR18 */ + case 15: /* 3 CR33 */ + case 16: /* 4 CR34 */ + moderegs[et6ksav + 12] = 0x90; /* 5 CR35 */ + moderegs[et6ksav + 6] = 0x08; /* 6 PCI 59 */ + if(modeinfo->greenWeight == 5) /* 7 AR17 */ + moderegs[et6ksav] = 0x00; /* 8 CR3F */ + else /* 9 PCI 40 */ + moderegs[et6ksav] = 0x02; /* 10 PCI 13 */ + break; /* 11 3CD */ + case 24: /* 12 AR16 */ + moderegs[et6ksav + 12] = 0xa0; + moderegs[et6ksav + 9] = 0x06; + moderegs[et6ksav + 6] = 0x02; + moderegs[et6ksav + 2] = 0xff; + moderegs[et6ksav + 1] = 0x02; + fac = 3.0; + break; + case 32: + moderegs[et6ksav + 12] = 0xb0; + moderegs[et6ksav + 9] = 0x06; + moderegs[et6ksav + 6] = 0x02; + moderegs[et6ksav + 2] = 0xff; + moderegs[et6ksav + 1] = 0x03; + fac = 4.0; + break; + default: + moderegs[et6ksav + 12] = 0x00; + moderegs[et6ksav + 6] = 0x04; + moderegs[et6ksav] &= 0xfe; + moderegs[VGA_GR5] = 0x00; /* 16 color mode not 0x02 */ + break; + } + + modetiming->selectedClockNo=6; /* use clock 6 */ + + if(modetiming->selectedClockNo > 3) + moderegs[et6ksav + 4] |= 2; + moderegs[VGA_MISCOUTPUT] = (moderegs[VGA_MISCOUTPUT] & 0xf3) | + ((modetiming->selectedClockNo & 0x03) << 2); + tmp=comp_lmn(modetiming->pixelClock,fac); + port_out_r(base1 | 0x68,6); + port_out_r(base1 | 0x69,tmp&0xff); + port_out_r(base1 | 0x69,tmp>>8); + /* because timing is giving the wrong */ + /* clock. FIX THIS WHEN CLOCK IS OK. */ +} + +static int et6000_saveregs(unsigned char regs[]) /* Called frm vga_saveregs */ +{ + int i; + + et6000_unlock(); +#ifdef DB6K + { + fprintf(outf,"In saveregs, regs at %x\n",(int) regs); + } +#endif + /* Save extended CRT registers. */ + for(i = 0; i < 3;i++) { + port_out(0x33 + i,__svgalib_CRT_I); + /* regs 30 and 31 are readonly and no 32 */ + regs[EXT + 3 + i] = port_in(__svgalib_CRT_D); + /* 36h and 37 do not exist on et6k */ + } + port_out(0x3f,__svgalib_CRT_I); + regs[EXT + 8] = port_in(__svgalib_CRT_D); + port_out(0x18,__svgalib_CRT_I); + regs[EXT + 2] = port_in(__svgalib_CRT_D); + /* ET6000 only. */ + /* Extended sequencer register 7 in EXT+9 doesen't exist on et6000. */ + /* Also EXT+10 doesn't exist. There is no 0x3c3 on et6000. */ + regs[EXT + 11] = port_in(SEG_SELECT); + regs[EXT + 10] = port_in(base1 | 0x13); /* I am using EXT+10 for the */ + /* linear map map location. */ + /* Reset flip flop. Page 137 */ + /* of the et6000 manual. These two */ + /* regs 10 & 11 are 0 for linear. */ + regs[EXT] = port_in(base1 | 0x58); /* Offset 58 describes 16bpp */ + regs[EXT + 6] = port_in(base1 | 0x59); /* bit1 = 0 555 RGB */ + /* 1 565 RGB */ + /* Offset 59 bits <32> set bpp. */ + /* --------------------- */ + /* | 3 | 2 | | */ + /* ===================== */ + /* | 0 | 0 | 24 bpp | */ + /* | 0 | 1 | 8 bpp | */ + /* | 1 | 0 | 15/16 bpp | */ + port_in(__svgalib_IS1_R); /* --------------------- */ + __svgalib_delay(); + port_out(0x16,ATT_IW); + __svgalib_delay(); + regs[EXT + 12] = port_in(ATT_R); + __svgalib_delay(); + port_in(__svgalib_IS1_R); + __svgalib_delay(); + port_out(0x17,ATT_IW); + __svgalib_delay(); + regs[EXT + 7] = port_in(ATT_R); + port_out(0x06,SEQ_I); + regs[EXT + 5] = ((port_in(base1 | 0x57) & 2) << 4); /* bit 1 of 57 to bit5 */ + regs[EXT + 9] = port_in(base1 | 0x40); /* Sets memory mapping. */ + regs[EXT + 1] = port_in(base1 | 0x42); /* Saved for future use. */ +#ifdef DB6K + fprintf(outf,"Leaving saveregs.\n"); +#endif + return(13); /* ET6000 requires 13 EXT regs. */ + /* We may find that it needs more! */ +} + +/* Set chipset-specific registers */ + +static void et6000_setregs(const unsigned char regs[], int mode) +{ + int i; + unsigned char save; + et6000_linear(LINEAR_DISABLE,0); /* Turn off linear. */ +#ifdef DB6K + fprintf(outf,"In setregs for regs at %x, mode = %d\n",(int) regs,mode); +#endif + + et6000_unlock(); + /* Write some et6000 specific registers. */ + port_out(regs[EXT+11],SEG_SELECT); + if(regs[EXT + 10]) /* I am using EXT+10 for linear */ + port_out_r(base1 | 0x13,regs[EXT + 10]); /* modes */ + port_out_r(base1 | 0x40,regs[EXT + 9]); + /* Unprotect writing CRT reg 0x35 */ + port_out(0x11,__svgalib_CRT_I); + save = port_in(__svgalib_CRT_D); + port_out(save &0x7F,__svgalib_CRT_D); +#ifdef DB6K + fprintf(outf,"After first block\n"); +#endif + + /* Write extended CRT regs */ + for(i = 0;i < 3;i++) { + port_out(0x33 + i,__svgalib_CRT_I); + port_out(regs[EXT + 3 + i],__svgalib_CRT_D); + } + port_out(0x3F,__svgalib_CRT_I); + port_out(regs[EXT + 8],__svgalib_CRT_D); + port_out(0x18,__svgalib_CRT_I); + port_out(regs[EXT + 2],__svgalib_CRT_D); + /* See saveregs for these registers. */ + port_out_r(base1 | 0x58,(vga_getcolors() == (1 << 16))? (regs[EXT] | 0x02): + regs[EXT]); + port_out_r(base1 | 0x59,regs[EXT + 6]); + port_out_r(base1 | 0x57,((port_in(base1 | 0x57) | ((regs[EXT + 5] & 0x20) >> 4)))); + + /* For True Color modes we must devide the MCLK by 3. */ + port_out_r(base1 | 0x42,regs[EXT + 1]); + port_out_r(base1 | 0x40,regs[EXT + 9]); +#ifdef DB6K + fprintf(outf,"after second block\n"); +#endif + /* Original value for reg 0x11. */ + port_out(0x11,__svgalib_CRT_I); + port_out(save,__svgalib_CRT_D); + + /* Write extended attribute register. */ + port_in(__svgalib_IS1_R); /* Reset flip flop. Page 137 of et6000 chip */ + __svgalib_delay(); /* manual. */ + port_out(0x16,ATT_IW); + __svgalib_delay(); + port_out(regs[EXT + 12],ATT_IW); + __svgalib_delay(); + port_in(__svgalib_IS1_R); + __svgalib_delay(); + port_out(0x17,ATT_IW); + __svgalib_delay(); + port_out(regs[EXT + 7],ATT_IW); + /* I don't have an external DAC so I didn't include the last 3 regs. */ +#ifdef DB6K + fprintf(outf,"End of setregs\n"); +#endif +} + +static void et6000_unlock(void) +{ + if(x3_8) + port_out_r(x3_8,0xa0); + else + fprintf(stderr,"et6000_unlock called when et6000 was not initialized.\n"); +} + +static void et6000_lock(void) +{ + if(x3_8) { +#ifdef DB6K + fprintf(outf,"Lock called\n"); +#endif + return; /* et4000 does this, I don't know why! */ + port_out_r(x3_8,0); /* I think it is because we lose root */ + } /* privalege after initialize and can */ + else /* no longer unlock registers. */ + fprintf(stderr,"et6000_lock called when et6000 was not initialized.\n"); +} + +static int et6000_test(void) +{ + if(et6000_chiptype) + return(1); + else { + et6000_init(0,0,0); + DPRT("In et6000 test\n"); + if(et6000_chiptype) + return(1); + return(0); + } +} +/* Routines needed for modline calculation. */ +static int et6000_map_clock(int bpp, int clock) +{ + return(clock); +} + +static int et6000_match_programable_clock(int clock) +{ + return(clock); +} + +static int et6000_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + return(htiming); +} +/* End of modeline subroutines. */ + +static int et6000_init(int force, int par1, int par2) +{ + unsigned char mem_cfg_reg; + unsigned int buf[64]; /* 256 bytes of the pci bus registers. */ + +#ifdef DB6K +#include + char dboutfile[30]; + if(et6000_chiptype) return(1); + sprintf(dboutfile,"D%ld.txt",time(NULL)); + outf = fopen(dboutfile,"w"); + if(!outf){ + fprintf(stderr,"Can't open a debug output file in et6000_init.\n"); + exit(1); + } + else + { + fprintf(outf,"et6000 init entered.\n"); + chmod(dboutfile,0666); + } +#endif + + if(et6000_chiptype) + return(1); /* An attempt to reenter init. */ + /* Check for ET6000 chiptype. */ + /* Get PCI and VL configuration space. The VL bus has not been checked. */ + /* I have a PCI bus. */ + + /* Test color mode or mono mode */ + x3_4 = __svgalib_CRT_I; /* set in vga.c */ + x3_5 = __svgalib_CRT_D; + x3_a = __svgalib_IS1_R; + if(__svgalib_CRT_I == CRT_IC) + x3_8 = 0x3d8; + else + x3_8 = 0x3b8; + + et6000_linear_base = 0; + if(__svgalib_pci_find_vendor_vga_pos(0x100c,buf) && + (buf[0] == 0x3208100cu)) + { +DPRT("Found et6000\n"); + et6000_chiptype = ET6000; /* Defined in vga.h */ + } + else + { +#ifdef DB6K + fprintf(outf,"Can't find et6000 chipset. buf[0] = 0x%08x\n", + buf[0]); +#endif + return(0); + } + + et6000_unlock(); /* Set key. */ + mem_type = port_in(MIS_W) & 1; /* 0 = DRAM, 1 = MDRAM */ + + base1 = buf[0x5] & ~0xFF; + /* 14 hex. The start of confg. */ + /* 3C2 is the input status register. It has + ** things like the monitor ID and the video + ** memory type. The two low order bits are + ** both zero for DRAM and both 1 for MDRAM. + ** Offset 0x45 is the memory configuration + ** register which gives the memory size depending + ** on the type. Aparently one can't have 1Mbyte + ** of MDRAM. + */ + if(!pci59std) { + /* Saving pcibus registers so they may be restored. */ + pci40std = port_in(base1 | 0x40); + pci42std = port_in(base1 | 0x42); + pci57std = port_in(base1 | 0x57); + pci58std = port_in(base1 | 0x58); + pci59std = port_in(base1 | 0x59); + } + mem_cfg_reg = port_in(base1 | 0x45) & 3; +#ifdef DB6K + { + int i; + for(i = 0;i < 64;i+=4) + fprintf(outf,"%08x %08x %08x %08x %08x\n", + (unsigned int)(i*4),buf[i+3],buf[i+2],buf[i+1],buf[i]); + fprintf(outf,"\npci40std 0x%02x pci42std 0x%02x pci58std " + "0x%02x pci59std 0x%02x\n" + "mem_cfg_reg 0x%02x mem_type 0x%02x\n",pci40std, + pci42std,pci58std,pci59std,mem_cfg_reg,mem_type); + } +#endif + if(mem_type) + { /* MDRAM type */ + if(mem_cfg_reg == 1) + et6000_memory = 4; /* 4 MBytes of MDRAM */ + else + et6000_memory = 2; /* 2 MBytes of MDRAM */ + } + else /* DRAM */ + { + if(mem_cfg_reg == 2) + et6000_memory = 4; /* 4 MBytes of DRAM */ + else if(mem_cfg_reg == 1) + et6000_memory = 2; /* 2 MBytes of DRAM */ + else + et6000_memory = 1; /* 1 MByte or DRAM */ + } + et6000_linear_base = buf[4] & 0xff000000; + __svgalib_linear_mem_size = et6000_memory*0x100000; + __svgalib_linear_mem_base = et6000_linear_base; + /* Banked memory is set in vga.c */ + port_out_r(base1 | 0x68,0xa); /* Set clocka */ + port_out_r(base1 | 0x69,0x24); + port_out_r(base1 | 0x69,0x21); + if(__svgalib_driver_report) + fprintf(stderr,"Using Tseng ET6000 driver (%d MBytes %sDRAM)\n", + et6000_memory,mem_type ? "M" : ""); +#ifdef DB6K + else + fprintf(outf,"NO driver report. %d MBytes %sDRAM\n",et6000_memory, + mem_type ? "M" : ""); +#endif + __svgalib_driverspecs = &__svgalib_et6000_driverspecs; + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = et6000_memory << 10; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 160000; + cardspecs->maxPixelClock16bpp = 160000; + cardspecs->maxPixelClock24bpp = 160000; + cardspecs->maxPixelClock32bpp = 160000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 2040; + cardspecs->nClocks = 0; + cardspecs->clocks = NULL; + cardspecs->mapClock = et6000_map_clock; + cardspecs->matchProgrammableClock = et6000_match_programable_clock; + cardspecs->mapHorizontalCrtc = et6000_map_horizontal_crtc; + et6000_lock(); +#ifdef DBG + { + int i,*csp; + fdm = fopen("regset.txt","w"); + if(!fdm) + { + fprintf(stderr,"Can't open register setting file.\n"); + exit(1); + } + fprintf(fdm,"CardSpecs\n"); + csp = (int* ) cardspecs; + for(i = 1;i < 13; i++) + { + fprintf(fdm,"%d, ",*(csp+i)); + if(i % 3 == 0) fprintf(fdm,"\n"); + } + fprintf(fdm,"videoMemory %d\n",cardspecs->videoMemory); + } +#endif /* DBG */ + return(0); +} + +static unsigned char last_page = 0; + +/* Bank switching function. Set 64k bank number. */ +static void et6000_setpage(int page) +{ +#ifdef DB6KP + fprintf(outf,"setpage %d\n",page); +#endif + /* Set both read and write bank. 3cd */ + port_out(last_page = (page | ((page & 15) << 4)), SEG_SELECT); + /* Write page4-5 to bits 0-1 of ext. bank register, */ + /* and to bits 4-5. */ + /* return; Testing */ + port_out_r(0x3cb, ((port_in(0x3cb) & ~0x33) | (page >> 4) | (page & 0x30))); +} + +static void et6000_setrdpage(int page) +{ + DPRT("In setrdpage.\n"); + last_page &= 0x0F; + last_page |= (page << 4); + port_out(last_page,SEG_SELECT); + port_out_r(0x3cb,(port_in(0x3cb) & ~0x30) | (page & 0x30)); +} + +static void et6000_setwrpage(int page) +{ + DPRT("In setwrpage"); + last_page &= 0xF0; + last_page |= (page | 0x0F); + port_out(last_page,SEG_SELECT); + port_out_r(0x3cb,(port_in(0x3cb) & ~0x03) | page >> 4); +} + +static int et6000_setmode(int mode, int prv_mode) +{ + + unsigned char i,*moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + +#ifdef DB6K + fprintf(outf,"In setmode, mode = %d, prv_mode = %d\n",mode,prv_mode); + compareregs(); +#endif + /* Standard dac behaviour */ + switch (et6000_modeavailable(mode)) { + case STDVGADRV: + /* Reset extended register that is set to non-VGA */ + /* compatible value for 132-column textodes (at */ + /* least on some cards). */ +DPRT("STDVGADRV\n"); + et6000_unlock(); + port_out_r(__svgalib_CRT_I, 0x34); /* 3#4 */ + i = port_in(__svgalib_CRT_D); /* 3#5 */ + if ((i & 0x02) == 0x02) /* Clock0 select bit 2 */ + port_out_r(__svgalib_CRT_D, (i & 0xFD)); /* Turn it off. */ + /* Make sure pci bus is set right. */ +#ifdef DB6K + fprintf(outf,"reg 42 = %2x 58 = %2x before.\n",port_in(base1 | 0x42) + ,port_in(base1 | 0x58)); +#endif + port_out_r(base1 | 0x40,pci40std); + port_out_r(base1 | 0x42,pci42std); + port_out_r(base1 | 0x57,pci57std); + port_out_r(base1 | 0x58,pci58std); + port_out_r(base1 | 0x59,pci59std); + port_out_r(base1 | 0x46,(port_in(base1 | 0x46)&0xfe)); + /* make sure cursor is off */ + if(mode == 5) cursor_doublescan = 1; +#ifdef DB6K + fprintf(outf,"pci42 = %2x, pci58 = %2x, pci59 = %2x\n",pci42std, + pci58std,pci59std); + fprintf(outf,"reg 42 = %2x after.\n",port_in(base1 | 0x42)); +#endif + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + case SVGADRV: +DPRT("SVGADRV\n"); + break; + default: + return 1; /* mode not available */ + } + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + modetiming = malloc(sizeof(ModeTiming)); + if(__svgalib_getmodetiming(modetiming,modeinfo,cardspecs)) + { + free(modetiming); + free(modeinfo); + return(1); + } + moderegs = malloc(ET6000_TOTAL_REGS); + et6000_initializemode(moderegs,modetiming,modeinfo,mode); + cursor_doublescan = modetiming->flags & DOUBLESCAN ?1:0; +#ifdef DBG + fprintf(fdm,"In setmode.\n"); + pmodetiming(modetiming); + fdumpregs(fdm,moderegs,ET6000_TOTAL_REGS); + fprintf(fdm,"cursor_doublescan = %1d\n",cursor_doublescan); +#endif + __svgalib_setregs(moderegs); + et6000_setregs(moderegs,mode); + free(moderegs); + free(modeinfo); + free(modetiming); + return(0); +} + +static int et6000_modeavailable(int mode) +{ + int rtn; + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return(__svgalib_vga_driverspecs.modeavailable(mode)); + if(mode <= TEXT || mode > GLASTMODE) + return(0); + info = &__svgalib_infotable[mode]; + if(et6000_memory*1024*1024 < info->ydim*info->xbytes) + return(0); /* The xbytes is xdim*bytesperpixel + ** The DAC is built in and I should be able to create + ** anything I have memory for. I will DISABLE_MODE what + ** I can't handle. */ + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + modetiming = malloc(sizeof(ModeTiming)); +#ifdef DBG + fprintf(fdm,"Calling getmodetiming\n"); +#endif + if(__svgalib_getmodetiming(modetiming,modeinfo,cardspecs)) + rtn = 0; + else if(modetiming->flags & INTERLACED) + rtn = 0; + else if(modetiming->flags & DOUBLESCAN && (modeinfo->bytesPerPixel == 1)) + rtn = 0; + else + rtn = SVGADRV; +#ifdef DBG + pmodeinfo(modeinfo); + pmodetiming(modetiming); + fprintf(fdm,"Mode %d %s.\n",mode,rtn?"OK":"failure"); +#endif + free(modetiming); + free(modeinfo); + return(rtn); +} + +static void et6000_setdisplaystart(int address) +{ + /* DPRT("setdisplaystart\n"); + #ifdef DB6K + fprintf(outf,"address = 0x%08x\n",address); + #endif */ + port_outw_r(x3_4, 0x0d +(((address >>2) & 0x00ff) << 8)); /* ds0-7 */ + port_outw_r(x3_4, 0x0c + ((address >>2) & 0xff00)); /* ds0 15 */ + port_out_r(x3_4, 0x33); + port_out_r(x3_5, (port_in(x3_5) & 0xf0) | ((address & 0xf0000) >> 18 )); + /* ds 16-19 */ +} + +static void et6000_setlogicalwidth(int width) +{ + DPRT("setlogicalwidth\n"); +#ifdef DB6K + fprintf(outf,"width = 0x%08x\n",width); +#endif + port_outw_r(x3_4,0x13 + (((width >> 3 ) & 0xff) << 8)); /* lw3-10 */ + port_out_r(x3_4 ,0x3f); + port_out_r(x3_5,(port_in(x3_5) & 0x3f) | ((width & 0x1800) >> 3)); /* lw11-12 */ +} + +static void et6000_getmodeinfo(int mode,vga_modeinfo *modeinfo) +{ + switch(modeinfo->colors){ + case 16: + modeinfo->maxpixels = 65536*8; + break; + default: + if(modeinfo->bytesperpixel > 0) + modeinfo->maxpixels = et6000_memory*1024*1024/ + modeinfo->bytesperpixel; + else + modeinfo->maxpixels = et6000_memory*1024*1024; + break; + } + modeinfo->maxlogicalwidth = 4088; /* Why? */ + modeinfo->startaddressrange = 0xfffff*et6000_memory; + /* Mask for the startaddress */ + if(mode == G320x200x256) + modeinfo->startaddressrange = 0; + modeinfo->haveblit = 0; + modeinfo->memory = et6000_memory*1024; /* In kbytes. */ + modeinfo->flags |= HAVE_RWPAGE; + if(et6000_interlaced(mode)) + modeinfo->flags |= IS_INTERLACED; +#ifdef DB6K + fprintf(outf,"Getmodeinfo mode = %d, colors = %d, linearset = 0x%x " + ,mode,modeinfo->colors,__svgalib_modeinfo_linearset); +#endif + if((mode > LMODEMIN) && (mode < LMODEMAX)) { + modeinfo->flags |= (__svgalib_modeinfo_linearset | CAPABLE_LINEAR); +#ifdef DB6K + fprintf(outf,"flag = 0x%x\n",modeinfo->flags); +#endif + } + modeinfo->chiptype = et6000_chiptype; /* is set in vgamisc.c */ + modeinfo->linewidth_unit = 8; + modeinfo->aperture_size = et6000_memory*1024; +#ifdef DB6K + fprintf(outf,"\nModeinfo at the end of the subroutine:\n"); + prtmodeinfo(modeinfo); + fprintf(outf,"Text mode errors = %d\n",compareregs()); +} + +static void prtmodeinfo(vga_modeinfo *m) +{ + fprintf(outf,"width\t\t\t%4d\nheight\t\t\t%4d\nbytesperpixel\t\t%4d\ +\ncolors\t\t\t%4d\nlinewidth\t\t%4d\nmaxlogicalwidth\t\t%4d\ +\nstartaddressrange\t%4d\nmaxpixels\t\t%4d\nhaveblit\t\t%4d\nflags\t\t\t%4x\ +\nchiptype\t\t%4d\nmemory\t\t\t%4dkbytes\nlinewidth_unit\t\t%4d\ +\nlinear_aperture\t\t%s\naperture_size\t\t%4d\nset_aperture_page\t%4x\ +\nextensions\t\t%4s\n", + m->width,m->height,m->bytesperpixel,m->colors,m->linewidth, + m->maxlogicalwidth,m->startaddressrange,m->maxpixels,m->haveblit, + m->flags,m->chiptype,m->memory,m->linewidth_unit, + m->linear_aperture ? "available":"not available",m->aperture_size, + m->set_aperture_page ? (int) *m->set_aperture_page :(int) 0, + m->extensions ? "yes" : "no"); +} + +static int compareregs(void) +{ + int n,i; + + n = 0; + if(textset == 0) { + textstore = malloc(MAX_REGS); + vgatextstore = malloc(MAX_REGS); + textset = 1; + } + if(textset == 1) { + vga_gettextmoderegs(textstore); + fputc('C',outf); + if(textstore[25] == 1) + textset = 2; + } + if(textset == 2) { + vga_gettextmoderegs(vgatextstore); + fprintf(outf,"textstore = %x and vgatextstore = %x.\n",(int) textstore, + (int) vgatextstore); + for(i = 0;i < 73;i++) { + if(textstore[i] != vgatextstore[i]) { + fprintf(outf,"register %d text = %2x, vgatext = %2x\n",i, + textstore[i],vgatextstore[i]); + n++; + } + } + if(vgatextstore[25] == 0) + textset = 1; + } + return(n); +} +#else +} +#endif +/* +static int et6000_ext_set(unsigned what, va_list params) +{ + DNOTW("ext_set"); + return(0); +} + +static int et6000_accel(unsigned operation, va_list params) +{ + DNOTW("accel"); + return(0); +} +*/ +static int et6000_linear(int op, int param) +{ +#ifdef DB6K + fprintf(outf,"linear op = %d, param = 0x%0x ",op,param); +#endif + if(op == LINEAR_QUERY_BASE) { +#ifdef DB6K + fprintf(outf, "QUERY\n"); +#endif + /* Possible error with & */ + if((vga_getmodeinfo(vga_getcurrentmode())->flags & CAPABLE_LINEAR)) + return(et6000_linear_base); + else /* frame_ptr was determined at init time */ + return(-1); + } + else if(op == LINEAR_ENABLE) + { +#ifdef DB6K + fprintf(outf,"ENABLE, param = 0x%x\n",param); +#endif + port_out(0,SEG_SELECT); + port_out(0,0x3cb); + port_out(5,GRA_I); + port_out(0x40,GRA_D); /* Set linear graphics. Don't touch this */ + /* on disable. */ + port_out_r(base1 | 0x40, 0x09); + /* Set memory relocation and linear. */ + return(0); + } + else if(op == LINEAR_DISABLE) + { +#ifdef DB6K + fprintf(outf,"DISABLE\n"); +#endif + port_out_r(base1 | 0x40, 0); + /* Turn off memory relocation and linear. */ + __svgalib_modeinfo_linearset = 0; /* In vga.c */ + return(0); + } + else if(op == LINEAR_QUERY_RANGE) { +#ifdef DB6K + fprintf(outf,"RANGE\n"); +#endif + return(-1); + } + else if(op == LINEAR_QUERY_GRANULARITY) { +#ifdef DB6K + fprintf(outf,"GRANULARITY\n"); +#endif + return(et6000_memory*1024*1024); + } +#ifdef DB6K + fprintf(outf,"UNKNOWN function\n"); +#endif + return(-1); +} +static int et6000_cursor(int cmd,int p1,int p2,int p3,int p4,void *p5) +{ + int i,j; + +#ifdef DB6K + if(cmd != 2 && cmd != 3) + fprintf(outf,"In et6000_cursor cmd = %d\n",cmd); + fflush(outf); +#endif + switch(cmd) + { + case CURSOR_INIT: + for(i = 0;i < 16;i++) + cursors[i] = NULL; + break; + + case CURSOR_HIDE: + port_out_r(base1 | 0x46,port_in(base1 | 0x46)&0xfe); + break; + + case CURSOR_SHOW: + if(active_cursor == -1) + { + fprintf(stderr,"No active cursor\n"); + return(-1); + } + port_out_r(base1 | 0x46,port_in(base1 | 0x46) | 0x01); + break; + + case CURSOR_POSITION: + port_out_r(base1 | 0x84,p1&0xff); + port_out_r(base1 | 0x85,p1 >> 8); + port_out_r(base1 | 0x86,(p2<> 8); + break; + + case CURSOR_IMAGE: + switch(p2) + { + case 0: + if(cursors[p1] != NULL) + free(cursors[p1]); + cursors[p1] = malloc(256); + memcpy(cursors[p1],p5,256); + cursor_format[p1] = 0; + break; + + case 1: + if(cursors[p1] != NULL) + free(cursors[p1]); + cursors[p1] = malloc(4096); + memcpy(cursors[p1],p5,4096); + cursor_format[p1] = 1; + break; + } + cursor_colors[p1*2] = p3; + cursor_colors[p1*2 + 1] = p4; + cursor_loaded[p1] = 1; + break; + + case CURSOR_SELECT: + if(active_cursor == p1) + return(0); + if(cursor_loaded[p1]) + { + int c = 64, cl[2],sptptr,sptr,k,n,l,cf,islinear,col=0; + unsigned char c0=0,cr; + unsigned char f,f1,cb,*cu; + + if(vga_getmodeinfo(vga_getcurrentmode())->flags & IS_LINEAR) + islinear = 1; + else + islinear = 0; +#ifdef DB6K + + fprintf(outf,"cursor_loaded[%d] = %d\n",p1,cursor_loaded[p1]); + { + unsigned short pat[8] = {0x0055,0xaa55,0xff55,0x0033,0x0022, + 0x00aa,0xffaa,0x0000}; + int i,j; + if(islinear) + { + fprintf(outf,"Islinear = %d , 16*et6000_memory = %d\n", + islinear,16*et6000_memory); + /* Put something here for linear. */ + } + else + { + fprintf(outf,"islinear = %d\n",islinear); + et6000_setpage((16*et6000_memory) - 1); + } + for(i = 0;i < 0x8;i++) + for(j = 0;j < 0x2000;j+=2) + gr_writew(pat[i],i*0x2000 + j + islinear* + 65536*(16*et6000_memory - 1)); + if(!islinear) et6000_setpage(0); + } +#endif + for(j = 0;j < 2;j++) + { + cl[j] = 0; + col = cursor_colors[p1*2 + j]; + for(i = 0;i < 3;i++) + { + cf = (col << i*8) & 0xff0000; + if(c > cf) c0 = 0; + else if(2*c > cf) c0 = 1; + else if(3*c > cf) c0 = 2; + else c0 = 3; + cl[j] |= c0; + cl[j] = cl[j] << 2; +#ifdef DB6K + fprintf(outf,"f = 0x%02x \n",cf); +#endif + } + cl[j] = cl[j] >> 2; +#ifdef DB6K + fprintf(outf,"Col = 0x%x, Color %d = 0x%x\n c0 = 0x%x\n" + ,col,j,cl[j],c0); +#endif + } + port_out_r(base1 | 0x67,9); /* set register 9 for colors */ + port_out_r(base1 | 0x69,cl[0]); /* Sprite color 0 */ + port_out_r(base1 | 0x69,cl[1]); /* Sprite color 1 */ + /* sptr = sptptr = __svgalib_linear_mem_size/2 - 1024; */ + sptptr = 0x7ff00; + sptr = 64512 - 128 - 512*(cursor_doublescan - 1) + + (islinear)*65536*(16*et6000_memory - 2); + /* 64512 = 65536 - 16*64 */ + if(islinear) + { +#ifdef DB6K + fprintf(outf,"Linear sptr = %d\n",sptr); +#endif + /* Put something here for linear */ + } + else + { +#ifdef DB6K + fprintf(outf,"Paged sptr = %d\n",sptr); +#endif + + et6000_setpage((16*et6000_memory) - 1); + } + cr = 0; + cb = 0; + l = 0; + cu = (unsigned char *) cursors[p1]; + for(k = 0;k < 32;k++) + { + for(n = 3;n >= 0;n--) + { + f = *(cu + (32 + k)*4 + n); + f1 = *(cu + k*4 + n); + for(j = 0;j < 8;j++) + { + if(f&0x01) + { + if(f1&0x01) cr |= 0x01; + else + cr |= 0x00; + } + else cr |= 0x02; + cb = cb << 2; + cb |= cr; + cr = 0; + f = f >> 1; + f1 = f1 >> 1; + if(!((j+1) % 4)) + { + gr_writeb(cb,sptr + 16*8 + 9 + l - j/4); + cb = 0; + } + } + l += 2; + } + sptr += 8; + } + + port_out_r(x3_4,0x0E); /* CRTC Reg E bits 16-19 of sprite add. */ + port_out_r(x3_5,(sptptr >> 16) & 0x0f); + port_out_r(x3_4,0x0F); + port_out_r(x3_5,(sptptr >> 8)&0xff); + port_out_r(base1 | 0x82,0x20); /* set cursor size. */ + port_out_r(base1 | 0x83,0x20*(cursor_doublescan-1)); + active_cursor = p1; +#ifdef DB6K + port_out_r(x3_4,0x0E); + fprintf(outf,"sptptr = 0x%08x 0E = 0x%x ", + sptptr,port_in(x3_5)); + port_out_r(x3_4,0x0F); + fprintf(outf,"0F = 0x%x\n",port_in(x3_5)); + *(LINEAR_POINTER) = 0x26; + fprintf(outf," = 0x%02x\n", + *(LINEAR_POINTER)); + if(!islinear) et6000_setpage((16*et6000_memory) - 1); + for(i = 0;i < 64;i++) + { + for(j = 0;j < 16;j++) + fprintf(outf,"%02x", + gr_readb(64512 - 128 + 16*i + j + islinear*65536* + ((16*et6000_memory) - 1) - 512*(cursor_doublescan-1))); + fprintf(outf,"\n"); + } + fprintf(outf,"LINEAR_POINTER %08x, GM = %08x, islinear = %d\n", + (unsigned int) LINEAR_POINTER,GM,islinear); + if(!islinear)et6000_setpage(0); +#endif + if(!islinear)et6000_setpage(0); + } + else + { + fprintf(stderr,"Cursor %d's immage has not been loaded when selected!\n", + p1); + return(-1); + } + break; + } + return(0); +} + +/* Programs not exported. */ + +static int et6000_interlaced(int mode) +{ + ModeTiming *modetiming; + ModeInfo *modeinfo; + int rtn; + + DPRT("In interlaced\n"); +#ifdef DB6K + fprintf(outf,"Text mode errors = %d\n",compareregs()); +#endif + if (et6000_modeavailable(mode) != SVGADRV) + return 0; + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + modetiming = malloc(sizeof(ModeTiming)); + if(__svgalib_getmodetiming(modetiming,modeinfo,cardspecs)) + rtn = 0; + else + rtn = modeinfo->flags & INTERLACED; +#ifdef DB6K + fprintf(outf,"Interlaced %s\n",rtn?"Yes":"No"); +#endif + free(modetiming); + free(modeinfo); + return(rtn); +} + +#define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2))) + +static unsigned comp_lmn(unsigned clock,float fac){ + int m, n1, n2; + double fvco; + double fout; + double fmax, fmin; + double fref; + double fvco_goal; + + fmax = 230000.0; + fmin = 48000.0; + +/* fmin, fmax and limits for n and m are guesses */ + + fref = 14318; + + for (n1 = 4; n1 <= 33; n1++) + { + for (n2 = 0; n2 <= 3; n2++) + { + for (m = 42; m <= 115; m++) + { + fout = ((double)(m) * fref)/((double)(n1) * (1 << n2)); + fvco_goal = (double)clock * (double)(1 << n2)*fac; + fvco = fout * (double)(1 << n2); + if (!WITHIN(fvco, 0.995*fvco_goal, 1.005*fvco_goal)) + continue; + if (!WITHIN(fvco, fmin, fmax)) + continue; +#if 0 + fprintf(stderr,"clock=%i m=%i n1=%i n2=%i\n ",clock,m,n1,n2); +#endif + return (m - 2) | ((n1 - 2)<<8) | (n2 << 13) ; + } + } + } + fprintf(stderr,"ET6000: Illegal clock\n"); + return 0; +} diff --git a/src/drivers/fb_lnx.h b/src/drivers/fb_lnx.h new file mode 100644 index 0000000..1fbb675 --- /dev/null +++ b/src/drivers/fb_lnx.h @@ -0,0 +1,353 @@ +#ifndef _LINUX_FB_H +#define _LINUX_FB_H + +#include + +/* Definitions of frame buffers */ + +#define FB_MAJOR 29 +#define FB_MAX 32 /* sufficient for now */ + +/* ioctls + 0x46 is 'F' */ +#define FBIOGET_VSCREENINFO 0x4600 +#define FBIOPUT_VSCREENINFO 0x4601 +#define FBIOGET_FSCREENINFO 0x4602 +#define FBIOGETCMAP 0x4604 +#define FBIOPUTCMAP 0x4605 +#define FBIOPAN_DISPLAY 0x4606 +#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor) +/* 0x4607-0x460B are defined below */ +/* #define FBIOGET_MONITORSPEC 0x460C */ +/* #define FBIOPUT_MONITORSPEC 0x460D */ +/* #define FBIOSWITCH_MONIBIT 0x460E */ +#define FBIOGET_CON2FBMAP 0x460F +#define FBIOPUT_CON2FBMAP 0x4610 +#define FBIOBLANK 0x4611 /* arg: 0 or vesa level + 1 */ +#define FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank) +#define FBIO_ALLOC 0x4613 +#define FBIO_FREE 0x4614 +#define FBIOGET_GLYPH 0x4615 +#define FBIOGET_HWCINFO 0x4616 +#define FBIOPUT_MODEINFO 0x4617 +#define FBIOGET_DISPINFO 0x4618 + + +#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ +#define FB_TYPE_PLANES 1 /* Non interleaved planes */ +#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ +#define FB_TYPE_TEXT 3 /* Text/attributes */ +#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */ + +#define FB_AUX_TEXT_MDA 0 /* Monochrome text */ +#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ +#define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */ +#define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */ +#define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */ + +#define FB_AUX_VGA_PLANES_VGA4 0 /* 16 color planes (EGA/VGA) */ +#define FB_AUX_VGA_PLANES_CFB4 1 /* CFB4 in planes (VGA) */ +#define FB_AUX_VGA_PLANES_CFB8 2 /* CFB8 in planes (VGA) */ + +#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */ +#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */ +#define FB_VISUAL_TRUECOLOR 2 /* True color */ +#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ +#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */ +#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */ + +#define FB_ACCEL_NONE 0 /* no hardware accelerator */ +#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ +#define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */ +#define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */ +#define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */ +#define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */ +#define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */ +#define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */ +#define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */ +#define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */ +#define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */ +#define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */ +#define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */ +#define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */ +#define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */ +#define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */ +#define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */ +#define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */ +#define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */ +#define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */ +#define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */ +#define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */ +#define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */ +#define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */ +#define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */ +#define FB_ACCEL_SUN_TCX 25 /* Sun tcx */ +#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ +#define FB_ACCEL_NV3 27 /* nVidia RIVA 128 */ +#define FB_ACCEL_NV4 28 /* nVidia RIVA TNT */ +#define FB_ACCEL_NV5 29 /* nVidia RIVA TNT2 */ +#define FB_ACCEL_CT_6555x 30 /* C&T 6555x */ +#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */ +#define FB_ACCEL_ATI_RAGE128 32 /* ATI Rage128 family */ +#define FB_ACCEL_IGS_CYBER2000 33 /* CyberPro 2000 */ +#define FB_ACCEL_IGS_CYBER2010 34 /* CyberPro 2010 */ +#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */ +#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */ +#define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */ +#define FB_ACCEL_ATI_RADEON 38 /* ATI Radeon family */ +#define FB_ACCEL_I810 39 /* Intel 810/815 */ +#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 650, 740 */ +#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre") */ +#define FB_ACCEL_I830 42 /* Intel 830M/845G/85x/865G */ +#define FB_ACCEL_NV_10 43 /* nVidia Arch 10 */ +#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */ +#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */ +#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */ + +#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */ +#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */ +#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */ +#define FB_ACCEL_NEOMAGIC_NM2097 93 /* NeoMagic NM2097 */ +#define FB_ACCEL_NEOMAGIC_NM2160 94 /* NeoMagic NM2160 */ +#define FB_ACCEL_NEOMAGIC_NM2200 95 /* NeoMagic NM2200 */ +#define FB_ACCEL_NEOMAGIC_NM2230 96 /* NeoMagic NM2230 */ +#define FB_ACCEL_NEOMAGIC_NM2360 97 /* NeoMagic NM2360 */ +#define FB_ACCEL_NEOMAGIC_NM2380 98 /* NeoMagic NM2380 */ + +#define FB_ACCEL_SAVAGE4 0x80 /* S3 Savage4 */ +#define FB_ACCEL_SAVAGE3D 0x81 /* S3 Savage3D */ +#define FB_ACCEL_SAVAGE3D_MV 0x82 /* S3 Savage3D-MV */ +#define FB_ACCEL_SAVAGE2000 0x83 /* S3 Savage2000 */ +#define FB_ACCEL_SAVAGE_MX_MV 0x84 /* S3 Savage/MX-MV */ +#define FB_ACCEL_SAVAGE_MX 0x85 /* S3 Savage/MX */ +#define FB_ACCEL_SAVAGE_IX_MV 0x86 /* S3 Savage/IX-MV */ +#define FB_ACCEL_SAVAGE_IX 0x87 /* S3 Savage/IX */ +#define FB_ACCEL_PROSAVAGE_PM 0x88 /* S3 ProSavage PM133 */ +#define FB_ACCEL_PROSAVAGE_KM 0x89 /* S3 ProSavage KM133 */ +#define FB_ACCEL_S3TWISTER_P 0x8a /* S3 Twister */ +#define FB_ACCEL_S3TWISTER_K 0x8b /* S3 TwisterK */ +#define FB_ACCEL_SUPERSAVAGE 0x8c /* S3 Supersavage */ +#define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */ +#define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */ + +struct fb_fix_screeninfo { + char id[16]; /* identification string eg "TT Builtin" */ + unsigned long smem_start; /* Start of frame buffer mem */ + /* (physical address) */ + uint32_t smem_len; /* Length of frame buffer mem */ + uint32_t type; /* see FB_TYPE_* */ + uint32_t type_aux; /* Interleave for interleaved Planes */ + uint32_t visual; /* see FB_VISUAL_* */ + uint16_t xpanstep; /* zero if no hardware panning */ + uint16_t ypanstep; /* zero if no hardware panning */ + uint16_t ywrapstep; /* zero if no hardware ywrap */ + uint32_t line_length; /* length of a line in bytes */ + unsigned long mmio_start; /* Start of Memory Mapped I/O */ + /* (physical address) */ + uint32_t mmio_len; /* Length of Memory Mapped I/O */ + uint32_t accel; /* Type of acceleration available */ + uint16_t reserved[3]; /* Reserved for future compatibility */ +}; + +/* Interpretation of offset for color fields: All offsets are from the right, + * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you + * can use the offset as right argument to <<). A pixel afterwards is a bit + * stream and is written to video memory as that unmodified. This implies + * big-endian byte order if bits_per_pixel is greater than 8. + */ +struct fb_bitfield { + uint32_t offset; /* beginning of bitfield */ + uint32_t length; /* length of bitfield */ + uint32_t msb_right; /* != 0 : Most significant bit is */ + /* right */ +}; + +#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */ + +#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/ +#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */ +#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */ +#define FB_ACTIVATE_MASK 15 + /* values */ +#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */ +#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */ +#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */ +#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/ +#define FB_ACTIVATE_INV_MODE 256 /* invalidate videomode */ + +#define FB_ACCELF_TEXT 1 /* text mode acceleration */ + +#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ +#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ +#define FB_SYNC_EXT 4 /* external sync */ +#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ +#define FB_SYNC_BROADCAST 16 /* broadcast video timings */ + /* vtotal = 144d/288n/576i => PAL */ + /* vtotal = 121d/242n/484i => NTSC */ +#define FB_SYNC_ON_GREEN 32 /* sync on green */ + +#define FB_VMODE_NONINTERLACED 0 /* non interlaced */ +#define FB_VMODE_INTERLACED 1 /* interlaced */ +#define FB_VMODE_DOUBLE 2 /* double scan */ +#define FB_VMODE_MASK 255 + +#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */ +#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ +#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ + +#define PICOS2KHZ(a) (1000000000UL/(a)) +#define KHZ2PICOS(a) (1000000000UL/(a)) + +struct fb_var_screeninfo { + uint32_t xres; /* visible resolution */ + uint32_t yres; + uint32_t xres_virtual; /* virtual resolution */ + uint32_t yres_virtual; + uint32_t xoffset; /* offset from virtual to visible */ + uint32_t yoffset; /* resolution */ + + uint32_t bits_per_pixel; /* guess what */ + uint32_t grayscale; /* != 0 Graylevels instead of colors */ + + struct fb_bitfield red; /* bitfield in fb mem if true color, */ + struct fb_bitfield green; /* else only length is significant */ + struct fb_bitfield blue; + struct fb_bitfield transp; /* transparency */ + + uint32_t nonstd; /* != 0 Non standard pixel format */ + + uint32_t activate; /* see FB_ACTIVATE_* */ + + uint32_t height; /* height of picture in mm */ + uint32_t width; /* width of picture in mm */ + + uint32_t accel_flags; /* acceleration flags (hints) */ + + /* Timing: All values in pixclocks, except pixclock (of course) */ + uint32_t pixclock; /* pixel clock in ps (pico seconds) */ + uint32_t left_margin; /* time from sync to picture */ + uint32_t right_margin; /* time from picture to sync */ + uint32_t upper_margin; /* time from sync to picture */ + uint32_t lower_margin; + uint32_t hsync_len; /* length of horizontal sync */ + uint32_t vsync_len; /* length of vertical sync */ + uint32_t sync; /* see FB_SYNC_* */ + uint32_t vmode; /* see FB_VMODE_* */ + uint32_t rotate; /* angle we rotate counter clockwise */ + uint32_t reserved[5]; /* Reserved for future compatibility */ +}; + +struct fb_cmap { + uint32_t start; /* First entry */ + uint32_t len; /* Number of entries */ + uint16_t *red; /* Red values */ + uint16_t *green; + uint16_t *blue; + uint16_t *transp; /* transparency, can be NULL */ +}; + +struct fb_con2fbmap { + uint32_t console; + uint32_t framebuffer; +}; + +/* VESA Blanking Levels */ +#define VESA_NO_BLANKING 0 +#define VESA_VSYNC_SUSPEND 1 +#define VESA_HSYNC_SUSPEND 2 +#define VESA_POWERDOWN 3 + +struct fb_monspecs { + uint32_t hfmin; /* hfreq lower limit (Hz) */ + uint32_t hfmax; /* hfreq upper limit (Hz) */ + uint16_t vfmin; /* vfreq lower limit (Hz) */ + uint16_t vfmax; /* vfreq upper limit (Hz) */ + uint32_t dclkmin; /* pixelclock lower limit (Hz) */ + uint32_t dclkmax; /* pixelclock upper limit (Hz) */ + unsigned gtf : 1; /* supports GTF */ + unsigned dpms : 1; /* supports DPMS */ +}; + +#define FB_VBLANK_VBLANKING 0x001 /* currently in a vertical blank */ +#define FB_VBLANK_HBLANKING 0x002 /* currently in a horizontal blank */ +#define FB_VBLANK_HAVE_VBLANK 0x004 /* vertical blanks can be detected */ +#define FB_VBLANK_HAVE_HBLANK 0x008 /* horizontal blanks can be detected */ +#define FB_VBLANK_HAVE_COUNT 0x010 /* global retrace counter is available */ +#define FB_VBLANK_HAVE_VCOUNT 0x020 /* the vcount field is valid */ +#define FB_VBLANK_HAVE_HCOUNT 0x040 /* the hcount field is valid */ +#define FB_VBLANK_VSYNCING 0x080 /* currently in a vsync */ +#define FB_VBLANK_HAVE_VSYNC 0x100 /* verical syncs can be detected */ + +struct fb_vblank { + uint32_t flags; /* FB_VBLANK flags */ + uint32_t count; /* counter of retraces since boot */ + uint32_t vcount; /* current scanline position */ + uint32_t hcount; /* current scandot position */ + uint32_t reserved[4]; /* reserved for future compatibility */ +}; + +/* Internal HW accel */ +#define ROP_COPY 0 +/* #define ROP_XOR 1 Already defined by svgalib */ + +struct fb_copyarea { + uint32_t dx; + uint32_t dy; + uint32_t width; + uint32_t height; + uint32_t sx; + uint32_t sy; +}; + +struct fb_fillrect { + uint32_t dx; /* screen-relative */ + uint32_t dy; + uint32_t width; + uint32_t height; + uint32_t color; + uint32_t rop; +}; + +struct fb_image { + uint32_t dx; /* Where to place image */ + uint32_t dy; + uint32_t width; /* Size of image */ + uint32_t height; + uint32_t fg_color; /* Only used when a mono bitmap */ + uint32_t bg_color; + uint8_t depth; /* Depth of the image */ + const char *data; /* Pointer to image data */ + struct fb_cmap cmap; /* color map info */ +}; + +/* + * hardware cursor control + */ + +#define FB_CUR_SETCUR 0x01 +#define FB_CUR_SETPOS 0x02 +#define FB_CUR_SETHOT 0x04 +#define FB_CUR_SETCMAP 0x08 +#define FB_CUR_SETSHAPE 0x10 +#define FB_CUR_SETSIZE 0x20 +#define FB_CUR_SETALL 0xFF + +struct fbcurpos { + uint16_t x, y; +}; + +struct fb_cursor { + uint16_t set; /* what to set */ + uint16_t enable; /* cursor on/off */ + uint16_t rop; /* bitop operation */ + char *mask; /* cursor mask bits */ + struct fbcurpos hot; /* cursor hot spot */ + struct fb_image image; /* Cursor image */ +}; + +#define FB_PIXMAP_DEFAULT 1 /* used internally by fbcon */ +#define FB_PIXMAP_SYSTEM 2 /* memory is in system RAM */ +#define FB_PIXMAP_IO 4 /* memory is iomapped */ +#define FB_PIXMAP_SYNC 256 /* set if GPU can DMA */ + +#endif /* _LINUX_FB_H */ diff --git a/src/drivers/fbdev.c b/src/drivers/fbdev.c new file mode 100644 index 0000000..fcdf38f --- /dev/null +++ b/src/drivers/fbdev.c @@ -0,0 +1,660 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fb_lnx.h" +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "interface.h" + +/* #define DEBUG */ + +static int fbdev_fd = -1; +static int fbdev_vgamode = 0; +static int fbdev_banked_pointer_emulated = 1; +static size_t fbdev_memory; +static size_t fbdev_startaddressrange; +static CardSpecs *cardspecs; +static struct console_font_op fbdev_font; +/* Card Specs */ +static int fbdev_setpalette(int index, int red, int green, int blue); +static void fbdev_set_virtual_height(struct fb_var_screeninfo *info); +static int dacmode; + +static int fbdev_match_programmable_clock(int clock) +{ + return clock; +} + +static int fbdev_map_clock(int bpp, int clock) +{ + return clock; +} + +static int fbdev_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + return htiming; +} + +/* Driver Specs */ + +static int fbdev_saveregs(unsigned char *regs) +{ + ioctl(fbdev_fd, FBIOGET_VSCREENINFO, regs+EXT); + return sizeof(struct fb_var_screeninfo); +} + +static void fbdev_setregs(const unsigned char *regs, int mode) +{ + ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, regs+EXT); + fbdev_vgamode = 0; +} + +static void fbdev_unlock(void) +{ +} + +static void fbdev_lock(void) +{ +} + +static int fbdev_init(int force, int par1, int par2) +{ + struct fb_fix_screeninfo info; + int fd; + + if ((fd = open("/dev/fb0", O_RDWR)) < 0) + { + return -1; + } + + if (ioctl(fd, FBIOGET_FSCREENINFO, &info)) + { + close(fd); + return -1; + } + + /* Ensure this file is closed if we ever exec something else... */ + if (fcntl(fd, F_SETFD, 1) == -1) { + perror("fcntl 007"); + exit(-1); + } + + fbdev_memory = info.smem_len; + fbdev_fd = fd; + + fbdev_startaddressrange = 65536; + while (fbdev_startaddressrange < fbdev_memory) + { + fbdev_startaddressrange <<= 1; + } + fbdev_startaddressrange -= 1; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = fbdev_memory/1024; + +/* FIXME: autodetect these */ + cardspecs->maxPixelClock4bpp = 200000; + cardspecs->maxPixelClock8bpp = 200000; + cardspecs->maxPixelClock16bpp = 200000; + cardspecs->maxPixelClock24bpp = 200000; + cardspecs->maxPixelClock32bpp = 200000; + cardspecs->maxHorizontalCrtc = 8192; + + cardspecs->flags = CLOCK_PROGRAMMABLE; + + cardspecs->nClocks = 0; + cardspecs->clocks = 0; + + cardspecs->mapClock = fbdev_map_clock; + cardspecs->matchProgrammableClock = fbdev_match_programmable_clock; + cardspecs->mapHorizontalCrtc = fbdev_map_horizontal_crtc; + + __svgalib_driverspecs = &__svgalib_fbdev_driverspecs; + __svgalib_banked_mem_base = (unsigned long)info.smem_start; + __svgalib_banked_mem_size = 0x10000; + __svgalib_linear_mem_base = 0; + __svgalib_linear_mem_phys_addr = (unsigned long)info.smem_start; + __svgalib_linear_mem_size = fbdev_memory; + __svgalib_linear_mem_fd = fbdev_fd; + + dacmode = 6; + + fprintf(stderr,"Using fbdev, %iKB at %08x\n",(int)fbdev_memory/1024, (unsigned int)info.smem_start); + + return 0; +} + +static int fbdev_test(void) +{ + return !fbdev_init(0, 0, 0); +} + +static void fbdev_setpage(int page) +{ + if (fbdev_vgamode) + { + __svgalib_vga_driverspecs.__svgalib_setpage(page); + } + else + { + mmap(BANKED_POINTER, + __svgalib_banked_mem_size, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, + fbdev_fd, page << 16); + fbdev_banked_pointer_emulated = 1; + } +} + +static int fbdev_screeninfo(struct fb_var_screeninfo *info, int mode) +{ + ModeTiming modetiming; + ModeInfo *modeinfo; + + if (ioctl(fbdev_fd, FBIOGET_VSCREENINFO, info)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if (__svgalib_getmodetiming(&modetiming, modeinfo, cardspecs)) + { + free(modeinfo); + return 1; + } + + info->xres = modeinfo->width; + info->yres = modeinfo->height; + info->xres_virtual = modeinfo->width; + info->yres_virtual = modeinfo->height; + info->xoffset = 0; + info->yoffset = 0; + info->bits_per_pixel = modeinfo->bitsPerPixel; + info->grayscale = 0; + info->red.offset = modeinfo->redOffset; + info->red.length = modeinfo->redWeight; + info->red.msb_right = 0; + info->green.offset = modeinfo->greenOffset; + info->green.length = modeinfo->greenWeight; + info->green.msb_right = 0; + info->blue.offset = modeinfo->blueOffset; + info->blue.length = modeinfo->blueWeight; + info->blue.msb_right = 0; + info->nonstd = 0; + + free(modeinfo); + + info->vmode &= FB_VMODE_MASK; + + if (modetiming.flags & INTERLACED) + info->vmode |= FB_VMODE_INTERLACED; + if (modetiming.flags & DOUBLESCAN) + { + info->vmode |= FB_VMODE_DOUBLE; + modetiming.VDisplay >>= 1; + modetiming.VSyncStart >>= 1; + modetiming.VSyncEnd >>= 1; + modetiming.VTotal >>= 1; + } + + info->pixclock = 1000000000 / modetiming.pixelClock; + info->left_margin = modetiming.HTotal - modetiming.HSyncEnd; + info->right_margin = modetiming.HSyncStart - modetiming.HDisplay; + info->upper_margin = modetiming.VTotal - modetiming.VSyncEnd; + info->lower_margin = modetiming.VSyncStart - modetiming.VDisplay; + info->hsync_len = modetiming.HSyncEnd - modetiming.HSyncStart; + info->vsync_len = modetiming.VSyncEnd - modetiming.VSyncStart; + + info->sync &= ~(FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT); + + if (modetiming.flags & PHSYNC) + info->sync |= FB_SYNC_HOR_HIGH_ACT; + if (modetiming.flags & PVSYNC) + info->sync |= FB_SYNC_VERT_HIGH_ACT; + + fbdev_set_virtual_height(info); + + return 0; +} + +static void fbdev_set_virtual_height(struct fb_var_screeninfo *info) +{ + int maxpixels = fbdev_memory; + int bytesperpixel = info->bits_per_pixel / 8; + + if (bytesperpixel) + maxpixels /= bytesperpixel; + + info->yres_virtual = maxpixels / info->xres_virtual; + if (info->yres_virtual > 8192) + info->yres_virtual = 8192; +} + +static int fbdev_put_vscreeninfo(struct fb_var_screeninfo *info) +{ + if (!ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, info)) + return 0; + + /* try again with an yres virtual of 2x yres */ + info->yres_virtual = 2 * info->yres; + if (!ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, info)) + return 0; + + /* last try, with an yres_virtual of yres */ + info->yres_virtual = info->yres; + if (!ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, info)) + return 0; + + /* we failed */ + return 1; +} + +#ifdef DEBUG +static void print_vinfo(struct fb_var_screeninfo *vinfo) +{ + fprintf(stderr, "\txres: %d\n", vinfo->xres); + fprintf(stderr, "\tyres: %d\n", vinfo->yres); + fprintf(stderr, "\txres_virtual: %d\n", vinfo->xres_virtual); + fprintf(stderr, "\tyres_virtual: %d\n", vinfo->yres_virtual); + fprintf(stderr, "\txoffset: %d\n", vinfo->xoffset); + fprintf(stderr, "\tyoffset: %d\n", vinfo->yoffset); + fprintf(stderr, "\tbits_per_pixel: %d\n", vinfo->bits_per_pixel); + fprintf(stderr, "\tgrayscale: %d\n", vinfo->grayscale); + fprintf(stderr, "\tnonstd: %d\n", vinfo->nonstd); + fprintf(stderr, "\tactivate: %d\n", vinfo->activate); + fprintf(stderr, "\theight: %d\n", vinfo->height); + fprintf(stderr, "\twidth: %d\n", vinfo->width); + fprintf(stderr, "\taccel_flags: %d\n", vinfo->accel_flags); + fprintf(stderr, "\tpixclock: %d\n", vinfo->pixclock); + fprintf(stderr, "\tleft_margin: %d\n", vinfo->left_margin); + fprintf(stderr, "\tright_margin: %d\n", vinfo->right_margin); + fprintf(stderr, "\tupper_margin: %d\n", vinfo->upper_margin); + fprintf(stderr, "\tlower_margin: %d\n", vinfo->lower_margin); + fprintf(stderr, "\thsync_len: %d\n", vinfo->hsync_len); + fprintf(stderr, "\tvsync_len: %d\n", vinfo->vsync_len); + fprintf(stderr, "\tsync: %d\n", vinfo->sync); + fprintf(stderr, "\tvmode: %d\n", vinfo->vmode); + fprintf(stderr, "\tred: %d/%d\n", vinfo->red.length, vinfo->red.offset); + fprintf(stderr, "\tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset); + fprintf(stderr, "\tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset); + fprintf(stderr, "\talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset); + fflush(stderr); +} +#endif + +static int fbdev_setmode(int mode, int prv_mode) +{ + struct fb_var_screeninfo info; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + { + if (__svgalib_fbdev_novga) + return 1; + if (__svgalib_vga_driverspecs.setmode(mode, prv_mode)) + return 1; + if (fbdev_banked_pointer_emulated) + { + __svgalib_banked_mem_base = 0xA0000; + map_banked(MAP_FIXED); + fbdev_banked_pointer_emulated=0; + } + fbdev_vgamode = 1; + return 0; + } + + if (!fbdev_banked_pointer_emulated) + { + __svgalib_banked_mem_base = __svgalib_linear_mem_phys_addr; + map_banked(MAP_FIXED); + fbdev_banked_pointer_emulated=1; + } + + if (fbdev_screeninfo(&info, mode)) + return 1; + + info.activate = FB_ACTIVATE_NOW; +#ifdef DEBUG + fprintf(stderr, "Vinfo: before putvinfo\n"); + print_vinfo(&info); +#endif + if (fbdev_put_vscreeninfo(&info)) + return 1; +#ifdef DEBUG + fprintf(stderr, "Vinfo: after putvinfo\n"); + print_vinfo(&info); +#endif + + fbdev_vgamode = 0; + if(info.bits_per_pixel>16) { + int i; + dacmode = 8; + for(i=0;i<256;i++)fbdev_setpalette(i,i,i,i); + } else if(info.bits_per_pixel>8) { + int i; + dacmode = 8; + for(i=0;i<256;i++)fbdev_setpalette(i,0,0,0); + for(i=0;i<16;i++)fbdev_setpalette(i,i<<3,i<<3,i<<3); + } else { + dacmode = 6; + } + return 0; +} + +static int fbdev_modeavailable(int mode) +{ + struct fb_var_screeninfo info; + unsigned g, bpp; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + { + if (__svgalib_fbdev_novga) + return 0; + else + return __svgalib_vga_driverspecs.modeavailable(mode); + } + + if (fbdev_screeninfo(&info, mode)) + return 0; + + g = info.green.length; + bpp = info.bits_per_pixel; + + info.activate = FB_ACTIVATE_TEST; + if (fbdev_put_vscreeninfo(&info)) + return 0; + + if (info.bits_per_pixel != bpp ) + return 0; + + if (info.bits_per_pixel == 16 && + info.green.length != g) + return 0; + + /* We may need to add more checks here. */ + + return SVGADRV; +} + +static void fbdev_setdisplaystart(int address) +{ + struct fb_var_screeninfo info; + + if (fbdev_vgamode) + { + __svgalib_vga_driverspecs.setdisplaystart(address); + return; + } + + if (ioctl(fbdev_fd, FBIOGET_VSCREENINFO, &info)) + return; + + info.xoffset = address % info.xres_virtual; + info.yoffset = address / info.xres_virtual; + + ioctl(fbdev_fd, FBIOPAN_DISPLAY, &info); +} + +static void fbdev_setlogicalwidth(int width) +{ + struct fb_var_screeninfo info; + + if (fbdev_vgamode) + { + __svgalib_vga_driverspecs.setlogicalwidth(width); + return; + } + + if (ioctl(fbdev_fd, FBIOGET_VSCREENINFO, &info)) + return; + + info.xres_virtual = width; + fbdev_set_virtual_height(&info); + fbdev_put_vscreeninfo(&info); +} + +static void fbdev_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + struct fb_var_screeninfo info; + int maxpixels = fbdev_memory; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.getmodeinfo(mode, modeinfo); + + if (modeinfo->bytesperpixel) + maxpixels /= modeinfo->bytesperpixel; + + modeinfo->maxlogicalwidth = maxpixels / modeinfo->height; + modeinfo->startaddressrange = fbdev_startaddressrange; + modeinfo->maxpixels = maxpixels; + modeinfo->haveblit = 0; + modeinfo->flags |= (__svgalib_modeinfo_linearset | CAPABLE_LINEAR); + + if (fbdev_screeninfo(&info, mode)) + return; + + info.activate = FB_ACTIVATE_TEST; + if (fbdev_put_vscreeninfo(&info)) + return; + + modeinfo->linewidth = info.xres_virtual * info.bits_per_pixel / 8; + modeinfo->maxpixels = info.xres_virtual * info.yres_virtual; +} + +static int fbdev_linear(int op, int param) +{ + switch(op) + { + case LINEAR_QUERY_BASE: + return __svgalib_linear_mem_phys_addr; + case LINEAR_ENABLE: + case LINEAR_DISABLE: + return 0; + } + return -1; +} + +/* Emulation */ + +static void fbdev_savepalette(unsigned char *red, + unsigned char *green, + unsigned char *blue) +{ + uint16_t r[256], g[256], b[256], t[256]; + struct fb_cmap cmap; + unsigned i; + + if (fbdev_vgamode) + { + for (i = 0; i < 256; i++) { + int r,g,b; + __svgalib_inpal(i,&r,&g,&b); + *(red++) = r; + *(green++) = g; + *(blue++) = b; + } + return; + } + + cmap.start = 0; + cmap.len = 256; + cmap.red = r; + cmap.green = g; + cmap.blue = b; + cmap.transp = t; + + if (ioctl(fbdev_fd, FBIOGETCMAP, &cmap)) + return; + + for (i = 0; i < 256; i++) + { + red[i] = r[i] >> 10; + green[i] = g[i] >> 10; + blue[i] = b[i] >> 10; + } +} + +static void fbdev_restorepalette(const unsigned char *red, + const unsigned char *green, + const unsigned char *blue) +{ + uint16_t r[256], g[256], b[256], t[256]; + struct fb_cmap cmap; + unsigned i; + + if (fbdev_vgamode) + { + for (i = 0; i < 256; i++) { + __svgalib_outpal(i,*(red++),*(green++),*(blue++)); + } + return; + } + + for (i = 0; i < 256; i++) + { + r[i] = (red[i] << 10) | (red[i] << 4) | (red[i] >> 2); + g[i] = (green[i] << 10) | (green[i] << 4) | (green[i] >> 2); + b[i] = (blue[i] << 10) | (blue[i] << 4) | (blue[i] >> 2); + t[i] = 0; + } + + cmap.start = 0; + cmap.len = 256; + cmap.red = r; + cmap.green = g; + cmap.blue = b; + cmap.transp = t; + + ioctl(fbdev_fd, FBIOPUTCMAP, &cmap); +} + +static int fbdev_setpalette(int index, int red, int green, int blue) +{ + uint16_t r, g, b, t; + struct fb_cmap cmap; + + if (fbdev_vgamode) + { + __svgalib_outpal(index,red,green,blue); + return 0; + } + + if(dacmode==8) { + r=red<<8; + g=green<<8; + b=blue<<8; + } else { + r = (red << 10) | (red << 4) | (red >> 2); + g = (green << 10) | (green << 4) | (green >> 2); + b = (blue << 10) | (blue << 4) | (blue >> 2); + } + t = 0; + + cmap.start = index; + cmap.len = 1; + cmap.red = &r; + cmap.green = &g; + cmap.blue = &b; + cmap.transp = &t; + ioctl(fbdev_fd, FBIOPUTCMAP, &cmap); + + return 0; +} + +static void fbdev_getpalette(int index, int *red, int *green, int *blue) +{ + uint16_t r, g, b, t; + struct fb_cmap cmap; + + if (fbdev_vgamode) + { + __svgalib_inpal(index,red,green,blue); + return; + } + + cmap.start = 0; + cmap.len = 1; + cmap.red = &r; + cmap.green = &g; + cmap.blue = &b; + cmap.transp = &t; + + if (ioctl(fbdev_fd, FBIOGETCMAP, &cmap)) + return; + + *red = r >> 10; + *green = g >> 10; + *blue = b >> 10; +} + +static void fbdev_savefont(void) +{ + fbdev_font.op = KD_FONT_OP_GET; + fbdev_font.flags = 0; + fbdev_font.width = 32; + fbdev_font.height = 32; + fbdev_font.charcount = 512; + fbdev_font.data = malloc(65536); + + ioctl(fbdev_fd, KDFONTOP, &fbdev_font); +} + +static void fbdev_restorefont(void) +{ + fbdev_font.op = KD_FONT_OP_SET; + + ioctl(fbdev_fd, KDFONTOP, &fbdev_font); +} + +/* Function tables */ + +static Emulation fbdev_vgaemul = +{ + fbdev_savepalette, + fbdev_restorepalette, + fbdev_setpalette, + fbdev_getpalette, + fbdev_savefont, + fbdev_restorefont, + 0, /* screenoff */ + 0, /* screenon */ + 0, /* waitretrace */ +}; + +DriverSpecs __svgalib_fbdev_driverspecs = +{ + fbdev_saveregs, + fbdev_setregs, + fbdev_unlock, + fbdev_lock, + fbdev_test, + fbdev_init, + fbdev_setpage, + 0, /* setrdpage */ + 0, /* setwrpage */ + fbdev_setmode, + fbdev_modeavailable, + fbdev_setdisplaystart, + fbdev_setlogicalwidth, + fbdev_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, /* accel */ + fbdev_linear, + 0, /* Accelspecs */ + &fbdev_vgaemul, + 0 /* cursor */ +}; + diff --git a/src/drivers/g400.c b/src/drivers/g400.c new file mode 100644 index 0000000..da04aae --- /dev/null +++ b/src/drivers/g400.c @@ -0,0 +1,915 @@ +/* +Matrox Mystique(1064)/G100/G200/G400/G450 chipset driver + +Based on the XFree86 (4.1.0) mga driver. + +Tested only on G450 and Mystique. + +TODO: SDRAM, reference frequency checking. + +*/ + +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "mga.h" +#define SECONDCRTC 0 +#include "mga_g450pll.c" +#include "vgammvgaio.h" + +#define SKREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define G400_TOTAL_REGS (VGA_TOTAL_REGS + 32 + 176 + 4 + 32) + +enum { ID_1064 = 0, ID_G100, ID_G200, ID_G400, ID_G450 }; + +static int g400_init(int, int, int); +static void g400_unlock(void); +static void g400_lock(void); + +static int g400_memory, id, g400_pciposition; +static unsigned int g400_linear_base, g400_mmio_base; + +static int HasSDRAM; + +static CardSpecs *cardspecs; + +static int g400_inExt(int i) { + v_writeb(i, 0x1fde); + return v_readb(0x1fdf); +} + +static void g400_outExt(int i, int d) { + v_writeb(i, 0x1fde); + v_writeb(d, 0x1fdf); +} + +static int g400_inDAC(int i) { + v_writeb(i, 0x3c00); + return v_readb(0x3c0a); +} + +static void g400_outDAC(int i, int d) { + v_writeb(i, 0x3c00); + v_writeb(d, 0x3c0a); +} + +static void inpal(int i, int *r, int *g, int *b) +{ + v_writeb(i, 0x3c03); + *r = v_readb(0x3c01); + *g = v_readb(0x3c01); + *b = v_readb(0x3c01); +} + +static void outpal(int i, int r, int g, int b) +{ + v_writeb(i, 0x3c00); + v_writeb(r, 0x3c01); + v_writeb(g, 0x3c01); + v_writeb(b, 0x3c01); +} + +static void g400_setpage(int page) +{ + g400_outExt(4,page); +} + +/* Fill in chipset specific mode information */ +static void g400_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = g400_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 8184; + modeinfo->startaddressrange = g400_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(g400_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ +static int g400_saveregs(unsigned char regs[]) +{ + int i; + unsigned int *iregs=(unsigned int *)(regs+VGA_TOTAL_REGS); + + g400_unlock(); + + iregs[4] = __svgalib_pci_read_config_dword(g400_pciposition, 0x40); + + if(id>ID_1064) iregs[5] = __svgalib_pci_read_config_dword(g400_pciposition, 0x50); + + if(id>=ID_G400) iregs[6] = __svgalib_pci_read_config_dword(g400_pciposition, 0x54); + + for(i=0;i<0xb0;i++) regs[VGA_TOTAL_REGS + 32 + i]=g400_inDAC(i); + for(i=0;i<9;i++) regs[VGA_TOTAL_REGS + i]=g400_inExt(i); + + regs[VGA_TOTAL_REGS + 15] = 1; + + iregs[7]=INREG(0x1e54); + iregs[52]=INREG(0x3c0c); + + iregs[53]=INREG(MGAREG_C2DATACTL); + iregs[54]=INREG(MGAREG_C2HPARAM); + iregs[55]=INREG(MGAREG_C2HSYNC); + iregs[56]=INREG(MGAREG_C2VPARAM); + iregs[57]=INREG(MGAREG_C2VSYNC); + iregs[58]=INREG(MGAREG_C2OFFSET); + iregs[59]=INREG(MGAREG_C2STARTADD0); + iregs[60]=INREG(MGAREG_C2CTL); + + return G400_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void g400_setregs(const unsigned char regs[], int mode) +{ + int i; + unsigned int t; + unsigned int *iregs=(unsigned int *)(regs+VGA_TOTAL_REGS); + +inrestore=1; + + g400_unlock(); + for(i=0;i<0x50;i++) { +#if 0 + if( (i> 0x03) && (i!=0x07) && (i!=0x0b) && (i!=0x0f) && + (i< 0x13) && (i> 0x17) && (i!=0x1b) && (i!=0x1c) && + (i< 0x1f) && (i> 0x29) && (i< 0x30) && (i> 0x37) && + (i!=0x39) && (i!=0x3b) && (i!=0x3f) && (i!=0x41) && + (i!=0x43) && (i!=0x47) && (i!=0x4b) + ) +#endif + if( (id!=ID_G450) || (regs[VGA_TOTAL_REGS + 15]) || (i<0x4c) || (i>0x4e) ) + g400_outDAC(i,regs[VGA_TOTAL_REGS + 32 + i]); + } + + t = __svgalib_pci_read_config_dword(g400_pciposition, 0x40); + t &= ~OPTION1_MASK; + t |= iregs[4]&OPTION1_MASK; + __svgalib_pci_write_config_dword(g400_pciposition, 0x40, t); + + if(id>ID_1064) { + t = __svgalib_pci_read_config_dword(g400_pciposition, 0x50); + t &= ~OPTION2_MASK; + t |= iregs[5]&OPTION2_MASK; + __svgalib_pci_write_config_dword(g400_pciposition, 0x50, t); + } + + if(id>=ID_G400) { + t = __svgalib_pci_read_config_dword(g400_pciposition, 0x54); + t &= ~OPTION3_MASK; + t |= iregs[6]&OPTION3_MASK; + __svgalib_pci_write_config_dword(g400_pciposition, 0x54, t); + } + + OUTREG(0x1e54, iregs[7]); + OUTREG(0x3c0c, iregs[52]); + + for(i=0;i<6;i++) g400_outExt(i, regs[VGA_TOTAL_REGS + i]); + +inrestore=0; + +} + + +/* Return nonzero if mode is available */ + +static int g400_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (g400_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +#define MGA_MIN_VCO_FREQ 50000 +#define MGA_MAX_VCO_FREQ 310000 + +static double +MGACalcClock (int f_out, + int *best_m, int *best_n, int *p, int *s ) +{ + int m, n; + double f_pll, f_vco; + double m_err, calc_f; + double ref_freq; + int feed_div_min, feed_div_max; + int in_div_min, in_div_max; + int post_div_max; + + switch( id ) + { + case ID_1064: + ref_freq = 14318.18; + feed_div_min = 100; + feed_div_max = 127; + in_div_min = 1; + in_div_max = 31; + post_div_max = 7; + break; + case ID_G400: + case ID_G450: + ref_freq = 27050.5; + feed_div_min = 7; + feed_div_max = 127; + in_div_min = 1; + in_div_max = 31; + post_div_max = 7; + break; + case ID_G100: + case ID_G200: + default: + if ( 0 /* pMga->Bios2.PinID && (pMga->Bios2.VidCtrl & 0x20) */ ) + ref_freq = 14318.18; + else + ref_freq = 27050.5; + feed_div_min = 7; + feed_div_max = 127; + in_div_min = 1; + in_div_max = 6; + post_div_max = 7; + break; + } + + /* Make sure that f_min <= f_out */ + if ( f_out < ( MGA_MIN_VCO_FREQ / 8)) + f_out = MGA_MIN_VCO_FREQ / 8; + + /* + * f_pll = f_vco / (p+1) + * Choose p so that MGA_MIN_VCO_FREQ <= f_vco <= MGA_MAX_VCO_FREQ + * we don't have to bother checking for this maximum limit. + */ + f_vco = ( double ) f_out; + for ( *p = 0; *p <= post_div_max && f_vco < MGA_MIN_VCO_FREQ; + *p = *p * 2 + 1, f_vco *= 2.0); + + /* Initial amount of error for frequency maximum */ + m_err = f_out; + + /* Search for the different values of ( m ) */ + for ( m = in_div_min ; m <= in_div_max ; m++ ) + { + /* see values of ( n ) which we can't use */ + for ( n = feed_div_min; n <= feed_div_max; n++ ) + { + calc_f = ref_freq * (n + 1) / (m + 1) ; + + /* + * Pick the closest frequency. + */ + if ( abs(calc_f - f_vco) < m_err ) { + m_err = abs(calc_f - f_vco); + *best_m = m; + *best_n = n; + } + } + } + + /* Now all the calculations can be completed */ + f_vco = ref_freq * (*best_n + 1) / (*best_m + 1); + + /* Adjustments for filtering pll feed back */ + if ( (50000.0 <= f_vco) && (f_vco < 100000.0) ) + *s = 0; else + if ( (100000.0 <= f_vco) && (f_vco < 140000.0) ) + *s = 1; else + if ( (140000.0 <= f_vco) && (f_vco < 180000.0) ) + *s = 2; else + *s = 3; + + f_pll = f_vco / ( *p + 1 ); + + return f_pll; +} + +static int MGASetPCLK(int f_out, unsigned char *initDAC ) +{ + /* Pixel clock values */ + int m, n, p, s; + + /* The actual frequency output by the clock */ + double f_pll; + + if(id==ID_G450) { + G450SetPLLFreq(f_out); + return 1; + } + + /* Do the calculations for m, n, p and s */ + f_pll = MGACalcClock(f_out, &m, &n, &p, &s ); + + /* Values for the pixel clock PLL registers */ + initDAC[ MGA1064_PIX_PLLC_M ] = m & 0x1F; + initDAC[ MGA1064_PIX_PLLC_N ] = n & 0x7F; + initDAC[ MGA1064_PIX_PLLC_P ] = (p & 0x07) | ((s & 0x03) << 3); + + return 0; +} + + +static void g400_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + const static unsigned char initDac[] = { + /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, + /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20, + /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40, + /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83, + /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A, + /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 + }; + unsigned char initDAC[0x50]; + int hd, hs, he, ht, vd, vs, ve, vt, wd; + int i; + int weight555 = 0; + int MGABppShft = 0; + + memcpy(initDAC, initDac, 0x50); + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + switch(id) + { + case ID_1064: + initDAC[ MGA1064_SYS_PLL_M ] = 0x04; + initDAC[ MGA1064_SYS_PLL_N ] = 0x44; + initDAC[ MGA1064_SYS_PLL_P ] = 0x18; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) = 0x5F094F21; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 4) = 0x00000000; + break; + case ID_G100: + initDAC[ MGAGDAC_XVREFCTRL ] = 0x03; + if(HasSDRAM) { + initDAC[ MGA1064_SYS_PLL_M ] = 0x01; + initDAC[ MGA1064_SYS_PLL_N ] = 0x0E; + initDAC[ MGA1064_SYS_PLL_P ] = 0x18; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) = 0x404991a9; + } else { + initDAC[ MGA1064_SYS_PLL_M ] = 0x04; + initDAC[ MGA1064_SYS_PLL_N ] = 0x16; + initDAC[ MGA1064_SYS_PLL_P ] = 0x08; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) = 0x4049d121; + } + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 4) = 0x0000007; + break; + case ID_G400: + if( 0 /* pMga->Dac.maxPixelClock == 360000 */) { /* G400 MAX */ + initDAC[ MGA1064_SYS_PLL_M ] = 0x02; + initDAC[ MGA1064_SYS_PLL_N ] = 0x1B; + initDAC[ MGA1064_SYS_PLL_P ] = 0x18; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 8) = 0x019B8419; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) = 0x5053C120; + } else { + initDAC[ MGA1064_SYS_PLL_M ] = 0x13; + initDAC[ MGA1064_SYS_PLL_N ] = 0x7A; + initDAC[ MGA1064_SYS_PLL_P ] = 0x08; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 8) = 0x0190a421; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) = 0x50044120; + } + if(HasSDRAM) + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) &= ~(1 << 14); + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 4) = 0x01003000; + break; + case ID_G450: + initDAC[ 0x2c ] = 0x05; + initDAC[ 0x2d ] = 0x23; + initDAC[ 0x2e ] = 0x40; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 0) = 0x40341160; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 4) = 0x01003000; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 8) = 0x0190a421; + if(!HasSDRAM) + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 0) |= (1 << 14); + break; + case ID_G200: + default: + initDAC[ MGA1064_SYS_PLL_M ] = 0x04; + initDAC[ MGA1064_SYS_PLL_N ] = 0x18; + initDAC[ MGA1064_SYS_PLL_P ] = 0x08; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 4) = 0x00008000; + if(HasSDRAM) + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) = 0x40499121; + else + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) = 0x4049cd21; + break; + } + + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16) &= ~0x20000000; + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 12)=INREG(0x1e54); + + switch(modeinfo->bitsPerPixel) + { + case 8: + initDAC[ 0x19 ] = 0; + initDAC[ 0x1e ] &= ~8; + MGABppShft=0; + break; + case 15: + case 16: + initDAC[ 0x19 ] = 2; + MGABppShft=1; + if ( modeinfo->greenWeight==5 ) { + weight555 = 1; + initDAC[ 0x19 ] = 1; + } +#if __BYTE_ORDER == __BIG_ENDIAN + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 12) &= ~0x300; + /* the aperture is little endian */ + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 12) |= 0x100; +#endif + break; + case 24: + MGABppShft=0; + initDAC[ 0x19 ] = 3; + break; + case 32: + MGABppShft=2; + initDAC[ 0x19 ] = 7; +#if __BYTE_ORDER == __BIG_ENDIAN + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 12) &= ~0x300; + /* the aperture is little endian */ + *(unsigned int *)(moderegs + VGA_TOTAL_REGS + 16 + 12) |= 0x200; +#endif + break; + } + + /* + * Here all of the other fields of 'newVS' get filled in. + */ + hd = (modetiming->CrtcHDisplay >> 3) - 1; + hs = (modetiming->CrtcHSyncStart>> 3) - 1; + he = (modetiming->CrtcHSyncEnd >> 3) - 1; + ht = (modetiming->CrtcHTotal >> 3) - 1; + vd = modetiming->CrtcVDisplay - 1; + vs = modetiming->CrtcVSyncStart - 1; + ve = modetiming->CrtcVSyncEnd - 1; + vt = modetiming->CrtcVTotal - 2; + + /* HTOTAL & 0xF equal to 0xE in 8bpp or 0x4 in 24bpp causes strange + * vertical stripes + */ + if((ht & 0x0F) == 0x0E || (ht & 0x0F) == 0x04) + ht++; + + if (modeinfo->bitsPerPixel == 24) + wd = (modeinfo->width * 3) >> (4 - MGABppShft); + else + wd = modeinfo->width >> (4 - MGABppShft); + + moderegs[VGA_TOTAL_REGS + 0] = 0; + moderegs[VGA_TOTAL_REGS + 5] = 0; + + if (modetiming->flags & INTERLACED) + { + moderegs[VGA_TOTAL_REGS + 0] = 0x80; + moderegs[VGA_TOTAL_REGS + 5] = (hs + he - ht) >> 1; + wd <<= 1; + vt &= 0xFFFE; + } + + moderegs[VGA_TOTAL_REGS + 0] |= (wd & 0x300) >> 4; + moderegs[VGA_TOTAL_REGS + 1] = (((ht - 4) & 0x100) >> 8) | + ((hd & 0x100) >> 7) | + ((hs & 0x100) >> 6) | + (ht & 0x40); + moderegs[VGA_TOTAL_REGS + 2] = ((vt & 0x400) >> 10) | + ((vt & 0x800) >> 10) | + ((vd & 0x400) >> 8) | + ((vd & 0x400) >> 7) | + ((vd & 0x800) >> 7) | + ((vs & 0x400) >> 5) | + ((vs & 0x800) >> 5); + if (modeinfo->bitsPerPixel == 24) + moderegs[VGA_TOTAL_REGS + 3] = (((1 << MGABppShft) * 3) - 1) | 0x80; + else + moderegs[VGA_TOTAL_REGS + 3] = ((1 << MGABppShft) - 1) | 0x80; + + moderegs[VGA_TOTAL_REGS + 3] &= 0xE7; /* ajv - bits 4-5 MUST be 0 or bad karma happens */ + + moderegs[VGA_TOTAL_REGS + 4] = 0; + + moderegs[0] = ht - 4; + moderegs[1] = hd; + moderegs[2] = hd; + moderegs[3] = (ht & 0x1F) | 0x80; + moderegs[4] = hs; + moderegs[5] = ((ht & 0x20) << 2) | (he & 0x1F); + moderegs[6] = vt & 0xFF; + moderegs[7] = ((vt & 0x100) >> 8 ) | + ((vd & 0x100) >> 7 ) | + ((vs & 0x100) >> 6 ) | + ((vd & 0x100) >> 5 ) | + 0x10 | + ((vt & 0x200) >> 4 ) | + ((vd & 0x200) >> 3 ) | + ((vs & 0x200) >> 2 ); + moderegs[9] = ((vd & 0x200) >> 4) | 0x40; + moderegs[16] = vs & 0xFF; + moderegs[17] = (ve & 0x0F) | 0x20; + moderegs[18] = vd & 0xFF; + moderegs[19] = wd & 0xFF; + moderegs[21] = vd & 0xFF; + moderegs[22] = (vt + 1) & 0xFF; + + if (modetiming->flags & DOUBLESCAN) + moderegs[9] |= 0x80; + + moderegs[59] |= 0x0C; + + if(id==ID_G450) OUTREG(MGAREG_ZORG, 0); + + if(MGASetPCLK( modetiming->pixelClock , initDAC)) + moderegs[VGA_TOTAL_REGS + 15] = 0; + + for (i = 0; i < sizeof(initDAC); i++) + { + moderegs[VGA_TOTAL_REGS + 32 + i] = initDAC[i]; + } + + return ; +} + + +static int g400_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + int i; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!g400_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(G400_TOTAL_REGS); + + g400_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + + g400_setregs(moderegs, mode); /* Set extended regs. */ + + if(mode>=G640x480x256) + switch(modeinfo->bitsPerPixel) { + case 16: + for(i=0;i<256;i++) outpal(i,i<<3,i<<(8-modeinfo->greenWeight),i<<3); + break; + case 24: + case 32: + for(i=0;i<256;i++) outpal(i,i,i,i); + break; + } + + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void g400_unlock(void) +{ + __svgalib_outcrtc(0x11, __svgalib_incrtc(0x11) &0x7f); + g400_outExt(3, g400_inExt(3) & 0x7f); +} + +static void g400_lock(void) +{ + __svgalib_outcrtc(0x11, __svgalib_incrtc(0x11)&0x7f); + g400_outExt(3, g400_inExt(3) | 0x80); +} + + +#define VENDOR_ID 0x102b + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int g400_test(void) +{ + int found, id; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if(!found) return 0; + + id=(buf[0]>>16)&0xffff; + + if((id==0x51a)||(id==0x51e)||(id==0x520)||(id==0x521)||(id==0x525)||(id==0x1000)||(id==0x1001) + ||(id==0x2527) ){ + g400_init(0,0,0); + return 1; + }; + return 0; +} + + +/* Set display start address (not for 16 color modes) */ + +static void g400_setdisplaystart(int address) +{ + address=address >> 3; + __svgalib_outcrtc(0x0c, (address & 0xFF00)>>8); + __svgalib_outcrtc(0x0d, address & 0x00FF); + g400_outExt(0, (g400_inExt(0)&0xb0) | ((address&0xf0000)>>16) | ((address&0x100000)>>14)); +} + + +/* Set logical scanline length (usually multiple of 8) */ + +static void g400_setlogicalwidth(int width) +{ + int offset = width >> 4; + + __svgalib_outcrtc(0x13,offset&0xff); + g400_outExt(0,(g400_inExt(0)&0xcf) | ((offset&0x300)>>4)); +} + +static int g400_linear(int op, int param) +{ + if (op==LINEAR_ENABLE || op==LINEAR_DISABLE) return 0; + if (op==LINEAR_QUERY_BASE) return g400_linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int g400_match_programmable_clock(int clock) +{ +return clock ; +} + +static int g400_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int g400_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +static unsigned int cur_colors[16*2]; + +static int g400_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j; + unsigned char *b3; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + g400_outDAC(6,0); + break; + case CURSOR_SHOW: + g400_outDAC(6,3); + break; + case CURSOR_POSITION: + p1+=64; + p2+=64; + *(MMIO_POINTER + 0x3c0c) = p1&0xff; + *(MMIO_POINTER + 0x3c0d) = (p1>>8)&0x0f; + *(MMIO_POINTER + 0x3c0e) = p2&0xff; + *(MMIO_POINTER + 0x3c0f) = (p2>>8)&0x0f; + break; + case CURSOR_SELECT: + i=g400_memory*1024-(p1+1)*4096; + while(i>16384*1024)i-=8192*1024; + g400_outDAC(4,(i>>10)&0xff); + g400_outDAC(5,(i>>18)&0x3f); + + g400_outDAC(8, (cur_colors[p1*2]>>16)&0xff); + g400_outDAC(9, (cur_colors[p1*2]>>8)&0xff); + g400_outDAC(10, cur_colors[p1*2]&0xff); + g400_outDAC(12,(cur_colors[p1*2+1]>>16)&0xff); + g400_outDAC(13,(cur_colors[p1*2+1]>>8)&0xff); + g400_outDAC(14, cur_colors[p1*2+1]&0xff); + break; + case CURSOR_IMAGE: + i=g400_memory*1024-(p1+1)*4096; + while(i>16384*1024)i-=8192*1024; + b3=(unsigned char *)p5; + switch(p2) { + case 0: + cur_colors[p1*2]=p3; + cur_colors[p1*2+1]=p4; + for(j=0;j<32;j++) { + *(LINEAR_POINTER+i+16*j)=0; + *(LINEAR_POINTER+i+16*j+1)=0; + *(LINEAR_POINTER+i+16*j+2)=0; + *(LINEAR_POINTER+i+16*j+3)=0; + *(LINEAR_POINTER+i+16*j+4)=*(b3+4*j+0); + *(LINEAR_POINTER+i+16*j+5)=*(b3+4*j+1); + *(LINEAR_POINTER+i+16*j+6)=*(b3+4*j+2); + *(LINEAR_POINTER+i+16*j+7)=*(b3+4*j+3); + *(LINEAR_POINTER+i+16*j+8)=0; + *(LINEAR_POINTER+i+16*j+9)=0; + *(LINEAR_POINTER+i+16*j+10)=0; + *(LINEAR_POINTER+i+16*j+11)=0; + *(LINEAR_POINTER+i+16*j+12)=*(b3+4*j+128+0); + *(LINEAR_POINTER+i+16*j+13)=*(b3+4*j+128+1); + *(LINEAR_POINTER+i+16*j+14)=*(b3+4*j+128+2); + *(LINEAR_POINTER+i+16*j+15)=*(b3+4*j+128+3); + } + memset(LINEAR_POINTER+i+512,0,512); + break; + } + break; + default: + return -1; + } + return 0; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_g400_driverspecs = +{ + g400_saveregs, + g400_setregs, + g400_unlock, + g400_lock, + g400_test, + g400_init, + g400_setpage, + NULL, + NULL, + g400_setmode, + g400_modeavailable, + g400_setdisplaystart, + g400_setlogicalwidth, + g400_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + g400_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + g400_cursor, +}; + +/* Initialize chipset (called after detection) */ + +static int g400_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + int pci_id; + int max_mem = 8; + char *ids[]={"Mystique", "G100", "G200", "G400", "G450"}; + + if (force) { + g400_memory = par1; + } else { + g400_memory = 0; + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if(!found) { + fprintf(stderr,"Error: Must use Matrox driver, but no card found\n"); + exit(1); + } + + g400_pciposition=found; + pci_id=(buf[0]>>16)&0xffff; + + switch(pci_id) { + case 0x525: + if((buf[11]&0xffff0000) == 0x07c00000) + id = ID_G450; else id = ID_G400; + max_mem=32; + break; + case 0x520: + case 0x521: + id = ID_G200; + max_mem=16; + break; + case 0x51a: + case 0x51e: + id = ID_1064; + break; + case 0x2527: + id = ID_G450; + default: + id = ID_G100; + } + + g400_linear_base = buf[4]&0xffffff00; + g400_mmio_base = buf[5]&0xffffff00; + + if(id == ID_1064){ + if(__svgalib_pci_read_aperture_len(g400_pciposition, 0) < 1024*1024) { + g400_linear_base = buf[5]&0xffffff00; + g400_mmio_base = buf[4]&0xffffff00; + } + } + + __svgalib_mmio_base=g400_mmio_base; + __svgalib_mmio_size=16384; + map_mmio(); + __svgalib_vgammbase = 0x1c00; + __svgalib_mm_io_mapio(); + + if(!g400_memory) { + __svgalib_linear_mem_base=g400_linear_base; + __svgalib_linear_mem_size=max_mem*1024*1024; + map_linear(0); + g400_memory=memorytest((uint32_t *)LINEAR_POINTER,max_mem); + unmap_linear(); + } + + __svgalib_inpal=inpal; + __svgalib_outpal=outpal; + + HasSDRAM=(buf[0x10]&(1<<14))?0:1; + + if (__svgalib_driver_report) { + fprintf(stderr,"Using Matrox %s driver, %iKB S%cRAM.\n",ids[id], + g400_memory, HasSDRAM?'D':'G'); + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = g400_memory; + cardspecs->maxPixelClock4bpp = 75000; + switch(id) { + default: + cardspecs->maxPixelClock8bpp = 250000; + cardspecs->maxPixelClock16bpp = 250000; + cardspecs->maxPixelClock24bpp = 250000; + cardspecs->maxPixelClock32bpp = 250000; + break; + } + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4095; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = g400_map_clock; + cardspecs->mapHorizontalCrtc = g400_map_horizontal_crtc; + cardspecs->matchProgrammableClock=g400_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_g400_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=g400_linear_base; + __svgalib_linear_mem_size=g400_memory*0x400; + __svgalib_mmio_base=g400_mmio_base; + __svgalib_mmio_size=16384; + return 0; +} diff --git a/src/drivers/g450c2.c b/src/drivers/g450c2.c new file mode 100644 index 0000000..eaeea69 --- /dev/null +++ b/src/drivers/g450c2.c @@ -0,0 +1,362 @@ +/* +Matrox Mystique(1064)/G100/G200/G400/G450 chipset driver + +Based on the XFree86 (4.1.0) mga driver. + +Tested only on G450 and Mystique. + + +*/ + +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "mga.h" +#define SECONDCRTC 1 +#include "mga_g450pll.c" +#include "vgammvgaio.h" + +#define SKREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define TOTAL_REGS (100) + +static int init(int, int, int); +static void unlock(void); +static void lock(void); + +static int memory, pciposition; +static unsigned int linear_base, mmio_base; + +static CardSpecs *cardspecs; + +static int inDAC(int i) { + *(MMIO_POINTER + 0x3c00) = i; + return *(MMIO_POINTER + 0x3c0a); +} + +static void outDAC(int i, int d) { + *(MMIO_POINTER + 0x3c00) = i; + *(MMIO_POINTER + 0x3c0a) = d; +} + +/* Fill in chipset specific mode information */ +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 8184; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ +static int saveregs(unsigned char regs[]) +{ + int i; + unsigned int *iregs=(unsigned int *)regs; + unlock(); + + for(i=0;i<0x22;i++) regs[i]=inDAC(i+0x80); + + iregs[9]=INREG(MGAREG_C2CTL); + iregs[10]=INREG(MGAREG_C2DATACTL); + iregs[11]=INREG(MGAREG_C2HPARAM); + iregs[12]=INREG(MGAREG_C2HSYNC); + iregs[13]=INREG(MGAREG_C2VPARAM); + iregs[14]=INREG(MGAREG_C2VSYNC); + iregs[15]=INREG(MGAREG_C2OFFSET); + iregs[16]=INREG(MGAREG_C2STARTADD0); + + return 40; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + int i; + unsigned int *iregs=(unsigned int *)regs; + unlock(); + + for(i=0;i<0x22;i++) outDAC(i+0x80,regs[i]); + + OUTREG(MGAREG_C2CTL,iregs[9]); + OUTREG(MGAREG_C2DATACTL,iregs[10]); + OUTREG(MGAREG_C2HPARAM,iregs[11]); + OUTREG(MGAREG_C2HSYNC,iregs[12]); + OUTREG(MGAREG_C2VPARAM,iregs[13]); + OUTREG(MGAREG_C2VSYNC,iregs[14]); + OUTREG(MGAREG_C2OFFSET,iregs[15]); + OUTREG(MGAREG_C2STARTADD0,iregs[16]); + +} + + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return 0; + + info = &__svgalib_infotable[mode]; + + if((info->colors==16) || (info->colors==256))return 0; + + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +static void initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + unsigned int *iregs=(unsigned int *)moderegs; + + float f_out; + + + G450SetPLLFreq(f_out); + + return ; +} + + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + int i; + + if (!modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + + setregs(moderegs, mode); /* Set extended regs. */ + + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ +} + +static void lock(void) +{ +} + + +#define VENDOR_ID 0x102b + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + int found, id; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if(!found) return 0; + + id=(buf[0]>>16)&0xffff; + + if((id==0x51a)||(id==0x51e)||(id==0x520)||(id==0x521)||(id==0x525)||(id==0x1000)||(id==0x1001)){ + init(0,0,0); + return 1; + }; + return 0; +} + + +/* Set display start address (not for 16 color modes) */ + +static void setdisplaystart(int address) +{ +} + + +/* Set logical scanline length (usually multiple of 8) */ + +static void setlogicalwidth(int width) +{ +} + +static int linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ return 0;}; + if (op==LINEAR_DISABLE){ return 0;}; + if (op==LINEAR_QUERY_BASE) return linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} + +static int map_clock(int bpp, int clock) +{ +return clock ; +} + +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_g450c2_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + NULL, + NULL, + NULL, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + NULL, +}; + +/* Initialize chipset (called after detection) */ + +static int init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + int pci_id; + int max_mem = 8; + + if (force) { + memory = par1; + } else { + memory = 0; + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if(!found) { + fprintf(stderr,"Error: Must use Matrox driver, but no card found\n"); + exit(1); + } + + pciposition=found; + pci_id=(buf[0]>>16)&0xffff; + + switch(pci_id) { + case 0x525: + if((buf[11]&0xffff0000) != 0x07c00000) exit(1); + break; + default: + exit(1); + } + + linear_base = buf[4]&0xffffff00; + mmio_base = buf[5]&0xffffff00; + + if(!memory) { + memory=2048; + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using Matrox G450 CRTC2 driver, %iKB RAM.\n", memory); + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = 0; + cardspecs->maxPixelClock16bpp = 250000; + cardspecs->maxPixelClock24bpp = 250000; + cardspecs->maxPixelClock32bpp = 250000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4095; + cardspecs->nClocks =0; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_g450c2_driverspecs; + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=0; + __svgalib_mmio_base=mmio_base; + __svgalib_mmio_size=16384; + __svgalib_novga=1; + __svgalib_emulatepage=2; + return 0; +} diff --git a/src/drivers/glint_regs.h b/src/drivers/glint_regs.h new file mode 100644 index 0000000..f436d78 --- /dev/null +++ b/src/drivers/glint_regs.h @@ -0,0 +1,1322 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/glint_regs.h,v 1.31 2001/12/08 16:01:52 alanh Exp $ */ + +/* + * glint register file + * + * Copyright by Stefan Dirsch, Dirk Hohndel, Alan Hourihane + * Authors: Alan Hourihane, + * Dirk Hohndel, + * Stefan Dirsch, + * Simon P., + * + * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and + * Siemens Nixdorf Informationssysteme + * + */ + +/* Device Identification */ +#define CFGVendorId 0x0000 +#define PCI_VENDOR_3DLABS 0x3D3D +#define PCI_VENDOR_TI 0x104C +#define CFGDeviceId 0x0002 + +#define CFGRevisionId 0x08 +#define CFGClassCode 0x09 +#define CFGHeaderType 0x0E + +/* Device Control/Status */ +#define CFGCommand 0x04 +#define CFGStatus 0x06 + +/* Miscellaneous Functions */ +#define CFGBist 0x0f +#define CFGLatTimer 0x0d +#define CFGCacheLine 0x0c +#define CFGMaxLat 0x3f +#define CFGMinGrant 0x3e +#define CFGIntPin 0x3d +#define CFGIntLine 0x3c + +/* Base Adresses */ +#define CFGBaseAddr0 0x10 +#define CFGBaseAddr1 0x14 +#define CFGBaseAddr2 0x18 +#define CFGBaseAddr3 0x1C +#define CFGBaseAddr4 0x20 +#define CFGRomAddr 0x30 + + + +/********************************** + * GLINT 500TX Region 0 Registers * + **********************************/ + +/* Control Status Registers */ +#define ResetStatus 0x0000 +#define IntEnable 0x0008 +#define IntFlags 0x0010 +#define InFIFOSpace 0x0018 +#define OutFIFOWords 0x0020 +#define DMAAddress 0x0028 +#define DMACount 0x0030 +#define ErrorFlags 0x0038 +#define VClkCtl 0x0040 +#define TestRegister 0x0048 +#define Aperture0 0x0050 +#define Aperture1 0x0058 +#define DMAControl 0x0060 +#define FIFODis 0x0068 + +/* GLINT PerMedia Region 0 additional Registers */ +#define ChipConfig 0x0070 +#define SCLK_SEL_MASK (3 << 10) +#define SCLK_SEL_MCLK_HALF (3 << 10) +#define ByDMAControl 0x00D8 + +/* GLINT 500TX LocalBuffer Registers */ +#define LBMemoryCtl 0x1000 +#define LBNumBanksMask 0x00000001 +#define LBNumBanks1 (0) +#define LBNumBanks2 (1) +#define LBPageSizeMask 0x00000006 +#define LBPageSize256 (0<<1) +#define LBPageSize512 (1<<1) +#define LBPageSize1024 (2<<1) +#define LBPageSize2048 (3<<1) +#define LBRASCASLowMask 0x00000018 +#define LBRASCASLow2 (0<<3) +#define LBRASCASLow3 (1<<3) +#define LBRASCASLow4 (2<<3) +#define LBRASCASLow5 (3<<3) +#define LBRASPrechargeMask 0x00000060 +#define LBRASPrecharge2 (0<<5) +#define LBRASPrecharge3 (1<<5) +#define LBRASPrecharge4 (2<<5) +#define LBRASPrecharge5 (3<<5) +#define LBCASLowMask 0x00000180 +#define LBCASLow1 (0<<7) +#define LBCASLow2 (1<<7) +#define LBCASLow3 (2<<7) +#define LBCASLow4 (3<<7) +#define LBPageModeMask 0x00000200 +#define LBPageModeEnabled (0<<9) +#define LBPageModeDisabled (1<<9) +#define LBRefreshCountMask 0x0003fc00 +#define LBRefreshCountShift 10 + +#define LBMemoryEDO 0x1008 +#define LBEDOMask 0x00000001 +#define LBEDODisabled (0) +#define LBEDOEnabled (1) +#define LBEDOBankSizeMask 0x0000000e +#define LBEDOBankSizeDiabled (0<<1) +#define LBEDOBankSize256K (1<<1) +#define LBEDOBankSize512K (2<<1) +#define LBEDOBankSize1M (3<<1) +#define LBEDOBankSize2M (4<<1) +#define LBEDOBankSize4M (5<<1) +#define LBEDOBankSize8M (6<<1) +#define LBEDOBankSize16M (7<<1) +#define LBTwoPageDetectorMask 0x00000010 +#define LBSinglePageDetector (0<<4) +#define LBTwoPageDetector (1<<4) + +/* GLINT PerMedia Memory Control Registers */ +#define PMReboot 0x1000 +#define PMRomControl 0x1040 +#define PMBootAddress 0x1080 +#define PMMemConfig 0x10C0 + #define RowCharge8 1 << 10 + #define TimeRCD8 1 << 7 + #define TimeRC8 0x6 << 3 + #define TimeRP8 1 + #define CAS3Latency8 0 << 16 + #define BootAdress8 0x10 + #define NumberBanks8 0x3 << 29 + #define RefreshCount8 0x41 << 21 + #define TimeRASMin8 1 << 13 + #define DeadCycle8 1 << 17 + #define BankDelay8 0 << 18 + #define Burst1Cycle8 1 << 31 + #define SDRAM8 0 << 4 + + #define RowCharge6 1 << 10 + #define TimeRCD6 1 << 7 + #define TimeRC6 0x6 << 3 + #define TimeRP6 0x2 + #define CAS3Latency6 1 << 16 + #define BootAdress6 0x60 + #define NumberBanks6 0x2 << 29 + #define RefreshCount6 0x41 << 21 + #define TimeRASMin6 1 << 13 + #define DeadCycle6 1 << 17 + #define BankDelay6 0 << 18 + #define Burst1Cycle6 1 << 31 + #define SDRAM6 0 << 4 + + #define RowCharge4 0 << 10 + #define TimeRCD4 0 << 7 + #define TimeRC4 0x4 << 3 + #define TimeRP4 1 + #define CAS3Latency4 0 << 16 + #define BootAdress4 0x10 + #define NumberBanks4 1 << 29 + #define RefreshCount4 0x30 << 21 + #define TimeRASMin4 1 << 13 + #define DeadCycle4 0 << 17 + #define BankDelay4 0 << 18 + #define Burst1Cycle4 1 << 31 + #define SDRAM4 0 << 4 + +/* Permedia 2 Control */ +#define MemControl 0x1040 + +#define PMBypassWriteMask 0x1100 +#define PMFramebufferWriteMask 0x1140 +#define PMCount 0x1180 + +/* Framebuffer Registers */ +#define FBMemoryCtl 0x1800 +#define FBModeSel 0x1808 +#define FBGCWrMask 0x1810 +#define FBGCColorLower 0x1818 +#define FBTXMemCtl 0x1820 +#define FBWrMaskk 0x1830 +#define FBGCColorUpper 0x1838 + +/* Core FIFO */ +#define OutputFIFO 0x2000 + +/* 500TX Internal Video Registers */ +#define VTGHLimit 0x3000 +#define VTGHSyncStart 0x3008 +#define VTGHSyncEnd 0x3010 +#define VTGHBlankEnd 0x3018 +#define VTGVLimit 0x3020 +#define VTGVSyncStart 0x3028 +#define VTGVSyncEnd 0x3030 +#define VTGVBlankEnd 0x3038 +#define VTGHGateStart 0x3040 +#define VTGHGateEnd 0x3048 +#define VTGVGateStart 0x3050 +#define VTGVGateEnd 0x3058 +#define VTGPolarity 0x3060 +#define VTGFrameRowAddr 0x3068 +#define VTGVLineNumber 0x3070 +#define VTGSerialClk 0x3078 +#define VTGModeCtl 0x3080 + +/* Permedia Video Control Registers */ +#define PMScreenBase 0x3000 +#define PMScreenStride 0x3008 +#define PMHTotal 0x3010 +#define PMHgEnd 0x3018 +#define PMHbEnd 0x3020 +#define PMHsStart 0x3028 +#define PMHsEnd 0x3030 +#define PMVTotal 0x3038 +#define PMVbEnd 0x3040 +#define PMVsStart 0x3048 +#define PMVsEnd 0x3050 +#define PMVideoControl 0x3058 +#define PMInterruptLine 0x3060 +#define PMDDCData 0x3068 +#define DataIn (1<<0) +#define ClkIn (1<<1) +#define DataOut (1<<2) +#define ClkOut (1<<3) +#define PMLineCount 0x3070 +#define PMFifoControl 0x3078 + +/* Permedia 2 RAMDAC Registers */ +#define PM2DACWriteAddress 0x4000 +#define PM2DACIndexReg 0x4000 +#define PM2DACData 0x4008 +#define PM2DACReadMask 0x4010 +#define PM2DACReadAddress 0x4018 +#define PM2DACCursorColorAddress 0x4020 +#define PM2DACCursorColorData 0x4028 +#define PM2DACIndexData 0x4050 +#define PM2DACCursorData 0x4058 +#define PM2DACCursorXLsb 0x4060 +#define PM2DACCursorXMsb 0x4068 +#define PM2DACCursorYLsb 0x4070 +#define PM2DACCursorYMsb 0x4078 +#define PM2DACCursorControl 0x06 +#define PM2DACIndexCMR 0x18 +#define PM2DAC_TRUECOLOR 0x80 +#define PM2DAC_RGB 0x20 +#define PM2DAC_GRAPHICS 0x10 +#define PM2DAC_PACKED 0x09 +#define PM2DAC_8888 0x08 +#define PM2DAC_565 0x06 +#define PM2DAC_4444 0x05 +#define PM2DAC_5551 0x04 +#define PM2DAC_2321 0x03 +#define PM2DAC_2320 0x02 +#define PM2DAC_332 0x01 +#define PM2DAC_CI8 0x00 +#define PM2DACIndexMDCR 0x19 +#define PM2DACIndexPalettePage 0x1c +#define PM2DACIndexMCR 0x1e +#define PM2DACIndexClockAM 0x20 +#define PM2DACIndexClockAN 0x21 +#define PM2DACIndexClockAP 0x22 +#define PM2DACIndexClockBM 0x23 +#define PM2DACIndexClockBN 0x24 +#define PM2DACIndexClockBP 0x25 +#define PM2DACIndexClockCM 0x26 +#define PM2DACIndexClockCN 0x27 +#define PM2DACIndexClockCP 0x28 +#define PM2DACIndexClockStatus 0x29 +#define PM2DACIndexMemClockM 0x30 +#define PM2DACIndexMemClockN 0x31 +#define PM2DACIndexMemClockP 0x32 +#define PM2DACIndexMemClockStatus 0x33 +#define PM2DACIndexColorKeyControl 0x40 +#define PM2DACIndexColorKeyOverlay 0x41 +#define PM2DACIndexColorKeyRed 0x42 +#define PM2DACIndexColorKeyGreen 0x43 +#define PM2DACIndexColorKeyBlue 0x44 + +/* Permedia 2V extensions */ +#define PM2VDACRDMiscControl 0x000 +#define PM2VDACRDSyncControl 0x001 +#define PM2VDACRDDACControl 0x002 +#define PM2VDACRDPixelSize 0x003 +#define PM2VDACRDColorFormat 0x004 +#define PM2VDACRDCursorMode 0x005 +#define PM2VDACRDCursorXLow 0x007 +#define PM2VDACRDCursorXHigh 0x008 +#define PM2VDACRDCursorYLow 0x009 +#define PM2VDACRDCursorYHigh 0x00A +#define PM2VDACRDCursorHotSpotX 0x00B +#define PM2VDACRDCursorHotSpotY 0x00C +#define PM2VDACRDOverlayKey 0x00D +#define PM2VDACRDPan 0x00E +#define PM2VDACRDSense 0x00F +#define PM2VDACRDCheckControl 0x018 +#define PM2VDACIndexClockControl 0x200 +#define PM2VDACRDDClk0PreScale 0x201 +#define PM2VDACRDDClk0FeedbackScale 0x202 +#define PM2VDACRDDClk0PostScale 0x203 +#define PM2VDACRDDClk1PreScale 0x204 +#define PM2VDACRDDClk1FeedbackScale 0x205 +#define PM2VDACRDDClk1PostScale 0x206 +#define PM2VDACRDMClkControl 0x20D +#define PM2VDACRDMClkPreScale 0x20E +#define PM2VDACRDMClkFeedbackScale 0x20F +#define PM2VDACRDMClkPostScale 0x210 +#define PM2VDACRDCursorPalette 0x303 +#define PM2VDACRDCursorPattern 0x400 +#define PM2VDACIndexRegLow 0x4020 +#define PM2VDACIndexRegHigh 0x4028 +#define PM2VDACIndexData 0x4030 +#define PM2VDACRDIndexControl 0x4038 + +/* Permedia 2 Video Streams Unit Registers */ +#define VSBIntFlag (1<<8) +#define VSAIntFlag (1<<9) + +#define VSConfiguration 0x5800 +#define VS_UnitMode_ROM 0 +#define VS_UnitMode_AB8 3 +#define VS_UnitMode_Mask 7 +#define VS_GPBusMode_A (1<<3) +#define VS_HRefPolarityA (1<<9) +#define VS_VRefPolarityA (1<<10) +#define VS_VActivePolarityA (1<<11) +#define VS_UseFieldA (1<<12) +#define VS_FieldPolarityA (1<<13) +#define VS_FieldEdgeA (1<<14) +#define VS_VActiveVBIA (1<<15) +#define VS_InterlaceA (1<<16) +#define VS_ReverseDataA (1<<17) +#define VS_HRefPolarityB (1<<18) +#define VS_VRefPolarityB (1<<19) +#define VS_VActivePolarityB (1<<20) +#define VS_UseFieldB (1<<21) +#define VS_FieldPolarityB (1<<22) +#define VS_FieldEdgeB (1<<23) +#define VS_VActiveVBIB (1<<24) +#define VS_InterlaceB (1<<25) +#define VS_ColorSpaceB_RGB (1<<26) +#define VS_ReverseDataB (1<<27) +#define VS_DoubleEdgeB (1<<28) + +#define VSStatus 0x5808 +#define VS_FieldOne0A (1<<9) +#define VS_FieldOne1A (1<<10) +#define VS_FieldOne2A (1<<11) +#define VS_InvalidInterlaceA (1<<12) +#define VS_FieldOne0B (1<<17) +#define VS_FieldOne1B (1<<18) +#define VS_FieldOne2B (1<<19) +#define VS_InvalidInterlaceB (1<<20) + +#define VSSerialBusControl 0x5810 + +#define VSABase 0x5900 +#define VSA_Video (1<<0) +#define VSA_VBI (1<<1) +#define VSA_BufferCtl (1<<2) +#define VSA_MirrorX (1<<7) +#define VSA_MirrorY (1<<8) +#define VSA_Discard_None (0<<9) +#define VSA_Discard_FieldOne (1<<9) +#define VSA_Discard_FieldTwo (2<<9) +#define VSA_CombineFields (1<<11) +#define VSA_LockToStreamB (1<<12) +#define VSBBase 0x5A00 +#define VSB_Video (1<<0) +#define VSB_VBI (1<<1) +#define VSB_BufferCtl (1<<2) +#define VSB_CombineFields (1<<3) +#define VSB_RGBOrder (1<<11) +#define VSB_GammaCorrect (1<<12) +#define VSB_LockToStreamA (1<<13) + +#define VSControl 0x0000 +#define VSInterrupt 0x0008 +#define VSCurrentLine 0x0010 +#define VSVideoAddressHost 0x0018 +#define VSVideoAddressIndex 0x0020 +#define VSVideoAddress0 0x0028 +#define VSVideoAddress1 0x0030 +#define VSVideoAddress2 0x0038 +#define VSVideoStride 0x0040 +#define VSVideoStartLine 0x0048 +#define VSVideoEndLine 0x0050 +#define VSVideoStartData 0x0058 +#define VSVideoEndData 0x0060 +#define VSVBIAddressHost 0x0068 +#define VSVBIAddressIndex 0x0070 +#define VSVBIAddress0 0x0078 +#define VSVBIAddress1 0x0080 +#define VSVBIAddress2 0x0088 +#define VSVBIStride 0x0090 +#define VSVBIStartLine 0x0098 +#define VSVBIEndLine 0x00A0 +#define VSVBIStartData 0x00A8 +#define VSVBIEndData 0x00B0 +#define VSFifoControl 0x00B8 + +/********************************** + * GLINT Delta Region 0 Registers * + **********************************/ + +/* Control Status Registers */ +#define DResetStatus 0x0800 +#define DIntEnable 0x0808 +#define DIntFlags 0x0810 +#define DErrorFlags 0x0838 +#define DTestRegister 0x0848 +#define DFIFODis 0x0868 + + + +/********************************** + * GLINT Gamma Region 0 Registers * + **********************************/ + +/* Control Status Registers */ +#define GInFIFOSpace 0x0018 +#define GDMAAddress 0x0028 +#define GDMACount 0x0030 +#define GDMAControl 0x0060 +#define GOutDMA 0x0080 +#define GOutDMACount 0x0088 +#define GResetStatus 0x0800 +#define GIntEnable 0x0808 +#define GIntFlags 0x0810 +#define GErrorFlags 0x0838 +#define GTestRegister 0x0848 +#define GFIFODis 0x0868 + +#define GChipConfig 0x0870 +#define GChipAGPCapable 1 << 0 +#define GChipAGPSideband 1 << 1 +#define GChipMultiGLINTApMask 3 << 19 +#define GChipMultiGLINTAp_0M 0 << 19 +#define GChipMultiGLINTAp_16M 1 << 19 +#define GChipMultiGLINTAp_32M 2 << 19 +#define GChipMultiGLINTAp_64M 3 << 19 + +#define GCSRAperture 0x0878 +#define GCSRSecondaryGLINTMapEn 1 << 0 + +#define GPageTableAddr 0x0c00 +#define GPageTableLength 0x0c08 +#define GDelayTimer 0x0c38 +#define GCommandMode 0x0c40 +#define GCommandIntEnable 0x0c48 +#define GCommandIntFlags 0x0c50 +#define GCommandErrorFlags 0x0c58 +#define GCommandStatus 0x0c60 +#define GCommandFaultingAddr 0x0c68 +#define GVertexFaultingAddr 0x0c70 +#define GWriteFaultingAddr 0x0c88 +#define GFeedbackSelectCount 0x0c98 +#define GGammaProcessorMode 0x0cb8 +#define GVGAShadow 0x0d00 +#define GMultGLINTAperture 0x0d08 +#define GMultGLINT1 0x0d10 +#define GMultGLINT2 0x0d18 + +/************************ + * GLINT Core Registers * + ************************/ + +#define GLINT_TAG(major,offset) (((major) << 7) | ((offset) << 3)) +#define GLINT_TAG_ADDR(major,offset) (0x8000 | GLINT_TAG((major),(offset))) + +#define UNIT_DISABLE 0 +#define UNIT_ENABLE 1 + +#define StartXDom GLINT_TAG_ADDR(0x00,0x00) +#define dXDom GLINT_TAG_ADDR(0x00,0x01) +#define StartXSub GLINT_TAG_ADDR(0x00,0x02) +#define dXSub GLINT_TAG_ADDR(0x00,0x03) +#define StartY GLINT_TAG_ADDR(0x00,0x04) +#define dY GLINT_TAG_ADDR(0x00,0x05) +#define GLINTCount GLINT_TAG_ADDR(0x00,0x06) +#define Render GLINT_TAG_ADDR(0x00,0x07) + #define AreaStippleEnable 0x00001 + #define LineStippleEnable 0x00002 + #define ResetLineStipple 0x00004 + #define FastFillEnable 0x00008 + #define PrimitiveLine 0 + #define PrimitiveTrapezoid 0x00040 + #define PrimitivePoint 0x00080 + #define PrimitiveRectangle 0x000C0 + #define AntialiasEnable 0x00100 + #define AntialiasingQuality 0x00200 + #define UsePointTable 0x00400 + #define SyncOnBitMask 0x00800 + #define SyncOnHostData 0x01000 + #define TextureEnable 0x02000 + #define FogEnable 0x04000 + #define CoverageEnable 0x08000 + #define SubPixelCorrectionEnable 0x10000 + #define SpanOperation 0x40000 + #define XPositive 1<<21 + #define YPositive 1<<22 + + +#define ContinueNewLine GLINT_TAG_ADDR(0x00,0x08) +#define ContinueNewDom GLINT_TAG_ADDR(0x00,0x09) +#define ContinueNewSub GLINT_TAG_ADDR(0x00,0x0a) +#define Continue GLINT_TAG_ADDR(0x00,0x0b) +#define FlushSpan GLINT_TAG_ADDR(0x00,0x0c) +#define BitMaskPattern GLINT_TAG_ADDR(0x00,0x0d) + +#define PointTable0 GLINT_TAG_ADDR(0x01,0x00) +#define PointTable1 GLINT_TAG_ADDR(0x01,0x01) +#define PointTable2 GLINT_TAG_ADDR(0x01,0x02) +#define PointTable3 GLINT_TAG_ADDR(0x01,0x03) +#define RasterizerMode GLINT_TAG_ADDR(0x01,0x04) +#define RMMultiGLINT 1<<17 +#define BitMaskPackingEachScanline 1<<9 +#define ForceBackgroundColor 1<<6 +#define InvertBitMask 1<<1 +#define YLimits GLINT_TAG_ADDR(0x01,0x05) +#define ScanLineOwnership GLINT_TAG_ADDR(0x01,0x06) +#define WaitForCompletion GLINT_TAG_ADDR(0x01,0x07) +#define PixelSize GLINT_TAG_ADDR(0x01,0x08) +#define XLimits GLINT_TAG_ADDR(0x01,0x09) /* PM only */ + +#define RectangleOrigin GLINT_TAG_ADDR(0x01,0x0A) /* PM2 only */ +#define RectangleSize GLINT_TAG_ADDR(0x01,0x0B) /* PM2 only */ + +#define PackedDataLimits GLINT_TAG_ADDR(0x02,0x0a) /* PM only */ + +#define ScissorMode GLINT_TAG_ADDR(0x03,0x00) + #define SCI_USER 0x01 + #define SCI_SCREEN 0x02 + #define SCI_USERANDSCREEN 0x03 + +#define ScissorMinXY GLINT_TAG_ADDR(0x03,0x01) +#define ScissorMaxXY GLINT_TAG_ADDR(0x03,0x02) +#define ScreenSize GLINT_TAG_ADDR(0x03,0x03) +#define AreaStippleMode GLINT_TAG_ADDR(0x03,0x04) + /* 0: */ + /* NoMirrorY */ + /* NoMirrorX */ + /* NoInvertPattern */ + /* YAddress_1bit */ + /* XAddress_1bit */ + /* UNIT_DISABLE */ + + #define ASM_XAddress_2bit 1 << 1 + #define ASM_XAddress_3bit 2 << 1 + #define ASM_XAddress_4bit 3 << 1 + #define ASM_XAddress_5bit 4 << 1 + #define ASM_YAddress_2bit 1 << 4 + #define ASM_YAddress_3bit 2 << 4 + #define ASM_YAddress_4bit 3 << 4 + #define ASM_YAddress_5bit 4 << 4 + #define ASM_InvertPattern 1 << 17 + #define ASM_MirrorX 1 << 18 + #define ASM_MirrorY 1 << 19 + +#define LineStippleMode GLINT_TAG_ADDR(0x03,0x05) +#define LoadLineStippleCounters GLINT_TAG_ADDR(0x03,0x06) +#define UpdateLineStippleCounters GLINT_TAG_ADDR(0x03,0x07) +#define SaveLineStippleState GLINT_TAG_ADDR(0x03,0x08) +#define WindowOrigin GLINT_TAG_ADDR(0x03,0x09) + +#define AreaStipplePattern0 GLINT_TAG_ADDR(0x04,0x00) +#define AreaStipplePattern1 GLINT_TAG_ADDR(0x04,0x01) +#define AreaStipplePattern2 GLINT_TAG_ADDR(0x04,0x02) +#define AreaStipplePattern3 GLINT_TAG_ADDR(0x04,0x03) +#define AreaStipplePattern4 GLINT_TAG_ADDR(0x04,0x04) +#define AreaStipplePattern5 GLINT_TAG_ADDR(0x04,0x05) +#define AreaStipplePattern6 GLINT_TAG_ADDR(0x04,0x06) +#define AreaStipplePattern7 GLINT_TAG_ADDR(0x04,0x07) + +#define TextureAddressMode GLINT_TAG_ADDR(0x07,0x00) +#define SStart GLINT_TAG_ADDR(0x07,0x01) +#define dSdx GLINT_TAG_ADDR(0x07,0x02) +#define dSdyDom GLINT_TAG_ADDR(0x07,0x03) +#define TStart GLINT_TAG_ADDR(0x07,0x04) +#define dTdx GLINT_TAG_ADDR(0x07,0x05) +#define dTdyDom GLINT_TAG_ADDR(0x07,0x06) +#define QStart GLINT_TAG_ADDR(0x07,0x07) +#define dQdx GLINT_TAG_ADDR(0x07,0x08) +#define dQdyDom GLINT_TAG_ADDR(0x07,0x09) +#define LOD GLINT_TAG_ADDR(0x07,0x0A) +#define dSdy GLINT_TAG_ADDR(0x07,0x0B) +#define dTdy GLINT_TAG_ADDR(0x07,0x0C) +#define dQdy GLINT_TAG_ADDR(0x07,0x0D) + +#define TextureReadMode GLINT_TAG_ADDR(0x09,0x00) +#define TextureFormat GLINT_TAG_ADDR(0x09,0x01) + #define Texture_4_Components 3 << 3 + #define Texture_Texel 0 + +#define TextureCacheControl GLINT_TAG_ADDR(0x09,0x02) + #define TextureCacheControlEnable 2 + #define TextureCacheControlInvalidate 1 + +#define GLINTBorderColor GLINT_TAG_ADDR(0x09,0x05) + +#define TexelLUTIndex GLINT_TAG_ADDR(0x09,0x08) +#define TexelLUTData GLINT_TAG_ADDR(0x09,0x09) +#define TexelLUTAddress GLINT_TAG_ADDR(0x09,0x0A) +#define TexelLUTTransfer GLINT_TAG_ADDR(0x09,0x0B) +#define TextureFilterMode GLINT_TAG_ADDR(0x09,0x0C) +#define TextureChromaUpper GLINT_TAG_ADDR(0x09,0x0D) +#define TextureChromaLower GLINT_TAG_ADDR(0x09,0x0E) + +#define TxBaseAddr0 GLINT_TAG_ADDR(0x0A,0x00) +#define TxBaseAddr1 GLINT_TAG_ADDR(0x0A,0x01) +#define TxBaseAddr2 GLINT_TAG_ADDR(0x0A,0x02) +#define TxBaseAddr3 GLINT_TAG_ADDR(0x0A,0x03) +#define TxBaseAddr4 GLINT_TAG_ADDR(0x0A,0x04) +#define TxBaseAddr5 GLINT_TAG_ADDR(0x0A,0x05) +#define TxBaseAddr6 GLINT_TAG_ADDR(0x0A,0x06) +#define TxBaseAddr7 GLINT_TAG_ADDR(0x0A,0x07) +#define TxBaseAddr8 GLINT_TAG_ADDR(0x0A,0x08) +#define TxBaseAddr9 GLINT_TAG_ADDR(0x0A,0x09) +#define TxBaseAddr10 GLINT_TAG_ADDR(0x0A,0x0A) +#define TxBaseAddr11 GLINT_TAG_ADDR(0x0A,0x0B) + +#define PMTextureBaseAddress GLINT_TAG_ADDR(0x0b,0x00) +#define PMTextureMapFormat GLINT_TAG_ADDR(0x0b,0x01) +#define PMTextureDataFormat GLINT_TAG_ADDR(0x0b,0x02) + +#define Texel0 GLINT_TAG_ADDR(0x0c,0x00) +#define Texel1 GLINT_TAG_ADDR(0x0c,0x01) +#define Texel2 GLINT_TAG_ADDR(0x0c,0x02) +#define Texel3 GLINT_TAG_ADDR(0x0c,0x03) +#define Texel4 GLINT_TAG_ADDR(0x0c,0x04) +#define Texel5 GLINT_TAG_ADDR(0x0c,0x05) +#define Texel6 GLINT_TAG_ADDR(0x0c,0x06) +#define Texel7 GLINT_TAG_ADDR(0x0c,0x07) +#define Interp0 GLINT_TAG_ADDR(0x0c,0x08) +#define Interp1 GLINT_TAG_ADDR(0x0c,0x09) +#define Interp2 GLINT_TAG_ADDR(0x0c,0x0a) +#define Interp3 GLINT_TAG_ADDR(0x0c,0x0b) +#define Interp4 GLINT_TAG_ADDR(0x0c,0x0c) +#define TextureFilter GLINT_TAG_ADDR(0x0c,0x0d) +#define PMTextureReadMode GLINT_TAG_ADDR(0x0c,0x0e) +#define TexelLUTMode GLINT_TAG_ADDR(0x0c,0x0f) + +#define TextureColorMode GLINT_TAG_ADDR(0x0d,0x00) + #define TextureTypeOpenGL 0 + #define TextureTypeApple 1 << 4 + #define TextureKsDDA 1 << 5 /* only Apple-Mode */ + #define TextureKdDDA 1 << 6 /* only Apple-Mode */ + +#define TextureEnvColor GLINT_TAG_ADDR(0x0d,0x01) +#define FogMode GLINT_TAG_ADDR(0x0d,0x02) + /* 0: */ + /* FOG RGBA */ + /* UNIT_DISABLE */ + + #define FOG_CI 0x0002 + +#define FogColor GLINT_TAG_ADDR(0x0d,0x03) +#define FStart GLINT_TAG_ADDR(0x0d,0x04) +#define dFdx GLINT_TAG_ADDR(0x0d,0x05) +#define dFdyDom GLINT_TAG_ADDR(0x0d,0x06) +#define KsStart GLINT_TAG_ADDR(0x0d,0x09) +#define dKsdx GLINT_TAG_ADDR(0x0d,0x0a) +#define dKsdyDom GLINT_TAG_ADDR(0x0d,0x0b) +#define KdStart GLINT_TAG_ADDR(0x0d,0x0c) +#define dKdStart GLINT_TAG_ADDR(0x0d,0x0d) +#define dKddyDom GLINT_TAG_ADDR(0x0d,0x0e) + +#define RStart GLINT_TAG_ADDR(0x0f,0x00) +#define dRdx GLINT_TAG_ADDR(0x0f,0x01) +#define dRdyDom GLINT_TAG_ADDR(0x0f,0x02) +#define GStart GLINT_TAG_ADDR(0x0f,0x03) +#define dGdx GLINT_TAG_ADDR(0x0f,0x04) +#define dGdyDom GLINT_TAG_ADDR(0x0f,0x05) +#define BStart GLINT_TAG_ADDR(0x0f,0x06) +#define dBdx GLINT_TAG_ADDR(0x0f,0x07) +#define dBdyDom GLINT_TAG_ADDR(0x0f,0x08) +#define AStart GLINT_TAG_ADDR(0x0f,0x09) +#define dAdx GLINT_TAG_ADDR(0x0f,0x0a) +#define dAdyDom GLINT_TAG_ADDR(0x0f,0x0b) +#define ColorDDAMode GLINT_TAG_ADDR(0x0f,0x0c) + /* 0: */ + #define CDDA_FlatShading 0 + /* UNIT_DISABLE */ + #define CDDA_GouraudShading 0x0002 + + +#define ConstantColor GLINT_TAG_ADDR(0x0f,0x0d) +#define GLINTColor GLINT_TAG_ADDR(0x0f,0x0e) +#define AlphaTestMode GLINT_TAG_ADDR(0x10,0x00) +#define AntialiasMode GLINT_TAG_ADDR(0x10,0x01) +#define AlphaBlendMode GLINT_TAG_ADDR(0x10,0x02) + /* 0: */ + /* SrcZERO */ + /* DstZERO */ + /* ColorFormat8888 */ + /* AlphaBuffer present */ + /* ColorOrderBGR */ + /* TypeOpenGL */ + /* DstFBData */ + /* UNIT_DISABLE */ + + #define ABM_SrcONE 1 << 1 + #define ABM_SrcDST_COLOR 2 << 1 + #define ABM_SrcONE_MINUS_DST_COLOR 3 << 1 + #define ABM_SrcSRC_ALPHA 4 << 1 + #define ABM_SrcONE_MINUS_SRC_ALPHA 5 << 1 + #define ABM_SrcDST_ALPHA 6 << 1 + #define ABM_SrcONE_MINUS_DST_ALPHA 7 << 1 + #define ABM_SrcSRC_ALPHA_SATURATE 8 << 1 + #define ABM_DstONE 1 << 5 + #define ABM_DstSRC_COLOR 2 << 5 + #define ABM_DstONE_MINUS_SRC_COLOR 3 << 5 + #define ABM_DstSRC_ALPHA 4 << 5 + #define ABM_DstONE_MINUS_SRC_ALPHA 5 << 5 + #define ABM_DstDST_ALPHA 6 << 5 + #define ABM_DstONE_MINUS_DST_ALPHA 7 << 5 + #define ABM_ColorFormat5555 1 << 8 + #define ABM_ColorFormat4444 2 << 8 + #define ABM_ColorFormat4444_Front 3 << 8 + #define ABM_ColorFormat4444_Back 4 << 8 + #define ABM_ColorFormat332_Front 5 << 8 + #define ABM_ColorFormat332_Back 6 << 8 + #define ABM_ColorFormat121_Front 7 << 8 + #define ABM_ColorFormat121_Back 8 << 8 + #define ABM_ColorFormat555_Back 13 << 8 + #define ABM_ColorFormat_CI8 14 << 8 + #define ABM_ColorFormat_CI4 15 << 8 + #define ABM_NoAlphaBuffer 0x1000 + #define ABM_ColorOrderRGB 0x2000 + #define ABM_TypeQuickDraw3D 0x4000 + #define ABM_DstFBSourceData 0x8000 + +#define DitherMode GLINT_TAG_ADDR(0x10,0x03) + /* 0: */ + /* ColorOrder BGR */ + /* AlphaDitherDefault */ + /* ColorFormat8888 */ + /* TruncateMode */ + /* DitherDisable */ + /* UNIT_DISABLE */ + + #define DTM_DitherEnable 1 << 1 + #define DTM_ColorFormat5555 1 << 2 + #define DTM_ColorFormat4444 2 << 2 + #define DTM_ColorFormat4444_Front 3 << 2 + #define DTM_ColorFormat4444_Back 4 << 2 + #define DTM_ColorFormat332_Front 5 << 2 + #define DTM_ColorFormat332_Back 6 << 2 + #define DTM_ColorFormat121_Front 7 << 2 + #define DTM_ColorFormat121_Back 8 << 2 + #define DTM_ColorFormat555_Back 13 << 2 + #define DTM_ColorFormat_CI8 14 << 2 + #define DTM_ColorFormat_CI4 15 << 2 + #define DTM_ColorOrderRGB 1 << 10 + #define DTM_NoAlphaDither 1 << 14 + #define DTM_RoundMode 1 << 15 + +#define FBSoftwareWriteMask GLINT_TAG_ADDR(0x10,0x04) +#define LogicalOpMode GLINT_TAG_ADDR(0x10,0x05) + #define Use_ConstantFBWriteData 0x40 + + +#define FBWriteData GLINT_TAG_ADDR(0x10,0x06) +#define RouterMode GLINT_TAG_ADDR(0x10,0x08) + #define ROUTER_Depth_Texture 1 + #define ROUTER_Texture_Depth 0 + + +#define LBReadMode GLINT_TAG_ADDR(0x11,0x00) + /* 0: */ + /* SrcNoRead */ + /* DstNoRead */ + /* DataLBDefault */ + /* WinTopLeft */ + /* NoPatch */ + /* ScanlineInterval1 */ + + #define LBRM_SrcEnable 1 << 9 + #define LBRM_DstEnable 1 << 10 + #define LBRM_DataLBStencil 1 << 16 + #define LBRM_DataLBDepth 2 << 16 + #define LBRM_WinBottomLeft 1 << 18 + #define LBRM_DoPatch 1 << 19 + + #define LBRM_ScanlineInt2 1 << 20 + #define LBRM_ScanlineInt4 2 << 20 + #define LBRM_ScanlineInt8 3 << 20 + + +#define LBReadFormat GLINT_TAG_ADDR(0x11,0x01) + #define LBRF_DepthWidth15 0x03 /* only permedia */ + #define LBRF_DepthWidth16 0x00 + #define LBRF_DepthWidth24 0x01 + #define LBRF_DepthWidth32 0x02 + + #define LBRF_StencilWidth0 (0 << 2) + #define LBRF_StencilWidth4 (1 << 2) + #define LBRF_StencilWidth8 (2 << 2) + + #define LBRF_StencilPos16 (0 << 4) + #define LBRF_StencilPos20 (1 << 4) + #define LBRF_StencilPos24 (2 << 4) + #define LBRF_StencilPos28 (3 << 4) + #define LBRF_StencilPos32 (4 << 4) + + #define LBRF_FrameCount0 (0 << 7) + #define LBRF_FrameCount4 (1 << 7) + #define LBRF_FrameCount8 (2 << 7) + + #define LBRF_FrameCountPos16 (0 << 9) + #define LBRF_FrameCountPos20 (1 << 9) + #define LBRF_FrameCountPos24 (2 << 9) + #define LBRF_FrameCountPos28 (3 << 9) + #define LBRF_FrameCountPos32 (4 << 9) + #define LBRF_FrameCountPos36 (5 << 9) + #define LBRF_FrameCountPos40 (6 << 9) + + #define LBRF_GIDWidth0 (0 << 12) + #define LBRF_GIDWidth4 (1 << 12) + + #define LBRF_GIDPos16 (0 << 13) + #define LBRF_GIDPos20 (1 << 13) + #define LBRF_GIDPos24 (2 << 13) + #define LBRF_GIDPos28 (3 << 13) + #define LBRF_GIDPos32 (4 << 13) + #define LBRF_GIDPos36 (5 << 13) + #define LBRF_GIDPos40 (6 << 13) + #define LBRF_GIDPos44 (7 << 13) + #define LBRF_GIDPos48 (8 << 13) + + #define LBRF_Compact32 (1 << 17) + + + +#define LBSourceOffset GLINT_TAG_ADDR(0x11,0x02) +#define LBStencil GLINT_TAG_ADDR(0x11,0x05) +#define LBDepth GLINT_TAG_ADDR(0x11,0x06) +#define LBWindowBase GLINT_TAG_ADDR(0x11,0x07) +#define LBWriteMode GLINT_TAG_ADDR(0x11,0x08) + #define LBWM_WriteEnable 0x1 + #define LBWM_UpLoad_LBDepth 0x2 + #define LBWM_UpLoad_LBStencil 0x4 + +#define LBWriteFormat GLINT_TAG_ADDR(0x11,0x09) + + +#define TextureData GLINT_TAG_ADDR(0x11,0x0d) +#define TextureDownloadOffset GLINT_TAG_ADDR(0x11,0x0e) +#define LBWindowOffset GLINT_TAG_ADDR(0x11,0x0f) + +#define GLINTWindow GLINT_TAG_ADDR(0x13,0x00) + #define GWIN_UnitEnable (1 << 0) + #define GWIN_ForceLBUpdate (1 << 3) + #define GWIN_LBUpdateSourceREG (1 << 4) + #define GWIN_LBUpdateSourceLB (0 << 4) + #define GWIN_StencilFCP (1 << 17) + #define GWIN_DepthFCP (1 << 18) + #define GWIN_OverrideWriteFilter (1 << 19) + + /* ??? is this needed, set by permedia (2) modules */ + #define GWIN_DisableLBUpdate 0x40000 + +#define StencilMode GLINT_TAG_ADDR(0x13,0x01) +#define StencilData GLINT_TAG_ADDR(0x13,0x02) +#define GLINTStencil GLINT_TAG_ADDR(0x13,0x03) +#define DepthMode GLINT_TAG_ADDR(0x13,0x04) + /* 0: */ + /* WriteDisable */ + /* SrcCompFragment */ + /* CompFuncNEVER */ + /* UNIT_DISABLE */ + + #define DPM_WriteEnable 1 << 1 + #define DPM_SrcCompLBData 1 << 2 + #define DPM_SrcCompDregister 2 << 2 + #define DPM_SrcCompLBSourceData 3 << 2 + #define DPM_CompFuncLESS 1 << 4 + #define DPM_CompFuncEQUAL 2 << 4 + #define DPM_CompFuncLESS_OR_EQ 3 << 4 + #define DPM_CompFuncGREATER 4 << 4 + #define DPM_CompFuncNOT_EQ 5 << 4 + #define DPM_CompFuncGREATER_OR_EQ 6 << 4 + #define DPM_CompFuncALWAYS 7 << 4 + +#define GLINTDepth GLINT_TAG_ADDR(0x13,0x05) +#define ZStartU GLINT_TAG_ADDR(0x13,0x06) +#define ZStartL GLINT_TAG_ADDR(0x13,0x07) +#define dZdxU GLINT_TAG_ADDR(0x13,0x08) +#define dZdxL GLINT_TAG_ADDR(0x13,0x09) +#define dZdyDomU GLINT_TAG_ADDR(0x13,0x0a) +#define dZdyDomL GLINT_TAG_ADDR(0x13,0x0b) +#define FastClearDepth GLINT_TAG_ADDR(0x13,0x0c) + +#define FBReadMode GLINT_TAG_ADDR(0x15,0x00) + /* 0: */ + /* SrcNoRead */ + /* DstNoRead */ + /* DataFBDefault */ + /* WinTopLeft */ + /* ScanlineInterval1 */ + + #define FBRM_SrcEnable 1 << 9 + #define FBRM_DstEnable 1 << 10 + #define FBRM_DataFBColor 1 << 15 + #define FBRM_WinBottomLeft 1 << 16 + #define FBRM_Packed 1 << 19 + #define FBRM_ScanlineInt2 1 << 23 + #define FBRM_ScanlineInt4 2 << 23 + #define FBRM_ScanlineInt8 3 << 23 + + +#define FBSourceOffset GLINT_TAG_ADDR(0x15,0x01) +#define FBPixelOffset GLINT_TAG_ADDR(0x15,0x02) +#define FBColor GLINT_TAG_ADDR(0x15,0x03) +#define FBData GLINT_TAG_ADDR(0x15,0x04) +#define FBSourceData GLINT_TAG_ADDR(0x15,0x05) + +#define FBWindowBase GLINT_TAG_ADDR(0x15,0x06) +#define FBWriteMode GLINT_TAG_ADDR(0x15,0x07) + /* 0: */ + /* FBWM_NoColorUpload */ + /* FBWM_WriteDisable */ + #define FBWM_WriteEnable 1 + #define FBWM_UploadColor 1 << 3 +/* Permedia3 extensions */ + #define FBWM_Enable0 1 << 12 + +#define FBHardwareWriteMask GLINT_TAG_ADDR(0x15,0x08) +#define FBBlockColor GLINT_TAG_ADDR(0x15,0x09) +#define FBReadPixel GLINT_TAG_ADDR(0x15,0x0a) /* PM */ +#define PatternRamMode GLINT_TAG_ADDR(0x15,0x0f) + +#define PatternRamData0 GLINT_TAG_ADDR(0x16,0x00) +#define PatternRamData1 GLINT_TAG_ADDR(0x16,0x01) +#define PatternRamData2 GLINT_TAG_ADDR(0x16,0x02) +#define PatternRamData3 GLINT_TAG_ADDR(0x16,0x03) +#define PatternRamData4 GLINT_TAG_ADDR(0x16,0x04) +#define PatternRamData5 GLINT_TAG_ADDR(0x16,0x05) +#define PatternRamData6 GLINT_TAG_ADDR(0x16,0x06) +#define PatternRamData7 GLINT_TAG_ADDR(0x16,0x07) + +#define FilterMode GLINT_TAG_ADDR(0x18,0x00) + /* 0: */ + /* CullDepthTags */ + /* CullDepthData */ + /* CullStencilTags */ + /* CullStencilData */ + /* CullColorTag */ + /* CullColorData */ + /* CullSyncTag */ + /* CullSyncData */ + /* CullStatisticTag */ + /* CullStatisticData */ + + #define FM_PassDepthTags 0x0010 + #define FM_PassDepthData 0x0020 + #define FM_PassStencilTags 0x0040 + #define FM_PassStencilData 0x0080 + #define FM_PassColorTag 0x0100 + #define FM_PassColorData 0x0200 + #define FM_PassSyncTag 0x0400 + #define FM_PassSyncData 0x0800 + #define FM_PassStatisticTag 0x1000 + #define FM_PassStatisticData 0x2000 + +#define Sync_tag 0x0188 + +#define StatisticMode GLINT_TAG_ADDR(0x18,0x01) +#define MinRegion GLINT_TAG_ADDR(0x18,0x02) +#define MaxRegion GLINT_TAG_ADDR(0x18,0x03) +#define ResetPickResult GLINT_TAG_ADDR(0x18,0x04) +#define MitHitRegion GLINT_TAG_ADDR(0x18,0x05) +#define MaxHitRegion GLINT_TAG_ADDR(0x18,0x06) +#define PickResult GLINT_TAG_ADDR(0x18,0x07) +#define GlintSync GLINT_TAG_ADDR(0x18,0x08) + +#define FBBlockColorU GLINT_TAG_ADDR(0x18,0x0d) +#define FBBlockColorL GLINT_TAG_ADDR(0x18,0x0e) +#define SuspendUntilFrameBlank GLINT_TAG_ADDR(0x18,0x0f) + +#define KsRStart GLINT_TAG_ADDR(0x19,0x00) +#define dKsRdx GLINT_TAG_ADDR(0x19,0x01) +#define dKsRdyDom GLINT_TAG_ADDR(0x19,0x02) +#define KsGStart GLINT_TAG_ADDR(0x19,0x03) +#define dKsGdx GLINT_TAG_ADDR(0x19,0x04) +#define dKsGdyDom GLINT_TAG_ADDR(0x19,0x05) +#define KsBStart GLINT_TAG_ADDR(0x19,0x06) +#define dKsBdx GLINT_TAG_ADDR(0x19,0x07) +#define dKsBdyDom GLINT_TAG_ADDR(0x19,0x08) + +#define KdRStart GLINT_TAG_ADDR(0x1A,0x00) +#define dKdRdx GLINT_TAG_ADDR(0x1A,0x01) +#define dKdRdyDom GLINT_TAG_ADDR(0x1A,0x02) +#define KdGStart GLINT_TAG_ADDR(0x1A,0x03) +#define dKdGdx GLINT_TAG_ADDR(0x1A,0x04) +#define dKdGdyDom GLINT_TAG_ADDR(0x1A,0x05) +#define KdBStart GLINT_TAG_ADDR(0x1A,0x06) +#define dKdBdx GLINT_TAG_ADDR(0x1A,0x07) +#define dKdBdyDom GLINT_TAG_ADDR(0x1A,0x08) + +#define FBSourceBase GLINT_TAG_ADDR(0x1B,0x00) +#define FBSourceDelta GLINT_TAG_ADDR(0x1B,0x01) +#define Config GLINT_TAG_ADDR(0x1B,0x02) +#define CFBRM_SrcEnable 1<<0 +#define CFBRM_DstEnable 1<<1 +#define CFBRM_Packed 1<<2 +#define CWM_Enable 1<<3 +#define CCDDA_Enable 1<<4 +#define CLogOp_Enable 1<<5 +#define ContextDump GLINT_TAG_ADDR(0x1B,0x08) +#define ContextRestore GLINT_TAG_ADDR(0x1B,0x09) +#define ContextData GLINT_TAG_ADDR(0x1B,0x0a) + +#define TexelLUT0 GLINT_TAG_ADDR(0x1D,0x00) +#define TexelLUT1 GLINT_TAG_ADDR(0x1D,0x01) +#define TexelLUT2 GLINT_TAG_ADDR(0x1D,0x02) +#define TexelLUT3 GLINT_TAG_ADDR(0x1D,0x03) +#define TexelLUT4 GLINT_TAG_ADDR(0x1D,0x04) +#define TexelLUT5 GLINT_TAG_ADDR(0x1D,0x05) +#define TexelLUT6 GLINT_TAG_ADDR(0x1D,0x06) +#define TexelLUT7 GLINT_TAG_ADDR(0x1D,0x07) +#define TexelLUT8 GLINT_TAG_ADDR(0x1D,0x08) +#define TexelLUT9 GLINT_TAG_ADDR(0x1D,0x09) +#define TexelLUT10 GLINT_TAG_ADDR(0x1D,0x0A) +#define TexelLUT11 GLINT_TAG_ADDR(0x1D,0x0B) +#define TexelLUT12 GLINT_TAG_ADDR(0x1D,0x0C) +#define TexelLUT13 GLINT_TAG_ADDR(0x1D,0x0D) +#define TexelLUT14 GLINT_TAG_ADDR(0x1D,0x0E) +#define TexelLUT15 GLINT_TAG_ADDR(0x1D,0x0F) + +#define YUVMode GLINT_TAG_ADDR(0x1E,0x00) +#define ChromaUpper GLINT_TAG_ADDR(0x1E,0x01) +#define ChromaLower GLINT_TAG_ADDR(0x1E,0x02) +#define ChromaTestMode GLINT_TAG_ADDR(0x1E,0x03) + + +/****************************** + * GLINT Delta Core Registers * + ******************************/ + +#define V0FixedTag GLINT_TAG_ADDR(0x20,0x00) +#define V1FixedTag GLINT_TAG_ADDR(0x21,0x00) +#define V2FixedTag GLINT_TAG_ADDR(0x22,0x00) +#define V0FloatTag GLINT_TAG_ADDR(0x23,0x00) +#define V1FloatTag GLINT_TAG_ADDR(0x24,0x00) +#define V2FloatTag GLINT_TAG_ADDR(0x25,0x00) + +#define VPAR_s 0x00 +#define VPAR_t 0x08 +#define VPAR_q 0x10 +#define VPAR_Ks 0x18 +#define VPAR_Kd 0x20 + +/* have changed colors in ramdac ! +#define VPAR_R 0x28 +#define VPAR_G 0x30 +#define VPAR_B 0x38 +#define VPAR_A 0x40 +*/ +#define VPAR_B 0x28 +#define VPAR_G 0x30 +#define VPAR_R 0x38 +#define VPAR_A 0x40 + +#define VPAR_f 0x48 + +#define VPAR_x 0x50 +#define VPAR_y 0x58 +#define VPAR_z 0x60 + +#define DeltaModeTag GLINT_TAG_ADDR(0x26,0x00) + /* 0: */ + /* GLINT_300SX */ + + /* DeltaMode Register Bit Field Assignments */ + #define DM_GLINT_300SX 0x0000 + #define DM_GLINT_500TX 0x0001 + #define DM_PERMEDIA 0x0002 + #define DM_Depth_16BPP (1 << 2) + #define DM_Depth_24BPP (2 << 2) + #define DM_Depth_32BPP (3 << 2) + #define DM_FogEnable 0x0010 + #define DM_TextureEnable 0x0020 + #define DM_SmoothShadingEnable 0x0040 + #define DM_DepthEnable 0x0080 + #define DM_SpecularTextureEnable 0x0100 + #define DM_DiffuseTextureEnable 0x0200 + #define DM_SubPixelCorrectionEnable 0x0400 + #define DM_DiamondExit 0x0800 + #define DM_NoDraw 0x1000 + #define DM_ClampEnable 0x2000 + #define DM_ClampedTexParMode 0x4000 + #define DM_NormalizedTexParMode 0xC000 + + + #define DDCMD_AreaStrippleEnable 0x0001 + #define DDCMD_LineStrippleEnable 0x0002 + #define DDCMD_ResetLineStripple 1 << 2 + #define DDCMD_FastFillEnable 1 << 3 + /* 2 Bits reserved */ + #define DDCMD_PrimitiveType_Point 2 << 6 + #define DDCMD_PrimitiveType_Line 0 << 6 + #define DDCMD_PrimitiveType_Trapezoid 1 << 6 + #define DDCMD_AntialiasEnable 1 << 8 + #define DDCMD_AntialiasingQuality 1 << 9 + #define DDCMD_UsePointTable 1 << 10 + #define DDCMD_SyncOnBitMask 1 << 11 + #define DDCMD_SyncOnHostDate 1 << 12 + #define DDCMD_TextureEnable 1 << 13 + #define DDCMD_FogEnable 1 << 14 + #define DDCMD_CoverageEnable 1 << 15 + #define DDCMD_SubPixelCorrectionEnable 1 << 16 + + + +#define DrawTriangle GLINT_TAG_ADDR(0x26,0x01) +#define RepeatTriangle GLINT_TAG_ADDR(0x26,0x02) +#define DrawLine01 GLINT_TAG_ADDR(0x26,0x03) +#define DrawLine10 GLINT_TAG_ADDR(0x26,0x04) +#define RepeatLine GLINT_TAG_ADDR(0x26,0x05) +#define BroadcastMask GLINT_TAG_ADDR(0x26,0x0F) + +/* Permedia 3 - Accelerator Extensions */ +#define FillRectanglePosition 0x8348 +#define FillRender2D 0x8350 +#define FBDstReadBufAddr0 0xAE80 +#define FBDstReadBufOffset0 0xAEA0 +#define FBDstReadBufWidth0 0xAEC0 +#define FBDstReadMode 0xAEE0 +#define FBDRM_Enable0 1<<8 +#define FBDRM_Blocking 1<<24 +#define FBDstReadEnables 0xAEE8 +#define FBSrcReadMode 0xAF00 +#define FBSRM_Blocking 1<<11 +#define FBSrcReadBufAddr 0xAF08 +#define FBSrcReadBufOffset0 0xAF10 +#define FBSrcReadBufWidth 0xAF18 +#define FBWriteBufAddr0 0xB000 +#define FBWriteBufOffset0 0xB020 +#define FBWriteBufWidth0 0xB040 +#define FBBlockColorBack 0xB0A0 +#define ForegroundColor 0xB0C0 +#define BackgroundColor 0xB0C8 +#define RectanglePosition 0xB600 +#define Render2D 0xB640 + +/* Colorformats */ +#define BGR555 1 +#define BGR565 16 +#define CI8 14 +#define CI4 15 + +#define GLINT_WRITE_REG(v,r) v_writel(v, r) +#define GLINT_READ_REG(r) v_readl(r) + +#define mem_barrier() + +#if 0 +#define GLINT_WAIT(n) \ +do{ \ + if (pGlint->InFifoSpace>=(n)) \ + pGlint->InFifoSpace -= (n); \ + else { \ + int tmp; \ + while((tmp=GLINT_READ_REG(InFIFOSpace))<(n)); \ + /* Clamp value due to bugs in PM3 */ \ + if (tmp > pGlint->FIFOSize) \ + tmp = pGlint->FIFOSize; \ + pGlint->InFifoSpace = tmp - (n); \ + } \ +}while(0) +#else +#define GLINT_WAIT(n) +#endif + +#define GLINTDACDelay(x) do { \ + int delay = x; \ + unsigned char tmp; \ + while(delay--){tmp = GLINT_READ_REG(InFIFOSpace);}; \ + } while(0) + +#define GLINT_MASK_WRITE_REG(v,m,r) \ + GLINT_WRITE_REG((GLINT_READ_REG(r)&(m))|(v),r) + +#define GLINT_SLOW_WRITE_REG(v,r) \ +do{ \ + mem_barrier(); \ + GLINT_WAIT(pGlint->FIFOSize); \ + mem_barrier(); \ + GLINT_WRITE_REG(v,r); \ +}while(0) + +#define GLINT_SET_INDEX(index) \ +do{ \ + GLINT_SLOW_WRITE_REG(((index)>>8)&0xff,PM2VDACIndexRegHigh); \ + GLINT_SLOW_WRITE_REG((index)&0xff,PM2VDACIndexRegLow); \ +} while(0) + +#define REPLICATE(r) \ +{ \ + if (pScrn->bitsPerPixel == 16) { \ + r &= 0xFFFF; \ + r |= (r<<16); \ + } else \ + if (pScrn->bitsPerPixel == 8) { \ + r &= 0xFF; \ + r |= (r<<8); \ + r |= (r<<16); \ + } \ +} + +#define STOREREG(address,value) \ + pReg->glintRegs[address >> 3] = value; + +#define SAVEREG(address) \ + pReg->glintRegs[address >> 3] = GLINT_READ_REG(address); + +#define RESTOREREG(address) \ + GLINT_SLOW_WRITE_REG(pReg->glintRegs[address >> 3], address); + +#define STOREDAC(address,value) \ + pReg->DacRegs[address] = value; + +#define P2VOUT(address) \ + Permedia2vOutIndReg(pScrn, address, 0x00, pReg->DacRegs[address]); + +#define P2VIN(address) \ + pReg->DacRegs[address] = Permedia2vInIndReg(pScrn, address); + +/* RamDac Save/Restore functions, used by external DAC's */ + +#define STORERAMDAC(address,value) \ + ramdacReg->DacRegs[address] = value; + +typedef struct { + uint32_t glintRegs[0x2000]; + uint32_t DacRegs[0x100]; + uint8_t cmap[0x300]; +} GLINTRegRec, *GLINTRegPtr; + +#define GLINTPTR(p) ((GLINTPtr)((p)->driverPrivate)) + +void +Permedia2ReadAddress (uint32_t index) +{ + GLINT_SLOW_WRITE_REG(0xFF, PM2DACReadMask); + GLINT_SLOW_WRITE_REG(index, PM2DACReadAddress); +} + +unsigned char +Permedia2ReadData (void) +{ + GLINTDACDelay(5); + return(GLINT_READ_REG(PM2DACData)); +} + +void +Permedia2WriteAddress (uint32_t index) +{ + GLINT_SLOW_WRITE_REG(index, PM2DACWriteAddress); +} + +void +Permedia2WriteData (unsigned char data) +{ + GLINT_SLOW_WRITE_REG(data, PM2DACData); +} + +void +Permedia2OutIndReg( uint32_t reg, unsigned char mask, unsigned char data) +{ + unsigned char tmp = 0x00; + + GLINT_SLOW_WRITE_REG (reg, PM2DACIndexReg); + + if (mask != 0x00) + tmp = GLINT_READ_REG (PM2DACIndexData) & mask; + + GLINT_SLOW_WRITE_REG (tmp | data, PM2DACIndexData); +} + +unsigned char +Permedia2InIndReg (uint32_t reg) +{ + unsigned char ret; + + GLINT_SLOW_WRITE_REG (reg, PM2DACIndexReg); + ret = GLINT_READ_REG (PM2DACIndexData); + + return (ret); +} + + +void +Permedia2vOutIndReg( uint32_t reg, unsigned char mask, unsigned char data) +{ + unsigned char tmp = 0x00; + + GLINT_SLOW_WRITE_REG ((reg>>8)&0xff, PM2VDACIndexRegHigh); + GLINT_SLOW_WRITE_REG (reg&0xff, PM2VDACIndexRegLow); + + if (mask != 0x00) + tmp = GLINT_READ_REG (PM2VDACIndexData) & mask; + + GLINT_WRITE_REG (tmp | data, PM2VDACIndexData); +} + +unsigned char +Permedia2vInIndReg (uint32_t reg) +{ + unsigned char ret; + + GLINT_SLOW_WRITE_REG ((reg>>8)&0xff, PM2VDACIndexRegHigh); + GLINT_SLOW_WRITE_REG (reg&0xff, PM2VDACIndexRegLow); + + ret = GLINT_READ_REG (PM2VDACIndexData); + + return (ret); +} + diff --git a/src/drivers/gvga6400.c b/src/drivers/gvga6400.c new file mode 100644 index 0000000..82d6dfc --- /dev/null +++ b/src/drivers/gvga6400.c @@ -0,0 +1,316 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* GVGA 6400 driver Copyright 1994 Arno Schaefer */ +/* only Hires 256 color modes (640x480, 800x600) supported */ + + +#include /* for NULL */ +#include +#include +#include +#include + +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#include "regs/gvga6400.regs" + +/* Mode table */ +static ModeTable gvga6400_modes[] = +{ +/* *INDENT-OFF* */ + OneModeEntry(640x480x256), + OneModeEntry(800x600x256), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +static unsigned char last_page = 0; + +static void gvga6400_setregs(const unsigned char regs[], int mode); +static int gvga6400_init(int force, int par1, int par2); + +/* Fill in chipset-specific modeinfo */ + +static void gvga6400_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + if (modeinfo->bytesperpixel == 1) { /* linear mode */ + modeinfo->maxpixels = 512 * 1024; + modeinfo->startaddressrange = 0xffff; + } else + switch (modeinfo->colors) { + case 16: /* 4-plane 16 color mode */ + modeinfo->maxpixels = 65536 * 8; + modeinfo->startaddressrange = 0x7ffff; + break; + case 256: /* 4-plane 256 color mode */ + modeinfo->maxpixels = 65536 * 4; + modeinfo->startaddressrange = 0x3ffff; + break; + } + + modeinfo->maxlogicalwidth = 2040; + modeinfo->haveblit = 0; + modeinfo->flags &= ~IS_INTERLACED; + modeinfo->flags |= HAVE_RWPAGE; +} + +static void nothing(void) +{ +} + +/* Return nonzero if mode available */ + +static int gvga6400_modeavailable(int mode) +{ + const unsigned char *regs; + + regs = LOOKUPMODE(gvga6400_modes, mode); + + if (regs == NULL || mode == GPLANE16) + return __svgalib_vga_driverspecs.modeavailable(mode); + if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE) + return 0; + + return SVGADRV; +} + + +/* Set a mode */ + +static int lastmode; + +static int gvga6400_setmode(int mode, int prv_mode) +{ + const unsigned char *regs; + + switch (gvga6400_modeavailable(mode)) { + case STDVGADRV: + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + case SVGADRV: + regs = LOOKUPMODE(gvga6400_modes, mode); + if (regs != NULL) + break; + default: + return (1); /* not available */ + } + + __svgalib_setregs(regs); + gvga6400_setregs(regs, mode); + + return 0; +} + +static void gvga6400_setpage(int page) +{ + page &= 7; + last_page = 0x40 | page | (page << 3); + + port_out_r(SEQ_I, 6); + port_out_r(SEQ_D, last_page); +} + +static void gvga6400_setrdpage(int page) +{ + last_page &= 0xf8; + last_page |= page & 0x07; + + port_out_r(SEQ_I, 6); + port_out_r(SEQ_D, last_page); +} + +static void gvga6400_setwrpage(int page) +{ + last_page &= 0xc7; + last_page |= ((page & 7) << 3); + + port_out_r(SEQ_I, 6); + port_out_r(SEQ_D, last_page); +} + + +/* Set display start */ + +static void gvga6400_setdisplaystart(int address) +{ + vga_modeinfo modeinfo; + gvga6400_getmodeinfo(lastmode, &modeinfo); + + if (modeinfo.bytesperpixel == 0) + switch (modeinfo.colors) { + case 16: /* planar 16-color mode */ + port_in(0x3da); + port_out_r(ATT_IW, 0x13 + 0x20); + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | (address & 7)); + /* write sa0-2 to bits 0-2 */ + address >>= 3; + break; + case 256: /* planar 256-color mode */ + port_in(0x3da); + port_out_r(ATT_IW, 0x13 + 0x20); + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); + /* write sa0-1 to bits 1-2 */ + address >>= 2; + break; + } + port_outw_r(CRT_IC, 0x0d + (address & 0x00ff) * 256); /* sa0-sa7 */ + port_outw_r(CRT_IC, 0x0c + (address & 0xff00)); /* sa8-sa15 */ +} + +static void gvga6400_setlogicalwidth(int width) +{ + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ +} + + +static int gvga6400_test(void) +{ + int mem_fd; + unsigned char *vga_bios; + int result = 0; + int address; + + /* Ensure that this open gets a file descriptor greater + * than 2, else problems can occur with stdio functions + * under certain strange conditions: */ + if ((fcntl(0,F_GETFD) == -1) && (open("/dev/null", O_RDONLY) == -1)) { + perror("/dev/null"); + exit(1); + } + if ((fcntl(1,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)) { + perror("/dev/null"); + exit(1); + } + if ((fcntl(2,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)) { + perror("/dev/null"); + exit(1); + } + mem_fd = open("/dev/mem", O_RDONLY); + if (mem_fd == -1) { + perror("/dev/mem"); + exit(-1); + } + /* Ensure this file is closed if we were ever to exec something else... */ + if (fcntl(mem_fd, F_SETFD, 1) == -1) { + perror("fcntl"); + exit(-1); + } + + /* Changed to use valloc(). */ + if ((vga_bios = valloc(4096)) == NULL) { + fprintf(stderr, "svgalib: malloc error\n"); + exit(-1); + } + vga_bios = (unsigned char *) mmap + ( + (caddr_t) vga_bios, + 4096, + PROT_READ, + MAP_SHARED | MAP_FIXED, + mem_fd, + 0xc0000 + ); + if (vga_bios == MAP_FAILED) { + fprintf(stderr, "svgalib: mmap error\n"); + exit(-1); + } + address = vga_bios[0x37]; + + if (vga_bios[address] == 0x77 && + vga_bios[address + 1] == 0x11 && + vga_bios[address + 2] == 0x99 && + vga_bios[address + 3] == 0x66) { + result = 1; + gvga6400_init(0, 0, 0); + } +#if 0 + munmap((caddr_t) vga_bios, 4096); + free(vga_bios); +#endif + close(mem_fd); + + return (result); +} + +static int gvga6400_saveregs(unsigned char regs[]) +{ + port_out_r(SEQ_I, 6); + regs[EXT + 2] = port_in(SEQ_D); + port_out_r(SEQ_I, 7); + regs[EXT + 3] = port_in(SEQ_D); + port_out_r(SEQ_I, 8); + regs[EXT + 4] = port_in(SEQ_D); + port_out_r(SEQ_I, 0x10); + regs[EXT + 5] = port_in(SEQ_D); + port_out_r(GRA_I, 9); + regs[EXT + 6] = port_in(GRA_D); + port_out_r(CRT_IC, 0x2f); + regs[EXT + 10] = port_in(CRT_DC); + + return (11); +} + +static void gvga6400_setregs(const unsigned char regs[], int mode) +{ + port_out_r(SEQ_I, 6); + port_out_r(SEQ_D, regs[EXT + 2]); + port_out_r(SEQ_I, 7); + port_out_r(SEQ_D, regs[EXT + 3]); + port_out_r(SEQ_I, 8); + port_out_r(SEQ_D, regs[EXT + 4]); + port_out_r(SEQ_I, 0x10); + port_out_r(SEQ_D, regs[EXT + 5]); + port_out_r(GRA_I, 9); + port_out_r(GRA_D, regs[EXT + 6]); + port_out_r(CRT_IC, 0x2f); + port_out_r(CRT_DC, regs[EXT + 10]); +} + +DriverSpecs __svgalib_gvga6400_driverspecs = +{ + gvga6400_saveregs, + gvga6400_setregs, + nothing, + nothing, + gvga6400_test, + gvga6400_init, + gvga6400_setpage, + gvga6400_setrdpage, + gvga6400_setwrpage, + gvga6400_setmode, + gvga6400_modeavailable, + gvga6400_setdisplaystart, + gvga6400_setlogicalwidth, + gvga6400_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int gvga6400_init(int force, int par1, int par2) +{ + if (__svgalib_driver_report) + fprintf(stderr,"Using Genoa GVGA 6400 driver.\n"); + __svgalib_driverspecs = &__svgalib_gvga6400_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + + return 0; +} diff --git a/src/drivers/i740.c b/src/drivers/i740.c new file mode 100644 index 0000000..c0d4986 --- /dev/null +++ b/src/drivers/i740.c @@ -0,0 +1,834 @@ +/* + i740 chipset driver + written by Matan Ziv-Av. + Only tested on a Hercules Terminator 2x/I + Interlaced modes don't work yet. +*/ +#include +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "i740_reg.h" +#include "vgammvgaio.h" + +typedef struct { + unsigned char DisplayControl; + unsigned char PixelPipeCfg0; + unsigned char PixelPipeCfg1; + unsigned char PixelPipeCfg2; + unsigned char VideoClk2_M; + unsigned char VideoClk2_N; + unsigned char VideoClk2_MN_MSBs; + unsigned char VideoClk2_DivisorSel; + unsigned char PLLControl; + unsigned char AddressMapping; + unsigned char IOControl; + unsigned char BitBLTControl; + unsigned char ExtVertTotal; + unsigned char ExtVertDispEnd; + unsigned char ExtVertSyncStart; + unsigned char ExtVertBlankStart; + unsigned char ExtHorizTotal; + unsigned char ExtHorizBlank; + unsigned char ExtOffset; + unsigned char InterlaceControl; + unsigned char ExtStartAddr; + unsigned char ExtStartAddrHi; + unsigned char CursorControl; + unsigned char CursorBaseAddrLo; + unsigned char CursorBaseAddrHi; + unsigned char CursorXLo; + unsigned char CursorXHi; + unsigned char CursorYLo; + unsigned char CursorYHi; + unsigned int LMI_FIFO_Watermark; +} vgaI740Rec, *vgaI740Ptr; + +#define I740REG_SAVE(i) (VGA_TOTAL_REGS+i) +#define I740_TOTAL_REGS (VGA_TOTAL_REGS + sizeof(vgaI740Rec)) + +static int i740_init(int, int, int); +static void i740_unlock(void); +static void i740_lock(void); + +static int i740_memory, I740HasSGRAM; +static unsigned int i740_linear_base, i740_mmio_base; + +static CardSpecs *cardspecs; + +static void i740_outxr_io(int index, int val) +{ + port_out(index, XRX); + port_out(val, XRX+1); +} + +static int i740_inxr_io(int index) +{ + port_out(index, XRX); + return port_in(XRX+1); +} + +static void i740_outxr_mm(int index, int val) +{ + v_writeb(index, __svgalib_vgammbase+XRX); + v_writeb(val, __svgalib_vgammbase+XRX+1); +} + +static int i740_inxr_mm(int index) +{ + v_writeb(index, __svgalib_vgammbase+XRX); + return v_readb(__svgalib_vgammbase+XRX+1); +} + +static void (*i740_outxr)(int,int)=i740_outxr_io; +static int (*i740_inxr)(int)=i740_inxr_io; + +static void i740_setpage(int page) +{ + i740_outxr(14,page); +} + +/* Fill in chipset specific mode information */ +static void i740_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = i740_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 8184; + modeinfo->startaddressrange = i740_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(i740_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int i740_saveregs(unsigned char regs[]) +{ + vgaI740Ptr save; + + i740_unlock(); + save = (vgaI740Ptr)(regs+VGA_TOTAL_REGS); + + save->IOControl=i740_inxr(IO_CTNL); + save->AddressMapping=i740_inxr(ADDRESS_MAPPING); + save->BitBLTControl=i740_inxr(BITBLT_CNTL); + save->VideoClk2_M=i740_inxr(VCLK2_VCO_M); + save->VideoClk2_N=i740_inxr(VCLK2_VCO_N); + save->VideoClk2_MN_MSBs=i740_inxr(VCLK2_VCO_MN_MSBS); + save->VideoClk2_DivisorSel=i740_inxr(VCLK2_VCO_DIV_SEL); + save->PLLControl=i740_inxr(PLL_CNTL); + + save->ExtVertTotal = __svgalib_incrtc(EXT_VERT_TOTAL); + save->ExtVertDispEnd = __svgalib_incrtc(EXT_VERT_DISPLAY); + save->ExtVertSyncStart = __svgalib_incrtc(EXT_VERT_SYNC_START); + save->ExtVertBlankStart = __svgalib_incrtc(EXT_VERT_BLANK_START); + save->ExtHorizTotal = __svgalib_incrtc(EXT_HORIZ_TOTAL); + save->ExtHorizBlank = __svgalib_incrtc(EXT_HORIZ_BLANK); + save->ExtOffset = __svgalib_incrtc(EXT_OFFSET); + save->InterlaceControl = __svgalib_incrtc(INTERLACE_CNTL); + save->ExtStartAddr = __svgalib_incrtc(EXT_START_ADDR); + save->ExtStartAddrHi = __svgalib_incrtc(EXT_START_ADDR_HI); + + save->PixelPipeCfg0=i740_inxr(PIXPIPE_CONFIG_0); + save->PixelPipeCfg1=i740_inxr(PIXPIPE_CONFIG_1); + save->PixelPipeCfg2=i740_inxr(PIXPIPE_CONFIG_2); + save->DisplayControl=i740_inxr(DISPLAY_CNTL); + + save->CursorControl=i740_inxr(CURSOR_CONTROL); + save->CursorBaseAddrHi=i740_inxr(CURSOR_BASEADDR_HI); + save->CursorBaseAddrLo=i740_inxr(CURSOR_BASEADDR_LO); + save->CursorXHi=i740_inxr(CURSOR_X_HI); + save->CursorXLo=i740_inxr(CURSOR_X_LO); + save->CursorYHi=i740_inxr(CURSOR_Y_HI); + save->CursorYLo=i740_inxr(CURSOR_Y_LO); + + save->LMI_FIFO_Watermark = INREG(FWATER_BLC); + + return I740_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void i740_setregs(const unsigned char regs[], int mode) +{ + int temp; + vgaI740Ptr restore; + + i740_unlock(); + restore = (vgaI740Ptr)(regs+VGA_TOTAL_REGS); + + i740_outxr(DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE); + + usleep(1000); /* Wait 1 ms */ + + /* Write the M, N and P values */ + i740_outxr(VCLK2_VCO_M, restore->VideoClk2_M); + i740_outxr(VCLK2_VCO_N, restore->VideoClk2_N); + i740_outxr(VCLK2_VCO_MN_MSBS, restore->VideoClk2_MN_MSBs); + i740_outxr(VCLK2_VCO_DIV_SEL, restore->VideoClk2_DivisorSel); + + temp = i740_inxr(PIXPIPE_CONFIG_0); + temp &= ~(DAC_8_BIT | HW_CURSOR_ENABLE); + temp |= (restore->PixelPipeCfg0 & (DAC_8_BIT | HW_CURSOR_ENABLE)); + i740_outxr(PIXPIPE_CONFIG_0, temp); + + __svgalib_outcrtc(EXT_VERT_TOTAL, restore->ExtVertTotal); + + __svgalib_outcrtc(EXT_VERT_DISPLAY, restore->ExtVertDispEnd); + + __svgalib_outcrtc(EXT_VERT_SYNC_START, restore->ExtVertSyncStart); + + __svgalib_outcrtc(EXT_VERT_BLANK_START, restore->ExtVertBlankStart); + + __svgalib_outcrtc(EXT_HORIZ_TOTAL, restore->ExtHorizTotal); + + __svgalib_outcrtc(EXT_HORIZ_BLANK, restore->ExtHorizBlank); + + __svgalib_outcrtc(EXT_OFFSET, restore->ExtOffset); + + __svgalib_outcrtc(EXT_START_ADDR, restore->ExtStartAddr); + __svgalib_outcrtc(EXT_START_ADDR_HI, restore->ExtStartAddrHi); + + i740_outxr(CURSOR_CONTROL,restore->CursorControl); + i740_outxr(CURSOR_BASEADDR_HI,restore->CursorBaseAddrHi); + i740_outxr(CURSOR_BASEADDR_LO,restore->CursorBaseAddrLo); + i740_outxr(CURSOR_X_HI,restore->CursorXHi); + i740_outxr(CURSOR_X_LO,restore->CursorXLo); + i740_outxr(CURSOR_Y_HI,restore->CursorYHi); + i740_outxr(CURSOR_Y_LO,restore->CursorYLo); + + temp=__svgalib_incrtc(INTERLACE_CNTL); + temp &= ~INTERLACE_ENABLE; + temp |= restore->InterlaceControl; + __svgalib_outcrtc(INTERLACE_CNTL, temp); + + temp = i740_inxr(ADDRESS_MAPPING); + temp &= 0xE0; /* Save reserved bits 7:5 */ + temp |= restore->AddressMapping; + i740_outxr(ADDRESS_MAPPING, temp); + + temp = i740_inxr(IO_CTNL); + temp &= ~(EXTENDED_ATTR_CNTL|EXTENDED_CRTC_CNTL); + temp |= restore->IOControl; + i740_outxr(IO_CTNL, temp); + + temp = i740_inxr(BITBLT_CNTL); + temp &= ~COLEXP_MODE; + temp |= restore->BitBLTControl; + i740_outxr(BITBLT_CNTL, temp); + + temp = i740_inxr(DISPLAY_CNTL); + temp &= ~(VGA_WRAP_MODE | GUI_MODE); + temp |= restore->DisplayControl; + i740_outxr(DISPLAY_CNTL, temp); + + temp = i740_inxr(PIXPIPE_CONFIG_0); + temp &= 0x64; /* Save reserved bits 6:5,2 */ + temp |= restore->PixelPipeCfg0; + i740_outxr(PIXPIPE_CONFIG_0, temp); + + temp = i740_inxr(PIXPIPE_CONFIG_2); + temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ + temp |= restore->PixelPipeCfg2; + i740_outxr(PIXPIPE_CONFIG_2, temp); + + temp = i740_inxr(PLL_CNTL); + temp &= ~PLL_MEMCLK_SEL; +#if 1 + temp = restore->PLLControl; /* To fix the 2.3X BIOS problem */ +#else + temp |= restore->PLLControl; +#endif + i740_outxr(PLL_CNTL, temp); + + temp = i740_inxr(PIXPIPE_CONFIG_1); + temp &= ~DISPLAY_COLOR_MODE; + temp |= restore->PixelPipeCfg1; + i740_outxr(PIXPIPE_CONFIG_1, temp); + + temp = INREG(FWATER_BLC); + temp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK); + temp |= restore->LMI_FIFO_Watermark; + OUTREG(FWATER_BLC, temp); + + /* Turn on DRAM Refresh */ + i740_outxr(DRAM_EXT_CNTL, DRAM_REFRESH_60HZ); + + usleep(50000); + +} + +/* Return nonzero if mode is available */ + +static int i740_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (i740_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +static unsigned int I740CalcFIFO(double freq, int bpp) +{ + /* + * Would like to calculate these values automatically, but a generic + * algorithm does not seem possible. Note: These FIFO water mark + * values were tested on several cards and seem to eliminate the + * all of the snow and vertical banding, but fine adjustments will + * probably be required for other cards. + */ + + unsigned int wm = 0x18120000; + + switch (bpp) { + case 8: + if (I740HasSGRAM) { + if (freq > 200) wm = 0x18120000; + else if (freq > 175) wm = 0x16110000; + else if (freq > 135) wm = 0x120E0000; + else wm = 0x100D0000; + } else { + if (freq > 200) wm = 0x18120000; + else if (freq > 175) wm = 0x16110000; + else if (freq > 135) wm = 0x120E0000; + else wm = 0x100D0000; + } + break; + case 16: + if (I740HasSGRAM) { + if (freq > 140) wm = 0x2C1D0000; + else if (freq > 120) wm = 0x2C180000; + else if (freq > 100) wm = 0x24160000; + else if (freq > 90) wm = 0x18120000; + else if (freq > 50) wm = 0x16110000; + else if (freq > 32) wm = 0x13100000; + else wm = 0x120E0000; + } else { + if (freq > 160) wm = 0x28200000; + else if (freq > 140) wm = 0x2A1E0000; + else if (freq > 130) wm = 0x2B1A0000; + else if (freq > 120) wm = 0x2C180000; + else if (freq > 100) wm = 0x24180000; + else if (freq > 90) wm = 0x18120000; + else if (freq > 50) wm = 0x16110000; + else if (freq > 32) wm = 0x13100000; + else wm = 0x120E0000; + } + break; + case 24: + if (I740HasSGRAM) { + if (freq > 130) wm = 0x31200000; + else if (freq > 120) wm = 0x2E200000; + else if (freq > 100) wm = 0x2C1D0000; + else if (freq > 80) wm = 0x25180000; + else if (freq > 64) wm = 0x24160000; + else if (freq > 49) wm = 0x18120000; + else if (freq > 32) wm = 0x16110000; + else wm = 0x13100000; + } else { + if (freq > 120) wm = 0x311F0000; + else if (freq > 100) wm = 0x2C1D0000; + else if (freq > 80) wm = 0x25180000; + else if (freq > 64) wm = 0x24160000; + else if (freq > 49) wm = 0x18120000; + else if (freq > 32) wm = 0x16110000; + else wm = 0x13100000; + } + break; + case 32: + if (I740HasSGRAM) { + if (freq > 80) wm = 0x2A200000; + else if (freq > 60) wm = 0x281A0000; + else if (freq > 49) wm = 0x25180000; + else if (freq > 32) wm = 0x18120000; + else wm = 0x16110000; + } else { + if (freq > 80) wm = 0x29200000; + else if (freq > 60) wm = 0x281A0000; + else if (freq > 49) wm = 0x25180000; + else if (freq > 32) wm = 0x18120000; + else wm = 0x16110000; + } + break; + } + + return wm; +} + +#define MAX_VCO_FREQ 450.0 +#define TARGET_MAX_N 30 +#define REF_FREQ 66.66666666667 + +#define CALC_VCLK(m,n,p,d) \ + (double)m / ((double)n * (1 << p)) * (4 << (d << 1)) * REF_FREQ + +static void +I740CalcVCLK(double freq ,int *M, int *N, int *MN, int *DIVSEL ) +{ + int m, n, p, d; + double f_out; + double f_err; + double f_vco; + int m_best = 0, n_best = 0, p_best = 0, d_best = 0; + double f_target = freq; + double err_max = 0.005; + double err_target = 0.001; + double err_best = 999999.0; + + p_best = p = log(MAX_VCO_FREQ/f_target)/log((double)2); + d_best = d = 0; + + f_vco = f_target * (1 << p); + + n = 2; + do { + n++; + m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5; + if (m < 3) m = 3; + f_out = CALC_VCLK(m,n,p,d); + f_err = 1.0 - (f_target/f_out); + if (fabs(f_err) < err_max) { + m_best = m; + n_best = n; + err_best = f_err; + } + } while ((fabs(f_err) >= err_target) && + ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max))); + + if (fabs(f_err) < err_target) { + m_best = m; + n_best = n; + } + + *M = (m_best-2) & 0xFF; + *N = (n_best-2) & 0xFF; + *MN = ((((n_best-2) >> 4) & VCO_N_MSBS) | + (((m_best-2) >> 8) & VCO_M_MSBS)); + *DIVSEL= ((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1); + +#if 0 + fprintf(stderr,"Setting dot clock to %.6lf MHz " + "[ %02X %02X %02X ] " + "[ %d %d %d %d ]\n", + CALC_VCLK(m_best,n_best,p_best,d_best), + new->VideoClk2_M, + new->VideoClk2_N, + new->VideoClk2_DivisorSel, + m_best, n_best, p_best, d_best); +#endif +} + +/* Local, called by i740_setmode(). */ +static void i740_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + vgaI740Ptr new; + int n, m, mn, divsel; + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + new = (vgaI740Ptr)(moderegs+VGA_TOTAL_REGS); + + moderegs[0x13] = modeinfo->lineWidth >> 3; + new->ExtOffset = modeinfo->lineWidth >> 11; + + switch (modeinfo->bitsPerPixel) { + case 8: + new->PixelPipeCfg1 = DISPLAY_8BPP_MODE; + break; + case 15: + case 16: + if (modeinfo->greenWeight == 5) { + new->PixelPipeCfg1 = DISPLAY_15BPP_MODE; + } else { + new->PixelPipeCfg1 = DISPLAY_16BPP_MODE; + } + break; + case 24: + new->PixelPipeCfg1 = DISPLAY_24BPP_MODE; + break; + case 32: + new->PixelPipeCfg1 = DISPLAY_32BPP_MODE; + break; + default: + break; + } + + if (modeinfo->bitsPerPixel>8) + new->PixelPipeCfg0 = DAC_8_BIT; + else + new->PixelPipeCfg0 = DAC_6_BIT; + + new->PixelPipeCfg2 = 0; + + /* Turn on Extended VGA Interpretation */ + new->IOControl = EXTENDED_CRTC_CNTL; + + /* Turn on linear and page mapping */ + new->AddressMapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE; + + /* Turn on GUI mode */ + new->DisplayControl = HIRES_MODE; + + /* Set the MCLK freq */ + if (0) + new->PLLControl = PLL_MEMCLK__66667KHZ; /* 66 MHz */ + else + new->PLLControl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */ + + /* Calculate the extended CRTC regs */ + new->ExtVertTotal = (modetiming->CrtcVTotal - 2) >> 8; + new->ExtVertDispEnd = (modetiming->CrtcVDisplay - 1) >> 8; + new->ExtVertSyncStart = modetiming->CrtcVSyncStart >> 8; + new->ExtVertBlankStart = modetiming->CrtcVSyncStart >> 8; + new->ExtHorizTotal = ((modetiming->CrtcHTotal >> 3) - 5) >> 8; + new->ExtHorizBlank = ((modetiming->CrtcHSyncEnd >> 3) & 0x40) >> 6; + + /* Turn on interlaced mode if necessary */ + if (modetiming->flags & INTERLACED) + new->InterlaceControl = INTERLACE_ENABLE; + else + new->InterlaceControl = INTERLACE_DISABLE; + + moderegs[0x11] = 0; + + I740CalcVCLK(modetiming->pixelClock/1000, &m, &n, &mn, &divsel); + + new->VideoClk2_M = m; + new->VideoClk2_N = n; + new->VideoClk2_MN_MSBs = mn; + new->VideoClk2_DivisorSel = divsel; + + /* Since we program the clocks ourselves, always use VCLK2. */ + moderegs[59] |= 0x0C; + + new->ExtStartAddr=0; + new->ExtStartAddrHi=0; + + /* Calculate the FIFO Watermark and Burst Length. */ + new->LMI_FIFO_Watermark = I740CalcFIFO(modetiming->pixelClock/1000,modeinfo->bitsPerPixel); + + new->CursorControl= CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_32_4C_AX; + + return ; +} + + +static int i740_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!i740_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(I740_TOTAL_REGS); + + i740_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + i740_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void i740_unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + +} + +static void i740_lock(void) +{ +} + + +#define VENDOR_ID 0x8086 +#define I740_ID_PCI 0x00d1 +#define I740_ID_AGP 0x7800 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int i740_test(void) +{ + int found; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if(found&& + ((((buf[0]>>16)&0xffff)==I740_ID_PCI)|| + (((buf[0]>>16)&0xffff)==I740_ID_AGP))){ + i740_init(0,0,0); + return 1; + }; + + return 0; +} + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void i740_setdisplaystart(int address) +{ + address=address >> 2; + __svgalib_outcrtc(0x0c, address & 0xFF00); + __svgalib_outcrtc(0x0d, address & 0x00FF); + __svgalib_outcrtc(EXT_START_ADDR_HI,(address&0x3fc00000)>>22); + __svgalib_outcrtc(EXT_START_ADDR,((address&0x3f0000)>>16)|EXT_START_ADDR_ENABLE); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void i740_setlogicalwidth(int width) +{ + int offset = width >> 3; + + __svgalib_outcrtc(0x13,offset&0xff); + __svgalib_outcrtc(EXT_OFFSET, offset>>8); +} + +static int i740_linear(int op, int param) +{ + if (op==LINEAR_DISABLE || op==LINEAR_ENABLE) return 0; + if (op==LINEAR_QUERY_BASE) return __svgalib_linear_mem_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static unsigned char cur_colors[16*6]; + +static int i740_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j, tmp; + unsigned int *b3; + unsigned int l1, l2, l3, l4; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + i740_outxr(PIXPIPE_CONFIG_0,i740_inxr(PIXPIPE_CONFIG_0)&~HW_CURSOR_ENABLE); + break; + case CURSOR_SHOW: + i740_outxr(PIXPIPE_CONFIG_0,i740_inxr(PIXPIPE_CONFIG_0)|HW_CURSOR_ENABLE); + break; + case CURSOR_POSITION: + i740_outxr(CURSOR_X_LO,p1&0xff); + i740_outxr(CURSOR_X_HI,(p1&0x700)>>8); + i740_outxr(CURSOR_Y_LO,p2&0xff); + i740_outxr(CURSOR_Y_HI,(p2&0x700)>>8); + break; + case CURSOR_SELECT: + i=i740_memory*1024-(p1+1)*4096; + if(i>4096*1024)i-=4096*1024; + tmp=i740_inxr(PIXPIPE_CONFIG_0); + i740_outxr(PIXPIPE_CONFIG_0,tmp| EXTENDED_PALETTE); + __svgalib_outpal(4,cur_colors[p1*6],cur_colors[p1*6+1],cur_colors[p1*6+2]); + __svgalib_outpal(5,cur_colors[p1*6+3],cur_colors[p1*6+4],cur_colors[p1*6+5]); + i740_outxr(PIXPIPE_CONFIG_0,tmp); + i740_outxr(CURSOR_BASEADDR_LO,i>>8); + i740_outxr(CURSOR_BASEADDR_HI,i>>16); + break; + case CURSOR_IMAGE: + i=i740_memory*1024-(p1+1)*4096; + if(i>4096*1024)i-=4096*1024; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*6]=(p3&0xff0000)>>16; + cur_colors[p1*6+1]=(p3&0xff00)>>8; + cur_colors[p1*6+2]=p3&0xff; + cur_colors[p1*6+3]=(p4&0xff0000)>>16; + cur_colors[p1*6+4]=(p4&0xff00)>>8; + cur_colors[p1*6+5]=p4&0xff; + for(j=0;j<16;j++) { + l1=*(b3+2*j); + l2=~(*(b3+32+2*j)); + l3=*(b3+2*j+1); + l4=~(*(b3+32+2*j+1)); + /*change endianess */ + l1=(l1<<24)|(l1>>24)|((l1>>8)&0xff00)|((l1<<8)&0xff0000); + l2=(l2<<24)|(l2>>24)|((l2>>8)&0xff00)|((l2<<8)&0xff0000); + l3=(l3<<24)|(l3>>24)|((l3>>8)&0xff00)|((l3<<8)&0xff0000); + l4=(l4<<24)|(l4>>24)|((l4>>8)&0xff00)|((l4<<8)&0xff0000); + *(unsigned int *)(LINEAR_POINTER+i+16*j)=l2; + *(unsigned int *)(LINEAR_POINTER+i+16*j+4)=l4; + *(unsigned int *)(LINEAR_POINTER+i+16*j+8)=l1; + *(unsigned int *)(LINEAR_POINTER+i+16*j+12)=l3; + } + break; + } + break; + } + return 0; +} + +static int i740_match_programmable_clock(int clock) +{ +return clock ; +} + +static int i740_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int i740_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_i740_driverspecs = +{ + i740_saveregs, + i740_setregs, + i740_unlock, + i740_lock, + i740_test, + i740_init, + i740_setpage, + NULL, + NULL, + i740_setmode, + i740_modeavailable, + i740_setdisplaystart, + i740_setlogicalwidth, + i740_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + i740_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + i740_cursor +}; + +/* Initialize chipset (called after detection) */ +static int i740_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + int temp; + + i740_inxr=i740_inxr_io; + i740_outxr=i740_outxr_io; + + i740_unlock(); + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + i740_linear_base=0; + if(found&&((((buf[0]>>16)&0xffff)==I740_ID_PCI)||(((buf[0]>>16)&0xffff)==I740_ID_AGP))){ + i740_linear_base=buf[4]&0xffffff00; + i740_mmio_base=buf[5]&0xffffff00; + }; + + __svgalib_mmio_base=i740_mmio_base; + __svgalib_mmio_size=512*0x400; + map_mmio(); + + __svgalib_vgammbase=0; + __svgalib_mm_io_mapio(); + + i740_inxr=i740_inxr_mm; + i740_outxr=i740_outxr_mm; + + if (force) { + i740_memory = par1; +/* i740_chiptype = par2;*/ + } else { + if((i740_inxr(DRAM_ROW_TYPE)&DRAM_ROW_1) == DRAM_ROW_1_SDRAM) + i740_memory=i740_inxr(DRAM_ROW_BNDRY_1)*1024; else + i740_memory=i740_inxr(DRAM_ROW_BNDRY_0)*1024; + }; + + temp=i740_inxr(DRAM_ROW_CNTL_LO); + I740HasSGRAM = !((temp & DRAM_RAS_TIMING) || (temp & DRAM_RAS_PRECHARGE)); + + if (__svgalib_driver_report) { + fprintf(stderr,"Using I740 driver, %iKB.\n",i740_memory); + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = i740_memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 203000; + cardspecs->maxPixelClock16bpp = 163000; + cardspecs->maxPixelClock24bpp = 128000; + cardspecs->maxPixelClock32bpp = 86000; + cardspecs->flags = CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = i740_map_clock; + cardspecs->mapHorizontalCrtc = i740_map_horizontal_crtc; + cardspecs->matchProgrammableClock=i740_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_i740_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=i740_linear_base; + __svgalib_linear_mem_size=i740_memory*0x400; + return 0; +} diff --git a/src/drivers/i740_reg.h b/src/drivers/i740_reg.h new file mode 100644 index 0000000..d51e3ce --- /dev/null +++ b/src/drivers/i740_reg.h @@ -0,0 +1,330 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/i740/i740_reg.h,v 1.1.2.1 1999/04/15 11:40:36 hohndel Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin + * + * $PI: i740_reg.h,v 1.8 1999/02/18 20:50:59 martin Exp martin $ + */ + +#define INREG(addr) v_readl(addr) +#define OUTREG(addr, val) v_writel(val, addr) + +/* I/O register offsets */ +#define SRX SEQ_I +#define GRX GRA_I +#define ARX ATT_IW +#define XRX 0x3D6 +#define MRX 0x3D2 + +/* VGA Color Palette Registers */ +#define DACMASK 0x3C6 +#define DACSTATE 0x3C7 +#define DACRX 0x3C7 +#define DACWX 0x3C8 +#define DACDATA 0x3C9 + +/* CRT Controller Registers (CRX) */ +#define START_ADDR_HI 0x0C +#define START_ADDR_LO 0x0D +#define VERT_SYNC_END 0x11 +#define EXT_VERT_TOTAL 0x30 +#define EXT_VERT_DISPLAY 0x31 +#define EXT_VERT_SYNC_START 0x32 +#define EXT_VERT_BLANK_START 0x33 +#define EXT_HORIZ_TOTAL 0x35 +#define EXT_HORIZ_BLANK 0x39 +#define EXT_START_ADDR 0x40 +#define EXT_START_ADDR_ENABLE 0x80 +#define EXT_OFFSET 0x41 +#define EXT_START_ADDR_HI 0x42 +#define INTERLACE_CNTL 0x70 +#define INTERLACE_ENABLE 0x80 +#define INTERLACE_DISABLE 0x00 + +/* Miscellaneous Output Register */ +#define MSR_R 0x3CC +#define MSR_W 0x3C2 +#define IO_ADDR_SELECT 0x01 + +#define MDA_BASE 0x3B0 +#define CGA_BASE 0x3D0 + +/* System Configuration Extension Registers (XRX) */ +#define IO_CTNL 0x09 +#define EXTENDED_ATTR_CNTL 0x02 +#define EXTENDED_CRTC_CNTL 0x01 + +#define ADDRESS_MAPPING 0x0A +#define PACKED_MODE_ENABLE 0x04 +#define LINEAR_MODE_ENABLE 0x02 +#define PAGE_MAPPING_ENABLE 0x01 + +#define BITBLT_CNTL 0x20 +#define COLEXP_MODE 0x30 +#define COLEXP_8BPP 0x00 +#define COLEXP_16BPP 0x10 +#define COLEXP_24BPP 0x20 +#define COLEXP_RESERVED 0x30 +#define CHIP_RESET 0x02 +#define BITBLT_STATUS 0x01 + +#define DISPLAY_CNTL 0x40 +#define VGA_WRAP_MODE 0x02 +#define VGA_WRAP_AT_256KB 0x00 +#define VGA_NO_WRAP 0x02 +#define GUI_MODE 0x01 +#define STANDARD_VGA_MODE 0x00 +#define HIRES_MODE 0x01 + +#define DRAM_ROW_TYPE 0x50 +#define DRAM_ROW_0 0x07 +#define DRAM_ROW_0_SDRAM 0x00 +#define DRAM_ROW_0_EMPTY 0x07 +#define DRAM_ROW_1 0x38 +#define DRAM_ROW_1_SDRAM 0x00 +#define DRAM_ROW_1_EMPTY 0x38 +#define DRAM_ROW_CNTL_LO 0x51 +#define DRAM_CAS_LATENCY 0x10 +#define DRAM_RAS_TIMING 0x08 +#define DRAM_RAS_PRECHARGE 0x04 +#define DRAM_ROW_CNTL_HI 0x52 +#define DRAM_EXT_CNTL 0x53 +#define DRAM_REFRESH_RATE 0x03 +#define DRAM_REFRESH_DISABLE 0x00 +#define DRAM_REFRESH_60HZ 0x01 +#define DRAM_REFRESH_FAST_TEST 0x02 +#define DRAM_REFRESH_RESERVED 0x03 +#define DRAM_TIMING 0x54 +#define DRAM_ROW_BNDRY_0 0x55 +#define DRAM_ROW_BNDRY_1 0x56 + +#define DPMS_SYNC_SELECT 0x61 +#define VSYNC_CNTL 0x08 +#define VSYNC_ON 0x00 +#define VSYNC_OFF 0x08 +#define HSYNC_CNTL 0x02 +#define HSYNC_ON 0x00 +#define HSYNC_OFF 0x02 + +#define PIXPIPE_CONFIG_0 0x80 +#define DAC_8_BIT 0x80 +#define DAC_6_BIT 0x00 +#define HW_CURSOR_ENABLE 0x10 +#define EXTENDED_PALETTE 0x01 + +#define PIXPIPE_CONFIG_1 0x81 +#define DISPLAY_COLOR_MODE 0x0F +#define DISPLAY_VGA_MODE 0x00 +#define DISPLAY_8BPP_MODE 0x02 +#define DISPLAY_15BPP_MODE 0x04 +#define DISPLAY_16BPP_MODE 0x05 +#define DISPLAY_24BPP_MODE 0x06 +#define DISPLAY_32BPP_MODE 0x07 + +#define PIXPIPE_CONFIG_2 0x82 +#define DISPLAY_GAMMA_ENABLE 0x08 +#define DISPLAY_GAMMA_DISABLE 0x00 +#define OVERLAY_GAMMA_ENABLE 0x04 +#define OVERLAY_GAMMA_DISABLE 0x00 + +#define CURSOR_CONTROL 0xA0 +#define CURSOR_ORIGIN_SCREEN 0x00 +#define CURSOR_ORIGIN_DISPLAY 0x10 +#define CURSOR_MODE 0x07 +#define CURSOR_MODE_DISABLE 0x00 +#define CURSOR_MODE_32_4C_AX 0x01 +#define CURSOR_MODE_128_2C 0x02 +#define CURSOR_MODE_128_1C 0x03 +#define CURSOR_MODE_64_3C 0x04 +#define CURSOR_MODE_64_4C_AX 0x05 +#define CURSOR_MODE_64_4C 0x06 +#define CURSOR_MODE_RESERVED 0x07 +#define CURSOR_BASEADDR_LO 0xA2 +#define CURSOR_BASEADDR_HI 0xA3 +#define CURSOR_X_LO 0xA4 +#define CURSOR_X_HI 0xA5 +#define CURSOR_X_POS 0x00 +#define CURSOR_X_NEG 0x80 +#define CURSOR_Y_LO 0xA6 +#define CURSOR_Y_HI 0xA7 +#define CURSOR_Y_POS 0x00 +#define CURSOR_Y_NEG 0x80 + +#define VCLK2_VCO_M 0xC8 +#define VCLK2_VCO_N 0xC9 +#define VCLK2_VCO_MN_MSBS 0xCA +#define VCO_N_MSBS 0x30 +#define VCO_M_MSBS 0x03 +#define VCLK2_VCO_DIV_SEL 0xCB +#define POST_DIV_SELECT 0x70 +#define POST_DIV_1 0x00 +#define POST_DIV_2 0x10 +#define POST_DIV_4 0x20 +#define POST_DIV_8 0x30 +#define POST_DIV_16 0x40 +#define POST_DIV_32 0x50 +#define VCO_LOOP_DIV_BY_4M 0x00 +#define VCO_LOOP_DIV_BY_16M 0x04 +#define REF_CLK_DIV_BY_5 0x02 +#define REF_DIV_4 0x00 +#define REF_DIV_1 0x01 + +#define PLL_CNTL 0xCE +#define PLL_MEMCLK_SEL 0x03 +#define PLL_MEMCLK__66667KHZ 0x00 +#define PLL_MEMCLK__75000KHZ 0x01 +#define PLL_MEMCLK__88889KHZ 0x02 +#define PLL_MEMCLK_100000KHZ 0x03 + +/* Multimedia Extension Registers (MRX) */ +#define ACQ_CNTL_1 0x02 +#define ACQ_CNTL_2 0x03 +#define FRAME_CAP_MODE 0x01 +#define CONT_CAP_MODE 0x00 +#define SINGLE_CAP_MODE 0x01 +#define ACQ_CNTL_3 0x04 +#define COL_KEY_CNTL_1 0x3C +#define BLANK_DISP_OVERLAY 0x20 + +/* FIFOs */ +#define LP_FIFO 0x1000 +#define HP_FIFO 0x2000 +#define INSTPNT 0x3040 +#define LP_FIFO_COUNT 0x3040 +#define HP_FIFO_COUNT 0x3041 + +/* FIFO Commands */ +#define CLIENT 0xE0000000 +#define CLIENT_2D 0x60000000 + +/* Command Parser Mode Register */ +#define COMPARS 0x3038 +#define TWO_D_INST_DISABLE 0x08 +#define THREE_D_INST_DISABLE 0x04 +#define STATE_VAR_UPDATE_DISABLE 0x02 +#define PAL_STIP_DISABLE 0x01 + +/* Interrupt Control Registers */ +#define IER 0x3030 +#define IIR 0x3032 +#define IMR 0x3034 +#define ISR 0x3036 +#define VMIINTB_EVENT 0x2000 +#define GPIO4_INT 0x1000 +#define DISP_FLIP_EVENT 0x0800 +#define DVD_PORT_DMA 0x0400 +#define DISP_VBLANK 0x0200 +#define FIFO_EMPTY_DMA_DONE 0x0100 +#define INST_PARSER_ERROR 0x0080 +#define USER_DEFINED 0x0040 +#define BREAKPOINT 0x0020 +#define DISP_HORIZ_COUNT 0x0010 +#define DISP_VSYNC 0x0008 +#define CAPTURE_HORIZ_COUNT 0x0004 +#define CAPTURE_VSYNC 0x0002 +#define THREE_D_PIPE_FLUSHED 0x0001 + +/* FIFO Watermark and Burst Length Control Register */ +#define FWATER_BLC 0x00006000 +#define LMI_BURST_LENGTH 0x7F000000 +#define LMI_FIFO_WATERMARK 0x003F0000 +#define AGP_BURST_LENGTH 0x00007F00 +#define AGP_FIFO_WATERMARK 0x0000003F + +/* BitBLT Registers */ +#define SRC_DST_PITCH 0x00040000 +#define DST_PITCH 0x1FFF0000 +#define SRC_PITCH 0x00001FFF +#define COLEXP_BG_COLOR 0x00040004 +#define COLEXP_FG_COLOR 0x00040008 +#define MONO_SRC_CNTL 0x0004000C +#define MONO_USE_COLEXP 0x00000000 +#define MONO_USE_SRCEXP 0x08000000 +#define MONO_DATA_ALIGN 0x07000000 +#define MONO_BIT_ALIGN 0x01000000 +#define MONO_BYTE_ALIGN 0x02000000 +#define MONO_WORD_ALIGN 0x03000000 +#define MONO_DWORD_ALIGN 0x04000000 +#define MONO_QWORD_ALIGN 0x05000000 +#define MONO_SRC_INIT_DSCRD 0x003F0000 +#define MONO_SRC_RIGHT_CLIP 0x00003F00 +#define MONO_SRC_LEFT_CLIP 0x0000003F +#define BITBLT_CONTROL 0x00040010 +#define BLTR_STATUS 0x80000000 +#define DYN_DEPTH 0x03000000 +#define DYN_DEPTH_8BPP 0x00000000 +#define DYN_DEPTH_16BPP 0x01000000 +#define DYN_DEPTH_24BPP 0x02000000 +#define DYN_DEPTH_32BPP 0x03000000 /* Not implemented on the i740 */ +#define DYN_DEPTH_ENABLE 0x00800000 +#define PAT_VERT_ALIGN 0x00700000 +#define SOLID_PAT_SELECT 0x00080000 +#define PAT_IS_IN_COLOR 0x00000000 +#define PAT_IS_MONO 0x00040000 +#define MONO_PAT_TRANSP 0x00020000 +#define COLOR_TRANSP_ROP 0x00000000 +#define COLOR_TRANSP_DST 0x00008000 +#define COLOR_TRANSP_EQ 0x00000000 +#define COLOR_TRANSP_NOT_EQ 0x00010000 +#define COLOR_TRANSP_ENABLE 0x00004000 +#define MONO_SRC_TRANSP 0x00002000 +#define SRC_IS_IN_COLOR 0x00000000 +#define SRC_IS_MONO 0x00001000 +#define SRC_USE_SRC_ADDR 0x00000000 +#define SRC_USE_BLTDATA 0x00000400 +#define BLT_TOP_TO_BOT 0x00000000 +#define BLT_BOT_TO_TOP 0x00000200 +#define BLT_LEFT_TO_RIGHT 0x00000000 +#define BLT_RIGHT_TO_LEFT 0x00000100 +#define BLT_ROP 0x000000FF +#define BLT_PAT_ADDR 0x00040014 +#define BLT_SRC_ADDR 0x00040018 +#define BLT_DST_ADDR 0x0004001C +#define BLT_DST_H_W 0x00040020 +#define BLT_DST_HEIGHT 0x1FFF0000 +#define BLT_DST_WIDTH 0x00001FFF +#define SRCEXP_BG_COLOR 0x00040024 +#define SRCEXP_FG_COLOR 0x00040028 +#define BLTDATA 0x00050000 + +typedef struct { + unsigned int cmd; + unsigned int BR00; + unsigned int BR01; + unsigned int BR02; + unsigned int BR03; + unsigned int BR04; + unsigned int BR05; + unsigned int BR06; + unsigned int BR07; + unsigned int BR09; + unsigned int BR0A; + unsigned int BR08; +} GFX2DOPREG_BLTER_FULL_LOAD; diff --git a/src/drivers/i810.c b/src/drivers/i810.c new file mode 100644 index 0000000..0cbb339 --- /dev/null +++ b/src/drivers/i810.c @@ -0,0 +1,749 @@ +/* + i810 chipset driver + written by Matan Ziv-Av. +*/ + +#include +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "i810_reg.h" +#include "i810_wmark.c" +#include "vgammvgaio.h" +#include +#include "svgalib_helper.h" + +int __svgalib_i810_usegtt=1; + +typedef struct { +/* 00 */ + unsigned char DisplayControl; + unsigned char PixelPipeCfg0; + unsigned char PixelPipeCfg1; + unsigned char PixelPipeCfg2; + unsigned short VideoClk2_M; + unsigned short VideoClk2_N; +/* 08 */ + unsigned char VideoClk2_DivisorSel; + + unsigned char AddressMapping; + unsigned char IOControl; + unsigned char BitBLTControl; + + unsigned char ExtVertTotal; + unsigned char ExtVertDispEnd; + unsigned char ExtVertSyncStart; + unsigned char ExtVertBlankStart; +/* 10 */ + unsigned char ExtHorizTotal; + unsigned char ExtHorizBlank; + unsigned char ExtOffset; + unsigned char InterlaceControl; + unsigned char ExtStartAddr; + unsigned char ExtStartAddrHi; + + unsigned short CursorControl; +/* 18 */ + unsigned int CursorBaseAddr; + unsigned char CursorXLo; + unsigned char CursorXHi; + unsigned char CursorYLo; + unsigned char CursorYHi; +/* 20 */ + unsigned int LMI_FIFO_Watermark; +} vgaI810Rec, *vgaI810Ptr; + +#define I810REG_SAVE(i) (VGA_TOTAL_REGS+i) +#define I810_TOTAL_REGS (VGA_TOTAL_REGS + sizeof(vgaI810Rec)) + +static int init(int, int, int); +static void unlock(void); +static void lock(void); + +static int memory, lmfreq; +static unsigned int linear_base, mmio_base; +static unsigned int cur_base; +static CardSpecs *cardspecs; + +static void setpage(int page) +{ + __svgalib_outgra(0x11,page); +} + +/* Fill in chipset specific mode information */ +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 8184; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(__svgalib_i810_usegtt) { + if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } + } +} + +/* Read and save chipset-specific registers */ + +static int saveregs(unsigned char regs[]) +{ + vgaI810Ptr save; + + unlock(); + save = (vgaI810Ptr)(regs+VGA_TOTAL_REGS); + + save->IOControl=__svgalib_incrtc(IO_CTNL); + save->AddressMapping=__svgalib_ingra(ADDRESS_MAPPING); + save->BitBLTControl=INREG8(BITBLT_CNTL); + save->VideoClk2_M=INREG16(VCLK2_VCO_M); + save->VideoClk2_N=INREG16(VCLK2_VCO_N); + save->VideoClk2_DivisorSel=INREG8(VCLK2_VCO_DIV_SEL); + + save->ExtVertTotal = __svgalib_incrtc(EXT_VERT_TOTAL); + save->ExtVertDispEnd = __svgalib_incrtc(EXT_VERT_DISPLAY); + save->ExtVertSyncStart = __svgalib_incrtc(EXT_VERT_SYNC_START); + save->ExtVertBlankStart = __svgalib_incrtc(EXT_VERT_BLANK_START); + save->ExtHorizTotal = __svgalib_incrtc(EXT_HORIZ_TOTAL); + save->ExtHorizBlank = __svgalib_incrtc(EXT_HORIZ_BLANK); + save->ExtOffset = __svgalib_incrtc(EXT_OFFSET); + save->InterlaceControl = __svgalib_incrtc(INTERLACE_CNTL); + save->ExtStartAddr = __svgalib_incrtc(EXT_START_ADDR); + save->ExtStartAddrHi = __svgalib_incrtc(EXT_START_ADDR_HI); + + save->PixelPipeCfg0=INREG8(PIXPIPE_CONFIG_0); + save->PixelPipeCfg1=INREG8(PIXPIPE_CONFIG_1); + save->PixelPipeCfg2=INREG8(PIXPIPE_CONFIG_2); + save->DisplayControl=INREG8(DISPLAY_CNTL); + + save->CursorControl=INREG(CURSOR_CONTROL); + save->CursorBaseAddr=INREG(CURSOR_BASEADDR); + save->CursorXHi=INREG8(CURSOR_X_HI); + save->CursorXLo=INREG8(CURSOR_X_LO); + save->CursorYHi=INREG8(CURSOR_Y_HI); + save->CursorYLo=INREG8(CURSOR_Y_LO); + + save->LMI_FIFO_Watermark = INREG(FWATER_BLC); + + return I810_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + int temp; + vgaI810Ptr restore; + + unlock(); + restore = (vgaI810Ptr)(regs+VGA_TOTAL_REGS); + + temp=__svgalib_inseq(0x01); + __svgalib_outseq(0, 1); + __svgalib_outseq(1, temp | 0x20); + + usleep(50000); + + temp=INREG8(DRAM_ROW_CNTL_HI); + temp &= ~0x18; + OUTREG8(DRAM_ROW_CNTL_HI, temp); + + usleep(1000); /* Wait 1 ms */ + + /* Write the M, N and P values */ + OUTREG16(VCLK2_VCO_M, restore->VideoClk2_M); + OUTREG16(VCLK2_VCO_N, restore->VideoClk2_N); + OUTREG8(VCLK2_VCO_DIV_SEL, restore->VideoClk2_DivisorSel); + + + temp = INREG(PIXPIPE_CONFIG_0); + temp &= ~(DAC_8_BIT | HW_CURSOR_ENABLE); + temp |= (restore->PixelPipeCfg0 & (DAC_8_BIT | HW_CURSOR_ENABLE)); + OUTREG(PIXPIPE_CONFIG_0, temp); + + temp = __svgalib_incrtc(IO_CTNL); + temp &= ~(EXTENDED_ATTR_CNTL|EXTENDED_CRTC_CNTL); + temp |= EXTENDED_CRTC_CNTL; + __svgalib_outcrtc(IO_CTNL, temp); + + __svgalib_outcrtc(EXT_VERT_TOTAL, restore->ExtVertTotal); + __svgalib_outcrtc(EXT_VERT_DISPLAY, restore->ExtVertDispEnd); + __svgalib_outcrtc(EXT_VERT_SYNC_START, restore->ExtVertSyncStart); + __svgalib_outcrtc(EXT_VERT_BLANK_START, restore->ExtVertBlankStart); + __svgalib_outcrtc(EXT_HORIZ_TOTAL, restore->ExtHorizTotal); + __svgalib_outcrtc(EXT_HORIZ_BLANK, restore->ExtHorizBlank); + __svgalib_outcrtc(EXT_OFFSET, restore->ExtOffset); + __svgalib_outcrtc(EXT_START_ADDR, restore->ExtStartAddr); + __svgalib_outcrtc(EXT_START_ADDR_HI, restore->ExtStartAddrHi); + + OUTREG16(CURSOR_CONTROL,restore->CursorControl); + OUTREG(CURSOR_BASEADDR,restore->CursorBaseAddr); + OUTREG8(CURSOR_X_HI,restore->CursorXHi); + OUTREG8(CURSOR_X_LO,restore->CursorXLo); + OUTREG8(CURSOR_Y_HI,restore->CursorYHi); + OUTREG8(CURSOR_Y_LO,restore->CursorYLo); + + temp=__svgalib_incrtc(INTERLACE_CNTL); + temp &= ~INTERLACE_ENABLE; + temp |= restore->InterlaceControl; + __svgalib_outcrtc(INTERLACE_CNTL, temp); + + temp = __svgalib_ingra(ADDRESS_MAPPING); + temp &= 0xE0; /* Save reserved bits 7:5 */ + temp |= restore->AddressMapping; + __svgalib_outgra(ADDRESS_MAPPING, temp); + + + temp=INREG8(DRAM_ROW_CNTL_HI); + temp &= ~0x18; + temp |= 0x08; + OUTREG8(DRAM_ROW_CNTL_HI, temp); + +#if 0 + temp = INREG8(BITBLT_CNTL); + temp &= ~COLEXP_MODE; + temp |= restore->BitBLTControl; + OUTREG8(BITBLT_CNTL, temp); +#endif + + temp = INREG8(DISPLAY_CNTL); + temp &= ~(VGA_WRAP_MODE | GUI_MODE); + temp |= restore->DisplayControl; + OUTREG8(DISPLAY_CNTL, temp); + + temp = INREG8(PIXPIPE_CONFIG_0); + temp &= 0x64; /* Save reserved bits 6:5,2 */ + temp |= restore->PixelPipeCfg0; + OUTREG8(PIXPIPE_CONFIG_0, temp); + + temp = INREG8(PIXPIPE_CONFIG_2); + temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ + temp |= restore->PixelPipeCfg2; + OUTREG8(PIXPIPE_CONFIG_2, temp); + + temp = INREG8(PIXPIPE_CONFIG_1); + temp &= 0xe0; + temp |= restore->PixelPipeCfg1; + OUTREG8(PIXPIPE_CONFIG_1, temp); + +#if 0 + temp = INREG(FWATER_BLC); + temp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK | MM_BURST_LENGTH | MM_FIFO_WATERMARK); + temp |= restore->LMI_FIFO_Watermark; + OUTREG(FWATER_BLC, temp); +#endif + + temp=__svgalib_inseq(0x01); + __svgalib_outseq(1, temp & ~0x20); + __svgalib_outseq(0, 3); + + temp = __svgalib_incrtc(IO_CTNL); + temp &= ~(EXTENDED_ATTR_CNTL|EXTENDED_CRTC_CNTL); + temp |= restore->IOControl; + __svgalib_outcrtc(IO_CTNL, temp); + +} + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +#define MAX_VCO_FREQ 600000 +#define TARGET_MAX_N 30 +#define REF_FREQ 24000 + +#define CALC_VCLK(m,n,p) \ + ((m * 4 * REF_FREQ / n ) >> p) + +static void +I810CalcVCLK(int freq, int *M, int *N, int *DIVSEL ) +{ + int m, n, p; + int f_out; + int f_err, f_best; + int f_vco; + int m_best = 0, n_best = 0, p_best = 0; + int f_target = freq; + int err_max = 5000; + int err_target = 100; + int err_best = 999999; + + p=1; + while((1<5)p=5; + p_best=p; + + f_vco = f_target * (1 << p); + + n = 2; + do { + n++; + m = f_vco * n / REF_FREQ / 4; + if (m < 3) m = 3; + f_out = CALC_VCLK(m,n,p); + f_err = f_target-f_out; + if (f_err < err_max) { + m_best = m; + n_best = n; + f_best = f_out; + err_best = f_err; + } + } while ((f_err >= err_target) && + ((n <= TARGET_MAX_N) || (err_best > err_max))); + + if (f_err < err_target) { + m_best = m; + n_best = n; + } + + *M = (m_best-2) & 0x3FF; + *N = (n_best-2) & 0x3FF; + *DIVSEL= p_best << 4; +} + +/* Local, called by setmode(). */ +static void initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + vgaI810Ptr new; + int n, m, divsel; + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + new = (vgaI810Ptr)(moderegs+VGA_TOTAL_REGS); + + moderegs[0x13] = modeinfo->lineWidth >> 3; + new->ExtOffset = modeinfo->lineWidth >> 11; + + switch (modeinfo->bitsPerPixel) { + case 8: + new->PixelPipeCfg1 = DISPLAY_8BPP_MODE; + break; + case 15: + case 16: + if (modeinfo->greenWeight == 5) { + new->PixelPipeCfg1 = DISPLAY_15BPP_MODE; + } else { + new->PixelPipeCfg1 = DISPLAY_16BPP_MODE; + } + break; + case 24: + new->PixelPipeCfg1 = DISPLAY_24BPP_MODE; + break; + case 32: + new->PixelPipeCfg1 = DISPLAY_32BPP_MODE; + break; + default: + break; + } + + if (modeinfo->bitsPerPixel>8) + new->PixelPipeCfg0 = DAC_8_BIT; + else + new->PixelPipeCfg0 = DAC_6_BIT; + + new->PixelPipeCfg2 = 0; + new->PixelPipeCfg1 |= 0x10; + + /* Turn on Extended VGA Interpretation */ + new->IOControl = EXTENDED_CRTC_CNTL; + + /* Turn on linear and page mapping */ + if(__svgalib_i810_usegtt) { + new->AddressMapping = LINEAR_MODE_ENABLE | 8 ; + new->DisplayControl = 1; + } else { + new->AddressMapping = PACKED_MODE_ENABLE | PAGE_MAPPING_ENABLE ; + new->DisplayControl = 2; + } + + /* Calculate the extended CRTC regs */ + new->ExtVertTotal = (modetiming->CrtcVTotal - 2) >> 8; + new->ExtVertDispEnd = (modetiming->CrtcVDisplay - 1) >> 8; + new->ExtVertSyncStart = modetiming->CrtcVSyncStart >> 8; + new->ExtVertBlankStart = modetiming->CrtcVSyncStart >> 8; + new->ExtHorizTotal = ((modetiming->CrtcHTotal >> 3) - 5) >> 8; + new->ExtHorizBlank = ((modetiming->CrtcHSyncEnd >> 3) & 0x40) >> 6; + + /* Turn on interlaced mode if necessary */ + if (modetiming->flags & INTERLACED) + new->InterlaceControl = INTERLACE_ENABLE; + else + new->InterlaceControl = INTERLACE_DISABLE; + + moderegs[VGA_AR11] = 0; + + I810CalcVCLK(modetiming->pixelClock, &m, &n, &divsel); + + new->VideoClk2_M = m; + new->VideoClk2_N = n; + new->VideoClk2_DivisorSel = divsel; + + /* Since we program the clocks ourselves, always use VCLK2. */ + moderegs[59] |= 0x0C; + + new->ExtStartAddr=0; + new->ExtStartAddrHi=0; + + /* Calculate the FIFO Watermark and Burst Length. */ + new->LMI_FIFO_Watermark = I810CalcWatermark(modetiming->pixelClock/1000, + modeinfo->bitsPerPixel, lmfreq, 0); + + new->CursorControl= CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_32_4C_AX; + + return ; +} + +static void setdisplaystart(int address); + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + + if (!modeavailable(mode)) return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(I810_TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + setdisplaystart(0); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); +} + +static void lock(void) +{ +} + + +#define VENDOR_ID 0x8086 +#define ID10 0x7121 +#define ID10DC 0x7123 +#define ID10E 0x7125 +#define ID15 0x1132 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + int found; + unsigned int buf[64]; + int id; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + id=buf[0]>>16; + + if(found && ((id==ID10) || (id==ID10DC) || (id==ID10E) || (id==ID15)) ){ + init(0,0,0); + return 1; + }; + + return 0; +} + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void setdisplaystart(int address) +{ + address=address >> 2; + __svgalib_outcrtc(0x0c, address & 0xFF00); + __svgalib_outcrtc(0x0d, address & 0x00FF); + __svgalib_outcrtc(EXT_START_ADDR_HI,(address&0x3fc00000)>>22); + __svgalib_outcrtc(EXT_START_ADDR,((address&0x3f0000)>>16)|EXT_START_ADDR_ENABLE); +} + +/* Set logical scanline length (usually multiple of 8) */ + +static void setlogicalwidth(int width) +{ + int offset = width >> 3; + + if(!__svgalib_i810_usegtt) offset>>=1; + + __svgalib_outcrtc(0x13,offset&0xff); + __svgalib_outcrtc(EXT_OFFSET, offset>>8); + +} + +static int linear(int op, int param) +{ + if (op==LINEAR_ENABLE || op==LINEAR_DISABLE) return 0; + if (op==LINEAR_QUERY_BASE) return linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ + else return -1; /* Unknown function. */ +} + +static unsigned char cur_colors[16*6]; + +static int cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j, tmp; + unsigned int *b3; + unsigned int l1, l2, l3, l4; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + OUTREG8(PIXPIPE_CONFIG_0,INREG8(PIXPIPE_CONFIG_0)&~HW_CURSOR_ENABLE); + break; + case CURSOR_SHOW: + OUTREG8(PIXPIPE_CONFIG_0,INREG8(PIXPIPE_CONFIG_0)|HW_CURSOR_ENABLE); + break; + case CURSOR_POSITION: + OUTREG8(CURSOR_X_LO,p1&0xff); + OUTREG8(CURSOR_X_HI,(p1&0x700)>>8); + OUTREG8(CURSOR_Y_LO,p2&0xff); + OUTREG8(CURSOR_Y_HI,(p2&0x700)>>8); + break; + case CURSOR_SELECT: + tmp=INREG8(PIXPIPE_CONFIG_0); + OUTREG8(PIXPIPE_CONFIG_0,tmp| EXTENDED_PALETTE); + OUTREG8(0x3c6, 0xff); + OUTREG8(0x3c8, 0x04); + for(i=0;i<6;i++) + OUTREG8(0x3c9, cur_colors[p1*6+i]); + OUTREG8(PIXPIPE_CONFIG_0,tmp); + OUTREG(CURSOR_BASEADDR,cur_base+(15-p1)*256); + break; + case CURSOR_IMAGE: + i=memory*1024-(p1+1)*256; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*6]=(p3&0xff0000)>>16; + cur_colors[p1*6+1]=(p3&0xff00)>>8; + cur_colors[p1*6+2]=p3&0xff; + cur_colors[p1*6+3]=(p4&0xff0000)>>16; + cur_colors[p1*6+4]=(p4&0xff00)>>8; + cur_colors[p1*6+5]=p4&0xff; + for(j=0;j<16;j++) { + l1=*(b3+2*j); + l2=~(*(b3+32+2*j)); + l3=*(b3+2*j+1); + l4=~(*(b3+32+2*j+1)); + /*change endianess */ + l1=(l1<<24)|(l1>>24)|((l1>>8)&0xff00)|((l1<<8)&0xff0000); + l2=(l2<<24)|(l2>>24)|((l2>>8)&0xff00)|((l2<<8)&0xff0000); + l3=(l3<<24)|(l3>>24)|((l3>>8)&0xff00)|((l3<<8)&0xff0000); + l4=(l4<<24)|(l4>>24)|((l4>>8)&0xff00)|((l4<<8)&0xff0000); + *(unsigned int *)(LINEAR_POINTER+i+16*j)=l2; + *(unsigned int *)(LINEAR_POINTER+i+16*j+4)=l4; + *(unsigned int *)(LINEAR_POINTER+i+16*j+8)=l1; + *(unsigned int *)(LINEAR_POINTER+i+16*j+12)=l3; + } + break; + } + break; + } + return 0; +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} + +static int map_clock(int bpp, int clock) +{ +return clock ; +} + +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_i810_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + setpage, + NULL, + NULL, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + cursor +}; + +/* Initialize chipset (called after detection) */ +static int init(int force, int par1, int par2) +{ + unsigned int buf[64]; + unsigned int t, i, id; + int found=0; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + linear_base=0; + id=buf[0]>>16; + + if( found && ((id==ID10) || (id==ID10DC) || (id==ID10E) || (id==ID15)) ){ + linear_base=buf[4]&0xffffff00; + mmio_base=buf[5]&0xffffff00; + } else return 1; + + if(__svgalib_nohelper && __svgalib_i810_usegtt) { + /* Can't use GTT withoout helper */ + + fprintf(stderr, "I810: WARNING: Can't use GTT without kernel helper.\n" + " Using I810 driver in no-gtt mode.\n"); + __svgalib_i810_usegtt=0; + } + + __svgalib_mmio_base=mmio_base; + __svgalib_mmio_size=512*0x400; + map_mmio(); + __svgalib_vgammbase=0; + __svgalib_mm_io_mapio(); + + if (force) { + memory = par1; + } else { + memory = 512; + }; + + if(__svgalib_i810_usegtt) { + if(v_readl(0x2020) & 1) { + /* GTT already set */ + memory = 4096; + } else { + memory = 4096; + ioctl(__svgalib_mem_fd, SVGAHELPER_I810GTT, &t); + v_writel(t|1, 0x2020); + for(i=0;i<1024;i++) { + t=i; + ioctl(__svgalib_mem_fd, SVGAHELPER_I810GTTE, &t); + v_writel(t, 0x10000 + 4*i); + } + } + cur_base = (memory>>2)-1; + ioctl(__svgalib_mem_fd, SVGAHELPER_I810GTTE, &cur_base); + cur_base &= ~1 ; + __svgalib_banked_mem_base=linear_base; + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=memory*0x400; + __svgalib_modeinfo_linearset |= LINEAR_CAN; + __svgalib_emulatepage = 2; + __svgalib_i810_driverspecs.__svgalib_setpage = NULL; + } else { + linear_base=0; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_size=0; + } + + if(buf[20]&0x10) { + lmfreq=133; + } else { + lmfreq=100; + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using i810 driver, %iKB.\n",memory); + }; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 203000; + cardspecs->maxPixelClock16bpp = 163000; + cardspecs->maxPixelClock24bpp = 128000; + cardspecs->maxPixelClock32bpp = 86000; + cardspecs->flags = CLOCK_PROGRAMMABLE | INTERLACE_DIVIDE_VERT; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks = 0; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_i810_driverspecs; + return 0; +} diff --git a/src/drivers/i810_reg.h b/src/drivers/i810_reg.h new file mode 100644 index 0000000..96d647a --- /dev/null +++ b/src/drivers/i810_reg.h @@ -0,0 +1,96 @@ +#define INREG(addr) v_readl(addr) +#define OUTREG(addr, val) v_writel(val, addr) + +#define INREG8(addr) v_readb(addr) +#define OUTREG8(addr, val) v_writeb(val, addr) + +#define INREG16(addr) v_readw(addr) +#define OUTREG16(addr, val) v_writew(val, addr) + +#define START_ADDR_HI 0x0C /* p246 */ +#define START_ADDR_LO 0x0D /* p247 */ +#define VERT_SYNC_END 0x11 /* p249 */ +#define EXT_VERT_TOTAL 0x30 /* p257 */ +#define EXT_VERT_DISPLAY 0x31 /* p258 */ +#define EXT_VERT_SYNC_START 0x32 /* p259 */ +#define EXT_VERT_BLANK_START 0x33 /* p260 */ +#define EXT_HORIZ_TOTAL 0x35 /* p261 */ +#define EXT_HORIZ_BLANK 0x39 /* p261 */ +#define EXT_START_ADDR 0x40 /* p262 */ +#define EXT_START_ADDR_ENABLE 0x80 +#define EXT_OFFSET 0x41 /* p263 */ +#define EXT_START_ADDR_HI 0x42 /* p263 */ +#define INTERLACE_CNTL 0x70 /* p264 */ +#define INTERLACE_ENABLE 0x80 +#define INTERLACE_DISABLE 0x00 + +#define IO_CTNL 0x80 +#define EXTENDED_ATTR_CNTL 0x02 +#define EXTENDED_CRTC_CNTL 0x01 + +#define ADDRESS_MAPPING 0x10 +#define PAGE_TO_LOCAL_MEM_ENABLE 0x10 +#define GTT_MEM_MAP_ENABLE 0x08 +#define PACKED_MODE_ENABLE 0x04 +#define LINEAR_MODE_ENABLE 0x02 +#define PAGE_MAPPING_ENABLE 0x01 + +#define DRAM_ROW_CNTL_HI 0x3002 + +#define BITBLT_CNTL 0x7000c +#define COLEXP_MODE 0x30 +#define COLEXP_8BPP 0x00 +#define COLEXP_16BPP 0x10 +#define COLEXP_24BPP 0x20 +#define COLEXP_RESERVED 0x30 +#define BITBLT_STATUS 0x01 +#define DISPLAY_CNTL 0x70008 +#define VGA_WRAP_MODE 0x02 +#define VGA_WRAP_AT_256KB 0x00 +#define VGA_NO_WRAP 0x02 +#define GUI_MODE 0x01 +#define STANDARD_VGA_MODE 0x00 +#define HIRES_MODE 0x01 +#define PIXPIPE_CONFIG_0 0x70009 +#define DAC_8_BIT 0x80 +#define DAC_6_BIT 0x00 +#define HW_CURSOR_ENABLE 0x10 +#define EXTENDED_PALETTE 0x01 +#define PIXPIPE_CONFIG_1 0x7000a +#define DISPLAY_COLOR_MODE 0x0F +#define DISPLAY_VGA_MODE 0x00 +#define DISPLAY_8BPP_MODE 0x02 +#define DISPLAY_15BPP_MODE 0x04 +#define DISPLAY_16BPP_MODE 0x05 +#define DISPLAY_24BPP_MODE 0x06 +#define DISPLAY_32BPP_MODE 0x07 +#define PIXPIPE_CONFIG_2 0x7000b +#define DISPLAY_GAMMA_ENABLE 0x08 +#define DISPLAY_GAMMA_DISABLE 0x00 + +#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */ +#define VCLK2_VCO_N 0x600a +#define VCLK2_VCO_DIV_SEL 0x6012 + +#define CURSOR_CONTROL 0x70080 +#define CURSOR_ORIGIN_SCREEN 0x00 +#define CURSOR_ORIGIN_DISPLAY 0x10 +#define CURSOR_MODE 0x07 +#define CURSOR_MODE_DISABLE 0x00 +#define CURSOR_MODE_32_4C_AX 0x01 +#define CURSOR_MODE_64_3C 0x04 +#define CURSOR_MODE_64_4C_AX 0x05 +#define CURSOR_MODE_64_4C 0x06 +#define CURSOR_MODE_RESERVED 0x07 +#define CURSOR_BASEADDR 0x70084 +#define CURSOR_X_LO 0x70088 +#define CURSOR_X_HI 0x70089 +#define CURSOR_Y_LO 0x7008A +#define CURSOR_Y_HI 0x7008B + +#define FWATER_BLC 0x20d8 +#define MM_BURST_LENGTH 0x00700000 +#define MM_FIFO_WATERMARK 0x0001F000 +#define LM_BURST_LENGTH 0x00000700 +#define LM_FIFO_WATERMARK 0x0000001F + diff --git a/src/drivers/i810_wmark.c b/src/drivers/i810_wmark.c new file mode 100644 index 0000000..4582e9b --- /dev/null +++ b/src/drivers/i810_wmark.c @@ -0,0 +1,306 @@ + +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_wmark.c,v 1.4 2000/09/08 22:43:06 mvojkovi Exp $ */ + +/* + * Authors: + * Keith Whitwell + */ + +struct wm_info { + double freq; + unsigned int wm; +}; + +struct wm_info i810_wm_8_100[] = { + { 0, 0x22003000 }, + { 25.2, 0x22003000 }, + { 28.0, 0x22003000 }, + { 31.5, 0x22003000 }, + { 36.0, 0x22007000 }, + { 40.0, 0x22007000 }, + { 45.0, 0x22007000 }, + { 49.5, 0x22008000 }, + { 50.0, 0x22008000 }, + { 56.3, 0x22008000 }, + { 65.0, 0x22008000 }, + { 75.0, 0x22008000 }, + { 78.8, 0x22008000 }, + { 80.0, 0x22008000 }, + { 94.0, 0x22008000 }, + { 96.0, 0x22107000 }, + { 99.0, 0x22107000 }, + { 108.0, 0x22107000 }, + { 121.0, 0x22107000 }, + { 128.9, 0x22107000 }, + { 132.0, 0x22109000 }, + { 135.0, 0x22109000 }, + { 157.5, 0x2210b000 }, + { 162.0, 0x2210b000 }, + { 175.5, 0x2210b000 }, + { 189.0, 0x2220e000 }, + { 202.5, 0x2220e000 } +}; + +struct wm_info i810_wm_16_100[] = { + { 0, 0x22004000 }, + { 25.2, 0x22006000 }, + { 28.0, 0x22006000 }, + { 31.5, 0x22007000 }, + { 36.0, 0x22007000 }, + { 40.0, 0x22007000 }, + { 45.0, 0x22007000 }, + { 49.5, 0x22009000 }, + { 50.0, 0x22009000 }, + { 56.3, 0x22108000 }, + { 65.0, 0x2210e000 }, + { 75.0, 0x2210e000 }, + { 78.8, 0x2210e000 }, + { 80.0, 0x22210000 }, + { 94.5, 0x22210000 }, + { 96.0, 0x22210000 }, + { 99.0, 0x22210000 }, + { 108.0, 0x22210000 }, + { 121.0, 0x22210000 }, + { 128.9, 0x22210000 }, + { 132.0, 0x22314000 }, + { 135.0, 0x22314000 }, + { 157.5, 0x22415000 }, + { 162.0, 0x22416000 }, + { 175.5, 0x22416000 }, + { 189.0, 0x22416000 }, + { 195.0, 0x22416000 }, + { 202.5, 0x22416000 } +}; + + +struct wm_info i810_wm_24_100[] = { + { 0, 0x22006000 }, + { 25.2, 0x22009000 }, + { 28.0, 0x22009000 }, + { 31.5, 0x2200a000 }, + { 36.0, 0x2210c000 }, + { 40.0, 0x2210c000 }, + { 45.0, 0x2210c000 }, + { 49.5, 0x22111000 }, + { 50.0, 0x22111000 }, + { 56.3, 0x22111000 }, + { 65.0, 0x22214000 }, + { 75.0, 0x22214000 }, + { 78.8, 0x22215000 }, + { 80.0, 0x22216000 }, + { 94.5, 0x22218000 }, + { 96.0, 0x22418000 }, + { 99.0, 0x22418000 }, + { 108.0, 0x22418000 }, + { 121.0, 0x22418000 }, + { 128.9, 0x22419000 }, + { 132.0, 0x22519000 }, + { 135.0, 0x4441d000 }, + { 157.5, 0x44419000 }, + { 162.0, 0x44419000 }, + { 175.5, 0x44419000 }, + { 189.0, 0x44419000 }, + { 195.0, 0x44419000 }, + { 202.5, 0x44419000 } +}; + +struct wm_info i810_wm_32_100[] = { + { 0, 0x2210b000 }, + { 60, 0x22415000 }, /* 0x314000 works too */ + { 80, 0x22419000 } /* 0x518000 works too */ +}; + + +struct wm_info i810_wm_8_133[] = { + { 0, 0x22003000 }, + { 25.2, 0x22003000 }, + { 28.0, 0x22003000 }, + { 31.5, 0x22003000 }, + { 36.0, 0x22007000 }, + { 40.0, 0x22007000 }, + { 45.0, 0x22007000 }, + { 49.5, 0x22008000 }, + { 50.0, 0x22008000 }, + { 56.3, 0x22008000 }, + { 65.0, 0x22008000 }, + { 75.0, 0x22008000 }, + { 78.8, 0x22008000 }, + { 80.0, 0x22008000 }, + { 94.0, 0x22008000 }, + { 96.0, 0x22107000 }, + { 99.0, 0x22107000 }, + { 108.0, 0x22107000 }, + { 121.0, 0x22107000 }, + { 128.9, 0x22107000 }, + { 132.0, 0x22109000 }, + { 135.0, 0x22109000 }, + { 157.5, 0x2210b000 }, + { 162.0, 0x2210b000 }, + { 175.5, 0x2210b000 }, + { 189.0, 0x2220e000 }, + { 202.5, 0x2220e000 } +}; + + +struct wm_info i810_wm_16_133[] = { + { 0, 0x22004000 }, + { 25.2, 0x22006000 }, + { 28.0, 0x22006000 }, + { 31.5, 0x22007000 }, + { 36.0, 0x22007000 }, + { 40.0, 0x22007000 }, + { 45.0, 0x22007000 }, + { 49.5, 0x22009000 }, + { 50.0, 0x22009000 }, + { 56.3, 0x22108000 }, + { 65.0, 0x2210e000 }, + { 75.0, 0x2210e000 }, + { 78.8, 0x2210e000 }, + { 80.0, 0x22210000 }, + { 94.5, 0x22210000 }, + { 96.0, 0x22210000 }, + { 99.0, 0x22210000 }, + { 108.0, 0x22210000 }, + { 121.0, 0x22210000 }, + { 128.9, 0x22210000 }, + { 132.0, 0x22314000 }, + { 135.0, 0x22314000 }, + { 157.5, 0x22415000 }, + { 162.0, 0x22416000 }, + { 175.5, 0x22416000 }, + { 189.0, 0x22416000 }, + { 195.0, 0x22416000 }, + { 202.5, 0x22416000 } +}; + +struct wm_info i810_wm_24_133[] = { + { 0, 0x22006000 }, + { 25.2, 0x22009000 }, + { 28.0, 0x22009000 }, + { 31.5, 0x2200a000 }, + { 36.0, 0x2210c000 }, + { 40.0, 0x2210c000 }, + { 45.0, 0x2210c000 }, + { 49.5, 0x22111000 }, + { 50.0, 0x22111000 }, + { 56.3, 0x22111000 }, + { 65.0, 0x22214000 }, + { 75.0, 0x22214000 }, + { 78.8, 0x22215000 }, + { 80.0, 0x22216000 }, + { 94.5, 0x22218000 }, + { 96.0, 0x22418000 }, + { 99.0, 0x22418000 }, + { 108.0, 0x22418000 }, + { 121.0, 0x22418000 }, + { 128.9, 0x22419000 }, + { 132.0, 0x22519000 }, + { 135.0, 0x4441d000 }, + { 157.5, 0x44419000 }, + { 162.0, 0x44419000 }, + { 175.5, 0x44419000 }, + { 189.0, 0x44419000 }, + { 195.0, 0x44419000 }, + { 202.5, 0x44419000 } +}; + + +#define Elements(x) (sizeof(x)/sizeof(*x)) + + + +/* + * I810CalcFIFO -- + * + * Calculate burst length and FIFO watermark. + */ + +static unsigned int I810CalcWatermark(double freq, int bpp, int lmfreq, int dcache ) +{ + struct wm_info *tab; + int nr; + int i; + + if (lmfreq == 100) { + switch(bpp) { + case 8: + tab = i810_wm_8_100; + nr = Elements(i810_wm_8_100); + break; + case 16: + tab = i810_wm_16_100; + nr = Elements(i810_wm_16_100); + break; + case 24: + tab = i810_wm_24_100; + nr = Elements(i810_wm_24_100); + break; + default: + return 0; + } + } else { + switch(bpp) { + case 8: + tab = i810_wm_8_133; + nr = Elements(i810_wm_8_133); + break; + case 16: + tab = i810_wm_16_133; + nr = Elements(i810_wm_16_133); + break; + case 24: + tab = i810_wm_24_133; + nr = Elements(i810_wm_24_133); + break; + default: + return 0; + } + } + + for (i = 0 ; i < nr && tab[i].freq < freq ; i++); + + if (i == nr) + i--; + + /* None of these values (sourced from intel) have watermarks for + * the dcache memory. Fake it for now by using the same watermark + * for both... + * + * Update: this is probably because dcache isn't real useful as + * framebuffer memory, so intel's drivers don't need watermarks + * for that memory because they never use it to feed the ramdacs. + * We do use it in the fallback mode, so keep the watermarks for + * now. + */ + if (dcache) + return (tab[i].wm & ~0xffffff) | ((tab[i].wm>>12) & 0xfff); + else + return tab[i].wm; +} + diff --git a/src/drivers/laguna.c b/src/drivers/laguna.c new file mode 100644 index 0000000..4c64e96 --- /dev/null +++ b/src/drivers/laguna.c @@ -0,0 +1,671 @@ +/* +Laguna chipset driver for cirrus logic 5462, 5464, 5465 + +Only tested on 5464. +Problems: + mouse cursor does not work. + secondary (mmio only) not tested. + fifo threshold needs more tuning. +*/ + + +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" + +#include "lagunaio.h" + +struct lagunahw { + unsigned char crt[5]; + unsigned char gra[3]; + unsigned char seq[3]; + unsigned char pal_state; + unsigned char bclk; + unsigned char tile; + unsigned short tiling_control; + unsigned short control; + unsigned short format; + unsigned short cur_x; + unsigned short cur_y; + unsigned short cur_preset; + unsigned short cur_misc; + unsigned short cur_address; + unsigned short disp_thresh; + unsigned int pcifc; +}; + +#define LAGUNAREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define LAGUNA_TOTAL_REGS (VGA_TOTAL_REGS + sizeof(struct lagunahw)) + +enum { + L5462=0, L5464, L5465 +}; + +static int pagemul=4; + +static int laguna_init(int, int, int); +static void laguna_unlock(void); +static void laguna_lock(void); + +static int laguna_memory, laguna_chiptype; +static unsigned int laguna_linear_base, laguna_mmio_base; + +static CardSpecs *cardspecs; + +static void laguna_setpage(int page) +{ + __svgalib_outgra(0x09,page*pagemul); +} + +/* Fill in chipset specific mode information */ +static void laguna_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = laguna_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = laguna_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(laguna_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int laguna_saveregs(unsigned char regs[]) +{ + struct lagunahw *l=(struct lagunahw *)(regs+VGA_TOTAL_REGS); + + laguna_unlock(); + + l->crt[0]= __svgalib_incrtc(0x19); + l->crt[1]= __svgalib_incrtc(0x1a); + l->crt[2]= __svgalib_incrtc(0x1b); + l->crt[3]= __svgalib_incrtc(0x1d); + l->crt[4]= __svgalib_incrtc(0x1e); + + l->gra[0]= __svgalib_ingra(0x09); + l->gra[1]= __svgalib_ingra(0x0a); + l->gra[2]= __svgalib_ingra(0x0b); + + l->seq[0]= __svgalib_inseq(0x0e); + l->seq[1]= __svgalib_inseq(0x1e); + l->seq[2]= __svgalib_inseq(0x07); + + if(laguna_chiptype==L5465) + l->tiling_control=laguna_readw(0x2c4); + l->control=laguna_readw(0x402); + if(laguna_chiptype==L5465) + l->bclk=laguna_readb(0x2c0); + else l->bclk=laguna_readb(0x8c); + l->tile=laguna_readb(0x407); + l->pal_state=laguna_readb(0xb0); + l->format=laguna_readw(0xc0); + l->cur_x=laguna_readw(0xe0); + l->cur_y=laguna_readw(0xe2); + l->cur_preset=laguna_readw(0xe4); + l->cur_misc=laguna_readw(0xe6); + l->cur_address=laguna_readw(0xe8); + l->disp_thresh=laguna_readw(0xea); + l->pcifc=laguna_readl(0x3fc); + + return LAGUNA_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void laguna_setregs(const unsigned char regs[], int mode) +{ + struct lagunahw *l=(struct lagunahw *)(regs+VGA_TOTAL_REGS); + + laguna_unlock(); + + __svgalib_outcrtc(0x19,l->crt[0]); + __svgalib_outcrtc(0x1a,l->crt[1]); + __svgalib_outcrtc(0x1b,l->crt[2]); + __svgalib_outcrtc(0x1d,l->crt[3]); + __svgalib_outcrtc(0x1e,l->crt[4]); + + __svgalib_outseq(0x07,l->seq[2]); + __svgalib_outseq(0x0e,l->seq[0]); + __svgalib_outseq(0x1e,l->seq[1]); + + laguna_writew(0xc0,l->format); + + laguna_writel(0x3fc,l->pcifc); + + laguna_writew(0xea,l->disp_thresh); + + if(laguna_chiptype==L5465) + laguna_writew(0x2c4,l->tiling_control); + + laguna_writew(0x407,l->tile); + + if(laguna_chiptype==L5465) + laguna_writeb(0x2c0,l->bclk); + else laguna_writeb(0x8c,l->bclk); + + laguna_writew(0x402,l->control); + + laguna_writew(0xb0,l->pal_state); + laguna_writew(0xe0,l->cur_x); + laguna_writew(0xe2,l->cur_y); + laguna_writew(0xe4,l->cur_preset); + laguna_writew(0xe6,l->cur_misc); + laguna_writew(0xe8,l->cur_address); + + __svgalib_outgra(0x09,l->gra[0]); + __svgalib_outgra(0x0a,l->gra[1]); + __svgalib_outgra(0x0b,l->gra[2]); +} + + +/* Return nonzero if mode is available */ + +static int laguna_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (laguna_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +/* Local, called by laguna_setmode(). */ + +#define REF 14318 + +static int laguna_findclock(int clock, int *on, int *om, int *op, int *opp) +{ + int n, m, diff, best, bestm; + + *opp=0; + +// while(clock<20000) { +// clock*=2; +// *opp=+1; +// } + + if(clock<40000) { + clock *= 2; + *op=1; + } else *op=0; + + best=clock; + bestm=5; + for(m=6; m<30;m++) { + n=clock*m/REF; + if((n<32)||(n>127)) continue; + diff=clock-(n*REF/m); + if(diff<0)diff=-diff; + if(diff100)) { + *on=clock*bestm/REF; + *om=bestm; + return 0; + } else { + fprintf(stderr,"Can't find clock %iKHz.\n",clock); + return -1; + } +} + +static void laguna_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + struct lagunahw *l=(struct lagunahw *)(moderegs+VGA_TOTAL_REGS); + int hd, htot, hss, hse, hbs, hbe; + int vd, vtot, vss, vse, vbs, vbe; + int offset; + int n,m,p,pp; + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + + if(laguna_chiptype==L5465) { + l->tiling_control=laguna_readw(0x2c4); + l->tiling_control &= ~0x80; /* disable tiling */ + } + + l->control=laguna_readw(0x402) & 0x87ff; /* narrow tiles */ + l->control |= 0x1000; /* disable tiling */ + + l->disp_thresh=laguna_readw(0xea)&0xffe0; + l->disp_thresh &= 0x3fbf; /* 1-way interleave and narrow tiles */ + switch(modeinfo->bitsPerPixel) { + case 8: + case 15: + case 16: + l->disp_thresh |= 0x10; + break; + case 24: + case 32: + l->disp_thresh |= 0x20; + break; + default: + l->disp_thresh |= 0x18; + } + + l->pcifc=laguna_readl(0x3fc); + l->pcifc |= 0x10000000; + + if(laguna_chiptype==L5465) + l->bclk=laguna_readb(0x2c0); + else l->bclk=laguna_readb(0x8c); + + l->bclk=18; + + l->tile=laguna_readb(0x407) & 0x3f; /* no interleave */ + + offset = modeinfo->lineWidth >> 3; + + moderegs[0x13]=offset&0xff; + + hd = (modetiming->CrtcHDisplay >> 3) - 1; + htot = (modetiming->CrtcHTotal >> 3) - 5; + hss = (modetiming->CrtcHSyncStart >> 3); + hse = (modetiming->CrtcHSyncEnd >> 3); + hbs = (modetiming->CrtcHSyncStart >> 3) - 1; + hbe = (modetiming->CrtcHSyncEnd >> 3); + vd = modetiming->CrtcVDisplay - 1; + vtot = modetiming->CrtcVTotal - 2; + vss = modetiming->CrtcVSyncStart; + vse = modetiming->CrtcVSyncEnd; + vbs = modetiming->CrtcVSyncStart - 1; + vbe = modetiming->CrtcVSyncEnd; + + l->crt[0] = htot>>1; + l->crt[1] = ((vbe>>2)&0xf0) | /* vertical blank end overflow */ + 2; /* double buffered display start */ + if (modetiming->flags & INTERLACED) l->crt[1] |= 0x1; + l->crt[2] = 0x22 | /* extended address and no border*/ + ((offset&0x100)>>4); + l->crt[3]=(offset&0x200)>>9; + l->crt[4] = ((htot&0x100)>>1) | + ((hd&0x100)>>2) | + ((hbs&0x100)>>3) | + ((hss&0x100)>>4) | + ((vtot&0x400)>>7) | + ((vd&0x400)>>8) | + ((vbs&0x400)>>9) | + ((vss&0x400)>>10); + + l->gra[0]=0; + l->gra[2]=32; /* use 16KB granularity, only one bank */ + + if(laguna_findclock(modetiming->pixelClock,&n,&m,&p,&pp)) { + /* should not happen */ + exit(4); + } + l->seq[0]=(m<<1)|p; + l->seq[1]=n; + l->seq[2]=1; + + l->pal_state=0; + l->format=0; + switch(modeinfo->bitsPerPixel) { + case 8: + l->format|=0; + l->control |= 0; + break; + case 15: + case 16: if(modeinfo->greenWeight==5) + l->format|=0x1600; else + l->format|=0x1400; + l->control |= 0x2000; + break; + case 24: + l->format|=0x2400; + l->control |= 0x4000; + break; + case 32: + l->format|=0x3400; + l->control |= 0x6000; + break; + } + + l->cur_misc=0; /* disable cursor */ + l->cur_preset=0; + + moderegs[59] |= 0x0c; + + return; +} + + +static int laguna_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + laguna_writeb(0xe6,0); + __svgalib_outseq(0x07,0); + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!laguna_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(LAGUNA_TOTAL_REGS); + + laguna_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + laguna_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void laguna_unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); +} + +static void laguna_lock(void) +{ +} + +#define VENDOR_ID 0x1013 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int laguna_test(void) +{ + int found; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if(found&& + ((((buf[0]>>16)&0xffff)==0x00d0)|| + (((buf[0]>>16)&0xffff)==0x00d4)|| + (((buf[0]>>16)&0xffff)==0x00d6))){ + laguna_init(0,0,0); + return 1; + }; + return 0; +} + + +/* Set display start address (not for 16 color modes) */ +static void laguna_setdisplaystart(int address) +{ + address=address >> 2; + __svgalib_outcrtc(0x0c,(address & 0xFF00)>>8); + __svgalib_outcrtc(0x0d, address & 0xFF); + __svgalib_outcrtc(0x1b, (__svgalib_incrtc(0x1b)&0xf2) | ((address&0x100)>>8) | ((address&0x600)>>7)); + __svgalib_outcrtc(0x1d, (__svgalib_incrtc(0x1b)&0xe7) | ((address&0x1800)>>8) ); + +} + + +/* Set logical scanline length (usually multiple of 8) */ +static void laguna_setlogicalwidth(int width) +{ + int offset = width >> 3; + + __svgalib_outcrtc(0x13,offset&0xff); + __svgalib_outcrtc(0x1b, (__svgalib_incrtc(0x1b)&0xef)| ((offset&0x100)>>4)); + __svgalib_outcrtc(0x1d, (__svgalib_incrtc(0x1b)&0xfe)| ((offset&0x200)>>9)); +} + +static int laguna_linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ return 0;}; + if (op==LINEAR_DISABLE){ return 0;}; + if (op==LINEAR_QUERY_BASE) return laguna_linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ + else return -1; /* Unknown function. */ +} + +static int laguna_match_programmable_clock(int clock) +{ +return clock ; +} + +static int laguna_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int laguna_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +static unsigned char cur_colors[16*6]; + +static int laguna_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + unsigned int *b3; + int i, j; + unsigned int l1, l2; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + laguna_writew(0xe6,laguna_readw(0xe6)&0xfffe); + break; + case CURSOR_SHOW: + laguna_writew(0xe6,laguna_readw(0xe6)|1); + break; + case CURSOR_POSITION: + laguna_writew(0xe0,p1); + laguna_writew(0xe2,p2); + break; + case CURSOR_SELECT: + i=laguna_memory*1024-(16-p1)*1024; + laguna_writew(0xb0,laguna_readw(0xb0)|8); + laguna_writeb(0xa8,15); + laguna_writeb(0xac,cur_colors[p1*6]>>2); + laguna_writeb(0xac,cur_colors[p1*6+1]>>2); + laguna_writeb(0xac,cur_colors[p1*6+2]>>2); + laguna_writeb(0xa8,0); + laguna_writeb(0xac,cur_colors[p1*6+3]>>2); + laguna_writeb(0xac,cur_colors[p1*6+4]>>2); + laguna_writeb(0xac,cur_colors[p1*6+5]>>2); + laguna_writew(0xb0,laguna_readw(0xb0)&~8); + laguna_writew(0xe8,i>>8); + break; + case CURSOR_IMAGE: + i=laguna_memory*1024-(16-p1)*1024; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*6]=(p3&0xff0000)>>16; + cur_colors[p1*6+1]=(p3&0xff00)>>8; + cur_colors[p1*6+2]=p3&0xff; + cur_colors[p1*6+3]=(p4&0xff0000)>>16; + cur_colors[p1*6+4]=(p4&0xff00)>>8; + cur_colors[p1*6+5]=p4&0xff; + for(j=0;j<32;j++) { + l1=*(b3+j); + l2=*(b3+32+j); + *(unsigned int *)(LINEAR_POINTER+i+j*16)=l1&l2; + *(unsigned int *)(LINEAR_POINTER+i+j*16+4)=0; + *(unsigned int *)(LINEAR_POINTER+i+j*16+8)=l1; + *(unsigned int *)(LINEAR_POINTER+i+j*16+12)=0; + } + memset(LINEAR_POINTER+i+512,0,512); + break; + } + break; + } + return 0; +} + +DriverSpecs __svgalib_laguna_driverspecs = +{ + laguna_saveregs, + laguna_setregs, + laguna_unlock, + laguna_lock, + laguna_test, + laguna_init, + laguna_setpage, + NULL, + NULL, + laguna_setmode, + laguna_modeavailable, + laguna_setdisplaystart, + laguna_setlogicalwidth, + laguna_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + laguna_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + laguna_cursor, +}; + +/* Initialize chipset (called after detection) */ + +static int laguna_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + char *chipnames[]={"5462", "5464", "5465"}; + + laguna_unlock(); + if (force) { + laguna_memory = par1; + laguna_chiptype = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + laguna_linear_base=0; + + if (found){ + int i,j; + switch(buf[0]>>16) { + case 0xd0: + laguna_chiptype=L5462; + break; + case 0xd4: + laguna_chiptype=L5464; + break; + case 0xd6: + laguna_chiptype=L5465; + break; + } + if(laguna_chiptype==L5465) { + laguna_mmio_base=buf[5]&0xffffff00; + laguna_linear_base=buf[4]&0xffffff00; + } else { + laguna_mmio_base=buf[4]&0xffffff00; + laguna_linear_base=buf[5]&0xffffff00; + } + if(__svgalib_secondary)laguna_mapio(); + + __svgalib_mmio_base=laguna_mmio_base; + __svgalib_mmio_size=4096; + map_mmio(); + + i=*(MMIO_POINTER + 0x200); + j=*(MMIO_POINTER + 0x201); + + laguna_memory = 512*(1<<((j&0xc0)>>6))*((i&7)+1); + } else return -1; + + if(laguna_memory<4096) pagemul<<=2; + + if (__svgalib_driver_report) { + fprintf(stderr,"Using LAGUNA driver, %s with %iKB video ram found.\n", + chipnames[laguna_chiptype],laguna_memory); + }; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = laguna_memory; + cardspecs->maxPixelClock4bpp = 170000; + switch(laguna_chiptype) { + case L5462: + cardspecs->maxPixelClock8bpp = 170000; + cardspecs->maxPixelClock16bpp = 135100; + cardspecs->maxPixelClock24bpp = 135100; + cardspecs->maxPixelClock32bpp = 85500; + case L5464: + cardspecs->maxPixelClock8bpp = 230000; + cardspecs->maxPixelClock16bpp = 170000; + cardspecs->maxPixelClock24bpp = 170000; + cardspecs->maxPixelClock32bpp = 135100; + case L5465: + cardspecs->maxPixelClock8bpp = 250000; + cardspecs->maxPixelClock16bpp = 170000; + cardspecs->maxPixelClock24bpp = 170000; + cardspecs->maxPixelClock32bpp = 135100; + } + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->nClocks =0; + cardspecs->mapClock = laguna_map_clock; + cardspecs->mapHorizontalCrtc = laguna_map_horizontal_crtc; + cardspecs->matchProgrammableClock=laguna_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_laguna_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=laguna_linear_base; + __svgalib_linear_mem_size=laguna_memory*0x400; + return 0; +} diff --git a/src/drivers/lagunaio.h b/src/drivers/lagunaio.h new file mode 100644 index 0000000..f538546 --- /dev/null +++ b/src/drivers/lagunaio.h @@ -0,0 +1,152 @@ +static inline unsigned char laguna_readb(int a) { + return *(MMIO_POINTER+a); +} + +static inline unsigned short laguna_readw(int a) { + return *(unsigned short *)(MMIO_POINTER+a); +} + +static inline unsigned int laguna_readl(int a) { + return *(unsigned int *)(MMIO_POINTER+a); +} + +static inline void laguna_writeb(int a, unsigned char d) { + *(MMIO_POINTER+a)=d; +} + +static inline void laguna_writew(int a, unsigned short d) { + *(unsigned short *)(MMIO_POINTER+a)=d; +} + +static inline void laguna_writel(int a, unsigned int d) { + *(unsigned int *)(MMIO_POINTER+a)=d; +} + +static int __svgalib_laguna_inmisc(void) +{ + return laguna_readb(0x80); +} + +static void __svgalib_laguna_outmisc(int i) +{ + laguna_writeb(0x80,i); +} + +static int __svgalib_laguna_incrtc(int i) +{ + if(i>0x1e)return 0; + return laguna_readb(i*4); +} + +static void __svgalib_laguna_outcrtc(int i, int d) +{ + if(i>0x1e)return; + laguna_writeb(i*4,d); +} + +static int __svgalib_laguna_inseq(int index) +{ + switch(index) { + case 0x0e: + return laguna_readb(0x84); + break; + case 0x18: + return laguna_readb(0x90); + break; + case 0x19: + return laguna_readb(0x94); + break; + case 0x1a: + return laguna_readb(0x98); + break; + case 0x1e: + return laguna_readb(0x88); + break; + default: + return 0; + } +} + +static void __svgalib_laguna_outseq(int index, int val) +{ + switch(index) { + case 0x0e: + laguna_writeb(0x84,val); + break; + case 0x18: + laguna_writeb(0x90,val); + break; + case 0x19: + laguna_writeb(0x94,val); + break; + case 0x1a: + laguna_writeb(0x98,val); + break; + case 0x1e: + laguna_writeb(0x88,val); + break; + } +} + +static int __svgalib_laguna_ingra(int index) +{ + return 0; +} + +static void __svgalib_laguna_outgra(int index, int val) +{ +} + +static int __svgalib_laguna_inis1(void) +{ + return 0; +} + +static int __svgalib_laguna_inatt(int index) +{ + return 0; +} + +static void __svgalib_laguna_outatt(int index, int val) +{ +} + +static void __svgalib_laguna_attscreen(int i) +{ + laguna_writeb(0x7c,i); +} + +static void __svgalib_laguna_inpal(int i, int *r, int *g, int *b) +{ + laguna_writeb(0xa4,i); + *r=laguna_readb(0xac); + *g=laguna_readb(0xac); + *b=laguna_readb(0xac); +} + +static void __svgalib_laguna_outpal(int i, int r, int g, int b) +{ + laguna_writeb(0xa8,i); + laguna_writeb(0xac,r); + laguna_writeb(0xac,g); + laguna_writeb(0xac,b); +} + +static void laguna_mapio(void) +{ + __svgalib_inmisc=__svgalib_laguna_inmisc; + __svgalib_outmisc=__svgalib_laguna_outmisc; + __svgalib_incrtc=__svgalib_laguna_incrtc; + __svgalib_outcrtc=__svgalib_laguna_outcrtc; + __svgalib_inseq=__svgalib_laguna_inseq; + __svgalib_outseq=__svgalib_laguna_outseq; + __svgalib_ingra=__svgalib_laguna_ingra; + __svgalib_outgra=__svgalib_laguna_outgra; + __svgalib_inatt=__svgalib_laguna_inatt; + __svgalib_outatt=__svgalib_laguna_outatt; + __svgalib_attscreen=__svgalib_laguna_attscreen; + __svgalib_inis1=__svgalib_laguna_inis1; + __svgalib_inpal=__svgalib_laguna_inpal; + __svgalib_outpal=__svgalib_laguna_outpal; +} + diff --git a/src/drivers/mach32.c b/src/drivers/mach32.c new file mode 100644 index 0000000..f0906c4 --- /dev/null +++ b/src/drivers/mach32.c @@ -0,0 +1,4112 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* ATI Mach32 driver (C) 1995 Michael Weller */ +/* eowmob@exp-math.uni-essen.de mat42b@aixrs1.hrz.uni-essen.de */ +/* eowmob@pollux.exp-math.uni-essen.de */ + +/* + * MICHAEL WELLER DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL MICHAEL WELLER BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* This tool contains one routine out of Xfree86, therefore I repeat */ +/* its copyright here: (Actually it is longer than the copied code) */ + +/* + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Orest Zborowski and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * Copyright 1993 by Kevin E. Martin, Chapel Hill, North Carolina. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL, KEVIN E. MARTIN, AND RICKARD E. FAITH DISCLAIM ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY + * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Thomas Roell, roell@informatik.tu-muenchen.de + * + * Rewritten for the 8514/A by Kevin E. Martin (martin@cs.unc.edu) + * Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu) + * Rewritten for the Mach32 by Kevin E. Martin (martin@cs.unc.edu) + * + */ + +/* Works only if Mach32 onboard VGA is enabled. */ +/* Reads in eeprom. */ +/* There is a dirty hack in here to raise the linewidth for */ +/* 800x600 to 832 to keep my mem happy.. (and even though it's a */ +/* VRAM card... probably has to do something with mempages.... */ +/* I change it by tweaking the info array.. so watch out. */ +/* The Number of additional pixels to append is set below, it has */ +/* to be a multiple of 8. This seems only to be needed for 16/24bpp */ +/* Ok,later I found that the number of pixels has to be a multiple */ +/* of 64 at least... somewhere in the ATI docs, always choosing a */ +/* multiple of 128 was suggested.... */ +/* So set the multiple to be used below.. */ + +#define PIXALIGN 64 + +#define DAC_SAFETY 0x1d /*reminder for people with DAC!=4,3,2,0 */ + /*set bits for well known DACTYPES */ + +/* + * Sync allowance in 1/1000ths. 10 (1%) corresponds to a 315 Hz + * deviation at 31.5 kHz, 1 Hz at 100 Hz + */ +#define SYNC_ALLOWANCE 10 + +#define SUPP_32BPP /*Accept 32BPP modes */ +/*#define USE_RGBa *//* ifdef(SUPP_32BPP) use RGBa format (R first in memory), + otherwise aBGR is used */ +/*Pure experimental and probably specific to my card (VRAM 68800-3) */ +#define MAXCLK8 2000 /*This effectly switches this off.. seems not + to be needed with PIXTWEAK>32 */ +#define MAXCLK16 2000 /*This effectly switches this off.. seems not + to be needed with PIXTWEAK>32 */ +#define MAXCLK24 49 +#define MAXCLK32 39 + +/*Clock values to be set on original ATI Mach32 to emulate vga compatible timings */ +/*Bit 4 is ATI3e:4, bits 3-2 are ATI39:1-0, bits 1-0 are ATI38:7-6 */ +#define SVGA_CLOCK 0x09 + +/*And here are minimum Vfifo values.. just guessed values (valid settings are 0..15): */ +#define VFIFO8 6 +#define VFIFO16 9 +#define VFIFO24 14 +#define VFIFO32 14 + +/*Wait count for busywait loops */ +#define BUSYWAIT 10000000 /* Around 1-2 sec on my 486-50 this should be enough for + any graphics command to complete, even on a fast machine. + however after that slower code is called to ensure a minimum + wait of another: */ +#define ADDIWAIT 5 /* seconds. */ + +/*#define FAST_MEMCPY *//* Use a very fast inline memcpy instead of the standard libc one */ + /* Seems not to make a big difference for the Mach32 */ + /* Even more seems to be MUCH slower than the libc memcpy, even */ + /* though this uses a function call. Probably just rep movsb is */ + /* fastest. So => do not use this feature. */ + +#define MODESWITCHDELAY 50000 /* used to wait for clocks to stabilize */ + +/*#define DEBUG */ +/*#define DEBUG_KEY *//*Wait for keypress at some locations */ +/*#define EXPERIMENTAL *//*Experimental flags */ +/*#define FAKEBGR *//* Use BGR instead of RGB, this is for debugging only. Leave it alone! */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mach32.h" +#include "8514a.h" +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#define OFF_ALLOWANCE(a) ((a) * (1.0f - (SYNC_ALLOWANCE/1000.0f))) +#define ADD_ALLOWANCE(a) ((a) * (1.0f + (SYNC_ALLOWANCE/1000.0f))) + +/*List preallocate(for internal info table mixup commands): */ +#define PREALLOC 16 + +/*Internal mixup commands: */ +#define CMD_MSK 0xf000 +#define CMD_ADD 0x0000 +#define CMD_DEL 0x1000 +#define CMD_MOD 0x2000 +#define CMD_CPY 0x3000 +#define CMD_MOV 0x4000 + +#define ATIPORT 0x1ce +#define ATIOFF 0x80 +#define ATISEL(reg) (ATIOFF+reg) + +/* Ports we use: */ +/* moved to 8514a.h - Stephen Lee */ +#define VGA_DAC_MASK 0x3C6 +#define DISP_STATUS 0x2E8 + +#define DAC_W_INDEX 0x02EC +#define DAC_DATA 0x02ED +#define DAC_MASK 0x02EA +#define DAC_R_INDEX 0x02EB + +#define DAC0 0x02EC +#define DAC1 0x02ED +#define DAC2 0x02EA +#define DAC3 0x02EB + +/* Bit masks: */ +#define GE_BUSY 0x0200 +#define ONLY_8514 1 +#define LOCAL_BUS_CONF2 (1<<6) +#define BUS_TYPE 0x000E +#define PCI 0x000E +#define ISA 0x0000 +#define Z4GBYTE (1<<13) + +/* ATI-EXT regs to save (ensure lock regs are set latest, that is they are listed first here!): */ +static const unsigned char mach32_eregs[] = +{ + /* Lock regs: */ + 0x38, 0x34, 0x2e, 0x2b, + /* All other extended regs. */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x20, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2c, + 0x2d, 0x30, 0x31, 0x32, 0x33, 0x35, 0x36, + 0x37, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f}; + +/* Extended ATI VGA regs that have to be reset for plain vga-modes */ +/* First num is ATI reg, 2nd has bits set where to clear bits in the */ +/* ATI reg. Note: the most important clocksel regs 0x38 & 0x39 are */ +/* handled manually */ +static const unsigned char mach32_ati_ext[] = +{ + 0x05, 0x80, /* VGA std blink rate */ + 0x23, 0x18, /* clear ext CRTC bits */ + 0x26, 0xc1, /* no skew of disp enab, dashedunderl */ + 0x27, 0xf1, + 0x2c, 0x41, + 0x2d, 0xff, /* several ext bits */ + 0x2e, 0xef, /* ext page pointers */ + 0x30, 0x65, + 0x31, 0x7b, + 0x32, 0xff, + 0x33, 0xc0, + 0x34, 0x03, + 0x35, 0xf7, + 0x36, 0xf7, + 0x3d, 0x0d}; + + +/* Mach32 regs to save.. read, write address alternating: */ +static const unsigned short mach32_acc_regs[] = +{ + 0xB2EE, 0x06E8, /* H_DISP(ALT H_TOTAL) */ + 0xC2EE, 0x12E8, /* V_TOTAL */ + 0xC6EE, 0x16E8, /* V_DISP */ + 0xCAEE, 0x1AE8, /* V_SYNC_STRT */ + 0xD2EE, 0x1EE8, /* V_SYNC_WID */ + 0x4AEE, 0x4AEE, /* CLOCK_SEL */ + 0x96EE, 0x96EE, /* BRES_COUNT */ + 0x86E8, 0x86E8, /* CUR_X */ + 0x82E8, 0x82E8, /* CUR_Y */ + 0x22EE, 0x22EE, /* DAC_CONT(PCI) */ + 0xF2EE, 0xF2EE, /* DEST_COLOR_CMP_MASK */ + 0x92E8, 0x92E8, /* ERR_TERM */ + 0xA2EE, 0xA2EE, /* LINEDRAW_OPT */ + 0x32EE, 0x32EE, /* LOCAL_CNTL */ + 0x6AEE, 0x6AEE, /* MAX_WAITSTATES / MISC_CONT(PCI) */ + 0x36EE, 0x36EE, /* MISC_OPTIONS */ + 0x82EE, 0x82EE, /* PATT_DATA_INDEX */ + 0x8EEE, 0x7AEE, /* EXT_GE_CONFIG */ + 0xB6EE, 0x0AE8, /* H_SYNC_STRT */ + 0xBAEE, 0x0EE8, /* H_SYNC_WID */ + 0x92EE, 0x7EEE, /* MISC_CNTL */ + 0xDAEE, 0x8EE8, /* SRC_X */ + 0xDEEE, 0x8AE8, /* SRC_Y */ + 0x52EE, 0x52EE, /* SCRATCH0 */ + 0x56EE, 0x56EE, /* SCRATCH1 */ + 0x42EE, 0x42EE, /* MEM_BNDRY */ + 0x5EEE, 0x5EEE, /* MEM_CFG */ +}; + +/* Some internal flags */ +#define PAGE_UNKNOWN 0 +#define PAGE_DIFF 1 +#define PAGE_BOTH 2 + +#define DAC_MODE8 0 +#define DAC_MODEMUX 1 +#define DAC_MODE555 2 +#define DAC_MODE565 3 +#define DAC_MODERGB 4 +#define DAC_MODE32B 5 +#define DAC_SEMICLK 0x80 + +#define EMU_POSS 1 +#define EMU_OVER 2 + +#define EEPROM_USE_CHKSUM 1 +#define EEPROM_USE_MEMCFG 2 +#define EEPROM_USE_TIMING 4 +#define EEPROM_UPDATE 8 + +/*DAC_MODETABLES: */ +static const unsigned char mach32_dac1[4] = +{0x00, 0x00, 0xa2, 0xc2}; + +static const unsigned char mach32_dac4[5] = +{0x00, 0x00, 0xa8, 0xe8, 0xf8}; + +static const unsigned char mach32_dac5[6] = +{0x00, 0x00, 0x20, 0x21, 0x40, +#ifdef USE_RGBa + 0x61 +#else + 0x60 +#endif +}; + +typedef struct { + unsigned char vfifo16, vfifo24; + unsigned char h_disp, h_total, h_sync_wid, h_sync_strt; + unsigned short v_total, v_disp, v_sync_strt; + unsigned char disp_cntl, v_sync_wid; + unsigned short clock_sel, flags, mask, offset; +} mode_entry; + +typedef enum { + R_UNKNOWN, R_STANDARD, R_EXTENDED +} accelstate; + +/*sizeof mode_entry in shorts: */ +#define SOMOD_SH ((sizeof(mode_entry)+sizeof(short)-1)/sizeof(short)) + +/*I put the appropriate VFIFO values from my selfdefined modes in... raise them if you get + strange screen flickering.. (but they have to be <=0xf !!!!) */ +static const mode_entry predef_modes[] = +{ + {0x9, 0xe, 0x4f, 0x63, 0x2c, 0x52, 0x418, 0x3bf, 0x3d6, 0x23, 0x22, 0x50, 0, 0x0000, 0}, + {0x9, 0xe, 0x4f, 0x69, 0x25, 0x52, 0x40b, 0x3bf, 0x3d0, 0x23, 0x23, 0x24, 0, 0x0001, 7}, + {0x9, 0xe, 0x63, 0x84, 0x10, 0x6e, 0x580, 0x4ab, 0x4c2, 0x33, 0x2c, 0x7c, 0, 0x003f, 8}, + {0x9, 0xe, 0x63, 0x84, 0x10, 0x6d, 0x580, 0x4ab, 0x4c2, 0x33, 0x0c, 0x0c, 0, 0x003d, 8}, + {0x9, 0xe, 0x63, 0x7f, 0x09, 0x66, 0x4e0, 0x4ab, 0x4b0, 0x23, 0x02, 0x0c, 0, 0x003c, 8}, + {0x9, 0xe, 0x63, 0x83, 0x10, 0x68, 0x4e3, 0x4ab, 0x4b3, 0x23, 0x04, 0x30, 0, 0x0038, 8}, + {0x9, 0xe, 0x63, 0x7d, 0x12, 0x64, 0x4f3, 0x4ab, 0x4c0, 0x23, 0x2c, 0x1c, 0, 0x0030, 8}, + {0x9, 0xe, 0x63, 0x82, 0x0f, 0x6a, 0x531, 0x4ab, 0x4f8, 0x23, 0x06, 0x10, 0, 0x0020, 8}, + {0xd, 0xe, 0x7f, 0x9d, 0x16, 0x81, 0x668, 0x5ff, 0x600, 0x33, 0x08, 0x1c, 0, 0x0001, 9}, + {0xd, 0xe, 0x7f, 0xa7, 0x31, 0x82, 0x649, 0x5ff, 0x602, 0x23, 0x26, 0x3c, 0, 0x0003, 9}, + {0xd, 0xe, 0x7f, 0xad, 0x16, 0x85, 0x65b, 0x5ff, 0x60b, 0x23, 0x04, 0x38, 0, 0x0013, 9}, + {0xd, 0xe, 0x7f, 0xa5, 0x31, 0x83, 0x649, 0x5ff, 0x602, 0x23, 0x26, 0x38, 0, 0x0017, 9}, + {0xd, 0xe, 0x7f, 0xa0, 0x31, 0x82, 0x649, 0x5ff, 0x602, 0x23, 0x26, 0x38, 0, 0x001f, 9}, + {0xe, 0xe, 0x9f, 0xc7, 0x0a, 0xa9, 0x8f8, 0x7ff, 0x861, 0x33, 0x0a, 0x2c, 0, 0x0001, 10}, + {0xe, 0xe, 0x9f, 0xc7, 0x0a, 0xa9, 0x838, 0x7ff, 0x811, 0x33, 0x0a, 0x2c, 0, 0x0003, 10}, +}; + +#define NUM_MODES (sizeof(predef_modes)/sizeof(mode_entry)) + +static const mode_entry **mach32_modes = NULL; + +static int mach32_clocks[32] = +{ /* init to zero for safety */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; + +static signed char mach32_clock_by2[32], mach32_clock_by3[32]; + +/*Bitmask is 1 256-col, 2 15-16 bpp, 4 24 bpp, 8 32bpp */ +static unsigned char mach32_mmask[2][8] = +{ + { /* General supported modes.. */ 3, 3, 0xf, 1, 0x7, 0xf, 1, 1}, + { /* Modes above 80Mhz.. */ 0, 0, 1, 0, 0, 0xf, 0, 0}}; + +/* Modes that ATI mentions for it's DACS.. this is for safety and the internal + predefined modes.. I think the above restrictions should be enough.. However + I don't want to risk the life of your DAC so.. */ +static unsigned char dacmo640[] = +{0x3, 0x3, 0xf, 0x1, 0x7, 0xf, 0x1, 0x1}; +static unsigned char dacmo800[] = +{0x3, 0x3, 0xf, 0x1, 0x3, 0xf, 0x1, 0x1}; +static unsigned char dacmo1024[] = +{0x3, 0x1, 0x3, 0x1, 0x1, 0xf, 0x1, 0x1}; +static unsigned char dacmo1280[] = +{0x0, 0x0, 0x1, 0x0, 0x0, 0xf, 0x0, 0x0}; + +/* several globals.. mostly to record current state of the driver */ +static char vfifo8 = VFIFO8, vfifo16 = VFIFO16, vfifo24 = VFIFO24, vfifo32 = VFIFO32, + mach32_apsiz = 0; +static char dac_override = 127, svga_clock = SVGA_CLOCK, mach32_ast = 0; +static char *eeprom_fname = NULL; +static char emuimage = EMU_POSS | EMU_OVER; /* Never set EMU_OVER w/o EMU_POSS !!! */ +static char eeprom_option = EEPROM_USE_CHKSUM | EEPROM_USE_MEMCFG | EEPROM_USE_TIMING; + +static unsigned short *mach32_eeprom, mach32_disp_shadow = 0, mach32_strictness = 0, +*mach32_modemixup; +static unsigned short mach32_apadd = 1, mach32_memcfg; + +static unsigned short mach32_ge_pitch = 0, mach32_ge_off_h = 0, mach32_ge_off_l = 0; +static unsigned short mach32_bkgd_alu_fn = 7, mach32_frgd_alu_fn = 7; +static unsigned short mach32_frgd_col = 0xFFFF, mach32_bkgd_col = 0; +static unsigned short mach32_polyfill = 0, mach32_rop = ROP_COPY; + +static int mach32_memory, mach32_dac, mach32_pagemode = PAGE_UNKNOWN, + mach32_dacmode = DAC_MODE8; +static int mach32_chiptype, mixup_alloc = 0, mixup_ptr = 0, clocks_set = 0, + ext_settings = 0; +static int mach32_maxclk8 = MAXCLK8, mach32_maxclk16 = MAXCLK16, mach32_maxclk24 = MAXCLK24; +static int mach32_maxclk32 = MAXCLK32, latchopt = ~0, bladj = -1; +static int pos_ext_settings = VGA_CLUT8; +static int acc_supp = HAVE_BLITWAIT | HAVE_FILLBLIT | HAVE_IMAGEBLIT | HAVE_BITBLIT | HAVE_HLINELISTBLIT; +static int accel_supp = ACCELFLAG_SETFGCOLOR | ACCELFLAG_SETBGCOLOR | + ACCELFLAG_SETTRANSPARENCY | ACCELFLAG_SETRASTEROP | + ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY | + ACCELFLAG_DRAWLINE | ACCELFLAG_PUTIMAGE | + ACCELFLAG_DRAWHLINELIST | ACCELFLAG_PUTBITMAP | + ACCELFLAG_SCREENCOPYMONO | ACCELFLAG_SETMODE | + ACCELFLAG_POLYLINE | ACCELFLAG_POLYHLINE | + ACCELFLAG_POLYFILLMODE | ACCELFLAG_SYNC; + +static int palcurind = -1; +static int palsetget = -1; + +static accelstate mach32_accelstate = R_UNKNOWN; + +#ifdef DEBUG +static char verbose = 1; +#else +static char verbose = 0; +#endif +#ifdef EXPERIMENTAL +static unsigned mach32_experimental = 0; +#endif + + +static volatile char *mach32_aperture = NULL; +static volatile int dummy; + +static signed char mach32_search_clk(int clk); +static void mach32_setstate(accelstate which); +static void mach32_blankadj(int adj); +static void mach32_modfill(const mode_entry * mode, int modemask, int forcein); +static int mach32_test(void); +static int mach32_init(int force, int chiptype, int memory); +static void mach32_i_bltwait(void); +static void mach32_bltwait(void); +static void mach32_wait(void); +static void mach32_experm(void); +static int mach32_eeclock(register int ati33); +static void mach32_eekeyout(register int ati33, register int offset, register int mask); +static int mach32_eeget(int offset); +static int mach32_saveregs(unsigned char regs[]); +static void mach32_setregs(const unsigned char regs[], int mode); +static void mach32_unlock(void); +static void mach32_lock(void); +static int mach32_sav_dac(int offset, unsigned char regs[]); +static int mach32_set_dac(int dac_mode, int clock_intended, int xres); +static void mach32_setpage(int page); +static void mach32_setrdpage(int page); +static void mach32_setwrpage(int page); +static void mach32_setappage(int page); +static void mach32_setdisplaystart(int address); +static void mach32_setlogicalwidth(int width); +static int mach32_modeavailable(int mode); +static void mach32_getmodeinfo(int mode, vga_modeinfo * modeinfo); +static int mach32_setmode(int mode, int previous); +static void mach32_bitblt(int srcaddr, int destaddr, int w, int h, int pitch); +static void mach32_fillblt(int destaddr, int w, int h, int pitch, int c); +static void mach32_imageblt(void *srcaddr, int destaddr, int w, int h, int pitch); +static void mach32_memimageblt(void *srcaddr, int destaddr, int w, int h, int pitch); +static void mach32_hlinelistblt(int ymin, int n, int *xmin, int *xmax, int pitch, int c); +static void mach32_readconfig(void); +static void mach32_final_modefixup(void); +static int mach32_ext_set(unsigned what, va_list params); +static int mach32_accel(unsigned operation, va_list params); +static void mach32_ge_reset(void); +static void slow_queue(unsigned short mask); + +static void mach32_savepalette(unsigned char *red, unsigned char *green, unsigned char *blue); +static void mach32_restorepalette(const unsigned char *red, const unsigned char *green, + const unsigned char *blue); +static int mach32_setpalette(int index, int red, int green, int blue); +static void mach32_getpalette(int index, int *red, int *green, int *blue); +static int mach32_screenon(void); +static void mach32_waitretrace(void); + +DriverSpecs __svgalib_mach32_driverspecs = +{ + mach32_saveregs, /* saveregs */ + mach32_setregs, /* setregs */ + mach32_unlock, /* unlock */ + mach32_lock, /* lock */ + mach32_test, + mach32_init, + mach32_setpage, /* __svgalib_setpage */ + mach32_setrdpage, /* __svgalib_setrdpage */ + mach32_setwrpage, /* __svgalib_setwrpage */ + mach32_setmode, /* setmode */ + mach32_modeavailable, /* modeavailable */ + mach32_setdisplaystart, /* setdisplaystart */ + mach32_setlogicalwidth, /* setlogicalwidth */ + mach32_getmodeinfo, /* getmodeinfo */ + mach32_bitblt, /* bitblt */ + mach32_imageblt, /* imageblt */ + mach32_fillblt, /* fillblt */ + mach32_hlinelistblt, /* hlinelistblt */ + mach32_bltwait, /* bltwait */ + mach32_ext_set, + mach32_accel, + 0, /* linear -- mach32 driver handles it differently */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + +static Emulation mach32_vgaemul = { + mach32_savepalette, + mach32_restorepalette, + mach32_setpalette, + mach32_getpalette, + NULL, /* void (*savefont)(void); */ + NULL, /* void (*restorefont)(void); */ + NULL, /* int (*screenoff)(void); */ + mach32_screenon, + mach32_waitretrace, +}; + +#ifdef FAST_MEMCPY +/* This memcpy is immediately derived from memset as given in speedtest.c in this + same svgalib package written by Harm Hanemaayer */ + +static inline void * + fast_memcpy(void *dest, void *source, size_t count) +{ + __asm__( + "cld\n\t" + "cmpl $12,%%edx\n\t" + "jl 1f\n\t" /* if (count >= 12) */ + + "movl %%edx,%%ecx\n\t" + "negl %%ecx\n\t" + "andl $3,%%ecx\n\t" /* (-s % 4) */ + "subl %%ecx,%%edx\n\t" /* count -= (-s % 4) */ + "rep ; movsb\n\t" /* align to longword boundary */ + + "movl %%edx,%%ecx\n\t" + "shrl $2,%%ecx\n\t" + + /* Doing any loop unrolling here proved to SLOW!!! down + the copy on my system, at least it didn't show any speedup. */ + + "rep ; movsl\n\t" /* copy remaining longwords */ + + "andl $3,%%edx\n" /* copy last few bytes */ + "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ + "rep ; movsb\n\t": + /* no outputs */ : + /* inputs */ + /* SI= source address */ "S"(source), + /* DI= destination address */ "D"(dest), + /* CX= words to transfer */ "d"(count): + /* eax, edx, esi, edi, ecx destructed: */ "%eax", "%edx", "%esi", "%edi", "%ecx"); + return dest; +} +#else +#define fast_memcpy memcpy +#endif + +static inline int max(int a, int b) +{ + return (a > b) ? a : b; +} + +static inline void checkqueue(int n) +{ /* This checks for at least n free queue positions */ +/*Prepare mask: */ + unsigned short mask = (unsigned short) (0xffff0000 >> n); + int i = BUSYWAIT; + + while (i--) + if (!(inw(EXT_FIFO_STATUS) & mask)) + return; + + slow_queue(mask); +} + +static void slow_queue(unsigned short mask) +{ + clock_t clk_time; + + clk_time = clock(); + + do { + if (!(inw(EXT_FIFO_STATUS) & mask)) + return; + } + while ((clock() - clk_time) < (CLOCKS_PER_SEC * ADDIWAIT)); + + mach32_ge_reset(); /* Give up */ +} + +static void mach32_ge_reset(void) +{ /* This is intended as a safety bailout if we locked + up the card. */ + int queue_stat, ioerr, ge_stat; + int i = 1000000; + volatile int dummy; + +/* Provide diagnostics: */ + ioerr = inw(SUBSYS_STAT); + queue_stat = inw(EXT_FIFO_STATUS); + ge_stat = inw(GE_STAT); + + + port_outw_r(SUBSYS_CNTL, 0x800f); /*Reset GE, disable all IRQ, reset all IRQ state bits */ + while (i--) + dummy++; + port_outw_r(SUBSYS_CNTL, 0x400f); /*Continue normal operation */ +/* Better reconfigure all used registers */ + mach32_accelstate = R_UNKNOWN; + CRITICAL = 0; /* Obviously we are idle */ + fprintf(stderr,"\asvgalib: mach32: Warning! GE_Engine timed out, draw command\n" + "was probably corrupted! If you have a very fast machine (10*Pentium)\n" + "raise BUSYWAIT and ADDIWAIT in mach32.c, may also be a driver/card bug,\n" + "so report detailed info to me (Michael Weller).\nBUT:\n" + "This reaction is normal when svgalib is killed in a very critical operation\n" + "by a fatal signal like INT (pressing ^C). In this situation this reset just\n" + "guarantees that you can continue working on the console, so in this case\n" + "PLEASE don't bloat my mailbox with bug reports. Thx, Michael.\n"); + fprintf(stderr,"POST-Mortem:\n\tSubsys stat: %04x - %sIOerror (is usually a queue overrun)\n" + "\tGE stat : %04x - engine %s, %sdata ready for host.\n\tQueue stat : %04x\n", + ioerr, (ioerr & 4) ? "" : "no ", ge_stat, + (ge_stat & GE_BUSY) ? "busy" : "idle", (ge_stat & 0x100) ? "" : "no ", queue_stat); +} + +static void mach32_setstate(accelstate which) +{ /* Set GE registers to values assumed elsewhere */ + mach32_accelstate = which; + + checkqueue(10); + /*Effectively switch off hardware clipping: */ + port_outw_r(MULTI_FUNC_CNTL, 0x1000 | (0xfff & -1)); /*TOP */ + port_outw_r(MULTI_FUNC_CNTL, 0x2000 | (0xfff & -1)); /*LEFT */ + port_outw_r(MULTI_FUNC_CNTL, 0x3000 | 1535); /*BOTTOM */ + port_outw_r(MULTI_FUNC_CNTL, 0x4000 | 1535); /*RIGHT */ + /*Same for ATI EXT commands: */ + port_outw_r(EXT_SCISSOR_T, 0xfff & -512); /*TOP */ + port_outw_r(EXT_SCISSOR_L, 0xfff & -512); /*LEFT */ + port_outw_r(EXT_SCISSOR_B, 1535); /*BOTTOM */ + port_outw_r(EXT_SCISSOR_R, 1535); /*RIGHT */ + port_outw_r(MULTI_FUNC_CNTL, 0xa000); + port_outw_r(DP_CONFIG, 0x3291); + + checkqueue(4); + port_outw_r(DEST_CMP_FN, 0); + if (which == R_STANDARD) { + checkqueue(2); + port_outw_r(BKGD_MIX, 0x0027); /* Not used .. however ensure PIX_TRANS is not used */ + port_outw_r(ALU_FG_FN, 7); + } else { + checkqueue(5); + port_outw_r(GE_OFFSET_LO, mach32_ge_off_l); + port_outw_r(GE_OFFSET_HI, mach32_ge_off_h); + port_outw_r(GE_PITCH, mach32_ge_pitch); + port_outw_r(BKGD_MIX, mach32_bkgd_alu_fn); + port_outw_r(FRGD_MIX, mach32_frgd_alu_fn | 0x20); + checkqueue(6); + port_outw_r(ALU_BG_FN, mach32_bkgd_alu_fn); + port_outw_r(ALU_FG_FN, mach32_frgd_alu_fn); + port_outw_r(FRGD_COLOR, mach32_frgd_col); + port_outw_r(BKGD_COLOR, mach32_bkgd_col); + port_outw_r(RD_MASK, (infotable[CM].colors == 32768) ? 0x7fff : 0xffff); + port_outw_r(LINEDRAW_OPT, 0); + } +} + +static void mach32_setdisplaystart(int address) +{ +#ifdef DEBUG + fprintf(stderr,"mach32_setdisplaystart(%x)\n", address); +#endif + mach32_ge_off_l = address >> 2; + port_outw_r(CRT_OFFSET_LO, mach32_ge_off_l); + mach32_ge_off_h = 0xff & (address >> 18); + port_outw_r(CRT_OFFSET_HI, mach32_ge_off_h); + if (mach32_accelstate == R_EXTENDED) { + checkqueue(2); + port_outw_r(GE_OFFSET_LO, mach32_ge_off_l); + port_outw_r(GE_OFFSET_HI, mach32_ge_off_h); + } + __svgalib_vga_driverspecs.setdisplaystart(address); +} + +static void mach32_setlogicalwidth(int width) +{ + register int mywidth; +#ifdef DEBUG + fprintf(stderr,"mach32_setlogicalwidth(%d)\n", width); +#endif + if (infotable[CM].bytesperpixel) { /* always >= 1 for Mach32 modes */ + /*Unfortunately the Mach32 expects this value in Pixels not bytes: */ + mywidth = width / (infotable[CM].bytesperpixel); + mywidth = (mywidth >> 3) & 0xff; +#ifdef DEBUG + fprintf(stderr,"mach32_setlogicalwidth: Mach32 width to %d pels.\n", mywidth * 8); +#endif + port_outw_r(CRT_PITCH, mywidth); + mach32_ge_pitch = mywidth; + if (mach32_accelstate == R_EXTENDED) { + checkqueue(1); + port_outw_r(GE_PITCH, mywidth); + } + } + __svgalib_vga_driverspecs.setlogicalwidth(width); +} + + +static void mach32_setpage(int page) +{ + register unsigned short tmp; + +#ifdef DEBUG + fprintf(stderr,"mach32_setpage(%d)\n", page); +#endif + if (mach32_pagemode != PAGE_BOTH) { + port_out_r(ATIPORT, ATISEL(0x3E)); + tmp = port_in(ATIPORT + 1) & 0xf7; + tmp = (tmp << 8) | ATISEL(0x3E); + port_outw_r(ATIPORT, tmp); + mach32_pagemode = PAGE_BOTH; + } + tmp = (page << 9) & 0x1e00; + port_outw_r(ATIPORT, ATISEL(0x32) | tmp); + port_out_r(ATIPORT, ATISEL(0x2e)); + tmp = (port_in(ATIPORT + 1) & 0xfc) | ((page >> 4) & 3); + port_outw_r(ATIPORT, ATISEL(0x2e) | (tmp << 8)); +} + +static void mach32_setwrpage(int page) +{ + register unsigned short tmp; + if (mach32_pagemode != PAGE_DIFF) { + port_out_r(ATIPORT, ATISEL(0x3E)); + port_outw_r(ATIPORT, (ATISEL(0x3E) << 8) | (port_in(ATIPORT + 1) | 8)); + mach32_pagemode = PAGE_DIFF; + } + port_out_r(ATIPORT, ATISEL(0x32)); + tmp = port_in(ATIPORT + 1) & 0xe1; + port_outw_r(ATIPORT, (ATISEL(0x32) << 8) | ((page << 1) & 0x1e)); + port_out_r(ATIPORT, ATISEL(0x2e)); + tmp = port_in(ATIPORT + 1) & 0xfc; + port_outw_r(ATIPORT, (ATISEL(0x2e) << 8) | tmp | ((page >> 4) & 3)); +} + +static void mach32_setrdpage(int page) +{ + register unsigned short tmp; + if (mach32_pagemode != PAGE_DIFF) { + port_out_r(ATIPORT, ATISEL(0x3E)); + port_outw_r(ATIPORT, (ATISEL(0x3E) << 8) | (port_in(ATIPORT + 1) | 8)); + mach32_pagemode = PAGE_DIFF; + } + port_out_r(ATIPORT, ATISEL(0x32)); + tmp = port_in(ATIPORT + 1) & 0x1e; + if (page & 8) + tmp |= 1; + port_outw_r(ATIPORT, (ATISEL(0x32) << 8) | tmp | ((page << 5) & 0xe0)); + port_out_r(ATIPORT, ATISEL(0x2e)); + tmp = port_in(ATIPORT + 1) & 0xf3; + port_outw_r(ATIPORT, (ATISEL(0x2e) << 8) | tmp | ((page >> 2) & 0xc)); +} + +static void mach32_setappage(int page) +{ + port_outw_r(MEM_CFG, (mach32_memcfg | (0xc & (page << 2)))); +} + +static int mach32_sav_dac(int offset, unsigned char regs[]) +{ +/* I was unable to read out the actual DAC_config, so + we just save which mode we are in: */ + + regs[offset] = mach32_dacmode; +#ifdef DEBUG + fprintf(stderr,"mach32_sav_dac(%d,...): Dac:%d, dac_mode:%d\n", offset, mach32_dac, + regs[offset]); +#endif + return offset + 1; +} + +static inline void clean_clocks(void) +{ + port_outw_r(CLOCK_SEL, (inw(CLOCK_SEL) & ~0x7f) | 0x11); +} + +static int mach32_set_dac(int dac_mode, int clock_intended, int xres) +{ + unsigned short act_ge_conf; + const unsigned char *dac_reg; + + + act_ge_conf = inw(R_EXT_GE_CONF) & 0x8fff; + +#ifdef DEBUG + fprintf(stderr,"mach32_set_dac(%d,%d): Dac:%d\n", dac_mode, clock_intended, mach32_dac); +#endif + mach32_dacmode = dac_mode; + dac_mode &= 0x7f; + mach32_blankadj((mach32_dac == MACH32_ATI68830) ? 0x4 : 0xc); + switch (mach32_dac) { + case MACH32_SC11483: + dac_reg = mach32_dac1; +#ifdef DEBUG + fputs("DAC1: ", stderr); +#endif + if (dac_mode <= DAC_MODE565) + goto dac1_4; + break; + case MACH32_ATI6871: + /*This one is a nightmare: */ + clean_clocks(); + port_outw_r(EXT_GE_CONF, 0x201a); + + switch (dac_mode) { + + default: + case DAC_MODE8: + case DAC_MODEMUX: + port_out_r(DAC1, 0x00); + port_out_r(DAC2, 0x30); + port_out_r(DAC3, 0x2d); +#ifdef DEBUG + fprintf(stderr,"DAC2: 0x00 0x30 0x2d (8bpp)\n"); +#endif + if (dac_mode != DAC_MODEMUX) + break; + port_out_r(DAC2, 0x09); + port_out_r(DAC3, 0x1d); + port_out_r(DAC1, 0x01); + mach32_blankadj(1); +#ifdef DEBUG + fprintf(stderr"DAC2: 0x01 0x09 0x1d (8bpp MUX)\n"); +#endif + break; + case DAC_MODE555: + case DAC_MODE565: + case DAC_MODERGB: + mach32_blankadj(1); + case DAC_MODE32B: + port_out_r(DAC1, 0x01); + if ((!(clock_intended & 0xc0)) && (!(mach32_dacmode & DAC_SEMICLK))) { + port_out_r(DAC2, 0x00); +#ifdef DEBUG + fprintf(stderr,"DAC2: 0x01 0x00 0x0d (16/24bpp)\n"); +#endif + } else { + clock_intended &= 0xff3f; + port_out_r(DAC2, 0x08); + mach32_dacmode |= DAC_SEMICLK; + if (xres <= 640) + mach32_blankadj(2); +#ifdef DEBUG + fprintf(stderr,"DAC2: 0x01 0x08 0x0d (16/24bpp)\n"); +#endif + } + port_out_r(DAC3, 0x0d); + act_ge_conf |= 0x4000; + if (dac_mode == DAC_MODE32B) + mach32_blankadj(3); + break; + } + if (bladj >= 0) + mach32_blankadj(bladj); + break; + case MACH32_BT481: + dac_reg = mach32_dac4; +#ifdef DEBUG + fputs("DAC4: ", stderr); +#endif + dac1_4: + if (dac_mode <= DAC_MODERGB) { + clean_clocks(); + port_outw_r(EXT_GE_CONF, 0x101a); +#ifdef DEBUG + fprintf(stderr,"%02x\n", dac_reg[dac_mode]); +#endif + port_out_r(DAC2, dac_reg[dac_mode]); + } + break; + case MACH32_ATI68860: + clean_clocks(); + port_outw_r(EXT_GE_CONF, 0x301a); +#ifdef DEBUG + fprintf(stderr,"DAC5: %02x\n", mach32_dac5[dac_mode]); +#endif + port_out_r(DAC0, mach32_dac5[dac_mode]); + break; + } +/*Dac RS2,3 to 0 */ + act_ge_conf &= 0x8fff; + if ((dac_mode == DAC_MODE8) || (dac_mode == DAC_MODEMUX)) + if (ext_settings & VGA_CLUT8) + act_ge_conf |= 0x4000; + port_outw_r(EXT_GE_CONF, act_ge_conf); +/*Set appropriate DAC_MASK: */ + switch (dac_mode) { + case DAC_MODE8: + case DAC_MODEMUX: +#ifdef DEBUG + fprintf(stderr,"DAC-Mask to 0xff\n"); +#endif + port_out_r(DAC_MASK, 0xff); + break; + default: + switch (mach32_dac) { + case MACH32_ATI6871: + case MACH32_BT481: +#ifdef DEBUG + fprintf(stderr,"DAC-Mask to 0x00\n"); +#endif + port_out_r(DAC_MASK, 0x00); + break; + } +#ifdef DEBUG + fprintf(stderr,"VGA-DAC-Mask to 0x0f\n"); +#endif + port_out_r(VGA_DAC_MASK, 0x0f); + break; + } + return clock_intended; +} + +static int mach32_saveregs(unsigned char regs[]) +{ + int i, retval; + unsigned short tmp; + + mach32_bltwait(); /* Ensure noone draws in the screen */ + + for (i = 0; i < sizeof(mach32_eregs); i++) { + port_out_r(ATIPORT, ATISEL(mach32_eregs[i])); + regs[EXT + i] = port_in(ATIPORT + 1); + } + regs[EXT + i] = mach32_disp_shadow; /* This is for DISP_CNTL */ + retval = i + EXT + 1; + for (i = 0; i < (sizeof(mach32_acc_regs) / sizeof(unsigned short)); i += 2) { + tmp = inw(mach32_acc_regs[i]); + regs[retval++] = tmp; + regs[retval++] = (tmp >> 8); + } + retval = mach32_sav_dac(retval, regs); +#ifdef DEBUG + fprintf(stderr,"mach32_saveregs: retval=%d\n", retval); +#endif + return retval - EXT; +} + +static void mach32_setregs(const unsigned char regs[], int mode) +{ + int i, offset, retval, clock_intended = 0; + unsigned short tmp; + + mach32_bltwait(); /* Ensure noone draws in the screen */ + mach32_accelstate = R_UNKNOWN; /* Accel registers need to be reset */ + + offset = EXT + sizeof(mach32_eregs) + (sizeof(mach32_acc_regs) / sizeof(unsigned short)) + 1; + +/*Find out which clock we want to use: */ + for (i = (sizeof(mach32_acc_regs) / sizeof(unsigned short)) - 1, retval = offset; i >= 0; + i -= 2, retval -= 2) + if (mach32_acc_regs[i] == CLOCK_SEL) { + clock_intended = ((unsigned short) regs[--retval]) << 8; + clock_intended |= regs[--retval]; + break; + } +#ifdef DEBUG + fprintf(stderr,"mach32_setregs: offset=%d, clock_intended=%d\n", offset, clock_intended); +#endif + + retval = offset + 1; + mach32_set_dac(regs[offset], clock_intended, 0); /*We can savely call with a fake xres coz + blank adjust will be restored afterwards + anyways... */ + + for (i = (sizeof(mach32_acc_regs) / sizeof(unsigned short)) - 1; i >= 0; i -= 2) { + tmp = ((unsigned short) regs[--offset]) << 8; + tmp |= regs[--offset]; + /* restore only appage in MEM_CFG... otherwise badly interaction + with X that may change MEM_CFG and does not only not restore it's + original value but also insist on it not being changed on VC + change... =:-o */ + if (mach32_acc_regs[i] == MEM_CFG) + tmp = (inw(MEM_CFG) & ~0xc) | (tmp & 0xc); + if (mach32_ast && (mach32_acc_regs[i] == MISC_CTL)) + continue; + if (mach32_acc_regs[i] == H_DISP) { + /* H_TOTAL (alt) in H_DISP broken for some chipsets... */ + port_out_r(H_TOTAL, tmp >> 8); + port_out_r(H_DISP, tmp); + } else { + port_outw_r(mach32_acc_regs[i], tmp); + } + } + mach32_disp_shadow = regs[--offset] & ~0x60; + port_out_r(DISP_CNTL, mach32_disp_shadow | 0x40); /* Mach32 CRT reset */ + if (inw(CLOCK_SEL) & 1) /* If in non VGA mode */ + port_outw_r(DISP_CNTL, mach32_disp_shadow | 0x20); /* Mach32 CRT enabled */ + + for (i = sizeof(mach32_eregs) - 1; i >= 0; i--) { + port_out_r(ATIPORT, ATISEL(mach32_eregs[i])); + port_out_r(ATIPORT + 1, regs[--offset]); + } + +} + +static void mach32_unlock(void) +{ + unsigned short oldval; + +#ifdef DEBUG + fprintf(stderr,"mach32_unlock\n"); +#endif /* DEBUG */ + port_out_r(ATIPORT, ATISEL(0x2e)); + oldval = port_in(ATIPORT + 1) & ~0x10; /* Unlock CPUCLK Select */ + port_outw_r(ATIPORT, ATISEL(0x2e) | (oldval << 8)); + + port_out_r(ATIPORT, ATISEL(0x2b)); + oldval = port_in(ATIPORT + 1) & ~0x18; /* Unlock DAC, Dbl Scan. */ + port_outw_r(ATIPORT, ATISEL(0x2b) | (oldval << 8)); + + port_out_r(ATIPORT, ATISEL(0x34)); + oldval = port_in(ATIPORT + 1) & ~0xfc; /* Unlock Crt9[0:4,7], Vtiming, Cursr start/end, + CRT0-7,8[0-6],CRT14[0-4]. but disable ignore of CRT11[7] */ + port_outw_r(ATIPORT, ATISEL(0x34) | (oldval << 8)); + + port_out_r(ATIPORT, ATISEL(0x38)); /* Unlock ATTR00-0f, ATTR11, whole vga, port 3c2 */ + oldval = port_in(ATIPORT + 1) & ~0x0f; + port_outw_r(ATIPORT, ATISEL(0x38) | (oldval << 8)); + +/* Unlock vga-memory too: */ + + port_outw_r(MEM_BNDRY, 0); + +/* Unlock Mach32 CRT Shadowregisters... this one made me crazy... + Thanx to the Xfree sources I finally figured it out.... */ + port_outw_r(SHADOW_SET, 1); + port_outw_r(SHADOW_CTL, 0); + port_outw_r(SHADOW_SET, 2); + port_outw_r(SHADOW_CTL, 0); + port_outw_r(SHADOW_SET, 0); +} + +static void mach32_lock(void) +{ + unsigned short oldval; + +#ifdef DEBUG + fprintf(stderr,"mach32_lock\n"); +#endif /* DEBUG */ +/* I'm really not sure if calling this function would be a good idea */ +/* Actually it is not called in svgalib */ + port_out_r(ATIPORT, ATISEL(0x2b)); + oldval = port_in(ATIPORT + 1) | 0x18; /* Lock DAC, Dbl Scan. */ + port_outw_r(ATIPORT, ATISEL(0x2b) | (oldval << 8)); + + port_out_r(ATIPORT, ATISEL(0x34)); + oldval = port_in(ATIPORT + 1) | 0xfc; /* Lock Crt9[0:4,7], Vtiming, Cursr start/end, + CRT0-7,8[0-6],CRT14[0-4]. but disable ignore of CRT11[7] */ + port_outw_r(ATIPORT, ATISEL(0x34) | (oldval << 8)); + + port_out_r(ATIPORT, ATISEL(0x38)); /* Lock ATTR00-0f, ATTR11, whole vga, port 3c2 */ + oldval = port_in(ATIPORT + 1) | 0x0f; + port_outw_r(ATIPORT, ATISEL(0x38) | (oldval << 8)); + + port_outw_r(SHADOW_SET, 1); + port_outw_r(SHADOW_CTL, 0x7f); + port_outw_r(SHADOW_SET, 2); + port_outw_r(SHADOW_CTL, 0x7f); + port_outw_r(SHADOW_SET, 0); +} + +static void mach32_experm(void) +{ + fprintf(stderr,"svgalib(mach32): Cannot get I/O permissions.\n"); + exit(-1); +} + +static void mach32_bltwait(void) +{ + int i = BUSYWAIT; + clock_t clk_time; + + checkqueue(16); /* Ensure nothing in the queue */ + + while (i--) + if (!(inw(GE_STAT) & (GE_BUSY | 1))) { + done: + /* Check additional stats */ + if (inw(SUBSYS_STAT) & 4) + goto failure; + CRITICAL = 0; /* Obviously we're idle */ + return; + } + clk_time = clock(); + + do { + if (!(inw(GE_STAT) & (GE_BUSY | 1))) + goto done; + } + while ((clock() - clk_time) < (CLOCKS_PER_SEC * ADDIWAIT)); + + failure: + mach32_ge_reset(); +} + +static void mach32_i_bltwait(void) +{ + int i; + + for (i = 0; i < 100000; i++) + if (!(inw(GE_STAT) & (GE_BUSY | 1))) + break; +} + +static int mach32_test(void) +{ + int result = 0; + short tmp; + +/* Har, har.. now we can switch off interrupts to crash the system... ;-)=) */ +/* (But actually we need only access to extended io-ports...) */ + + tmp = inw(SCRATCH_PAD_0); + port_outw_r(SCRATCH_PAD_0, 0x5555); + mach32_i_bltwait(); + if (inw(SCRATCH_PAD_0) == 0x5555) { + port_outw_r(SCRATCH_PAD_0, 0x2a2a); + mach32_i_bltwait(); + if (inw(SCRATCH_PAD_0) == 0x2a2a) { + /* Aha.. 8514/a detected.. */ + result = 1; + } + } + port_outw_r(SCRATCH_PAD_0, tmp); + if (!result) + goto quit; +/* Now ensure it is not a plain 8514/a: */ + result = 0; + port_outw_r(DESTX_DIASTP, 0xaaaa); + mach32_i_bltwait(); + if (inw(R_SRC_X) == 0x02aa) { + port_outw_r(DESTX_DIASTP, 0x5555); + mach32_i_bltwait(); + if (inw(R_SRC_X) == 0x0555) + result = 1; + } + if (!result) + goto quit; + result = 0; +/* Ok, now we have a Mach32. Unfortunately we need also the VGA to be enabled: */ + if (inw(CONF_STAT1) & ONLY_8514) { + if (__svgalib_driver_report) + fprintf(stderr,"Mach32 detected, but unusable with VGA disabled.\nSorry.\n"); + goto quit; /*VGA circuitry disabled. */ + } + result = 1; + quit: + if (result) + mach32_init(0, 0, 0); +#ifdef DEBUG + fprintf(stderr,"mach32_test: returning %d.\n", result); +#endif /* DEBUG */ + return result; +} + +static void mach32_wait(void) +{ +/* Wait for at least 22 us.. (got that out of a BIOS disassemble on my 486/50 ;-) ) ... */ + register int i; + for (i = 0; i < 16; i++) + dummy++; /*Dummy is volatile.. */ +} + +static int mach32_eeclock(register int ati33) +{ + port_outw_r(ATIPORT, ati33 |= 0x200); /* clock on */ + mach32_wait(); + port_outw_r(ATIPORT, ati33 &= ~0x200); /* clock off */ + mach32_wait(); + return ati33; +} + +static void mach32_eekeyout(register int ati33, register int offset, register int mask) +{ + do { + if (mask & offset) + ati33 |= 0x100; + else + ati33 &= ~0x100; + port_outw_r(ATIPORT, ati33); + mach32_eeclock(ati33); + } + while (mask >>= 1); +} + +static int mach32_eeget(int offset) +{ + register int ati33; + register int result, i; + +/* get current ATI33 */ + port_out_r(ATIPORT, ATISEL(0x33)); + ati33 = ((int) inw(ATIPORT + 1)) << 8; + ati33 |= ATISEL(0x33); +/* prepare offset.. cut and add header and trailer */ + offset = (0x600 | (offset & 0x7f)) << 1; + +/* enable eeprom sequence */ + ati33 = mach32_eeclock(ati33); +/*input to zero.. */ + port_outw_r(ATIPORT, ati33 &= ~0x100); +/*enable to one */ + port_outw_r(ATIPORT, ati33 |= 0x400); + mach32_eeclock(ati33); +/*select to one */ + port_outw_r(ATIPORT, ati33 |= 0x800); + mach32_eeclock(ati33); + mach32_eekeyout(ati33, offset, 0x800); + for (i = 0, result = 0; i < 16; i++) { + result <<= 1; + port_out_r(ATIPORT, ATISEL(0x37)); + if (port_in(ATIPORT + 1) & 0x8) + result |= 1; + mach32_eeclock(ati33); + } +/*deselect... */ + port_outw_r(ATIPORT, ati33 &= ~0x800); + mach32_eeclock(ati33); +/*disable... */ + port_outw_r(ATIPORT, ati33 &= ~0x400); + mach32_eeclock(ati33); + return result; +} + +static int mach32_max_mask(int x) +{ + if (x <= 0x4f) + return dacmo640[mach32_dac]; + if (x <= 0x63) + return dacmo800[mach32_dac]; + if (x <= 0x7f) + return dacmo1024[mach32_dac]; + return dacmo1280[mach32_dac]; +} + +static int mach32_max_vfifo16(int x) +{ + int retval; + + if (x <= 0x63) + retval = vfifo16; + else if (x <= 0x7f) + retval = vfifo16 + 4; + else + retval = vfifo16 + 5; + return (retval < 15) ? retval : 15; +} + +/* Shameless ripped out of Xfree2.1 (with slight changes) : */ + +static void mach32_scan_clocks(void) +{ + const int knownind = 7; + const double knownfreq = 44.9; + + char hstrt, hsync; + int htotndisp, vdisp, vtotal, vstrt, vsync, clck, i; + + int count, saved_nice, loop; + double scale; + + saved_nice = nice(0); + nice(-20 - saved_nice); + + fprintf(stderr,"Warning, about to measure clocks. Wait until system is completely idle!\n" + "Any activity will disturb measuring, and therefor hinder correct driver\n" + "function. Test will need about 3-4 seconds.\n" + "If your monitor doesn't switch off when it gets signals it can't sync on\n" + "better switch it off now before continuing. I'll beep when you can safely\n" + "switch it back on.\n"); +#if 1 + fprintf(stderr,"\n(Enter Y to continue, any other text to bail out)\n"); + + if (getchar() != 'Y') { + bailout: + fprintf(stderr,"\aBailed out.\n"); + exit(0); + } + if (getchar() != '\n') + goto bailout; +#endif + + htotndisp = inw(R_H_TOTAL); + hstrt = port_in(R_H_SYNC_STRT); + hsync = port_in(R_H_SYNC_WID); + vdisp = inw(R_V_DISP); + vtotal = inw(R_V_TOTAL); + vstrt = inw(R_V_SYNC_STRT); + vsync = inw(R_V_SYNC_WID); + clck = inw(CLOCK_SEL); + + port_out_r(DISP_CNTL, 0x63); + + port_out_r(H_TOTAL, 0x63); + port_out_r(H_DISP, 0x4f); + port_out_r(H_SYNC_STRT, 0x52); + port_out_r(H_SYNC_WID, 0x2c); + port_outw_r(V_TOTAL, 0x418); + port_outw_r(V_DISP, 0x3bf); + port_outw_r(V_SYNC_STRT, 0x3d6); + port_outw_r(V_SYNC_WID, 0x22); + + for (i = 0; i < 16; i++) { + port_outw_r(CLOCK_SEL, (i << 2) | 0xac1); + port_out_r(DISP_CNTL, 0x23); + + usleep(MODESWITCHDELAY); + + count = 0; + loop = 200000; + + while (!(port_in(DISP_STATUS) & 2)) + if (loop-- == 0) + goto done; + while (port_in(DISP_STATUS) & 2) + if (loop-- == 0) + goto done; + while (!(port_in(DISP_STATUS) & 2)) + if (loop-- == 0) + goto done; + + for (loop = 0; loop < 5; loop++) { + while (!(port_in(DISP_STATUS) & 2)) + count++; + while ((port_in(DISP_STATUS) & 2)) + count++; + } + done: + mach32_clocks[i] = count; + + port_out_r(DISP_CNTL, 0x63); + } + + port_outw_r(CLOCK_SEL, clck); + + port_out_r(H_TOTAL, htotndisp >> 8); + port_out_r(H_DISP, htotndisp); + port_out_r(H_SYNC_STRT, hstrt); + port_out_r(H_SYNC_WID, hsync); + port_outw_r(V_DISP, vdisp); + port_outw_r(V_TOTAL, vtotal); + port_outw_r(V_SYNC_STRT, vstrt); + port_outw_r(V_SYNC_WID, vsync); + nice(20 + saved_nice); + +/*Recalculation: */ + scale = ((double) mach32_clocks[knownind]) * knownfreq; + for (i = 0; i < 16; i++) { + if (i == knownind) + continue; + if (mach32_clocks[i]) + mach32_clocks[i] = 0.5 + scale / ((double) mach32_clocks[i]); + } + mach32_clocks[knownind] = knownfreq + 0.5; +} + +static signed char mach32_search_clk(int clk) +{ + int i; + + if (!clk) + return 0; + if (clk > 80) /* Actually filter out the too high clocks here already */ + return 0; + for (i = 0; i < 32; i++) + if (abs(clk - mach32_clocks[i]) <= 1) + return i + 1; + return 0; +} + +static unsigned short dac14_clock_adjust(unsigned short clock, signed char *clock_map) +{ + unsigned short clock_ind; + + if ((mach32_dac != MACH32_SC11483) && (mach32_dac != MACH32_BT481)) + return clock; + clock_ind = 0x1f & (clock >> 2); + clock &= 0xff83; + if (!clock_map[clock_ind]) { + vga_setmode(TEXT); + fprintf(stderr,"svgalib-mach32: Panic, internal error: DAC1/4, invalid clock for >8bpp.\n"); + exit(1); + } + return clock | ((clock_map[clock_ind] - 1) << 2); +} + +static int mach32_init(int force, int chiptype, int memory) +{ + char messbuf[12], eeapert = 0; + static int max2msk[] = + {1, 3, 0xf, 0xf}; + static const short mem_conf[] = + {512, 1024, 2048, 4096}; + static const short mem_aper[] = + {0, + MACH32_APERTURE, + MACH32_APERTURE | MACH32_APERTURE_4M, + 0}; + int i; + unsigned short *ptr, cfg1, cfg2; + unsigned int apertloc = 0; + +#ifdef EXPERIMENTAL + if (getenv("EXPERIMENTAL") != NULL) { + mach32_experimental = atoi(getenv("EXPERIMENTAL")); + fprintf(stderr,"mach32: EXPERIMENTAL set to: %04x\n", mach32_experimental); + } else { + fprintf(stderr,"mach32: EXPERIMENTAL defaults to: %04x\n", mach32_experimental); + } +#endif + + mach32_readconfig(); +/* Ensure we are idle. (Probable dead lock if no 8514 installed) */ + mach32_bltwait(); + +/*get main config registers */ + cfg1 = inw(CONF_STAT1); + cfg2 = inw(CONF_STAT2); + +/* get 2 eeprom buffers */ + if (mach32_eeprom == NULL) { + unsigned short sum, crea_eeprom = 1; + + if ((mach32_eeprom = malloc(sizeof(short) * 2 * 128)) == NULL) { + fprintf(stderr,"svgalib: mach32: Fatal error,\n" + "not enough memory for EEPROM image (512 Bytes needed)\n"); + /* svgamode not yet set.. */ + exit(-1); + } + /* Do we have it already in a file ? */ + if ((eeprom_fname != NULL) && !(eeprom_option & EEPROM_UPDATE)) { + FILE *fd; + + fd = fopen(eeprom_fname, "rb"); + if (fd == NULL) { + readerr: + fprintf(stderr,"mach32: Warning, can't access EEPROM file >%s<\nError was %d - %s\n", + eeprom_fname, errno, strerror(errno)); + goto read_eeprom; + } + if (1 != fread(mach32_eeprom, sizeof(short) * 129, 1, fd)) { + i = errno; + fclose(fd); + errno = i; + goto readerr; + } + if (fclose(fd)) + goto readerr; + /*Checksum.. */ + for (i = 0, sum = 0, ptr = mach32_eeprom; i < 128; i++) + sum += *ptr++; + if (sum == *ptr) { + crea_eeprom = 0; /*Mark succesful read... */ + goto skip_read; /* Use the read in file... */ + } + sum = 0; /*Mark unsuccesful read.. */ + fprintf(stderr,"mach32: Warning, EEPROM file >%s< corrupted.\n", eeprom_fname); + } + /* Read in eeprom */ + read_eeprom: + if (!(eeprom_option & (EEPROM_USE_CHKSUM | + EEPROM_USE_MEMCFG | EEPROM_USE_TIMING))) { + /* No need to bother reading the EEPROM */ + goto skip_read; + } + for (i = 0, ptr = mach32_eeprom; i < 128; i++) + *ptr++ = mach32_eeget(i); + if (eeprom_option & EEPROM_USE_CHKSUM) { + for (i = 0, sum = 0, ptr = mach32_eeprom; i < 128; i++) + sum += *ptr++; + sum &= 0xffff; + if (sum) { + /*Hmm.. no ATI checksum... try AST: */ + sum -= (mach32_eeprom[0x7f] << 1) - 1; + } + } else + sum = 0; + if (sum & 0xffff) { + fprintf(stderr,"mach32: Warning, Illegal checksum in Mach32 EEPROM.\n" + "Check configuration of your card and read README.mach32,\n" + "esp. the Mach32 Eeprom Woe chapter.\n" + "Ignoring contents...\n"); + eeprom_option &= ~(EEPROM_USE_MEMCFG | EEPROM_USE_TIMING); + } + skip_read: + + if ((eeprom_fname != NULL) && (crea_eeprom || (eeprom_option & EEPROM_UPDATE))) + /* create file if not there or unsuccesful or requested */ + { + FILE *fd; + + /*Calc valid checksum.. */ + for (i = 0, sum = 0, ptr = mach32_eeprom; i < 128; i++) + sum += *ptr++; + + /* Ensure that this fopen gets a file descriptor greater + * than 2, else problems can occur with stdio functions + * under certain strange conditions: */ + if ((fcntl(0,F_GETFD) == -1) && (open("/dev/null", O_RDONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + if ((fcntl(1,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + if ((fcntl(2,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + fd = fopen(eeprom_fname, "wb"); + if (fd == NULL) { + writerr: + fprintf(stderr,"mach32: Warning, can't create new EEPROM file >%s<\nError was %d - %s\n", + eeprom_fname, errno, strerror(errno)); + crea_eeprom = 0; + goto finish_w_eeprom; + } + if (1 != fwrite(mach32_eeprom, sizeof(short) * 128, 1, fd)) { + fwri_err: + i = errno; + fclose(fd); + errno = i; + goto writerr; + } + if (1 != fwrite(&sum, sizeof(short), 1, fd)) + goto fwri_err; + if (fclose(fd)) + goto writerr; + fprintf(stderr,"mach32: Notice: new EEPROM file >%s< succesful created.\n", + eeprom_fname); + } + finish_w_eeprom: + /* Change eeprom contents if requested: */ + if (!(eeprom_option & EEPROM_USE_MEMCFG)) + mach32_eeprom[6] = 0; + if (!(eeprom_option & EEPROM_USE_TIMING)) { + /* Consider ALL standard modes, but no user defined */ + mach32_eeprom[0x07] = 0x01; /* 640 x 480 */ + mach32_eeprom[0x08] = 0x3f; /* 640 x 480 */ + mach32_eeprom[0x09] = 0x1f; /* 640 x 480 */ + mach32_eeprom[0x0A] = 0x03; /* 640 x 480 */ + mach32_eeprom[0x0B] = 0x00; /* no 1152x900 or 1120x750 */ + } + if (!clocks_set) { + char linebuffer[512]; + + fprintf(stderr,"mach32: Warning, no clocks defined.. please have a look at\n" + "README.Mach32 and README.config for details.\n"); + mach32_scan_clocks(); + fputs("\a\nResulting clocks command for your libvga.config should be:\n\n" + "clocks", stderr); + for (i = 0; i < 16; i++) + fprintf(stderr," %3d", mach32_clocks[i]); + fputs("\n\nPlease edit \"" + SVGALIB_CONFIG_FILE + "\" appropriately.\n" + "Or shall I try to do it for you? You have to have write access to the\n" + "config file to do it! (y/n) ", stderr); + i = getchar(); + if (i != '\n') + while (getchar() != '\n'); + if ((i != 'y') && (i != 'Y')) { + fprintf(stderr,"Ok, then do it yourself.\n"); + exit(0); + } + /* Toast setuid settings coz of security breach of system().. */ + + setreuid(getuid(), getuid()); + setuid(getuid()); + setgid(getgid()); + + strcpy(linebuffer, "rm -f " + SVGALIB_CONFIG_FILE + ".bak; mv " + SVGALIB_CONFIG_FILE + " " + SVGALIB_CONFIG_FILE + ".bak; echo clocks"); + for (i = 0; i < 16; i++) + sprintf(strchr(linebuffer, 0), " %d", mach32_clocks[i]); + strcat(linebuffer, " | cat - " + SVGALIB_CONFIG_FILE + ".bak >" + SVGALIB_CONFIG_FILE); + if (system(linebuffer)) + fprintf(stderr,"Failed (at least partial, maybe there was just no config file yet).\n"); + else + fprintf(stderr,"Ok. (But you should check it anyway)\n"); + exit(0); + } +#ifdef DEBUG + fprintf(stderr,"ATI-EEPROM contents:"); + for (i = 0; i < 128; i++) { + if (i & 7) + putc(' ',stderr); + else + fprintf(stderr,""); + fprintf(stderr,"%02x - %04x", i, mach32_eeprom[i]); + } +#ifdef DEBUG_KEY + fputs("\n(Hit Return)", stderr); + while (getchar() != '\n'); +#else + putc('\n',stderr); +#endif /* DEBUG_KEY */ +#endif /* DEBUG */ + } +/*create a scratch copy. */ + memcpy(mach32_eeprom + 128, mach32_eeprom, (size_t) (128 * sizeof(short))); + +/*Get current memcfg */ + mach32_memcfg = inw(MEM_CFG) & 0xfff3; + +/*If aperture not currently enabled but configured in EEPROM or setup already, + then setup a faked setuplinear, switched off with setuplinear 0 0 */ + + if ((!(mach32_memcfg & 3)) && (((mach32_eeprom[6] + 1) & 3) > 1) && (!mach32_apsiz)) { + /*create setup from eeprom: */ + mach32_apsiz = (mach32_eeprom[6] & 3); + mach32_apadd = (mach32_eeprom[6] >> 4); + eeapert = 1; + } +/*setup up memory aperture if requested: */ + + if (mach32_apsiz) { + unsigned new_memcfg; + + if (!mach32_apadd) + mach32_memcfg = 0; /*disable any aperture */ + else { + if (((cfg1 & BUS_TYPE) == PCI) || ((cfg2 & Z4GBYTE) && !(cfg2 & LOCAL_BUS_CONF2))) { + /* 4GB address range... */ + new_memcfg = (mach32_apadd << 4) & 0xfff0; + i = 4096; + } else { + /* 128MB address range... */ + new_memcfg = (mach32_apadd << 8) & 0xff00; + i = 128; + } + new_memcfg |= mach32_apsiz; + if ((cfg1 & BUS_TYPE) == ISA) + i = 16; + i -= mach32_apadd; + i -= (mach32_apsiz == 1) ? 1 : 4; + if (i < 0) { + fprintf(stderr,"svgalib-mach32: Dangerous warning:\n" + "\tsetuplinear setting exceeds phys. address range of card!\n" + "\tSetting ignored.\n"); + mach32_apsiz = 0; + } else { + /* will be actually set by setappage(0) call in setmode */ + mach32_memcfg = new_memcfg; + } + } + } + if (dac_override > 5) + mach32_dac = (cfg1 >> 9) & 7; + else + mach32_dac = dac_override; + mach32_chiptype = mem_aper[mach32_memcfg & 3]; + if (!force) + mach32_memory = mem_conf[(inw(MISC_OPTIONS) >> 2) & 3]; + else { + mach32_memory = memory; + if (chiptype & MACH32_FORCEDAC) + mach32_dac = chiptype & 0xf; + if (chiptype & MACH32_FORCE_APERTURE) { + mach32_chiptype = (chiptype & (MACH32_APERTURE | MACH32_APERTURE_4M)); + if (mach32_chiptype & MACH32_APERTURE_4M) + mach32_chiptype |= MACH32_APERTURE; + } + } + if (mach32_dac > 5) { + fprintf(stderr,"mach32: Warning, unknown DAC type: %d. Assuming stupid 8bpp DAC rated at 80Mhz!\n", + mach32_dac); + /* Assumption is already done in all tables used... */ + } + if (!(DAC_SAFETY & (1 << mach32_dac))) { + char *cptr; + /* Safety notification */ + cptr = getenv("SVGALIB_MACH32"); + if (cptr == NULL) { + messexit: + fprintf(stderr,"\aWarning!! The mach32 driver of svgalib was never tried with a DAC type\n" + "!=4,3,2,0. Nevertheless, I put every knowledge I got from the DOCs in this\n" + "driver, so it should work. If you think you can stand this risk\n" + "(for example, your monitor will just switch off if he can't stand the\n" + "video signal) then set the environment variable SVGALIB_MACH32 to\n" + "ILLTRYIT or --- of course --- recompile svgalib after changing the\n" + "#define DAC_SAFETY in mach32.c\n\n" + "To reduce possibility of damage to your card you should check that no\n" + "video mode above 80Mhz dotclock is used with dacs !=2 or 5. To check\n" + "recompile with DEBUG defined in mach32.c and look at the output.\n" + "In any case, that is, if it works or not (and what went wrong),\n" + "please tell me about:\n" + "Michael Weller, eowmob@exp-math.uni-essen.de,\n" + "eowmob@pollux.exp-math.uni-essen.de, or mat42b@aixrs1.hrz.uni-essen.de.\n.\n"); + exit(-1); + } + if (strcmp(cptr, "ILLTRYIT")) + goto messexit; + } + if (mach32_dac != 2) + pos_ext_settings &= ~VGA_CLUT8; + + +/* Access aperture */ + if ((mach32_chiptype & MACH32_APERTURE) && (mach32_aperture == NULL)) { + if (((cfg1 & BUS_TYPE) == PCI) || ((cfg2 & Z4GBYTE) && !(cfg2 & LOCAL_BUS_CONF2))) { + /* 4GB address range... */ + apertloc = ((unsigned int) (mach32_memcfg & 0xfff0)) << 16; + } else { + /* 128MB address range... */ + apertloc = ((unsigned int) (mach32_memcfg & 0xff00)) << 12; + } +#ifdef DEBUG + fprintf(stderr,"mach32: Physical aperture starts at %08x.\n", apertloc); +#endif + mach32_aperture = (char *) mmap(NULL, + (mach32_chiptype & MACH32_APERTURE_4M) ? 4194304 : 1048576, + PROT_READ | PROT_WRITE, + MAP_SHARED, + __svgalib_mem_fd, + apertloc); + /* I trust the comment about memory waste in vgamisc.c... */ + if (mach32_aperture == MAP_FAILED) { + i = errno; + fprintf(stderr,"mach32: Mmaping of aperture failed.\nError was %d", i); + errno = i; + perror(" - "); + exit(-1); + } +#ifdef DEBUG + fprintf(stderr,"mach32: Aperture mapped to %p.\n", mach32_aperture); +#endif + } + __svgalib_driverspecs = &__svgalib_mach32_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; +/* __svgalib_linear_mem_base=MACH32_APERTURE; + __svgalib_linear_mem_sizemach32_memory*0x400; */ + +/* Check if imageblit emulation possible: */ + i = 0; + if (mach32_chiptype & MACH32_APERTURE_4M) + i = (4 << 10); + else if (mach32_chiptype & MACH32_APERTURE) + i = (1 << 10); + if (i < mach32_memory) { /*aperture to small */ + emuimage &= ~(EMU_OVER | EMU_POSS); + } + if (!mach32_modes) { + mach32_modes = malloc(__svgalib_max_modes * sizeof(mode_entry *)); + if (!mach32_modes) { + fprintf(stderr,"mach32: No memory for dynamic mode table.\n"); + exit(1); + } + } +/*Calculate the double and triple clocks */ + for (i = 0; i < 32; i++) + mach32_clock_by2[i] = mach32_search_clk(mach32_clocks[i] << 1); + for (i = 0; i < 32; i++) + mach32_clock_by3[i] = mach32_search_clk(mach32_clocks[i] * 3); + +#ifdef DEBUG + fprintf(stderr,"15/16bpp DAC1/4 clock_maps:\n"); + for (i = 0; i < 32; i++) { + if (!(i & 7)) + putc('\n',stderr); + if (mach32_clock_by2[i]) + fprintf(stderr,"%3d->%3d ", mach32_clocks[i], mach32_clocks[mach32_clock_by2[i] - 1]); + else + fprintf(stderr,"%3d-> - ", mach32_clocks[i]); + } + fprintf(stderr,"\n24bpp DAC1/4 clock_maps:\n"); + for (i = 0; i < 32; i++) { + if (!(i & 7)) + putc('\n',stderr); + if (mach32_clock_by3[i]) + fprintf(stderr,"%3d->%3d ", mach32_clocks[i], mach32_clocks[mach32_clock_by3[i] - 1]); + else + fprintf(stderr,"%3d-> - ", mach32_clocks[i]); + } + putc('\n',stderr); +#endif + +/*Populating database: */ + if (verbose) + fprintf(stderr,"Populating mode table:\n"); + + for (i = 0; i < __svgalib_max_modes; i++) + mach32_modes[i] = NULL; + + for (i = 0; i < NUM_MODES; i++) { + if ((predef_modes[i].offset == 0) || + (mach32_eeprom[predef_modes[i].offset] & predef_modes[i].mask)) + mach32_modfill(predef_modes + i, mach32_max_mask(predef_modes[i].h_disp), -1); + } + + if (mach32_eeprom[7] & 2) { + i = (mach32_eeprom[7] >> 8) & 0xff; + if ((mach32_eeprom[i] & 0x140) == 0x140) + mach32_modfill((mode_entry *) (mach32_eeprom + i + 2), + max2msk[3 & (mach32_eeprom[i] >> 9)], -1); + } + if (mach32_eeprom[8] & 0x80) { + i = (mach32_eeprom[8] >> 8) & 0xff; + if ((mach32_eeprom[i] & 0x140) == 0x140) + mach32_modfill((mode_entry *) (mach32_eeprom + i + 2), + max2msk[3 & (mach32_eeprom[i] >> 9)], -1); + } + if (mach32_eeprom[9] & 0x80) { + i = (mach32_eeprom[9] >> 8) & 0xff; + if ((mach32_eeprom[i] & 0x140) == 0x140) + mach32_modfill((mode_entry *) (mach32_eeprom + i + 2), + max2msk[3 & (mach32_eeprom[i] >> 9)], -1); + } + if (mach32_eeprom[10] & 0x80) { + i = (mach32_eeprom[10] >> 8) & 0xff; + if ((mach32_eeprom[i] & 0x140) == 0x140) + mach32_modfill((mode_entry *) (mach32_eeprom + i + 2), + max2msk[3 & (mach32_eeprom[i] >> 9)], -1); + } + if (verbose) + fprintf(stderr,"Squeeze in run-time config:\n"); + mach32_final_modefixup(); + + if (__svgalib_driver_report) { + sprintf(messbuf, " at %uM", apertloc >> 20); + fprintf(stderr,"Using Mach32 driver 2.1 (%s apert%s (%s), %dK mem, DAC %d%s%s).\n", + (mach32_chiptype & MACH32_APERTURE) ? + ((mach32_chiptype & MACH32_APERTURE_4M) ? "4M" : "1M") + : "no", + (mach32_chiptype & MACH32_APERTURE) ? messbuf : "", + mach32_apsiz ? (eeapert ? "EEPROM" : "setup") : "autodetect", + mach32_memory, mach32_dac, (dac_override < 6) ? "(set)" : "", + force ? ", forced" : ""); + } + return 0; +} + +static inline int col2msk(struct vgainfo *iptr) +{ + switch (iptr->colors) { + case 1 << 24: + if (iptr->bytesperpixel == 3) + return 4; +#ifdef SUPP_32BPP + if (iptr->bytesperpixel == 4) + return 8; +#endif + else + return 0; + case 1 << 15: + case 1 << 16: + if (iptr->bytesperpixel == 2) + return 2; + else + return 0; + case 256: + if (iptr->bytesperpixel == 1) + return 1; + else + return 0; + } + return 0; +} + +static inline int col2bypp(struct vgainfo *iptr) +{ + return iptr->bytesperpixel; +} + +static int mach32_log2(struct vgainfo *iptr) +{ + int res = -1, n = iptr->colors; + + while (n) { + res++; + n >>= 1; + } + if ((res == 24) && (iptr->bytesperpixel == 4)) + return 32; + return res; +} + +static void mach32_modfill(const mode_entry * mode, int modemask, int forcein) +{ + register int i; + register struct vgainfo *iptr; + register unsigned wid, hei; + + float horz, vert, n_horz, n_vert, cmpvert; + int clock, n_clock, tmp; + + clock = mach32_clocks[n_clock = 0x1f & (mode->clock_sel >> 2)]; + if (!clock) { + if (verbose) + fprintf(stderr,"%s","Illegal clock #%d of unknown frequency! (rejected)\n"); + return; + } + horz = (1e3 * clock) / (float) (mode->h_total * 8 + 8); + hei = mode->v_total; + if (!(mode->disp_cntl & 0x6)) + hei = ((hei >> 2) & 0xfffe) | (hei & 1); + else + hei = ((hei >> 1) & 0xfffc) | (hei & 3); + hei++; + vert = (horz * 1000) / hei; + + wid = mode->h_disp * 8 + 8; + hei = mode->v_disp; + if (!(mode->disp_cntl & 0x6)) + hei = ((hei >> 2) & 0xfffe) | (hei & 1); + else + hei = ((hei >> 1) & 0xfffc) | (hei & 3); + hei++; + +/*Maskout impossible colorsettings for high clock rates: */ + i = modemask; + modemask &= mach32_mmask[(clock > 80) ? 1 : 0][mach32_dac]; + if (verbose && (i != modemask)) { + fprintf(stderr,"Modemask (32bpp,24bpp,16bpp,8bpp) %x cut down to %x by DAC restrictions.\n", i, modemask); + } +/*Check if needed multiples are available */ + if ((mach32_dac == MACH32_BT481) || (mach32_dac == MACH32_SC11483)) { + if ((modemask & 2) && (!mach32_clock_by2[n_clock])) { + modemask &= ~2; + if (verbose) + fprintf(stderr,"DAC1/4: There is no clock with two times the requested\n" + "\tfreq. of %dMHz => no 15 or 16 bpp.\n", clock); + } + if ((mach32_dac == MACH32_BT481) && (modemask & 4) && (!mach32_clock_by3[n_clock])) { + modemask &= ~4; + if (verbose) + fprintf(stderr,"DAC4: There is no clock with three times the requested\n" + "\tfreq. of %dMHz => no 24bpp.\n", clock); + } + } + i = modemask; +/*Rate down clocks exceeding mem bandwidth */ + if (clock > mach32_maxclk8) + modemask &= ~1; + if (clock > mach32_maxclk16) + modemask &= ~2; + if (clock > mach32_maxclk24) + modemask &= ~4; + if (clock > mach32_maxclk32) + modemask &= ~8; + + if (verbose && (i != modemask)) + fprintf(stderr,"Modemask (32bpp,24bpp,16bpp,8bpp) %x cut down to %x by maxclocks.\n", i, modemask); + + if (forcein >= 0) { + /*Well hack the next loop to run exactly one time for i=forcein.. */ + /*I know it's dirty... */ + i = forcein; + iptr = infotable + i; + goto jumpin; /*Show that to a Pascal coder and he falls down dead.. */ + } + for (i = 0, iptr = infotable; (i < __svgalib_max_modes) && (forcein < 0); i++, iptr++) { + jumpin: + if ((iptr->xdim != wid) || (iptr->ydim != hei) || !(modemask & col2msk(iptr))) + continue; + cmpvert = (mode->disp_cntl & 0x10) ? 2.0 * vert : vert; + if (verbose) { + fprintf(stderr,"%4ux%4ux%2u: ", + wid, hei, mach32_log2(iptr)); + fprintf(stderr,"%3d MHz Clock, %6.3f KHz horz., %6.3f Hz vert.,\n\t%s, VFIFO(16-%d,24-%d)", + clock, horz, cmpvert, + (mode->disp_cntl & 0x10) ? "Interlaced" : "Non-Interlaced", + mode->vfifo16, mode->vfifo24); + } + if (iptr->xbytes * iptr->ydim > mach32_memory * 1024) { + if (verbose) + fprintf(stderr," (not enough memory)\n"); + continue; + } + if (__svgalib_horizsync.max < OFF_ALLOWANCE(horz * 1000)) { + if (verbose) + fprintf(stderr," (rejected, hsync too high)\n"); + continue; + } + if (__svgalib_horizsync.min > ADD_ALLOWANCE(horz * 1000)) { + if (verbose) + fprintf(stderr," (rejected, hsync too low)\n"); + continue; + } + if (__svgalib_vertrefresh.max < OFF_ALLOWANCE(cmpvert)) { + if (verbose) + fprintf(stderr," (rejected, vsync too high)\n"); + continue; + } + if (__svgalib_vertrefresh.min > ADD_ALLOWANCE(cmpvert)) { + if (verbose) + fprintf(stderr," (rejected, vsync too low)\n"); + continue; + } + if ((mach32_modes[i] == NULL) || (forcein >= 0)) { + if (verbose) + fprintf(stderr," (accepted)\n"); + fillin: + mach32_modes[i] = mode; + continue; + } + if ((mach32_modes[i]->disp_cntl ^ mode->disp_cntl) & 0x10) { + if (mode->disp_cntl & 0x10) { + if (verbose) + fprintf(stderr," (rejected, is interlaced)\n"); + continue; + } else { + if (verbose) + fprintf(stderr," (preferred, is non-interlaced)\n"); + goto fillin; + } + } + n_clock = mach32_clocks[0x1f & (mach32_modes[i]->clock_sel >> 2)]; + n_horz = (1e3 * n_clock) / (float) (mach32_modes[i]->h_total * 8 + 8); + tmp = mach32_modes[i]->v_total; + if (!(mach32_modes[i]->disp_cntl & 0x6)) + tmp = ((tmp >> 2) & 0xfffe) | (tmp & 1); + else + tmp = ((tmp >> 1) & 0xfffc) | (tmp & 3); + tmp++; + /* Note: both modes are either interlaced or not, hence we directly compare vsyncs */ + n_vert = (n_horz * 1000) / tmp; + if (n_vert < vert) { + if (verbose) + fprintf(stderr," (higher V_SYNC preferred)\n"); + goto fillin; + } + if (verbose) + fprintf(stderr," (rejected, have a better one already)\n"); + } +} + +static int mach32_modeavailable(int mode) +{ + if (mode >= __svgalib_max_modes) + return 0; + if (mach32_modes[mode] == NULL) + return __svgalib_vga_driverspecs.modeavailable(mode); + return SVGADRV; +} + +static void mach32_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + if (mode >= __svgalib_max_modes) + return; + modeinfo->flags |= HAVE_EXT_SET; + modeinfo->haveblit = 0; + + if (mach32_modes[mode] == NULL) + return; + + if (infotable[mode].bytesperpixel <= 2) + modeinfo->haveblit = acc_supp; + else if (emuimage & EMU_POSS) { /* imageblt can be emulated with memory aperture */ + modeinfo->haveblit = acc_supp & HAVE_IMAGEBLIT; + } + modeinfo->flags |= (HAVE_RWPAGE | EXT_INFO_AVAILABLE); + if (mach32_modes[mode]->disp_cntl & 0x10) + modeinfo->flags |= IS_INTERLACED; + + if (modeinfo->colors == 256) + modeinfo->linewidth_unit = 8; + else if (modeinfo->colors == (1 << 24)) { + modeinfo->linewidth_unit = (PIXALIGN * infotable[mode].bytesperpixel); + if ((infotable[mode].bytesperpixel == 4) || +#ifdef FAKEBGR + ((infotable[mode].bytesperpixel == 3) && (mach32_dac == MACH32_ATI6871))) +#else + ((infotable[mode].bytesperpixel == 3) && (mach32_dac == MACH32_BT481))) +#endif + modeinfo->flags |= RGB_MISORDERED; + } else + modeinfo->linewidth_unit = (PIXALIGN * 2); + + modeinfo->bytesperpixel = infotable[mode].bytesperpixel; + modeinfo->linewidth = infotable[mode].xbytes; + modeinfo->maxlogicalwidth = 0xff * 8 * modeinfo->bytesperpixel; + +/* This is obsolete.. modeinfo->bytesperpixel should always be > 0 here */ + if (modeinfo->bytesperpixel > 0) { + modeinfo->maxpixels = (mach32_memory * 1024) / modeinfo->bytesperpixel; + } else { + modeinfo->maxpixels = (mach32_memory * 1024); + } + + modeinfo->startaddressrange = 0xfffffffc & (mach32_memory * 1024 - 1); + + modeinfo->chiptype = mach32_dac | (mach32_chiptype & (MACH32_APERTURE_4M | MACH32_APERTURE)); + if (mach32_chiptype & MACH32_APERTURE_4M) + modeinfo->aperture_size = (4 << 10); + else if (mach32_chiptype & MACH32_APERTURE) + modeinfo->aperture_size = (1 << 10); + else + modeinfo->aperture_size = 0; + modeinfo->memory = mach32_memory; + if (modeinfo->aperture_size >= mach32_memory) + modeinfo->flags |= CAPABLE_LINEAR; + modeinfo->linear_aperture = (char *) mach32_aperture; + modeinfo->set_aperture_page = mach32_setappage; + modeinfo->extensions = (mach32_eeprom + 128); +} + +static void mach32_blankadj(int adj) +{ + if(mach32_ast) + return; +#ifdef DEBUG + fprintf(stderr,"mach32_blankadj(%d)\n", adj); +#endif + port_out_r(MISC_CTL + 1, (port_in(R_MISC_CTL + 1) & 0xf0) | adj); +} + +static int mach32_setmode(int mode, int previous) +{ + register const mode_entry *mptr; + int type, clock, clock_intended, vfifo; + unsigned short act_ge_conf; + + type = mach32_modeavailable(mode); + if (!type) + return 1; + +#ifdef DEBUG + fprintf(stderr,"mach32_setmode: %d -> %d\n", previous, mode); +#endif + + if (mach32_modeavailable(previous) == SVGADRV) + mach32_bltwait(); /* Ensure noone draws in the screen */ + + mach32_accelstate = R_UNKNOWN; /* Accel registers need to be reset */ + +#ifdef DEBUG + fprintf(stderr,"mach32_setmode: accel set.\n"); +#endif + + if (type != SVGADRV) { + int i; + const unsigned char *ptr; + unsigned int val; + +#ifdef DEBUG + fprintf(stderr,"mach32_setmode: standard mode:%d\n", mode); +#endif + + __svgalib_mach32_driverspecs.emul = NULL; + + /*if imageblit works at all, it'll be this one: */ + __svgalib_mach32_driverspecs.imageblt = mach32_memimageblt; + + /*Set std dac-mode */ + mach32_set_dac(DAC_MODE8, 0, 0); + + /* Ensure we are in VGA-mode: */ + port_outw_r(CLOCK_SEL, (inw(CLOCK_SEL) & ~0x7f) | 0x10); /* slow clock and disable + Mach CRT */ + port_outw_r(DISP_CNTL, mach32_disp_shadow | 0x40); /* Mach32 CRT reset */ + + /* Force all extended ati regs to std. vga mode. This is needed for + correct function when using non standard console text modes. */ + + /* Stop vga sequencer: */ + port_out_r(SEQ_I, 0x00); + port_out_r(SEQ_D, 0x00); + + /* Handle the important reg 0x38: clock-diff by from bits 0+1 svga_clock, no herc emul */ + + port_out_r(ATIPORT, ATISEL(0x38)); + val = port_in(ATIPORT + 1); + if (svga_clock >= 0) + val = (val & 0x3f) | ((svga_clock << 6) & 0xc0); + port_outw_r(ATIPORT, ATISEL(0x38) | (val << 8)); + + /* Handle the important reg 0x39: Select some clock */ + + port_out_r(ATIPORT, ATISEL(0x39)); + val = port_in(ATIPORT + 1); + if (svga_clock >= 0) + val = (val & 0xfc) | ((svga_clock >> 2) & 0x03); + port_outw_r(ATIPORT, ATISEL(0x39) | (val << 8)); + + /* Register 3e, reset several bits and set clock as needed */ + port_out_r(ATIPORT, ATISEL(0x3e)); + val = port_in(ATIPORT + 1) & 0x30; + if (svga_clock >= 0) + val = (val & 0xef) | (svga_clock & 0x10); + port_outw_r(ATIPORT, ATISEL(0x3e) | (val << 8)); + + /* reset several remaining extended bits: */ + for (i = 0, ptr = mach32_ati_ext; i < (sizeof(mach32_ati_ext) / 2); i++, ptr += 2) { + port_out_r(ATIPORT, ATISEL(*ptr)); + val = port_in(ATIPORT + 1) & ~ptr[1]; + port_outw_r(ATIPORT, ATISEL(*ptr) | (val << 8)); + } + + /* sequencer is reenabled by vga setmode */ + return __svgalib_vga_driverspecs.setmode(mode, previous); + /* vga_setmode ensured vga is notblanked... */ + } else { + /* handle the selection of imageblit */ + if ((infotable[mode].colors != (1 << 24)) /* mode is supported by engine */ + &&(!(emuimage & EMU_OVER)) /* and should not be overridden */ + ) + __svgalib_mach32_driverspecs.imageblt = mach32_imageblt; + else + __svgalib_mach32_driverspecs.imageblt = mach32_memimageblt; + } + + __svgalib_mach32_driverspecs.emul = &mach32_vgaemul; + +#ifdef DEBUG + fprintf(stderr,"mach32_setmode: Setting vga in 8bpp graphmode.\n"); +#endif + +/*Ripped out from Xfree.. mach32 Server.. */ + port_outw_r(SEQ_I, 4 | (0x0a << 8)); +/* Enable write access to all memory maps */ + port_outw_r(SEQ_I, 2 | (0x0f << 8)); +/* Set linear addressing mode */ + port_outw_r(ATIPORT, ATISEL(0x36) | (0x05 << 8)); +/* Set the VGA display buffer to 0xa0000 */ + port_outw_r(GRA_I, 6 | (0x05 << 8)); +/*These are mine...someone turned the VGA to erase on write....(Eeeek!) */ + port_outw_r(GRA_I, 1 | (0x00 << 8)); + port_outw_r(GRA_I, 3 | (0x00 << 8)); + port_outw_r(GRA_I, 5 | (0x00 << 8)); + port_outw_r(GRA_I, 7 | (0x00 << 8)); + port_outw_r(GRA_I, 8 | (0xff << 8)); +/*Switch on any videomemory latches we have: */ + port_outw_r(MISC_OPTIONS, (inw(MISC_OPTIONS) & 0x8f7f) | (latchopt & 0x7080)); +#ifdef DEBUG + fprintf(stderr,"mach32_setmode: extended mode:%d\n", mode); +#endif + + mptr = mach32_modes[mode]; + + mach32_disp_shadow = mptr->disp_cntl & 0x7f; + port_outw_r(DISP_CNTL, mach32_disp_shadow | 0x60); /* Mach32 CRT reset */ + port_outw_r(MULTI_FUNC_CNTL, 0x5006); /* Linear memory layout */ +/*set dac: */ + + clock_intended = mptr->clock_sel; + clock = mach32_clocks[0x1f & (clock_intended >> 2)]; + + switch (infotable[mode].colors) { + default: /* 256 */ + clock_intended = mach32_set_dac((clock > 80) ? DAC_MODEMUX : DAC_MODE8, + clock_intended, infotable[mode].xdim); + act_ge_conf = inw(R_EXT_GE_CONF) & 0xf80f; + if (clock > 80) + act_ge_conf |= 0x0110; + else + act_ge_conf |= 0x0010; + /* Force VFIFO in clock_sel to zero: */ + clock_intended &= 0xf0ff; + clock_intended |= (vfifo8 << 8); + break; + case 1 << 15: + clock_intended = mach32_set_dac(DAC_MODE555, + dac14_clock_adjust(clock_intended, mach32_clock_by2), + infotable[mode].xdim); + act_ge_conf = inw(R_EXT_GE_CONF) & 0xf80f; + act_ge_conf |= 0x0020; + /* Force VFIFO in clock_sel to zero: */ + clock_intended &= 0xf0ff; + vfifo = max(mptr->vfifo16, mach32_max_vfifo16(infotable[mode].xdim)); + clock_intended |= (vfifo << 8); + break; + case 1 << 16: + clock_intended = mach32_set_dac(DAC_MODE565, + dac14_clock_adjust(clock_intended, mach32_clock_by2), + infotable[mode].xdim); + act_ge_conf = inw(R_EXT_GE_CONF) & 0xf80f; + act_ge_conf |= 0x0060; + /* Force VFIFO in clock_sel to zero: */ + clock_intended &= 0xf0ff; + vfifo = max(mptr->vfifo16, mach32_max_vfifo16(infotable[mode].xdim)); + clock_intended |= (vfifo << 8); + break; + case 1 << 24: + clock_intended = mach32_set_dac( + (infotable[mode].bytesperpixel == 3) ? DAC_MODERGB : DAC_MODE32B, + dac14_clock_adjust(clock_intended, mach32_clock_by3), + infotable[mode].xdim); + act_ge_conf = inw(R_EXT_GE_CONF) & 0xf80f; + if (infotable[mode].bytesperpixel == 3) { + act_ge_conf |= 0x0030; +#ifdef FAKEBGR + if (mach32_dac == MACH32_ATI6871) + act_ge_conf |= 0x0400; +#endif + vfifo = max(mptr->vfifo24, vfifo24); + } +#ifdef SUPP_32BPP + else { +#ifdef USE_RGBa + act_ge_conf |= 0x0630; +#else + act_ge_conf |= 0x0230; +#endif + vfifo = max(mptr->vfifo24, vfifo32); + } +#endif + /* Force VFIFO in clock_sel to zero: */ + clock_intended &= 0xf0ff; + clock_intended |= (vfifo << 8); + break; + } + port_outw_r(EXT_GE_CONF, act_ge_conf); +/*Set clock and disable VGA... those pinheads from ATI have the clock + settings in all their tables with the VGA enabled....Gee.. */ + clock_intended |= 1; + +#ifdef DEBUG + fprintf(stderr,"GE_CONF:%hx\n", act_ge_conf); + fprintf(stderr,"Setting mode:\th_disp: %x\th_total: %x\th_sync_wid: %x\th_sync_strt: %x\t" + "v_disp: %x\tv_total: %x\tv_sync_wid: %x\tv_sync_strt: %x\tclock_sel: %x\tdisp_ctl: %x\n", + mptr->h_disp, mptr->h_total, mptr->h_sync_wid, mptr->h_sync_strt, mptr->v_disp, mptr->v_total, + mptr->v_sync_wid, mptr->v_sync_strt, clock_intended, mach32_disp_shadow); +#endif + port_out_r(H_DISP, mptr->h_disp); + port_out_r(H_TOTAL, mptr->h_total); + port_out_r(H_SYNC_STRT, mptr->h_sync_strt); + port_out_r(H_SYNC_WID, mptr->h_sync_wid); + port_outw_r(V_TOTAL, mptr->v_total); + port_outw_r(V_DISP, mptr->v_disp); + port_outw_r(V_SYNC_STRT, mptr->v_sync_strt); + port_outw_r(V_SYNC_WID, mptr->v_sync_wid); + +#ifdef DEBUG + port_outw_r(CLOCK_SEL, clock_intended); +#else + port_outw_r(CLOCK_SEL, clock_intended & ~1); /*Screen does not show up yet.. + will be fired up by final vga_screenon + called from setmode (still time to + erase the screen.. ;) */ +#endif + + mach32_setlogicalwidth(infotable[mode].xbytes); + mach32_setdisplaystart(0); + mach32_setappage(0); /* This sets up a requested mem aperture too.. */ + + port_outw_r(DISP_CNTL, mach32_disp_shadow | 0x20); /* Mach32 CRT enable */ + +#if defined(DEBUG_KEY)&&defined(DEBUG) + fputs("\n(Hit Return)", stderr); + while (getchar() != '\n'); +#endif + return 0; +} + +static short * + push(int num) +{ + short *ptr; + + if (mixup_ptr + num >= mixup_alloc) { + if (mach32_modemixup == NULL) + mach32_modemixup = malloc(PREALLOC * sizeof(short)); + else + mach32_modemixup = realloc(mach32_modemixup, (mixup_alloc += PREALLOC) * sizeof(short)); + if (mach32_modemixup == NULL) { + fprintf(stderr,"mach32-config: Fatal error: Out of memory.\n"); + exit(-1); + } + } + ptr = mach32_modemixup + mixup_ptr; + mixup_ptr += num; + return ptr; +} + +static int isnumber(char *str) +{ + if (str == NULL) + return 0; + return strlen(str) == strspn(str, "0123456789"); +} + +static int parsemode(char *str, int linelength, int create) +{ + char tmpstr[6], *ptr; + int i; + unsigned width, height, colors, bytesperpixel; + + if (!str) + return -1; + for (ptr = str; *ptr; ptr++) + *ptr = tolower(*ptr); + if (sscanf(str, "%ux%ux%5s", &width, &height, tmpstr) != 3) + return -1; + if (!strcmp(tmpstr, "256")) { + colors = 256; + bytesperpixel = 1; + } else if (!strcmp(tmpstr, "32k")) { + colors = (1 << 15); + bytesperpixel = 2; + } else if (!strcmp(tmpstr, "64k")) { + colors = (1 << 16); + bytesperpixel = 2; + } else if (!strcmp(tmpstr, "16m")) { + colors = (1 << 24); + bytesperpixel = 3; + } +#ifdef SUPP_32BPP + else if (!strcmp(tmpstr, "16m32")) { + colors = (1 << 24); + bytesperpixel = 4; + } else if (!strcmp(tmpstr, "16m4")) { /* compatibility */ + colors = (1 << 24); + bytesperpixel = 4; + } +#endif + else { + fprintf(stderr,"mach32-config: mode %s unsupported, only 256, 32K, 64K, 16M, 16M32 colors allowed.\n", tmpstr); + return -2; + } + width = (width + 7) & ~7; + if (linelength < width) + linelength = width; + else + linelength = (linelength + 7) & ~7; + + linelength *= bytesperpixel; + + for (i = 0; i < __svgalib_max_modes; i++) { + if ((infotable[i].xdim == width) && (infotable[i].ydim == height) && + (infotable[i].colors == colors) && (infotable[i].bytesperpixel == bytesperpixel)) { + infotable[i].xbytes = linelength; + return i; + } + } + if (!create) + return -2; + if ((i = __svgalib_addmode(width, height, colors, linelength, bytesperpixel)) < 0) { + fprintf(stderr,"mach32-config: no more dynamic modes, %s ignored.\n", tmpstr); + return -2; + } + return i; +} + +static inline unsigned int mach32_skip2(unsigned int vtime) +{ + return ((vtime << 1) & 0xfff8) | (vtime & 3) | ((vtime & 0x80) >> 5); +} + +static char *mach32_conf_commands[] = +{ + "mach32eeprom", "inhibit", "define", "setlinelength", "maxclock16", + "maxclock24", "clocks", "variablelinelength", "strictlinelength", "duplicatelinelength", + "maxclock8", "maxclock32", "verbose", "quiet", "vfifo8", + "latch", "blank", "vfifo16", "vfifo24", "vfifo32", + "setuplinear", "blit", "ramdac", "svgaclock", "vendor", "misc_ctl", + NULL}; + +static char * + mach32_procopt(int command, int mode, char** dummy) +{ + mode_entry *mptr; + char *ptr; + int i, currptr, flag; + + switch (command) { + case 0: + { + int position = 0; /* We are handling the POSITION-th parameter */ + + if (!mode) { + access_denied: + fprintf(stderr,"mach32-config: %s command access denied.", + mach32_conf_commands[command]); + break; + } + for (;;) { + position++; + ptr = strtok(NULL, " "); + if (ptr == NULL) { + if (position <= 1) + fprintf(stderr,"mach32-config: mach32eeprom " + "command expects a parameter.\n"); + return ptr; + } + if (!strcasecmp(ptr, "compatible")) { + eeprom_option |= EEPROM_USE_CHKSUM | + EEPROM_USE_MEMCFG | EEPROM_USE_TIMING; + } else if (!strcasecmp(ptr, "ignore")) { + eeprom_option &= ~(EEPROM_USE_CHKSUM | + EEPROM_USE_MEMCFG | EEPROM_USE_TIMING); + } else if (!strcasecmp(ptr, "useaperture")) { + eeprom_option |= EEPROM_USE_MEMCFG; + } else if (!strcasecmp(ptr, "usetimings")) { + eeprom_option |= EEPROM_USE_TIMING; + } else if (!strcasecmp(ptr, "nofile")) { + eeprom_fname = NULL; + } else if (!strcasecmp(ptr, "updatefile")) { + eeprom_option |= EEPROM_UPDATE; + } else if (!strcasecmp(ptr, "keepfile")) { + eeprom_option &= ~EEPROM_UPDATE; + } else if (!strcasecmp(ptr, "file")) { + ptr = strtok(NULL, " "); + if (ptr == NULL) { + fprintf(stderr,"mach32-config: mach32eeprom file subcommand " + "expects a parameter.\n"); + return ptr; + } + goto fileparam; + } else if (position == 1) { + fileparam: + if (*ptr == '/') { + if (eeprom_fname != NULL) + free(eeprom_fname); + eeprom_fname = strdup(ptr); + if (eeprom_fname == NULL) { + fprintf(stderr,"mach32-config: Fatal error: out of memory.\n"); + exit(-1); + } + } else { + fprintf(stderr,"mach32-config: mach32eeprom: filename has " + "to start with a / !!\n"); + } + } else + return ptr; + } + } + break; + case 1: + for (;;) { + ptr = strtok(NULL, " "); + i = parsemode(ptr, 0, 0); + if (i == -1) + return ptr; + if (i >= 0) + *push(1) = CMD_DEL + i; + } + break; + case 2: /* Define a new mode.. */ + currptr = mixup_ptr; + flag = 0; + for (;;) { + ptr = strtok(NULL, " "); + i = parsemode(ptr, 0, 1); + if (i == -1) + break; + if (i >= 0) { + *push(1) = CMD_ADD + i; + flag = 1; + } + } + if (!flag) { + fprintf(stderr,"mach32-config: Invalid define command, no valid vga-mode given\n"); + ex_inv_mod: + mixup_ptr = currptr; + return ptr; + } + *push(1) = CMD_MOD; + mptr = (mode_entry *) push(SOMOD_SH); + /* Read the mode in, this is almost like Xconfig.. */ + /*The clock is the only thing that may differ: */ + if (ptr == NULL) { + inv_clk: + fprintf(stderr,"mach32-config: Invalid define command, clock is invalid\n"); + goto ex_inv_mod; + } + if (*ptr == ':') { /*No. of clock given */ + if (!isnumber(ptr + 1)) + goto inv_clk; + i = atoi(ptr + 1); + } else { /* search clock in table */ + if (!isnumber(ptr)) + goto inv_clk; + flag = atoi(ptr); + for (i = 0; i < 32; i++) + if (flag == mach32_clocks[i]) + break; + } + if (i > 31) + goto inv_clk; + mptr->clock_sel = (i << 2); +#ifdef DEBUG + fprintf(stderr,"Constructed clock_sel is: %d\n", mptr->clock_sel); +#endif + mptr->disp_cntl = 0x23; /* Assume non interlaced */ + /* The rest is straight forward: */ + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) { + inv_time: + fprintf(stderr,"mach32-config: Invalid define command, timing is invalid\n"); + goto ex_inv_mod; + } + mptr->h_disp = (atoi(ptr) >> 3) - 1; + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) + goto inv_time; + i = atoi(ptr); + mptr->h_sync_strt = (i >> 3) - 1; + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) + goto inv_time; + mptr->h_sync_wid = ((atoi(ptr) - i) >> 3); + if (mptr->h_sync_wid > 0x1f) + mptr->h_sync_wid = 0x1f; + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) + goto inv_time; + mptr->h_total = (atoi(ptr) >> 3) - 1; + + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) + goto inv_time; + mptr->v_disp = mach32_skip2(atoi(ptr) - 1); + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) + goto inv_time; + i = atoi(ptr); + mptr->v_sync_strt = mach32_skip2(i - 1); + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) + goto inv_time; + mptr->v_sync_wid = atoi(ptr) - i; + if (mptr->v_sync_wid > 0x1f) + mptr->v_sync_wid = 0x1f; + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) + goto inv_time; + mptr->v_total = mach32_skip2(atoi(ptr) - 1); + for (;;) { /* Parse for additional goodies */ + ptr = strtok(NULL, " "); + if (!ptr) + break; + if (!strcasecmp(ptr, "interlace")) + mptr->disp_cntl |= 0x10; + else if (!strcasecmp(ptr, "+hsync")) + mptr->h_sync_wid &= ~0x20; + else if (!strcasecmp(ptr, "-hsync")) + mptr->h_sync_wid |= 0x20; + else if (!strcasecmp(ptr, "+vsync")) + mptr->v_sync_wid &= ~0x20; + else if (!strcasecmp(ptr, "-vsync")) + mptr->v_sync_wid |= 0x20; + else + break; + } + /*final fixup */ + if (mptr->h_disp > 0x4f) { /* x>640 */ + mptr->vfifo24 = 0xe; + if (mptr->h_disp > 0x7f) + mptr->vfifo16 = 0xe; + else if (mptr->h_disp > 0x63) + mptr->vfifo16 = 0xd; + else + mptr->vfifo16 = 0x9; + } else { + mptr->vfifo16 = 0; + mptr->vfifo24 = 0; + } + return ptr; + case 3: + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) { + fprintf(stderr,"mach32-config: illegal setlinelength command.\n" + "Usage: setlinelength integer modes...\n"); + return ptr; + } + i = atoi(ptr); + do + ptr = strtok(NULL, " "); + while (parsemode(ptr, i, 0) != -1); + return ptr; + case 4: + ptr = strtok(NULL, " "); + + if (!mode) { + maxclk_deny: + fprintf(stderr,"Don't use the maxclock's commands out of the environment variable.\n"); + return ptr; + } + if (!isnumber(ptr)) { + ilmaxclk: + fprintf(stderr,"mach32-config: illegal maxclock16 or maxclock24 command.\n" + "Usage: maxclock16 integer or maxclock24 integer\n"); + return ptr; + } + mach32_maxclk16 = atoi(ptr); + break; + case 5: + ptr = strtok(NULL, " "); + if (!mode) + goto maxclk_deny; + if (!isnumber(ptr)) + goto ilmaxclk; + mach32_maxclk24 = atoi(ptr); + break; + case 6: + if (!mode) + goto access_denied; + for (i = 0; i < 16; i++) { + ptr = strtok(NULL, " "); + clocks_set = 1; + if (!isnumber(ptr)) { + fprintf(stderr,"mach32-config: illegal clocks command.\n" + "Usage: clocks integer integer ...\n" + "16 clocks have to be specified.\n" + "specify 0 for unsupported clocks\n" + "(using 0's for the mistyped clocks)\n"); + if (mode) { + while (i < 16) + mach32_clocks[i++] = 0; + /*Set halfed clocks: */ + for (i = 0; i < 16; i++) + mach32_clocks[i + 16] = mach32_clocks[i] / 2; + } + return ptr; + } + if (mode) + mach32_clocks[i] = atoi(ptr); + } + /*Set halfed clocks: */ + for (i = 0; i < 16; i++) + mach32_clocks[i + 16] = mach32_clocks[i] / 2; + break; + case 7: + mach32_strictness = 0; + break; + case 8: + mach32_strictness = 1; + break; + case 9: + mach32_strictness = 2; + break; + case 10: + ptr = strtok(NULL, " "); + if (!mode) + goto maxclk_deny; + if (!isnumber(ptr)) + goto ilmaxclk; + mach32_maxclk8 = atoi(ptr); + break; + case 11: + ptr = strtok(NULL, " "); + if (!mode) + goto maxclk_deny; + if (!isnumber(ptr)) + goto ilmaxclk; + mach32_maxclk32 = atoi(ptr); + break; + case 12: + verbose = 1; + break; + case 13: +#ifndef DEBUG + verbose = 0; +#endif + break; + case 14: + ptr = strtok(NULL, " "); + if (!mode) { + tweak_deny: + fprintf(stderr,"The vfifo, latch, blank commands are not allowed out of the environment.\n"); + return ptr; + } + if (!isnumber(ptr)) { + ilvfi: + fprintf(stderr,"Illegal vfifo command\n"); + return ptr; + } + vfifo8 = atoi(ptr) & 0xf; + break; + case 15: + ptr = strtok(NULL, " "); + if (!mode) + goto tweak_deny; + if (!isnumber(ptr)) { + fprintf(stderr,"Illegal latch command\n"); + return ptr; + } + latchopt = atoi(ptr); + break; + case 16: + ptr = strtok(NULL, " "); + if (!mode) + goto tweak_deny; + if (!isnumber(ptr)) { + fprintf(stderr,"Illegal blank command\n"); + return ptr; + } + bladj = atoi(ptr) & 0xf; + break; + case 17: + ptr = strtok(NULL, " "); + if (!mode) + goto tweak_deny; + if (!isnumber(ptr)) + goto ilvfi; + vfifo16 = atoi(ptr) & 0xf; + break; + case 18: + ptr = strtok(NULL, " "); + if (!mode) + goto tweak_deny; + if (!isnumber(ptr)) + goto ilvfi; + vfifo24 = atoi(ptr) & 0xf; + break; + case 19: + ptr = strtok(NULL, " "); + if (!mode) + goto tweak_deny; + if (!isnumber(ptr)) + goto ilvfi; + vfifo32 = atoi(ptr) & 0xf; + break; + case 20: + ptr = strtok(NULL, " "); + if (!isnumber(ptr)) { + ilsetupli: + fprintf(stderr,"Illegal setuplinear command.\n" + "usage: setuplinear address size\n" + "where size = 1 or 4 and both are in MB\n"); + return ptr; + } + i = atoi(ptr); + ptr = strtok(NULL, " "); + if (!strcmp(ptr, "4")) + flag = 1; + else if (!strcmp(ptr, "1")) + flag = 0; + else if (!strcmp(ptr, "0")) { + flag = 0; + i = 0; + goto setuplin; + } else + goto ilsetupli; + if ((i & ~0xfff) || (!i)) { + fprintf(stderr,"setuplinear: address out of range\n"); + return ptr; + } + setuplin: + if (!mode) { + fprintf(stderr,"setuplinear config option strictly disallowed from the environment.\n"); + return ptr; + } + mach32_apsiz = flag + 1; + mach32_apadd = i; + break; + case 21: + for (;;) { + ptr = strtok(NULL, " "); + if (!ptr) + break; + if (!strcasecmp(ptr, "bit")) + acc_supp |= HAVE_BITBLIT; + else if (!strcasecmp(ptr, "nobit")) + acc_supp &= ~HAVE_BITBLIT; + else if (!strcasecmp(ptr, "fill")) + acc_supp |= HAVE_FILLBLIT; + else if (!strcasecmp(ptr, "nofill")) + acc_supp &= ~HAVE_FILLBLIT; + else if (!strcasecmp(ptr, "image")) { + acc_supp |= HAVE_IMAGEBLIT; + emuimage &= ~EMU_OVER; + } else if (!strcasecmp(ptr, "noimage")) { + acc_supp &= ~HAVE_IMAGEBLIT; + } else if (!strcasecmp(ptr, "memimage")) { + acc_supp |= HAVE_IMAGEBLIT; + emuimage |= EMU_OVER | EMU_POSS; + } else if (!strcasecmp(ptr, "nomemimage")) { + emuimage &= ~(EMU_OVER | EMU_POSS); + } else if (!strcasecmp(ptr, "hlinelist")) { + acc_supp |= HAVE_HLINELISTBLIT; + } else if (!strcasecmp(ptr, "nohlinelist")) { + acc_supp &= ~HAVE_HLINELISTBLIT; + } else if (!strcasecmp(ptr, "settrans")) { + accel_supp |= ACCELFLAG_SETTRANSPARENCY; + } else if (!strcasecmp(ptr, "nosettrans")) { + accel_supp &= ~ACCELFLAG_SETTRANSPARENCY; + } else if (!strcasecmp(ptr, "setrop")) { + accel_supp |= ACCELFLAG_SETRASTEROP; + } else if (!strcasecmp(ptr, "nosetrop")) { + accel_supp &= ~ACCELFLAG_SETRASTEROP; + } else if (!strcasecmp(ptr, "fillbox")) { + accel_supp |= ACCELFLAG_FILLBOX; + } else if (!strcasecmp(ptr, "nofillbox")) { + accel_supp &= ~ACCELFLAG_FILLBOX; + } else if (!strcasecmp(ptr, "screencopy")) { + accel_supp |= ACCELFLAG_SCREENCOPY; + } else if (!strcasecmp(ptr, "noscreencopy")) { + accel_supp &= ~ACCELFLAG_SCREENCOPY; + } else if (!strcasecmp(ptr, "drawline")) { + accel_supp |= ACCELFLAG_DRAWLINE; + } else if (!strcasecmp(ptr, "nodrawline")) { + accel_supp &= ~ACCELFLAG_DRAWLINE; + } else if (!strcasecmp(ptr, "putimage")) { + accel_supp |= ACCELFLAG_PUTIMAGE; + emuimage &= ~EMU_OVER; + } else if (!strcasecmp(ptr, "noputimage")) { + accel_supp &= ~ACCELFLAG_PUTIMAGE; + } else if (!strcasecmp(ptr, "drawhlinelist")) { + accel_supp |= ACCELFLAG_DRAWHLINELIST; + } else if (!strcasecmp(ptr, "nodrawhlinelist")) { + accel_supp &= ~ACCELFLAG_DRAWHLINELIST; + } else if (!strcasecmp(ptr, "putbitmap")) { + accel_supp |= ACCELFLAG_PUTBITMAP; + } else if (!strcasecmp(ptr, "noputbitmap")) { + accel_supp &= ~ACCELFLAG_PUTBITMAP; + } else if (!strcasecmp(ptr, "screencopymono")) { + accel_supp |= ACCELFLAG_SCREENCOPYMONO; + } else if (!strcasecmp(ptr, "noscreencopymono")) { + accel_supp &= ~ACCELFLAG_SCREENCOPYMONO; + } else if (!strcasecmp(ptr, "setmode")) { + accel_supp |= ACCELFLAG_SETMODE | ACCELFLAG_SYNC; + } else if (!strcasecmp(ptr, "nosetmode")) { + accel_supp &= ~(ACCELFLAG_SETMODE | ACCELFLAG_SYNC); + } else if (!strcasecmp(ptr, "polyline")) { + accel_supp |= ACCELFLAG_POLYLINE; + } else if (!strcasecmp(ptr, "nopolyline")) { + accel_supp &= ~ACCELFLAG_POLYLINE; + } else if (!strcasecmp(ptr, "polyhline")) { + accel_supp |= ACCELFLAG_POLYHLINE; + } else if (!strcasecmp(ptr, "nopolyhline")) { + accel_supp &= ~ACCELFLAG_POLYHLINE; + } else if (!strcasecmp(ptr, "polyfillmode")) { + accel_supp |= ACCELFLAG_POLYFILLMODE; + } else if (!strcasecmp(ptr, "nopolyfillmode")) { + accel_supp &= ~ACCELFLAG_POLYFILLMODE; + } else + return ptr; + } + break; + case 22: + ptr = strtok(NULL, " "); + if (!mode) + goto access_denied; + if (!ptr) + goto invpar; + else if (!strcasecmp(ptr, "auto")) + dac_override = 127; + else if (!strcasecmp(ptr, "dumb")) + dac_override = MACH32_BT476; + else if ((ptr[0] >= '0') && (ptr[0] <= '5') && (ptr[1] == 0)) + dac_override = *ptr - '0'; + else { + invpar: + fprintf(stderr,"Invalid parameter: \"%s %s\"\n", + mach32_conf_commands[command], ptr); + } + break; + case 23: + ptr = strtok(NULL, " "); + if (!mode) + goto access_denied; + if (!ptr) + goto invpar; + else if (!strcasecmp(ptr, "keep")) + svga_clock = (-1); + else { + if (!isnumber(ptr)) + goto invpar; + i = atoi(ptr); + if ((i < 0) || (i > 0x1f)) + goto invpar; + svga_clock = i; + } + break; + case 24: + ptr = strtok(NULL, " "); + if (!mode) + goto access_denied; + if (!ptr) + goto invpar; + else if (!strcasecmp(ptr, "ati")) { + dac_override = 127; + svga_clock = SVGA_CLOCK; + eeprom_option |= EEPROM_USE_CHKSUM | + EEPROM_USE_MEMCFG | EEPROM_USE_TIMING; + mach32_ast = 0; + } else if (!strcasecmp(ptr, "dell")) { + dac_override = MACH32_BT476; + svga_clock = 0x00; + mach32_ast = 0; + eeprom_option &= ~(EEPROM_USE_CHKSUM | + EEPROM_USE_MEMCFG | EEPROM_USE_TIMING); + } else if (!strcasecmp(ptr, "ast")) { + dac_override = 127; + svga_clock = SVGA_CLOCK; + mach32_ast = 1; + eeprom_option &= ~(EEPROM_USE_CHKSUM | + EEPROM_USE_MEMCFG | EEPROM_USE_TIMING); + } else + goto invpar; + break; + case 25: + ptr = strtok(NULL, " "); + if (!mode) + goto access_denied; + if (!ptr) + goto invpar; + else if (!strcasecmp(ptr, "keep-off")) { + mach32_ast = 1; + } else if (!strcasecmp(ptr, "use")) { + mach32_ast = 0; + } else + goto invpar; + break; + } + return strtok(NULL, " "); +} + +static void mach32_readconfig(void) +{ + static int conf_read = 0; + int i, j, limit, newxbytes; + + if (conf_read) + return; + conf_read = 1; + +/*Hack info table.. see comment at start of file */ + for (i = 0; i < __svgalib_max_modes; i++) { + if (infotable[i].bytesperpixel < 2) + continue; /* Not needed for those.. also excludes STDVGA non MACH32 modes */ + j = infotable[i].xdim % PIXALIGN; + if (j) + infotable[i].xbytes += infotable[i].bytesperpixel * (PIXALIGN - j); + } + __svgalib_read_options(mach32_conf_commands, mach32_procopt); + if (mach32_strictness) { /* Do something about the modes where we redefined xbytes.. */ + limit = GLASTMODE; + for (i = G640x480x256; i < limit; i++) { /* leave the non SVGA modes alone */ + if (!col2bypp(infotable + i)) + continue; /* Don't deal with non mach32-modes */ + if (infotable[i].xbytes != infotable[i].xdim * col2bypp(infotable + i)) { /* mode was redefined */ + newxbytes = infotable[i].xbytes; + /*Let infotable[i] look like a virgin again: */ + infotable[i].xbytes = infotable[i].xdim * col2bypp(infotable + i); + j = __svgalib_addmode(infotable[i].xdim, infotable[i].ydim, infotable[i].colors, + newxbytes, infotable[i].bytesperpixel); + if (j < 0) { + fprintf(stderr,"mach32: Out of dynamic modes for redefinition of modes with\n" + " non-standard linelength. Use inhibit in case of problems.\n"); + goto giveup; + } + if (mach32_strictness == 1) + *push(1) = CMD_MOV + i; /* later move this mode up to the newly defined.. */ + else + *push(1) = CMD_CPY + i; /* Nope, copy instead of move.. */ + *push(1) = j; /* The destination mode. */ +/* #ifdef 1 */ + fprintf(stderr,"Redefining mode %d to %d:%dx%dx%d\n", i, j, + infotable[i].xdim, infotable[i].ydim, infotable[i].colors); +/* #endif */ + } + } + } + giveup: + *push(1) = CMD_MSK; /* End of fixup commands */ + mach32_modemixup = realloc(mach32_modemixup, mixup_ptr * sizeof(short)); + if (mach32_modemixup == NULL) { + fprintf(stderr,"mach32-config: Fatal: queue shrink failed.\n"); + exit(-1); + } +} + +static char * + colstr(struct vgainfo *mode) +{ + static char str[4]; + if (mode->colors <= 256) { + sprintf(str, "%d", mode->colors); + return str; + } + switch (mode->colors) { + case 1 << 15: + return "32K"; + case 1 << 16: + return "64K"; + case 1 << 24: + if (mode->bytesperpixel == 3) + return "16M"; + if (mode->bytesperpixel == 4) + return "16M32"; + } + return "?"; +} + +static void mach32_final_modefixup(void) +{ + int i; + const mode_entry *oldentry; + short *ptr, *ptm; + + + for (ptr = mach32_modemixup;; ptr++) + switch (*ptr & CMD_MSK) { + case CMD_MSK: /* end marker.. */ + return; + case CMD_DEL: /* any mode found here is invalid. */ + mach32_modes[*ptr & ~CMD_MSK] = NULL; + break; + case CMD_MOD: /* skip embedded mode table */ + ptr += SOMOD_SH; + break; + case CMD_MOV: /* move from this position to the one in next command short. */ + i = (*ptr++) & ~CMD_MSK; + mach32_modes[*ptr & ~CMD_MSK] = mach32_modes[i]; + /* erase old entry... */ + mach32_modes[i] = NULL; + break; + case CMD_CPY: /*Same as above, but without erase.. */ + i = (*ptr++) & ~CMD_MSK; + mach32_modes[*ptr & ~CMD_MSK] = mach32_modes[i]; + break; + case CMD_ADD: /* Add next mode in supplied position.. */ + /*First find the mode table.. */ + ptm = ptr + 1; + while ((*ptm & CMD_MSK) != CMD_MOD) + ptm++; + /* one more to skip modemarker.. */ + ptm++; + /*Override any entry we had already for this mode.. (if the mode is acceptable) */ + i = *ptr & ~CMD_MSK; + oldentry = mach32_modes[i]; +#ifdef DEBUG + fprintf(stderr,"Calling mach32_modfill to add new mode.\n"); +#endif + mach32_modfill((mode_entry *) ptm, col2msk(infotable + i), i); + if (mach32_modes[i] == oldentry) { + fprintf(stderr,"mach32: Setting of mode %dx%dx%s failed.\n" + "Mode cannot be realized with your hardware\n" + "(or due to configured restrictions ;-) ), sorry.\n" + "specify verbose in config file or SVGALIB_CONFIG to get\n" + "detailed information\n", + infotable[i].xdim, infotable[i].ydim, colstr(infotable + i)); + } + break; + } +} + +static int mach32_canaccel(void) +{ + if (CM >= __svgalib_max_modes) + return 0; + if (mach32_modes[CM] == NULL) + return 0; + return (infotable[CM].bytesperpixel <= 2); +} + +static int mach32_ext_set(unsigned what, va_list params) +{ + int param2, old_values, retval; + + switch (what) { + case VGA_EXT_AVAILABLE: + param2 = va_arg(params, int); + switch (param2) { + case VGA_AVAIL_SET: + return VGA_EXT_AVAILABLE | VGA_EXT_SET | VGA_EXT_CLEAR | VGA_EXT_RESET; + case VGA_AVAIL_ACCEL: + if (mach32_canaccel()) { + retval = ACCELFLAG_SETFGCOLOR | ACCELFLAG_SETBGCOLOR | + ACCELFLAG_SETTRANSPARENCY | ACCELFLAG_SETRASTEROP | + ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY | + ACCELFLAG_DRAWLINE | ACCELFLAG_PUTIMAGE | + ACCELFLAG_DRAWHLINELIST | ACCELFLAG_PUTBITMAP | + ACCELFLAG_SCREENCOPYMONO | ACCELFLAG_SETMODE | + ACCELFLAG_POLYLINE | ACCELFLAG_POLYHLINE | + ACCELFLAG_POLYFILLMODE | ACCELFLAG_SYNC; + retval = accel_supp & retval; + if (! (retval & ~(ACCELFLAG_SETFGCOLOR | ACCELFLAG_SETBGCOLOR | + ACCELFLAG_SETTRANSPARENCY | ACCELFLAG_SETRASTEROP | + ACCELFLAG_POLYFILLMODE | ACCELFLAG_SYNC | + ACCELFLAG_SETMODE)) ) + return 0; /* No real operations left at all */ + else + return retval; + } else if ((emuimage & EMU_POSS) && (CM < __svgalib_max_modes) && + (mach32_modes[CM] != NULL)) { + return ACCELFLAG_PUTIMAGE; /* putimage can be emulated with memory aperture */ + } else + return 0; + case VGA_AVAIL_FLAGS: + if (((mach32_dacmode & 0x7f) == DAC_MODE8) || + ((mach32_dacmode & 0x7f) == DAC_MODEMUX)) + return pos_ext_settings; + else + return pos_ext_settings & ~VGA_CLUT8; + case VGA_AVAIL_ROP: + if (mach32_canaccel() && (accel_supp & ACCELFLAG_SETRASTEROP)) { + retval = ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY | + ACCELFLAG_PUTIMAGE | ACCELFLAG_DRAWLINE | + ACCELFLAG_SETFGCOLOR | ACCELFLAG_SETBGCOLOR | + ACCELFLAG_PUTBITMAP | ACCELFLAG_SCREENCOPYMONO | + ACCELFLAG_POLYLINE | ACCELFLAG_POLYHLINE | + ACCELFLAG_POLYFILLMODE | ACCELFLAG_DRAWHLINELIST; + return accel_supp & retval; + } else + return 0; + case VGA_AVAIL_TRANSPARENCY: + if (mach32_canaccel() && (accel_supp & ACCELFLAG_SETTRANSPARENCY)) { + retval = ACCELFLAG_PUTBITMAP | ACCELFLAG_SCREENCOPYMONO | ACCELFLAG_POLYFILLMODE; + return accel_supp & retval; + } else + return 0; + case VGA_AVAIL_ROPMODES: + if (mach32_canaccel() && (accel_supp & ACCELFLAG_SETRASTEROP)) + return (1 << ROP_COPY) | (1 << ROP_OR) | (1 << ROP_AND) | + (1 << ROP_XOR) | (1 << ROP_INVERT); + else + return 0; + case VGA_AVAIL_TRANSMODES: + if (mach32_canaccel() && (accel_supp & ACCELFLAG_SETTRANSPARENCY)) + return (1 << ENABLE_BITMAP_TRANSPARENCY); + else + return 0; + } + return 0; + case VGA_EXT_SET: + old_values = ext_settings; + ext_settings |= (va_arg(params, int)) & pos_ext_settings; + params_changed: + if (((old_values ^ ext_settings) & pos_ext_settings) && + (((mach32_dacmode & 0x7f) == DAC_MODE8) || + ((mach32_dacmode & 0x7f) == DAC_MODEMUX))) { + CRITICAL = 1; + vga_lockvc(); + if (ext_settings & VGA_CLUT8) + port_outw_r(EXT_GE_CONF, inw(R_EXT_GE_CONF) | 0x4000); + else + port_outw_r(EXT_GE_CONF, inw(R_EXT_GE_CONF) & 0xbfff); + vga_unlockvc(); + CRITICAL = 0; + } + return old_values; + case VGA_EXT_CLEAR: + old_values = ext_settings; + ext_settings &= ~((va_arg(params, int)) & pos_ext_settings); + goto params_changed; + case VGA_EXT_RESET: + old_values = ext_settings; + ext_settings = (va_arg(params, int)) & pos_ext_settings; + goto params_changed; + default: + return 0; + } +} + +static void mach32_bitblt(int srcaddr, int destaddr, int w, int h, int pitch) +{ + int base, src_x, des_x, adj_w, forw_cpy; + +#ifdef DEBUG + fprintf(stderr,"mach32_bitblt(%xh,%xh,%d,%d,%d)\n", srcaddr, destaddr, w, h, pitch); +#endif + + base = (forw_cpy = (srcaddr > destaddr)) ? destaddr : srcaddr; + + base &= ~3; + srcaddr -= base; + destaddr -= base; + +/*calculate resulting x values */ + src_x = srcaddr % pitch; + des_x = destaddr % pitch; + +/*width in bytes */ + adj_w = (infotable[CM].bytesperpixel == 2) ? w << 1 : w; + +#ifdef DEBUG + fprintf(stderr," base=%xh,src=%xh,des=%xh,src_x=%d,des_x=%d,adj_w=%d\n", base, srcaddr, + destaddr, src_x, des_x, adj_w); +#endif + +/*Currentsetting invalid? */ + if (((src_x + adj_w) > pitch) || ((des_x + adj_w) > pitch)) { + int adj; + /* try to adjust: */ + adj = des_x - src_x; + if (adj < 0) + adj = -adj; + adj = pitch - (adj & ~3); + srcaddr += adj;; + destaddr += adj; + base -= adj; + if ((src_x += adj) >= pitch) + src_x -= pitch; + if ((des_x += adj) >= pitch) + des_x -= pitch; + +#ifdef DEBUG + fprintf(stderr," src=%xh,des=%xh,src_x=%d,des_x=%d,adj=%d\n", srcaddr, destaddr, src_x, des_x, adj); +#endif + /*Still invalid? */ + if (((src_x + adj_w) > pitch) || ((des_x + adj_w) > pitch)) + goto f_ugh; + } +/*reduce addresses to y values: */ + srcaddr /= pitch; + destaddr /= pitch; + +#ifdef DEBUG + fprintf(stderr," >>src=%xh,des=%xh,base=%xh\n", srcaddr, destaddr, base); +#endif + + if ((srcaddr > (1535 - h)) || (destaddr > (1535 - h))) + goto f_ugh; +/*Reduce values to pixels */ + if (infotable[CM].bytesperpixel == 2) { + if ((src_x & 1) || (des_x & 1) || (pitch & 0xfffff00f)) { + f_ugh: + fprintf(stderr,"\asvgalib: mach32: mach32_bitblt can't emulate Cirrus.\n"); + return; + } + src_x >>= 1; + des_x >>= 1; + pitch >>= 4; + } else { + if (pitch & 0xfffff807) + goto f_ugh; + pitch >>= 3; + } + +/*y in range is not checked. */ + +/* Do not disturb us: */ + CRITICAL = 1; + vga_lockvc(); + +/* Ensure std GE config to emulate simple Cirrus */ + if (mach32_accelstate != R_STANDARD) + mach32_setstate(R_STANDARD); + + checkqueue(5); /* Need FIFO room for commands */ + +/* set GE base close to destination: */ + port_outw_r(GE_OFFSET_LO, (unsigned short) (base >> 2)); + port_outw_r(GE_OFFSET_HI, (unsigned short) (base >> 18)); + port_outw_r(GE_PITCH, (unsigned char) pitch); + port_outw_r(DP_CONFIG, 0x6011); /* Replace with VRAM blit source */ + checkqueue(10); /* Need new FIFO room for commands */ +/*start coords: */ +#ifdef DEBUG + fprintf(stderr," ##x=%x,y=%x,xd=%x,yd=%x\n", src_x, srcaddr, des_x, destaddr); +#endif + if (forw_cpy) { + /* cpy from lower to higher addr, x, y */ + /* Use Mach32 extended blit. */ + port_outw_r(SRC_X, src_x); + port_outw_r(SRC_X_START, src_x); + port_outw_r(SRC_Y, srcaddr); + port_outw_r(SRC_X_END, 0x7ff & (src_x + w)); + port_outw_r(SRC_Y_DIR, 1); + port_outw_r(CUR_X, des_x); + port_outw_r(DEST_X_START, des_x); + port_outw_r(CUR_Y, destaddr); + port_outw_r(DEST_X_END, 0x7ff & (des_x + w)); + port_outw_r(DEST_Y_END, 0x7ff & (destaddr + h)); + } else { + /* rev_cpy, adj start coords. */ + /* Use Mach32 extended blit. */ + port_outw_r(SRC_X, 0x7ff & (src_x + w)); + port_outw_r(SRC_X_START, 0x7ff & (src_x + w)); + port_outw_r(SRC_Y, 0x7ff & (srcaddr + h - 1)); + port_outw_r(SRC_X_END, src_x); + port_outw_r(SRC_Y_DIR, 0); + port_outw_r(CUR_X, 0x7ff & (des_x + w)); + port_outw_r(DEST_X_START, 0x7ff & (des_x + w)); + port_outw_r(CUR_Y, 0x7ff & (destaddr + h - 1)); + port_outw_r(DEST_X_END, des_x); + port_outw_r(DEST_Y_END, 0x7ff & (destaddr - 1)); + } +/* Wait then unlock vc */ + mach32_bltwait(); /* resets critical as well */ + port_outw_r(DP_CONFIG, 0x3291); /* reset to standard config.. otherwise dramatical speed down */ +#ifdef DEBUG + fprintf(stderr," **x=%xh,y=%xh\n", (int) inw(CUR_X), (int) inw(CUR_Y)); +#endif + + vga_unlockvc(); +} + +static void mach32_fillblt(int destaddr, int w, int h, int pitch, int c) +{ +#ifdef DEBUG + fprintf(stderr,"mach32_fillblt(%xh,%d,%d,%d,%d)\n", destaddr, w, h, pitch, c); +#endif + +/* Do not disturb us: */ + CRITICAL = 1; + vga_lockvc(); + +/* Ensure std GE config to emulate simple Cirrus */ + if (mach32_accelstate != R_STANDARD) + mach32_setstate(R_STANDARD); + + checkqueue(5); /* Need FIFO room for commands */ +/* set GE base close to destination: */ + port_outw_r(GE_OFFSET_LO, (unsigned short) (destaddr >> 2)); + port_outw_r(GE_OFFSET_HI, (unsigned short) (destaddr >> 18)); + destaddr &= 3; /* remaining x offset */ + + if (infotable[CM].bytesperpixel == 2) { + if ((destaddr & 1) || (pitch & 0xfffff00f)) { + ugh: + fprintf(stderr,"\asvgalib: mach32: mach32_fillblt can't emulate Cirrus.\n"); + CRITICAL = 0; + vga_unlockvc(); + return; + } + destaddr >>= 1; + pitch >>= 4; + } else { + if (pitch & 0xfffff807) + goto ugh; + pitch >>= 3; + } + port_outw_r(GE_PITCH, (unsigned char) pitch); + port_outw_r(FRGD_COLOR, (unsigned short) c); + port_outw_r(FRGD_MIX, 0x27); /* replace with FRGD_COLOR */ + checkqueue(5); /* Need new FIFO room for commands */ +/*start coords: */ + port_outw_r(CUR_X, destaddr); + port_outw_r(CUR_Y, 0); +/*width+height */ + port_outw_r(MAJ_AXIS_PCNT, w - 1); + port_outw_r(MULTI_FUNC_CNTL, 0x7ff & (h - 1)); +/*kick it off */ + port_outw_r(CMD, 0x50B3); /*Rectangle fill with horz lines,pos x+y dir,draw last pel */ + +/* Wait then unlock vc */ + mach32_bltwait(); /* resets critical as well */ + vga_unlockvc(); +} + +static void mach32_hlinelistblt(int ymin, int n, int *xmin, int *xmax, int pitch, int c) +{ +#ifdef DEBUG + fprintf(stderr,"mach32_hlinelistblt(%d,%d,%08xh,%08xh,%d,%d)\n", ymin, n, (unsigned) xmin, (unsigned) xmax, pitch, c); +#endif + +/* Do not disturb us: */ + CRITICAL = 1; + vga_lockvc(); + +/* Ensure std GE config to emulate simple Cirrus */ + if (mach32_accelstate != R_STANDARD) + mach32_setstate(R_STANDARD); + + checkqueue(5); /* Need FIFO room for commands */ + /* This is how I understand the Cirrus-code. Since we have to be compatible: */ + port_outw_r(GE_OFFSET_LO, 0); + port_outw_r(GE_OFFSET_HI, 0); + + if (infotable[CM].bytesperpixel == 2) { + if (pitch & 0xfffff00f) { + ugh: + fprintf(stderr,"\asvgalib: mach32: mach32_hlinelistblt can't emulate Cirrus.\n"); + CRITICAL = 0; + vga_unlockvc(); + return; + } + pitch >>= 4; + } else { + if (pitch & 0xfffff807) + goto ugh; + pitch >>= 3; + } + port_outw_r(GE_PITCH, (unsigned char) pitch); + port_outw_r(FRGD_COLOR, (unsigned short) c); + +/*DP_CONFIG is replace with foreground already... */ +/*And now close your eyes and enjoy.. this is exactly what a Mach32 is built for.. */ + + checkqueue(12); /* Need new FIFO room for commands */ + +/*I think we can trust the hardware handshake from now on. */ +/*Sigh.. no we can't.. queue overruns in 16bpp */ + + while (n-- > 0) { + port_outw_r(CUR_X, 0x7ff & (*xmin)); + port_outw_r(CUR_Y, 0x7ff & (ymin++)); + if (*xmin <= *xmax) + port_outw_r(SCAN_TO_X, (0x7ff & (*xmax + 1))); + xmin++; + xmax++; + + if (!(n & 3)) + checkqueue(12); + } + +/* Wait then unlock vc */ + mach32_bltwait(); /* resets critical as well */ + vga_unlockvc(); +} + +static void mach32_imageblt(void *srcaddr, int destaddr, int w, int h, int pitch) +{ + unsigned count; /* 16bit words needed to transfer */ + +/* Do not disturb us: */ + CRITICAL = 1; + vga_lockvc(); + +#ifdef DEBUG + fprintf(stderr,"mach32_imageblt(%xh,%xh,%d,%d,%d)\n", (int) srcaddr, destaddr, w, h, pitch); +#endif + +/* Ensure std GE config to emulate simple Cirrus */ + if (mach32_accelstate != R_STANDARD) + mach32_setstate(R_STANDARD); + + checkqueue(4); /* Need FIFO room for commands */ +/* set GE base close to destination: */ + port_outw_r(GE_OFFSET_LO, (unsigned short) (destaddr >> 2)); + port_outw_r(GE_OFFSET_HI, (unsigned short) (destaddr >> 18)); + destaddr &= 3; /* remaining x offset */ + + count = w * h; + if (infotable[CM].bytesperpixel == 2) { + if ((destaddr & 1) || (pitch & 0xfffff00f)) { + ugh: + fprintf(stderr,"\asvgalib: mach32: mach32_imageblt can't emulate Cirrus.\n"); + + CRITICAL = 0; + vga_unlockvc(); + return; + } + destaddr >>= 1; + pitch >>= 4; + } else { + if (pitch & 0xfffff807) + goto ugh; + pitch >>= 3; + count = (count + 1) >> 1; /* two pixels transferred in one blow */ + } + + if (!count) { + CRITICAL = 0; + vga_unlockvc(); + return; /* safety bailout */ + } + port_outw_r(GE_PITCH, (unsigned char) pitch); + port_outw_r(FRGD_MIX, 0x47); /* replace with value of PIX_TRANS */ + checkqueue(6); /* Need new FIFO room for commands, one more than actually needed to ensure + correct hostdata fifo operation. */ +/*start coords: */ + port_outw_r(CUR_X, destaddr); + port_outw_r(CUR_Y, 0); +/*width+height */ + port_outw_r(MAJ_AXIS_PCNT, w - 1); + port_outw_r(MULTI_FUNC_CNTL, 0x7ff & (h - 1)); +/*kick it off */ + port_outw_r(CMD, 0x53B1); /*Rectangle fill with horz lines,pos x+y dir,draw last pel */ + /*(set also wait for MSB in the hope that it will ensure the correct + thing if we write out an odd number of bytes) */ + +/* Do the transfer: All handshake is done in hardware by waitstates. Note that the first + word can be transferred w/o problems.. after that automatic handshake by waitstates is enabled + by the ATI on it's own. + The outs is regarding to my assembler docs not only the most simple but also by far the + fastest way to do this. Loop unrolling will gain nothing, so it is not done.. */ + +#ifdef __alpha__ + fprintf(stderr,"mach32_imageblt: not done yet\n"); +#else + asm("cld\n" /* Increasing addresses.. */ + " movw $0xe2e8,%%dx\n" /* PIX_TRANS port */ + " rep\n" /* repeat.. count is in ECX */ + " outsw\n": /* Blast data out in 16bit pieces */ + /* no outputs */ : + /* inputs */ + /* SI= source address */ "S"(srcaddr), + /* CX= words to transfer */ "c"(count): + /* dx destructed: */ "%dx" + ); +#endif + + checkqueue(2); +/*Sigh, it seems that DP_CONFIG gets affected by the 8514/A settings. so reset to standard. */ + port_outw_r(DP_CONFIG, 0x3291); + +/* The bltwait is more intended for a final checkup if everything worked ok and we + didn't lock up the Mach32 fifo */ + +/* Wait then unlock vc */ + mach32_bltwait(); /* resets critical as well */ + vga_unlockvc(); +} + +static void mach32_memimageblt(void *srcaddr, int destaddr, int w, int h, int pitch) +{ + char *source = srcaddr, *dest = (char * /*discard volatile */ ) mach32_aperture + destaddr; + +#ifdef DEBUG + fprintf(stderr,"mach32_memimageblt(%xh,%xh,%d,%d,%d)\n", (int) srcaddr, destaddr, w, h, pitch); + fprintf(stderr,"\tmemtrans: %xh -> %xh\n", (int) source, (int) dest); +#endif + + if (!infotable[CM].bytesperpixel) + return; + + w *= infotable[CM].bytesperpixel; + + if (w == pitch) { + fast_memcpy(dest, source, w * h); + } else { + while (h--) { + fast_memcpy(dest, source, w); + dest += pitch; + source += w; + } + } +#ifdef DEBUG + fprintf(stderr,"mach32_mach32_imageblt ended.\n"); +#endif +} + +static unsigned char mach32ropdefs[] = { 0x7, 0xB, 0xC, 0x5, 0x0 }; + +static void enter_accel(void) +{ + if (!CRITICAL) { + CRITICAL = 1; + vga_lockvc(); + } + if (mach32_accelstate != R_EXTENDED) + mach32_setstate(R_EXTENDED); +} + +static unsigned short *mk_bitrot(void) +{ + unsigned short *bitrot, *ptr; + int i = 0; + + ptr = bitrot = malloc(sizeof(unsigned short) * (1 << 16)); + if (!bitrot) { + fprintf(stderr,"svgalib: mach32: Not enough memory for PUTBITMAP rotation table.\n"); + return NULL; + } + for (i = 0; i < 16; i++) + *ptr++ = ((i & 1) << 15) | ((i & 2) << 13) | ((i & 4) << 11) | ((i & 8) << 9); + for (; i < 256; i++) + *ptr++ = bitrot[i & 15] | (bitrot[i >> 4] >> 4); + for (; i < (1 << 16); i++) + *ptr++ = bitrot[i & 255] | (bitrot[i >> 8] >> 8); + return bitrot; +} + +static int mach32_accel(unsigned operation, va_list params) +{ + static int accel_blockmode = BLITS_SYNC; + static unsigned short *bitrot = NULL; + unsigned short x, y, x2, y2, w, h; + + switch(operation) { + case ACCEL_SETRASTEROP: + enter_accel(); + x = va_arg(params, int); + if (x <= sizeof(mach32ropdefs)) { + mach32_rop = x; + checkqueue(4); /* could check for 2 + 2 but this is probably not worth it */ + mach32_frgd_alu_fn = mach32ropdefs[x]; + port_outw_r(FRGD_MIX, mach32_frgd_alu_fn | 0x20); + port_outw_r(ALU_FG_FN, mach32_frgd_alu_fn); + if (mach32_bkgd_alu_fn != 0x3) { + mach32_bkgd_alu_fn = mach32_frgd_alu_fn; + port_outw_r(BKGD_MIX, mach32_bkgd_alu_fn); + port_outw_r(ALU_BG_FN, mach32_bkgd_alu_fn); + } + } + break; + case ACCEL_SETTRANSPARENCY: + enter_accel(); + x = va_arg(params, int); + if (x == ENABLE_BITMAP_TRANSPARENCY) { + if (mach32_bkgd_alu_fn != 0x3) { + checkqueue(2); + mach32_bkgd_alu_fn = 0x3; + port_outw_r(BKGD_MIX, mach32_bkgd_alu_fn); + port_outw_r(ALU_BG_FN, mach32_bkgd_alu_fn); + } + } else if (x == DISABLE_BITMAP_TRANSPARENCY) { + if (mach32_bkgd_alu_fn == 0x3) { + checkqueue(2); + mach32_bkgd_alu_fn = mach32_frgd_alu_fn; + port_outw_r(BKGD_MIX, mach32_bkgd_alu_fn); + port_outw_r(ALU_BG_FN, mach32_bkgd_alu_fn); + } + } + break; + case ACCEL_SETFGCOLOR: + enter_accel(); + mach32_frgd_col = va_arg(params, int); + checkqueue(1); + port_outw_r(FRGD_COLOR, mach32_frgd_col); + break; + case ACCEL_SETBGCOLOR: + enter_accel(); + mach32_bkgd_col = va_arg(params, int); + checkqueue(1); + port_outw_r(BKGD_COLOR, mach32_bkgd_col); + break; + case ACCEL_SETMODE: + x = va_arg(params, int); + switch(x) { + case BLITS_IN_BACKGROUND: + case BLITS_SYNC: + accel_blockmode = x; + break; + } + break; + case ACCEL_SYNC: + if (CRITICAL) { + mach32_bltwait(); + vga_unlockvc(); + } + return 0; + default: + return -1; + case ACCEL_FILLBOX: + enter_accel(); + checkqueue(5); /* Need new FIFO room for commands */ + /*start coords: */ + port_outw_r(CUR_X, (unsigned short)va_arg(params, int)); + port_outw_r(CUR_Y, (unsigned short)va_arg(params, int)); + /*width+height */ + port_outw_r(MAJ_AXIS_PCNT, (unsigned short)(va_arg(params, int) - 1)); + port_outw_r(MULTI_FUNC_CNTL, (unsigned short)(0x7ff & (va_arg(params, int) - 1))); + /*kick it off */ + port_outw_r(CMD, 0x50B3); /*Rectangle fill with horz lines,pos x+y dir,draw last pel */ + break; + case ACCEL_SCREENCOPY: + enter_accel(); + checkqueue(1); + port_outw_r(DP_CONFIG, 0x6011); /* Replace with VRAM blit source */ + x = va_arg(params, int); + y = va_arg(params, int); + x2 = va_arg(params, int); + y2 = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + checkqueue(10); /* Need new FIFO room for commands */ + if ((y > y2) || ((y == y2) && (x >= x2))) { + /* cpy from lower to higher addr, x, y */ + /* Use Mach32 extended blit. */ + port_outw_r(SRC_X, x & 0x7ff); + port_outw_r(SRC_X_START, x & 0x7ff); + port_outw_r(SRC_Y, y & 0x7ff); + port_outw_r(SRC_X_END, 0x7ff & (x + w)); + port_outw_r(SRC_Y_DIR, 1); + port_outw_r(CUR_X, x2 & 0x7ff); + port_outw_r(DEST_X_START, x2 & 0x7ff); + port_outw_r(CUR_Y, y2 & 0x7ff); + port_outw_r(DEST_X_END, 0x7ff & (x2 + w)); + port_outw_r(DEST_Y_END, 0x7ff & (y2 + h)); + } else { + /* rev_cpy, adj start coords. */ + /* Use Mach32 extended blit. */ + port_outw_r(SRC_X, 0x7ff & (x + w)); + port_outw_r(SRC_X_START, 0x7ff & (x + w)); + port_outw_r(SRC_Y, 0x7ff & (y + h - 1)); + port_outw_r(SRC_X_END, x & 0x7ff); + port_outw_r(SRC_Y_DIR, 0); + port_outw_r(CUR_X, 0x7ff & (x2 + w)); + port_outw_r(DEST_X_START, 0x7ff & (x2 + w)); + port_outw_r(CUR_Y, 0x7ff & (y2 + h - 1)); + port_outw_r(DEST_X_END, x2 & 0x7ff); + port_outw_r(DEST_Y_END, 0x7ff & (y2 - 1)); + } + checkqueue(1); + port_outw_r(DP_CONFIG, 0x3291); + break; + case ACCEL_DRAWHLINELIST: + { + int *xmin, *xmax; + + enter_accel(); + y = va_arg(params, int); + h = va_arg(params, int); + xmin = va_arg(params, int *); + xmax = va_arg(params, int *); + checkqueue(12); + while (h-- > 0) { + x = *xmin++; + x2 = *xmax++; + if (x > x2) { + x = x2; + x2 = xmin[-1]; + } + port_outw_r(CUR_X, x); + port_outw_r(CUR_Y, y++); + port_outw_r(SCAN_TO_X, 0x7ff & (x2 + 1)); + + if (!(h & 3)) + checkqueue(12); + } + + } + break; + case ACCEL_PUTIMAGE: + { + unsigned char *data; + unsigned int count; + + enter_accel(); + if (((emuimage & EMU_OVER) || infotable[CM].colors == (1 << 24)) && + mach32_rop == ROP_COPY) { + /* Ensure the engine is idle */ + mach32_bltwait(); + /* Emulate putimage: */ + x = va_arg(params, int); + y = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + data = va_arg(params, unsigned char *); + mach32_memimageblt(data, + (((int)mach32_ge_off_l) << 2) + + (((int)mach32_ge_off_h) << 18) + + infotable[CM].xbytes * y + + infotable[CM].bytesperpixel * x, + w, h, infotable[CM].bytesperpixel * (int)(mach32_ge_pitch << 3)); + break; + } + checkqueue(12); + port_outw_r(FRGD_MIX, mach32_frgd_alu_fn | 0x40); + port_outw_r(CUR_X, va_arg(params, int)); + port_outw_r(CUR_Y, va_arg(params, int)); + w = va_arg(params, int); + h = va_arg(params, int); + count = w * h; + port_outw_r(MAJ_AXIS_PCNT, w - 1); + port_outw_r(MULTI_FUNC_CNTL, 0x7ff & (h - 1)); + data = va_arg(params, unsigned char *); + port_outw_r(CMD, 0x53B1); +#ifdef __alpha__ + fprintf(stderr,"mach32_ACCEL_PUTIMAGE: not done yet\n"); +#else + if (infotable[CM].bytesperpixel == 2) { + asm("cld\n" + "movw $0xe2e8, %%dx\n" + "rep\n" + "outsw\n": : "S"(data), "c"(count): "%dx" + ); + } else { + if (count > 1) + asm("cld\n" + "movw $0xe2e8, %%dx\n" + "rep\n" + "outsw\n": : "S"(data), "c"(count >> 1): "%dx" + ); + if (count & 1) + port_outw_r(PIX_TRANS, ((unsigned short)data[count - 1])); + } +#endif + checkqueue(2); + port_outw_r(FRGD_MIX, mach32_frgd_alu_fn | 0x20); + port_outw_r(DP_CONFIG, 0x3291); + } + break; + case ACCEL_DRAWLINE: + enter_accel(); + checkqueue(6); + port_outw_r(LINEDRAW_OPT, mach32_polyfill); + port_outw_r(LINEDRAW_INDEX, 0); + port_outw_r(LINEDRAW, va_arg(params, int)); + port_outw_r(LINEDRAW, va_arg(params, int)); + port_outw_r(LINEDRAW, va_arg(params, int)); + port_outw_r(LINEDRAW, va_arg(params, int)); + break; + case ACCEL_PUTBITMAP: + { + unsigned short *data; + unsigned int count; + + if (!bitrot) + bitrot = mk_bitrot(); + if (!bitrot) + break; + + enter_accel(); + checkqueue(1); + port_outw_r(DP_CONFIG, 0x2255); + x = va_arg(params, int); + y = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + checkqueue(10); + /* cpy from lower to higher addr, x, y */ + /* Use Mach32 extended blit for packed bitmap. */ + port_outw_r(EXT_SCISSOR_R, x + w - 1); + w = (w + 31) & ~31; + port_outw_r(CUR_X, x & 0x7ff); + port_outw_r(DEST_X_START, x & 0x7ff); + port_outw_r(CUR_Y, y & 0x7ff); + port_outw_r(DEST_X_END, 0x7ff & (x + w)); + port_outw_r(DEST_Y_END, 0x7ff & (y + h)); + count = (w * h) / 16; + data = va_arg(params, unsigned short *); + checkqueue(12); + while(count--) + port_outw_r(PIX_TRANS, bitrot[*data++]); + checkqueue(2); + port_outw_r(DP_CONFIG, 0x3291); + port_outw_r(EXT_SCISSOR_R, 1535); + } + break; + case ACCEL_SCREENCOPYMONO: + enter_accel(); + checkqueue(1); + if (mach32_polyfill) + port_outw_r(DP_CONFIG, 0x3217); + else + port_outw_r(DP_CONFIG, 0x3275); + x = va_arg(params, int); + y = va_arg(params, int); + x2 = va_arg(params, int); + y2 = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + checkqueue(10); + /* cpy from lower to higher addr, x, y */ + port_outw_r(SRC_X, x & 0x7ff); + port_outw_r(SRC_X_START, x & 0x7ff); + port_outw_r(SRC_Y, y & 0x7ff); + port_outw_r(SRC_X_END, 0x7ff & (x + w)); + port_outw_r(SRC_Y_DIR, 1); + port_outw_r(CUR_X, x2 & 0x7ff); + port_outw_r(DEST_X_START, x2 & 0x7ff); + port_outw_r(CUR_Y, y2 & 0x7ff); + port_outw_r(DEST_X_END, 0x7ff & (x2 + w)); + port_outw_r(DEST_Y_END, 0x7ff & (y2 + h)); + checkqueue(1); + port_outw_r(DP_CONFIG, 0x3291); + break; + case ACCEL_SETOFFSET: + { + unsigned int address; + + address = va_arg(params, unsigned int); + enter_accel(); + checkqueue(2); + mach32_ge_off_l = address >> 2; + port_outw_r(GE_OFFSET_LO, mach32_ge_off_l); + mach32_ge_off_h = 0xff & (address >> 18); + port_outw_r(GE_OFFSET_HI, mach32_ge_off_h); + } + break; + case ACCEL_POLYLINE: + { + unsigned short *data; + int count, flag; + + enter_accel(); + flag = va_arg(params, int); + count = va_arg(params, int) << 1; + data = va_arg(params, unsigned short *); + + checkqueue(5); + if (flag & ACCEL_START) { + port_outw_r(LINEDRAW_OPT, 0x4 | mach32_polyfill); + port_outw_r(LINEDRAW_INDEX, 0); + } + if (flag & ACCEL_END) { + count -= 2; + } + if (count > 0) + asm("cld\n" + "movw $0xfeee, %%dx\n" + "rep\n" + "outsw\n": : "S"(data), "c"(count): "%dx" + ); + if (flag & ACCEL_END) { + checkqueue(3); + port_outw_r(LINEDRAW_OPT, mach32_polyfill); + port_outw_r(LINEDRAW, data[count++]); + port_outw_r(LINEDRAW, data[count]); + } + } + break; + case ACCEL_POLYHLINE: + { + unsigned short *data; + int flag; + static int loc_y; + + enter_accel(); + flag = va_arg(params, int); + y = va_arg(params, int); + h = va_arg(params, int); + data = va_arg(params, unsigned short *); + checkqueue(12); + + if (flag & ACCEL_START) { + loc_y = y; + } + while (h--) { + w = (*data++) - 1; + port_outw_r(CUR_X, *data++); + port_outw_r(CUR_Y, loc_y++); + for(; w > 1; w -= 2) { + port_outw_r(SCAN_TO_X, (*data++) + 1); + port_outw_r(SCAN_TO_X, (*data++)); + } + port_outw_r(SCAN_TO_X, (*data++) + 1); + if (!(h & 3)) + checkqueue(12); + } + } + break; + case ACCEL_POLYFILLMODE: + { + if (va_arg(params, int)) + mach32_polyfill = 2; + else + mach32_polyfill = 0; + } + return 0; + } + if (accel_blockmode == BLITS_SYNC) { + mach32_bltwait(); /* resets critical as well */ + vga_unlockvc(); + } + return 0; +} + +static void mach32_savepalette(unsigned char *red, unsigned char *green, unsigned char *blue) { + int i; + + port_out(0, PEL8514_IR); + for (i = 0; i < 256; i++) { + __svgalib_delay(); + *(red++) = port_in(PEL8514_D); + __svgalib_delay(); + *(green++) = port_in(PEL8514_D); + __svgalib_delay(); + *(blue++) = port_in(PEL8514_D); + } +} + +static void mach32_restorepalette(const unsigned char *red, const unsigned char *green, + const unsigned char *blue) { + int i; + + port_out(0, PEL8514_IW); + for (i = 0; i < 256; i++) { + __svgalib_delay(); + port_out(*(red++), PEL8514_D); + __svgalib_delay(); + port_out(*(green++), PEL8514_D); + __svgalib_delay(); + port_out(*(blue++), PEL8514_D); + } +} + +static int mach32_setpalette(int index, int red, int green, int blue) { + if ((index != palcurind) || (palsetget != 1)) { + port_out(index, PEL8514_IW); + palcurind = index + 1; + palsetget = 1; + } else { + palcurind++; + } + __svgalib_delay(); + port_out(red, PEL8514_D); + __svgalib_delay(); + port_out(green, PEL8514_D); + __svgalib_delay(); + port_out(blue, PEL8514_D); + return 0; +} + +static void mach32_getpalette(int index, int *red, int *green, int *blue) { + if ((index != palcurind) || (palsetget != 0)) { + port_out(index, PEL8514_IR); + palcurind = index + 1; + palsetget = 0; + } else { + palcurind++; + } + __svgalib_delay(); + *red = (int) port_in(PEL8514_D); + __svgalib_delay(); + *green = (int) port_in(PEL8514_D); + __svgalib_delay(); + *blue = (int) port_in(PEL8514_D); +} + +static int mach32_screenon(void) { + /* Force Mach32 to ATI mode (used by setmode) */ + port_outw_r(0x4AEE, inw(0x4AEE) | 1); + return 0; +} + +static void mach32_waitretrace(void) { + unsigned char csync; + + csync = port_in(0xd2ee) >> 3; /* Current sync polarity in bit 2, + 0-pos, 1-neg */ + /*Wait until in displayed area.. */ + while ((port_in(0x2e8) ^ csync) & 2); + /*Wait until V_SYNC */ + csync = ~csync; + while ((port_in(0x2e8) ^ csync) & 2); +} diff --git a/src/drivers/mach32.h b/src/drivers/mach32.h new file mode 100644 index 0000000..6a8b65e --- /dev/null +++ b/src/drivers/mach32.h @@ -0,0 +1,31 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* ATI Mach32 driver (C) 1994 Michael Weller */ +/* Silly defines for convenience application communication with */ +/* Mach32 Driver. */ + +#ifndef _MACH32_H +#define _MACH32_H + +/* Valid params for chiptype in mach32_init(int force, int chiptype, int memory); + Combine with | */ + +#define MACH32_FORCE_APERTURE 0x80 /* Force aperture to type given.. */ +#define MACH32_APERTURE 0x20 /* Aperture is available */ +#define MACH32_APERTURE_4M 0x40 /* Aperture has 4Megs (and is available ) */ + + +#define MACH32_FORCEDAC 0x10 /* Set dac to type specified below: */ +/* Known Dac-Types */ +#define MACH32_ATI68830 0 +#define MACH32_SC11483 1 +#define MACH32_ATI6871 2 +#define MACH32_BT476 3 +#define MACH32_BT481 4 +#define MACH32_ATI68860 5 + +#endif /* _MACH32_H */ diff --git a/src/drivers/mga.h b/src/drivers/mga.h new file mode 100644 index 0000000..721fa1a --- /dev/null +++ b/src/drivers/mga.h @@ -0,0 +1,154 @@ +typedef int Bool; + +#define TRUE 1 +#define FALSE 0 + +#define INREG8(addr) v_readb(addr) +#define INREG16(addr) v_readw(addr) +#define INREG(addr) v_readl(addr) +#define OUTREG8(addr, val) v_writeb(val, addr) +#define OUTREG16(addr, val) v_writew(val, addr) +#define OUTREG(addr, val) v_writel(val, addr) + +#define RAMDAC_OFFSET 0x3c00 +#define MGA1064_INDEX 0 +#define MGA1064_DATA 0x0a + +typedef struct { + unsigned char ExtVga[6]; + unsigned char DacClk[6]; + unsigned char DacRegs[32]; + unsigned int Option; + unsigned int opmode; +} MGARegRec, *MGARegPtr; + +#define MIL_TOTAL_REGS sizeof(MGARegRec) + +#define inMGAdreg(reg) INREG8(RAMDAC_OFFSET + (reg)) + +#define outMGAdreg(reg, val) OUTREG8(RAMDAC_OFFSET + (reg), val) + +#define inMGAdac(reg) \ + (outMGAdreg(MGA1064_INDEX, reg), inMGAdreg(MGA1064_DATA)) + +#define outMGAdac(reg, val) \ + (outMGAdreg(MGA1064_INDEX, reg), outMGAdreg(MGA1064_DATA, val)) + +#define inTi3026dreg(reg) INREG8(RAMDAC_OFFSET + (reg)) + +#define outTi3026dreg(reg, val) OUTREG8(RAMDAC_OFFSET + (reg), val) + +#define inTi3026(reg) \ + (outTi3026dreg(TVP3026_INDEX, reg), inTi3026dreg(TVP3026_DATA)) + +#define outTi3026(reg, mask, val) \ + do { /* note: mask and reg may get evaluated twice */ \ + unsigned char tmp = (mask) ? (inTi3026(reg) & (mask)) : 0; \ + outTi3026dreg(TVP3026_INDEX, reg); \ + outTi3026dreg(TVP3026_DATA, tmp | (val)); \ + } while (0) + +/* TVP3026 direct registers */ + +#define TVP3026_INDEX 0x00 +#define TVP3026_WADR_PAL 0x00 +#define TVP3026_COL_PAL 0x01 +#define TVP3026_PIX_RD_MSK 0x02 +#define TVP3026_RADR_PAL 0x03 +#define TVP3026_CUR_COL_ADDR 0x04 +#define TVP3026_CUR_COL_DATA 0x05 +#define TVP3026_DATA 0x0a +#define TVP3026_CUR_RAM 0x0b +#define TVP3026_CUR_XLOW 0x0c +#define TVP3026_CUR_XHI 0x0d +#define TVP3026_CUR_YLOW 0x0e +#define TVP3026_CUR_YHI 0x0f + +/* TVP3026 indirect registers */ + +#define TVP3026_SILICON_REV 0x01 +#define TVP3026_CURSOR_CTL 0x06 +#define TVP3026_LATCH_CTL 0x0f +#define TVP3026_TRUE_COLOR_CTL 0x18 +#define TVP3026_MUX_CTL 0x19 +#define TVP3026_CLK_SEL 0x1a +#define TVP3026_PAL_PAGE 0x1c +#define TVP3026_GEN_CTL 0x1d +#define TVP3026_MISC_CTL 0x1e +#define TVP3026_GEN_IO_CTL 0x2a +#define TVP3026_GEN_IO_DATA 0x2b +#define TVP3026_PLL_ADDR 0x2c +#define TVP3026_PIX_CLK_DATA 0x2d +#define TVP3026_MEM_CLK_DATA 0x2e +#define TVP3026_LOAD_CLK_DATA 0x2f +#define TVP3026_KEY_RED_LOW 0x32 +#define TVP3026_KEY_RED_HI 0x33 +#define TVP3026_KEY_GREEN_LOW 0x34 +#define TVP3026_KEY_GREEN_HI 0x35 +#define TVP3026_KEY_BLUE_LOW 0x36 +#define TVP3026_KEY_BLUE_HI 0x37 +#define TVP3026_KEY_CTL 0x38 +#define TVP3026_MCLK_CTL 0x39 +#define TVP3026_SENSE_TEST 0x3a +#define TVP3026_TEST_DATA 0x3b +#define TVP3026_CRC_LSB 0x3c +#define TVP3026_CRC_MSB 0x3d +#define TVP3026_CRC_CTL 0x3e +#define TVP3026_ID 0x3f +#define TVP3026_RESET 0xff + +#define MGAREG_ZORG 0x1c0c +#define MGAGDAC_XVREFCTRL 0x18 + +#define MGA1064_MUL_CTL 0x19 +#define MGA1064_MUL_CTL_8bits 0x0 +#define MGA1064_MUL_CTL_15bits 0x01 +#define MGA1064_MUL_CTL_16bits 0x02 +#define MGA1064_MUL_CTL_24bits 0x03 +#define MGA1064_MUL_CTL_32bits 0x04 +#define MGA1064_MUL_CTL_2G8V16bits 0x05 +#define MGA1064_MUL_CTL_G16V16bits 0x06 +#define MGA1064_MUL_CTL_32_24bits 0x07 + +#define MGA1064_SYS_PLL_M 0x2c +#define MGA1064_SYS_PLL_N 0x2d +#define MGA1064_SYS_PLL_P 0x2e +#define MGA1064_SYS_PLL_STAT 0x2f + +#define MGA1064_PIX_PLLA_M 0x44 +#define MGA1064_PIX_PLLA_N 0x45 +#define MGA1064_PIX_PLLA_P 0x46 +#define MGA1064_PIX_PLLB_M 0x48 +#define MGA1064_PIX_PLLB_N 0x49 +#define MGA1064_PIX_PLLB_P 0x4a +#define MGA1064_PIX_PLLC_M 0x4c +#define MGA1064_PIX_PLLC_N 0x4d +#define MGA1064_PIX_PLLC_P 0x4e + +#define MGA1064_VID_PLL_P 0x8D +#define MGA1064_VID_PLL_M 0x8E +#define MGA1064_VID_PLL_N 0x8F + + +#define OPTION_MASK 0xffeffeff +#define PCI_OPTION_REG 0x40 + +//#define OPTION1_MASK 0xFFFFFEFF +#define OPTION2_MASK 0xFFFFFFFF +#define OPTION3_MASK 0xFFFFFFFF +#define OPTION1_MASK 0xFFFC0FF + +#define MGAREG_C2CTL 0x3c10 +#define MGAREG_C2HPARAM 0x3c14 +#define MGAREG_C2HSYNC 0x3c18 +#define MGAREG_C2VPARAM 0x3c1c +#define MGAREG_C2VSYNC 0x3c20 +#define MGAREG_C2STARTADD0 0x3c28 + +#define MGAREG_C2OFFSET 0x3c40 +#define MGAREG_C2DATACTL 0x3c4c + +#define MGA1064_DISP_CTL 0x8a +#define MGA1064_SYNC_CTL 0x8b +#define MGA1064_PWR_CTL 0xa0 + diff --git a/src/drivers/mga_g450pll.c b/src/drivers/mga_g450pll.c new file mode 100644 index 0000000..7478bb1 --- /dev/null +++ b/src/drivers/mga_g450pll.c @@ -0,0 +1,420 @@ +#define MNP_TABLE_SIZE 64 +#define CLKSEL_MGA 0x0c +#define PLLLOCK 0x40 + +static uint32_t G450ApplyPFactor(uint8_t ucP, uint32_t *pulFIn) +{ + if(!(ucP & 0x40)) + { + *pulFIn = *pulFIn / (2L << (ucP & 3)); + } + + return TRUE; +} + + +static uint32_t G450RemovePFactor(uint8_t ucP, uint32_t *pulFIn) +{ + if(!(ucP & 0x40)) + { + *pulFIn = *pulFIn * (2L << (ucP & 3)); + } + + return TRUE; +} + + +static uint32_t G450CalculVCO(uint32_t ulMNP, uint32_t *pulF) +{ + uint8_t ucM, ucN, ucP; + + ucM = (uint8_t)((ulMNP >> 16) & 0xff); + ucN = (uint8_t)((ulMNP >> 8) & 0xff); + ucP = (uint8_t)(ulMNP & 0x03); + + *pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1); + + return TRUE; +} + + +static uint32_t G450CalculDeltaFreq(uint32_t ulF1, uint32_t ulF2, uint32_t *pulDelta) +{ + if(ulF2 < ulF1) + { + *pulDelta = ((ulF1 - ulF2) * 1000) / ulF1; + } + else + { + *pulDelta = ((ulF2 - ulF1) * 1000) / ulF1; + } + + return TRUE; +} + + + + +static uint32_t G450FindNextPLLParam(uint32_t ulFout, uint32_t *pulPLLMNP) +{ + uint8_t ucM, ucN, ucP, ucS; + uint32_t ulVCO, ulVCOMin; + + ucM = (uint8_t)((*pulPLLMNP >> 16) & 0xff); + ucN = (uint8_t)((*pulPLLMNP >> 8) & 0xff); + ucP = (uint8_t)(*pulPLLMNP & 0x43); + + ulVCOMin = 256000; + + if(ulVCOMin >= (255L * 8000)) + { + ulVCOMin = 230000; + } + + if((ucM == 9) && (ucP & 0x40)) + { + *pulPLLMNP = 0xffffffff; + } else if (ucM == 9) + { + if(ucP) + { + ucP--; + } + else + { + ucP = 0x40; + } + ucM = 0; + } + else + { + ucM++; + } + + ulVCO = ulFout; + + G450RemovePFactor(ucP, &ulVCO); + + if(ulVCO < ulVCOMin) + { + *pulPLLMNP = 0xffffffff; + } + + if(*pulPLLMNP != 0xffffffff) + { + ucN = (uint8_t)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2); + + ucS = 5; + /* I guess those limits depend on the other clocks / fifo settings - MZ */ + if(ulVCO < 1300000) ucS = 4; + if(ulVCO < 1100000) ucS = 3; + if(ulVCO < 1050000) ucS = 2; + if(ulVCO < 800000) ucS = 1; + if(ulVCO < 580000) ucS = 0; + + ucP |= (uint8_t)(ucS << 3); + + *pulPLLMNP &= 0xff000000; + *pulPLLMNP |= (uint32_t)ucM << 16; + *pulPLLMNP |= (uint32_t)ucN << 8; + *pulPLLMNP |= (uint32_t)ucP; + } + + return TRUE; +} + + +static uint32_t G450FindFirstPLLParam(uint32_t ulFout, uint32_t *pulPLLMNP) +{ + uint8_t ucP; + uint32_t ulVCO; + uint32_t ulVCOMax; + + /* Default value */ + ulVCOMax = 1300000; + + if(ulFout > (ulVCOMax/2)) + { + ucP = 0x40; + ulVCO = ulFout; + } + else + { + ucP = 3; + ulVCO = ulFout; + G450RemovePFactor(ucP, &ulVCO); + while(ucP && (ulVCO > ulVCOMax)) + { + ucP--; + ulVCO = ulFout; + G450RemovePFactor(ucP, &ulVCO); + } + } + + if(ulVCO > ulVCOMax) + { + *pulPLLMNP = 0xffffffff; + } + else + { + /* Pixel clock: 1 */ + *pulPLLMNP = (1 << 24) + 0xff0000 + ucP; + G450FindNextPLLParam(ulFout, pulPLLMNP); + } + + return TRUE; + +} + + +static uint32_t G450WriteMNP(uint32_t ulMNP) +{ + if ( !SECONDCRTC ) { + outMGAdac(MGA1064_PIX_PLLC_M, (uint8_t)(ulMNP >> 16)); + outMGAdac(MGA1064_PIX_PLLC_N, (uint8_t)(ulMNP >> 8)); + outMGAdac(MGA1064_PIX_PLLC_P, (uint8_t) ulMNP ); + } else { + outMGAdac(MGA1064_VID_PLL_M, (uint8_t)(ulMNP >> 16)); + outMGAdac(MGA1064_VID_PLL_N, (uint8_t)(ulMNP >> 8)); + outMGAdac(MGA1064_VID_PLL_P, (uint8_t) ulMNP); + } + return TRUE; +} + + +static uint32_t G450CompareMNP(uint32_t ulFout, uint32_t ulMNP1, + uint32_t ulMNP2, int *pulResult) +{ + uint32_t ulFreq, ulDelta1, ulDelta2; + + G450CalculVCO(ulMNP1, &ulFreq); + G450ApplyPFactor((uint8_t) ulMNP1, &ulFreq); + G450CalculDeltaFreq(ulFout, ulFreq, &ulDelta1); + + G450CalculVCO(ulMNP2, &ulFreq); + G450ApplyPFactor((uint8_t) ulMNP2, &ulFreq); + G450CalculDeltaFreq(ulFout, ulFreq, &ulDelta2); + + if(ulDelta1 < ulDelta2) + { + *pulResult = -1; + } + else if(ulDelta1 > ulDelta2) + { + *pulResult = 1; + } + else + { + *pulResult = 0; + } + + if((ulDelta1 <= 5) && (ulDelta2 <= 5)) + { + if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000)) + { + *pulResult = -1; + } + else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000)) + { + *pulResult = 1; + } + } + + return TRUE; +} + + +static uint32_t G450IsPllLocked(Bool *lpbLocked) +{ + uint32_t ulFallBackCounter, ulLockCount, ulCount; + uint8_t ucPLLStatus; + + /* Pixel PLL */ + if ( !SECONDCRTC ) + OUTREG8(0x3c00, 0x4f); + else + OUTREG8(0x3c00, 0x8f); + + ulFallBackCounter = 0; + + do + { + ucPLLStatus = INREG8(0x3c0a); + ulFallBackCounter++; + } while(!(ucPLLStatus & PLLLOCK) && (ulFallBackCounter < 1000)); + + ulLockCount = 0; + if(ulFallBackCounter < 1000) + { + for(ulCount = 0; ulCount < 100; ulCount++) + { + ucPLLStatus = INREG8(0x3c0a); + if(ucPLLStatus & PLLLOCK) + { + ulLockCount++; + } + } + } + + *lpbLocked = ulLockCount >= 90; + + return TRUE; +} + + +static double G450SetPLLFreq(int f_out) +{ + Bool bFoundValidPLL; + Bool bLocked; + uint8_t ucMisc; + uint32_t ulMaxIndex; + uint32_t ulMNP; + uint32_t ulMNPTable[MNP_TABLE_SIZE]; + uint32_t ulIndex; + uint32_t ulTryMNP; + int CompareResult; + + G450FindFirstPLLParam(f_out, &ulMNP); + ulMNPTable[0] = ulMNP; + G450FindNextPLLParam(f_out, &ulMNP); + ulMaxIndex = 1; + while(ulMNP != 0xffffffff) + { + int ulIndex; + Bool bSkipValue; + + bSkipValue = FALSE; + if(ulMaxIndex == MNP_TABLE_SIZE) + { + G450CompareMNP(f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1], + &CompareResult); + + if(CompareResult > 0) + { + bSkipValue = TRUE; + } + else + { + ulMaxIndex--; + } + } + + if(!bSkipValue) + { + for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--) + { + G450CompareMNP(f_out, ulMNP, ulMNPTable[ulIndex - 1], + &CompareResult); + + if(CompareResult < 0) + { + ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1]; + } + else + { + break; + } + } + ulMNPTable[ulIndex] = ulMNP; + ulMaxIndex++; + } + + G450FindNextPLLParam(f_out, &ulMNP); + } + + bFoundValidPLL = FALSE; + ulMNP = 0; + + /* For pixel pll */ + ucMisc = INREG8(0x1FCC); + OUTREG8(0x1fc2, (uint8_t)(ucMisc | CLKSEL_MGA)); + + for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++) + { + ulTryMNP = ulMNPTable[ulIndex]; + +/* for(ucS = 0; !bFoundValidPLL && (ucS < 0x40); ucS += 8)*/ + { +/* ulTryMNP &= 0xffffffc7;*/ +/* ulTryMNP |= (uint32_t)ucS;*/ + + bLocked = TRUE; + if((ulMNPTable[ulIndex] & 0xff00) < 0x300 || + (ulMNPTable[ulIndex] & 0xff00) > 0x7a00) + { + bLocked = FALSE; + } + + if(bLocked) + { + G450WriteMNP(ulTryMNP - 0x300); + G450IsPllLocked(&bLocked); + } + + if(bLocked) + { + G450WriteMNP(ulTryMNP + 0x300); + G450IsPllLocked(&bLocked); + } + + if(bLocked) + { + G450WriteMNP(ulTryMNP - 0x200); + G450IsPllLocked(&bLocked); + } + + if(bLocked) + { + G450WriteMNP(ulTryMNP + 0x200); + G450IsPllLocked(&bLocked); + } + + if(bLocked) + { + G450WriteMNP(ulTryMNP - 0x100); + G450IsPllLocked(&bLocked); + } + + if(bLocked) + { + G450WriteMNP(ulTryMNP + 0x100); + G450IsPllLocked(&bLocked); + } + + if(bLocked) + { + G450WriteMNP(ulTryMNP); + G450IsPllLocked(&bLocked); + } + else if(!ulMNP) + { + G450WriteMNP(ulTryMNP); + G450IsPllLocked(&bLocked); + if(bLocked) + { + ulMNP = ulMNPTable[ulIndex]; + } + bLocked = FALSE; + } + + if(bLocked) + { + bFoundValidPLL = TRUE; + } + } + } + + if(!bFoundValidPLL) + { + if(ulMNP) + { + G450WriteMNP(ulMNP); + } + else + { + G450WriteMNP(ulMNPTable[0]); + } + } + + return TRUE; +} diff --git a/src/drivers/millennium.c b/src/drivers/millennium.c new file mode 100644 index 0000000..a99ccf3 --- /dev/null +++ b/src/drivers/millennium.c @@ -0,0 +1,938 @@ +/* +Matrox Millennium / Millenium II driver +*/ +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "vgammvgaio.h" +#include "mga.h" + +static int mil_init(int, int, int); +static void mil_unlock(void); +static void mil_lock(void); + +static int mil_memory=0, mil_pciposition, mil_chiptype; +static unsigned int mil_linear_base, mil_mmio_base; +static int interleave, rounding; + +static CardSpecs *cardspecs; + +static void mil_outext(int ind, int data) { + OUTREG8(0x1fde, ind); + OUTREG8(0x1fdf, data); +} + +static int mil_inext(int ind) { + OUTREG8(0x1fde, ind); + return INREG8(0x1fdf); +} + +static void mil_setpage(int page) +{ + mil_outext(4, page); +} + +/* Fill in chipset specific mode information */ +static void mil_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + if(modeinfo->bytesperpixel==3)return; + + if(modeinfo->linewidth & rounding) { + modeinfo->linewidth = (modeinfo->linewidth | rounding) + 1; + } + + modeinfo->maxpixels = mil_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = mil_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(mil_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +const static unsigned char MGADACregs[] = { + 0x0F, 0x18, 0x19, 0x1A, 0x1C, 0x1D, 0x1E, 0x2A, 0x2B, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, + 0x06 +}; + + +#define DACREGSIZE sizeof(MGADACregs) +/* + * initial values of ti3026 registers + */ +const static unsigned char MGADACbpp8[DACREGSIZE] = { + 0x06, 0x80, 0x4b, 0x25, 0x00, 0x00, 0x04, 0x00, 0x1E, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0, 0x00, + 0x00 +}; +const static unsigned char MGADACbpp16[DACREGSIZE] = { + 0x07, 0x45, 0x53, 0x15, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, + 0x00 +}; +const static unsigned char MGADACbpp24[DACREGSIZE] = { + 0x06, 0x56, 0x5b, 0x25, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, + 0x00 +}; +const static unsigned char MGADACbpp32[DACREGSIZE] = { + 0x07, 0x46, 0x5b, 0x05, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, + 0x00 +}; + +#define TI_MIN_VCO_FREQ 110000 +#define TI_MAX_VCO_FREQ 220000 +#define TI_MAX_MCLK_FREQ 100000 +#define TI_REF_FREQ 14318.18 + +static double +MGATi3026CalcClock ( + int f_out, int f_max, + int *m, int *n, int *p +){ + int best_m = 0, best_n = 0; + double f_pll, f_vco; + double m_err, inc_m, calc_m; + + /* Make sure that f_min <= f_out <= f_max */ + if ( f_out < ( TI_MIN_VCO_FREQ / 8 )) + f_out = TI_MIN_VCO_FREQ / 8; + if ( f_out > f_max ) + f_out = f_max; + + /* + * f_pll = f_vco / 2 ^ p + * Choose p so that TI_MIN_VCO_FREQ <= f_vco <= TI_MAX_VCO_FREQ + * Note that since TI_MAX_VCO_FREQ = 2 * TI_MIN_VCO_FREQ + * we don't have to bother checking for this maximum limit. + */ + f_vco = ( double ) f_out; + for ( *p = 0; *p < 3 && f_vco < TI_MIN_VCO_FREQ; ( *p )++ ) + f_vco *= 2.0; + + /* + * We avoid doing multiplications by ( 65 - n ), + * and add an increment instead - this keeps any error small. + */ + inc_m = f_vco / ( TI_REF_FREQ * 8.0 ); + + /* Initial value of calc_m for the loop */ + calc_m = inc_m + inc_m + inc_m; + + /* Initial amount of error for an integer - impossibly large */ + m_err = 2.0; + + /* Search for the closest INTEGER value of ( 65 - m ) */ + for ( *n = 3; *n <= 25; ( *n )++, calc_m += inc_m ) { + + /* Ignore values of ( 65 - m ) which we can't use */ + if ( calc_m < 3.0 || calc_m > 64.0 ) + continue; + + /* + * Pick the closest INTEGER (has smallest fractional part). + * The optimizer should clean this up for us. + */ + if (( calc_m - ( int ) calc_m ) < m_err ) { + m_err = calc_m - ( int ) calc_m; + best_m = ( int ) calc_m; + best_n = *n; + } + } + + /* 65 - ( 65 - x ) = x */ + *m = 65 - best_m; + *n = 65 - best_n; + + /* Now all the calculations can be completed */ + f_vco = 8.0 * TI_REF_FREQ * best_m / best_n; + f_pll = f_vco / ( 1 << *p ); + + return f_pll; +} + +static void +MGATi3026SetPCLK( MGARegPtr pReg, int f_out, int bpp ) +{ + /* Pixel clock values */ + int m, n, p; + + /* Loop clock values */ + int lm, ln, lp, lq; + double z; + + /* The actual frequency output by the clock */ + double f_pll; + + int f_max = TI_MAX_VCO_FREQ; + + /* Do the calculations for m, n, and p */ + f_pll = MGATi3026CalcClock( f_out, f_max, & m, & n, & p ); + + /* Values for the pixel clock PLL registers */ + pReg->DacClk[ 0 ] = ( n & 0x3f ) | 0xc0; + pReg->DacClk[ 1 ] = ( m & 0x3f ); + pReg->DacClk[ 2 ] = ( p & 0x03 ) | 0xb0; + + /* + * Now that the pixel clock PLL is setup, + * the loop clock PLL must be setup. + */ + + /* + * First we figure out lm, ln, and z. + * Things are different in packed pixel mode (24bpp) though. + */ + if ( bpp == 24 ) { + + /* ln:lm = ln:3 */ + lm = 65 - 3; + +#if 0 + /* Check for interleaved mode */ + if ( bpp == 2 ) + /* ln:lm = 4:3 */ + ln = 65 - 4; + else +#endif + /* ln:lm = 8:3 */ + ln = 65 - 8; + + /* Note: this is actually 100 * z for more precision */ + z = ( 11000 * ( 65 - ln )) / (( f_pll / 1000 ) * ( 65 - lm )); + } + else { + /* ln:lm = ln:4 */ + lm = 65 - 4; + + /* Note: bpp = bytes per pixel */ + ln = 65 - 4 * ( 64 / 8 ) / bpp; + + /* Note: this is actually 100 * z for more precision */ + z = (( 11000 / 4 ) * ( 65 - ln )) / ( f_pll / 1000 ); + } + + /* + * Now we choose dividers lp and lq so that the VCO frequency + * is within the operating range of 110 MHz to 220 MHz. + */ + + /* Assume no lq divider */ + lq = 0; + + /* Note: z is actually 100 * z for more precision */ + if ( z <= 200.0 ) + lp = 0; + else if ( z <= 400.0 ) + lp = 1; + else if ( z <= 800.0 ) + lp = 2; + else if ( z <= 1600.0 ) + lp = 3; + else { + lp = 3; + lq = ( int )( z / 1600.0 ); + } + + /* Values for the loop clock PLL registers */ + if ( bpp == 24 ) { + /* Packed pixel mode values */ + pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0x80; + pReg->DacClk[ 4 ] = ( lm & 0x3f ) | 0x80; + pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf8; + } else { + /* Non-packed pixel mode values */ + pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0xc0; + pReg->DacClk[ 4 ] = ( lm & 0x3f ); + pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf0; + } + pReg->DacRegs[ 18 ] = lq | 0x38; + +} + +/* + * MGA3026Init -- for mga2064 with ti3026 + * + * The 'mode' parameter describes the video mode. The 'mode' structure + * as well as the 'vga256InfoRec' structure can be dereferenced for + * information that is needed to initialize the mode. The 'new' macro + * (see definition above) is used to simply fill in the structure. + */ +static int BppShifts[4]={0,1,0,2}; + +static int +MGA3026Init(unsigned char *regs, ModeTiming * modetiming, ModeInfo * modeinfo) +{ + int hd, hs, he, ht, vd, vs, ve, vt, wd; + int i, BppShift, index_1d = 0; + const unsigned char* initDAC; + MGARegPtr pReg; + + pReg = (MGARegPtr)(regs+60); + + BppShift = BppShifts[(modeinfo->bitsPerPixel >> 3) - 1]; + + pReg->opmode=0; + + switch(modeinfo->bitsPerPixel) + { + case 16: + initDAC = MGADACbpp16; +#if __BYTE_ORDER == __BIG_ENDIAN + pReg->opmode &= ~0x300; /* the aperture is little endian */ + pReg->opmode |= 0x100; +#endif + break; + case 24: + initDAC = MGADACbpp24; + break; + case 32: + initDAC = MGADACbpp32; +#if __BYTE_ORDER == __BIG_ENDIAN + pReg->opmode &= ~0x300; /* the aperture is little endian */ + pReg->opmode |= 0x200; +#endif + break; + case 8: + default: + initDAC = MGADACbpp8; + break; + } + + /* Allocate the DacRegs space if not done already */ + for (i = 0; i < DACREGSIZE; i++) { + pReg->DacRegs[i] = initDAC[i]; + if (MGADACregs[i] == 0x1D) + index_1d = i; + } + + if ( (modeinfo->bitsPerPixel == 16) && (modeinfo->greenWeight == 5) ) { + pReg->DacRegs[1] &= ~0x01; + } + + if ( modeinfo->bitsPerPixel == 24 ) { + int silicon_rev; + /* we need to set DacRegs[0] differently based on the silicon + * revision of the 3026 RAMDAC, as per page 2-14 of tvp3026.pdf. + * If we have rev A silicon, we want 0x07; rev B silicon wants + * 0x06. + */ + silicon_rev = inTi3026(TVP3026_SILICON_REV); + + if(silicon_rev <= 0x20) { + /* rev A */ + pReg->DacRegs[0] = 0x07; + } else { + /* rev B */ + pReg->DacRegs[0] = 0x06; + } + } + + if(interleave) pReg->DacRegs[2]+=1; + + /* + * Here all of the MGA registers get filled in. + */ + hd = (modetiming->CrtcHDisplay >> 3) - 1; + hs = (modetiming->CrtcHSyncStart>> 3) - 1; + he = (modetiming->CrtcHSyncEnd >> 3) - 1; + ht = (modetiming->CrtcHTotal >> 3) - 1; + vd = modetiming->CrtcVDisplay - 1; + vs = modetiming->CrtcVSyncStart - 1; + ve = modetiming->CrtcVSyncEnd - 1; + vt = modetiming->CrtcVTotal - 2; + + /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange + * vertical stripes + */ + if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04) + ht++; + + if (modeinfo->bitsPerPixel == 24) + wd = (modeinfo->width * 3) >> (4 - BppShift); + else + wd = modeinfo->width >> (4 - BppShift); + + if(wd&7) { + wd=(wd|7)+1; + } + + pReg->ExtVga[0] = 0; + pReg->ExtVga[5] = 0; + + if (modetiming->flags & INTERLACED) + { + pReg->ExtVga[0] = 0x80; + pReg->ExtVga[5] = (hs + he - ht) >> 1; + wd <<= 1; + vt &= 0xFFFE; + + /* enable interlaced cursor */ + pReg->DacRegs[20] |= 0x20; + } + + pReg->ExtVga[0] |= (wd & 0x300) >> 4; + pReg->ExtVga[1] = (((ht - 4) & 0x100) >> 8) | + ((hd & 0x100) >> 7) | + ((hs & 0x100) >> 6) | + (ht & 0x40); + pReg->ExtVga[2] = ((vt & 0xc00) >> 10) | + ((vd & 0x400) >> 8) | + ((vd & 0xc00) >> 7) | + ((vs & 0xc00) >> 5); + if (modeinfo->bitsPerPixel == 24) + pReg->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80; + else + pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80; + + /* Set viddelay (CRTCEXT3 Bits 3-4). */ + pReg->ExtVga[3] |= (mil_memory == 8192 ? 0x10 + : mil_memory == 2048 ? 0x08 : 0x00); + + pReg->ExtVga[4] = 0; + + regs[0] = ht - 4; + regs[1] = hd; + regs[2] = hd; + regs[3] = (ht & 0x1F) | 0x80; + regs[4] = hs; + regs[5] = ((ht & 0x20) << 2) | (he & 0x1F); + regs[6] = vt & 0xFF; + regs[7] = ((vt & 0x100) >> 8 ) | + ((vd & 0x100) >> 7 ) | + ((vs & 0x100) >> 6 ) | + ((vd & 0x100) >> 5 ) | + 0x10 | + ((vt & 0x200) >> 4 ) | + ((vd & 0x200) >> 3 ) | + ((vs & 0x200) >> 2 ); + regs[9] = ((vd & 0x200) >> 4) | 0x40; + regs[16] = vs & 0xFF; + regs[17] = (ve & 0x0F) | 0x20; + regs[18] = vd & 0xFF; + regs[19] = wd & 0xFF; + regs[21] = vd & 0xFF; + regs[22] = (vt + 1) & 0xFF; + + if (modetiming->flags & DOUBLESCAN) + regs[9] |= 0x80; + + /* Per DDK vid.c line 75, sync polarity should be controlled + * via the TVP3026 RAMDAC register 1D and so MISC Output Register + * should always have bits 6 and 7 set. */ + + regs[59] |= 0xC0; + if ((modetiming->flags & (PHSYNC | NHSYNC)) && + (modetiming->flags & (PVSYNC | NVSYNC))) + { + if (modetiming->flags & PHSYNC) + pReg->DacRegs[index_1d] |= 0x01; + if (modetiming->flags & PVSYNC) + pReg->DacRegs[index_1d] |= 0x02; + } + else + { + int VDisplay = modetiming->CrtcVDisplay; + if (modetiming->flags & DOUBLESCAN) + VDisplay *= 2; + if (VDisplay < 400) + pReg->DacRegs[index_1d] |= 0x01; /* +hsync -vsync */ + else if (VDisplay < 480) + pReg->DacRegs[index_1d] |= 0x02; /* -hsync +vsync */ + else if (VDisplay < 768) + pReg->DacRegs[index_1d] |= 0x00; /* -hsync -vsync */ + else + pReg->DacRegs[index_1d] |= 0x03; /* +hsync +vsync */ + } + + pReg->Option = 0x402C0100; /* fine for 2064 and 2164 */ + + if(interleave) { + pReg->Option |= 0x1000; + } else { + pReg->Option &= ~0x1000; + } + /* must always have the pci retries on but rely on + polling to keep them from occuring */ + pReg->Option &= ~0x20000000; + + regs[59] |= 0x0C; + /* XXX Need to check the first argument */ + MGATi3026SetPCLK( pReg, modetiming->pixelClock, 1 << BppShift ); + + /* this one writes registers rather than writing to the + mgaReg->ModeReg and letting Restore write to the hardware + but that's no big deal since we will Restore right after + this function */ + +#if 0 + MGATi3026SetMCLK(pScrn, MGAdac->MemoryClock); +#endif + + /* This disables the VGA memory aperture */ + regs[59] |= 0x02; + return 1; +} + +/* + * MGA3026Restore -- for mga2064 with ti3026 + * + * This function restores a video mode. It basically writes out all of + * the registers that have previously been saved in the vgaMGARec data + * structure. + */ +static void +MGA3026Restore(MGARegPtr mgaReg) +{ + int i; + + /* + * Code is needed to get things back to bank zero. + */ + for (i = 0; i < 6; i++) + mil_outext(i, mgaReg->ExtVga[i]); + + i = __svgalib_pci_read_config_dword(mil_pciposition, PCI_OPTION_REG); + i &= ~OPTION_MASK; + i |= mgaReg->Option&OPTION_MASK; + __svgalib_pci_write_config_dword(mil_pciposition, PCI_OPTION_REG, i); + + /* select pixel clock PLL as clock source */ + outTi3026(TVP3026_CLK_SEL, 0, mgaReg->DacRegs[3]); + + /* set loop and pixel clock PLL PLLEN bits to 0 */ + outTi3026(TVP3026_PLL_ADDR, 0, 0x2A); + outTi3026(TVP3026_LOAD_CLK_DATA, 0, 0); + outTi3026(TVP3026_PIX_CLK_DATA, 0, 0); + + outTi3026(TVP3026_PLL_ADDR, 0, 0x00); + for (i = 0; i < 3; i++) + outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i]); + +#if 0 + if (vgaReg->MiscOutReg & 0x08) { + /* poll until pixel clock PLL LOCK bit is set */ + outTi3026(TVP3026_PLL_ADDR, 0, 0x3F); + while ( ! (inTi3026(TVP3026_PIX_CLK_DATA) & 0x40) ); + } +#else + usleep(1); +#endif + /* set Q divider for loop clock PLL */ + outTi3026(TVP3026_MCLK_CTL, 0, mgaReg->DacRegs[18]); + + /* program loop PLL */ + outTi3026(TVP3026_PLL_ADDR, 0, 0x00); + for (i = 3; i < 6; i++) + outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i]); + +#if 0 + if ((vgaReg->MiscOutReg & 0x08) && ((mgaReg->DacClk[3] & 0xC0) == 0xC0) ) { + /* poll until loop PLL LOCK bit is set */ + outTi3026(TVP3026_PLL_ADDR, 0, 0x3F); + while ( ! (inTi3026(TVP3026_LOAD_CLK_DATA) & 0x40) ); + } +#else + usleep(1); +#endif + + /* + * restore other DAC registers + */ + for (i = 0; i < DACREGSIZE; i++) + outTi3026(MGADACregs[i], 0, mgaReg->DacRegs[i]); + + OUTREG(0x1e54, mgaReg->opmode); + +} + +/* + * MGA3026Save -- for mga2064 with ti3026 + * + * This function saves the video state. + */ +static void +MGA3026Save(MGARegPtr mgaReg) +{ + int i; + + mil_setpage(0); + + /* + * The port I/O code necessary to read in the extended registers + * into the fields of the vgaMGARec structure. + */ + for (i = 0; i < 6; i++) + { + mgaReg->ExtVga[i] = mil_inext(i); + } + + outTi3026(TVP3026_PLL_ADDR, 0, 0x00); + for (i = 0; i < 3; i++) + outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i] = + inTi3026(TVP3026_PIX_CLK_DATA)); + + outTi3026(TVP3026_PLL_ADDR, 0, 0x00); + for (i = 3; i < 6; i++) + outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i] = + inTi3026(TVP3026_LOAD_CLK_DATA)); + for (i = 0; i < DACREGSIZE; i++) + mgaReg->DacRegs[i] = inTi3026(MGADACregs[i]); + + mgaReg->Option = __svgalib_pci_read_config_dword(mil_pciposition, PCI_OPTION_REG); + mgaReg->opmode = INREG(0x1e54); +} + + +/* Read and save chipset-specific registers */ +static int mil_saveregs(unsigned char regs[]) +{ + mil_unlock(); + MGA3026Save((MGARegPtr)(regs+60)); + + return MIL_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void mil_setregs(const unsigned char regs[], int mode) +{ + mil_unlock(); + MGA3026Restore((MGARegPtr)(regs+60)); +} + + +/* Return nonzero if mode is available */ + +static int mil_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + + if (mil_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if(modeinfo->bitsPerPixel==24) { + free(modeinfo); + return 0; + } + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +/* Local, called by mil_setmode(). */ + +static void mil_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + MGA3026Init(moderegs, modetiming, modeinfo); + + return ; +} + + +static int mil_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + int i; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!mil_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(MIL_TOTAL_REGS + 60); + + mil_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + mil_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + if(mode>=G640x480x256) + for(i=0;i<256;i++) __svgalib_outpal(i,i,i,i); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void mil_unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); +} + +static void mil_lock(void) +{ +} + + +#define VENDOR_ID 0x102b + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int mil_test(void) +{ + unsigned int buf[64]; + int found; + int id; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + id=(buf[0]>>16)&0xffff; + if(!found)return 0; + switch(id) { + case 0x519: + case 0x51b: + case 0x51f: + mil_init(0,0,0); + return 1; + break; + default: + return 0; + } +} + + +/* Set display start address (not for 16 color modes) */ + +static void mil_setdisplaystart(int address) +{ + address=address >> (2+interleave); + __svgalib_outcrtc(0x0d,address&0xff); + __svgalib_outcrtc(0x0c,(address>>8)&0xff); + mil_outext(0, (mil_inext(0) & 0xf0) | ((address&0xf0000)>>16)); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void mil_setlogicalwidth(int width) +{ + int wd; + + wd = width >> (3+interleave); + if(wd&7) { + wd=(wd|7)+1; + } + __svgalib_outcrtc(0x13,wd&0xff); + mil_outext(0, (mil_inext(0) & 0xcf) | ((wd&0x300)>>4)); +} + +static int mil_linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ return 0;}; + if (op==LINEAR_DISABLE){ return 0;}; + if (op==LINEAR_QUERY_BASE) return mil_linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ + else return -1; /* Unknown function. */ +} + +static int mil_match_programmable_clock(int clock) +{ +return clock ; +} + +static int mil_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int mil_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_mil_driverspecs = +{ + mil_saveregs, + mil_setregs, + mil_unlock, + mil_lock, + mil_test, + mil_init, + mil_setpage, + NULL, + NULL, + mil_setmode, + mil_modeavailable, + mil_setdisplaystart, + mil_setlogicalwidth, + mil_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + mil_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ +}; + +static void __svgalib_mil_inpal(int i, int *r, int *g, int *b) +{ + outTi3026dreg(TVP3026_RADR_PAL,i); + *r=inTi3026dreg(TVP3026_COL_PAL); + *g=inTi3026dreg(TVP3026_COL_PAL); + *b=inTi3026dreg(TVP3026_COL_PAL); +} + +static void __svgalib_mil_outpal(int i, int r, int g, int b) +{ + + outTi3026dreg(TVP3026_WADR_PAL,i); + outTi3026dreg(TVP3026_COL_PAL,r); + outTi3026dreg(TVP3026_COL_PAL,g); + outTi3026dreg(TVP3026_COL_PAL,b); +} + +/* Initialize chipset (called after detection) */ + +static int mil_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0, id; + + if (force) { + mil_memory = par1; + mil_chiptype = par2; + } else { + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + mil_linear_base=0; + id=(buf[0]>>16)&0xffff; + if(found) { + mil_pciposition=found; + switch(id) { + case 0x519: /* Millennium */ + case 0x51b: /* Millennium II */ + case 0x51f: /* Millennium II */ + break; + + default: + return 1; + } + } else { + return 1; + } + + if(id==0x519) { + mil_linear_base = buf[5]&0xffffff00; + mil_mmio_base = buf[4]&0xffffff00; + } else { + mil_linear_base = buf[4]&0xffffff00; + mil_mmio_base = buf[5]&0xffffff00; + } + + if(!mil_memory) { + __svgalib_linear_mem_base=mil_linear_base; + __svgalib_linear_mem_size=8*1024*1024; + map_linear(0); + mil_memory=memorytest((uint32_t *)LINEAR_POINTER, 8); + unmap_linear(); + } + + __svgalib_mmio_base=mil_mmio_base; + __svgalib_mmio_size=16384; + map_mmio(); + __svgalib_vgammbase = 0x1c00; + __svgalib_mm_io_mapio(); + + __svgalib_inpal=__svgalib_mil_inpal; + __svgalib_outpal=__svgalib_mil_outpal; + + if(mil_memory > 2048 ) { + interleave=1; + rounding=127; + } else { + interleave=0; + rounding=63; + BppShifts[0]++; + BppShifts[1]++; + BppShifts[2]++; + BppShifts[3]++; + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using Millennium driver, %iKB.\n",mil_memory); + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = mil_memory; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = 220000; + cardspecs->maxPixelClock16bpp = 220000; + cardspecs->maxPixelClock24bpp = 220000; + cardspecs->maxPixelClock32bpp = 220000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4080; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = mil_map_clock; + cardspecs->mapHorizontalCrtc = mil_map_horizontal_crtc; + cardspecs->matchProgrammableClock=mil_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_mil_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=mil_linear_base; + __svgalib_linear_mem_size=mil_memory*0x400; + __svgalib_mmio_base=mil_mmio_base; + __svgalib_mmio_size=16384; + return 0; +} diff --git a/src/drivers/mx.c b/src/drivers/mx.c new file mode 100644 index 0000000..2dba1c1 --- /dev/null +++ b/src/drivers/mx.c @@ -0,0 +1,717 @@ +/* +MX 86251 driver + +chipset MX 0 1 # 86251 +chipset MX 0 0 # 86250 - not tested. + +Unless I make sure I lock after every unlock, after the first +run, et4000 autodetects. +This slows down the bank switching and setting display start. +Fixes should be made either to vga.c (to run chipset_lock +when entering text mode) or to the et4000 autodetection. + +*/ + +#include +#include /* for printf */ +#include /* for memset */ +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" + +#define MXREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define MX_TOTAL_REGS (VGA_TOTAL_REGS + 36) + +static struct { + unsigned char c8; + unsigned short c15; + unsigned short c16; + unsigned int c32; +} cursor_colors[16*2]; +static unsigned char *cursors[16]; + +static int mx_init(int, int, int); +static void mx_unlock(void); +static void mx_lock(void); + +static int mx_memory,mx_chiptype; +static unsigned int mx_linear_base; +static int SysControl, BankIdx; + +static CardSpecs *cardspecs; + +enum { + MX86250 = 0, MX86251 +}; + +static int pal=1, palette[768]; + +static int findcolor(int rgb) { + int i,j,k,l=0; + + if(pal)vga_getpalvec(0,256,palette); + pal=0; + k=0xffffff; + for(i=0;i<256;i++) { + j=((rgb&0xff)-(palette[i*3+2]<<2))*((rgb&0xff)-(palette[i*3+2]<<2))+ + (((rgb>>8)&0xff)-(palette[i*3+1]<<2))*(((rgb>>8)&0xff)-(palette[i*3+1]<<2))+ + (((rgb>>16)&0xff)-(palette[i*3]<<2))*(((rgb>>16)&0xff)-(palette[i*3]<<2)); + if(j==0) { + return i; + } + if(jcolors==16)return; + + modeinfo->maxpixels = mx_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = mx_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(mx_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int mx_saveregs(unsigned char regs[]) +{ + int i; + + mx_unlock(); /* May be locked again by other programs (e.g. X) */ + regs[MXREG_SAVE(0)] = __svgalib_inCR(0x21); + regs[MXREG_SAVE(1)] = __svgalib_inCR(0x22); + regs[MXREG_SAVE(2)] = __svgalib_inCR(0x23); + regs[MXREG_SAVE(3)] = __svgalib_inCR(0x24); + regs[MXREG_SAVE(4)] = __svgalib_inSR(0x18); + regs[MXREG_SAVE(5)] = __svgalib_inSR(0x19); + regs[MXREG_SAVE(6)] = __svgalib_inSR(0x1D); + regs[MXREG_SAVE(7)] = __svgalib_inCR(SysControl); + regs[MXREG_SAVE(21)] = __svgalib_inSR(0x11); + regs[MXREG_SAVE(22)] = __svgalib_inCR(0x66); + + switch(mx_chiptype){ + case MX86250: + for(i=0x33;i<0x3d;i++)regs[MXREG_SAVE(i-0x33+8)]=__svgalib_inCR(i); + break; + case MX86251: + regs[MXREG_SAVE(8)]=__svgalib_inCR(0x1f); + regs[MXREG_SAVE(9)]=__svgalib_inCR(0x20); + break; + } + + for(i=0x60;i<0x6d;i++) if(i!=0x66) + regs[MXREG_SAVE(i-0x60+23)]=__svgalib_inCR(i); + + return MX_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void mx_setregs(const unsigned char regs[], int mode) +{ + int i; + + mx_unlock(); /* May be locked again by other programs (eg. X) */ + + __svgalib_outSR(0,1); + __svgalib_outCR(0x21,regs[MXREG_SAVE(0)]); + __svgalib_outCR(0x22,regs[MXREG_SAVE(1)]); + __svgalib_outCR(0x23,regs[MXREG_SAVE(2)]); + __svgalib_outCR(0x24,regs[MXREG_SAVE(3)]); + __svgalib_outCR(SysControl,regs[MXREG_SAVE(7)]); + __svgalib_outSR(0x1D,regs[MXREG_SAVE(6)]); + __svgalib_outSR(0x18,regs[MXREG_SAVE(4)]); + __svgalib_outSR(0x19,regs[MXREG_SAVE(5)]); + __svgalib_outSR(0x11,regs[MXREG_SAVE(21)]); + __svgalib_outCR(0x66,regs[MXREG_SAVE(22)]); + __svgalib_outSR(0x1c,0x10); + __svgalib_outSR(0x1c,0x00); + + switch(mx_chiptype){ + case MX86250: + for(i=0x33;i<0x3d;i++)__svgalib_outCR(i,regs[MXREG_SAVE(i-0x33+8)]); + break; + case MX86251: + for(i=0x1f;i<0x21;i++)__svgalib_outCR(i,regs[MXREG_SAVE(i-0x1f+8)]); + break; + } + + for(i=0x60;i<0x6d;i++) if(i!=0x66) + __svgalib_outCR(i,regs[MXREG_SAVE(i-0x60+23)]); + + __svgalib_outSR(0,3); +} + + +/* Return nonzero if mode is available */ + +static int mx_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (mx_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +static unsigned comp_lmn(unsigned clock) ; +/* Set a mode */ + +/* Local, called by mx_setmode(). */ + +static void mx_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ /* int k; */ + int tmp, tmptot, tmpss, tmpse, tmpbs, tmpbe, k; + int offset; + + mx_saveregs(moderegs); + moderegs[MXREG_SAVE(22)]&=0xfe; /* disable hardware cursor */ + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + offset = modeinfo->lineWidth >> 3; + moderegs[0x13] = offset&0xff; + moderegs[0x14]=0x40; + moderegs[0x17]=0xA3; + + moderegs[MXREG_SAVE(0)] = 0x00; + tmp = (modetiming->CrtcHDisplay >> 3) - 1; + tmptot = (modetiming->CrtcHTotal >> 3) - 5; + tmpss = (modetiming->CrtcHSyncStart >> 3); + tmpse = (modetiming->CrtcHSyncEnd >> 3); + tmpbs = (modetiming->CrtcHSyncStart >> 3) - 1; + tmpbe = (modetiming->CrtcHSyncEnd >> 3); + moderegs[MXREG_SAVE(1)]=((tmptot & 0x100)>>8) | + ((tmp & 0x100)>>7) | + ((tmpss & 0x100)>>6) | + ((tmpbs & 0x100)>>5) | + ((tmpse & 0x20)>>1) | + ((tmpbe & 0x40)); + tmp = modetiming->CrtcVDisplay - 1; + tmptot = modetiming->CrtcVTotal - 2; + tmpss = modetiming->CrtcVSyncStart; + tmpse = modetiming->CrtcVSyncEnd; + tmpbs = modetiming->CrtcVSyncStart - 1; + tmpbe = offset; /* borrow for offset */ + moderegs[MXREG_SAVE(2)]=((tmptot & 0x400)>>10) | + ((tmp & 0x400)>>9) | + ((tmpss & 0x400)>>8) | + ((tmpbs & 0x400)>>7) | + ((tmpse & 0x10)<<1) | + ((tmpbe & 0x300)>>2); + moderegs[MXREG_SAVE(3)] = 0x60 ; + if (modetiming->flags & INTERLACED) + moderegs[MXREG_SAVE(3)] |= 0x8; + switch (modeinfo->bitsPerPixel) + { + case 8: + moderegs[MXREG_SAVE(3)] |= 0x3; + moderegs[MXREG_SAVE(21)]=0x0; + break; + case 15: + case 16: if(modeinfo->greenWeight==5){ + moderegs[MXREG_SAVE(21)]=0x20; + moderegs[MXREG_SAVE(3)] |= 0x7;} + else { + moderegs[MXREG_SAVE(3)] |= 0x4; + moderegs[MXREG_SAVE(21)]=0x40;}; + break; + case 24: + moderegs[MXREG_SAVE(3)] |= 0x5; + moderegs[MXREG_SAVE(21)]=0x60; + break; + case 32: + moderegs[MXREG_SAVE(3)] |= 0x6; + moderegs[MXREG_SAVE(21)]=0x60; + break; + default: + moderegs[MXREG_SAVE(3)] |= 0x3; + moderegs[MXREG_SAVE(21)]=0x20; + break; + } + if(modeinfo->bitsPerPixel!=8){ + moderegs[0x28]&=0xbf; + }; + moderegs[MXREG_SAVE(7)] = 0x77; + k=comp_lmn(modetiming->pixelClock); + moderegs[MXREG_SAVE(4)] = k&0xff; + moderegs[MXREG_SAVE(5)] = k>>8; + moderegs[MXREG_SAVE(6)] = 0x2f; + if (mx_chiptype == MX86251) + { + moderegs[MXREG_SAVE(8)] = offset & 0xFF; + moderegs[MXREG_SAVE(9)] = (offset >> 8) | 0x50; + } + else if (mx_chiptype == MX86250) + { + moderegs[MXREG_SAVE(8)] = 0x1f; + moderegs[MXREG_SAVE(9)] = 0xf7; + moderegs[MXREG_SAVE(10)] = 0x77; + moderegs[MXREG_SAVE(11)] = 0x1e; + moderegs[MXREG_SAVE(12)] = 0x01; + moderegs[MXREG_SAVE(13)] = 0x1e; + moderegs[MXREG_SAVE(14)] = 0x5d; + moderegs[MXREG_SAVE(15)] = 0x00; + + tmp = (modeinfo->bitsPerPixel + 7) >> 3; + + if (mx_memory == 1024) + { + tmp = (modetiming->CrtcHDisplay * tmp) >> 2; + moderegs[MXREG_SAVE(16)] = tmp & 0x00ff; +/* moderegs[MXREG_SAVE(17)] = (tmp & 0x0300);*/ + } + else + { + tmp = (modetiming->CrtcHDisplay * tmp) >> 3; + moderegs[MXREG_SAVE(16)] = tmp & 0x00ff; +/* moderegs[MXREG_SAVE(17)] = tmp & 0x0300;*/ + } + } + + { int p,q,r; + + p=moderegs[1]+((moderegs[MXREG_SAVE(1)]&2)<<7); + moderegs[2]=p&0xff; + q=moderegs[4]+((moderegs[MXREG_SAVE(1)]&8)<<5); + r=moderegs[0]+4; + moderegs[3]&=0xe0; + moderegs[3]|=(r&0x1f); + moderegs[5]&=0x7f; + moderegs[5]|=(r&0x20)<<2; + + p=moderegs[0x12]+((moderegs[0x7]&2)<<7)+((moderegs[7]&0x40)<<3)+((moderegs[MXREG_SAVE(2)]&2)<<9); + moderegs[0x15]=p&0xff; + moderegs[0x7]&=0xf7; + moderegs[0x7]|=(p&0x100)>>5; + moderegs[0x9]&=0xdf; + moderegs[0x9]|=(p&0x200)>>4; + moderegs[0x16]=moderegs[6]+1; + } + + return ; +} + + +static int mx_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!mx_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(MX_TOTAL_REGS); + + mx_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + mx_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void mx_unlock(void) +{ + int vgaIOBase, temp; + + vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; + port_out_r(vgaIOBase + 4, 0x11); + temp = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 5, temp & 0x7F); + + __svgalib_outCR(0x19, 0x88); +} + +static void mx_lock(void) +{ + int vgaIOBase, temp; + + vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; + port_out_r(vgaIOBase + 4, 0x11); + temp = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 5, temp & 0x7F); + + __svgalib_outCR(0x19, 0x0); +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int mx_test(void) +{ + int i; + + i=(__svgalib_inCR(0xf2)<< 8) | __svgalib_inCR(0xf1); + if((i&0xfff0)!=0x8620)return 0; + + mx_chiptype=-1; + if((i&0xff)==0x25)mx_chiptype=MX86250; + if((i&0xff)==0x26)mx_chiptype=MX86251; + if(mx_chiptype>=0){ mx_init(0,0,0); return 1;}; + return 0; +} + + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void mx_setdisplaystart(int address) +{ + address=address >> 2; + port_outw_r(CRT_IC, (address & 0x00FF00) | 0x0C); + port_outw_r(CRT_IC, ((address & 0x00FF) << 8) | 0x0D); + port_outw_r(CRT_IC, ((address & 0xFF0000) >> 8) | 0x21); + +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void mx_setlogicalwidth(int width) +{ int i; + int offset = width >> 3; + + __svgalib_outCR(0x13,offset&0xff); + i=__svgalib_inCR(0x23); + i&=0x3f; + i|=(offset&0x300)>>2; + __svgalib_outCR(0x23,i); +} + +static int mx_linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ return 0;} + if (op==LINEAR_DISABLE){ return 0;} + if (op==LINEAR_QUERY_BASE) return mx_linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; + else return -1; +} + +static int mx_match_programmable_clock(int clock) +{ +return clock ; +} + +static int mx_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int mx_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +static int mx_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + unsigned int *b3; + int i, j, k, l; + unsigned int l1, l2; + unsigned char c; + + switch(cmd){ + case CURSOR_INIT: + for (i=0;i<16;i++)cursors[i]=NULL; + return 1; + case CURSOR_HIDE: + __svgalib_outcrtc(0x66,__svgalib_incrtc(0x66)&0xfe); + break; + case CURSOR_SHOW: + __svgalib_outcrtc(0x66,__svgalib_incrtc(0x66)|1); + break; + case CURSOR_POSITION: + if(CI.colors>65536)p1&= ~1; /* the X server does this */ + __svgalib_outcrtc(0x61,p1>>8); + __svgalib_outcrtc(0x60,p1&0xff); + __svgalib_outcrtc(0x63,p2&0xff); + __svgalib_outcrtc(0x62,0); + __svgalib_outcrtc(0x65,0); + __svgalib_outcrtc(0x64,p2>>8); + break; + case CURSOR_IMAGE: + switch(p2){ + case 0: + if(cursors[p1]!=NULL) { + free(cursors[p1]); + } + cursors[p1]=malloc(256); + memcpy(cursors[p1],p5,256); + cursor_colors[p1*2].c8=findcolor(p3); + cursor_colors[p1*2].c32=p3; + cursor_colors[p1*2].c16=((p3&0xf80000)>>8)|((p3&0xfc00)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2].c15=((p3&0xf80000)>>9)|((p3&0xf800)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2+1].c8=findcolor(p4); + cursor_colors[p1*2+1].c32=p4; + cursor_colors[p1*2+1].c16=((p4&0xf80000)>>8)|((p4&0xfc00)>>5)|((p4&0xf8)>>3); + cursor_colors[p1*2+1].c15=((p4&0xf80000)>>9)|((p4&0xf800)>>5)|((p4&0xf8)>>3); + break; + } + case CURSOR_SELECT: + i=mx_memory*1024-256; + b3=(unsigned int *)cursors[p1]; + switch(p2) { + case 0: + switch(CI.colors) { + case 256: + __svgalib_outcrtc(0x6a,cursor_colors[p1*2+1].c8); + __svgalib_outcrtc(0x67,cursor_colors[p1*2].c8); + break; + case 32768: + __svgalib_outcrtc(0x6a,cursor_colors[p1*2+1].c15>>8); + __svgalib_outcrtc(0x6b,cursor_colors[p1*2+1].c15&0xff); + __svgalib_outcrtc(0x67,cursor_colors[p1*2].c15>>8); + __svgalib_outcrtc(0x68,cursor_colors[p1*2].c15&0xff); + break; + case 65536: + __svgalib_outcrtc(0x6a,cursor_colors[p1*2+1].c16>>8); + __svgalib_outcrtc(0x6b,cursor_colors[p1*2+1].c16&0xff); + __svgalib_outcrtc(0x67,cursor_colors[p1*2].c16>>8); + __svgalib_outcrtc(0x68,cursor_colors[p1*2].c16&0xff); + break; + case (1<<24): + __svgalib_outcrtc(0x6a,cursor_colors[p1*2+1].c32>>16); + __svgalib_outcrtc(0x6b,(cursor_colors[p1*2+1].c32>>8)&0xff); + __svgalib_outcrtc(0x6c,cursor_colors[p1*2+1].c32&0xff); + __svgalib_outcrtc(0x67,cursor_colors[p1*2].c32>>16); + __svgalib_outcrtc(0x68,(cursor_colors[p1*2].c32>>8)&0xff); + __svgalib_outcrtc(0x69,cursor_colors[p1*2].c32&0xff); + break; + } + + for(j=0;j<32;j++) { + l1=*(b3+j); + l2=~(*(b3+32+j)); + for(k=0;k<8;k++) { + c=0; + for(l=0;l<4;l++) { + c<<=1; + c|=(l2>>31); + c<<=1; + c|=(l1>>31); + if(c&2)c&=0xfe; + l1<<=1; + l2<<=1; + } + *(LINEAR_POINTER+i+8*j+k)=c; + } + } + break; + } + break; + } + return 0; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_mx_driverspecs = +{ + mx_saveregs, + mx_setregs, + mx_unlock, + mx_lock, + mx_test, + mx_init, + mx_setpage, + NULL, + NULL, + mx_setmode, + mx_modeavailable, + mx_setdisplaystart, + mx_setlogicalwidth, + mx_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + mx_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + mx_cursor, +}; + +/* Initialize chipset (called after detection) */ + +static int mx_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + + mx_unlock(); + if (force) { + mx_memory = par1; + mx_chiptype = par2; + } else { + + }; + if(mx_memory==0)mx_memory=1024<<((__svgalib_inCR(0x57)>>3)& 3); + + found=__svgalib_pci_find_vendor_vga_pos(0x10d9,buf); + mx_linear_base=0; + if (found){ + mx_linear_base=buf[4]&0xffffff00; + }; + + if (__svgalib_driver_report) { + fprintf(stderr,"Using MX driver, %iKB.\n",mx_memory); + switch(mx_chiptype){ + case 1: + fprintf(stderr,"82651 chipset.\n"); + break; + case 0: + fprintf(stderr,"82650 chipset.\n"); + break; + default: + fprintf(stderr,"unknown chipset, using 82650.\n"); + break; + }; + } + switch(mx_chiptype){ + case 1: + SysControl=0x32; + BankIdx=0x34; + break; + case 0: + default: + SysControl=0x25; + BankIdx=0x2e; + break; + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = mx_memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 160000; + cardspecs->maxPixelClock16bpp = 160000; + cardspecs->maxPixelClock24bpp = 160000; + cardspecs->maxPixelClock32bpp = 160000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = mx_map_clock; + cardspecs->mapHorizontalCrtc = mx_map_horizontal_crtc; + cardspecs->matchProgrammableClock=mx_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_mx_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=mx_linear_base; + __svgalib_linear_mem_size=mx_memory*0x400; + return 0; +} + +#define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2))) + +static unsigned +comp_lmn(unsigned clock) +{ + int n, m, l, f, b; + double fvco; + double fout; + double fmax; + double fref; + double fvco_goal; + + fmax = 162000.0; + + fref = 28636.5; /* I'm not sure */ + + for (m = 1; m <= 30; m++) + { + for (l = 2; l >= 0; l--) + { + for (n = 6; n <= 127; n++) + { + fout = ((double)(n + 1) * fref)/((double)(m + 1) * (1 << l)); + fvco_goal = (double)clock * (double)(1 << l); + fvco = fout * (double)(1 << l); + if (!WITHIN(fvco, 0.995*fvco_goal, 1.005*fvco_goal)) + continue; + if (!WITHIN(fvco, 32000.0, fmax)) + continue; + f=0; + if((l==2)||(fvco>100000.0))f=1; + b=0; + if((fvco>150000.0))b=1; +#if 0 +fprintf(stderr,"clock=%i l=%i m=%i n=%i f=%i b=%i\n",clock,n,m,l,f,b); +#endif + if(l==2)l=3; + return (n << 8) | m | (l << 5) | (f<<7) | (b<<15); + } + } + } +fprintf(stderr,"MX driver: Can't do clock=%i\n",clock); + return 0; +} + diff --git a/src/drivers/neo.c b/src/drivers/neo.c new file mode 100644 index 0000000..32c2534 --- /dev/null +++ b/src/drivers/neo.c @@ -0,0 +1,957 @@ +/* + NeoMagic chipset driver + Written by Shigehiro Nomura + +Does not support external screen. + +Remarks: +Problem: The modes whose width is longer than the width of LCD panel + are also reported by vgatest, but not displaying properly. + --> Please do not select such modes :-) + +Note: + When use Toshiba Libretto100,110. + And add the following lines to libvga.config + ------------------------------------------------------------------- + HorizSync 31.5 70 + VertRefresh 50 100 + Modeline "800x480" 50 800 856 976 1024 480 483 490 504 +hsync ++vsync + newmode 800 480 256 800 1 + newmode 800 480 32768 1600 2 + newmode 800 480 65536 1600 2 + newmode 800 480 16777216 2400 3 + ------------------------------------------------------------------- + +*/ +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" + +#undef NEO_PCI_BURST + +#define TRUE (1) +#define FALSE (0) + +#define VENDOR_ID 0x10c8 /* NeoMagic */ +#define PCI_CHIP_NM2070 0x0001 +#define PCI_CHIP_NM2090 0x0002 +#define PCI_CHIP_NM2093 0x0003 +#define PCI_CHIP_NM2097 0x0083 +#define PCI_CHIP_NM2160 0x0004 +#define PCI_CHIP_NM2200 0x0005 + +#define GRAX 0x3ce + +#define NEO_EXT_CR_MAX 0x85 +#define NEO_EXT_GR_MAX 0xC7 + +#define NEOREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define GeneralLockReg NEOREG_SAVE(0) /* GRAX(0x0a) */ +#define ExtCRTDispAddr NEOREG_SAVE(1) /* GRAX(0x0e) */ +#define ExtCRTOffset NEOREG_SAVE(2) /* GRAX(0x0f) */ +#define SysIfaceCntl1 NEOREG_SAVE(3) /* GRAX(0x10) */ +#define SysIfaceCntl2 NEOREG_SAVE(4) /* GRAX(0x11) */ +#define SingleAddrPage NEOREG_SAVE(5) /* GRAX(0x15) */ +#define DualAddrPage NEOREG_SAVE(6) /* GRAX(0x16) */ +#define PanelDispCntlReg1 NEOREG_SAVE(7) /* GRAX(0x20) */ +#define PanelDispCntlReg2 NEOREG_SAVE(8) /* GRAX(0x25) */ +#define PanelDispCntlReg3 NEOREG_SAVE(9) /* GRAX(0x30) */ +#define PanelVertCenterReg1 NEOREG_SAVE(10) /* GRAX(0x28) */ +#define PanelVertCenterReg2 NEOREG_SAVE(11) /* GRAX(0x29) */ +#define PanelVertCenterReg3 NEOREG_SAVE(12) /* GRAX(0x2a) */ +#define PanelVertCenterReg4 NEOREG_SAVE(13) /* GRAX(0x32) */ +#define PanelVertCenterReg5 NEOREG_SAVE(14) /* GRAX(0x37) */ +#define PanelHorizCenterReg1 NEOREG_SAVE(15) /* GRAX(0x33) */ +#define PanelHorizCenterReg2 NEOREG_SAVE(16) /* GRAX(0x34) */ +#define PanelHorizCenterReg3 NEOREG_SAVE(17) /* GRAX(0x35) */ +#define PanelHorizCenterReg4 NEOREG_SAVE(18) /* GRAX(0x36) */ +#define PanelHorizCenterReg5 NEOREG_SAVE(19) /* GRAX(0x38) */ +#define ExtColorModeSelect NEOREG_SAVE(20) /* GRAX(0x90) */ +#define VCLK3NumeratorLow NEOREG_SAVE(21) /* GRAX(0x9b) */ +#define VCLK3NumeratorHigh NEOREG_SAVE(22) /* GRAX(0x8f) */ +#define VCLK3Denominator NEOREG_SAVE(23) /* GRAX(0x9f) */ +#define VerticalExt NEOREG_SAVE(24) +#define EXT_SAVED NEOREG_SAVE(25) /* EXT regs. saved ? */ +#define EXTCR NEOREG_SAVE(26) /* CR(0x00..) */ +#define EXTGR (EXTCR + NEO_EXT_CR_MAX + 1) /* GR(0x00..) */ +#define DAC (EXTGR + NEO_EXT_GR_MAX + 1) /* DAC */ +#define NEO_TOTAL_REGS (DAC + 768) + +#define DACDelay \ + { \ + unsigned char temp = port_in(vgaIOBase + 0x0A); \ + temp = port_in(vgaIOBase + 0x0A); \ + } + + +static int neo_init(int, int, int); +static void neo_unlock(void); +static void neo_lock(void); + +extern unsigned char __svgalib_neolibretto100; +static int neo_memory; +static int NeoChipset; +static int NeoPanelWidth, NeoPanelHeight; +static unsigned int neo_linear_base; +static int vgaIOBase; + +static CardSpecs *cardspecs; + +static void neo_setpage(int page) +{ +#ifdef DEBUG + fprintf(stderr, "neo_setpage: %d\n", page); +#endif + port_out_r(GRAX, 0x11); + port_outw_r(GRAX, ((port_in(GRAX+1) & 0xfc) << 8) | 0x11); + port_outw_r(GRAX, (page << 10) | 0x15); /* set read/write bank */ +} + +static void neo_setrdpage(int page) +{ +#ifdef DEBUG + fprintf(stderr, "neo_setrdpage: %d\n", page); +#endif + port_out_r(GRAX, 0x11); + port_outw_r(GRAX, (((port_in(GRAX+1) & 0xfc) | 0x01) << 8) | 0x11); + port_outw_r(GRAX, (page << 10) | 0x15); /* set read bank */ +} + +static void neo_setwrpage(int page) +{ +#ifdef DEBUG + fprintf(stderr, "neo_setwrpage: %d\n", page); +#endif + port_out_r(GRAX, 0x11); + port_outw_r(GRAX, (((port_in(GRAX+1) & 0xfc) | 0x01) << 8) | 0x11); + port_outw_r(GRAX, (page << 10) | 0x16); /* set write bank */ +} + +/* Fill in chipset specific mode information */ +static void neo_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ +#ifdef DEBUG + fprintf(stderr, "neo_getmodeinfo: %d\n", mode); +#endif + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = neo_memory*1024/modeinfo->bytesperpixel; + if (NeoChipset == PCI_CHIP_NM2200) + modeinfo->maxlogicalwidth = 1280; + else + modeinfo->maxlogicalwidth = 1024; + modeinfo->startaddressrange = neo_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags |= HAVE_RWPAGE; + +#if 1 + if (modeinfo->bytesperpixel >= 1) { + if(neo_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +#endif +} + +/* Read and save chipset-specific registers */ + +static int neo_saveregs(unsigned char regs[]) +{ + int i; + +#ifdef DEBUG + fprintf(stderr, "neo_saveregs\n"); +#endif + neo_unlock(); + port_outw_r(GRAX, 0x0015); /* bank#0 */ + + port_out_r(GRAX, 0x0a); regs[GeneralLockReg] = port_in(GRAX + 1); + port_out_r(GRAX, 0x0e); regs[ExtCRTDispAddr] = port_in(GRAX + 1); + port_out_r(GRAX, 0x0f); regs[ExtCRTOffset] = port_in(GRAX + 1); + port_out_r(GRAX, 0x10); regs[SysIfaceCntl1] = port_in(GRAX + 1); + port_out_r(GRAX, 0x11); regs[SysIfaceCntl2] = port_in(GRAX + 1); + port_out_r(GRAX, 0x15); regs[SingleAddrPage] = port_in(GRAX + 1); + port_out_r(GRAX, 0x16); regs[DualAddrPage] = port_in(GRAX+1); + port_out_r(GRAX, 0x20); regs[PanelDispCntlReg1] = port_in(GRAX+1); + port_out_r(GRAX, 0x25); regs[PanelDispCntlReg2] = port_in(GRAX+1); + port_out_r(GRAX, 0x30); regs[PanelDispCntlReg3] = port_in(GRAX+1); + port_out_r(GRAX, 0x28); regs[PanelVertCenterReg1] = port_in(GRAX+1); + port_out_r(GRAX, 0x29); regs[PanelVertCenterReg2] = port_in(GRAX+1); + port_out_r(GRAX, 0x2a); regs[PanelVertCenterReg3] = port_in(GRAX+1); + if (NeoChipset != PCI_CHIP_NM2070){ + port_out_r(GRAX, 0x32); regs[PanelVertCenterReg4] = port_in(GRAX+1); + port_out_r(GRAX, 0x33); regs[PanelHorizCenterReg1] = port_in(GRAX+1); + port_out_r(GRAX, 0x34); regs[PanelHorizCenterReg2] = port_in(GRAX+1); + port_out_r(GRAX, 0x35); regs[PanelHorizCenterReg3] = port_in(GRAX+1); + } + if (NeoChipset == PCI_CHIP_NM2160){ + port_out_r(GRAX, 0x36); regs[PanelHorizCenterReg4] = port_in(GRAX+1); + } + if (NeoChipset == PCI_CHIP_NM2200){ + port_out_r(GRAX, 0x36); regs[PanelHorizCenterReg4] = port_in(GRAX+1); + port_out_r(GRAX, 0x37); regs[PanelVertCenterReg5] = port_in(GRAX+1); + port_out_r(GRAX, 0x38); regs[PanelHorizCenterReg5] = port_in(GRAX+1); + } + port_out_r(GRAX, 0x90); regs[ExtColorModeSelect] = port_in(GRAX+1); + port_out_r(GRAX, 0x9B); regs[VCLK3NumeratorLow] = port_in(GRAX+1); + if (NeoChipset == PCI_CHIP_NM2200){ + port_out_r(GRAX, 0x8F); regs[VCLK3NumeratorHigh] = port_in(GRAX+1); + } + port_out_r(GRAX, 0x9F); regs[VCLK3Denominator] = port_in(GRAX+1); + + regs[EXT_SAVED] = TRUE; + port_out_r(vgaIOBase + 4, 0x25); regs[EXTCR + 0x25] = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 4, 0x2F); regs[EXTCR + 0x2F] = port_in(vgaIOBase + 5); + for (i = 0x40; i <= 0x59; i++){ + port_out_r(vgaIOBase + 4, i); regs[EXTCR + i] = port_in(vgaIOBase + 5); + } + for (i = 0x60; i <= 0x69; i++){ + port_out_r(vgaIOBase + 4, i); regs[EXTCR + i] = port_in(vgaIOBase + 5); + } + for (i = 0x70; i <= NEO_EXT_CR_MAX; i++){ + port_out_r(vgaIOBase + 4, i); regs[EXTCR + i] = port_in(vgaIOBase + 5); + } + + for (i = 0x0A; i <= NEO_EXT_GR_MAX; i++){ + port_out_r(GRAX, i); regs[EXTGR + i] = port_in(GRAX+1); + } + + /* DAC */ + port_out_r(0x3C6,0xFF); /* mask */ + port_out_r(0x3C7,0x00); /* read address */ + for (i = 0; i < 768; i++){ + regs[DAC + i] = port_in(0x3C9); + DACDelay; + } + + return NEO_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void neo_setregs(const unsigned char regs[], int mode) +{ + int i; + unsigned char temp; + +#ifdef DEBUG + fprintf(stderr, "neo_setregs\n"); +#endif + neo_unlock(); + port_outw_r(GRAX, 0x0015); /* bank#0 */ + + port_out_r(GRAX, 0x0a); port_out_r(GRAX+1, regs[GeneralLockReg]); + + /* set color mode first */ + port_out_r(GRAX, 0x90); temp = port_in(GRAX+1); + switch (NeoChipset){ + case PCI_CHIP_NM2070: + temp &= 0xF0; /* Save bits 7:4 */ + temp |= (regs[ExtColorModeSelect] & ~0xF0); + break; + case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: case PCI_CHIP_NM2097: + case PCI_CHIP_NM2160: case PCI_CHIP_NM2200: + temp &= 0x70; /* Save bits 6:4 */ + temp |= (regs[ExtColorModeSelect] & ~0x70); + break; + } + port_out_r(GRAX, 0x90); port_out_r(GRAX+1, temp); + + /* Disable horizontal and vertical graphics and text expansions */ + port_out_r(GRAX, 0x25); + temp = port_in(GRAX+1); + port_out_r(GRAX, 0x25); + temp &= 0x39; + port_out_r(GRAX+1, temp); + + usleep(200000); + + /* DAC */ + port_out_r(0x3C6,0xFF); /* mask */ + port_out_r(0x3C8,0x00); /* write address */ + for (i = 0; i < 768; i++){ + port_out_r(0x3C9, regs[DAC + i]); + DACDelay; + } + + port_out_r(GRAX, 0x0E); port_out_r(GRAX+1, regs[ExtCRTDispAddr]); + port_out_r(GRAX, 0x0F); port_out_r(GRAX+1, regs[ExtCRTOffset]); + port_out_r(GRAX, 0x10); temp = port_in(GRAX+1); + temp &= 0x0F; /* Save bits 3:0 */ + temp |= (regs[SysIfaceCntl1] & ~0x0F); + port_out_r(GRAX, 0x10); port_out_r(GRAX+1, temp); + + port_out_r(GRAX, 0x11); port_out_r(GRAX+1, regs[SysIfaceCntl2]); + port_out_r(GRAX, 0x15); port_out_r(GRAX+1, regs[SingleAddrPage]); + port_out_r(GRAX, 0x16); port_out_r(GRAX+1, regs[DualAddrPage]); + port_out_r(GRAX, 0x20); temp = port_in(GRAX+1); + switch (NeoChipset){ + case PCI_CHIP_NM2070: + temp &= 0xFC; /* Save bits 7:2 */ + temp |= (regs[PanelDispCntlReg1] & ~0xFC); + break; + case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: case PCI_CHIP_NM2097: + case PCI_CHIP_NM2160: + temp &= 0xDC; /* Save bits 7:6,4:2 */ + temp |= (regs[PanelDispCntlReg1] & ~0xDC); + break; + case PCI_CHIP_NM2200: + temp &= 0x98; /* Save bits 7,4:3 */ + temp |= (regs[PanelDispCntlReg1] & ~0x98); + break; + } + port_out_r(GRAX, 0x20); port_out_r(GRAX+1, temp); + port_out_r(GRAX, 0x25); temp = port_in(GRAX+1); + temp &= 0x38; /* Save bits 5:3 */ + temp |= (regs[PanelDispCntlReg2] & ~0x38); + port_out_r(GRAX, 0x25); port_out_r(GRAX+1, temp); + + if (NeoChipset != PCI_CHIP_NM2070){ + port_out_r(GRAX, 0x30); temp = port_in(GRAX+1); + temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */ + temp |= (regs[PanelDispCntlReg3] & ~0xEF); + port_out_r(GRAX, 0x30); port_out_r(GRAX+1, temp); + } + + port_out_r(GRAX, 0x28); port_out_r(GRAX+1, regs[PanelVertCenterReg1]); + port_out_r(GRAX, 0x29); port_out_r(GRAX+1, regs[PanelVertCenterReg2]); + port_out_r(GRAX, 0x2a); port_out_r(GRAX+1, regs[PanelVertCenterReg3]); + + if (NeoChipset != PCI_CHIP_NM2070){ + port_out_r(GRAX, 0x32); port_out_r(GRAX+1, regs[PanelVertCenterReg4]); + port_out_r(GRAX, 0x33); port_out_r(GRAX+1, regs[PanelHorizCenterReg1]); + port_out_r(GRAX, 0x34); port_out_r(GRAX+1, regs[PanelHorizCenterReg2]); + port_out_r(GRAX, 0x35); port_out_r(GRAX+1, regs[PanelHorizCenterReg3]); + } + + if (NeoChipset == PCI_CHIP_NM2160){ + port_out_r(GRAX, 0x36); port_out_r(GRAX+1, regs[PanelHorizCenterReg4]); + } + + if (NeoChipset == PCI_CHIP_NM2200){ + port_out_r(GRAX, 0x36); port_out_r(GRAX+1, regs[PanelHorizCenterReg4]); + port_out_r(GRAX, 0x37); port_out_r(GRAX+1, regs[PanelVertCenterReg5]); + port_out_r(GRAX, 0x38); port_out_r(GRAX+1, regs[PanelHorizCenterReg5]); + } + +#if 0 + port_out_r(GRAX, 0x9B); port_out_r(GRAX+1, regs[VCLK3NumeratorLow]); + if (NeoChipset == PCI_CHIP_NM2200){ + port_out_r(GRAX, 0x8F); temp = port_in(GRAX+1); + temp &= 0x0F; /* Save bits 3:0 */ + temp |= (regs[VCLK3NumeratorHigh] & ~0x0F); + port_out_r(GRAX, 0x8F); port_out_r(GRAX+1, temp); + } + port_out_r(GRAX, 0x9F); port_out_r(GRAX+1, regs[VCLK3Denominator]); +#endif + + if (regs[EXT_SAVED]){ + port_out_r(vgaIOBase + 4, 0x25); port_out_r(vgaIOBase + 5, regs[EXTCR + 0x25]); + port_out_r(vgaIOBase + 4, 0x2F); port_out_r(vgaIOBase + 5, regs[EXTCR + 0x2F]); + for (i = 0x40; i <= 0x59; i++){ + port_out_r(vgaIOBase + 4, i); port_out_r(vgaIOBase + 5, regs[EXTCR + i]); + } + for (i = 0x60; i <= 0x69; i++){ + port_out_r(vgaIOBase + 4, i); port_out_r(vgaIOBase + 5, regs[EXTCR + i]); + } + for (i = 0x70; i <= NEO_EXT_CR_MAX; i++){ + port_out_r(vgaIOBase + 4, i); port_out_r(vgaIOBase + 5, regs[EXTCR + i]); + } + + for (i = 0x0a; i <= 0x3f; i++){ + port_out_r(GRAX, i); port_out_r(GRAX+1, regs[EXTGR + i]); + } + for (i = 0x90; i <= NEO_EXT_GR_MAX; i++){ + port_out_r(GRAX, i); port_out_r(GRAX+1, regs[EXTGR + i]); + } + } + + /* Program vertical extension register */ + if (NeoChipset == PCI_CHIP_NM2200){ + port_out_r(vgaIOBase + 4, 0x70); port_out_r(vgaIOBase + 5, regs[VerticalExt]); + } +} + +#if 0 +/* + * NeoCalcVCLK -- + * + * Determine the closest clock frequency to the one requested. + */ +#define REF_FREQ 14.31818 +#define MAX_N 127 +#define MAX_D 31 +#define MAX_F 1 + +static void NeoCalcVCLK(int freq, unsigned char *moderegs) +{ + int n, d, f; + double f_out; + double f_diff; + int n_best = 0, d_best = 0, f_best = 0; + double f_best_diff = 999999.0; + double f_target = freq/1000.0; + + for (f = 0; f <= MAX_F; f++) + for (n = 0; n <= MAX_N; n++) + for (d = 0; d <= MAX_D; d++) { + f_out = (n+1.0)/((d+1.0)*(1<ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +/* Local, called by neo_setmode(). */ + +static void neo_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + int i, hoffset, voffset; + +#ifdef DEBUG + fprintf(stderr, "neo_initializemode: %d\n", mode); +#endif + neo_saveregs(moderegs); + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + moderegs[EXT_SAVED] = FALSE; + moderegs[VGA_AR10] = 0x01; /* Attribute 0x10 */ + + moderegs[0x13] = modeinfo->lineWidth >> 3; + moderegs[ExtCRTOffset] = modeinfo->lineWidth >> 11; + switch (modeinfo->bitsPerPixel){ + case 8: + moderegs[ExtColorModeSelect] = 0x11; + break; + case 15: + case 16: + if (modeinfo->greenWeight == 5){ /* 15bpp */ + for (i = 0; i < 64; i++){ + moderegs[DAC + i*3+0] = i << 1; + moderegs[DAC + i*3+1] = i << 1; + moderegs[DAC + i*3+2] = i << 1; + } + moderegs[ExtColorModeSelect] = 0x12; + } else { /* 16bpp */ + for (i = 0; i < 64; i++){ + moderegs[DAC + i*3+0] = i << 1; + moderegs[DAC + i*3+1] = i; + moderegs[DAC + i*3+2] = i << 1; + } + moderegs[ExtColorModeSelect] = 0x13; + } + break; + case 24: + for (i = 0; i < 256; i++){ + moderegs[DAC + i*3+0] = i; + moderegs[DAC + i*3+1] = i; + moderegs[DAC + i*3+2] = i; + } + moderegs[ExtColorModeSelect] = 0x14; + break; + } + moderegs[ExtCRTDispAddr] = 0x10; + +#if 0 + /* Vertical Extension */ + moderegs[VerticalExt] = (((modetiming->CrtcVTotal -2) & 0x400) >> 10 ) + | (((modetiming->CrtcVDisplay -1) & 0x400) >> 9 ) + | (((modetiming->CrtcVSyncStart) & 0x400) >> 8 ) + | (((modetiming->CrtcVSyncStart) & 0x400) >> 7 ); +#endif + + /* Disable read/write bursts if requested. */ +#ifdef NEO_PCI_BURST + moderegs[SysIfaceCntl1] = 0x30; +#else /* NEO_PCI_BURST */ + moderegs[SysIfaceCntl1] = 0x00; +#endif /* NEO_PCI_BURST */ + + /* If they are used, enable linear addressing and/or enable MMIO. */ + moderegs[SysIfaceCntl2] = 0x00; + moderegs[SysIfaceCntl2] |= 0x80; /* Linear */ +#if 0 + moderegs[SysIfaceCntl2] |= 0x40; /* MMIO */ +#endif + + moderegs[PanelDispCntlReg1] = 0x00; + moderegs[PanelDispCntlReg1] |= 0x02; /* Enable internal display */ +#if 0 + moderegs[PanelDispCntlReg1] |= 0x01; /* Enable external display */ +#endif + + /* If we are using a fixed mode, then tell the chip we are. */ + switch (modetiming->HDisplay) { + case 1280: + moderegs[PanelDispCntlReg1] |= 0x60; + break; + case 1024: + moderegs[PanelDispCntlReg1] |= 0x40; + break; + case 800: + moderegs[PanelDispCntlReg1] |= 0x20; + break; + case 640: + break; + } + + /* Setup shadow register locking. */ + moderegs[GeneralLockReg] = 0x01; + + moderegs[PanelDispCntlReg2] = 0x00; + moderegs[PanelDispCntlReg3] = 0x00; + + /* + * If the screen is to be centerd, turn on the centering for the + * various modes. + */ + moderegs[PanelVertCenterReg1] = 0x00; + moderegs[PanelVertCenterReg2] = 0x00; + moderegs[PanelVertCenterReg3] = 0x00; + moderegs[PanelVertCenterReg4] = 0x00; + moderegs[PanelVertCenterReg5] = 0x00; + moderegs[PanelHorizCenterReg1] = 0x00; + moderegs[PanelHorizCenterReg2] = 0x00; + moderegs[PanelHorizCenterReg3] = 0x00; + moderegs[PanelHorizCenterReg4] = 0x00; + moderegs[PanelHorizCenterReg5] = 0x00; + + if (moderegs[PanelDispCntlReg1] & 0x02){ + if (modetiming->HDisplay < NeoPanelWidth){ + moderegs[PanelDispCntlReg3] |= 0x10; + hoffset = ((NeoPanelWidth - modetiming->HDisplay) >> 4) - 1; + moderegs[PanelHorizCenterReg1] = hoffset; + switch (modetiming->HDisplay){ + case 320: + moderegs[PanelHorizCenterReg3] = hoffset; + break; + case 400: + moderegs[PanelHorizCenterReg4] = hoffset; + break; + case 640: + moderegs[PanelHorizCenterReg1] = hoffset; + break; + case 800: + moderegs[PanelHorizCenterReg2] = hoffset; + break; + case 1024: + moderegs[PanelHorizCenterReg5] = hoffset; + break; + case 1280: + /* No centering in these modes. */ + break; + } + } + if (modetiming->VDisplay < NeoPanelHeight){ + moderegs[PanelDispCntlReg2] |= 0x01; + voffset = ((NeoPanelHeight - modetiming->VDisplay) >> 1) - 2; + moderegs[PanelVertCenterReg2] = voffset; + switch (modetiming->VDisplay){ + case 240: + moderegs[PanelVertCenterReg2] = voffset; + break; + case 300: case 384: + moderegs[PanelVertCenterReg1] = voffset; + break; + case 480: + moderegs[PanelVertCenterReg3] = voffset; + break; + case 600: + moderegs[PanelVertCenterReg4] = voffset; + break; + case 768: + moderegs[PanelVertCenterReg5] = voffset; + break; + case 1280: + /* No centering in these modes. */ + break; + } + } + } + +#if 0 + /* + * Calculate the VCLK that most closely matches the requested dot + * clock. + */ + NeoCalcVCLK(modetiming->pixelClock, moderegs); +#endif + /* Since we program the clocks ourselves, always use VCLK3. */ + moderegs[MIS] |= 0x0C; + + return ; +} + + +static int neo_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + +#ifdef DEBUG + fprintf(stderr, "neo_setmode: %d\n", mode); +#endif + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!neo_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(NEO_TOTAL_REGS); + + neo_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + neo_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + __svgalib_InitializeAcceleratorInterface(modeinfo); + + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void neo_unlock(void) +{ + int temp; + +#ifdef DEBUG + fprintf(stderr, "neo_unlock\n"); +#endif + port_out_r(vgaIOBase + 4, 0x11); + temp = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 5, temp & 0x7F); + port_outw_r(GRAX, 0x2609); /* Unlock NeoMagic registers */ +} + +static void neo_lock(void) +{ + int temp; + +#ifdef DEBUG + fprintf(stderr, "neo_lock\n"); +#endif + port_out_r(vgaIOBase + 4, 0x11); + temp = port_in(vgaIOBase + 5); + port_out_r(vgaIOBase + 5, temp | 0x80); + port_outw_r(GRAX, 0x0009); /* Lock NeoMagic registers */ +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int neo_test(void) +{ + unsigned int buf[64]; + int found=0; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if (found){ /* found */ + switch ((buf[0] >> 16) & 0xffff){ + case PCI_CHIP_NM2070: case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: + case PCI_CHIP_NM2097: case PCI_CHIP_NM2160: case PCI_CHIP_NM2200: + neo_init(0,0,0); + return (TRUE); + } + } + + return (FALSE); +} + + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void neo_setdisplaystart(int address) +{ + int oldExtCRTDispAddr; + +#ifdef DEBUG + fprintf(stderr, "neo_setdisplaystart: 0x%x\n", address); +#endif + address=address >> 2; + port_outw_r(vgaIOBase + 4, (address & 0x00FF00) | 0x0C); + port_outw_r(vgaIOBase + 4, ((address & 0x00FF) << 8) | 0x0D); + + port_out_r(GRAX, 0x0E); + oldExtCRTDispAddr = port_in(GRAX+1); + port_outw_r(GRAX, + ((((address >> 16) & 0x07) | (oldExtCRTDispAddr & 0xf8)) << 8) | 0x0E); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void neo_setlogicalwidth(int width) +{ + int offset = width >> 3; + +#ifdef DEBUG + fprintf(stderr, "neo_setlogicalwidth: %d\n", width); +#endif + __svgalib_outCR(0x13,offset&0xff); + port_out_r(GRAX, 0x0F); + port_out_r(GRAX+1, width >> 11); +} + +static int neo_linear(int op, int param) +{ +#ifdef DEBUG + fprintf(stderr, "neo_linear: %d\n", op); +#endif + if (op==LINEAR_ENABLE){ return 0;}; + if (op==LINEAR_DISABLE){ return 0;}; + if (op==LINEAR_QUERY_BASE) return neo_linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ + else return -1; /* Unknown function. */ +} + +static int neo_match_programmable_clock(int clock) +{ +return clock ; +} + +static int neo_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int neo_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_neo_driverspecs = +{ + neo_saveregs, + neo_setregs, +#if 1 + neo_unlock, + neo_lock, +#else + 0, + 0, +#endif + neo_test, + neo_init, + neo_setpage, + neo_setrdpage, + neo_setwrpage, + neo_setmode, + neo_modeavailable, + neo_setdisplaystart, + neo_setlogicalwidth, + neo_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + neo_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ +}; + + +/* Initialize chipset (called after detection) */ + +static int neo_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + int w; + + vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; + neo_unlock(); + if (force) { + neo_memory = par1; + NeoChipset = par2; + } else { + neo_memory = -1; + NeoChipset = -1; + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + neo_linear_base=0; + if (found){ /* found */ + neo_linear_base=buf[4]&0xffffff00; + if (NeoChipset < 0) + NeoChipset = (buf[0] >> 16) & 0xffff; + if (neo_memory < 0){ + switch (NeoChipset){ + case PCI_CHIP_NM2070: + neo_memory = 896; + break; + case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: case PCI_CHIP_NM2097: + neo_memory = 1152; + break; + case PCI_CHIP_NM2160: + neo_memory = 2048; + break; + case PCI_CHIP_NM2200: + neo_memory = 2560; + break; + default: + neo_memory = 0; + } + } + } + if (__svgalib_driver_report) { + fprintf(stderr,"Using NeoMagic driver, %iKB.\n",neo_memory); + }; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = neo_memory; + cardspecs->maxPixelClock4bpp = 75000; + switch (NeoChipset){ + case PCI_CHIP_NM2070: + cardspecs->maxPixelClock8bpp = 65000; + cardspecs->maxPixelClock16bpp = 65000; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 0; + break; + case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: case PCI_CHIP_NM2097: + cardspecs->maxPixelClock8bpp = 80000; + cardspecs->maxPixelClock16bpp = 80000; + cardspecs->maxPixelClock24bpp = 80000; + cardspecs->maxPixelClock32bpp = 0; + break; + case PCI_CHIP_NM2160: + cardspecs->maxPixelClock8bpp = 90000; + cardspecs->maxPixelClock16bpp = 90000; + cardspecs->maxPixelClock24bpp = 90000; + cardspecs->maxPixelClock32bpp = 0; + break; + case PCI_CHIP_NM2200: + cardspecs->maxPixelClock8bpp = 110000; + cardspecs->maxPixelClock16bpp = 110000; + cardspecs->maxPixelClock24bpp = 110000; + cardspecs->maxPixelClock32bpp = 0; + break; + } + + /* Determine panel width -- used in NeoValidMode. */ + port_out_r(GRAX, 0x20); + w = port_in(GRAX+1); + switch ((w & 0x18) >> 3){ + case 0x00: + NeoPanelWidth = 640; + NeoPanelHeight = 480; + break; + case 0x01: + NeoPanelWidth = 800; + if (__svgalib_neolibretto100) + NeoPanelHeight = 480; + else + NeoPanelHeight = 600; + break; + case 0x02: + NeoPanelWidth = 1024; + NeoPanelHeight = 768; + break; + case 0x03: + NeoPanelWidth = 1280; + NeoPanelHeight = 1024; + break; + default : + NeoPanelWidth = 640; + NeoPanelHeight = 480; + } + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 2040; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = neo_map_clock; + cardspecs->mapHorizontalCrtc = neo_map_horizontal_crtc; + cardspecs->matchProgrammableClock=neo_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_neo_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=neo_linear_base; + __svgalib_linear_mem_size=neo_memory*0x400; + + return 0; +} diff --git a/src/drivers/nv3.c b/src/drivers/nv3.c new file mode 100644 index 0000000..e998030 --- /dev/null +++ b/src/drivers/nv3.c @@ -0,0 +1,945 @@ +/* +Riva 128 driver - Matan Ziv-Av matan@svgalib.org +please report problems to me, + +This driver is based on the XFREE86 nv3 driver, developed by +David J. Mckay. + +I used the file cirrus.c in this directory as a skeleton. + +there are still the following problems: + * no 24bit modes. (maybe the hardware does not support) + * pageflipping (in threeDKit) does not work. + * no acceleration (is there a program that uses it anyway?). +*/ + +#include +#include /* for printf */ +#include /* for memset */ +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "nv3ref.h" +#include "nvreg.h" +#include "vgapci.h" + +struct nv_regs { + uint8_t old[VGA_TOTAL_REGS]; + uint8_t repaint0; + uint8_t repaint1; + uint8_t extra; + uint8_t pixel; + uint8_t horiz_extra; + uint8_t fifo_control; + uint8_t fifo; + uint8_t screen; + uint32_t config_0; + uint32_t vpll_coeff; + uint32_t vpllb_coeff; + uint32_t pll_coeff_select; + uint32_t general_control; + uint32_t gcursor_start_pos; + uint8_t crtc[0x3A-0x18]; +}; + +#define NV3_TOTAL_REGS (sizeof(struct nv_regs)) + +#define P_MIN 0 + +#define SetBitField(value,from,to) SetBF(to,GetBF(value,from)) +#define SetBit(n) (1<<(n)) +#define Set8Bits(value) ((value)&0xff) + +#define GET15BITCOLOR(r,g,b) ((((r)&0xf8)<<7)|(((g)&0xf8)<<2)|((b)>>3)) + +#include "nv3io.c" + +static int init(int, int, int); +static void unlock(void); + +static int memory, chip, nvnum, nvarch; +static CardSpecs *cardspecs; +static int PLL_INPUT_FREQ, MAXVCLOCK, M_MIN, M_MAX, P_MAX; +static int dualhead, twostagepll; + +static unsigned int MMIOBASE, LINEARBASE; + +enum { + Riva128 = 0, RivaTNT, GEFORCE +}; + +static void setpage(int page) +{ + __svgalib_outcrtc(0x1d,page << 1); + __svgalib_outcrtc(0x1e,page << 1); +} + + +/* Fill in chipset specific mode information */ +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + modeinfo->flags |= CAPABLE_LINEAR; +// if(chip==Riva128) +// modeinfo->flags |= IOCTL_SETDISPLAY; + } +} + +/* Read and save chipset-specific registers */ + +static int saveregs(unsigned char regs[]) +{ + int i; + struct nv_regs *save = (struct nv_regs *)regs; + + unlock(); /* May be locked again by other programs (e.g. X) */ + + save->repaint0 = __svgalib_incrtc(NV_PCRTC_REPAINT0); + save->repaint1 = __svgalib_incrtc(NV_PCRTC_REPAINT1); + save->extra = __svgalib_incrtc(NV_PCRTC_EXTRA); + save->pixel = __svgalib_incrtc(NV_PCRTC_PIXEL); + save->horiz_extra = __svgalib_incrtc(NV_PCRTC_HORIZ_EXTRA); + save->fifo_control = __svgalib_incrtc(NV_PCRTC_FIFO_CONTROL); + save->fifo = __svgalib_incrtc(NV_PCRTC_FIFO); + save->screen = __svgalib_incrtc(NV_PCRTC_SCREEN); + + save->config_0 = v_readl(NV_PFB_CONFIG_0); + + save->vpll_coeff = v_readl(NV_PRAMDAC_VPLL_COEFF); + if(twostagepll) + save->vpllb_coeff = v_readl(NV_PRAMDAC_VPLLB_COEFF); + + save->pll_coeff_select = v_readl(NV_PRAMDAC_PLL_COEFF_SELECT); + save->general_control = v_readl(NV_PRAMDAC_GENERAL_CONTROL); + save->gcursor_start_pos = v_readl(NV_PRAMDAC_GRCURSOR_START_POS); + + for(i=0x18;i<0x3A;i++) save->crtc[i-0x18]=__svgalib_incrtc(i); + + return NV3_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + struct nv_regs *save = (struct nv_regs *)regs; + + unlock(); /* May be locked again by other programs (eg. X) */ + + __svgalib_outcrtc(NV_PCRTC_REPAINT0,save->repaint0); + __svgalib_outcrtc(NV_PCRTC_REPAINT1,save->repaint1); + __svgalib_outcrtc(NV_PCRTC_EXTRA,save->extra); + __svgalib_outcrtc(NV_PCRTC_PIXEL,save->pixel); + __svgalib_outcrtc(NV_PCRTC_HORIZ_EXTRA,save->horiz_extra); + __svgalib_outcrtc(NV_PCRTC_FIFO_CONTROL,save->fifo_control); + __svgalib_outcrtc(NV_PCRTC_FIFO,save->fifo); + + if(chip >= GEFORCE) + __svgalib_outcrtc(NV_PCRTC_SCREEN, save->screen); + + __svgalib_outcrtc(0x1c,save->crtc[0x1c-0x18]); /* this enables banking at 0xa0000 */ + __svgalib_outcrtc(0x1d,save->crtc[0x1d-0x18]); + __svgalib_outcrtc(0x1e,save->crtc[0x1E -0x18]); + __svgalib_outcrtc(0x30,save->crtc[0x30-0x18]); + __svgalib_outcrtc(0x31,save->crtc[0x31-0x18]); + __svgalib_outcrtc(0x39,save->crtc[0x39-0x18]); + + v_writel(save->config_0, NV_PFB_CONFIG_0); + + v_writel(save->vpll_coeff, NV_PRAMDAC_VPLL_COEFF); + if(twostagepll) + v_writel(save->vpllb_coeff, NV_PRAMDAC_VPLLB_COEFF); + + v_writel(save->pll_coeff_select, NV_PRAMDAC_PLL_COEFF_SELECT); + v_writel(save->general_control, NV_PRAMDAC_GENERAL_CONTROL); + v_writel(save->gcursor_start_pos, NV_PRAMDAC_GRCURSOR_START_POS); +} + + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if(modeinfo->bitsPerPixel==24) { + free(modeinfo); + return 0; + } + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +static int CalcVClock(int clockIn,int *clockOut,int *mOut, + int *nOut,int *pOut); +static void CalcVClock2Stage ( + int clockIn, + int *clockOut, + uint32_t *pllOut, + uint32_t *pllBOut + ); + +static int CalculateCRTC(ModeTiming *mode, ModeInfo *modeinfo, unsigned char *moderegs) +{ + + struct nv_regs *save = (struct nv_regs *)moderegs; + int bpp=modeinfo->bitsPerPixel/8, + horizDisplay = (mode->CrtcHDisplay/8) - 1, + horizStart = (mode->CrtcHSyncStart/8) - 0, + horizEnd = (mode->CrtcHSyncEnd/8) - 0, + horizTotal = (mode->CrtcHTotal/8) - 5, + horizBlankStart = (mode->CrtcHDisplay/8) - 1, + horizBlankEnd = (mode->CrtcHTotal/8) - 1, + vertDisplay = mode->CrtcVDisplay - 1, + vertStart = mode->CrtcVSyncStart - 1, + vertEnd = mode->CrtcVSyncEnd - 1, + vertTotal = mode->CrtcVTotal - 2, + vertBlankStart = mode->CrtcVDisplay - 1, + vertBlankEnd = mode->CrtcVTotal - 1; + + if(mode->flags & INTERLACED) vertTotal |= 1; + + /* Calculate correct value for offset register */ + moderegs[0x13]=((modeinfo->width/8)*bpp)&0xff; + + /* Extra bits for CRTC offset register */ + save->repaint0= + SetBitField((modeinfo->width/8)*bpp,10:8,7:5); + + /* The NV3 manuals states that for native modes, there should be no + * * borders. This code should also be tidied up to use symbolic names + * */ + moderegs[0x0]=Set8Bits(horizTotal); + moderegs[0x1]=Set8Bits(horizDisplay); + moderegs[0x2]=Set8Bits(horizBlankStart); + moderegs[0x3]=SetBitField(horizBlankEnd,4:0,4:0) | SetBit(7); + moderegs[0x4]=Set8Bits(horizStart); + moderegs[0x5]=SetBitField(horizBlankEnd,5:5,7:7)| + SetBitField(horizEnd,4:0,4:0); + moderegs[0x6]=SetBitField(vertTotal,7:0,7:0); + + moderegs[0x7]=SetBitField(vertTotal,8:8,0:0)| + SetBitField(vertDisplay,8:8,1:1)| + SetBitField(vertStart,8:8,2:2)| + SetBitField(vertBlankStart,8:8,3:3)| + SetBit(4)| + SetBitField(vertTotal,9:9,5:5)| + SetBitField(vertDisplay,9:9,6:6)| + SetBitField(vertStart,9:9,7:7); + + moderegs[0x9]= SetBitField(vertBlankStart,9:9,5:5) | SetBit(6); + moderegs[0x10]= Set8Bits(vertStart); + moderegs[0x11]= SetBitField(vertEnd,3:0,3:0) | SetBit(5); + moderegs[0x12]= Set8Bits(vertDisplay); + moderegs[0x15]= Set8Bits(vertBlankStart); + moderegs[0x16]= Set8Bits(vertBlankEnd); + + save->extra = SetBitField(horizBlankEnd,6:6,4:4) + | SetBitField(vertBlankStart,10:10,3:3) + | SetBitField(vertStart,10:10,2:2) + | SetBitField(vertDisplay,10:10,1:1) + | SetBitField(vertTotal,10:10,0:0); + + save->horiz_extra = SetBitField(horizTotal,8:8,0:0) + | SetBitField(horizDisplay,8:8,1:1) + | SetBitField(horizBlankStart,8:8,2:2) + | SetBitField(horizStart,8:8,3:3); + + save->screen = SetBitField(vertTotal,11:11,0:0) + | SetBitField(vertDisplay,11:11,2:2) + | SetBitField(vertStart,11:11,4:4) + | SetBitField(vertBlankStart,11:11,6:6); + + if(mode->flags & DOUBLESCAN) moderegs[0x9]|=0x80; + + /* I think this should be SetBitField(horizTotal,8:8,0:0), but this + * * doesn't work apparently. Why 260 ? 256 would make sense. + * */ + if(mode->flags & INTERLACED) { + horizTotal=(horizTotal>>1)& ~1; + save->crtc[33]=horizTotal & 0xff; + save->horiz_extra |= SetBitField(horizTotal,8:8,4:4); + } else { + save->crtc[33]=255; + } + + return 1; +} + +/* Set a mode */ + +/* Local, called by setmode(). */ + +static void initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + int k; + unsigned int config0=0; + struct nv_regs *save = (struct nv_regs *)moderegs; + + int clockIn=modetiming->pixelClock; + int clockOut; + int pixelDepth; + + saveregs(moderegs); + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + if(twostagepll) { + CalcVClock2Stage(clockIn, &clockOut, &save->vpll_coeff, &save->vpllb_coeff); + } else { + int m,n,p; + CalcVClock(clockIn,&clockOut,&m,&n,&p); + save->vpll_coeff = PRAMDAC_Val(VPLL_COEFF_NDIV,n) | + PRAMDAC_Val(VPLL_COEFF_MDIV,m) | + PRAMDAC_Val(VPLL_COEFF_PDIV,p); + } + + CalculateCRTC(modetiming,modeinfo,moderegs); + + save->repaint1 = PCRTC_Val(REPAINT1_LARGE_SCREEN,modetiming->CrtcHDisplay<1280); + +/* The new xfree driver (from nVidia) calculates those in some + twisted way, but I leave it for now */ + save->fifo_control=0x83; + if(modetiming->pixelClock*modeinfo->bytesPerPixel>720000) { + save->fifo=0x2f; + } + + /* PixelFormat controls how many bits per pixel. + * There is another register in the + * DAC which controls if mode is 5:5:5 or 5:6:5 + */ + pixelDepth=(modeinfo->bitsPerPixel+1)/8; + if(pixelDepth>3) pixelDepth=3; + + save->pixel=pixelDepth; + + if(modetiming->flags & TVMODE) { + save->pixel|=0x80; + if(modetiming->flags & TVPAL) save->pixel|=0x40; + }; + + save->general_control= + PRAMDAC_Def(GENERAL_CONTROL_IDC_MODE,GAMMA)| + PRAMDAC_Val(GENERAL_CONTROL_565_MODE,modeinfo->greenWeight==6)| + PRAMDAC_Def(GENERAL_CONTROL_TERMINATION,37OHM)| + ((modeinfo->bitsPerPixel>8) ? + PRAMDAC_Def(GENERAL_CONTROL_BPC,8BITS) : + PRAMDAC_Def(GENERAL_CONTROL_BPC,6BITS)) | PRAMDAC_Def(GENERAL_CONTROL_VGA_STATE,SEL); + /* Not sure about this */ + + switch(chip){ + case Riva128: + config0=PFB_Val(CONFIG_0_RESOLUTION,((modeinfo->lineWidth+31)/32))| + PFB_Val(CONFIG_0_PIXEL_DEPTH,pixelDepth)| + PFB_Def(CONFIG_0_TILING,DISABLED); + k=PRAMDAC_Def(PLL_COEFF_SELECT_MPLL_SOURCE,PROG)| + PRAMDAC_Def(PLL_COEFF_SELECT_VPLL_SOURCE,PROG)| + PRAMDAC_Def(PLL_COEFF_SELECT_VCLK_RATIO,DB2); + save->repaint1 |= PCRTC_Def(REPAINT1_PALETTE_WIDTH,6BITS); + break; + case RivaTNT: + config0=0x1114; + k=0x10000700; + break; + case GEFORCE: + default: + config0=save->config_0; + k=0x10000700; + break; + }; + + save->pll_coeff_select=k; + save->config_0=config0; + + save->crtc[4]=28; + save->crtc[25]&=0xfe; /* hide cursor */ + + return; +} + + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + int i; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + unsigned int k; + + if(chip==Riva128) + v_writel(0x00000100, NV_PRAMDAC_PLL_COEFF_SELECT); + else v_writel(0x00000500, NV_PRAMDAC_PLL_COEFF_SELECT); + __svgalib_outcrtc(NV_PCRTC_REPAINT0,0); + __svgalib_outcrtc(NV_PCRTC_REPAINT1,0x3d); + __svgalib_outcrtc(NV_PCRTC_EXTRA,0); + __svgalib_outcrtc(NV_PCRTC_PIXEL,0); + __svgalib_outcrtc(NV_PCRTC_HORIZ_EXTRA,0); + __svgalib_outcrtc(NV_PCRTC_FIFO_CONTROL,0x83); + __svgalib_outcrtc(0x1c,0x18); + __svgalib_outcrtc(0x1d,0); + __svgalib_outcrtc(0x1e,0); + __svgalib_outcrtc(0x30,0); + __svgalib_outcrtc(0x31,0); + k = v_readl(NV_PRAMDAC_GENERAL_CONTROL); + k &= ~0x00100000; + v_writel(k, NV_PRAMDAC_GENERAL_CONTROL); + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + + if (!modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(NV3_TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + __svgalib_InitializeAcceleratorInterface(modeinfo); + + for(i=0;i<256;i++)vga_setpalette(i,i,i,i); + free(modeinfo); + return 0; +} + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ + if(chip!=Riva128) { + __svgalib_nv3_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + __svgalib_nv3_outcrtc(0x1f, UNLOCK_EXT_MAGIC); + } else { +// __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + __svgalib_outseq(LOCK_EXT_INDEX,UNLOCK_EXT_MAGIC); + } +} + +/* Relock chipset-specific registers */ +/* (currently not used) */ + +static void lock(void) +{ + __svgalib_outseq(LOCK_EXT_INDEX,UNLOCK_EXT_MAGIC+1); + +} + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + unsigned int buf[64]; + int found=0; + found=__svgalib_pci_find_vendor_vga_pos(0x12d2,buf); + + if (!found) { + found=__svgalib_pci_find_vendor_vga_pos(0x10de,buf); + if(!found) return 0; + }; + + MMIOBASE=0; /* let init() find those */ + LINEARBASE=0; + init(0,0,0); + + return 1; +} + +/* Set display start address (not for 16 color modes) */ + +static void setdisplaystart(int address) +{ + unsigned char byte; + int pan; + + pan=(address&3)<<1; + address=address >> 2; + __svgalib_outcrtc(0x0d,address&0xff); + __svgalib_outcrtc(0x0c,(address>>8)&0xff); + byte=__svgalib_incrtc(NV_PCRTC_REPAINT0) & 0xe0; + __svgalib_outcrtc(NV_PCRTC_REPAINT0,((address>>16)&0x1f)|byte); + byte=__svgalib_incrtc(0x2D) & ~0x60; + __svgalib_outcrtc(0x2D,((address>>16)&0x60)|byte); + + byte = __svgalib_inis1(); + __svgalib_outatt(0x13, pan); +} + +/* Set logical scanline length (usually multiple of 8) */ + +static void setlogicalwidth(int width) +{ + int byte ; + + __svgalib_outcrtc(0x13,(width >> 3)&0xff); + byte=__svgalib_incrtc(NV_PCRTC_REPAINT0) & 0x1f; + __svgalib_outcrtc(NV_PCRTC_REPAINT0,SetBitField(width,13:11,7:5)|byte); + +} + +static int linear(int op, int param) +{ + if (op==LINEAR_DISABLE || op==LINEAR_ENABLE) return 0; + if (op==LINEAR_QUERY_BASE) return __svgalib_linear_mem_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + unsigned char *b1, *b2; + unsigned short *b3; + unsigned int i, j, k, l, c0, c1; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + __svgalib_outcrtc(0x31,__svgalib_incrtc(0x31)&0xfe); /* disable cursor */ + break; + case CURSOR_SHOW: + __svgalib_outcrtc(0x31,__svgalib_incrtc(0x31)|1); /* enable cursor */ + break; + case CURSOR_POSITION: + v_writel(p1+(p2<<16), NV_PRAMDAC_GRCURSOR_START_POS); + break; + case CURSOR_SELECT: + i=memory/2-(p1+1); + if (chip==Riva128) { + __svgalib_outcrtc(0x31,(__svgalib_incrtc(0x31)&7)|(((~i)&0x1f)<<3)); + } else { + __svgalib_outcrtc(0x31,(__svgalib_incrtc(0x31)&3)|(((~i)&0x3f)<<2)); + } +#if 0 + __svgalib_outcrtc(0x30,((~i)&0x3fc0)>>6); +#else + __svgalib_outcrtc(0x30,0); +#endif + break; + case CURSOR_IMAGE: + i=memory/2-(p1+1); + i=i*2048; + switch(p2) { + case 0: /* X11 format, 32x32 */ + b3=malloc(2048); + b1=(unsigned char *)p5; + b2=b1+128; + c0=0x8000|GET15BITCOLOR((p3>>16)&0xff,(p3>>8)&0xff,p3&0xff); + c1=0x8000|GET15BITCOLOR((p4>>16)&0xff,(p4>>8)&0xff,p4&0xff); + l=992; + for(k=0;k<128;k++) { + int cc1=*(b1+k); + int cc2=*(b2+k); + for(j=0;j<8;j++) { + if(!(cc2&0x80)) *(b3+l)=0; else if (cc1&0x80) + *(b3+l)=c1; else *(b3+l)=c0; + l++; + if((l&0x1f)==0)l-=64; + cc2<<=1; + cc1<<=1; + } + } + memcpy(LINEAR_POINTER+i,b3,2048); + free(b3); + break; + case 1: /* nvidia 1555 format 32x32 */ + memcpy(LINEAR_POINTER+i,p5,2048); + break; + } + break; + } + return 0; +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} +static int map_clock(int bpp, int clock) +{ +return clock ; +} +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} +/* Function table (exported) */ + +DriverSpecs __svgalib_nv3_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + setpage, + 0, + 0, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + 0, + cursor +}; + +/* Initialize chipset (called after detection) */ + +static int init(int force, int par1, int par2) +{ + char *archs[3]={"Riva128", + "RivaTNT", + "GeForce"}; + int flags; + + flags=0; + dualhead=1; + twostagepll=0; + + if(MMIOBASE==0) { + unsigned int buf[64]; + int found; + + found=__svgalib_pci_find_vendor_vga_pos(0x12d2,buf); + + if (!found) { + found=__svgalib_pci_find_vendor_vga_pos(0x10de,buf); + if(!found) return 1; + } + + switch((buf[0]>>20)&0xff){ + case 0x1: + dualhead=0; + chip=Riva128; + nvnum=3; + nvarch=3; + break; + case 0x2: + case 0xA: + dualhead=0; + chip=RivaTNT; + nvarch=4; + switch((buf[0]>>16)&0xff){ + case 0x20: + nvnum=4; + break; + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + nvnum=6; + break; + default: + nvnum=5; + } + break; + case 0x04: /* Geforce 6xxx NV4x */ + case 0x09: + case 0x0C: + case 0x0F: + case 0x12: + case 0x13: + case 0x14: + case 0x16: + case 0x19: + case 0x1D: + case 0x21: + case 0x31: /* untested */ + case 0x34: /* untested */ + twostagepll=1; + chip=GEFORCE; + nvnum=0x40; + nvarch=0x40; + break; + case 0x10: + case 0x15: + case 0x1A: + dualhead=0; /* fall thru */ + case 0x11: + case 0x17: + case 0x18: + case 0x1F: + chip=GEFORCE; + nvnum=(buf[0]>>20)&0xff; + nvarch=0x10; + break; + case 0x20: + dualhead=0; /* fall thru */ + case 0x25: + case 0x28: /* untested */ + case 0x30: /* untested */ + case 0x32: /* untested */ + case 0x33: /* untested */ + default: + flags = NO_INTERLACE; + chip=GEFORCE; + nvnum=(buf[0]>>20)&0xff; + nvarch=(buf[0]>>20)&0xf0; + break; + }; + MMIOBASE=buf[4]&0xffffff00; + LINEARBASE=buf[5]&0xffffff00; + }; + + if(nvnum==0x31 || nvnum==0x34) twostagepll=1; + + if (force) { + memory = par1; + chip = par2; + }; + + __svgalib_mmio_base=MMIOBASE; + __svgalib_mmio_size=8*1024*1024; + + map_mmio(); + + if(!force){ + int boot0; + + boot0=v_readl(NV_PFB_BOOT_0); + //fprintf(stderr, "BOOT0=%08x\n",boot0); + switch(chip){ + case Riva128: + if(boot0&0x20)memory=8192; else memory=1024<<(boot0&3); + if(memory==1024)memory=8192; + break; + case RivaTNT: + memory=2048<<(boot0&3); + if(memory==2048)memory=32768; + break; + case GEFORCE: + memory=(v_readl(NV_PFB_BOOT_10)>>10) & 0x3fc00; + if(memory<8192)memory=8192; /* do this later */ + break; + } + } + + mapio(); + unlock(); + + { + int temp; + + temp=v_readl(NV_PEXTDEV_0); + switch(chip){ + case Riva128: + PLL_INPUT_FREQ= (temp&0x20) ? 14318 : 13500; + MAXVCLOCK=256000; + P_MAX=4; /* XFree say 3, but 4 works on my Riva128 */ + if(PLL_INPUT_FREQ==13500)M_MAX=12; else M_MAX=13; + M_MIN=M_MAX-5; + break; + case RivaTNT: + PLL_INPUT_FREQ= (temp&0x40) ? 14318 : 13500; + MAXVCLOCK=350000; + P_MAX=4; + if(PLL_INPUT_FREQ==13500)M_MAX=13; else M_MAX=14; + M_MIN=M_MAX-6; + break; + case GEFORCE: + default: + PLL_INPUT_FREQ= (temp&0x40 ) ? 14318 : 13500; + if(dualhead && (nvnum!=0x11)) { + if(temp&0x400000) PLL_INPUT_FREQ=27000; + } + MAXVCLOCK=350000; + P_MAX=4; + if(PLL_INPUT_FREQ==13500)M_MAX=13; else M_MAX=14; + M_MIN=M_MAX-6; + break; + }; + }; + + if (__svgalib_driver_report) { + fprintf(stderr,"Using nvidia driver, %iKB, Type: %s (NV %x).\n",memory,archs[chip],nvnum); + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + if(chip==Riva128) { + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 230000; + cardspecs->maxPixelClock16bpp = 230000; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 230000; + } else { + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 350000; + cardspecs->maxPixelClock16bpp = 350000; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 350000; + } + cardspecs->flags = flags | CLOCK_PROGRAMMABLE ; + cardspecs->maxHorizontalCrtc = 4080; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->clocks = NULL; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_nv3_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=LINEARBASE; + __svgalib_linear_mem_size=memory*0x400; + + return 0; +} + +/* + * Calculate the Video Clock parameters for the PLL. + */ +static int CalcVClock +( + int clockIn, + int *clockOut, + int *mOut, + int *nOut, + int *pOut +) +{ + unsigned DeltaNew, DeltaOld; + unsigned VClk, Freq; + unsigned M, N, P; + + DeltaOld = 0xFFFFFFFF; + + VClk = (unsigned)clockIn; + + for (P = 0; P <= P_MAX; P ++) + { + Freq = VClk << P; + if ((Freq >= 128000) && (Freq <= MAXVCLOCK)) + { + for (M = M_MIN; M <= M_MAX; M++) + { + N = ((VClk<> P; + if (Freq > VClk) + DeltaNew = Freq - VClk; + else + DeltaNew = VClk - Freq; + if ((DeltaNew < DeltaOld) && (N<256)) + { + *mOut = M; + *nOut = N; + *pOut = P; + *clockOut = Freq; + DeltaOld = DeltaNew; + } + } + } + } + return (DeltaOld != 0xFFFFFFFF); +} + +static void CalcVClock2Stage ( + int clockIn, + int *clockOut, + uint32_t *pllOut, + uint32_t *pllBOut + ) +{ + unsigned DeltaNew, DeltaOld; + unsigned VClk, Freq; + unsigned M, N, P; + + DeltaOld = 0xFFFFFFFF; + + *pllBOut = 0x80000401; /* fixed at x4 for now */ + + VClk = (unsigned)clockIn; + + for (P = 0; P <= 6; P++) { + Freq = VClk << P; + if ((Freq >= 400000) && (Freq <= 1000000)) { + for (M = 1; M <= 13; M++) { + N = ((VClk << P) * M) / (PLL_INPUT_FREQ << 2); + if((N >= 5) && (N <= 255)) { + Freq = (((PLL_INPUT_FREQ << 2) * N) / M) >> P; + if (Freq > VClk) + DeltaNew = Freq - VClk; + else + DeltaNew = VClk - Freq; + if (DeltaNew < DeltaOld) { + *pllOut = (P << 16) | (N << 8) | M; + *clockOut = Freq; + DeltaOld = DeltaNew; + } + } + } + } + } +} + + + diff --git a/src/drivers/nv3io.c b/src/drivers/nv3io.c new file mode 100644 index 0000000..b6c579d --- /dev/null +++ b/src/drivers/nv3io.c @@ -0,0 +1,105 @@ +static int __svgalib_nv3_inmisc(void) +{ + return v_readb(NV_PVGA0+MIS_R); +} + +static void __svgalib_nv3_outmisc(int i) +{ + v_writeb(i, NV_PVGA0+MIS_W); +} + +static int __svgalib_nv3_incrtc(int i) +{ + v_writeb(i, NV_PVGA1+__svgalib_CRT_I); + return v_readb(NV_PVGA1+__svgalib_CRT_D); +} + +static void __svgalib_nv3_outcrtc(int i, int d) +{ + v_writeb(i, NV_PVGA1+__svgalib_CRT_I); + v_writeb(d, NV_PVGA1+__svgalib_CRT_D); +} + +static int __svgalib_nv3_inseq(int index) +{ + v_writeb(index, NV_PVGA0+SEQ_I); + return v_readb(NV_PVGA0+SEQ_D); +} + +static void __svgalib_nv3_outseq(int index, int val) +{ + v_writeb(index, NV_PVGA0+SEQ_I); + v_writeb(val, NV_PVGA0+SEQ_D); +} + +static int __svgalib_nv3_ingra(int index) +{ + v_writeb(index, NV_PVGA0+GRA_I); + return v_readb(NV_PVGA0+GRA_D); +} + +static void __svgalib_nv3_outgra(int index, int val) +{ + v_writeb(index, NV_PVGA0+GRA_I); + v_writeb(val, NV_PVGA0+GRA_D); +} + +static int __svgalib_nv3_inis1(void) +{ + return v_readb(NV_PVGA1+__svgalib_IS1_R); +} + +static int __svgalib_nv3_inatt(int index) +{ + __svgalib_nv3_inis1(); + v_writeb(index, NV_PVGA1+ATT_IW); + return v_readb(NV_PVGA1+ATT_R); +} + +static void __svgalib_nv3_outatt(int index, int val) +{ + __svgalib_nv3_inis1(); + v_writeb(index, NV_PVGA1+ATT_IW); + v_writeb(val, NV_PVGA1+ATT_IW); +} + +static void __svgalib_nv3_attscreen(int i) +{ + __svgalib_nv3_inis1(); + v_writeb(i, NV_PVGA1+ATT_IW); +} + +static void __svgalib_nv3_inpal(int i, int *r, int *g, int *b) +{ + v_writeb(i, NV_PVGA2+PEL_IR); + *r=v_readb(NV_PVGA2+PEL_D); + *g=v_readb(NV_PVGA2+PEL_D); + *b=v_readb(NV_PVGA2+PEL_D); +} + +static void __svgalib_nv3_outpal(int i, int r, int g, int b) +{ + v_writeb(i, NV_PVGA2+PEL_IW); + v_writeb(r, NV_PVGA2+PEL_D); + v_writeb(g, NV_PVGA2+PEL_D); + v_writeb(b, NV_PVGA2+PEL_D); +} + +static void mapio(void) +{ + __svgalib_inmisc=__svgalib_nv3_inmisc; + __svgalib_outmisc=__svgalib_nv3_outmisc; + __svgalib_incrtc=__svgalib_nv3_incrtc; + __svgalib_outcrtc=__svgalib_nv3_outcrtc; + __svgalib_inseq=__svgalib_nv3_inseq; + __svgalib_outseq=__svgalib_nv3_outseq; + __svgalib_ingra=__svgalib_nv3_ingra; + __svgalib_outgra=__svgalib_nv3_outgra; + __svgalib_inatt=__svgalib_nv3_inatt; + __svgalib_outatt=__svgalib_nv3_outatt; + __svgalib_attscreen=__svgalib_nv3_attscreen; + __svgalib_inis1=__svgalib_nv3_inis1; + __svgalib_inpal=__svgalib_nv3_inpal; + __svgalib_outpal=__svgalib_nv3_outpal; +} + diff --git a/src/drivers/nv3ref.h b/src/drivers/nv3ref.h new file mode 100644 index 0000000..1c5343c --- /dev/null +++ b/src/drivers/nv3ref.h @@ -0,0 +1,647 @@ + /***************************************************************************\ +|* *| +|* Copyright (c) 1996-1998 NVIDIA, Corp. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. NVIDIA, Corp. of Sunnyvale, California owns *| +|* the copyright and as design patents pending on the design and *| +|* interface of the NV chips. Users and possessors of this source *| +|* code are hereby granted a nonexclusive, royalty-free copyright *| +|* and design patent license to use this code in individual and *| +|* commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright (c) 1996-1998 NVIDIA, Corp. NVIDIA design patents *| +|* pending in the U.S. and foreign countries. *| +|* *| +|* NVIDIA, CORP. MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF *| +|* THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT *| +|* EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORP. DISCLAIMS *| +|* ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL *| +|* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *| +|* PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA, CORP. BE LIABLE *| +|* FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, *| +|* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR *| +|* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER *| +|* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR *| +|* PERFORMANCE OF THIS SOURCE CODE. *| +|* *| + \***************************************************************************/ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/nv3ref.h,v 1.1.2.3 1998/01/24 00:04:39 robin Exp $ */ + +#ifndef __NV3REF_H__ +#define __NV3REF_H__ + + +/* Magic values to lock/unlock extended regs */ +#define UNLOCK_EXT_MAGIC 0x57 +#define LOCK_EXT_MAGIC 0x99 /* Any value other than 0x57 will do */ + +#define LOCK_EXT_INDEX 0x6 + +/* Extended offset and start address */ +#define NV_PCRTC_REPAINT0 0x19 +#define NV_PCRTC_REPAINT0_OFFSET_10_8 7:5 +#define NV_PCRTC_REPAINT0_START_ADDR_20_16 4:0 + +/* Horizonal extended bits */ +#define NV_PCRTC_HORIZ_EXTRA 0x2d +#define NV_PCRTC_HORIZ_EXTRA_INTER_HALF_START_8 4:4 +#define NV_PCRTC_HORIZ_EXTRA_HORIZ_RETRACE_START_8 3:3 +#define NV_PCRTC_HORIZ_EXTRA_HORIZ_BLANK_START_8 2:2 +#define NV_PCRTC_HORIZ_EXTRA_DISPLAY_END_8 1:1 +#define NV_PCRTC_HORIZ_EXTRA_DISPLAY_TOTAL_8 0:0 + +/* Assorted extra bits */ +#define NV_PCRTC_EXTRA 0x25 +#define NV_PCRTC_EXTRA_OFFSET_11 5:5 +#define NV_PCRTC_EXTRA_HORIZ_BLANK_END_6 4:4 +#define NV_PCRTC_EXTRA_VERT_BLANK_START_10 3:3 +#define NV_PCRTC_EXTRA_VERT_RETRACE_START_10 2:2 +#define NV_PCRTC_EXTRA_VERT_DISPLAY_END_10 1:1 +#define NV_PCRTC_EXTRA_VERT_TOTAL_10 0:0 + + +/* Controls how much data the refresh fifo requests */ +#define NV_PCRTC_FIFO_CONTROL 0x1b +#define NV_PCRTC_FIFO_CONTROL_UNDERFLOW_WARN 7:7 +#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH 2:0 +#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_8 0x0 +#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_32 0x1 +#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_64 0x2 +#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_128 0x3 +#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_256 0x4 + +/* When the fifo occupancy falls below *twice* the watermark, + * the refresh fifo will start to be refilled. If this value is + * too low, you will get junk on the screen. Too high, and performance + * will suffer. Watermark in units of 8 bytes + */ +#define NV_PCRTC_FIFO 0x20 +#define NV_PCRTC_FIFO_RESET 7:7 +#define NV_PCRTC_FIFO_WATERMARK 5:0 + + +/* Various flags */ +#define NV_PCRTC_REPAINT1 0x1a +#define NV_PCRTC_REPAINT1_HSYNC 7:7 +#define NV_PCRTC_REPAINT1_HYSNC_DISABLE 0x01 +#define NV_PCRTC_REPAINT1_HYSNC_ENABLE 0x00 +#define NV_PCRTC_REPAINT1_VSYNC 6:6 +#define NV_PCRTC_REPAINT1_VYSNC_DISABLE 0x01 +#define NV_PCRTC_REPAINT1_VYSNC_ENABLE 0x00 +#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT 4:4 +#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT_ENABLE 0x01 +#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT_DISABLE 0x00 +#define NV_PCRTC_REPAINT1_LARGE_SCREEN 2:2 +#define NV_PCRTC_REPAINT1_LARGE_SCREEN_DISABLE 0x01 +#define NV_PCRTC_REPAINT1_LARGE_SCREEN_ENABLE 0x00 /* >=1280 */ +#define NV_PCRTC_REPAINT1_PALETTE_WIDTH 1:1 +#define NV_PCRTC_REPAINT1_PALETTE_WIDTH_8BITS 0x00 +#define NV_PCRTC_REPAINT1_PALETTE_WIDTH_6BITS 0x01 + + +#define NV_PCRTC_GRCURSOR0 0x30 +#define NV_PCRTC_GRCURSOR0_START_ADDR_21_16 5:0 + +#define NV_PCRTC_GRCURSOR1 0x31 +#define NV_PCRTC_GRCURSOR1_START_ADDR_15_11 7:3 +#define NV_PCRTC_GRCURSOR1_SCAN_DBL 1:1 +#define NV_PCRTC_GRCURSOR1_SCAN_DBL_DISABLE 0 +#define NV_PCRTC_GRCURSOR1_SCAN_DBL_ENABLE 1 +#define NV_PCRTC_GRCURSOR1_CURSOR 0:0 +#define NV_PCRTC_GRCURSOR1_CURSOR_DISABLE 0 +#define NV_PCRTC_GRCURSOR1_CURSOR_ENABLE 1 + +#define NV_PCRTC_SCREEN 0x41 + + +/* Controls what the format of the framebuffer is */ +#define NV_PCRTC_PIXEL 0x28 +#define NV_PCRTC_PIXEL_MODE 7:7 +#define NV_PCRTC_PIXEL_MODE_TV 0x01 +#define NV_PCRTC_PIXEL_MODE_VGA 0x00 +#define NV_PCRTC_PIXEL_TV_MODE 6:6 +#define NV_PCRTC_PIXEL_TV_MODE_NTSC 0x00 +#define NV_PCRTC_PIXEL_TV_MODE_PAL 0x01 +#define NV_PCRTC_PIXEL_TV_HORIZ_ADJUST 5:3 +#define NV_PCRTC_PIXEL_FORMAT 1:0 +#define NV_PCRTC_PIXEL_FORMAT_VGA 0x00 +#define NV_PCRTC_PIXEL_FORMAT_8BPP 0x01 +#define NV_PCRTC_PIXEL_FORMAT_16BPP 0x02 +#define NV_PCRTC_PIXEL_FORMAT_32BPP 0x03 + +#define NV_PEXTDEV 0x00101fff:0x00101000 +#define NV_PEXTDEV_0 0x00101000 + +#define NV_PRAMDAC 0x00680FFF:0x00680000 /* RW--D */ + +#define NV_PRAMDAC_VPLL_COEFF 0x00680508 /* RW-4R */ +#define NV_PRAMDAC_VPLL_COEFF_MDIV 7:0 /* RWIUF */ +#define NV_PRAMDAC_VPLL_COEFF_NDIV 15:8 /* RWIUF */ +#define NV_PRAMDAC_VPLL_COEFF_PDIV 18:16 /* RWIVF */ +#define NV_PRAMDAC_VPLLB_COEFF 0x00680578 /* RW-4R */ + + +#define NV_PRAMDAC_PLL_COEFF_SELECT 0x0068050C /* RW-4R */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS 4:4 /* RWIVF */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS_FALSE 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS_TRUE 0x00000001 /* RW--V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE 8:8 /* RWIVF */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE_DEFAULT 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE_PROG 0x00000001 /* RW--V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS 12:12 /* RWIVF */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS_FALSE 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS_TRUE 0x00000001 /* RW--V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE 16:16 /* RWIVF */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE_DEFAULT 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE_PROG 0x00000001 /* RW--V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS 20:20 /* RWIVF */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS_FALSE 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS_TRUE 0x00000001 /* RW--V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE 25:24 /* RWIVF */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_VPLL 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_VIP 0x00000001 /* RW--V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_XTALOSC 0x00000002 /* RW--V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO 28:28 /* RWIVF */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB1 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2 0x00000001 /* RW--V */ + + +/* Various flags for DAC. BPC controls the width of the palette */ + +#define NV_PRAMDAC_GENERAL_CONTROL 0x00680600 /* RW-4R */ +#define NV_PRAMDAC_GENERAL_CONTROL_FF_COEFF 1:0 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_FF_COEFF_DEF 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE 4:4 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE_GAMMA 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE_INDEX 0x00000001 /* RW--V */ +#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE 8:8 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_NOTSE 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL 0x00000001 /* RW--V */ +#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE 12:12 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE_NOTSEL 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE_SEL 0x00000001 /* RW--V */ +#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL 16:16 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL_OFF 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL_ON 0x00000001 /* RW--V */ +#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION 17:17 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_37OHM 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM 0x00000001 /* RW--V */ +#define NV_PRAMDAC_GENERAL_CONTROL_BPC 20:20 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_BPC_6BITS 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS 0x00000001 /* RW--V */ +#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP 24:24 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP_DIS 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP_EN 0x00000001 /* RW--V */ +#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK 28:28 /* RWIVF */ +#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK_EN 0x00000000 /* RWI-V */ +#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK_DIS 0x00000001 /* RW--V */ + + +#define NV_PRAMDAC_GRCURSOR_START_POS 0x00680300 /* RW-4R */ +#define NV_PRAMDAC_GRCURSOR_START_POS_X 11:0 /* RWXSF */ +#define NV_PRAMDAC_GRCURSOR_START_POS_Y 27:16 /* RWXSF */ + +#define NV_PMC 0x00000FFF:0x00000000 /* RW--D */ +#define NV_PMC_INTR_0 0x00000100 /* RW-4R */ +#define NV_PMC_INTR_0_PAUDIO 0:0 /* R--VF */ +#define NV_PMC_INTR_0_PAUDIO_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PAUDIO_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PMEDIA 4:4 /* R--VF */ +#define NV_PMC_INTR_0_PMEDIA_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PMEDIA_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PFIFO 8:8 /* R--VF */ +#define NV_PMC_INTR_0_PFIFO_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PFIFO_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PGRAPH0 12:12 /* R--VF */ +#define NV_PMC_INTR_0_PGRAPH0_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PGRAPH0_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PGRAPH1 13:13 /* R--VF */ +#define NV_PMC_INTR_0_PGRAPH1_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PGRAPH1_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PVIDEO 16:16 /* R--VF */ +#define NV_PMC_INTR_0_PVIDEO_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PVIDEO_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PTIMER 20:20 /* R--VF */ +#define NV_PMC_INTR_0_PTIMER_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PTIMER_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PFB 24:24 /* R--VF */ +#define NV_PMC_INTR_0_PFB_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PFB_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_PBUS 28:28 /* R--VF */ +#define NV_PMC_INTR_0_PBUS_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PMC_INTR_0_PBUS_PENDING 0x00000001 /* R---V */ +#define NV_PMC_INTR_0_SOFTWARE 31:31 /* RWIVF */ +#define NV_PMC_INTR_0_SOFTWARE_NOT_PENDING 0x00000000 /* RWI-V */ +#define NV_PMC_INTR_0_SOFTWARE_PENDING 0x00000001 /* RW--V */ + +#define NV_PMC_INTR_EN_0 0x00000140 /* RW-4R */ +#define NV_PMC_INTR_EN_0_INTA 1:0 /* RWIVF */ +#define NV_PMC_INTR_EN_0_INTA_DISABLED 0x00000000 /* RWI-V */ +#define NV_PMC_INTR_EN_0_INTA_HARDWARE 0x00000001 /* RW--V */ +#define NV_PMC_INTR_EN_0_INTA_SOFTWARE 0x00000002 /* RW--V */ + +#define NV_PMC_ENABLE 0x00000200 /* RW-4R */ + +#define NV_PFIFO 0x00003FFF:0x00002000 /* RW--D */ +#define NV_PFIFO_INTR_0 0x00002100 /* RW-4R */ +#define NV_PFIFO_INTR_0_CACHE_ERROR 0:0 /* RWXVF */ +#define NV_PFIFO_INTR_0_CACHE_ERROR_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PFIFO_INTR_0_CACHE_ERROR_PENDING 0x00000001 /* R---V */ +#define NV_PFIFO_INTR_0_CACHE_ERROR_RESET 0x00000001 /* -W--V */ +#define NV_PFIFO_INTR_0_RUNOUT 4:4 /* RWXVF */ +#define NV_PFIFO_INTR_0_RUNOUT_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PFIFO_INTR_0_RUNOUT_PENDING 0x00000001 /* R---V */ +#define NV_PFIFO_INTR_0_RUNOUT_RESET 0x00000001 /* -W--V */ +#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW 8:8 /* RWXVF */ +#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_PENDING 0x00000001 /* R---V */ +#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_RESET 0x00000001 /* -W--V */ +#define NV_PFIFO_INTR_0_DMA_PUSHER 12:12 /* RWXVF */ +#define NV_PFIFO_INTR_0_DMA_PUSHER_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PFIFO_INTR_0_DMA_PUSHER_PENDING 0x00000001 /* R---V */ +#define NV_PFIFO_INTR_0_DMA_PUSHER_RESET 0x00000001 /* -W--V */ +#define NV_PFIFO_INTR_0_DMA_PTE 16:16 /* RWXVF */ +#define NV_PFIFO_INTR_0_DMA_PTE_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PFIFO_INTR_0_DMA_PTE_PENDING 0x00000001 /* R---V */ +#define NV_PFIFO_INTR_0_DMA_PTE_RESET 0x00000001 /* -W--V */ +#define NV_PFIFO_INTR_EN_0 0x00002140 /* RW-4R */ +#define NV_PFIFO_INTR_EN_0_CACHE_ERROR 0:0 /* RWIVF */ +#define NV_PFIFO_INTR_EN_0_CACHE_ERROR_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_INTR_EN_0_CACHE_ERROR_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_INTR_EN_0_RUNOUT 4:4 /* RWIVF */ +#define NV_PFIFO_INTR_EN_0_RUNOUT_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_INTR_EN_0_RUNOUT_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW 8:8 /* RWIVF */ +#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_CONFIG_0 0x00002200 /* RW-4R */ +#define NV_PFIFO_RAMHT 0x00002210 /* RW-4R */ +#define NV_PFIFO_RAMHT_BASE_ADDRESS 15:12 /* RWXVF */ +#define NV_PFIFO_RAMHT_SIZE 17:16 /* RWXVF */ +#define NV_PFIFO_RAMHT_SIZE_4K 0x00000000 /* RWI-V */ +#define NV_PFIFO_RAMHT_SIZE_8K 0x00000001 /* RW--V */ +#define NV_PFIFO_RAMHT_SIZE_16K 0x00000002 /* RW--V */ +#define NV_PFIFO_RAMHT_SIZE_32K 0x00000003 /* RW--V */ +#define NV_PFIFO_RAMFC 0x00002214 /* RW-4R */ +#define NV_PFIFO_RAMFC_BASE_ADDRESS 15:9 /* RWXVF */ +#define NV_PFIFO_RAMRO 0x00002218 /* RW-4R */ +#define NV_PFIFO_RAMRO_BASE_ADDRESS 15:9 /* RWXVF */ +#define NV_PFIFO_RAMRO_SIZE 16:16 /* RWXVF */ +#define NV_PFIFO_RAMRO_SIZE_512 0x00000000 /* RWI-V */ +#define NV_PFIFO_RAMRO_SIZE_8K 0x00000001 /* RW--V */ +#define NV_PFIFO_CACHES 0x00002500 /* RW-4R */ +#define NV_PFIFO_CACHES_REASSIGN 0:0 /* RWIVF */ +#define NV_PFIFO_CACHES_REASSIGN_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_CACHES_REASSIGN_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_CACHE0_PUSH0 0x00003000 /* RW-4R */ +#define NV_PFIFO_CACHE0_PUSH0_ACCESS 0:0 /* RWIVF */ +#define NV_PFIFO_CACHE0_PUSH0_ACCESS_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_CACHE0_PUSH0_ACCESS_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_CACHE1_PUSH0 0x00003200 /* RW-4R */ +#define NV_PFIFO_CACHE1_PUSH0_ACCESS 0:0 /* RWIVF */ +#define NV_PFIFO_CACHE1_PUSH0_ACCESS_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_CACHE1_PUSH0_ACCESS_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_CACHE0_PUSH1 0x00003004 /* RW-4R */ +#define NV_PFIFO_CACHE0_PUSH1_CHID 6:0 /* RWXUF */ +#define NV_PFIFO_CACHE1_PUSH1 0x00003204 /* RW-4R */ +#define NV_PFIFO_CACHE1_PUSH1_CHID 6:0 /* RWXUF */ +#define NV_PFIFO_CACHE1_DMA0 0x00003220 /* RW-4R */ +#define NV_PFIFO_CACHE1_DMA1 0x00003224 /* RW-4R */ +#define NV_PFIFO_CACHE1_DMA2 0x00003228 /* RW-4R */ +#define NV_PFIFO_CACHE0_PULL0 0x00003040 /* RW-4R */ +#define NV_PFIFO_CACHE0_PULL0_ACCESS 0:0 /* RWIVF */ +#define NV_PFIFO_CACHE0_PULL0_ACCESS_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_CACHE0_PULL0_ACCESS_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_CACHE1_PULL0 0x00003240 /* RW-4R */ +#define NV_PFIFO_CACHE1_PULL0_ACCESS 0:0 /* RWIVF */ +#define NV_PFIFO_CACHE1_PULL0_ACCESS_DISABLED 0x00000000 /* RWI-V */ +#define NV_PFIFO_CACHE1_PULL0_ACCESS_ENABLED 0x00000001 /* RW--V */ +#define NV_PFIFO_CACHE1_PULL1 0x00003250 /* RW-4R */ +#define NV_PFIFO_CACHE1_PULL1_CTX 4:4 /* RWXVF */ +#define NV_PFIFO_CACHE1_PULL1_CTX_CLEAN 0x00000000 /* RW--V */ +#define NV_PFIFO_CACHE1_PULL1_CTX_DIRTY 0x00000001 /* RW--V */ +#define NV_PFIFO_CACHE1_PUT 0x00003210 /* RW-4R */ +#define NV_PFIFO_CACHE1_PUT_ADDRESS 6:2 /* RWXUF */ +#define NV_PFIFO_CACHE1_GET 0x00003270 /* RW-4R */ +#define NV_PFIFO_CACHE1_GET_ADDRESS 6:2 /* RWXUF */ +#define NV_PFIFO_CACHE1_CTX(i) (0x00003280+(i)*16) /* RW-4A */ +#define NV_PFIFO_CACHE1_CTX__SIZE_1 8 /* */ +#define NV_PFIFO_RUNOUT_PUT 0x00002410 /* RW-4R */ +#define NV_PFIFO_RUNOUT_GET 0x00002420 /* RW-4R */ +#define NV_PFIFO_RUNOUT_STATUS 0x00002400 /* R--4R */ + +#define NV_PGRAPH 0x00401FFF:0x00400000 /* RW--D */ +#define NV_PGRAPH_DEBUG_0 0x00400080 /* RW-4R */ +#define NV_PGRAPH_DEBUG_0_STATE 0:0 /* CW-VF */ +#define NV_PGRAPH_DEBUG_0_STATE_NORMAL 0x00000000 /* CW--V */ +#define NV_PGRAPH_DEBUG_0_STATE_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_DEBUG_0_BULK_READS 4:4 /* RWIVF */ +#define NV_PGRAPH_DEBUG_0_BULK_READS_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_0_BULK_READS_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_0_WRITE_ONLY_ROPS_2D 20:20 /* RWIVF */ +#define NV_PGRAPH_DEBUG_0_WRITE_ONLY_ROPS_2D_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_0_WRITE_ONLY_ROPS_2D_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_0_DRAWDIR_AUTO 24:24 /* RWIVF */ +#define NV_PGRAPH_DEBUG_0_DRAWDIR_AUTO_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_0_DRAWDIR_AUTO_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_1 0x00400084 /* RW-4R */ +#define NV_PGRAPH_DEBUG_1_VOLATILE_RESET 0:0 /* RWIVF */ +#define NV_PGRAPH_DEBUG_1_VOLATILE_RESET_NOT_LAST 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_1_VOLATILE_RESET_LAST 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_1_INSTANCE 16:16 /* RWIVF */ +#define NV_PGRAPH_DEBUG_1_INSTANCE_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_1_INSTANCE_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_1_CTX 20:20 /* RWIVF */ +#define NV_PGRAPH_DEBUG_1_CTX_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_1_CTX_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_2 0x00400088 /* RW-4R */ +#define NV_PGRAPH_DEBUG_2_AVOID_RMW_BLEND 0:0 /* RWIVF */ +#define NV_PGRAPH_DEBUG_2_AVOID_RMW_BLEND_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_2_AVOID_RMW_BLEND_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_2_DPWR_FIFO 8:8 /* RWIVF */ +#define NV_PGRAPH_DEBUG_2_DPWR_FIFO_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_2_DPWR_FIFO_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_2_VOLATILE_RESET 28:28 /* RWIVF */ +#define NV_PGRAPH_DEBUG_2_VOLATILE_RESET_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_2_VOLATILE_RESET_ENABLED 0x00000001 /* RW--V */ +#define NV_PGRAPH_DEBUG_3 0x0040008C /* RW-4R */ +#define NV_PGRAPH_DEBUG_3_HONOR_ALPHA 24:24 /* RWIVF */ +#define NV_PGRAPH_DEBUG_3_HONOR_ALPHA_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_DEBUG_3_HONOR_ALPHA_ENABLED 0x00000001 /* RW--V */ + +#define NV_PGRAPH_INTR_0 0x00400100 /* RW-4R */ +#define NV_PGRAPH_INTR_0_RESERVED 0:0 /* RW-VF */ +#define NV_PGRAPH_INTR_0_RESERVED_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PGRAPH_INTR_0_RESERVED_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_RESERVED_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_0_CONTEXT_SWITCH 4:4 /* RWIVF */ +#define NV_PGRAPH_INTR_0_CONTEXT_SWITCH_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_0_CONTEXT_SWITCH_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_CONTEXT_SWITCH_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_0_VBLANK 8:8 /* RWIVF */ +#define NV_PGRAPH_INTR_0_VBLANK_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_0_VBLANK_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_VBLANK_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_0_RANGE 12:12 /* RWIVF */ +#define NV_PGRAPH_INTR_0_RANGE_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_0_RANGE_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_RANGE_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_0_METHOD_COUNT 16:16 /* RWIVF */ +#define NV_PGRAPH_INTR_0_METHOD_COUNT_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_0_METHOD_COUNT_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_METHOD_COUNT_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_0_FORMAT 20:20 /* RWIVF */ +#define NV_PGRAPH_INTR_0_FORMAT_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_0_FORMAT_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_FORMAT_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_0_COMPLEX_CLIP 24:24 /* RWIVF */ +#define NV_PGRAPH_INTR_0_COMPLEX_CLIP_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_0_COMPLEX_CLIP_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_COMPLEX_CLIP_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_0_NOTIFY 28:28 /* RWIVF */ +#define NV_PGRAPH_INTR_0_NOTIFY_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_0_NOTIFY_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_0_NOTIFY_RESET 0x00000001 /* -W--V */ + +#define NV_PGRAPH_INTR_1 0x00400104 /* RW-4R */ +#define NV_PGRAPH_INTR_1_METHOD 0:0 /* RWIVF */ +#define NV_PGRAPH_INTR_1_METHOD_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_1_METHOD_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_1_METHOD_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_1_DATA 4:4 /* RWIVF */ +#define NV_PGRAPH_INTR_1_DATA_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_1_DATA_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_1_DATA_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_1_DOUBLE_NOTIFY 12:12 /* RWIVF */ +#define NV_PGRAPH_INTR_1_DOUBLE_NOTIFY_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_1_DOUBLE_NOTIFY_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_1_DOUBLE_NOTIFY_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_INTR_1_CTXSW_NOTIFY 16:16 /* RWIVF */ +#define NV_PGRAPH_INTR_1_CTXSW_NOTIFY_NOT_PENDING 0x00000000 /* R-I-V */ +#define NV_PGRAPH_INTR_1_CTXSW_NOTIFY_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_INTR_1_CTXSW_NOTIFY_RESET 0x00000001 /* -W--V */ + +#define NV_PGRAPH_INTR_EN_0 0x00400140 /* RW-4R */ + +#define NV_PGRAPH_INTR_EN_1 0x00400144 /* RW-4R */ + +#define NV_PGRAPH_CTX_CACHE(i) (0x004001a0+(i)*4) /* RW-4A */ +#define NV_PGRAPH_CTX_CACHE__SIZE_1 8 /* */ + +#define NV_PGRAPH_CTX_SWITCH 0x00400180 /* RW-4R */ + +#define NV_PGRAPH_CTX_CONTROL 0x00400190 /* RW-4R */ +#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME 1:0 /* RWIVF */ +#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_33US 0x00000000 /* RWI-V */ +#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_262US 0x00000001 /* RW--V */ +#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_2MS 0x00000002 /* RW--V */ +#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_17MS 0x00000003 /* RW--V */ +#define NV_PGRAPH_CTX_CONTROL_TIME 8:8 /* RWIVF */ +#define NV_PGRAPH_CTX_CONTROL_TIME_EXPIRED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_CTX_CONTROL_TIME_NOT_EXPIRED 0x00000001 /* RW--V */ +#define NV_PGRAPH_CTX_CONTROL_CHID 16:16 /* RWIVF */ +#define NV_PGRAPH_CTX_CONTROL_CHID_INVALID 0x00000000 /* RWI-V */ +#define NV_PGRAPH_CTX_CONTROL_CHID_VALID 0x00000001 /* RW--V */ +#define NV_PGRAPH_CTX_CONTROL_SWITCH 20:20 /* R--VF */ +#define NV_PGRAPH_CTX_CONTROL_SWITCH_UNAVAILABLE 0x00000000 /* R---V */ +#define NV_PGRAPH_CTX_CONTROL_SWITCH_AVAILABLE 0x00000001 /* R---V */ +#define NV_PGRAPH_CTX_CONTROL_SWITCHING 24:24 /* RWIVF */ +#define NV_PGRAPH_CTX_CONTROL_SWITCHING_IDLE 0x00000000 /* RWI-V */ +#define NV_PGRAPH_CTX_CONTROL_SWITCHING_BUSY 0x00000001 /* RW--V */ +#define NV_PGRAPH_CTX_CONTROL_DEVICE 28:28 /* RWIVF */ +#define NV_PGRAPH_CTX_CONTROL_DEVICE_DISABLED 0x00000000 /* RWI-V */ +#define NV_PGRAPH_CTX_CONTROL_DEVICE_ENABLED 0x00000001 /* RW--V */ + +#define NV_PGRAPH_CTX_USER 0x00400194 /* RW-4R */ + +#define NV_PGRAPH_FIFO 0x004006A4 /* RW-4R */ +#define NV_PGRAPH_FIFO_ACCESS 0:0 /* RWIVF */ +#define NV_PGRAPH_FIFO_ACCESS_DISABLED 0x00000000 /* RW--V */ +#define NV_PGRAPH_FIFO_ACCESS_ENABLED 0x00000001 /* RWI-V */ + +#define NV_PGRAPH_STATUS 0x004006B0 /* R--4R */ + +#define NV_PGRAPH_CLIP_MISC 0x004006A0 /* RW-4R */ +#define NV_PGRAPH_SRC_CANVAS_MIN 0x00400550 /* RW-4R */ +#define NV_PGRAPH_DST_CANVAS_MIN 0x00400558 /* RW-4R */ +#define NV_PGRAPH_SRC_CANVAS_MAX 0x00400554 /* RW-4R */ +#define NV_PGRAPH_DST_CANVAS_MAX 0x0040055C /* RW-4R */ +#define NV_PGRAPH_CLIP0_MIN 0x00400690 /* RW-4R */ +#define NV_PGRAPH_CLIP1_MIN 0x00400698 /* RW-4R */ +#define NV_PGRAPH_CLIP0_MAX 0x00400694 /* RW-4R */ +#define NV_PGRAPH_CLIP1_MAX 0x0040069C /* RW-4R */ +#define NV_PGRAPH_DMA 0x00400680 /* RW-4R */ +#define NV_PGRAPH_NOTIFY 0x00400684 /* RW-4R */ +#define NV_PGRAPH_INSTANCE 0x00400688 /* RW-4R */ +#define NV_PGRAPH_MEMFMT 0x0040068C /* RW-4R */ +#define NV_PGRAPH_BOFFSET0 0x00400630 /* RW-4R */ +#define NV_PGRAPH_BOFFSET1 0x00400634 /* RW-4R */ +#define NV_PGRAPH_BOFFSET2 0x00400638 /* RW-4R */ +#define NV_PGRAPH_BOFFSET3 0x0040063C /* RW-4R */ +#define NV_PGRAPH_BPITCH0 0x00400650 /* RW-4R */ +#define NV_PGRAPH_BPITCH1 0x00400654 /* RW-4R */ +#define NV_PGRAPH_BPITCH2 0x00400658 /* RW-4R */ +#define NV_PGRAPH_BPITCH3 0x0040065C /* RW-4R */ + +#define NV_PGRAPH_BPIXEL 0x004006a8 /* RW-4R */ +#define NV_PGRAPH_BPIXEL_DEPTH0_FMT 1:0 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH0_FMT_Y16_BITS 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH0_FMT_BITS_8 0x00000001 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH0_FMT_BITS_16 0x00000002 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH0_FMT_BITS_32 0x00000003 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH0 2:2 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH0_NOT_VALID 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH0_VALID 0x00000001 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH1_FMT 5:4 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH1_FMT_Y16_BITS 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH1_FMT_BITS_8 0x00000001 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH1_FMT_BITS_16 0x00000002 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH1_FMT_BITS_32 0x00000003 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH1 6:6 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH1_NOT_VALID 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH1_VALID 0x00000001 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH2_FMT 9:8 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH2_FMT_Y16_BITS 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH2_FMT_BITS_8 0x00000001 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH2_FMT_BITS_16 0x00000002 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH2_FMT_BITS_32 0x00000003 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH2 10:10 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH2_NOT_VALID 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH2_VALID 0x00000001 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH3_FMT 13:12 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH3_FMT_Y16_BITS 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH3_FMT_BITS_8 0x00000001 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH3_FMT_BITS_16 0x00000002 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH3_FMT_BITS_32 0x00000003 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH3 14:14 /* RWXVF */ +#define NV_PGRAPH_BPIXEL_DEPTH3_NOT_VALID 0x00000000 /* RW--V */ +#define NV_PGRAPH_BPIXEL_DEPTH3_VALID 0x00000001 /* RW--V */ + +#define NV_PGRAPH_PATT_COLOR0_0 0x00400600 /* RW-4R */ +#define NV_PGRAPH_PATT_COLOR0_1 0x00400604 /* RW-4R */ +#define NV_PGRAPH_PATT_COLOR1_0 0x00400608 /* RW-4R */ +#define NV_PGRAPH_PATT_COLOR1_1 0x0040060C /* RW-4R */ +#define NV_PGRAPH_PATTERN(i) (0x00400610+(i)*4) /* RW-4A */ +#define NV_PGRAPH_PATTERN_SHAPE 0x00400618 /* RW-4R */ +#define NV_PGRAPH_PATTERN_SHAPE_VALUE 1:0 /* RWXVF */ +#define NV_PGRAPH_PATTERN_SHAPE_VALUE_8X8 0x00000000 /* RW--V */ +#define NV_PGRAPH_PATTERN_SHAPE_VALUE_64X1 0x00000001 /* RW--V */ +#define NV_PGRAPH_PATTERN_SHAPE_VALUE_1X64 0x00000002 /* RW--V */ +#define NV_PGRAPH_MONO_COLOR0 0x0040061C /* RW-4R */ +#define NV_PGRAPH_ROP3 0x00400624 /* RW-4R */ +#define NV_PGRAPH_PLANE_MASK 0x00400628 /* RW-4R */ +#define NV_PGRAPH_CHROMA 0x0040062C /* RW-4R */ +#define NV_PGRAPH_BETA 0x00400640 /* RW-4R */ +#define NV_PGRAPH_CONTROL_OUT 0x00400644 /* RW-4R */ +#define NV_PGRAPH_ABS_X_RAM(i) (0x00400400+(i)*4) /* RW-4A */ +#define NV_PGRAPH_ABS_X_RAM__SIZE_1 32 /* */ +#define NV_PGRAPH_ABS_Y_RAM(i) (0x00400480+(i)*4) /* RW-4A */ +#define NV_PGRAPH_ABS_Y_RAM__SIZE_1 32 /* */ + +#define NV_PGRAPH_XY_LOGIC_MISC0 0x00400514 /* RW-4R */ +#define NV_PGRAPH_XY_LOGIC_MISC1 0x00400518 /* RW-4R */ +#define NV_PGRAPH_XY_LOGIC_MISC2 0x0040051C /* RW-4R */ +#define NV_PGRAPH_XY_LOGIC_MISC1_DVDY_VALUE 0x00000000 /* RWI-V */ +#define NV_PGRAPH_XY_LOGIC_MISC3 0x00400520 /* RW-4R */ +#define NV_PGRAPH_X_MISC 0x00400500 /* RW-4R */ +#define NV_PGRAPH_Y_MISC 0x00400504 /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIP_XMIN 0x0040053C /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIP_XMAX 0x00400544 /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIP_YMIN 0x00400540 /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIP_YMAX 0x00400548 /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 /* RW-4R */ +#define NV_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C /* RW-4R */ +#define NV_PGRAPH_SOURCE_COLOR 0x0040050C /* RW-4R */ +#define NV_PGRAPH_EXCEPTIONS 0x00400508 /* RW-4R */ +#define NV_PGRAPH_ABS_ICLIP_XMAX 0x00400534 /* RW-4R */ +#define NV_PGRAPH_ABS_ICLIP_YMAX 0x00400538 /* RW-4R */ +#define NV_PGRAPH_CLIPX_0 0x00400524 /* RW-4R */ +#define NV_PGRAPH_CLIPX_1 0x00400528 /* RW-4R */ +#define NV_PGRAPH_CLIPY_0 0x0040052c /* RW-4R */ +#define NV_PGRAPH_CLIPY_1 0x00400530 /* RW-4R */ +#define NV_PGRAPH_DMA_INTR_0 0x00401100 /* RW-4R */ +#define NV_PGRAPH_DMA_INTR_0_INSTANCE 0:0 /* RWXVF */ +#define NV_PGRAPH_DMA_INTR_0_INSTANCE_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_INSTANCE_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_INSTANCE_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_DMA_INTR_0_PRESENT 4:4 /* RWXVF */ +#define NV_PGRAPH_DMA_INTR_0_PRESENT_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_PRESENT_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_PRESENT_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_DMA_INTR_0_PROTECTION 8:8 /* RWXVF */ +#define NV_PGRAPH_DMA_INTR_0_PROTECTION_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_PROTECTION_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_PROTECTION_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_DMA_INTR_0_LINEAR 12:12 /* RWXVF */ +#define NV_PGRAPH_DMA_INTR_0_LINEAR_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_LINEAR_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_LINEAR_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_DMA_INTR_0_NOTIFY 16:16 /* RWXVF */ +#define NV_PGRAPH_DMA_INTR_0_NOTIFY_NOT_PENDING 0x00000000 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_NOTIFY_PENDING 0x00000001 /* R---V */ +#define NV_PGRAPH_DMA_INTR_0_NOTIFY_RESET 0x00000001 /* -W--V */ +#define NV_PGRAPH_DMA_INTR_EN_0 0x00401140 /* RW-4R */ +#define NV_PGRAPH_DMA_CONTROL 0x00401210 /* RW-4R */ + +#define NV_PFB 0x00100FFF:0x00100000 /* RW--D */ +#define NV_PFB_BOOT_0 0x00100000 /* RW-4R */ +#define NV_PFB_BOOT_0_RAM_AMOUNT 1:0 /* RWIVF */ +#define NV_PFB_BOOT_0_RAM_AMOUNT_1MB 0x00000000 /* RW--V */ +#define NV_PFB_BOOT_0_RAM_AMOUNT_2MB 0x00000001 /* RW--V */ +#define NV_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000002 /* RW--V */ + +#define NV_PFB_CONFIG_0 0x00100200 /* RW-4R */ +#define NV_PFB_CONFIG_0_RESOLUTION 5:0 /* RWIVF */ +#define NV_PFB_CONFIG_0_RESOLUTION_320_PIXELS 0x0000000a /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_400_PIXELS 0x0000000d /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_480_PIXELS 0x0000000f /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_512_PIXELS 0x00000010 /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_640_PIXELS 0x00000014 /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_800_PIXELS 0x00000019 /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_960_PIXELS 0x0000001e /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_1024_PIXELS 0x00000020 /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_1152_PIXELS 0x00000024 /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_1280_PIXELS 0x00000028 /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_1600_PIXELS 0x00000032 /* RW--V */ +#define NV_PFB_CONFIG_0_RESOLUTION_DEFAULT 0x00000014 /* RWI-V */ +#define NV_PFB_CONFIG_0_PIXEL_DEPTH 9:8 /* RWIVF */ +#define NV_PFB_CONFIG_0_PIXEL_DEPTH_8_BITS 0x00000001 /* RW--V */ +#define NV_PFB_CONFIG_0_PIXEL_DEPTH_16_BITS 0x00000002 /* RW--V */ +#define NV_PFB_CONFIG_0_PIXEL_DEPTH_32_BITS 0x00000003 /* RW--V */ +#define NV_PFB_CONFIG_0_PIXEL_DEPTH_DEFAULT 0x00000001 /* RWI-V */ +#define NV_PFB_CONFIG_0_TILING 12:12 /* RWIVF */ +#define NV_PFB_CONFIG_0_TILING_ENABLED 0x00000000 /* RW--V */ +#define NV_PFB_CONFIG_0_TILING_DISABLED 0x00000001 /* RWI-V */ + +#define NV_PFB_BOOT_10 0x0010020C /* RW-4R */ + + +#define NV_PRAMIN 0x00FFFFFF:0x00C00000 +#define NV_PNVM 0x00BFFFFF:0x00800000 +#define NV_CHAN0 0x0080ffff:0x00800000 + +#define NV_UROP 0x00421FFF:0x00420000 /* -W--D */ +#define NV_UCHROMA 0x00431FFF:0x00430000 /* -W--D */ +#define NV_UPLANE 0x00441FFF:0x00440000 /* -W--D */ +#define NV_UCLIP 0x00451FFF:0x00450000 /* -W--D */ +#define NV_UPATT 0x00461FFF:0x00460000 /* -W--D */ +#define NV_ULINE 0x00491FFF:0x00490000 /* -W--D */ +#define NV_ULIN 0x004A1FFF:0x004A0000 /* -W--D */ +#define NV_UTRI 0x004B1FFF:0x004B0000 /* -W--D */ +#define NV_URECT 0x00471FFF:0x00470000 /* -W--D */ +#define NV_UBLIT 0x00501FFF:0x00500000 /* -W--D */ +#define NV_UBITMAP 0x00521FFF:0x00520000 /* -W--D */ + +#define NV_PVGA0 0x000C0000 +#define NV_PVGA1 0x00601000 +#define NV_PVGA2 0x00681000 + +#endif diff --git a/src/drivers/nvreg.h b/src/drivers/nvreg.h new file mode 100644 index 0000000..d60de12 --- /dev/null +++ b/src/drivers/nvreg.h @@ -0,0 +1,176 @@ +/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/nvreg.h,v 3.2.2.1 1998/01/18 10:35:36 hohndel Exp $ */ + +#ifndef __NVREG_H_ +#define __NVREG_H_ + +/* Little macro to construct bitmask for contiguous ranges of bits */ +#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b)) +#define MASKEXPAND(mask) BITMASK(1?mask,0?mask) + +/* Macro to set specific bitfields (mask has to be a macro x:y) ! */ +#define SetBF(mask,value) ((value) << (0?mask)) +#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) ) + +#define MaskAndSetBF(var,mask,value) (var)=(((var)&(~MASKEXPAND(mask)) \ + | SetBF(mask,value))) + +#define DEVICE_BASE(device) (0?NV##_##device) +#define DEVICE_SIZE(device) ((1?NV##_##device) - DEVICE_BASE(device)+1) + +/* This is where we will have to have conditional compilation */ +#define DEVICE_ACCESS(device,reg) \ + nv##device##Port[((NV_##device##_##reg)-DEVICE_BASE(device))/4] + +#define DEVICE_WRITE(device,reg,value) DEVICE_ACCESS(device,reg)=(value) +#define DEVICE_READ(device,reg) DEVICE_ACCESS(device,reg) +#define DEVICE_PRINT(device,reg) \ + ErrorF("NV_"#device"_"#reg"=#%08lx\n",DEVICE_ACCESS(device,reg)) +#define DEVICE_DEF(device,mask,value) \ + SetBF(NV_##device##_##mask,NV_##device##_##mask##_##value) +#define DEVICE_VALUE(device,mask,value) SetBF(NV_##device##_##mask,value) +#define DEVICE_MASK(device,mask) MASKEXPAND(NV_##device##_##mask) + +#define PDAC_Write(reg,value) DEVICE_WRITE(PDAC,reg,value) +#define PDAC_Read(reg) DEVICE_READ(PDAC,reg) +#define PDAC_Print(reg) DEVICE_PRINT(PDAC,reg) +#define PDAC_Def(mask,value) DEVICE_DEF(PDAC,mask,value) +#define PDAC_Val(mask,value) DEVICE_VALUE(PDAC,mask,value) +#define PDAC_Mask(mask) DEVICE_MASK(PDAC,mask) + +#define PFB_Write(reg,value) DEVICE_WRITE(PFB,reg,value) +#define PFB_Read(reg) DEVICE_READ(PFB,reg) +#define PFB_Print(reg) DEVICE_PRINT(PFB,reg) +#define PFB_Def(mask,value) DEVICE_DEF(PFB,mask,value) +#define PFB_Val(mask,value) DEVICE_VALUE(PFB,mask,value) +#define PFB_Mask(mask) DEVICE_MASK(PFB,mask) + +#define PRM_Write(reg,value) DEVICE_WRITE(PRM,reg,value) +#define PRM_Read(reg) DEVICE_READ(PRM,reg) +#define PRM_Print(reg) DEVICE_PRINT(PRM,reg) +#define PRM_Def(mask,value) DEVICE_DEF(PRM,mask,value) +#define PRM_Val(mask,value) DEVICE_VALUE(PRM,mask,value) +#define PRM_Mask(mask) DEVICE_MASK(PRM,mask) + +#define PGRAPH_Write(reg,value) DEVICE_WRITE(PGRAPH,reg,value) +#define PGRAPH_Read(reg) DEVICE_READ(PGRAPH,reg) +#define PGRAPH_Print(reg) DEVICE_PRINT(PGRAPH,reg) +#define PGRAPH_Def(mask,value) DEVICE_DEF(PGRAPH,mask,value) +#define PGRAPH_Val(mask,value) DEVICE_VALUE(PGRAPH,mask,value) +#define PGRAPH_Mask(mask) DEVICE_MASK(PGRAPH,mask) + +#define PDMA_Write(reg,value) DEVICE_WRITE(PDMA,reg,value) +#define PDMA_Read(reg) DEVICE_READ(PDMA,reg) +#define PDMA_Print(reg) DEVICE_PRINT(PDMA,reg) +#define PDMA_Def(mask,value) DEVICE_DEF(PDMA,mask,value) +#define PDMA_Val(mask,value) DEVICE_VALUE(PDMA,mask,value) +#define PDMA_Mask(mask) DEVICE_MASK(PDMA,mask) + +#define PFIFO_Write(reg,value) DEVICE_WRITE(PFIFO,reg,value) +#define PFIFO_Read(reg) DEVICE_READ(PFIFO,reg) +#define PFIFO_Print(reg) DEVICE_PRINT(PFIFO,reg) +#define PFIFO_Def(mask,value) DEVICE_DEF(PFIFO,mask,value) +#define PFIFO_Val(mask,value) DEVICE_VALUE(PFIFO,mask,value) +#define PFIFO_Mask(mask) DEVICE_MASK(PFIFO,mask) + +#define PRAM_Write(reg,value) DEVICE_WRITE(PRAM,reg,value) +#define PRAM_Read(reg) DEVICE_READ(PRAM,reg) +#define PRAM_Print(reg) DEVICE_PRINT(PRAM,reg) +#define PRAM_Def(mask,value) DEVICE_DEF(PRAM,mask,value) +#define PRAM_Val(mask,value) DEVICE_VALUE(PRAM,mask,value) +#define PRAM_Mask(mask) DEVICE_MASK(PRAM,mask) + +#define PRAMFC_Write(reg,value) DEVICE_WRITE(PRAMFC,reg,value) +#define PRAMFC_Read(reg) DEVICE_READ(PRAMFC,reg) +#define PRAMFC_Print(reg) DEVICE_PRINT(PRAMFC,reg) +#define PRAMFC_Def(mask,value) DEVICE_DEF(PRAMFC,mask,value) +#define PRAMFC_Val(mask,value) DEVICE_VALUE(PRAMFC,mask,value) +#define PRAMFC_Mask(mask) DEVICE_MASK(PRAMFC,mask) + +#define PMC_Write(reg,value) DEVICE_WRITE(PMC,reg,value) +#define PMC_Read(reg) DEVICE_READ(PMC,reg) +#define PMC_Print(reg) DEVICE_PRINT(PMC,reg) +#define PMC_Def(mask,value) DEVICE_DEF(PMC,mask,value) +#define PMC_Val(mask,value) DEVICE_VALUE(PMC,mask,value) +#define PMC_Mask(mask) DEVICE_MASK(PMC,mask) + +#define PMC_Write(reg,value) DEVICE_WRITE(PMC,reg,value) +#define PMC_Read(reg) DEVICE_READ(PMC,reg) +#define PMC_Print(reg) DEVICE_PRINT(PMC,reg) +#define PMC_Def(mask,value) DEVICE_DEF(PMC,mask,value) +#define PMC_Val(mask,value) DEVICE_VALUE(PMC,mask,value) +#define PMC_Mask(mask) DEVICE_MASK(PMC,mask) + + +#define PBUS_Write(reg,value) DEVICE_WRITE(PBUS,reg,value) +#define PBUS_Read(reg) DEVICE_READ(PBUS,reg) +#define PBUS_Print(reg) DEVICE_PRINT(PBUS,reg) +#define PBUS_Def(mask,value) DEVICE_DEF(PBUS,mask,value) +#define PBUS_Val(mask,value) DEVICE_VALUE(PBUS,mask,value) +#define PBUS_Mask(mask) DEVICE_MASK(PBUS,mask) + + +#define PRAMDAC_Write(reg,value) DEVICE_WRITE(PRAMDAC,reg,value) +#define PRAMDAC_Read(reg) DEVICE_READ(PRAMDAC,reg) +#define PRAMDAC_Print(reg) DEVICE_PRINT(PRAMDAC,reg) +#define PRAMDAC_Def(mask,value) DEVICE_DEF(PRAMDAC,mask,value) +#define PRAMDAC_Val(mask,value) DEVICE_VALUE(PRAMDAC,mask,value) +#define PRAMDAC_Mask(mask) DEVICE_MASK(PRAMDAC,mask) + +#define PDAC_ReadExt(reg) \ + ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\ + (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\ + (PDAC_Read(INDEX_DATA))) + +#define PDAC_WriteExt(reg,value)\ + ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\ + (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\ + (PDAC_Write(INDEX_DATA,(value)))) + +#define CRTC_Write(index,value) port_out_r(CRT_IC,(index));port_out_r(CRT_DC,value) +#define CRTC_Read(index) (port_out_r(CRT_IC,index),port_in(CRT_DC)) + +#define PCRTC_Write(index,value) __svgalib_outcrtc(NV_PCRTC_##index,value) +#define PCRTC_Read(index) __svgalib_incrtc(NV_PCRTC_##index) + +#define PCRTC_Def(mask,value) DEVICE_DEF(PCRTC,mask,value) +#define PCRTC_Val(mask,value) DEVICE_VALUE(PCRTC,mask,value) +#define PCRTC_Mask(mask) DEVICE_MASK(PCRTC,mask) + +#define SR_Write(index,value) port_out_r(SEQ_I,(index));port_out_r(SEQ_D,value) +#define SR_Read(index) (port_out_r(SEQ_I,index),port_in(SEQ_D)) + +#define PEXTDEV_Read(reg) DEVICE_READ(PEXTDEV,reg) + +/* These are the variables which actually point at the register blocks */ + +/*typedef enum {NV1,NV3,NumNVChips} NVChipType; + +NVChipType GetChipType(void); +*/ + +#endif + + diff --git a/src/drivers/oak.c b/src/drivers/oak.c new file mode 100644 index 0000000..570a73d --- /dev/null +++ b/src/drivers/oak.c @@ -0,0 +1,768 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen + + This library is free software; you can redistribute it and/or + modify it without any restrictions. This library is distributed + in the hope that it will be useful, but without any warranty. + + Multi-chipset support Copyright 1993 Harm Hanemaayer + partially copyrighted (C) 1993 by Hartmut Schirmer + + OTI-067/077/087 support driver release 1.2 (12 September 1994) + Rewritten/fleshed out by Christopher Wiles (a0017097@wsuaix.csc.wsu.edu) + + Features in this release: + * _real_ 640x480x256 mode + * 800x600x16, 800x600x256 modes + * 1024x768x16, 1024x768x256 modes + * 640x480x32K, 800x600x32K modes + * 1280x1024x16 mode (untested) + * OTI-087 chipset support, including 2M variants + + + Still left to do: + * linear addressing + The stubs are in the code, and can be activated by setting + OTI87_LINEAR_OK to 1 (I've set it to 0). The '87 goes into and out + of linear mode just fine; I'm having a hell of a time getting SVGALIB + to use the linear buffer instead of the bank switched buffer at A0000. + In any event, if someone feels adventurous, the bones are present. + + * 64K/16M modes + 64K/16M modes appear to be broken. I couldn't even switch them in + from Oak's own DOS test utility ... + + * 1280x1024 modes + I've included a definition for the 16 color mode. I couldn't test + it, as my monitor's maximum resolution is 1024x768. According to + the documentation, a 2 meg board should be able to do an interlaced + 1280x1024x256. I couldn't force Oak's BIOS to enter that mode. + Could be because I have only 1 meg on board. + */ + +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include +#include "regs/oak.regs" + +#define OTI_MISC_DATA EXT+01 +#define OTI_BCOMPAT_DATA EXT+02 +#define OTI_SEGMENT_DATA EXT+03 +#define OTI_CONFIG_DATA EXT+04 +#define OTI_OVERFLOW_DATA EXT+05 +#define OTI_HSYNC2_DATA EXT+06 +#define OTI_OVERFLOW2_DATA EXT+07 + +#define CLOCK_DATA EXT + 08 +#define OVERFLOW_DATA EXT + 09 +#define OTI87_HSYNC2_DATA EXT+10 +#define OTI87_XCRTC_DATA EXT+11 +#define OTI87_COLORS_DATA EXT+12 +#define OTI87_FIFO_DATA EXT+13 +#define OTI87_MODESELECT_DATA EXT+14 +#define OTI87_FEATURE_DATA EXT+15 +#define OTI87_XREADSEGMENT_DATA EXT+16 +#define OTI87_XWRITESEGMENT_DATA EXT+17 +#define OTI87_RAMDAC_DATA EXT+18 + +#define OTI_INDEX 0x3DE /* Oak extended index register */ +#define OTI_R_W 0x3DF /* Oak extended r/w register */ +#define OTI_CRT_CNTL 0xC /* Oak CRT COntrol Register */ +#define OTI_MISC 0xD /* Oak Misc register */ +#define OTI_BCOMPAT 0xE /* Oak Back compat register */ +#define OTI_SEGMENT 0x11 /* Oak segment register */ +#define OTI_CONFIG 0x12 /* Oak config register */ +#define OTI_OVERFLOW 0x14 /* Oak overflow register */ +#define OTI_OVERFLOW2 0x16 /* Oak overflow2 register */ + +#define OTI87_PRODUCT 0x00 /* Oak product register */ +#define OTI87_STATUS 0x02 /* Oak status register */ +#define OTI87_VIDMAP 0x05 /* Oak video memory register */ +#define OTI87_CLOCK 0x06 /* Oak clock select register */ +#define OTI87_OVERFLOW 0x14 /* Oak overflow register */ +#define OTI87_HSYNC2 0x15 /* Oak hsynch/2 register */ +#define OTI87_XCRTC 0x17 /* Oak extended CRTC register */ +#define OTI87_COLORS 0x19 /* Oak color range register */ +#define OTI87_FIFO 0x20 /* Oak FIFO depth register */ +#define OTI87_MODESELECT 0x21 /* Oak mode select register */ +#define OTI87_FEATURE 0x22 /* Oak feature select register */ +#define OTI87_XREADSEGMENT 0x23 /* Oak extended read segment reg. */ +#define OTI87_XWRITESEGMENT 0x24 /* Oak extended write seg. reg. */ +#define OTI87_XCOMMONSEGMENT 0x25 /* Oak extended common register */ + +#define OTI87_OK_LINEAR 0 /* Set to 1 for linear addressing */ +#define DAC_SC11487 0x3c6 /* Sierra DAC command register */ +#define DAC_REVERT 0x3c8 /* Clears DAC from command mode */ + +static int oak_chiptype; +static int oak_memory; +static int oak_lockreg_save; +static unsigned char last_page = 0; +static unsigned char *VGAMemory_Save; + +static int oak_init(int, int, int); +static int oak_interlaced(int mode); +static int oak_memorydetect(void); +static int oak_chipdetect(void); +static int oak_inlinearmode(void); +static int OAKGetByte(int); + +static void oak_unlock(void); +static void oak_setlinearmode(void); +static void oak_clearlinearmode(void); +static void oak_setpage(int page); +static void OAK_WriteDAC(int function); +static void OAKSetByte(int, int); +static void * linearframebuffer; + +/* Mode table */ + +static ModeTable oak_modes[] = +{ +/* *INDENT-OFF* */ + OneModeEntry(640x480x256), + OneModeEntry(640x480x32K), + OneModeEntry(800x600x16), + OneModeEntry(1024x768x16), + OneModeEntry(800x600x256), + OneModeEntry(800x600x32K), + OneModeEntry(1024x768x256), + OneModeEntry(1280x1024x16), + END_OF_MODE_TABLE +/* *INDENT-ON* */ + + + + + + + + + + + + + +}; + +/* oak_getmodeinfo( int mode, vga_modeinfo *modeinfo) Tell SVGALIB stuff + + * Return mode information (blityes/no, start address, interlace, linear + */ + +static void oak_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + if (modeinfo->bytesperpixel > 0) { + modeinfo->maxpixels = oak_memory * 1024 / modeinfo->bytesperpixel; + } else { + modeinfo->maxpixels = oak_memory * 1024; /* any val */ + } + + modeinfo->maxlogicalwidth = 2040; + modeinfo->startaddressrange = 0xfffff; + modeinfo->haveblit = 0; + modeinfo->flags |= HAVE_RWPAGE; + + if (oak_interlaced(mode)) { + modeinfo->flags |= IS_INTERLACED; + } + if ((oak_chiptype == 87) & (OTI87_OK_LINEAR == 1)) { + modeinfo->flags |= CAPABLE_LINEAR; + modeinfo->flags |= EXT_INFO_AVAILABLE; + modeinfo->chiptype = 87; + modeinfo->aperture_size = oak_memorydetect(); + modeinfo->set_aperture_page = oak_setpage; + if (oak_inlinearmode()) { + modeinfo->linear_aperture = linearframebuffer; + } + } +} + +/* oak_saveregs( unsigned char regs[] ) Save extended regs + + * Save extended registers into regs[]. + * OTI-067/077 have eight registers + * OTI-087 has nineteen registers (only 11 used for native mode) + * + */ + +static int oak_saveregs(unsigned char regs[]) +{ + oak_unlock(); + regs[OTI_SEGMENT_DATA] = OAKGetByte(OTI_SEGMENT); + regs[OTI_MISC_DATA] = OAKGetByte(OTI_MISC); + regs[OTI_BCOMPAT_DATA] = OAKGetByte(OTI_BCOMPAT); + regs[OTI_CONFIG_DATA] = OAKGetByte(OTI_CONFIG); + regs[OTI_OVERFLOW_DATA] = OAKGetByte(OTI_OVERFLOW); + regs[OTI_HSYNC2_DATA] = OAKGetByte(OTI87_HSYNC2); + regs[OTI_OVERFLOW2_DATA] = OAKGetByte(OTI_OVERFLOW2); + if (oak_chiptype == 87) { + regs[EXT + 8] = OAKGetByte(OTI87_CLOCK); + regs[EXT + 9] = OAKGetByte(OTI87_OVERFLOW); + regs[OTI87_HSYNC2_DATA] = OAKGetByte(OTI87_HSYNC2); + regs[OTI87_XCRTC_DATA] = OAKGetByte(OTI87_XCRTC); + regs[OTI87_COLORS_DATA] = OAKGetByte(OTI87_COLORS); + regs[OTI87_FIFO_DATA] = OAKGetByte(OTI87_FIFO_DATA); + regs[OTI87_MODESELECT_DATA] = OAKGetByte(OTI87_MODESELECT); + regs[OTI87_FEATURE_DATA] = OAKGetByte(OTI87_FEATURE_DATA); + regs[OTI87_XREADSEGMENT_DATA] = OAKGetByte(OTI87_XREADSEGMENT); + regs[OTI87_XWRITESEGMENT_DATA] = OAKGetByte(OTI87_XWRITESEGMENT); + } + return 19; /*19 additional registers */ +} + +/* oak_setregs( const unsigned char regs[], int mode ) Set Oak registers + + * Set extended registers for specified graphics mode + * regs [EXT+1] through [EXT+7] used for OTI-067/77 + * regs [EXT+9] through [EXT+17] used for OTI-087 native mode + */ + +static void oak_setregs(const unsigned char regs[], int mode) +{ + int junk; + + oak_unlock(); + if (oak_chiptype == 87) { + OAKSetByte(OTI87_XREADSEGMENT, regs[OTI87_XREADSEGMENT_DATA]); + OAKSetByte(OTI87_XWRITESEGMENT, regs[OTI87_XWRITESEGMENT_DATA]); + + port_out_r(SEQ_I, 0); /* reset sync. */ + junk = port_in(SEQ_D); + port_outw_r(SEQ_I, 0x00 + ((junk & 0xfd) << 8)); + + OAKSetByte(OTI87_CLOCK, regs[EXT + 8]); + OAKSetByte(OTI87_FIFO, regs[OTI87_FIFO_DATA]); + OAKSetByte(OTI87_MODESELECT, regs[OTI87_MODESELECT_DATA]); + + port_outw_r(SEQ_I, 0x00 + (junk << 8)); /* set sync. */ + + OAKSetByte(OTI87_XCRTC, regs[OTI87_XCRTC_DATA]); + OAKSetByte(OTI87_OVERFLOW, regs[EXT + 9]); + OAKSetByte(OTI87_HSYNC2, regs[OTI87_HSYNC2_DATA]); + OAK_WriteDAC(regs[OTI87_RAMDAC_DATA]); + } else { + OAKSetByte(OTI_SEGMENT, regs[OTI_SEGMENT_DATA]); + + /* doc says don't OTI-MISC unless sync. reset is off */ + port_out_r(SEQ_I, 0); + junk = port_in(SEQ_D); + port_outw_r(SEQ_I, 0x00 + ((junk & 0xFD) << 8)); /* now disable the timing sequencer */ + + OAKSetByte(OTI_MISC, regs[OTI_MISC_DATA]); + + /* put sequencer back */ + port_outw_r(SEQ_I, 0x00 + (junk << 8)); + + OAKSetByte(OTI_BCOMPAT, regs[OTI_BCOMPAT_DATA]); + OAKSetByte(OTI_CONFIG, regs[OTI_CONFIG_DATA]); + OAKSetByte(OTI_OVERFLOW, regs[OTI_OVERFLOW_DATA]); + OAKSetByte(OTI87_HSYNC2, regs[OTI_HSYNC2_DATA]); + OAKSetByte(OTI_OVERFLOW2, regs[OTI_OVERFLOW2_DATA]); + } +} + +/* oak_modeavailable( int mode ) Check if mode supported + + * Verify that desired graphics mode can be displayed by chip/memory combo + * Returns SVGADRV flag if SVGA, vga_chipsetfunctions if VGA, 0 otherwise + */ + +static int oak_modeavailable(int mode) +{ + const unsigned char *regs; + struct vgainfo *info; + + regs = LOOKUPMODE(oak_modes, mode); + if (regs == NULL || mode == GPLANE16) { + return __svgalib_vga_driverspecs.modeavailable(mode); + } + if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE) { + return 0; + } + info = &__svgalib_infotable[mode]; + if (oak_memory * 1024 < info->ydim * info->xbytes) { + return 0; + } + return SVGADRV; +} + + + +/* oak_interlaced( int mode ) Is mode interlaced? + + * Self-explanatory. + * Returns non-zero if mode is interlaced (bit 7) + */ + +static int oak_interlaced(int mode) +{ + const unsigned char *regs; + + if (oak_modeavailable(mode) != SVGADRV) { + return 0; + } else { + regs = LOOKUPMODE(oak_modes, mode); + if (regs == NULL || regs == DISABLE_MODE) { + return 0; + } else { + return regs[EXT + 05] & 0x80; + } + } +} + +/* oak_setmode( int mode, int prv_mode ) Set graphics mode + + * Attempts to set a graphics mode. + * Returns 0 if successful, 1 if unsuccessful + * + * Calls vga_chipsetfunctions if VGA mode) + */ + +static int oak_setmode(int mode, int prv_mode) +{ + const unsigned char *rp; + unsigned char regs[sizeof(g640x480x256_regs)]; + + if ((oak_chiptype == 87) & (OTI87_OK_LINEAR == 1)) { + oak_clearlinearmode(); + } + rp = LOOKUPMODE(oak_modes, mode); + if (rp == NULL || mode == GPLANE16) + return (int) (__svgalib_vga_driverspecs.setmode(mode, prv_mode)); + if (!oak_modeavailable(mode)) + return 1; /* mode not available */ + + /* Update the register information */ + memcpy(regs, rp, sizeof(regs)); + + /* Number of memory chips */ + if (oak_chiptype != 87) { + regs[OTI_MISC_DATA] &= 0x3F; + regs[OTI_MISC_DATA] |= (oak_memory == 1024 ? 0x40 : 0x00); + regs[OTI_MISC_DATA] |= (oak_memory >= 512 ? 0x80 : 0x00); + if (oak_chiptype == 77) { + regs[OTI_CONFIG_DATA] |= 0x08; + } else { + regs[OTI_CONFIG_DATA] &= 0xF7; + } + } else { /* oak_chiptype == 87 */ + if (mode == G640x480x256) { + /* Oak-87 needs this bit, Oak-67 does not stand it - MW */ + regs[SEQ + 1] |= 0x8; + } + } + + if (__svgalib_infotable[mode].colors == 16) { + + /* switch from 256 to 16 color mode (from XFree86) */ + regs[SEQ + 4] &= 0xf7; /* Switch off chain 4 mode */ + if (oak_chiptype == 87) { + regs[OTI87_FIFO_DATA] &= 0xf0; + regs[OTI87_MODESELECT_DATA] &= 0xf3; + } else { + regs[OTI_MISC_DATA] &= 0xf0; + regs[OTI_MISC_DATA] |= 0x18; + } + } + __svgalib_setregs(regs); + oak_setregs(regs, mode); + if ((oak_chiptype == 87) & (OTI87_OK_LINEAR == 1)) { + oak_setlinearmode(); + } + return 0; +} + + + + +/* oak_unlock() Unlock Oak registers + + * Enable register changes + * + * _No effect with OTI-087 -- register is nonfunctional_ + */ + +static void oak_unlock(void) +{ + int temp; + /* Unprotect CRTC[0-7] */ + port_out_r(__svgalib_CRT_I, 0x11); + temp = port_in(__svgalib_CRT_D); + port_out_r(__svgalib_CRT_D, temp & 0x7F); + temp = OAKGetByte(OTI_CRT_CNTL); + OAKSetByte(OTI_CRT_CNTL, temp & 0xf0); + oak_lockreg_save = temp; +} + +/* oak_lock() Lock Oak registers + + * Prevents registers from accidental change + * + * _No effect with OTI-087 -- register is nonfunctional_ + */ + +static void oak_lock(void) +{ + int temp; + /* don't set the i/o write test bit, though we cleared it on entry */ + OAKSetByte(OTI_CRT_CNTL, oak_lockreg_save & 0xf7); + /* Protect CRTC[0-7] */ + port_out_r(__svgalib_CRT_I, 0x11); + temp = port_in(__svgalib_CRT_D); + port_out_r(__svgalib_CRT_D, (temp & 0x7F) | 0x80); +} + +/* oak_test() Probe for Oak card + + * Checks for Oak segment register, then chip type and memory size. + * + * Returns 1 for Oak, 0 otherwise. + */ + +static int oak_test(void) +{ + int save, temp1; + oak_unlock(); + + save = OAKGetByte(OTI_SEGMENT); + OAKSetByte(OTI_SEGMENT, save ^ 0x11); + temp1 = OAKGetByte(OTI_SEGMENT); + OAKSetByte(OTI_SEGMENT, save); + if (temp1 != (save ^ 0x11)) { + oak_lock(); /* unsuccesful */ + return 0; + } + /* HH: Only allow 087, 077 support seems to be broken for at */ + /* least one 512K card. May be due to mode dump configuring */ + /* for 1024K. */ + + /* Reallow 067 and 077 */ + /* if (oak_chipdetect() < 87) + return 0; */ + + return oak_init(0, 0, 0); +} + +/* oak_setpage( int page ) Set read/write pages + + * Sets both read and write extended segments (64k bank number) + * Should be good for 5 bits with OTI-087 + */ + +static void oak_setpage(int page) +{ + if (oak_chiptype == 87) { + OAKSetByte(OTI87_XCOMMONSEGMENT, page); + } else { + OAKSetByte(OTI_SEGMENT, (last_page = page | (page << 4))); + } +} + +/* oak_setrdpage( int page ) Set read page + + * Sets read extended segment (64k bank number) + * Should be good for 5 bits with OTI-087 + */ + +static void oak_setrdpage(int page) +{ + if (oak_chiptype == 87) { + OAKSetByte(OTI87_XREADSEGMENT, page); + } else { + last_page &= 0xF0; + last_page |= page; + OAKSetByte(OTI_SEGMENT, last_page); + } +} + +/* oak_setwrpage( int page ) Set write page + + * Sets write extended segment (64k bank number) + * Should be good for 5 bits with OTI-087 + */ + +static void oak_setwrpage(int page) +{ + if (oak_chiptype == 87) { + OAKSetByte(OTI87_XWRITESEGMENT, page); + } else { + last_page &= 0x0F; + last_page |= page << 4; + OAKSetByte(OTI_SEGMENT, last_page); + } +} + +/* oak_setdisplaystart( int address ) Set display address + + * Sets display start address. + * First word goes into CRT_IC indices 0x0c and 0x0d + * If 067, bit 16 goes to OTI_OVERFLOW bit 3 + * If 077, bit 17 goes to OTI_OVERFLOW2 bit 3 + * If 087, bits 16, 17, and 18 go to OTI87_XCRTC bits 0-2 + */ + +static void oak_setdisplaystart(int address) +{ + port_outw_r(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */ + port_outw_r(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */ + port_in(0x3da); /* set ATC to addressing mode */ + port_out_r(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); + /* write sa0-1 to bits 1-2 */ + + if (oak_chiptype == 87) { + OAKSetByte(OTI87_XCRTC, (address & 0x1c0000) >> 18); + } else { + OAKSetByte(OTI_OVERFLOW, (OAKGetByte(OTI_OVERFLOW) & 0xf7) + | ((address & 0x40000) >> 15)); + /* write sa18 to bit 3 */ + if (oak_chiptype == 77) { + OAKSetByte(OTI_OVERFLOW2, + (OAKGetByte(OTI_OVERFLOW2) & 0xf7) + | ((address & 0x80000) >> 16)); + /* write sa19 to bit 3 */ + } + } +} + +/* oak_setlogicalwidth( int width ) Set scanline length + + * Set logical scanline length (usually multiple of 8) + * Multiples of 8 to 2040 + */ + +static void oak_setlogicalwidth(int width) +{ + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ +} + +/* oak_init ( int force, int par1, int par2) Initialize chipset + + * Detects Oak chipset type and installed video memory. + * Returns 1 if chipset is supported, 0 otherwise + */ + +static int oak_init(int force, int par1, int par2) +{ + if (force) { + oak_chiptype = par1; + oak_memory = par2; + } else { + oak_chiptype = oak_chipdetect(); + if (oak_chiptype == 0) { + return 0; /* not supported */ + } + oak_memory = oak_memorydetect(); + } + if (__svgalib_driver_report) { + fprintf(stderr,"Using Oak driver (OTI-0%d, %dK).\n", oak_chiptype, + oak_memory); + } + __svgalib_driverspecs = &__svgalib_oak_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=0xe00000; + __svgalib_linear_mem_size=oak_memory*0x400; + + return 1; +} + +/* oak_memorydetect() Report installed video RAM + + * Returns size (in Kb) of installed video memory + * Defined values are 256, 512, 1024, and 2048 (OTI-087 only) + */ + +static int oak_memorydetect(void) +{ + int temp1; + if (oak_chiptype == 87) { + temp1 = OAKGetByte(OTI87_STATUS) & 0x06; + if (temp1 == 0x06) + return 2048; + else if (temp1 == 0x04) + return 1024; + else if (temp1 == 0x02) + return 512; + else if (temp1 == 0x00) + return 512; + else { + fprintf(stderr,"Oak driver: Invalid amount of memory. Using 256K.\n"); + return 256; + } + } else { + temp1 = OAKGetByte(OTI_MISC) & 0xc0; + if (temp1 == 0xC0) + return 1024; + else if (temp1 == 0x80) + return 512; + else if (temp1 == 0x00) + return 256; + else { + fprintf(stderr,"Oak driver: Invalid amount of memory. Using 256K.\n"); + return 256; + } + } +} + +/* oak_chipdetect() Detect Oak chip type + + * Returns chip id (67, 77, 87) if video chipset is a supported Oak type + * (57 is _not_ supported). + * Returns 0 otherwise + */ + +static int oak_chipdetect(void) +{ + int temp1; + + temp1 = port_in(OTI_INDEX); + temp1 &= 0xe0; + if (temp1 == 0x40) + return 67; + if (temp1 == 0xa0) + return 77; + + /* not a '67 or '77 ... try for '87 ... */ + + temp1 = OAKGetByte(OTI87_PRODUCT) & 0x01; + + if (temp1 == 0x01) + return 87; + + + /* none of the above ... maybe the nonexistant '97 I've been + hearing about? */ + +/* fprintf(stderr,"Oak driver: Unknown chipset (id = %2x)\n", temp1);*/ + oak_lock(); + return 0; +} + +/* oak_inlinearmode() Check if OTI-087 is in linear mode + + * Bit 0 set if yes, clear if no + * Return: true/false + */ + +static int oak_inlinearmode(void) +{ + return (OAKGetByte(OTI87_VIDMAP) & 0x01) != 0; +} + +/* oak_setlinearmode() Set linear mode for OTI-087 + + * For simplicity's sake, we're forcing map at the E0000 (14M) mark + * We grab the memory size from OTI87_STATUS, and we're mapping it all. + * + * Video map register looks like this: + * Bit 0: 0 = VGA mapping (A0000-BFFFF) 1 = Linear + * Bit 1: 0 = Enable DMA 1 = Disable DMA + * Bit 2/3: Aperature (256/512/1024/2048, bitwise) + * Bit 4-7: Starting address (High nybble, 1-F) + */ + +static void oak_setlinearmode(void) +{ + int temp1; + temp1 = ((OAKGetByte(OTI87_STATUS) & 0x06) << 1) | 0xe1; + OAKSetByte(OTI87_VIDMAP, temp1); + linearframebuffer=LINEAR_POINTER; + VGAMemory_Save = __svgalib_graph_mem; +} + +/* oak_clearlinearmode() Stop linear mode for OTI-087 + + * Switches linear mode off, reset aperture and address range + * (see oak_golinearmode() for register description) + */ + +static void oak_clearlinearmode(void) +{ + OAKSetByte(OTI87_VIDMAP, 0x00); + __svgalib_graph_mem = VGAMemory_Save; + graph_mem = VGAMemory_Save; + +} + +/* OAK_WriteDAC ( int dac_value ) Write value to DAC + + * Writes function command to DAC at 0x03c6 + * (Assumes that DAC is SC11487 ... may not work for others) + * + */ + +static void OAK_WriteDAC(int dac_value) +{ + port_in(DAC_REVERT); /* reset DAC r/w pointer */ + port_in(DAC_SC11487); /* do this four times to set register A */ + port_in(DAC_SC11487); + port_in(DAC_SC11487); + port_in(DAC_SC11487); + port_out_r(DAC_SC11487, dac_value); + port_in(DAC_REVERT); /* and reset DAC ... */ +} + +/* OAKSetByte ( index, value) Set extended register + + * Puts a specified value in a specified extended register. + * Splitting this commonly used instruction sequence into its own subroutine + * saves about 100 bytes of code overall ... + */ + +static void OAKSetByte(int OTI_index, int OTI_value) +{ + port_out_r(OTI_INDEX, OTI_index); + port_out_r(OTI_R_W, OTI_value); +} + +/* OAKGetByte ( index ) Returns ext. register + + * Returns value from specified extended register. + * As with OakSetByte, this tightens the code considerably. + */ + +static int OAKGetByte(int OTI_index) +{ + port_out_r(OTI_INDEX, OTI_index); + return port_in(OTI_R_W); +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_oak_driverspecs = +{ + oak_saveregs, + oak_setregs, + oak_unlock, + oak_lock, + oak_test, + oak_init, + oak_setpage, + oak_setrdpage, + oak_setwrpage, + oak_setmode, + oak_modeavailable, + oak_setdisplaystart, + oak_setlogicalwidth, + oak_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +#if 0 + (int (*)()) oak_setlinearmode, + (int (*)()) oak_clearlinearmode, + (int (*)()) OAK_WriteDAC, +#endif +}; diff --git a/src/drivers/paradise.c b/src/drivers/paradise.c new file mode 100644 index 0000000..5bee8c2 --- /dev/null +++ b/src/drivers/paradise.c @@ -0,0 +1,448 @@ +/* Western Digital Paradise WD90C31 driver for VGAlib */ +/* (c) 1998 Petr Kulhavy */ +/* */ +/* This driver is absolutely free software. You can redistribute */ +/* and/or it modify without any restrictions. But it's WITHOUT ANY */ +/* WARRANTY. */ + +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#include "regs/paradise.regs" + +/* static int paradise_chiptype; */ +static int paradise_memory; /* amount of video memory in K */ + +static int paradise_init(int, int, int); +static void paradise_unlock(void); + +/* Mode table */ +static ModeTable paradise_modes_512[] = +{ /* 512k, non-interlaced modes */ +/* *INDENT-OFF* */ + OneModeEntry(640x480x256), + OneModeEntry(800x600x16), + OneModeEntry(800x600x256), + OneModeEntry(1024x768x16), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +/* Interlaced modes suck, I hate them */ + +static ModeTable *paradise_modes = NULL; + +static void nothing(void) +{ +} + +static void inline _outb(unsigned port,unsigned value) +{ +#ifdef DEBUG + fprintf (stderr,"0x%x, 0x%x\n",port,value); +#endif +port_out_r(port,value); +} + +/* Fill in chipset specific mode information */ + +static void paradise_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ +#ifdef DEBUG + fprintf(stderr,"paradise_getmodeinfo\n"); +#endif + switch(modeinfo->colors) + { + case 16: /* 16 colors, 4 planes */ + modeinfo->maxpixels=65536*8; + modeinfo->startaddressrange = 0x7ffff; + break; + default: + if (modeinfo->bytesperpixel > 0) + modeinfo->maxpixels = paradise_memory * 1024 / + modeinfo->bytesperpixel; + else + modeinfo->maxpixels = paradise_memory * 1024; + modeinfo->startaddressrange = 0x3ffff; + break; + } + modeinfo->maxlogicalwidth = 2040; + modeinfo->haveblit = 0; + modeinfo->flags |= HAVE_RWPAGE; +} + + +/* select the correct register table */ +static void setup_registers(void) +{ +#ifdef DEBUG + fprintf(stderr,"setup_registers\n"); +#endif + if (paradise_modes == NULL) { + paradise_modes = paradise_modes_512; + } +} + + +/* Read and store chipset-specific registers */ + +static int paradise_saveregs(unsigned char regs[]) +{ +unsigned a,b; + +#ifdef DEBUG + fprintf(stderr,"paradise_saveregs\n"); +#endif + +paradise_unlock(); +b=0; +for (a=0x03;a<=0x15;) + { + port_out_r(SEQ_I,a); + regs[EXT+b]=port_in(SEQ_D); + b++; + if (a==0x03)a=0x06; + else if (a==0x07)a=0x10; + else if (a==0x12)a=0x14; + else a++; + } +for (a=0x09;a<=0x0f;a++) + { + port_out_r(GRA_I,a); + regs[EXT+b]=port_in(GRA_D); + b++; + } +for (a=0x29;a<=0x3e;) + { + port_out_r(CRT_IC,a); + regs[EXT+b]=port_in(CRT_DC); + b++; + if (a==0x30)a=0x32; + else if (a==0x32)a=0x34; + else if (a==0x34)a=0x3e; + else a++; + } +/* VGA registers, not set by shitty svgalib */ +port_out_r(CRT_IC,0x18); +regs[EXT+b+1]=port_in(CRT_DC); +port_out_r(ATT_IW,0x20); +__svgalib_delay(); +regs[EXT+b+2]=port_in(ATT_IW); +return 28; /* Paradise requires 28 additional registers */ +} + +static void paradise_unlock(void) +{ +unsigned char b; +#ifdef DEBUG + fprintf(stderr,"paradise_unlock\n"); +#endif +port_outw_r(GRA_I,0x050f); +port_outw_r(CRT_IC,0x8529); +port_outw_r(SEQ_I,0x4806); +/* let's unlock sync, timing ... */ +port_out_r(GRA_I,0xd); +b=port_in (GRA_D); +b&=30; +b|=2; +port_out_r(GRA_I,0xd); +port_out_r(GRA_D,b); +port_out_r(GRA_I,0xe); +b=port_in(GRA_D); +b&=251; +port_out_r(GRA_I,0xe); +port_out_r(GRA_D,b); +port_out_r(CRT_IC,0x2a); +b=port_in(CRT_DC); +b&=248; +port_out_r(CRT_IC,0x2a); +port_out_r(CRT_DC,b); +} + +static void paradise_lock(void) +{ +#ifdef DEBUG + fprintf(stderr,"paradise_lock\n"); +#endif +port_outw_r(GRA_I,0x000f); +port_outw_r(CRT_IC,0x0029); +port_outw_r(SEQ_I,0x0006); +} + +/* Set chipset-specific registers */ + +static void paradise_setregs(const unsigned char regs[], int mode) +{ +unsigned a,b; +#ifdef DEBUG +fprintf(stderr,"paradise_setregs\n"); +#endif + +paradise_unlock(); + +b=0; +for (a=0x03;a<=0x15;) + { + _outb(SEQ_I,a); + _outb(SEQ_D,regs[EXT+b]); + b++; + if (a==0x03)a=0x06; + else if (a==0x07)a=0x10; + else if (a==0x12)a=0x14; + else a++; + } +for (a=0x09;a<=0x0f;a++) + { + _outb(GRA_I,a); + _outb(GRA_D,regs[EXT+b]); + b++; + } +for (a=0x29;a<=0x3e;) + { + _outb(CRT_IC,a); + _outb(CRT_DC,regs[EXT+b]); + b++; + if (a==0x30)a=0x32; + else if (a==0x32)a=0x34; + else if (a==0x34)a=0x3e; + else a++; + } +/* VGA registers, not set by shitty svgalib */ +_outb(CRT_IC,0x18); +_outb(CRT_DC,regs[EXT+b+1]); +_outb(0x3da,0x100); +_outb(ATT_IW,0x20); +__svgalib_delay(); +_outb(ATT_IW,regs[EXT+b+2]); +} + + +/* Return nonzero if mode is available */ + +static int paradise_modeavailable(int mode) +{ + const unsigned char *regs; + struct vgainfo *info; +#ifdef DEBUG + fprintf(stderr,"paradise_modeavailable\n"); +#endif + + regs = LOOKUPMODE(paradise_modes, mode); + if (regs == NULL || mode == GPLANE16) + return __svgalib_vga_driverspecs.modeavailable(mode); + if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE) + return 0; + + info = &__svgalib_infotable[mode]; + if (paradise_memory * 1024 < info->ydim * info->xbytes) + return 0; + + return SVGADRV; +} + +/* Set a mode */ + +static int paradise_setmode(int mode, int prv_mode) +{ + const unsigned char *regs; + +#ifdef DEBUG + fprintf(stderr,"paradise_setmode\n"); +#endif + + regs = LOOKUPMODE(paradise_modes, mode); + if (regs == NULL) + return (int) (__svgalib_vga_driverspecs.setmode(mode, prv_mode)); + if (!paradise_modeavailable(mode)) + return 1; + paradise_unlock(); + __svgalib_setregs(regs); + paradise_setregs(regs, mode); + return 0; +} + + +/* Indentify chipset; return non-zero if detected */ + +static int paradise_test(void) +{ + /* + * Check first that we have a Paradise card. + */ + int a; + unsigned char old_value; + unsigned char txt[6]; +#ifdef DEBUG + fprintf(stderr,"paradise_test\n"); +#endif + txt[5]=0; + old_value=port_in(CRT_IC); + for (a=0;a<5;a++) + { + port_out_r(CRT_IC,0x31+a); + txt[a]=port_in(CRT_DC); + } + if (strcmp((char *)txt,"WD90C")) + { + port_out_r(CRT_IC,old_value); + return 0; + } + /* check version */ + port_out_r(CRT_IC, 0x36); + switch (port_in(CRT_DC)) + { + case 0x32: /* WD90C2x */ + port_out_r(CRT_IC, 0x37); + switch (port_in(CRT_DC)) + { + case 0x34: /* WD90C24 */ + case 0x36: /* WD90C26 */ + break; + default: + return 0; + } + break; + case 0x33: /* WD90C3x */ + port_out_r(CRT_IC, 0x37); + port_out_r(CRT_IC, 0x37); + switch (port_in(CRT_DC)) + { + case 0x30: /* WD90C30 */ + case 0x31: /* WD90C31 */ + case 0x33: /* WD90C31 */ + break; + default: + return 0; + } + break; + default: + return 0; + } + + paradise_init(0, 0, 0); + return 1; +} + + +/* Bank switching function - set 64K bank number */ + +static void paradise_setpage(int page) +{ +#ifdef DEBUG + fprintf(stderr,"paradise_setpage\n"); +#endif +paradise_unlock(); +/* set read-write paging mode */ +port_out_r(SEQ_I,0x11); +port_out_r(SEQ_D,port_in(SEQ_D)|0x80); +port_out_r(GRA_I,0x0b); +port_out_r(GRA_D,port_in(GRA_D)|0x80); +/* set bank number */ +port_out_r(GRA_I,0x09); +port_out_r(GRA_D,page<<4); +port_out_r(GRA_I,0x0a); +port_out_r(GRA_D,page<<4); +} + + +/* Set display start address (not for 16 color modes) */ + +static void paradise_setdisplaystart(int address) +{unsigned char bits,orig; +#ifdef DEBUG + fprintf(stderr,"paradise_setdisplaystart\n"); +#endif +paradise_unlock(); +port_out_r(CRT_IC,0x2f); +bits=address>>13; +orig=port_in(CRT_DC); +orig^=bits; +orig&=0xe7; +orig^=bits; +port_out_r(CRT_DC,orig); +} + + +/* Set logical scanline length (usually multiple of 8) */ + +static void paradise_setlogicalwidth(int width) +{ +#ifdef DEBUG + fprintf(stderr,"paradise_setlogicalwidth\n"); +#endif +paradise_unlock(); + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); +} + + +/* Function table */ +DriverSpecs __svgalib_paradise_driverspecs = +{ + paradise_saveregs, + paradise_setregs, + paradise_unlock, + paradise_lock, + paradise_test, + paradise_init, + paradise_setpage, + (void (*)(int)) nothing, /* __svgalib_setrdpage */ + (void (*)(int)) nothing, /* __svgalib_setwrpage */ + paradise_setmode, + paradise_modeavailable, + paradise_setdisplaystart, + paradise_setlogicalwidth, + paradise_getmodeinfo, /*?*/ + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL /* accelspecs */ +}; + + +/* Initialize chipset (called after detection) */ + +static int paradise_init(int force, int par1, int par2) +{ +#ifdef DEBUG + fprintf(stderr,"paradise_init\n"); +#endif + if (force) { +#ifdef DEBUG + fprintf(stderr,"forcing memory to %dkB\n",par1); +#endif + paradise_memory = par1; + } else { + port_out_r(GRA_I,0x0b); + paradise_memory=(port_in(GRA_D)>>6); + switch (paradise_memory) + { + case 0: + case 1: + paradise_memory=256; + break; + case 2: + paradise_memory=512; + break; + case 3: + paradise_memory=1024; + break; + } + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using WD90C31 Paradise driver (%dK non-interlaced).\n", + paradise_memory); + } + __svgalib_driverspecs = &__svgalib_paradise_driverspecs; + setup_registers(); + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + return 0; +} diff --git a/src/drivers/pm2.c b/src/drivers/pm2.c new file mode 100644 index 0000000..5d28ce0 --- /dev/null +++ b/src/drivers/pm2.c @@ -0,0 +1,766 @@ +/* +Permedia 2 chipset driver +*/ + +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "glint_regs.h" +#include "pm2io.h" + +#define REG_SAVE(i) (VGA_TOTAL_REGS+i) +#define TOTAL_REGS (VGA_TOTAL_REGS + 768 + 4*48) + +static int init(int, int, int); +static void unlock(void); +static void lock(void); + +static int memory; +static unsigned int linear_base; + +static enum {cPM2=1, cPM2V} chiptype; + +static CardSpecs *cardspecs; + +/* Fill in chipset specific mode information */ +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int saveregs(unsigned char regs[]) +{ + int i; + unsigned int *p = (unsigned int *)(regs+VGA_TOTAL_REGS); + unsigned char *q = regs+188; + + unlock(); + + p[0]=GLINT_READ_REG(Aperture0); + p[1]=GLINT_READ_REG(Aperture1); + p[2]=GLINT_READ_REG(PMFramebufferWriteMask); + p[3]=GLINT_READ_REG(PMBypassWriteMask); + p[4]=GLINT_READ_REG(DFIFODis); + p[5]=GLINT_READ_REG(FIFODis); + p[6]=GLINT_READ_REG(PMMemConfig); + p[7]=GLINT_READ_REG(PMHTotal); + p[8]=GLINT_READ_REG(PMHbEnd); + p[9]=GLINT_READ_REG(PMHgEnd); + p[10]=GLINT_READ_REG(PMScreenStride); + p[24]=GLINT_READ_REG(PMHsStart); + p[11]=GLINT_READ_REG(PMHsEnd); + p[12]=GLINT_READ_REG(PMVTotal); + p[13]=GLINT_READ_REG(PMVbEnd); + p[14]=GLINT_READ_REG(PMVsStart); + p[15]=GLINT_READ_REG(PMVsEnd); + p[16]=GLINT_READ_REG(PMScreenBase); + p[17]=GLINT_READ_REG(PMVideoControl); + p[18]=GLINT_READ_REG(VClkCtl); + p[19]=GLINT_READ_REG(ChipConfig); + + for(i=0;i<768;i++) { + Permedia2ReadAddress(i); + regs[128+VGA_TOTAL_REGS+i]=Permedia2ReadData(); + } + + switch(chiptype) { + case cPM2: + p[25]=Permedia2InIndReg(PM2DACIndexMCR); + p[26]=Permedia2InIndReg(PM2DACIndexMDCR); + p[27]=Permedia2InIndReg(PM2DACIndexCMR); + p[20]=Permedia2InIndReg(PM2DACIndexClockAM); + p[21]=Permedia2InIndReg(PM2DACIndexClockAN); + p[22]=Permedia2InIndReg(PM2DACIndexClockAP); + break; + case cPM2V: + p[23]=GLINT_READ_REG(PM2VDACRDIndexControl); + p[25]=Permedia2vInIndReg(PM2VDACRDOverlayKey); + p[26]=Permedia2vInIndReg(PM2VDACRDSyncControl); + p[27]=Permedia2vInIndReg(PM2VDACRDMiscControl); + p[28]=Permedia2vInIndReg(PM2VDACRDDACControl); + p[29]=Permedia2vInIndReg(PM2VDACRDPixelSize); + p[30]=Permedia2vInIndReg(PM2VDACRDColorFormat); + p[20]=Permedia2vInIndReg(PM2VDACRDDClk0PreScale); + p[21]=Permedia2vInIndReg(PM2VDACRDDClk0FeedbackScale); + p[22]=Permedia2vInIndReg(PM2VDACRDDClk0PostScale); + + for(i=0;i<6;i++) + q[i]=Permedia2vInIndReg(PM2VDACRDCursorPalette+i); + q[6]=Permedia2vInIndReg(PM2VDACRDCursorHotSpotX); + q[7]=Permedia2vInIndReg(PM2VDACRDCursorHotSpotY); + q[8]=Permedia2vInIndReg(PM2VDACRDCursorXLow); + q[9]=Permedia2vInIndReg(PM2VDACRDCursorXHigh); + q[10]=Permedia2vInIndReg(PM2VDACRDCursorYLow); + q[11]=Permedia2vInIndReg(PM2VDACRDCursorYHigh); + q[12]=Permedia2vInIndReg(PM2DACCursorControl); + q[13]=Permedia2vInIndReg(PM2VDACRDCursorMode); + break; + } + + return TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + int i; + unsigned int *p = (unsigned int *)(regs+VGA_TOTAL_REGS); + const unsigned char *q = regs+188; + + unlock(); + + GLINT_SLOW_WRITE_REG(0xFF, PM2DACReadMask); + + if(chiptype == cPM2V) + GLINT_SLOW_WRITE_REG(p[19], ChipConfig); + GLINT_SLOW_WRITE_REG(p[0], Aperture0); + GLINT_SLOW_WRITE_REG(p[1], Aperture1); + GLINT_SLOW_WRITE_REG(p[2], PMFramebufferWriteMask); + GLINT_SLOW_WRITE_REG(p[3], PMBypassWriteMask); + GLINT_SLOW_WRITE_REG(p[4], DFIFODis); + GLINT_SLOW_WRITE_REG(p[5], FIFODis); + if(0) + GLINT_SLOW_WRITE_REG(p[6], PMMemConfig); + GLINT_SLOW_WRITE_REG(p[17], PMVideoControl); + GLINT_SLOW_WRITE_REG(p[9], PMHgEnd); + GLINT_SLOW_WRITE_REG(p[16], PMScreenBase); + GLINT_SLOW_WRITE_REG(p[18], VClkCtl); + GLINT_SLOW_WRITE_REG(p[10], PMScreenStride); + GLINT_SLOW_WRITE_REG(p[7], PMHTotal); + GLINT_SLOW_WRITE_REG(p[8], PMHbEnd); + GLINT_SLOW_WRITE_REG(p[24], PMHsStart); + GLINT_SLOW_WRITE_REG(p[11], PMHsEnd); + GLINT_SLOW_WRITE_REG(p[12], PMVTotal); + GLINT_SLOW_WRITE_REG(p[13], PMVbEnd); + GLINT_SLOW_WRITE_REG(p[14], PMVsStart); + GLINT_SLOW_WRITE_REG(p[15], PMVsEnd); + if(chiptype != cPM2V) + GLINT_SLOW_WRITE_REG(p[19], ChipConfig); + + for (i=0;i<768;i++) { + Permedia2WriteAddress(i); + Permedia2WriteData(regs[VGA_TOTAL_REGS + 128 + i]); + } + + switch(chiptype) { + case cPM2: + Permedia2OutIndReg(PM2DACIndexMCR, 0x00, p[25]); + Permedia2OutIndReg(PM2DACIndexMDCR, 0x00, p[26]); + Permedia2OutIndReg(PM2DACIndexCMR, 0x00, p[27]); + Permedia2OutIndReg(PM2DACIndexClockAM, 0x00, p[20]); + Permedia2OutIndReg(PM2DACIndexClockAN, 0x00, p[21]); + Permedia2OutIndReg(PM2DACIndexClockAP, 0x00, p[22]); + break; + case cPM2V: + GLINT_SLOW_WRITE_REG(p[23],PM2VDACRDIndexControl); + Permedia2vOutIndReg(PM2VDACRDOverlayKey, 0x00, p[25]); + Permedia2vOutIndReg(PM2VDACRDSyncControl, 0x00, p[26]); + Permedia2vOutIndReg(PM2VDACRDMiscControl, 0x00, p[27]); + Permedia2vOutIndReg(PM2VDACRDDACControl, 0x00, p[28]); + Permedia2vOutIndReg(PM2VDACRDPixelSize, 0x00, p[29]); + Permedia2vOutIndReg(PM2VDACRDColorFormat, 0x00, p[30]); + i = Permedia2vInIndReg(PM2VDACIndexClockControl) & 0xFC; + Permedia2vOutIndReg(PM2VDACRDDClk0PreScale, 0x00, p[20]); + Permedia2vOutIndReg(PM2VDACRDDClk0FeedbackScale, 0x00, p[21]); + Permedia2vOutIndReg(PM2VDACRDDClk0PostScale, 0x00, p[22]); + Permedia2vOutIndReg(PM2VDACIndexClockControl, 0x00, i | 0x03); + for(i=0;i<6;i++) + Permedia2vOutIndReg(PM2VDACRDCursorPalette+i, 0x00, q[i]); + Permedia2vOutIndReg(PM2VDACRDCursorHotSpotX, 0x00, q[6]); + Permedia2vOutIndReg(PM2VDACRDCursorHotSpotY, 0x00, q[7]); + Permedia2vOutIndReg(PM2VDACRDCursorXLow, 0x00, q[8]); + Permedia2vOutIndReg(PM2VDACRDCursorXHigh, 0x00, q[9]); + Permedia2vOutIndReg(PM2VDACRDCursorYLow, 0x00, q[10]); + Permedia2vOutIndReg(PM2VDACRDCursorYHigh, 0x00, q[11]); + Permedia2vOutIndReg(PM2DACCursorControl, 0x00, q[12]); + Permedia2vOutIndReg(PM2VDACRDCursorMode, 0x00, q[13]); + } + +} + + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if(modeinfo->bitsPerPixel==24) { + free(modeinfo); + return 0; + } + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +#define INITIALFREQERR 100000 +#define MINCLK 110000 /* VCO frequency range */ +#define MAXCLK 250000 + +static unsigned int +PM2DAC_CalculateMNPCForClock +( + unsigned int reqclock, /* In kHz units */ + unsigned int refclock, /* In kHz units */ + unsigned char *rm, /* M Out */ + unsigned char *rn, /* N Out */ + unsigned char *rp /* P Out */ + ) +{ + unsigned char m, n, p; + unsigned int f; + int freqerr, lowestfreqerr = INITIALFREQERR; + unsigned int clock,actualclock = 0; + + for (n = 2; n <= 14; n++) { + for (m = 2; m != 0; m++) { /* this is a char, so this counts to 255 */ + f = refclock * m / n; + if ( (f < MINCLK) || (f > MAXCLK) ) + continue; + for (p = 0; p <= 4; p++) { + clock = f >> p; + freqerr = reqclock - clock; + if (freqerr < 0) + freqerr = -freqerr; + if (freqerr < lowestfreqerr) { + *rn = n; + *rm = m; + *rp = p; + lowestfreqerr = freqerr; + actualclock = clock; + } + } + } + } + + return(actualclock); +} + +static unsigned int +PM2VDAC_CalculateClock +( + unsigned int reqclock, /* In kHz units */ + unsigned int refclock, /* In kHz units */ + unsigned char *prescale, /* ClkPreScale */ + unsigned char *feedback, /* ClkFeedBackScale */ + unsigned char *postscale /* ClkPostScale */ + ) +{ + int f, pre, post; + unsigned int freq; + int freqerr = 1000; + unsigned int actualclock = 0; + + for (f=1;f<256;f++) { + for (pre=1;pre<256;pre++) { + for (post=0;post<1;post++) { + freq = ((refclock * f) / pre); + if ((reqclock > freq - freqerr)&&(reqclock < freq + freqerr)){ + freqerr = (reqclock > freq) ? + reqclock - freq : freq - reqclock; + *feedback = f; + *prescale = pre; + *postscale = post; + actualclock = freq; + } + } + } + } + + return(actualclock); +} + + +/* Local, called by setmode(). */ +static void initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ /* int k; */ + unsigned int *p = (unsigned int *)(moderegs+VGA_TOTAL_REGS); + int t1, t2, t3, t4; + unsigned char m, n, r; + + p[0]=0; + p[1]=0; + p[2]=0xffffffff; + p[3]=0xffffffff; + p[4]=1; + p[5]=1; + + if(0) p[6]=GLINT_READ_REG(PMMemConfig) | (1<<21); + + t1 = modetiming->CrtcHSyncStart - modetiming->CrtcHDisplay; + t2 = modetiming->CrtcVSyncStart - modetiming->CrtcVDisplay; + t3 = modetiming->CrtcHSyncEnd - modetiming->CrtcHSyncStart; + t4 = modetiming->CrtcVSyncEnd - modetiming->CrtcVSyncStart; + + switch(modeinfo->bytesPerPixel) { + case 1: + p[7]=modetiming->CrtcHTotal >> 2; + p[11]=(t1+t3) >> 2; + p[24]=t1 >> 2; + p[8]=(modetiming->CrtcHTotal-modetiming->CrtcHDisplay) >>2; + p[10]=modeinfo->lineWidth >> 3; + break; + case 2: + p[7]=modetiming->CrtcHTotal >> 1; + p[11]=(t1+t3) >> 1; + p[24]=t1 >> 1; + p[8]=(modetiming->CrtcHTotal-modetiming->CrtcHDisplay) >>1; + p[10]=modeinfo->lineWidth >> 3; + break; + case 3: + p[7]=(3*modetiming->CrtcHTotal) >> 2; + p[11]=(3*(t1+t3)) >> 2; + p[24]=(3*t1) >> 2; + p[8]=(3*(modetiming->CrtcHTotal-modetiming->CrtcHDisplay)) >> 2; + p[10]=modeinfo->lineWidth >> 3; + break; + case 4: + p[7]=modetiming->CrtcHTotal >> 0; + p[11]=(t1+t3) >> 0; + p[24]=t1 >> 0; + p[8]=(modetiming->CrtcHTotal-modetiming->CrtcHDisplay) >>0; + p[10]=modeinfo->lineWidth >> 3; + break; + } + + p[12]= modetiming->CrtcVTotal; + p[15]= t2+t4; + p[14]= t2; + p[13]= modetiming->CrtcVTotal-modetiming->CrtcVDisplay; + + p[17]=(1<<5)|(1<<3)|1; + + if (modetiming->flags & DOUBLESCAN) { + p[17] |= (1<<2); + } + + if((modeinfo->bytesPerPixel>1)||(chiptype==cPM2V)) { + p[17]|= 1<<16; + p[7]>>=1; + p[11]>>=1; + p[24]>>=1; + p[8]>>=1; + } + + p[18]=GLINT_READ_REG(VClkCtl)&0xfffffffc; + p[16]=0; + p[7] -= 1; + p[12] -= 1; + p[24] -= 1; + p[19]=GLINT_READ_REG(ChipConfig)&0xffffffdd; + + switch(chiptype) { + case cPM2: + PM2DAC_CalculateMNPCForClock(modetiming->pixelClock, 14318, &m, &n, &r); + p[20]=m; + p[21]=n; + p[22]=r|8; + break; + case cPM2V: + if(modetiming->pixelClock>28635) { + PM2VDAC_CalculateClock(modetiming->pixelClock, 14318, &m, &n, &r); + p[22]=0; + } else { + PM2VDAC_CalculateClock(modetiming->pixelClock*2, 14318, &m, &n, &r); + p[22]=1; + } + p[20]=m; + p[21]=n; + break; + }; + + if(chiptype == cPM2V) { + p[23]=0; + p[26]=0; + p[28]=0; + p[25]=0; /* ??? */ + + if(!(modetiming->flags&PHSYNC)) p[26] |= 1; + if(!(modetiming->flags&PVSYNC)) p[26] |= 8; + switch(modeinfo->bytesPerPixel) { + case 1: + p[29]=0; + p[30]=0x2e; + p[27]=0; + break; + case 2: + p[29]=1; + p[27]=0x09; + if(modeinfo->colorBits==15) { + p[30] |= 0x61; + } else { + p[30] |= 0x70; + } + break; + case 3: + p[29]=4; + p[27]=9; + p[30]=0x60; + break; + case 4: + p[29]=2; + p[27]=9; + p[30]=0x20; + break; + } + } else { + p[25]=0; + switch(modeinfo->bytesPerPixel) { + case 1: + p[25]=2; + p[27] = PM2DAC_RGB | PM2DAC_GRAPHICS | PM2DAC_CI8 ; + break; + case 2: + p[27] = PM2DAC_RGB | PM2DAC_GRAPHICS | PM2DAC_TRUECOLOR ; + if(modeinfo->colorBits==15) { + p[27] |= PM2DAC_5551; + } else { + p[27] |= PM2DAC_565; + } + break; + case 3: + p[27] = PM2DAC_RGB | PM2DAC_GRAPHICS | PM2DAC_TRUECOLOR | PM2DAC_PACKED; + break; + case 4: + p[27] = PM2DAC_RGB | PM2DAC_GRAPHICS | PM2DAC_TRUECOLOR | PM2DAC_8888; + break; + } + + if(!(modetiming->flags&PHSYNC)) p[25] |= 4; + if(!(modetiming->flags&PVSYNC)) p[25] |= 8; + + } + + p[9]=p[8]; + + return ; +} + + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ +} + +static void lock(void) +{ +} + +#define VENDOR_ID 0x3d3d + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + unsigned int buf[64]; + int found, id; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + id=(buf[0]>>16)&0xffff; + if(!found)return 0; + switch(id) { + case 0x0007: + case 0x0009: + init(0,0,0); + return 1; + break; + default: + return 0; + } +} + + +/* Set display start address (not for 16 color modes) */ +static void setdisplaystart(int address) +{ + GLINT_SLOW_WRITE_REG(address>>3, PMScreenBase); +} + + +/* Set logical scanline length (usually multiple of 8) */ +static void setlogicalwidth(int width) +{ + GLINT_SLOW_WRITE_REG(width>>3, PMScreenStride); +} + +static int linear(int op, int param) +{ + if (op==LINEAR_DISABLE || op==LINEAR_ENABLE) return 0; + if (op==LINEAR_QUERY_BASE) return linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} + +static int map_clock(int bpp, int clock) +{ +return clock ; +} + +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +unsigned char *cursors[16]; +unsigned int cur_cols[32]; + +static int pm2v_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j; + unsigned int *b3; + unsigned int l1, l2, k, c, l; + + switch(cmd){ + case CURSOR_INIT: + cursors[0]=malloc(16*1024); + for(i=1;i<16;i++)cursors[i]=cursors[0]+(i*1024); + return 1; + case CURSOR_HIDE: + Permedia2vOutIndReg(PM2VDACRDCursorMode, 0x00, 0x10); + break; + case CURSOR_SHOW: + Permedia2vOutIndReg(PM2VDACRDCursorMode, 0x00, 0x11); + break; + case CURSOR_POSITION: + p1+=64; + p2+=64; + Permedia2vOutIndReg(PM2VDACRDCursorHotSpotX, 0x00, 0x3f); + Permedia2vOutIndReg(PM2VDACRDCursorHotSpotY, 0x00, 0x3f); + Permedia2vOutIndReg(PM2VDACRDCursorXLow, 0x00, p1&0xff); + Permedia2vOutIndReg(PM2VDACRDCursorXHigh, 0x00, p1>>8); + Permedia2vOutIndReg(PM2VDACRDCursorYLow, 0x00, p2&0xff); + Permedia2vOutIndReg(PM2VDACRDCursorYHigh, 0x00, p2>>8); + break; + case CURSOR_SELECT: + for(i=0;i<1024;i++)Permedia2vOutIndReg(PM2VDACRDCursorPattern+i, 0x00, cursors[p1][i]); + Permedia2vOutIndReg(PM2VDACRDCursorPalette, 0x00, cur_cols[p1*2]>>16); + Permedia2vOutIndReg(PM2VDACRDCursorPalette+1, 0x00, cur_cols[p1*2]>>8); + Permedia2vOutIndReg(PM2VDACRDCursorPalette+2, 0x00, cur_cols[p1*2]); + Permedia2vOutIndReg(PM2VDACRDCursorPalette+3, 0x00, cur_cols[p1*2+1]>>16); + Permedia2vOutIndReg(PM2VDACRDCursorPalette+4, 0x00, cur_cols[p1*2+1]>>8); + Permedia2vOutIndReg(PM2VDACRDCursorPalette+5, 0x00, cur_cols[p1*2+1]); + break; + case CURSOR_IMAGE: + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_cols[p1*2]=p3; + cur_cols[p1*2+1]=p4; + for(j=0;j<32;j++) { + l1=*(b3+j); + l2=*(b3+32+j); + for(k=0;k<8;k++) { + c=0; + for(l=0;l<4;l++) { + c>>=1; + c|=(l1>>31)<<7; + c>>=1; + c|=(l2>>31)<<7; + l1<<=1; + l2<<=1; + } + *(cursors[p1]+16*j+k)=c; + *(cursors[p1]+16*j+k+8)=0; + } + } + memset(cursors[p1]+512,0,512); + break; + } + break; + } + return 0; +} + + +/* Function table (exported) */ +DriverSpecs __svgalib_pm2_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + NULL, + NULL, + NULL, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0, id; + unsigned int mmio_base; + + unlock(); + if (force) { + memory = par1; + chiptype = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + linear_base=0; + id=(buf[0]>>16)&0xffff; + if(found) { + switch(id) { + case 0x0007: + chiptype = cPM2; + break; + case 0x0009: + chiptype = cPM2V; + break; + default: + return 1; + } + } + + linear_base = buf[6] & 0xffffc000; + mmio_base = buf[4] & 0xffffc000; + __svgalib_mmio_base=mmio_base; + __svgalib_mmio_size=64*1024; + map_mmio(); + + memory = (((GLINT_READ_REG(PMMemConfig) >> 29) & 0x03) + 1) * 2048; + + switch(chiptype) { + case cPM2V: + __svgalib_pm2_driverspecs.cursor = pm2v_cursor; + break; + default: + break; + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using PM2 driver, %iKB.\n",memory); + }; + + pm2_mapio(); + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 230000; + cardspecs->maxPixelClock16bpp = 230000; + cardspecs->maxPixelClock24bpp = 150000; + cardspecs->maxPixelClock32bpp = 110000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE | EMULATE_BANK; + cardspecs->maxHorizontalCrtc = 4080; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_pm2_driverspecs; + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=memory*0x400; + __svgalib_emulatepage=2; + return 0; +} diff --git a/src/drivers/pm2io.h b/src/drivers/pm2io.h new file mode 100644 index 0000000..6d16b5a --- /dev/null +++ b/src/drivers/pm2io.h @@ -0,0 +1,97 @@ +#include "libvga.h" +#include + +static int __svgalib_pm2_inmisc(void) +{ + return 0; +} + +static void __svgalib_pm2_outmisc(int i) +{ +} + +static int __svgalib_pm2_incrtc(int i) +{ + return 0; +} + +static void __svgalib_pm2_outcrtc(int i, int d) +{ +} + +static int __svgalib_pm2_inseq(int index) +{ + return 0; +} + +static void __svgalib_pm2_outseq(int index, int val) +{ +} + +static int __svgalib_pm2_ingra(int index) +{ + return 0; +} + +static void __svgalib_pm2_outgra(int index, int val) +{ +} + +static int __svgalib_pm2_inis1(void) +{ + return 0; +} + +static int __svgalib_pm2_inatt(int index) +{ + return 0; +} + +static void __svgalib_pm2_outatt(int index, int val) +{ +} + +static void __svgalib_pm2_attscreen(int i) +{ +} + +static void __svgalib_pm2_inpal(int i, int *r, int *g, int *b) +{ + Permedia2ReadAddress(i); + *r=Permedia2ReadData(); + *g=Permedia2ReadData(); + *b=Permedia2ReadData(); +} + +static void __svgalib_pm2_outpal(int i, int r, int g, int b) +{ + Permedia2WriteAddress(i); + Permedia2WriteData(r); + Permedia2WriteData(g); + Permedia2WriteData(b); +} + +static void pm2_mapio(void) +{ +#ifndef __PPC + if(__svgalib_secondary) { +#endif + __svgalib_inmisc=__svgalib_pm2_inmisc; + __svgalib_outmisc=__svgalib_pm2_outmisc; + __svgalib_incrtc=__svgalib_pm2_incrtc; + __svgalib_outcrtc=__svgalib_pm2_outcrtc; + __svgalib_inseq=__svgalib_pm2_inseq; + __svgalib_outseq=__svgalib_pm2_outseq; + __svgalib_ingra=__svgalib_pm2_ingra; + __svgalib_outgra=__svgalib_pm2_outgra; + __svgalib_inatt=__svgalib_pm2_inatt; + __svgalib_outatt=__svgalib_pm2_outatt; + __svgalib_attscreen=__svgalib_pm2_attscreen; + __svgalib_inis1=__svgalib_pm2_inis1; +#ifndef __PPC + } +#endif + __svgalib_inpal=__svgalib_pm2_inpal; + __svgalib_outpal=__svgalib_pm2_outpal; +} + diff --git a/src/drivers/r128.c b/src/drivers/r128.c new file mode 100644 index 0000000..d90e3e5 --- /dev/null +++ b/src/drivers/r128.c @@ -0,0 +1,2107 @@ +/* +Rage 128 chipset driver +*/ + +#include +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "endianess.h" +#include "r128_reg.h" +#include "xf86PciInfo.h" + +static int RADEONProbePLLParameters(void); + +static int id; + +static enum { Rage128=0, Radeon } chiptype; /* r128io needs to know */ +static enum { + CHIP_FAMILY_UNKNOW, + CHIP_FAMILY_LEGACY, + CHIP_FAMILY_RADEON, + CHIP_FAMILY_RV100, + CHIP_FAMILY_RS100, /* U1 (IGP320M) or A3 (IGP320)*/ + CHIP_FAMILY_RV200, + CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350), RS250 (IGP 7000) */ + CHIP_FAMILY_R200, + CHIP_FAMILY_RV250, + CHIP_FAMILY_RS300, /* RS300/RS350 */ + CHIP_FAMILY_RV280, + CHIP_FAMILY_R300, + CHIP_FAMILY_R350, + CHIP_FAMILY_RV350, + CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */ + CHIP_FAMILY_R420, /* R420/R423/M18 */ + CHIP_FAMILY_LAST +} ChipFamily; +static char *familynames[] = { + "Rage 128", + "Legacy", + "Radeon", + "Radeon RV100", + "Radeon RS100", + "Radeon RV200", + "Radeon RS200", + "Radeon R200", + "Radeon RV250", + "Radeon RS300", + "Radeon RV280", + "Radeon R300", + "Radeon R350", + "Radeon RV350", + "Radeon RV380", + "Radeon R420", +}; + +#define IS_RV100_VARIANT ((ChipFamily == CHIP_FAMILY_RV100) || \ + (ChipFamily == CHIP_FAMILY_RV200) || \ + (ChipFamily == CHIP_FAMILY_RS100) || \ + (ChipFamily == CHIP_FAMILY_RS200) || \ + (ChipFamily == CHIP_FAMILY_RV250) || \ + (ChipFamily == CHIP_FAMILY_RV280) || \ + (ChipFamily == CHIP_FAMILY_RS300)) + +#define IS_R300_VARIANT ((ChipFamily == CHIP_FAMILY_R300) || \ + (ChipFamily == CHIP_FAMILY_RV350) || \ + (ChipFamily == CHIP_FAMILY_R350) || \ + (ChipFamily == CHIP_FAMILY_RV380) || \ + (ChipFamily == CHIP_FAMILY_R420)) + +#define TRUE 1 +#define FALSE 0 + +static int dac6bits; +#include "r128io.h" + +#ifdef __PPC +#define NO_BIOS +#else +#undef NO_BIOS +#endif + +typedef int Bool; + +static int r128_ramtype; +static int BusCntl, CRTOnly, HasPanelRegs, IsIGP, IsMobility, HasSingleDAC, HasCRTC2; + +static float mclk, sclk; +static uint32_t ChipErrata; + +typedef struct { + uint16_t reference_freq; + uint16_t reference_div; + uint32_t min_pll_freq; + uint32_t max_pll_freq; + uint16_t xclk; +} R128PLLRec, *R128PLLPtr; + +typedef struct { + /* Common registers */ + uint32_t ovr_clr; + uint32_t ovr_wid_left_right; + uint32_t ovr_wid_top_bottom; + uint32_t ov0_scale_cntl; + uint32_t mpp_tb_config; + uint32_t mpp_gp_config; + uint32_t subpic_cntl; + uint32_t viph_control; + uint32_t i2c_cntl_1; + uint32_t gen_int_cntl; + uint32_t cap0_trig_cntl; + uint32_t cap1_trig_cntl; + uint32_t bus_cntl; + uint32_t bus_cntl1; + uint32_t mem_cntl; + uint32_t config_cntl; + uint32_t mem_vga_wp_sel; + uint32_t mem_vga_rp_sel; + uint32_t surface_cntl; + uint32_t dac_cntl2; + uint32_t crtc_more_cntl; + uint32_t dac_ext_cntl; + uint32_t grph_buf_cntl; + uint32_t vga_buf_cntl; + + /* Other registers to save for VT switches */ + uint32_t dp_datatype; + uint32_t gen_reset_cntl; + uint32_t clock_cntl_index; + uint32_t amcgpio_en_reg; + uint32_t amcgpio_mask; + /* CRTC registers */ + uint32_t crtc_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t dac_cntl; + uint32_t crtc_h_total_disp; + uint32_t crtc_h_sync_strt_wid; + uint32_t crtc_v_total_disp; + uint32_t crtc_v_sync_strt_wid; + uint32_t crtc_offset; + uint32_t crtc_offset_cntl; + uint32_t crtc_pitch; + /* CRTC2 registers */ + uint32_t crtc2_gen_cntl; + /* Flat panel registers */ + uint32_t fp_crtc_h_total_disp; + uint32_t fp_crtc_v_total_disp; + uint32_t fp_gen_cntl; + uint32_t fp_h_sync_strt_wid; + uint32_t fp_horz_stretch; + uint32_t fp_panel_cntl; + uint32_t fp_v_sync_strt_wid; + uint32_t fp_vert_stretch; + uint32_t lvds_gen_cntl; + uint32_t tmds_crc; + /* Computed values for PLL */ + uint32_t dot_clock_freq; + uint32_t pll_output_freq; + int feedback_div; + int post_div; + /* PLL registers */ + uint32_t ppll_ref_div; + uint32_t ppll_div_3; + uint32_t htotal_cntl; + /* Computed values for PLL2 */ + uint32_t dot_clock_freq_2; + uint32_t pll_output_freq_2; + int feedback_div_2; + int post_div_2; + + /* PLL2 registers */ + uint32_t p2pll_ref_div; + uint32_t p2pll_div_0; + uint32_t htotal_cntl2; + + /* DDA register */ + uint32_t dda_config; + uint32_t dda_on_off; + uint32_t vga_dda_config; + uint32_t vga_dda_on_off; + /* Pallet */ + Bool palette_valid; + uint32_t palette[256]; +} R128SaveRec, *R128SavePtr; + +typedef struct { /* All values in XCLKS */ + int ML; /* Memory Read Latency */ + int MB; /* Memory Burst Length */ + int Trcd; /* RAS to CAS delay */ + int Trp; /* RAS percentage */ + int Twr; /* Write Recovery */ + int CL; /* CAS Latency */ + int Tr2w; /* Read to Write Delay */ + int Rloop; /* Loop Latency */ + int Rloop_fudge; /* Add to ML to get Rloop */ + char *name; +} R128RAMRec, *R128RAMPtr; + +#define R128_TOTAL_REGS (VGA_TOTAL_REGS + sizeof(R128SaveRec)) + +static int R128MinBits(int val) +{ + int bits; + + if (!val) return 1; + for (bits = 0; val; val >>= 1, ++bits); + return bits; +} + +static int R128Div(int n, int d) +{ + return (n + (d / 2)) / d; +} + +static R128PLLRec pll; + +static R128RAMRec ram[] = { /* Memory Specifications + From RAGE 128 Software Development + Manual (Technical Reference Manual P/N + SDK-G04000 Rev 0.01), page 3-21. */ + { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" }, + { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" }, + { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" }, + { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" }, +}; +void RADEONPllErrataAfterIndex(void) +{ + if (!(ChipErrata & CHIP_ERRATA_PLL_DUMMYREADS)) + return; + + /* This workaround is necessary on rv200 and RS200 or PLL + * reads may return garbage (among others...) + */ + (void)INREG(R128_CLOCK_CNTL_DATA); + (void)INREG(R128_CRTC_GEN_CNTL); +} + +void RADEONPllErrataAfterData(void) +{ + /* This workarounds is necessary on RV100, RS100 and RS200 chips + * or the chip could hang on a subsequent access + */ + + if (ChipErrata & CHIP_ERRATA_PLL_DELAY) { + /* we can't deal with posted writes here ... */ + usleep(5000); + } + + /* This function is required to workaround a hardware bug in + * some (all?) revisions of the R300. This workaround should + * be called after every CLOCK_CNTL_INDEX register access. + * If not, register reads afterward may not be correct. + */ + + if (ChipErrata & CHIP_ERRATA_R300_CG) { + uint32_t save, tmp; + + save = INREG(R128_CLOCK_CNTL_INDEX); + tmp = save & ~(0x3f | R128_PLL_WR_EN); + OUTREG(R128_CLOCK_CNTL_INDEX, tmp); + tmp = INREG(R128_CLOCK_CNTL_DATA); + OUTREG(R128_CLOCK_CNTL_INDEX, save); + } +} + +static unsigned R128INPLL(int addr) +{ + OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f); + return INREG(R128_CLOCK_CNTL_DATA); +} + +static void R128WaitForVerticalSync(void) +{ + volatile int i; + + OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK); + for (i = 0; i < R128_TIMEOUT; i++) { + if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break; + } +} + +/* Blank screen. */ +static void R128Blank(void) +{ + OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS); +} + +/* Unblank screen. */ +static void R128Unblank(void) +{ + OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS); +} + +static void R128RestoreCommonRegisters(R128SavePtr restore) +{ + OUTREG(R128_OVR_CLR, restore->ovr_clr); + OUTREG(R128_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right); + OUTREG(R128_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom); + OUTREG(R128_OV0_SCALE_CNTL, restore->ov0_scale_cntl); + OUTREG(R128_MPP_TB_CONFIG, restore->mpp_tb_config ); + OUTREG(R128_MPP_GP_CONFIG, restore->mpp_gp_config ); + OUTREG(R128_SUBPIC_CNTL, restore->subpic_cntl); + OUTREG(R128_VIPH_CONTROL, restore->viph_control); + OUTREG(R128_I2C_CNTL_1, restore->i2c_cntl_1); + OUTREG(R128_GEN_INT_CNTL, restore->gen_int_cntl); + OUTREG(R128_CAP0_TRIG_CNTL, restore->cap0_trig_cntl); + OUTREG(R128_CAP1_TRIG_CNTL, restore->cap1_trig_cntl); + OUTREG(R128_BUS_CNTL, restore->bus_cntl); + OUTREG(R128_BUS_CNTL1, restore->bus_cntl1); + OUTREG(R128_CONFIG_CNTL, restore->config_cntl); + OUTREG(R128_MEM_VGA_WP_SEL, restore->mem_vga_wp_sel); + OUTREG(R128_MEM_VGA_RP_SEL, restore->mem_vga_rp_sel); + + if(chiptype == Radeon) { + OUTREG(RADEON_SURFACE_CNTL, restore->surface_cntl); + OUTREG(RADEON_DAC_CNTL2, restore->dac_cntl2); + OUTREG(RADEON_CRTC_MORE_CNTL,restore->crtc_more_cntl); + OUTREG(RADEON_DAC_EXT_CNTL, restore->dac_ext_cntl); + OUTREG(RADEON_GRPH_BUF_CNTL, restore->grph_buf_cntl); + OUTREG(RADEON_VGA_BUF_CNTL, restore->vga_buf_cntl); + } + +} + +/* Write CRTC registers. */ +static void R128RestoreCrtcRegisters(R128SavePtr restore) +{ + OUTREG(R128_CRTC_GEN_CNTL, restore->crtc_gen_cntl); + + OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl, + R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS); + + OUTREGP(R128_DAC_CNTL, restore->dac_cntl, + R128_DAC_RANGE_CNTL | R128_DAC_BLANKING); + + OUTREG(R128_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); + OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); + OUTREG(R128_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); + OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); + OUTREG(R128_CRTC_OFFSET, restore->crtc_offset); + OUTREG(R128_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); + OUTREG(R128_CRTC_PITCH, restore->crtc_pitch); +} + +/* Write flat panel registers */ +#if 0 +static void R128RestoreFPRegisters(R128SavePtr restore) +{ + uint32_t tmp; + + OUTREG(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); + OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); + OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); + OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl); + OUTREG(R128_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); + OUTREG(R128_FP_HORZ_STRETCH, restore->fp_horz_stretch); + OUTREG(R128_FP_PANEL_CNTL, restore->fp_panel_cntl); + OUTREG(R128_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); + OUTREG(R128_FP_VERT_STRETCH, restore->fp_vert_stretch); + OUTREG(R128_TMDS_CRC, restore->tmds_crc); + + tmp = INREG(R128_LVDS_GEN_CNTL); + if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) == + (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) { + OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); + } else { + if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) { + OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl & ~R128_LVDS_BLON); +// usleep(R128PTR(pScrn)->PanelPwrDly * 1000); + OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); + } else { + OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON); +// usleep(R128PTR(pScrn)->PanelPwrDly * 1000); + OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); + } + } +} +#endif +static void R128PLLWaitForReadUpdateComplete(void) +{ + int i = 0; + + /* FIXME: Certain revisions of R300 can't recover here. Not sure of + the cause yet, but this workaround will mask the problem for now. + Other chips usually will pass at the very first test, so the + workaround shouldn't have any effect on them. */ + for (i = 0; + (i < 10000 && + INPLL(R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); + i++); +} + +static void R128PLLWriteUpdate(void) +{ + while (INPLL ( R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); + OUTPLLP(R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W, ~(R128_PPLL_ATOMIC_UPDATE_W)); +} + +/* Write PLL registers. */ +static void RADEONRestorePLLRegisters(R128SavePtr restore) +{ + OUTPLLP(R128_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_CPUCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); + + OUTPLLP(R128_PPLL_CNTL, + R128_PPLL_RESET + | R128_PPLL_ATOMIC_UPDATE_EN + | R128_PPLL_VGA_ATOMIC_UPDATE_EN, + ~(R128_PPLL_RESET + | R128_PPLL_ATOMIC_UPDATE_EN + | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); + + OUTREGP(R128_CLOCK_CNTL_INDEX, + R128_PLL_DIV_SEL, + ~(R128_PLL_DIV_SEL)); + + + if(ChipFamily>=CHIP_FAMILY_R300) /* IS_R300_VARIANT */ + { + if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { + /* When restoring console mode, use saved PPLL_REF_DIV + * setting. */ + OUTPLLP(R128_PPLL_REF_DIV, + restore->ppll_ref_div, + 0); + } else { + /* R300 uses ref_div_acc field as real ref divider */ + OUTPLLP(R128_PPLL_REF_DIV, + (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), + ~R300_PPLL_REF_DIV_ACC_MASK); + } + } else { + + OUTPLLP(R128_PPLL_REF_DIV, + restore->ppll_ref_div, + ~R128_PPLL_REF_DIV_MASK); + } + + + + OUTPLLP(R128_PPLL_DIV_3, + restore->ppll_div_3, + ~R128_PPLL_FB3_DIV_MASK); + + OUTPLLP(R128_PPLL_DIV_3, + restore->ppll_div_3, + ~R128_PPLL_POST3_DIV_MASK); + + R128PLLWriteUpdate(); + R128PLLWaitForReadUpdateComplete(); + + OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl); + + OUTPLLP(R128_PPLL_CNTL, + 0, + ~(R128_PPLL_RESET + | R128_PPLL_SLEEP + | R128_PPLL_ATOMIC_UPDATE_EN + | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); + + usleep(500000); /* Let the clock to lock */ + + OUTPLLP(R128_VCLK_ECP_CNTL, + RADEON_VCLK_SRC_SEL_PPLLCLK, + ~(RADEON_VCLK_SRC_SEL_MASK)); +} + +static void R128RestorePLLRegisters(R128SavePtr restore) +{ + OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, 0xffff); + + OUTPLLP( + R128_PPLL_CNTL, + R128_PPLL_RESET + | R128_PPLL_ATOMIC_UPDATE_EN, + 0xffff); + + R128PLLWaitForReadUpdateComplete(); + OUTPLLP(R128_PPLL_REF_DIV, + restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK); + R128PLLWriteUpdate(); + + R128PLLWaitForReadUpdateComplete(); + OUTPLLP(R128_PPLL_DIV_3, + restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK); + R128PLLWriteUpdate(); + OUTPLLP(R128_PPLL_DIV_3, + restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK); + R128PLLWriteUpdate(); + + R128PLLWaitForReadUpdateComplete(); + OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl); + R128PLLWriteUpdate(); + + OUTPLLP( R128_PPLL_CNTL, 0, ~R128_PPLL_RESET); + +} + +/* Write DDA registers. */ +static void R128RestoreDDARegisters(R128SavePtr restore) +{ + OUTREG(R128_DDA_CONFIG, restore->dda_config); + OUTREG(R128_DDA_ON_OFF, restore->dda_on_off); +// OUTREG(R128_VGA_DDA_CONFIG, restore->vga_dda_config); +// OUTREG(R128_VGA_DDA_ON_OFF, restore->vga_dda_on_off); +} + +/* Write palette data. */ +static void R128RestorePalette( R128SavePtr restore) +{ + int i; + +if (!restore->palette_valid) return; + + /* Select palette 0 (main CRTC) if using FP-enabled chip */ +// if (info->HasPanelRegs) PAL_SELECT(0); + + OUTPAL_START(0); + for (i = 0; i < 256; i++) OUTPAL_NEXT_uint32_t(restore->palette[i]); +} + +/* Write out state to define a new video mode. */ +static void R128RestoreMode(R128SavePtr restore) +{ + R128Blank(); + + OUTREG(R128_AMCGPIO_MASK, restore->amcgpio_mask); + OUTREG(R128_AMCGPIO_EN_REG, restore->amcgpio_en_reg); + OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index); +#if 0 /* works without, and it causes problems with it */ + OUTREG(R128_GEN_RESET_CNTL, restore->gen_reset_cntl); +#endif + OUTREG(R128_DP_DATATYPE, restore->dp_datatype); + + R128RestoreCommonRegisters( restore); + R128RestoreCrtcRegisters( restore); +// if (info->HasPanelRegs) +// R128RestoreFPRegisters(restore); +// if (!info->HasPanelRegs || info->CRTOnly) + switch(chiptype) { + case Rage128: + R128RestorePLLRegisters(restore); + break; + case Radeon: + RADEONRestorePLLRegisters(restore); + break; + } + + if(chiptype == Rage128) { + R128RestoreDDARegisters(restore); + } + + R128RestorePalette(restore); +} + +/* Read common registers. */ +static void R128SaveCommonRegisters(R128SavePtr save) +{ + save->ovr_clr = INREG(R128_OVR_CLR); + save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT); + save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM); + save->ov0_scale_cntl = INREG(R128_OV0_SCALE_CNTL); + save->mpp_tb_config = INREG(R128_MPP_TB_CONFIG); + save->mpp_gp_config = INREG(R128_MPP_GP_CONFIG); + save->subpic_cntl = INREG(R128_SUBPIC_CNTL); + save->viph_control = INREG(R128_VIPH_CONTROL); + save->i2c_cntl_1 = INREG(R128_I2C_CNTL_1); + save->gen_int_cntl = INREG(R128_GEN_INT_CNTL); + save->cap0_trig_cntl = INREG(R128_CAP0_TRIG_CNTL); + save->cap1_trig_cntl = INREG(R128_CAP1_TRIG_CNTL); + save->bus_cntl = INREG(R128_BUS_CNTL); + save->bus_cntl1 = INREG(R128_BUS_CNTL1); + save->mem_cntl = INREG(R128_MEM_CNTL); + save->config_cntl = INREG(R128_CONFIG_CNTL); + save->mem_vga_wp_sel = INREG(R128_MEM_VGA_WP_SEL); + save->mem_vga_rp_sel = INREG(R128_MEM_VGA_RP_SEL); + + if(chiptype==Radeon) { + save->surface_cntl = INREG(RADEON_SURFACE_CNTL); + save->dac_cntl2 = INREG(RADEON_DAC_CNTL2); + save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); + save->dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + save->grph_buf_cntl = INREG(RADEON_GRPH_BUF_CNTL); + save->vga_buf_cntl = INREG(RADEON_VGA_BUF_CNTL); + } +} + +/* Read CRTC registers. */ +static void R128SaveCrtcRegisters(R128SavePtr save) +{ + save->crtc_gen_cntl = INREG(R128_CRTC_GEN_CNTL); + save->crtc_ext_cntl = INREG(R128_CRTC_EXT_CNTL); + save->dac_cntl = INREG(R128_DAC_CNTL); + save->crtc_h_total_disp = INREG(R128_CRTC_H_TOTAL_DISP); + save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID); + save->crtc_v_total_disp = INREG(R128_CRTC_V_TOTAL_DISP); + save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID); + save->crtc_offset = INREG(R128_CRTC_OFFSET); + save->crtc_offset_cntl = INREG(R128_CRTC_OFFSET_CNTL); + save->crtc_pitch = INREG(R128_CRTC_PITCH); +} + +#if 0 +/* Read flat panel registers */ +static void R128SaveFPRegisters(R128SavePtr save) +{ + save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); + save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP); + save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP); + save->fp_gen_cntl = INREG(R128_FP_GEN_CNTL); + save->fp_h_sync_strt_wid = INREG(R128_FP_H_SYNC_STRT_WID); + save->fp_horz_stretch = INREG(R128_FP_HORZ_STRETCH); + save->fp_panel_cntl = INREG(R128_FP_PANEL_CNTL); + save->fp_v_sync_strt_wid = INREG(R128_FP_V_SYNC_STRT_WID); + save->fp_vert_stretch = INREG(R128_FP_VERT_STRETCH); + save->lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL); + save->tmds_crc = INREG(R128_TMDS_CRC); +} +#endif + +/* Read PLL registers. */ +static void R128SavePLLRegisters(R128SavePtr save) +{ + save->ppll_ref_div = INPLL(R128_PPLL_REF_DIV); + save->ppll_div_3 = INPLL(R128_PPLL_DIV_3); + save->htotal_cntl = INPLL(R128_HTOTAL_CNTL); +} + +/* Read DDA registers. */ +static void R128SaveDDARegisters(R128SavePtr save) +{ + save->dda_config = INREG(R128_DDA_CONFIG); + save->dda_on_off = INREG(R128_DDA_ON_OFF); + save->vga_dda_config = INREG(R128_VGA_DDA_CONFIG); + save->vga_dda_on_off = INREG(R128_VGA_DDA_ON_OFF); +} + +/* Read palette data. */ +static void R128SavePalette(R128SavePtr save) +{ + int i; + + /* Select palette 0 (main CRTC) if using FP-enabled chip */ +// if (info->HasPanelRegs) PAL_SELECT(0); + + INPAL_START(0); + for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT(); + save->palette_valid = 1; +} + +/* Save state that defines current video mode. */ +static void R128SaveMode(R128SavePtr save) +{ + R128SaveCommonRegisters(save); + R128SaveCrtcRegisters(save); +// if (R128PTR(pScrn)->HasPanelRegs) +// R128SaveFPRegisters(save); + R128SavePLLRegisters(save); + if(chiptype == Rage128) + R128SaveDDARegisters(save); + R128SavePalette(save); + + save->dp_datatype = INREG(R128_DP_DATATYPE); + save->gen_reset_cntl = INREG(R128_GEN_RESET_CNTL); + save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX); + save->amcgpio_en_reg = INREG(R128_AMCGPIO_EN_REG); + save->amcgpio_mask = INREG(R128_AMCGPIO_MASK); +} + +static void R128InitCommonRegisters(R128SavePtr save) +{ + save->ovr_clr = 0; + save->ovr_wid_left_right = 0; + save->ovr_wid_top_bottom = 0; + save->ov0_scale_cntl = 0; + save->mpp_tb_config = 0; + save->mpp_gp_config = 0; + save->subpic_cntl = 0; + save->viph_control = 0; + save->i2c_cntl_1 = 0; + save->gen_int_cntl = 0; + save->cap0_trig_cntl = 0; + save->cap1_trig_cntl = 0; + save->mem_vga_wp_sel = 0; + save->mem_vga_rp_sel = 0; + save->config_cntl = INREG(R128_CONFIG_CNTL); + save->bus_cntl = BusCntl; + save->bus_cntl1 = INREG(R128_BUS_CNTL1); + if(chiptype == Radeon) { + if(save->bus_cntl & RADEON_BUS_READ_BURST) + save->bus_cntl |=RADEON_BUS_RD_DISCARD_EN; + } + + save->amcgpio_en_reg = INREG(R128_AMCGPIO_EN_REG); + save->amcgpio_mask = INREG(R128_AMCGPIO_MASK); + + /* + * If bursts are enabled, turn on discards and aborts + */ + if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST)) + save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN; +} + +/* Define CRTC registers for requested video mode. */ +static Bool R128InitCrtcRegisters(R128SavePtr save, + ModeTiming *mode, ModeInfo *info) +{ + int format; + int hsync_start; + int hsync_wid; + int hsync_fudge; + int vsync_wid; + int bytpp; + int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; + int hsync_fudge_fp[] = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 }; + int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 }; + + dac6bits=0; + + switch (info->bitsPerPixel) { + case 4: format = 1; bytpp = 0; dac6bits = 1; break; + case 8: format = 2; bytpp = 1; dac6bits = 1; break; + case 16: + if(info->greenWeight==5) + format = 3; else format = 4; + bytpp = 2; + break; + case 24: format = 5; bytpp = 3; break; /* RGB */ + case 32: format = 6; bytpp = 4; break; /* xRGB */ + default: + return 0; + } + + if(chiptype==Rage128) { + if (HasPanelRegs) + if (CRTOnly) hsync_fudge = hsync_fudge_fp_crt[format-1]; + else hsync_fudge = hsync_fudge_fp[format-1]; + else hsync_fudge = hsync_fudge_default[format-1]; + } else hsync_fudge = 0; + + save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN + | R128_CRTC_EN + | (format << 8) + | ((mode->flags & DOUBLESCAN) + ? R128_CRTC_DBL_SCAN_EN + : 0) + | ((mode->flags & INTERLACED) + ? R128_CRTC_INTERLACE_EN + : 0)); + + save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | R128_XCRT_CNT_EN | R128_VGA_MEM_PS_EN; + if(chiptype == Radeon) save->crtc_ext_cntl |= R128_CRTC_CRT_ON; + save->dac_cntl = (R128_DAC_MASK_ALL + | R128_DAC_VGA_ADR_EN + | (dac6bits ? 0 : R128_DAC_8BIT_EN)); + + save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + + hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; + + save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & NHSYNC) + ? R128_CRTC_H_SYNC_POL + : 0)); + +#if 1 + /* This works for double scan mode. */ + save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); +#else + /* This is what cce/nbmode.c example code + does -- is this correct? */ + save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay + * ((mode->Flags & DOUBLESCAN) ? 2 : 1) - 1) + << 16)); +#endif + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if(chiptype==Rage128) { + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + } else { + vsync_wid &= 0x1f; + } + + save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->flags & NVSYNC) + ? R128_CRTC_V_SYNC_POL + : 0)); + save->crtc_offset = 0; + +#if 0 + /* The register reference says this bit should be 0, + * but on my RV280 it appears as if it should be 1 + * for changing offset at vertical blank. */ + save->crtc_offset_cntl = 1<<16; +#endif + save->crtc_offset_cntl = INREG(R128_CRTC_OFFSET_CNTL); + + if(chiptype==Rage128) { + save->crtc_pitch = info->width / 8; + } else { + save->crtc_pitch = (((info->width * info->bitsPerPixel) + + ((info->bitsPerPixel * 8) -1)) / + (info->bitsPerPixel * 8)); + } + + save->config_cntl |= R128_CFG_VGA_RAM_EN; + + if(chiptype == Radeon) { + save->crtc_pitch |= save->crtc_pitch<<16; + save->surface_cntl = RADEON_SURF_TRANSLATION_DIS; + + save->dac_cntl2 = INREG(RADEON_DAC_CNTL2); + save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); + save->dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + save->grph_buf_cntl = INREG(RADEON_GRPH_BUF_CNTL); + save->vga_buf_cntl = INREG(RADEON_VGA_BUF_CNTL); + + } + +#ifdef __PPC + /* Change the endianness of the aperture */ + switch (info->bitsPerPixel) { + case 15: + case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break; + case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break; + default: break; + } +#endif + + return 1; +} + +#if 0 +/* Define CRTC registers for requested video mode. */ +static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, + ModeTiming *mode, ModeInfo *info) +{ +#if 0 + int xres = mode->CrtcHDisplay; + int yres = mode->CrtcVDisplay; + float Hratio, Vratio; + + if (CRTOnly) { + save->crtc_ext_cntl |= R128_CRTC_CRT_ON; + save->crtc2_gen_cntl = 0; + save->fp_gen_cntl = orig->fp_gen_cntl; + save->fp_gen_cntl &= ~(R128_FP_FPON | + R128_FP_CRTC_USE_SHADOW_VEND | + R128_FP_CRTC_HORZ_DIV2_EN | + R128_FP_CRTC_HOR_CRT_DIV2_DIS | + R128_FP_USE_SHADOW_EN); + save->fp_gen_cntl |= (R128_FP_SEL_CRTC2 | + R128_FP_CRTC_DONT_SHADOW_VPAR); + save->fp_panel_cntl = orig->fp_panel_cntl & ~R128_FP_DIGON; + save->lvds_gen_cntl = orig->lvds_gen_cntl & ~(R128_LVDS_ON | + R128_LVDS_BLON); + return; + } + + + if (xres > info->PanelXRes) xres = info->PanelXRes; + if (yres > info->PanelYRes) yres = info->PanelYRes; + + Hratio = (float)xres/(float)info->PanelXRes; + Vratio = (float)yres/(float)info->PanelYRes; + + save->fp_horz_stretch = + (((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5)) + & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) | + (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE | + R128_HORZ_FP_LOOP_STRETCH | + R128_HORZ_STRETCH_RESERVED))); + save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN; + if (Hratio == 1.0) save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | + R128_HORZ_STRETCH_ENABLE); + else save->fp_horz_stretch |= (R128_HORZ_STRETCH_BLEND | + R128_HORZ_STRETCH_ENABLE); + + save->fp_vert_stretch = + (((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5)) + & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) | + (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE | + R128_VERT_STRETCH_RESERVED))); + save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN; + if (Vratio == 1.0) save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | + R128_VERT_STRETCH_BLEND); + else save->fp_vert_stretch |= (R128_VERT_STRETCH_ENABLE | + R128_VERT_STRETCH_BLEND); + + save->fp_gen_cntl = (orig->fp_gen_cntl & ~(R128_FP_SEL_CRTC2 | + R128_FP_CRTC_USE_SHADOW_VEND | + R128_FP_CRTC_HORZ_DIV2_EN | + R128_FP_CRTC_HOR_CRT_DIV2_DIS | + R128_FP_USE_SHADOW_EN)); + if (orig->fp_gen_cntl & R128_FP_DETECT_SENSE) { + save->fp_gen_cntl |= (R128_FP_CRTC_DONT_SHADOW_VPAR | + R128_FP_TDMS_EN); + } + + save->fp_panel_cntl = orig->fp_panel_cntl; + save->lvds_gen_cntl = orig->lvds_gen_cntl; + + save->tmds_crc = orig->tmds_crc; + + /* Disable CRT output by disabling CRT output and setting the CRT + DAC to use CRTC2, which we set to 0's. In the future, we will + want to use the dual CRTC capabilities of the R128 to allow both + the flat panel and external CRT to either simultaneously display + the same image or display two different images. */ + save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON; + save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; + save->crtc2_gen_cntl = 0; + + /* WARNING: Be careful about turning on the flat panel */ +#if 1 + save->lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_BLON); +#else + save->fp_panel_cntl |= (R128_FP_DIGON | R128_FP_BLON); + save->fp_gen_cntl |= (R128_FP_FPON); +#endif + + save->fp_crtc_h_total_disp = save->crtc_h_total_disp; + save->fp_crtc_v_total_disp = save->crtc_v_total_disp; + save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; + save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; +#endif +} +#endif + +/* Define PLL registers for requested video mode. */ +static void RADEONInitPLLRegisters(R128SavePtr save, R128PLLPtr pll, + double dot_clock) +{ + unsigned int freq; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + Reference Manual (Technical Reference + Manual P/N RRG-G04100-C Rev. 0.04), page + 3-17 (PLL_DIV_[3:0]). */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 16, 5 }, + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + freq = dot_clock * 100; + + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; + if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + save->pll_output_freq = post_div->divider * freq; + if (save->pll_output_freq >= pll->min_pll_freq + && save->pll_output_freq <= pll->max_pll_freq) break; + } + + if (!post_div->divider) { + save->pll_output_freq = freq; + post_div = &post_divs[0]; + } + + save->dot_clock_freq = freq; + save->feedback_div = R128Div(pll->reference_div * save->pll_output_freq, + pll->reference_freq); + save->post_div = post_div->divider; + + save->ppll_ref_div = pll->reference_div; + save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); + save->htotal_cntl = 0; +} + +static void R128InitPLLRegisters(R128SavePtr save, R128PLLPtr pll, + double dot_clock) +{ + unsigned int freq = dot_clock * 100; + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + Reference Manual (Technical Reference + Manual P/N RRG-G04100-C Rev. 0.04), page + 3-17 (PLL_DIV_[3:0]). */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + /* bitvalue = 5 is reserved */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; + if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + save->pll_output_freq = post_div->divider * freq; + if (save->pll_output_freq >= pll->min_pll_freq + && save->pll_output_freq <= pll->max_pll_freq) break; + } + + save->dot_clock_freq = freq; + save->feedback_div = R128Div(pll->reference_div * save->pll_output_freq, + pll->reference_freq); + save->post_div = post_div->divider; + + save->ppll_ref_div = pll->reference_div; + save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); + save->htotal_cntl = 0; +} + +/* Define DDA registers for requested video mode. */ +static Bool R128InitDDARegisters(R128SavePtr save, + R128PLLPtr pll, ModeInfo *info) +{ + int DisplayFifoWidth = 128; + int DisplayFifoDepth = 32; + int XclkFreq; + int VclkFreq; + int XclksPerTransfer; + int XclksPerTransferPrecise; + int UseablePrecision; + int Roff; + int Ron; + + XclkFreq = pll->xclk; + + VclkFreq = R128Div(pll->reference_freq * save->feedback_div, + pll->reference_div * save->post_div); + + XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, + VclkFreq * (info->bytesPerPixel * 8)); + + UseablePrecision = R128MinBits(XclksPerTransfer) + 1; + + XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) + << (11 - UseablePrecision), + VclkFreq * (info->bytesPerPixel * 8)); + + Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); + + Ron = (4 * ram[r128_ramtype].MB + + 3 * (((ram[r128_ramtype].Trcd - 2)>0)?(ram[r128_ramtype].Trcd - 2):0) + + 2 * ram[r128_ramtype].Trp + + ram[r128_ramtype].Twr + + ram[r128_ramtype].CL + + ram[r128_ramtype].Tr2w + + XclksPerTransfer) << (11 - UseablePrecision); + + if (Ron + ram[r128_ramtype].Rloop >= Roff) { + return 0; + } + + save->dda_config = (XclksPerTransferPrecise + | (UseablePrecision << 16) + | (ram[r128_ramtype].Rloop << 20)); + + save->dda_on_off = (Ron << 16) | Roff; + + return 1; +} + + +/* Define initial palette for requested video mode. This doesn't do + anything for XFree86 4.0. */ +static void R128InitPalette(R128SavePtr save) +{ + int i; + save->palette_valid = 1; + for(i=0;i<256;i++) save->palette[i]=i | (i<<8) | (i<<16); +} + +/* Define registers for a requested video mode. */ +static Bool R128Init(ModeTiming *mode, ModeInfo *info, R128SavePtr save) +{ + double dot_clock; + + dot_clock = mode->pixelClock/1000.0; + + R128InitCommonRegisters(save); + if (!R128InitCrtcRegisters(save, mode, info)) return 0; +#if 0 + if (HasPanelRegs) + R128InitFPRegisters(&info->SavedReg, save, mode, info); +#endif + switch(chiptype) { + case Rage128: + R128InitPLLRegisters(save, &pll, dot_clock); + break; + case Radeon: + RADEONInitPLLRegisters(save, &pll, dot_clock); + break; + } + + if(chiptype == Rage128) { + if (!R128InitDDARegisters(save, &pll, info)) + return 0; + } +// if (!info->PaletteSavedOnVT) + R128InitPalette(save); + + return 1; +} + +static int r128_init(int, int, int); +static void r128_unlock(void); +static void r128_lock(void); + +static int r128_memory; +static unsigned int r128_linear_base, r128_mmio_base; + +static CardSpecs *cardspecs; + +static void r128_setpage(int page) +{ + page*=2; + OUTREG(R128_MEM_VGA_WP_SEL, page | ((page+1)<<16)); + OUTREG(R128_MEM_VGA_RP_SEL, page | ((page+1)<<16)); +} + +/* Fill in chipset specific mode information */ +static void r128_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = r128_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = r128_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + modeinfo->flags |= HAVE_EXT_SET; + + if (modeinfo->bytesperpixel >= 1) { + if(r128_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int r128_saveregs(unsigned char regs[]) +{ + r128_unlock(); + R128SaveMode((R128SavePtr)(regs+VGA_TOTAL_REGS)); + return R128_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void r128_setregs(const unsigned char regs[], int mode) +{ + r128_unlock(); + + R128RestoreMode((R128SavePtr)(regs+VGA_TOTAL_REGS)); + + R128Unblank(); +} +/* Return nonzero if mode is available */ + +static int r128_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + /* On radeon's 320x200x256 (INT13) only works with the real banked mem */ + if ((chiptype==Radeon) && (mode==G320x200x256) && __svgalib_emulatepage) + return 0; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (r128_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +/* Local, called by r128_setmode(). */ + +static void r128_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ /* long k; */ + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + R128Init(modetiming, modeinfo, (R128SavePtr)(moderegs+VGA_TOTAL_REGS)); + + return ; +} + + +static int r128_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + //OUTREG(R128_DAC_CNTL, INREG(R128_DAC_CNTL) & ~R128_DAC_8BIT_EN); + dac6bits=1; + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + + if (!r128_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(R128_TOTAL_REGS); + + r128_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + r128_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ +static void r128_unlock(void) +{ + __svgalib_outcrtc(0x11, __svgalib_incrtc(0x11) & 0x7f); +} + +static void r128_lock(void) +{ +} + +/* Indentify chipset, initialize and return non-zero if detected */ +static int r128_test(void) +{ + return !r128_init(0,0,0); +} + + +/* Set display start address (not for 16 color modes) */ + +static void r128_setdisplaystart(int address) +{ +// int naddress=address >> 2; +// __svgalib_outcrtc(0x0c,(naddress>>8)&0xff); +// __svgalib_outcrtc(0x0d,(naddress)&0xff); + OUTREG(R128_CRTC_OFFSET, address); +} + +/* Set logical scanline length (usually multiple of 8) */ + +static void r128_setlogicalwidth(int width) +{ + int offset = width >> 3; + + if(CI.bytesperpixel>1) { + offset = offset/CI.bytesperpixel; + } + __svgalib_outcrtc(0x13,offset&0xff); + OUTREG(R128_CRTC_PITCH, offset); +} + +static int r128_linear(int op, int param) +{ + if (op==LINEAR_DISABLE || op==LINEAR_ENABLE) return 0; + if (op==LINEAR_QUERY_BASE) return __svgalib_linear_mem_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int r128_match_programmable_clock(int clock) +{ +return clock ; +} + +static int r128_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int r128_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +static unsigned int cur_colors[16*2]; + +static int r128_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j; + unsigned int *b3; + unsigned int l1, l2; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + OUTREG(R128_CRTC_GEN_CNTL,INREG(R128_CRTC_GEN_CNTL) & ~R128_CRTC_CUR_EN ); + break; + case CURSOR_SHOW: + OUTREG(R128_CRTC_GEN_CNTL,INREG(R128_CRTC_GEN_CNTL) | R128_CRTC_CUR_EN ); + break; + case CURSOR_POSITION: + OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | 0); + OUTREG(R128_CUR_HORZ_VERT_POSN, p2|(p1<<16)); + break; + case CURSOR_SELECT: + i=r128_memory*1024-(p1+1)*4096; + OUTREG(R128_CUR_OFFSET,i); + OUTREG(R128_CUR_CLR0,cur_colors[p1*2]); + OUTREG(R128_CUR_CLR1,cur_colors[p1*2+1]); + break; + case CURSOR_IMAGE: + i=r128_memory*1024-(p1+1)*4096; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*2]=p3; + cur_colors[p1*2+1]=p4; + + for(j=0;j<32;j++) { + l1=*(b3+j); /* source */ + l2=*(b3+32+j); /* mask */ + l1=BE32(l1); + l2=BE32(l2); + *(unsigned int *)(LINEAR_POINTER+i+16*j)=~l2; + *(unsigned int *)(LINEAR_POINTER+i+16*j+4)=0xffffffff; + *(unsigned int *)(LINEAR_POINTER+i+16*j+8)=l1&l2; + *(unsigned int *)(LINEAR_POINTER+i+16*j+12)=0; + *(unsigned int *)(LINEAR_POINTER+i+512+16*j)=0xffffffff; + *(unsigned int *)(LINEAR_POINTER+i+512+16*j+4)=0xffffffff; + *(unsigned int *)(LINEAR_POINTER+i+512+16*j+8)=0; + *(unsigned int *)(LINEAR_POINTER+i+512+16*j+12)=0; + } + break; + } + break; + } + return 0; +} + +static Emulation r128_emul = +{ + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* screenoff */ + 0, /* screenon */ + R128WaitForVerticalSync, /* waitretrace */ +}; + +static int r128_ext_set( unsigned what, va_list params ) +{ + int param2; + param2 = va_arg(params, int); + + switch (what) { + case VGA_EXT_AVAILABLE: + switch (param2) { + case VGA_AVAIL_SET: + return VGA_EXT_AVAILABLE | VGA_EXT_SET | VGA_EXT_CLEAR | VGA_EXT_RESET; + case VGA_AVAIL_ACCEL: + return 0; + case VGA_AVAIL_FLAGS: + return VGA_CLUT8; + } + break; + case VGA_EXT_SET: + if (param2 & VGA_CLUT8) OUTREGP( R128_DAC_CNTL, R128_DAC_8BIT_EN, R128_DAC_MASK_ALL ); + return 1; + break; + } + return 0; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_r128_driverspecs = +{ + r128_saveregs, + r128_setregs, + r128_unlock, + r128_lock, + r128_test, + r128_init, + r128_setpage, + NULL, + NULL, + r128_setmode, + r128_modeavailable, + r128_setdisplaystart, + r128_setlogicalwidth, + r128_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + r128_ext_set, /* ext_set */ + 0, /* accel */ + r128_linear, + 0, /* accelspecs, filled in during init. */ + &r128_emul, /* Emulation */ + r128_cursor, +}; + +#define VENDOR_ID 0x1002 + +/* Initialize chipset (called after detection) */ +static int r128_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0, NOBIOS=0; + unsigned char *BIOS_POINTER; + + r128_memory=0; + chiptype=-1; + if (force) { + r128_memory = par1; + chiptype = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + if(!found) return 1; + + id=(buf[0]>>16)&0xffff; + + if( (id==0x4c45) || + (id==0x4c46) || + (id==0x4d46) || + (id==0x4d4c) || + ((id>>8)==0x50) || + ((id>>8)==0x52) || + ((id>>8)==0x53) || + ((id>>4)==0x544) || + ((id>>4)==0x545) || + 0) chiptype=Rage128; + + if( + (id==0x4242) || + (id==0x4336) || + (id==0x4337) || + (id==0x4437) || + (id==0x7c37) || + ((id>=0x4c57)&&(id<0x4d00)) || + ((id>>4)==0x546) || + ((id>>8)==0x31) || + ((id>>8)==0x3E) || + ((id>>8)==0x41) || + ((id>>8)==0x49) || + ((id>>8)==0x4a) || + ((id>>8)==0x4e) || + ((id>>8)==0x51) || + ((id>>8)==0x55) || + ((id>>8)==0x58) || + ((id>>8)==0x59) || + ((id>>8)==0x5b) || + ((id>>8)==0x5c) || + ((id>>8)==0x5d) || + ((id>>8)==0x5e) || + ((id>>8)==0x71) + ) chiptype = Radeon; + + if( (id == 0x4158) || + (id == 0x5354) + ) return 1; /* Mach64/Mach32 */ + + if(chiptype==-1) return 1; + + ChipFamily = CHIP_FAMILY_LEGACY; + if(chiptype == Radeon) { + switch(id) { + case PCI_CHIP_RADEON_LY: + case PCI_CHIP_RADEON_LZ: + IsMobility = TRUE; + ChipFamily = CHIP_FAMILY_RV100; + break; + + case PCI_CHIP_RV100_QY: + case PCI_CHIP_RV100_QZ: + case PCI_CHIP_RN50_515E: /* RN50 is based on the RV100 but 3D isn't guaranteed to work. YMMV. */ + case PCI_CHIP_RN50_5969: + ChipFamily = CHIP_FAMILY_RV100; + + break; + + case PCI_CHIP_RS100_4336: + IsMobility = TRUE; + case PCI_CHIP_RS100_4136: + ChipFamily = CHIP_FAMILY_RS100; + IsIGP = TRUE; + break; + + case PCI_CHIP_RS200_4337: + IsMobility = TRUE; + case PCI_CHIP_RS200_4137: + ChipFamily = CHIP_FAMILY_RS200; + IsIGP = TRUE; + break; + + case PCI_CHIP_RS250_4437: + IsMobility = TRUE; + case PCI_CHIP_RS250_4237: + ChipFamily = CHIP_FAMILY_RS200; + IsIGP = TRUE; + break; + + case PCI_CHIP_R200_BB: + case PCI_CHIP_R200_BC: + case PCI_CHIP_R200_QH: + case PCI_CHIP_R200_QL: + case PCI_CHIP_R200_QM: + ChipFamily = CHIP_FAMILY_R200; + break; + + case PCI_CHIP_RADEON_LW: + case PCI_CHIP_RADEON_LX: + IsMobility = TRUE; + case PCI_CHIP_RV200_QW: /* RV200 desktop */ + case PCI_CHIP_RV200_QX: + ChipFamily = CHIP_FAMILY_RV200; + break; + + case PCI_CHIP_RV250_Ld: + case PCI_CHIP_RV250_Lf: + case PCI_CHIP_RV250_Lg: + IsMobility = TRUE; + case PCI_CHIP_RV250_If: + case PCI_CHIP_RV250_Ig: + ChipFamily = CHIP_FAMILY_RV250; + break; + + case PCI_CHIP_RS300_5835: + case PCI_CHIP_RS350_7835: + IsMobility = TRUE; + case PCI_CHIP_RS300_5834: + case PCI_CHIP_RS350_7834: + ChipFamily = CHIP_FAMILY_RS300; + IsIGP = TRUE; + HasSingleDAC = TRUE; + break; + + case PCI_CHIP_RV280_5C61: + case PCI_CHIP_RV280_5C63: + IsMobility = TRUE; + case PCI_CHIP_RV280_5960: + case PCI_CHIP_RV280_5961: + case PCI_CHIP_RV280_5962: + case PCI_CHIP_RV280_5964: + case PCI_CHIP_RV280_5965: + ChipFamily = CHIP_FAMILY_RV280; + break; + + case PCI_CHIP_R300_AD: + case PCI_CHIP_R300_AE: + case PCI_CHIP_R300_AF: + case PCI_CHIP_R300_AG: + case PCI_CHIP_R300_ND: + case PCI_CHIP_R300_NE: + case PCI_CHIP_R300_NF: + case PCI_CHIP_R300_NG: + ChipFamily = CHIP_FAMILY_R300; + break; + + case PCI_CHIP_RV350_NP: + case PCI_CHIP_RV350_NQ: + case PCI_CHIP_RV350_NR: + case PCI_CHIP_RV350_NS: + case PCI_CHIP_RV350_NT: + case PCI_CHIP_RV350_NV: + IsMobility = TRUE; + case PCI_CHIP_RV350_AP: + case PCI_CHIP_RV350_AQ: + case PCI_CHIP_RV360_AR: + case PCI_CHIP_RV350_AS: + case PCI_CHIP_RV350_AT: + case PCI_CHIP_RV350_AV: + case PCI_CHIP_RV350_4155: + ChipFamily = CHIP_FAMILY_RV350; + break; + + case PCI_CHIP_R350_AH: + case PCI_CHIP_R350_AI: + case PCI_CHIP_R350_AJ: + case PCI_CHIP_R350_AK: + case PCI_CHIP_R350_NH: + case PCI_CHIP_R350_NI: + case PCI_CHIP_R350_NK: + case PCI_CHIP_R360_NJ: + ChipFamily = CHIP_FAMILY_R350; + break; + + case PCI_CHIP_RV380_3150: + case PCI_CHIP_RV380_3154: + IsMobility = TRUE; + case PCI_CHIP_RV380_3E50: + case PCI_CHIP_RV380_3E54: + ChipFamily = CHIP_FAMILY_RV380; + break; + + case PCI_CHIP_RV370_5460: + case PCI_CHIP_RV370_5464: + IsMobility = TRUE; + case PCI_CHIP_RV370_5B60: + case PCI_CHIP_RV370_5B62: + case PCI_CHIP_RV370_5B64: + case PCI_CHIP_RV370_5B65: + ChipFamily = CHIP_FAMILY_RV380; + break; + + case PCI_CHIP_RS400_5A42: + case PCI_CHIP_RC410_5A62: + case PCI_CHIP_RS480_5955: + case PCI_CHIP_RS482_5975: + IsMobility = TRUE; + case PCI_CHIP_RS400_5A41: + case PCI_CHIP_RC410_5A61: + case PCI_CHIP_RS480_5954: + case PCI_CHIP_RS482_5974: + ChipFamily = CHIP_FAMILY_RV380; /*CHIP_FAMILY_RS400*/ + /*IsIGP = TRUE;*/ /* ??? */ + /*HasSingleDAC = TRUE;*/ /* ??? */ + break; + + case PCI_CHIP_RV410_564A: + case PCI_CHIP_RV410_564B: + case PCI_CHIP_RV410_5652: + case PCI_CHIP_RV410_5653: + IsMobility = TRUE; + case PCI_CHIP_RV410_5E48: + case 0x5E49: + case PCI_CHIP_RV410_5E4A: + case PCI_CHIP_RV410_5E4B: + case PCI_CHIP_RV410_5E4C: + case PCI_CHIP_RV410_5E4D: + case PCI_CHIP_RV410_5E4F: + case 0x5E6B: + case 0x5E6D: + ChipFamily = CHIP_FAMILY_R420; /* CHIP_FAMILY_RV410*/ + break; + + case PCI_CHIP_R420_JN: + IsMobility = TRUE; + case PCI_CHIP_R420_JH: + case PCI_CHIP_R420_JI: + case PCI_CHIP_R420_JJ: + case PCI_CHIP_R420_JK: + case PCI_CHIP_R420_JL: + case PCI_CHIP_R420_JM: + case PCI_CHIP_R420_JP: + case PCI_CHIP_R420_4A4F: + ChipFamily = CHIP_FAMILY_R420; + break; + + case PCI_CHIP_R423_UH: + case PCI_CHIP_R423_UI: + case PCI_CHIP_R423_UJ: + case PCI_CHIP_R423_UK: + case PCI_CHIP_R423_UQ: + case PCI_CHIP_R423_UR: + case PCI_CHIP_R423_UT: + case PCI_CHIP_R423_5D57: + case PCI_CHIP_R423_5550: + ChipFamily = CHIP_FAMILY_R420; + break; + + case PCI_CHIP_R430_5D49: + case PCI_CHIP_R430_5D4A: + case PCI_CHIP_R430_5D48: + IsMobility = TRUE; + case PCI_CHIP_R430_554F: + case PCI_CHIP_R430_554D: + case PCI_CHIP_R430_554E: + case PCI_CHIP_R430_554C: + ChipFamily = CHIP_FAMILY_R420; /*CHIP_FAMILY_R430*/ + break; + + case PCI_CHIP_R480_5D4C: + case PCI_CHIP_R480_5D50: + case PCI_CHIP_R480_5D4E: + case PCI_CHIP_R480_5D4F: + case PCI_CHIP_R480_5D52: + case PCI_CHIP_R480_5D4D: + case PCI_CHIP_R481_4B4B: + case PCI_CHIP_R481_4B4A: + case PCI_CHIP_R481_4B49: + case PCI_CHIP_R481_4B4C: + case 0x7105: + case 0x7109: + ChipFamily = CHIP_FAMILY_R420; /*CHIP_FAMILY_R480*/ + break; + + default: + /* Original Radeon/7200 */ + ChipFamily = CHIP_FAMILY_RADEON; + HasCRTC2 = FALSE; + } + } + + r128_linear_base=buf[4]&0xffffff00; + r128_mmio_base=buf[6]&0xffffff00; + + __svgalib_mmio_size=16*1024; + __svgalib_mmio_base= r128_mmio_base; + map_mmio(); + + if(!r128_memory) r128_memory = INREG(R128_CONFIG_MEMSIZE) / 1024; + + BusCntl = INREG(R128_BUS_CNTL); + HasPanelRegs = 0; + CRTOnly = 1; + r128_ramtype = 1; + + ChipErrata = 0; + + if (ChipFamily == CHIP_FAMILY_R300 && + (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) + == RADEON_CFG_ATI_REV_A11) + ChipErrata |= CHIP_ERRATA_R300_CG; + + if (ChipFamily == CHIP_FAMILY_RV200 || + ChipFamily == CHIP_FAMILY_RS200) + ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS; + + if (ChipFamily == CHIP_FAMILY_RV100 || + ChipFamily == CHIP_FAMILY_RS100 || + ChipFamily == CHIP_FAMILY_RS200) + ChipErrata |= CHIP_ERRATA_PLL_DELAY; + +// RADEONProbePLLParameters(); + +#ifdef __i386__ + if(__svgalib_secondary) +#endif + NOBIOS=1; + + pll.min_pll_freq = 0; + +#define R128_BIOS16(x) (*(unsigned short *)(BIOS_POINTER + x)) +#define R128_BIOS32(x) (*(unsigned int *)(BIOS_POINTER + x)) + if(!NOBIOS) { + uint16_t bios_header; + uint16_t pll_info_block; + BIOS_POINTER = mmap(0, 64*1024, PROT_READ | PROT_WRITE, MAP_SHARED, __svgalib_mem_fd, + 0xc0000); + bios_header = R128_BIOS16(0x48); + pll_info_block = R128_BIOS16(bios_header + 0x30); + pll.reference_freq = R128_BIOS16(pll_info_block + 0x0e); + pll.reference_div = R128_BIOS16(pll_info_block + 0x10); + pll.min_pll_freq = R128_BIOS32(pll_info_block + 0x12); + pll.max_pll_freq = R128_BIOS32(pll_info_block + 0x16); + pll.xclk = R128_BIOS16(pll_info_block + 0x08); + munmap(BIOS_POINTER, 64*1024); + } + if((pll.min_pll_freq<2500) || (pll.min_pll_freq>1000000)) { + int x_mpll_ref_fb_div, xclk_cntl, Nx, M, tmp; + int PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12}; + + switch(chiptype) { + case Rage128: + pll.reference_freq = 2950; + pll.min_pll_freq = 12500; + pll.max_pll_freq = 25000; + pll.reference_div = INPLL(R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK; + + x_mpll_ref_fb_div = INPLL(R128_X_MPLL_REF_FB_DIV); + xclk_cntl = INPLL(R128_XCLK_CNTL) & 0x7; + Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8; + M = (x_mpll_ref_fb_div & 0x0000FF); + pll.xclk = R128Div((2 * Nx * pll.reference_freq), + (M * PostDivSet[xclk_cntl])); + break; + case Radeon: + pll.reference_freq = IsIGP ? 1432 : 2700; + pll.min_pll_freq = 20000; /* X says 12500 */ + pll.max_pll_freq = 35000; + pll.reference_div = 67; + if(ChipFamily==CHIP_FAMILY_R420) { + pll.min_pll_freq = 20000; + pll.max_pll_freq = 50000; + } + tmp = INPLL(R128_PPLL_REF_DIV); + if (IS_R300_VARIANT || (ChipFamily == CHIP_FAMILY_RS300)) { + pll.reference_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> + R300_PPLL_REF_DIV_ACC_SHIFT; + } else { + pll.reference_div = tmp & R128_PPLL_REF_DIV_MASK; + } + if (pll.reference_div < 2) pll.reference_div = 12; + + break; + } + } +#if 0 +fprintf(stderr,"pll: %i %i %i %i %i\n",pll.reference_freq,pll.reference_div, + pll.min_pll_freq, pll.max_pll_freq, pll.xclk); +#endif + + r128_mapio(); + + if (__svgalib_driver_report) { + fprintf(stderr,"Using ATI R128/Radeon driver, %s with %iMB found.\n", + familynames[chiptype*ChipFamily],r128_memory/1024); + }; + + __svgalib_modeinfo_linearset = LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = r128_memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 250000; + cardspecs->maxPixelClock16bpp = 250000; + cardspecs->maxPixelClock24bpp = 250000; + cardspecs->maxPixelClock32bpp = 250000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4080; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = r128_map_clock; + cardspecs->mapHorizontalCrtc = r128_map_horizontal_crtc; + cardspecs->matchProgrammableClock=r128_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_r128_driverspecs; + __svgalib_linear_mem_base=r128_linear_base; + __svgalib_linear_mem_size=r128_memory*0x400; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + if(chiptype==Radeon) { +// __svgalib_emulatepage = 2; + } + + return 0; +} + +static void xf86getsecs(long * secs, long * usecs) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + if (secs) + *secs = tv.tv_sec; + if (usecs) + *usecs= tv.tv_usec; + + return; +} + +#define xf86DrvMsg(a,b, ...) printf(__VA_ARGS__) + +static int RADEONProbePLLParameters(void) +{ + R128PLLRec ppll; + R128PLLPtr pll = &ppll; + unsigned char ppll_div_sel; + unsigned mpll_fb_div, spll_fb_div, M; + unsigned xclk, tmp, ref_div; + int hTotal, vTotal, num, denom, m, n; + float hz, prev_xtal, vclk, xtal, mpll, spll; + long start_secs, start_usecs, stop_secs, stop_usecs, total_usecs; + long to1_secs, to1_usecs, to2_secs, to2_usecs; + unsigned int f1, f2, f3; + int tries = 0; + + prev_xtal = 0; + again: + xtal = 0; + if (++tries > 10) + goto failed; + + xf86getsecs(&to1_secs, &to1_usecs); + f1 = INREG(RADEON_CRTC_CRNT_FRAME); + for (;;) { + f2 = INREG(RADEON_CRTC_CRNT_FRAME); + if (f1 != f2) + break; + xf86getsecs(&to2_secs, &to2_usecs); + if ((to2_secs - to1_secs) > 1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Clock not counting...\n"); + goto failed; + } + } + xf86getsecs(&start_secs, &start_usecs); + for(;;) { + f3 = INREG(RADEON_CRTC_CRNT_FRAME); + if (f3 != f2) + break; + xf86getsecs(&to2_secs, &to2_usecs); + if ((to2_secs - start_secs) > 1) + goto failed; + } + xf86getsecs(&stop_secs, &stop_usecs); + + if ((stop_secs - start_secs) != 0) + goto again; + total_usecs = abs(stop_usecs - start_usecs); + if (total_usecs == 0) + goto again; + hz = 1000000.0/(float)total_usecs; + + hTotal = ((INREG(R128_CRTC_H_TOTAL_DISP) & 0x3ff) + 1) * 8; + vTotal = ((INREG(R128_CRTC_V_TOTAL_DISP) & 0xfff) + 1); + vclk = (float)(hTotal * (float)(vTotal * hz)); + + switch((INPLL( R128_PPLL_REF_DIV) & 0x30000) >> 16) { + case 0: + default: + num = 1; + denom = 1; + break; + case 1: + n = ((INPLL( R128_X_MPLL_REF_FB_DIV) >> 16) & 0xff); + m = (INPLL( R128_X_MPLL_REF_FB_DIV) & 0xff); + num = 2*n; + denom = 2*m; + break; + case 2: + n = ((INPLL( R128_X_MPLL_REF_FB_DIV) >> 8) & 0xff); + m = (INPLL( R128_X_MPLL_REF_FB_DIV) & 0xff); + num = 2*n; + denom = 2*m; + break; + } + + ppll_div_sel = INREG8(R128_CLOCK_CNTL_INDEX + 1) & 0x3; + RADEONPllErrataAfterIndex(); + + n = (INPLL( R128_PPLL_DIV_0 + ppll_div_sel) & 0x7ff); + m = (INPLL( R128_PPLL_REF_DIV) & 0x3ff); + + num *= n; + denom *= m; + + switch ((INPLL( R128_PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) { + case 1: + denom *= 2; + break; + case 2: + denom *= 4; + break; + case 3: + denom *= 8; + break; + case 4: + denom *= 3; + break; + case 6: + denom *= 6; + break; + case 7: + denom *= 12; + break; + } + + xtal = (int)(vclk *(float)denom/(float)num); + + if ((xtal > 26900000) && (xtal < 27100000)) + xtal = 2700; + else if ((xtal > 14200000) && (xtal < 14400000)) + xtal = 1432; + else if ((xtal > 29400000) && (xtal < 29600000)) + xtal = 2950; + else + goto again; + failed: + if (xtal == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to probe xtal value ! " + "Using default 27Mhz\n"); + xtal = 2700; + } else { + if (prev_xtal == 0) { + prev_xtal = xtal; + tries = 0; + goto again; + } else if (prev_xtal != xtal) { + prev_xtal = 0; + goto again; + } + } + + tmp = INPLL( R128_X_MPLL_REF_FB_DIV); + ref_div = INPLL( R128_PPLL_REF_DIV) & 0x3ff; + + /* Some sanity check based on the BIOS code .... */ +#if 0 + if (ref_div < 2) { + CARD32 tmp; + tmp = INPLL( R128_PPLL_REF_DIV); + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300)) + ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> + R300_PPLL_REF_DIV_ACC_SHIFT; + else + ref_div = tmp & R128_PPLL_REF_DIV_MASK; + if (ref_div < 2) + ref_div = 12; + } +#endif + /* Calculate "base" xclk straight from MPLL, though that isn't + * really useful (hopefully). This isn't called XCLK anymore on + * radeon's... + */ + mpll_fb_div = (tmp & 0xff00) >> 8; + spll_fb_div = (tmp & 0xff0000) >> 16; + M = (tmp & 0xff); + xclk = R128Div((2 * mpll_fb_div * xtal), (M)); + + /* + * Calculate MCLK based on MCLK-A + */ + mpll = (2.0 * (float)mpll_fb_div * (xtal / 100.0)) / (float)M; + spll = (2.0 * (float)spll_fb_div * (xtal / 100.0)) / (float)M; + + tmp = INPLL( R128_MCLK_CNTL) & 0x7; + switch(tmp) { + case 1: mclk = mpll; break; + case 2: mclk = mpll / 2.0; break; + case 3: mclk = mpll / 4.0; break; + case 4: mclk = mpll / 8.0; break; + case 7: mclk = spll; break; + default: + mclk = 200.00; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported MCLKA source" + " setting %d, can't probe MCLK value !\n", tmp); + } + + /* + * Calculate SCLK + */ + tmp = INPLL( RADEON_SCLK_CNTL) & 0x7; + switch(tmp) { + case 1: sclk = spll; break; + case 2: sclk = spll / 2.0; break; + case 3: sclk = spll / 4.0; break; + case 4: sclk = spll / 8.0; break; + case 7: sclk = mpll; + default: + sclk = 200.00; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported SCLK source" + " setting %d, can't probe SCLK value !\n", tmp); + } + + /* we're done, hopefully these are sane values */ + pll->reference_div = ref_div; + pll->xclk = xclk; + pll->reference_freq = xtal; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probed PLL values: xtal: %f Mhz, " + "sclk: %f Mhz, mclk: %f Mhz\n", xtal/100.0, sclk, mclk); + + return 1; +} + + diff --git a/src/drivers/r128_reg.h b/src/drivers/r128_reg.h new file mode 100644 index 0000000..056172b --- /dev/null +++ b/src/drivers/r128_reg.h @@ -0,0 +1,1519 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.6 2000/12/12 17:17:13 dawes Exp $ */ +/* + * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, + * Precision Insight, Inc., Cedar Park, Texas, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX + * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Authors: + * Rickard E. Faith + * Kevin E. Martin + * Gareth Hughes + * + * References: + * + * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical + * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April + * 1999. + * + * RAGE 128 Software Development Manual (Technical Reference Manual P/N + * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. + * + */ + +#ifndef _R128_REG_H_ +#define _R128_REG_H_ + +#define R128_TIMEOUT 2000000 + +#define MMIO_IN8(dummy, addr) v_readb(addr) +#define MMIO_IN16(dummy, addr) v_readw(addr) +#define MMIO_IN32(dummy, addr) LE32(v_readl(addr)) + +#define MMIO_OUT8(dummy, addr, val) v_writeb(val, addr) +#define MMIO_OUT16(dummy, addr, val) v_writew(val, addr) +#define MMIO_OUT32(dummy, addr, val) v_writel(LE32(val), addr) + + /* Memory mapped register access macros */ +#define INREG8(addr) MMIO_IN8(R128MMIO, addr) +#define INREG16(addr) MMIO_IN16(R128MMIO, addr) +#define INREG(addr) MMIO_IN32(R128MMIO, addr) +#define OUTREG8(addr, val) MMIO_OUT8(R128MMIO, addr, val) +#define OUTREG16(addr, val) MMIO_OUT16(R128MMIO, addr, val) +#define OUTREG(addr, val) MMIO_OUT32(R128MMIO, addr, val) + +#if 0 +#define R128_BIOS8(v) (VBIOS[v]) +#define R128_BIOS16(v) (VBIOS[v] | \ + (VBIOS[(v) + 1] << 8)) +#define R128_BIOS32(v) (VBIOS[v] | \ + (VBIOS[(v) + 1] << 8) | \ + (VBIOS[(v) + 2] << 16) | \ + (VBIOS[(v) + 3] << 24)) +#endif + +#define OUTREGP(addr, val, mask) \ + do { \ + uint32_t tmp = INREG(addr); \ + tmp &= (mask); \ + tmp |= ((val) & ~(mask)); \ + OUTREG(addr, tmp); \ + } while (0) + +#define INPLL(addr) R128INPLL(addr) + +#define OUTPLL(addr, val) \ + do { \ + OUTREG8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x3f) | R128_PLL_WR_EN); \ + OUTREG(R128_CLOCK_CNTL_DATA, val); \ + } while (0) + +#define OUTPLLP(addr, val, mask) \ + do { \ + uint32_t tmp = INPLL(addr); \ + tmp &= (mask); \ + tmp |= ((val) & ~(mask)); \ + OUTPLL(addr, tmp); \ + } while (0) + +#define OUTPAL_START(idx) \ + do { \ + OUTREG8(R128_PALETTE_INDEX, (idx)); \ + } while (0) + +#define OUTPAL_NEXT(r, g, b) \ + do { \ + OUTREG(R128_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \ + } while (0) + +#define OUTPAL_NEXT_uint32_t(v) \ + do { \ + OUTREG(R128_PALETTE_DATA, (v & 0x00ffffff)); \ + } while (0) + +#define OUTPAL(idx, r, g, b) \ + do { \ + OUTPAL_START((idx)); \ + OUTPAL_NEXT((r), (g), (b)); \ + } while (0) + +#define INPAL_START(idx) \ + do { \ + OUTREG(R128_PALETTE_INDEX, (idx) << 16); \ + } while (0) + +#define INPAL_NEXT() INREG(R128_PALETTE_DATA) + +#define PAL_SELECT(idx) \ + do { \ + if (idx) { \ + OUTREG(R128_DAC_CNTL, INREG(R128_DAC_CNTL) | \ + R128_DAC_PALETTE_ACC_CTL); \ + } else { \ + OUTREG(R128_DAC_CNTL, INREG(R128_DAC_CNTL) & \ + ~R128_DAC_PALETTE_ACC_CTL); \ + } \ + } while (0) + +#define R128_ADAPTER_ID 0x0f2c /* PCI */ +#define R128_AGP_APER_OFFSET 0x0178 +#define R128_AGP_BASE 0x0170 +#define R128_AGP_CNTL 0x0174 +# define R128_AGP_APER_SIZE_256MB (0x00 << 0) +# define R128_AGP_APER_SIZE_128MB (0x20 << 0) +# define R128_AGP_APER_SIZE_64MB (0x30 << 0) +# define R128_AGP_APER_SIZE_32MB (0x38 << 0) +# define R128_AGP_APER_SIZE_16MB (0x3c << 0) +# define R128_AGP_APER_SIZE_8MB (0x3e << 0) +# define R128_AGP_APER_SIZE_4MB (0x3f << 0) +# define R128_AGP_APER_SIZE_MASK (0x3f << 0) +#define R128_AGP_CNTL_B 0x0b44 +#define R128_AGP_COMMAND 0x0f58 /* PCI */ +#define R128_AGP_PLL_CNTL 0x0010 /* PLL */ +#define R128_AGP_STATUS 0x0f54 /* PCI */ +# define R128_AGP_1X_MODE 0x01 +# define R128_AGP_2X_MODE 0x02 +# define R128_AGP_4X_MODE 0x04 +# define R128_AGP_MODE_MASK 0x07 +#define R128_AMCGPIO_A_REG 0x01a0 +#define R128_AMCGPIO_EN_REG 0x01a8 +#define R128_AMCGPIO_MASK 0x0194 +#define R128_AMCGPIO_Y_REG 0x01a4 +#define R128_ATTRDR 0x03c1 /* VGA */ +#define R128_ATTRDW 0x03c0 /* VGA */ +#define R128_ATTRX 0x03c0 /* VGA */ +#define R128_AUX_SC_CNTL 0x1660 +# define R128_AUX1_SC_EN (1 << 0) +# define R128_AUX1_SC_MODE_OR (0 << 1) +# define R128_AUX1_SC_MODE_NAND (1 << 1) +# define R128_AUX2_SC_EN (1 << 2) +# define R128_AUX2_SC_MODE_OR (0 << 3) +# define R128_AUX2_SC_MODE_NAND (1 << 3) +# define R128_AUX3_SC_EN (1 << 4) +# define R128_AUX3_SC_MODE_OR (0 << 5) +# define R128_AUX3_SC_MODE_NAND (1 << 5) +#define R128_AUX1_SC_BOTTOM 0x1670 +#define R128_AUX1_SC_LEFT 0x1664 +#define R128_AUX1_SC_RIGHT 0x1668 +#define R128_AUX1_SC_TOP 0x166c +#define R128_AUX2_SC_BOTTOM 0x1680 +#define R128_AUX2_SC_LEFT 0x1674 +#define R128_AUX2_SC_RIGHT 0x1678 +#define R128_AUX2_SC_TOP 0x167c +#define R128_AUX3_SC_BOTTOM 0x1690 +#define R128_AUX3_SC_LEFT 0x1684 +#define R128_AUX3_SC_RIGHT 0x1688 +#define R128_AUX3_SC_TOP 0x168c +#define R128_AUX_WINDOW_HORZ_CNTL 0x02d8 +#define R128_AUX_WINDOW_VERT_CNTL 0x02dc + +#define R128_BASE_CODE 0x0f0b +#define R128_BIOS_0_SCRATCH 0x0010 +#define R128_BIOS_1_SCRATCH 0x0014 +#define R128_BIOS_2_SCRATCH 0x0018 +#define R128_BIOS_3_SCRATCH 0x001c +#define R128_BIOS_ROM 0x0f30 /* PCI */ +#define R128_BIST 0x0f0f /* PCI */ +#define R128_BRUSH_DATA0 0x1480 +#define R128_BRUSH_DATA1 0x1484 +#define R128_BRUSH_DATA10 0x14a8 +#define R128_BRUSH_DATA11 0x14ac +#define R128_BRUSH_DATA12 0x14b0 +#define R128_BRUSH_DATA13 0x14b4 +#define R128_BRUSH_DATA14 0x14b8 +#define R128_BRUSH_DATA15 0x14bc +#define R128_BRUSH_DATA16 0x14c0 +#define R128_BRUSH_DATA17 0x14c4 +#define R128_BRUSH_DATA18 0x14c8 +#define R128_BRUSH_DATA19 0x14cc +#define R128_BRUSH_DATA2 0x1488 +#define R128_BRUSH_DATA20 0x14d0 +#define R128_BRUSH_DATA21 0x14d4 +#define R128_BRUSH_DATA22 0x14d8 +#define R128_BRUSH_DATA23 0x14dc +#define R128_BRUSH_DATA24 0x14e0 +#define R128_BRUSH_DATA25 0x14e4 +#define R128_BRUSH_DATA26 0x14e8 +#define R128_BRUSH_DATA27 0x14ec +#define R128_BRUSH_DATA28 0x14f0 +#define R128_BRUSH_DATA29 0x14f4 +#define R128_BRUSH_DATA3 0x148c +#define R128_BRUSH_DATA30 0x14f8 +#define R128_BRUSH_DATA31 0x14fc +#define R128_BRUSH_DATA32 0x1500 +#define R128_BRUSH_DATA33 0x1504 +#define R128_BRUSH_DATA34 0x1508 +#define R128_BRUSH_DATA35 0x150c +#define R128_BRUSH_DATA36 0x1510 +#define R128_BRUSH_DATA37 0x1514 +#define R128_BRUSH_DATA38 0x1518 +#define R128_BRUSH_DATA39 0x151c +#define R128_BRUSH_DATA4 0x1490 +#define R128_BRUSH_DATA40 0x1520 +#define R128_BRUSH_DATA41 0x1524 +#define R128_BRUSH_DATA42 0x1528 +#define R128_BRUSH_DATA43 0x152c +#define R128_BRUSH_DATA44 0x1530 +#define R128_BRUSH_DATA45 0x1534 +#define R128_BRUSH_DATA46 0x1538 +#define R128_BRUSH_DATA47 0x153c +#define R128_BRUSH_DATA48 0x1540 +#define R128_BRUSH_DATA49 0x1544 +#define R128_BRUSH_DATA5 0x1494 +#define R128_BRUSH_DATA50 0x1548 +#define R128_BRUSH_DATA51 0x154c +#define R128_BRUSH_DATA52 0x1550 +#define R128_BRUSH_DATA53 0x1554 +#define R128_BRUSH_DATA54 0x1558 +#define R128_BRUSH_DATA55 0x155c +#define R128_BRUSH_DATA56 0x1560 +#define R128_BRUSH_DATA57 0x1564 +#define R128_BRUSH_DATA58 0x1568 +#define R128_BRUSH_DATA59 0x156c +#define R128_BRUSH_DATA6 0x1498 +#define R128_BRUSH_DATA60 0x1570 +#define R128_BRUSH_DATA61 0x1574 +#define R128_BRUSH_DATA62 0x1578 +#define R128_BRUSH_DATA63 0x157c +#define R128_BRUSH_DATA7 0x149c +#define R128_BRUSH_DATA8 0x14a0 +#define R128_BRUSH_DATA9 0x14a4 +#define R128_BRUSH_SCALE 0x1470 +#define R128_BRUSH_Y_X 0x1474 +#define R128_BUS_CNTL 0x0030 +# define R128_BUS_MASTER_DIS (1 << 6) +# define R128_BUS_RD_DISCARD_EN (1 << 24) +# define R128_BUS_RD_ABORT_EN (1 << 25) +# define R128_BUS_MSTR_DISCONNECT_EN (1 << 28) +# define R128_BUS_WRT_BURST (1 << 29) +# define R128_BUS_READ_BURST (1 << 30) +#define R128_BUS_CNTL1 0x0034 +# define R128_BUS_WAIT_ON_LOCK_EN (1 << 4) + +#define R128_CACHE_CNTL 0x1724 +#define R128_CACHE_LINE 0x0f0c /* PCI */ +#define R128_CAP0_TRIG_CNTL 0x0950 /* ? */ +#define R128_CAP1_TRIG_CNTL 0x09c0 /* ? */ +#define R128_CAPABILITIES_ID 0x0f50 /* PCI */ +#define R128_CAPABILITIES_PTR 0x0f34 /* PCI */ +#define R128_CLK_PIN_CNTL 0x0001 /* PLL */ +#define R128_CLOCK_CNTL_DATA 0x000c +#define R128_CLOCK_CNTL_INDEX 0x0008 +# define R128_PLL_WR_EN (1 << 7) +# define R128_PLL_DIV_SEL (3 << 8) +#define R128_CLR_CMP_CLR_3D 0x1a24 +#define R128_CLR_CMP_CLR_DST 0x15c8 +#define R128_CLR_CMP_CLR_SRC 0x15c4 +#define R128_CLR_CMP_CNTL 0x15c0 +# define R128_SRC_CMP_EQ_COLOR (4 << 0) +# define R128_SRC_CMP_NEQ_COLOR (5 << 0) +# define R128_CLR_CMP_SRC_SOURCE (1 << 24) +#define R128_CLR_CMP_MASK 0x15cc +# define R128_CLR_CMP_MSK 0xffffffff +#define R128_CLR_CMP_MASK_3D 0x1A28 +#define R128_COMMAND 0x0f04 /* PCI */ +#define R128_COMPOSITE_SHADOW_ID 0x1a0c +#define R128_CONFIG_APER_0_BASE 0x0100 +#define R128_CONFIG_APER_1_BASE 0x0104 +#define R128_CONFIG_APER_SIZE 0x0108 +#define R128_CONFIG_BONDS 0x00e8 +#define R128_CONFIG_CNTL 0x00e0 +# define APER_0_BIG_ENDIAN_16BPP_SWAP (1 << 0) +# define APER_0_BIG_ENDIAN_32BPP_SWAP (2 << 0) +# define R128_CFG_VGA_RAM_EN (1 << 8) +#define R128_CONFIG_MEMSIZE 0x00f8 +#define R128_CONFIG_MEMSIZE_EMBEDDED 0x0114 +#define R128_CONFIG_REG_1_BASE 0x010c +#define R128_CONFIG_REG_APER_SIZE 0x0110 +#define R128_CONFIG_XSTRAP 0x00e4 +#define R128_CONSTANT_COLOR_C 0x1d34 +# define R128_CONSTANT_COLOR_MASK 0x00ffffff +# define R128_CONSTANT_COLOR_ONE 0x00ffffff +# define R128_CONSTANT_COLOR_ZERO 0x00000000 +#define R128_CRC_CMDFIFO_ADDR 0x0740 +#define R128_CRC_CMDFIFO_DOUT 0x0744 +#define R128_CRTC_CRNT_FRAME 0x0214 +#define R128_CRTC_DEBUG 0x021c +#define R128_CRTC_EXT_CNTL 0x0054 +# define R128_CRTC_VGA_XOVERSCAN (1 << 0) +# define R128_VGA_ATI_LINEAR (1 << 3) +# define R128_XCRT_CNT_EN (1 << 6) +# define R128_CRTC_HSYNC_DIS (1 << 8) +# define R128_CRTC_VSYNC_DIS (1 << 9) +# define R128_CRTC_DISPLAY_DIS (1 << 10) +# define R128_CRTC_CRT_ON (1 << 15) +# define R128_VGA_MEM_PS_EN (1 << 19) +#define R128_CRTC_EXT_CNTL_DPMS_BYTE 0x0055 +# define R128_CRTC_HSYNC_DIS_BYTE (1 << 0) +# define R128_CRTC_VSYNC_DIS_BYTE (1 << 1) +# define R128_CRTC_DISPLAY_DIS_BYTE (1 << 2) +#define R128_CRTC_GEN_CNTL 0x0050 +# define R128_CRTC_DBL_SCAN_EN (1 << 0) +# define R128_CRTC_INTERLACE_EN (1 << 1) +# define R128_CRTC_CSYNC_EN (1 << 4) +# define R128_CRTC_CUR_EN (1 << 16) +# define R128_CRTC_CUR_MODE_MASK (7 << 17) +# define R128_CRTC_ICON_EN (1 << 20) +# define R128_CRTC_EXT_DISP_EN (1 << 24) +# define R128_CRTC_EN (1 << 25) +# define R128_CRTC_DISP_REQ_EN_B (1 << 26) +#define R128_CRTC_GUI_TRIG_VLINE 0x0218 +#define R128_CRTC_H_SYNC_STRT_WID 0x0204 +# define R128_CRTC_H_SYNC_STRT_PIX (0x07 << 0) +# define R128_CRTC_H_SYNC_STRT_CHAR (0x1ff << 3) +# define R128_CRTC_H_SYNC_STRT_CHAR_SHIFT 3 +# define R128_CRTC_H_SYNC_WID (0x3f << 16) +# define R128_CRTC_H_SYNC_WID_SHIFT 16 +# define R128_CRTC_H_SYNC_POL (1 << 23) +#define R128_CRTC_H_TOTAL_DISP 0x0200 +# define R128_CRTC_H_TOTAL (0x01ff << 0) +# define R128_CRTC_H_TOTAL_SHIFT 0 +# define R128_CRTC_H_DISP (0x00ff << 16) +# define R128_CRTC_H_DISP_SHIFT 16 +#define R128_CRTC_OFFSET 0x0224 +#define R128_CRTC_OFFSET_CNTL 0x0228 +#define R128_CRTC_PITCH 0x022c +#define R128_CRTC_STATUS 0x005c +# define R128_CRTC_VBLANK_SAVE (1 << 1) +#define R128_CRTC_V_SYNC_STRT_WID 0x020c +# define R128_CRTC_V_SYNC_STRT (0x7ff << 0) +# define R128_CRTC_V_SYNC_STRT_SHIFT 0 +# define R128_CRTC_V_SYNC_WID (0x1f << 16) +# define R128_CRTC_V_SYNC_WID_SHIFT 16 +# define R128_CRTC_V_SYNC_POL (1 << 23) +#define R128_CRTC_V_TOTAL_DISP 0x0208 +# define R128_CRTC_V_TOTAL (0x07ff << 0) +# define R128_CRTC_V_TOTAL_SHIFT 0 +# define R128_CRTC_V_DISP (0x07ff << 16) +# define R128_CRTC_V_DISP_SHIFT 16 +#define R128_CRTC_VLINE_CRNT_VLINE 0x0210 +# define R128_CRTC_CRNT_VLINE_MASK (0x7ff << 16) +#define R128_CRTC2_CRNT_FRAME 0x0314 +#define R128_CRTC2_DEBUG 0x031c +#define R128_CRTC2_GEN_CNTL 0x03f8 +#define R128_CRTC2_GUI_TRIG_VLINE 0x0318 +#define R128_CRTC2_H_SYNC_STRT_WID 0x0304 +#define R128_CRTC2_H_TOTAL_DISP 0x0300 +#define R128_CRTC2_OFFSET 0x0324 +#define R128_CRTC2_OFFSET_CNTL 0x0328 +#define R128_CRTC2_PITCH 0x032c +#define R128_CRTC2_STATUS 0x03fc +#define R128_CRTC2_V_SYNC_STRT_WID 0x030c +#define R128_CRTC2_V_TOTAL_DISP 0x0308 +#define R128_CRTC2_VLINE_CRNT_VLINE 0x0310 +#define R128_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ +#define R128_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ +#define R128_CUR_CLR0 0x026c +#define R128_CUR_CLR1 0x0270 +#define R128_CUR_HORZ_VERT_OFF 0x0268 +#define R128_CUR_HORZ_VERT_POSN 0x0264 +#define R128_CUR_OFFSET 0x0260 +# define R128_CUR_LOCK (1 << 31) + +#define R128_DAC_CNTL 0x0058 +# define R128_DAC_RANGE_CNTL (3 << 0) +# define R128_DAC_BLANKING (1 << 2) +# define R128_DAC_CRT_SEL_CRTC2 (1 << 4) +# define R128_DAC_PALETTE_ACC_CTL (1 << 5) +# define R128_DAC_8BIT_EN (1 << 8) +# define R128_DAC_VGA_ADR_EN (1 << 13) +# define R128_DAC_MASK_ALL (0xff << 24) +#define R128_DAC_CRC_SIG 0x02cc +#define R128_DAC_DATA 0x03c9 /* VGA */ +#define R128_DAC_MASK 0x03c6 /* VGA */ +#define R128_DAC_R_INDEX 0x03c7 /* VGA */ +#define R128_DAC_W_INDEX 0x03c8 /* VGA */ +#define R128_DDA_CONFIG 0x02e0 +#define R128_DDA_ON_OFF 0x02e4 +#define R128_DEFAULT_OFFSET 0x16e0 +#define R128_DEFAULT_PITCH 0x16e4 +#define R128_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 +# define R128_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) +# define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) +#define R128_DESTINATION_3D_CLR_CMP_VAL 0x1820 +#define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824 +#define R128_DEVICE_ID 0x0f02 /* PCI */ +#define R128_DP_BRUSH_BKGD_CLR 0x1478 +#define R128_DP_BRUSH_FRGD_CLR 0x147c +#define R128_DP_CNTL 0x16c0 +# define R128_DST_X_LEFT_TO_RIGHT (1 << 0) +# define R128_DST_Y_TOP_TO_BOTTOM (1 << 1) +#define R128_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 +# define R128_DST_Y_MAJOR (1 << 2) +# define R128_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) +# define R128_DST_X_DIR_LEFT_TO_RIGHT (1 << 31) +#define R128_DP_DATATYPE 0x16c4 +# define R128_HOST_BIG_ENDIAN_EN (1 << 29) +#define R128_DP_GUI_MASTER_CNTL 0x146c +# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) +# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) +# define R128_GMC_SRC_CLIPPING (1 << 2) +# define R128_GMC_DST_CLIPPING (1 << 3) +# define R128_GMC_BRUSH_DATATYPE_MASK (0x0f << 4) +# define R128_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4) +# define R128_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4) +# define R128_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4) +# define R128_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4) +# define R128_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4) +# define R128_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4) +# define R128_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4) +# define R128_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4) +# define R128_GMC_BRUSH_8x8_COLOR (10 << 4) +# define R128_GMC_BRUSH_1X8_COLOR (12 << 4) +# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4) +# define R128_GMC_BRUSH_NONE (15 << 4) +# define R128_GMC_DST_8BPP_CI (2 << 8) +# define R128_GMC_DST_15BPP (3 << 8) +# define R128_GMC_DST_16BPP (4 << 8) +# define R128_GMC_DST_24BPP (5 << 8) +# define R128_GMC_DST_32BPP (6 << 8) +# define R128_GMC_DST_8BPP_RGB (7 << 8) +# define R128_GMC_DST_Y8 (8 << 8) +# define R128_GMC_DST_RGB8 (9 << 8) +# define R128_GMC_DST_VYUY (11 << 8) +# define R128_GMC_DST_YVYU (12 << 8) +# define R128_GMC_DST_AYUV444 (14 << 8) +# define R128_GMC_DST_ARGB4444 (15 << 8) +# define R128_GMC_DST_DATATYPE_MASK (0x0f << 8) +# define R128_GMC_DST_DATATYPE_SHIFT 8 +# define R128_GMC_SRC_DATATYPE_MASK (3 << 12) +# define R128_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12) +# define R128_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12) +# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12) +# define R128_GMC_BYTE_PIX_ORDER (1 << 14) +# define R128_GMC_BYTE_MSB_TO_LSB (0 << 14) +# define R128_GMC_BYTE_LSB_TO_MSB (1 << 14) +# define R128_GMC_CONVERSION_TEMP (1 << 15) +# define R128_GMC_CONVERSION_TEMP_6500 (0 << 15) +# define R128_GMC_CONVERSION_TEMP_9300 (1 << 15) +# define R128_GMC_ROP3_MASK (0xff << 16) +# define R128_DP_SRC_SOURCE_MASK (7 << 24) +# define R128_DP_SRC_SOURCE_MEMORY (2 << 24) +# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24) +# define R128_GMC_3D_FCN_EN (1 << 27) +# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28) +# define R128_GMC_AUX_CLIP_DIS (1 << 29) +# define R128_GMC_WR_MSK_DIS (1 << 30) +# define R128_GMC_LD_BRUSH_Y_X (1 << 31) +# define R128_ROP3_ZERO 0x00000000 +# define R128_ROP3_DSa 0x00880000 +# define R128_ROP3_SDna 0x00440000 +# define R128_ROP3_S 0x00cc0000 +# define R128_ROP3_DSna 0x00220000 +# define R128_ROP3_D 0x00aa0000 +# define R128_ROP3_DSx 0x00660000 +# define R128_ROP3_DSo 0x00ee0000 +# define R128_ROP3_DSon 0x00110000 +# define R128_ROP3_DSxn 0x00990000 +# define R128_ROP3_Dn 0x00550000 +# define R128_ROP3_SDno 0x00dd0000 +# define R128_ROP3_Sn 0x00330000 +# define R128_ROP3_DSno 0x00bb0000 +# define R128_ROP3_DSan 0x00770000 +# define R128_ROP3_ONE 0x00ff0000 +# define R128_ROP3_DPa 0x00a00000 +# define R128_ROP3_PDna 0x00500000 +# define R128_ROP3_P 0x00f00000 +# define R128_ROP3_DPna 0x000a0000 +# define R128_ROP3_D 0x00aa0000 +# define R128_ROP3_DPx 0x005a0000 +# define R128_ROP3_DPo 0x00fa0000 +# define R128_ROP3_DPon 0x00050000 +# define R128_ROP3_PDxn 0x00a50000 +# define R128_ROP3_PDno 0x00f50000 +# define R128_ROP3_Pn 0x000f0000 +# define R128_ROP3_DPno 0x00af0000 +# define R128_ROP3_DPan 0x005f0000 + + +#define R128_DP_GUI_MASTER_CNTL_C 0x1c84 +#define R128_DP_MIX 0x16c8 +#define R128_DP_SRC_BKGD_CLR 0x15dc +#define R128_DP_SRC_FRGD_CLR 0x15d8 +#define R128_DP_WRITE_MASK 0x16cc +#define R128_DST_BRES_DEC 0x1630 +#define R128_DST_BRES_ERR 0x1628 +#define R128_DST_BRES_INC 0x162c +#define R128_DST_BRES_LNTH 0x1634 +#define R128_DST_BRES_LNTH_SUB 0x1638 +#define R128_DST_HEIGHT 0x1410 +#define R128_DST_HEIGHT_WIDTH 0x143c +#define R128_DST_HEIGHT_WIDTH_8 0x158c +#define R128_DST_HEIGHT_WIDTH_BW 0x15b4 +#define R128_DST_HEIGHT_Y 0x15a0 +#define R128_DST_OFFSET 0x1404 +#define R128_DST_PITCH 0x1408 +#define R128_DST_PITCH_OFFSET 0x142c +#define R128_DST_PITCH_OFFSET_C 0x1c80 +# define R128_PITCH_SHIFT 21 +# define R128_DST_TILE (1 << 31) +#define R128_DST_WIDTH 0x140c +#define R128_DST_WIDTH_HEIGHT 0x1598 +#define R128_DST_WIDTH_X 0x1588 +#define R128_DST_WIDTH_X_INCY 0x159c +#define R128_DST_X 0x141c +#define R128_DST_X_SUB 0x15a4 +#define R128_DST_X_Y 0x1594 +#define R128_DST_Y 0x1420 +#define R128_DST_Y_SUB 0x15a8 +#define R128_DST_Y_X 0x1438 + +#define R128_EXT_MEM_CNTL 0x0144 + +#define R128_FCP_CNTL 0x0012 /* PLL */ +#define R128_FLUSH_1 0x1704 +#define R128_FLUSH_2 0x1708 +#define R128_FLUSH_3 0x170c +#define R128_FLUSH_4 0x1710 +#define R128_FLUSH_5 0x1714 +#define R128_FLUSH_6 0x1718 +#define R128_FLUSH_7 0x171c +#define R128_FOG_3D_TABLE_START 0x1810 +#define R128_FOG_3D_TABLE_END 0x1814 +#define R128_FOG_3D_TABLE_DENSITY 0x181c +#define R128_FOG_TABLE_INDEX 0x1a14 +#define R128_FOG_TABLE_DATA 0x1a18 +#define R128_FP_CRTC_H_TOTAL_DISP 0x0250 +#define R128_FP_CRTC_V_TOTAL_DISP 0x0254 +#define R128_FP_GEN_CNTL 0x0284 +# define R128_FP_FPON (1 << 0) +# define R128_FP_TDMS_EN (1 << 2) +# define R128_FP_DETECT_SENSE (1 << 8) +# define R128_FP_SEL_CRTC2 (1 << 13) +# define R128_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) +# define R128_FP_CRTC_USE_SHADOW_VEND (1 << 18) +# define R128_FP_CRTC_HORZ_DIV2_EN (1 << 20) +# define R128_FP_CRTC_HOR_CRT_DIV2_DIS (1 << 21) +# define R128_FP_USE_SHADOW_EN (1 << 24) +#define R128_FP_H_SYNC_STRT_WID 0x02c4 +#define R128_FP_HORZ_STRETCH 0x028c +# define R128_HORZ_STRETCH_RATIO_MASK 0xffff +# define R128_HORZ_STRETCH_RATIO_SHIFT 0 +# define R128_HORZ_STRETCH_RATIO_MAX 4096 +# define R128_HORZ_PANEL_SIZE (0xff << 16) +# define R128_HORZ_PANEL_SHIFT 16 +# define R128_HORZ_STRETCH_PIXREP (0 << 25) +# define R128_HORZ_STRETCH_BLEND (1 << 25) +# define R128_HORZ_STRETCH_ENABLE (1 << 26) +# define R128_HORZ_FP_LOOP_STRETCH (0x7 << 27) +# define R128_HORZ_STRETCH_RESERVED (1 << 30) +# define R128_HORZ_AUTO_RATIO_FIX_EN (1 << 31) + +#define R128_FP_PANEL_CNTL 0x0288 +# define R128_FP_DIGON (1 << 0) +# define R128_FP_BLON (1 << 1) +#define R128_FP_V_SYNC_STRT_WID 0x02c8 +#define R128_FP_VERT_STRETCH 0x0290 +# define R128_VERT_PANEL_SIZE (0x7ff << 0) +# define R128_VERT_PANEL_SHIFT 0 +# define R128_VERT_STRETCH_RATIO_MASK 0x3ff +# define R128_VERT_STRETCH_RATIO_SHIFT 11 +# define R128_VERT_STRETCH_RATIO_MAX 1024 +# define R128_VERT_STRETCH_ENABLE (1 << 24) +# define R128_VERT_STRETCH_LINEREP (0 << 25) +# define R128_VERT_STRETCH_BLEND (1 << 25) +# define R128_VERT_AUTO_RATIO_EN (1 << 26) +# define R128_VERT_STRETCH_RESERVED 0xf8e00000 + +#define R128_GEN_INT_CNTL 0x0040 +#define R128_GEN_INT_STATUS 0x0044 +# define R128_VSYNC_INT_AK (1 << 2) +# define R128_VSYNC_INT (1 << 2) +#define R128_GEN_RESET_CNTL 0x00f0 +# define R128_SOFT_RESET_GUI (1 << 0) +# define R128_SOFT_RESET_VCLK (1 << 8) +# define R128_SOFT_RESET_PCLK (1 << 9) +# define R128_SOFT_RESET_DISPENG_XCLK (1 << 11) +# define R128_SOFT_RESET_MEMCTLR_XCLK (1 << 12) +#define R128_GENENB 0x03c3 /* VGA */ +#define R128_GENFC_RD 0x03ca /* VGA */ +#define R128_GENFC_WT 0x03da /* VGA, 0x03ba */ +#define R128_GENMO_RD 0x03cc /* VGA */ +#define R128_GENMO_WT 0x03c2 /* VGA */ +#define R128_GENS0 0x03c2 /* VGA */ +#define R128_GENS1 0x03da /* VGA, 0x03ba */ +#define R128_GPIO_MONID 0x0068 +# define R128_GPIO_MONID_A_0 (1 << 0) +# define R128_GPIO_MONID_A_1 (1 << 1) +# define R128_GPIO_MONID_A_2 (1 << 2) +# define R128_GPIO_MONID_A_3 (1 << 3) +# define R128_GPIO_MONID_Y_0 (1 << 8) +# define R128_GPIO_MONID_Y_1 (1 << 9) +# define R128_GPIO_MONID_Y_2 (1 << 10) +# define R128_GPIO_MONID_Y_3 (1 << 11) +# define R128_GPIO_MONID_EN_0 (1 << 16) +# define R128_GPIO_MONID_EN_1 (1 << 17) +# define R128_GPIO_MONID_EN_2 (1 << 18) +# define R128_GPIO_MONID_EN_3 (1 << 19) +# define R128_GPIO_MONID_MASK_0 (1 << 24) +# define R128_GPIO_MONID_MASK_1 (1 << 25) +# define R128_GPIO_MONID_MASK_2 (1 << 26) +# define R128_GPIO_MONID_MASK_3 (1 << 27) +#define R128_GPIO_MONIDB 0x006c +#define R128_GRPH8_DATA 0x03cf /* VGA */ +#define R128_GRPH8_IDX 0x03ce /* VGA */ +#define R128_GUI_DEBUG0 0x16a0 +#define R128_GUI_DEBUG1 0x16a4 +#define R128_GUI_DEBUG2 0x16a8 +#define R128_GUI_DEBUG3 0x16ac +#define R128_GUI_DEBUG4 0x16b0 +#define R128_GUI_DEBUG5 0x16b4 +#define R128_GUI_DEBUG6 0x16b8 +#define R128_GUI_PROBE 0x16bc +#define R128_GUI_SCRATCH_REG0 0x15e0 +#define R128_GUI_SCRATCH_REG1 0x15e4 +#define R128_GUI_SCRATCH_REG2 0x15e8 +#define R128_GUI_SCRATCH_REG3 0x15ec +#define R128_GUI_SCRATCH_REG4 0x15f0 +#define R128_GUI_SCRATCH_REG5 0x15f4 +#define R128_GUI_STAT 0x1740 +# define R128_GUI_FIFOCNT_MASK 0x0fff +# define R128_GUI_ACTIVE (1 << 31) + +#define R128_HEADER 0x0f0e /* PCI */ +#define R128_HOST_DATA0 0x17c0 +#define R128_HOST_DATA1 0x17c4 +#define R128_HOST_DATA2 0x17c8 +#define R128_HOST_DATA3 0x17cc +#define R128_HOST_DATA4 0x17d0 +#define R128_HOST_DATA5 0x17d4 +#define R128_HOST_DATA6 0x17d8 +#define R128_HOST_DATA7 0x17dc +#define R128_HOST_DATA_LAST 0x17e0 +#define R128_HOST_PATH_CNTL 0x0130 +#define R128_HTOTAL_CNTL 0x0009 /* PLL */ +#define R128_HW_DEBUG 0x0128 +#define R128_HW_DEBUG2 0x011c + +#define R128_I2C_CNTL_1 0x0094 /* ? */ +#define R128_INTERRUPT_LINE 0x0f3c /* PCI */ +#define R128_INTERRUPT_PIN 0x0f3d /* PCI */ +#define R128_IO_BASE 0x0f14 /* PCI */ + +#define R128_LATENCY 0x0f0d /* PCI */ +#define R128_LEAD_BRES_DEC 0x1608 +#define R128_LEAD_BRES_ERR 0x1600 +#define R128_LEAD_BRES_INC 0x1604 +#define R128_LEAD_BRES_LNTH 0x161c +#define R128_LEAD_BRES_LNTH_SUB 0x1624 +#define R128_LVDS_GEN_CNTL 0x02d0 +# define R128_LVDS_ON (1 << 0) +# define R128_LVDS_BLON (1 << 19) +# define R128_LVDS_SEL_CRTC2 (1 << 23) +# define R128_HSYNC_DELAY_SHIFT 28 +# define R128_HSYNC_DELAY_MASK (0xf << 28) + +#define R128_MAX_LATENCY 0x0f3f /* PCI */ +#define R128_MCLK_CNTL 0x000f /* PLL */ +# define R128_FORCE_GCP (1 << 16) +# define R128_FORCE_PIPE3D_CP (1 << 17) +# define R128_FORCE_RCP (1 << 18) +#define R128_MDGPIO_A_REG 0x01ac +#define R128_MDGPIO_EN_REG 0x01b0 +#define R128_MDGPIO_MASK 0x0198 +#define R128_MDGPIO_Y_REG 0x01b4 +#define R128_MEM_ADDR_CONFIG 0x0148 +#define R128_MEM_BASE 0x0f10 /* PCI */ +#define R128_MEM_CNTL 0x0140 +#define R128_MEM_INIT_LAT_TIMER 0x0154 +#define R128_MEM_INTF_CNTL 0x014c +#define R128_MEM_SDRAM_MODE_REG 0x0158 +#define R128_MEM_STR_CNTL 0x0150 +#define R128_MEM_VGA_RP_SEL 0x003c +#define R128_MEM_VGA_WP_SEL 0x0038 +#define R128_MIN_GRANT 0x0f3e /* PCI */ +#define R128_MM_DATA 0x0004 +#define R128_MM_INDEX 0x0000 +#define R128_MPLL_CNTL 0x000e /* PLL */ +#define R128_MPP_TB_CONFIG 0x01c0 /* ? */ +#define R128_MPP_GP_CONFIG 0x01c8 /* ? */ + +#define R128_N_VIF_COUNT 0x0248 + +#define R128_OVR_CLR 0x0230 +#define R128_OVR_WID_LEFT_RIGHT 0x0234 +#define R128_OVR_WID_TOP_BOTTOM 0x0238 + +/* first overlay unit (there is only one) */ + +#define R128_OV0_Y_X_START 0x0400 +#define R128_OV0_Y_X_END 0x0404 +#define R128_OV0_EXCLUSIVE_HORZ 0x0408 +# define R128_EXCL_HORZ_START_MASK 0x000000ff +# define R128_EXCL_HORZ_END_MASK 0x0000ff00 +# define R128_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000 +# define R128_EXCL_HORZ_EXCLUSIVE_EN 0x80000000 +#define R128_OV0_EXCLUSIVE_VERT 0x040C +# define R128_EXCL_VERT_START_MASK 0x000003ff +# define R128_EXCL_VERT_END_MASK 0x03ff0000 +#define R128_OV0_REG_LOAD_CNTL 0x0410 +# define R128_REG_LD_CTL_LOCK 0x00000001L +# define R128_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L +# define R128_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L +# define R128_REG_LD_CTL_LOCK_READBACK 0x00000008L +#define R128_OV0_SCALE_CNTL 0x0420 +# define R128_SCALER_PIX_EXPAND 0x00000001L +# define R128_SCALER_Y2R_TEMP 0x00000002L +# define R128_SCALER_HORZ_PICK_NEAREST 0x00000003L +# define R128_SCALER_VERT_PICK_NEAREST 0x00000004L +# define R128_SCALER_SIGNED_UV 0x00000010L +# define R128_SCALER_GAMMA_SEL_MASK 0x00000060L +# define R128_SCALER_GAMMA_SEL_BRIGHT 0x00000000L +# define R128_SCALER_GAMMA_SEL_G22 0x00000020L +# define R128_SCALER_GAMMA_SEL_G18 0x00000040L +# define R128_SCALER_GAMMA_SEL_G14 0x00000060L +# define R128_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L +# define R128_SCALER_SURFAC_FORMAT 0x00000f00L +# define R128_SCALER_SOURCE_15BPP 0x00000300L +# define R128_SCALER_SOURCE_16BPP 0x00000400L +# define R128_SCALER_SOURCE_32BPP 0x00000600L +# define R128_SCALER_SOURCE_YUV9 0x00000900L +# define R128_SCALER_SOURCE_YUV12 0x00000A00L +# define R128_SCALER_SOURCE_VYUY422 0x00000B00L +# define R128_SCALER_SOURCE_YVYU422 0x00000C00L +# define R128_SCALER_SMART_SWITCH 0x00008000L +# define R128_SCALER_BURST_PER_PLANE 0x00ff0000L +# define R128_SCALER_DOUBLE_BUFFER 0x01000000L +# define R128_SCALER_DIS_LIMIT 0x08000000L +# define R128_SCALER_PRG_LOAD_START 0x10000000L +# define R128_SCALER_INT_EMU 0x20000000L +# define R128_SCALER_ENABLE 0x40000000L +# define R128_SCALER_SOFT_RESET 0x80000000L +#define R128_OV0_V_INC 0x0424 +#define R128_OV0_P1_V_ACCUM_INIT 0x0428 +# define R128_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L +# define R128_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L +#define R128_OV0_P23_V_ACCUM_INIT 0x042C +#define R128_OV0_P1_BLANK_LINES_AT_TOP 0x0430 +# define R128_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL +# define R128_P1_ACTIVE_LINES_M1 0x0fff0000L +#define R128_OV0_P23_BLANK_LINES_AT_TOP 0x0434 +# define R128_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL +# define R128_P23_ACTIVE_LINES_M1 0x07ff0000L +#define R128_OV0_VID_BUF0_BASE_ADRS 0x0440 +# define R128_VIF_BUF0_PITCH_SEL 0x00000001L +# define R128_VIF_BUF0_TILE_ADRS 0x00000002L +# define R128_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L +# define R128_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L +#define R128_OV0_VID_BUF1_BASE_ADRS 0x0444 +# define R128_VIF_BUF1_PITCH_SEL 0x00000001L +# define R128_VIF_BUF1_TILE_ADRS 0x00000002L +# define R128_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L +# define R128_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L +#define R128_OV0_VID_BUF2_BASE_ADRS 0x0448 +# define R128_VIF_BUF2_PITCH_SEL 0x00000001L +# define R128_VIF_BUF2_TILE_ADRS 0x00000002L +# define R128_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L +# define R128_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L +#define R128_OV0_VID_BUF3_BASE_ADRS 0x044C +#define R128_OV0_VID_BUF4_BASE_ADRS 0x0450 +#define R128_OV0_VID_BUF5_BASE_ADRS 0x0454 +#define R128_OV0_VID_BUF_PITCH0_VALUE 0x0460 +#define R128_OV0_VID_BUF_PITCH1_VALUE 0x0464 +#define R128_OV0_AUTO_FLIP_CNTL 0x0470 +#define R128_OV0_DEINTERLACE_PATTERN 0x0474 +#define R128_OV0_H_INC 0x0480 +#define R128_OV0_STEP_BY 0x0484 +#define R128_OV0_P1_H_ACCUM_INIT 0x0488 +#define R128_OV0_P23_H_ACCUM_INIT 0x048C +#define R128_OV0_P1_X_START_END 0x0494 +#define R128_OV0_P2_X_START_END 0x0498 +#define R128_OV0_P3_X_START_END 0x049C +#define R128_OV0_FILTER_CNTL 0x04A0 +#define R128_OV0_FOUR_TAP_COEF_0 0x04B0 +#define R128_OV0_FOUR_TAP_COEF_1 0x04B4 +#define R128_OV0_FOUR_TAP_COEF_2 0x04B8 +#define R128_OV0_FOUR_TAP_COEF_3 0x04BC +#define R128_OV0_FOUR_TAP_COEF_4 0x04C0 +#define R128_OV0_COLOUR_CNTL 0x04E0 +#define R128_OV0_VIDEO_KEY_CLR 0x04E4 +#define R128_OV0_VIDEO_KEY_MSK 0x04E8 +#define R128_OV0_GRAPHICS_KEY_CLR 0x04EC +#define R128_OV0_GRAPHICS_KEY_MSK 0x04F0 +#define R128_OV0_KEY_CNTL 0x04F4 +# define R128_VIDEO_KEY_FN_MASK 0x00000007L +# define R128_VIDEO_KEY_FN_FALSE 0x00000000L +# define R128_VIDEO_KEY_FN_TRUE 0x00000001L +# define R128_VIDEO_KEY_FN_EQ 0x00000004L +# define R128_VIDEO_KEY_FN_NE 0x00000005L +# define R128_GRAPHIC_KEY_FN_MASK 0x00000070L +# define R128_GRAPHIC_KEY_FN_FALSE 0x00000000L +# define R128_GRAPHIC_KEY_FN_TRUE 0x00000010L +# define R128_GRAPHIC_KEY_FN_EQ 0x00000040L +# define R128_GRAPHIC_KEY_FN_NE 0x00000050L +# define R128_CMP_MIX_MASK 0x00000100L +# define R128_CMP_MIX_OR 0x00000000L +# define R128_CMP_MIX_AND 0x00000100L +#define R128_OV0_TEST 0x04F8 + + +#define R128_PALETTE_DATA 0x00b4 +#define R128_PALETTE_INDEX 0x00b0 +#define R128_PC_DEBUG_MODE 0x1760 +#define R128_PC_GUI_CTLSTAT 0x1748 +#define R128_PC_GUI_MODE 0x1744 +# define R128_PC_IGNORE_UNIFY (1 << 5) +#define R128_PC_MISC_CNTL 0x0188 +#define R128_PC_NGUI_CTLSTAT 0x0184 +# define R128_PC_FLUSH_GUI (3 << 0) +# define R128_PC_RI_GUI (1 << 2) +# define R128_PC_FLUSH_ALL 0x00ff +# define R128_PC_BUSY (1 << 31) +#define R128_PC_NGUI_MODE 0x0180 +#define R128_PCI_GART_PAGE 0x017c +#define R128_PLANE_3D_MASK_C 0x1d44 +#define R128_PLL_TEST_CNTL 0x0013 /* PLL */ +#define R128_PMI_CAP_ID 0x0f5c /* PCI */ +#define R128_PMI_DATA 0x0f63 /* PCI */ +#define R128_PMI_NXT_CAP_PTR 0x0f5d /* PCI */ +#define R128_PMI_PMC_REG 0x0f5e /* PCI */ +#define R128_PMI_PMCSR_REG 0x0f60 /* PCI */ +#define R128_PMI_REGISTER 0x0f5c /* PCI */ +#define R128_PPLL_CNTL 0x0002 /* PLL */ +# define R128_PPLL_RESET (1 << 0) +# define R128_PPLL_SLEEP (1 << 1) +# define R128_PPLL_ATOMIC_UPDATE_EN (1 << 16) +# define R128_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17) +#define R128_PPLL_DIV_0 0x0004 /* PLL */ +#define R128_PPLL_DIV_1 0x0005 /* PLL */ +#define R128_PPLL_DIV_2 0x0006 /* PLL */ +#define R128_PPLL_DIV_3 0x0007 /* PLL */ +# define R128_PPLL_FB3_DIV_MASK 0x07ff +# define R128_PPLL_POST3_DIV_MASK 0x00070000 +#define R128_PPLL_REF_DIV 0x0003 /* PLL */ +# define R128_PPLL_REF_DIV_MASK 0x03ff +# define R128_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ +# define R128_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ +#define R128_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */ +#define R128_REG_BASE 0x0f18 /* PCI */ +#define R128_REGPROG_INF 0x0f09 /* PCI */ +#define R128_REVISION_ID 0x0f08 /* PCI */ + +#define R128_SC_BOTTOM 0x164c +#define R128_SC_BOTTOM_RIGHT 0x16f0 +#define R128_SC_BOTTOM_RIGHT_C 0x1c8c +#define R128_SC_LEFT 0x1640 +#define R128_SC_RIGHT 0x1644 +#define R128_SC_TOP 0x1648 +#define R128_SC_TOP_LEFT 0x16ec +#define R128_SC_TOP_LEFT_C 0x1c88 +#define R128_SEQ8_DATA 0x03c5 /* VGA */ +#define R128_SEQ8_IDX 0x03c4 /* VGA */ +#define R128_SNAPSHOT_F_COUNT 0x0244 +#define R128_SNAPSHOT_VH_COUNTS 0x0240 +#define R128_SNAPSHOT_VIF_COUNT 0x024c +#define R128_SRC_OFFSET 0x15ac +#define R128_SRC_PITCH 0x15b0 +#define R128_SRC_PITCH_OFFSET 0x1428 +#define R128_SRC_SC_BOTTOM 0x165c +#define R128_SRC_SC_BOTTOM_RIGHT 0x16f4 +#define R128_SRC_SC_RIGHT 0x1654 +#define R128_SRC_X 0x1414 +#define R128_SRC_X_Y 0x1590 +#define R128_SRC_Y 0x1418 +#define R128_SRC_Y_X 0x1434 +#define R128_STATUS 0x0f06 /* PCI */ +#define R128_SUBPIC_CNTL 0x0540 /* ? */ +#define R128_SUB_CLASS 0x0f0a /* PCI */ +#define R128_SURFACE_DELAY 0x0b00 +#define R128_SURFACE0_INFO 0x0b0c +#define R128_SURFACE0_LOWER_BOUND 0x0b04 +#define R128_SURFACE0_UPPER_BOUND 0x0b08 +#define R128_SURFACE1_INFO 0x0b1c +#define R128_SURFACE1_LOWER_BOUND 0x0b14 +#define R128_SURFACE1_UPPER_BOUND 0x0b18 +#define R128_SURFACE2_INFO 0x0b2c +#define R128_SURFACE2_LOWER_BOUND 0x0b24 +#define R128_SURFACE2_UPPER_BOUND 0x0b28 +#define R128_SURFACE3_INFO 0x0b3c +#define R128_SURFACE3_LOWER_BOUND 0x0b34 +#define R128_SURFACE3_UPPER_BOUND 0x0b38 +#define R128_SW_SEMAPHORE 0x013c + +#define R128_TEST_DEBUG_CNTL 0x0120 +#define R128_TEST_DEBUG_MUX 0x0124 +#define R128_TEST_DEBUG_OUT 0x012c +#define R128_TMDS_CRC 0x02a0 +#define R128_TRAIL_BRES_DEC 0x1614 +#define R128_TRAIL_BRES_ERR 0x160c +#define R128_TRAIL_BRES_INC 0x1610 +#define R128_TRAIL_X 0x1618 +#define R128_TRAIL_X_SUB 0x1620 + +#define R128_VCLK_ECP_CNTL 0x0008 /* PLL */ +#define R128_VENDOR_ID 0x0f00 /* PCI */ +#define R128_VGA_DDA_CONFIG 0x02e8 +#define R128_VGA_DDA_ON_OFF 0x02ec +#define R128_VID_BUFFER_CONTROL 0x0900 +#define R128_VIDEOMUX_CNTL 0x0190 +#define R128_VIPH_CONTROL 0x01D0 /* ? */ + +#define R128_WAIT_UNTIL 0x1720 + +#define R128_X_MPLL_REF_FB_DIV 0x000a /* PLL */ +#define R128_XCLK_CNTL 0x000d /* PLL */ +#define R128_XDLL_CNTL 0x000c /* PLL */ +#define R128_XPLL_CNTL 0x000b /* PLL */ + + /* Registers for CCE and Microcode Engine */ +#define R128_PM4_MICROCODE_ADDR 0x07d4 +#define R128_PM4_MICROCODE_RADDR 0x07d8 +#define R128_PM4_MICROCODE_DATAH 0x07dc +#define R128_PM4_MICROCODE_DATAL 0x07e0 + +#define R128_PM4_BUFFER_OFFSET 0x0700 +#define R128_PM4_BUFFER_CNTL 0x0704 +# define R128_PM4_NONPM4 (0 << 28) +# define R128_PM4_192PIO (1 << 28) +# define R128_PM4_192BM (2 << 28) +# define R128_PM4_128PIO_64INDBM (3 << 28) +# define R128_PM4_128BM_64INDBM (4 << 28) +# define R128_PM4_64PIO_128INDBM (5 << 28) +# define R128_PM4_64BM_128INDBM (6 << 28) +# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) +# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) +# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) +#define R128_PM4_BUFFER_WM_CNTL 0x0708 +# define R128_WMA_SHIFT 0 +# define R128_WMB_SHIFT 8 +# define R128_WMC_SHIFT 16 +# define R128_WB_WM_SHIFT 24 +#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c +#define R128_PM4_BUFFER_DL_RPTR 0x0710 +#define R128_PM4_BUFFER_DL_WPTR 0x0714 +# define R128_PM4_BUFFER_DL_DONE (1 << 31) +#define R128_PM4_BUFFER_DL_WPTR_DELAY 0x0718 +# define R128_PRE_WRITE_TIMER_SHIFT 0 +# define R128_PRE_WRITE_LIMIT_SHIFT 23 +#define R128_PM4_VC_FPU_SETUP 0x071c +# define R128_FRONT_DIR_CW (0 << 0) +# define R128_FRONT_DIR_CCW (1 << 0) +# define R128_FRONT_DIR_MASK (1 << 0) +# define R128_BACKFACE_CULL (0 << 1) +# define R128_BACKFACE_POINTS (1 << 1) +# define R128_BACKFACE_LINES (2 << 1) +# define R128_BACKFACE_SOLID (3 << 1) +# define R128_BACKFACE_MASK (3 << 1) +# define R128_FRONTFACE_CULL (0 << 3) +# define R128_FRONTFACE_POINTS (1 << 3) +# define R128_FRONTFACE_LINES (2 << 3) +# define R128_FRONTFACE_SOLID (3 << 3) +# define R128_FRONTFACE_MASK (3 << 3) +# define R128_FPU_COLOR_SOLID (0 << 5) +# define R128_FPU_COLOR_FLAT (1 << 5) +# define R128_FPU_COLOR_GOURAUD (2 << 5) +# define R128_FPU_COLOR_GOURAUD2 (3 << 5) +# define R128_FPU_COLOR_MASK (3 << 5) +# define R128_FPU_SUB_PIX_2BITS (0 << 7) +# define R128_FPU_SUB_PIX_4BITS (1 << 7) +# define R128_FPU_MODE_2D (0 << 8) +# define R128_FPU_MODE_3D (1 << 8) +# define R128_TRAP_BITS_DISABLE (1 << 9) +# define R128_EDGE_ANTIALIAS (1 << 10) +# define R128_SUPERSAMPLE (1 << 11) +# define R128_XFACTOR_2 (0 << 12) +# define R128_XFACTOR_4 (1 << 12) +# define R128_YFACTOR_2 (0 << 13) +# define R128_YFACTOR_4 (1 << 13) +# define R128_FLAT_SHADE_VERTEX_D3D (0 << 14) +# define R128_FLAT_SHADE_VERTEX_OGL (1 << 14) +# define R128_FPU_ROUND_TRUNCATE (0 << 15) +# define R128_FPU_ROUND_NEAREST (1 << 15) +# define R128_WM_SEL_8DW (0 << 16) +# define R128_WM_SEL_16DW (1 << 16) +# define R128_WM_SEL_32DW (2 << 16) +#define R128_PM4_VC_DEBUG_CONFIG 0x07a4 +#define R128_PM4_VC_STAT 0x07a8 +#define R128_PM4_VC_TIMESTAMP0 0x07b0 +#define R128_PM4_VC_TIMESTAMP1 0x07b4 +#define R128_PM4_STAT 0x07b8 +# define R128_PM4_FIFOCNT_MASK 0x0fff +# define R128_PM4_BUSY (1 << 16) +# define R128_PM4_GUI_ACTIVE (1 << 31) +#define R128_PM4_BUFFER_ADDR 0x07f0 +#define R128_PM4_MICRO_CNTL 0x07fc +# define R128_PM4_MICRO_FREERUN (1 << 30) +#define R128_PM4_FIFO_DATA_EVEN 0x1000 +#define R128_PM4_FIFO_DATA_ODD 0x1004 + +#define R128_SCALE_3D_CNTL 0x1a00 +# define R128_SCALE_DITHER_ERR_DIFF (0 << 1) +# define R128_SCALE_DITHER_TABLE (1 << 1) +# define R128_TEX_CACHE_SIZE_FULL (0 << 2) +# define R128_TEX_CACHE_SIZE_HALF (1 << 2) +# define R128_DITHER_INIT_CURR (0 << 3) +# define R128_DITHER_INIT_RESET (1 << 3) +# define R128_ROUND_24BIT (1 << 4) +# define R128_TEX_CACHE_DISABLE (1 << 5) +# define R128_SCALE_3D_NOOP (0 << 6) +# define R128_SCALE_3D_SCALE (1 << 6) +# define R128_SCALE_3D_TEXMAP_SHADE (2 << 6) +# define R128_SCALE_PIX_BLEND (0 << 8) +# define R128_SCALE_PIX_REPLICATE (1 << 8) +# define R128_TEX_CACHE_SPLIT (1 << 9) +# define R128_APPLE_YUV_MODE (1 << 10) +# define R128_TEX_CACHE_PALLETE_MODE (1 << 11) +# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) +# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12) +# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12) +# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12) +# define R128_FOG_TABLE (1 << 14) +# define R128_SIGNED_DST_CLAMP (1 << 15) +# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16) +# define R128_ALPHA_BLEND_SRC_ONE (1 << 16) +# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16) +# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16) +# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16) +# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16) +# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16) +# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16) +# define R128_ALPHA_BLEND_SRC_SAT (10 << 16) +# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16) +# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16) +# define R128_ALPHA_BLEND_DST_ZERO (0 << 20) +# define R128_ALPHA_BLEND_DST_ONE (1 << 20) +# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20) +# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20) +# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20) +# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20) +# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20) +# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20) +# define R128_ALPHA_TEST_NEVER (0 << 24) +# define R128_ALPHA_TEST_LESS (1 << 24) +# define R128_ALPHA_TEST_LESSEQUAL (2 << 24) +# define R128_ALPHA_TEST_EQUAL (3 << 24) +# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24) +# define R128_ALPHA_TEST_GREATER (5 << 24) +# define R128_ALPHA_TEST_NEQUAL (6 << 24) +# define R128_ALPHA_TEST_ALWAYS (7 << 24) +# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28) +# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28) +# define R128_COMPOSITE_SHADOW (1 << 29) +# define R128_TEX_MAP_ALPHA_IN_TEXTURE (1 << 30) +# define R128_TEX_CACHE_LINE_SIZE_8QW (0 << 31) +# define R128_TEX_CACHE_LINE_SIZE_4QW (1 << 31) +#define R128_SCALE_3D_DATATYPE 0x1a20 + +#define R128_SETUP_CNTL 0x1bc4 +# define R128_DONT_START_TRIANGLE (1 << 0) +# define R128_Z_BIAS (0 << 1) +# define R128_DONT_START_ANY_ON (1 << 2) +# define R128_COLOR_SOLID_COLOR (0 << 3) +# define R128_COLOR_FLAT_VERT_1 (1 << 3) +# define R128_COLOR_FLAT_VERT_2 (2 << 3) +# define R128_COLOR_FLAT_VERT_3 (3 << 3) +# define R128_COLOR_GOURAUD (4 << 3) +# define R128_PRIM_TYPE_TRI (0 << 7) +# define R128_PRIM_TYPE_LINE (1 << 7) +# define R128_PRIM_TYPE_POINT (2 << 7) +# define R128_PRIM_TYPE_POLY_EDGE (3 << 7) +# define R128_TEXTURE_ST_MULT_W (0 << 9) +# define R128_TEXTURE_ST_DIRECT (1 << 9) +# define R128_STARTING_VERTEX_1 (1 << 14) +# define R128_STARTING_VERTEX_2 (2 << 14) +# define R128_STARTING_VERTEX_3 (3 << 14) +# define R128_ENDING_VERTEX_1 (1 << 16) +# define R128_ENDING_VERTEX_2 (2 << 16) +# define R128_ENDING_VERTEX_3 (3 << 16) +# define R128_SU_POLY_LINE_LAST (0 << 18) +# define R128_SU_POLY_LINE_NOT_LAST (1 << 18) +# define R128_SUB_PIX_2BITS (0 << 19) +# define R128_SUB_PIX_4BITS (1 << 19) +# define R128_SET_UP_CONTINUE (1 << 31) + +#define R128_WINDOW_XY_OFFSET 0x1bcc +# define R128_WINDOW_Y_SHIFT 4 +# define R128_WINDOW_X_SHIFT 20 + +#define R128_Z_OFFSET_C 0x1c90 +#define R128_Z_PITCH_C 0x1c94 +# define R128_Z_TILE (1 << 16) +#define R128_Z_STEN_CNTL_C 0x1c98 +# define R128_Z_PIX_WIDTH_16 (0 << 1) +# define R128_Z_PIX_WIDTH_24 (1 << 1) +# define R128_Z_PIX_WIDTH_32 (2 << 1) +# define R128_Z_PIX_WIDTH_MASK (3 << 1) +# define R128_Z_TEST_NEVER (0 << 4) +# define R128_Z_TEST_LESS (1 << 4) +# define R128_Z_TEST_LESSEQUAL (2 << 4) +# define R128_Z_TEST_EQUAL (3 << 4) +# define R128_Z_TEST_GREATEREQUAL (4 << 4) +# define R128_Z_TEST_GREATER (5 << 4) +# define R128_Z_TEST_NEQUAL (6 << 4) +# define R128_Z_TEST_ALWAYS (7 << 4) +# define R128_Z_TEST_MASK (7 << 4) +# define R128_STENCIL_TEST_NEVER (0 << 12) +# define R128_STENCIL_TEST_LESS (1 << 12) +# define R128_STENCIL_TEST_LESSEQUAL (2 << 12) +# define R128_STENCIL_TEST_EQUAL (3 << 12) +# define R128_STENCIL_TEST_GREATEREQUAL (4 << 12) +# define R128_STENCIL_TEST_GREATER (5 << 12) +# define R128_STENCIL_TEST_NEQUAL (6 << 12) +# define R128_STENCIL_TEST_ALWAYS (7 << 12) +# define R128_STENCIL_S_FAIL_KEEP (0 << 16) +# define R128_STENCIL_S_FAIL_ZERO (1 << 16) +# define R128_STENCIL_S_FAIL_REPLACE (2 << 16) +# define R128_STENCIL_S_FAIL_INC (3 << 16) +# define R128_STENCIL_S_FAIL_DEC (4 << 16) +# define R128_STENCIL_S_FAIL_INV (5 << 16) +# define R128_STENCIL_ZPASS_KEEP (0 << 20) +# define R128_STENCIL_ZPASS_ZERO (1 << 20) +# define R128_STENCIL_ZPASS_REPLACE (2 << 20) +# define R128_STENCIL_ZPASS_INC (3 << 20) +# define R128_STENCIL_ZPASS_DEC (4 << 20) +# define R128_STENCIL_ZPASS_INV (5 << 20) +# define R128_STENCIL_ZFAIL_KEEP (0 << 24) +# define R128_STENCIL_ZFAIL_ZERO (1 << 24) +# define R128_STENCIL_ZFAIL_REPLACE (2 << 24) +# define R128_STENCIL_ZFAIL_INC (3 << 24) +# define R128_STENCIL_ZFAIL_DEC (4 << 24) +# define R128_STENCIL_ZFAIL_INV (5 << 24) +#define R128_TEX_CNTL_C 0x1c9c +# define R128_Z_ENABLE (1 << 0) +# define R128_Z_WRITE_ENABLE (1 << 1) +# define R128_STENCIL_ENABLE (1 << 3) +# define R128_SHADE_ENABLE (0 << 4) +# define R128_TEXMAP_ENABLE (1 << 4) +# define R128_SEC_TEXMAP_ENABLE (1 << 5) +# define R128_FOG_ENABLE (1 << 7) +# define R128_DITHER_ENABLE (1 << 8) +# define R128_ALPHA_ENABLE (1 << 9) +# define R128_ALPHA_TEST_ENABLE (1 << 10) +# define R128_SPEC_LIGHT_ENABLE (1 << 11) +# define R128_TEX_CHROMA_KEY_ENABLE (1 << 12) +# define R128_ALPHA_IN_TEX_COMPLETE_A (0 << 13) +# define R128_ALPHA_IN_TEX_LSB_A (1 << 13) +# define R128_LIGHT_DIS (0 << 14) +# define R128_LIGHT_COPY (1 << 14) +# define R128_LIGHT_MODULATE (2 << 14) +# define R128_LIGHT_ADD (3 << 14) +# define R128_LIGHT_BLEND_CONSTANT (4 << 14) +# define R128_LIGHT_BLEND_TEXTURE (5 << 14) +# define R128_LIGHT_BLEND_VERTEX (6 << 14) +# define R128_LIGHT_BLEND_CONST_COLOR (7 << 14) +# define R128_ALPHA_LIGHT_DIS (0 << 18) +# define R128_ALPHA_LIGHT_COPY (1 << 18) +# define R128_ALPHA_LIGHT_MODULATE (2 << 18) +# define R128_ALPHA_LIGHT_ADD (3 << 18) +# define R128_ANTI_ALIAS (1 << 21) +# define R128_TEX_CACHE_FLUSH (1 << 23) +# define R128_LOD_BIAS_SHIFT 24 +# define R128_LOD_BIAS_MASK (0xff << 24) +#define R128_MISC_3D_STATE_CNTL_REG 0x1ca0 +# define R128_REF_ALPHA_MASK 0xff +# define R128_MISC_SCALE_3D_NOOP (0 << 8) +# define R128_MISC_SCALE_3D_SCALE (1 << 8) +# define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8) +# define R128_MISC_SCALE_PIX_BLEND (0 << 10) +# define R128_MISC_SCALE_PIX_REPLICATE (1 << 10) +# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) +# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12) +# define R128_FOG_VERTEX (0 << 14) +# define R128_FOG_TABLE (1 << 14) +# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16) +# define R128_ALPHA_BLEND_SRC_ONE (1 << 16) +# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16) +# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16) +# define R128_ALPHA_BLEND_SRC_DESTALPHA (6 << 16) +# define R128_ALPHA_BLEND_SRC_INVDESTALPHA (7 << 16) +# define R128_ALPHA_BLEND_SRC_DESTCOLOR (8 << 16) +# define R128_ALPHA_BLEND_SRC_INVDESTCOLOR (9 << 16) +# define R128_ALPHA_BLEND_SRC_SRCALPHASAT (10 << 16) +# define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA (11 << 16) +# define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16) +# define R128_ALPHA_BLEND_SRC_MASK (15 << 16) +# define R128_ALPHA_BLEND_DST_ZERO (0 << 20) +# define R128_ALPHA_BLEND_DST_ONE (1 << 20) +# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20) +# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20) +# define R128_ALPHA_BLEND_DST_DESTALPHA (6 << 20) +# define R128_ALPHA_BLEND_DST_INVDESTALPHA (7 << 20) +# define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20) +# define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20) +# define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20) +# define R128_ALPHA_BLEND_DST_MASK (15 << 20) +# define R128_ALPHA_TEST_NEVER (0 << 24) +# define R128_ALPHA_TEST_LESS (1 << 24) +# define R128_ALPHA_TEST_LESSEQUAL (2 << 24) +# define R128_ALPHA_TEST_EQUAL (3 << 24) +# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24) +# define R128_ALPHA_TEST_GREATER (5 << 24) +# define R128_ALPHA_TEST_NEQUAL (6 << 24) +# define R128_ALPHA_TEST_ALWAYS (7 << 24) +# define R128_ALPHA_TEST_MASK (7 << 24) +#define R128_TEXTURE_CLR_CMP_CLR_C 0x1ca4 +#define R128_TEXTURE_CLR_CMP_MSK_C 0x1ca8 +#define R128_FOG_COLOR_C 0x1cac +# define R128_FOG_BLUE_SHIFT 0 +# define R128_FOG_GREEN_SHIFT 8 +# define R128_FOG_RED_SHIFT 16 +#define R128_PRIM_TEX_CNTL_C 0x1cb0 +# define R128_MIN_BLEND_NEAREST (0 << 1) +# define R128_MIN_BLEND_LINEAR (1 << 1) +# define R128_MIN_BLEND_MIPNEAREST (2 << 1) +# define R128_MIN_BLEND_MIPLINEAR (3 << 1) +# define R128_MIN_BLEND_LINEARMIPNEAREST (4 << 1) +# define R128_MIN_BLEND_LINEARMIPLINEAR (5 << 1) +# define R128_MIN_BLEND_MASK (7 << 1) +# define R128_MAG_BLEND_NEAREST (0 << 4) +# define R128_MAG_BLEND_LINEAR (1 << 4) +# define R128_MAG_BLEND_MASK (7 << 4) +# define R128_MIP_MAP_DISABLE (1 << 7) +# define R128_TEX_CLAMP_S_WRAP (0 << 8) +# define R128_TEX_CLAMP_S_MIRROR (1 << 8) +# define R128_TEX_CLAMP_S_CLAMP (2 << 8) +# define R128_TEX_CLAMP_S_BORDER_COLOR (3 << 8) +# define R128_TEX_CLAMP_S_MASK (3 << 8) +# define R128_TEX_WRAP_S (1 << 10) +# define R128_TEX_CLAMP_T_WRAP (0 << 11) +# define R128_TEX_CLAMP_T_MIRROR (1 << 11) +# define R128_TEX_CLAMP_T_CLAMP (2 << 11) +# define R128_TEX_CLAMP_T_BORDER_COLOR (3 << 11) +# define R128_TEX_CLAMP_T_MASK (3 << 11) +# define R128_TEX_WRAP_T (1 << 13) +# define R128_TEX_PERSPECTIVE_DISABLE (1 << 14) +# define R128_DATATYPE_VQ (0 << 16) +# define R128_DATATYPE_CI4 (1 << 16) +# define R128_DATATYPE_CI8 (2 << 16) +# define R128_DATATYPE_ARGB1555 (3 << 16) +# define R128_DATATYPE_RGB565 (4 << 16) +# define R128_DATATYPE_RGB888 (5 << 16) +# define R128_DATATYPE_ARGB8888 (6 << 16) +# define R128_DATATYPE_RGB332 (7 << 16) +# define R128_DATATYPE_Y8 (8 << 16) +# define R128_DATATYPE_RGB8 (9 << 16) +# define R128_DATATYPE_CI16 (10 << 16) +# define R128_DATATYPE_YUV422 (11 << 16) +# define R128_DATATYPE_YUV422_2 (12 << 16) +# define R128_DATATYPE_AYUV444 (14 << 16) +# define R128_DATATYPE_ARGB4444 (15 << 16) +# define R128_PALLETE_EITHER (0 << 20) +# define R128_PALLETE_1 (1 << 20) +# define R128_PALLETE_2 (2 << 20) +# define R128_PSEUDOCOLOR_DT_RGB565 (0 << 24) +# define R128_PSEUDOCOLOR_DT_ARGB1555 (1 << 24) +# define R128_PSEUDOCOLOR_DT_ARGB4444 (2 << 24) +#define R128_PRIM_TEXTURE_COMBINE_CNTL_C 0x1cb4 +# define R128_COMB_DIS (0 << 0) +# define R128_COMB_COPY (1 << 0) +# define R128_COMB_COPY_INP (2 << 0) +# define R128_COMB_MODULATE (3 << 0) +# define R128_COMB_MODULATE2X (4 << 0) +# define R128_COMB_MODULATE4X (5 << 0) +# define R128_COMB_ADD (6 << 0) +# define R128_COMB_ADD_SIGNED (7 << 0) +# define R128_COMB_BLEND_VERTEX (8 << 0) +# define R128_COMB_BLEND_TEXTURE (9 << 0) +# define R128_COMB_BLEND_CONST (10 << 0) +# define R128_COMB_BLEND_PREMULT (11 << 0) +# define R128_COMB_BLEND_PREV (12 << 0) +# define R128_COMB_BLEND_PREMULT_INV (13 << 0) +# define R128_COMB_ADD_SIGNED2X (14 << 0) +# define R128_COMB_BLEND_CONST_COLOR (15 << 0) +# define R128_COMB_MASK (15 << 0) +# define R128_COLOR_FACTOR_TEX (4 << 4) +# define R128_COLOR_FACTOR_NTEX (5 << 4) +# define R128_COLOR_FACTOR_ALPHA (6 << 4) +# define R128_COLOR_FACTOR_NALPHA (7 << 4) +# define R128_COLOR_FACTOR_MASK (15 << 4) +# define R128_INPUT_FACTOR_CONST_COLOR (2 << 10) +# define R128_INPUT_FACTOR_CONST_ALPHA (3 << 10) +# define R128_INPUT_FACTOR_INT_COLOR (4 << 10) +# define R128_INPUT_FACTOR_INT_ALPHA (5 << 10) +# define R128_INPUT_FACTOR_MASK (15 << 10) +# define R128_COMB_ALPHA_DIS (0 << 14) +# define R128_COMB_ALPHA_COPY (1 << 14) +# define R128_COMB_ALPHA_COPY_INP (2 << 14) +# define R128_COMB_ALPHA_MODULATE (3 << 14) +# define R128_COMB_ALPHA_MODULATE2X (4 << 14) +# define R128_COMB_ALPHA_MODULATE4X (5 << 14) +# define R128_COMB_ALPHA_ADD (6 << 14) +# define R128_COMB_ALPHA_ADD_SIGNED (7 << 14) +# define R128_COMB_ALPHA_ADD_SIGNED2X (14 << 14) +# define R128_COMB_ALPHA_MASK (15 << 14) +# define R128_ALPHA_FACTOR_TEX_ALPHA (6 << 18) +# define R128_ALPHA_FACTOR_NTEX_ALPHA (7 << 18) +# define R128_ALPHA_FACTOR_MASK (15 << 18) +# define R128_INP_FACTOR_A_CONST_ALPHA (1 << 25) +# define R128_INP_FACTOR_A_INT_ALPHA (2 << 25) +# define R128_INP_FACTOR_A_MASK (7 << 25) +#define R128_TEX_SIZE_PITCH_C 0x1cb8 +# define R128_TEX_PITCH_SHIFT 0 +# define R128_TEX_SIZE_SHIFT 4 +# define R128_TEX_HEIGHT_SHIFT 8 +# define R128_TEX_MIN_SIZE_SHIFT 12 +# define R128_SEC_TEX_PITCH_SHIFT 16 +# define R128_SEC_TEX_SIZE_SHIFT 20 +# define R128_SEC_TEX_HEIGHT_SHIFT 24 +# define R128_SEC_TEX_MIN_SIZE_SHIFT 28 +# define R128_TEX_PITCH_MASK (0x0f << 0) +# define R128_TEX_SIZE_MASK (0x0f << 4) +# define R128_TEX_HEIGHT_MASK (0x0f << 8) +# define R128_TEX_MIN_SIZE_MASK (0x0f << 12) +# define R128_SEC_TEX_PITCH_MASK (0x0f << 16) +# define R128_SEC_TEX_SIZE_MASK (0x0f << 20) +# define R128_SEC_TEX_HEIGHT_MASK (0x0f << 24) +# define R128_SEC_TEX_MIN_SIZE_MASK (0x0f << 28) +# define R128_TEX_SIZE_PITCH_SHIFT 0 +# define R128_SEC_TEX_SIZE_PITCH_SHIFT 16 +# define R128_TEX_SIZE_PITCH_MASK (0xffff << 0) +# define R128_SEC_TEX_SIZE_PITCH_MASK (0xffff << 16) +#define R128_PRIM_TEX_0_OFFSET_C 0x1cbc +#define R128_PRIM_TEX_1_OFFSET_C 0x1cc0 +#define R128_PRIM_TEX_2_OFFSET_C 0x1cc4 +#define R128_PRIM_TEX_3_OFFSET_C 0x1cc8 +#define R128_PRIM_TEX_4_OFFSET_C 0x1ccc +#define R128_PRIM_TEX_5_OFFSET_C 0x1cd0 +#define R128_PRIM_TEX_6_OFFSET_C 0x1cd4 +#define R128_PRIM_TEX_7_OFFSET_C 0x1cd8 +#define R128_PRIM_TEX_8_OFFSET_C 0x1cdc +#define R128_PRIM_TEX_9_OFFSET_C 0x1ce0 +#define R128_PRIM_TEX_10_OFFSET_C 0x1ce4 +# define R128_TEX_NO_TILE (0 << 30) +# define R128_TEX_TILED_BY_HOST (1 << 30) +# define R128_TEX_TILED_BY_STORAGE (2 << 30) +# define R128_TEX_TILED_BY_STORAGE2 (3 << 30) + +#define R128_SEC_TEX_CNTL_C 0x1d00 +# define R128_SEC_SELECT_PRIM_ST (0 << 0) +# define R128_SEC_SELECT_SEC_ST (1 << 0) +#define R128_SEC_TEX_COMBINE_CNTL_C 0x1d04 +# define R128_INPUT_FACTOR_PREV_COLOR (8 << 10) +# define R128_INPUT_FACTOR_PREV_ALPHA (9 << 10) +# define R128_INP_FACTOR_A_PREV_ALPHA (4 << 25) +#define R128_SEC_TEX_0_OFFSET_C 0x1d08 +#define R128_SEC_TEX_1_OFFSET_C 0x1d0c +#define R128_SEC_TEX_2_OFFSET_C 0x1d10 +#define R128_SEC_TEX_3_OFFSET_C 0x1d14 +#define R128_SEC_TEX_4_OFFSET_C 0x1d18 +#define R128_SEC_TEX_5_OFFSET_C 0x1d1c +#define R128_SEC_TEX_6_OFFSET_C 0x1d20 +#define R128_SEC_TEX_7_OFFSET_C 0x1d24 +#define R128_SEC_TEX_8_OFFSET_C 0x1d28 +#define R128_SEC_TEX_9_OFFSET_C 0x1d2c +#define R128_SEC_TEX_10_OFFSET_C 0x1d30 +#define R128_CONSTANT_COLOR_C 0x1d34 +# define R128_CONSTANT_BLUE_SHIFT 0 +# define R128_CONSTANT_GREEN_SHIFT 8 +# define R128_CONSTANT_RED_SHIFT 16 +# define R128_CONSTANT_ALPHA_SHIFT 24 +#define R128_PRIM_TEXTURE_BORDER_COLOR_C 0x1d38 +# define R128_PRIM_TEX_BORDER_BLUE_SHIFT 0 +# define R128_PRIM_TEX_BORDER_GREEN_SHIFT 8 +# define R128_PRIM_TEX_BORDER_RED_SHIFT 16 +# define R128_PRIM_TEX_BORDER_ALPHA_SHIFT 24 +#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c +# define R128_SEC_TEX_BORDER_BLUE_SHIFT 0 +# define R128_SEC_TEX_BORDER_GREEN_SHIFT 8 +# define R128_SEC_TEX_BORDER_RED_SHIFT 16 +# define R128_SEC_TEX_BORDER_ALPHA_SHIFT 24 +#define R128_STEN_REF_MASK_C 0x1d40 +# define R128_STEN_REFERENCE_SHIFT 0 +# define R128_STEN_MASK_SHIFT 16 +# define R128_STEN_WRITE_MASK_SHIFT 24 +#define R128_PLANE_3D_MASK_C 0x1d44 +#define R128_TEX_CACHE_STAT_COUNT 0x1974 + + + /* Constants */ +#define R128_AGP_TEX_OFFSET 0x02000000 + +#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0 + + /* CCE packet types */ +#define R128_CCE_PACKET0 0x00000000 +#define R128_CCE_PACKET0_ONE_REG_WR 0x00008000 +#define R128_CCE_PACKET1 0x40000000 +#define R128_CCE_PACKET2 0x80000000 +#define R128_CCE_PACKET3 0xC0000000 +#define R128_CCE_PACKET3_NOP 0xC0001000 +#define R128_CCE_PACKET3_PAINT 0xC0001100 +#define R128_CCE_PACKET3_BITBLT 0xC0001200 +#define R128_CCE_PACKET3_SMALLTEXT 0xC0001300 +#define R128_CCE_PACKET3_HOSTDATA_BLT 0xC0001400 +#define R128_CCE_PACKET3_POLYLINE 0xC0001500 +#define R128_CCE_PACKET3_SCALING 0xC0001600 +#define R128_CCE_PACKET3_TRANS_SCALING 0xC0001700 +#define R128_CCE_PACKET3_POLYSCANLINES 0xC0001800 +#define R128_CCE_PACKET3_NEXT_CHAR 0xC0001900 +#define R128_CCE_PACKET3_PAINT_MULTI 0xC0001A00 +#define R128_CCE_PACKET3_BITBLT_MULTI 0xC0001B00 +#define R128_CCE_PACKET3_PLY_NEXTSCAN 0xC0001D00 +#define R128_CCE_PACKET3_SET_SCISSORS 0xC0001E00 +#define R128_CCE_PACKET3_SET_MODE24BPP 0xC0001F00 +#define R128_CCE_PACKET3_CNTL_PAINT 0xC0009100 +#define R128_CCE_PACKET3_CNTL_BITBLT 0xC0009200 +#define R128_CCE_PACKET3_CNTL_SMALLTEXT 0xC0009300 +#define R128_CCE_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 +#define R128_CCE_PACKET3_CNTL_POLYLINE 0xC0009500 +#define R128_CCE_PACKET3_CNTL_SCALING 0xC0009600 +#define R128_CCE_PACKET3_CNTL_TRANS_SCALING 0xC0009700 +#define R128_CCE_PACKET3_CNTL_POLYSCANLINES 0xC0009800 +#define R128_CCE_PACKET3_CNTL_NEXT_CHAR 0xC0009900 +#define R128_CCE_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 +#define R128_CCE_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 +#define R128_CCE_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 +#define R128_CCE_PACKET3_3D_SAVE_CONTEXT 0xC0002000 +#define R128_CCE_PACKET3_3D_PLAY_CONTEXT 0xC0002100 +#define R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 +#define R128_CCE_PACKET3_3D_RNDR_GEN_PRIM 0xC0002500 +#define R128_CCE_PACKET3_LOAD_PALETTE 0xC0002C00 +#define R128_CCE_PACKET3_PURGE 0xC0002D00 +#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE 0xC0002E00 +# define R128_CCE_PACKET_MASK 0xC0000000 +# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000 +# define R128_CCE_PACKET_MAX_DWORDS (1 << 12) +# define R128_CCE_PACKET0_REG_MASK 0x000007ff +# define R128_CCE_PACKET1_REG0_MASK 0x000007ff +# define R128_CCE_PACKET1_REG1_MASK 0x003ff800 + +#define R128_CCE_VC_FRMT_RHW 0x00000001 +#define R128_CCE_VC_FRMT_DIFFUSE_BGR 0x00000002 +#define R128_CCE_VC_FRMT_DIFFUSE_A 0x00000004 +#define R128_CCE_VC_FRMT_DIFFUSE_ARGB 0x00000008 +#define R128_CCE_VC_FRMT_SPEC_BGR 0x00000010 +#define R128_CCE_VC_FRMT_SPEC_F 0x00000020 +#define R128_CCE_VC_FRMT_SPEC_FRGB 0x00000040 +#define R128_CCE_VC_FRMT_S_T 0x00000080 +#define R128_CCE_VC_FRMT_S2_T2 0x00000100 +#define R128_CCE_VC_FRMT_RHW2 0x00000200 + +#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000 +#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001 +#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002 +#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007 +#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010 +#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020 +#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 +#define R128_CCE_VC_CNTL_NUM_SHIFT 16 + +#define RADEON_DAC_CNTL2 0x007c +#define RADEON_CRTC_MORE_CNTL 0x027c +#define RADEON_DAC_EXT_CNTL 0x0280 +#define RADEON_GRPH_BUF_CNTL 0x02f0 +#define RADEON_VGA_BUF_CNTL 0x02f4 +#define RADEON_CRTC_CRNT_FRAME 0x0214 + +#define RADEON_SURFACE_CNTL 0x0b00 +#define RADEON_SCLK_CNTL 0x0d + +#define RADEON_VCLK_SRC_SEL_MASK 0x0003 +#define RADEON_VCLK_SRC_SEL_CPUCLK 0x0000 +#define RADEON_VCLK_SRC_SEL_PPLLCLK 0x0003 + +#define RADEON_BUS_READ_BURST (1<<30) +#define RADEON_BUS_RD_DISCARD_EN (1<<24) + +#define RADEON_SURF_TRANSLATION_DIS (1<<8) + +#define RADEON_CONFIG_CNTL R128_CONFIG_CNTL +#define RADEON_CFG_ATI_REV_ID_MASK (0xf << 16) +#define RADEON_CFG_ATI_REV_A11 (0 << 16) + +#define CHIP_ERRATA_R300_CG (1<<0) +#define CHIP_ERRATA_PLL_DUMMYREADS (1<<1) +#define CHIP_ERRATA_PLL_DELAY (1<<2) + +#define R300_PPLL_REF_DIV_ACC_SHIFT 18 +#define R300_PPLL_REF_DIV_ACC_MASK (0x3ff << 18) + +#endif + diff --git a/src/drivers/r128io.h b/src/drivers/r128io.h new file mode 100644 index 0000000..a5bffa8 --- /dev/null +++ b/src/drivers/r128io.h @@ -0,0 +1,115 @@ +#include "libvga.h" +#include + +static int __svgalib_r128_inmisc(void) +{ + return 0; +} + +static void __svgalib_r128_outmisc(int i) +{ +} + +static int __svgalib_r128_incrtc(int i) +{ + return 0; +} + +static void __svgalib_r128_outcrtc(int i, int d) +{ +} + +static int __svgalib_r128_inseq(int index) +{ + return 0; +} + +static void __svgalib_r128_outseq(int index, int val) +{ +} + +static int __svgalib_r128_ingra(int index) +{ + return 0; +} + +static void __svgalib_r128_outgra(int index, int val) +{ +} + +static int __svgalib_r128_inis1(void) +{ + return 0; +} + +static int __svgalib_r128_inatt(int index) +{ + return 0; +} + +static void __svgalib_r128_outatt(int index, int val) +{ +} + +static void __svgalib_r128_attscreen(int i) +{ +} + +static void __svgalib_r128_inpal(int i, int *r, int *g, int *b) +{ + volatile int rgb; + if(chiptype==Radeon) { + OUTREG(R128_PALETTE_INDEX, i ); + rgb=INREG(R128_PALETTE_DATA); + *r=(rgb>>16) & 0xff; + *g=(rgb>>8) & 0xff; + *b=rgb & 0xff; + if(dac6bits) { + *r>>=2; + *g>>=2; + *b>>=2; + } + } else { + OUTREG(R128_PALETTE_INDEX, i<<16 ); + rgb=INREG(R128_PALETTE_DATA); + *r=(rgb>>16) & 0xff; + *g=(rgb>>8) & 0xff; + *b=rgb & 0xff; + } +} + +static void __svgalib_r128_outpal(int i, int r, int g, int b) +{ + OUTREG(R128_PALETTE_INDEX, i ); + if((chiptype==Radeon) && dac6bits) { + r<<=2; + g<<=2; + b<<=2; + } + OUTREG(R128_PALETTE_DATA, b | (g<<8) | (r<<16) ); +} + +static void r128_mapio(void) +{ +#ifndef __PPC + if(__svgalib_secondary) { +#endif + __svgalib_inmisc=__svgalib_r128_inmisc; + __svgalib_outmisc=__svgalib_r128_outmisc; + __svgalib_incrtc=__svgalib_r128_incrtc; + __svgalib_outcrtc=__svgalib_r128_outcrtc; + __svgalib_inseq=__svgalib_r128_inseq; + __svgalib_outseq=__svgalib_r128_outseq; + __svgalib_ingra=__svgalib_r128_ingra; + __svgalib_outgra=__svgalib_r128_outgra; + __svgalib_inatt=__svgalib_r128_inatt; + __svgalib_outatt=__svgalib_r128_outatt; + __svgalib_attscreen=__svgalib_r128_attscreen; + __svgalib_inis1=__svgalib_r128_inis1; +#ifndef __PPC + } +#endif + __svgalib_inpal=__svgalib_r128_inpal; + __svgalib_outpal=__svgalib_r128_outpal; +} + diff --git a/src/drivers/rage.c b/src/drivers/rage.c new file mode 100644 index 0000000..41943a0 --- /dev/null +++ b/src/drivers/rage.c @@ -0,0 +1,1560 @@ +/* +ATI Rage chipset + +By Matan Ziv-Av (matan@svgalib.org) + +Please report to me any problem with the driver + +It works on my Xpert98 AGP 8MB SDRAM. + +The driver assumes a PCI (or AGP) device, i.e a device that registers on the +PCI bus. + +This driver should work (maybe with small changes) on all Mach64 cards +that use internal Clock and DAC. (Mach64 CT,ET,VT,GT (Rage),Rage II, +Rage II+DVD, and Rage Pro according to the XFree86 Documentation. + +If you have an older Mach64 card, it should be easy to adapt this driver +to work on your card. + +The test only tests for a Mach64 card, not for internal DAC. + +This driver is based on The XFree86 Mach64 Server and ati driver for the +SVGA server. That code is : + +Copyright 1994 through 1998 by Marc Aurele La France (TSI @ UQV), tsi@ualberta.ca + +*/ + +#include +#include /* for printf */ +#include /* for memset */ +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "rage.h" + +static int ATIIOPortCRTC_H_TOTAL_DISP, ATIIOPortCRTC_H_SYNC_STRT_WID, + ATIIOPortCRTC_V_TOTAL_DISP, ATIIOPortCRTC_V_SYNC_STRT_WID, + ATIIOPortCRTC_OFF_PITCH,ATIIOPortCRTC_INT_CNTL, + ATIIOPortCRTC_GEN_CNTL, ATIIOPortDSP_CONFIG, ATIIOPortDSP_ON_OFF, + ATIIOPortOVR_CLR, + ATIIOPortCLOCK_CNTL, ATIIOPortBUS_CNTL, ATIIOPortMEM_INFO, + ATIIOPortMEM_VGA_WP_SEL, ATIIOPortMEM_VGA_RP_SEL, + ATIIOPortDAC_REGS, ATIIOPortDAC_CNTL, ATIIOPortDAC_DATA, + ATIIOPortDAC_READ, ATIIOPortDAC_WRITE,ATIIOPortDAC_MASK, + ATIIOPortGEN_TEST_CNTL, ATIIOPortCONFIG_CNTL, + ATIIOPortCONFIG_STATUS64_0, ATIIOPortCUR_HORZ_VERT_OFF, + ATIIOPortCUR_HORZ_VERT_POSN, ATIIOPortCUR_CLR0, + ATIIOPortCUR_CLR1, ATIIOPortCUR_OFFSET; + +#include "rageio.c" + +static void ATIAccessMach64PLLReg(const int Index, const int Write) +{ + int clock_cntl1 = rage_inb(ATIIOPortCLOCK_CNTL + 1) & + ~GetByte(PLL_WR_EN | PLL_ADDR, 1); + + /* Set PLL register to be read or written */ + rage_outb(ATIIOPortCLOCK_CNTL + 1, clock_cntl1 | + GetByte(SetBits(Index, PLL_ADDR) | SetBits(Write, PLL_WR_EN), 1)); +} + +#define DAC_SIZE 768 + +typedef struct { + unsigned int + crtc_h_total_disp, crtc_h_sync_strt_wid, + crtc_v_total_disp, crtc_v_sync_strt_wid, + crtc_off_pitch, crtc_gen_cntl, + crtc_vline_crnt_vline, dsp_config, + dsp_on_off, ovr_clr, + clock_cntl, bus_cntl, + mem_vga_wp_sel, mem_vga_rp_sel, + dac_cntl, config_cntl, + banks, planes, + dac_read, dac_write, + dac_mask, mem_info, + mem_buf_cntl, shared_cntl, + shared_mem_config, crtc_int_cntl, + gen_test_cntl, misc_options, + mem_bndry, mem_cfg, + cur_clr0, cur_clr1, + cur_offset, cur_horz_vert_posn, + cur_horz_vert_off; + unsigned char PLL[32]; + unsigned char DAC[DAC_SIZE]; + unsigned char extdac[16]; + int ics2595; + unsigned char atib[16]; + } ATIHWRec, *ATIHWPtr; + +#define RAGE_TOTAL_REGS (VGA_TOTAL_REGS + sizeof(ATIHWRec)) + +extern unsigned char __svgalib_ragedoubleclock; +static int rage_init(int, int, int); +static void rage_unlock(void); +static void rage_lock(void); +static int rage_memory,rage_chiptyperev; +static unsigned int rage_linear_base; +static int ATIIODecoding; +static int ATIIOBase; +static int postdiv[8]={1,2,4,8,3,0,6,12}; +static int rage_bpp; +static int maxM, minM, Madj, minN, maxN, Nadj; +static double fref; +static int ATIClockToProgram; +static int ATIChip, ATIMemoryType; +static int rage_dac, rage_clock; + +static CardSpecs *cardspecs; + +static void rage_ChipID(void) +{ + int ATIChipType, ATIChipClass, ATIChipRevision, ATIChipVersion, + ATIChipFoundry; + unsigned int IO_Value = rage_inl(ATIIOPort(CONFIG_CHIP_ID)); + ATIChipType = GetBits(IO_Value, 0xFFFFU); + ATIChipClass = GetBits(IO_Value, CFG_CHIP_CLASS); + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REV); + ATIChipVersion = GetBits(IO_Value, CFG_CHIP_VERSION); + ATIChipFoundry = GetBits(IO_Value, CFG_CHIP_FOUNDRY); + switch (ATIChipType) + { + case 0x00D7U: + ATIChipType = 0x4758U; + case 0x4758U: + switch (ATIChipRevision) + { + case 0x00U: + ATIChip = ATI_CHIP_88800GXC; + break; + + case 0x01U: + ATIChip = ATI_CHIP_88800GXD; + break; + + case 0x02U: + ATIChip = ATI_CHIP_88800GXE; + break; + + case 0x03U: + ATIChip = ATI_CHIP_88800GXF; + break; + + default: + ATIChip = ATI_CHIP_88800GX; + break; + } + break; + + case 0x0057U: + ATIChipType = 0x4358U; + case 0x4358U: + ATIChip = ATI_CHIP_88800CX; + break; + + case 0x0053U: + ATIChipType = 0x4354U; + case 0x4354U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264CT; + break; + + case 0x0093U: + ATIChipType = 0x4554U; + case 0x4554U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264ET; + break; + + case 0x02B3U: + ATIChipType = 0x5654U; + case 0x5654U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264VT; + /* Some early GT's are detected as VT's */ +/* if (ExpectedChipType && (ATIChipType != ExpectedChipType)) + { + if (ExpectedChipType == 0x4754U) + ATIChip = ATI_CHIP_264GT; + else + ErrorF("Mach64 chip type probe discrepancy detected:\n" + " PCI=0x%04X; CHIP_ID=0x%04X.\n", + ExpectedChipType, ATIChipType); + } + else */if (ATIChipVersion) + ATIChip = ATI_CHIP_264VTB; + break; + + case 0x00D3U: + ATIChipType = 0x4754U; + case 0x4754U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + if (!ATIChipVersion) + ATIChip = ATI_CHIP_264GT; + else + ATIChip = ATI_CHIP_264GTB; + break; + + case 0x02B4U: + ATIChipType = 0x5655U; + case 0x5655U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264VT3; + break; + + case 0x00D4U: + ATIChipType = 0x4755U; + case 0x4755U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264GTDVD; + break; + + case 0x0166U: + ATIChipType = 0x4C47U; + case 0x4C47U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264LT; + break; + + case 0x0315U: + ATIChipType = 0x5656U; + case 0x5656U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264VT4; + break; + + case 0x00D5U: + ATIChipType = 0x4756U; + case 0x4756U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264GT2C; + break; + + case 0x00D6U: + case 0x00D9U: + ATIChipType = 0x4757U; + case 0x4757U: + case 0x475AU: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264GT2C; + break; + + case 0x00CEU: + case 0x00CFU: + case 0x00D0U: + ATIChipType = 0x4750U; + case 0x4749U: + case 0x4750U: + case 0x4751U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264GTPRO; + break; + + case 0x00C7U: + case 0x00C9U: + ATIChipType = 0x4742U; + case 0x4742U: + case 0x4744U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264GTPRO; + break; + + case 0x0168U: + case 0x016FU: + ATIChipType = 0x4C50U; + case 0x4C49U: + case 0x4C50U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264LTPRO; + break; + + case 0x0161U: + case 0x0163U: + ATIChipType = 0x4C42U; + case 0x4C42U: + case 0x4C44U: + ATIChipRevision = GetBits(IO_Value, CFG_CHIP_REVISION); + ATIChip = ATI_CHIP_264LTPRO; + break; + + default: + ATIChip = ATI_CHIP_Mach64; + break; + } +}; + +static int rage_probe(void) +{ + unsigned int i=rage_inl(ATIIOPort(SCRATCH_REG0)); + rage_outl(ATIIOPort(SCRATCH_REG0),0x55555555); + if(rage_inl(ATIIOPort(SCRATCH_REG0))!=0x55555555) { + rage_outl(ATIIOPort(SCRATCH_REG0),i); + return 0; + }; + rage_outl(ATIIOPort(SCRATCH_REG0),0xaaaaaaaa); + if(rage_inl(ATIIOPort(SCRATCH_REG0))!=0xaaaaaaaa) { + rage_outl(ATIIOPort(SCRATCH_REG0),i); + return 0; + }; + rage_outl(ATIIOPort(SCRATCH_REG0),i); + + return 1; +}; + +static int +ATIDivide(int Numerator, int Denominator, int Shift, const int RoundingKind) +{ + int Multiplier, Divider; + int Rounding = 0; /* Default to floor */ + + /* Deal with right shifts */ + if (Shift < 0) + { + Divider = (Numerator - 1) ^ Numerator; + Multiplier = 1 << (-Shift); + if (Divider > Multiplier) + Divider = Multiplier; + Numerator /= Divider; + Denominator *= Multiplier / Divider; + Shift = 0; + } + + if (!RoundingKind) /* Nearest */ + Rounding = Denominator >> 1; + else if (RoundingKind > 0) /* Ceiling */ + Rounding = Denominator - 1; + + return ((Numerator / Denominator) << Shift) + + ((((Numerator % Denominator) << Shift) + Rounding) / Denominator); +} + +static void rage_setpage(int page) +{ + page*=2; + rage_outl(ATIIOPortMEM_VGA_WP_SEL, page | ((page+1)<<16)); + rage_outl(ATIIOPortMEM_VGA_RP_SEL, page | ((page+1)<<16)); +} + +static void rage_setrdpage(int page) +{ + page*=2; + rage_outl(ATIIOPortMEM_VGA_RP_SEL, page | ((page+1)<<16)); +} + +static void rage_setwrpage(int page) +{ + page*=2; + rage_outl(ATIIOPortMEM_VGA_WP_SEL, page | ((page+1)<<16)); +} + +/* Fill in chipset specific mode information */ +static void rage_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = rage_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = rage_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + modeinfo->flags |= HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(rage_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int rage_saveregs(unsigned char regs[]) +{ + ATIHWPtr save; + int i; + + save=(ATIHWPtr)(regs+VGA_TOTAL_REGS); + + save->crtc_gen_cntl = rage_inl(ATIIOPortCRTC_GEN_CNTL); + + save->crtc_h_total_disp = rage_inl(ATIIOPortCRTC_H_TOTAL_DISP); + save->crtc_h_sync_strt_wid = rage_inl(ATIIOPortCRTC_H_SYNC_STRT_WID); + save->crtc_v_total_disp = rage_inl(ATIIOPortCRTC_V_TOTAL_DISP); + save->crtc_v_sync_strt_wid = rage_inl(ATIIOPortCRTC_V_SYNC_STRT_WID); + save->crtc_off_pitch = rage_inl(ATIIOPortCRTC_OFF_PITCH); + + save->ovr_clr = rage_inl(ATIIOPortOVR_CLR); + + save->clock_cntl = rage_inl(ATIIOPortCLOCK_CNTL); + + save->bus_cntl = rage_inl(ATIIOPortBUS_CNTL); + + save->mem_vga_wp_sel = rage_inl(ATIIOPortMEM_VGA_WP_SEL); + save->mem_vga_rp_sel = rage_inl(ATIIOPortMEM_VGA_RP_SEL); + + save->dac_cntl = rage_inl(ATIIOPortDAC_CNTL); /* internal DAC */ + + save->config_cntl = rage_inl(ATIIOPortCONFIG_CNTL); + + save->mem_info = rage_inl(ATIIOPortMEM_INFO); + + save->crtc_int_cntl=rage_inl(ATIIOPortCRTC_INT_CNTL); + save->crtc_gen_cntl=rage_inl(ATIIOPortCRTC_GEN_CNTL); + save->gen_test_cntl=rage_inl(ATIIOPortGEN_TEST_CNTL); + + if((ATIChip>=ATI_CHIP_264VTB)&&(ATIIODecoding==BLOCK_IO)) { + save->dsp_on_off=rage_inl(ATIIOPortDSP_ON_OFF); + save->dsp_config=rage_inl(ATIIOPortDSP_CONFIG); + }; + + ATIIOPortDAC_DATA = ATIIOPortDAC_REGS + 1; + ATIIOPortDAC_MASK = ATIIOPortDAC_REGS + 2; + ATIIOPortDAC_READ = ATIIOPortDAC_REGS + 3; + ATIIOPortDAC_WRITE = ATIIOPortDAC_REGS + 0; + save->dac_read = rage_inb(ATIIOPortDAC_READ); + save->dac_write = rage_inb(ATIIOPortDAC_WRITE); + save->dac_mask = rage_inb(ATIIOPortDAC_MASK); + + rage_outl(ATIIOPortCRTC_GEN_CNTL, save->crtc_gen_cntl | 0x1000000); + + switch(rage_clock){ + case -1: /* internal clock */ + for(i=6;i<12;i++) + save->PLL[i]=ATIGetMach64PLLReg(i); /* internal Clock */ + break; + case 4: /* CH8398 */ + i=rage_inl(ATIIOPortDAC_CNTL); + rage_outl(ATIIOPortDAC_CNTL,(i&~3)|3); + rage_outb(ATIIOPortDAC_READ, ATIClockToProgram); + save->PLL[0]=rage_inb(ATIIOPortDAC_DATA); + save->PLL[1]=rage_inb(ATIIOPortDAC_DATA); + rage_outl(ATIIOPortDAC_CNTL,i); + break; + }; + + rage_outb(ATIIOPortDAC_MASK, 0xFFU); + rage_outb(ATIIOPortDAC_READ, 0x00U); + + for (i = 0; iDAC[i] =rage_inb(ATIIOPortDAC_DATA); + + switch(rage_dac){ + case -1: + save->cur_clr0=rage_inl(ATIIOPortCUR_CLR0); + save->cur_clr1=rage_inl(ATIIOPortCUR_CLR1); + save->cur_offset=rage_inl(ATIIOPortCUR_OFFSET); + save->cur_horz_vert_posn=rage_inl(ATIIOPortCUR_HORZ_VERT_POSN); + save->cur_horz_vert_off=rage_inl(ATIIOPortCUR_HORZ_VERT_OFF); + break; + case 4: /* CH8398 */ + i=rage_inl(ATIIOPortDAC_CNTL); + rage_outl(ATIIOPortDAC_CNTL,(i&~3)|3); + save->extdac[4]=rage_inb(ATIIOPortDAC_WRITE); + save->extdac[5]=rage_inb(ATIIOPortDAC_DATA); + save->extdac[7]=rage_inb(ATIIOPortDAC_READ); + save->extdac[6]=rage_inb(ATIIOPortDAC_MASK); + rage_outl(ATIIOPortDAC_CNTL,i); + break; + case 5: + i=rage_inl(ATIIOPortDAC_CNTL); + rage_outl(ATIIOPortDAC_CNTL,(i&~3)|2); + save->extdac[8]=rage_inb(ATIIOPortDAC_WRITE); + save->extdac[10]=rage_inb(ATIIOPortDAC_MASK); + save->extdac[11]=rage_inb(ATIIOPortDAC_READ); + rage_outl(ATIIOPortDAC_CNTL,(i&~3)|3); + save->extdac[12]=rage_inb(ATIIOPortDAC_WRITE); + rage_outl(ATIIOPortDAC_CNTL,i); + break; + }; + + if(ATIChipatib[i]=rage_inb(0x1cf); + } + + rage_outl(ATIIOPortCRTC_GEN_CNTL, save->crtc_gen_cntl); + + return RAGE_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void rage_setregs(const unsigned char regs[], int mode) +{ + ATIHWPtr restore; + int Index; + int i; + + restore=(ATIHWPtr)(regs+VGA_TOTAL_REGS); + + rage_outl(ATIIOPortCRTC_GEN_CNTL, restore->crtc_gen_cntl & ~CRTC_EN ); + + /* Load Mach64 CRTC registers */ + rage_outl(ATIIOPortCRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); + rage_outl(ATIIOPortCRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); + rage_outl(ATIIOPortCRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); + rage_outl(ATIIOPortCRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); + rage_outl(ATIIOPortCRTC_OFF_PITCH, restore->crtc_off_pitch); + /* Set pixel clock */ + rage_outl(ATIIOPortCLOCK_CNTL, restore->clock_cntl); + + /* Load overscan registers */ + rage_outl(ATIIOPortOVR_CLR, restore->ovr_clr); + + /* Finalize CRTC setup and turn on the screen */ + rage_outl(ATIIOPortCRTC_GEN_CNTL, restore->crtc_gen_cntl); + + /* Aperture setup */ + rage_outl(ATIIOPortBUS_CNTL, restore->bus_cntl); + + rage_outl(ATIIOPortMEM_VGA_WP_SEL, restore->mem_vga_wp_sel); + rage_outl(ATIIOPortMEM_VGA_RP_SEL, restore->mem_vga_rp_sel); + + rage_outl(ATIIOPortCONFIG_CNTL, restore->config_cntl); + + if((ATIChip>=ATI_CHIP_264VTB)&&(ATIIODecoding==BLOCK_IO)) { + rage_outl(ATIIOPortDSP_ON_OFF, restore->dsp_on_off); + rage_outl(ATIIOPortDSP_CONFIG, restore->dsp_config); + }; + + rage_outl(ATIIOPortMEM_INFO, restore->mem_info); + rage_outl(ATIIOPortCRTC_INT_CNTL,restore->crtc_int_cntl); + rage_outl(ATIIOPortCRTC_GEN_CNTL,restore->crtc_gen_cntl); + rage_outl(ATIIOPortGEN_TEST_CNTL,restore->gen_test_cntl); + + rage_outl(ATIIOPortCRTC_GEN_CNTL, restore->crtc_gen_cntl | 0x1000000); + + switch(rage_clock){ + case -1: /* internal clock */ + i=ATIGetMach64PLLReg(PLL_VCLK_CNTL) | PLL_VCLK_RESET; + ATIPutMach64PLLReg(PLL_VCLK_CNTL,i); + + ATIPutMach64PLLReg(PLL_VCLK_POST_DIV, restore->PLL[PLL_VCLK_POST_DIV]); + ATIPutMach64PLLReg(PLL_XCLK_CNTL, restore->PLL[PLL_XCLK_CNTL]); + ATIPutMach64PLLReg(PLL_VCLK0_FB_DIV+ATIClockToProgram, restore->PLL[PLL_VCLK0_FB_DIV+ATIClockToProgram]); + + i&= ~PLL_VCLK_RESET; + ATIPutMach64PLLReg(PLL_VCLK_CNTL,i); + break; + case 4: /* CH8398 */ + i=rage_inl(ATIIOPortDAC_CNTL); + rage_outl(ATIIOPortDAC_CNTL,(i&~3)|3); + rage_outb(ATIIOPortDAC_WRITE, ATIClockToProgram); + rage_outb(ATIIOPortDAC_DATA, restore->PLL[0]); + rage_outb(ATIIOPortDAC_DATA, restore->PLL[1]); + rage_outl(ATIIOPortDAC_CNTL,i); + break; + }; + + /* make sure the dac is in 8 bit or 6 bit mode, as needed */ + rage_outl(ATIIOPortDAC_CNTL, restore->dac_cntl); + + rage_outb(ATIIOPortDAC_MASK, 0xFFU); + rage_outb(ATIIOPortDAC_WRITE, 0x00U); + for (Index = 0; Index < DAC_SIZE; Index++) + rage_outb(ATIIOPortDAC_DATA, restore->DAC[Index]); + + switch(rage_dac){ + case -1: + rage_outl(ATIIOPortCUR_CLR0, restore->cur_clr0); + rage_outl(ATIIOPortCUR_CLR1, restore->cur_clr1); + rage_outl(ATIIOPortCUR_OFFSET, restore->cur_offset); + rage_outl(ATIIOPortCUR_HORZ_VERT_POSN, restore->cur_horz_vert_posn); + rage_outl(ATIIOPortCUR_HORZ_VERT_OFF, restore->cur_horz_vert_off); + break; + case 4: /* CH8398 */ + i=rage_inl(ATIIOPortDAC_CNTL); + rage_outl(ATIIOPortDAC_CNTL,(i&~3)|3); + rage_outb(ATIIOPortDAC_MASK, restore->extdac[6]); + rage_outl(ATIIOPortDAC_CNTL,i); + break; + case 5: + i=rage_inl(ATIIOPortDAC_CNTL); + rage_outl(ATIIOPortDAC_CNTL,(i&0xfffffffc)|2); + rage_outb(ATIIOPortDAC_WRITE,restore->extdac[8]); + rage_outb(ATIIOPortDAC_MASK,restore->extdac[10]); + rage_outb(ATIIOPortDAC_READ,restore->extdac[11]); + rage_outl(ATIIOPortDAC_CNTL,(i&0xfffffffc)|3); + rage_outb(ATIIOPortDAC_WRITE,(rage_inb(ATIIOPortDAC_WRITE)&0x80)|restore->extdac[12]); + break; + }; + + rage_outb(ATIIOPortDAC_READ, restore->dac_read); + rage_outb(ATIIOPortDAC_WRITE, restore->dac_write); + rage_outl(ATIIOPortDAC_CNTL, restore->dac_cntl); + + if(ATIChipatib[i]); + } + rage_outl(ATIIOPortCRTC_GEN_CNTL, restore->crtc_gen_cntl); + +}; +/* Return nonzero if mode is available */ + +static int rage_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (rage_memory * 1024 < info->ydim * info->xbytes) + return 0; + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + + +static unsigned comp_lmn(unsigned clock, int *n, int *mp, int *lp); +static int rage_map_clock(int bpp, int clock); +static int ClacDSP(int n, int l, int bpp, unsigned int *conf, unsigned int *onoff); +/* Local, called by rage_setmode(). */ +static void rage_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + int m,n,l,i; + ATIHWPtr ATINewHWPtr; + int + horizDisplay = (modetiming->CrtcHDisplay/8) - 1, + horizStart = (modetiming->CrtcHSyncStart/8) - 1, + horizWidth = (modetiming->CrtcHSyncEnd/8) - (modetiming->CrtcHSyncStart/8), + horizTotal = (modetiming->CrtcHTotal/8) - 1, + vertDisplay = modetiming->CrtcVDisplay -1, + vertStart = modetiming->CrtcVSyncStart -1, + vertWidth = modetiming->CrtcVSyncEnd - modetiming->CrtcVSyncStart, + vertTotal = modetiming->CrtcVTotal -1; + + ATINewHWPtr=(ATIHWPtr)(moderegs+VGA_TOTAL_REGS); + + moderegs[GRA+0]=0; + moderegs[GRA+1]=0; + moderegs[GRA+2]=0; + moderegs[GRA+3]=0; + moderegs[GRA+4]=0; + moderegs[GRA+5]=0x10; + moderegs[GRA+6]=1; + moderegs[GRA+7]=0; + moderegs[GRA+8]=0xff; + moderegs[SEQ+0]=0x3; + moderegs[SEQ+1]=0x0; + moderegs[SEQ+2]=0x0F; + moderegs[SEQ+3]=0x0; + moderegs[SEQ+4]=0x0A; + moderegs[ATT+0x10]=0x0c; + moderegs[ATT+0x11]=0x11; + moderegs[ATT+0x12]=0xf; + moderegs[ATT+0x13]=0x13; + moderegs[ATT+0x14]=0; + moderegs[VGA_MISCOUTPUT]=0x27; + + ATINewHWPtr->clock_cntl=ATIClockToProgram; + + ATINewHWPtr->crtc_int_cntl=(rage_inl(ATIIOPortCRTC_INT_CNTL) & ~CRTC_INT_ENS) + | CRTC_INT_ACKS /*0x80000074 */; + + ATINewHWPtr->shared_cntl=0; + ATINewHWPtr->gen_test_cntl=0; + + ATINewHWPtr->mem_info=rage_inl(ATIIOPortMEM_INFO); + + if(ATIChipmem_info &= ~(CTL_MEM_BNDRY | CTL_MEM_BNDRY_EN) ; + + ATINewHWPtr->PLL[PLL_VCLK_POST_DIV]=ATIGetMach64PLLReg(PLL_VCLK_POST_DIV); + ATINewHWPtr->PLL[PLL_XCLK_CNTL]=ATIGetMach64PLLReg(PLL_XCLK_CNTL); + + for(i=0;i<256;i++)ATINewHWPtr->DAC[i*3]=ATINewHWPtr->DAC[i*3+1]= + ATINewHWPtr->DAC[i*3+2]=i; + + ATINewHWPtr->crtc_off_pitch=SetBits(modeinfo->width >> 3, CRTC_PITCH); + + ATINewHWPtr->bus_cntl = (rage_inl(ATIIOPortBUS_CNTL) & + ~BUS_HOST_ERR_INT_EN) | BUS_HOST_ERR_INT; + if (ATIChip < ATI_CHIP_264VTB) + ATINewHWPtr->bus_cntl = (ATINewHWPtr->bus_cntl & + ~(BUS_FIFO_ERR_INT_EN | BUS_ROM_DIS)) | + (SetBits(15, BUS_FIFO_WS) | BUS_FIFO_ERR_INT); + else + ATINewHWPtr->bus_cntl |= BUS_APER_REG_DIS; + + ATINewHWPtr->dac_cntl=rage_inl(ATIIOPortDAC_CNTL); + + if (modeinfo->bitsPerPixel>8) + ATINewHWPtr->dac_cntl |= DAC_8BIT_EN; + else + ATINewHWPtr->dac_cntl &= ~DAC_8BIT_EN; + + ATINewHWPtr->config_cntl= rage_inl(ATIIOPortCONFIG_CNTL) | CFG_MEM_VGA_AP_EN | 2; + + ATINewHWPtr->ovr_clr=0; + + comp_lmn(rage_map_clock(modeinfo->bitsPerPixel, modetiming->pixelClock),&n,&m,&l); + + switch(rage_clock) { + case 5: + ATINewHWPtr->ics2595=n|(l<<9); + break; + case 4: /* CH8398 */ + for(i=0;i<16;i++)ATINewHWPtr->atib[i]=0; + ATINewHWPtr->atib[6]=0x04; + ATINewHWPtr->PLL[0]=n; + ATINewHWPtr->PLL[1]=m | (l<<6); + ATINewHWPtr->clock_cntl = 0x40 + ATIClockToProgram; + break; + case -1: + ATINewHWPtr->PLL[PLL_VCLK0_FB_DIV+ATIClockToProgram]=n; + ATINewHWPtr->PLL[PLL_VCLK_POST_DIV]&=0xfc<<(ATIClockToProgram<<1); + ATINewHWPtr->PLL[PLL_VCLK_POST_DIV]|=(l&3)<<(ATIClockToProgram<<1); + ATINewHWPtr->PLL[PLL_XCLK_CNTL]&=~(0x10<PLL[PLL_XCLK_CNTL]|=((l>>2)<<4)<0x1f) { + horizWidth=0x1f; + } else if(horizWidth<1) { + horizWidth=1; + if(horizStart>horizDisplay)horizStart++; + } + + ATINewHWPtr->crtc_h_total_disp = + SetBits(horizTotal, CRTC_H_TOTAL) | + SetBits(horizDisplay, CRTC_H_DISP); + ATINewHWPtr->crtc_h_sync_strt_wid = + SetBits(horizStart, CRTC_H_SYNC_STRT) | + SetBits(0, CRTC_H_SYNC_DLY) | + SetBits(GetBits(horizStart, 0x0100U),CRTC_H_SYNC_STRT_HI) | + SetBits(horizWidth,CRTC_H_SYNC_WID); + if (modetiming->flags & NHSYNC) + ATINewHWPtr->crtc_h_sync_strt_wid |= CRTC_H_SYNC_POL; + + ATINewHWPtr->crtc_v_total_disp = + SetBits(vertTotal, CRTC_V_TOTAL) | + SetBits(vertDisplay, CRTC_V_DISP); + ATINewHWPtr->crtc_v_sync_strt_wid = + SetBits(vertStart, CRTC_V_SYNC_STRT) | + SetBits(vertWidth,CRTC_V_SYNC_WID); + if (modetiming->flags & NVSYNC) + ATINewHWPtr->crtc_v_sync_strt_wid |= CRTC_V_SYNC_POL; + + ATINewHWPtr->crtc_gen_cntl = rage_inl(ATIIOPortCRTC_GEN_CNTL) & + ~(CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN | + CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_CSYNC_EN | + CRTC_PIX_BY_2_EN | CRTC_DISPLAY_DIS | CRTC_VGA_XOVERSCAN | + CRTC_PIX_WIDTH | CRTC_BYTE_PIX_ORDER | CRTC_FIFO_LWM | + CRTC_VGA_128KAP_PAGING | CRTC_VFC_SYNC_TRISTATE | + CRTC_LOCK_REGS | + CRTC_SYNC_TRISTATE | CRTC_DISP_REQ_EN | + CRTC_VGA_TEXT_132 | CRTC_CUR_B_TEST); + ATINewHWPtr->crtc_gen_cntl |= CRTC_EXT_DISP_EN | CRTC_EN | + CRTC_VGA_LINEAR | CRTC_CNT_EN | CRTC_BYTE_PIX_ORDER; + + switch (modeinfo->bitsPerPixel) + { + case 1: + ATINewHWPtr->crtc_gen_cntl |= CRTC_PIX_WIDTH_1BPP; + break; + case 4: + ATINewHWPtr->crtc_gen_cntl |= CRTC_PIX_WIDTH_4BPP; + break; + case 8: + ATINewHWPtr->crtc_gen_cntl |= CRTC_PIX_WIDTH_8BPP; + break; + case 16: + switch(modeinfo->colorBits) + { + case 15: + ATINewHWPtr->crtc_gen_cntl |= CRTC_PIX_WIDTH_15BPP; + break; + case 16: + ATINewHWPtr->crtc_gen_cntl |= CRTC_PIX_WIDTH_16BPP; + break; + }; + break; + case 24: + ATINewHWPtr->crtc_gen_cntl |= CRTC_PIX_WIDTH_24BPP; + break; + case 32: + ATINewHWPtr->crtc_gen_cntl |= CRTC_PIX_WIDTH_32BPP; + break; + default: + break; + } + + if (modetiming->flags & DOUBLESCAN) + ATINewHWPtr->crtc_gen_cntl |= CRTC_DBL_SCAN_EN; + if (modetiming->flags & INTERLACED) + ATINewHWPtr->crtc_gen_cntl |= CRTC_INTERLACE_EN; + + switch(rage_dac){ + case 4: /* CH8398 */ + moderegs[VGA_MISCOUTPUT]=0x6f; + switch(modeinfo->bitsPerPixel) { + case 8: ATINewHWPtr->extdac[6]=0x04; break; + case 16: + if(modeinfo->colorBits==15) ATINewHWPtr->extdac[6]=0x14; + else ATINewHWPtr->extdac[6]=0x34; + break; + case 24: ATINewHWPtr->extdac[6]=0xb4; break; + }; + break; + case 5: /* 68860/68880 */ + ATINewHWPtr->extdac[8]=2; + ATINewHWPtr->extdac[10]=0x1d; + switch(modeinfo->bitsPerPixel) { + case 8: ATINewHWPtr->extdac[11]=0x83; break; + case 15: ATINewHWPtr->extdac[11]=0xa0; break; + case 16: ATINewHWPtr->extdac[11]=0xa1; break; + case 24: ATINewHWPtr->extdac[11]=0xc0; break; + case 32: ATINewHWPtr->extdac[11]=0xe3; break; + }; + ATINewHWPtr->extdac[12]=0x60; + if(modeinfo->bitsPerPixel==8)ATINewHWPtr->extdac[12]=0x61; + if(rage_memory<1024)ATINewHWPtr->extdac[12]|=0x04; + if(rage_memory==1024)ATINewHWPtr->extdac[12]|=0x08; + if(rage_memory>1024)ATINewHWPtr->extdac[12]|=0x0c; + break; + }; + + rage_bpp = modeinfo->bytesPerPixel; + + if((ATIChip>=ATI_CHIP_264VTB)&&(ATIIODecoding==BLOCK_IO)) + ClacDSP(n, l, modeinfo->bitsPerPixel, &ATINewHWPtr->dsp_config, &ATINewHWPtr->dsp_on_off); + if (ATIChip < ATI_CHIP_264VTB) + ATINewHWPtr->crtc_gen_cntl |= CRTC_FIFO_LWM; + +} + + +static int rage_setmode(int mode, int prv_mode) +{ + + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + ATIHWPtr ATINewHWPtr; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!rage_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(MAX_REGS); + + ATINewHWPtr=(ATIHWPtr)(moderegs+VGA_TOTAL_REGS); + + rage_initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); + rage_setregs(moderegs, mode); + free(moderegs); + + free(modeinfo); + + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void rage_unlock(void) +{ +} + +static void rage_lock(void) +{ +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int rage_test(void) +{ + int i=0, found; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(0x1002,buf); + if(!found)return 0; + + rage_init(0,0,0); + return 1; + + ATIIOBase=buf[5]&BLOCK_IO_BASE; + + if(ATIIOBase) + { + ATIIODecoding=BLOCK_IO; + i=rage_probe(); + } else + { + ATIIOBase=0x2EC; + ATIIODecoding=SPARSE_IO; + if(!(i=rage_probe())){ + ATIIOBase=0x1C8; + if(!(i=rage_probe())){ + ATIIOBase=0x1CC; + i=rage_probe(); + }; + }; + }; + + if(!i)return 0; + + rage_init(0,0,0); + return 1; +} + +/* Set display start address (not for 16 color modes) */ + +static void rage_setdisplaystart(int address) +{ + unsigned int t; + + address>>=3; + t=rage_inl(ATIIOPortCRTC_OFF_PITCH); + rage_outl(ATIIOPortCRTC_OFF_PITCH,(t&~CRTC_OFFSET)|address); + +} + +static void rage_setlogicalwidth(int width) +{ + unsigned int t; + + if(rage_bpp>0)width=width/rage_bpp; + t=rage_inl(ATIIOPortCRTC_OFF_PITCH); + rage_outl(ATIIOPortCRTC_OFF_PITCH,(t&~CRTC_PITCH)|((width>>3)<<22)); + +} + +static int rage_linear(int op, int param) +{ + if (op==LINEAR_DISABLE || op==LINEAR_ENABLE) return 0; + if (op==LINEAR_QUERY_BASE) return __svgalib_linear_mem_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int rage_match_programmable_clock(int clock) +{ +return clock ; +} + +static int rage_map_clock(int bpp, int clock) +{ + if((bpp==24)&&(rage_clock==4))clock += (clock>>1); + return clock ; +} + +static int rage_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +static int pal=1, palette[768]; + +static int findcolor(int rgb) { + int i,j,k,l=0; + + if(pal)vga_getpalvec(0,256,palette); + pal=0; + k=0xffffff; + for(i=0;i<256;i++) { + j=((rgb&0xff)-(palette[i*3+2]<<2))*((rgb&0xff)-(palette[i*3+2]<<2))+ + (((rgb>>8)&0xff)-(palette[i*3+1]<<2))*(((rgb>>8)&0xff)-(palette[i*3+1]<<2))+ + (((rgb>>16)&0xff)-(palette[i*3]<<2))*(((rgb>>16)&0xff)-(palette[i*3]<<2)); + if(j==0) { + return i; + } + if(j>3); + rage_outl(ATIIOPortCUR_CLR0,cur_colors[p1*2]); + rage_outl(ATIIOPortCUR_CLR1,cur_colors[p1*2+1]); + break; + case CURSOR_IMAGE: + i=rage_memory*1024-(p1+1)*4096; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*2]=p3<<8 | findcolor(p3); + cur_colors[p1*2+1]=p4<<8 | findcolor(p4); + for(j=0;j<32;j++) { + l1=*(b3+j); + l2=~(*(b3+32+j)); + for(k=0;k<8;k++) { + c=0; + for(l=0;l<4;l++) { + c>>=1; + c|=(l1>>31)<<7; + c>>=1; + c|=(l2>>31)<<7; + if(c&128)c&=0xbf; + l1<<=1; + l2<<=1; + } + *(LINEAR_POINTER+i+16*j+k)=c; + *(LINEAR_POINTER+i+16*j+k+8)=0xaa; + } + } + memset(LINEAR_POINTER+i+512,0xaa,512); + break; + } + break; + } + return 0; +} + +/* Function table (exported) */ +DriverSpecs __svgalib_rage_driverspecs = +{ + rage_saveregs, + rage_setregs, + rage_unlock, + rage_lock, + rage_test, + rage_init, + rage_setpage, + rage_setrdpage, + rage_setwrpage, + rage_setmode, + rage_modeavailable, + rage_setdisplaystart, + rage_setlogicalwidth, + rage_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + rage_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + rage_cursor +}; + +/* Initialize chipset (called after detection) */ + +static int rage_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + int i,j; + unsigned char *BIOS; + + static int videoRamSizes[] = { 0 , 256 , 512 , 1024, 2*1024 , + 4*1024 , 6*1024 , 8*1024 , 12*1024 , 16*1024 , 0 }; + + rage_unlock(); + if (force) { + rage_memory = par1; + rage_chiptyperev = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(0x1002,buf); + rage_linear_base=0; + if (found){ + rage_linear_base=buf[4]&0xffffff00u; +#if 0 + // This uses IO + ATIIOBase=buf[5]&BLOCK_IO_BASE; +#else + // This uses MMIO + __svgalib_mmio_base=buf[6]&0xffffff00u; + if(__svgalib_mmio_base==0) { + __svgalib_mmio_base=rage_linear_base+0x007ff000; + ATIIOBase=0xc00; + } else { + ATIIOBase=1024; + } + __svgalib_mmio_size=4096; + map_mmio(); +#endif + }; + + if(ATIIOBase) + { + ATIIODecoding=BLOCK_IO; + i=rage_probe(); + } else + { + ATIIOBase=0x2EC; + ATIIODecoding=SPARSE_IO; + if(!(i=rage_probe())){ + ATIIOBase=0x1C8; + if(!(i=rage_probe())){ + ATIIOBase=0x1CC; + i=rage_probe(); + }; + }; + }; + + if(!found || !i){ + fprintf(stderr,"svgalib: Rage driver must be used, but not found\n"); + exit(1); + }; + + rage_chiptyperev=(buf[0]&0xffff0000) | (buf[2]&0xff); + + rage_ChipID(); + + ATIIOPortCRTC_H_TOTAL_DISP=ATIIOPort(CRTC_H_TOTAL_DISP); + ATIIOPortCRTC_H_SYNC_STRT_WID=ATIIOPort(CRTC_H_SYNC_STRT_WID); + ATIIOPortCRTC_V_TOTAL_DISP=ATIIOPort(CRTC_V_TOTAL_DISP); + ATIIOPortCRTC_V_SYNC_STRT_WID=ATIIOPort(CRTC_V_SYNC_STRT_WID); + ATIIOPortCRTC_OFF_PITCH=ATIIOPort(CRTC_OFF_PITCH); + ATIIOPortCRTC_INT_CNTL=ATIIOPort(CRTC_INT_CNTL); + ATIIOPortCRTC_GEN_CNTL=ATIIOPort(CRTC_GEN_CNTL); + ATIIOPortDSP_CONFIG=ATIIOPort(DSP_CONFIG); + ATIIOPortDSP_ON_OFF=ATIIOPort(DSP_ON_OFF); + ATIIOPortOVR_CLR=ATIIOPort(OVR_CLR); + ATIIOPortCLOCK_CNTL=ATIIOPort(CLOCK_CNTL); + ATIIOPortBUS_CNTL=ATIIOPort(BUS_CNTL); + ATIIOPortMEM_INFO=ATIIOPort(MEM_INFO); + ATIIOPortMEM_VGA_WP_SEL=ATIIOPort(MEM_VGA_WP_SEL); + ATIIOPortMEM_VGA_RP_SEL=ATIIOPort(MEM_VGA_RP_SEL); + ATIIOPortDAC_REGS=ATIIOPort(DAC_REGS); + ATIIOPortDAC_CNTL=ATIIOPort(DAC_CNTL); + ATIIOPortGEN_TEST_CNTL=ATIIOPort(GEN_TEST_CNTL); + ATIIOPortCONFIG_CNTL=ATIIOPort(CONFIG_CNTL); + ATIIOPortCONFIG_STATUS64_0=ATIIOPort(CONFIG_STATUS64_0); + ATIIOPortCUR_HORZ_VERT_OFF=ATIIOPort(CUR_HORZ_VERT_OFF); + ATIIOPortCUR_HORZ_VERT_POSN=ATIIOPort(CUR_HORZ_VERT_POSN); + ATIIOPortCUR_CLR0=ATIIOPort(CUR_CLR0); + ATIIOPortCUR_CLR1=ATIIOPort(CUR_CLR1); + ATIIOPortCUR_OFFSET=ATIIOPort(CUR_OFFSET); + i = rage_inl(ATIIOPort(MEM_INFO)); + j = rage_inl(ATIIOPort(CONFIG_STATUS64_0)); + if(ATIChip=ATI_CHIP_264VTB) { + i = GetBits(i, CTL_MEM_SIZEB); + if (i < 8) rage_memory = (i + 1) * 512; + else if (i < 12) rage_memory = (i - 3) * 1024; + else rage_memory = (i - 7) * 2048; + } else { + i = GetBits(i, CTL_MEM_SIZE); + rage_memory = videoRamSizes[i+2]; + }; + + rage_mapio(); + + if (__svgalib_driver_report) { + fprintf(stderr,"Using RAGE driver, %iKB. ChipID:%i MemType:%i\n", + rage_memory,ATIChip,ATIMemoryType); + if(rage_dac)fprintf(stderr,"Using external DAC:%i\n",rage_dac); + } + if(ATIChip>=ATI_CHIP_264GTPRO) /* enable offset double buffering */ + rage_outl(ATIIOPort(HW_DEBUG), rage_inl(ATIIOPort(HW_DEBUG))|0x400); + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = rage_memory; + switch(ATIChip){ + case ATI_CHIP_264GTPRO: + case ATI_CHIP_264LTPRO: + cardspecs->maxPixelClock8bpp = 230000; + cardspecs->maxPixelClock16bpp = 230000; + cardspecs->maxPixelClock24bpp = 230000; + cardspecs->maxPixelClock32bpp = 230000; + break; + case ATI_CHIP_264GTDVD: + case ATI_CHIP_264LT: + case ATI_CHIP_264VT4: + case ATI_CHIP_264GT2C: + case ATI_CHIP_264VT3: + cardspecs->maxPixelClock8bpp = 200000; + cardspecs->maxPixelClock16bpp = 200000; + cardspecs->maxPixelClock24bpp = 200000; + cardspecs->maxPixelClock32bpp = 200000; + break; + case ATI_CHIP_264VTB: + case ATI_CHIP_264GTB: + cardspecs->maxPixelClock8bpp = 170000; + cardspecs->maxPixelClock16bpp = 170000; + cardspecs->maxPixelClock24bpp = 170000; + cardspecs->maxPixelClock32bpp = 170000; + break; + default: + cardspecs->maxPixelClock8bpp = 135000; + cardspecs->maxPixelClock16bpp =135000; + cardspecs->maxPixelClock24bpp = 60000; + cardspecs->maxPixelClock32bpp = 60000; + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs->flags = CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->nClocks = 0; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->mapClock = rage_map_clock; + cardspecs->mapHorizontalCrtc = rage_map_horizontal_crtc; + cardspecs->matchProgrammableClock=rage_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_rage_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=rage_linear_base; + __svgalib_linear_mem_size=rage_memory*0x400; + +#define BIOSWord(x) ((int)BIOS[x]+256*(int)BIOS[x+1]) + + if(biosparams) { + fref=biosparam[1]; + ATIClockToProgram=biosparam[0]; + rage_dac = -1; + rage_clock = -1; + maxM=minM=ATIGetMach64PLLReg(PLL_REF_DIV); + minN=2; + maxN=255; + Nadj=0; + Madj=0; + fref*=2; /* X says double for all chips */ + } else { + BIOS=mmap(0,32*1024,PROT_READ|PROT_WRITE,MAP_SHARED,__svgalib_mem_fd,0xc0000); + + i=BIOSWord(0x48); + j=BIOSWord(i+0x10); + + ATIClockToProgram=BIOS[j+6]; + + if(ATIChip>=ATI_CHIP_264CT) { + rage_dac = -1; + rage_clock = -1; + maxM=minM=ATIGetMach64PLLReg(PLL_REF_DIV); + minN=2; + maxN=255; + switch (BIOSWord(j+0x08)/10) { + case 143: + fref=14318; + break; + case 286: + fref=28636; + break; + default: + fref=BIOSWord(j+0x08)*10; + break; + } + Nadj=0; + Madj=0; + fref*=2; /* X says double for all chips */ + + if(__svgalib_ragedoubleclock)fref/=2; /* just in case */ + if (__svgalib_driver_report) { + fprintf(stderr,"Rage: BIOS reports base frequency=%.3fMHz Denominator=%3i\n", + fref/1000,maxM); + } + } else { + rage_dac=(j>>9)&7; + switch(rage_dac) { + case 4: + rage_clock=4; + Nadj=8; + minN=64; + maxN=263; + maxM=34; + minM=23; + Madj=2; + for(i=0;i<3;i++)postdiv[i]=1<maxPixelClock32bpp = 0; + break; + case 5: + rage_clock=5; + maxM=minM=46; + Madj=0; + minN=257; + maxN=512; + Nadj=257; + for(i=0;i<4;i++)postdiv[i]=1<= (c1)) && ((v) <= (c2))) + +static unsigned +comp_lmn(unsigned clock, int *np, int *mp, int *lp) +{ + int n, m, l; + double fvco; + double fout; + double fvco_goal; + + for (m = minM; m <= maxM; m++) + { + for (l = 0;(l < 8); l++) if(postdiv[l]) + { + for (n = minN; n <= maxN; n++) + { + fout = ((double)(n) * fref)/((double)(m) * (postdiv[l])); + fvco_goal = (double)clock * (double)(postdiv[l]); + fvco = fout * (double)(postdiv[l]); + if (!WITHIN(fvco, 0.995*fvco_goal, 1.005*fvco_goal)) + continue; + *lp=l; + *np=n-Nadj; + *mp=m-Madj; + return 1 ; + } + } + } +fprintf(stderr,"Can't do clock=%i\n",clock); +fprintf(stderr,"fref=%f, M= in %i - %i, N in %i - %i\n",fref,minM, maxM, minN,maxN); +{int i; for (i=0;i<8;i++) fprintf(stderr,"%i ",postdiv[i]); fprintf(stderr,"\n");}; + return 0; +} + +static int ClacDSP(int n, int l, int bpp, unsigned int *conf, unsigned int *onoff) +{ + int ATIDisplayFIFODepth; + int Multiplier, Divider, vshift, xshift; + int dsp_precision, dsp_on, dsp_off, dsp_xclks; + unsigned int dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off; + unsigned int tmp; + int ATIXCLKFeedbackDivider, + ATIXCLKReferenceDivider, + ATIXCLKPostDivider; + + int ATIXCLKMaxRASDelay, + ATIXCLKPageFaultDelay, + ATIDisplayLoopLatency; + + int IO_Value; + + IO_Value = ATIGetMach64PLLReg(PLL_XCLK_CNTL); + ATIXCLKPostDivider = GetBits(IO_Value, PLL_XCLK_SRC_SEL); + ATIXCLKReferenceDivider = 1 ; + switch (ATIXCLKPostDivider) + { + case 0: case 1: case 2: case 3: + break; + + case 4: + ATIXCLKReferenceDivider = 3; + ATIXCLKPostDivider = 0; + break; + + default: + return -1; + } + + ATIXCLKPostDivider -= GetBits(IO_Value, PLL_MFB_TIMES_4_2B); + ATIXCLKFeedbackDivider = ATIGetMach64PLLReg(PLL_MCLK_FB_DIV); + + IO_Value = rage_inl(ATIIOPortMEM_INFO); + tmp = GetBits(IO_Value, CTL_MEM_TRP); + ATIXCLKPageFaultDelay = GetBits(IO_Value, CTL_MEM_TRCD) + + GetBits(IO_Value, CTL_MEM_TCRD) + tmp + 2; + ATIXCLKMaxRASDelay = GetBits(IO_Value, CTL_MEM_TRAS) + tmp + 2; + ATIDisplayFIFODepth = 32; + + if ( ATIChip < ATI_CHIP_264VT4 ) + { + ATIXCLKPageFaultDelay += 2; + ATIXCLKMaxRASDelay += 3; + ATIDisplayFIFODepth = 24; + } + + + switch (ATIMemoryType) + { + case MEM_264_DRAM: + if (rage_memory <= 1024) + ATIDisplayLoopLatency = 10; + else + { + ATIDisplayLoopLatency = 8; + ATIXCLKPageFaultDelay += 2; + } + break; + + case MEM_264_EDO: + case MEM_264_PSEUDO_EDO: + if (rage_memory <= 1024) + ATIDisplayLoopLatency = 9; + else + { + ATIDisplayLoopLatency = 8; + ATIXCLKPageFaultDelay++; + } + break; + + case MEM_264_SDRAM: + if (rage_memory <= 1024) + ATIDisplayLoopLatency = 11; + else + { + ATIDisplayLoopLatency = 10; + ATIXCLKPageFaultDelay++; + } + break; + + case MEM_264_SGRAM: + ATIDisplayLoopLatency = 8; + ATIXCLKPageFaultDelay += 3; + break; + + default: + ATIDisplayLoopLatency = 11; + ATIXCLKPageFaultDelay += 3; + break; + } + + if (ATIXCLKMaxRASDelay <= ATIXCLKPageFaultDelay) + ATIXCLKMaxRASDelay = ATIXCLKPageFaultDelay + 1; + + /* Allow BIOS to override */ + dsp_config = rage_inl(ATIIOPortDSP_CONFIG); + dsp_on_off = rage_inl(ATIIOPortDSP_ON_OFF); + vga_dsp_config = rage_inl(ATIIOPort(VGA_DSP_CONFIG)); + vga_dsp_on_off = rage_inl(ATIIOPort(VGA_DSP_ON_OFF)); + + if (dsp_config) + ATIDisplayLoopLatency = GetBits(dsp_config, DSP_LOOP_LATENCY); + + if ((!dsp_on_off && (ATIChip < ATI_CHIP_264GTPRO)) || + ((dsp_on_off == vga_dsp_on_off) && + (!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) + { + if (ATIDivide(GetBits(vga_dsp_on_off, VGA_DSP_OFF), + GetBits(vga_dsp_config, VGA_DSP_XCLKS_PER_QW), 5, 1) > 24) + ATIDisplayFIFODepth = 32; + else + ATIDisplayFIFODepth = 24; + } + +# define Maximum_DSP_PRECISION ((int)GetBits(DSP_PRECISION, DSP_PRECISION)) + + Multiplier = ATIXCLKFeedbackDivider * postdiv[l]; + Divider = n * ATIXCLKReferenceDivider; + + Divider *= bpp >> 2; + + vshift = (6 - 2) - ATIXCLKPostDivider; + + tmp = ATIDivide(Multiplier * ATIDisplayFIFODepth, Divider, vshift, 1); + for (dsp_precision = -5; tmp; dsp_precision++) + tmp >>= 1; + if (dsp_precision < 0) + dsp_precision = 0; + else if (dsp_precision > Maximum_DSP_PRECISION) + dsp_precision = Maximum_DSP_PRECISION; + + xshift = 6 - dsp_precision; + vshift += xshift; + + dsp_off = ATIDivide(Multiplier * (ATIDisplayFIFODepth - 1), Divider, vshift, -1) - + ATIDivide(1, 1, vshift - xshift, 1); + + dsp_on = ATIDivide(Multiplier, Divider, vshift, 1); + tmp = ATIDivide(ATIXCLKMaxRASDelay, 1, xshift, 1); + if (dsp_on < tmp) + dsp_on = tmp; + dsp_on += (tmp*2) + ATIDivide(ATIXCLKPageFaultDelay, 1, xshift, 1); + + + /* Calculate rounding factor and apply it to dsp_on */ + tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1; + dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1); + + if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) { + dsp_on = dsp_off - ATIDivide(Multiplier, Divider, vshift, -1); + dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1); + } + + /* Last but not least: dsp_xclks */ + dsp_xclks = ATIDivide(Multiplier, Divider, vshift + 5, 1); + + *onoff = SetBits(dsp_on, DSP_ON) | SetBits(dsp_off, DSP_OFF); + *conf = SetBits(dsp_precision, DSP_PRECISION) | + SetBits(dsp_xclks, DSP_XCLKS_PER_QW) | + SetBits(ATIDisplayLoopLatency, DSP_LOOP_LATENCY); + + return 0; +} + diff --git a/src/drivers/rage.h b/src/drivers/rage.h new file mode 100644 index 0000000..3d4583a --- /dev/null +++ b/src/drivers/rage.h @@ -0,0 +1,343 @@ +#if 1 +//#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") +#define mb() __asm__ __volatile__ ("": : :"memory") +#define rage_inb(a) v_readb(a) +#define rage_inl(a) v_readl(a) +#define rage_outb(a,v) do {v_writeb(v,a); mb();}while(0) +#define rage_outl(a,v) do {v_writel(v,a); mb();}while(0) +#else +#define rage_inb(a) port_in(a) +#define rage_inl(a) port_inl(a) +#define rage_outb(a,v) port_out_r(a,v) +#define rage_outl(a,v) port_outl_r(a,v) +#endif + +#define SPARSE_IO 0 +#define BLOCK_IO 1 + +#define _ByteMask(__Byte) ((unsigned char)(-1) << (8 * (__Byte))) +#define GetByte(_Value, _Byte) GetBits(_Value, _ByteMask(_Byte)) + +#define GetReg(_Register, _Index) \ + ( \ + rage_outb(_Register, _Index), \ + rage_inb(_Register + 1) \ + ) + +#define ATIIOPort(_PortTag) \ + (((ATIIODecoding == SPARSE_IO) ? \ + (((_PortTag) & SPARSE_IO_SELECT) | ((_PortTag) & IO_BYTE_SELECT)) : \ + (((_PortTag) & BLOCK_IO_SELECT) | ((_PortTag) & IO_BYTE_SELECT))) | \ + ATIIOBase) + +#define ATTRX 0x03c0u +#define ATTRD 0x03c1u +#define SEQX 0x03c4u +#define SEQD 0x03c5u +#define GRAX 0x03ceu +#define GRAD 0x03cfu +#define GENS1 0x03dau +#define CRTX 0x03d4u +#define CRTD 0x03d5u + +#define SPARSE_IO_BASE 0x03fcu +#define SPARSE_IO_SELECT 0xfc00u +#define BLOCK_IO_BASE 0xff00u +#define BLOCK_IO_SELECT 0x00fcu +#define IO_BYTE_SELECT 0x0003u + +#define _UnitOf(___Value) ((((___Value) ^ ((___Value) - 1)) + 1) >> 1) +#define GetBits(__Value, _Mask) (((__Value) & (_Mask)) / _UnitOf(_Mask)) +#define SetBits(__Value, _Mask) (((__Value) * _UnitOf(_Mask)) & (_Mask)) +#define IOPortTag(_SparseIOSelect, _BlockIOSelect) \ + (SetBits(_SparseIOSelect, SPARSE_IO_SELECT) | \ + SetBits(_BlockIOSelect, BLOCK_IO_SELECT)) +#define SparseIOTag(_IOSelect) IOPortTag(_IOSelect, (unsigned)(-1)) +#define BlockIOTag(_IOSelect) IOPortTag((unsigned)(-1), _IOSelect) + +#define CRTC_H_TOTAL_DISP IOPortTag(0x00u, 0x00u) +#define CRTC_H_SYNC_STRT_WID IOPortTag(0x01u, 0x01u) +#define CRTC_V_TOTAL_DISP IOPortTag(0x02u, 0x02u) +#define CRTC_V_SYNC_STRT_WID IOPortTag(0x03u, 0x03u) +#define CRTC_VLINE_CRNT_VLINE IOPortTag(0x04u, 0x04u) +#define CRTC_OFF_PITCH IOPortTag(0x05u, 0x05u) + +#define SCRATCH_REG0 IOPortTag(0x10u, 0x20u) +#define OVR_WID_LEFT_RIGHT IOPortTag(0x09u, 0x11u) +#define OVR_WID_TOP_BOTTOM IOPortTag(0x0au, 0x12u) +#define CLOCK_CNTL IOPortTag(0x12u, 0x24u) +#define BUS_CNTL IOPortTag(0x13u, 0x28u) +#define MEM_VGA_WP_SEL IOPortTag(0x15u, 0x2du) +#define MEM_VGA_RP_SEL IOPortTag(0x16u, 0x2eu) +#define DAC_CNTL IOPortTag(0x18u, 0x31u) +#define DAC_REGS IOPortTag(0x17u, 0x30u) /* 4 separate bytes */ +#define CRTC_GEN_CNTL IOPortTag(0x07u, 0x07u) +#define DSP_CONFIG BlockIOTag(0x08u) /* VTB/GTB/LT */ +#define DSP_ON_OFF BlockIOTag(0x09u) /* VTB/GTB/LT */ +#define VGA_DSP_CONFIG BlockIOTag(0x13u) /* VTB/GTB/LT */ +#define VGA_DSP_ON_OFF BlockIOTag(0x14u) /* VTB/GTB/LT */ +#define HW_DEBUG BlockIOTag(0x1fu) +#define OVR_CLR IOPortTag(0x08u, 0x10u) +#define MEM_INFO IOPortTag(0x14u, 0x2cu) /* Renamed MEM_CNTL */ +#define CONFIG_CNTL IOPortTag(0x1au, 0x37u) +#define GEN_TEST_CNTL IOPortTag(0x19u, 0x34u) +#define CRTC_INT_CNTL IOPortTag(0x06u, 0x06u) +#define CONFIG_STATUS64_0 IOPortTag(0x1cu, 0x39u) + +#define MEM_BUF_CNTL BlockIOTag(0x0bu) /* VTB/GTB/LT */ +#define SHARED_CNTL BlockIOTag(0x0cu) /* VTB/GTB/LT */ +#define SHARED_MEM_CONFIG BlockIOTag(0x0du) /* GT3 */ + +#define CUR_CLR0 IOPortTag(0x0bu, 0x18u) +#define CUR_CLR1 IOPortTag(0x0cu, 0x19u) +#define CUR_OFFSET IOPortTag(0x0du, 0x1au) +#define CUR_HORZ_VERT_POSN IOPortTag(0x0eu, 0x1bu) +#define CUR_HORZ_VERT_OFF IOPortTag(0x0fu, 0x1cu) + +#define CONFIG_CHIP_ID IOPortTag(0x1bu, 0x38u) /* Read */ +#define CFG_CHIP_TYPE0 0x000000fful +#define CFG_CHIP_TYPE1 0x0000ff00ul +#define CFG_CHIP_TYPE 0x0000fffful +#define CFG_CHIP_CLASS 0x00ff0000ul +#define CFG_CHIP_REV 0xff000000ul +#define CFG_CHIP_VERSION 0x07000000ul /* 264xT */ +#define CFG_CHIP_FOUNDRY 0x38000000ul /* 264xT */ +#define CFG_CHIP_REVISION 0xc0000000ul /* 264xT */ +#define CFG_MEM_TYPE_T 0x00000007ul +#define CFG_MEM_TYPE 0x00000038ul + +#define DAC_8BIT_EN 0x00000100ul + +#define CRTC_OFFSET 0x000ffffful +#define CRTC_H_TOTAL 0x000001fful +#define CRTC_H_DISP 0x01ff0000ul +#define CRTC_H_SYNC_STRT 0x000000fful +#define CRTC_H_SYNC_DLY 0x00000700ul +#define CRTC_H_SYNC_POL 0x00200000ul +#define CRTC_H_SYNC_WID 0x001f0000ul +#define CRTC_H_SYNC_STRT_HI 0x00001000ul +#define CRTC_V_TOTAL 0x000007fful +#define CRTC_V_DISP 0x07ff0000ul +#define CRTC_V_SYNC_STRT 0x000007fful +#define CRTC_V_SYNC_WID 0x001f0000ul +#define CRTC_V_SYNC_POL 0x00200000ul +#define CRTC_PIX_WIDTH 0x00000700ul +#define CRTC_PIX_WIDTH_1BPP 0x00000000ul +#define CRTC_PIX_WIDTH_4BPP 0x00000100ul +#define CRTC_PIX_WIDTH_8BPP 0x00000200ul +#define CRTC_PIX_WIDTH_15BPP 0x00000300ul +#define CRTC_PIX_WIDTH_16BPP 0x00000400ul +#define CRTC_PIX_WIDTH_24BPP 0x00000500ul +#define CRTC_PIX_WIDTH_32BPP 0x00000600ul +#define CRTC_VBLANK 0x00000001ul +#define CRTC_VBLANK_INT_EN 0x00000002ul +#define CRTC_VBLANK_INT 0x00000004ul +#define CRTC_VLINE_INT_EN 0x00000008ul +#define CRTC_VLINE_INT 0x00000010ul +#define CRTC_VLINE_SYNC 0x00000020ul +#define CRTC_FRAME 0x00000040ul +/* ? 0x0000ff80ul */ +#define CRTC_SNAPSHOT_INT_EN 0x00000080ul /* GT3 */ +#define CRTC_SNAPSHOT_INT 0x00000100ul /* GT3 */ +#define CRTC_I2C_INT_EN 0x00000200ul /* GT3 */ +#define CRTC_I2C_INT 0x00000400ul /* GT3 */ +#define CRTC_CAPBUF0_INT_EN 0x00010000ul /* VT/GT */ +#define CRTC_CAPBUF0_INT 0x00020000ul /* VT/GT */ +#define CRTC_CAPBUF1_INT_EN 0x00040000ul /* VT/GT */ +#define CRTC_CAPBUF1_INT 0x00080000ul /* VT/GT */ +#define CRTC_OVERLAY_EOF_INT_EN 0x00100000ul /* VT/GT */ +#define CRTC_OVERLAY_EOF_INT 0x00200000ul /* VT/GT */ +#define CRTC_ONESHOT_CAP_INT_EN 0x00400000ul /* VT/GT */ +#define CRTC_ONESHOT_CAP_INT 0x00800000ul /* VT/GT */ +#define CRTC_BUSMASTER_EOL_INT_EN 0x01000000ul /* VTB/GTB/LT */ +#define CRTC_BUSMASTER_EOL_INT 0x02000000ul /* VTB/GTB/LT */ +#define CRTC_GP_INT_EN 0x04000000ul /* VTB/GTB/LT */ +#define CRTC_GP_INT 0x08000000ul /* VTB/GTB/LT */ +/* ? 0xf0000000ul */ +#define CRTC_VBLANK_BIT2 0x80000000ul /* GT3 */ +#define CRTC_INT_ENS /* *** UPDATE ME *** */ \ + ( \ + CRTC_VBLANK_INT_EN | \ + CRTC_VLINE_INT_EN | \ + CRTC_SNAPSHOT_INT_EN | \ + CRTC_I2C_INT_EN | \ + CRTC_CAPBUF0_INT_EN | \ + CRTC_CAPBUF1_INT_EN | \ + CRTC_OVERLAY_EOF_INT_EN | \ + CRTC_ONESHOT_CAP_INT_EN | \ + CRTC_BUSMASTER_EOL_INT_EN | \ + CRTC_GP_INT_EN | \ + 0 \ + ) +#define CRTC_INT_ACKS /* *** UPDATE ME *** */ \ + ( \ + CRTC_VBLANK_INT | \ + CRTC_VLINE_INT | \ + CRTC_SNAPSHOT_INT | \ + CRTC_I2C_INT | \ + CRTC_CAPBUF0_INT | \ + CRTC_CAPBUF1_INT | \ + CRTC_OVERLAY_EOF_INT | \ + CRTC_ONESHOT_CAP_INT | \ + CRTC_BUSMASTER_EOL_INT | \ + CRTC_GP_INT | \ + 0 \ + ) +#define CRTC_DBL_SCAN_EN 0x00000001ul +#define CRTC_INTERLACE_EN 0x00000002ul +#define CRTC_HSYNC_DIS 0x00000004ul +#define CRTC_VSYNC_DIS 0x00000008ul +#define CRTC_CSYNC_EN 0x00000010ul +#define CRTC_PIX_BY_2_EN 0x00000020ul +#define CRTC_DISPLAY_DIS 0x00000040ul +#define CRTC_VGA_XOVERSCAN 0x00000080ul +#define CRTC_PIX_WIDTH 0x00000700ul +#define CRTC_PIX_WIDTH_1BPP 0x00000000ul +#define CRTC_PIX_WIDTH_4BPP 0x00000100ul +#define CRTC_PIX_WIDTH_8BPP 0x00000200ul +#define CRTC_PIX_WIDTH_15BPP 0x00000300ul +#define CRTC_PIX_WIDTH_16BPP 0x00000400ul +#define CRTC_PIX_WIDTH_24BPP 0x00000500ul +#define CRTC_PIX_WIDTH_32BPP 0x00000600ul +/* ? 0x00000700ul */ +#define CRTC_BYTE_PIX_ORDER 0x00000800ul +#define CRTC_FIFO_OVERFILL 0x0000c000ul /* VT/GT */ +#define CRTC_FIFO_LWM 0x000f0000ul +#define CRTC_VGA_128KAP_PAGING 0x00100000ul /* VT/GT */ +#define CRTC_DISPREQ_ONLY 0x00200000ul /* VT/GT */ +#define CRTC_VFC_SYNC_TRISTATE 0x00200000ul /* VTB/GTB/LT */ +#define CRTC_LOCK_REGS 0x00400000ul /* VT/GT */ +#define CRTC_SYNC_TRISTATE 0x00800000ul /* VT/GT */ +#define CRTC_EXT_DISP_EN 0x01000000ul +#define CRTC_EN 0x02000000ul +#define CRTC_DISP_REQ_EN 0x04000000ul +#define CRTC_VGA_LINEAR 0x08000000ul +#define CRTC_VSYNC_FALL_EDGE 0x10000000ul +#define CRTC_VGA_TEXT_132 0x20000000ul +#define CRTC_CNT_EN 0x40000000ul +#define CRTC_CUR_B_TEST 0x80000000ul +#define DSP_OFF 0x000007fful +#define VGA_DSP_OFF DSP_OFF +#define CRTC_PITCH 0xffc00000ul +#define CTL_MEM_SIZE 0x00000007ul +#define CTL_MEM_SIZEB 0x0000000ful /* VTB/GTB/LT */ +#define PLL_WR_EN 0x00000200ul /* For internal PLL */ +#define PLL_ADDR 0x00007c00ul /* For internal PLL */ +#define BUS_HOST_ERR_INT_EN 0x00400000ul +#define BUS_HOST_ERR_INT 0x00800000ul +#define BUS_APER_REG_DIS 0x00000010ul /* VTB/GTB/LT */ +#define CLOCK_SELECT 0x0000000ful +#define CLOCK_DIVIDER 0x00000030ul +#define CLOCK_STROBE 0x00000040ul + +#define GEN_CUR_EN 0x00000080ul + +#define BUS_WS 0x0000000ful +#define BUS_DBL_RESYNC 0x00000001ul /* VTB/GTB/LT */ +#define BUS_MSTR_RESET 0x00000002ul /* VTB/GTB/LT */ +#define BUS_FLUSH_BUF 0x00000004ul /* VTB/GTB/LT */ +#define BUS_STOP_REQ_DIS 0x00000008ul /* VTB/GTB/LT */ +#define BUS_ROM_WS 0x000000f0ul +#define BUS_APER_REG_DIS 0x00000010ul /* VTB/GTB/LT */ +#define BUS_EXTRA_PIPE_DIS 0x00000020ul /* VTB/GTB/LT */ +#define BUS_MASTER_DIS 0x00000040ul /* VTB/GTB/LT */ +#define BUS_ROM_WRT_EN 0x00000080ul /* GT3 */ +#define BUS_ROM_PAGE 0x00000f00ul +#define BUS_ROM_DIS 0x00001000ul +#define BUS_IO_16_EN 0x00002000ul /* GX */ +#define BUS_PCI_READ_RETRY_EN 0x00002000ul /* VTB/GTB/LT */ +#define BUS_DAC_SNOOP_EN 0x00004000ul +#define BUS_PCI_RETRY_EN 0x00008000ul /* VT/GT */ +#define BUS_PCI_WRT_RETRY_EN 0x00008000ul /* VTB/GTB/LT */ +#define BUS_FIFO_WS 0x000f0000ul +#define BUS_RETRY_WS 0x000f0000ul /* VTB/GTB/LT */ +#define BUS_FIFO_ERR_INT_EN 0x00100000ul +#define BUS_MSTR_RD_MULT 0x00100000ul /* VTB/GTB/LT */ +#define BUS_FIFO_ERR_INT 0x00200000ul +#define BUS_MSTR_RD_LINE 0x00200000ul /* VTB/GTB/LT */ +#define BUS_HOST_ERR_INT_EN 0x00400000ul +#define BUS_SUSPEND 0x00400000ul /* GT3 */ +#define BUS_HOST_ERR_INT 0x00800000ul +#define BUS_LAT16X 0x00800000ul /* GT3 */ +#define BUS_PCI_DAC_WS 0x07000000ul +#define BUS_RD_DISCARD_EN 0x01000000ul /* VTB/GTB/LT */ +#define BUS_RD_ABORT_EN 0x02000000ul /* VTB/GTB/LT */ +#define BUS_MSTR_WS 0x04000000ul /* VTB/GTB/LT */ +#define BUS_PCI_DAC_DLY 0x08000000ul +#define BUS_EXT_REG_EN 0x08000000ul /* VT/GT */ +#define BUS_PCI_MEMW_WS 0x10000000ul +#define BUS_MSTR_DISCONNECT_EN 0x10000000ul /* VTB/GTB/LT */ +#define BUS_PCI_BURST_DEC 0x20000000ul /* GX/CX */ +#define BUS_BURST 0x20000000ul /* 264xT */ +#define BUS_WRT_BURST 0x20000000ul /* VTB/GTB/LT */ +#define BUS_RDY_READ_DLY 0xc0000000ul +#define BUS_READ_BURST 0x40000000ul /* VTB/GTB/LT */ +#define BUS_RDY_READ_DLY_B 0x80000000ul /* VTB/GTB/LT */ + +#define CFG_MEM_VGA_AP_EN 0x00000004ul +#define DSP_XCLKS_PER_QW 0x00003ffful +#define VGA_DSP_XCLKS_PER_QW DSP_XCLKS_PER_QW +#define DSP_FLUSH_WB 0x00008000ul +#define DSP_LOOP_LATENCY 0x000f0000ul +#define DSP_PRECISION 0x00700000ul +#define DSP_OFF 0x000007fful +#define DSP_ON 0x07ff0000ul + +#define PLL_VCLK_CNTL 0x05u +#define PLL_VCLK_POST_DIV 0x06u +#define PLL_VCLK0_FB_DIV 0x07u +#define PLL_VCLK0_XDIV 0x10u +#define PLL_XCLK_CNTL 0x0bu /* VT/GT */ +#define PLL_VCLK_RESET 0x04u +#define PLL_XCLK_SRC_SEL 0x07u /* VTB/GTB/LT */ +#define PLL_MCLK_FB_DIV 0x04u +#define PLL_MFB_TIMES_4_2B 0x08u +#define PLL_REF_DIV 0x02u + +#define CTL_MEM_TRAS 0x00070000ul /* VTB/GTB/LT */ +#define CTL_MEM_TRCD 0x00000c00ul /* VTB/GTB/LT */ +#define CTL_MEM_TCRD 0x00001000ul /* VTB/GTB/LT */ +#define CTL_MEM_TRP 0x00000300ul /* VTB/GTB/LT */ + +#define CTL_MEM_BNDRY 0x00030000ul +#define CTL_MEM_BNDRY_EN 0x00040000ul + +#define ATI_CHIP_88800GXC 16 /* Mach64 */ +#define ATI_CHIP_88800GXD 17 /* Mach64 */ +#define ATI_CHIP_88800GXE 18 /* Mach64 */ +#define ATI_CHIP_88800GXF 19 /* Mach64 */ +#define ATI_CHIP_88800GX 20 /* Mach64 */ +#define ATI_CHIP_88800CX 21 /* Mach64 */ +#define ATI_CHIP_264CT 22 /* Mach64 */ +#define ATI_CHIP_264ET 23 /* Mach64 */ +#define ATI_CHIP_264VT 24 /* Mach64 */ +#define ATI_CHIP_264GT 25 /* Mach64 */ +#define ATI_CHIP_264VTB 26 /* Mach64 */ +#define ATI_CHIP_264GTB 27 /* Mach64 */ +#define ATI_CHIP_264VT3 28 /* Mach64 */ +#define ATI_CHIP_264GTDVD 29 /* Mach64 */ +#define ATI_CHIP_264LT 30 /* Mach64 */ +#define ATI_CHIP_264VT4 31 /* Mach64 */ +#define ATI_CHIP_264GT2C 32 /* Mach64 */ +#define ATI_CHIP_264GTPRO 33 /* Mach64 */ +#define ATI_CHIP_264LTPRO 34 /* Mach64 */ +#define ATI_CHIP_Mach64 35 /* Mach64 */ + +#define MEM_264_NONE 0 +#define MEM_264_DRAM 1 +#define MEM_264_EDO 2 +#define MEM_264_PSEUDO_EDO 3 +#define MEM_264_SDRAM 4 +#define MEM_264_SGRAM 5 +#define MEM_264_TYPE_6 6 +#define MEM_264_TYPE_7 7 + +#define ATIGetMach64PLLReg(_Index) \ + ( \ + ATIAccessMach64PLLReg(_Index, 0), \ + rage_inb(ATIIOPortCLOCK_CNTL + 2) \ + ) +#define ATIPutMach64PLLReg(_Index, _Value) \ + ATIAccessMach64PLLReg(_Index, 1); \ + rage_outb(ATIIOPortCLOCK_CNTL + 2, _Value) + diff --git a/src/drivers/rageio.c b/src/drivers/rageio.c new file mode 100644 index 0000000..97dfc6a --- /dev/null +++ b/src/drivers/rageio.c @@ -0,0 +1,97 @@ +#include "libvga.h" +#include + +static int __svgalib_rage_inmisc(void) +{ + return 0; +} + +static void __svgalib_rage_outmisc(int i) +{ +} + +static int __svgalib_rage_incrtc(int i) +{ + return 0; +} + +static void __svgalib_rage_outcrtc(int i, int d) +{ +} + +static int __svgalib_rage_inseq(int index) +{ + return 0; +} + +static void __svgalib_rage_outseq(int index, int val) +{ +} + +static int __svgalib_rage_ingra(int index) +{ + return 0; +} + +static void __svgalib_rage_outgra(int index, int val) +{ +} + +static int __svgalib_rage_inis1(void) +{ + return 0; +} + +static int __svgalib_rage_inatt(int index) +{ + return 0; +} + +static void __svgalib_rage_outatt(int index, int val) +{ +} + +static void __svgalib_rage_attscreen(int i) +{ +} + +static void __svgalib_rage_inpal(int i, int *r, int *g, int *b) +{ + rage_outb(ATIIOPortDAC_READ, i); + *r=rage_inb(ATIIOPortDAC_DATA); + *g=rage_inb(ATIIOPortDAC_DATA); + *b=rage_inb(ATIIOPortDAC_DATA); +} + +static void __svgalib_rage_outpal(int i, int r, int g, int b) +{ + rage_outb(ATIIOPortDAC_WRITE, i); + rage_outb(ATIIOPortDAC_DATA,r); + rage_outb(ATIIOPortDAC_DATA,g); + rage_outb(ATIIOPortDAC_DATA,b); +} + +static void rage_mapio(void) +{ +#ifndef __PPC + if(__svgalib_secondary) { +#endif + __svgalib_inmisc=__svgalib_rage_inmisc; + __svgalib_outmisc=__svgalib_rage_outmisc; + __svgalib_incrtc=__svgalib_rage_incrtc; + __svgalib_outcrtc=__svgalib_rage_outcrtc; + __svgalib_inseq=__svgalib_rage_inseq; + __svgalib_outseq=__svgalib_rage_outseq; + __svgalib_ingra=__svgalib_rage_ingra; + __svgalib_outgra=__svgalib_rage_outgra; + __svgalib_inatt=__svgalib_rage_inatt; + __svgalib_outatt=__svgalib_rage_outatt; + __svgalib_attscreen=__svgalib_rage_attscreen; + __svgalib_inis1=__svgalib_rage_inis1; +#ifndef __PPC + } +#endif + __svgalib_inpal=__svgalib_rage_inpal; + __svgalib_outpal=__svgalib_rage_outpal; +} + diff --git a/src/drivers/rendition.c b/src/drivers/rendition.c new file mode 100644 index 0000000..d7dee28 --- /dev/null +++ b/src/drivers/rendition.c @@ -0,0 +1,551 @@ +/* +Skeleton chipset driver +*/ + +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "v2kregs.h" + +static int io_base; + +#include "renditionio.h" + +typedef struct { + uint8_t memendian; + uint8_t mode; + uint8_t bankselect; + uint32_t sclkpll; + uint32_t dramctl; + uint32_t pclkpll; + uint32_t crtchorz; + uint32_t crtcvert; + uint32_t crtcctl; + uint32_t framebasea; + uint32_t crtcoffset; + uint8_t dac[17]; +} hwregs, *hwregsptr; + +#define TOTAL_REGS (VGA_TOTAL_REGS + sizeof(hwregs)) + +static int init(int, int, int); +static void unlock(void); +static void lock(void); + +static int memory=0, id; +static unsigned int linear_base; + +static CardSpecs *cardspecs; + +static void setpage(int page) +{ + OUT(BANKSELECT+2, page); +} + +/* Fill in chipset specific mode information */ +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int saveregs(unsigned char regs[]) +{ + int i; + hwregsptr r; + + r=(hwregsptr)(regs+VGA_TOTAL_REGS); + + r->memendian= IN(MEMENDIAN); + r->mode = IN(MODEREG); + r->bankselect=IN(BANKSELECT+2); + r->sclkpll = IN32(SCLKPLL); + r->dramctl = IN32(DRAMCTL); + r->pclkpll = IN32(PCLKPLL); + r->crtchorz = IN32(CRTCHORZ); + r->crtcvert = IN32(CRTCVERT); + r->crtcctl = IN32(CRTCCTL); + r->framebasea=IN32(FRAMEBASEA); + r->crtcoffset=IN32(CRTCOFFSET); + + for(i=0;i<16;i++) r->dac[i]=IN(PALETTE+i); + OUT(DACRAMWRITEADR, 1); + r->dac[16]=IN(DACSTATUS); + OUT(DACRAMWRITEADR, r->dac[0]); + + return TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + hwregsptr r; + + r=(hwregsptr)(regs+VGA_TOTAL_REGS); + unlock(); + + OUT(MODEREG, r->mode); + OUT(MEMENDIAN, r->memendian); + OUT(BANKSELECT+2, r->bankselect); + OUT32(SCLKPLL, r->sclkpll); + usleep(500); + OUT32(DRAMCTL, r->dramctl); + OUT32(PCLKPLL, r->pclkpll); + usleep(500); + + OUT(DACCOMMAND0, r->dac[DACCOMMAND0-PALETTE]); + OUT(DACCOMMAND1, r->dac[DACCOMMAND1-PALETTE]); + OUT(DACCOMMAND2, r->dac[DACCOMMAND2-PALETTE]); + OUT(DACRAMWRITEADR, 1); + OUT(DACSTATUS, r->dac[16]); + OUT(DACPIXELMSK, r->dac[2]); + + OUT32(CRTCHORZ, r->crtchorz); + OUT32(CRTCVERT, r->crtcvert); + OUT32(FRAMEBASEA, r->framebasea); + OUT32(CRTCOFFSET, r->crtcoffset); + OUT32(CRTCCTL, r->crtcctl); +} + + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if(modeinfo->bitsPerPixel==24) { + free(modeinfo); + return 0; + } + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +#define V2_MIN_VCO_FREQ 125 +#define V2_MAX_VCO_FREQ 250 +#define V2_REF_FREQ 14.31818 /* Eh, is this right? */ +#define V2_MIN_PCF_FREQ 1 +#define V2_MAX_PCF_FREQ 3 + +static double V2200CalcClock(double target, int *m, int *n, int *p) +{ + double mindiff = 1e10; + double vco, pcf, diff, freq; + int mm, nn, pp; + + for (pp=1; pp<=0x0f; pp++) + for (nn=1; nn<=0x3f; nn++) + for (mm=1; mm<=0xff; mm++) { + vco = V2_REF_FREQ*mm/nn; + if ((vco < V2_MIN_VCO_FREQ) || (vco > V2_MAX_VCO_FREQ)) + continue; + pcf = V2_REF_FREQ/nn; + if ((pcf < V2_MIN_PCF_FREQ) || (pcf > V2_MAX_PCF_FREQ)) + continue; + freq = vco/pp; + diff = target-freq; + if(diff<0) diff=-diff; + if (diff < mindiff) { + *m = mm; *n = nn; *p = pp; + mindiff = diff; + } + } + + vco = V2_REF_FREQ * *m / *n; + pcf = V2_REF_FREQ / *n; + freq = vco / *p; + + return freq; +} + +#define combineNMP(N, M, P) \ + (((uint32_t)(M-2)<<10) | ((uint32_t)P<<8) | (uint32_t)(N-2)) + +#define v2kcombineNMP(N, M, P) (((uint32_t)N<<13) | ((uint32_t)P<<9) | (uint32_t)M) + +#define CTL(ldbl, hsynchi, vsynchi) \ + (((ldbl) ? CRTCCTL_LINEDOUBLE : 0) \ + |((hsynchi) ? CRTCCTL_HSYNCHI : 0) \ + |((vsynchi) ? CRTCCTL_VSYNCHI : 0) \ + |(CRTCCTL_VSYNCENABLE | CRTCCTL_HSYNCENABLE)) + +#define HORZ(fp, sy, bp, ac) \ +(((((uint32_t)(((fp)>>3)-1))&7)<<21)|((((uint32_t)(((sy)>>3)-1))&0x1F)<<16)|\ +((((uint32_t)(((bp)>>3)-1))&0x3f)<<9)|((((uint32_t)(((ac)>>3)-1))&0xff))) + +#define VERT(fp, sy, bp, ac) \ +(((((uint32_t)(fp-1))&0x3f)<<20)|((((uint32_t)(sy-1))&0x7)<<17)|\ +((((uint32_t)(bp-1))&0x3f)<<11)|((((uint32_t)(ac-1))&0x7ff))) + +#define HORZAC(crtchorz) \ + (((((uint32_t)crtchorz)&CRTCHORZ_ACTIVE_MASK)+1)<<3) + +#define HORZBP(crtchorz) \ + ((((((uint32_t)crtchorz)&CRTCHORZ_BACKPORCH_MASK)>>9)+1)<<3) + +#define HORZSY(crtchorz) \ + ((((((uint32_t)crtchorz)&CRTCHORZ_SYNC_MASK)>>16)+1)<<3) + +#define HORZFP(crtchorz) \ + ((((((uint32_t)crtchorz)&CRTCHORZ_FRONTPORCH_MASK)>>21)+1)<<3) + +#define VERTAC(crtcvert) \ + ((((uint32_t)crtcvert)&CRTCVERT_ACTIVE_MASK)+1) + +#define VERTBP(crtcvert) \ + (((((uint32_t)crtcvert)&CRTCVERT_BACKPORCH_MASK)>>11)+1) + +#define VERTSY(crtcvert) \ + (((((uint32_t)crtcvert)&CRTCVERT_SYNC_MASK)>>17)+1) + +#define VERTFP(crtcvert) \ + (((((uint32_t)crtcvert)&CRTCVERT_FRONTPORCH_MASK)>>20)+1) + + +static void initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + int m,n,p, pixelformat = 0, offset, fifosize; + hwregsptr r; + + r=(hwregsptr)(moderegs+VGA_TOTAL_REGS); + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + r->mode = NATIVE_MODE | VESA_MODE; + + switch(modeinfo->bitsPerPixel) { + case 8: + r->memendian= MEMENDIAN_END; + r->dac[6]= BT485_CR0_EXTENDED_REG_ACCESS; + r->dac[8]= BT485_CR1_8BPP | BT485_CR1_PIXEL_PORT_AB; + r->dac[9]= BT485_PIXEL_INPUT_GATE | BT485_DISABLE_CURSOR; + pixelformat = V_PIXFMT_8I; + break; + case 16: + r->memendian= MEMENDIAN_HW; + r->dac[6] = BT485_CR0_EXTENDED_REG_ACCESS | BT485_CR0_8_BIT_DAC; + r->dac[8] = BT485_CR1_16BPP | + BT485_CR1_1_TO_1_16BPP | BT485_CR1_PIXEL_PORT_AB; + r->dac[9] = BT485_PIXEL_INPUT_GATE | BT485_DISABLE_CURSOR; + if(modeinfo->greenWeight == 6) { + r->dac[8] |= BT485_CR1_BYPASS_CLUT | BT485_CR1_565_16BPP; + pixelformat = V_PIXFMT_565; + } else { + int i; + pixelformat = V_PIXFMT_1555; + for(i=0; i<256; i++)vga_setpalette(i, i>>2, i>>1, i>>2); + } + break; + case 32: + r->memendian= MEMENDIAN_NO; + r->dac[6] = BT485_CR0_EXTENDED_REG_ACCESS | BT485_CR0_8_BIT_DAC; + r->dac[8] = BT485_CR1_24BPP | BT485_CR1_BYPASS_CLUT | + BT485_CR1_PIXEL_PORT_AB; + r->dac[9] = BT485_PIXEL_INPUT_GATE | BT485_DISABLE_CURSOR; + pixelformat = V_PIXFMT_8888; + break; + } + + r->dac[16]=0; + r->dac[2]=0xff; + + r->bankselect=0; + + r->sclkpll = IN32(SCLKPLL); + r->dramctl = (IN32(DRAMCTL) & 0xc7ff) | 0x330000; + + V2200CalcClock(modetiming->pixelClock/1000.0, &m, &n, &p); + + r->pclkpll = v2kcombineNMP(n, m, p); + + r->crtchorz = HORZ(modetiming->HSyncStart-modetiming->HDisplay, + modetiming->HSyncEnd-modetiming->HSyncStart, + modetiming->HTotal-modetiming->HSyncEnd, + modetiming->HDisplay); + + r->crtcvert = VERT(modetiming->VSyncStart-modetiming->VDisplay, + modetiming->VSyncEnd-modetiming->VSyncStart, + modetiming->VTotal-modetiming->VSyncEnd, + modetiming->VDisplay); + r->crtcctl = CTL(modetiming->flags&DOUBLESCAN, 0, 0) + | pixelformat + | CRTCCTL_VIDEOFIFOSIZE128 + | CRTCCTL_HSYNCENABLE + | CRTCCTL_VSYNCENABLE + | CRTCCTL_VIDEOENABLE; + + r->framebasea=0; + + fifosize=128; + offset=modeinfo->lineWidth%fifosize; + if((modeinfo->lineWidth%fifosize)==0) offset += fifosize; + r->crtcoffset = offset; + + return ; +} + + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); +} + +static void lock(void) +{ +} + +#define VENDOR_ID 0x1163 +#define CARD_ID 0x2000 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + unsigned int buf[64]; + int found; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + id=(buf[0]>>16)&0xffff; + if(!found)return 0; + switch(id) { + case CARD_ID: + return !init(0,0,0); + default: + return 0; + } +} + + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void setdisplaystart(int address) +{ + OUT(FRAMEBASEA, address); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void setlogicalwidth(int width) +{ + int sw, fifosize, offset; + + fifosize=128; + sw=CI.bytesperpixel*CI.xdim; + + offset=width - sw + (sw%fifosize); + + if((sw%fifosize)==0) offset += fifosize; + + OUT(CRTCOFFSET, offset); +} + +static int linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ return 0;}; + if (op==LINEAR_DISABLE){ return 0;}; + if (op==LINEAR_QUERY_BASE) return linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} + +static int map_clock(int bpp, int clock) +{ +return clock ; +} + +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_rendition_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + setpage, + NULL, + NULL, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + unsigned int mmio_base; + + unlock(); + if (force) { + memory = par1; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + linear_base=0; + id=(buf[0]>>16)&0xffff; + if(found) { + switch(id) { + case CARD_ID: + break; + default: + return 1; + } + } + + linear_base=buf[4]&0xffff0000; + io_base=buf[5]&0xff00; + mmio_base=buf[6]&0xffff0000; + + rendition_mapio(); + + if(!memory) { + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=4*1024*1024; + map_linear(0); + memory=memorytest((uint32_t *)LINEAR_POINTER, 4); + unmap_linear(); + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using Rendition driver, %iKB.\n",memory); + }; + + __svgalib_modeinfo_linearset |= LINEAR_CAN; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = 170000; + cardspecs->maxPixelClock16bpp = 170000; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 170000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->nClocks =0; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_rendition_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=memory*0x400; + __svgalib_mmio_base = mmio_base; + __svgalib_mmio_size = 256*1024; + return 0; +} diff --git a/src/drivers/renditionio.h b/src/drivers/renditionio.h new file mode 100644 index 0000000..757ca1c --- /dev/null +++ b/src/drivers/renditionio.h @@ -0,0 +1,90 @@ +static int __svgalib_rendition_inmisc(void) +{ + return 0; +} + +static void __svgalib_rendition_outmisc(int i) +{ +} + +static int __svgalib_rendition_incrtc(int i) +{ + return 0; +} + +static void __svgalib_rendition_outcrtc(int i, int d) +{ +} + +static int __svgalib_rendition_inseq(int index) +{ + return 0; +} + +static void __svgalib_rendition_outseq(int index, int val) +{ +} + +static int __svgalib_rendition_ingra(int index) +{ + return 0; +} + +static void __svgalib_rendition_outgra(int index, int val) +{ +} + +static int __svgalib_rendition_inis1(void) +{ + return 0; +} + +static int __svgalib_rendition_inatt(int index) +{ + return 0; +} + +static void __svgalib_rendition_outatt(int index, int val) +{ +} + +static void __svgalib_rendition_attscreen(int i) +{ +} + +static void __svgalib_rendition_inpal(int i, int *r, int *g, int *b) +{ + OUT(DACRAMREADADR, i ); + *r=IN(DACRAMDATA); + *g=IN(DACRAMDATA); + *b=IN(DACRAMDATA); +} + +static void __svgalib_rendition_outpal(int i, int r, int g, int b) +{ + OUT(DACRAMWRITEADR, i ); + OUT(DACRAMDATA, r ); + OUT(DACRAMDATA, g ); + OUT(DACRAMDATA, b ); +} + +static void rendition_mapio(void) +{ + if(__svgalib_secondary) { + __svgalib_inmisc=__svgalib_rendition_inmisc; + __svgalib_outmisc=__svgalib_rendition_outmisc; + __svgalib_incrtc=__svgalib_rendition_incrtc; + __svgalib_outcrtc=__svgalib_rendition_outcrtc; + __svgalib_inseq=__svgalib_rendition_inseq; + __svgalib_outseq=__svgalib_rendition_outseq; + __svgalib_ingra=__svgalib_rendition_ingra; + __svgalib_outgra=__svgalib_rendition_outgra; + __svgalib_inatt=__svgalib_rendition_inatt; + __svgalib_outatt=__svgalib_rendition_outatt; + __svgalib_attscreen=__svgalib_rendition_attscreen; + __svgalib_inis1=__svgalib_rendition_inis1; + } + __svgalib_inpal=__svgalib_rendition_inpal; + __svgalib_outpal=__svgalib_rendition_outpal; +} + diff --git a/src/drivers/s3.c b/src/drivers/s3.c new file mode 100644 index 0000000..bc00f02 --- /dev/null +++ b/src/drivers/s3.c @@ -0,0 +1,1807 @@ +/* + * VGAlib version 1.2 - (c) 1993 Tommy Frandsen + * + * This library is free software; you can redistribute it and/or + * modify it without any restrictions. This library is distributed + * in the hope that it will be useful, but without any warranty. + * + * Multi-chipset support Copyright (C) 1993 Harm Hanemaayer + * S3 805,868 support Copyright (C) 1995 Stephen Lee + */ + +/* + * Mar 1999 (Eduardo ...) + * Recognizes Trio3D as Trio64 + * + * Sep 1997 (Greg Alexander): + * Recognizes S3Trio64V2/DX cards as Trio64's. + * + * Feb 1996 (Stephen Lee): + * 968/IBMRGB support. Only 256 colors for now. + * can now save more than 10 DAC registers (IBMRGB has 256!) + * Trio64 patch from Moto Kawamura . + * Changed handling of CR34 for VGA modes at Andreas' suggestion. + * Changes to s3_saveregs() and s3_setregs() to make them more safe against + * lockups. + * 16 color mode should work on the 868/SDAC. + * SDAC 4/8bpp doesn't seem to do pixel multiplexing. + * + * Dec 1995 (Stephen Lee): + * Fixed color problem with 868 (CR43 again!). Could somebody find the + * value that works with Trio64? + * + * Nov 1995 (Stephen Lee): + * Linear addressing mode partially works (but is very alpha). + * Merged in Andreas Arens' patch for the 928. + * + * Sep 1995 (Stephen Lee): + * 16 Colors works on my 805, should work on other cards too. + * + * Alternate banking scheme for 864+. If you have problems, try undefining + * S3_LINEAR_MODE_BANKING_864. + * + * 8 bit color *really* works. Took me 3 months to bag this sucker. + * + * SVGA 8 bit color modes works. 320x200x256 is not really 'packed-pixel', + * it occupies 256K per page. There is no SVGA 320x200x256 mode; I cannot + * get the display (timing?) right. + * + * Aug 1995 (Stephen Lee): + * Added "Dacspeed" parsing. + * Added support for CLUT8_8 on ATT20C490/498. + * Improved support for S3-801/805. + * 15/16/24 bit colors works on the 805 + ATT20C490 I tested. + * Newer chipsets are recognized (but no support coded in yet). + * Should recognize memory size correctly on S3-924. + * + * Dec 1994 (Harm Hanemaayer): + * Partially rewritten using new SVGA-abstracted interface. + * Based on XFree86 code (accel/s3/s3.c and s3init.c). + * Goal is to have support for the S3-864 + S3-SDAC (which I can test). + * 80x with GENDAC might also be supported. + * Also, 640x480x256 should work on cards that have standard 25 and 28 MHz + * clocks. + * + * XFree86-equivalent clock select is now supported plus some + * industry-standard RAMDACs. + * + * Remaining problems: + * * Okay, okay, so 256 color still isn't fully working on the 805. I'm + * trying to get a fix for it. + * + * * The DCLK limit for 864/868 is a bit too relaxed. If you see noise at + * the highest resolutions when the screen is drawing it is possibly due + * to this. (How about changing MCLK?) + * + * * Horizontal Total is limited to 4088 which makes some modes unavailable + * (e.g. 800x600x16M with HTotal > 1022). Should experiment with + * CR43.7? + * + * * Some 864 problems are now fixed -- XF86_S3 seems to program the + * linewidth in bytes doubled for the S3-864 with > 1024K, which + * caused problems for this driver. There's still interference + * though when writing to video memory in the higher resolutions. + * + * * XXXX results of malloc() are not checked: should fix sometime. + */ + +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "ramdac/ramdac.h" +#include "clockchip/clockchip.h" +#include "vgaregs.h" +#include "interface.h" +#include "8514a.h" +#include "vgapci.h" + +/* no acceleration as of now. */ +#undef S3_USE_GRAPHIC_ENGINE + +/* kludge packed pixel for 320x200x256 */ +/* XXXX doesn't really work */ +#undef S3_KLUDGE_PAGE_MODE + +/* use alternate 'linear' banking method for 864+ */ +#undef S3_LINEAR_MODE_BANKING_864 + +#ifdef __alpha__ /* no good for alpha's */ +#undef S3_LINEAR_MODE_BANKING_864 +#endif + +/* + * supports linear buffer. + * + * XXXX does not work with console switching and might be incompatible with + * S3_LINEAR_MODE_BANKING_864. + */ +#define S3_LINEAR_SUPPORT + +/* supports 16 colors */ +#define S3_16_COLORS + +/* + * zero wait state + (ramdac?) FIFO for 864 & 805, + * twice as fast but might not work on some cards. + */ +#undef S3_0_WAIT_805_864 + +enum { + S3_911, S3_924, S3_801, S3_805, S3_928, S3_864, S3_964, S3_TRIO32, + S3_TRIO64, S3_866, S3_868, S3_968, S3_765 +}; + +static const char *s3_chipname[] = +{"911", "924", "801", "805", "928", + "864", "964", "Trio32", "Trio64", "866", "868", "968", "Trio64V+"}; + +#define S3_CR(n) (EXT + (0x##n) - 0x30) + +#define S3_CR30 S3_CR(30) +#define S3_CR31 S3_CR(31) +#define S3_CR32 S3_CR(32) +#define S3_CR33 S3_CR(33) +#define S3_CR34 S3_CR(34) +#define S3_CR35 S3_CR(35) +#define S3_CR3A S3_CR(3A) +#define S3_CR3B S3_CR(3B) +#define S3_CR3C S3_CR(3C) +#define S3_CR40 S3_CR(40) +#define S3_CR42 S3_CR(42) +#define S3_CR43 S3_CR(43) +#define S3_CR44 S3_CR(44) +#define S3_CR50 S3_CR(50) /* 801+ */ +#define S3_CR51 S3_CR(51) +#define S3_CR53 S3_CR(53) +#define S3_CR54 S3_CR(54) +#define S3_CR55 S3_CR(55) +#define S3_CR58 S3_CR(58) +#define S3_CR59 S3_CR(59) +#define S3_CR5A S3_CR(5A) +#define S3_CR5D S3_CR(5D) +#define S3_CR5E S3_CR(5E) +#define S3_CR60 S3_CR(60) +#define S3_CR61 S3_CR(61) +#define S3_CR62 S3_CR(62) +#define S3_CR67 S3_CR(67) +#define S3_CR6A S3_CR(6A) +#define S3_CR6D S3_CR(6D) + +/* For debugging, these (non-)registers are read also (but never written). */ + +#define S3_CR36 S3_CR(36) +#define S3_CR37 S3_CR(37) +#define S3_CR38 S3_CR(38) +#define S3_CR39 S3_CR(39) +#define S3_CR3D S3_CR(3D) +#define S3_CR3E S3_CR(3E) +#define S3_CR3F S3_CR(3F) +#define S3_CR45 S3_CR(45) +#define S3_CR46 S3_CR(46) +#define S3_CR47 S3_CR(47) +#define S3_CR48 S3_CR(48) +#define S3_CR49 S3_CR(49) +#define S3_CR4A S3_CR(4A) +#define S3_CR4B S3_CR(4B) +#define S3_CR4C S3_CR(4C) +#define S3_CR4D S3_CR(4D) +#define S3_CR4E S3_CR(4E) +#define S3_CR4F S3_CR(4F) +#define S3_CR52 S3_CR(52) +#define S3_CR56 S3_CR(56) +#define S3_CR57 S3_CR(57) +#define S3_CR5B S3_CR(5B) +#define S3_CR5C S3_CR(5C) +#define S3_CR5F S3_CR(5F) +#define S3_CR63 S3_CR(63) +#define S3_CR64 S3_CR(64) +#define S3_CR65 S3_CR(65) +#define S3_CR66 S3_CR(66) +#define S3_CR6E S3_CR(6E) +#define S3_CR6F S3_CR(6F) + +/* Trio extended SR registers */ + +#define S3_SR(n) (S3_CR6F + 1 + (0x##n) - 0x08) + +#define S3_SR08 S3_SR(08) +#define S3_SR09 S3_SR(09) +#define S3_SR0A S3_SR(0A) +#define S3_SR0D S3_SR(0D) +#define S3_SR10 S3_SR(10) +#define S3_SR11 S3_SR(11) +#define S3_SR12 S3_SR(12) +#define S3_SR13 S3_SR(13) +#define S3_SR15 S3_SR(15) +#define S3_SR18 S3_SR(18) +#define S3_SR1D S3_SR(1D) + +#define S3_8514_OFFSET (S3_SR1D + 1) + +#define S3_8514_COUNT (1) /* number of 2-byte words */ + +#define S3_DAC_OFFSET (S3_8514_OFFSET + (S3_8514_COUNT * 2)) + +#define S3_TOTAL_REGS (S3_DAC_OFFSET + MAX_DAC_STATE) + +/* 8514 regs */ +#define S3_ADVFUNC_CNTL 0 + +static unsigned short s3_8514regs[S3_8514_COUNT] = +{ + /* default assuming text mode */ + 0x0000U +}; + +/* flags used by this driver */ +#define S3_LOCALBUS 0x01 +#define S3_CLUT8_8 0x02 +#define S3_OLD_STEPPING 0x04 + +static int s3_flags = 0; + +static int s3_chiptype; +static int s3_memory; +static CardSpecs *cardspecs; +static DacMethods *dac_used; +static ClockChipMethods *clk_used; +static int dac_speed = 0; + +int __svgalib_s3_s3Mclk = 0; + +/* forward declaration. */ +extern DriverSpecs __svgalib_s3_driverspecs; + +static int s3_init(int, int, int); +static void s3_setpage(int page); +#ifdef S3_LINEAR_MODE_BANKING_864 +static void s3_setpage864(int page); +#endif + +#ifdef S3_LINEAR_SUPPORT +static int s3_cr40; +static int s3_cr54; +static int s3_cr58; +static int s3_cr59; +static int s3_cr5A; +static int s3_linear_opt = 0; +static int s3_linear_addr = 0; +static unsigned int s3_linear_base = 0; +static void s3_linear_enable(void); +static void s3_linear_disable(void); +#endif + +static void nothing(void) +{ +} + +/* + * Lock S3's registers. + * There are more locks, but this should suffice. + * + * ARI: More complete Extended VGA Register Lock Documentation, as of Ferraro: + * + * Register Bit Controls Access To: Function + * CR33 1 CR7 bits 1 and 6 1=disable write protect + * setting of CR11 bit 7 + * CR33 4 Ramdac Register 1=disable writes + * CR33 6 Palette/Overscan Registers 1=lock + * CR34 5 Memory Configuration bit 5 1=lock + * CR34 7 Misc Register bit 3-2 (Clock) 1=lock + * CR35 4 Vertical Timing Registers 1=lock + * CR35 5 Horizontal Timing Registers 1=lock + * + * XXXX mostly, need to lock the enhanced command regs on the 805 (and + * probably below) to avoid display corruption. + */ +static void s3_lock(void) +{ + __svgalib_outCR(0x39, 0x00); /* Lock system control regs. */ + __svgalib_outCR(0x38, 0x00); /* Lock special regs. */ +} + +static void s3_lock_enh(void) +{ + if (s3_chiptype > S3_911) + __svgalib_outCR(0x40, __svgalib_inCR(0x40) & ~0x01); /* Lock enhanced command regs. */ + s3_lock(); +} + +/* + * Unlock S3's registers. + * There are more locks, but this should suffice. + */ +static void s3_unlock(void) +{ + __svgalib_outCR(0x38, 0x48); /* Unlock special regs. */ + __svgalib_outCR(0x39, 0xA5); /* Unlock system control regs. */ +} + +static void s3_unlock_enh(void) +{ + s3_unlock(); + if (s3_chiptype > S3_911) + __svgalib_outCR(0x40, __svgalib_inCR(0x40) | 0x01); /* Unlock enhanced command regs. */ +} + +/* + * Adjust the display width. This is necessary for the graphics + * engine if acceleration is used. However it will require more + * memory making some modes unavailable. + */ +static int s3_adjlinewidth(int oldwidth) +{ + if (s3_chiptype < S3_801) + return 1024; +#ifdef S3_USE_GRAPHIC_ENGINE + if (oldwidth <= 640) + return 640; + if (oldwidth <= 800) + return 800; + if (oldwidth <= 1024) + return 1024; + if (!(s3_flags & S3_OLD_STEPPING)) + if (oldwidth <= 1152) + return 1152; + if (oldwidth <= 1280) + return 1280; + if (oldwidth <= 1600 && s3_chiptype >= S3_864) + return 1600; + + return 2048; +#else + return oldwidth; +#endif +} + +/* Fill in chipset specific mode information */ + +static void s3_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + switch (modeinfo->colors) { + case 16: /* 4-plane 16 color mode */ + modeinfo->maxpixels = s3_memory * 1024 * 2; + break; + default: + modeinfo->maxpixels = s3_memory * 1024 / + modeinfo->bytesperpixel; + } + + /* Adjust line width (only for SVGA modes) */ + if (!IS_IN_STANDARD_VGA_DRIVER(mode)) + modeinfo->linewidth = s3_adjlinewidth(modeinfo->linewidth); + + modeinfo->maxlogicalwidth = 8184; + if (s3_chiptype >= S3_801) + modeinfo->startaddressrange = 0x3fffff; + else + modeinfo->startaddressrange = 0xfffff; + +#ifdef S3_KLUDGE_PAGE_MODE + if (mode == G320x200x256) { + /* set page size to 256k. */ + modeinfo->startaddressrange /= 4; + modeinfo->maxpixels /= 4; + } +#else + if (mode == G320x200x256) { + /* disable page flipping. */ + /* modeinfo->startaddressrange = 0xffff; */ + modeinfo->startaddressrange = 0; + modeinfo->maxpixels = 65536; + } +#endif + + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + modeinfo->flags |= HAVE_EXT_SET; +#ifdef S3_LINEAR_SUPPORT + if (modeinfo->bytesperpixel >= 1) { + modeinfo->flags |= CAPABLE_LINEAR; + } +#endif + + modeinfo->memory = s3_memory; + modeinfo->chiptype = s3_chiptype; +} + +/* + * XXX Part of this function should be implemented in ramdac.c, + * but we just kludge it here for now. + */ +static int s3_ext_set(unsigned what, va_list params) +{ + int param2, old_values; + unsigned char regs[10]; + + /* only know this, for now */ + if (dac_used->id != ATT20C490 && dac_used->id != ATT20C498 && + dac_used->id != SIERRA_15025) + return 0; + + param2 = va_arg(params, int); + old_values = (s3_flags & S3_CLUT8_8) ? VGA_CLUT8 : 0; + + switch (what) { + case VGA_EXT_AVAILABLE: + switch (param2) { + case VGA_AVAIL_SET: + return VGA_EXT_AVAILABLE | VGA_EXT_SET | VGA_EXT_CLEAR | VGA_EXT_RESET; + case VGA_AVAIL_ACCEL: + return 0; + case VGA_AVAIL_FLAGS: + return VGA_CLUT8; + } + break; + + case VGA_EXT_SET: + if (param2 & VGA_CLUT8) + goto setclut8; + + case VGA_EXT_CLEAR: + if (param2 & VGA_CLUT8) + goto clearclut8; + + case VGA_EXT_RESET: + if (param2 & VGA_CLUT8) { + setclut8: + dac_used->saveState(regs); + if (regs[0] == 0x00) { /* 8bpp, 6 bits/color */ + s3_flags |= S3_CLUT8_8; + if (dac_used->id == SIERRA_15025) + regs[1] = 1; + regs[0] = 0x02; + } + dac_used->restoreState(regs); + return old_values; + } else { + clearclut8: + dac_used->saveState(regs); + if (regs[0] == 0x02) { /* 8bpp, 8 bits/color */ + s3_flags &= ~S3_CLUT8_8; + if (dac_used->id == SIERRA_15025) + regs[1] = 0; + regs[0] = 0x00; + } + dac_used->restoreState(regs); + return old_values; + } + default: + break; + } + return 0; +} + +/* Return non-zero if mode is available */ + +static int s3_modeavailable(int mode) +{ + struct vgainfo *info; + ModeInfo *modeinfo; + ModeTiming *modetiming; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + /* Enough memory? */ + info = &__svgalib_infotable[mode]; + if (s3_memory * 1024 < info->ydim * s3_adjlinewidth(info->xbytes)) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +/* + * save S3 registers. Lock registers receive special treatment + * so dumpreg will work under X. + */ +static int s3_saveregs(unsigned char regs[]) +{ + unsigned char b, bmax; + unsigned char cr38, cr39, cr40; + + cr38 = __svgalib_inCR(0x38); + __svgalib_outCR(0x38, 0x48); /* unlock S3 VGA regs (CR30-CR3B) */ + + cr39 = __svgalib_inCR(0x39); + __svgalib_outCR(0x39, 0xA5); /* unlock S3 system control (CR40-CR4F) */ + /* and extended regs (CR50-CR6D) */ + + cr40 = __svgalib_inCR(0x40); /* unlock enhanced regs */ + __svgalib_outCR(0x40, cr40 | 0x01); + + /* retrieve values from private copy */ + memcpy(regs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2); + + /* get S3 VGA/Ext registers */ + bmax = 0x4F; + if (s3_chiptype >= S3_801) + bmax = 0x66; + if (s3_chiptype >= S3_864) + bmax = 0x6D; + for (b = 0x30; b <= bmax; b++) + regs[EXT + b - 0x30] = __svgalib_inCR(b); + + /* get S3 ext. SR registers */ + /* if (s3_chiptype >= S3_864) { */ + if (s3_chiptype == S3_TRIO32 || s3_chiptype == S3_TRIO64 + || s3_chiptype == S3_765) {/* SL: actually Trio32/64/V+ */ + regs[S3_SR08] = __svgalib_inSR(0x08); + __svgalib_outSR(0x08, 0x06); /* unlock extended seq regs */ + regs[S3_SR09] = __svgalib_inSR(0x09); + regs[S3_SR0A] = __svgalib_inSR(0x0A); + regs[S3_SR0D] = __svgalib_inSR(0x0D); + regs[S3_SR10] = __svgalib_inSR(0x10); + regs[S3_SR11] = __svgalib_inSR(0x11); + regs[S3_SR12] = __svgalib_inSR(0x12); + regs[S3_SR13] = __svgalib_inSR(0x13); + regs[S3_SR15] = __svgalib_inSR(0x15); + regs[S3_SR18] = __svgalib_inSR(0x18); + __svgalib_outSR(0x08, regs[S3_SR08]); + } + + dac_used->saveState(regs + S3_DAC_OFFSET); + + /* leave the locks the way we found it */ + __svgalib_outCR(0x40, regs[EXT + 0x40 - 0x30] = cr40); + __svgalib_outCR(0x39, regs[EXT + 0x39 - 0x30] = cr39); + __svgalib_outCR(0x38, regs[EXT + 0x38 - 0x30] = cr38); +#if 0 +#include "ramdac/IBMRGB52x.h" + + do { + unsigned char m, n, df; + + fprintf(stderr,"pix_fmt = 0x%02X, 8bpp = 0x%02X, 16bpp = 0x%02X, 24bpp = 0x%02X, 32bpp = 0x%02X,\n" + "CR58 = 0x%02X, CR66 = 0x%02X, CR67 = 0x%02X, CR6D = 0x%02X\n", + regs[S3_DAC_OFFSET + IBMRGB_pix_fmt], + regs[S3_DAC_OFFSET + IBMRGB_8bpp], + regs[S3_DAC_OFFSET + IBMRGB_16bpp], + regs[S3_DAC_OFFSET + IBMRGB_24bpp], + regs[S3_DAC_OFFSET + IBMRGB_32bpp], + regs[S3_CR58], + regs[S3_CR66], + regs[S3_CR67], + regs[S3_CR6D]); + + m = regs[S3_DAC_OFFSET + IBMRGB_m0 + 4]; + n = regs[S3_DAC_OFFSET + IBMRGB_n0 + 4]; + df = m >> 6; + m &= ~0xC0; + + fprintf(stderr,"m = 0x%02X %d, n = 0x%02X %d, df = 0x%02X %d, freq = %.3f\n", + m, m, n, n, df, df, ((m + 65.0) / n) / (8 >> df) * 16.0); + } while (0); +#endif + return S3_DAC_OFFSET - VGA_TOTAL_REGS + dac_used->stateSize; +} + +/* Set chipset-specific registers */ +static void s3_setregs(const unsigned char regs[], int mode) +{ + unsigned char b, bmax; + /* + * Right now, anything != 0x00 gets written in s3_setregs. + * May change this into a bitmask later. + */ + static unsigned char s3_regmask[] = + { + 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x00, 0x00, /* CR30-CR37 */ + 0x00, 0x00, 0x3A, 0x3B, 0x3C, 0x00, 0x00, 0x00, /* CR38-CR3F */ + 0x00, 0x00, 0x42, 0x43, 0x44, 0x45, 0x00, 0x00, /* CR40-CR47 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR48-CR4F */ + 0x50, 0x51, 0x00, 0x00, 0x54, 0x55, 0x00, 0x00, /* CR50-CR57 */ + 0x58, 0x59, 0x5A, 0x00, 0x00, 0x5D, 0x5E, 0x00, /* CR58-CR5F */ + 0x60, 0x61, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR60-CR67 */ + 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00 /* CR68-CR6D */ + }; + + s3_unlock_enh(); + + /* save a private copy */ + memcpy(s3_8514regs, regs + S3_8514_OFFSET, S3_8514_COUNT * 2); + /* + * set this first, so if we segfault on this + * we don't get a screwed up display + */ + port_outw_r(ADVFUNC_CNTL, s3_8514regs[S3_ADVFUNC_CNTL]); + + /* get S3 VGA/Ext registers */ + bmax = 0x4F; + if (s3_chiptype >= S3_801) + bmax = 0x66; + if (s3_chiptype >= S3_864) + bmax = 0x6D; + for (b = 0x30; b <= bmax; b++) { + if (s3_regmask[b - 0x30]) + __svgalib_outCR(b, regs[EXT + b - 0x30]); + } + + if (dac_used->id != NORMAL_DAC) { + unsigned char CR1; + /* Blank the screen. */ + CR1 = __svgalib_inCR(0x01); + __svgalib_outCR(0x01, CR1 | 0x20); + + __svgalib_outcrtc(0x55, __svgalib_inCR(0x55) | 1); + __svgalib_outcrtc(0x66, regs[S3_CR66]); + __svgalib_outcrtc(0x67, regs[S3_CR67]); /* S3 pixmux. */ + + dac_used->restoreState(regs + S3_DAC_OFFSET); + + __svgalib_outcrtc(0x6D, regs[S3_CR6D]); + __svgalib_outcrtc(0x55, __svgalib_inCR(0x55) & ~1); + + __svgalib_outcrtc(0x01, CR1); /* Unblank screen. */ + } +#ifdef S3_LINEAR_SUPPORT + if (mode == TEXT && s3_linear_addr) + s3_linear_disable(); /* make sure linear is off */ +#endif + + /* restore CR38/39 (may lock other regs) */ + if (mode == TEXT) { + /* restore lock registers as well */ + __svgalib_outCR(0x40, regs[S3_CR40]); + __svgalib_outCR(0x39, regs[S3_CR39]); + __svgalib_outCR(0x38, regs[S3_CR38]); + } else + s3_lock_enh(); +} + +/* + * Initialize register state for a mode. + */ + +static void s3_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo) +{ + /* Get current values. */ + s3_saveregs(moderegs); + + /* Set up the standard VGA registers for a generic SVGA. */ + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + /* Set up the extended register values, including modifications */ + /* of standard VGA registers. */ + + moderegs[VGA_SR0] = 0x03; + moderegs[VGA_CR13] = modeinfo->lineWidth >> 3; + moderegs[VGA_CR17] = 0xE3; + + if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 2048) + moderegs[S3_CR31] = 0x8F; + else + moderegs[S3_CR31] = 0x8D; +#ifdef S3_LINEAR_MODE_BANKING_864 + if (s3_chiptype >= S3_864) { + /* moderegs[S3_ENHANCEDMODE] |= 0x01; */ + /* Enable enhanced memory mode. */ + moderegs[S3_CR31] |= 0x04; + /* Enable banking via CR6A in linear mode. */ + moderegs[S3_CR31] |= 0x01; + } +#endif + moderegs[S3_CR32] = 0; + moderegs[S3_CR33] = 0x20; + moderegs[S3_CR34] = 0x10; /* 1024 */ + moderegs[S3_CR35] = 0; + /* Call cebank() here when setting registers. */ + if (modeinfo->bitsPerPixel >= 8) { + moderegs[S3_CR3A] = 0xB5; + if (s3_chiptype == S3_928) + /* ARI: Turn on CHAIN4 for 928, since __svgalib_setup_VGA_registers + initializes ModeX */ + moderegs[VGA_CR14] = 0x60; + } else { + /* 16 color mode */ + moderegs[VGA_CR13] = modeinfo->lineWidth >> 1; + moderegs[VGA_GR0] = 0x0F; + moderegs[VGA_GR1] = 0x0F; + moderegs[VGA_GR5] = 0x00; /* write mode 0 */ + moderegs[VGA_AR11] = 0x00; + moderegs[S3_CR3A] = 0x85; + } + + moderegs[S3_CR3B] = (moderegs[VGA_CR0] + moderegs[VGA_CR4] + 1) / 2; + moderegs[S3_CR3C] = moderegs[VGA_CR0] / 2; + if (s3_chiptype == S3_911) { + moderegs[S3_CR40] &= 0xF2; + moderegs[S3_CR40] |= 0x09; + } else if (s3_flags & S3_LOCALBUS) { + moderegs[S3_CR40] &= 0xF2; + /* Pegasus wants 0x01 for zero wait states. */ +#ifdef S3_0_WAIT_805_864 + moderegs[S3_CR40] |= 0x09; /* use fifo + 0 wait state */ +#else + moderegs[S3_CR40] |= 0x05; +#endif + } else { + moderegs[S3_CR40] &= 0xF6; + moderegs[S3_CR40] |= 0x01; + } + + if (modeinfo->bitsPerPixel >= 24) { + /* 24/32 bit color */ + if (s3_chiptype == S3_864 || s3_chiptype == S3_964) + moderegs[S3_CR43] = 0x08; + else if (s3_chiptype == S3_928 && dac_used->id == SIERRA_15025) + moderegs[S3_CR43] = 0x01; /* ELSA Winner 1000 */ + } else if (modeinfo->bitsPerPixel >= 15) { + /* 15/16 bit color */ + if (s3_chiptype <= S3_864 || s3_chiptype >= S3_866) { /* XXXX Trio? */ + moderegs[S3_CR43] = 0x08; + if (dac_used->id == IBMRGB52x) + moderegs[S3_CR43] = 0x10; + else if (s3_chiptype == S3_928 && dac_used->id == SIERRA_15025) + moderegs[S3_CR43] = 0x01; + if (s3_chiptype <= S3_924 && dac_used->id != NORMAL_DAC) + moderegs[S3_CR43] = 0x01; + + } else + /* XXXX some DAC might need this; XF86 source says... */ + moderegs[S3_CR43] = 0x09; + } else { + /* 4/8 bit color */ + moderegs[S3_CR43] = 0x00; + } + + if (s3_chiptype >= S3_924 && s3_chiptype <= S3_928) { /* different for 864+ */ + s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002; + if ((s3_chiptype == S3_928 && modeinfo->bitsPerPixel != 4) || !(s3_flags & S3_OLD_STEPPING)) + s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001; + if (modeinfo->bitsPerPixel == 4) + s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004; +#if 0 + /* 864 databook says it is for enhanced 4bpp */ + if (modeinfo->lineWidth > 640) + s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004; +#endif + } else if (s3_chiptype == S3_968) { + s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002; + if (modeinfo->bitsPerPixel == 4) + s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004; +#ifdef PIXEL_MULTIPLEXING + else + s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001; +#endif + } else if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 1024) + s3_8514regs[S3_ADVFUNC_CNTL] = 0x0007; + else + s3_8514regs[S3_ADVFUNC_CNTL] = 0x0003; + + moderegs[S3_CR44] = 0; + /* Skip CR45, 'hi/truecolor cursor color enable'. */ + + if (s3_chiptype >= S3_801) { + int m, n; /* for FIFO balancing */ + + /* XXXX Not all chips support all widths. */ + moderegs[S3_CR50] &= ~0xF1; + switch (modeinfo->bitsPerPixel) { + case 16: + moderegs[S3_CR50] |= 0x10; + break; + case 24: /* XXXX 868/968 only */ + if (s3_chiptype >= S3_868) + moderegs[S3_CR50] |= 0x20; + break; + case 32: + moderegs[S3_CR50] |= 0x30; + break; + } + + switch (modeinfo->lineWidth / modeinfo->bytesPerPixel) { + case 640: + moderegs[S3_CR50] |= 0x40; + break; + case 800: + moderegs[S3_CR50] |= 0x80; + break; + case 1152: + if (!(s3_flags & S3_OLD_STEPPING)) { + moderegs[S3_CR50] |= 0x01; + break; + } /* else fall through */ + case 1280: + moderegs[S3_CR50] |= 0xC0; + break; + case 1600: + moderegs[S3_CR50] |= 0x81; + break; + /* 1024/2048 no change. */ + } + + moderegs[S3_CR51] &= 0xC0; + moderegs[S3_CR51] |= (modeinfo->lineWidth >> 7) & 0x30; + + /* moderegs[S3_CR53] |= 0x10; *//* Enable MMIO. */ + /* moderegs[S3_CR53] |= 0x20; *//* DRAM interleaving for S3_805i with 2MB */ + + n = 0xFF; + if (s3_chiptype >= S3_864 || + s3_chiptype == S3_801 || s3_chiptype == S3_805) { + /* + * CRT FIFO balancing for DRAM cards and 964/968 + * in VGA mode. + */ + int clock, mclk; + if (modeinfo->bitsPerPixel < 8) { + clock = modetiming->pixelClock; + } else { + clock = modetiming->pixelClock * + modeinfo->bytesPerPixel; + } + if (s3_memory < 2048 || s3_chiptype == S3_TRIO32) + clock *= 2; + if (__svgalib_s3_s3Mclk > 0) + mclk = __svgalib_s3_s3Mclk; + else if (s3_chiptype == S3_801 || s3_chiptype == S3_805) + mclk = 50000; /* Assumption. */ + else + mclk = 60000; /* Assumption. */ + m = (int) ((mclk / 1000.0 * .72 + 16.867) * 89.736 / (clock / 1000.0 + 39) - 21.1543); + if (s3_memory < 2048 || s3_chiptype == S3_TRIO32) + m /= 2; + if (m > 31) + m = 31; + else if (m < 0) { + m = 0; + n = 16; + } + } else if (s3_memory == 512 || modetiming->HDisplay > 1200) + m = 0; + else if (s3_memory == 1024) + m = 2; + else + m = 20; + + moderegs[S3_CR54] = m << 3; + moderegs[S3_CR60] = n; + + moderegs[S3_CR55] &= 0x08; + moderegs[S3_CR55] |= 0x40; + +#ifdef S3_LINEAR_MODE_BANKING_864 + if (s3_chiptype >= S3_864) { + if (modeinfo->bitsPerPixel >= 8) { + /* Enable linear addressing. */ + moderegs[S3_CR58] |= 0x10; + /* Set window size to 64K. */ + moderegs[S3_CR58] &= ~0x03; + /* Assume CR59/5A are correctly set up for 0xA0000. */ + /* Set CR6A linear bank to zero. */ + moderegs[S3_CR6A] &= ~0x3F; + /* use alternate __svgalib_setpage() function */ + __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage864; + } else { + /* doesn't work for 4bpp. */ + __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage; + } + } +#endif +#ifdef S3_LINEAR_SUPPORT + moderegs[S3_CR59] = s3_cr59; + moderegs[S3_CR5A] = s3_cr5A; +#endif + + /* Extended CRTC timing. */ + moderegs[S3_CR5E] = + (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) | + (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 8) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40; + + { + int i, j; + i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | + ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | + ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | + ((modetiming->CrtcHSyncStart & 0x800) >> 7); + if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64) + i |= 0x08; + if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32) + i |= 0x20; + j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) + + moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2); + if (j - (moderegs[VGA_CR4] + ((i & 0x10) << 4)) < 4) { + if (moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4 <= moderegs[VGA_CR0] + ((i & 0x01) << 8)) + j = moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4; + else + j = moderegs[VGA_CR0] + ((i & 0x01) << 8) + 1; + } + + moderegs[S3_CR3B] = j & 0xFF; + i |= (j & 0x100) >> 2; + /* Interlace mode frame offset. */ + moderegs[S3_CR3C] = (moderegs[VGA_CR0] + ((i & 0x01) << 8)) / 2; + moderegs[S3_CR5D] = (moderegs[S3_CR5D] & 0x80) | i; + } + + { + int i; + + if (modeinfo->bitsPerPixel < 8) + i = modetiming->HDisplay / 4 + 1; + else + i = modetiming->HDisplay * + modeinfo->bytesPerPixel / 4 + 1; + + moderegs[S3_CR61] = (i >> 8) | 0x80; + moderegs[S3_CR62] = i & 0xFF; + } + } /* 801+ */ + if (modetiming->flags & INTERLACED) + moderegs[S3_CR42] |= 0x20; + + /* + * Clock select works as follows: + * Clocks 0 and 1 (VGA 25 and 28 MHz) can be selected via the + * two VGA MiscOutput clock select bits. + * If 0x3 is written to these bits, the selected clock index + * is taken from the S3 clock select register at CR42. Clock + * indices 0 and 1 should correspond to the VGA ones above, + * and 3 is often 0 MHz, followed by extended clocks for a + * total of mostly 16. + */ + + if (modetiming->flags & USEPROGRCLOCK) + moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */ + else if (modetiming->selectedClockNo < 2) { + /* Program clock select bits 0 and 1. */ + moderegs[VGA_MISCOUTPUT] &= ~0x0C; + moderegs[VGA_MISCOUTPUT] |= + (modetiming->selectedClockNo & 3) << 2; + } else if (modetiming->selectedClockNo >= 2) { + moderegs[VGA_MISCOUTPUT] |= 0x0C; + /* Program S3 clock select bits. */ + moderegs[S3_CR42] &= ~0x1F; + moderegs[S3_CR42] |= + modetiming->selectedClockNo; + } + if (s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) { + moderegs[S3_CR33] &= ~0x08; + if (modeinfo->bitsPerPixel == 16) + moderegs[S3_CR33] |= 0x08; + /* + * The rest of the DAC/clocking is setup by the + * Trio64 code in the RAMDAC interface (ramdac.c). + */ + } + if (dac_used->id != NORMAL_DAC) { + int colormode; + colormode = __svgalib_colorbits_to_colormode(modeinfo->bitsPerPixel, + modeinfo->colorBits); + dac_used->initializeState(&moderegs[S3_DAC_OFFSET], + modeinfo->bitsPerPixel, colormode, + modetiming->pixelClock); + + if (dac_used->id == ATT20C490) { + int pixmux, invert_vclk, blank_delay; + pixmux = 0; + invert_vclk = 0; + blank_delay = 2; + if (colormode == CLUT8_6 + && modetiming->pixelClock >= 67500) { + pixmux = 0x00; + invert_vclk = 1; + } else if (colormode == CLUT8_8) + pixmux = 0x02; + else if (colormode == RGB16_555) + pixmux = 0xa0; + else if (colormode == RGB16_565) + pixmux = 0xc0; + else if (colormode == RGB24_888_B) + pixmux = 0xe0; + moderegs[S3_CR67] = pixmux | invert_vclk; + moderegs[S3_CR6D] = blank_delay; + } + if (dac_used->id == S3_SDAC) { + int pixmux, invert_vclk, blank_delay; + pixmux = 0; + invert_vclk = 0; + blank_delay = 0; + if (colormode == CLUT8_6 + && modetiming->pixelClock >= 67500) { +#ifdef SDAC_8BPP_PIXMUX + /* x64 8bpp pixel multiplexing? */ + pixmux = 0x10; + if (s3_chiptype != S3_866 && s3_chiptype != S3_868) + invert_vclk = 1; + blank_delay = 2; +#endif + } else if (colormode == RGB16_555) { + pixmux = 0x30; + blank_delay = 2; + } else if (colormode == RGB16_565) { + pixmux = 0x50; + blank_delay = 2; + } else if (colormode == RGB24_888_B) { /* XXXX 868/968 only */ + pixmux = 0x90; + blank_delay = 2; + } else if (colormode == RGB32_888_B) { + pixmux = 0x70; + blank_delay = 2; + } + moderegs[S3_CR67] = pixmux | invert_vclk; + moderegs[S3_CR6D] = blank_delay; + /* Clock select. */ + moderegs[S3_CR42] &= ~0x0F; + moderegs[S3_CR42] |= 0x02; + } + if (dac_used->id == IBMRGB52x) { + unsigned char pixmux, blank_delay, tmp; + tmp = 0; + pixmux = 0x11; + blank_delay = 0; + if (modeinfo->bitsPerPixel < 8 || colormode == RGB32_888_B) + pixmux = 0x00; + moderegs[S3_CR58] |= 0x40; + moderegs[S3_CR65] = 0; + moderegs[S3_CR66] &= 0xf8; + moderegs[S3_CR66] |= tmp; +#ifdef PIXEL_MULTIPLEXING + moderegs[S3_CR67] = pixmux; +#endif + moderegs[S3_CR6D] = blank_delay; + /* Clock select. */ + moderegs[S3_CR42] &= ~0x0F; + moderegs[S3_CR42] |= 0x02; + } + } +#ifdef S3_LINEAR_SUPPORT + s3_cr58 = moderegs[S3_CR58]; + s3_cr40 = moderegs[S3_CR40]; + s3_cr54 = moderegs[S3_CR54]; +#endif + if (clk_used == &__svgalib_I2061A_clockchip_methods && + (modetiming->flags & USEPROGRCLOCK)) { + /* Clock select. */ + moderegs[S3_CR42] &= ~0x0F; + moderegs[S3_CR42] |= 0x02; + } + /* update the 8514 regs */ + memcpy(moderegs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2); +} + + +/* Set a mode */ + +static int s3_setmode(int mode, int prv_mode) +{ + ModeInfo *modeinfo; + ModeTiming *modetiming; + unsigned char moderegs[S3_TOTAL_REGS]; + int res; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + /* Let the standard VGA driver set standard VGA modes. */ + res = __svgalib_vga_driverspecs.setmode(mode, prv_mode); + if (res == 0) { + /* + * ARI: Turn off virtual size of 1024 - this fixes all problems + * with standard modes, including 320x200x256. + * + * SL: Is this for 928 only? Doesn't matter for 805. + * + * MZ: Affects 765 as well, so I assume it is good for all chipsets. + */ + s3_unlock(); + __svgalib_outCR(0x34, __svgalib_inCR(0x34) & ~0x10); + s3_lock(); + } + return res; + } + if (!s3_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + /* Adjust the display width. */ + modeinfo->lineWidth = s3_adjlinewidth(modeinfo->lineWidth); + CI.xbytes = modeinfo->lineWidth; + + s3_initializemode(moderegs, modetiming, modeinfo); + free(modeinfo); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + s3_setregs(moderegs, mode); /* Set extended regs. */ + return 0; +} + + +/* Indentify chipset; return non-zero if detected */ + +/* Some port I/O functions: */ +static unsigned char rdinx(int port, unsigned char index) +{ + port_out_r(port, index); + return port_in(port + 1); +} + +static void wrinx(int port, unsigned char index, unsigned char val) +{ + port_out_r(port, index); + port_out_r(port + 1, val); +} + +/* + * Returns true iff the bits in 'mask' of register 'port', index 'index' + * are read/write. + */ +static int testinx2(int port, unsigned char index, unsigned char mask) +{ + unsigned char old, new1, new2; + + old = rdinx(port, index); + wrinx(port, index, (old & ~mask)); + new1 = rdinx(port, index) & mask; + wrinx(port, index, (old | mask)); + new2 = rdinx(port, index) & mask; + wrinx(port, index, old); + return (new1 == 0) && (new2 == mask); +} + +static int s3_test(void) +{ + int vgaIOBase, vgaCRIndex, vgaCRReg; + + vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; + vgaCRIndex = vgaIOBase + 4; + vgaCRReg = vgaIOBase + 5; + + port_out_r(vgaCRIndex, 0x11); /* for register CR11, (Vertical Retrace End) */ + port_out_r(vgaCRReg, 0x00); /* set to 0 */ + + port_out_r(vgaCRIndex, 0x38); /* check if we have an S3 */ + port_out_r(vgaCRReg, 0x00); + + /* Make sure we can't write when locked */ + + if (testinx2(vgaCRIndex, 0x35, 0x0f)) + return 0; + + port_out_r(vgaCRIndex, 0x38); /* for register CR38, (REG_LOCK1) */ + port_out_r(vgaCRReg, 0x48); /* unlock S3 register set for read/write */ + + /* Make sure we can write when unlocked */ + + if (!testinx2(vgaCRIndex, 0x35, 0x0f)) + return 0; + + if (s3_init(0, 0, 0)) /* type not OK */ + return 0; + return 1; +} + +/* + * Bank switching function - set 64K bank number + * + * XXXX locking and unlocking might hurt performance but is safer. + */ +static void s3_setpage(int page) +{ +#ifdef S3_16_COLORS + /* + * XXXX adjust the parameter for 4bpp (1bpp is ignored). Shouldn't + * need this, but either me or the drawing functions are making bad + * assumptions about 4bpp. + */ + if (infotable[CM].bytesperpixel == 0) + page *= 4; +#endif +#ifdef S3_KLUDGE_PAGE_MODE + /* adjust to use 256K pages */ + if (CM == G320x200x256) + page *= 4; +#endif + s3_unlock(); + port_out_r(CRT_IC, 0x35); + port_out_r(CRT_DC, (port_in(CRT_DC) & 0xF0) | (page & 0x0F)); + if (s3_chiptype >= S3_801) { + port_out_r(CRT_IC, 0x51); + port_out_r(CRT_DC, (port_in(CRT_DC) & ~0x0C) | ((page & 0x30) >> 2)); + } + port_in(CRT_DC); /* ARI: Ferraro says: required for first generation 911 only */ + s3_lock(); +} + +/* + * Bank switching function - set 64K bank number for 864+ + * (not for 4bpp) + * + * XXXX locking and unlocking might hurt performance + * (864 shouldn't need it). + */ +#ifdef S3_LINEAR_MODE_BANKING_864 +static void s3_setpage864(int page) +{ + s3_unlock(); + /* "Linear" mode banking. */ + port_out_r(CRT_IC, 0x6A); + port_out_r(CRT_DC, (port_in(CRT_DC) & ~0x3F) | page); + s3_lock(); +} + +#endif + +/* + * Set display start address (not for 16 color modes). + * + * This works up to 4Mb (should be able to go higher). + * + * XXXX locking and unlocking might hurt performance but is safer. + */ +static void s3_setdisplaystart(int address) +{ +#ifdef S3_KLUDGE_PAGE_MODE + /* adjust to use 256K pages */ + if (CM == G320x200x256) + address *= 4; +#endif + s3_unlock(); + port_outw_r(CRT_IC, 0x0d | ((address << 6) & 0xff00)); /* sa2-sa9 */ + port_outw_r(CRT_IC, 0x0c | ((address >> 2) & 0xff00)); /* sa10-sa17 */ + port_in(0x3da); /* set ATC to addressing mode */ + port_out_r(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); + /* write sa0-1 to bits 1-2 */ + + port_out_r(CRT_IC, 0x31); + port_out_r(CRT_DC, (port_in(CRT_DC) & ~0x30) | ((address & 0xc0000) >> 14)); + if (s3_chiptype >= S3_801) { + port_out_r(CRT_IC, 0x51); + port_out_r(CRT_DC, (port_in(CRT_DC) & ~0x03) | ((address & 0x300000) >> 20)); + } + s3_lock(); +} + +/* + * Set logical scanline length (Multiples of 8 to 8184). + * CR43.2 should be 0 for this. + */ +static void s3_setlogicalwidth(int width) +{ + __svgalib_outCR(0x13, (width >> 3)); /* lw3-lw11 */ + __svgalib_outCR(0x51, (width & 0x300) >> 4); /* lw12-lw13 */ +} + +#ifdef S3_LINEAR_SUPPORT +static void s3_linear_enable(void) +{ + s3_unlock(); + + if (s3_chiptype > S3_924) { + int i; + port_out_r (CRT_IC, 0x40); + i = (s3_cr40 & 0xf6) | 0x0a; + port_out_r (CRT_DC, (unsigned char) i); + port_out_r (CRT_IC, 0x58); + port_out_r (CRT_DC, s3_linear_opt | s3_cr58); + if (s3_chiptype > S3_928) { + port_out_r (CRT_IC, 0x54); + port_out_r (CRT_DC, (s3_cr54 + 0x07)); + } + } + + s3_lock(); +} + +static void s3_linear_disable(void) +{ + s3_unlock(); + + if (s3_chiptype > S3_924) { + if (s3_chiptype > S3_928) { + port_out_r (CRT_IC, 0x54); + port_out_r (CRT_DC, s3_cr54); + } + port_out_r (CRT_IC, 0x58); + port_out_r (CRT_DC, s3_cr58); + port_out_r (CRT_IC, 0x40); + port_out_r (CRT_DC, s3_cr40); + } + + s3_lock(); +} + +/* Set linear addressing mode */ + +static int s3_linear(int op, int param) +{ + if (op == LINEAR_QUERY_BASE) + return s3_linear_base; + if (op == LINEAR_QUERY_GRANULARITY) { + switch (s3_memory) { + case 4096: + case 2048: + case 1024: + return s3_memory * 1024; + default: + return 1024 * 1024; + } + } else if (op == LINEAR_QUERY_RANGE) + return 256; + else if (op == LINEAR_ENABLE) { + s3_setpage(0); + s3_linear_enable(); + s3_linear_addr = param; + return 0; + } else if (op == LINEAR_DISABLE) { + s3_setpage(0); + s3_linear_disable(); + s3_linear_addr = 0; + return 0; + } else + return -1; +} + +#define S3_LINEAR_FUNC s3_linear +#else +#define S3_LINEAR_FUNC 0 +#endif /* S3_LINEAR_SUPPORT */ + +/* Function table (exported) */ + +DriverSpecs __svgalib_s3_driverspecs = +{ + s3_saveregs, /* saveregs */ + s3_setregs, /* setregs */ + (void (*)(void)) nothing, /* unlock */ + (void (*)(void)) nothing, /* lock */ + s3_test, + s3_init, + s3_setpage, + (void (*)(int)) nothing, + (void (*)(int)) nothing, + s3_setmode, + s3_modeavailable, + s3_setdisplaystart, + s3_setlogicalwidth, + s3_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + s3_ext_set, /* extset */ + 0, /* accel */ + S3_LINEAR_FUNC, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + + +/* S3-specific config file options. */ + +/* + * Currently this only handles Clocks. It would a good idea to have + * higher-level code process options like Clocks that are valid for + * more than one driver driver (with better error detection etc.). + */ + +static char *s3_config_options[] = +{ + "clocks", "ramdac", "dacspeed", "clockchip", NULL +}; + +static char *s3_process_option(int option, int mode, char **nptr) +{ +/* + * option is the number of the option string in s3_config_options, + * mode seems to be a 'hardness' indicator for security. + */ + if (option == 0) { /* "Clocks" */ + /* Process at most 16 specified clocks. */ + cardspecs->clocks = malloc(sizeof(int) * 16); + /* cardspecs->nClocks should be already be 0. */ + for (;;) { + char *ptr; + int freq; + ptr = __svgalib_token(nptr); + if (ptr == NULL) + break; + /* + * This doesn't protect against bad characters + * (atof() doesn't detect errors). + */ + freq = atof(ptr) * 1000; + cardspecs->clocks[cardspecs->nClocks] = freq; + cardspecs->nClocks++; + if (cardspecs->nClocks == 16) + break; + } + } + if (option == 1) { /* "Ramdac" */ + char *ptr; + ptr = __svgalib_token(nptr); +#ifdef INCLUDE_IBMRGB52x_DAC + if (strcasecmp(ptr, "IBMRGB52x") == 0) + dac_used = &__svgalib_IBMRGB52x_methods; +#endif +#ifdef INCLUDE_SIERRA_DAC + if (strcasecmp(ptr, "Sierra32K") == 0) + dac_used = &__svgalib_Sierra_32K_methods; +#endif +#ifdef INCLUDE_SC15025_DAC + if (strcasecmp(ptr, "SC15025") == 0) + dac_used = &__svgalib_SC15025_methods; +#endif +#ifdef INCLUDE_S3_SDAC_DAC + if (strcasecmp(ptr, "SDAC") == 0) + dac_used = &__svgalib_S3_SDAC_methods; +#endif +#ifdef INCLUDE_S3_GENDAC_DAC + if (strcasecmp(ptr, "GenDAC") == 0) + dac_used = &__svgalib_S3_GENDAC_methods; +#endif +#ifdef INCLUDE_ATT20C490_DAC + if (strcasecmp(ptr, "ATT20C490") == 0) + dac_used = &__svgalib_ATT20C490_methods; +#endif +#ifdef INCLUDE_ATT20C498_DAC + if (strcasecmp(ptr, "ATT20C498") == 0) + dac_used = &__svgalib_ATT20C498_methods; +#endif +#ifdef INCLUDE_NORMAL_DAC + if (strcasecmp(ptr, "Normal") == 0) /* force normal VGA dac */ + dac_used = &__svgalib_normal_dac_methods; +#endif + + if (clk_used) + clk_used->initialize(cardspecs, dac_used); + } + if (option == 2) { /* "Dacspeed" */ + char *ptr; + ptr = __svgalib_token(nptr); + /* + * This doesn't protect against bad characters + * (atoi() doesn't detect errors). + */ + dac_speed = atoi(ptr) * 1000; + } + if (option == 3) { /* "ClockChip" */ + char *ptr; + int freq; + ptr = strtok(NULL, " \t"); + if (strcasecmp(ptr, "ICD2061A") == 0 || + strcasecmp(ptr, "DCS2824") == 0) /* Diamond, compatible to icd2061a */ + clk_used = &__svgalib_I2061A_clockchip_methods; + clk_used->initialize(cardspecs, dac_used); + ptr = strtok(NULL, " \t"); + if (ptr != NULL) { + freq = atof(ptr) * 1000L; + if (freq) { + clk_used->TextFrequency = freq; + ptr = strtok(NULL, " \t"); + } + } + return ptr; + } + return __svgalib_token(nptr); +} + + +/* Initialize driver (called after detection) */ +/* Derived from XFree86 SuperProbe and s3 driver. */ + +static DacMethods *dacs_to_probe[] = +{ +#ifdef INCLUDE_S3_SDAC_DAC_TEST + &__svgalib_S3_SDAC_methods, +#endif +#ifdef INCLUDE_S3_GENDAC_DAC_TEST + &__svgalib_S3_GENDAC_methods, +#endif +#ifdef INCLUDE_ATT20C490_DAC_TEST + &__svgalib_ATT20C490_methods, +#endif +#ifdef INCLUDE_SC15025_DAC_TEST + &__svgalib_SC15025_methods, +#endif +#ifdef INCLUDE_SC1148X_DAC_TEST + &__svgalib_SC1148X_methods, +#endif +#ifdef INCLUDE_IBMRGB52x_DAC_TEST + &__svgalib_IBMRGB52x_methods, +#endif + NULL}; + +static int s3_init(int force, int par1, int par2) +{ + int id, rev, config; + + s3_unlock(); + + s3_flags = 0; /* initialize */ + id = __svgalib_inCR(0x30); /* Get chip id. */ + rev = id & 0x0F; + if (id >= 0xE0) { + id |= __svgalib_inCR(0x2E) << 8; + rev |= __svgalib_inCR(0x2F) << 4; + } + if (force) { + s3_chiptype = par1; /* we already know the type */ + s3_memory = par2; + /* ARI: can we really trust the user's specification, or should we ignore + it and probe ourselves ? */ + if (s3_chiptype == S3_801 || s3_chiptype == S3_805) { + if ((rev & 0x0F) < 2) + s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ + } else if (s3_chiptype == S3_928) { + if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */ + s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ + } + } else { + s3_chiptype = -1; + config = __svgalib_inCR(0x36); /* get configuration info */ + switch (id & 0xf0) { + case 0x80: + if (rev == 1) { + s3_chiptype = S3_911; + break; + } + if (rev == 2) { + s3_chiptype = S3_924; + break; + } + break; + case 0xa0: + switch (config & 0x03) { + case 0x00: + case 0x01: + /* EISA or VLB - 805 */ + s3_chiptype = S3_805; + /* ARI: Test stepping: 0:B, 1:unknown, 2,3,4:C, 8:I, >=5:D */ + if ((rev & 0x0F) < 2) + s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ + break; + case 0x03: + /* ISA - 801 */ + s3_chiptype = S3_801; + /* Stepping same as 805, just ISA */ + if ((rev & 0x0F) < 2) + s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ + break; + } + break; + case 0x90: + s3_chiptype = S3_928; + if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */ + s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ + break; + case 0xB0: + /* 928P */ + s3_chiptype = S3_928; + break; + case 0xC0: + s3_chiptype = S3_864; + break; + case 0xD0: + s3_chiptype = S3_964; + break; + case 0xE0: + switch (id & 0xFFF0) { + case 0x10E0: + s3_chiptype = S3_TRIO32; + break; + case 0x3DE0: /* ViRGE/VX ID */ + case 0x31E0: /* ViRGE ID */ + case 0x01E0: /* S3Trio64V2/DX ... any others? */ + case 0x04E0: + case 0x11E0: + if (rev & 0x0400) + s3_chiptype = S3_765; + else + s3_chiptype = S3_TRIO64; + break; + case 0x80E0: + s3_chiptype = S3_866; + break; + case 0x90E0: + s3_chiptype = S3_868; + break; + case 0xF0E0: /* XXXX From data book; XF86 says 0xB0E0? */ + s3_chiptype = S3_968; + break; + } + } + if (s3_chiptype == -1) { + fprintf(stderr,"svgalib: S3: Unknown chip id %02x\n", + id); + return -1; + } + if (s3_chiptype <= S3_924) { + if ((config & 0x20) != 0) + s3_memory = 512; + else + s3_memory = 1024; + } else { + /* look at bits 5, 6 and 7 */ + switch ((config & 0xE0) >> 5) { + case 0: + s3_memory = 4096; + break; + case 2: + s3_memory = 3072; + break; + case 3: + s3_memory = 8192; + break; + case 4: + s3_memory = 2048; + break; + case 5: + s3_memory = 6144; + break; + case 6: + s3_memory = 1024; + break; + case 7: + s3_memory = 512; + break; /* Trio32 */ + } + } + + if ((config & 0x03) < 3) /* XXXX 928P is ignored */ + s3_flags |= S3_LOCALBUS; + } + + if (__svgalib_driver_report) { + fprintf(stderr,"svgalib: Using S3 driver (%s, %dK).\n", s3_chipname[s3_chiptype], + s3_memory); + if (s3_flags & S3_OLD_STEPPING) + fprintf(stderr,"svgalib: Chip revision cannot handle modes with width 1152.\n"); + if (s3_chiptype > S3_TRIO64) { + fprintf(stderr,"svgalib: s3: chipsets newer than S3 Trio64 is not supported well yet.\n"); + } + } +/* begin: Initialize cardspecs. */ +#ifdef S3_LINEAR_SUPPORT + if (s3_chiptype > S3_805) { + int found_pciconfig; + unsigned int pci_conf[64]; + + found_pciconfig = __svgalib_pci_find_vendor_vga_pos(0x5333, pci_conf); + if (found_pciconfig) + s3_linear_base = pci_conf[4] & 0xFF800000; + } + + s3_cr59 = s3_linear_base >> 24; + s3_cr5A = (s3_linear_base >> 16); + if (! (s3_cr59 | s3_cr5A)) { + s3_cr59 = __svgalib_inCR(0x59); + s3_cr5A = __svgalib_inCR(0x5A); + if (!s3_cr59) { + s3_cr59 = 0xF3000000 >> 24; + s3_cr5A = (0xF3000000 >> 16); + } + s3_linear_base = (s3_cr59 << 24) | (s3_cr5A << 16); + } + s3_linear_opt |= 0x10; + switch (s3_memory) { + case 512 : + case 1024 : + s3_linear_opt |= 0x01; + break; + case 2048 : + s3_linear_opt |= 0x02; + break; + case 3072 : + case 4096 : + case 6144 : + case 8192 : + s3_linear_opt |= 0x03; + break; + default : + s3_linear_opt = 0x14; /* like XFree */ + } +#endif + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = s3_memory; + cardspecs->nClocks = 0; + /* cardspecs->maxHorizontalCrtc = 2040; SL: kills 800x600x32k and above */ + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->flags = INTERLACE_DIVIDE_VERT; + + /* Process S3-specific config file options. */ + __svgalib_read_options(s3_config_options, s3_process_option); + +#ifdef INCLUDE_S3_TRIO64_DAC + if ((s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) && dac_used == NULL) + dac_used = &__svgalib_Trio64_methods; +#endif + + if (dac_used == NULL) + dac_used = __svgalib_probeDacs(dacs_to_probe); + else + dac_used->initialize(); + + + if (dac_used == NULL) { + /* Not supported. */ + fprintf(stderr,"svgalib: s3: Assuming normal VGA DAC.\n"); +#ifdef INCLUDE_NORMAL_DAC + dac_used = &__svgalib_normal_dac_methods; + dac_used->initialize(); +#else + fprintf(stderr,"svgalib: Alas, normal VGA DAC support is not compiled in, goodbye.\n"); + return 1; +#endif + } + if (clk_used) + clk_used->initialize(cardspecs, dac_used); + + dac_used->qualifyCardSpecs(cardspecs, dac_speed); + + /* Initialize standard clocks for unknown DAC. */ + if ((!(cardspecs->flags & CLOCK_PROGRAMMABLE)) + && cardspecs->nClocks == 0) { + /* + * Almost all cards have 25 and 28 MHz on VGA clocks 0 and 1, + * so use these for an unknown DAC, yielding 640x480x256. + */ + cardspecs->nClocks = 2; + cardspecs->clocks = malloc(sizeof(int) * 2); + cardspecs->clocks[0] = 25175; + cardspecs->clocks[1] = 28322; + } + /* Limit pixel clocks according to chip specifications. */ + if (s3_chiptype == S3_864 || s3_chiptype == S3_868) { + /* Limit max clocks according to 95 MHz DCLK spec. */ + /* SL: might just be 95000 for 4/8bpp since no pixmux'ing */ + LIMIT(cardspecs->maxPixelClock4bpp, 95000 * 2); + LIMIT(cardspecs->maxPixelClock8bpp, 95000 * 2); + LIMIT(cardspecs->maxPixelClock16bpp, 95000); + /* see explanation below */ + LIMIT(cardspecs->maxPixelClock24bpp, 36000); + /* + * The official 32bpp limit is 47500, but we allow + * 50 MHz for VESA 800x600 timing (actually the + * S3-864 doesn't have the horizontal timing range + * to run unmodified VESA 800x600 72 Hz timings). + */ + LIMIT(cardspecs->maxPixelClock32bpp, 50000); + } +#ifndef S3_16_COLORS + cardspecs->maxPixelClock4bpp = 0; /* 16-color doesn't work. */ +#endif + +/* end: Initialize cardspecs. */ + + __svgalib_driverspecs = &__svgalib_s3_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; +#ifdef S3_LINEAR_SUPPORT + __svgalib_linear_mem_base=s3_linear_base; + __svgalib_linear_mem_size=s3_memory*0x400; +#endif + + return 0; +} diff --git a/src/drivers/savage.c b/src/drivers/savage.c new file mode 100644 index 0000000..41f10f5 --- /dev/null +++ b/src/drivers/savage.c @@ -0,0 +1,1420 @@ +/* +Savage chipset driver + +Written by Matan Ziv-Av (matan@svgalib.org) + +Based on XFree 3.3.6 driver by S. Marineau and Tim Roberts. +And XFree 4.1.0 driver by Kevin Brosius. + +*/ + +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "endianess.h" +#include "vgammvgaio.h" + +#define SAVAGEREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define TOTAL_REGS (VGA_TOTAL_REGS + 96) + +typedef struct { + + unsigned char SR08, SR0A, SR0E, SR0F, SR10, SR11, SR12, SR13; + unsigned char SR15, SR18, SR1B, SR29, SR30; + unsigned char SR54[8]; + unsigned char Clock; +// unsigned char s3DacRegs[0x101]; + unsigned char CR31, CR32, CR33, CR34, CR36, CR3A, CR3B, CR3C; + unsigned char CR40, CR41, CR42, CR43, CR45; + unsigned char CR50, CR51, CR53, CR54, CR55, CR58, CR5B, CR5D, CR5E; + unsigned char CR60, CR63, CR65, CR66, CR67, CR68, CR69, CR6D, CR6F; + unsigned char CR7B, CR7D; + unsigned char CR85, CR86, CR87, CR88; + unsigned char CR90, CR91, CR92, CR93, CRB0; +} vgaS3VRec, *vgaS3VPtr; + +#define S3_CR(n) (VGA_TOTAL_REGS + (0x##n) - 0x30) + +#define S3_CR30 S3_CR(30) +#define S3_CR31 S3_CR(31) +#define S3_CR32 S3_CR(32) +#define S3_CR33 S3_CR(33) +#define S3_CR34 S3_CR(34) +#define S3_CR35 S3_CR(35) +#define S3_CR3A S3_CR(3A) +#define S3_CR3B S3_CR(3B) +#define S3_CR3C S3_CR(3C) +#define S3_CR40 S3_CR(40) +#define S3_CR42 S3_CR(42) +#define S3_CR43 S3_CR(43) +#define S3_CR44 S3_CR(44) +#define S3_CR50 S3_CR(50) /* 801+ */ +#define S3_CR51 S3_CR(51) +#define S3_CR53 S3_CR(53) +#define S3_CR54 S3_CR(54) +#define S3_CR55 S3_CR(55) +#define S3_CR58 S3_CR(58) +#define S3_CR59 S3_CR(59) +#define S3_CR5A S3_CR(5A) +#define S3_CR5D S3_CR(5D) +#define S3_CR5E S3_CR(5E) +#define S3_CR60 S3_CR(60) +#define S3_CR61 S3_CR(61) +#define S3_CR62 S3_CR(62) +#define S3_CR67 S3_CR(67) +#define S3_CR6A S3_CR(6A) +#define S3_CR6D S3_CR(6D) + +/* For debugging, these (non-)registers are read also (but never written). */ + +#define S3_CR36 S3_CR(36) +#define S3_CR37 S3_CR(37) +#define S3_CR38 S3_CR(38) +#define S3_CR39 S3_CR(39) +#define S3_CR3D S3_CR(3D) +#define S3_CR3E S3_CR(3E) +#define S3_CR3F S3_CR(3F) +#define S3_CR45 S3_CR(45) +#define S3_CR46 S3_CR(46) +#define S3_CR47 S3_CR(47) +#define S3_CR48 S3_CR(48) +#define S3_CR49 S3_CR(49) +#define S3_CR4A S3_CR(4A) +#define S3_CR4B S3_CR(4B) +#define S3_CR4C S3_CR(4C) +#define S3_CR4D S3_CR(4D) +#define S3_CR4E S3_CR(4E) +#define S3_CR4F S3_CR(4F) +#define S3_CR52 S3_CR(52) +#define S3_CR56 S3_CR(56) +#define S3_CR57 S3_CR(57) +#define S3_CR5B S3_CR(5B) +#define S3_CR5C S3_CR(5C) +#define S3_CR5F S3_CR(5F) +#define S3_CR63 S3_CR(63) +#define S3_CR64 S3_CR(64) +#define S3_CR65 S3_CR(65) +#define S3_CR66 S3_CR(66) +#define S3_CR6E S3_CR(6E) +#define S3_CR6F S3_CR(6F) + +/* Trio extended SR registers */ + +#define S3_SR(n) (S3_CR6F + 1 + (0x##n) - 0x08) + +#define S3_SR08 S3_SR(08) +#define S3_SR09 S3_SR(09) +#define S3_SR0A S3_SR(0A) +#define S3_SR0D S3_SR(0D) +#define S3_SR10 S3_SR(10) +#define S3_SR11 S3_SR(11) +#define S3_SR12 S3_SR(12) +#define S3_SR13 S3_SR(13) +#define S3_SR15 S3_SR(15) +#define S3_SR18 S3_SR(18) +#define S3_SR1D S3_SR(1D) + + +static int init(int, int, int); +static void unlock(void); +static void lock(void); + +enum { UNKNOWN, TRIO64, TRIO3D, TRIO3D2X, + VIRGE, VIRGEVX, VIRGEDX, VIRGEGX2, VIRGEMX, + SAVAGE3D, SAVAGEMX, SAVAGE4, PROSAVAGE, SUPERSAVAGE, SAVAGE2000 }; + +#define SAVAGE3D_SERIES(chip) ((chip==SAVAGE3D) || (chip==SAVAGEMX)) +#define SAVAGE4_SERIES(chip) ((chip==SAVAGE4) || (chip==PROSAVAGE)) +#define SAVAGE_MOBILE_SERIES(chip) ((chip==SAVAGEMX) || (chip==SUPERSAVAGE)) +#define ViRGE_GX2_SERIES(chip) (chip == VIRGEGX2 || chip == TRIO3D2X) +#define ViRGE_MX_SERIES(chip) (chip == VIRGEMX) +#define TRIO_3D_SERIES(chip) (chip == TRIO3D) +#define TRIO_3D_2X_SERIES(chip) (chip == TRIO3D2X) + +static int memory, chipset, is_linear; +static unsigned int linear_base; +static int is_savage; +static int cr58; + +static CardSpecs *cardspecs; + +static void setpage(int page) +{ + __svgalib_outcrtc(0x6a, page); +} + +static int inlinearmode(void) +{ +return is_linear; +} + +/* Fill in chipset specific mode information */ + +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int saveregs(unsigned char regs[]) +{ + + if(is_savage) { + unsigned char cr3a, cr66; + vgaS3VPtr save = (vgaS3VPtr)(regs+VGA_TOTAL_REGS); + unlock(); + + cr66 = __svgalib_incrtc(0x66); + __svgalib_outcrtc(0x66, cr66 | 0x80); + cr3a = __svgalib_incrtc(0x3a); + __svgalib_outcrtc(0x3a, cr3a | 0x80); + + cr66 = __svgalib_incrtc(0x66); + __svgalib_outcrtc(0x66, cr66 | 0x80); + cr3a = __svgalib_incrtc(0x3a); + __svgalib_outcrtc(0x3a, cr3a | 0x80); + + __svgalib_outcrtc(0x66, cr66); + __svgalib_outcrtc(0x3a, cr3a); + __svgalib_outcrtc(0x66, cr66); + __svgalib_outcrtc(0x3a, cr3a); + + /* First unlock extended sequencer regs */ + save->SR08 = __svgalib_inseq(0x08); + __svgalib_outseq(0x08, 0x06); + + /* Now we save all the s3 extended regs we need */ + save->CR31 = __svgalib_incrtc(0x31); + save->CR32 = __svgalib_incrtc(0x32); + save->CR34 = __svgalib_incrtc(0x34); + save->CR36 = __svgalib_incrtc(0x36); + save->CR3A = __svgalib_incrtc(0x3a); + + save->CR40 = __svgalib_incrtc(0x40); + save->CR42 = __svgalib_incrtc(0x42); + save->CR45 = __svgalib_incrtc(0x45); + + save->CR50 = __svgalib_incrtc(0x50); + save->CR51 = __svgalib_incrtc(0x51); + save->CR53 = __svgalib_incrtc(0x53); + save->CR58 = __svgalib_incrtc(0x58); + + save->CR60 = __svgalib_incrtc(0x60); + save->CR66 = __svgalib_incrtc(0x66); + save->CR67 = __svgalib_incrtc(0x67); + save->CR68 = __svgalib_incrtc(0x68); + save->CR69 = __svgalib_incrtc(0x69); + save->CR6F = __svgalib_incrtc(0x6f); + + save->CR33 = __svgalib_incrtc(0x33); + + save->CR86 = __svgalib_incrtc(0x86); + + save->CR88 = __svgalib_incrtc(0x88); + save->CR90 = __svgalib_incrtc(0x90); + save->CR91 = __svgalib_incrtc(0x91); + save->CRB0 = __svgalib_incrtc(0xb0) | 0x80; + + save->CR3B = __svgalib_incrtc(0x3b); + save->CR3C = __svgalib_incrtc(0x3c); + save->CR43 = __svgalib_incrtc(0x43); + save->CR5D = __svgalib_incrtc(0x5d); + save->CR5E = __svgalib_incrtc(0x5e); + save->CR65 = __svgalib_incrtc(0x65); + + /* Save sequencer extended regs for DCLK PLL programming */ + save->SR0E = __svgalib_inseq(0x0E); + save->SR0F = __svgalib_inseq(0x0F); + save->SR10 = __svgalib_inseq(0x10); + save->SR11 = __svgalib_inseq(0x11); + save->SR12 = __svgalib_inseq(0x12); + save->SR13 = __svgalib_inseq(0x13); + + save->SR29 = __svgalib_inseq(0x29); + + save->SR15 = __svgalib_inseq(0x15); + + save->SR30 = __svgalib_inseq(0x30); + + save->SR18 = __svgalib_inseq(0x18); + + save->SR1B = __svgalib_inseq(0x1B); + + if(SAVAGE_MOBILE_SERIES(chipset)) { + int i; + for( i = 0; i < 8; i++ ) { + save->SR54[i] = __svgalib_inseq(0x54+i); + } + } else { + + } + + __svgalib_outcrtc(0x3a, cr3a); + __svgalib_outcrtc(0x66, cr66); + } else { + unsigned char cr38, cr39, cr40; + int i; + + cr38=__svgalib_incrtc(0x38); + __svgalib_outcrtc(0x38, 0x48); + cr39=__svgalib_incrtc(0x39); + __svgalib_outcrtc(0x39, 0xa5); + cr40=__svgalib_incrtc(0x40); + __svgalib_outcrtc(0x40, cr40|1); + for(i=0x30;i<0x70;i++) regs[VGA_TOTAL_REGS - 0x30 + i]=__svgalib_incrtc(i); + regs[VGA_TOTAL_REGS+0x40]=__svgalib_inseq(0x08); + __svgalib_outseq(0x08, 0x06); + for(i=0x08;i<0x19;i++)regs[VGA_TOTAL_REGS+0x38+i]=__svgalib_inseq(i); + __svgalib_outseq(0x08, regs[VGA_TOTAL_REGS+0x40]); + __svgalib_outcrtc(0x40, regs[VGA_TOTAL_REGS - 0x30 + 0x40] = cr40); + __svgalib_outcrtc(0x39, regs[VGA_TOTAL_REGS - 0x30 + 0x39] = cr39); + __svgalib_outcrtc(0x39, regs[VGA_TOTAL_REGS - 0x30 + 0x38] = cr38); + } + + return TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + int tmp; + vgaS3VPtr restore = (vgaS3VPtr)(regs+VGA_TOTAL_REGS); + + + if(is_savage) { + + unlock(); + __svgalib_outseq(0x08, 0x06); + + /* As per databook, always disable STREAMS before changing modes */ + __svgalib_outcrtc(0x67, __svgalib_incrtc(0x67)&0xf3); + + __svgalib_outcrtc(0x66, restore->CR66); + __svgalib_outcrtc(0x3a, restore->CR3A); + __svgalib_outcrtc(0x31, restore->CR31); + __svgalib_outcrtc(0x32, restore->CR32); + __svgalib_outcrtc(0x58, restore->CR58); + + __svgalib_outcrtc(0x53, restore->CR53 & 0x7f); + + __svgalib_outseq(0x08, 0x06); + + __svgalib_outseq(0x0e, restore->SR0E); + __svgalib_outseq(0x0f, restore->SR0F); + __svgalib_outseq(0x29, restore->SR29); + __svgalib_outseq(0x15, restore->SR15); + + if(SAVAGE_MOBILE_SERIES(chipset)) { + int i; + for( i = 0; i < 8; i++ ) { + __svgalib_outseq( 0x54+i, restore->SR54[i]); + } + } + + __svgalib_outcrtc(0x53, restore->CR53); + __svgalib_outcrtc(0x5d, restore->CR5D); + __svgalib_outcrtc(0x5e, restore->CR5E); + __svgalib_outcrtc(0x3b, restore->CR3B); + __svgalib_outcrtc(0x3c, restore->CR3C); + __svgalib_outcrtc(0x43, restore->CR43); + __svgalib_outcrtc(0x65, restore->CR65); + +/* + __svgalib_outcrtc(0x67, 0x50 | (__svgalib_incrtc(0x67)&0xf3)); + usleep(10000); +*/ + + __svgalib_outcrtc(0x67, restore->CR67&0xf3); + __svgalib_outcrtc(0x34, restore->CR34); + __svgalib_outcrtc(0x40, restore->CR40); + __svgalib_outcrtc(0x42, restore->CR42); + __svgalib_outcrtc(0x45, restore->CR45); + + __svgalib_outcrtc(0x50, restore->CR50); + __svgalib_outcrtc(0x51, restore->CR51); + + __svgalib_outcrtc(0x36, restore->CR36); + __svgalib_outcrtc(0x68, restore->CR68); + __svgalib_outcrtc(0x69, restore->CR69); + __svgalib_outcrtc(0x6f, restore->CR6F); + + __svgalib_outcrtc(0x33, restore->CR33); + __svgalib_outcrtc(0x86, restore->CR86); + __svgalib_outcrtc(0x88, restore->CR88); + __svgalib_outcrtc(0x90, restore->CR90); + __svgalib_outcrtc(0x91, restore->CR91); + if(chipset == SAVAGE4) __svgalib_outcrtc(0xb0, restore->CRB0); + __svgalib_outcrtc(0x32, restore->CR32); + + __svgalib_outseq(0x08, 0x06); + /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that + * we should leave the default SR10 and SR11 values there. + */ + + if (restore->SR10 != 255) { + __svgalib_outseq(0x10, restore->SR10); + __svgalib_outseq(0x11, restore->SR11); + } + + /* Restore extended sequencer regs for DCLK */ + __svgalib_outseq(0x0e, restore->SR0E); + __svgalib_outseq(0x0f, restore->SR0F); + __svgalib_outseq(0x12, restore->SR12); + __svgalib_outseq(0x13, restore->SR13); +// __svgalib_outseq(0x29, restore->SR29); + + __svgalib_outseq(0x18, restore->SR18); + + __svgalib_outseq(0x1B, restore->SR1B); + + tmp = __svgalib_inseq(0x15) & ~0x21; + __svgalib_outseq(0x15, tmp | 0x03); + __svgalib_outseq(0x15, tmp | 0x23); + __svgalib_outseq(0x15, tmp | 0x03); + __svgalib_outseq(0x15, restore->SR15); + + usleep(100); + +// __svgalib_outseq(0x30, restore->SR30); + + __svgalib_outseq(0x08, restore->SR08); + + /* Now write out CR67 in full, possibly starting STREAMS */ +/* + __svgalib_outcrtc(0x67, 0x50); + usleep(10000); +*/ + __svgalib_outcrtc(0x67, restore->CR67&0xf3); + + __svgalib_outcrtc(0x53, restore->CR53); + __svgalib_outcrtc(0x66, restore->CR66); + __svgalib_outcrtc(0x3a, restore->CR3A); + } else { + static unsigned char s3_regmask[] = { + 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x00, 0x00, /* CR30-CR37 */ + 0x00, 0x00, 0x3A, 0x3B, 0x3C, 0x00, 0x00, 0x00, /* CR38-CR3F */ + 0x00, 0x00, 0x42, 0x43, 0x44, 0x45, 0x00, 0x00, /* CR40-CR47 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR48-CR4F */ + 0x50, 0x51, 0x00, 0x00, 0x54, 0x55, 0x00, 0x00, /* CR50-CR57 */ + 0x58, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x5E, 0x00, /* CR58-CR5F */ + 0x60, 0x61, 0x62, 0x00, 0x00, 0x00, 0x66, 0x67, /* CR60-CR67 */ + 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00 /* CR68-CR6F */ + }; + int i; + + unlock(); + __svgalib_outcrtc(0x40, __svgalib_incrtc(0x40) | 0x01); + + for(i=0x30; i<0x70;i++)if(s3_regmask[i-0x30]) + __svgalib_outcrtc(i, regs[VGA_TOTAL_REGS+i-0x30]); + + __svgalib_outseq(0x15, regs[VGA_TOTAL_REGS+0x38 + 0x15]); + __svgalib_outseq(0x18, regs[VGA_TOTAL_REGS+0x38 + 0x18]); + __svgalib_outseq(0x12, regs[VGA_TOTAL_REGS+0x38 + 0x12]); + __svgalib_outseq(0x13, regs[VGA_TOTAL_REGS+0x38 + 0x13]); + i=__svgalib_inseq(0x15); + __svgalib_outseq(0x15, i & ~0x20); + __svgalib_outseq(0x15, i | 0x20); + __svgalib_outseq(0x15, i & ~0x20); + + } +} + + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if(modeinfo->bytesPerPixel==3) return 0; + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +/* Local, called by setmode(). */ +#define BASE_FREQ 14.31818 + +static void savageCalcClock(int freq, int min_m, int min_n1, int max_n1, int min_n2, int max_n2, + int freq_min, int freq_max, unsigned int *mdiv, unsigned int *ndiv, unsigned int *r) +{ + double ffreq, ffreq_min, ffreq_max; + double div, diff, best_diff; + unsigned int m; + unsigned char n1, n2; + unsigned char best_n1=16+2, best_n2=2, best_m=125+2; + + ffreq = freq / 1000.0 / BASE_FREQ; + ffreq_min = freq_min / 1000.0 / BASE_FREQ; + ffreq_max = freq_max / 1000.0 / BASE_FREQ; + + if (ffreq < ffreq_min / (1< ffreq_max / (1< 127+2) + continue; + div = (double)(m) / (double)(n1); + if ((div >= ffreq_min) && + (div <= ffreq_max)) { + diff = ffreq - div / (1<CR31 = 0x09; /* Enable 64k window */ + new->CR32 = 0x10; + new->CR33 = 0x08; + new->CR34 = 0x10; + new->CR43 = 0x00; + new->CR45 = 0x00; + new->CR53 = 0; + new->CR54 = 0x00; + new->CR58 = 0; + new->CR63 = 0x00; + new->CR65 = 0x00; + new->CR66 = 0x89; + new->CR67 = 0x00; + new->CR69 = 0; + + new->SR10 = 255; /* This is a reserved value, so we use as flag */ + new->SR11 = 255; + new->SR15 = 0x03 | 0x80; + new->SR18 = 0x00; + new->SR1B = 0; + + new->SR30 = __svgalib_inseq(0x30); + new->CR36 = __svgalib_incrtc(0x36); + new->CR3A = __svgalib_incrtc(0x3a) | 0x15 ; + new->CR40 = __svgalib_incrtc(0x40) & 0xfe ; + new->CR68 = __svgalib_incrtc(0x68); + new->CR6F = __svgalib_incrtc(0x6f); + new->CR86 = __svgalib_incrtc(0x86); + new->CR88 = __svgalib_incrtc(0x88); + new->CRB0 = __svgalib_incrtc(0xb0) | 0x80; + + dclk = modetiming->pixelClock; + + switch( modeinfo->colorBits ) { + case 8: + new->CR67 = 0x00; /* 8bpp, 1 pixel/clock */ + if(dclk >= clocklimits[chipset][0]) new->CR67 |= 0x10; + break; + case 15: + new->CR67 = 0x20; + if(dclk >= clocklimits[chipset][1]) new->CR67 |= 0x10; + break; + case 16: + new->CR67 = 0x40; + if(dclk >= clocklimits[chipset][1]) new->CR67 |= 0x10; + break; + case 24: + new->CR67 = 0xd0; + break; + } + + { + unsigned int m, n, r; + + savageCalcClock(dclk, 1, 1, cargs[chipset][0], cargs[chipset][1], + cargs[chipset][2], cargs[chipset][3], cargs[chipset][3]*2, + &m, &n, &r); + new->SR12 = (r << 6) | (n & 0x3F); + new->SR13 = m & 0xFF; + new->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; + } + + /* If we have an interlace mode, set the interlace bit. Note that mode + * vertical timings are already adjusted by the standard VGA code + */ + if (modetiming->flags & INTERLACED) { + new->CR42 = 0x20; /* Set interlace mode */ + } else { + new->CR42 = 0x00; + } + + /* Now we adjust registers for extended mode timings */ + /* This is taken without change from the accel/s3_virge code */ + + i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | + ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | + ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | + ((modetiming->CrtcHSyncStart & 0x800) >> 7); + + if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64) + i |= 0x08; /* add another 64 DCLKs to blank pulse width */ + + if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32) + i |= 0x20; /* add another 32 DCLKs to hsync pulse width */ + + j = ( moderegs[0] + ((i&0x01)<<8) + + moderegs[4] + ((i&0x10)<<4) + 1) / 2; + + if (j-(moderegs[4] + ((i&0x10)<<4)) < 4) { + if (moderegs[4] + ((i&0x10)<<4) + 4 <= moderegs[0]+ ((i&0x01)<<8)) + j = moderegs[4] + ((i&0x10)<<4) + 4; + else + j = moderegs[0]+ ((i&0x01)<<8) + 1; + } + + new->CR3B = j & 0xFF; + i |= (j & 0x100) >> 2; + new->CR3C = (moderegs[0] + ((i&0x01)<<8))/2; + + new->CR5D = i; + + new->CR5E = (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) | + (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 8) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40; + + width = modeinfo->lineWidth >> 3; + moderegs[19] = 0xFF & width; + new->CR51 = (0x300 & width) >> 4; /* Extension bits */ + + /* And finally, select clock source 2 for programmable PLL */ + moderegs[VGA_MISCOUTPUT] |= 0x0c; + + /* Set frame buffer description */ + if (modeinfo->colorBits <= 8) { + new->CR50 = 0; + } else { + if (modeinfo->colorBits <= 16) { + new->CR50 = 0x10; + } else { + new->CR50 = 0x30; + } + } + + if (modeinfo->width == 640) + new->CR50 |= 0x40; + else if (modeinfo->width == 800) + new->CR50 |= 0x80; + else if (modeinfo->width == 1024); + else if (modeinfo->width == 1152) + new->CR50 |= 0x01; + else if (modeinfo->width == 1280) + new->CR50 |= 0x41; + else if (modeinfo->width == 2048 && new->CR31 & 2); + else if (modeinfo->width == 1600) + new->CR50 |= 0x81; /* TODO: need to consider bpp=4 */ + else + new->CR50 |= 0xC1; /* default to use GlobalBD */ + + if(__svgalib_emulatepage || is_linear) new->CR58 |= 0x13; + } else { + cr58=0x13; + saveregs(moderegs); + moderegs[S3_CR66] |= 1; + + moderegs[VGA_SR0] = 0x03; + moderegs[VGA_CR13] = modeinfo->lineWidth >> 3; + moderegs[VGA_CR17] = 0xE3; + + if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 2048) + moderegs[S3_CR31] = 0x8F; + else + moderegs[S3_CR31] = 0x8D; + /* moderegs[S3_ENHANCEDMODE] |= 0x01; */ + /* Enable enhanced memory mode. */ + moderegs[S3_CR31] |= 0x04; + /* Enable banking via CR6A in linear mode. */ + moderegs[S3_CR31] |= 0x01; + moderegs[S3_CR32] = 0; + moderegs[S3_CR33] = 0x20; + moderegs[S3_CR34] = 0x10; /* 1024 */ + moderegs[S3_CR35] = 0; + /* Call cebank() here when setting registers. */ + moderegs[S3_CR3A] = 0xB5; + + moderegs[S3_CR3B] = (moderegs[VGA_CR0] + moderegs[VGA_CR4] + 1) / 2; + moderegs[S3_CR3C] = moderegs[VGA_CR0] / 2; + moderegs[S3_CR40] &= 0xF2; + /* Pegasus wants 0x01 for zero wait states. */ + moderegs[S3_CR40] |= 0x05; + + if (modeinfo->bitsPerPixel >= 15) { + moderegs[S3_CR43] = 0x09; + } else { + moderegs[S3_CR43] = 0x00; + } + + moderegs[S3_CR44] = 0; + /* Skip CR45, 'hi/truecolor cursor color enable'. */ + + { + /* XXXX Not all chips support all widths. */ + moderegs[S3_CR50] &= ~0xF1; + switch (modeinfo->bitsPerPixel) { + case 16: + moderegs[S3_CR50] |= 0x10; + break; + case 24: /* XXXX 868/968 only */ + moderegs[S3_CR50] |= 0x20; + break; + case 32: + moderegs[S3_CR50] |= 0x30; + break; + } + + switch (modeinfo->lineWidth / modeinfo->bytesPerPixel) { + case 640: + moderegs[S3_CR50] |= 0x40; + break; + case 800: + moderegs[S3_CR50] |= 0x80; + break; + case 1152: + case 1280: + moderegs[S3_CR50] |= 0xC0; + break; + case 1600: + moderegs[S3_CR50] |= 0x81; + break; + } + + moderegs[S3_CR51] &= 0xC0; + moderegs[S3_CR51] |= (modeinfo->lineWidth >> 7) & 0x30; + + moderegs[S3_CR55] &= 0x08; + moderegs[S3_CR55] |= 0x40; + + /* Extended CRTC timing. */ + moderegs[S3_CR5E] = + (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) | + (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 8) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40; + + { + int i, j; + i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | + ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | + ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | + ((modetiming->CrtcHSyncStart & 0x800) >> 7); + if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64) + i |= 0x08; + if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32) + i |= 0x20; + j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) + + moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2); + if (j - (moderegs[VGA_CR4] + ((i & 0x10) << 4)) < 4) { + if (moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4 <= moderegs[VGA_CR0] + ((i & 0x01) << 8)) + j = moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4; + else + j = moderegs[VGA_CR0] + ((i & 0x01) << 8) + 1; + } + + moderegs[S3_CR3B] = j & 0xFF; + i |= (j & 0x100) >> 2; + /* Interlace mode frame offset. */ + moderegs[S3_CR3C] = (moderegs[VGA_CR0] + ((i & 0x01) << 8)) / 2; + moderegs[S3_CR5D] = (moderegs[S3_CR5D] & 0x80) | i; + } + + { + int i; + + if (modeinfo->bitsPerPixel < 8) + i = modetiming->HDisplay / 4 + 1; + else + i = modetiming->HDisplay * + modeinfo->bytesPerPixel / 4 + 1; + + moderegs[S3_CR61] = (i >> 8) | 0x80; + moderegs[S3_CR62] = i & 0xFF; + } + } /* 801+ */ + if (modetiming->flags & INTERLACED) + moderegs[S3_CR42] |= 0x20; + + moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */ + { + moderegs[S3_CR33] &= ~0x08; + if (modeinfo->bitsPerPixel == 16) + moderegs[S3_CR33] |= 0x08; + } + + dclk = modetiming->pixelClock; + moderegs[S3_SR15] &= ~0x50; + moderegs[S3_SR18] &= ~0x80; + + switch( modeinfo->colorBits ) { + case 8: + moderegs[S3_CR67] = 0x00; /* 8bpp, 1 pixel/clock */ + if(dclk >= clocklimits[chipset][0]) { + moderegs[S3_CR67] |= 0x10; + moderegs[S3_SR15] |= 0x50; + moderegs[S3_SR18] |= 0x80; + } + break; + case 15: + moderegs[S3_CR67] = 0x20; +// if(dclk >= clocklimits[chipset][1]) + moderegs[S3_CR67] |= 0x12; + break; + case 16: + moderegs[S3_CR67] = 0x40; +// if(dclk >= clocklimits[chipset][1]) + moderegs[S3_CR67] |= 0x12; + break; + case 24: + moderegs[S3_CR67] = 0xd2; + break; + } + + { + unsigned int m, n, r; + + savageCalcClock(dclk, 1, 1, cargs[chipset][0], cargs[chipset][1], + cargs[chipset][2], cargs[chipset][3], cargs[chipset][3]*2, + &m, &n, &r); + moderegs[S3_SR12] = (r << 5) | (n & 0x1F); + moderegs[S3_SR13] = m & 0xFF; +// moderegs[S3_SR29] = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; + } + { + int clock, mclk, n, m; + n = 0xFF; + clock = modetiming->pixelClock * modeinfo->bytesPerPixel; + if (memory < 2048 ) clock *= 2; + mclk = 60000; /* Assumption. */ + m = (int) ((mclk / 1000.0 * .72 + 16.867) * 89.736 / (clock / 1000.0 + 39) - 21.1543); + if (memory < 2048) m /= 2; + if (m > 31) m = 31; + else if (m < 0) { + m = 0; + n = 16; + } + + moderegs[S3_CR54] = m << 3; + moderegs[S3_CR60] = n; + } + + } + + return ; +} + + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + __svgalib_outcrtc(0x34, 0); + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + __svgalib_outcrtc(0x38, 0x48); + __svgalib_outcrtc(0x39, 0xa5); +// __svgalib_outcrtc(0x40,__svgalib_incrtc(0x40)&0xfe); +} + +static void lock(void) +{ +} + + +#define VENDOR_ID 0x5333 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + int found; + int id; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + id=(buf[0]>>16)&0xffff; + if(!found)return 0; + switch(id) { + case 0x8811: + case 0x8903: + case 0x8904: + case 0x8a13: + case 0x5631: + case 0x883d: + case 0x8a01: + case 0x8a10: + case 0x8c00: + case 0x8c01: + case 0x8c02: + case 0x8c03: + case 0x8a20: + case 0x8a21: + case 0x8a22: + case 0x8a23: + case 0x8a25: + case 0x8a26: + case 0x8c10: + case 0x8c12: + case 0x9102: + case 0x8d01: + case 0x8d02: + case 0x8d03: + case 0x8d04: + return !init(0,0,0); + default: + return 0; + } +} + + +/* Set display start address (not for 16 color modes) */ + +static void setdisplaystart(int address) +{ + address=address >> 2; + __svgalib_outcrtc(0x0d,address&0xff); + __svgalib_outcrtc(0x0c,(address>>8)&0xff); + __svgalib_outcrtc(0x69,(address>>16)&0xff); + +} + +/* Set logical scanline length (usually multiple of 8) */ + +static void setlogicalwidth(int width) +{ + int offset = width >> 3; + + __svgalib_outcrtc(0x13,offset&0xff); +} + +static int linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ + __svgalib_outcrtc(0x58,__svgalib_incrtc(0x58)|cr58); + is_linear=1; + return 0; + }; + if (op==LINEAR_DISABLE) { + __svgalib_outcrtc(0x58,__svgalib_incrtc(0x58)&~cr58); + is_linear=0; + return 0; + }; + if (op==LINEAR_QUERY_BASE) return linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ + else return -1; /* Unknown function. */ +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} + +static int map_clock(int bpp, int clock) +{ +return clock ; +} + +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + if (bpp == 16 && !is_savage) return htiming * 2; + + return htiming; +} + +static struct { + unsigned char c8; + unsigned short c15; + unsigned short c16; + unsigned int c32; +} cursor_colors[16*2]; + +static int pal=1, palette[768]; + +static int findcolor(int rgb) { + int i,j,k,l=0; + + if(pal)vga_getpalvec(0,256,palette); + pal=0; + k=0xffffff; + for(i=0;i<256;i++) { + j=((rgb&0xff)-(palette[i*3+2]<<2))*((rgb&0xff)-(palette[i*3+2]<<2))+ + (((rgb>>8)&0xff)-(palette[i*3+1]<<2))*(((rgb>>8)&0xff)-(palette[i*3+1]<<2))+ + (((rgb>>16)&0xff)-(palette[i*3]<<2))*(((rgb>>16)&0xff)-(palette[i*3]<<2)); + if(j==0) { + return i; + } + if(j>8); + __svgalib_outcrtc(0x47,p1&0xff); + __svgalib_outcrtc(0x49,p2&0xff); + __svgalib_outcrtc(0x4e,0); + __svgalib_outcrtc(0x4f,0); + __svgalib_outcrtc(0x48,p2>>8); + break; + case CURSOR_SELECT: + i=memory-(16-p1); + switch(CI.colors) { + case 256: + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c8); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c8); + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c8); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c8); + break; + case 32768: + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15&0xff); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15>>8); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15&0xff); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15>>8); + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15&0xff); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15>>8); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15&0xff); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15>>8); + break; + case 65536: + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16&0xff); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16>>8); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16&0xff); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16>>8); + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16&0xff); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16>>8); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16&0xff); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16>>8); + break; + case (1<<24): + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c32&0xff); + __svgalib_outcrtc(0x4b,(cursor_colors[p1*2].c32>>8)&0xff); + __svgalib_outcrtc(0x4b,(cursor_colors[p1*2].c32>>16)&0xff); + __svgalib_incrtc(0x45); + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c32&0xff); + __svgalib_outcrtc(0x4a,(cursor_colors[p1*2+1].c32>>8)&0xff); + __svgalib_outcrtc(0x4a,(cursor_colors[p1*2+1].c32>>16)&0xff); + break; + } + __svgalib_outcrtc(0x4d, i&0xff); + __svgalib_outcrtc(0x4c, i>>8); + break; + case CURSOR_IMAGE: + buf=malloc(1024); + cursor_colors[p1*2].c8=findcolor(p3); + cursor_colors[p1*2].c32=p3; + cursor_colors[p1*2].c16=((p3&0xf80000)>>8)|((p3&0xfc00)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2].c15=((p3&0xf80000)>>9)|((p3&0xf800)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2+1].c8=findcolor(p4); + cursor_colors[p1*2+1].c32=p4; + cursor_colors[p1*2+1].c16=((p4&0xf80000)>>8)|((p4&0xfc00)>>5)|((p4&0xf8)>>3); + cursor_colors[p1*2+1].c15=((p4&0xf80000)>>9)|((p4&0xf800)>>5)|((p4&0xf8)>>3); + i=memory*1024-(16-p1)*1024; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + for(j=0;j<32;j++) { + l2=*(b3+j); + l1=*(b3+32+j); + l1=BE32(l1); + l2=BE32(l2); + l2=l2&l1; + l1=~l1; + *(unsigned short *)(buf+16*j)=l1&0xffff; + *(unsigned short *)(buf+16*j+2)=l2&0xffff; + *(unsigned short *)(buf+16*j+4)=(l1>>16)&0xffff; + *(unsigned short *)(buf+16*j+6)=(l2>>16)&0xffff; + *(unsigned short *)(buf+16*j+8)=0xffff; + *(unsigned short *)(buf+16*j+10)=0; + *(unsigned short *)(buf+16*j+12)=0xffff; + *(unsigned short *)(buf+16*j+14)=0; + } + for(j=32;j<64;j++) { + *(unsigned short *)(buf+16*j)=0xffff; + *(unsigned short *)(buf+16*j+2)=0; + *(unsigned short *)(buf+16*j+4)=0xffff; + *(unsigned short *)(buf+16*j+6)=0; + *(unsigned short *)(buf+16*j+8)=0xffff; + *(unsigned short *)(buf+16*j+10)=0; + *(unsigned short *)(buf+16*j+12)=0xffff; + *(unsigned short *)(buf+16*j+14)=0; + } + break; + } + vga_drawscansegment(buf, i/CI.bytesperpixel,0,1024); + break; + } + return 0; +} + +/* Function table (exported) */ +DriverSpecs __svgalib_savage_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + setpage, + NULL, + NULL, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + cursor, +}; + +/* Initialize chipset (called after detection) */ + +static int init(int force, int par1, int par2) +{ + unsigned int buf[64]; + unsigned int mmio_base; + int found=0, config1; + int mems[8]={2,4,8,12,16,32,64,2}; + char *chipnames[] = {"Unknown", "Trio64", "Trio 3D", "Trio 3d/2X", "Virge", "Virge VX", + "Virge DX", "Virge GX2", "Virge MX", + "Savage3D", "SavageMX", "Savage4", "ProSavage", "SuperSavage", "savage2000"}; + int vmems[9][8]= { {0}, + {0,0,0,1,2,0,1,0}, + {4,0,4,0,2,0,0,0}, + {4,0,4,0,0,0,2,0}, + {4,0,0,0,2,0,1,0}, + {2,4,6,8,2,4,6,8}, + {4,0,0,0,2,0,1,0}, + {0,0,4,4,0,0,2,2}, + {0,0,4,4,0,0,2,2} + }; + int id; + + if (force) { + memory = par1; + chipset = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + id=(buf[0]>>16)&0xffff; + + switch(id) { + case 0x8811: + chipset = TRIO64; + break; + case 0x8903: + case 0x8904: + chipset = TRIO3D; + break; + case 0x8a13: + chipset = TRIO3D2X; + break; + case 0x5631: + chipset = VIRGE; + break; + case 0x883d: + chipset = VIRGEVX; + break; + case 0x8a01: + chipset = VIRGEDX; + break; + case 0x8a10: + chipset = VIRGEGX2; + break; + case 0x8c00: + case 0x8c01: + case 0x8c02: + case 0x8c03: + chipset = VIRGEMX; + break; + case 0x8a20: + case 0x8a21: + chipset = SAVAGE3D; + break; + case 0x8a22: + case 0x8a23: + chipset = SAVAGE4; + break; + case 0x9102: + chipset = SAVAGE2000; + break; + case 0x8c10: + case 0x8c11: + case 0x8c12: + case 0x8c13: + chipset = SAVAGEMX; + break; + case 0x8a25: + case 0x8a26: + case 0x8d01: + case 0x8d02: + case 0x8d03: + case 0x8d04: + chipset = PROSAVAGE; + break; + case 0x8c22: + case 0x8c24: + case 0x8c26: + case 0x8c2a: + case 0x8c2b: + case 0x8c2c: + case 0x8c2d: + case 0x8c2e: + case 0x8c2f: + chipset = SUPERSAVAGE; + default: + chipset = UNKNOWN; + } + + is_savage=(chipset>=SAVAGE3D); + + if(!is_savage) { + linear_base=buf[4]&0xffffff00; + mmio_base = linear_base + 0x1000000; +#if 0 /* You need to write linear address to CR59 5A, and enable MMIO in CR53 - + But how to do it if it's a secondary card??? */ + if(__svgalib_secondary) { + __svgalib_mmio_base = mmio_base; + __svgalib_mmio_size = 0x10000; + map_mmio(); + __svgalib_vgammbase=0x8000; + __svgalib_mm_io_mapio(); + } +#endif + unlock(); + config1=__svgalib_incrtc(0x36); + memory = 1024 * vmems[chipset][(config1&0xe0)>>5]; + } else { + linear_base=buf[5]&0xffffff00; + mmio_base =buf[4]&0xffffff00; + __svgalib_mmio_base = mmio_base; + __svgalib_mmio_size = 0x10000; + map_mmio(); + + __svgalib_vgammbase=0x8000; + __svgalib_mm_io_mapio(); + unlock(); + + config1=__svgalib_incrtc(0x36); + if(chipset >= SAVAGE4) { + memory=mems[config1>>5]*1024; + } else { + switch(config1>>6) { + case 0: + memory=8192; + break; + case 0x40: + case 0x80: + memory=4096; + break; + case 0xC0: + memory=2048; + break; + } + } + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using SAVAGE driver, %iKB. Chipset: %s\n",memory, chipnames[chipset]); + }; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = 250000; + cardspecs->maxPixelClock16bpp = 250000; + cardspecs->maxPixelClock24bpp = 220000; + cardspecs->maxPixelClock32bpp = 220000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->nClocks = 0; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_savage_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=memory*0x400; + return 0; +} diff --git a/src/drivers/sis.c b/src/drivers/sis.c new file mode 100644 index 0000000..e8e7ab5 --- /dev/null +++ b/src/drivers/sis.c @@ -0,0 +1,1439 @@ +/* +SIS chipset driver + +Matan Ziv-Av + +Fixes for 530 and for vesafb by Marcelo de Paula Bezerra +. + +This driver is based on the XFree86 sis driver, written by + + Alan Hourihane + +and modified by + Xavier Ducoin, + Mike Chapman, + Juanjo Santamarta, + Mitani Hiroshi, + David Thomas, + Thomas Winischhofer. + +And on the documentation availbale from sis's web pages (not many +chipset companies still do this). + +*/ + +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "vgarelvgaio.h" + +#define SISREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define SIS_TOTAL_REGS (VGA_TOTAL_REGS + 64 + 40 + 20) + +#define XR(i) (VGA_TOTAL_REGS+i-5) +#define CR(i) (VGA_TOTAL_REGS+i+0x28) + +#define PCI_CHIP_SG86C201 0x0001 +#define PCI_CHIP_SG86C202 0x0002 +#define PCI_CHIP_SG86C205 0x0205 +#define PCI_CHIP_SG86C215 0x0215 +#define PCI_CHIP_SG86C225 0x0225 +#define PCI_CHIP_SIS5597 0x0200 +#define PCI_CHIP_SIS6326 0x6326 +#define PCI_CHIP_SIS530 0x6306 + +#define PCI_CHIP_SIS300 0x0300 +#define PCI_CHIP_SIS540 0x5300 +#define PCI_CHIP_SIS630 0x6300 +#define PCI_CHIP_SIS730 0x7300 + +#define PCI_CHIP_SIS315H 0x0310 +#define PCI_CHIP_SIS315 0x0315 +#define PCI_CHIP_SIS315PRO 0x0325 +#define PCI_CHIP_SIS550 0x5315 +#define PCI_CHIP_SIS650 0x6325 + +#define ClockReg XR(0x07) +#define DualBanks XR(0x0B) +#define BankReg XR(0x06) +#define CRTCOff XR(0x0A) +#define DispCRT XR(0x27) +#define Unknown XR(0x08) +#define LinearAddr0 XR(0x20) +#define LinearAddr1 XR(0x21) + +enum { SIS_OLD=1, SIS_5597, SIS_6326, SIS_530, SIS_300, SIS_315 }; + +#define write_xr(num,val) {__svgalib_outseq(num,val);} +#define read_xr(num,var) {var=__svgalib_inseq(num);} +#define in_xr(num) __svgalib_inseq(num) + +static int sis_init(int, int, int); +static void sis_unlock(void); +static void sis_lock(void); +static void sisClockLoad(int, unsigned char *); +static void sis_CPUthreshold(int,int,int *,int *); +static int compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div, int *out_sbit, int *out_scale); + +static int sis_memory, sis_is_linear, chip; +static unsigned int sis_linear_base; + +static int sis_edo_vram = 0, sis_host_bus = 0, sis_fast_vram = 0, + sis_pci_burst_on = 0, sis_pci_burst_off = 0; + +static CardSpecs *cardspecs; + +static void sis_setpage(int page) +{ + port_out_r(0x3cb+__svgalib_io_reloc,page); + port_out_r(0x3cd+__svgalib_io_reloc,page); +} + +static void sis_300_setpage(int page) +{ + port_out_r(0x3cb+__svgalib_io_reloc,((page>>4)&0x0f) | (page&0xf0)); + port_out_r(0x3cd+__svgalib_io_reloc,(page&0x0f) | ((page&0x0f)<<4)); +} + +/* Fill in chipset specific mode information */ + +static void sis_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = sis_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 8192; + modeinfo->startaddressrange = sis_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(sis_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int sis_saveregs(unsigned char regs[]) +{ + int i; + int max=0x37; + + switch(chip) { + case SIS_5597: + max=0x39; + break; + case SIS_6326: + case SIS_530: + max=0x3f; + break; + case SIS_300: + case SIS_315: + max=0x3d; + break; + } + + sis_unlock(); + + for(i=6; i<=max;i++)read_xr(i,regs[XR(i)]); + + if(chip>=SIS_300) { + int tmp; + for(i=0x19; i<0x40;i++)regs[CR(i)]=__svgalib_incrtc(i); + read_xr(0x20,tmp); + write_xr(0x20,tmp|0x01); + *(uint32_t *)(regs+CR(0x40))=v_readl(0x8500 + 0); + *(uint32_t *)(regs+CR(0x44))=v_readl(0x8500 + 4); + *(uint32_t *)(regs+CR(0x48))=v_readl(0x8500 + 8); + *(uint32_t *)(regs+CR(0x4c))=v_readl(0x8500 + 12); + *(uint32_t *)(regs+CR(0x50))=v_readl(0x8500 + 16); + write_xr(0x20,tmp); + } + + return SIS_TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void sis_setregs(const unsigned char regs[], int mode) +{ + int i; + int max=0x37; + + switch(chip) { + case SIS_5597: + max=0x39; + break; + case SIS_6326: + case SIS_530: + max=0x3f; + break; + case SIS_300: + case SIS_315: + max=0x3d; + break; + } + + sis_unlock(); + + if(chip>=SIS_300) { + write_xr(0x20,in_xr(0x20)|0x01); + v_writel(*(uint32_t *)(regs+CR(0x40)), 0x8500 + 0); + v_writel(*(uint32_t *)(regs+CR(0x44)), 0x8500 + 4); + v_writel(*(uint32_t *)(regs+CR(0x48)), 0x8500 + 8); + v_writel(*(uint32_t *)(regs+CR(0x4c)), 0x8500 + 12); + v_writel(*(uint32_t *)(regs+CR(0x50)), 0x8500 + 16); + for(i=0x19; i<0x40;i++)__svgalib_outcrtc(i,regs[CR(i)]); + } + + for(i=6; i<=max; i++)write_xr(i,regs[XR(i)]); + +} + +/* Return nonzero if mode is available */ + +static int sis_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (sis_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if(modeinfo->bytesPerPixel==4-(chip>=SIS_300)){ + free(modeinfo); + return 0; + }; + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +/* Local, called by sis_setmode(). */ + +static void sis_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + int offset; + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + sis_saveregs(moderegs); + + sisClockLoad(modetiming->pixelClock,moderegs); + offset = modetiming->CrtcHDisplay >> + ((modetiming->flags & INTERLACED) ? 2 : 3); + + moderegs[VGA_CR14] = 0x40; + moderegs[VGA_CR17] = 0xA3; + + moderegs[ATT+0x10] = 0x01; /* mode */ + moderegs[ATT+0x11] = 0x00; /* overscan (border) color */ + moderegs[ATT+0x12] = 0x0F; /* enable all color planes */ + moderegs[ATT+0x13] = 0x00; /* horiz pixel panning 0 */ + + if ( (modeinfo->bitsPerPixel == 16) || (modeinfo->bitsPerPixel == 24) ) + moderegs[GRA+0x05] = 0x00; /* normal read/write mode */ + + if (modeinfo->bitsPerPixel == 16) { + offset <<= 1; /* double the width of the buffer */ + } else if (modeinfo->bitsPerPixel == 24) { + offset += offset << 1; + } + + moderegs[BankReg] = 0x02; + moderegs[DualBanks] = 0x00; + + if ( sis_is_linear || __svgalib_emulatepage) { + moderegs[BankReg] |= 0x80; /* enable linear mode addressing */ + moderegs[LinearAddr0] = (sis_linear_base & 0x07f80000) >> 19 ; + moderegs[LinearAddr1] = ((sis_linear_base & 0xf8000000) >> 27) | + (0x60) ; /* Enable Linear with max 4 mb*/ + } else moderegs[DualBanks] |= 0x08; + + if (modeinfo->bitsPerPixel == 16) { + if (modeinfo->greenWeight == 5) + moderegs[BankReg] |= 0x04; /* 16bpp = 5-5-5 */ + else + moderegs[BankReg] |= 0x08; /* 16bpp = 5-6-5 */ + } + + if (modeinfo->bitsPerPixel == 24) { + moderegs[BankReg] |= 0x10; + moderegs[DualBanks] |= 0x80; + } + + moderegs[0x13] = offset & 0xFF; + moderegs[CRTCOff] = ((offset & 0xF00) >> 4) | + (((modetiming->CrtcVTotal-2) & 0x400) >> 10 ) | + (((modetiming->CrtcVDisplay-1) & 0x400) >> 9 ) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 8 ) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 7 ) ; + + if (modetiming->flags & INTERLACED) + moderegs[BankReg] |= 0x20; + + if ((chip == SIS_5597) || + (chip == SIS_6326) || + (chip == SIS_530)) { + moderegs[XR(0x0C)] |= 0x20; /* readahead cache */ + moderegs[XR(0x07)] |= 0x80; /* combine FIFOs */ + } + + if((chip == SIS_530) || (chip==SIS_5597)) { + moderegs[XR(0x0c)] |= 0x80; /* 32 bit memory access */ + moderegs[XR(0x26)]&=0xfe; /* zero bit 20 of start address */ + }; + + /* makes SR27 d[3:1]=0; If yes, I believe this is the offset for the + scroll, or somthing like that... */ + moderegs[XR(0x27)]&=0xf0; + + { + int CRT_ENGthreshold,CRT_CPUthresholdLow, CRT_CPUthresholdHigh; + + CRT_ENGthreshold = 0x1F; + sis_CPUthreshold(modetiming->pixelClock, modeinfo->bitsPerPixel, + &CRT_CPUthresholdLow, &CRT_CPUthresholdHigh); + moderegs[XR(0x08)] = (CRT_ENGthreshold & 0x0F) | + (CRT_CPUthresholdLow & 0x0F)<<4 ; + moderegs[XR(0x09)] &= 0xF0; /* Yeou */ + moderegs[XR(0x09)] |= (CRT_CPUthresholdHigh & 0x0F); /* Yeou */ + + if (chip == SIS_530) { + /* CRT/CPU/Engine Threshold Bit[4] */ + moderegs[XR(0x3F)] &= 0xE3; + moderegs[XR(0x3F)] |= ((CRT_CPUthresholdHigh & 0x10) | + ((CRT_ENGthreshold & 0x10) >> 1) | + ((CRT_CPUthresholdLow & 0x10) >> 2)); + } + } + + + moderegs[59]=0x6f; + + moderegs[XR(0x1c)]=0; + moderegs[XR(0x1f)]=0; + + return ; +} + +static void sis_300_initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ + int offset; + int n, m, d, sb, sc; + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + sis_saveregs(moderegs); + + offset = modeinfo->lineWidth; + + moderegs[CR(0x19)] = 0; + moderegs[CR(0x1A)] &= 0x0fc; + + if(modetiming->flags & INTERLACED) { + offset>>=2; + moderegs[XR(0x06)] |= 0x20; + } else { + offset>>=3; + moderegs[XR(0x06)] &= ~0x20; + } + + switch(modeinfo->bytesPerPixel) { + case 1: + moderegs[XR(0x06)] |= (0<<2) | 3; + break; + case 2: + moderegs[XR(0x06)] |= ((modeinfo->greenWeight-4)<<2) | 3; + break; + case 3: + moderegs[XR(0x06)] |= (3<<2) | 3; + break; + case 4: + moderegs[XR(0x06)] |= (4<<2) | 3; + break; + } + + moderegs[XR(0x07)] |= 0x10; /* enable High Speed DAC */ + moderegs[XR(0x07)] &= 0xFC; + if (modetiming->pixelClock < 100000) + moderegs[XR(0x07)] |= 0x03; + else if (modetiming->pixelClock < 200000) + moderegs[XR(0x07)] |= 0x02; + else if (modetiming->pixelClock < 250000) + moderegs[XR(0x07)] |= 0x01; + + moderegs[XR(0x0a)] = + (((modetiming->CrtcVTotal-2) & 0x400) >> 10) | + (((modetiming->CrtcVDisplay-1) & 0x400) >> 9 ) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 8 ) | + (((modetiming->CrtcVSyncStart) & 0x400) >> 7 ) | + (((modetiming->CrtcVSyncEnd) & 0x100) >> 4 ) | + (((modetiming->CrtcVSyncEnd) & 0x010) << 1 ) ; + + moderegs[XR(0x0b)] = + ((((modetiming->CrtcHTotal>>3)-5) & 0x300) >> 8 ) | + ((((modetiming->CrtcHDisplay>>3)-1) & 0x300) >> 6 ) | + ((((modetiming->CrtcHSyncStart>>3)) & 0x300) >> 4 ) | + ((((modetiming->CrtcVSyncStart>>3)) & 0x300) >> 2 ) ; + + moderegs[XR(0x0c)] &= 0xf8; + moderegs[XR(0x0c)] = + ((((modetiming->CrtcHSyncEnd>>3)) & 0xc0) >> 6 ) | + ((((modetiming->CrtcHSyncEnd>>3)) & 0x20) >> 3 ) ; + + + moderegs[0x13] = offset & 0xFF; + moderegs[XR(0x0e)] &= 0xf0; + moderegs[XR(0x0e)] |= (offset&0xf00)>>8; + + moderegs[XR(0x0f)] |= 0x08; + + moderegs[XR(0x10)] = ((modeinfo->lineWidth+63) >> 6 ) + 1; + + moderegs[XR(0x20)] &= 0xa1; + moderegs[XR(0x20)] |= 0x80; /* Enable linear */ + moderegs[XR(0x20)] |= 0x01; /* Enable MMIO */ + + compute_vclk(modetiming->pixelClock, &n, &m, &d, &sb, &sc); + moderegs[XR(0x2b)] = ((n-1) & 0x7f) | ((d-1)<<7); + moderegs[XR(0x2c)] = ((m-1) & 0x1f) | (((sc-1)&3)<<5) | (sb ? 0x80:0); + moderegs[XR(0x2d)] = 0x80; + +/* + if(modetiming->pixelClock>150000) { + moderegs[XR(0x07)] |= 0x80; + moderegs[XR(0x32)] |= 0x08; + } else { + moderegs[XR(0x07)] &= ~0x80; + moderegs[XR(0x32)] &= ~0x08; + } +*/ + + moderegs[XR(0x21)] = 0xa5; /* What is this ??? */ + + moderegs[ATT + 0x10] = 1; + moderegs[ATT + 0x11] = 0; + moderegs[ATT + 0x12] = 0; + + moderegs[MIS] |= 0x0c; /* Use programmed clock */ + + return ; +} + + +static int sis_setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + int tmp; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + if(chip >= SIS_5597) { + /* Work Arrout for vesafb case */ + read_xr(0x06,tmp); + tmp&=~(0x1E); /* Depth registers */ + write_xr(0x06,tmp); + } + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!sis_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(SIS_TOTAL_REGS); + + if(chip>=SIS_300) + sis_300_initializemode(moderegs, modetiming, modeinfo, mode); else + sis_initializemode(moderegs, modetiming, modeinfo, mode); + + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + sis_setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void sis_unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + __svgalib_outseq(0x05,0x86); +} + +static void sis_lock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + __svgalib_outseq(0x05,0x0); +} + +#define VENDOR_ID 0x1039 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int sis_test(void) +{ + int found; + unsigned int buf[64]; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + + if(found&&( + (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C201)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C202)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C205)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C215)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C225)|| + + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS5597)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS6326)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS530)|| + + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS540)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS630)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS730)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS300)|| + + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS315H)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS315)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS315PRO)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS550)|| + (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS650)|| + 0)){ + return !sis_init(0,0,0); + }; + return 0; +} + + +/* Set display start address (not for 16 color modes) */ +static void sis_setdisplaystart(int address) +{ + int temp; + address=address >> 2; + __svgalib_outcrtc(0x0c,(address & 0x00FF00)>>8); + __svgalib_outcrtc(0x0d,address & 0x0000ff); + + if(chip>=SIS_300) { + write_xr(0x0d,(address&0xff0000)>>16); + } else { + read_xr(0x27,temp); + temp &= 0xf0; + temp |= (address&0xf0000)>>16; + write_xr(0x27,temp); + } +} + +/* Set logical scanline length (usually multiple of 8) */ +static void sis_setlogicalwidth(int width) +{ + int offset = width >> 3; + int temp; + + __svgalib_outcrtc(0x13,offset & 0xff); + + if(chip>=SIS_300) { + read_xr(0x0e,temp); + temp &= 0xf0; + temp |= (offset&0xf00)>>8; + write_xr(0x0e,temp); + } else { + read_xr(0x0a,temp); + temp &= 0xf; + temp |= (offset&0xf00)>>4; + write_xr(0x0a,temp); + } +} + +static int sis_linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ + int temp; + + sis_is_linear=1; + if(chip> 19) ; + write_xr(0x21,((sis_linear_base & 0xf8000000) >> 27) | + (0x60)) ; /* Enable Linear with max 4 mb*/ + write_xr(6,temp); + } + return 0; + }; + if (op==LINEAR_DISABLE && !__svgalib_emulatepage){ + int temp; + + sis_is_linear=0; + if(chip>8); + p2>>=1; + write_xr(0x1d,p2&0xff); + write_xr(0x1e,(in_xr(0x1e)&0xf8)|((p2>>8)&0x07)); + break; + case CURSOR_SELECT: +#if 1 + i=sis_memory*1024-(16-p1)*1024; +#else + i=sis_memory*1024-16384; +#endif + if((chip==SIS_6326)&&(sis_memory>4096)) + i-=4096*1024; /* 6326 can't put cursor beyond 4MB */ + for(j=0;j<6;j++)write_xr(0x14+j,cur_colors[p1*6+j]>>2); + write_xr(0x1e,(in_xr(0x1e)&0x0f)|(p1<<4)); + write_xr(0x38,(in_xr(0x38)&0x0f)|((i>>18)<<4)); + if(i&0x400000) { + write_xr(0x3e,in_xr(0x3e)|0x04); + } else { + write_xr(0x3e,in_xr(0x3e)&0xfb); + } + break; + case CURSOR_IMAGE: + i=sis_memory*1024-(16-p1)*1024; + if((chip==SIS_6326)&&(sis_memory>4096)) + i-=4096*1024; /* 6326 can't put cursor beyond 4MB */ + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*6]=(p3&0xff0000)>>16; + cur_colors[p1*6+1]=(p3&0xff00)>>8; + cur_colors[p1*6+2]=p3&0xff; + cur_colors[p1*6+3]=(p4&0xff0000)>>16; + cur_colors[p1*6+4]=(p4&0xff00)>>8; + cur_colors[p1*6+5]=p4&0xff; + for(j=0;j<32;j++) { + l1=*(b3+j); + l2=~(*(b3+32+j)); + for(k=0;k<8;k++) { + c=0; + for(l=0;l<4;l++) { + c<<=1; + c|=(l2>>31); + c<<=1; + c|=(l1>>31); + if(c&2)c&=0xfe; + l1<<=1; + l2<<=1; + } + *(LINEAR_POINTER+i+16*j+k)=c; + *(LINEAR_POINTER+i+16*j+k+8)=0xaa; + } + } + memset(LINEAR_POINTER+i+512,0xaa,512); + break; + } + break; + } + return 0; +} + +static int sis_300_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + unsigned int *b3; + int i, j; + uint32_t l1, l2; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + l1 = v_readl(0x8500 + 0); + v_writel(l1 & 0x3fffffff, 0x8500 + 0); + break; + case CURSOR_SHOW: + l1 = v_readl(0x8500 + 0); + v_writel((l1 & 0x3fffffff) | 0x40000000, 0x8500 + 0); + break; + case CURSOR_POSITION: + v_writel(p1, 0x8500 + 12); + v_writel(p2, 0x8500 + 16); + break; + case CURSOR_SELECT: + i=sis_memory-16+p1; + if(i>=0x10000)i&=0xffff; /* can use more that 64MB ? */ + v_writel(cur_colors[p1*6+2]+(cur_colors[p1*6+1]<<8)+(cur_colors[p1*6+0]<<16), 0x8500 + 4); + v_writel(cur_colors[p1*6+5]+(cur_colors[p1*6+4]<<8)+(cur_colors[p1*6+3]<<16), 0x8500 + 8); + l1 = v_readl(0x8500 + 0); + v_writel((l1 & 0xf0fe0000) | i, 0x8500 + 0); + break; + case CURSOR_IMAGE: + i=(sis_memory-16+p1)*1024; + if(i>0x4000000)i&=0x3ffffff; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*6]=(p3&0xff0000)>>16; + cur_colors[p1*6+1]=(p3&0xff00)>>8; + cur_colors[p1*6+2]=p3&0xff; + cur_colors[p1*6+3]=(p4&0xff0000)>>16; + cur_colors[p1*6+4]=(p4&0xff00)>>8; + cur_colors[p1*6+5]=p4&0xff; + for(j=0;j<32;j++) { + l1=*(b3+j); + l2=~(*(b3+32+j)); + l1=(l1<<24) | ((l1&0xff00)<<8) | ((l1>>8)&0xff00) | (l1>>24); + l2=(l2<<24) | ((l2&0xff00)<<8) | ((l2>>8)&0xff00) | (l2>>24); + *(uint32_t *)(LINEAR_POINTER+i+16*j)=l2; + *(uint32_t *)(LINEAR_POINTER+i+16*j+8)=l1; + *(uint32_t *)(LINEAR_POINTER+i+16*j+4)=0xffffffff; + *(uint32_t *)(LINEAR_POINTER+i+16*j+12)=0; + } + for(j=32;j<64;j++) { + *(uint32_t *)(LINEAR_POINTER+i+16*j)=0xffffffff; + *(uint32_t *)(LINEAR_POINTER+i+16*j+8)=0; + *(uint32_t *)(LINEAR_POINTER+i+16*j+4)=0xffffffff; + *(uint32_t *)(LINEAR_POINTER+i+16*j+12)=0; + } + break; + } + break; + } + return 0; +} + +static int sis_match_programmable_clock(int clock) +{ +return clock ; +} + +static int sis_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int sis_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_sis_driverspecs = +{ + sis_saveregs, + sis_setregs, + sis_unlock, + sis_lock, + sis_test, + sis_init, + sis_setpage, + NULL, + NULL, + sis_setmode, + sis_modeavailable, + sis_setdisplaystart, + sis_setlogicalwidth, + sis_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + sis_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + sis_cursor +}; + +/* Initialize chipset (called after detection) */ + +static int sis_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int pci_id; + int found=0; + + sis_unlock(); + if (force) { + sis_memory = par1; + chip = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + sis_linear_base=0; + chip=0; + if (found){ + sis_linear_base=buf[4]&0xffffff00; + pci_id=(buf[0]>>16)&0xffff; + switch(pci_id) { + case PCI_CHIP_SG86C201: + case PCI_CHIP_SG86C202: + case PCI_CHIP_SG86C205: + case PCI_CHIP_SG86C215: + case PCI_CHIP_SG86C225: + chip=SIS_OLD; break; + + case PCI_CHIP_SIS5597: + chip=SIS_5597; break; + + default: + case PCI_CHIP_SIS6326: + chip=SIS_6326; break; + + case PCI_CHIP_SIS530: + chip=SIS_530; break; + + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS540: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS730: + chip = SIS_300; + break; + + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + chip = SIS_315; + break; + }; + } else { + return 1; + } + + if(chip>=SIS_5597) { + __svgalib_io_reloc=(buf[6]&0xffffff80)-0x380; /* should work at least for 6326 and 530 */ + __svgalib_rel_io_mapio(); + } + + if(sis_memory==0){ + int bsiz, temp, config; + int ramsize[8] = { 1, 2, 4, 0, 0, 2, 4, 8}; + + switch(chip) { + case SIS_OLD: + read_xr(0x0F,temp); + sis_memory=1024<<(temp&0x03); + if(sis_memory==8192)sis_memory=4096; + break; + + case SIS_5597: + read_xr(0x0C,temp); + bsiz = (temp >> 1) & 3; + read_xr(0x2F,temp); + temp &= 7; + temp++; + if (bsiz > 0) temp = temp << 1; + sis_memory = 256 * temp; + break; + + case SIS_6326: + case SIS_530: + read_xr(0x0c, temp); + config = ((temp & 0x10) >> 2 ) | ((temp & 0x6) >> 1); + sis_memory = ramsize[config] * 1024; + break; + + case SIS_300: + read_xr(0x14, config); + sis_memory = ((config & 0x3F) + 1) * 1024; + break; + + case SIS_315: + read_xr(0x14, temp); + sis_memory = (1 << ((temp & 0xF0)>>4)) * 1024; + config = (temp & 0x0C) >> 2; + /* If SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK -> mem * 2 */ + if ((config == 0x01) || (config == 0x03)) + sis_memory <<= 1; + /* If DDR asymetric -> mem * 1,5*/ + if (config == 0x02) + sis_memory += sis_memory/2; + break; + } + }; + + if (__svgalib_driver_report) { + fprintf(stderr,"Using SIS driver, %iKB. Chiptype=%i\n",sis_memory,chip); + }; + + /* program the 25 and 28 Mhz clocks */ + if ((chip==SIS_5597)||(chip==SIS_6326)||(chip==SIS_530)) { + int temp,var; + read_xr(0x38,temp); + temp &= 0xfc; + write_xr(0x38,temp|1); + read_xr(0x13,var); + write_xr(0x13,var|0x40); + write_xr(0x2a,0x1b); + write_xr(0x2b,0xe1); + write_xr(0x38,temp|2); + read_xr(0x13,var); + write_xr(0x13,var|0x40); + write_xr(0x2a,0x4e); + write_xr(0x2b,0xe4); + write_xr(0x38,temp); + } + if(chip>=SIS_300) { + __svgalib_modeinfo_linearset |= LINEAR_CAN; + } + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = sis_memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 135000; + cardspecs->maxPixelClock16bpp = 135000; + cardspecs->maxPixelClock24bpp = 135000; + cardspecs->maxPixelClock32bpp = 0; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 8160; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = sis_map_clock; + cardspecs->mapHorizontalCrtc = sis_map_horizontal_crtc; + cardspecs->matchProgrammableClock=sis_match_programmable_clock; + + if(chip==SIS_300 || chip==SIS_315) { + if(pci_id!=PCI_CHIP_SIS630) /* maybe it's all 300 */ + __svgalib_sis_driverspecs.__svgalib_setpage=sis_300_setpage; + __svgalib_sis_driverspecs.cursor=sis_300_cursor; + cardspecs->maxPixelClock8bpp = 250000; + cardspecs->maxPixelClock16bpp = 250000; + cardspecs->maxPixelClock32bpp = 250000; + cardspecs->maxPixelClock24bpp = 0; + __svgalib_mmio_base=buf[5]&0xfffff000; + __svgalib_mmio_size=0x10000; + } + + __svgalib_driverspecs = &__svgalib_sis_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=sis_linear_base; + __svgalib_linear_mem_size=sis_memory*0x400; + return 0; +} + +static void +sisCalcClock(int Clock, int max_VLD, unsigned int *vclk) +{ + int M, N, P, PSN, VLD, PSNx; + + int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0; + double bestError, abest = 42.0, bestFout; + double target; + + double Fvco, Fout; + double error, aerror; + + /* + * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler) + * + * M = Numerator [1:128] + * N = DeNumerator [1:32] + * VLD = Divider (Vco Loop Divider) : divide by 1, 2 + * P = Post Scaler : divide by 1, 2, 3, 4 + * PSN = Pre Scaler (Reference Divisor Select) + * + * result in vclk[] + */ +#define Midx 0 +#define Nidx 1 +#define VLDidx 2 +#define Pidx 3 +#define PSNidx 4 +#define Fref 14318180 +/* stability constraints for internal VCO -- MAX_VCO also determines + * the maximum Video pixel clock */ +#define MIN_VCO Fref +#define MAX_VCO 135000000 +#define MAX_VCO_5597 353000000 +#define MAX_PSN 0 /* no pre scaler for this chip */ +#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ + + int M_min = 2; + int M_max = 128; + +/* abest=10000.0; */ + + target = Clock * 1000; + + if ((chip == SIS_5597) || (chip == SIS_6326)){ + int low_N = 2; + int high_N = 5; + int PSN = 1; + + P = 1; + if (target < MAX_VCO_5597 / 2) + P = 2; + if (target < MAX_VCO_5597 / 3) + P = 3; + if (target < MAX_VCO_5597 / 4) + P = 4; + if (target < MAX_VCO_5597 / 6) + P = 6; + if (target < MAX_VCO_5597 / 8) + P = 8; + + Fvco = P * target; + + for (N = low_N; N <= high_N; N++){ + double M_desired = Fvco / Fref * N; + if (M_desired > M_max * max_VLD) + continue; + + if ( M_desired > M_max ) { + M = M_desired / 2 + 0.5; + VLD = 2; + } else { + M = Fvco / Fref * N + 0.5; + VLD = 1; + }; + + Fout = (double)Fref * (M * VLD)/(N * P); + + error = (target - Fout) / target; + aerror = (error < 0) ? -error : error; +/* if (aerror < abest && abest > TOLERANCE) {*/ + if (aerror < abest) { + abest = aerror; + bestError = error; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; + bestVLD = VLD; + bestFout = Fout; + } + } + } + else { + for (PSNx = 0; PSNx <= MAX_PSN ; PSNx++) { + int low_N, high_N; + double FrefVLDPSN; + + PSN = !PSNx ? 1 : 4; + + low_N = 2; + high_N = 32; + + for ( VLD = 1 ; VLD <= max_VLD ; VLD++ ) { + + FrefVLDPSN = (double)Fref * VLD / PSN; + for (N = low_N; N <= high_N; N++) { + double tmp = FrefVLDPSN / N; + + for (P = 1; P <= 4; P++) { + double Fvco_desired = target * ( P ); + double M_desired = Fvco_desired / tmp; + + /* Which way will M_desired be rounded? + * Do all three just to be safe. + */ + int M_low = M_desired - 1; + int M_hi = M_desired + 1; + + if (M_hi < M_min || M_low > M_max) + continue; + + if (M_low < M_min) + M_low = M_min; + if (M_hi > M_max) + M_hi = M_max; + + for (M = M_low; M <= M_hi; M++) { + Fvco = tmp * M; + if (Fvco <= MIN_VCO) + continue; + if (Fvco > MAX_VCO) + break; + + Fout = Fvco / ( P ); + + error = (target - Fout) / target; + aerror = (error < 0) ? -error : error; + if (aerror < abest) { + abest = aerror; + bestError = error; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; + bestVLD = VLD; + bestFout = Fout; + } + } + } + } + } + } + } + vclk[Midx] = bestM; + vclk[Nidx] = bestN; + vclk[VLDidx] = bestVLD; + vclk[Pidx] = bestP; + vclk[PSNidx] = bestPSN; +}; + +static void +sisClockLoad(int Clock, unsigned char *regs) + { + unsigned int vclk[5]; + unsigned char temp, xr2a, xr2b; + + sisCalcClock(Clock, 2, vclk); + + xr2a = (vclk[Midx] - 1) & 0x7f ; + xr2a |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ; + xr2b = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */ + if (vclk[Pidx] <= 4){ + xr2b |= (vclk[Pidx] -1 ) << 5 ; /* postscale 1,2,3,4 */ + temp=regs[XR(0x13)]; + temp &= 0xBF; + regs[XR(0x13)]=temp; + } else { + xr2b |= ((vclk[Pidx] / 2) -1 ) << 5 ; /* postscale 6,8 */ + + temp=regs[XR(0x13)]; + temp |= 0x40; + regs[XR(0x13)]=temp; + }; + xr2b |= 0x80 ; /* gain for high frequency */ + + regs[XR(0x2a)]=xr2a; + regs[XR(0x2b)]=xr2b; + + if (chip == SIS_5597 || chip == SIS_6326) { + temp=regs[XR(0x23)]; + if (sis_edo_vram) + temp |= 0x40; + regs[XR(0x23)]=temp; + } + + if (chip == SIS_5597 || chip == SIS_6326 || chip == SIS_530) { + /*write_xr(0x3B, 0x08 );*/ + if (chip == SIS_5597) { + temp=regs[XR(0x34)]; + if (sis_host_bus) + temp |= 0x18; + else temp &= ~0x18; + regs[XR(0x34)]=temp; + + temp=regs[XR(0x3D)]; + if (sis_host_bus) + temp &= 0x0F; + regs[XR(0x3D)]=temp; + } + + /* One-Cycle VRAM */ + temp=regs[XR(0x34)]; + if (sis_fast_vram) + regs[XR(0x34)]=temp; + + /* pci burst */ + temp=regs[XR(0x35)]; + if (sis_pci_burst_on) + temp |= 0x10; + else if (sis_pci_burst_off) + temp &= ~0x10; + regs[XR(0x35)]=temp; + + /* pci burst,also */ + if (chip != SIS_530) { + temp=regs[XR(0x26)]; + if (sis_pci_burst_on) + temp |= 0x20; + else if (sis_pci_burst_off) + temp &= ~0x20; + regs[XR(0x26)]=temp; + } +/* Merge FIFOs */ + temp=regs[XR(0x07)]; + temp |= 0x80; + regs[XR(0x07)]=temp; + }; + +} + +static int sisMClk(void) +{ int mclk; + unsigned char xr28, xr29, xr13, xr10; + + if (chip == SIS_530) { + /* The MCLK in SiS530/620 is set by BIOS in SR10 */ + read_xr(0x10, xr10); + switch(xr10 & 0x0f) { + case 1: + mclk = 75000; /* 75 Mhz */ + break; + case 2: + mclk = 83000; /* 83 Mhz */ + break; + case 3: + mclk = 100000;/* 100 Mhz */ + break; + case 0: + default: + mclk = 66000; /* 66 Mhz */ + } + return(mclk); + } + /* Numerator */ + read_xr(0x28,xr28); + mclk=14318*((xr28 & 0x7f)+1); + + /* Denumerator */ + read_xr(0x29,xr29); + mclk=mclk/((xr29 & 0x1f)+1); + + /* Divider. Does not seem to work for mclk for older cards */ + if ( (chip==SIS_6326) && + ((xr28 & 0x80)!=0 ) ) { + mclk = mclk*2; + } + /* Post-scaler. Values depends on SR13 bit 7 */ + read_xr(0x13,xr13); + + if ( (xr13 & 0x80)==0 ) { + mclk = mclk / (((xr29 & 0x60) >> 5)+1); + } + else { + /* Values 00 and 01 are reserved */ + if ((xr29 & 0x60) == 0x40) mclk=mclk/6; + if ((xr29 & 0x60) == 0x60) mclk=mclk/8; + } + + return(mclk); +} + +static void +sis_CPUthreshold(int dotClock,int bpp,int *thresholdLow,int *thresholdHigh) +{ + unsigned char temp; + int mclk; + int safetymargin, gap; + float z, z1, z2; /* Yeou */ + int factor; + + mclk=sisMClk(); + + if (chip == SIS_530) /* Yeou for 530 thresholod */ + { + /* z = f *((dotClock * bpp)/(buswidth*mclk); + thresholdLow = (z+1)/2 + 4; + thresholdHigh = 0x1F; + + where f = 0x60 when UMA (SR0D D[0] = 1) + 0x30 LFB (SR0D D[0] = 0) + */ + read_xr (0x0d, temp); + if (temp & 0x01) factor = 0x60; + else factor = 0x30; + + z1 = (float)(dotClock * bpp); + z2 = (float)(64.0 * mclk); + z = ((float) factor * (z1 / z2)); + *thresholdLow = ((int)z + 1) / 2 + 4 ; + *thresholdHigh = 0x1F; + } else { /* For sis other product */ + /* Adjust thresholds. Safetymargin is to be adjusted by fifo_XXX + options. Try to mantain a fifo margin of gap. At high Vclk*bpp + this isn't possible, so limit the thresholds. + + The values I guess are : + + FIFO_CONSERVATIVE : safetymargin = 5 ; + FIFO_MODERATE : safetymargin = 3 ; + Default : safetymargin = 1 ; (good enough in many cases) + FIFO_AGGRESSIVE : safetymargin = 0 ; + + gap=4 seems to be the best value in either case... + */ + + safetymargin=3; + + gap = 4; + *thresholdLow = ((bpp*dotClock) / mclk)+safetymargin; + *thresholdHigh = ((bpp*dotClock) / mclk)+gap+safetymargin; + + /* 24 bpp seems to need lower FIFO limits. + At 16bpp is possible to put a thresholdHigh of 0 (0x10) with + good results on my system(good performance, and virtually no noise) */ + + if ( *thresholdLow > (bpp < 24 ? 0xe:0x0d) ) { + *thresholdLow = (bpp < 24 ? 0xe:0x0d); + } + + if ( *thresholdHigh > (bpp < 24 ? 0x10:0x0f) ) { + *thresholdHigh = (bpp < 24 ? 0x10:0x0f); + } + }; /* sis530 */ +} + +static int compute_vclk( + int Clock, + int *out_n, + int *out_dn, + int *out_div, + int *out_sbit, + int *out_scale) +{ + float f,x,y,t, error, min_error; + int n, dn, best_n=0, best_dn=0; + + /* + * Rules + * + * VCLK = 14.318 * (Divider/Post Scalar) * (Numerator/DeNumerator) + * Factor = (Divider/Post Scalar) + * Divider is 1 or 2 + * Post Scalar is 1, 2, 3, 4, 6 or 8 + * Numberator ranged from 1 to 128 + * DeNumerator ranged from 1 to 32 + * a. VCO = VCLK/Factor, suggest range is 150 to 250 Mhz + * b. Post Scalar selected from 1, 2, 4 or 8 first. + * c. DeNumerator selected from 2. + * + * According to rule a and b, the VCO ranges that can be scaled by + * rule b are: + * 150 - 250 (Factor = 1) + * 75 - 125 (Factor = 2) + * 37.5 - 62.5 (Factor = 4) + * 18.75 - 31.25 (Factor = 8) + * + * The following ranges use Post Scalar 3 or 6: + * 125 - 150 (Factor = 1.5) + * 62.5 - 75 (Factor = 3) + * 31.25 - 37.5 (Factor = 6) + * + * Steps: + * 1. divide the Clock by 2 until the Clock is less or equal to 31.25. + * 2. if the divided Clock is range from 18.25 to 31.25, than + * the Factor is 1, 2, 4 or 8. + * 3. if the divided Clock is range from 15.625 to 18.25, than + * the Factor is 1.5, 3 or 6. + * 4. select the Numberator and DeNumberator with minimum deviation. + * + * ** this function can select VCLK ranged from 18.75 to 250 Mhz + */ + f = (float) Clock; + f /= 1000.0; + if ((f > 250.0) || (f < 18.75)) + return 0; + + min_error = f; + y = 1.0; + x = f; + while (x > 31.25) { + y *= 2.0; + x /= 2.0; + } + if (x >= 18.25) { + x *= 8.0; + y = 8.0 / y; + } else if (x >= 15.625) { + x *= 12.0; + y = 12.0 / y; + } + + t = y; + if (t == (float) 1.5) { + *out_div = 2; + t *= 2.0; + } else { + *out_div = 1; + } + if (t > (float) 4.0) { + *out_sbit = 1; + t /= 2.0; + } else { + *out_sbit = 0; + } + + *out_scale = (int) t; + + for (dn=2;dn<=32;dn++) { + for (n=1;n<=128;n++) { + error = x; + error -= ((float) 14.318 * (float) n / (float) dn); + if (error < (float) 0) + error = -error; + if (error < min_error) { + min_error = error; + best_n = n; + best_dn = dn; + } + } + } + *out_n = best_n; + *out_dn = best_dn; + return 1; +} + diff --git a/src/drivers/skeleton.c b/src/drivers/skeleton.c new file mode 100644 index 0000000..a652bd2 --- /dev/null +++ b/src/drivers/skeleton.c @@ -0,0 +1,314 @@ +/* +Skeleton chipset driver +*/ + +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" + +#define SKREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define TOTAL_REGS (VGA_TOTAL_REGS + 100) + +static int init(int, int, int); +static void unlock(void); +static void lock(void); + +static int memory; +static unsigned int linear_base; + +static CardSpecs *cardspecs; + +static void setpage(int page) +{ +} + +/* Fill in chipset specific mode information */ +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int saveregs(unsigned char regs[]) +{ + int i; + + unlock(); + return TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + int i; + + unlock(); + +} + + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +/* Local, called by setmode(). */ + +static void initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ /* int k; */ + int tmp, tmptot, tmpss, tmpse, tmpbs, tmpbe, k; + int offset; + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + return ; +} + + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(SK_TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); +} + +static void lock(void) +{ +} + +#define VENDOR_ID 0xf00 +#define CARD_ID 0xba7 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + unsigned int buf[64]; + int found; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + id=(buf[0]>>16)&0xffff; + if(!found)return 0; + switch(id) { + case CARD_ID: + init(0,0,0); + return 1; + break; + default: + return 0; + } +} + + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void setdisplaystart(int address) +{ + address=address >> 2; + __svgalib_outcrtc(0x0d,address&0xff); + __svgalib_outcrtc(0x0c,(address>>8)&0xff); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void setlogicalwidth(int width) +{ + int offset = width >> 3; + + __svgalib_outcrtc(0x13,offset&0xff); +} + +static int linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ return 0;}; + if (op==LINEAR_DISABLE){ return 0;}; + if (op==LINEAR_QUERY_BASE) return linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} + +static int map_clock(int bpp, int clock) +{ +return clock ; +} + +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + setpage, + NULL, + NULL, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + + unlock(); + if (force) { + memory = par1; + chiptype = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + linear_base=0; + id=(buf[0]>>16)&0xffff; + if(found) { + switch(id) { + case CARD_ID: + return 1; + break; + default: + return 0; + } + } + + if (__svgalib_driver_report) { + fprintf(stderr,"Using SK driver, %iKB.\n",memory); + }; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + cardspecs->maxPixelClock4bpp = 75000; + cardspecs->maxPixelClock8bpp = 160000; + cardspecs->maxPixelClock16bpp = 160000; + cardspecs->maxPixelClock24bpp = 160000; + cardspecs->maxPixelClock32bpp = 160000; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 2040; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=memory*0x400; + return 0; +} diff --git a/src/drivers/trident.c b/src/drivers/trident.c new file mode 100644 index 0000000..276cb01 --- /dev/null +++ b/src/drivers/trident.c @@ -0,0 +1,1462 @@ +/* +Trident PCI driver +Tested on 9685, CyberbladeXP4 +*/ + +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" +#include "trident.h" +#include "vgammvgaio.h" +#include "endianess.h" + +#define TOTAL_REGS (VGA_TOTAL_REGS + sizeof(TRIDENTRegRec)) + +static int init(int, int, int); +static void unlock(void); +static void lock(void); + +static int memory, chip, NewClockCode, shadowNew, lcdactive, lcdmode, stretch=1; +static int frequency=0, is_linear; +static unsigned int linear_base, mmio_base; + +static CardSpecs *cardspecs; + +static int TridentFindMode(int xres, int yres, int depth) +{ + int xres_s; + int i, size; + biosMode *mode; + + switch (depth) { + case 1: + size = sizeof(bios1) / sizeof(biosMode); + mode = bios1; + break; + case 4: + size = sizeof(bios4) / sizeof(biosMode); + mode = bios4; + break; + case 8: + size = sizeof(bios8) / sizeof(biosMode); + mode = bios8; + break; + case 15: + size = sizeof(bios15) / sizeof(biosMode); + mode = bios15; + break; + case 16: + size = sizeof(bios16) / sizeof(biosMode); + mode = bios16; + break; + case 24: + size = sizeof(bios24) / sizeof(biosMode); + mode = bios24; + break; + default: + return 0; + } + + for (i = 0; i < size; i++) { + if (xres <= mode[i].x_res) { + xres_s = mode[i].x_res; + for (; i < size; i++) { + if (mode[i].x_res != xres_s) + return mode[i-1].mode; + if (yres <= mode[i].y_res) + return mode[i].mode; + } + } + } + + return mode[size - 1].mode; +} + +static void TridentFindNewMode(int xres, int yres, CARD8 *gr5a, CARD8 *gr5c) +{ + int xres_s; + int i, size; + + size = sizeof(newModeRegs) / sizeof(newModes); + + for (i = 0; i < size; i++) { + if (xres <= newModeRegs[i].x_res) { + xres_s = newModeRegs[i].x_res; + for (; i < size; i++) { + if (newModeRegs[i].x_res != xres_s + || yres <= newModeRegs[i].y_res) { + *gr5a = newModeRegs[i].GR5a; + *gr5c = newModeRegs[i].GR5c; + return; + } + } + } + } + + *gr5a = newModeRegs[size - 1].GR5a; + *gr5c = newModeRegs[size - 1].GR5c; + + return; +} + + +static void setpage(int page) +{ + OUTB(0x3D8, page); + OUTB(0x3D9, page); +} + +/* Fill in chipset specific mode information */ + +static void getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +/* Read and save chipset-specific registers */ + +static int saveregs(unsigned char regs[]) +{ + int temp, i; + + TRIDENTRegPtr tridentReg; + + tridentReg = (TRIDENTRegPtr)(regs+60); + + unlock(); + + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); + temp = INB(0x3C5); + + INB_3C4(NewMode1); + if (chip > PROVIDIA9685) + INB_3C4(Protection); + + /* Unprotect registers */ + __svgalib_outseq(NewMode1, 0xC0 ^ 0x02); + __svgalib_outseq(Protection, 0x92); + +#if 0 /* save all regs */ + for(i=0x18;i<0xd0;i++) + INB_3x4(i); + for(i=9;i<0xe0;i++) + INB_3CE(i); + for(i=5;i<0xc0;i++) + INB_3C4(i); +#else + INB_3x4(Offset); + INB_3x4(LinearAddReg); + INB_3x4(CRTCModuleTest); + INB_3x4(CRTHiOrd); + INB_3x4(HorizOverflow); + INB_3x4(Performance); + INB_3x4(InterfaceSel); + INB_3x4(DRAMControl); + INB_3x4(AddColReg); + INB_3x4(PixelBusReg); + INB_3x4(GraphEngReg); + INB_3x4(PCIReg); + INB_3x4(PCIRetry); + + if(chip >= CYBER9388) { + INB_3C4(Threshold); + INB_3C4(SSetup); + INB_3C4(SKey); + INB_3C4(SPKey); + INB_3x4(PreEndControl); + INB_3x4(PreEndFetch); + INB_3C4(GBslope1); + INB_3C4(GBslope2); + INB_3C4(GBslope3); + INB_3C4(GBslope4); + INB_3C4(GBintercept1); + INB_3C4(GBintercept2); + INB_3C4(GBintercept3); + INB_3C4(GBintercept4); + } + + if (chip >= PROVIDIA9685) INB_3x4(Enhancement0); + if (chip >= BLADE3D) INB_3x4(RAMDACTiming); + if (chip == CYBERBLADEE4 || chip == CYBERBLADEXP4) INB_3x4(New32); + if (chip == CYBERBLADEXP4) INB_3CE(DisplayEngCont); + + if (IsCyber) { + uint8_t tmp; + INB_3CE(VertStretch); + INB_3CE(HorStretch); + + if(chip < CYBERBLADEXP) { + INB_3CE(BiosMode); + } else { + INB_3CE(BiosNewMode1); + INB_3CE(BiosNewMode2); + } + + INB_3CE(BiosReg); + INB_3CE(FPConfig); + INB_3CE(CyberControl); + INB_3CE(CyberEnhance); + SHADOW_ENABLE(tmp); + INB_3x4(0x0); + if(shadowNew) { + INB_3x4(0x1); + INB_3x4(0x2); + } + INB_3x4(0x3); + INB_3x4(0x4); + INB_3x4(0x5); + INB_3x4(0x6); + INB_3x4(0x7); + INB_3x4(0x10); + INB_3x4(0x11); + if(shadowNew) { + INB_3x4(0x12); + INB_3x4(0x15); + } + INB_3x4(0x16); + SHADOW_RESTORE(tmp); + } + + /* save cursor registers */ + INB_3x4(CursorControl); + + INB_3CE(MiscExtFunc); + INB_3CE(MiscIntContReg); + + tridentReg->tridentRegsClock[0x00] = INB(0x3CC); + if (Is3Dchip) { + OUTB(0x3C4, ClockLow); + tridentReg->tridentRegsClock[0x01] = INB(0x3C5); + OUTB(0x3C4, ClockHigh); + tridentReg->tridentRegsClock[0x02] = INB(0x3C5); +#if 0 + if (pTrident->MCLK > 0) { + OUTB(0x3C4, MCLKLow); + tridentReg->tridentRegsClock[0x03] = INB(0x3C5); + OUTB(0x3C4, MCLKHigh); + tridentReg->tridentRegsClock[0x04] = INB(0x3C5); + } +#endif + } else { + tridentReg->tridentRegsClock[0x01] = INB(0x43C8); + tridentReg->tridentRegsClock[0x02] = INB(0x43C9); +#if 0 + if (pTrident->MCLK > 0) { + tridentReg->tridentRegsClock[0x03] = INB(0x43C6); + tridentReg->tridentRegsClock[0x04] = INB(0x43C7); + } +#endif + } + + temp = INB(0x3C8); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + tridentReg->tridentRegsDAC[0x00] = INB(0x3C6); + temp = INB(0x3C8); + +#endif + + INB_3C4(NewMode2); + + /* Protect registers */ + OUTW_3C4(NewMode1); + + return TOTAL_REGS - VGA_TOTAL_REGS; +} + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + int temp,i; + TRIDENTRegPtr tridentReg; + + tridentReg = (TRIDENTRegPtr)(regs+60); + + unlock(); + + if (chip > PROVIDIA9685) { + OUTB(0x3C4, Protection); + OUTB(0x3C5, 0x92); + } + /* Goto New Mode */ + OUTB(0x3C4, 0x0B); + temp = INB(0x3C5); + + /* Unprotect registers */ + __svgalib_outseq(NewMode1, 0xC0 ^ 0x02); + + temp = INB(0x3C8); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + temp = INB(0x3C6); + OUTB(0x3C6, tridentReg->tridentRegsDAC[0x00]); + temp = INB(0x3C8); + +#if 0 /* restore all regs */ + for(i=0x18;i<0xd0;i++) + OUTW_3x4(i); + for(i=9;i<0xe0;i++) + OUTW_3CE(i); + for(i=5;i<0xc0;i++) + OUTW_3C4(i); +#else + OUTW_3x4(CRTCModuleTest); + OUTW_3x4(LinearAddReg); + OUTW_3C4(NewMode2); + OUTW_3x4(CursorControl); + OUTW_3x4(CRTHiOrd); + OUTW_3x4(HorizOverflow); + OUTW_3x4(AddColReg); + OUTW_3x4(GraphEngReg); + OUTW_3x4(Performance); + OUTW_3x4(InterfaceSel); + OUTW_3x4(DRAMControl); + OUTW_3x4(PixelBusReg); + OUTW_3x4(PCIReg); + OUTW_3x4(PCIRetry); + OUTW_3CE(MiscIntContReg); + OUTW_3CE(MiscExtFunc); + OUTW_3x4(Offset); + + if(chip >= CYBER9388) { + OUTW_3C4(Threshold); + OUTW_3C4(SSetup); + OUTW_3C4(SKey); + OUTW_3C4(SPKey); + OUTW_3x4(PreEndControl); + OUTW_3x4(PreEndFetch); + OUTW_3C4(GBslope1); + OUTW_3C4(GBslope2); + OUTW_3C4(GBslope3); + OUTW_3C4(GBslope4); + OUTW_3C4(GBintercept1); + OUTW_3C4(GBintercept2); + OUTW_3C4(GBintercept3); + OUTW_3C4(GBintercept4); + + } + + if (chip >= PROVIDIA9685) OUTW_3x4(Enhancement0); + if (chip >= BLADE3D) OUTW_3x4(RAMDACTiming); + if (chip == CYBERBLADEE4 || chip == CYBERBLADEXP4) OUTW_3x4(New32); + if (chip == CYBERBLADEXP4) OUTW_3CE(DisplayEngCont); + if (IsCyber) { + uint8_t tmp; + + OUTW_3CE(VertStretch); + OUTW_3CE(HorStretch); + if(chip <= CYBERBLADEXP) { + OUTW_3CE(BiosMode); + } else { + OUTW_3CE(BiosNewMode1); + OUTW_3CE(BiosNewMode2); + } + OUTW_3CE(BiosReg); + OUTW_3CE(FPConfig); + OUTW_3CE(CyberControl); + OUTW_3CE(CyberEnhance); + SHADOW_ENABLE(tmp); + OUTW_3x4(0x0); + if(shadowNew) { + OUTW_3x4(0x1); + OUTW_3x4(0x2); + } + OUTW_3x4(0x3); + OUTW_3x4(0x4); + OUTW_3x4(0x5); + OUTW_3x4(0x6); + OUTW_3x4(0x7); + OUTW_3x4(0x10); + OUTW_3x4(0x11); + if(shadowNew) { + OUTW_3x4(0x12); + OUTW_3x4(0x15); + } + OUTW_3x4(0x16); + SHADOW_RESTORE(tmp); + } + + if (Is3Dchip) { + __svgalib_outseq(ClockLow, tridentReg->tridentRegsClock[0x01]); + __svgalib_outseq(ClockHigh, tridentReg->tridentRegsClock[0x02]); + +#if 0 + if (pTrident->MCLK > 0) { + OUTW(0x3C4,(tridentReg->tridentRegsClock[0x03])<<8 | MCLKLow); + OUTW(0x3C4,(tridentReg->tridentRegsClock[0x04])<<8 | MCLKHigh); + } +#endif + } else { + OUTB(0x43C8, tridentReg->tridentRegsClock[0x01]); + OUTB(0x43C9, tridentReg->tridentRegsClock[0x02]); +#if 0 + if (pTrident->MCLK > 0) { + OUTB(0x43C6, tridentReg->tridentRegsClock[0x03]); + OUTB(0x43C7, tridentReg->tridentRegsClock[0x04]); + } +#endif + } + OUTB(0x3C2, tridentReg->tridentRegsClock[0x00]); + +#endif + if (chip > PROVIDIA9685) { + OUTB(0x3C4, Protection); + OUTB(0x3C5, tridentReg->tridentRegs3C4[Protection]); + } + + __svgalib_outseq(NewMode1, tridentReg->tridentRegs3C4[NewMode1] ^ 0x02); + +} + + +/* Return nonzero if mode is available */ + +static int modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + return SVGADRV; +} + +static void TGUISetClock(int clock, uint8_t *a, uint8_t *b) +{ + int powerup[4] = { 1,2,4,8 }; + int clock_diff = 750; + int freq, ffreq; + int m, n, k; + int p, q, r, s; + int endn, endm, endk, startk=0, startn; + + p = q = r = s = 0; + + if (NewClockCode) + { + startn = 64; + endn = 255; + endm = 63; + endk = 2; + if (clock >= 100000) startk = 0; + if (clock < 100000) startk = 1; + if (clock < 50000) startk = 2; + } + else + { + startn = 32; + endn = 121; + endm = 31; + endk = 1; + if(clock>50000) startk=1; else startk = 0; + } + + freq = clock; + + for (k=startk;k<=endk;k++) + for (n=startn;n<=endn;n++) + for (m=1;m<=endm;m++) { + ffreq = ( ((n + 8) * frequency) / ((m + 2) * powerup[k]) ) ; + if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff)) + { +/* + * It seems that the 9440 docs have this STRICT limitation, although + * most 9440 boards seem to cope. 96xx/Cyber chips don't need this limit + * so, I'm gonna remove it and it allows lower clocks < 25.175 too ! + */ +#define STRICT 1 +#ifdef STRICT + if ((chip>TGUI9440AGi) || ((n+8)*100/(m+2) < 978 && (n+8)*100/(m+2) > 349)) { +#endif + clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq; + p = n; q = m; r = k; s = ffreq; +#ifdef STRICT + } +#endif + } + } + + if (s == 0) { + exit(1); + } + + if (NewClockCode) { + /* N is all 8bits */ + *a = p; + /* M is first 6bits, with K last 2bits */ + *b = (q & 0x3F) | (r << 6); + } else { + /* N is first 7bits, first M bit is 8th bit */ + *a = ((1 & q) << 7) | p; + /* first 4bits are rest of M, 1bit for K value */ + *b = (((q & 0xFE) >> 1) | (r << 4)); + } +} + +static void initializemode(unsigned char *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ /* int k; */ + + int offset=0, protect=0, fullsize=0, MUX; + int clock; + + TRIDENTRegPtr pReg; + + pReg = (TRIDENTRegPtr)(moderegs+60); + + clock=modetiming->pixelClock; + + if((clock>90000) && (modeinfo->bitsPerPixel==8)) { + MUX=1; + modetiming->CrtcHDisplay>>=1; + modetiming->CrtcHTotal>>=1; + modetiming->CrtcHSyncStart>>=1; + modetiming->CrtcHSyncEnd>>=1; + } else { + MUX=0; + } + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + if(chip>PROVIDIA9685) { + protect=__svgalib_inseq(Protection); + __svgalib_outseq( Protection, 0x92); + } + + __svgalib_inseq(0x0b); + + pReg->tridentRegs3x4[PixelBusReg] = 0x00; + pReg->tridentRegsDAC[0x00] = 0x00; + pReg->tridentRegs3C4[NewMode2] = 0x20; + pReg->tridentRegs3CE[MiscExtFunc] = __svgalib_ingra(MiscExtFunc); + pReg->tridentRegs3x4[GraphEngReg] = 0x00; + pReg->tridentRegs3x4[PreEndControl] = 0; + pReg->tridentRegs3x4[PreEndFetch] = 0; + + pReg->tridentRegs3x4[CRTHiOrd] = (((modetiming->CrtcVSyncEnd-1) & 0x400)>>4) | + (((modetiming->CrtcVTotal - 2) & 0x400) >> 3) | + ((modetiming->CrtcVSyncStart & 0x400) >> 5) | + (((modetiming->CrtcVDisplay - 1) & 0x400) >> 6)| + 0x08; + + pReg->tridentRegs3x4[HorizOverflow] = ((modetiming->CrtcHTotal & 0x800) >> 11) | + ((modetiming->CrtcHSyncStart & 0x800)>>7); + + if(IsCyber) { + pReg->tridentRegs3CE[FPConfig] = __svgalib_ingra(FPConfig); + pReg->tridentRegs3CE[CyberEnhance] = __svgalib_ingra(CyberEnhance) & 0x8f; + + if (modetiming->CrtcVDisplay > 1024) + pReg->tridentRegs3CE[CyberEnhance] |= 0x50; + else if (modetiming->CrtcVDisplay > 768) + pReg->tridentRegs3CE[CyberEnhance] |= 0x30; + else if (modetiming->CrtcVDisplay > 600) + pReg->tridentRegs3CE[CyberEnhance] |= 0x20; + else if (modetiming->CrtcVDisplay > 480) + pReg->tridentRegs3CE[CyberEnhance] |= 0x10; + + pReg->tridentRegs3CE[CyberControl] = __svgalib_ingra(CyberControl); + pReg->tridentRegs3CE[HorStretch] = __svgalib_ingra(HorStretch); + pReg->tridentRegs3CE[VertStretch] = __svgalib_ingra(VertStretch); + + if(lcdmode!=0xff) { + pReg->tridentRegs3x4[0x0] = LCD[lcdmode].shadow_0; + pReg->tridentRegs3x4[0x1] = moderegs[0x1]; + pReg->tridentRegs3x4[0x2] = moderegs[0x2]; + pReg->tridentRegs3x4[0x3] = LCD[lcdmode].shadow_3; + pReg->tridentRegs3x4[0x4] = LCD[lcdmode].shadow_4; + pReg->tridentRegs3x4[0x5] = LCD[lcdmode].shadow_5; + pReg->tridentRegs3x4[0x6] = LCD[lcdmode].shadow_6; + pReg->tridentRegs3x4[0x7] = LCD[lcdmode].shadow_7; + pReg->tridentRegs3x4[0x10] = LCD[lcdmode].shadow_10; + pReg->tridentRegs3x4[0x11] = LCD[lcdmode].shadow_11; + pReg->tridentRegs3x4[0x12] = moderegs[0x12]; + pReg->tridentRegs3x4[0x15] = moderegs[0x15]; + pReg->tridentRegs3x4[0x16] = LCD[lcdmode].shadow_16; + if(lcdactive) { + pReg->tridentRegs3x4[CRTHiOrd] = LCD[lcdmode].shadow_HiOrd; + } + fullsize = (modetiming->HDisplay == LCD[lcdmode].display_x) + && (modetiming->VDisplay == LCD[lcdmode].display_y); + } + + pReg->tridentRegs3x4[0x7] &= ~0x4A; + pReg->tridentRegs3x4[0x7] |= moderegs[0x7] & 0x4A; + + if(lcdactive && fullsize) { + moderegs[0x0]=pReg->tridentRegs3x4[0x0]; + moderegs[0x3]=pReg->tridentRegs3x4[0x3]; + moderegs[0x4]=pReg->tridentRegs3x4[0x4]; + moderegs[0x5]=pReg->tridentRegs3x4[0x5]; + moderegs[0x6]=pReg->tridentRegs3x4[0x6]; + moderegs[0x7]=pReg->tridentRegs3x4[0x7]; + moderegs[0x10]=pReg->tridentRegs3x4[0x10]; + moderegs[0x11]=pReg->tridentRegs3x4[0x11]; + moderegs[0x16]=pReg->tridentRegs3x4[0x16]; + } + + if(lcdactive && !fullsize) { + moderegs[VGA_MISCOUTPUT] |= 0xc0; + pReg->tridentRegs3CE[CyberControl] |= 0x81; + } else { + pReg->tridentRegs3CE[CyberControl] &= 0x7e; + } + + /* FPDELAY CYBERSHADOW ??? */ + + /* disable stretching, enable centering */ + pReg->tridentRegs3CE[VertStretch] &= 0xFC; + pReg->tridentRegs3CE[VertStretch] |= 0x80; + pReg->tridentRegs3CE[HorStretch] &= 0xFC; + pReg->tridentRegs3CE[HorStretch] |= 0x80; + +#if 1 + { + int mul = (modeinfo->bitsPerPixel+1) >> 3; + int val; + + if (!mul) mul = 1; + + /* this is what my BIOS does */ + val = (modetiming->HDisplay * mul / 8) + 16; + + pReg->tridentRegs3x4[PreEndControl] = ((val >> 8) < 2 ? 2 :0) + | ((val >> 8) & 0x01); + pReg->tridentRegs3x4[PreEndFetch] = val & 0xff; + } +#else + pReg->tridentRegs3x4[PreEndControl]=__svgalib_incrtc(PreEndControl); + pReg->tridentRegs3x4[PreEndFetch]=__svgalib_incrtc(PreEndFetch); +#endif + + if(chiptridentRegs3CE[BiosMode] = TridentFindMode( + modetiming->HDisplay, modetiming->VDisplay, modeinfo->colorBits); + } else { + TridentFindNewMode(modetiming->HDisplay, modetiming->VDisplay, + &pReg->tridentRegs3CE[BiosNewMode1], + &pReg->tridentRegs3CE[BiosNewMode2]); + } + + if(chip != CYBERBLADEXPAI1) { + pReg->tridentRegs3CE[BiosReg] = 0; + } else { + pReg->tridentRegs3CE[BiosReg] = 8; + } + + if(stretch) { + pReg->tridentRegs3CE[HorStretch] |= 0x01; + pReg->tridentRegs3CE[VertStretch] |= 0x01; + } + } + + switch(chip) { + case CYBERBLADEXP4: + case CYBERBLADEXPAI1: + case CYBERBLADEXP: + case CYBERBLADEI7: + case CYBERBLADEI7D: + case CYBERBLADEI1: + case CYBERBLADEI1D: + case CYBERBLADEAI1: + case CYBERBLADEAI1D: + case CYBERBLADEE4: + case BLADE3D: + pReg->tridentRegs3x4[RAMDACTiming] = __svgalib_incrtc(RAMDACTiming) | 0x0F; + /* Fall Through */ + case CYBER9520: + case CYBER9525DVD: + case CYBER9397DVD: + case CYBER9397: + case IMAGE975: + case IMAGE985: + case CYBER9388: + if (modeinfo->bitsPerPixel >= 8) + pReg->tridentRegs3CE[MiscExtFunc] |= 0x10; + else + pReg->tridentRegs3CE[MiscExtFunc] &= ~0x10; + if (!pReg->tridentRegs3x4[PreEndControl]) + pReg->tridentRegs3x4[PreEndControl] = 0x01; + if (!pReg->tridentRegs3x4[PreEndFetch]) + pReg->tridentRegs3x4[PreEndFetch] = 0xFF; + /* Fall Through */ + case PROVIDIA9685: + case CYBER9385: + pReg->tridentRegs3x4[Enhancement0] = 0x40; + /* Fall Through */ + case PROVIDIA9682: + case CYBER9382: +#if 0 + if (pTrident->UsePCIRetry) + pReg->tridentRegs3x4[PCIRetry] = 0xDF; + else +#endif + pReg->tridentRegs3x4[PCIRetry] = 0x1F; + /* Fall Through */ + case TGUI9660: + case TGUI9680: + if (MUX && modeinfo->bitsPerPixel == 8) { + pReg->tridentRegs3x4[PixelBusReg] |= 0x01; /* 16bit bus */ + pReg->tridentRegs3C4[NewMode2] |= 0x02; /* half clock */ + pReg->tridentRegsDAC[0x00] |= 0x20; /* mux mode */ + } + } + + /* Defaults for all trident chipsets follows */ + switch (modeinfo->bitsPerPixel) { + case 1: + case 4: + offset = modeinfo->lineWidth >> 4; + break; + case 8: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = modeinfo->lineWidth >> 3; + break; + case 16: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = modeinfo->lineWidth >> 3; + if (modeinfo->colorBits == 15) + pReg->tridentRegsDAC[0x00] = 0x10; + else + pReg->tridentRegsDAC[0x00] = 0x30; + pReg->tridentRegs3x4[PixelBusReg] = 0x04; + /* Reload with any chipset specific stuff here */ + if (chip >= TGUI9660) + pReg->tridentRegs3x4[PixelBusReg] |= 0x01; + if (chip == TGUI9440AGi) { + pReg->tridentRegs3CE[MiscExtFunc] |= 0x08;/*Clock Division / 2*/ + clock *= 2; /* Double the clock */ + } + break; + case 24: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + offset = modeinfo->lineWidth >> 3; + pReg->tridentRegs3x4[PixelBusReg] = 0x29; + pReg->tridentRegsDAC[0x00] = 0xD0; + if (chip == CYBERBLADEXP4 || chip == CYBERBLADEE4) { + pReg->tridentRegs3x4[New32] = __svgalib_incrtc(New32) & 0x7F; + } + break; + case 32: + pReg->tridentRegs3CE[MiscExtFunc] |= 0x02; + if (chip != CYBERBLADEXP4 + && chip != CYBERBLADEE4 && chip != CYBERBLADEXPAI1) { + /* Clock Division by 2*/ + pReg->tridentRegs3CE[MiscExtFunc] |= 0x08; + clock *= 2; /* Double the clock */ + } + offset = modeinfo->lineWidth >> 3; + pReg->tridentRegs3x4[PixelBusReg] = 0x09; + pReg->tridentRegsDAC[0x00] = 0xD0; + if (chip == CYBERBLADEXP4 || chip == CYBERBLADEE4 + || chip == CYBERBLADEXPAI1) { + pReg->tridentRegs3x4[New32] = __svgalib_incrtc(New32) | 0x80; + /* With new mode 32bpp we set the packed flag */ + pReg->tridentRegs3x4[PixelBusReg] |= 0x20; + } + break; + } + + pReg->tridentRegs3x4[Offset] = offset & 0xFF; + { + uint8_t a, b; + TGUISetClock(clock, &a, &b); + pReg->tridentRegsClock[0x00] = moderegs[VGA_MISCOUTPUT] | 0x08; + pReg->tridentRegsClock[0x01] = a; + pReg->tridentRegsClock[0x02] = b; + } + + pReg->tridentRegs3C4[NewMode1] = 0xC0; + pReg->tridentRegs3C4[Protection] = 0x92; + + pReg->tridentRegs3x4[LinearAddReg] = 0; + + if(chiptridentRegs3x4[LinearAddReg] |= 0x20; + } + + pReg->tridentRegs3CE[MiscExtFunc] |= 0x04; + + pReg->tridentRegs3x4[CRTCModuleTest] = + (modetiming->flags & INTERLACED ? 0x84 : 0x80); + + pReg->tridentRegs3x4[InterfaceSel] = __svgalib_incrtc(InterfaceSel)| 0x40; + + pReg->tridentRegs3x4[Performance] = __svgalib_incrtc(Performance); + if(chiptridentRegs3x4[Performance] |= 0x10; + + if(chip >= CYBER9388) pReg->tridentRegs3x4[DRAMControl] = + __svgalib_incrtc(DRAMControl) | 0x10; + + if (IsCyber) pReg->tridentRegs3x4[DRAMControl] |= 0x20; + + if(NewClockCode && chip <= CYBER9397DVD) { + pReg->tridentRegs3x4[ClockControl] = __svgalib_incrtc(ClockControl) | 0x01; + } + + pReg->tridentRegs3x4[AddColReg] = __svgalib_incrtc(AddColReg) & 0xEF; + pReg->tridentRegs3x4[AddColReg] |= (offset & 0x100) >> 4; + + if (chip >= TGUI9660) { + pReg->tridentRegs3x4[AddColReg] &= 0xDF; + pReg->tridentRegs3x4[AddColReg] |= (offset & 0x200) >> 4; + } + + pReg->tridentRegs3CE[MiscIntContReg] = __svgalib_ingra(MiscIntContReg) | 0x04; + + + pReg->tridentRegs3x4[PCIReg] = __svgalib_incrtc(PCIReg) & 0xF8; + + /* PCIBURST BRIGHTNESS */ + + pReg->tridentRegs3C4[SSetup] = __svgalib_inseq(0x20) | 0x4; + pReg->tridentRegs3C4[SKey] = 0x00; + pReg->tridentRegs3C4[SPKey] = 0xC0; + pReg->tridentRegs3C4[Threshold] = __svgalib_inseq(0x12); + if (modeinfo->bitsPerPixel > 16) pReg->tridentRegs3C4[Threshold] = + (pReg->tridentRegs3C4[Threshold] & 0xf0) | 0x2; + + + if (chip > PROVIDIA9685) { + __svgalib_outseq( Protection, protect); + } + + if (chip == CYBERBLADEXP4) + pReg->tridentRegs3CE[DisplayEngCont] = 0x08; + + /* Avoid lockup on Blade3D, PCI Retry is permanently on */ + if (chip == BLADE3D) + pReg->tridentRegs3x4[PCIRetry] = 0x9F; + + return; +} + + +static int setmode(int mode, int prv_mode) +{ + unsigned char *moderegs; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + + if (!modeavailable(mode)) return 1; + + is_linear=0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 1; + } + + moderegs = malloc(TOTAL_REGS); + + initializemode(moderegs, modetiming, modeinfo, mode); + free(modetiming); + + __svgalib_setregs(moderegs); /* Set standard regs. */ + setregs(moderegs, mode); /* Set extended regs. */ + free(moderegs); + + free(modeinfo); + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); +} + +static void lock(void) +{ +} + +#define VENDOR_ID 0x1023 + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int test(void) +{ + unsigned int buf[64]; + int found, id; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + id=(buf[0]>>16)&0xffff; + if(!found)return 0; + if( !init(0,0,0)) return 1; + return 0; +} + + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void setdisplaystart(int address) +{ + address=address >> 2; + __svgalib_outcrtc(0x0d,address&0xff); + __svgalib_outcrtc(0x0c,(address>>8)&0xff); + __svgalib_outcrtc(CRTCModuleTest, (__svgalib_incrtc(CRTCModuleTest)&0xdf) | ((address&0x10000)>>11)); + __svgalib_outcrtc(CRTHiOrd, (__svgalib_incrtc(CRTHiOrd)&0xf8) | ((address&0xe0000)>>17)); +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Cirrus supports multiples of 8, up to 4088 */ + +static void setlogicalwidth(int width) +{ + int offset = width >> 3; + + __svgalib_outcrtc(0x13,offset&0xff); +} + +static int linear(int op, int param) +{ + if (op==LINEAR_ENABLE){ + int t; + OUTB(0x3CE, MiscExtFunc); + t=INB(0x3CF); + OUTB(0x3CF, t&~0x04); + OUTB(0x3D4, LinearAddReg); + if(chip>24)<<6) | ((linear_base>>20)&0x0f) | 0x20; + } else { + t=0x20; + } + OUTB(0x3D5, t); + is_linear=1; + return 0; + }; + if (op==LINEAR_DISABLE){ + int t; + OUTB(0x3CE, MiscExtFunc); + t=INB(0x3CF); + OUTB(0x3CF, t|0x04); + OUTB(0x3D4, LinearAddReg); + OUTB(0x3D5, 0 ); + is_linear=0; + return 0; + }; + if (op==LINEAR_QUERY_BASE) return linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ + else return -1; /* Unknown function. */ +} + +static int match_programmable_clock(int clock) +{ +return clock ; +} + +static int map_clock(int bpp, int clock) +{ +return clock ; +} + +static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +static struct { + unsigned char c8; + unsigned short c15; + unsigned short c16; + unsigned int c32; +} cursor_colors[16*2]; + +static int pal=1, palette[768]; + +static int findcolor(int rgb) { + int i,j,k,l=0; + + if(pal)vga_getpalvec(0,256,palette); + pal=0; + k=0xffffff; + for(i=0;i<256;i++) { + j=((rgb&0xff)-(palette[i*3+2]<<2))*((rgb&0xff)-(palette[i*3+2]<<2))+ + (((rgb>>8)&0xff)-(palette[i*3+1]<<2))*(((rgb>>8)&0xff)-(palette[i*3+1]<<2))+ + (((rgb>>16)&0xff)-(palette[i*3]<<2))*(((rgb>>16)&0xff)-(palette[i*3]<<2)); + if(j==0) { + return i; + } + if(j>8)&0xff); + __svgalib_outcrtc(0x42, p2&0xff); + __svgalib_outcrtc(0x43, (p2>>8)&0xff); + break; + case CURSOR_SELECT: + i=memory-(p1+1); + switch(CI.colors) { + case 256: + __svgalib_outcrtc(0x48,cursor_colors[p1*2+1].c8); + __svgalib_outcrtc(0x4c,cursor_colors[p1*2].c8); + break; + case 32768: + __svgalib_outcrtc(0x49,cursor_colors[p1*2+1].c15>>8); + __svgalib_outcrtc(0x48,cursor_colors[p1*2+1].c15&0xff); + __svgalib_outcrtc(0x4d,cursor_colors[p1*2].c15>>8); + __svgalib_outcrtc(0x4c,cursor_colors[p1*2].c15&0xff); + break; + case 65536: + __svgalib_outcrtc(0x49,cursor_colors[p1*2+1].c16>>8); + __svgalib_outcrtc(0x48,cursor_colors[p1*2+1].c16&0xff); + __svgalib_outcrtc(0x4d,cursor_colors[p1*2].c16>>8); + __svgalib_outcrtc(0x4c,cursor_colors[p1*2].c16&0xff); + break; + case (1<<24): + __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c32>>16); + __svgalib_outcrtc(0x49,(cursor_colors[p1*2+1].c32>>8)&0xff); + __svgalib_outcrtc(0x48,cursor_colors[p1*2+1].c32&0xff); + __svgalib_outcrtc(0x4e,cursor_colors[p1*2].c32>>16); + __svgalib_outcrtc(0x4d,(cursor_colors[p1*2].c32>>8)&0xff); + __svgalib_outcrtc(0x4c,cursor_colors[p1*2].c32&0xff); + break; + } + __svgalib_outcrtc(0x44, i&0xff); + __svgalib_outcrtc(0x45, i>>8); + break; + case CURSOR_IMAGE: + i=memory*1024-(p1+1)*1024; + b3=(unsigned int *)p5; + b4=(unsigned int *)(LINEAR_POINTER+i); + if (!is_linear){ + int t; + OUTB(0x3CE, MiscExtFunc); + t=INB(0x3CF); + OUTB(0x3CF, t&~0x04); + OUTB(0x3D4, LinearAddReg); + if(chip>24)<<6) | ((linear_base>>20)&0x0f) | 0x20; + } else { + t=0x20; + } + OUTB(0x3D5, t); + }; + cursor_colors[p1*2].c8=findcolor(p3); + cursor_colors[p1*2].c32=p3; + cursor_colors[p1*2].c16=((p3&0xf80000)>>8)|((p3&0xfc00)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2].c15=((p3&0xf80000)>>9)|((p3&0xf800)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2+1].c8=findcolor(p4); + cursor_colors[p1*2+1].c32=p4; + cursor_colors[p1*2+1].c16=((p4&0xf80000)>>8)|((p4&0xfc00)>>5)|((p4&0xf8)>>3); + cursor_colors[p1*2+1].c15=((p4&0xf80000)>>9)|((p4&0xf800)>>5)|((p4&0xf8)>>3); + switch(p2) { + case 0: + for(j=0;j<32;j++) { + *b4=BE32(*(b3+32)); + b4++; + *b4=BE32(*b3); + b4++; + b3++; + } + break; + } + if (!is_linear){ + int t; + OUTB(0x3CE, MiscExtFunc); + t=INB(0x3CF); + OUTB(0x3CF, t|0x04); + OUTB(0x3D4, LinearAddReg); + OUTB(0x3D5, 0 ); + }; + break; + } + return 0; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_trident_driverspecs = +{ + saveregs, + setregs, + unlock, + lock, + test, + init, + setpage, + NULL, + NULL, + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + cursor, +}; + +/* Initialize chipset (called after detection) */ + +static int init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int rev, i, id; + int found=0; + char *chipnames[]={ + "9420", "9430", "9440", "9320", "9660", "9680", + "9682", "9382", "9385", "9685", "9388", "9397", + "9397DVD", "9520", "9525", "975", "985", "Blade3D", + "CyberBladeI7", "CyberBladeI7D", "CyberBladeI1", + "CyberBladeI1D", "CyberBladeAI1", "CyberBladeAI1D", + "CyberBladeE4", "CyberBladeXP", "CyberBladeXPAI1", + "CyberBladeXP4" + }; + + unlock(); + + if (force) { + memory = par1; + chip = par2; + } else { + + }; + + found=__svgalib_pci_find_vendor_vga_pos(VENDOR_ID,buf); + linear_base=0; + id=(buf[0]>>16)&0xffff; + if(!found) + return 1; + + linear_base=buf[4]&0xffff0000; + mmio_base=buf[5]&0xffff0000; + +#if 0 + /* This should work */ + __svgalib_mmio_base=mmio_base; + __svgalib_mmio_size=32*0x400; + map_mmio(); + __svgalib_vgammbase=0; + __svgalib_mm_io_mapio(); +#endif + + OUTB(0x3C4, RevisionID); + rev=INB(0x3C5); + + NewClockCode=0; + shadowNew=0; + + switch(id) { + case 0x9420: + chip=TGUI9420DGi; + frequency = 14318; + break; + case 0x9430: + chip=TGUI9430DGi; + frequency = 14318; + break; + case 0x9440: + case 0x9460: + case 0x9470: + chip=TGUI9440AGi; + frequency = 14318; + break; + case 0x9320: + chip=CYBER9320; + break; + case 0x9660: + switch(rev) { + case 0x0: + chip=TGUI9660; + break; + case 0x1: + chip=TGUI9680; + break; + case 0x10: + chip=PROVIDIA9682; + break; + case 0x21: + chip=PROVIDIA9685; + NewClockCode=1; + break; + case 0x22: + case 0x23: + chip=CYBER9397; + NewClockCode=1; + break; + case 0x2a: + chip=CYBER9397DVD; + NewClockCode=1; + break; + case 0x30: + case 0x33: + case 0x34: + case 0x35: + case 0x38: + case 0x3a: + case 0xb3: + chip=CYBER9385; + NewClockCode=1; + break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + chip=CYBER9382; + NewClockCode=1; + break; + case 0x4a: + chip=CYBER9388; + NewClockCode=1; + break; + default: + chip=TGUI9660; + break; + } + break; + case 0x9388: + chip=CYBER9388; + NewClockCode=1; + break; + case 0x9397: + chip=CYBER9397; + NewClockCode=1; + break; + case 0x939a: + chip=CYBER9397DVD; + NewClockCode=1; + break; + case 0x9520: + chip=CYBER9520; + NewClockCode=1; + break; + case 0x9525: + chip=CYBER9525DVD; + NewClockCode=1; + break; + case 0x9540: + chip=CYBERBLADEE4; + NewClockCode=1; + break; + case 0x9750: + chip=IMAGE975; + NewClockCode=1; + break; + case 0x9850: + chip=IMAGE985; + NewClockCode=1; + break; + case 0x9880: + chip=BLADE3D; + NewClockCode=1; + frequency = 14318; + break; + case 0x8400: + chip=CYBERBLADEI7; + NewClockCode=1; + frequency = 14318; + break; + case 0x8420: + chip=CYBERBLADEI7D; + NewClockCode=1; + frequency = 14318; + break; + case 0x8500: + chip=CYBERBLADEI1; + NewClockCode=1; + frequency = 14318; + break; + case 0x8520: + chip=CYBERBLADEI1D; + NewClockCode=1; + frequency = 14318; + break; + case 0x8600: + chip=CYBERBLADEAI1; + NewClockCode=1; + frequency = 14318; + break; + case 0x8620: + chip=CYBERBLADEAI1D; + NewClockCode=1; + frequency = 14318; + break; + case 0x9910: + chip=CYBERBLADEXP; + NewClockCode=1; + frequency = 14318; + break; + case 0x2100: + case 0x9930: + chip=CYBERBLADEXP4; + NewClockCode=1; + shadowNew=1; + frequency = 14318; + break; + default: + chip=TGUI9440AGi; + frequency = 14318; + break; + } + + i=__svgalib_incrtc(SPR)&0x0f; + switch(i) { + case 1: + memory=512; + break; + case 2: + memory=6144; + break; + case 3: + memory=1024; + break; + case 4: + memory=4096; /* actually, 8192 - but it has problems */ + break; + case 6: + memory=10240; + break; + case 7: + memory=2048; + break; + case 8: + memory=12288; + break; + case 10: + memory=14336; + break; + case 12: + memory=16384; + break; + case 14: + memory=32768; + break; + case 15: + memory=4096; + break; + default: + memory=1024; + } + + if((frequency==0) && (__svgalib_incrtc(TVinterface) & 0x80)) + frequency = 17734; else frequency=14318; + + + if(IsCyber) { + int mod, dsp, dsp1; + dsp = __svgalib_ingra(0x42); + dsp1 = __svgalib_ingra(0x43); + mod = __svgalib_ingra(0x52); + + for (i = 0; LCD[i].mode != 0xff; i++) { + if (LCD[i].mode == ((mod >> 4) & 3)) { + lcdactive = __svgalib_ingra(FPConfig) & 0x10; + lcdmode=LCD[i].mode; + fprintf(stderr, "%s Panel %ix%i found (%s).\n", + (dsp & 0x80) ? "TFT" : + ((dsp1 & 0x20) ? "DSTN" : "STN"), + LCD[i].display_x,LCD[i].display_y, + lcdactive ? "active":"inactive"); + } + } + } + + + if (__svgalib_driver_report) { + fprintf(stderr,"Using Trident driver, %s with %iKB.\n", chipnames[chip],memory); + }; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = memory; + cardspecs->maxPixelClock8bpp = ClockLimit[chip+12]; + cardspecs->maxPixelClock16bpp = ClockLimit16bpp[chip+12]; + cardspecs->maxPixelClock24bpp = ClockLimit24bpp[chip+12]; + cardspecs->maxPixelClock32bpp = ClockLimit32bpp[chip+12]; + cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 2040; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->nClocks =0; + cardspecs->mapClock = map_clock; + cardspecs->mapHorizontalCrtc = map_horizontal_crtc; + cardspecs->matchProgrammableClock=match_programmable_clock; + __svgalib_driverspecs = &__svgalib_trident_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + __svgalib_linear_mem_base=linear_base; + __svgalib_linear_mem_size=memory*0x400; + return 0; +} diff --git a/src/drivers/trident.h b/src/drivers/trident.h new file mode 100644 index 0000000..188bed8 --- /dev/null +++ b/src/drivers/trident.h @@ -0,0 +1,504 @@ +typedef unsigned char CARD8; + +typedef struct { + unsigned char tridentRegs3x4[0xd0]; + unsigned char tridentRegs3CE[0xe0]; + unsigned char tridentRegs3C4[0xc0]; + unsigned char tridentRegsDAC[0x01]; + unsigned char tridentRegsClock[0x03]; +} TRIDENTRegRec, *TRIDENTRegPtr; + +enum { + TGUI9420DGi=0, + TGUI9430DGi, + TGUI9440AGi, + CYBER9320, + TGUI9660, + TGUI9680, + PROVIDIA9682, + CYBER9382, + CYBER9385, + PROVIDIA9685, + CYBER9388, + CYBER9397, + CYBER9397DVD, + CYBER9520, + CYBER9525DVD, + IMAGE975, + IMAGE985, + BLADE3D, + CYBERBLADEI7, + CYBERBLADEI7D, + CYBERBLADEI1, + CYBERBLADEI1D, + CYBERBLADEAI1, + CYBERBLADEAI1D, + CYBERBLADEE4, + CYBERBLADEXP, + CYBERBLADEXPAI1, + CYBERBLADEXP4 +}; + +#define Is3Dchip ((chip == CYBER9397) || \ + (chip == CYBER9397DVD) || \ + (chip == CYBER9520) || \ + (chip == CYBER9525DVD) || \ + (chip == CYBERBLADEE4) || \ + (chip == IMAGE975) || \ + (chip == IMAGE985) || \ + (chip == CYBERBLADEI7) || \ + (chip == CYBERBLADEI7D) || \ + (chip == CYBERBLADEI1) || \ + (chip == CYBERBLADEI1D) || \ + (chip == CYBERBLADEAI1) || \ + (chip == CYBERBLADEAI1D) || \ + (chip == BLADE3D) || \ + (chip == CYBERBLADEXP) || \ + (chip == CYBERBLADEXPAI1) || \ + (chip == CYBERBLADEXP4)) + +#define IsCyber ((chip == CYBER9397) || \ + (chip == CYBER9397DVD) || \ + (chip == CYBER9525DVD) || \ + (chip == CYBER9382) || \ + (chip == CYBER9385) || \ + (chip == CYBER9388) || \ + (chip == CYBER9520) || \ + (chip == CYBERBLADEE4) || \ + (chip == CYBERBLADEI7D) || \ + (chip == CYBERBLADEI1) || \ + (chip == CYBERBLADEI1D) || \ + (chip == CYBERBLADEAI1) || \ + (chip == CYBERBLADEAI1D) || \ + (chip == CYBERBLADEXP) || \ + (chip == CYBERBLADEXPAI1) || \ + (chip == CYBERBLADEXP4)) + + + +#if 0 +#define INB(addr) (*(unsigned char *)(__svgalib_vgammbase+addr)) +#define OUTB(addr, val) (*(unsigned char *)(__svgalib_vgammbase+addr) = val) +#define OUTW(addr, val) (*(unsigned short *)(__svgalib_vgammbase+addr) = val) +#else +#define INB(addr) port_in(addr) +#define OUTB(addr, val) port_out_r(addr,val) +#define OUTW(addr, val) port_outw_r(addr,val) +#endif + +#define OUTW_3C4(reg) \ + __svgalib_outseq(reg, tridentReg->tridentRegs3C4[reg]) +#define OUTW_3CE(reg) \ + __svgalib_outgra(reg, tridentReg->tridentRegs3CE[reg]) +#define OUTW_3x4(reg) \ + __svgalib_outcrtc(reg, tridentReg->tridentRegs3x4[reg]) + +#define INB_3x4(reg) \ + tridentReg->tridentRegs3x4[reg] = __svgalib_incrtc(reg) +#define INB_3C4(reg) \ + tridentReg->tridentRegs3C4[reg] = __svgalib_inseq(reg) +#define INB_3CE(reg) \ + tridentReg->tridentRegs3CE[reg] = __svgalib_ingra(reg) + +#define SPR 0x1F /* Software Programming Register (videoram) */ + +/* 3C4 */ +#define RevisionID 0x09 +#define ConfPort1 0x0C +#define ConfPort2 0x0C +#define NewMode2 0x0D +#define OldMode2 0x00 /* Should be 0x0D - dealt with in trident_dac.c */ +#define OldMode1 0x0E +#define NewMode1 0x0E +#define Protection 0x11 +#define Threshold 0x12 +#define MCLKLow 0x16 +#define MCLKHigh 0x17 +#define ClockLow 0x18 +#define ClockHigh 0x19 +#define SSetup 0x20 +#define SKey 0x37 +#define SPKey 0x57 +#define GBslope1 0xB4 +#define GBslope2 0xB5 +#define GBslope3 0xB6 +#define GBslope4 0xB7 +#define GBintercept1 0xB8 +#define GBintercept2 0xB9 +#define GBintercept3 0xBA +#define GBintercept4 0xBB + +/* 3D4 */ +#define Offset 0x13 +#define Underline 0x14 +#define CRTCMode 0x17 +#define CRTCModuleTest 0x1E +#define FIFOControl 0x20 +#define LinearAddReg 0x21 +#define DRAMTiming 0x23 +#define New32 0x23 +#define RAMDACTiming 0x25 +#define CRTHiOrd 0x27 +#define AddColReg 0x29 +#define InterfaceSel 0x2A +#define HorizOverflow 0x2B +#define GETest 0x2D +#define Performance 0x2F +#define GraphEngReg 0x36 +#define I2C 0x37 +#define PixelBusReg 0x38 +#define PCIReg 0x39 +#define DRAMControl 0x3A +#define MiscContReg 0x3C +#define CursorXLow 0x40 +#define CursorXHigh 0x41 +#define CursorYLow 0x42 +#define CursorYHigh 0x43 +#define CursorLocLow 0x44 +#define CursorLocHigh 0x45 +#define CursorXOffset 0x46 +#define CursorYOffset 0x47 +#define CursorFG1 0x48 +#define CursorFG2 0x49 +#define CursorFG3 0x4A +#define CursorFG4 0x4B +#define CursorBG1 0x4C +#define CursorBG2 0x4D +#define CursorBG3 0x4E +#define CursorBG4 0x4F +#define CursorControl 0x50 +#define PCIRetry 0x55 +#define PreEndControl 0x56 +#define PreEndFetch 0x57 +#define PCIMaster 0x60 +#define Enhancement0 0x62 +#define NewEDO 0x64 +#define TVinterface 0xC0 +#define TVMode 0xC1 +#define ClockControl 0xCF + +/* 3CE */ +#define MiscExtFunc 0x0F +#define MiscIntContReg 0x2F +#define CyberControl 0x30 +#define CyberEnhance 0x31 +#define FPConfig 0x33 +#define VertStretch 0x52 +#define HorStretch 0x53 +#define BiosMode 0x5c +#define BiosNewMode1 0x5a +#define BiosNewMode2 0x5c +#define BiosReg 0x5d +#define DisplayEngCont 0xD1 + +#define SHADOW_ENABLE(oldval) \ + do {\ + OUTB(0x3CE, CyberControl); \ + oldval = INB(0x3CF);\ + OUTB(0x3CF,oldval | (1 << 6));\ + } while (0) +#define SHADOW_RESTORE(val) \ + do {\ + OUTB(0x3CE, CyberControl); \ + OUTB(0x3CF,val); \ + } while (0); + +static int ClockLimit[] = { + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, + 80000, +/* 9440 */ + 70000, /* is it 90000 ?? The strict mode limitation means 70 */ + 90000, + 135000, + 135000, + 170000, + 170000, + 170000, +/* 9685 */ + 170000, + 170000, + 170000, + 170000, + 230000, + 230000, + 230000, + 230000, + 230000, +/* CYBERBLADEI7 */ + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, +}; + +static int ClockLimit16bpp[] = { + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, + 40000, +/* 9440 */ + 35000, /* is it 45000 ?? The strict mode limitation means 35 */ + 45000, + 90000, + 90000, + 135000, + 135000, + 170000, +/* 9685 */ + 170000, + 170000, + 170000, + 170000, + 230000, + 230000, + 230000, + 230000, + 230000, +/* CYBERBLADEI7 */ + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, + 230000, +}; + +static int ClockLimit24bpp[] = { + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, +/* 9440 */ + 25180, + 25180, + 40000, + 40000, + 70000, + 70000, + 70000, +/* 9685 */ + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, +/* CYBERBLADEI7 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + +static int ClockLimit32bpp[] = { + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, + 25180, +/* 9440 */ + 25180, + 25180, + 40000, + 40000, + 70000, + 70000, + 70000, +/* 9685 */ + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, +/* CYBERBLADEI7 */ + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, + 115000, +}; + +typedef struct { + int mode; + int display_x; + int display_y; + int clock; + int shadow_0; + int shadow_3; + int shadow_4; + int shadow_5; + int shadow_6; + int shadow_7; + int shadow_10; + int shadow_11; + int shadow_16; + int shadow_HiOrd; +} tridentLCD; + + +tridentLCD LCD[] = { + { 1,640,480,25200,0x5f,0x80,0x52,0x1e,0xb,0x3e,0xea,0x0c,0xb,0x08}, + { 3,800,600,40000,0x7f,0x00,0x69,0x7f,0x72,0xf0,0x59,0x0d,0x00,0x08}, + { 2,1024,768,65000,0xa3,0x00,0x84,0x94,0x24,0xf5,0x03,0x09,0x24,0x08}, + { 0,1280,1024,108000,0xce,0x91,0xa6,0x14,0x28,0x5a,0x01,0x04,0x28,0xa8}, + { 4,1400,1050,122000,0xe6,0xcd,0xba,0x1d,0x38,0x00,0x1c,0x28,0x28,0xf8}, + { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +typedef struct { + int x_res; + int y_res; + int mode; +} biosMode; + +typedef struct { + int x_res; + int y_res; + CARD8 GR5a; + CARD8 GR5c; +} newModes; + +static biosMode bios1[] = { + { 640, 480, 0x11 } +}; + +static biosMode bios4[] = { + { 320, 200, 0xd }, + { 640, 200, 0xe }, + { 640, 350, 0x11 }, + { 640, 480, 0x12 }, + { 800, 600, 0x5b }, + { 1024, 768 , 0x5f }, + { 1280, 1024, 0x63 }, + { 1600, 1200, 0x65 } +}; + +static biosMode bios8[] = { + { 320, 200, 0x13 }, + { 640, 400, 0x5c }, + { 640, 480, 0x5d }, + { 720, 480, 0x60 }, + { 800, 600, 0x5e }, + { 1024, 768, 0x62 }, + { 1280, 1024, 0x64 }, + { 1600, 1200, 0x66 } +}; + +static biosMode bios15[] = { + { 640, 400, 0x72 }, + { 640, 480, 0x74 }, + { 720, 480, 0x70 }, + { 800, 600, 0x76 }, + { 1024, 768, 0x78 }, + { 1280, 1024, 0x7a }, + { 1600, 1200, 0x7c } +}; + +static biosMode bios16[] = { + { 640, 400, 0x73 }, + { 640, 480, 0x75 }, + { 720, 480, 0x71 }, + { 800, 600, 0x77 }, + { 1024, 768, 0x79 }, + { 1280, 1024, 0x7b }, + { 1600, 1200, 0x7d } +}; + +static biosMode bios24[] = { + { 640, 400, 0x6b }, + { 640, 480, 0x6c }, + { 720, 480, 0x61 }, + { 800, 600, 0x6d }, + { 1024, 768, 0x6e } +}; + +static newModes newModeRegs [] = { + { 320, 200, 0x13, 0x30 }, + { 640, 480, 0x13, 0x61 }, + { 800, 600, 0x13, 0x61 }, + { 1024, 768, 0x3b, 0x63 }, + { 1280, 1024, 0x7b, 0x64 }, + { 1400, 1050, 0x11, 0x7b } +}; + + diff --git a/src/drivers/tvga8900.c b/src/drivers/tvga8900.c new file mode 100644 index 0000000..a6b3cb1 --- /dev/null +++ b/src/drivers/tvga8900.c @@ -0,0 +1,759 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright (C) 1993 Harm Hanemaayer */ +/* Modified by Hartmut Schirmer */ + +/* TVGA 8900c code taken from tvgalib by Toomas Losin */ + +/* TVGA 9440 code added by ARK 29-OCT-97 */ +/* (root@ark.dyn.ml.org, ark@lhq.com) [nitc?] */ +/* updated 9-NOV-97 to support more regs */ +/* this should alllow it to work on 9680's as well */ + +/* Thanks to Albert Erdmann (theone@miami.gdi.net) */ +/* for blindly testing files and mailing me results */ +/* for the 9680 registers */ + + +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#include "regs/tvga8900.regs" +#include "regs/tvga9440.regs" +#include "regs/tvga9680.regs" + +/* static int tvga_chiptype; */ +static int tvga8900_memory; /* amount of video memory in K */ +static int tvga8900_nonint; /* nonzero if non-interlaced jumper set */ + +static int tvga8900_init(int, int, int); +static int tvga8900_interlaced(int mode); + +static int reg_0c = 0xad; /* value for 256k cards */ + +static int tvga_model = 8900; /* set to 8900, 9440, or 9680 based on model */ + +/* Mode table */ +#define ModeEntry94(res) { G##res, g##res##_regs94 } +#define ModeEntry96(res) { G##res, g##res##_regs96 } + +static ModeTable tvga_modes_2048_96[] = +{ /* 2M modes for the 9680 */ + ModeEntry96(800x600x16), + ModeEntry96(1024x768x16), + ModeEntry96(1280x1024x16), + ModeEntry96(1600x1200x16), + ModeEntry96(640x480x256), + ModeEntry96(800x600x256), + ModeEntry96(1024x768x256), + ModeEntry96(1280x1024x256), + ModeEntry96(1600x1200x256), + ModeEntry96(320x200x32K), + ModeEntry96(640x480x32K), + ModeEntry96(800x600x32K), + ModeEntry96(1024x768x32K), + ModeEntry96(320x200x64K), + ModeEntry96(640x480x64K), + ModeEntry96(800x600x64K), + ModeEntry96(1024x768x64K), + ModeEntry96(320x200x16M), + ModeEntry96(640x480x16M), + ModeEntry96(800x600x16M), + END_OF_MODE_TABLE +}; + +static ModeTable tvga_modes_1024_96[] = +{ /* 1M modes for the 9680 */ + ModeEntry96(800x600x16), + ModeEntry96(1024x768x16), + ModeEntry96(1280x1024x16), + ModeEntry96(1600x1200x16), + ModeEntry96(640x480x256), + ModeEntry96(800x600x256), + ModeEntry96(1024x768x256), + ModeEntry96(320x200x32K), + ModeEntry96(640x480x32K), + ModeEntry96(800x600x32K), + ModeEntry96(320x200x64K), + ModeEntry96(640x480x64K), + ModeEntry96(800x600x64K), + ModeEntry96(320x200x16M), + ModeEntry96(640x480x16M), + END_OF_MODE_TABLE +}; + +static ModeTable tvga_modes_512_96[] = +{ /* 512K modes for the 9680 */ + ModeEntry96(800x600x16), + ModeEntry96(1024x768x16), + ModeEntry96(640x480x256), + ModeEntry96(800x600x256), + ModeEntry96(320x200x32K), + ModeEntry96(320x200x64K), + ModeEntry96(320x200x16M), + END_OF_MODE_TABLE +}; + +static ModeTable tvga_modes_1024_94[] = +{ /* 1M modes for the 9440 */ + ModeEntry94(800x600x16), + ModeEntry94(1024x768x16), + ModeEntry94(1280x1024x16), + ModeEntry94(1600x1200x16), + ModeEntry94(640x480x256), + ModeEntry94(800x600x256), + ModeEntry94(1024x768x256), + ModeEntry94(320x200x32K), + ModeEntry94(640x480x32K), + ModeEntry94(800x600x32K), + ModeEntry94(320x200x64K), + ModeEntry94(640x480x64K), + ModeEntry94(800x600x64K), + ModeEntry94(320x200x16M), + ModeEntry94(640x480x16M), + END_OF_MODE_TABLE +}; + +static ModeTable tvga_modes_512_94[] = +{ /* 512K modes for the 9440 */ + ModeEntry94(800x600x16), + ModeEntry94(1024x768x16), + ModeEntry94(640x480x256), + ModeEntry94(800x600x256), + ModeEntry94(320x200x32K), + ModeEntry94(320x200x64K), + ModeEntry94(320x200x16M), + END_OF_MODE_TABLE +}; + +static ModeTable tvga_modes_1024[] = +{ /* 1Mb, non-interlace jumper set */ +/* *INDENT-OFF* */ + OneModeEntry(640x480x256), + OneModeEntry(800x600x256), + OneModeEntry(1024x768x256), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +#define INTERL(res,i) { G##res, g##res##i##_regs } + +static ModeTable tvga_modes_1024i[] = +{ /* 1Mb, jumper set to interlaced */ +/* *INDENT-OFF* */ + INTERL(640x480x256, i), + INTERL(800x600x256, i), + INTERL(1024x768x256, i), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +static ModeTable tvga_modes_512[] = +{ /* 512K */ +/* *INDENT-OFF* */ + INTERL(640x480x256, i), + INTERL(800x600x256, i1), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +static ModeTable *tvga_modes = NULL; + +static void nothing(void) +{ +} + +/* Fill in chipset specific mode information */ + +static void tvga8900_getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + if (modeinfo->bytesperpixel > 0) + modeinfo->maxpixels = tvga8900_memory * 1024 / + modeinfo->bytesperpixel; + else + modeinfo->maxpixels = tvga8900_memory * 1024; + modeinfo->maxlogicalwidth = 2040; + modeinfo->startaddressrange = 0xfffff; + if (mode == G320x200x256) { + /* Special case: bank boundary may not fall within display. */ + modeinfo->startaddressrange = 0xf0000; + /* Hack: disable page flipping capability for the moment. */ + modeinfo->startaddressrange = 0xffff; + modeinfo->maxpixels = 65536; + } + modeinfo->haveblit = 0; + + if (tvga8900_interlaced(mode)) + modeinfo->flags |= IS_INTERLACED; + modeinfo->flags &= ~HAVE_RWPAGE; +} + + +/* select the correct register table */ +static void setup_registers(void) +{ + if (tvga_modes == NULL) { + if (tvga_model == 9440) { + if (tvga8900_memory < 1024) + tvga_modes = tvga_modes_512_94; + else + tvga_modes = tvga_modes_1024_94; + } + else if (tvga_model == 9680) { + if (tvga8900_memory < 1024) + tvga_modes = tvga_modes_512_96; + else if (tvga8900_memory < 2048) + tvga_modes = tvga_modes_1024_96; + else + tvga_modes = tvga_modes_2048_96; + } + else { + if (tvga8900_memory < 1024) + tvga_modes = tvga_modes_512; + if (tvga8900_nonint) + tvga_modes = tvga_modes_1024; + else + tvga_modes = tvga_modes_1024i; + } + } +} + + +/* Read and store chipset-specific registers */ + +static int tvga8900_saveregs(unsigned char regs[]) +{ + int i; + + /* I know goto is bad, but i didnt want to indent all the old code.. */ + /* the 9680 uses the same regs, just completely different values */ + if (tvga_model == 9440 || tvga_model == 9680) goto tvga9440_saveregs; + + /* save extended CRT registers */ + for (i = 0; i < 7; i++) { + port_out(0x18 + i, __svgalib_CRT_I); + regs[EXT + i] = port_in(__svgalib_CRT_D); + } + + /* now do the sequencer mode regs */ + port_out(0x0b, SEQ_I); /* force old mode regs */ + port_out(port_in(SEQ_D), SEQ_D); /* by writing */ + + /* port_outw_r(SEQ_I, 0x820E); */ /* unlock conf. reg */ + /* port_out(0x0c, SEQ_I); */ /* save conf. reg */ + /* regs[EXT + 11] = port_in(SEQ_D); */ + + port_out(0x0d, SEQ_I); /* old reg 13 */ + regs[EXT + 7] = port_in(SEQ_D); + port_out(0x0e, SEQ_I); /* old reg 14 */ + regs[EXT + 8] = port_in(SEQ_D); + + port_out(0x0b, SEQ_I); /* now use new regs */ + port_in(SEQ_D); + port_out(0x0d, SEQ_I); /* new reg 13 */ + regs[EXT + 9] = port_in(SEQ_D); + port_out(0x0e, SEQ_I); /* new reg 14 */ + regs[EXT + 10] = port_in(SEQ_D) ^ 0x02; + + /* we do the ^ 0x02 so that when the regs are restored */ + /* later we don't have a special case; see trident.doc */ + + return 12; /* tridents requires 12 additional registers */ + + + /* 9440 code added by ARK */ + tvga9440_saveregs: + + /* unprotect some trident regs */ + port_out(0x0E, SEQ_I); + port_out(port_in(SEQ_D) | 0x80, SEQ_D); + + /* save sequencer regs */ + port_out(0x0B, SEQ_I); + regs[EXT + 0] = port_in(SEQ_D); + port_out(0x0D, SEQ_I); + regs[EXT + 1] = port_in(SEQ_D); + port_out(0x0E, SEQ_I); + regs[EXT + 2] = port_in(SEQ_D); + port_out(0x0F, SEQ_I); + regs[EXT + 3] = port_in(SEQ_D); + + /* save extended CRT registers */ + port_out(0x19, __svgalib_CRT_I); + regs[EXT + 4] = port_in(__svgalib_CRT_D); + port_out(0x1E, __svgalib_CRT_I); + regs[EXT + 5] = port_in(__svgalib_CRT_D); + port_out(0x1F, __svgalib_CRT_I); + regs[EXT + 6] = port_in(__svgalib_CRT_D); + port_out(0x21, __svgalib_CRT_I); + regs[EXT + 7] = port_in(__svgalib_CRT_D); + port_out(0x25, __svgalib_CRT_I); + regs[EXT + 8] = port_in(__svgalib_CRT_D); + port_out(0x27, __svgalib_CRT_I); + regs[EXT + 9] = port_in(__svgalib_CRT_D); + port_out(0x29, __svgalib_CRT_I); + regs[EXT + 10] = port_in(__svgalib_CRT_D); + /* Extended regs 11/12 are clobbered by vga.c */ + port_out(0x2A, __svgalib_CRT_I); + regs[EXT + 13] = port_in(__svgalib_CRT_D); + port_out(0x2F, __svgalib_CRT_I); + regs[EXT + 14] = port_in(__svgalib_CRT_D); + port_out(0x30, __svgalib_CRT_I); + regs[EXT + 15] = port_in(__svgalib_CRT_D); + port_out(0x36, __svgalib_CRT_I); + regs[EXT + 16] = port_in(__svgalib_CRT_D); + port_out(0x38, __svgalib_CRT_I); + regs[EXT + 17] = port_in(__svgalib_CRT_D); + port_out(0x50, __svgalib_CRT_I); + regs[EXT + 18] = port_in(__svgalib_CRT_D); + + /* grfx controller */ + port_out(0x0F, GRA_I); + regs[EXT + 19] = port_in(GRA_D); + port_out(0x2F, GRA_I); + regs[EXT + 20] = port_in(GRA_D); + + /* trident specific ports */ + regs[EXT + 21] = port_in(0x43C8); + regs[EXT + 22] = port_in(0x43C9); + regs[EXT + 23] = port_in(0x83C6); + regs[EXT + 24] = port_in(0x83C8); + for(i=0;i<5;i++) + port_in(PEL_MSK); + regs[EXT + 25] = port_in(PEL_MSK); + + /* reprotect the regs to avoid conflicts */ + port_out(0x0E, SEQ_I); + port_out(port_in(SEQ_D) & 0x7F, SEQ_D); + + return 26; /* The 9440 requires 26 additional registers */ +} + + +/* Set chipset-specific registers */ + +static void tvga8900_setregs(const unsigned char regs[], int mode) +{ + int i; + int crtc31 = 0; + + /* 7 extended CRT registers */ + /* 4 extended Sequencer registers (old and new) */ + /* CRTC reg 0x1f is apparently dependent */ + /* on the amount of memory installed. */ + + switch (tvga8900_memory >> 8) { + case 1: + crtc31 = 0x94; + reg_0c = 0xad; + break; /* 256K */ + case 2: + case 3: + crtc31 = 0x98; + reg_0c = 0xcd; + break; /* 512/768K */ + case 4: /* 1024K */ + crtc31 = 0x18; + reg_0c = 0xcd; + if (mode == G1024x768x256) { + reg_0c = 0xed; + crtc31 = 0x98; + } else if (mode == G640x480x256 || mode == G800x600x256) + reg_0c = 0xed; + break; + } + + if (tvga_model == 9440 || tvga_model == 9680) goto tvga9440_setregs; + + if (mode == TEXT) { + reg_0c = regs[EXT + 11]; + crtc31 = regs[EXT + 12]; + } +#ifdef REG_DEBUG + fprintf(stderr,"Setting extended registers\n"); +#endif + + /* write extended CRT registers */ + for (i = 0; i < 7; i++) { + port_out(0x18 + i, __svgalib_CRT_I); + port_out(regs[EXT + i], __svgalib_CRT_D); + } + + /* update sequencer mode regs */ + port_out(0x0b, SEQ_I); /* select old regs */ + port_out(port_in(SEQ_D), SEQ_D); + port_out(0x0d, SEQ_I); /* old reg 13 */ + port_out(regs[EXT + 7], SEQ_D); + port_out(0x0e, SEQ_I); /* old reg 14 */ +#if 0 + port_out(regs[EXT + 8], SEQ_D); +#endif + port_out(((port_in(SEQ_D) & 0x08) | (regs[EXT + 8] & 0xf7)), SEQ_D); + + + port_out(0x0b, SEQ_I); + port_in(SEQ_D); /* select new regs */ + + if (tvga8900_memory > 512) { + port_out(0x0e, SEQ_I); /* set bit 7 of reg 14 */ + port_out(0x80, SEQ_D); /* to enable writing to */ + port_out(0x0c, SEQ_I); /* reg 12 */ + port_out(reg_0c, SEQ_D); + } + /* port_outw_r(SEQ_I, 0x820e); */ /* unlock conf. reg */ + /* port_out(0x0c, SEQ_I); */ /* reg 12 */ + + port_out(0x0d, SEQ_I); /* new reg 13 */ + port_out(regs[EXT + 9], SEQ_D); + port_out(0x0e, SEQ_I); /* new reg 14 */ + port_out(regs[EXT + 10], SEQ_D); + +#ifdef REG_DEBUG + fprintf(stderr,"Now setting last two extended registers.\n"); +#endif + + /* update CRTC reg 1f */ + port_out(0x1f, __svgalib_CRT_I); + port_out((port_in(__svgalib_CRT_D) & 0x03) | crtc31, __svgalib_CRT_D); + + return; + + + tvga9440_setregs: + + /* update sequencer mode regs */ + port_out(0x0D, SEQ_I); + port_out(regs[EXT + 1], SEQ_D); + port_out(0x0E, SEQ_I); + port_out(regs[EXT + 2], SEQ_D); + port_out(0x0F, SEQ_I); + port_out(regs[EXT + 3], SEQ_D); +/* you cant write to this anyways... it messes things up... + port_out(0x0B, SEQ_I); + port_out(regs[EXT + 0], SEQ_D); +*/ + /* write extended CRT registers */ + port_out(0x19, __svgalib_CRT_I); + port_out(regs[EXT + 4], __svgalib_CRT_D); + port_out(0x1E, __svgalib_CRT_I); + port_out(regs[EXT + 5], __svgalib_CRT_D); + port_out(0x1F, __svgalib_CRT_I); + port_out(regs[EXT + 6], __svgalib_CRT_D); + port_out(0x21, __svgalib_CRT_I); + port_out(regs[EXT + 7], __svgalib_CRT_D); + port_out(0x25, __svgalib_CRT_I); + port_out(regs[EXT + 8], __svgalib_CRT_D); + port_out(0x27, __svgalib_CRT_I); + port_out(regs[EXT + 9], __svgalib_CRT_D); + port_out(0x29, __svgalib_CRT_I); + port_out(regs[EXT + 10], __svgalib_CRT_D); + /* Extended regs 11/12 are clobbered by vga.c */ + port_out(0x2A, __svgalib_CRT_I); + port_out(regs[EXT + 13], __svgalib_CRT_D); + port_out(0x2F, __svgalib_CRT_I); + port_out(regs[EXT + 14], __svgalib_CRT_D); + port_out(0x30, __svgalib_CRT_I); + port_out(regs[EXT + 15], __svgalib_CRT_D); + port_out(0x36, __svgalib_CRT_I); + port_out(regs[EXT + 16], __svgalib_CRT_D); + port_out(0x38, __svgalib_CRT_I); + port_out(regs[EXT + 17], __svgalib_CRT_D); + port_out(0x50, __svgalib_CRT_I); + port_out(regs[EXT + 18], __svgalib_CRT_D); + + /* grfx controller */ + port_out(0x0F, GRA_I); + port_out(regs[EXT + 19], GRA_D); + port_out(0x2F, GRA_I); + port_out(regs[EXT + 20], GRA_D); + + /* unprotect 3DB */ + port_out(0x0F, GRA_I); + port_out(port_in(GRA_D) | 0x04, GRA_D); + /* allow user-defined clock rates */ + port_out((port_in(0x3DB) & 0xFC) | 0x02, 0x3DB); + + /* trident specific ports */ + port_out(regs[EXT + 21], 0x43C8); + port_out(regs[EXT + 22], 0x43C9); + port_out(regs[EXT + 23], 0x83C6); + port_out(regs[EXT + 24], 0x83C8); + for(i=0;i<5;i++) + port_in(PEL_MSK); + port_out(regs[EXT + 25], PEL_MSK); + port_out(0xFF, PEL_MSK); +} + + +/* Return nonzero if mode is available */ + +static int tvga8900_modeavailable(int mode) +{ + const unsigned char *regs; + struct vgainfo *info; + + regs = LOOKUPMODE(tvga_modes, mode); + if (regs == NULL || mode == GPLANE16) + return __svgalib_vga_driverspecs.modeavailable(mode); + if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE) + return 0; + + info = &__svgalib_infotable[mode]; + if (tvga8900_memory * 1024 < info->ydim * info->xbytes) + return 0; + + return SVGADRV; +} + + +/* Check if mode is interlaced */ + +static int tvga8900_interlaced(int mode) +{ + const unsigned char *regs; + + setup_registers(); + regs = LOOKUPMODE(tvga_modes, mode); + if (regs == NULL || regs == DISABLE_MODE) + return 0; + return tvga8900_nonint == 0; +} + + +/* Set a mode */ + +static int tvga8900_setmode(int mode, int prv_mode) +{ + const unsigned char *regs; + + regs = LOOKUPMODE(tvga_modes, mode); + if (regs == NULL) + return (int) (__svgalib_vga_driverspecs.setmode(mode, prv_mode)); + if (!tvga8900_modeavailable(mode)) + return 1; + __svgalib_setregs(regs); + tvga8900_setregs(regs, mode); + return 0; +} + + +/* Indentify chipset; return non-zero if detected */ + +static int tvga8900_test(void) +{ + int origVal, newVal; + int save0b; + /* + * Check first that we have a Trident card. + */ + port_out_r(SEQ_I, 0x0b); + save0b = port_in(SEQ_D); + port_outw_r(SEQ_I, 0x000B); /* Switch to Old Mode */ + port_in(SEQ_D); /* Now to New Mode */ + port_out_r(SEQ_I, 0x0E); + origVal = port_in(SEQ_D); + port_out_r(SEQ_D, 0x00); + newVal = port_in(SEQ_D) & 0x0F; + port_out_r(SEQ_D, (origVal ^ 0x02)); + + if (newVal != 2) { + port_out_r(SEQ_D, origVal); + port_out_r(SEQ_I, 0x0b); + port_out_r(SEQ_D, save0b); + return 0; + } + + /* The version check that was here was moved to the init function by ARK */ + /* in order to tell the 8900 from the 9440 model.. */ + + tvga8900_init(0, 0, 0); + return 1; +} + + +/* Bank switching function - set 64K bank number */ + +static void tvga8900_setpage(int page) +{ + port_out(0x0b, SEQ_I); + port_out(port_in(SEQ_D), SEQ_D); + port_in(SEQ_D); /* select new mode regs */ + + port_out(0x0e, SEQ_I); + port_out(page ^ 0x02, SEQ_D); /* select the page */ +} + + +/* Set display start address (not for 16 color modes) */ +/* Trident supports any address in video memory (up to 1Mb) */ + +static void tvga8900_setdisplaystart(int address) +{ + if (__svgalib_cur_mode == G320x200x256) { + port_outw_r(CRT_IC, 0x0d + (address & 0x00ff) * 256); + port_outw_r(CRT_IC, 0x0c + (address & 0xff00)); + address <<= 2; /* Adjust address so that extended bits */ + /* are correctly set later (too allow for */ + /* multi-page flipping in 320x200). */ + goto setextendedbits; + } + if (tvga8900_memory == 1024) { + port_outw_r(CRT_IC, 0x0d + ((address >> 3) & 0x00ff) * 256); /* sa2-sa9 */ + port_outw_r(CRT_IC, 0x0c + ((address >> 3) & 0xff00)); /* sa10-sa17 */ + } else { + port_outw_r(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */ + port_outw_r(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */ + } + if (__svgalib_cur_mode != G320x200x256) { + port_in(0x3da); /* set ATC to addressing mode */ + port_out_r(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ + if (tvga8900_memory == 1024) { + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | (address & 7)); + /* write sa0-2 to bits 0-2 */ + address >>= 1; + } else + port_out_r(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); + /* write sa0-1 to bits 1-2 */ + } + setextendedbits: + port_out_r(CRT_IC, 0x1e); + port_out_r(CRT_DC, (port_in(CRT_DC) & 0x5f) | 0x80 /* set bit 7 */ + | ((address & 0x40000) >> 13)); /* sa18: write to bit 5 */ + port_out_r(SEQ_I, 0x0b); + port_out_r(SEQ_D, 0); /* select 'old mode' */ + port_out_r(SEQ_I, 0x0e); + port_out_r(SEQ_D, (port_in(SEQ_D) & 0xfe) + | ((address & 0x80000) >> 19)); /* sa19: write to bit 0 */ + port_out_r(SEQ_I, 0x0b); + port_in(SEQ_D); /* return to 'new mode' */ +} + + +/* Set logical scanline length (usually multiple of 8) */ +/* Trident supports multiples of 8 to 2040 */ + +static void tvga8900_setlogicalwidth(int width) +{ + port_outw_r(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ +} + + +/* Function table */ + +DriverSpecs __svgalib_tvga8900_driverspecs = +{ + tvga8900_saveregs, + tvga8900_setregs, + nothing, /* unlock */ + nothing, /* lock */ + tvga8900_test, + tvga8900_init, + tvga8900_setpage, + (void (*)(int)) nothing, /* __svgalib_setrdpage */ + (void (*)(int)) nothing, /* __svgalib_setwrpage */ + tvga8900_setmode, + tvga8900_modeavailable, + tvga8900_setdisplaystart, + tvga8900_setlogicalwidth, + tvga8900_getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + + +/* Initialize chipset (called after detection) */ + +static int tvga8900_init(int force, int par1, int par2) +{ + if (force) { +#ifdef DEBUG + fprintf(stderr,"Forcing memory to %dK\n", par1); +#endif + tvga8900_memory = par1; + tvga8900_nonint = par2 & 1; +/* +par2 specs +bit 31-3: reserved +bit 2-1: 00 - force 8900 + 01 - force 9440 + 10 - force 9680 + 11 - reserved +bit 0: force noninterlaced if set + only affects the 8900 +*/ + switch (par2 & 6) + { + case 0: tvga_model=8900; + break; + case 2: tvga_model=9440; + break; + case 4: tvga_model=9680; + break; + case 6: tvga_model=0; + break; + } + } else { + port_out(0x1f, __svgalib_CRT_I); + /* this should detect up to 2M memory now */ + tvga8900_memory = (port_in(__svgalib_CRT_D) & 0x07) * 256 + 256; + + /* Now is the card running in interlace mode? */ + port_out(0x0f, SEQ_I); + tvga8900_nonint = port_in(SEQ_D) & 0x04; + + /* check version */ + port_outw_r(SEQ_I, 0x000b); + switch (port_in(SEQ_D)) { + case 0x02: /* 8800cs */ + case 0x03: /* 8900b */ + case 0x04: /* 8900c */ + case 0x13: + case 0x33: /* 8900cl */ + case 0x23: /* 9000 */ + tvga_model = 8900; + break; + case 0xD3: +/* I know 0xD3 is a 9680, but if your 9680 is detected as a */ +/* 9440, EMAIL ME! (ark) and I will change this... */ + tvga_model = 9680; + break; + default: +/* Whatever the original 8900 driver thought was */ +/* an invalid version, we will use as a 9440. */ + tvga_model = 9440; + } + } + + if (__svgalib_driver_report) { + if(tvga_model == 9440) + fprintf(stderr,"Using Trident 9440 driver (%dK)\n", + tvga8900_memory); + else if(tvga_model == 9680) + fprintf(stderr,"Using Trident 9680 driver (%dK)\n", + tvga8900_memory); + else + fprintf(stderr,"Using Trident 8900/9000 driver (%dK, %sinterlaced).\n", + tvga8900_memory, (tvga8900_nonint) ? "non-" : ""); + } + __svgalib_driverspecs = &__svgalib_tvga8900_driverspecs; + setup_registers(); + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + return 0; +} diff --git a/src/drivers/unichrome.c b/src/drivers/unichrome.c new file mode 100644 index 0000000..b9be769 --- /dev/null +++ b/src/drivers/unichrome.c @@ -0,0 +1,549 @@ +/* +VIA Unichrome driver +*/ + +#include +#include /* for printf */ +#include /* for memset */ +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "vgarelvgaio.h" + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vgapci.h" + +static int unichrome_init(int, int, int); +static void unichrome_unlock(void); +static void unichrome_lock(void); + +static int unichrome_memory, unichrome_io_base; +static unsigned int unichrome_linear_base; + +static CardSpecs *cardspecs; +typedef struct { + unsigned char seq[0x50]; + unsigned char crt[0xc0]; +} UNIRegRec, *UNIRegPtr; + +enum { CLE266=1, CLE266CX, KM400, KM800, PM800} chiptype; + +//static void unichrome_setpage(int page) {} + +/* Fill in chipset specific mode information */ +static void unichrome_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = unichrome_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; + modeinfo->startaddressrange = unichrome_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + + if (modeinfo->bytesperpixel >= 1) { + if(unichrome_linear_base)modeinfo->flags |= CAPABLE_LINEAR; + } +} + +static int unichrome_saveregs(uint8_t regs[]) +{ + UNIRegPtr save; + int i; + + unichrome_unlock(); /* May be locked again by other programs (e.g. X) */ + + save=(UNIRegPtr)(regs+60); + + for(i=0x10; i<0x50; i++)save->seq[i]=__svgalib_inseq(i); + for(i=0x18; i<0xc0; i++)save->crt[i]=__svgalib_incrtc(i); + + + return sizeof(UNIRegRec); +} + +/* Set chipset-specific registers */ +void ViaSeqMask(int index, int value, int mask) { + int tmp; + + tmp = __svgalib_inseq(index); + tmp &= ~mask; + tmp |= (value & mask); + + __svgalib_outseq(index, tmp); +} + +static void unichrome_setregs(const uint8_t regs[], int mode) +{ + UNIRegPtr restore; + int i; + + unichrome_unlock(); /* May be locked again by other programs (eg. X) */ + + restore=(UNIRegPtr)(regs+60); + + __svgalib_outcrtc(0x6a, 0); + __svgalib_outcrtc(0x6b, 0); + __svgalib_outcrtc(0x6c, 0); + + for(i=0x14; i<=0x1f;i++) __svgalib_outseq(i, restore->seq[i]); + for(i=0x22; i<=0x2b;i++) __svgalib_outseq(i, restore->seq[i]); + __svgalib_outseq(0x2e, restore->seq[0x2e]); + for(i=0x44; i<=0x47;i++) __svgalib_outseq(i, restore->seq[i]); + + ViaSeqMask( 0x40, 0x06, 0x06); + ViaSeqMask( 0x40, 0x00, 0x06); + + for(i=0x32; i<=0x36;i++) __svgalib_outcrtc(i, restore->crt[i]); + for(i=0x50; i<=0xb7;i++) __svgalib_outcrtc(i, restore->crt[i]); + + +} + + +/* Return nonzero if mode is available */ +static int unichrome_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + if (unichrome_memory * 1024 < info->ydim * info->xbytes) + return 0; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if((modeinfo->bitsPerPixel==16)&&(modeinfo->greenWeight==5)) { + free(modeinfo); + return 0; + } + + modetiming = malloc(sizeof(ModeTiming)); + + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + + free(modetiming); + free(modeinfo); + + return SVGADRV; +} + +static int CalcPLL(int freq, int isBanshee); +/* Set a mode */ + +/* Local, called by unichrome_setmode(). */ + +static void unichrome_initializemode(uint8_t *moderegs, + ModeTiming * modetiming, ModeInfo * modeinfo, int mode) +{ /* int k; */ + + int vd,vt,vbs,vbe,ht,hd,hss,hse, of, tmp; + UNIRegPtr regs; + + regs=(UNIRegPtr)(moderegs+60); + + unichrome_saveregs(moderegs); + + __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); + + hd = (modetiming->CrtcHDisplay>>3)-1; + hss = (modetiming->CrtcHSyncStart>>3); + hse = (modetiming->CrtcHSyncEnd>>3); + ht = (modetiming->CrtcHTotal>>3)-5; + + regs->crt[0x33] = 0; + regs->crt[0x33] |= (hss&0x100)>>4; + regs->crt[0x33] |= (hse&0x040)>>1; + regs->crt[0x33] |= 7; /* line compare */ + + regs->crt[0x36] &= ~0x08; + regs->crt[0x36] |= (ht&0x100)>>5; + + vd = modetiming->CrtcVDisplay - 1; + vt = modetiming->CrtcVTotal - 2; + vbs = vd; + vbe = vt; + + regs->crt[0x35] &= ~0xef; + regs->crt[0x35] |= (vt&0x400)>>10; + regs->crt[0x35] |= (vbs&0x400)>>9; + regs->crt[0x35] |= (vd&0x400)>>8; + regs->crt[0x35] |= (vbe&0x400)>>7; + + of=modeinfo->lineWidth/8; + moderegs[VGA_CR13] = of&0xff; + regs->crt[0x35] |= (of&0x700)>>3; + + regs->crt[0x34] = 0; /* start address */ + + switch (modeinfo->bitsPerPixel) { + case 8: + regs->seq[0x15] = 0x22; + break; + case 15: + case 16:if(modeinfo->greenWeight==5){ + regs->seq[0x15] = 0xb6; + } else regs->seq[0x15] = 0xb6; + break; +// case 24: +// regs->vidProcCfg|=2<<18; +// break; + case 32: + regs->seq[0x15] = 0xae; + break; + default: + break; + } + + tmp=CalcPLL(modetiming->pixelClock, 0); + regs->seq[0x46] = tmp>>8; + regs->seq[0x47] = tmp&0xff; + +// moderegs[VGA_GR5]=0; + moderegs[VGA_MISCOUTPUT]|=0x0c; /* pixel clock = pllCtrl0 */ + + /* FIFO */ + regs->seq[0x17] = 0x1f; + regs->seq[0x1a] = 0x08; + + if(hd>=1600) { + regs->seq[0x16] = 0x0f; + regs->seq[0x18] = 0x4f; + } else if(hd>=1024) { + regs->seq[0x16] = 0x0c; + regs->seq[0x18] = 0x4c; + } else { + regs->seq[0x16] = 0x08; + regs->seq[0x18] = 0x4e; + } + + /* Fetch count */ + if(of&3)of=(of+3)&~3; + regs->seq[0x1c] = (of>>1)&0xff; + regs->seq[0x1d] = (of>>9)&0xff; + +} + +static int unichrome_setmode(int mode, int prv_mode) +{ + uint8_t *moderegs; + ModeTiming modetiming; + ModeInfo *modeinfo; + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + + if (!unichrome_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + if (__svgalib_getmodetiming(&modetiming, modeinfo, cardspecs)) { + free(modeinfo); + return 1; + } + + moderegs = malloc(sizeof(UNIRegRec) + 60); + + unichrome_initializemode(moderegs, &modetiming, modeinfo, mode); + + unichrome_setregs(moderegs, mode); /* Set extended regs. */ + __svgalib_setregs(moderegs); /* Set standard regs. */ + free(moderegs); + + free(modeinfo); + + return 0; +} + +/* Unlock chipset-specific registers */ + +static void unichrome_unlock(void) +{ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + __svgalib_outcrtc(0x47,__svgalib_incrtc(0x47)&0xfe); + __svgalib_outseq(0x10,__svgalib_inseq(0x10)|1); +} + +static void unichrome_lock(void) +{ + __svgalib_outseq(0x10,__svgalib_inseq(0x10)&0xfe); +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int unichrome_test(void) +{ + return !unichrome_init(0,0,0); +} + +/* Set display start address (not for 16 color modes) */ +/* Cirrus supports any address in video memory (up to 2Mb) */ + +static void unichrome_setdisplaystart(int address) +{ + __svgalib_outcrtc(0x23, ((address>>2) & 0xFF0000)>>16); + __svgalib_outcrtc(0x0c, ((address>>2) & 0x00FF00)>>8); + __svgalib_outcrtc(0x0d, (address>>2) & 0x00FF); +} + + +/* Set logical scanline length (usually multiple of 8) */ + +static void unichrome_setlogicalwidth(int width) +{ + int offset = width >> 3; + + __svgalib_outcrtc(0x13,offset&0xff); + __svgalib_outcrtc(0x35, (__svgalib_incrtc(0x35)&0x1f)| ((offset&0x700)>>3)); +} + +static int unichrome_linear(int op, int param) +{ + if (op==LINEAR_DISABLE || op==LINEAR_ENABLE) return 0; + if (op==LINEAR_QUERY_BASE) return unichrome_linear_base; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + return -1; /* Unknown function. */ +} + +static int unichrome_match_programmable_clock(int clock) +{ +return clock ; +} + +static int unichrome_map_clock(int bpp, int clock) +{ +return clock ; +} + +static int unichrome_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} + +static unsigned int cur_colors[16*2]; + +static int unichrome_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j; + unsigned int *b3; + unsigned int l1, l2; + + switch(cmd){ + case CURSOR_INIT: + return 1; + case CURSOR_HIDE: + port_outl_r(unichrome_io_base+0x5c,port_inl(unichrome_io_base+0x5c)&~(1<<27)); + break; + case CURSOR_SHOW: + port_outl_r(unichrome_io_base+0x5c,port_inl(unichrome_io_base+0x5c)|(1<<27)); + break; + case CURSOR_POSITION: + port_outl_r(unichrome_io_base+0x64,((p2+64)<<16)|(p1+64)); + break; + case CURSOR_SELECT: + i=unichrome_memory*1024-(p1+1)*4096; + port_outl_r(unichrome_io_base+0x68,cur_colors[p1*2]); + port_outl_r(unichrome_io_base+0x6c,cur_colors[p1*2+1]); + port_outl_r(unichrome_io_base+0x60,i); + break; + case CURSOR_IMAGE: + i=unichrome_memory*1024-(p1+1)*4096; + b3=(unsigned int *)p5; + switch(p2) { + case 0: + cur_colors[p1*2]=p3; + cur_colors[p1*2+1]=p4; + for(j=0;j<32;j++) { + l2=*(b3+j); + l1=*(b3+32+j); + /*change endianess */ + l1=(l1<<24)|(l1>>24)|((l1>>8)&0xff00)|((l1<<8)&0xff0000); + l2=(l2<<24)|(l2>>24)|((l2>>8)&0xff00)|((l2<<8)&0xff0000); + *(unsigned int *)(LINEAR_POINTER+i+16*j)=l1; + *(unsigned int *)(LINEAR_POINTER+i+16*j+4)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+8)=l2; + *(unsigned int *)(LINEAR_POINTER+i+16*j+12)=0; + } + for(j=32;j<64;j++) { + *(unsigned int *)(LINEAR_POINTER+i+16*j)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+4)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+8)=0; + *(unsigned int *)(LINEAR_POINTER+i+16*j+12)=0; + } + break; + } + break; + } + return 0; +} + +/* Function table (exported) */ + +DriverSpecs __svgalib_unichrome_driverspecs = +{ + unichrome_saveregs, + unichrome_setregs, + unichrome_unlock, + unichrome_lock, + unichrome_test, + unichrome_init, +// unichrome_setpage, + NULL, + NULL, + NULL, + unichrome_setmode, + unichrome_modeavailable, + unichrome_setdisplaystart, + unichrome_setlogicalwidth, + unichrome_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + unichrome_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ + unichrome_cursor +}; + +/* Initialize chipset (called after detection) */ + +static int unichrome_init(int force, int par1, int par2) +{ + unsigned int buf[64]; + int found=0; + + if (force) { + unichrome_memory = par1; + chiptype = par2; + } else { + + }; + + found=(__svgalib_pci_find_vendor_vga_pos(0x1106,buf))&& ( + ((buf[0]>>16)==0x3108)|| + ((buf[0]>>16)==0x3118)|| + ((buf[0]>>16)==0x3122)|| + ((buf[0]>>16)==0x7205)); + if(!found) return 1; + + switch(buf[0]>>16) { + case 0x3122: + if((buf[3]&0xff)<0x10) chiptype=CLE266; else chiptype=CLE266CX; +// unichrome_memory=1024*__svgalib_inseq(0x34); + break; + case 0x3108: + chiptype=KM800; + break; + case 0x3118: + chiptype=PM800; + break; + case 0x7205: + chiptype=KM400; + break; + } + + if (found){ + unichrome_linear_base=buf[4]&0xffffff00; +// unichrome_io_base=buf[6]&0xff00; +// __svgalib_io_reloc=unichrome_io_base-0x300; +// __svgalib_rel_io_mapio(); + }; + + if(unichrome_memory==0) { + unichrome_memory = 16384; + } + + unichrome_unlock(); + + if (__svgalib_driver_report) { + fprintf(stderr,"Using VIA Unichrome driver, %iKB.\n",unichrome_memory); + } + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = unichrome_memory; + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = 270000; + cardspecs->maxPixelClock16bpp = 270000; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 270000; + cardspecs->flags = CLOCK_PROGRAMMABLE | NO_INTERLACE; + cardspecs->maxHorizontalCrtc = 2040; + cardspecs->nClocks = 0; + cardspecs->mapClock = unichrome_map_clock; + cardspecs->mapHorizontalCrtc = unichrome_map_horizontal_crtc; + cardspecs->matchProgrammableClock=unichrome_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_unichrome_driverspecs; + __svgalib_linear_mem_base=unichrome_linear_base; + __svgalib_linear_mem_size=unichrome_memory*0x400; + __svgalib_emulatepage = 2; + return 0; +} + +#define REFFREQ 14318 + +static int +CalcPLL(int freq, int isBanshee) { + int m, n, k, best_m, best_n, best_k, f_cur, best_error; + int minm, maxm, minn, maxn; + + best_error=freq; + best_n=best_m=best_k=0; + + minm=3; + maxm=16; + minn=0x13; + maxn=0x79; + + for (n=minn; nmaxm) { + k++; + m/=2; + } + + while( (k<4) && ((m&1)==0) && (f_cur/m<160000)) { + k++; + m/=2; + } + + if( k>3 || (m>maxm) || (m0, 2<>1. */ +#define FIFO_SWAP_INHW 0x08 /* FIFO. Swap bytes 3<>2, 1<>0. */ +#define FIFO_SWAP_HW 0x0c /* FIFO. Swap half-words. */ +#define FIFOINFREE 0x40 /* Input FIFO free entry count. */ +#define FIFOOUTVALID 0x41 /* Output FIFO valid entry count. */ +#define COMM 0x42 /* dual 4 bit communications ports */ +#define MEMENDIAN 0x43 /* set byte swapping on PCI mem accesses */ +#define INTR 0x44 /* which interrupts occurred */ +#define INTREN 0x46 /* enable different interrupts */ +#define DEBUGREG 0x48 /* soft resets, RISC hold/single step */ +#define LOWWATERMARK 0x49 /* Input FIFO low water mark for interrupt */ +#define STATUS 0x4A /* specifies which blocks of the V2000 are busy */ +#define XBUSCTL 0x4B /* XBus control register */ +#define PCITEST 0x4C /* PCI test */ +#define DMACMDPTR 0x50 /* DMA command list pointer */ +#define DMA_ADDRESS 0x54 /* DMA data address */ +#define DMA_COUNT 0x58 /* DMA remaining transfer count */ +#define STATEINDEX 0x60 /* state index info */ +#define STATEDATA 0x64 /* state data info */ +#define SCLKPLL 0x68 /* system clock PLL control register */ +#define SCRATCH 0x70 /* 16-bit BIOS scratch space */ +#define MODEREG 0x72 /* Mode -- to differentiate from old MODE */ +#define MODE_ MODEREG +#define MODE MODEREG +#define BANKSELECT 0x74 /* Local memory to A0000 mapping */ +#define BANKSELECT_PHYSADDR ((unsigned long)(0xA0000)) +#define CRTCTEST 0x80 /* CRTC test register */ +#define CRTCCTL 0x84 /* CRTC mode */ +#define CRTCHORZ 0x88 /* CRTC horizontal timing */ +#define CRTCVERT 0x8c /* CRTC vertical timing */ +#define FRAMEBASEB 0x90 /* Stereoscopic frame base b address */ +#define FRAMEBASEA 0x94 /* Frame base A address */ +#define CRTCOFFSET 0x98 /* CRTC StrideOffset */ +#define CRTCSTATUS 0x9c /* CRTC video scan position */ +#define DRAMCTL 0xa0 /* DRAM timing */ +#define MEMDIAG 0xa4 /* Memory diagnostic register #1 */ +#define CURSORBASE 0xac /* cursor base address bits [23:10] aligne to 1024 byte boundary */ +#define PALETTE 0xb0 /* Access to DAC */ +#define PCLKPLL 0xc0 /* external device 0 */ +#define VINEVENBASE 0xd0 /* video input even field base address */ +#define VINODDBASE 0xd4 /* video input odd field base address */ +#define WRITEINTR0ADDR 0xd8 /* Memory write interrupt address0 */ +#define WRITEINTR1ADDR 0xdc /* Memory write interrupt address1 */ +#define DEVICE0_V2x000 0xf0 /* external device 1 (PLL) */ + +/* + * PCLKPLL/SCLKPLL register bit defn + */ +#define PCLKPLLPMASK 0xffffe1ff +#define SCLKPLLPMASK 0xffffe1ff +#define MCLKPLLPMASK 0xfffe1fff +#define PLLPCLKP 9 +#define PLLSCLKP 9 +#define PLLMCLKP 13 +#define PLLPCLKN 13 +#define PLLSCLKN 17 +#define PLLPCLKDOUBLE 26 /* bit 26 in PClkPLL register */ + +#define DIRECTPCLKMASK 0x00400000 +#define DIRECTMCLKMASK 0x00800000 + +#define VGASTDCLOCK 0x100000 +#define EXTRADIV2 0x200000 + +#define PLLINCLKFREQ 14318 /* PLL input clk freq in KHz */ + +/* + * memory controller + */ +#define MCLK_BYPASSEDGEFREQ 90000 /* in KHz */ + +/* + * Microcode commands + */ +#define CMD_SETPALETTE 0x21 + +/* + * MMIO registers + */ + +#define MMIO_FIFOINFREE 0x20040 +#define MMIO_COMM 0x20042 +#define MMIO_FIFOOUTVALID 0x20041 +#define MMIO_INTR 0x20044 /* which interrupts occurred */ +#define MMIO_DMACMDPTR 0x20050 +#define MMIO_CRTCHORZ 0x20088 /* CRTC horizontal timing */ +#define MMIO_CRTCVERT 0x2008c /* CRTC vertical timing */ +#define MMIO_CRTCSTATUS 0x2009c +#define MMIO_DACRAMWRITEADR 0x200b0 /* Palette Write Index */ +#define MMIO_DACRAMDATA 0x200b1 /* Palette Data */ +#define MMIO_VINEVENBASE 0x200d0 /* video input even field base address */ +#define MMIO_VINODDBASE 0x200d4 /* video input odd field base address */ +#define MMIO_WRITEINTR0ADDR 0x200d8 /* Memory write interrupt address0 */ +#define MMIO_WRITEINTR1ADDR 0x200dc /* Memory write interrupt address1 */ + +/* IO register flag bits */ +/* _MASK defined for multi-bit values */ +/* _ADDR defined for registers accessible from RISC */ + +/* COMM */ +#define SYSSTATUS_MASK 0x0f /* host->RISC comm */ +#define SYSSTATUS_SHIFT 0 +#define RISCSTATUS_MASK 0xf0 /* RISC->host comm r/o */ +#define RISCSTATUS_SHIFT 4 + +/* MEMENDIAN */ +#define MEMENDIAN_NO 0 /* No byte swap. */ +#define MEMENDIAN_END 1 /* Swap bytes 3<>0, 2<>1. */ +#define MEMENDIAN_INHW 2 /* Swap bytes 3<>2, 1<>0. */ +#define MEMENDIAN_HW 3 /* Swap half-words. */ +#define MEMENDIAN_MASK 3 +#define MEMENDIAN_SHIFT 0 + +#define DMABUSY 0x80 /* DMA busy r/o */ +#define DMACMDPTR_DMABUSY 0x1 /* corresponding bit in other reg */ + +/* INTR */ +#define VERTINTR 0x01 /* vert retrace */ +#define FIFOLOWINTR 0x02 /* free entries rose above low water */ +#define RISCINTR 0x04 /* RISC firmware interrupt */ +#define HALTINTR 0x08 /* RISC halted */ +#define FIFOERRORINTR 0x10 /* FIFO under/over flow */ +#define DMAERRORINTR 0x20 /* PCI error during DMA */ +#define DMAINTR 0x40 /* DMA done interrupt */ +#define XINTR 0x80 /* external device pass thru intr */ +#define VIDEOINEVENINTR 0x100 /* Video input even field interrupt */ +#define VIDEOINODDINTR 0x100 /* Video input even field interrupt */ + +/* INTREN */ +#define VERTINTREN 0x01 /* vert retrace */ +#define FIFOLOWINTREN 0x02 /* free entries rose above low water */ +#define RISCINTREN 0x04 /* RISC firmware interrupt */ +#define HALTINTREN 0x08 /* RISC halted */ +#define FIFOERRORINTREN 0x10 /* FIFO under/over flow */ +#define DMAERRORINTREN 0x20 /* PCI error during DMA */ +#define DMAINTREN 0x40 /* DMA done interrupt */ +#define XINTREN 0x80 /* external device pass thru intr */ + +/* DEBUG */ +#define SOFTRESET 0x01 /* soft reset chip */ +#define HOLDRISC 0x02 /* stop RISC when set */ +#define STEPRISC 0x04 /* single step RISC */ +#define DIRECTSCLK 0x08 /* disable internal divide by 2 for sys clk */ +#define SOFTVGARESET 0x10 /* assert VGA reset */ +#define SOFTXRESET 0x20 /* assert XReset output to ext devices */ + +/* MODE_ register */ +#define VESA_MODE 0x01 /* enable 0xA0000 in native mode */ +#define VGA_MODE 0x02 /* VGA mode if set else native mode */ +#define VGA_32 0x04 /* enable VGA 32 bit accesses */ +#define DMA_EN 0x08 /* enable DMA accesses */ + +#define NATIVE_MODE 0 /* not VESA and not VGA */ + +/* DRAM register */ +#define DRAMCTL_ADDR 0xffe00500 + +/* CRTC registers */ +#define CRTCTEST_ADDR 0xffe00400 +#define CRTCCTL_ADDR 0xffe00420 +#define CRTCHORZ_ADDR 0xffe00440 +#define CRTCVERT_ADDR 0xffe00460 +#define FRAMEBASEB_ADDR 0xffe00480 +#define FRAMEBASEA_ADDR 0xffe004a0 +#define CRTCOFFSET_ADDR 0xffe004c0 +#define CRTCSTATUS_ADDR 0xffe004e0 + +#define CRTCTEST_VIDEOLATENCY_MASK 0x1F +#define CRTCTEST_NOTVBLANK 0x10000 +#define CRTCTEST_VBLANK 0x40000 + +#define CRTCCTL_SCRNFMT_MASK 0xF +#define CRTCCTL_VIDEOFIFOSIZE128 0x10 +#define CRTCCTL_ENABLEDDC 0x20 +#define CRTCCTL_DDCOUTPUT 0x40 +#define CRTCCTL_DDCDATA 0x80 +#define CRTCCTL_VSYNCHI 0x100 +#define CRTCCTL_HSYNCHI 0x200 +#define CRTCCTL_VSYNCENABLE 0x400 +#define CRTCCTL_HSYNCENABLE 0x800 +#define CRTCCTL_VIDEOENABLE 0x1000 +#define CRTCCTL_STEREOSCOPIC 0x2000 +#define CRTCCTL_FRAMEDISPLAYED 0x4000 +#define CRTCCTL_FRAMEBUFFERBGR 0x8000 +#define CRTCCTL_EVENFRAME 0x10000 +#define CRTCCTL_LINEDOUBLE 0x20000 +#define CRTCCTL_FRAMESWITCHED 0x40000 +#define CRTCCTL_VIDEOFIFOSIZE256 0x800010 + +#define CRTCHORZ_ACTIVE_MASK 0xFF +#define CRTCHORZ_ACTIVE_SHIFT 0 +#define CRTCHORZ_BACKPORCH_MASK 0x7E00 +#define CRTCHORZ_BACKPORCH_SHIFT 11 +#define CRTCHORZ_SYNC_MASK 0x1F0000L +#define CRTCHORZ_SYNC_SHIFT 16 +#define CRTCHORZ_FRONTPORCH_MASK 0xE00000L +#define CRTCHORZ_FRONTPORCH_SHIFT 20 + +#define CRTCVERT_ACTIVE_MASK 0x7FF +#define CRTCVERT_BACKPORCH_MASK 0x1F800 +#define CRTCVERT_SYNC_MASK 0xE0000 +#define CRTCVERT_FRONTPORCH_MASK 0x03F00000 + +#define CRTCOFFSET_MASK 0xFFFF + +#define CRTCSTATUS_HORZCLOCKS_MASK 0xFF +#define CRTCSTATUS_HORZ_MASK 0x600 +#define CRTCSTATUS_HORZ_FPORCH 0x200 +#define CRTCSTATUS_HORZ_SYNC 0x600 +#define CRTCSTATUS_HORZ_BPORCH 0x400 +#define CRTCSTATUS_HORZ_ACTIVE 0x000 +#define CRTCSTATUS_SCANLINESLEFT_MASK 0x003FF800 +#define CRTCSTATUS_VERT_MASK 0xC00000 +#define CRTCSTATUS_VERT_FPORCH 0x400000 +#define CRTCSTATUS_VERT_SYNC 0xC00000 +#define CRTCSTATUS_VERT_BPORCH 0x800000 +#define CRTCSTATUS_VERT_ACTIVE 0x000000 + +/* RAMDAC registers - avail through I/O space */ + +#define DACRAMWRITEADR 0xb0 +#define DACRAMDATA 0xb1 +#define DACPIXELMSK 0xb2 +#define DACRAMREADADR 0xb3 +#define DACOVSWRITEADR 0xb4 +#define DACOVSDATA 0xb5 +#define DACCOMMAND0 0xb6 +#define DACOVSREADADR 0xb7 +#define DACCOMMAND1 0xb8 +#define DACCOMMAND2 0xb9 +#define DACSTATUS 0xba +#define DACCOMMAND3 0xba /* accessed via unlocking/indexing */ +#define DACCURSORDATA 0xbb +#define DACCURSORXLOW 0xbc +#define DACCURSORXHIGH 0xbd +#define DACCURSORYLOW 0xbe +#define DACCURSORYHIGH 0xbf + +#define BT_CO_COLORWR_ADDR DACOVSWRITEADR +#define BT_CO_COLORDATA DACOVSDATA +#define BT_PTR_ROWOFFSET 32 +#define BT_PTR_COLUMNOFFSET 32 + +/* PCLKPLL register */ +#define PLLDEV DEVICE0 +#define VOUTEN 0x00080000L /* bit 19 */ +#define VGASCLKOVER2 0x00100000L /* bit 20 */ +#define PCLKSTARTEN 0x00800000L /* bit 23 */ + +/* Some state indices */ +#define STATEINDEX_IR 128 +#define STATEINDEX_PC 129 +#define STATEINDEX_S1 130 + +/* PCI configuration registers. */ +#define CONFIGIOREG 0xE0000014 +#define CONFIGENABLE 0xE0000004 +#ifdef USEROM +#define CONFIGROMREG 0xE0000030 +#endif + +/* Cache parameters. */ +#define ICACHESIZE 2048 /* I cache size. */ +#define ICACHELINESIZE 32 /* I cache line size. */ +#ifndef ICACHE_ONOFF_MASK +#define ICACHE_ONOFF_MASK (((v_u32)1<<17)|(1<<3)) +#define ICACHE_ON ((0<<17)|(0<<3)) +#define ICACHE_OFF (((v_u32)1<<17)|(1<<3)) +#endif + +/* Video registers */ +#define BT829_DEV DEVICE0 +#define VIDEO_DECODER_DEV_ENABLE 0x4 +#define VIDEO_DECODER_DEV_DISABLE 0x0 + +#define VINBASE_MASK 0x1FFFFFL +#define VINMAXVERT_SHIFT 24 +#define VINSTRIDE_SHIFT 27 +#define VINQSIZE_SHIFT 30 + +#define VINORDER_SHIFT 24 +#define ACTIVE_LOW 0 +#define ACTIVE_HI 1L +#define VINHSYNCHI_SHIFT 26 +#define VINVSYNCHI_SHIFT 27 +#define VINACTIVE_SHIFT 28 +#define VINNOODD_SHIFT 29 +#define VINENABLE_SHIFT 30 + +/* directly accessable RAMDAC registers */ +#define BT485_WRITE_ADDR 0x00 +#define BT485_RAMDAC_DATA 0x01 +#define BT485_PIXEL_MASK 0x02 +#define BT485_READ_ADDR 0x03 +#define BT485_CURS_WR_ADDR 0x04 +#define BT485_CURS_DATA 0x05 +#define BT485_COMMAND_REG_0 0x06 +#define BT485_CURS_RD_ADDR 0x07 +#define BT485_COMMAND_REG_1 0x08 +#define BT485_COMMAND_REG_2 0x09 +#define BT485_STATUS_REG 0x0a +#define BT485_CURS_RAM_DATA 0x0b +#define BT485_CURS_X_LOW 0x0c +#define BT485_CURS_X_HIGH 0x0d +#define BT485_CURS_Y_LOW 0x0e +#define BT485_CURS_Y_HIGH 0x0f + +/* indirectly accessable ramdac registers */ +#define BT485_COMMAND_REG_3 0x01 + +/* bits in command register 0 */ +#define BT485_CR0_EXTENDED_REG_ACCESS 0x80 +#define BT485_CR0_SCLK_SLEEP_DISABLE 0x40 +#define BT485_CR0_BLANK_PEDESTAL 0x20 +#define BT485_CR0_SYNC_ON_BLUE 0x10 +#define BT485_CR0_SYNC_ON_GREEN 0x08 +#define BT485_CR0_SYNC_ON_RED 0x04 +#define BT485_CR0_8_BIT_DAC 0x02 +#define BT485_CR0_SLEEP_ENABLE 0x01 + +/* bits in command register 1 */ +#define BT485_CR1_24BPP 0x00 +#define BT485_CR1_16BPP 0x20 +#define BT485_CR1_8BPP 0x40 +#define BT485_CR1_4BPP 0x60 +#define BT485_CR1_1BPP 0x80 +#define BT485_CR1_BYPASS_CLUT 0x10 +#define BT485_CR1_565_16BPP 0x08 +#define BT485_CR1_555_16BPP 0x00 +#define BT485_CR1_1_TO_1_16BPP 0x04 +#define BT485_CR1_2_TO_1_16BPP 0x00 +#define BT485_CR1_PD7_PIXEL_SWITCH 0x02 +#define BT485_CR1_PIXEL_PORT_CD 0x01 +#define BT485_CR1_PIXEL_PORT_AB 0x00 + +/* bits in command register 2 */ +#define BT485_CR2_SCLK_DISABLE 0x80 +#define BT485_TEST_PATH_SELECT 0x40 +#define BT485_PIXEL_INPUT_GATE 0x20 +#define BT485_PIXEL_CLK_SELECT 0x10 +#define BT485_INTERLACE_SELECT 0x08 +#define BT485_16BPP_CLUT_PACKED 0x04 +#define BT485_X_WINDOW_CURSOR 0x03 +#define BT485_2_COLOR_CURSOR 0x02 +#define BT485_3_COLOR_CURSOR 0x01 +#define BT485_DISABLE_CURSOR 0x00 +#define BT485_CURSOR_MASK 0x03 + +/* bits in command register 3 */ +#define BT485_4BPP_NIBBLE_SWAP 0x10 +#define BT485_CLOCK_DOUBLER 0x08 +#define BT485_64_BY_64_CURSOR 0x04 +#define BT485_32_BY_32_CURSOR 0x00 +#define BT485_SIZE_MASK 0x04 + +/* special constants for the Brooktree BT485 RAMDAC */ +#define BT485_INPUT_LIMIT 110000000 + +typedef enum { + V_PIXFMT_DSTFMT=0, + V_PIXFMT_332=1, /**/ +#define V_PIXFMT_233 V_PIXFMT_332 + V_PIXFMT_8I=2, /**/ + V_PIXFMT_8A=3, + V_PIXFMT_565=4, /**/ + V_PIXFMT_4444=5, /**/ + V_PIXFMT_1555=6, /**/ + /* 7 reserved */ + V_PIXFMT_4I_565=8, + V_PIXFMT_4I_4444=9, + V_PIXFMT_4I_1555=10, + /* 11 reserved */ + V_PIXFMT_8888=12, /**/ + V_PIXFMT_Y0CRY1CB=13 +#define V_PIXFMT_Y0CBY1CR V_PIXFMT_Y0CRY1CB + /* 14 reserved */ + /* 15 reserved */ +} vpixfmt; + diff --git a/src/drivers/vbe.h b/src/drivers/vbe.h new file mode 100644 index 0000000..2bb51e8 --- /dev/null +++ b/src/drivers/vbe.h @@ -0,0 +1,119 @@ +/* +Copyright (C) 1996 by Josh Vanderhoof + +You are free to distribute and modify this file, as long as you +do not remove this copyright notice and clearly label modified +versions as being modified. + +This software has NO WARRANTY. Use it at your own risk. +*/ + +#ifndef _VBE_H +#define _VBE_H + +/* structures for vbe 2.0 */ + +struct vbe_info_block + { + char vbe_signature[4]; + short vbe_version; + unsigned short oem_string_off; + unsigned short oem_string_seg; + int capabilities; + unsigned short video_mode_list_off; + unsigned short video_mode_list_seg; + short total_memory; + short oem_software_rev; + unsigned short oem_vendor_name_off; + unsigned short oem_vendor_name_seg; + unsigned short oem_product_name_off; + unsigned short oem_product_name_seg; + unsigned short oem_product_rev_off; + unsigned short oem_product_rev_seg; + char reserved[222]; + char oem_data[256]; + } __attribute__ ((packed)); + +#define VBE_ATTR_MODE_SUPPORTED (1 << 0) +#define VBE_ATTR_TTY (1 << 2) +#define VBE_ATTR_COLOR (1 << 3) +#define VBE_ATTR_GRAPHICS (1 << 4) +#define VBE_ATTR_NOT_VGA (1 << 5) +#define VBE_ATTR_NOT_WINDOWED (1 << 6) +#define VBE_ATTR_LINEAR (1 << 7) + +#define VBE_WIN_RELOCATABLE (1 << 0) +#define VBE_WIN_READABLE (1 << 1) +#define VBE_WIN_WRITEABLE (1 << 2) + +#define VBE_MODEL_TEXT 0 +#define VBE_MODEL_CGA 1 +#define VBE_MODEL_HERCULES 2 +#define VBE_MODEL_PLANAR 3 +#define VBE_MODEL_PACKED 4 +#define VBE_MODEL_256 5 +#define VBE_MODEL_RGB 6 +#define VBE_MODEL_YUV 7 + +struct vbe_mode_info_block + { + unsigned short mode_attributes; + uint8_t win_a_attributes; + uint8_t win_b_attributes; + unsigned short win_granularity; + unsigned short win_size; + unsigned short win_a_segment; + unsigned short win_b_segment; + unsigned short win_func_ptr_off; + unsigned short win_func_ptr_seg; + unsigned short bytes_per_scanline; + unsigned short x_resolution; + unsigned short y_resolution; + uint8_t x_char_size; + uint8_t y_char_size; + uint8_t number_of_planes; + uint8_t bits_per_pixel; + uint8_t number_of_banks; + uint8_t memory_model; + uint8_t bank_size; + uint8_t number_of_image_pages; + uint8_t res1; + uint8_t red_mask_size; + uint8_t red_field_position; + uint8_t green_mask_size; + uint8_t green_field_position; + uint8_t blue_mask_size; + uint8_t blue_field_position; + uint8_t rsvd_mask_size; + uint8_t rsvd_field_position; + uint8_t direct_color_mode_info; + unsigned int phys_base_ptr; + unsigned int offscreen_mem_offset; + unsigned short offscreen_mem_size; + uint8_t res2[206]; + } __attribute__ ((packed)); + +struct vbe_palette_entry + { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t align; + } __attribute__ ((packed)); + +/* CRTC Info Block */ +struct vbe_crtc_info_block +{ + unsigned short horiz_total; + unsigned short horiz_start; + unsigned short horiz_end; + unsigned short vert_total; + unsigned short vert_start; + unsigned short vert_end; + uint8_t flags; + unsigned int pixel_clock; + unsigned short refresh_rate; + uint8_t reserved[40]; +} __attribute__ ((packed)); + +#endif diff --git a/src/drivers/vesa.c b/src/drivers/vesa.c new file mode 100644 index 0000000..904fed6 --- /dev/null +++ b/src/drivers/vesa.c @@ -0,0 +1,620 @@ +/* +*/ + +#include +#include /* for printf */ +#include /* for memset */ +#include +#include /* for mmap */ +#include +#include "lrmi.h" +#include "libvga.h" +#include "driver.h" + +/* New style driver interface. */ +#include "timing.h" +#include "vgaregs.h" +#include "interface.h" +#include "vbe.h" +#define VESAREG_SAVE(i) (VGA_TOTAL_REGS+i) +#define VESA_TOTAL_REGS (VGA_TOTAL_REGS + 4024) + +/* #define VESA_savebitmap 0x0e */ +int __svgalib_VESA_savebitmap=0x0e; +int __svgalib_VESA_textmode=3; + +static int vesa_init(int, int, int); +static void vesa_unlock(void); + +static int vesa_memory,vesa_chiptype; +static int vesa_is_linear, vesa_logical_width, vesa_bpp, vesa_granularity; +static int vesa_regs_size, vesa_linear_base, vesa_last_mode_set; +static struct LRMI_regs vesa_r; +static int vesa_read_write, vesa_read_window, vesa_write_window; +static void * LRMI_mem1, * LRMI_mem2; + +static CardSpecs *cardspecs; +static struct + { + struct vbe_info_block *info; + struct vbe_mode_info_block *mode; + } vesa_data; + +static int SVGALIB_VESA[__GLASTMODE+1]; + +static struct vbe_crtc_info_block *vesa_crtc; + +static void vesa_setpage(int page) +{ +vesa_r.eax=0x4f05; +vesa_r.ebx=0; +vesa_r.edx=page*64/vesa_granularity; +__svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + +if(vesa_read_write){ + vesa_r.eax=0x4f05; + vesa_r.ebx=1; + vesa_r.edx=page*64/vesa_granularity; + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); +}; +} + +/* Fill in chipset specific mode information */ + +static void vesa_getmodeinfo(int mode, vga_modeinfo *modeinfo) +{ + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.getmodeinfo(mode, modeinfo); + + if(modeinfo->colors==16)return; + + modeinfo->maxpixels = vesa_memory*1024/modeinfo->bytesperpixel; + modeinfo->maxlogicalwidth = 4088; /* just a guess, */ + modeinfo->startaddressrange = vesa_memory * 1024 - 1; + modeinfo->haveblit = 0; + modeinfo->flags &= ~HAVE_RWPAGE; + modeinfo->flags |= vesa_read_write; /* sets HAVE_RWPAGE bit */ + + /* for linear need VBE2 */ + if((vesa_chiptype>=1) && (modeinfo->bytesperpixel >= 1)) { + modeinfo->flags |= CAPABLE_LINEAR; + } + + /* to get the logical scanline width */ + memset(&vesa_r, 0, sizeof(vesa_r)); + + vesa_r.eax = 0x4f01; + vesa_r.ecx = SVGALIB_VESA[mode]; + vesa_r.es = (unsigned int)vesa_data.mode >> 4; + vesa_r.edi = (unsigned int)vesa_data.mode & 0xf; + + if (!__svgalib_LRMI_callbacks->rm_int(0x10, &vesa_r)) { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return; + } + modeinfo->linewidth = vesa_data.mode->bytes_per_scanline; +} + +/* Read and save chipset-specific registers */ +static int vesa_saveregs(uint8_t regs[]) +{ + void * buf; + buf=LRMI_mem1; + vesa_r.eax=0x4f04; + vesa_r.ebx=0; + vesa_r.es=((long)buf)>>4; + vesa_r.edx=1; + vesa_r.ecx=__svgalib_VESA_savebitmap; + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + memcpy(®s[VGA_TOTAL_REGS],buf,vesa_regs_size); + + return vesa_regs_size; +} + +/* Set chipset-specific registers */ + +static void vesa_setregs(const uint8_t regs[], int mode) +{ + + void * buf; + buf=LRMI_mem1; + memcpy(buf,®s[VGA_TOTAL_REGS],vesa_regs_size); + vesa_r.eax=0x4f04; + vesa_r.ebx=0; + vesa_r.es=((long)buf)>>4; + vesa_r.edx=2; + vesa_r.ecx=__svgalib_VESA_savebitmap; + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); +} + + +/* Return nonzero if mode is available */ + +static int vesa_modeavailable(int mode) +{ + struct vgainfo *info; + ModeTiming *modetiming; + ModeInfo *modeinfo; + + + if (IS_IN_STANDARD_VGA_DRIVER(mode)) + return __svgalib_vga_driverspecs.modeavailable(mode); + + info = &__svgalib_infotable[mode]; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + modetiming = malloc(sizeof(ModeTiming)); + if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { + free(modetiming); + free(modeinfo); + return 0; + } + free(modetiming); + free(modeinfo); + +return SVGALIB_VESA[mode]; +} + +/* Set CRTC info related registers when setting video mode */ +static void vesa_set_crtc_info_regs( void ) +{ + if (vesa_chiptype >= 2) + { + vesa_r.ebx |= 0x0800; + vesa_r.es = (unsigned int)vesa_crtc >> 4; + vesa_r.edi = (unsigned int)vesa_crtc & 0xf; + } +} + + + +static int vesa_setmode(int mode, int prv_mode) +{ + vesa_bpp=1; + vesa_granularity=1; + if (IS_IN_STANDARD_VGA_DRIVER(mode)) { + + if(__svgalib_vesatext){ + vesa_r.eax=0x4f02; /* make sure we are in a regular VGA mode before we start */ + vesa_r.ebx=__svgalib_VESA_textmode; /* without this, if we start in SVGA mode the result might */ + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); /* be something weird */ + }; + return __svgalib_vga_driverspecs.setmode(mode, prv_mode); + } + if (!vesa_modeavailable(mode)) return 1; + vesa_r.eax=0x4f02; + vesa_r.ebx=SVGALIB_VESA[mode]|0x8000|(vesa_is_linear*0x4000); + + /* Set timing information */ + if (vesa_chiptype >= 2) + { + ModeTiming *modetiming; + ModeInfo *modeinfo; + + /* Get mode timing */ + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + modetiming = malloc(sizeof(ModeTiming)); + if (!__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) + { + /* Fill VBE Timing structure */ + memset(vesa_crtc, 0, sizeof(*vesa_crtc)); + vesa_crtc->horiz_start = modetiming->HSyncStart; + vesa_crtc->horiz_end = modetiming->HSyncEnd; + vesa_crtc->horiz_total = modetiming->HTotal; + vesa_crtc->vert_start = modetiming->VSyncStart; + vesa_crtc->vert_end = modetiming->VSyncEnd; + vesa_crtc->vert_total = modetiming->VTotal; + vesa_crtc->pixel_clock = modetiming->pixelClock * 1000; + vesa_crtc->refresh_rate = (unsigned short) + (100 * (vesa_crtc->pixel_clock / + (vesa_crtc->vert_total * vesa_crtc->horiz_total))); + } + free(modetiming); + free(modeinfo); + } + vesa_set_crtc_info_regs(); + vesa_last_mode_set=vesa_r.ebx; + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + + vesa_data.info = LRMI_mem2 ; + vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1); + vesa_r.eax = 0x4f01; + vesa_r.ecx=SVGALIB_VESA[mode]; + vesa_r.es = (unsigned int)vesa_data.mode >> 4; + vesa_r.edi = (unsigned int)vesa_data.mode&0xf; + __svgalib_LRMI_callbacks->rm_int(0x10, &vesa_r); + vesa_logical_width=vesa_data.mode->bytes_per_scanline; + vesa_bpp=(vesa_data.mode->bits_per_pixel+7)/8; + if(vesa_logical_width==0) vesa_logical_width=vesa_bpp*vesa_data.mode->x_resolution; + /* if not reported then guess */ + vesa_granularity=vesa_data.mode->win_granularity; + if(vesa_granularity==0)vesa_granularity=64; /* if not reported then guess */ + if(vesa_chiptype>=1)vesa_linear_base=vesa_data.mode->phys_base_ptr; + vesa_read_write=0; + vesa_read_window=0; + vesa_write_window=0; + if((vesa_data.mode->win_a_attributes&6)!=6){ + vesa_read_write=1; + if ((vesa_data.mode->win_b_attributes&2) == 2) vesa_read_window=1; + if ((vesa_data.mode->win_b_attributes&4) == 4) vesa_write_window=1; + } + return 0; +} + + +/* Unlock chipset-specific registers */ + +static void vesa_unlock(void) +{ +} + + +/* Relock chipset-specific registers */ +/* (currently not used) */ + +static void vesa_lock(void) +{ +} + + +/* Indentify chipset, initialize and return non-zero if detected */ + +static int vesa_test(void) +{ + __svgalib_LRMI_callbacks->rm_init(); + LRMI_mem2 = __svgalib_LRMI_callbacks->rm_alloc_real(sizeof(struct vbe_info_block) + + sizeof(struct vbe_mode_info_block)); + vesa_data.info = LRMI_mem2; + vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1); + vesa_r.eax = 0x4f00; + vesa_r.es = (unsigned int)vesa_data.info >> 4; + vesa_r.edi = 0; + + __svgalib_LRMI_callbacks->rm_free_real(LRMI_mem2); + + __svgalib_LRMI_callbacks->rm_int(0x10, &vesa_r); + if (vesa_r.eax!=0x4f) return 0; + return !vesa_init(0,0,0); +} + + +/* No r/w paging */ +static void vesa_setrdpage(int page) +{ +vesa_r.eax=0x4f05; +vesa_r.ebx=vesa_read_window; +vesa_r.edx=page*64/vesa_granularity; +__svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); +} +static void vesa_setwrpage(int page) +{ +vesa_r.eax=0x4f05; +vesa_r.ebx=vesa_write_window; +vesa_r.edx=page*64/vesa_granularity; +__svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); +} + + +/* Set display start address (not for 16 color modes) */ + +static void vesa_setdisplaystart(int address) +{ + vesa_r.eax=0x4f07; + vesa_r.ebx=0; + vesa_r.ecx=address % vesa_logical_width; + vesa_r.edx=address / vesa_logical_width; + + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + +} + +/* Set logical scanline length (usually multiple of 8) */ + +static void vesa_setlogicalwidth(int width) +{ + vesa_r.eax=0x4f06; + vesa_r.ebx=0; + vesa_r.ecx=width / vesa_bpp ; + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + vesa_logical_width=vesa_r.ebx; + +} + +static int vesa_linear(int op, int param) +{ +if (op==LINEAR_ENABLE) { + vesa_r.eax=0x4f02; + vesa_r.ebx=vesa_last_mode_set|0x4000; + vesa_set_crtc_info_regs(); + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + vesa_is_linear=1; +}; + +if (op==LINEAR_DISABLE){ + vesa_r.eax=0x4f02; + vesa_r.ebx=vesa_last_mode_set; + vesa_set_crtc_info_regs(); + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + vesa_is_linear=0; +}; +if (op==LINEAR_QUERY_BASE) {return vesa_linear_base ;} +if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ + else return -1; /* Unknown function. */ +} + +static int vesa_match_programmable_clock(int clock) +{ +return clock ; +} +static int vesa_map_clock(int bpp, int clock) +{ +return clock ; +} +static int vesa_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +return htiming; +} +/* Function table (exported) */ + +DriverSpecs __svgalib_vesa_driverspecs = +{ + vesa_saveregs, + vesa_setregs, + vesa_unlock, + vesa_lock, + vesa_test, + vesa_init, + vesa_setpage, + vesa_setrdpage, + vesa_setwrpage, + vesa_setmode, + vesa_modeavailable, + vesa_setdisplaystart, + vesa_setlogicalwidth, + vesa_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + vesa_linear, + 0, /* accelspecs, filled in during init. */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int vesa_init(int force, int par1, int par2) +{ + short int *mode_list; + int i; +#if 0 + uint8_t *m; + int address; + + m=mmap(0,0x502,PROT_READ,MAP_SHARED,__svgalib_mem_fd,0); + + address=((int)*(unsigned short *)(m+64))+(((int)*(unsigned short *)(m+66))<<4); + if((address<0xa0000)||(address>0xfffff)) { + fprintf(stderr, "Real mode int 0x10 at 0x%08x handler not in ROM.\n",address); + fprintf(stderr, "Try running vga_reset.\n"); + return 1; + }; +#endif + __svgalib_textprog|=1; + vesa_bpp=1; + vesa_granularity=1; + + /* Get I/O privilege */ + + if (force) { + vesa_memory = par1; + vesa_chiptype = par2; + } else { + vesa_memory=4096; + }; + + __svgalib_LRMI_callbacks->rm_init(); + for(i=0;i<__GLASTMODE;i++)SVGALIB_VESA[i]=IS_IN_STANDARD_VGA_DRIVER(i); + + vesa_data.info = __svgalib_LRMI_callbacks->rm_alloc_real(sizeof(struct vbe_info_block) + + sizeof(struct vbe_mode_info_block)); + vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1); + vesa_r.eax = 0x4f00; + vesa_r.es = (unsigned int)vesa_data.info >> 4; + vesa_r.edi = 0; + + memcpy(vesa_data.info->vbe_signature, "VBE2", 4); + + __svgalib_LRMI_callbacks->rm_int(0x10, &vesa_r); + + if ((vesa_r.eax & 0xffff) != 0x4f || strncmp(vesa_data.info->vbe_signature, "VESA", 4) != 0) { + fprintf(stderr,"No VESA bios detected!\n"); + fprintf(stderr,"Try running vga_reset.\n"); + return 1; + } + + if(vesa_data.info->vbe_version>=0x0200)vesa_chiptype=1 ; else vesa_chiptype=0; + if(vesa_data.info->vbe_version>=0x0300)vesa_chiptype=2 ; + + vesa_memory = vesa_data.info->total_memory*64; + + mode_list = (short int *)(vesa_data.info->video_mode_list_seg * 16 + vesa_data.info->video_mode_list_off); + + while (*mode_list != -1) { + memset(&vesa_r, 0, sizeof(vesa_r)); + + vesa_r.eax = 0x4f01; + vesa_r.ecx = *mode_list; + vesa_r.es = (unsigned int)vesa_data.mode >> 4; + vesa_r.edi = (unsigned int)vesa_data.mode & 0xf; + + if (!__svgalib_LRMI_callbacks->rm_int(0x10, &vesa_r)) { + fprintf(stderr, "Can't get mode info (vm86 failure)\n"); + return 1; + } + if((vesa_chiptype>=1)&&(vesa_data.mode->mode_attributes&0x80)) + vesa_linear_base=vesa_data.mode->phys_base_ptr; +#if 1 + for(i=0;i<=__GLASTMODE;i++) + if((infotable[i].xdim==vesa_data.mode->x_resolution)&& + (infotable[i].ydim==vesa_data.mode->y_resolution)&& + (((vesa_data.mode->rsvd_mask_size==8)&&(infotable[i].bytesperpixel==4))|| + ((vesa_data.mode->bits_per_pixel==32)&&(infotable[i].bytesperpixel==4))|| + ((vesa_data.mode->bits_per_pixel==24)&&(infotable[i].bytesperpixel==3))|| + ((vesa_data.mode->green_mask_size==5)&&(infotable[i].colors==32768))|| + ((vesa_data.mode->green_mask_size==6)&&(infotable[i].colors==65536))|| + ((vesa_data.mode->memory_model==VBE_MODEL_PLANAR)&&(infotable[i].colors==16))|| + ((vesa_data.mode->memory_model==VBE_MODEL_256)&&(infotable[i].colors==256))|| + ((vesa_data.mode->memory_model==VBE_MODEL_PACKED)&& + (infotable[i].colors==256)&&(vesa_data.mode->bits_per_pixel==8)))){ + SVGALIB_VESA[i]=*mode_list; + i=__GLASTMODE+1; + }; + +#else + if (vesa_data.mode->memory_model == VBE_MODEL_RGB) { + if((vesa_data.mode->rsvd_mask_size==8)||(vesa_data.mode->bits_per_pixel==32)) { + switch(vesa_data.mode->y_resolution){ + case 200: if(vesa_data.mode->x_resolution==320) + SVGALIB_VESA[G320x200x16M32]=*mode_list; break; + case 240: if(vesa_data.mode->x_resolution==320) + SVGALIB_VESA[G320x240x16M32]=*mode_list; break; + case 300: if(vesa_data.mode->x_resolution==400) + SVGALIB_VESA[G400x300x16M32]=*mode_list; break; + case 384: if(vesa_data.mode->x_resolution==512) + SVGALIB_VESA[G512x384x16M32]=*mode_list; break; + case 480: if(vesa_data.mode->x_resolution==640) + SVGALIB_VESA[G640x480x16M32]=*mode_list; break; + case 600: if(vesa_data.mode->x_resolution==800) + SVGALIB_VESA[G800x600x16M32]=*mode_list; break; + case 720: if(vesa_data.mode->x_resolution==960) + SVGALIB_VESA[G960x720x16M32]=*mode_list; break; + case 768: if(vesa_data.mode->x_resolution==1024) + SVGALIB_VESA[G1024x768x16M32]=*mode_list; break; + case 864: if(vesa_data.mode->x_resolution==1152) + SVGALIB_VESA[G1152x864x16M32]=*mode_list; break; + case 1024: if(vesa_data.mode->x_resolution==1280) + SVGALIB_VESA[G1280x1024x16M32]=*mode_list; break; + case 1200: if(vesa_data.mode->x_resolution==1600) + SVGALIB_VESA[G1600x1200x16M32]=*mode_list; break; + case 1440: if(vesa_data.mode->x_resolution==1920) + SVGALIB_VESA[G1920x1440x16M32]=*mode_list; break; + } + } else { + i=0; + switch(vesa_data.mode->y_resolution){ + case 200: if(vesa_data.mode->x_resolution==320) + i=G320x200x32K; break; + case 240: if(vesa_data.mode->x_resolution==320) + i=G320x240x32K; break; + case 300: if(vesa_data.mode->x_resolution==400) + i=G400x300x32K; break; + case 384: if(vesa_data.mode->x_resolution==512) + i=G512x384x32K; break; + case 480: if(vesa_data.mode->x_resolution==640) + i=G640x480x32K; break; + case 600: if(vesa_data.mode->x_resolution==800) + i=G800x600x32K; break; + case 720: if(vesa_data.mode->x_resolution==960) + i=G960x720x32K; break; + case 768: if(vesa_data.mode->x_resolution==1024) + i=G1024x768x32K; break; + case 864: if(vesa_data.mode->x_resolution==1152) + i=G1152x864x32K; break; + case 1024: if(vesa_data.mode->x_resolution==1280) + i=G1280x1024x32K; break; + case 1200: if(vesa_data.mode->x_resolution==1600) + i=G1600x1200x32K; break; + case 1440: if(vesa_data.mode->x_resolution==1920) + i=G1920x1440x32K; break; + }; + if(i>0)switch(vesa_data.mode->green_mask_size){ + case 5:SVGALIB_VESA[i]=*mode_list; break; + case 6:SVGALIB_VESA[i+1]=*mode_list; break; + case 8:if(vesa_data.mode->rsvd_mask_size==0)SVGALIB_VESA[i+2]=*mode_list; break; + }; + }; + } else if ((vesa_data.mode->memory_model == VBE_MODEL_256) || + (vesa_data.mode->memory_model == VBE_MODEL_PACKED)){ + switch(vesa_data.mode->y_resolution){ + case 200: if(vesa_data.mode->x_resolution==320) + SVGALIB_VESA[G320x200x256]=*mode_list; break; + case 240: if(vesa_data.mode->x_resolution==320) { + if(vesa_data.mode->number_of_planes==8) + SVGALIB_VESA[G320x240x256]=*mode_list; + else SVGALIB_VESA[G320x240x256V]=*mode_list; + }; + break; + case 300: if(vesa_data.mode->x_resolution==400) + SVGALIB_VESA[G400x300x256]=*mode_list; break; + case 384: if(vesa_data.mode->x_resolution==512) + SVGALIB_VESA[G512x384x256]=*mode_list; break; + case 480: if(vesa_data.mode->x_resolution==640) + SVGALIB_VESA[G640x480x256]=*mode_list; break; + case 600: if(vesa_data.mode->x_resolution==800) + SVGALIB_VESA[G800x600x256]=*mode_list; break; + case 720: if(vesa_data.mode->x_resolution==960) + SVGALIB_VESA[G960x720x256]=*mode_list; break; + case 768: if(vesa_data.mode->x_resolution==1024) + SVGALIB_VESA[G1024x768x256]=*mode_list; break; + case 864: if(vesa_data.mode->x_resolution==1152) + SVGALIB_VESA[G1152x864x256]=*mode_list; break; + case 1024: if(vesa_data.mode->x_resolution==1280) + SVGALIB_VESA[G1280x1024x256]=*mode_list; break; + case 1200: if(vesa_data.mode->x_resolution==1600) + SVGALIB_VESA[G1600x1200x256]=*mode_list; break; + case 1440: if(vesa_data.mode->x_resolution==1920) + SVGALIB_VESA[G1920x1440x256]=*mode_list; break; + } + } +#endif + mode_list++; + }; + vesa_r.eax=0x4f04; + vesa_r.edx=0; + vesa_r.ecx=__svgalib_VESA_savebitmap; + vesa_r.ebx=0; + __svgalib_LRMI_callbacks->rm_int(0x10,&vesa_r); + vesa_regs_size=vesa_r.ebx*64; + __svgalib_LRMI_callbacks->rm_free_real(vesa_data.info); + + SVGALIB_VESA[TEXT]=3; + + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = vesa_memory; + cardspecs->maxPixelClock4bpp = 300000; + cardspecs->maxPixelClock8bpp = 300000; + cardspecs->maxPixelClock16bpp = 300000; + cardspecs->maxPixelClock24bpp = 300000; + cardspecs->maxPixelClock32bpp = 300000; + cardspecs->flags = CLOCK_PROGRAMMABLE; + cardspecs->maxHorizontalCrtc = 4088; + cardspecs->nClocks =1; + cardspecs->clocks = NULL; + cardspecs->mapClock = vesa_map_clock; + cardspecs->mapHorizontalCrtc = vesa_map_horizontal_crtc; + cardspecs->matchProgrammableClock=vesa_match_programmable_clock; + __svgalib_driverspecs = &__svgalib_vesa_driverspecs; + + LRMI_mem1 = __svgalib_LRMI_callbacks->rm_alloc_real(vesa_regs_size); + LRMI_mem2 = __svgalib_LRMI_callbacks->rm_alloc_real(sizeof(struct vbe_info_block) + + sizeof(struct vbe_mode_info_block)); + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + if(vesa_chiptype>=1) { + __svgalib_linear_mem_base=vesa_linear_base; + __svgalib_linear_mem_size=vesa_memory*0x400; + }; + + if (__svgalib_driver_report) { + fprintf(stderr,"Using VESA driver, %iKB. %s\n",vesa_memory, + (vesa_chiptype==2)?"VBE3":(vesa_chiptype?"VBE2.0":"VBE1.2")); + } + return 0; +} + diff --git a/src/drivers/xf86PciInfo.h b/src/drivers/xf86PciInfo.h new file mode 100644 index 0000000..183797e --- /dev/null +++ b/src/drivers/xf86PciInfo.h @@ -0,0 +1,726 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h,v 1.156 2003/10/30 15:26:33 tsi Exp $ */ + +/* + * Copyright (c) 1995-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains macros for the PCI Vendor and Device IDs for video + * cards plus a few other things that are needed in drivers or elsewhere. + * This information is used in several ways: + * 1. It is used by drivers and/or other code. + * 2. It is used by the pciid2c.pl script to determine what vendor data to + * include in the pcidata module that the X server loads. + * 3. A side-effect of 2. affects how config-generation works for + * otherwise "unknown" cards. + * + * Don't add entries here for vendors that don't make video cards, + * or for non-video devices unless they're needed by a driver or elsewhere. + * A comprehensive set of PCI vendor, device and subsystem data is + * auto-generated from the ../etc/pci.ids file using the pciids2c.pl script, + * and is used in both the scanpci module and the scanpci utility. Don't + * modify the pci.ids file. If new/corrected entries are required, add them + * to ../etc/extrapci.ids. + */ + +#ifndef _XF86_PCIINFO_H +#define _XF86_PCIINFO_H + +/* PCI Pseudo Vendor */ +#define PCI_VENDOR_GENERIC 0x00FF + +#define PCI_VENDOR_REAL3D 0x003D +#define PCI_VENDOR_COMPAQ 0x0E11 +#define PCI_VENDOR_ATI 0x1002 +#define PCI_VENDOR_AVANCE 0x1005 +#define PCI_VENDOR_TSENG 0x100C +#define PCI_VENDOR_NS 0x100B +#define PCI_VENDOR_WEITEK 0x100E +#define PCI_VENDOR_VIDEOLOGIC 0x1010 +#define PCI_VENDOR_DIGITAL 0x1011 +#define PCI_VENDOR_CIRRUS 0x1013 +#define PCI_VENDOR_AMD 0x1022 +#define PCI_VENDOR_TRIDENT 0x1023 +#define PCI_VENDOR_ALI 0x1025 +#define PCI_VENDOR_DELL 0x1028 +#define PCI_VENDOR_MATROX 0x102B +#define PCI_VENDOR_CHIPSTECH 0x102C +#define PCI_VENDOR_MIRO 0x1031 +#define PCI_VENDOR_NEC 0x1033 +#define PCI_VENDOR_SIS 0x1039 +#define PCI_VENDOR_HP 0x103C +#define PCI_VENDOR_SGS 0x104A +#define PCI_VENDOR_TI 0x104C +#define PCI_VENDOR_SONY 0x104D +#define PCI_VENDOR_OAK 0x104E +#define PCI_VENDOR_MOTOROLA 0x1057 +#define PCI_VENDOR_NUMNINE 0x105D +#define PCI_VENDOR_CYRIX 0x1078 +#define PCI_VENDOR_SUN 0x108E +#define PCI_VENDOR_DIAMOND 0x1092 +#define PCI_VENDOR_BROOKTREE 0x109E +#define PCI_VENDOR_NEOMAGIC 0x10C8 +#define PCI_VENDOR_NVIDIA 0x10DE +#define PCI_VENDOR_IMS 0x10E0 +#define PCI_VENDOR_INTEGRAPHICS 0x10EA +#define PCI_VENDOR_ALLIANCE 0x1142 +#define PCI_VENDOR_RENDITION 0x1163 +#define PCI_VENDOR_3DFX 0x121A +#define PCI_VENDOR_SMI 0x126F +#define PCI_VENDOR_TRITECH 0x1292 +#define PCI_VENDOR_NVIDIA_SGS 0x12D2 +#define PCI_VENDOR_VMWARE 0x15AD +#define PCI_VENDOR_3DLABS 0x3D3D +#define PCI_VENDOR_AVANCE_2 0x4005 +#define PCI_VENDOR_HERCULES 0x4843 +#define PCI_VENDOR_S3 0x5333 +#define PCI_VENDOR_INTEL 0x8086 +#define PCI_VENDOR_ARK 0xEDD8 + + +/* Generic */ +#define PCI_CHIP_VGA 0x0000 +#define PCI_CHIP_8514 0x0001 + +/* Real 3D */ +#define PCI_CHIP_I740_PCI 0x00D1 + +/* Compaq */ +#define PCI_CHIP_QV1280 0x3033 + +/* ATI */ +#define PCI_CHIP_RV380_3150 0x3150 +#define PCI_CHIP_RV380_3151 0x3151 +#define PCI_CHIP_RV380_3152 0x3152 +#define PCI_CHIP_RV380_3153 0x3153 +#define PCI_CHIP_RV380_3154 0x3154 +#define PCI_CHIP_RV380_3156 0x3156 +#define PCI_CHIP_RV380_3E50 0x3E50 +#define PCI_CHIP_RV380_3E51 0x3E51 +#define PCI_CHIP_RV380_3E52 0x3E52 +#define PCI_CHIP_RV380_3E53 0x3E53 +#define PCI_CHIP_RV380_3E54 0x3E54 +#define PCI_CHIP_RV380_3E56 0x3E56 +#define PCI_CHIP_RS100_4136 0x4136 +#define PCI_CHIP_RS200_4137 0x4137 +#define PCI_CHIP_R300_AD 0x4144 +#define PCI_CHIP_R300_AE 0x4145 +#define PCI_CHIP_R300_AF 0x4146 +#define PCI_CHIP_R300_AG 0x4147 +#define PCI_CHIP_R350_AH 0x4148 +#define PCI_CHIP_R350_AI 0x4149 +#define PCI_CHIP_R350_AJ 0x414A +#define PCI_CHIP_R350_AK 0x414B +#define PCI_CHIP_RV350_AP 0x4150 +#define PCI_CHIP_RV350_AQ 0x4151 +#define PCI_CHIP_RV360_AR 0x4152 +#define PCI_CHIP_RV350_AS 0x4153 +#define PCI_CHIP_RV350_AT 0x4154 +#define PCI_CHIP_RV350_4155 0x4155 +#define PCI_CHIP_RV350_AV 0x4156 +#define PCI_CHIP_MACH32 0x4158 +#define PCI_CHIP_RS250_4237 0x4237 +#define PCI_CHIP_R200_BB 0x4242 +#define PCI_CHIP_R200_BC 0x4243 +#define PCI_CHIP_RS100_4336 0x4336 +#define PCI_CHIP_RS200_4337 0x4337 +#define PCI_CHIP_MACH64CT 0x4354 +#define PCI_CHIP_MACH64CX 0x4358 +#define PCI_CHIP_RS250_4437 0x4437 +#define PCI_CHIP_MACH64ET 0x4554 +#define PCI_CHIP_MACH64GB 0x4742 +#define PCI_CHIP_MACH64GD 0x4744 +#define PCI_CHIP_MACH64GI 0x4749 +#define PCI_CHIP_MACH64GL 0x474C +#define PCI_CHIP_MACH64GM 0x474D +#define PCI_CHIP_MACH64GN 0x474E +#define PCI_CHIP_MACH64GO 0x474F +#define PCI_CHIP_MACH64GP 0x4750 +#define PCI_CHIP_MACH64GQ 0x4751 +#define PCI_CHIP_MACH64GR 0x4752 +#define PCI_CHIP_MACH64GS 0x4753 +#define PCI_CHIP_MACH64GT 0x4754 +#define PCI_CHIP_MACH64GU 0x4755 +#define PCI_CHIP_MACH64GV 0x4756 +#define PCI_CHIP_MACH64GW 0x4757 +#define PCI_CHIP_MACH64GX 0x4758 +#define PCI_CHIP_MACH64GY 0x4759 +#define PCI_CHIP_MACH64GZ 0x475A +#define PCI_CHIP_RV250_Id 0x4964 +#define PCI_CHIP_RV250_Ie 0x4965 +#define PCI_CHIP_RV250_If 0x4966 +#define PCI_CHIP_RV250_Ig 0x4967 +#define PCI_CHIP_R420_JH 0x4A48 +#define PCI_CHIP_R420_JI 0x4A49 +#define PCI_CHIP_R420_JJ 0x4A4A +#define PCI_CHIP_R420_JK 0x4A4B +#define PCI_CHIP_R420_JL 0x4A4C +#define PCI_CHIP_R420_JM 0x4A4D +#define PCI_CHIP_R420_JN 0x4A4E +#define PCI_CHIP_R420_4A4F 0x4A4F +#define PCI_CHIP_R420_JP 0x4A50 +#define PCI_CHIP_R481_4B49 0x4B49 +#define PCI_CHIP_R481_4B4A 0x4B4A +#define PCI_CHIP_R481_4B4B 0x4B4B +#define PCI_CHIP_R481_4B4C 0x4B4C +#define PCI_CHIP_MACH64LB 0x4C42 +#define PCI_CHIP_MACH64LD 0x4C44 +#define PCI_CHIP_RAGE128LE 0x4C45 +#define PCI_CHIP_RAGE128LF 0x4C46 +#define PCI_CHIP_MACH64LG 0x4C47 +#define PCI_CHIP_MACH64LI 0x4C49 +#define PCI_CHIP_MACH64LM 0x4C4D +#define PCI_CHIP_MACH64LN 0x4C4E +#define PCI_CHIP_MACH64LP 0x4C50 +#define PCI_CHIP_MACH64LQ 0x4C51 +#define PCI_CHIP_MACH64LR 0x4C52 +#define PCI_CHIP_MACH64LS 0x4C53 +#define PCI_CHIP_RADEON_LW 0x4C57 +#define PCI_CHIP_RADEON_LX 0x4C58 +#define PCI_CHIP_RADEON_LY 0x4C59 +#define PCI_CHIP_RADEON_LZ 0x4C5A +#define PCI_CHIP_RV250_Ld 0x4C64 +#define PCI_CHIP_RV250_Le 0x4C65 +#define PCI_CHIP_RV250_Lf 0x4C66 +#define PCI_CHIP_RV250_Lg 0x4C67 +#define PCI_CHIP_RV250_Ln 0x4C6E +#define PCI_CHIP_RAGE128MF 0x4D46 +#define PCI_CHIP_RAGE128ML 0x4D4C +#define PCI_CHIP_R300_ND 0x4E44 +#define PCI_CHIP_R300_NE 0x4E45 +#define PCI_CHIP_R300_NF 0x4E46 +#define PCI_CHIP_R300_NG 0x4E47 +#define PCI_CHIP_R350_NH 0x4E48 +#define PCI_CHIP_R350_NI 0x4E49 +#define PCI_CHIP_R360_NJ 0x4E4A +#define PCI_CHIP_R350_NK 0x4E4B +#define PCI_CHIP_RV350_NP 0x4E50 +#define PCI_CHIP_RV350_NQ 0x4E51 +#define PCI_CHIP_RV350_NR 0x4E52 +#define PCI_CHIP_RV350_NS 0x4E53 +#define PCI_CHIP_RV350_NT 0x4E54 +#define PCI_CHIP_RV350_NV 0x4E56 +#define PCI_CHIP_RAGE128PA 0x5041 +#define PCI_CHIP_RAGE128PB 0x5042 +#define PCI_CHIP_RAGE128PC 0x5043 +#define PCI_CHIP_RAGE128PD 0x5044 +#define PCI_CHIP_RAGE128PE 0x5045 +#define PCI_CHIP_RAGE128PF 0x5046 +#define PCI_CHIP_RAGE128PG 0x5047 +#define PCI_CHIP_RAGE128PH 0x5048 +#define PCI_CHIP_RAGE128PI 0x5049 +#define PCI_CHIP_RAGE128PJ 0x504A +#define PCI_CHIP_RAGE128PK 0x504B +#define PCI_CHIP_RAGE128PL 0x504C +#define PCI_CHIP_RAGE128PM 0x504D +#define PCI_CHIP_RAGE128PN 0x504E +#define PCI_CHIP_RAGE128PO 0x504F +#define PCI_CHIP_RAGE128PP 0x5050 +#define PCI_CHIP_RAGE128PQ 0x5051 +#define PCI_CHIP_RAGE128PR 0x5052 +#define PCI_CHIP_RAGE128PS 0x5053 +#define PCI_CHIP_RAGE128PT 0x5054 +#define PCI_CHIP_RAGE128PU 0x5055 +#define PCI_CHIP_RAGE128PV 0x5056 +#define PCI_CHIP_RAGE128PW 0x5057 +#define PCI_CHIP_RAGE128PX 0x5058 +#define PCI_CHIP_RADEON_QD 0x5144 +#define PCI_CHIP_RADEON_QE 0x5145 +#define PCI_CHIP_RADEON_QF 0x5146 +#define PCI_CHIP_RADEON_QG 0x5147 +#define PCI_CHIP_R200_QH 0x5148 +#define PCI_CHIP_R200_QI 0x5149 +#define PCI_CHIP_R200_QJ 0x514A +#define PCI_CHIP_R200_QK 0x514B +#define PCI_CHIP_R200_QL 0x514C +#define PCI_CHIP_R200_QM 0x514D +#define PCI_CHIP_R200_QN 0x514E +#define PCI_CHIP_R200_QO 0x514F +#define PCI_CHIP_RV200_QW 0x5157 +#define PCI_CHIP_RV200_QX 0x5158 +#define PCI_CHIP_RV100_QY 0x5159 +#define PCI_CHIP_RV100_QZ 0x515A +#define PCI_CHIP_RN50_515E 0x515E +#define PCI_CHIP_RAGE128RE 0x5245 +#define PCI_CHIP_RAGE128RF 0x5246 +#define PCI_CHIP_RAGE128RG 0x5247 +#define PCI_CHIP_RAGE128RK 0x524B +#define PCI_CHIP_RAGE128RL 0x524C +#define PCI_CHIP_RAGE128SE 0x5345 +#define PCI_CHIP_RAGE128SF 0x5346 +#define PCI_CHIP_RAGE128SG 0x5347 +#define PCI_CHIP_RAGE128SH 0x5348 +#define PCI_CHIP_RAGE128SK 0x534B +#define PCI_CHIP_RAGE128SL 0x534C +#define PCI_CHIP_RAGE128SM 0x534D +#define PCI_CHIP_RAGE128SN 0x534E +#define PCI_CHIP_RAGE128TF 0x5446 +#define PCI_CHIP_RAGE128TL 0x544C +#define PCI_CHIP_RAGE128TR 0x5452 +#define PCI_CHIP_RAGE128TS 0x5453 +#define PCI_CHIP_RAGE128TT 0x5454 +#define PCI_CHIP_RAGE128TU 0x5455 +#define PCI_CHIP_RV370_5460 0x5460 +#define PCI_CHIP_RV370_5461 0x5461 +#define PCI_CHIP_RV370_5462 0x5462 +#define PCI_CHIP_RV370_5463 0x5463 +#define PCI_CHIP_RV370_5464 0x5464 +#define PCI_CHIP_RV370_5465 0x5465 +#define PCI_CHIP_RV370_5466 0x5466 +#define PCI_CHIP_RV370_5467 0x5467 +#define PCI_CHIP_R423_UH 0x5548 +#define PCI_CHIP_R423_UI 0x5549 +#define PCI_CHIP_R423_UJ 0x554A +#define PCI_CHIP_R423_UK 0x554B +#define PCI_CHIP_R430_554C 0x554C +#define PCI_CHIP_R430_554D 0x554D +#define PCI_CHIP_R430_554E 0x554E +#define PCI_CHIP_R430_554F 0x554F +#define PCI_CHIP_R423_5550 0x5550 +#define PCI_CHIP_R423_UQ 0x5551 +#define PCI_CHIP_R423_UR 0x5552 +#define PCI_CHIP_R423_UT 0x5554 +#define PCI_CHIP_RV410_564A 0x564A +#define PCI_CHIP_RV410_564B 0x564B +#define PCI_CHIP_RV410_5652 0x5652 +#define PCI_CHIP_RV410_5653 0x5653 +#define PCI_CHIP_MACH64VT 0x5654 +#define PCI_CHIP_MACH64VU 0x5655 +#define PCI_CHIP_MACH64VV 0x5656 +#define PCI_CHIP_RS300_5834 0x5834 +#define PCI_CHIP_RS300_5835 0x5835 +#define PCI_CHIP_RS300_5836 0x5836 +#define PCI_CHIP_RS300_5837 0x5837 +#define PCI_CHIP_RS480_5954 0x5954 +#define PCI_CHIP_RS480_5955 0x5955 +#define PCI_CHIP_RV280_5960 0x5960 +#define PCI_CHIP_RV280_5961 0x5961 +#define PCI_CHIP_RV280_5962 0x5962 +#define PCI_CHIP_RV280_5964 0x5964 +#define PCI_CHIP_RV280_5965 0x5965 +#define PCI_CHIP_RN50_5969 0x5969 +#define PCI_CHIP_RS482_5974 0x5974 +#define PCI_CHIP_RS482_5975 0x5975 +#define PCI_CHIP_RS400_5A41 0x5A41 +#define PCI_CHIP_RS400_5A42 0x5A42 +#define PCI_CHIP_RC410_5A61 0x5A61 +#define PCI_CHIP_RC410_5A62 0x5A62 +#define PCI_CHIP_RV370_5B60 0x5B60 +#define PCI_CHIP_RV370_5B61 0x5B61 +#define PCI_CHIP_RV370_5B62 0x5B62 +#define PCI_CHIP_RV370_5B63 0x5B63 +#define PCI_CHIP_RV370_5B64 0x5B64 +#define PCI_CHIP_RV370_5B65 0x5B65 +#define PCI_CHIP_RV370_5B66 0x5B66 +#define PCI_CHIP_RV370_5B67 0x5B67 +#define PCI_CHIP_RV280_5C61 0x5C61 +#define PCI_CHIP_RV280_5C63 0x5C63 +#define PCI_CHIP_R430_5D48 0x5D48 +#define PCI_CHIP_R430_5D49 0x5D49 +#define PCI_CHIP_R430_5D4A 0x5D4A +#define PCI_CHIP_R480_5D4C 0x5D4C +#define PCI_CHIP_R480_5D4D 0x5D4D +#define PCI_CHIP_R480_5D4E 0x5D4E +#define PCI_CHIP_R480_5D4F 0x5D4F +#define PCI_CHIP_R480_5D50 0x5D50 +#define PCI_CHIP_R480_5D52 0x5D52 +#define PCI_CHIP_R423_5D57 0x5D57 +#define PCI_CHIP_RV410_5E48 0x5E48 +#define PCI_CHIP_RV410_5E4A 0x5E4A +#define PCI_CHIP_RV410_5E4B 0x5E4B +#define PCI_CHIP_RV410_5E4C 0x5E4C +#define PCI_CHIP_RV410_5E4D 0x5E4D +#define PCI_CHIP_RV410_5E4F 0x5E4F +#define PCI_CHIP_RS350_7834 0x7834 +#define PCI_CHIP_RS350_7835 0x7835 + +/* Avance Logic */ +#define PCI_CHIP_ALG2064 0x2064 +#define PCI_CHIP_ALG2301 0x2301 +#define PCI_CHIP_ALG2501 0x2501 + +/* Tseng */ +#define PCI_CHIP_ET4000_W32P_A 0x3202 +#define PCI_CHIP_ET4000_W32P_B 0x3205 +#define PCI_CHIP_ET4000_W32P_D 0x3206 +#define PCI_CHIP_ET4000_W32P_C 0x3207 +#define PCI_CHIP_ET6000 0x3208 +#define PCI_CHIP_ET6300 0x4702 + +/* Weitek */ +#define PCI_CHIP_P9000 0x9001 +#define PCI_CHIP_P9100 0x9100 + +/* Digital */ +#define PCI_CHIP_DC21050 0x0001 +#define PCI_CHIP_DEC21030 0x0004 +#define PCI_CHIP_TGA2 0x000D + +/* Cirrus Logic */ +#define PCI_CHIP_GD7548 0x0038 +#define PCI_CHIP_GD7555 0x0040 +#define PCI_CHIP_GD5430 0x00A0 +#define PCI_CHIP_GD5434_4 0x00A4 +#define PCI_CHIP_GD5434_8 0x00A8 +#define PCI_CHIP_GD5436 0x00AC +#define PCI_CHIP_GD5446 0x00B8 +#define PCI_CHIP_GD5480 0x00BC +#define PCI_CHIP_GD5462 0x00D0 +#define PCI_CHIP_GD5464 0x00D4 +#define PCI_CHIP_GD5464BD 0x00D5 +#define PCI_CHIP_GD5465 0x00D6 +#define PCI_CHIP_6729 0x1100 +#define PCI_CHIP_6832 0x1110 +#define PCI_CHIP_GD7542 0x1200 +#define PCI_CHIP_GD7543 0x1202 +#define PCI_CHIP_GD7541 0x1204 + +/* AMD */ +#define PCI_CHIP_AMD761 0x700E + +/* Trident */ +#define PCI_CHIP_2100 0x2100 +#define PCI_CHIP_8400 0x8400 +#define PCI_CHIP_8420 0x8420 +#define PCI_CHIP_8500 0x8500 +#define PCI_CHIP_8520 0x8520 +#define PCI_CHIP_8600 0x8600 +#define PCI_CHIP_8620 0x8620 +#define PCI_CHIP_8820 0x8820 +#define PCI_CHIP_9320 0x9320 +#define PCI_CHIP_9388 0x9388 +#define PCI_CHIP_9397 0x9397 +#define PCI_CHIP_939A 0x939A +#define PCI_CHIP_9420 0x9420 +#define PCI_CHIP_9440 0x9440 +#define PCI_CHIP_9520 0x9520 +#define PCI_CHIP_9525 0x9525 +#define PCI_CHIP_9540 0x9540 +#define PCI_CHIP_9660 0x9660 +#define PCI_CHIP_9750 0x9750 +#define PCI_CHIP_9850 0x9850 +#define PCI_CHIP_9880 0x9880 +#define PCI_CHIP_9910 0x9910 + +/* ALI */ +#define PCI_CHIP_M1435 0x1435 + +/* Matrox */ +#define PCI_CHIP_MGA2085 0x0518 +#define PCI_CHIP_MGA2064 0x0519 +#define PCI_CHIP_MGA1064 0x051A +#define PCI_CHIP_MGA2164 0x051B +#define PCI_CHIP_MGA2164_AGP 0x051F +#define PCI_CHIP_MGAG200_PCI 0x0520 +#define PCI_CHIP_MGAG200 0x0521 +#define PCI_CHIP_MGAG400 0x0525 +#define PCI_CHIP_MGAG550 0x2527 +#define PCI_CHIP_IMPRESSION 0x0D10 +#define PCI_CHIP_MGAG100_PCI 0x1000 +#define PCI_CHIP_MGAG100 0x1001 + +#define PCI_CARD_G400_TH 0x2179 +#define PCI_CARD_MILL_G200_SD 0xFF00 +#define PCI_CARD_PROD_G100_SD 0xFF01 +#define PCI_CARD_MYST_G200_SD 0xFF02 +#define PCI_CARD_MILL_G200_SG 0xFF03 +#define PCI_CARD_MARV_G200_SD 0xFF04 + +/* Chips & Tech */ +#define PCI_CHIP_65545 0x00D8 +#define PCI_CHIP_65548 0x00DC +#define PCI_CHIP_65550 0x00E0 +#define PCI_CHIP_65554 0x00E4 +#define PCI_CHIP_65555 0x00E5 +#define PCI_CHIP_68554 0x00F4 +#define PCI_CHIP_69000 0x00C0 +#define PCI_CHIP_69030 0x0C30 + +/* Miro */ +#define PCI_CHIP_ZR36050 0x5601 + +/* NEC */ +#define PCI_CHIP_POWER_VR 0x0046 + +/* SiS */ +#define PCI_CHIP_SG86C201 0x0001 +#define PCI_CHIP_SG86C202 0x0002 +#define PCI_CHIP_SG85C503 0x0008 +#define PCI_CHIP_SIS5597 0x0200 +/* Agregado por Carlos Duclos & Manuel Jander */ +#define PCI_CHIP_SIS82C204 0x0204 +#define PCI_CHIP_SG86C205 0x0205 +#define PCI_CHIP_SG86C215 0x0215 +#define PCI_CHIP_SG86C225 0x0225 +#define PCI_CHIP_85C501 0x0406 +#define PCI_CHIP_85C496 0x0496 +#define PCI_CHIP_85C601 0x0601 +#define PCI_CHIP_85C5107 0x5107 +#define PCI_CHIP_85C5511 0x5511 +#define PCI_CHIP_85C5513 0x5513 +#define PCI_CHIP_SIS5571 0x5571 +#define PCI_CHIP_SIS5597_2 0x5597 +#define PCI_CHIP_SIS530 0x6306 +#define PCI_CHIP_SIS6326 0x6326 +#define PCI_CHIP_SIS7001 0x7001 +#define PCI_CHIP_SIS300 0x0300 +#define PCI_CHIP_SIS315H 0x0310 +#define PCI_CHIP_SIS315PRO 0x0325 +#define PCI_CHIP_SIS330 0x0330 +#define PCI_CHIP_SIS630 0x6300 +#define PCI_CHIP_SIS540 0x5300 +#define PCI_CHIP_SIS550 0x5315 +#define PCI_CHIP_SIS650 0x6325 +#define PCI_CHIP_SIS730 0x7300 + +/* Hewlett-Packard */ +#define PCI_CHIP_ELROY 0x1054 +#define PCI_CHIP_ZX1_SBA 0x1229 +#define PCI_CHIP_ZX1_IOC 0x122A +#define PCI_CHIP_ZX1_LBA 0x122E /* a.k.a. Mercury */ +#define PCI_CHIP_ZX1_AGP8 0x12B4 /* a.k.a. QuickSilver */ +#define PCI_CHIP_ZX2_LBA 0x12EE +#define PCI_CHIP_ZX2_SBA 0x4030 +#define PCI_CHIP_ZX2_IOC 0x4031 + +/* SGS */ +#define PCI_CHIP_STG2000 0x0008 +#define PCI_CHIP_STG1764 0x0009 +#define PCI_CHIP_KYROII 0x0010 + +/* Texas Instruments */ +#define PCI_CHIP_TI_PERMEDIA 0x3D04 +#define PCI_CHIP_TI_PERMEDIA2 0x3D07 + +/* Oak */ +#define PCI_CHIP_OTI107 0x0107 + +/* Number Nine */ +#define PCI_CHIP_I128 0x2309 +#define PCI_CHIP_I128_2 0x2339 +#define PCI_CHIP_I128_T2R 0x493D +#define PCI_CHIP_I128_T2R4 0x5348 + +/* Sun */ +#define PCI_CHIP_EBUS 0x1000 +#define PCI_CHIP_HAPPY_MEAL 0x1001 +#define PCI_CHIP_SIMBA 0x5000 +#define PCI_CHIP_PSYCHO 0x8000 +#define PCI_CHIP_SCHIZO 0x8001 +#define PCI_CHIP_SABRE 0xA000 +#define PCI_CHIP_HUMMINGBIRD 0xA001 + +/* BrookTree */ +#define PCI_CHIP_BT848 0x0350 +#define PCI_CHIP_BT849 0x0351 + +/* NVIDIA */ +#define PCI_CHIP_NV1 0x0008 +#define PCI_CHIP_DAC64 0x0009 +#define PCI_CHIP_TNT 0x0020 +#define PCI_CHIP_TNT2 0x0028 +#define PCI_CHIP_UTNT2 0x0029 +#define PCI_CHIP_VTNT2 0x002C +#define PCI_CHIP_UVTNT2 0x002D +#define PCI_CHIP_ITNT2 0x00A0 +#define PCI_CHIP_GEFORCE_256 0x0100 +#define PCI_CHIP_GEFORCE_DDR 0x0101 +#define PCI_CHIP_QUADRO 0x0103 +#define PCI_CHIP_GEFORCE2_MX 0x0110 +#define PCI_CHIP_GEFORCE2_MX_100 0x0111 +#define PCI_CHIP_GEFORCE2_GO 0x0112 +#define PCI_CHIP_QUADRO2_MXR 0x0113 +#define PCI_CHIP_GEFORCE2_GTS 0x0150 +#define PCI_CHIP_GEFORCE2_TI 0x0151 +#define PCI_CHIP_GEFORCE2_ULTRA 0x0152 +#define PCI_CHIP_QUADRO2_PRO 0x0153 +#define PCI_CHIP_GEFORCE4_MX_460 0x0170 +#define PCI_CHIP_GEFORCE4_MX_440 0x0171 +#define PCI_CHIP_GEFORCE4_MX_420 0x0172 +#define PCI_CHIP_GEFORCE4_440_GO 0x0174 +#define PCI_CHIP_GEFORCE4_420_GO 0x0175 +#define PCI_CHIP_GEFORCE4_420_GO_M32 0x0176 +#define PCI_CHIP_QUADRO4_500XGL 0x0178 +#define PCI_CHIP_GEFORCE4_440_GO_M64 0x0179 +#define PCI_CHIP_QUADRO4_200 0x017A +#define PCI_CHIP_QUADRO4_550XGL 0x017B +#define PCI_CHIP_QUADRO4_500_GOGL 0x017C +#define PCI_CHIP_IGEFORCE2 0x01A0 +#define PCI_CHIP_GEFORCE3 0x0200 +#define PCI_CHIP_GEFORCE3_TI_200 0x0201 +#define PCI_CHIP_GEFORCE3_TI_500 0x0202 +#define PCI_CHIP_QUADRO_DCC 0x0203 +#define PCI_CHIP_GEFORCE4_TI_4600 0x0250 +#define PCI_CHIP_GEFORCE4_TI_4400 0x0251 +#define PCI_CHIP_GEFORCE4_TI_4200 0x0253 +#define PCI_CHIP_QUADRO4_900XGL 0x0258 +#define PCI_CHIP_QUADRO4_750XGL 0x0259 +#define PCI_CHIP_QUADRO4_700XGL 0x025B + +/* NVIDIA & SGS */ +#define PCI_CHIP_RIVA128 0x0018 + +/* IMS */ +#define PCI_CHIP_IMSTT128 0x9128 +#define PCI_CHIP_IMSTT3D 0x9135 + +/* Alliance Semiconductor */ +#define PCI_CHIP_AP6410 0x3210 +#define PCI_CHIP_AP6422 0x6422 +#define PCI_CHIP_AT24 0x6424 +#define PCI_CHIP_AT3D 0x643D + +/* 3dfx Interactive */ +#define PCI_CHIP_VOODOO_GRAPHICS 0x0001 +#define PCI_CHIP_VOODOO2 0x0002 +#define PCI_CHIP_BANSHEE 0x0003 +#define PCI_CHIP_VOODOO3 0x0005 +#define PCI_CHIP_VOODOO5 0x0009 + +#define PCI_CARD_VOODOO3_2000 0x0036 +#define PCI_CARD_VOODOO3_3000 0x003A + +/* Rendition */ +#define PCI_CHIP_V1000 0x0001 +#define PCI_CHIP_V2x00 0x2000 + +/* 3Dlabs */ +#define PCI_CHIP_300SX 0x0001 +#define PCI_CHIP_500TX 0x0002 +#define PCI_CHIP_DELTA 0x0003 +#define PCI_CHIP_PERMEDIA 0x0004 +#define PCI_CHIP_MX 0x0006 +#define PCI_CHIP_PERMEDIA2 0x0007 +#define PCI_CHIP_GAMMA 0x0008 +#define PCI_CHIP_PERMEDIA2V 0x0009 +#define PCI_CHIP_PERMEDIA3 0x000A +#define PCI_CHIP_PERMEDIA4 0x000C +#define PCI_CHIP_R4 0x000D +#define PCI_CHIP_GAMMA2 0x000E +#define PCI_CHIP_R4ALT 0x0011 + +/* S3 */ +#define PCI_CHIP_PLATO 0x0551 +#define PCI_CHIP_VIRGE 0x5631 +#define PCI_CHIP_TRIO 0x8811 +#define PCI_CHIP_AURORA64VP 0x8812 +#define PCI_CHIP_TRIO64UVP 0x8814 +#define PCI_CHIP_VIRGE_VX 0x883D +#define PCI_CHIP_868 0x8880 +#define PCI_CHIP_928 0x88B0 +#define PCI_CHIP_864_0 0x88C0 +#define PCI_CHIP_864_1 0x88C1 +#define PCI_CHIP_964_0 0x88D0 +#define PCI_CHIP_964_1 0x88D1 +#define PCI_CHIP_968 0x88F0 +#define PCI_CHIP_TRIO64V2_DXGX 0x8901 +#define PCI_CHIP_PLATO_PX 0x8902 +#define PCI_CHIP_Trio3D 0x8904 +#define PCI_CHIP_VIRGE_DXGX 0x8A01 +#define PCI_CHIP_VIRGE_GX2 0x8A10 +#define PCI_CHIP_Trio3D_2X 0x8A13 +#define PCI_CHIP_SAVAGE3D 0x8A20 +#define PCI_CHIP_SAVAGE3D_MV 0x8A21 +#define PCI_CHIP_SAVAGE4 0x8A22 +#define PCI_CHIP_PROSAVAGE_PM 0x8A25 +#define PCI_CHIP_PROSAVAGE_KM 0x8A26 +#define PCI_CHIP_VIRGE_MX 0x8C01 +#define PCI_CHIP_VIRGE_MXPLUS 0x8C02 +#define PCI_CHIP_VIRGE_MXP 0x8C03 +#define PCI_CHIP_SAVAGE_MX_MV 0x8C10 +#define PCI_CHIP_SAVAGE_MX 0x8C11 +#define PCI_CHIP_SAVAGE_IX_MV 0x8C12 +#define PCI_CHIP_SAVAGE_IX 0x8C13 +#define PCI_CHIP_SUPSAV_MX128 0x8C22 +#define PCI_CHIP_SUPSAV_MX64 0x8C24 +#define PCI_CHIP_SUPSAV_MX64C 0x8C26 +#define PCI_CHIP_SUPSAV_IX128SDR 0x8C2A +#define PCI_CHIP_SUPSAV_IX128DDR 0x8C2B +#define PCI_CHIP_SUPSAV_IX64SDR 0x8C2C +#define PCI_CHIP_SUPSAV_IX64DDR 0x8C2D +#define PCI_CHIP_SUPSAV_IXCSDR 0x8C2E +#define PCI_CHIP_SUPSAV_IXCDDR 0x8C2F +#define PCI_CHIP_S3TWISTER_P 0x8D01 +#define PCI_CHIP_S3TWISTER_K 0x8D02 +#define PCI_CHIP_PROSAVAGE_DDR 0x8D03 +#define PCI_CHIP_PROSAVAGE_DDRK 0x8D04 +#define PCI_CHIP_SAVAGE2000 0x9102 + +/* ARK Logic */ +#define PCI_CHIP_1000PV 0xA091 +#define PCI_CHIP_2000PV 0xA099 +#define PCI_CHIP_2000MT 0xA0A1 +#define PCI_CHIP_2000MI 0xA0A9 + +/* Tritech Microelectronics */ +#define PCI_CHIP_TR25202 0xFC02 + +/* Neomagic */ +#define PCI_CHIP_NM2070 0x0001 +#define PCI_CHIP_NM2090 0x0002 +#define PCI_CHIP_NM2093 0x0003 +#define PCI_CHIP_NM2097 0x0083 +#define PCI_CHIP_NM2160 0x0004 +#define PCI_CHIP_NM2200 0x0005 +#define PCI_CHIP_NM2230 0x0025 +#define PCI_CHIP_NM2360 0x0006 +#define PCI_CHIP_NM2380 0x0016 + +/* Intel */ +#define PCI_CHIP_I815_BRIDGE 0x1130 +#define PCI_CHIP_I815 0x1132 +#define PCI_CHIP_82801_P2P 0x244E +#define PCI_CHIP_845_G_BRIDGE 0x2560 +#define PCI_CHIP_845_G 0x2562 +#define PCI_CHIP_I830_M_BRIDGE 0x3575 +#define PCI_CHIP_I830_M 0x3577 +#define PCI_CHIP_I810_BRIDGE 0x7120 +#define PCI_CHIP_I810 0x7121 +#define PCI_CHIP_I810_DC100_BRIDGE 0x7122 +#define PCI_CHIP_I810_DC100 0x7123 +#define PCI_CHIP_I810_E_BRIDGE 0x7124 +#define PCI_CHIP_I810_E 0x7125 +#define PCI_CHIP_I740_AGP 0x7800 +#define PCI_CHIP_460GX_PXB 0x84CB +#define PCI_CHIP_460GX_SAC 0x84E0 +#define PCI_CHIP_460GX_GXB_2 0x84E2 /* PCI function 2 */ +#define PCI_CHIP_460GX_WXB 0x84E6 +#define PCI_CHIP_460GX_GXB_1 0x84EA /* PCI function 1 */ + +/* Silicon Motion Inc. */ +#define PCI_CHIP_SMI910 0x0910 +#define PCI_CHIP_SMI810 0x0810 +#define PCI_CHIP_SMI820 0x0820 +#define PCI_CHIP_SMI710 0x0710 +#define PCI_CHIP_SMI712 0x0712 +#define PCI_CHIP_SMI720 0x0720 +#define PCI_CHIP_SMI731 0x0730 + +/* VMware */ +#define PCI_CHIP_VMWARE0405 0x0405 +#define PCI_CHIP_VMWARE0710 0x0710 + +#endif /* _XF86_PCIINFO_H */ diff --git a/src/egadrv.c b/src/egadrv.c new file mode 100644 index 0000000..4f3448f --- /dev/null +++ b/src/egadrv.c @@ -0,0 +1,270 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* EGA support from EGAlib by Kapil Paranjape */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + + +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +static int ega_init(int force, int par1, int par2); + +/* BIOS mode 0Dh - 320x200x16 */ +static char g320x200x16_regs[60] = +{ + 0x37, 0x27, 0x2D, 0x37, 0x30, 0x14, 0x04, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE1, 0x24, 0xC7, 0x14, 0x00, 0xE0, 0xF0, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x0B, 0x0F, 0x00, 0x06, + 0x23 +}; + +/* BIOS mode 0Eh - 640x200x16 */ +static char g640x200x16_regs[60] = +{ + 0x70, 0x4F, 0x59, 0x2D, 0x5E, 0x06, 0x04, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE0, 0x23, 0xC7, 0x28, 0x00, 0xDF, 0xEF, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0x23 +}; + +/* BIOS mode 10h - 640x350x16 */ +static char g640x350x16_regs[60] = +{ + 0x5B, 0x4F, 0x53, 0x37, 0x52, 0x00, 0x6C, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5E, 0x2B, 0x5E, 0x28, 0x0F, 0x5F, 0x0A, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xA7 +}; + +/* EGA registers for saved text mode 03* */ +static char text_regs[60] = +{ + 0x5B, 0x4F, 0x53, 0x37, 0x51, 0x5B, 0x6C, 0x1F, 0x00, 0x0D, 0x0a, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x5E, 0x2B, 0x5D, 0x28, 0x0F, 0x5E, 0x0A, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x0A, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0xFF, + 0x03, 0x01, 0x03, 0x00, 0x03, + 0xA7 +}; + +/* Mode table */ +static ModeTable __ega_modes[] = +{ +/* *INDENT-OFF* */ + OneModeEntry(320x200x16), + OneModeEntry(640x200x16), + OneModeEntry(640x350x16), + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + +static ModeTable *ega_modes = NULL; + + +/* Fill in chipset-specific modeinfo */ + +static void getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + /* Taken from vga 16 colors. Correct ??? */ + modeinfo->maxpixels = 65536 * 8; + modeinfo->startaddressrange = 0x7ffff; + modeinfo->maxlogicalwidth = 2040; + modeinfo->haveblit = 0; + modeinfo->flags &= ~(IS_INTERLACED | HAVE_RWPAGE); +} + +static void nothing(void) +{ +} + + +/* Return nonzero if mode available */ + +static int modeavailable(int mode) +{ + const unsigned char *regs; + + regs = LOOKUPMODE(ega_modes, mode); + if (regs != NULL && regs != DISABLE_MODE) + return STDVGADRV; + return 0; +} + +static int lastmode = TEXT; + +static int saveregs(unsigned char *regs) +{ + /* We can't read the registers from an EGA card. */ + /* We just report the expected values. */ + + const unsigned char *r; + int i; + + if (lastmode == TEXT) + r = text_regs; + else + r = LOOKUPMODE(ega_modes, lastmode); + if (r == NULL) { + fprintf(stderr,"svgalib: egadrv.c/saveregs(): internal error\n"); + exit(-1); + } + memcpy(regs, r, CRT_C + ATT_C + GRA_C + SEQ_C + MIS_C); + + /* save all readable EGA registers; others are default */ + /* is this correct (even in graphics mode) ?? */ + for (i = 0x0C; i < 0x10; i++) { + port_out(i, __svgalib_CRT_I); + regs[CRT + i] = port_in(__svgalib_CRT_D); + } + + return CRT_C + ATT_C + GRA_C + SEQ_C + MIS_C; +} + + +/* Set chipset-specific registers */ + +static void setregs(const unsigned char regs[], int mode) +{ + /* Enable graphics register modification */ + port_out(0x00, GRA_E0); + port_out(0x01, GRA_E1); + + __svgalib_setregs(regs); +} + +/* Set a mode */ + +static int setmode(int mode, int prv_mode) +/* standard EGA driver: setmode */ +{ + const unsigned char *regs; + + regs = LOOKUPMODE(ega_modes, mode); + if (regs == NULL || regs == DISABLE_MODE) + return 1; + lastmode = mode; + + setregs(regs, mode); + return 0; +} + + +/* Set display start */ + +static void setdisplaystart(int address) +{ + port_in(__svgalib_IS1_R); + __svgalib_delay(); + port_out_r(ATT_IW, 0x13 + 0x20); + __svgalib_delay(); + port_out_r(ATT_IW, (address & 7)); + /* write sa0-2 to bits 0-2 */ + address >>= 3; + port_outw_r(__svgalib_CRT_I, 0x0d + (address & 0x00ff) * 256); /* sa0-sa7 */ + port_outw_r(__svgalib_CRT_I, 0x0c + (address & 0xff00)); /* sa8-sa15 */ +} + +static void setlogicalwidth(int width) +{ + port_outw_r(__svgalib_CRT_I, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ +} + + +/* Indentify chipset; return non-zero if detected */ + +static int ega_test(void) +{ + unsigned char save, back; + + /* Check if a DAC is present */ + save = port_in(PEL_IW); + __svgalib_delay(); + port_out_r(PEL_IW, ~save); + __svgalib_delay(); + back = port_in(PEL_IW); + __svgalib_delay(); + port_out_r(PEL_IW, save); + save = ~save; + if (back != save) { + ega_init(0, 0, 0); + return 1; + } + return 0; +} + + +DriverSpecs __svgalib_ega_driverspecs = +{ /* EGA */ + saveregs, + setregs, + nothing /* unlock */ , + nothing /* lock */ , + ega_test, + ega_init, + (void (*)(int)) nothing /* __svgalib_setpage */ , + (void (*)(int)) nothing /* __svgalib_setrdpage */ , + (void (*)(int)) nothing /* __svgalib_setwrpage */ , + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int ega_init(int force, int par1, int par2) +{ + + if (__svgalib_driver_report) + fprintf(stderr,"Using EGA driver.\n"); + + /* Read additional modes from file if available */ + if (ega_modes == NULL) { + ega_modes = __ega_modes; +#ifdef EGA_REGS + { + FILE *regs; + regs = fopen(EGA_REGS, "r"); + if (regs != 0) { + __svgalib_readmodes(regs, &ega_modes, NULL, NULL); + fclose(regs); + } + } +#endif + } + __svgalib_driverspecs = &__svgalib_ega_driverspecs; + + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + + return 0; +} diff --git a/src/endianess.h b/src/endianess.h new file mode 100644 index 0000000..0e532d8 --- /dev/null +++ b/src/endianess.h @@ -0,0 +1,14 @@ +#include +#include + +#if __BYTE_ORDER == __BIG_ENDIAN + +#define LE32(x) bswap_32(x) +#define BE32(x) (x) + +#else /* little endian */ + +#define LE32(x) (x) +#define BE32(x) bswap_32(x) + +#endif diff --git a/src/exports b/src/exports new file mode 100644 index 0000000..ef82ef8 --- /dev/null +++ b/src/exports @@ -0,0 +1,138 @@ +vga_version +vga_setmode +vga_hasmode +vga_setflipchar +vga_clear +vga_flip +vga_getxdim +vga_getydim +vga_getcolors +vga_setpalette +vga_getpalette +vga_setpalvec +vga_getpalvec +vga_screenoff +vga_screenon +vga_setcolor +vga_drawpixel +vga_drawline +vga_drawscanline +vga_drawscansegment +vga_getpixel +vga_getscansegment +vga_getch +vga_dumpregs +vga_getcardinfo +vga_getmodeinfo +vga_getdefaultmode +vga_getcurrentmode +vga_getcurrentchipset +vga_getmodename +vga_getmodenumber +vga_lastmodenumber +vga_getoptmode +vga_getgraphmem +vga_setpage +vga_setreadpage +vga_setwritepage +vga_setlogicalwidth +vga_setdisplaystart +vga_waitretrace +vga_claimvideomemory +vga_disabledriverreport +vga_setmodeX +vga_init +vga_initf +vga_getmousetype +vga_getmonitortype +vga_setmousesupport +vga_lockvc +vga_unlockvc +vga_getkey +vga_oktowrite +vga_copytoplanar256 +vga_copytoplanar16 +vga_copytoplane +vga_setlinearaddressing +vga_safety_fork +vga_simple_init +vga_chipset_saveregs +vga_chipset_setregs +vga_setchipset +vga_setchipsetandfeatures +vga_gettextfont +vga_puttextfont +vga_settextmoderegs +vga_gettextmoderegs +vga_white +vga_setegacolor +vga_setrgbcolor +vga_bitblt +vga_imageblt +vga_fillblt +vga_hlinelistblt +vga_blitwait +vga_ext_set +vga_accel +vga_initcursor +vga_showcursor +vga_setcursorposition +vga_selectcursor +vga_setcursorimage +vga_setcrtcregs +vga_getcrtcregs +vga_addtiming +vga_changetiming +vga_getcurrenttiming +vga_addmode +vga_guesstiming +vga_dpms +vga_waitevent +vga_runinbackground +vga_runinbackground_version +vga_waitvtactive +vga_norevokeprivs +vga_set_LRMI_callbacks +vga_disablechipset +graph_mem + +joystick_close +joystick_init +joystick_update +joystick_sethandler +joystick_setdefaulthandler +joystick_getaxis +joystick_getbutton +joystick_getnumaxes +joystick_getnumbuttons + +keyboard_init +keyboard_init_return_fd +keyboard_close +keyboard_update +keyboard_waitforupdate +keyboard_seteventhandler +keyboard_setdefaulteventhandler +keyboard_getstate +keyboard_clearstate +keyboard_keypressed +keyboard_translatekeys + +mouse_close +mouse_getbutton +mouse_getposition_6d +mouse_getx +mouse_gety +mouse_init +mouse_init_return_fd +mouse_setdefaulteventhandler +mouse_seteventhandler +mouse_setposition +mouse_setposition_6d +mouse_setrange_6d +mouse_setscale +mouse_setwrap +mouse_setxrange +mouse_setyrange +mouse_update +mouse_waitforupdate diff --git a/src/interface.c b/src/interface.c new file mode 100644 index 0000000..71e791b --- /dev/null +++ b/src/interface.c @@ -0,0 +1,98 @@ + +#include +#include + +#include "timing.h" +#include "libvga.h" /* for __svgalib_infotable and ramdac inlines */ +#include "ramdac/ramdac.h" +#include "accel.h" + + +/* + * This is a temporary function that allocates and fills in a ModeInfo + * structure based on a svgalib mode number. + */ + +ModeInfo * + __svgalib_createModeInfoStructureForSvgalibMode(int mode) +{ + ModeInfo *modeinfo; + /* Create the new ModeInfo structure. */ + modeinfo = malloc(sizeof(ModeInfo)); + modeinfo->width = __svgalib_infotable[mode].xdim; + modeinfo->height = __svgalib_infotable[mode].ydim; + modeinfo->bytesPerPixel = __svgalib_infotable[mode].bytesperpixel; + switch (__svgalib_infotable[mode].colors) { + case 16: + modeinfo->colorBits = 4; + break; + case 256: + modeinfo->colorBits = 8; + break; + case 32768: + modeinfo->colorBits = 15; + modeinfo->blueOffset = 0; + modeinfo->greenOffset = 5; + modeinfo->redOffset = 10; + modeinfo->blueWeight = 5; + modeinfo->greenWeight = 5; + modeinfo->redWeight = 5; + break; + case 65536: + modeinfo->colorBits = 16; + modeinfo->blueOffset = 0; + modeinfo->greenOffset = 5; + modeinfo->redOffset = 11; + modeinfo->blueWeight = 5; + modeinfo->greenWeight = 6; + modeinfo->redWeight = 5; + break; + case 256 * 65536: + modeinfo->colorBits = 24; + modeinfo->blueOffset = 0; + modeinfo->greenOffset = 8; + modeinfo->redOffset = 16; + modeinfo->blueWeight = 8; + modeinfo->greenWeight = 8; + modeinfo->redWeight = 8; + break; + } + modeinfo->bitsPerPixel = modeinfo->bytesPerPixel * 8; + if (__svgalib_infotable[mode].colors == 16) + modeinfo->bitsPerPixel = 4; + modeinfo->lineWidth = __svgalib_infotable[mode].xbytes; + return modeinfo; +} + + +/* + * This function converts a number of significant color bits to a matching + * DAC mode type as defined in the RAMDAC interface. + */ + +int __svgalib_colorbits_to_colormode(int bpp, int colorbits) +{ + if (colorbits == 8) + return CLUT8_6; + if (colorbits == 15) + return RGB16_555; + if (colorbits == 16) + return RGB16_565; + if (colorbits == 24) { + if (bpp == 24) + return RGB24_888_B; + else + return RGB32_888_B; + } + return CLUT8_6; +} + + +/* + * Clear the accelspecs structure (disable acceleration). + */ + +void __svgalib_clear_accelspecs(AccelSpecs * accelspecs) +{ + memset(accelspecs, 0, sizeof(AccelSpecs)); +} diff --git a/src/interface.h b/src/interface.h new file mode 100644 index 0000000..399c359 --- /dev/null +++ b/src/interface.h @@ -0,0 +1,23 @@ + + +/* Prototypes of functions defined in interface.c. */ + +/* + * This is a temporary function that allocates and fills in a ModeInfo + * structure based on a svgalib mode number. + */ + +ModeInfo *__svgalib_createModeInfoStructureForSvgalibMode(int mode); + +/* + * This function converts a number of significant color bits to a matching + * DAC mode type as defined in the RAMDAC interface. + */ + +int __svgalib_colorbits_to_colormode(int bpp, int colorbits); + +/* + * Clear the accelspecs structure (disable acceleration). + */ + +void __svgalib_clear_accelspecs(AccelSpecs * accelspecs); diff --git a/src/io.h b/src/io.h new file mode 100644 index 0000000..288e7d8 --- /dev/null +++ b/src/io.h @@ -0,0 +1,70 @@ +#include + +#ifndef __alpha__ + +#define v_readb(addr) (*(volatile uint8_t *) (MMIO_POINTER+(addr))) +#define v_readw(addr) (*(volatile uint16_t *) (MMIO_POINTER+(addr))) +#define v_readl(addr) (*(volatile uint32_t *) (MMIO_POINTER+(addr))) + +#define v_writeb(b,addr) (*(volatile uint8_t *) (MMIO_POINTER+(addr)) = (b)) +#define v_writew(b,addr) (*(volatile uint16_t *) (MMIO_POINTER+(addr)) = (b)) +#define v_writel(b,addr) (*(volatile uint32_t *) (MMIO_POINTER+(addr)) = (b)) + +#else + +#define vip volatile int * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +#define mb() \ +__asm__ __volatile__("mb": : :"memory") + +#define __kernel_extbl(val, shift) \ + ({ unsigned long __kir; \ + __asm__("extbl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \ + __kir; }) +#define __kernel_extwl(val, shift) \ + ({ unsigned long __kir; \ + __asm__("extwl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \ + __kir; }) + +static inline uint8_t v_readb(unsigned long addr) +{ + unsigned long result; + + result = *(vip) ((addr << 5) + SPARSE_MMIO + 0x00); + return __kernel_extbl(result, addr & 3); +} + +static inline uint16_t v_readw(unsigned long addr) +{ + unsigned long result; + + result = *(vip) ((addr << 5) + SPARSE_MMIO + 0x08); + return __kernel_extwl(result, addr & 3); +} + +static inline uint32_t v_readl(unsigned long addr) +{ + return *(vuip) ((addr << 5) + SPARSE_MMIO + 0x18); +} + +static inline void v_writeb(uint8_t b, unsigned long addr) +{ + *(vuip) ((addr << 5) + SPARSE_MMIO + 0x00) = b * 0x01010101; + mb(); +} + +static inline void v_writew(uint16_t b, unsigned long addr) +{ + *(vuip) ((addr << 5) + SPARSE_MMIO + 0x08) = b * 0x00010001; + mb(); +} + +static inline void v_writel(uint32_t b, unsigned long addr) +{ + *(vuip) ((addr << 5) + SPARSE_MMIO + 0x18) = b; + mb(); +} + +#endif /* __alpha__ */ diff --git a/src/joystick/joydev.h b/src/joystick/joydev.h new file mode 100644 index 0000000..1f045e7 --- /dev/null +++ b/src/joystick/joydev.h @@ -0,0 +1,131 @@ +#ifndef _LINUX_JOYSTICK_H +#define _LINUX_JOYSTICK_H + +/* + * $Id: joystick.h,v 1.3 2000/11/30 11:07:05 vojtech Exp $ + * + * Copyright (C) 1996-2000 Vojtech Pavlik + * + * Sponsored by SuSE + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + */ + +#include +#include /* for _IOR(x) and _IOW(x) macros */ + +/* From */ +#define KEY_MAX 0x1ff + +/* + * Version + */ + +#define JS_VERSION 0x020100 + +/* + * Types and constants for reading from /dev/js + */ + +#define JS_EVENT_BUTTON 0x01 /* button pressed/released */ +#define JS_EVENT_AXIS 0x02 /* joystick moved */ +#define JS_EVENT_INIT 0x80 /* initial state of device */ + +struct js_event { + uint32_t time; /* event timestamp in milliseconds */ + int16_t value; /* value */ + uint8_t type; /* event type */ + uint8_t number; /* axis/button number */ +}; + +/* + * IOCTL commands for joystick driver + */ + +#define JSIOCGVERSION _IOR('j', 0x01, uint32_t) /* get driver version */ + +#define JSIOCGAXES _IOR('j', 0x11, uint8_t) /* get number of axes */ +#define JSIOCGBUTTONS _IOR('j', 0x12, uint8_t) /* get number of buttons */ +#define JSIOCGNAME(len) _IOC(_IOC_READ, 'j', 0x13, len) /* get identifier string */ + +#define JSIOCSCORR _IOW('j', 0x21, struct js_corr) /* set correction values */ +#define JSIOCGCORR _IOR('j', 0x22, struct js_corr) /* get correction values */ + +#define JSIOCSAXMAP _IOW('j', 0x31, uint8_t[ABS_MAX]) /* set axis mapping */ +#define JSIOCGAXMAP _IOR('j', 0x32, uint8_t[ABS_MAX]) /* get axis mapping */ +#define JSIOCSBTNMAP _IOW('j', 0x33, uint16_t[KEY_MAX - BTN_MISC]) /* set button mapping */ +#define JSIOCGBTNMAP _IOR('j', 0x34, uint16_t[KEY_MAX - BTN_MISC]) /* get button mapping */ + +/* + * Types and constants for get/set correction + */ + +#define JS_CORR_NONE 0x00 /* returns raw values */ +#define JS_CORR_BROKEN 0x01 /* broken line */ + +struct js_corr { + int32_t coef[8]; + int16_t prec; + uint16_t type; +}; + +/* + * v0.x compatibility definitions + */ + +#define JS_RETURN sizeof(struct JS_DATA_TYPE) +#define JS_TRUE 1 +#define JS_FALSE 0 +#define JS_X_0 0x01 +#define JS_Y_0 0x02 +#define JS_X_1 0x04 +#define JS_Y_1 0x08 +#define JS_MAX 2 + +#define JS_DEF_TIMEOUT 0x1300 +#define JS_DEF_CORR 0 +#define JS_DEF_TIMELIMIT 10L + +#define JS_SET_CAL 1 +#define JS_GET_CAL 2 +#define JS_SET_TIMEOUT 3 +#define JS_GET_TIMEOUT 4 +#define JS_SET_TIMELIMIT 5 +#define JS_GET_TIMELIMIT 6 +#define JS_GET_ALL 7 +#define JS_SET_ALL 8 + +struct JS_DATA_TYPE { + int buttons; + int x; + int y; +}; + +struct JS_DATA_SAVE_TYPE { + int JS_TIMEOUT; + int BUSY; + long JS_EXPIRETIME; + long JS_TIMELIMIT; + struct JS_DATA_TYPE JS_SAVE; + struct JS_DATA_TYPE JS_CORR; +}; + +#endif /* _LINUX_JOYSTICK_H */ diff --git a/src/joystick/joystick.c b/src/joystick/joystick.c new file mode 100644 index 0000000..a547b46 --- /dev/null +++ b/src/joystick/joystick.c @@ -0,0 +1,713 @@ +/* Joystick interface modeled after svgalibs keyboard and mouse interfaces + * Copyright 1998 Daniel Engström + * Partly based on code from + * joystick-0.7.3 Copyright (C) 1992, 1993 Author C. Smith + * and + * joystick-1.0.6 Copyright (C) 1997 Vojtech Pavlik + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "joydev.h" +#include "vgajoystick.h" +#include + +#undef DEBUG + +#ifndef SVGA_AOUT + +/* forward declarations */ +static void joystick_defaulthandler(int event, int num, char val, int joydev); +static void joystick_initdefhandler(int joydev, int buttons, int axes); + +/* global variables */ +/* Do not just change the sizes, check vga.c too, 4 is a minimum */ +#define NUM_JOYSTICKS 4 + +char *__joystick_devicenames[NUM_JOYSTICKS] = { NULL, NULL, NULL, NULL }; +static char *defnames[NUM_JOYSTICKS] = { + "/dev/js0", "/dev/js1", "/dev/js2", "/dev/js3" +}; + +typedef struct { + int (*update)(int); + void (*handler)(int, int, char, int); + int (*flip_vc)(int, int); + char *dh_buttons; + char *dh_axes; + char axes, buttons; + union t{ + struct { + int b, x, y; + int xdif, ydif; + struct JS_DATA_TYPE caldata; + } prot0; + struct { + struct js_corr corrdata[4]; + } prot1; + } p; +} joydat_t; + +static struct { + int fd; + joydat_t *joydata; +} joydesc[NUM_JOYSTICKS] = { + {-1, NULL}, + {-1, NULL}, + {-1, NULL}, + {-1, NULL}, +}; + +#define PROT0_TIMELIMIT 5 + +/* NULL func to be used before we know which one to use */ +/* Update functions return bit 1 set if further events might be pending, bit 0 set + if status changed... */ + +static int joystick_updx(int joydev) +{ + return 0; +} + +/* For old version 0.x joystick drivers */ +static int joystick_upd0(int joydev) +{ + int retval = 0; + struct JS_DATA_TYPE js; + + if (read(joydesc[joydev].fd, &js, sizeof(struct JS_DATA_TYPE)) != + sizeof(struct JS_DATA_TYPE)) + return retval; + + if (js.buttons != joydesc[joydev].joydata->p.prot0.b) + { + int bmask=1, but; + + for (but=0; but<4; but++) + { + if ((js.buttons & bmask) != (joydesc[joydev].joydata->p.prot0.b & bmask)) { + joydesc[joydev].joydata->handler((js.buttons & bmask)? + JOY_EVENTBUTTONDOWN: + JOY_EVENTBUTTONUP, + but, 0, joydev); + } + bmask=bmask<<1; + } + joydesc[joydev].joydata->p.prot0.b=js.buttons; + retval = 1; + } + + if (js.x != joydesc[joydev].joydata->p.prot0.x) + { + joydesc[joydev].joydata->p.prot0.x = js.x; + js.x -= joydesc[joydev].joydata->p.prot0.xdif; + if (js.x < -128) + js.x = -128; + else if (js.x > 127) + js.x = 127; + joydesc[joydev].joydata->handler(JOY_EVENTAXIS, 0, (char)js.x, joydev); + retval = 1; + } + + if (js.y != joydesc[joydev].joydata->p.prot0.y) + { + joydesc[joydev].joydata->p.prot0.y = js.y; + js.y -= joydesc[joydev].joydata->p.prot0.ydif; + if (js.y < -128) + js.y = -128; + else if (js.y > 127) + js.y = 127; + joydesc[joydev].joydata->handler(JOY_EVENTAXIS, 1, (char)js.y, joydev); + retval = 1; + } + + return retval; +} + +static int joystick_flp0(int joydev, int acquire) { + unsigned long tmpl; + +#ifdef DEBUG + fprintf(stderr,"joyflp: %d, %d\n", joydev, acquire); +#endif + + if (!acquire) { + /* close joystick device */ + if (joydesc[joydev].fd >= 0) { + close(joydesc[joydev].fd); + joydesc[joydev].fd = -1; + } + } else if (joydesc[joydev].fd < 0) { +#ifdef DEBUG + fprintf("trying to reopen\n"); +#endif + /* (re)open joystick device */ + if ((joydesc[joydev].fd = open(__joystick_devicenames[joydev] ? + __joystick_devicenames[joydev] : defnames[joydev], O_RDONLY|O_NONBLOCK)) < 0) + return 1; + + tmpl = PROT0_TIMELIMIT; + if (-1 == ioctl(joydesc[joydev].fd, JS_SET_TIMELIMIT, &tmpl)) + return 1; + + if (-1 == ioctl(joydesc[joydev].fd, JS_SET_CAL, &joydesc[joydev].joydata->p.prot0.caldata)) + return 1; + } + return 0; +} + +/* For new, version 1.x+ joystick drivers */ +static int joystick_upd1(int joydev) +{ + int retval = 0; + struct js_event js; + + if (read(joydesc[joydev].fd, &js, sizeof(struct js_event)) != + sizeof(struct js_event)) + return retval; + + retval = 2; /* further events might be pending */ + + if ((js.type & JS_EVENT_AXIS) == JS_EVENT_AXIS) { + joydesc[joydev].joydata->handler(JOY_EVENTAXIS, js.number, js.value>>8, joydev); + retval = 3; + } + + if ((js.type & JS_EVENT_BUTTON) == JS_EVENT_BUTTON) + { + if (js.value) + joydesc[joydev].joydata->handler(JOY_EVENTBUTTONDOWN, js.number, 0, joydev); + else + joydesc[joydev].joydata->handler(JOY_EVENTBUTTONUP, js.number, 0, joydev); + retval = 3; + } + + return retval; +} + +static int joystick_flp1(int joydev, int acquire) { + if (!acquire) { + /* close joystick device */ + if (joydesc[joydev].fd >= 0) { + close(joydesc[joydev].fd); + joydesc[joydev].fd = -1; + } + } else if (joydesc[joydev].fd < 0) { + /* (re)open joystick device */ + if ((joydesc[joydev].fd = open(__joystick_devicenames[joydev] ? + __joystick_devicenames[joydev] : defnames[joydev], O_RDONLY|O_NONBLOCK)) < 0) + return 1; + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCSCORR, + &joydesc[joydev].joydata->p.prot1.corrdata)) + return 1; + } + return 0; +} + +/* calibration routine for version 0.x protocol */ +static int jscal0(int joydev, __joystick_output jo) +{ + char msg[100]; + int tmp; + long tmpl; + struct JS_DATA_TYPE js_data; + + tmpl = PROT0_TIMELIMIT; + + if (-1 == ioctl(joydesc[joydev].fd, JS_SET_TIMELIMIT, &tmpl)) { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick%d: Failed to set timelimit\n", joydev); + return -1; + } + + if (-1 == ioctl(joydesc[joydev].fd, JS_GET_CAL, &js_data)) { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick%d: Failed to read calibration data\n", joydev); + return -1; + } + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick%d: Current correction: %d , %d\n", joydev, + js_data.x, js_data.y); + + sprintf(msg, "Move Joystick %d to lower right corner and press either button...\n", joydev); + jo(msg); + + while ((read (joydesc[joydev].fd, &js_data, JS_RETURN) > 0) && js_data.buttons == 0x00) + usleep(100); + + for (tmp = 0; js_data.x > 0xff; tmp++, js_data.x = js_data.x >> 1); + js_data.x = tmp; + for (tmp = 0; js_data.y > 0xff; tmp++, js_data.y = js_data.y >> 1); + js_data.y = tmp; + + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick%d: Setting correction: %d , %d\n", joydev, + js_data.x, js_data.y); + + if (-1 == ioctl(joydesc[joydev].fd, JS_SET_CAL, &js_data)) + { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick%d: Failed to set calibration data\n", joydev); + return -1; + } + + sprintf(msg, "Center Joystick %d and press either button...\n", joydev); + jo(msg); + + while ((read (joydesc[joydev].fd, &js_data, JS_RETURN) > 0) && js_data.buttons) + usleep(100); + while ((read (joydesc[joydev].fd, &js_data, JS_RETURN) > 0) && !js_data.buttons) + usleep(100); + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick%d: Setting center offset: %d , %d\n", + joydev, js_data.x, js_data.y); + joydesc[joydev].joydata->p.prot0.xdif = js_data.x; + joydesc[joydev].joydata->p.prot0.ydif = js_data.y; + + sprintf(msg, "Joystick %d recalibrated.\n", joydev); + jo(msg); + + return joydesc[joydev].fd; +} + +/* Definitions and data types for jscal1() and friends */ +#define NUM_POS 3 + +struct js_info +{ + int time; + int buttons; + int axis[4]; +}; + +struct correction_data +{ + int cmin[NUM_POS]; + int cmax[NUM_POS]; +}; + +#if 0 +/* support routine for jscal1() + * Waits for a joystick event to happen + * and updates struct js_info *s accordingly */ +static int wait_for_event(int fd, struct js_info *s) +{ + struct js_event ev; + + if (read(fd, &ev, sizeof(struct js_event)) + != sizeof(struct js_event)) + return 0; + + s->time = ev.time; + + switch (ev.type & ~JS_EVENT_INIT) + { + case JS_EVENT_AXIS: + s->axis[ev.number]=ev.value; + break; + case JS_EVENT_BUTTON: + s->buttons = (s->buttons & ~(1 << ev.number)) | ev.value << ev.number; + } + return sizeof(struct js_event); +} +#endif + +/* calibration routine for 1.x protcol */ +#if 0 +static int jscal1(int joydev, __joystick_output jo) +{ + int i, j, t; + struct correction_data corda[4]; + struct js_corr corr[4]; + struct js_info js; + const char corr_coef_num[] = {0,6}; + char msg[200]; + + static const char *pos_name[] = {"minimum", "center", "maximum"}; + static const char *corr_name[] = {"none (raw)", "broken line"}; + + js.buttons=0; + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCGCORR, &corr)) + { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick %d: error getting correction\n", joydev); + return -1; + } + + for (i=0; i<3; i++) + { + corr[i].type = JS_CORR_NONE; + corr[i].prec = 0; + } + + for(i=0; i < joydesc[joydev].joydata->axes; i++) + js.axis[i]=0; + + for(i=0; i < joydesc[joydev].joydata->axes; i++) + while(0==js.axis[i]) + wait_for_event(joydesc[joydev].fd, &js); + + + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick %d: Setting correction to: %s\n", joydev, corr_name[JS_CORR_NONE]); + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCSCORR, &corr)) + { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick %d: error setting correction\n", joydev); + return -1; + } + + + for (i=0; iaxes; j++) + sprintf(strchr(msg, 0), "Axis %d:%5d ", j, js.axis[j]); + strcat(msg, "\r"); + jo(msg); + + wait_for_event(joydesc[joydev].fd, &js); + } + jo("\nHold ... "); + for (j = 0; j < joydesc[joydev].joydata->axes; j++) + { + corda[j].cmin[i] = js.axis[j]; + corda[j].cmax[i] = 0; + } + t = js.time; + while (js.time < t+2000 && js.buttons) + { + for (j = 0; j < joydesc[joydev].joydata->axes; j++) + { + if (js.axis[j] < corda[j].cmin[i]) + corda[j].cmin[i] = js.axis[j]; + if (js.axis[j] > corda[j].cmax[i]) + corda[j].cmax[i] = js.axis[j]; + } + wait_for_event(joydesc[joydev].fd, &js); + } + if (js.time < t+2000) { + jo("released too soon. Try again:\n\n"); + } + } while (js.time < t+2000); + jo("OK.\n"); + } + + for (j = 0; j < joydesc[joydev].joydata->axes; j++) + { + int temp; + + /* This used to use fp math, not any more */ + corr[j].coef[0] = corda[j].cmin[1]; + corr[j].coef[1] = corda[j].cmax[1]; + corr[j].coef[2] = (temp=32768 / (corda[j].cmin[1] - + corda[j].cmax[0]))*16384; + corr[j].coef[3] = -temp * corda[j].cmax[0]; + corr[j].coef[4] = (temp=32767 / (corda[j].cmin[2] - + corda[j].cmax[1]))*16384; + corr[j].coef[5] = -temp * corda[j].cmin[1] + 32768; + + + corr[j].type = JS_CORR_BROKEN; + corr[j].prec = 10; + } + + if (__svgalib_driver_report) + { + fprintf(stderr,"svgalib, joystick %d: Setting correction to: %s\n", joydev, + corr_name[(int)corr[0].type]); + for (i = 0; i < joydesc[joydev].joydata->axes; i++) + { + fprintf(stderr," Coefs for axis %d:", i); + for(j = 0; j < corr_coef_num[(int)corr[i].type]; j++) + { + fprintf(stderr," %d", corr[i].coef[j]); + if (j < corr_coef_num[(int)corr[i].type] - 1) putc(',',stderr); + } + fprintf(stderr,"\n"); + } + fprintf(stderr,"\n"); + } + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCSCORR, &corr)) + { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick %d: error setting correction\n", joydev); + return -1; + } + + return joydesc[joydev].fd; +} +#endif + +int joystick_update(void) { + int i, retval = 0, status, mask; + + for (i = 0, mask = 1; i < NUM_JOYSTICKS; i++, mask <<= 1) { + if ((joydesc[i].fd >= 0) && joydesc[i].joydata) { + do { + status = joydesc[i].joydata->update(i); + if (status & 1) + retval |= mask; + } while(status & 2); + } + } + return retval & 1; +} + +/* temporarily release joystick devices.. */ +void __joystick_flip_vc(int acquire) { + int i; + + for (i = 0; i < NUM_JOYSTICKS; i++) + if (joydesc[i].joydata && joydesc[i].joydata->flip_vc) + if (joydesc[i].joydata->flip_vc(i, acquire)) { + fprintf(stderr,"svgalib: Fatal, cannot reopen joystick after VC switch.\n"); + exit(1); + } +} + +static void joy_stdout(const char *msg) +{ + fputs(msg, stdout); + fflush(stdout); +} + +int joystick_init(int joydev, __joystick_output jo) +{ + if ((joydev < 0) || (joydev >= NUM_JOYSTICKS)) + return -1; + + if (jo == JOY_CALIB_STDOUT) + jo = joy_stdout; + + joystick_close(joydev); + + if ((joydesc[joydev].fd = open(__joystick_devicenames[joydev] ? + __joystick_devicenames[joydev] : defnames[joydev], O_RDONLY|O_NONBLOCK)) < 0) + { + return -1; + } + else + { + u_int32_t version; + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCGVERSION, &version)) + { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Initializing joystick %d: assuming old 0.x driver protocol\n", joydev); + + /* Old 0.x protocol */ + joystick_initdefhandler(joydev, 4, 2); + joydesc[joydev].joydata->update = joystick_upd0; + joydesc[joydev].joydata->flip_vc = joystick_flp0; + joydesc[joydev].joydata->p.prot0.b = 0; + joydesc[joydev].joydata->p.prot0.x = 0; + joydesc[joydev].joydata->p.prot0.y = 0; + joydesc[joydev].joydata->p.prot0.xdif = 0x80; + joydesc[joydev].joydata->p.prot0.ydif = 0x80; + + if (__svgalib_driver_report) + fprintf(stderr," assuming %d axes and %d buttons\n", + joydesc[joydev].joydata->axes, joydesc[joydev].joydata->buttons); + + /* Now calibrate ... */ + if (jo) + jscal0(joydev, jo); + + if (-1 == ioctl(joydesc[joydev].fd, JS_GET_CAL, + &joydesc[joydev].joydata->p.prot0.caldata)) { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick %d: Failed to read calibration data\n", joydev); + joystick_close(joydev); + return -1; + } + return 1; + } + else + { + char axes, buttons; + + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Initializing joystick %d: driver version %x.%x.%x (new protocol)\n", + joydev, + (version & 0xff0000) >> 16, (version & 0xff00)>> 8, + version & 0xff); + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCGAXES, &axes)) + { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick %d: error getting number of axes\n", joydev); + joystick_close(joydev); + return -1; + } + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCGBUTTONS, &buttons)) + { + if (__svgalib_driver_report) + fprintf(stderr, "svgalib, joystick %d: error getting number of buttons\n", joydev); + joystick_close(joydev); + return -1; + } + + if (__svgalib_driver_report) + fprintf(stderr,"joystick %d has %d axes and %d buttons\n", joydev, axes, buttons); + joystick_initdefhandler(joydev, buttons, axes); + + /* Now calibrate ... */ +#if 0 /* assume joystick is calibrated */ + if (jo) + jscal1(joydev, jo); + + if (-1 == ioctl(joydesc[joydev].fd, JSIOCGCORR, + &joydesc[joydev].joydata->p.prot1.corrdata)) { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib, joystick%d: Failed to read calibration data\n", joydev); + joystick_close(joydev); + return -1; + } +#endif + joydesc[joydev].joydata->update = joystick_upd1; + joydesc[joydev].joydata->flip_vc = joystick_flp1; + return 1; + } + } + return -1; +} + +void joystick_close(int joydev) +{ + if (joydev >= NUM_JOYSTICKS) + return; + if (joydev < 0) { + for (joydev = 0; joydev < NUM_JOYSTICKS; joydev++) + joystick_close(joydev); + return; + } + if (joydesc[joydev].fd >= 0) + close(joydesc[joydev].fd); + joydesc[joydev].fd = -1; + if (joydesc[joydev].joydata) { + if (joydesc[joydev].joydata->dh_buttons) + free(joydesc[joydev].joydata->dh_buttons); + if (joydesc[joydev].joydata->dh_axes) + free(joydesc[joydev].joydata->dh_axes); + free(joydesc[joydev].joydata); + joydesc[joydev].joydata = NULL; + } +} + +char joystick_getnumaxes(int joydev) +{ + if ((joydev >= 0) && (joydev < NUM_JOYSTICKS) && joydesc[joydev].joydata) + return joydesc[joydev].joydata->axes; + return 0; +} + +char joystick_getnumbuttons(int joydev) +{ + if ((joydev >= 0) && (joydev < NUM_JOYSTICKS) && joydesc[joydev].joydata) + return joydesc[joydev].joydata->buttons; + return 0; +} + +static void joystick_initdefhandler(int joydev, int buttons, int axes) +{ + joydesc[joydev].joydata = malloc(sizeof(joydat_t)); + if (!joydesc[joydev].joydata) { + nomem: + fprintf(stderr,"svgalib: Fatal, out of memory\n"); + exit(1); + } + joydesc[joydev].joydata->axes = axes; + joydesc[joydev].joydata->buttons = buttons; + joydesc[joydev].joydata->dh_buttons = malloc(buttons * sizeof(int)); + joydesc[joydev].joydata->dh_axes = malloc(axes * sizeof(int)); + + if ((!joydesc[joydev].joydata->dh_buttons) || + (!joydesc[joydev].joydata->dh_axes)) + goto nomem; + + memset(joydesc[joydev].joydata->dh_buttons, 0, buttons * sizeof(int)); + memset(joydesc[joydev].joydata->dh_axes, 0, axes * sizeof(int)); + joydesc[joydev].joydata->handler = joystick_defaulthandler; + joydesc[joydev].joydata->update = joystick_updx; + joydesc[joydev].joydata->flip_vc = NULL; +} + +static void joystick_defaulthandler(int event, int num, char val, int joydev) +{ +#ifdef DEBUG + fprintf(stderr,"%d: %d %d %d\n", joydev, event, num, val); +#endif + switch (event) + { + case JOY_EVENTAXIS: + joydesc[joydev].joydata->dh_axes[num]=val; + break; + + case JOY_EVENTBUTTONDOWN: + joydesc[joydev].joydata->dh_buttons[num]=1; + break; + + case JOY_EVENTBUTTONUP: + joydesc[joydev].joydata->dh_buttons[num]=0; + break; + } +} + +void joystick_sethandler(int joydev, __joystick_handler jh) +{ + if (joydev >= NUM_JOYSTICKS) + return; + if (joydev < 0) { + for (joydev = 0; joydev < NUM_JOYSTICKS; joydev++) + joystick_sethandler(joydev, jh); + return; + } + if (joydesc[joydev].joydata) + joydesc[joydev].joydata->handler=jh; +} + +void joystick_setdefaulthandler(int joydev) +{ + joystick_sethandler(joydev, joystick_defaulthandler); +} + +char joystick_getaxis(int joydev, int a) +{ + if ((joydev >= 0) && (joydev < NUM_JOYSTICKS) && joydesc[joydev].joydata && + (a >= 0) && (a < joydesc[joydev].joydata->axes)) + return joydesc[joydev].joydata->dh_axes[a]; + return 0; +} + +char joystick_getbutton(int joydev, int b) +{ + if ((joydev >= 0) && (joydev < NUM_JOYSTICKS) && joydesc[joydev].joydata && + (b >= 0) && (b < joydesc[joydev].joydata->buttons)) + return joydesc[joydev].joydata->dh_buttons[b]; + return 0; +} + +#endif diff --git a/src/joystick/vgajoystick.h b/src/joystick/vgajoystick.h new file mode 100644 index 0000000..4028d34 --- /dev/null +++ b/src/joystick/vgajoystick.h @@ -0,0 +1,68 @@ +#ifndef VGAJOYSTICK_H +#define VGAJOYSTICK_H +/* Joystick interface modeled after svgalibs keyboard and mouse interfaces + * Copyright 1998 Daniel Engström + * Partly based on code from + * joystick-0.7.3 Copyright (C) 1992, 1993 Author C. Smith + * and + * joystick-1.0.6 Copyright (C) 1997 Vojtech Pavlik + * + * Extension and modifications. Multiple joystick support, VC switching, + * etc. Michael Weller . + */ + +/* event for joystick handlers */ +#define JOY_EVENTBUTTONDOWN 1 +#define JOY_EVENTBUTTONUP 2 +#define JOY_EVENTAXIS 3 + +/* file is a struct FILE to output calibration instructions to, + * set to NULL to skip calibration + */ + +typedef void (*__joystick_output) (const char *msg); + +int joystick_init(int joydev, __joystick_output jo); + +/* This is guaranteed not to collide with any user definition */ +#define JOY_CALIB_STDOUT ((__joystick_output)(void *)joystick_init) + +void joystick_close(int joydev); + +/* polls the joystick and calls the eventhandler */ +int joystick_update(void); + +typedef void (*__joystick_handler) (int event, int number, char value, int joydev); + /* event - event type; see above + * number - the axis or button number for this event 0=x axis or button 1, etc. + * value - value for axis events -128 - 0 - +127 + */ +void joystick_sethandler(int joydev, __joystick_handler jh); +void joystick_setdefaulthandler(int joydev); + +char joystick_getnumaxes(int joydev); +char joystick_getnumbuttons(int joydev); + +/* querys the default handler if used */ +char joystick_getaxis(int joydev, int a); +char joystick_getbutton(int joydev, int b); + +#define joystick_button1(i) joystick_getbutton(i, 0) +#define joystick_button2(i) joystick_getbutton(i, 1) +#define joystick_button3(i) joystick_getbutton(i, 2) +#define joystick_button4(i) joystick_getbutton(i, 3) + +#define joystick_getb1() joystick_getbutton(0, 0) +#define joystick_getb2() joystick_getbutton(0, 1) +#define joystick_getb3() joystick_getbutton(0, 2) +#define joystick_getb4() joystick_getbutton(0, 3) + +#define joystick_x(i) joystick_getaxis(i, 0) +#define joystick_y(i) joystick_getaxis(i, 1) +#define joystick_z(i) joystick_getaxis(i, 2) + +#define joystick_getx() joystick_getaxis(0, 0) +#define joystick_gety() joystick_getaxis(0, 1) +#define joystick_getz() joystick_getaxis(0, 2) + +#endif diff --git a/src/keyboard/keyboard.c b/src/keyboard/keyboard.c new file mode 100644 index 0000000..8cfd757 --- /dev/null +++ b/src/keyboard/keyboard.c @@ -0,0 +1,901 @@ +/* Keyboard library functions */ +/* H. Hanemaayer (hhanemaa@cs.ruu.nl) */ + +/* Apr 03 1998: Added fake mouse event and some cleanup by 101 (Attila Lendvai) + e-mail: 101@kempelen.inf.bme.hu */ +/* + * May 28 1998: Changed __keyboard_eventhandler to + * __svgalib_keyboard_eventhandler and made non-static to allow for fake + * keyboard events for the wheelmice (Brion Vibber ) + * + * July 3 1998: Added keyboard remapping support - brion +*/ + +/* + * Keyboard I/O based on showkey.c from kbd-0.84 package. + * This is an initial version, it isn't very safe yet since it only catches + * sigsegv. +*/ + +/* #define DEBUG_KEYBOARD */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if 0 +/* linux/keyboard.h defines NR_KEYS and some scancode-like constants, so it */ +/* should also be useful for svgalib programs using the keyboard. It misses */ +/* a few KERNEL ifdefs around kernel data structures though. */ +#include +#else +#define NR_KEYS 128 +#endif +#include +/* Needed to check uid of keymap files */ +#include +#include + +#include +#include "../libvga.h" +#include "vgakeyboard.h" +#include "driver.h" + +void (*__svgalib_keyboard_eventhandler) (int, int); + +static struct termios oldkbdtermios, newkbdtermios; +static int oldkbmode; +/* vga.c needs to check that: */ +int __svgalib_kbd_fd = -1; /* nowadays merely used as a flag */ +static int c_state, ctrl_state, alt_state, functionkey_state, win_state; +static int translatemode = 0; +static unsigned char state[NR_KEYS]; /* NR_KEYS is defined in linux/keyboard.h */ +static int keymap[NR_KEYS]; +static int usekeymap = 0; /* If nonzero, we translate scancodes */ +static int rootkeymaps = 0; /* If nonzero, only load keymaps owned by root */ +static char keynames[NR_KEYS][MAX_KEYNAME_LEN] = { + /* The default US QWERTY layout */ + "", + "Escape", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero", "minus", "equal", "Delete", + "Tab", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "bracketleft", "bracketright", "Return", + "Control", "a", "s", "d", "f", "g", "h", "j", "k", "l", "semicolon", "apostrophe", "grave", + "Shift", "backslash", "z", "x", "c", "v", "b", "n", "m", "comma", "period", "slash", "Shift", "KP_Multiply", + "Alt", "space", "Caps_Lock", + "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", + "Num_Lock", "Scroll_Lock", + "KP_7", "KP_8", "KP_9", "KP_Subtract", + "KP_4", "KP_5", "KP_6", "KP_Add", + "KP_1", "KP_2", "KP_3", + "KP_0", "KP_Period", + "Last_Console", "", "less", "F11", "F12", "", "", "", "", "", "", "", + "KP_Enter", "Control", "KP_Divide", "Control_backslash", "AltGr", "Break", + "Find", "Up", "Prior", "Left", "Right", "Select", "Down", "Next", "Insert", + "Remove", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" +}; +static void default_handler(int, int); +static char *kbd_load_keymap(char *ptr); +static void kbd_update_keymap(void); +static int kbd_mapkey(int inscancode); + +static struct FakeMouseEvent { + int data; + short type; + short flags; + int scancode; + char keyname[MAX_KEYNAME_LEN]; +} **fake_mouse_events = 0; + +/* Number of events per scancode */ +static short *fme_numberof = 0; + +/* Number of scancodes used */ +static int fme_used = 0; + +/* Fake event flags */ +#define FMEF_TRIGGERED 1 /* Triggered, */ +#define FMEF_AT_PRESS 2 /* Request at press (or if false at release)*/ +#define FMEF_AT_BOTH 4 /* Request at press/release too */ +#define FMEF_REPEAT 8 /* Keep on sending fake events */ + +#define FME_TYPE_BUTTON 1 +#define FME_TYPE_DELTAX 2 +#define FME_TYPE_DELTAY 3 +#define FME_TYPE_DELTAZ 4 +#define FME_TYPE_IGNOREX 5 +#define FME_TYPE_IGNOREY 6 +#define FME_TYPE_IGNOREZ 7 +#define FME_TYPE_BUTTON1 8 +#define FME_TYPE_BUTTON2 9 +#define FME_TYPE_BUTTON3 10 + +static int expand_events(int n) { + struct FakeMouseEvent *newptr = 0; +/* int n; */ + + if ( ! fake_mouse_events) { +#ifdef DEBUG_KEYBOARD + fprintf(stderr," Allocating space for FMEs...\n"); +#endif + if ( (fake_mouse_events = malloc(sizeof(void *) * NR_KEYS)) == 0) { + error: + fputs("svgalib: keyboard-config: out of memory ?! Fake mouse events might be disabled !", stderr); + return 0; + } else { + if ( (fme_numberof = malloc(sizeof(short) * NR_KEYS)) == 0) { + free(fake_mouse_events); + fake_mouse_events = 0; + goto error; + } + memset(fake_mouse_events, 0, sizeof(void *) * NR_KEYS); + memset(fme_numberof, 0, sizeof(short) * NR_KEYS); + } + } +#ifdef DEBUG_KEYBOARD + fprintf(stderr," Expanding FME #%d... ", n); +#endif + if ( (newptr = realloc(fake_mouse_events[n], + sizeof(struct FakeMouseEvent) * ++fme_numberof[n])) != 0 ) { +#ifdef DEBUG_KEYBOARD + fprintf(stderr,"it's all good.\n"); +#endif + fake_mouse_events[n] = newptr; + return 1; + } else { + goto error; + } +} + +static char *kbd_config_options[] = { + "kbd_fake_mouse_event", "kbd_keymap", "kbd_only_root_keymaps", NULL +}; + +static char *kbd_process_option(int option, int mode, char **nptr) { + char *ptr; + short type = 0; + short ignore_type = 0; + short flags = FMEF_AT_PRESS; + int data = 0; + int scancode = 0; + int event_ok = 0; + int n = 0; + struct FakeMouseEvent *event; + char keyname[MAX_KEYNAME_LEN]; + + switch (option) { + case 0: /* kbd_fake_mouse_event */ + if ( (ptr = __svgalib_token(nptr)) == 0) { + param_needed: + fprintf(stderr, "svgalib: kbd-config: too few parameters for \'%s\'\n", + kbd_config_options[option]); + return ptr; + } else if ( (scancode = __svgalib_mapkeyname(ptr)) == -1) { + fprintf(stderr, "svgalib: kbd-config: \'%s\' is not a valid scancode\n", ptr); + return ptr; + } + + strncpy(keyname, ptr, MAX_KEYNAME_LEN); + + /* Find the event for this key if there is one*/ +#ifdef DEBUG_KEYBOARD + fprintf(stderr," Looking for fme for key \'%s\'... ", keyname); +#endif + for(n = 0; n < fme_used; n++) + if(strcmp(fake_mouse_events[n]->keyname, keyname) == 0) + break; + if(n == fme_used) + fme_used++; +#ifdef DEBUG_KEYBOARD + fprintf(stderr," found at #%d.\n", n); +#endif + + read_event: + if ( (ptr = __svgalib_token(nptr)) == 0) { + if ( event_ok ) + break; + else + goto param_needed; + } + + if ( ! strcasecmp(ptr, "both")) { + flags |= FMEF_AT_BOTH; + goto read_event; + } else if ( ! strcasecmp(ptr, "up")) { + flags &= ~FMEF_AT_PRESS; + flags &= ~FMEF_AT_BOTH; + goto read_event; + } else if ( ! strcasecmp(ptr, "down")) { + flags |= FMEF_AT_PRESS; + flags &= ~FMEF_AT_BOTH; + goto read_event; + } else if ( ! strcasecmp(ptr, "repeat")) { + flags |= FMEF_REPEAT; + goto read_event; + } else if ( ! strcasecmp(ptr, "discrete")) { + flags &= ~FMEF_REPEAT; + goto read_event; + } else if ( ! strcasecmp(ptr, "button")) { + type = FME_TYPE_BUTTON; + if ( (ptr = __svgalib_token(nptr)) == 0) + goto param_needed; + if ( (data = atoi(ptr)) == 0 || data > 10) { + fprintf(stderr, "svgalib: kbd-config: \'%s\' is not a valid mouse button\n", ptr); + return ptr; + } + + store_event: + +#ifdef DEBUG_KEYBOARD + fprintf(stderr," Fake Mouse Event: scancode: %d; type: %d; data: %d; flags: %d\n", scancode, (int)type, data, (int)flags); +#endif + if ( ! expand_events(n)) + return ptr; + event = &fake_mouse_events[n][fme_numberof[n] - 1]; + event -> type = type; + event -> flags = flags; + event -> data = data; + event -> scancode = scancode; + strcpy(event -> keyname, keyname); + event_ok = 1; + goto read_event; + } else if ( ! strcasecmp(ptr, "deltax")) { + type = FME_TYPE_DELTAX; + ignore_type = FME_TYPE_IGNOREX; + + process_delta: + if ( (ptr = __svgalib_token(nptr)) == 0) + goto param_needed; + if ( ! strcasecmp(ptr, "off")) { + type = ignore_type; + data = 1; + goto store_event; + } else if ( ! strcasecmp(ptr, "on")) { + type = ignore_type; + data = 0; + goto store_event; + } else if ( (data = atoi(ptr)) == 0) { + fprintf(stderr, "svgalib: kbd-config: \'%s\' is not a valid delta\n", ptr); + return ptr; + } + goto store_event; + } else if ( ! strcasecmp(ptr, "deltay")) { + type = FME_TYPE_DELTAY; + ignore_type = FME_TYPE_IGNOREY; + goto process_delta; + } else if ( ! strcasecmp(ptr, "deltaz")) { + type = FME_TYPE_DELTAZ; + ignore_type = FME_TYPE_IGNOREZ; + goto process_delta; + } else if ( ! strcasecmp(ptr, "button1")) { + type = FME_TYPE_BUTTON1; + process_button: + if ( (ptr = __svgalib_token(nptr)) == 0) + goto param_needed; + if ( ! strcasecmp(ptr, "pressed")) { + data = 1; + } else if ( ! strcasecmp(ptr, "released")) { + data = 0; + } else { + fprintf(stderr, "svgalib: kbd-config: \'%s\' is not a legal parameter for command " + "\'button[123]\'. Should be either \'pressed\' or \'released\'\n", ptr); + return ptr; + } + goto store_event; + } else if ( ! strcasecmp(ptr, "button2")) { + type = FME_TYPE_BUTTON2; + goto process_button; + } else if ( ! strcasecmp(ptr, "button3")) { + type = FME_TYPE_BUTTON3; + goto process_button; + } else if ( ! event_ok) { + fprintf(stderr, "svgalib: kbd-config: illegal mouse event: \'%s\'\n", ptr); + return ptr; + } else + return ptr; + break; + + case 1: /* kbd_keymap */ + if ( (ptr = __svgalib_token(nptr)) == 0 ) { + goto param_needed; + } else + if(kbd_load_keymap(ptr)) + return ptr; + + break; + + case 2: /* kbd_only_root_keymaps */ +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " Setting rootkeymaps to 1.\n"); +#endif + rootkeymaps = 1; + break; + + } + return __svgalib_token(nptr); +}; + +int keyboard_init_return_fd(void) { + char *ptr; + + DTP((stderr,"keyboard_init_return_fd\n")); + + keyboard_translatekeys(translatemode); /* Honour 'nosigint' setting */ + + /* Install default keyboard handler. */ + __svgalib_keyboard_eventhandler = default_handler; + + if(__svgalib_novccontrol) { + __svgalib_kbd_fd = open("/tmp/svga_kbd",O_RDONLY); + freopen("/tmp/svga_tty","r",stdin); + } else { + __svgalib_open_devconsole(); + __svgalib_kbd_fd = __svgalib_tty_fd; /* We are initialized. */ + + if (ioctl(__svgalib_kbd_fd, KDGKBMODE, &oldkbmode)) { + fprintf(stderr,"svgalib: cannot get keyboard mode.\n"); + return -1; + } + tcgetattr(__svgalib_kbd_fd, &oldkbdtermios); + newkbdtermios = oldkbdtermios; + + newkbdtermios.c_lflag &= ~(ICANON | ECHO | ISIG); + newkbdtermios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + newkbdtermios.c_cc[VMIN] = 0; /* Making these 0 seems to have the */ + newkbdtermios.c_cc[VTIME] = 0; /* desired effect. */ + + tcsetattr(__svgalib_kbd_fd, TCSAFLUSH, &newkbdtermios); + + ioctl(__svgalib_kbd_fd, KDSKBMODE, K_MEDIUMRAW); + } + + keyboard_clearstate(); + + __svgalib_read_options(kbd_config_options, kbd_process_option); + + /* Check SVGALIB_KEYMAP env var */ + if ( (ptr = getenv("SVGALIB_KEYMAP")) != 0) { + kbd_load_keymap(ptr); + } + + return __svgalib_kbd_fd; /* OK, return fd. */ +} + +/* Old compatible init function. */ + +int keyboard_init(void) +{ + DTP((stderr,"keyboard_init\n")); + + if (keyboard_init_return_fd() == -1) + return -1; + else + return 0; +} + +void keyboard_close(void) { + + DTP((stderr,"keyboard_close\n")); + + if (__svgalib_kbd_fd < 0) + return; + + if (fake_mouse_events) { + int i; + for (i = 0; i < NR_KEYS; i++) { + if (fake_mouse_events[i]) + free(fake_mouse_events[i]); + } + free(fake_mouse_events); + fake_mouse_events = NULL; + } + if(!__svgalib_novccontrol) { + ioctl(__svgalib_kbd_fd, KDSKBMODE, oldkbmode); + tcsetattr(__svgalib_kbd_fd, 0, &oldkbdtermios); + } + + __svgalib_kbd_fd = -1; +} + +/* For now, we assume there's no console switching. */ +/* (Actually, there won't be any unless we catch the console switching */ +/* keys). */ + +#define KBDREADBUFFERSIZE 32 + +static int keyboard_getevents(int wait) +{ +/* Read keyboard device, and handle events. */ +/* If wait == 1, process at least one event and return. */ +/* If wait == 0, handle all accumulated events; return 0 if no events */ +/* were handled, 1 otherwise. */ +/* Wait mode doesn't seem to work very well; the keyboard repeat delay is */ +/* present. I don't understand fcntl. */ + static unsigned char buf[KBDREADBUFFERSIZE]; + static int kfdmode = 0; /* 1 = DELAY, 0 = NDELAY */ + int bytesread, i; + int eventhandled; + + eventhandled = 0; + + again: + if (kfdmode == 1) { /* This only happens for wait == 1. */ +#if 0 + struct termios kbdtermios; +#endif + int flags; + /* We don't want to wait, set NDELAY mode. */ + fcntl(__svgalib_kbd_fd, F_GETFL, &flags); + fcntl(__svgalib_kbd_fd, F_SETFL, flags | O_NDELAY); + +#if 0 + tcgetattr(__svgalib_kbd_fd, &kbdtermios); + kbdtermios.c_lflag = kbdtermios.c_lflag & ~(ICANON | ECHO | ISIG); + kbdtermios.c_cc[VMIN] = 0; + kbdtermios.c_cc[VTIME] = 0; + tcsetattr(__svgalib_kbd_fd, TCSANOW, &kbdtermios); +#endif + + kfdmode = 0; + } + bytesread = read(__svgalib_kbd_fd, buf, KBDREADBUFFERSIZE); + + if (wait == 1 && bytesread < 1) { +#if 0 + struct termios kbdtermios; +#endif + int flags; + /* We already handled an event, no need to wait for another. */ + if (eventhandled) + return 1; + /* Wait mode, we'll sleep on reads. */ + fcntl(__svgalib_kbd_fd, F_GETFL, &flags); + fcntl(__svgalib_kbd_fd, F_SETFL, flags & ~O_NDELAY); + +#if 0 + tcgetattr(__svgalib_kbd_fd, &kbdtermios); + kbdtermios.c_lflag = kbdtermios.c_lflag & ~(ICANON | ECHO | ISIG); + kbdtermios.c_cc[VMIN] = 0; + kbdtermios.c_cc[VTIME] = 0; + tcsetattr(__svgalib_kbd_fd, TCSANOW, &kbdtermios); +#endif + + kfdmode = 1; + bytesread = read(__svgalib_kbd_fd, buf, 1); + } + if (wait == 0 && bytesread < 1) + return eventhandled; + + if (bytesread >= 1) + eventhandled = 1; + + for (i = 0; i < bytesread; i++) { + unsigned char scancode = kbd_mapkey(buf[i] & 0x7f); + unsigned char is_pressed = (buf[i] & 0x80) ? 0 : 1; + + /* Check for ctrl-c. */ + switch (scancode) { + case SCANCODE_C: + c_state = is_pressed; + break; + + case SCANCODE_LEFTCONTROL: + case SCANCODE_RIGHTCONTROL: + ctrl_state = is_pressed; + break; + + case SCANCODE_LEFTALT: + case SCANCODE_RIGHTALT: + alt_state = is_pressed; + break; + + case SCANCODE_LEFTWIN: + case SCANCODE_RIGHTWIN: + win_state = is_pressed; + break; + + case SCANCODE_F1 ... SCANCODE_F10: + functionkey_state = (is_pressed) ? + functionkey_state | 1 << (scancode - SCANCODE_F1) : + functionkey_state & ~(1 << (scancode - SCANCODE_F1)); + break; + } + + if (fake_mouse_events && __svgalib_mouse_fd > -1) { + int n; + + for(n = 0; n < fme_used; n++) + if(fake_mouse_events[n][0].scancode == scancode) + break; + + if(fme_numberof[n]) + { + int i; + int dx=0, dy=0, dz=0, but=0; /* To gather mutiple events into one */ + int but_changed = 0; + struct FakeMouseEvent *event; + + for (i = 0; i < fme_numberof[n]; i++) { + int request_at_down; + short flags; + event = &fake_mouse_events[n][i]; + if (!is_pressed) + event -> flags &= ~FMEF_TRIGGERED; + flags = event -> flags; + request_at_down = (event -> flags & FMEF_AT_PRESS) ? 1 : 0; +#ifdef DEBUG_KEYBOARD + fprintf(stderr," event type: %d; flags: %d; data: %d; is_pressed: %d\n", (int)event->type, flags, event->data, (int)is_pressed); +#endif + if (flags & FMEF_AT_BOTH || request_at_down == is_pressed) { +#ifdef DEBUG_KEYBOARD + fprintf(stderr," flags: %d\n", flags); +#endif + if ( (! (flags & FMEF_TRIGGERED)) || flags & FMEF_REPEAT) { +#ifdef DEBUG_KEYBOARD + fprintf(stderr," triggering\n"); +#endif + switch (event -> type) { + case FME_TYPE_BUTTON1: + but = (event -> data) ? but | 4 : but & ~4; + but_changed = 1; + break; + case FME_TYPE_BUTTON2: + but = (event -> data) ? but | 1 : but & ~1; + but_changed = 1; + break; + case FME_TYPE_BUTTON3: + but = (event -> data) ? but | 2 : but & ~2; + but_changed = 1; + break; + + case FME_TYPE_IGNOREX: + __svgalib_m_ignore_dx = event -> data; + break; + case FME_TYPE_IGNOREY: + __svgalib_m_ignore_dy = event -> data; + break; + case FME_TYPE_IGNOREZ: + __svgalib_m_ignore_dz = event -> data; + break; + + case FME_TYPE_DELTAX: + dx += event -> data; + break; + case FME_TYPE_DELTAY: + dy += event -> data; + break; + case FME_TYPE_DELTAZ: + dz += event -> data; + break; + } + if (is_pressed) + event -> flags |= FMEF_TRIGGERED; + } + } + } + if ((dx || dy || dz || but_changed) && __svgalib_mouse_eventhandler) { + __svgalib_mouse_eventhandler(but, dx, dy, dz, 0, 0, 0); + +#ifdef DEBUG_KEYBOARD + fprintf(stderr,"\tfake_mouse_event triggered; but: %d; dx: %d; dy: %d; dz: %d\n", + but, dx, dy, dz); +#endif + } + } + } + + if (ctrl_state && c_state && !(translatemode & DONT_CATCH_CTRLC)) + raise(SIGINT); + if (((alt_state && functionkey_state)||(win_state && functionkey_state)) && + !__svgalib_novccontrol && !(translatemode & DONT_CATCH_ALT_Fx)){ + /* VT switch. */ + /* *** what about F11 & F12? */ + int j, vt = 0; + struct vt_stat vts; + for (j = 0; j < 12; j++) + if (functionkey_state & (1 << j)) { + vt = j + 1; + if(win_state)j+=12; + break; + } + + /* Do not switch vt's if need not to */ + ioctl(__svgalib_tty_fd, VT_GETSTATE, &vts); + + if(vt != vts.v_active) { + /* if switching vt's, need to clear keystates */ + keyboard_clearstate(); + /* + * This will generate a signal catched by + * svgalib to restore textmode. + */ + ioctl(__svgalib_tty_fd, VT_ACTIVATE, vt); + return 1; + } + } + __svgalib_keyboard_eventhandler(scancode, + (buf[i] & 0x80) ? KEY_EVENTRELEASE : KEY_EVENTPRESS); + } + + /* Handle other events that have accumulated. */ + goto again; +} + +int keyboard_update(void) +{ + return keyboard_getevents(0); /* Don't wait. */ +} + +void keyboard_waitforupdate(void) +{ + keyboard_getevents(1); /* Wait for event. */ + return; +} + +void keyboard_seteventhandler(void (*handler) (int, int)) +{ + __svgalib_keyboard_eventhandler = handler; +} + + + +/* Default event handler. */ + +void keyboard_setdefaulteventhandler(void) +{ + __svgalib_keyboard_eventhandler = default_handler; +} + +static int checkscancode(int scancode) +{ + if (scancode < 0 || scancode >= NR_KEYS) { + fprintf(stderr,"svgalib: keyboard scancode out of range (%d).\n", + scancode); + return 1; + } + return 0; +} + +static void default_handler(int scancode, int newstate) +{ + if (checkscancode(scancode)) + return; + if (translatemode & TRANSLATE_CURSORKEYS) + /* Map cursor key block to keypad cursor keys. */ + switch (scancode) { + case SCANCODE_CURSORBLOCKUP: + scancode = SCANCODE_CURSORUP; + break; + case SCANCODE_CURSORBLOCKLEFT: + scancode = SCANCODE_CURSORLEFT; + break; + case SCANCODE_CURSORBLOCKRIGHT: + scancode = SCANCODE_CURSORRIGHT; + break; + case SCANCODE_CURSORBLOCKDOWN: + scancode = SCANCODE_CURSORDOWN; + break; + } + if (translatemode & TRANSLATE_DIAGONAL) { + /* Translate diagonal keypad keys to two keypad cursor keys. */ + switch (scancode) { + case SCANCODE_CURSORUPLEFT: + state[SCANCODE_CURSORUP] = newstate; + state[SCANCODE_CURSORLEFT] = newstate; + break; + case SCANCODE_CURSORUPRIGHT: + state[SCANCODE_CURSORUP] = newstate; + state[SCANCODE_CURSORRIGHT] = newstate; + break; + case SCANCODE_CURSORDOWNLEFT: + state[SCANCODE_CURSORDOWN] = newstate; + state[SCANCODE_CURSORLEFT] = newstate; + break; + case SCANCODE_CURSORDOWNRIGHT: + state[SCANCODE_CURSORDOWN] = newstate; + state[SCANCODE_CURSORRIGHT] = newstate; + break; + } + } + if ((translatemode & TRANSLATE_KEYPADENTER) && scancode == + SCANCODE_KEYPADENTER) + scancode = SCANCODE_ENTER; + +#if 0 /* This happens very often. */ + if (state[scancode] == newstate) { + fprintf(stderr,"svgalib: keyboard event does not match (scancode = %d)\n", + scancode); + return; + } +#endif + state[scancode] = newstate; +} + +void keyboard_clearstate(void) +{ + memset(state, 0, NR_KEYS); + ctrl_state = c_state = alt_state = 0; + functionkey_state = 0; +} + +int keyboard_keypressed(int scancode) +{ + if (checkscancode(scancode)) + return 0; + return state[scancode]; +} + +char * + keyboard_getstate(void) +{ + return (char *)state; +} + +void keyboard_translatekeys(int mode) +{ + translatemode = mode; + if (__svgalib_nosigint) + translatemode |= DONT_CATCH_CTRLC; +} + +static int kbd_mapkey(int inscancode) +{ + if (usekeymap) + return keymap[inscancode]; + else + return inscancode; +} + +static char *kbd_load_keymap(char *ptr) +{ + /* Find the specified keymap file */ + /* For now, use a full pathname */ + FILE *keymapfile; + +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " Trying to load keymap \'%s\'...\n",ptr); +#endif + + /* If so configured check if the file is owned by root */ + if(rootkeymaps) { + struct stat fs; + if(stat(ptr, &fs)) { + fprintf(stderr, "svgalib: kbd-config: cannot stat keymap file \'%s\'\n", + ptr); + return ptr; + } else if(fs.st_uid != 0) { + fprintf(stderr, "svgalib: kbd-config: keymap file \'%s\' not owned by root\n", + ptr); + return ptr; + } + } + + if((keymapfile = fopen(ptr, "rt"))) { + /* Load it in! */ + char buf[81], nbuf[81]; + int i, l = 0, insc, outsc; + + buf[80] = nbuf[80] = 0; /* Protect somewhat against overruns */ + + /* Disable the keymap until we're done in case something goes wrong... */ + usekeymap = 0; + + /* Initialize keymap */ + for (i = 0; i < NR_KEYS; keymap[i] = i, i++); + + while(!feof(keymapfile)) { + /* Read */ + fgets(buf, 80, keymapfile); + l++; + + /* Ignore comments & blank lines */ + if ((buf[0] != '#') && (buf[0] != '\n')) { + /* Interpret the numbers */ + if((i = sscanf(buf, "%d %d %s", &insc, &outsc, nbuf) == 3)) { + if(checkscancode(insc)) continue; + if(checkscancode(outsc)) continue; + keymap[insc] = outsc; + strncpy(keynames[insc], nbuf, MAX_KEYNAME_LEN); + } else { + fprintf(stderr, "svgalib: kbd-config: skipping line %d of keymap - bad %sput scancode\n", + l, ((i == 1)?("out"):("in"))); + } + } + } + + usekeymap = 1; + + /* Update the mouse driver's fake keyboard events */ +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " Keymap loaded. Updating fake keyboard events...\n"); +#endif + __svgalib_mouse_update_keymap(); + + /* And the fake mouse events */ +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " Updating fake mouse events...\n"); +#endif + kbd_update_keymap(); + + fclose(keymapfile); + } else { + fprintf(stderr, "svgalib: kbd-config: keymap file \'%s\' cannot be opened\n", ptr); + return ptr; + } + + return NULL; +} + +int __svgalib_mapkeyname(const char *keyname) +{ + int scancode; + char *ptr; + +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " Attempting to map \'%s\' to a scancode...", keyname); +#endif + + if(!keyname) { + fprintf(stderr, "svgalib: kbd-config: can't use NULL keyname!\n"); + return -1; + } + + if(!*keyname) { + fprintf(stderr, "svgalib: kbd-config: can't use empty keyname!\n"); + return -1; + } + + /* Is it a number? */ + scancode = strtol(keyname, &ptr, 0); + if(ptr != keyname) { + /* Is it in range? */ + if((scancode < 0) || (scancode >= NR_KEYS)) { + fprintf(stderr, "svgalib: kbd-config: scancode %s out of range!\n",keyname); + return -1; + } else { +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " mapped numerically to %d.\n", scancode); +#endif + return scancode; + } + } + + /* Look up a symbolic name */ + for(scancode = 0; scancode < NR_KEYS; scancode++) { +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " (%s)", keynames[scancode]); +#endif + if(strncasecmp(keyname, keynames[scancode], MAX_KEYNAME_LEN) == 0) { +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " mapped symbolically to %d", scancode); + if(usekeymap) + fprintf(stderr, ", remapped to %d", kbd_mapkey(scancode)); + fprintf(stderr, ".\n"); +#endif + return kbd_mapkey(scancode); + } + } + +#ifdef DEBUG_KEYBOARD + fprintf(stderr, " no match!\n"); +#endif + + /* No match */ + return -1; +} + +static void kbd_update_keymap(void) +{ + /* Remap the scancodes of the fake mouse events */ + int n, i=0; + + for(n = 0; n < fme_used; n++) + if(fake_mouse_events[n]) { + /*for(i = 0; i < fme_numberof[n]; i++)*/ + fake_mouse_events[n][i].scancode = + __svgalib_mapkeyname(fake_mouse_events[n][i].keyname); + } +} diff --git a/src/keyboard/vgakeyboard.h b/src/keyboard/vgakeyboard.h new file mode 100644 index 0000000..0d00a22 --- /dev/null +++ b/src/keyboard/vgakeyboard.h @@ -0,0 +1,200 @@ +/* Keyboard interface for svgalib. */ +/* Can be used independently. */ + +#ifndef VGAKEYBOARD_H +#define VGAKEYBOARD_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_LEFTWIN 125 +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_WINMENU 127 + +#define KEY_EVENTRELEASE 0 +#define KEY_EVENTPRESS 1 + +#define MAX_KEYNAME_LEN 20 + +/* Initialize keyboard handler (brings keyboard into RAW mode). Returns */ +/* 0 if succesful, -1 otherwise. */ + int keyboard_init(void); +/* Similar, but returns console fd if succesful. */ + int keyboard_init_return_fd(void); +/* Set event handler invoked by keyboard_update(). */ + typedef void (*__keyboard_handler) (int scancode, int press); + void keyboard_seteventhandler(__keyboard_handler handler); +/* Return keyboard to normal state. */ + void keyboard_close(void); +/* Read raw keyboard device and handle events. Returns 0 if no event. */ + int keyboard_update(void); +/* Similar to keyboard_update, but wait for an event to happen. */ +/* [This doesn't seem to work very well -- use select on fd] */ + void keyboard_waitforupdate(void); + +/* keyboard_init sets default event handler that keeps track of complete */ +/* keyboard state: */ + +/* Result of keypressed. */ +#define KEY_NOTPRESSED 0 +#define KEY_PRESSED 1 + +/* Modes for translatekeys. */ +#define TRANSLATE_CURSORKEYS 1 /* Map cursor block to keypad cursor. */ +#define TRANSLATE_DIAGONAL 2 /* Map keypad diagonal to keypad cursor. */ +#define TRANSLATE_KEYPADENTER 4 /* Map keypad enter to main enter key. */ +#define DONT_CATCH_CTRLC 8 /* Disable Crtl-C check. */ +#define DONT_CATCH_ALT_Fx 16 /* Disable Console switching on Alt-F[1-12] */ + +/* Revert to default handler. */ + void keyboard_setdefaulteventhandler(void); +/* Return pointer to buffer holding state of each key (scancode). */ +/* Value 1 corresponds to key that is pressed, 0 means not pressed. */ + char *keyboard_getstate(void); +/* Force keyboard state to nothing pressed (all zeroes). */ + void keyboard_clearstate(void); +/* Let default handler translate cursor key block events to numeric keypad */ +/* cursor key events and other translations. */ + void keyboard_translatekeys(int mask); + +/* Return nonzero if key is depressed. */ + int keyboard_keypressed(int scancode); + +#ifdef __cplusplus +} + +#endif +#endif diff --git a/src/libvga.h b/src/libvga.h new file mode 100644 index 0000000..b4db4e5 --- /dev/null +++ b/src/libvga.h @@ -0,0 +1,278 @@ + +/* SVGAlib, Copyright 1993 Harm Hanemaayer */ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* Internal definitions. */ + +#ifndef _LIBVGA_H +#define _LIBVGA_H + +#include + +#include +//typedef unsigned int CARD32; +//typedef unsigned short CARD16; +//typedef unsigned char CARD8; + +/* --------------------- Macro definitions shared by library modules */ + +/* VGA index register ports */ +#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ +#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ +#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define PEL_IW 0x3C8 /* PEL Write Index */ +#define PEL_IR 0x3C7 /* PEL Read Index */ + +/* VGA data register ports */ +#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ +#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ +#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ +#define MIS_R 0x3CC /* Misc Output Read Register */ +#define MIS_W 0x3C2 /* Misc Output Write Register */ +#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ +#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ +#define PEL_D 0x3C9 /* PEL Data Register */ +#define PEL_MSK 0x3C6 /* PEL mask register */ + +/* 8514/MACH regs we need outside of the mach32 driver.. */ +#define PEL8514_D 0x2ED +#define PEL8514_IW 0x2EC +#define PEL8514_IR 0x2EB +#define PEL8514_MSK 0x2EA + +/* EGA-specific registers */ + +#define GRA_E0 0x3CC /* Graphics enable processor 0 */ +#define GRA_E1 0x3CA /* Graphics enable processor 1 */ + +/* standard VGA indexes max counts */ +#define CRT_C 24 /* 24 CRT Controller Registers */ +#define ATT_C 21 /* 21 Attribute Controller Registers */ +#define GRA_C 9 /* 9 Graphics Controller Registers */ +#define SEQ_C 5 /* 5 Sequencer Registers */ +#define MIS_C 1 /* 1 Misc Output Register */ + +/* VGA registers saving indexes */ +#define CRT 0 /* CRT Controller Registers start */ +#define ATT (CRT+CRT_C) /* Attribute Controller Registers start */ +#define GRA (ATT+ATT_C) /* Graphics Controller Registers start */ +#define SEQ (GRA+GRA_C) /* Sequencer Registers */ +#define MIS (SEQ+SEQ_C) /* General Registers */ +#define EXT (MIS+MIS_C) /* SVGA Extended Registers */ + +/* Shorthands for chipset (driver) specific calls */ +#define chipset_saveregs __svgalib_driverspecs->saveregs +#define chipset_setregs __svgalib_driverspecs->setregs +#define chipset_unlock __svgalib_driverspecs->unlock +#define chipset_test __svgalib_driverspecs->test +#define chipset_setpage __svgalib_driverspecs->__svgalib_setpage +#define chipset_setmode __svgalib_driverspecs->setmode +#define chipset_modeavailable __svgalib_driverspecs->modeavailable +#define chipset_getmodeinfo __svgalib_driverspecs->getmodeinfo +#define chipset_cursor __svgalib_driverspecs->cursor + +/* Shorthands for internal variables and functions */ +#define CI __svgalib_cur_info +#define SM __svgalib_sparse_mem +#define GM __svgalib_graph_mem +#define CM __svgalib_cur_mode +#define VMEM __svgalib_videomemoryused +#define DREP __svgalib_driver_report +#define CRITICAL __svgalib_critical +#define COL __svgalib_cur_color +#define CHIPSET __svgalib_chipset +#define SCREENON __svgalib_screenon +#define MODEX __svgalib_modeX +#define MODEFLAGS __svgalib_modeflags +#define infotable __svgalib_infotable + +#define SVGADRV 2 +#define STDVGADRV 1 +#define STDVGAMODE(mode) (chipset_modeavailable(mode) == STDVGADRV) +#define SVGAMODE(mode) (chipset_modeavailable(mode) == SVGADRV) + +#define GRAPH_BASE 0xA0000 +#define FONT_BASE 0xA0000 +#define GRAPH_SIZE 0x10000 +#define FONT_SIZE (0x2000 * 4) /* 2.0.x kernel can use 2 512 char. fonts */ +#define GPLANE16 G640x350x16 + +/* graphics mode information */ +struct vgainfo { + int xdim; + int ydim; + int colors; + int xbytes; + int bytesperpixel; +}; + +/* --------------------- Variable definitions shared by library modules */ + +#define BANKED_POINTER __svgalib_banked_pointer +#define LINEAR_POINTER __svgalib_linear_pointer +#define MMIO_POINTER __svgalib_mmio_pointer + +extern int __svgalib_CRT_I; /* current CRT index register address */ +extern int __svgalib_CRT_D; /* current CRT data register address */ +extern int __svgalib_IS1_R; /* current input status register address */ +extern uint8_t * BANKED_POINTER, * LINEAR_POINTER; +extern uint8_t *MMIO_POINTER; +extern uint8_t *SPARSE_MMIO; +extern unsigned long __svgalib_banked_mem_base, __svgalib_banked_mem_size; +extern unsigned long __svgalib_mmio_base, __svgalib_mmio_size; +extern unsigned long __svgalib_linear_mem_base, __svgalib_linear_mem_size; +extern unsigned long __svgalib_linear_mem_phys_addr; +extern struct vgainfo CI; /* current video parameters */ +extern int COL; /* current color */ +extern int CM; /* current video mode */ +extern struct vgainfo infotable[]; +extern int SCREENON; /* screen visible if != 0 */ +extern unsigned char *GM; /* graphics memory frame */ +extern int MODEX; /* TRUE after vga_setmodeX() */ +extern int MODEFLAGS; /* copy of flags of current modeinfo->flags */ + +extern int __svgalib_mem_fd; +extern int __svgalib_linear_mem_fd; +extern int __svgalib_tty_fd; +extern int __svgalib_nosigint; +extern int __svgalib_mouse_fd; +extern int __svgalib_kbd_fd; +extern int __svgalib_runinbackground; +extern int __svgalib_vgacolormode; +extern int biosparams, biosparam[16]; + +extern unsigned char __svgalib_novga; +extern unsigned char __svgalib_textprog; +extern unsigned char __svgalib_secondary; +extern unsigned char __svgalib_emulatepage; +extern unsigned char __svgalib_novccontrol; +extern unsigned char __svgalib_m_ignore_dx; +extern unsigned char __svgalib_m_ignore_dy; +extern unsigned char __svgalib_m_ignore_dz; +extern unsigned char __svgalib_nohelper; +extern unsigned char __svgalib_fbdev_novga; +extern char *__joystick_devicenames[4]; + +extern int __svgalib_cursor_status; + +/* --------------------- Function definitions shared by library modules */ + +extern int (*__svgalib_inmisc)(void); +extern void (*__svgalib_outmisc)(int); +extern int (*__svgalib_incrtc)(int); +extern void (*__svgalib_outcrtc)(int,int); +extern int (*__svgalib_inseq)(int); +extern void (*__svgalib_outseq)(int,int); +extern int (*__svgalib_ingra)(int); +extern void (*__svgalib_outgra)(int,int); +extern int (*__svgalib_inatt)(int); +extern void (*__svgalib_outatt)(int,int); +extern void (*__svgalib_attscreen)(int); +extern void (*__svgalib_inpal)(int,int*,int*,int*); +extern void (*__svgalib_outpal)(int,int,int,int); +extern int (*__svgalib_inis1)(void); + +extern int __svgalib_setregs(const unsigned char *regs); +extern int __svgalib_saveregs(unsigned char *regs); +extern void __svgalib_dumpregs(const unsigned char regs[], int n); +extern int __svgalib_getchipset(void); +extern int __svgalib_name2number(char *modename); +extern void __svgalib_delay(void); +extern int __svgalib_addmode(int xdim, int ydim, int cols, int xbytes, int bytespp); +extern void __svgalib_waitvtactive(void); +extern void __svgalib_open_devconsole(void); +extern void (*__svgalib_mouse_eventhandler) (int, int, int, int, int, int, int); +extern void (*__svgalib_keyboard_eventhandler) (int, int); +extern void __joystick_flip_vc(int acquire); +extern char *__svgalib_TextProg_argv[16]; /* should be enough */ +extern char *__svgalib_TextProg; +extern int __svgalib_VESA_savebitmap; +extern int __svgalib_VESA_textmode; +extern unsigned char __svgalib_vesatext; +extern int __svgalib_mapkeyname(const char *keyname); +extern void __svgalib_mouse_update_keymap(void); +extern int __svgalib_vgacolor(void); +extern void __svgalib_cursor_restore(void); +extern void map_mmio(void); +extern void map_mem(void); +extern void map_linear(int flags); +extern void map_banked(int flags); +extern void unmap_linear(void); + +#if 0 +/* remove this part ? */ +extern void __svgalib_releasevt_signal(int n); +extern void __svgalib_acquirevt_signal(int n); +#endif + +#define gr_readb(off) (((volatile uint8_t *)GM)[(off)]) +#define gr_readw(off) (*(volatile uint16_t*)((GM)+(off))) +#define gr_readl(off) (*(volatile uint32_t*)((GM)+(off))) +#define gr_writeb(v,off) (GM[(off)] = (v)) +#define gr_writew(v,off) (*(uint16_t*)((GM)+(off)) = (v)) +#define gr_writel(v,off) (*(uint32_t*)((GM)+(off)) = (v)) + +extern void __svgalib_port_out(int value, int port); +extern void __svgalib_port_outw(int value, int port); +extern void __svgalib_port_outl(int value, int port); +extern void __svgalib_port_rep_outb(unsigned char* string, int length, int port); + +extern int __svgalib_port_in(int port); +extern int __svgalib_port_inw(int port); +extern int __svgalib_port_inl(int port); + +#define port_in __svgalib_port_in +#define port_inw __svgalib_port_inw +#define port_inl __svgalib_port_inl +#define port_out __svgalib_port_out +#define port_outw __svgalib_port_outw +#define port_outl __svgalib_port_outl +#define port_rep_outb __svgalib_port_rep_outb + +/* Note that the arguments of outb/w are reversed compared with the */ +/* kernel sources. The XFree86 drivers also use this format. */ +#define port_out_r(port, value) port_out(value, port) +#define port_outw_r(port, value) port_outw(value, port) +#define port_outl_r(port, value) port_outl(value, port) + +/* Background things */ + +extern unsigned char *__svgalib_give_graph_red(void); +extern unsigned char *__svgalib_give_graph_green(void); +extern unsigned char *__svgalib_give_graph_blue(void); + +#define zero_sa_mask(maskptr) memset(maskptr, 0, sizeof(sigset_t)) + +#if 1 + +#define SVGALIB_ACQUIRE_SIG SIGUSR2 +#define SVGALIB_RELEASE_SIG SIGUSR1 + +#else + +#define SVGALIB_ACQUIRE_SIG SIGUNUSED +#define SVGALIB_RELEASE_SIG SIGPROF + +#endif + +//#define DEBUG_TRACE + +#ifdef DEBUG_TRACE +#define DTP(x) fprintf x +#else +#define DTP(x) +#endif + +#ifdef DEBUG +#define DPRINTF(args...) fprintf(stderr, args) +#else +#define DPRINTF(...) +#endif + +#endif /* _LIBVGA_H */ + diff --git a/src/lrmi.6.c b/src/lrmi.6.c new file mode 100644 index 0000000..75df7df --- /dev/null +++ b/src/lrmi.6.c @@ -0,0 +1,897 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +You are free to distribute and modify this file, as long as you +do not remove this copyright notice and clearly label modified +versions as being modified. + +This software has NO WARRANTY. Use it at your own risk. +*/ + +#include +#include +#include + +#ifdef USE_LIBC_VM86 +#include +#endif + +#include +#include +#include +#include +#include + +#include "lrmi.h" +#include "libvga.h" + +#define REAL_MEM_BASE ((void *)0x10000) +#define REAL_MEM_SIZE 0x10000 +#define REAL_MEM_BLOCKS 0x100 + +struct mem_block + { + unsigned int size : 20; + unsigned int free : 1; + }; + +static struct + { + int ready; + int count; + struct mem_block blocks[REAL_MEM_BLOCKS]; + } mem_info = { 0 }; + +static int +real_mem_init(void) + { + void *m; + int fd_zero; + + if (mem_info.ready) + return 1; + + fd_zero = open("/dev/zero", O_RDONLY); + if (fd_zero == -1) + { + perror("open /dev/zero"); + return 0; + } + + m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_zero, 0); + + if (m == (void *)-1) + { + perror("mmap /dev/zero"); + close(fd_zero); + return 0; + } + + mem_info.ready = 1; + mem_info.count = 1; + mem_info.blocks[0].size = REAL_MEM_SIZE; + mem_info.blocks[0].free = 1; + + return 1; + } + + +static void +insert_block(int i) + { + memmove( + mem_info.blocks + i + 1, + mem_info.blocks + i, + (mem_info.count - i) * sizeof(struct mem_block)); + + mem_info.count++; + } + +static void +delete_block(int i) + { + mem_info.count--; + + memmove( + mem_info.blocks + i, + mem_info.blocks + i + 1, + (mem_info.count - i) * sizeof(struct mem_block)); + } + +static void * +LRMI_alloc_real(int size) + { + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return NULL; + + if (mem_info.count == REAL_MEM_BLOCKS) + return NULL; + + size = (size + 15) & ~15; + + for (i = 0; i < mem_info.count; i++) + { + if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) + { + insert_block(i); + + mem_info.blocks[i].size = size; + mem_info.blocks[i].free = 0; + mem_info.blocks[i + 1].size -= size; + + return (void *)r; + } + + r += mem_info.blocks[i].size; + } + + return NULL; + } + + +static void +LRMI_free_real(void *m) + { + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return; + + i = 0; + while (m != (void *)r) + { + r += mem_info.blocks[i].size; + i++; + if (i == mem_info.count) + return; + } + + mem_info.blocks[i].free = 1; + + if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) + { + mem_info.blocks[i].size += mem_info.blocks[i + 1].size; + delete_block(i + 1); + } + + if (i - 1 >= 0 && mem_info.blocks[i - 1].free) + { + mem_info.blocks[i - 1].size += mem_info.blocks[i].size; + delete_block(i); + } + } + + +#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK) +#define DEFAULT_STACK_SIZE 0x1000 +#define RETURN_TO_32_INT 255 + +static struct + { + int ready; + unsigned short ret_seg, ret_off; + unsigned short stack_seg, stack_off; + struct vm86_struct vm; + } context = { 0 }; + + +static inline void +set_bit(unsigned int bit, void *array) + { + unsigned char *a = array; + + a[bit / 8] |= (1 << (bit % 8)); + } + + +static inline unsigned int +get_int_seg(int i) + { + return *(unsigned short *)(i * 4 + 2); + } + + +static inline unsigned int +get_int_off(int i) + { + return *(unsigned short *)(i * 4); + } + + +static inline void +pushw(unsigned short i) + { + struct vm86_regs *r = &context.vm.regs; + r->esp -= 2; + *(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i; + } + + +static int +LRMI_init(void) + { + void *m; + int fd_mem; + + if (context.ready) + return 1; + + if (!real_mem_init()) + return 0; + + /* + Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) + and the ROM (0xa0000 - 0x100000) + */ + fd_mem = __svgalib_mem_fd; + + if (fd_mem == -1) + { + perror("open /dev/svga"); + return 0; + } + + m = mmap((void *)0, 0x502, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_mem, 0); + + if (m == (void *)-1) + { + perror("mmap /dev/svga"); + return 0; + } + + m = mmap((void *)0xa0000, 0x100000 - 0xa0000, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); + + if (m == (void *)-1) + { + perror("mmap /dev/svga"); + return 0; + } + + /* + Allocate a stack + */ + m = LRMI_alloc_real(DEFAULT_STACK_SIZE); + + context.stack_seg = (unsigned int)m >> 4; + context.stack_off = DEFAULT_STACK_SIZE; + + /* + Allocate the return to 32 bit routine + */ + m = LRMI_alloc_real(2); + + context.ret_seg = (unsigned int)m >> 4; + context.ret_off = (unsigned int)m & 0xf; + + ((unsigned char *)m)[0] = 0xcd; /* int opcode */ + ((unsigned char *)m)[1] = RETURN_TO_32_INT; + + memset(&context.vm, 0, sizeof(context.vm)); + + context.vm.cpu_type=CPU_386; + /* + Enable kernel emulation of all ints except RETURN_TO_32_INT + */ + memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); + set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); + + context.ready = 1; + + return 1; + } + + +static void +set_regs(struct vm86_regs *r) + { + context.vm.regs = *r; + context.vm.regs.eflags = DEFAULT_VM86_FLAGS; + } + + +static void +get_regs(struct vm86_regs *r) + { + *r = context.vm.regs; + } + +#define DIRECTION_FLAG (1 << 10) + +static void +em_ins(int size) + { + unsigned int edx, edi; + + edx = context.vm.regs.edx & 0xffff; + edi = context.vm.regs.edi & 0xffff; + edi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; insl; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("std; insw; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("std; insb; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + } + else + { + if (size == 4) + asm volatile ("cld; insl" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("cld; insw" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("cld; insb" + : "=D" (edi) : "d" (edx), "0" (edi)); + } + + edi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.edi &= 0xffff0000; + context.vm.regs.edi |= edi & 0xffff; + } + +static void +em_rep_ins(int size) + { + unsigned int ecx, edx, edi; + + ecx = context.vm.regs.ecx & 0xffff; + edx = context.vm.regs.edx & 0xffff; + edi = context.vm.regs.edi & 0xffff; + edi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; rep; insl; cld" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else if (size == 2) + asm volatile ("std; rep; insw; cld" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else + asm volatile ("std; rep; insb; cld" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + } + else + { + if (size == 4) + asm volatile ("cld; rep; insl" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else if (size == 2) + asm volatile ("cld; rep; insw" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + else + asm volatile ("cld; rep; insb" + : "=D" (edi), "=c" (ecx) + : "d" (edx), "0" (edi), "1" (ecx)); + } + + edi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.edi &= 0xffff0000; + context.vm.regs.edi |= edi & 0xffff; + + context.vm.regs.ecx &= 0xffff0000; + context.vm.regs.ecx |= ecx & 0xffff; + } + +static void +em_outs(int size) + { + unsigned int edx, esi; + + edx = context.vm.regs.edx & 0xffff; + esi = context.vm.regs.esi & 0xffff; + esi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; outsl; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("std; outsw; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("std; outsb; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + } + else + { + if (size == 4) + asm volatile ("cld; outsl" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("cld; outsw" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("cld; outsb" + : "=S" (esi) : "d" (edx), "0" (esi)); + } + + esi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.esi &= 0xffff0000; + context.vm.regs.esi |= esi & 0xffff; + } + +static void +em_rep_outs(int size) + { + unsigned int ecx, edx, esi; + + ecx = context.vm.regs.ecx & 0xffff; + edx = context.vm.regs.edx & 0xffff; + esi = context.vm.regs.esi & 0xffff; + esi += (unsigned int)context.vm.regs.ds << 4; + + if (context.vm.regs.eflags & DIRECTION_FLAG) + { + if (size == 4) + asm volatile ("std; rep; outsl; cld" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else if (size == 2) + asm volatile ("std; rep; outsw; cld" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else + asm volatile ("std; rep; outsb; cld" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + } + else + { + if (size == 4) + asm volatile ("cld; rep; outsl" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else if (size == 2) + asm volatile ("cld; rep; outsw" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + else + asm volatile ("cld; rep; outsb" + : "=S" (esi), "=c" (ecx) + : "d" (edx), "0" (esi), "1" (ecx)); + } + + esi -= (unsigned int)context.vm.regs.ds << 4; + + context.vm.regs.esi &= 0xffff0000; + context.vm.regs.esi |= esi & 0xffff; + + context.vm.regs.ecx &= 0xffff0000; + context.vm.regs.ecx |= ecx & 0xffff; + } + +static void +em_inb(int port) + { + context.vm.regs.eax&=0xffffff00; + context.vm.regs.eax|=port_in(port); + } + +static void +em_inw(int port) + { + context.vm.regs.eax&=0xffff0000; + context.vm.regs.eax|=port_inw(port); + } + +static void +em_inl(int port) + { + context.vm.regs.eax=port_inl(port); + } + +static void +em_outb(int port) + { + port_out(context.vm.regs.eax,port); + } + +static void +em_outw(int port) + { + port_outw(context.vm.regs.eax,port); + } + +static void +em_outl(int port) + { + port_outl(context.vm.regs.eax,port); + } + +static int +emulate(void) + { + unsigned char *insn; + struct + { + unsigned int size : 1; + unsigned int rep : 1; + } prefix = { 0, 0 }; + int i = 0; + + insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4); + insn += context.vm.regs.eip; + + while (1) + { + if (insn[i] == 0x66) + { + prefix.size = 1 - prefix.size; + i++; + } + else if (insn[i] == 0xf3) + { + prefix.rep = 1; + i++; + } + else if (insn[i] == 0xf0 || insn[i] == 0xf2 + || insn[i] == 0x26 || insn[i] == 0x2e + || insn[i] == 0x36 || insn[i] == 0x3e + || insn[i] == 0x64 || insn[i] == 0x65 + || insn[i] == 0x67) + { + /* these prefixes are just ignored */ + i++; + } + else if (insn[i] == 0x6c) + { + if (prefix.rep) + em_rep_ins(1); + else + em_ins(1); + i++; + break; + } + else if (insn[i] == 0x6d) + { + if (prefix.rep) + { + if (prefix.size) + em_rep_ins(4); + else + em_rep_ins(2); + } + else + { + if (prefix.size) + em_ins(4); + else + em_ins(2); + } + i++; + break; + } + else if (insn[i] == 0x6e) + { + if (prefix.rep) + em_rep_outs(1); + else + em_outs(1); + i++; + break; + } + else if (insn[i] == 0x6f) + { + if (prefix.rep) + { + if (prefix.size) + em_rep_outs(4); + else + em_rep_outs(2); + } + else + { + if (prefix.size) + em_outs(4); + else + em_outs(2); + } + i++; + break; + } + else if (insn[i] == 0xe4) + { + i++; + em_inb(insn[i]); + i++; + break; + } + else if (insn[i] == 0xe5) + { + i++; + if (prefix.size) + em_inl(insn[i]); + else + em_inw(insn[i]); + i++; + break; + } + else if (insn[i] == 0xe6) + { + i++; + em_outb(insn[i]); + i++; + break; + } + else if (insn[i] == 0xe7) + { + i++; + if (prefix.size) + em_outl(insn[i]); + else + em_outw(insn[i]); + i++; + break; + } + else if (insn[i] == 0xec) + { + em_inb(context.vm.regs.edx&0xffff); + i++; + break; + } + else if (insn[i] == 0xed) + { + if (prefix.size) + em_inl(context.vm.regs.edx&0xffff); + else + em_inw(context.vm.regs.edx&0xffff); + i++; + break; + } + else if (insn[i] == 0xee) + { + em_outb(context.vm.regs.edx&0xffff); + i++; + break; + } + else if (insn[i] == 0xef) + { + if (prefix.size) + em_outl(context.vm.regs.edx&0xffff); + else + em_outw(context.vm.regs.edx&0xffff); + + i++; + break; + } + else + return 0; + } + + context.vm.regs.eip += i; + return 1; + } + + +/* + I don't know how to make sure I get the right vm86() from libc. + The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) + which should be declared as "int vm86(struct vm86_struct *);" in + . + + This just does syscall 113 with inline asm, which should work + for both libc's (I hope). +*/ +#if !defined(USE_LIBC_VM86) +static int +lrmi_vm86(struct vm86_struct *vm) + { + int r; +#ifdef __PIC__ + asm volatile ( + "pushl %%ebx\n\t" + "movl %2, %%ebx\n\t" + "int $0x80\n\t" + "popl %%ebx" + : "=a" (r) + : "0" (113), "r" (vm)); +#else + asm volatile ( + "int $0x80" + : "=a" (r) + : "0" (113), "b" (vm)); +#endif + return r; + } +#else +#define lrmi_vm86 vm86 +#endif + + +static void +debug_info(int vret) + { + int i; + unsigned char *p; + + fputs("vm86() failed\n", stderr); + fprintf(stderr, "return = 0x%x\n", vret); + fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax); + fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx); + fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx); + fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx); + fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi); + fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi); + fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp); + fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip); + fprintf(stderr, "cs = 0x%04x\n", context.vm.regs.cs); + fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp); + fprintf(stderr, "ss = 0x%04x\n", context.vm.regs.ss); + fprintf(stderr, "ds = 0x%04x\n", context.vm.regs.ds); + fprintf(stderr, "es = 0x%04x\n", context.vm.regs.es); + fprintf(stderr, "fs = 0x%04x\n", context.vm.regs.fs); + fprintf(stderr, "gs = 0x%04x\n", context.vm.regs.gs); + fprintf(stderr, "eflags = 0x%08lx\n", context.vm.regs.eflags); + + fputs("cs:ip = [ ", stderr); + + p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff)); + + for (i = 0; i < 16; ++i) + fprintf(stderr, "%02x ", (unsigned int)p[i]); + + fputs("]\n", stderr); + } + + +static int +run_vm86(void) + { + unsigned int vret; + + while (1) + { + vret = lrmi_vm86(&context.vm); + + if (VM86_TYPE(vret) == VM86_SIGNAL || + VM86_TYPE(vret) == VM86_STI || + VM86_TYPE(vret) == VM86_PICRETURN) { + context.vm.regs.eflags &= ~VIP_MASK; + continue; + } + + if (VM86_TYPE(vret) == VM86_INTx) + { + unsigned int v = VM86_ARG(vret); + + if (v == RETURN_TO_32_INT) + return 1; + + pushw(context.vm.regs.eflags); + pushw(context.vm.regs.cs); + pushw(context.vm.regs.eip); + + context.vm.regs.cs = get_int_seg(v); + context.vm.regs.eip = get_int_off(v); + context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK); + + continue; + } + + if (VM86_TYPE(vret) != VM86_UNKNOWN) + break; + + if (!emulate()) + break; + } + + debug_info(vret); + + return 0; + } + + +static int +LRMI_call(struct vm86_regs *r) + { + unsigned int vret; + + set_regs(r); + + context.vm.regs.cs = r->cs; + context.vm.regs.eip = r->eip & 0xffff; + + if (r->ss == 0 && (r->esp & 0xffff) == 0) + { + context.vm.regs.ss = context.stack_seg; + context.vm.regs.esp = context.stack_off; + } + else + { + context.vm.regs.ss = r->ss; + context.vm.regs.esp = r->esp & 0xffff; + } + + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; + } + + +static int +LRMI_int(int i, struct vm86_regs *r) + { + unsigned int vret; + unsigned int seg, off; + + seg = get_int_seg(i); + off = get_int_off(i); + + /* + If the interrupt is in regular memory, it's probably + still pointing at a dos TSR (which is now gone). + */ + if (seg < 0xa000 || (seg << 4) + off >= 0x100000) + { + fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); + return 0; + } + + set_regs(r); + + context.vm.regs.cs = seg; + context.vm.regs.eip = off; + + if (r->ss == 0 && (r->esp & 0xffff) == 0) + { + context.vm.regs.ss = context.stack_seg; + context.vm.regs.esp = context.stack_off; + } + else + { + context.vm.regs.ss = r->ss; + context.vm.regs.esp = r->esp & 0xffff; + } + + pushw(DEFAULT_VM86_FLAGS); + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; + } + +LRMI_callbacks __svgalib_default_LRMI_callbacks = { + .rm_init = LRMI_init, + .rm_call = LRMI_call, + .rm_int = LRMI_int, + .rm_alloc_real = LRMI_alloc_real, + .rm_free_real = LRMI_free_real, +}; diff --git a/src/lrmi.6.h b/src/lrmi.6.h new file mode 100644 index 0000000..235594d --- /dev/null +++ b/src/lrmi.6.h @@ -0,0 +1,23 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +You are free to distribute and modify this file, as long as you +do not remove this copyright notice and clearly label modified +versions as being modified. + +This software has NO WARRANTY. Use it at your own risk. +*/ + +#ifndef LRMI_H +#define LRMI_H + +#define _SVGALIB_LRMI +#define LRMI_regs vm86_regs +#include "vga.h" + +extern LRMI_callbacks __svgalib_default_LRMI_callbacks; +extern LRMI_callbacks * __svgalib_LRMI_callbacks; + +#endif diff --git a/src/lrmi.9.c b/src/lrmi.9.c new file mode 100644 index 0000000..09cc6ae --- /dev/null +++ b/src/lrmi.9.c @@ -0,0 +1,1041 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined(__OpenBSD__)) + +#include +#include + +#if defined(__linux__) + +#include +#include + +#ifdef USE_LIBC_VM86 +#include +#endif + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + +#include +#include +#include +#include +#include +#include + +#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ + +#include +#include +#include +#include +#include + +#define LRMI_C + +#include "lrmi.h" +#include "libvga.h" + +#define REAL_MEM_BASE ((void *)0x10000) +#define REAL_MEM_SIZE 0x40000 +#define REAL_MEM_BLOCKS 0x100 + +struct mem_block { + unsigned int size : 20; + unsigned int free : 1; +}; + +static struct { + int ready; + int count; + struct mem_block blocks[REAL_MEM_BLOCKS]; +} mem_info = { 0 }; + +static int +real_mem_init(void) +{ + void *m; + int fd_zero; + + if (mem_info.ready) + return 1; + + fd_zero = open("/dev/zero", O_RDONLY); + if (fd_zero == -1) { + perror("open /dev/zero"); + return 0; + } + + m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_zero, 0); + + if (m == (void *)-1) { + perror("mmap /dev/zero"); + close(fd_zero); + return 0; + } + + close(fd_zero); + + mem_info.ready = 1; + mem_info.count = 1; + mem_info.blocks[0].size = REAL_MEM_SIZE; + mem_info.blocks[0].free = 1; + + return 1; +} + +static void +real_mem_deinit(void) +{ + if (mem_info.ready) { + munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE); + mem_info.ready = 0; + } +} + + +static void +insert_block(int i) +{ + memmove( + mem_info.blocks + i + 1, + mem_info.blocks + i, + (mem_info.count - i) * sizeof(struct mem_block)); + + mem_info.count++; +} + +static void +delete_block(int i) +{ + mem_info.count--; + + memmove( + mem_info.blocks + i, + mem_info.blocks + i + 1, + (mem_info.count - i) * sizeof(struct mem_block)); +} + +static void * +LRMI_alloc_real(int size) +{ + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return NULL; + + if (mem_info.count == REAL_MEM_BLOCKS) + return NULL; + + size = (size + 15) & ~15; + + for (i = 0; i < mem_info.count; i++) { + if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) { + insert_block(i); + + mem_info.blocks[i].size = size; + mem_info.blocks[i].free = 0; + mem_info.blocks[i + 1].size -= size; + + return (void *)r; + } + + r += mem_info.blocks[i].size; + } + + return NULL; +} + + +static void +LRMI_free_real(void *m) +{ + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return; + + i = 0; + while (m != (void *)r) { + r += mem_info.blocks[i].size; + i++; + if (i == mem_info.count) + return; + } + + mem_info.blocks[i].free = 1; + + if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) { + mem_info.blocks[i].size += mem_info.blocks[i + 1].size; + delete_block(i + 1); + } + + if (i - 1 >= 0 && mem_info.blocks[i - 1].free) { + mem_info.blocks[i - 1].size += mem_info.blocks[i].size; + delete_block(i); + } +} + + +#if defined(__linux__) +#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK) +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#define DEFAULT_VM86_FLAGS (PSL_I | PSL_IOPL) +#define TF_MASK PSL_T +#define VIF_MASK PSL_VIF +#endif +#define DEFAULT_STACK_SIZE 0x1000 +#define RETURN_TO_32_INT 255 + +#if defined(__linux__) +#define CONTEXT_REGS context.vm.regs +#define REG(x) x +#elif defined(__NetBSD__) || defined(__OpenBSD__) +#define CONTEXT_REGS context.vm.substr.regs +#define REG(x) vmsc.sc_ ## x +#elif defined(__FreeBSD__) +#define CONTEXT_REGS context.vm.uc +#define REG(x) uc_mcontext.mc_ ## x +#endif + +static struct { + int ready; + unsigned short ret_seg, ret_off; + unsigned short stack_seg, stack_off; +#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) + struct vm86_struct vm; +#elif defined(__FreeBSD__) + struct { + struct vm86_init_args init; + ucontext_t uc; + } vm; +#endif +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + int success; + jmp_buf env; + void *old_sighandler; + int vret; +#endif +} context = { 0 }; + + +static inline void +set_bit(unsigned int bit, void *array) +{ + unsigned char *a = array; + + a[bit / 8] |= (1 << (bit % 8)); +} + + +static inline unsigned int +get_int_seg(int i) +{ + return *(unsigned short *)(i * 4 + 2); +} + + +static inline unsigned int +get_int_off(int i) +{ + return *(unsigned short *)(i * 4); +} + + +static inline void +pushw(unsigned short i) +{ + CONTEXT_REGS.REG(esp) -= 2; + *(unsigned short *)(((unsigned int)CONTEXT_REGS.REG(ss) << 4) + + CONTEXT_REGS.REG(esp)) = i; +} + + +static int +LRMI_init(void) +{ + void *m; + int fd_mem; + + if (context.ready) + return 1; + + if (!real_mem_init()) + return 0; + + /* + Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) + and the ROM (0xa0000 - 0x100000) + */ + fd_mem = __svgalib_mem_fd; + + if (fd_mem == -1) { + real_mem_deinit(); + perror("open /dev/svga"); + return 0; + } + + m = mmap((void *)0, 0x502, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, fd_mem, 0); + + if (m == (void *)-1) { + real_mem_deinit(); + perror("mmap /dev/svga"); + return 0; + } + + m = mmap((void *)0xa0000, 0x100000 - 0xa0000, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); + + if (m == (void *)-1) { + munmap((void *)0, 0x502); + real_mem_deinit(); + perror("mmap /dev/mem"); + return 0; + } + + /* + Allocate a stack + */ + m = LRMI_alloc_real(DEFAULT_STACK_SIZE); + + context.stack_seg = (unsigned int)m >> 4; + context.stack_off = DEFAULT_STACK_SIZE; + + /* + Allocate the return to 32 bit routine + */ + m = LRMI_alloc_real(2); + + context.ret_seg = (unsigned int)m >> 4; + context.ret_off = (unsigned int)m & 0xf; + + ((unsigned char *)m)[0] = 0xcd; /* int opcode */ + ((unsigned char *)m)[1] = RETURN_TO_32_INT; + + memset(&context.vm, 0, sizeof(context.vm)); + + /* + Enable kernel emulation of all ints except RETURN_TO_32_INT + */ +#if defined(__linux__) + memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); + set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + set_bit(RETURN_TO_32_INT, &context.vm.int_byuser); +#elif defined(__FreeBSD__) + set_bit(RETURN_TO_32_INT, &context.vm.init.int_map); +#endif + + context.ready = 1; + + return 1; +} + + +static void +set_regs(struct LRMI_regs *r) +{ + CONTEXT_REGS.REG(edi) = r->edi; + CONTEXT_REGS.REG(esi) = r->esi; + CONTEXT_REGS.REG(ebp) = r->ebp; + CONTEXT_REGS.REG(ebx) = r->ebx; + CONTEXT_REGS.REG(edx) = r->edx; + CONTEXT_REGS.REG(ecx) = r->ecx; + CONTEXT_REGS.REG(eax) = r->eax; + CONTEXT_REGS.REG(eflags) = DEFAULT_VM86_FLAGS; + CONTEXT_REGS.REG(es) = r->es; + CONTEXT_REGS.REG(ds) = r->ds; + CONTEXT_REGS.REG(fs) = r->fs; + CONTEXT_REGS.REG(gs) = r->gs; +} + + +static void +get_regs(struct LRMI_regs *r) +{ + r->edi = CONTEXT_REGS.REG(edi); + r->esi = CONTEXT_REGS.REG(esi); + r->ebp = CONTEXT_REGS.REG(ebp); + r->ebx = CONTEXT_REGS.REG(ebx); + r->edx = CONTEXT_REGS.REG(edx); + r->ecx = CONTEXT_REGS.REG(ecx); + r->eax = CONTEXT_REGS.REG(eax); + r->flags = CONTEXT_REGS.REG(eflags); + r->es = CONTEXT_REGS.REG(es); + r->ds = CONTEXT_REGS.REG(ds); + r->fs = CONTEXT_REGS.REG(fs); + r->gs = CONTEXT_REGS.REG(gs); +} + +#define DIRECTION_FLAG (1 << 10) + +enum { + CSEG = 0x2e, SSEG = 0x36, DSEG = 0x3e, + ESEG = 0x26, FSEG = 0x64, GSEG = 0x65, +}; + +static void +em_ins(int size) +{ + unsigned int edx, edi; + + edx = CONTEXT_REGS.REG(edx) & 0xffff; + edi = CONTEXT_REGS.REG(edi) & 0xffff; + edi += (unsigned int)CONTEXT_REGS.REG(es) << 4; + + if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) { + if (size == 4) + asm volatile ("std; insl; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("std; insw; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("std; insb; cld" + : "=D" (edi) : "d" (edx), "0" (edi)); + } else { + if (size == 4) + asm volatile ("cld; insl" + : "=D" (edi) : "d" (edx), "0" (edi)); + else if (size == 2) + asm volatile ("cld; insw" + : "=D" (edi) : "d" (edx), "0" (edi)); + else + asm volatile ("cld; insb" + : "=D" (edi) : "d" (edx), "0" (edi)); + } + + edi -= (unsigned int)CONTEXT_REGS.REG(es) << 4; + + CONTEXT_REGS.REG(edi) &= 0xffff0000; + CONTEXT_REGS.REG(edi) |= edi & 0xffff; +} + +static void +em_rep_ins(int size) +{ + unsigned int cx; + + cx = CONTEXT_REGS.REG(ecx) & 0xffff; + + while (cx--) + em_ins(size); + + CONTEXT_REGS.REG(ecx) &= 0xffff0000; +} + +static void +em_outs(int size, int seg) +{ + unsigned int edx, esi, base; + + edx = CONTEXT_REGS.REG(edx) & 0xffff; + esi = CONTEXT_REGS.REG(esi) & 0xffff; + + switch (seg) { + case CSEG: base = CONTEXT_REGS.REG(cs); break; + case SSEG: base = CONTEXT_REGS.REG(ss); break; + case ESEG: base = CONTEXT_REGS.REG(es); break; + case FSEG: base = CONTEXT_REGS.REG(fs); break; + case GSEG: base = CONTEXT_REGS.REG(gs); break; + default: + case DSEG: base = CONTEXT_REGS.REG(ds); break; + } + + esi += base << 4; + + if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) { + if (size == 4) + asm volatile ("std; outsl; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("std; outsw; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("std; outsb; cld" + : "=S" (esi) : "d" (edx), "0" (esi)); + } else { + if (size == 4) + asm volatile ("cld; outsl" + : "=S" (esi) : "d" (edx), "0" (esi)); + else if (size == 2) + asm volatile ("cld; outsw" + : "=S" (esi) : "d" (edx), "0" (esi)); + else + asm volatile ("cld; outsb" + : "=S" (esi) : "d" (edx), "0" (esi)); + } + + esi -= base << 4; + + CONTEXT_REGS.REG(esi) &= 0xffff0000; + CONTEXT_REGS.REG(esi) |= esi & 0xffff; +} + +static void +em_rep_outs(int size, int seg) +{ + unsigned int cx; + + cx = CONTEXT_REGS.REG(ecx) & 0xffff; + + while (cx--) + em_outs(size, seg); + + CONTEXT_REGS.REG(ecx) &= 0xffff0000; +} + +static void +em_inb(int port) +{ + context.vm.regs.eax&=0xffffff00; + context.vm.regs.eax|=port_in(port); +} + +static void +em_inw(int port) +{ + context.vm.regs.eax&=0xffff0000; + context.vm.regs.eax|=port_inw(port); +} + +static void +em_inl(int port) +{ + context.vm.regs.eax=port_inl(port); +} + +static void +em_outb(int port) +{ + port_out(context.vm.regs.eax,port); +} + +static void +em_outw(int port) +{ + port_outw(context.vm.regs.eax,port); +} + +static void +em_outl(int port) +{ + port_outl(context.vm.regs.eax,port); +} + +static int +emulate(void) +{ + unsigned char *insn; + struct { + unsigned char seg; + unsigned int size : 1; + unsigned int rep : 1; + } prefix = { DSEG, 0, 0 }; + int i = 0; + + insn = (unsigned char *)((unsigned int)CONTEXT_REGS.REG(cs) << 4); + insn += CONTEXT_REGS.REG(eip); + + while (1) { + if (insn[i] == 0x66) { + prefix.size = 1 - prefix.size; + i++; + } else if (insn[i] == 0xf3) { + prefix.rep = 1; + i++; + } else if (insn[i] == CSEG || insn[i] == SSEG + || insn[i] == DSEG || insn[i] == ESEG + || insn[i] == FSEG || insn[i] == GSEG) { + prefix.seg = insn[i]; + i++; + } else if (insn[i] == 0xf0 || insn[i] == 0xf2 + || insn[i] == 0x67) { + /* these prefixes are just ignored */ + i++; + } else if (insn[i] == 0x6c) { + if (prefix.rep) + em_rep_ins(1); + else + em_ins(1); + i++; + break; + } else if (insn[i] == 0x6d) { + if (prefix.rep) { + if (prefix.size) + em_rep_ins(4); + else + em_rep_ins(2); + } else { + if (prefix.size) + em_ins(4); + else + em_ins(2); + } + i++; + break; + } else if (insn[i] == 0x6e) { + if (prefix.rep) + em_rep_outs(1, prefix.seg); + else + em_outs(1, prefix.seg); + i++; + break; + } else if (insn[i] == 0x6f) { + if (prefix.rep) { + if (prefix.size) + em_rep_outs(4, prefix.seg); + else + em_rep_outs(2, prefix.seg); + } else { + if (prefix.size) + em_outs(4, prefix.seg); + else + em_outs(2, prefix.seg); + } + i++; + break; + } else if (insn[i] == 0xe4) { + em_inb(insn[i + 1]); + i += 2; + break; + } else if (insn[i] == 0xe5) { + i++; + if (prefix.size) + em_inl(insn[i]); + else + em_inw(insn[i]); + i++; + break; + } else if (insn[i] == 0xe6) { + i++; + em_outb(insn[i]); + i++; + break; + } else if (insn[i] == 0xe7) { + i++; + if (prefix.size) + em_outl(insn[i]); + else + em_outw(insn[i]); + i++; + break; + } else if (insn[i] == 0xec) { + em_inb(CONTEXT_REGS.REG(edx)&0xffff); + i++; + break; + } else if (insn[i] == 0xed) { + if (prefix.size) + em_inl(CONTEXT_REGS.REG(edx)&0xffff); + else + em_inw(CONTEXT_REGS.REG(edx)&0xffff); + i++; + break; + } else if (insn[i] == 0xee) { + em_outb(CONTEXT_REGS.REG(edx)&0xffff); + i++; + break; + } else if (insn[i] == 0xef) { + if (prefix.size) + em_outl(CONTEXT_REGS.REG(edx)&0xffff); + else + em_outw(CONTEXT_REGS.REG(edx)&0xffff); + + i++; + break; + } else + return 0; + } + + CONTEXT_REGS.REG(eip) += i; + return 1; +} + + +#if defined(__linux__) +/* + I don't know how to make sure I get the right vm86() from libc. + The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) + which should be declared as "int vm86(struct vm86_struct *);" in + . + + This just does syscall 113 with inline asm, which should work + for both libc's (I hope). +*/ +#if !defined(USE_LIBC_VM86) +static int +lrmi_vm86(struct vm86_struct *vm) +{ + int r; +#ifdef __PIC__ + asm volatile ( + "pushl %%ebx\n\t" + "movl %2, %%ebx\n\t" + "int $0x80\n\t" + "popl %%ebx" + : "=a" (r) + : "0" (113), "r" (vm)); +#else + asm volatile ( + "int $0x80" + : "=a" (r) + : "0" (113), "b" (vm)); +#endif + return r; +} +#else +#define lrmi_vm86 vm86 +#endif +#endif /* __linux__ */ + + +static void +debug_info(int vret) +{ +#ifdef LRMI_DEBUG + int i; + unsigned char *p; + + fputs("vm86() failed\n", stderr); + fprintf(stderr, "return = 0x%x\n", vret); + fprintf(stderr, "eax = 0x%08x\n", CONTEXT_REGS.REG(eax)); + fprintf(stderr, "ebx = 0x%08x\n", CONTEXT_REGS.REG(ebx)); + fprintf(stderr, "ecx = 0x%08x\n", CONTEXT_REGS.REG(ecx)); + fprintf(stderr, "edx = 0x%08x\n", CONTEXT_REGS.REG(edx)); + fprintf(stderr, "esi = 0x%08x\n", CONTEXT_REGS.REG(esi)); + fprintf(stderr, "edi = 0x%08x\n", CONTEXT_REGS.REG(edi)); + fprintf(stderr, "ebp = 0x%08x\n", CONTEXT_REGS.REG(ebp)); + fprintf(stderr, "eip = 0x%08x\n", CONTEXT_REGS.REG(eip)); + fprintf(stderr, "cs = 0x%04x\n", CONTEXT_REGS.REG(cs)); + fprintf(stderr, "esp = 0x%08x\n", CONTEXT_REGS.REG(esp)); + fprintf(stderr, "ss = 0x%04x\n", CONTEXT_REGS.REG(ss)); + fprintf(stderr, "ds = 0x%04x\n", CONTEXT_REGS.REG(ds)); + fprintf(stderr, "es = 0x%04x\n", CONTEXT_REGS.REG(es)); + fprintf(stderr, "fs = 0x%04x\n", CONTEXT_REGS.REG(fs)); + fprintf(stderr, "gs = 0x%04x\n", CONTEXT_REGS.REG(gs)); + fprintf(stderr, "eflags = 0x%08x\n", CONTEXT_REGS.REG(eflags)); + + fputs("cs:ip = [ ", stderr); + + p = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) + (CONTEXT_REGS.REG(eip) & 0xffff)); + + for (i = 0; i < 16; ++i) + fprintf(stderr, "%02x ", (unsigned int)p[i]); + + fputs("]\n", stderr); +#endif +} + + +#if defined(__linux__) +static int +run_vm86(void) +{ + unsigned int vret; + sigset_t all_sigs, old_sigs; + unsigned long old_gs, old_fs; + + while (1) { + // FIXME: may apply this to BSD equivalents? + sigfillset(&all_sigs); + sigprocmask(SIG_SETMASK, &all_sigs, &old_sigs); + asm volatile ("movl %%gs, %0" : "=rm" (old_gs)); + asm volatile ("movl %%fs, %0" : "=rm" (old_fs)); + vret = lrmi_vm86(&context.vm); + asm volatile ("movl %0, %%gs" :: "rm" (old_gs)); + asm volatile ("movl %0, %%fs" :: "rm" (old_fs)); + sigprocmask(SIG_SETMASK, &old_sigs, NULL); + + if (VM86_TYPE(vret) == VM86_INTx) { + unsigned int v = VM86_ARG(vret); + + if (v == RETURN_TO_32_INT) + return 1; + + pushw(CONTEXT_REGS.REG(eflags)); + pushw(CONTEXT_REGS.REG(cs)); + pushw(CONTEXT_REGS.REG(eip)); + + CONTEXT_REGS.REG(cs) = get_int_seg(v); + CONTEXT_REGS.REG(eip) = get_int_off(v); + CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); + + continue; + } + + if (VM86_TYPE(vret) != VM86_UNKNOWN) + break; + + if (!emulate()) + break; + } + + debug_info(vret); + + return 0; +} +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__NetBSD__) || defined(__OpenBSD__) +static void +vm86_callback(int sig, int code, struct sigcontext *sc) +{ + /* Sync our context with what the kernel develivered to us. */ + memcpy(&CONTEXT_REGS, sc, sizeof(*sc)); + + switch (VM86_TYPE(code)) { + case VM86_INTx: + { + unsigned int v = VM86_ARG(code); + + if (v == RETURN_TO_32_INT) { + context.success = 1; + longjmp(context.env, 1); + } + + pushw(CONTEXT_REGS.REG(eflags)); + pushw(CONTEXT_REGS.REG(cs)); + pushw(CONTEXT_REGS.REG(eip)); + + CONTEXT_REGS.REG(cs) = get_int_seg(v); + CONTEXT_REGS.REG(eip) = get_int_off(v); + CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); + + break; + } + + case VM86_UNKNOWN: + if (emulate() == 0) { + context.success = 0; + context.vret = code; + longjmp(context.env, 1); + } + break; + + default: + context.success = 0; + context.vret = code; + longjmp(context.env, 1); + return; + } + + /* ...and sync our context back to the kernel. */ + memcpy(sc, &CONTEXT_REGS, sizeof(*sc)); +} +#elif defined(__FreeBSD__) +static void +vm86_callback(int sig, int code, struct sigcontext *sc) +{ + unsigned char *addr; + + /* Sync our context with what the kernel develivered to us. */ + memcpy(&CONTEXT_REGS, sc, sizeof(*sc)); + + if (code) { + /* XXX probably need to call original signal handler here */ + context.success = 0; + context.vret = code; + longjmp(context.env, 1); + } + + addr = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) + + CONTEXT_REGS.REG(eip)); + + if (addr[0] == 0xcd) { /* int opcode */ + if (addr[1] == RETURN_TO_32_INT) { + context.success = 1; + longjmp(context.env, 1); + } + + pushw(CONTEXT_REGS.REG(eflags)); + pushw(CONTEXT_REGS.REG(cs)); + pushw(CONTEXT_REGS.REG(eip)); + + CONTEXT_REGS.REG(cs) = get_int_seg(addr[1]); + CONTEXT_REGS.REG(eip) = get_int_off(addr[1]); + CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK); + } else { + if (emulate() == 0) { + context.success = 0; + longjmp(context.env, 1); + } + } + + /* ...and sync our context back to the kernel. */ + memcpy(sc, &CONTEXT_REGS, sizeof(*sc)); +} +#endif /* __FreeBSD__ */ + +static int +run_vm86(void) +{ + if (context.old_sighandler) { +#ifdef LRMI_DEBUG + fprintf(stderr, "run_vm86: callback already installed\n"); +#endif + return (0); + } + +#if defined(__NetBSD__) || defined(__OpenBSD__) + context.old_sighandler = signal(SIGURG, (void (*)(int))vm86_callback); +#elif defined(__FreeBSD__) + context.old_sighandler = signal(SIGBUS, (void (*)(int))vm86_callback); +#endif + + if (context.old_sighandler == (void *)-1) { + context.old_sighandler = NULL; +#ifdef LRMI_DEBUG + fprintf(stderr, "run_vm86: cannot install callback\n"); +#endif + return (0); + } + + if (setjmp(context.env)) { +#if defined(__NetBSD__) || defined(__OpenBSD__) + (void) signal(SIGURG, context.old_sighandler); +#elif defined(__FreeBSD__) + (void) signal(SIGBUS, context.old_sighandler); +#endif + context.old_sighandler = NULL; + + if (context.success) + return (1); + debug_info(context.vret); + return (0); + } + +#if defined(__NetBSD__) || defined(__OpenBSD__) + if (i386_vm86(&context.vm) == -1) + return (0); +#elif defined(__FreeBSD__) + if (i386_vm86(VM86_INIT, &context.vm.init)) + return 0; + + CONTEXT_REGS.REG(eflags) |= PSL_VM | PSL_VIF; + sigreturn(&context.vm.uc); +#endif /* __FreeBSD__ */ + + /* NOTREACHED */ + return (0); +} +#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ + +static int +LRMI_call(struct LRMI_regs *r) +{ + unsigned int vret; + + memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS)); + + set_regs(r); + + CONTEXT_REGS.REG(cs) = r->cs; + CONTEXT_REGS.REG(eip) = r->ip; + + if (r->ss == 0 && r->sp == 0) { + CONTEXT_REGS.REG(ss) = context.stack_seg; + CONTEXT_REGS.REG(esp) = context.stack_off; + } else { + CONTEXT_REGS.REG(ss) = r->ss; + CONTEXT_REGS.REG(esp) = r->sp; + } + + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; +} + + +static int +LRMI_int(int i, struct LRMI_regs *r) +{ + unsigned int vret; + unsigned int seg, off; + + seg = get_int_seg(i); + off = get_int_off(i); + + /* + If the interrupt is in regular memory, it's probably + still pointing at a dos TSR (which is now gone). + */ + if (seg < 0xa000 || (seg << 4) + off >= 0x100000) { +#ifdef LRMI_DEBUG + fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); +#endif + return 0; + } + + memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS)); + + set_regs(r); + + CONTEXT_REGS.REG(cs) = seg; + CONTEXT_REGS.REG(eip) = off; + + if (r->ss == 0 && r->sp == 0) { + CONTEXT_REGS.REG(ss) = context.stack_seg; + CONTEXT_REGS.REG(esp) = context.stack_off; + } else { + CONTEXT_REGS.REG(ss) = r->ss; + CONTEXT_REGS.REG(esp) = r->sp; + } + + pushw(DEFAULT_VM86_FLAGS); + pushw(context.ret_seg); + pushw(context.ret_off); + + vret = run_vm86(); + + get_regs(r); + + return vret; +} + +LRMI_callbacks __svgalib_default_LRMI_callbacks = { + .rm_init = LRMI_init, + .rm_call = LRMI_call, + .rm_int = LRMI_int, + .rm_alloc_real = LRMI_alloc_real, + .rm_free_real = LRMI_free_real, +}; + + +#else /* (__linux__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__) && __i386__ */ +#warning "LRMI is not supported on your system!" +#endif diff --git a/src/lrmi.9.h b/src/lrmi.9.h new file mode 100644 index 0000000..de6065b --- /dev/null +++ b/src/lrmi.9.h @@ -0,0 +1,117 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef LRMI_H +#define LRMI_H + +#if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined(__OpenBSD__)) + +struct LRMI_regs { + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int reserved; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + unsigned short int flags; + unsigned short int es; + unsigned short int ds; + unsigned short int fs; + unsigned short int gs; + unsigned short int ip; + unsigned short int cs; + unsigned short int sp; + unsigned short int ss; +}; + +#ifndef LRMI_PREFIX +#define LRMI_PREFIX LRMI_ +#endif + +#define LRMI_CONCAT2(a, b) a ## b +#define LRMI_CONCAT(a, b) LRMI_CONCAT2(a, b) +#define LRMI_MAKENAME(a) LRMI_CONCAT(LRMI_PREFIX, a) + +/* + Package version (high 16bit = major, low 16bit minor) +*/ +#define LRMI_version 0x0009 /* 0.9 */ + +#ifdef LRMI_C +/* + Initialize + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_init LRMI_MAKENAME(init) +static int +LRMI_init(void); + +/* + Simulate a 16 bit far call + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_call LRMI_MAKENAME(call) +static int +LRMI_call(struct LRMI_regs *r); + +/* + Simulate a 16 bit interrupt + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_int LRMI_MAKENAME(int) +static int +LRMI_int(int interrupt, struct LRMI_regs *r); + +/* + Allocate real mode memory + The returned block is paragraph (16 byte) aligned +*/ +#define LRMI_alloc_real LRMI_MAKENAME(alloc_real) +static void * +LRMI_alloc_real(int size); + +/* + Free real mode memory +*/ +#define LRMI_free_real LRMI_MAKENAME(free_real) +static void +LRMI_free_real(void *m); + +#endif + +#define _SVGALIB_LRMI +#include "vga.h" + +extern LRMI_callbacks __svgalib_default_LRMI_callbacks; +extern LRMI_callbacks * __svgalib_LRMI_callbacks; + +#else /* (__linux__ || __NetBSD__ || __FreeBSD__) && __i386__ */ +#warning "LRMI is not supported on your system!" +#endif + +#endif diff --git a/src/lrmi.c b/src/lrmi.c new file mode 100644 index 0000000..6707bc8 --- /dev/null +++ b/src/lrmi.c @@ -0,0 +1,6 @@ +#ifdef USE_LRMI_9 +#include "lrmi.9.c" +#else +#include "lrmi.6.c" +#endif + diff --git a/src/lrmi.h b/src/lrmi.h new file mode 100644 index 0000000..e418a54 --- /dev/null +++ b/src/lrmi.h @@ -0,0 +1,6 @@ +#ifdef USE_LRMI_9 +#include "lrmi.9.h" +#else +#include "lrmi.6.h" +#endif + diff --git a/src/modetab.c b/src/modetab.c new file mode 100644 index 0000000..5019969 --- /dev/null +++ b/src/modetab.c @@ -0,0 +1,27 @@ +/* + ** modetab.c - part of svgalib + ** (C) 1993 by Hartmut Schirmer + ** + ** A modetable holds a pair of values + ** for each mode : + ** + ** + ** + ** the last entry is marked by + ** + ** + */ + +#include +#include "driver.h" + +const unsigned char * + __svgalib_mode_in_table(const ModeTable * modes, int mode) +{ + while (modes->regs != NULL) { + if (modes->mode_number == mode) + return modes->regs; + modes++; + } + return NULL; +} diff --git a/src/mouse/mouse.c b/src/mouse/mouse.c new file mode 100644 index 0000000..1c8a4c0 --- /dev/null +++ b/src/mouse/mouse.c @@ -0,0 +1,410 @@ +/* hhanemaa@cs.ruu.nl */ +/* Mouse library functions */ + +#include +#include +#include +#include +#include "vgamouse.h" +#include "../libvga.h" +#include + +extern int mouse_open; +extern char *__svgalib_mouse_device; +extern int __svgalib_mouse_flag; + +void (*__svgalib_mouse_eventhandler) (int, int, int, int, int, int, int) = NULL; + +static struct MouseCaps mouse_caps = {0, 0, 0, 0, 0, 0}; + +#include "ms.c" /* include low-level mouse driver */ + + +static struct sigaction oldsiga; +static void (*currentinthandler) (int); + +static void inthandler(int signal) +{ + mouse_close(); + /* restore old interrupt */ + sigaction(SIGINT, &oldsiga, NULL); + raise(SIGINT); +} + +static void default_handler(int, int, int, int, int, int, int); + +int mouse_init_return_fd(char *dev, int type, int samplerate) +{ + struct sigaction siga; + + if (!mouse_open) { + if (strcmp(dev, "") == 0) + m_dev = "/dev/mouse"; + else + m_dev = dev; + m_type = type & MOUSE_TYPE_MASK; + m_modem_ctl = type & ~MOUSE_TYPE_MASK; + + m_sample = samplerate; + + currentinthandler = NULL; + + /* Initialize mouse device. */ + if (m_type == MOUSE_UNCONFIGURED) { + fprintf(stderr, + "Warning: you have not yet configured your mouse type. If you have no mouse,\n" + "setting the type to `none' in " SVGALIB_CONFIG_FILE " will get rid of this\n" + "annoying message.\n"); + return -1; + } + if (m_type == MOUSE_NONE || m_type < MOUSE_MICROSOFT || m_type > MOUSE_LAST) + return -1; + if (ms_init()) + return -1; + + /* Install default mouse handler. Old coordinates are preserved. */ + __svgalib_mouse_eventhandler = default_handler; + + /* Install interrupt handler. */ + currentinthandler = inthandler; + siga.sa_handler = inthandler; + siga.sa_flags = 0; + zero_sa_mask(&(siga.sa_mask)); + sigaction(SIGINT, &siga, &oldsiga); + mouse_open = 1; + } + return __svgalib_mouse_fd; /* Return mouse fd. */ +} + +/* Old compatible mouse_init. + Returns 0 if succesful, -1 on error. */ + +int mouse_init(char *dev, int type, int samplerate) +{ + if (mouse_open) + return 0; + if(dev==NULL) { + dev = __svgalib_mouse_device; + type = __svgalib_mouse_flag; + samplerate=MOUSE_DEFAULTSAMPLERATE; + } + if (mouse_init_return_fd(dev, type, samplerate) == -1) + return -1; + else { + mouse_open = 1; + return 0; + } +} + +/* Reads an event from the mouse buffer. + Warning: For now, we assume there's no console switching. */ + +int mouse_update() +{ + int result; + result = get_ms_event(0); + return result; +} + +void mouse_waitforupdate() +{ +#if 0 + fd_set *readfds, writefds, exceptfds; + struct timeval timeout; + FD_ZERO(readfds); + FD_ZERO(writefds); + FD_ZERO(exceptfds); + FD_SET(__svgalib_mouse_fd, readfds); + /* need to setup timeout. */ + select(readfds, writefds, exceptfds, &timeout); +#else + get_ms_event(1); +#endif + return; +} + +void mouse_seteventhandler(__mouse_handler handler) +{ + __svgalib_mouse_eventhandler = handler; +} + +void mouse_close() +{ + ms_close(); + if (currentinthandler != NULL) + /* Restore old interrupt. */ + sigaction(SIGINT, &oldsiga, NULL); +} + + +/* Default event handler. */ + +void mouse_setdefaulteventhandler() +{ + __svgalib_mouse_eventhandler = default_handler; +} + +static int mouse_x = 0; +static int mouse_y = 0; +static int mouse_z = 0; +static int mouse_rx = 0; +static int mouse_ry = 0; +static int mouse_rz = 0; +static int mouse_button = 0; +static int scale = 1; +static int minx = 0; +static int maxx = 32767; +static int miny = 0; +static int maxy = 32767; +static int minz = 0; +static int maxz = 32767; +static int minrx = 0; +static int maxrx = 32767; +static int minry = 0; +static int maxry = 32767; +static int minrz = 0; +static int maxrz = 32767; +static int wrap = 0; +static int wantcaps = 0; + +/* Sets mouse wrap state*/ +void mouse_setwrap(int state) +{ + wrap = state; +} + +static void default_handler(int button, int dx, int dy, int dz, int drx, + int dry, int drz) +{ + mouse_button = button; + mouse_x += dx; + mouse_y += dy; + mouse_z += dz; + if (mouse_x / scale > maxx) { + if (wrap & MOUSE_WRAPX) + mouse_x -= (maxx - minx) * scale; + else + mouse_x = maxx * scale; + } + /* - 1; ??? */ + if (mouse_x / scale < minx) { + if (wrap & MOUSE_WRAPX) + mouse_x += (maxx - minx) * scale; + else + mouse_x = minx * scale; + } + if (mouse_y / scale > maxy) { + if (wrap & MOUSE_WRAPY) + mouse_y -= (maxy - miny) * scale; + else + mouse_y = maxy * scale; + } + /* - 1; ??? */ + if (mouse_y / scale < miny) { + if (wrap & MOUSE_WRAPY) + mouse_y += (maxy - miny) * scale; + else + mouse_y = miny * scale; + } + if (mouse_z / scale > maxz) { + if (wrap & MOUSE_WRAPZ) + mouse_z -= (maxz - minz) * scale; + else + mouse_z = maxz * scale; + } + /* - 1; ??? */ + if (mouse_z / scale < minz) { + if (wrap & MOUSE_WRAPZ) + mouse_z += (maxz - minz) * scale; + else + mouse_z = minz * scale; + } + switch (wrap & MOUSE_ROT_COORDS) { + case MOUSE_ROT_INFINITESIMAL: + mouse_rx = drx; + mouse_ry = dry; + mouse_rz = drz; + break; + case MOUSE_ROT_RX_RY_RZ: + mouse_rx += drx; + mouse_ry += dry; + mouse_rz += drz; + break; + } + if (mouse_rx / scale > maxrx) { + if (wrap & MOUSE_WRAPRX) + mouse_rx -= (maxrx - minrx) * scale; + else + mouse_rx = maxrx * scale; + } + /* - 1; ??? */ + if (mouse_rx / scale < minrx) { + if (wrap & MOUSE_WRAPRX) + mouse_rx += (maxrx - minrx) * scale; + else + mouse_rx = minrx * scale; + } + if (mouse_ry / scale > maxry) { + if (wrap & MOUSE_WRAPRY) + mouse_ry -= (maxry - minry) * scale; + else + mouse_ry = maxry * scale; + } + /* - 1; ??? */ + if (mouse_ry / scale < minry) { + if (wrap & MOUSE_WRAPRY) + mouse_ry += (maxry - minry) * scale; + else + mouse_ry = minry * scale; + } + if (mouse_rz / scale > maxrz) { + if (wrap & MOUSE_WRAPRZ) + mouse_rz -= (maxrz - minrz) * scale; + else + mouse_rz = maxrz * scale; + } + /* - 1; ??? */ + if (mouse_rz / scale < minrz) { + if (wrap & MOUSE_WRAPRZ) + mouse_rz += (maxrz - minrz) * scale; + else + mouse_rz = minrz * scale; + } +} + +/* Sets the mouse position */ +void mouse_setposition(int x, int y) +{ + mouse_x = x * scale; + mouse_y = y * scale; +} + +/* Set the mouse position for up to six dimensions. */ +void mouse_setposition_6d(int x, int y, int z, int rx, int ry, int rz, + int dim_mask) +{ + if (dim_mask & MOUSE_XDIM) + mouse_x = x * scale; + if (dim_mask & MOUSE_YDIM) + mouse_y = y * scale; + if (dim_mask & MOUSE_ZDIM) + mouse_z = z * scale; + if (dim_mask & MOUSE_RXDIM) + mouse_rx = rx * scale; + if (dim_mask & MOUSE_RYDIM) + mouse_ry = ry * scale; + if (dim_mask & MOUSE_RZDIM) + mouse_rz = rz * scale; + if ((dim_mask & MOUSE_CAPS) && (x == MOUSE_WANTCAPS)) + wantcaps = 1; +} + +/* Set the mouse range along the x axis. */ +void mouse_setxrange(int x1, int x2) +{ + minx = x1; + maxx = x2; +} + +/* Set the mouse range along the y axis. */ +void mouse_setyrange(int y1, int y2) +{ + miny = y1; + maxy = y2; +} + +/* Set the mouse range for up to six dimensions. */ +void mouse_setrange_6d(int x1, int x2, int y1, int y2, int z1, int z2, + int rx1, int rx2, int ry1, int ry2, int rz1, int rz2, int dim_mask) +{ + + if (dim_mask & MOUSE_XDIM) { + minx = x1; + maxx = x2; + } + if (dim_mask & MOUSE_YDIM) { + miny = y1; + maxy = y2; + } + if (dim_mask & MOUSE_ZDIM) { + minz = z1; + maxz = z2; + } + if (dim_mask & MOUSE_RXDIM) { + minrx = rx1; + maxrx = rx2; + } + if (dim_mask & MOUSE_RYDIM) { + minry = ry1; + maxry = ry2; + } + if (dim_mask & MOUSE_RZDIM) { + minrz = rz1; + maxrz = rz2; + } +} + +/* set the sensitivity of the mouse + This routine sets the scale factor between the motion reported by the + mouse and the size of one pixel. The larger scale is, the slower the + mouse cursor apears to move. + Bugs: Scale cannot be set less than one, since it is an integer. This + means that there is no war to make the mouse faster than it inherently + is.*/ +void mouse_setscale(int s) +{ + if (scale==0) + fprintf(stderr,"Mouse scale must be non-zero!\n"); + else { + mouse_x = (mouse_x*s)/scale; + mouse_y = (mouse_y*s)/scale; + mouse_z = (mouse_z*s)/scale; + mouse_rx = (mouse_rx*s)/scale; + mouse_ry = (mouse_ry*s)/scale; + mouse_rz = (mouse_rz*s)/scale; + scale = s; + } +} + + +int mouse_getx() +{ + return mouse_x / scale; +} + +int mouse_gety() +{ + return mouse_y / scale; +} + +void mouse_getposition_6d(int *x, int *y, int *z, int *rx, int *ry, int *rz) +{ + if (wantcaps) { + /* Return the mouse capabilities */ + *x = mouse_caps.key; + *y = mouse_caps.buttons; + *z = mouse_caps.axes; + *rx = mouse_caps.info; + *ry = mouse_caps.reserved0; + *rz = mouse_caps.reserved1; + wantcaps = 0; + return; + } + if (x) + *x = mouse_x / scale; + if (y) + *y = mouse_y / scale; + if (z) + *z = mouse_z / scale; + if (rx) + *rx = mouse_rx / scale; + if (ry) + *ry = mouse_ry / scale; + if (rz) + *rz = mouse_rz / scale; +} + +int mouse_getbutton() +{ + return mouse_button; +} diff --git a/src/mouse/ms.c b/src/mouse/ms.c new file mode 100644 index 0000000..ea58155 --- /dev/null +++ b/src/mouse/ms.c @@ -0,0 +1,1249 @@ +#define MS3B +/* Based on: + * simple driver for serial mouse + * Andrew Haylett, 14th December 1992 + * and on the driver in XFree86. + * Edited for svgalib (hhanemaa@cs.ruu.nl). + * This probably doesn't work with all types of bus mouse. + * HH: Added PS/2 mouse support. + * Fixed Logitech support thanks to Daniel Jackson. + * MouseSystems movement overflow fixed by Steve VanDevender. + * Logitech fixed again. + * Michael: Added support for controlling DTR and RTS. + * Added mouse acceleration 3/97 - Mike Chapman mike@paranoia.com + * Added Intellimouse support 5/98 - Brion Vibber brion@pobox.com + * Totally customisable mouse behaviour 28 Mar 1998 - by 101; 101@kempelen.inf.bme.hu + * Added rx-axis support for IntelliMouse wheel and improved fake keyboard + * event scancode setting 7/98 - Brion + */ + +/* This file is included by mouse.c. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "driver.h" + +/* #define DEBUG */ +/* #define DEBUG_ACCEL */ +/* #define DEBUG_WHEEL */ + +static int m_type; +static int m_baud = 1200; /* Should be 1200. */ +static int m_sample; +static char* m_dev; + int __svgalib_mouse_fd = -1; +static int m_fdmode = 0; /* 0 means don't wait (NDELAY) */ +static int m_modem_ctl = 0; + +/* Settings found on mouse open.. Probably std termios should be restored as well */ +static int m_old_modem_info; /* original state of DTR/RTS */ +static char m_modem_info_valid = 0; /* ==0 means: couldn't get it: old kernel? */ + +unsigned char __svgalib_m_ignore_dx = 0; /* These are flags set by keyboard.c */ +unsigned char __svgalib_m_ignore_dy = 0; +unsigned char __svgalib_m_ignore_dz = 0; + +static char m_accel_type = DEFAULT_ACCEL_TYPE; /* don't accelerate mouse */ +static int m_accel_thresh = DEFAULT_ACCEL_THRESH; /* movement threshold */ +static float m_accel_mult = DEFAULT_ACCEL_MULT; /* multiply */ +static int m_maxdelta = DEFAULT_MAXDELTA; /* before acceleration; no limit by default */ +static int m_accel_maxdelta = DEFAULT_ACCEL_MAXDELTA;/* after acceleration; no limit by default */ +static float* m_accel_powertable = 0; /* precalculated table for power mode */ +static float m_accel_power = DEFAULT_ACCEL_POWER; +static float m_accel_offset = DEFAULT_ACCEL_OFFSET; +static int m_force = 0; /* Don't force parameters */ + +static int m_wheel_steps = DEFAULT_WHEEL_STEPS; /* Number of steps that make up a full turn of the wheel (for IntelliMouse & co) */ +static int m_wheel_delta = DEFAULT_WHEEL_DELTA; /* Amount to change rotation about the X axis when wheel is turned */ +static int m_fake_kbd_events = 0; /* Create fake keyboard events for turning the wheel */ +static int m_fake_upscancode = 0; /* Scan code to produce for turning up */ +static int m_fake_downscancode = 0; /* Scan code to produce for turning down */ +static char *m_fake_upkeyname = NULL; /* Symbolic key name from which scancode is determined */ +static char *m_fake_downkeyname = NULL; + +static const unsigned short cflag[] = { + (CS7 | CREAD | CLOCAL | HUPCL), /* MicroSoft */ + (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL), /* MouseSystems */ + (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL), /* MMSeries */ + (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL), /* Logitech */ + 0, /* BusMouse */ + 0, /* PS/2 */ + (CS7 | CREAD | CLOCAL | HUPCL), /* MouseMan */ + (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL), /* GPM (MouseSystems) */ + (CS8 | CLOCAL | CREAD | IXON | IXOFF ), /* Spaceball */ + 0, /* Dummy entry for MOUSE_NONE */ + (CS7 | CREAD | CLOCAL | HUPCL), /* IntelliMouse (Serial) */ + CS7, /* IntelliMouse (PS/2) */ + (CS7 | CREAD | CLOCAL | HUPCL), /* plug'n'pray */ + (CS8 | CREAD | CLOCAL | HUPCL), /* Wacom Graphire tablet/mouse */ + 0, /* DRMOUSE4DS */ + 0, /* IntelliMouse Explorer (PS/2) */ +}; + +static const unsigned char proto[][5] = +{ + /* hd_mask hd_id dp_mask dp_id nobytes */ + {0x40, 0x40, 0x40, 0x00, 3}, /* MicroSoft */ + {0xf8, 0x80, 0x00, 0x00, 5}, /* MouseSystems */ + {0xe0, 0x80, 0x80, 0x00, 3}, /* MMSeries */ + {0xe0, 0x80, 0x00, 0x00, 3}, /* Logitech */ + {0xf8, 0x80, 0x00, 0x00, 5}, /* BusMouse */ + {0xc0, 0x00, 0x00, 0x00, 3}, /* PS/2 mouse */ + {0x40, 0x40, 0x40, 0x00, 3}, /* Mouseman */ + {0xf8, 0x80, 0x00, 0x00, 5}, /* gpm (MouseSystems) */ + {0xe0, 0x40, 0x00, 0x00, 6}, /* Spaceball */ + {0, 0, 0, 0, 0}, /* Dummy entry for MOUSE_NONE */ + {0xc0, 0x40, 0xc0, 0x00, 4}, /* IntelliMouse (Serial) */ + {0xc8, 0x08, 0x00, 0x00, 4}, /* IntelliMouse (PS/2) */ + {0x40, 0x40, 0x40, 0x00, 3}, /* pnp */ + {0x80, 0x80, 0x80, 0x00, 7}, /* Wacom Graphire */ + {0xc8, 0x08, 0x00, 0x00, 4}, /* DRMOUSE4DS (Digital Research 2-wheel PS/2) */ + {0xc8, 0x08, 0x00, 0x00, 4}, /* IntelliMouse Explorer (PS/2) */ +}; + +static void ms_setspeed(const int old, const int new, + const unsigned short c_cflag) +{ + struct termios tty; + char *c; + + tcgetattr(__svgalib_mouse_fd, &tty); + + tty.c_iflag = IGNBRK | IGNPAR; + tty.c_oflag = 0; + tty.c_lflag = 0; + tty.c_line = 0; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + + switch (old) { + case 9600: + tty.c_cflag = c_cflag | B9600; + break; + case 4800: + tty.c_cflag = c_cflag | B4800; + break; + case 2400: + tty.c_cflag = c_cflag | B2400; + break; + case 1200: + default: + tty.c_cflag = c_cflag | B1200; + break; + } + + tcsetattr(__svgalib_mouse_fd, TCSAFLUSH, &tty); + + switch (new) { + case 9600: + c = "*q"; + tty.c_cflag = c_cflag | B9600; + break; + case 4800: + c = "*p"; + tty.c_cflag = c_cflag | B4800; + break; + case 2400: + c = "*o"; + tty.c_cflag = c_cflag | B2400; + break; + case 1200: + default: + c = "*n"; + tty.c_cflag = c_cflag | B1200; + break; + } + + write(__svgalib_mouse_fd, c, 2); + usleep(10000); + tcsetattr(__svgalib_mouse_fd, TCSAFLUSH, &tty); +} + +static char *mouse_config_options[] = { + "mouse_accel_type", "mouse_accel_mult", "mouse_accel_thresh", + "mouse_accel_power", "mouse_accel_maxdelta", "mouse_maxdelta", + "mouse_accel_offset", "mouse_override", "mouse_force", + "mouse_fake_kbd_event", "mouse_wheel_steps", NULL +}; + +static char* mouse_process_option(int option, int mode, char **nptr) { + + char *ptr; + int newmtype; + +#ifdef DEBUG_ACCEL + fprintf(stderr,"Processing option %d (%s)\n", option, mouse_config_options[option]); +#endif + + switch (option) { + float *fptr; + int *iptr; + char **cptr; + + case 0: /* mouse_accel_type */ + if ( (ptr = __svgalib_token(nptr)) == 0 ) { + param_needed: + fprintf(stderr, "svgalib: mouse-config: \'%s\' requires a parameter\n", + mouse_config_options[option]); + return ptr; + } else if (!strcasecmp(ptr, "normal")) { + m_accel_type = MOUSE_ACCEL_TYPE_NORMAL; + } else if (!strcasecmp(ptr, "power")) { + m_accel_type = MOUSE_ACCEL_TYPE_POWER; + } else if (!strcasecmp(ptr, "off")) { + m_accel_type = 0; + } else { + fprintf(stderr, "svgalib: mouse-config: ignoring unknown mouse acceleration \'%s\'\n", ptr); + m_accel_type = 0; + } + break; + + case 1: /* mouse_accel_mult */ + fptr = &m_accel_mult; + + process_float: + if ( (ptr = __svgalib_token(nptr)) == 0) { + goto param_needed; + } else { + char *endptr; + double dtmp = strtod(ptr, &endptr); + if (endptr == ptr) { + fprintf(stderr, "svgalib: mouse-config: illegal float \'%s\' %s\n", + ptr, mouse_config_options[option]); + return ptr; + } else { + *fptr = dtmp; + } + } + break; + + + case 2: /* mouse_accel_thresh */ + iptr = &m_accel_thresh; + + process_int: + if ( (ptr = __svgalib_token(nptr)) == 0) { + goto param_needed; + } else { + char *endptr; + long ltmp = strtol(ptr, &endptr, 10); + if (ptr == endptr) { + fprintf(stderr, "svgalib: mouse-config: illegal number \'%s\' for %s\n", + ptr, mouse_config_options[option]); + return ptr; + } else { + *iptr = ltmp; + } + } + break; + + case 3: /* mouse_accel_power */ + fptr = &m_accel_power; + goto process_float; + + case 4: /* mouse_accel_maxdelta */ + iptr = &m_accel_maxdelta; + goto process_int; + + case 5: /* mouse_maxdelta */ + iptr = &m_maxdelta; + goto process_int; + + case 6: /* mouse_accel_offset */ + fptr = &m_accel_offset; + goto process_float; + + case 7: /* mouse_override */ +#ifdef ALLOW_MOUSE_OVERRIDE + newmtype = vga_getmousetype(); + if (m_type != newmtype) { + fprintf(stderr,"svgalib: mouse-init: mouse type override %d to %d\n", + m_type, newmtype); + m_type = newmtype; + } +#else /* ALLOW_MOUSE_OVERRIDE */ + fputs("svgalib: was compiled with SVGA_MOUSE_OVERRIDE disabled !", stderr); +#endif /* ALLOW_MOUSE_OVERRIDE */ + break; + + case 8: /* mouse_force */ + m_force = 1; + break; + + case 9: /* mouse_fake_kbd_event */ + /* Set fake keyboard events for mouse wheel... + Turn them off temporarily in case the params are bad */ + m_fake_kbd_events = 0; + +#ifdef DEBUG_WHEEL + fprintf(stderr, " Setting up fake keyboard events"); +#endif + + /* Parse the config for the scancodes */ + cptr = &m_fake_upkeyname; + iptr = &m_fake_upscancode; + while(cptr) { + if ( (ptr = __svgalib_token(nptr)) == 0 ) + goto param_needed; + +#ifdef DEBUG_WHEEL + fprintf(stderr, "; keyname %s", ptr); +#endif + + /* Keep the name in case the keyboard gets remapped later */ + if(*cptr) + free(*cptr); + *cptr = (char *)malloc(strlen(ptr) + 1); + strcpy(*cptr, ptr); + + /* Determine the scancode */ + *iptr = __svgalib_mapkeyname(*cptr); + +#ifdef DEBUG_WHEEL + fprintf(stderr, " = scancode %d", *iptr); +#endif + + /* Move on to the next */ + iptr = ((cptr == &m_fake_upkeyname)?(&m_fake_downscancode):NULL); + cptr = ((cptr == &m_fake_upkeyname)?(&m_fake_downkeyname):NULL); + } + +#ifdef DEBUG_WHEEL + fprintf(stderr, "; done.\n"); +#endif + + /* Now that we've survived all that, turn on fake events */ + m_fake_kbd_events = 1; + + break; + + case 10: /* mouse_wheel_steps */ + /* Set the number of steps that make up a complete turn of + the wheel on an IntelliMouse or other wheel mouse. Zero + disables X-axis rotation but not fake keyboard events. */ + iptr = &m_wheel_steps; + goto process_int; + + } + return __svgalib_token(nptr); +} + +static int ms_init(void) +{ +/*------------------------------------------------------------------*/ +/* Define ALLOW_MOUSE_OVERRIDE to recognize the SVGA_MOUSE_OVERRIDE */ +/* environment variable. If this environment variable is set */ +/* then ignore the program's specified mouse type and use */ +/* the configuration file's type. */ +/* In particular, DOOM does not understand "MouseMan" as a valid */ +/* mouse type and so defaults the mouse type to "MouseSystems". */ +/*------------------------------------------------------------------*/ + __svgalib_read_options(mouse_config_options, mouse_process_option); + + if (m_maxdelta < 0 && !m_force) { + fprintf(stderr, "svgalib: mouse_maxdelta value '%d' is invalid, should be > 0\n", m_maxdelta); + m_maxdelta = DEFAULT_MAXDELTA; + } + + if (m_accel_maxdelta < 0 && !m_force) { + fprintf(stderr, "svgalib: mouse_accel_maxdelta value '%d' is invalid, should be > 0\n", m_accel_maxdelta); + m_accel_maxdelta = DEFAULT_ACCEL_MAXDELTA; + } + + if (m_accel_type) { + + if ((m_accel_mult <= 0 || m_accel_mult > 200.0) && !m_force) { + fprintf(stderr, "svgalib: mouse_accel_mult value '%.2f' is invalid, should be between 0 and 200.0\n", (double)m_accel_mult); + m_accel_mult = DEFAULT_ACCEL_MULT; + } + + if ((m_accel_power < -200.0 || m_accel_power > 200.0) && !m_force) { + fprintf(stderr, "svgalib: mouse_accel_power value '%.2f' is invalid, should be between -200.0 and 200.0\n", m_accel_power); + m_accel_power = DEFAULT_ACCEL_POWER; + } + + if ((m_accel_offset < -100.0 || m_accel_offset > 100.0) && !m_force) { + fprintf(stderr, "svgalib: mouse_accel_offset value '%.2f' is invalid, should be between -100.0 and 100.0\n", m_accel_offset); + m_accel_offset = DEFAULT_ACCEL_OFFSET; + } + + if (!m_force) { + if (m_accel_thresh <= 0 || m_accel_thresh > 200) { + fprintf(stderr, "svgalib: mouse_accel_thresh value '%d' is invalid, should be between 0 and 200\n", m_accel_thresh); + m_accel_thresh = DEFAULT_ACCEL_THRESH; + } + } else if (m_accel_thresh < 0) { + fputs("svgalib: mouse_accel_thresh musn't be negative !\n", stderr); + m_accel_thresh = DEFAULT_ACCEL_THRESH; + } + + if (m_accel_offset >= m_accel_mult) { + fputs("svgalib: warning: accel_offset should be less then accel_mult !", stderr); + } + + if (m_accel_thresh > 1 && m_accel_type == MOUSE_ACCEL_TYPE_POWER) { + if ((m_accel_powertable = malloc(m_accel_thresh * sizeof(float))) == 0 ) { + fputs("svgalib: out of memory in mouse init ! (Check SVGA_MOUSE_ACCEL_THRESH size) !", stderr); + fflush(stderr); + return 1; + } else { + int i; +#ifdef DEBUG_ACCEL + fprintf(stderr,"m_accel_powertable:\n"); +#endif + for (i = 1; i < m_accel_thresh; i++) { + m_accel_powertable[i] = pow((double)(i-1)/(m_accel_thresh-1), m_accel_power) + * (m_accel_mult - m_accel_offset) + m_accel_offset; + +#ifdef DEBUG_ACCEL + fprintf(stderr," %d => %f (%f)\n", i, (double)m_accel_powertable[i] * i, + (double)m_accel_powertable[i]); +#endif + } + } + } + } + +#ifdef DEBUG_ACCEL + fprintf(stderr,"m_accel_type: %d\n", (int)m_accel_type); + fprintf(stderr,"m_force: %d\n", m_force); + fprintf(stderr,"m_accel_thresh: %d\n", m_accel_thresh); + fprintf(stderr,"m_accel_offset: %d\n", (int)m_accel_offset); + fprintf(stderr,"m_accel_mult: %f\n", (double)m_accel_mult); + fprintf(stderr,"m_accel_power: %f\n", (double)m_accel_power); + fprintf(stderr,"m_maxdelta: %d\n", m_maxdelta); + fprintf(stderr,"m_accel_maxdelta: %d\n", m_accel_maxdelta); +#endif + + /* Ensure that the open will get a file descriptor greater + * than 2, else problems can occur with stdio functions + * under certain strange conditions: */ + if ((fcntl(0,F_GETFD) == -1) && (open("/dev/null", O_RDONLY) == -1) ) { + perror("/dev/null"); + exit(1); + } + if ((fcntl(1,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1) ) { + perror("/dev/null"); + exit(1); + } + if ((fcntl(2,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1) ) { + perror("/dev/null"); + exit(1); + } + + /* Set the proper wheel delta */ + if(m_wheel_steps) + m_wheel_delta = (360 / m_wheel_steps); + else + m_wheel_delta = 0; + + /* Added O_NDELAY here. */ +/* + if(__svgalib_mouse_fd!=-1)close(__svgalib_mouse_fd); +*/ + if ((__svgalib_mouse_fd = open(m_dev, O_RDWR | O_NDELAY )) < 0) + return -1; + + if (m_type == MOUSE_BUSMOUSE || m_type == MOUSE_PS2 + || m_type == MOUSE_IMPS2 || m_type == MOUSE_GPM + || m_type == MOUSE_DRMOUSE4DS || m_type == MOUSE_EXPPS2) + m_modem_ctl = 0; + + /* If no signal will change there is no need to restore + or safe original settings. */ + if (!m_modem_ctl) + m_modem_info_valid = 0; + else { + /* Get current modem signals; keep silent on errors.. */ + m_modem_info_valid = !ioctl(__svgalib_mouse_fd, + TIOCMGET, &m_old_modem_info); + + if (m_modem_info_valid) { + int param = m_old_modem_info; + + /* Prepare new stat: */ + + /*set DTR as ordered.. */ + if (m_modem_ctl & MOUSE_CHG_DTR) { + param &= ~TIOCM_DTR; + if (m_modem_ctl & MOUSE_DTR_HIGH) + param |= TIOCM_DTR; + } + /*set RTS as ordered.. */ + if (m_modem_ctl & MOUSE_CHG_RTS) { + param &= ~TIOCM_RTS; + if (m_modem_ctl & MOUSE_RTS_HIGH) + param |= TIOCM_RTS; + } + if (ioctl(__svgalib_mouse_fd, TIOCMSET, ¶m)) + m_modem_info_valid = 0; /* No try to restore if this failed */ + } + } + + if (m_type == MOUSE_SPACEBALL) { + m_baud = 9600; + ms_setspeed(1200, m_baud, cflag[m_type]); + } else if (m_type == MOUSE_LOGIMAN) { + ms_setspeed(9600, 1200, cflag[m_type]); + ms_setspeed(4800, 1200, cflag[m_type]); + ms_setspeed(2400, 1200, cflag[m_type]); + ms_setspeed(1200, 1200, cflag[m_type]); + write(__svgalib_mouse_fd, "*X", 2); + ms_setspeed(1200, m_baud, cflag[m_type]); + } else if (m_type == MOUSE_WACOM_GRAPHIRE) { + m_baud = 9600; + ms_setspeed(1200, m_baud, cflag[m_type]); + /* Reset baud rate */ + write(__svgalib_mouse_fd, "\r$", 2); + usleep(250000); + /* Reset tablet */ + write(__svgalib_mouse_fd, "\r#", 2); + usleep(75000); + /* Set hardware filtering */ + write(__svgalib_mouse_fd, "\rSU3", 4); + usleep(75000); + /* Start sending coordinates */ + write(__svgalib_mouse_fd, "\rST\r", 4); + } else if (m_type == MOUSE_IMPS2 || m_type == MOUSE_DRMOUSE4DS) { + /* Initialize the mouse into wheel mode */ + write(__svgalib_mouse_fd, "\363\310\363\144\363\120", 6); + } else if (m_type == MOUSE_EXPPS2) { + write(__svgalib_mouse_fd, "\363\310\363\310\363\120", 6); + } else if (m_type == MOUSE_PNP) { + /* Need to do this termios stuff here, by hand, ms_setspeed won't + work with pnp */ + struct termios tty; + m_baud = 1200; + tcgetattr(__svgalib_mouse_fd, &tty); + tty.c_iflag = IGNBRK | IGNPAR; + tty.c_oflag = 0; + tty.c_lflag = 0; + tty.c_line = 0; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + tty.c_cflag = cflag[m_type] | B1200; + tcsetattr(__svgalib_mouse_fd, TCSAFLUSH, &tty); + } else if (m_type != MOUSE_BUSMOUSE && m_type != MOUSE_PS2) { + ms_setspeed(9600, m_baud, cflag[m_type]); + ms_setspeed(4800, m_baud, cflag[m_type]); + ms_setspeed(2400, m_baud, cflag[m_type]); + ms_setspeed(1200, m_baud, cflag[m_type]); + + if (m_type == MOUSE_LOGITECH) { + write(__svgalib_mouse_fd, "S", 1); + ms_setspeed(m_baud, m_baud, cflag[MOUSE_MMSERIES]); + } + if (m_sample <= 0) + write(__svgalib_mouse_fd, "O", 1); + else if (m_sample <= 15) + write(__svgalib_mouse_fd, "J", 1); + else if (m_sample <= 27) + write(__svgalib_mouse_fd, "K", 1); + else if (m_sample <= 42) + write(__svgalib_mouse_fd, "L", 1); + else if (m_sample <= 60) + write(__svgalib_mouse_fd, "R", 1); + else if (m_sample <= 85) + write(__svgalib_mouse_fd, "M", 1); + else if (m_sample <= 125) + write(__svgalib_mouse_fd, "Q", 1); + else + write(__svgalib_mouse_fd, "N", 1); + } + + /* Set the mouse caps */ + mouse_caps.key = MOUSE_GOTCAPS; + + /* Zero out first to be sure... */ + mouse_caps.buttons = mouse_caps.axes = mouse_caps.info = + mouse_caps.reserved0 = mouse_caps.reserved1 = 0; + + switch(m_type) { + case MOUSE_SPACEBALL: + /* 6 axes, many buttons */ + mouse_caps.buttons = + MOUSE_LEFTBUTTON | MOUSE_MIDDLEBUTTON | MOUSE_RIGHTBUTTON | + MOUSE_FOURTHBUTTON | MOUSE_FIFTHBUTTON | MOUSE_SIXTHBUTTON | + MOUSE_RESETBUTTON; + mouse_caps.axes = MOUSE_6DIM; + break; + + case MOUSE_DRMOUSE4DS: + /* X, Y, RX and RY (two wheels), 3 buttons */ + mouse_caps.axes = MOUSE_2DIM | MOUSE_RXDIM | MOUSE_RYDIM; + mouse_caps.buttons = MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON | MOUSE_MIDDLEBUTTON; + mouse_caps.info = MOUSE_INFO_WHEEL; + break; + + case MOUSE_EXPPS2: + mouse_caps.buttons = MOUSE_FIFTHBUTTON; + + case MOUSE_INTELLIMOUSE: + case MOUSE_IMPS2: + case MOUSE_WACOM_GRAPHIRE: + /* X, Y, RX (wheel), 3 buttons, wheel */ + mouse_caps.axes = MOUSE_RXDIM; + mouse_caps.info = MOUSE_INFO_WHEEL; + + case MOUSE_LOGIMAN: /* Some TrackMen have 4 buttons */ + mouse_caps.buttons = MOUSE_FOURTHBUTTON; + + case MOUSE_MOUSESYSTEMS: + case MOUSE_MMSERIES: + case MOUSE_LOGITECH: + case MOUSE_BUSMOUSE: + case MOUSE_PS2: + case MOUSE_GPM: + case MOUSE_PNP: +#ifdef MS3B + case MOUSE_MICROSOFT: /* Two buttons only */ +#endif + /* Any of these _can_ have 3 buttons, but may not */ + mouse_caps.buttons |= MOUSE_MIDDLEBUTTON; + +#ifndef MS3B + case MOUSE_MICROSOFT: /* Two buttons only */ +#endif + mouse_caps.buttons |= MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON; + mouse_caps.axes |= MOUSE_2DIM; + break; + } + + return 0; +} + +/* Scooped from X driver. */ +static inline void ms_close(void) +{ + if (m_accel_powertable) + free(m_accel_powertable); + if (__svgalib_mouse_fd == -1) + return; + if (m_type == MOUSE_LOGITECH) { + write(__svgalib_mouse_fd, "U", 1); + ms_setspeed(m_baud, 1200, cflag[MOUSE_LOGITECH]); + } + /* Try to restore modem signals if we could get them. */ + if (m_modem_info_valid) + ioctl(__svgalib_mouse_fd, TIOCMSET, &m_old_modem_info); + + close(__svgalib_mouse_fd); + mouse_open=0; + __svgalib_mouse_fd = -1; +} + +#define MOUSEBUFFERSIZE 256 + +static int get_ms_event(int wait) { +/* + Changed to process multiple packets. + wait value: + 0 Process any mouse events, and return status. + 1 Wait for mouse event, then return. + + Status indicates whether an event was processed. + */ + + static unsigned char buf[MOUSEBUFFERSIZE]; + static int nu_bytes = 0; + int nu_packets = 0; + char event_handled = 0; + int bytesread; + int i, wheel; + static unsigned int prev=0; +/* int but; */ + static int but = 0; /* static is hack for MouseMan */ + static int mouse_orientation = 0; + int dx=0, dy=0, dz=0, drx=0, dry=0, drz=0; + int ax=0, ay=0; + static int oldax=0, olday=0, nodev = 0; + int j; + char SpaceWare[] = "SpaceWare!"; + + if (__svgalib_mouse_fd == -1) + return -1; + + again: + + if (m_fdmode == 1) { + /* We don't want to wait, set NDELAY mode. */ + fcntl(__svgalib_mouse_fd, F_SETFL, O_RDONLY | O_NDELAY ); + m_fdmode = 0; + } + bytesread = read(__svgalib_mouse_fd, + &buf[nu_bytes], MOUSEBUFFERSIZE - nu_bytes); + i = 0; + + if (bytesread >= 1) + nu_bytes += bytesread; + +#ifdef DEBUG + fprintf(stderr,"#bytes in buffer: %d\n", nu_bytes); +#endif + + handle_packets: + + /* Handle packets in buffer. */ + +#ifdef DEBUG + fprintf(stderr,"Bytes left in buffer: %d at %d, packet is %d bytes\n", + nu_bytes - i, i, proto[m_type][4]); + if (nu_bytes - i > 0 ) + fprintf(stderr,"Header byte: %c %d\n", (buf[i] & 0177), buf[i]); + +#endif + + if ((m_type == MOUSE_LOGIMAN) && + ((nu_bytes - i) >= 1) && + ((buf[i] & proto[m_type][0]) != proto[m_type][1]) && + ((char) (buf[i] & ~0x33) == 0)) { /* s/23/33/, for 4-but trackman */ + /* Hack-o-matic, stolen from xf86_Mouse.c */ + but = ((buf[i] & 0x20) >> 4) | ((buf[i] & 0x10) >> 1) | (but & 0x05); + __svgalib_mouse_eventhandler(but, 0, 0, 0, 0, 0, 0); + event_handled++; + i++; + } + if ((m_type == MOUSE_SPACEBALL)) { + j=i; + while ((nu_bytes - j > 0) && (buf[j]!=13)) + j++; + nu_packets=(buf[j]==13); + } else { + nu_packets=1; + } + if ((nu_packets==0)||(nu_bytes - i < proto[m_type][4])) { + /* No full packet available. */ + if (wait == 0 || (wait == 1 && event_handled)) { + if (i >= nu_bytes) { + nu_bytes = 0; + i = 0; + } else { + /* Move partial packet to front of buffer. */ + for (j = i; j < nu_bytes; j++) + buf[j - i] = buf[j]; + nu_bytes -= i; + } + return event_handled; + } else { /* (wait == 1 && !event_handled) */ + if (i >= nu_bytes) { + nu_bytes = 0; + i = 0; + } + /* Wait mode, we'll sleep on reads. */ + fcntl(__svgalib_mouse_fd, F_SETFL, O_RDONLY); + m_fdmode = 1; + read(__svgalib_mouse_fd, &buf[nu_bytes], 1); + if ((m_type == MOUSE_SPACEBALL)) { + nu_packets=(buf[nu_bytes]==13); + } else { + nu_packets=1; + } + nu_bytes++; + if ((nu_packets==0)||(nu_bytes - i < proto[m_type][4])) + /* Not a complete packet. */ + goto again; + } + } + + /* Check header byte. */ + if ((buf[i] & proto[m_type][0]) != proto[m_type][1]) { + /* Not a header byte. */ +#ifdef DEBUG + fprintf(stderr,"Bad header byte: %c %d\n", (buf[i] & 0177), buf[i]); +#endif + i++; + goto handle_packets; + } + /* Check whether it's a valid data packet. */ + if ((m_type != MOUSE_PS2)&&(m_type != MOUSE_IMPS2) + &&(m_type != MOUSE_EXPPS2)&&(m_type != MOUSE_SPACEBALL) + &&(m_type != MOUSE_WACOM_GRAPHIRE) && (m_type != MOUSE_DRMOUSE4DS) ) + for (j = 1; j < proto[m_type][4]; j++) + if ((buf[i + j] & proto[m_type][2]) != proto[m_type][3] + || buf[i + j] == 0x80) { + i = i + j + 1; + goto handle_packets; + } + /* Construct the event. */ + switch (m_type) { +#ifdef MS3B + case MOUSE_MICROSOFT: /* Microsoft */ + but = (but & 8) | ((buf[i] & 0x20) >> 3) | ((buf[i] & 0x10) >> 4); + dx = (char) (((buf[i] & 0x03) << 6) | (buf[i + 1] & 0x3F)); + dy = (char) (((buf[i] & 0x0C) << 4) | (buf[i + 2] & 0x3F)); + if((dx==0)&&(dy==0)&&(but==(prev&~MOUSE_MIDDLEBUTTON))) + but=prev^MOUSE_MIDDLEBUTTON; else + but |= prev&MOUSE_MIDDLEBUTTON; + prev=but; + break; +#else + case MOUSE_MICROSOFT: /* Microsoft */ +#endif + case MOUSE_LOGIMAN: /* MouseMan / TrackMan */ + case MOUSE_PNP: + default: + but = (but & 0x0A) | ((buf[i] & 0x20) >> 3) | ((buf[i] & 0x10) >> 4); + dx = (char) (((buf[i] & 0x03) << 6) | (buf[i + 1] & 0x3F)); + dy = (char) (((buf[i] & 0x0C) << 4) | (buf[i + 2] & 0x3F)); + break; + case MOUSE_WACOM_GRAPHIRE: /* Wacom Graphire Tablet */ + if (!(buf[i] & 0x40)) { /* no device on tablet */ + nodev = 1; + break; + } + but = (buf[i+3] & 0x08) ? MOUSE_LEFTBUTTON : 0 | + (buf[i+3] & 0x10) ? MOUSE_RIGHTBUTTON : 0 | + (buf[i+3] & 0x20) ? MOUSE_MIDDLEBUTTON : 0; + + /* The absolute position is returned, not the change in position, so + we convert it. */ + ax = ((buf[i+0] & 0x03) << 14) | (buf[i+1] << 7) | buf[i+2]; + ay = ((buf[i+3] & 0x03) << 14) | (buf[i+4] << 7) | buf[i+5]; + + if (nodev) { + oldax = ax; + olday = ay; + nodev = 0; + } + + dx = ax - oldax; + dy = ay - olday; + + dz = (((buf[i+6] & 0x3f) << 1) | ((buf[i+3] & 0x04) >> 2)); + + if (buf[i+6] & 0x40) + dz = -dz; + + /* The tablet has *very* high resolution, so we normalize + that a bit. */ + dx /= 2; + dy /= 2; + + oldax = ax; + olday = ay; + + if (buf[i] & 0x20 && dz) /* stylus has pressure */ + but |= MOUSE_LEFTBUTTON; + else if (buf[i+6] & 0x30) { /* roller is being turned */ + wheel = (buf[i+6] & 0x30) >> 3; + if (buf[i+6] & 0x40) + wheel = -wheel; +#ifdef DEBUG_WHEEL + fprintf(stderr, " Wheel turned (0x%02x)", wheel); +#endif + /* RX-axis */ + if(m_wheel_delta) { + drx = ((wheel < 0) ? (-m_wheel_delta) : m_wheel_delta); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; RX axis delta = %d", drx); +#endif + } + + /* Are fake keyboard events enabled? */ + if(m_fake_kbd_events && __svgalib_keyboard_eventhandler) { + /* Fake keypresses... */ + int key = ((wheel < 0) ? m_fake_upscancode : m_fake_downscancode); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; pressing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 1); /* press */ + /* todo: delay */ +#ifdef DEBUG_WHEEL + fprintf(stderr, ", releasing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 0); /* release */ +#ifdef DEBUG_WHEEL + fprintf(stderr, ".\n"); +#endif + } + } + break; + + case MOUSE_INTELLIMOUSE: /* Serial IntelliMouse */ + /* This bit modified from gpm 1.13 */ + but = ((buf[i] & 0x20) >> 3) /* left */ + | ((buf[i + 3] & 0x10) >> 3) /* middle */ + | ((buf[i] & 0x10) >> 4); /* right */ + dx = (char) (((buf[i] & 0x03) << 6) | (buf[i + 1] & 0x3F)); + dy = (char) (((buf[i] & 0x0C) << 4) | (buf[i + 2] & 0x3F)); + + /* Did we turn the wheel? */ + if((wheel = buf[i + 3] & 0x0f) != 0) { +#ifdef DEBUG_WHEEL + fprintf(stderr, " Wheel turned (0x%02x)", wheel); +#endif + /* RX-axis */ + if(m_wheel_delta) { + drx = ((wheel > 7) ? (-m_wheel_delta) : m_wheel_delta); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; RX axis delta = %d", drx); +#endif + } + + /* Are fake keyboard events enabled? */ + if(m_fake_kbd_events && __svgalib_keyboard_eventhandler) { + /* Fake keypresses... */ + int key = ((wheel > 7) ? m_fake_upscancode : m_fake_downscancode); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; pressing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 1); /* press */ + /* todo: delay */ +#ifdef DEBUG_WHEEL + fprintf(stderr, ", releasing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 0); /* release */ +#ifdef DEBUG_WHEEL + fprintf(stderr, ".\n"); +#endif + } + } + break; + case MOUSE_MOUSESYSTEMS: /* Mouse Systems Corp */ + case MOUSE_GPM: + but = (~buf[i]) & 0x07; + dx = (char) (buf[i + 1]); + dx += (char) (buf[i + 3]); + dy = -((char) (buf[i + 2])); + dy -= (char) (buf[i + 4]); + break; + case MOUSE_MMSERIES: /* MM Series */ + case MOUSE_LOGITECH: /* Logitech */ + but = buf[i] & 0x07; + dx = (buf[i] & 0x10) ? buf[i + 1] : -buf[i + 1]; + dy = (buf[i] & 0x08) ? -buf[i + 2] : buf[i + 2]; + break; + case MOUSE_BUSMOUSE: /* BusMouse */ + but = (~buf[i]) & 0x07; + dx = (char) buf[i + 1]; + dy = -(char) buf[i + 2]; + break; + case MOUSE_PS2: /* PS/2 mouse */ + but = (buf[i] & 0x04) >> 1 | /* Middle */ + (buf[i] & 0x02) >> 1 | /* Right */ + (buf[i] & 0x01) << 2; /* Left */ + dx = (buf[i] & 0x10) ? buf[i + 1] - 256 : buf[i + 1]; + dy = (buf[i] & 0x20) ? -(buf[i + 2] - 256) : -buf[i + 2]; + break; + case MOUSE_DRMOUSE4DS: + /* Digital Research 4-Axis mouse - like the PS/2 IntelliMouse, but + has two wheels. */ + /* This bit modified from the gpm 1.13 imps2 patch by Tim Goodwin */ + but = ((buf[i] & 1) << 2) /* left */ + | ((buf[i] & 6) >> 1); /* middle and right */ + dx = (buf[i] & 0x10) ? buf[i + 1] - 256 : buf[i + 1]; + dy = (buf[i] & 0x20) ? -(buf[i + 2] - 256) : -buf[i + 2]; + + /* Did we turn the wheel? */ + if((wheel = buf[i + 3]) != 0) { +#ifdef DEBUG_WHEEL + fprintf(stderr, " Wheel turned (0x%02x)", wheel); +#endif + /* RX reports as 1 or F, RY reports as 2 or E */ + /* both never report at the same time, which makes life easier */ + if (m_wheel_delta) + { + switch (wheel & 0x0F) + { + case 1: drx = m_wheel_delta; break; + case 15: drx = -m_wheel_delta; break; + case 2: dry = -m_wheel_delta; break; + case 14: dry = m_wheel_delta; break; + }; +#ifdef DEBUG_WHEEL + fprintf(stderr, "; RX axis delta = %d : RY axis delta = %d", drx, dry); +#endif + + /* Are fake keyboard events enabled? */ + if(m_fake_kbd_events && __svgalib_keyboard_eventhandler) { + /* Fake keypresses... */ + int key = ((drx+dry < 0) ? m_fake_upscancode : m_fake_downscancode); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; pressing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 1); /* press */ + /* todo: delay */ +#ifdef DEBUG_WHEEL + fprintf(stderr, ", releasing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 0); /* release */ + } +#ifdef DEBUG_WHEEL + fprintf(stderr, ".\n"); +#endif + + + } + } + break; + + case MOUSE_IMPS2: /* PS/2 IntelliMouse */ + /* This bit modified from the gpm 1.13 imps2 patch by Tim Goodwin */ + but = ((buf[i] & 1) << 2) /* left */ + | ((buf[i] & 6) >> 1); /* middle and right */ + dx = (buf[i] & 0x10) ? buf[i + 1] - 256 : buf[i + 1]; + dy = (buf[i] & 0x20) ? -(buf[i + 2] - 256) : -buf[i + 2]; + + /* Did we turn the wheel? */ + if((wheel = buf[i + 3]) != 0) { +#ifdef DEBUG_WHEEL + fprintf(stderr, " Wheel turned (0x%02x)", wheel); +#endif + /* RX-axis */ + if(m_wheel_delta) { + drx = ((wheel > 0x7f) ? (-m_wheel_delta) : m_wheel_delta); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; RX axis delta = %d", drx); +#endif + } + + /* Are fake keyboard events enabled? */ + if(m_fake_kbd_events && __svgalib_keyboard_eventhandler) { + /* Fake keypresses... */ + int key = ((wheel > 0x7f) ? m_fake_upscancode : m_fake_downscancode); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; pressing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 1); /* press */ + /* todo: delay */ +#ifdef DEBUG_WHEEL + fprintf(stderr, ", releasing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 0); /* release */ + } +#ifdef DEBUG_WHEEL + fprintf(stderr, ".\n"); +#endif + } + break; + + case MOUSE_EXPPS2: /* PS/2 IntelliMouse Explorer */ + /* This bit modified from the gpm 1.13 imps2 patch by Tim Goodwin */ + but = ((buf[i] & 1) << 2) /* left */ + | ((buf[i] & 6) >> 1) /* middle and right */ + | ((buf[i+3] & 48) >> 1); + dx = (buf[i] & 0x10) ? buf[i + 1] - 256 : buf[i + 1]; + dy = (buf[i] & 0x20) ? -(buf[i + 2] - 256) : -buf[i + 2]; + + /* Did we turn the wheel? */ + if(((wheel = buf[i + 3]) & 15) != 0) { +#ifdef DEBUG_WHEEL + fprintf(stderr, " Wheel turned (0x%02x)", wheel); +#endif + /* RX-axis */ + if(m_wheel_delta) { + drx = ((wheel > 7) ? (-m_wheel_delta) : m_wheel_delta); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; RX axis delta = %d", drx); +#endif + } + /* Are fake keyboard events enabled? */ + if(m_fake_kbd_events && __svgalib_keyboard_eventhandler) { + /* Fake keypresses... */ + int key = ((wheel > 7) ? m_fake_upscancode : m_fake_downscancode); +#ifdef DEBUG_WHEEL + fprintf(stderr, "; pressing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 1); /* press */ + /* todo: delay */ +#ifdef DEBUG_WHEEL + fprintf(stderr, ", releasing scancode %d", key); +#endif + __svgalib_keyboard_eventhandler(key, 0); /* release */ + } +#ifdef DEBUG_WHEEL + fprintf(stderr, ".\n"); +#endif + } + break; + + case MOUSE_SPACEBALL: + + switch (buf[i]) { + case 'D': + + but=0177 & buf[i+1]; + + /* Strip the MSB, which is a parity bit */ + for (j = 2; j < 11; ++j) { + buf[i+j] &= 0177; /* Make sure everything is 7bit */ + buf[i+j] ^= SpaceWare[j-2]; /* What's this doing in the data? */ + } + + /* Turn chars into 10 bit integers */ + if (mouse_orientation == MOUSE_ORIENTATION_VERTICAL) { + dx = ((buf[i+2] & 0177)<<3)|((buf[i+3] & 0160)>>4); + dy = ((buf[i+3] & 0017)<<6)|((buf[i+4] & 0176)>>1); + dz = ((buf[i+4] & 0001)<<9)|((buf[i+5] & 0177)<<2)| + ((buf[i+6] & 0140)>>5); + drx = ((buf[i+6] & 0037)<<5)|((buf[i+7] & 0174)>>2); + dry = ((buf[i+7] & 0003)<<8)|((buf[i+8] & 0177)<<1)| + ((buf[i+9] & 0100)>>6); + drz = ((buf[i+9] & 0077)<<4)|((buf[i+10] & 0170)>>3); + } else { + dx = ((buf[i+2] & 0177)<<3)|((buf[i+3] & 0160)>>4); + dz = ((buf[i+3] & 0017)<<6)|((buf[i+4] & 0176)>>1); + dy = ((buf[i+4] & 0001)<<9)|((buf[i+5] & 0177)<<2)| + ((buf[i+6] & 0140)>>5); + drx = ((buf[i+6] & 0037)<<5)|((buf[i+7] & 0174)>>2); + drz = ((buf[i+7] & 0003)<<8)|((buf[i+8] & 0177)<<1)| + ((buf[i+9] & 0100)>>6); + dry = ((buf[i+9] & 0077)<<4)|((buf[i+10] & 0170)>>3); + } + + /* Get the sign right. */ + if (dx > 511) dx -= 1024; + if (dy > 511) dy -= 1024; + if (dz > 511) dz -= 1024; + if (drx > 511) drx -= 1024; + if (dry > 511) dry -= 1024; + if (drz > 511) drz -= 1024; + if (mouse_orientation == MOUSE_ORIENTATION_HORIZONTAL) + { dz *= -1; + drz *= -1; + } + /* if (fabs(dx) < sorb_trans_thresh[1]) dx = 0; */ + i+=13; +#ifdef DEBUG + fprintf(stderr,"Got D packet! but=%d, x=%d y=%d z=%d rx=%d ry=%d rz=%d\n", + but,dx,dy,dz,drx,dry,drz); +#endif + break; + case 'K': + /* Button press/release w/out motion */ + but=0177 & buf[i+2]; + if (but==MOUSE_RESETBUTTON) + mouse_orientation=1-mouse_orientation; +#ifdef DEBUG + fprintf(stderr,"Got K packet! but=%d, x=%d y=%d z=%d rx=%d ry=%d rz=%d\n", + but,dx,dy,dz,drx,dry,drz); +#endif + i+=6; + break; + case 'R': +#ifdef DEBUG + fprintf(stderr,"Got init string!\n"); +#endif + for (j=i;((buf[j] !=13)&&(j= 1) && + ((buf[i] & proto[m_type][0]) != proto[m_type][1]) && + ((char) (buf[i] & ~0x23) == 0)) { + /* Hack-o-matic, stolen from xf86_Mouse.c */ + but = ((buf[i] & 0x20) >> 4) | (but & 0x05); + i++; + } + + if (__svgalib_m_ignore_dx) dx = 0; + if (__svgalib_m_ignore_dy) dy = 0; + if (__svgalib_m_ignore_dz) dz = 0; + + + if (m_maxdelta) { + if (abs(dx) > m_maxdelta) + dx = (dx > 0) ? m_maxdelta : -m_maxdelta; + if (abs(dy) > m_maxdelta) + dy = (dy > 0) ? m_maxdelta : -m_maxdelta; + if (abs(dz) > m_maxdelta) + dz = (dz > 0) ? m_maxdelta : -m_maxdelta; + } + + + switch (m_accel_type) { + int delta; + + case MOUSE_ACCEL_TYPE_NORMAL: +#ifdef DEBUG_ACCEL + fprintf(stderr,"%d\t", dx); +#endif + if (abs(dx) > m_accel_thresh) dx = (int) ((float)dx * m_accel_mult); + if (abs(dy) > m_accel_thresh) dy = (int) ((float)dy * m_accel_mult); + if (abs(dz) > m_accel_thresh) dz = (int) ((float)dz * m_accel_mult); +#ifdef DEBUG_ACCEL + fprintf(stderr,"%d\n", dx); +#endif + break; + + + case MOUSE_ACCEL_TYPE_POWER: +#ifdef DEBUG_ACCEL + fprintf(stderr,"%d\t", dx); +#endif + delta = abs(dx); + dx = (delta >= m_accel_thresh) ? (float)dx * m_accel_mult : + (float)dx * m_accel_powertable[delta]; + + delta = abs(dy); + dy = (delta >= m_accel_thresh) ? (float)dy * m_accel_mult : + (float)dy * m_accel_powertable[delta]; + + delta = abs(dz); + dz = (delta >= m_accel_thresh) ? (float)dz * m_accel_mult : + (float)dz * m_accel_powertable[delta]; + +#ifdef DEBUG_ACCEL + fprintf(stderr,"%d\n", dx); +#endif + break; + } + + if (m_accel_maxdelta && m_accel_type) { + if (abs(dx) > m_accel_maxdelta) + dx = (dx > 0) ? m_accel_maxdelta : -m_accel_maxdelta; + if (abs(dy) > m_accel_maxdelta) + dy = (dy > 0) ? m_accel_maxdelta : -m_accel_maxdelta; + if (abs(dz) > m_accel_maxdelta) + dz = (dz > 0) ? m_accel_maxdelta : -m_accel_maxdelta; + } + + __svgalib_mouse_eventhandler(but, dx, dy, dz, drx, dry, drz); + + event_handled = 1; + + goto handle_packets; +} + +void __svgalib_mouse_update_keymap(void) +{ + /* + The keyboard has been remapped, and we should accordingly remap any + symbolically-specified scancodes for fake keyboard events. + */ +#ifdef DEBUG_WHEEL + fprintf(stderr, " Remapping fake keyboard event scancodes... "); +#endif + if(m_fake_upkeyname) + m_fake_upscancode = __svgalib_mapkeyname(m_fake_upkeyname); + if(m_fake_downkeyname) + m_fake_downscancode = __svgalib_mapkeyname(m_fake_downkeyname); +#ifdef DEBUG_WHEEL + fprintf(stderr, "done.\n"); +#endif +} diff --git a/src/mouse/vgamouse.h b/src/mouse/vgamouse.h new file mode 100644 index 0000000..b57a142 --- /dev/null +++ b/src/mouse/vgamouse.h @@ -0,0 +1,187 @@ +/* Mouse interface for svgalib. */ +/* Can be used independently. */ + +#ifndef VGAMOUSE_H +#define VGAMOUSE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MOUSE_MICROSOFT 0 +#define MOUSE_MOUSESYSTEMS 1 +#define MOUSE_MMSERIES 2 +#define MOUSE_LOGITECH 3 +#define MOUSE_BUSMOUSE 4 +#define MOUSE_PS2 5 +#define MOUSE_LOGIMAN 6 +#define MOUSE_GPM 7 +#define MOUSE_SPACEBALL 8 +#define MOUSE_NONE 9 /* Some special number for a non supported/existing mouse */ +#define MOUSE_INTELLIMOUSE 10 +#define MOUSE_IMPS2 11 +#define MOUSE_PNP 12 +#define MOUSE_WACOM_GRAPHIRE 13 +#define MOUSE_DRMOUSE4DS 14 +#define MOUSE_EXPPS2 15 +#define MOUSE_UNCONFIGURED 16 +#define MOUSE_LAST MOUSE_UNCONFIGURED + +#define MOUSE_ORIENTATION_VERTICAL 0 +#define MOUSE_ORIENTATION_HORIZONTAL 1 + +#define MOUSE_ACCEL_TYPE_NORMAL 1 +#define MOUSE_ACCEL_TYPE_POWER 2 + +#define DEFAULT_ACCEL_THRESH 5 +#define DEFAULT_ACCEL_POWER 1.2 +#define DEFAULT_ACCEL_OFFSET 1 +#define DEFAULT_ACCEL_MULT 10 +#define DEFAULT_MAXDELTA 0 +#define DEFAULT_ACCEL_MAXDELTA 0 +#define DEFAULT_ACCEL_TYPE 0 /* MOUSE_ACCEL_TYPE_POWER */ + +/* MS IntelliMouse has 18 steps, Logitech FirstMouse+ has 24 */ +#define DEFAULT_WHEEL_STEPS 18 +#define DEFAULT_WHEEL_DELTA (360 / DEFAULT_WHEEL_STEPS) + +/* Logical or the following values to one of the above at will and give that for + type in mouse_init (still they make only sense for serial mice) */ + +#define MOUSE_CHG_DTR 0x80000000 /* CLEAR (!) the DTR line */ +#define MOUSE_DTR_HIGH 0x40000000 /* when used with MOUSE_CHG_DTR set DTR not clear it */ +#define MOUSE_CHG_RTS 0x20000000 /* CLEAR (!) the RTS line */ +#define MOUSE_RTS_HIGH 0x10000000 /* when used with MOUSE_CHG_RTS set RTS not clear it */ + +/* If MOUSE_CHG_DTR is not given the DTR state is not touched.. same with RTS resp. */ +/* So I use MOUSE_MOUSESYSTEMS|MOUSE_CHG_RTS to force my + multiprotocol mouse to MOUSESYSTEMS and use init the driver to MOUSESYSTEMS */ + +#define MOUSE_TYPE_MASK 0xffff /* the upper 16bit are reserved for future flags */ + +#define MOUSE_LEFTBUTTON 4 +#define MOUSE_MIDDLEBUTTON 2 +#define MOUSE_RIGHTBUTTON 1 +#define MOUSE_FOURTHBUTTON 8 +#define MOUSE_FIFTHBUTTON 16 +#define MOUSE_SIXTHBUTTON 32 +#define MOUSE_RESETBUTTON 64 + +#define MOUSE_XDIM 1 +#define MOUSE_YDIM 2 +#define MOUSE_ZDIM 4 +#define MOUSE_RXDIM 8 +#define MOUSE_RYDIM 16 +#define MOUSE_RZDIM 32 +#define MOUSE_2DIM 3 +#define MOUSE_3DIM 7 +#define MOUSE_6DIM 63 + +#define MOUSE_DEFAULTSAMPLERATE 150 + +/* Initialize mouse device. Returns 0 if succesful, -1 otherwise. */ +/* (Get the svgalib configured type with vga_getmousetype()). */ + int mouse_init(char *dev, int type, int samplerate); +/* Similar but returns the mouse fd if succesful. */ + int mouse_init_return_fd(char *dev, int type, int samplerate); +/* Set event handler invoked by mouse_update(). */ +#if 0 /* This is the actual definition */ + typedef void (*__mouse_handler) (int button, int dx, int dy, int dz, + int drx, int dry, int drz); +#else /* For backwards compatibility with: + typedef void (*__mouse_handler) (int button, int dx, int dy) we use: */ + typedef void *__mouse_handler; +#endif + void mouse_seteventhandler(__mouse_handler handler); +/* Close mouse device. */ + void mouse_close(void); +/* Read mouse and handle events. Returns 0 if no event. */ + int mouse_update(void); +/* Similar to mouse_update, but wait for an event to happen. */ + void mouse_waitforupdate(void); + +/* mouse_init sets default event handler that keeps track of absolute */ +/* coordinates: */ + +#define MOUSE_NOWRAP 0 +#define MOUSE_WRAPX 1 +#define MOUSE_WRAPY 2 +#define MOUSE_WRAPZ 4 +#define MOUSE_WRAPRX 8 +#define MOUSE_WRAPRY 16 +#define MOUSE_WRAPRZ 32 +#define MOUSE_WRAP 63 +#define MOUSE_ROT_COORDS 196 +#define MOUSE_ROT_INFINITESIMAL 0 /* report changes in angle about axes */ +#define MOUSE_ROT_RX_RY_RZ 64 /* report angle about axes */ + +/* Warning! Next two not yet supported! */ +#define MOUSE_ROT_ZXZ 128 /* use x convention Euler angles */ +#define MOUSE_ROT_YPR 196 /* use yaw, pitch, and roll */ + +/* Revert to default handler. */ + void mouse_setdefaulteventhandler(void); +/* Set position of mouse. */ + void mouse_setposition(int x, int y); +/* Set position of mouse in all 6 dimensions. */ + void mouse_setposition_6d(int x, int y, int z, + int rx, int ry, int rz, int dim_mask); +/* Set horizontal range of mouse to [x1, x2] incl. */ + void mouse_setxrange(int x1, int x2); +/* Set vertical range of mouse to [y1, y2] incl. */ + void mouse_setyrange(int y1, int y2); +/* Set all ranges of mouse in 6 dimensions. */ + void mouse_setrange_6d(int x1, int x2, int y1, int y2, int z1, int z2, + int rx1, int rx2, int ry1, int ry2, int rz1, int rz2, int dim_mask); +/* Set scale factor by which raw mouse coordinates are divided. */ + void mouse_setscale(int s); +/* Enable/disable wrapping of mouse in horizontal and/or vertical range. */ + void mouse_setwrap(int w); + +/* Get current mouse x-coordinate. */ + int mouse_getx(void); +/* Get current mouse y-coordinate. */ + int mouse_gety(void); +/* Get position of mouse in all 6 dimensions. */ + void mouse_getposition_6d(int *x, int *y, int *z, + int *rx, int *ry, int *rz); +/* Get current mouse button status. */ + int mouse_getbutton(void); + + +#define MOUSE_CAPS 1024 +#define MOUSE_WANTCAPS 0x002b0042 +#define MOUSE_GOTCAPS 0x0042ffd4 + +#define MOUSE_INFO_WHEEL 0x00000001 /* The mouse has a wheel */ + + struct MouseCaps { + int key; /* MOUSE_GOTCAPS */ + int buttons; /* MOUSE_*BUTTON */ + int axes; /* MOUSE_*DIM */ + int info; /* MOUSE_INFO_* */ + int reserved0; /* Don't use these! */ + int reserved1; /* The names may change in the future... */ + }; + +/* Use this function to get information about the mouse without depending on + mouse types known when your app was made. The weirdness is so that you + don't need to depend on having svgalib 1.3.0; as long as you don't depend + on other features your app should be able to work with older versions too, + just without this info... In a future version this will be made a real + function. Returns 0 on success or -1 on failure. */ + + static inline int mouse_getcaps(struct MouseCaps *caps) + { + mouse_setposition_6d(MOUSE_WANTCAPS,0,0, 0,0,0, MOUSE_CAPS); + mouse_getposition_6d(&(caps->key), &(caps->buttons), &(caps->axes), + &(caps->info), &(caps->reserved0), &(caps->reserved1)); + return ((caps->key == MOUSE_GOTCAPS) ? (0) : (-1)); + } + +#ifdef __cplusplus +} + +#endif +#endif diff --git a/src/ppcmemset.h b/src/ppcmemset.h new file mode 100644 index 0000000..62e2d02 --- /dev/null +++ b/src/ppcmemset.h @@ -0,0 +1,21 @@ +#ifdef __PPC + +#undef memset +static inline void memset(void *a, int c, int s) +{ + int i; + for(i=0;i +#endif diff --git a/src/ramdac/IBMRGB52x.c b/src/ramdac/IBMRGB52x.c new file mode 100644 index 0000000..3ba1c34 --- /dev/null +++ b/src/ramdac/IBMRGB52x.c @@ -0,0 +1,405 @@ +/* + * IBMRGB52x.c: + * + * RAMDAC definitions for IBM's RGB52x PaletteDAC. + * + * Portion of this file is derived from XFree86's source code. + * [insert XFree86's copyright here]. + */ + +#include +#include "libvga.h" + +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +#include "IBMRGB52x.h" + +#define IBMRGB52x_STATESIZE 0x101 + +static int IBMRGB52x_dacspeed = 170000; /* assuming 170MHz DAC */ +static int IBMRGB52x_fref = 16000; /* assuming 16MHz refclock */ +static int IBMRGB52x_clk = 2; /* use clock 2 */ + +#ifdef INCLUDE_IBMRGB52x_DAC_TEST +/* + * s3IBMRGB_Probe() from XFree86. + * + * returns 0x01xx for 525, 0x02xx for 524/528, where xx = revision. + */ +static int IBMRGB52x_probe(void) +{ + unsigned char CR43, CR55, dac[3], lut[6]; + unsigned char ilow, ihigh, id, rev, id2, rev2; + int i, j; + int ret = 0; + + port_out(0x43, 0x3D4); + CR43 = port_in(0x3D5); + port_out(CR43 & ~0x02, 0x3D5); + + port_out(0x55, 0x3D4); + CR55 = port_in(0x3D5); + port_out(CR55 & ~0x03, 0x3D5); + + /* save DAC and first LUT entries */ + for (i = 0; i < 3; i++) + dac[i] = port_in(IBMRGB_PIXEL_MASK + i); + for (i = j = 0; i < 2; i++) { + port_out(i, IBMRGB_READ_ADDR); + lut[j++] = port_in(IBMRGB_RAMDAC_DATA); + lut[j++] = port_in(IBMRGB_RAMDAC_DATA); + lut[j++] = port_in(IBMRGB_RAMDAC_DATA); + } + + port_out(0x55, 0x3D4); + port_out((CR55 & ~0x03) | 0x01, 0x3D5); /* set RS2 */ + + /* read ID and revision */ + ilow = port_in(IBMRGB_INDEX_LOW); + ihigh = port_in(IBMRGB_INDEX_HIGH); + port_out(0, IBMRGB_INDEX_HIGH); /* index high */ + port_out(IBMRGB_rev, IBMRGB_INDEX_LOW); + rev = port_in(IBMRGB_INDEX_DATA); + port_out(IBMRGB_id, IBMRGB_INDEX_LOW); + id = port_in(IBMRGB_INDEX_DATA); + + /* known IDs: + 1 = RGB525 + 2 = RGB524, RGB528 + */ + + if (id >= 1 && id <= 2) { + /* check if ID and revision are read only */ + port_out(IBMRGB_rev, IBMRGB_INDEX_LOW); + port_out(~rev, IBMRGB_INDEX_DATA); + port_out(IBMRGB_id, IBMRGB_INDEX_LOW); + port_out(~id, IBMRGB_INDEX_DATA); + port_out(IBMRGB_rev, IBMRGB_INDEX_LOW); + rev2 = port_in(IBMRGB_INDEX_DATA); + port_out(IBMRGB_id, IBMRGB_INDEX_LOW); + id2 = port_in(IBMRGB_INDEX_DATA); + + if (id == id2 && rev == rev2) { /* IBM RGB52x found */ + ret = (id << 8) | rev; + } else { + port_out(IBMRGB_rev, IBMRGB_INDEX_LOW); + port_out(rev, IBMRGB_INDEX_DATA); + port_out(IBMRGB_id, IBMRGB_INDEX_LOW); + port_out(id, IBMRGB_INDEX_DATA); + } + } + port_out(ilow, IBMRGB_INDEX_LOW); + port_out(ihigh, IBMRGB_INDEX_HIGH); + + port_out(0x55, 0x3D4); + port_out(CR55 & ~0x03, 0x3D5); /* reset RS2 */ + + /* restore DAC and first LUT entries */ + for (i = j = 0; i < 2; i++) { + port_out(i, IBMRGB_WRITE_ADDR); + port_out(lut[j++], IBMRGB_RAMDAC_DATA); + port_out(lut[j++], IBMRGB_RAMDAC_DATA); + port_out(lut[j++], IBMRGB_RAMDAC_DATA); + } + for (i = 0; i < 3; i++) + port_out(dac[i], IBMRGB_PIXEL_MASK + i); + + port_out(0x43, 0x3D4); + port_out(CR43, 0x3D5); + port_out(0x55, 0x3D4); + port_out(CR55, 0x3D5); + + return ret; +} +#else +#define IBMRGB52x_probe 0 +#endif + +#ifdef INCLUDE_IBMRGB52x_DAC +static void IBMRGBSetClock(int freq, int clk, int dacspeed, int fref, + int *best_m_out, int *best_n_out, int *best_df_out) +{ + volatile double ffreq, fdacspeed, ffref; + volatile int df, n, m, max_n, min_df; + volatile int best_m = 69, best_n = 17, best_df = 0; + volatile double diff, mindiff; + +#define FREQ_MIN 16250 /* 1000 * (0+65) / 4 */ +#define FREQ_MAX dacspeed + + if (freq < FREQ_MIN) + ffreq = FREQ_MIN / 1000.0; + else if (freq > FREQ_MAX) + ffreq = FREQ_MAX / 1000.0; + else + ffreq = freq / 1000.0; + + fdacspeed = dacspeed / 1e3; + ffref = fref / 1e3; + + ffreq /= ffref; + ffreq *= 16; + mindiff = ffreq; + + if (freq <= dacspeed / 4) + min_df = 0; + else if (freq <= dacspeed / 2) + min_df = 1; + else + min_df = 2; + + for (df = 0; df < 4; df++) { + ffreq /= 2; + mindiff /= 2; + if (df < min_df) + continue; + + /* the remaining formula is ffreq = (m+65) / n */ + + if (df < 3) + max_n = fref / 1000 / 2; + else + max_n = fref / 1000; + if (max_n > 31) + max_n = 31; + + for (n = 2; n <= max_n; n++) { + m = (int) (ffreq * n + 0.5) - 65; + if (m < 0) + m = 0; + else if (m > 63) + m = 63; + + diff = (m + 65.0) / n - ffreq; + if (diff < 0) + diff = -diff; + + if (diff < mindiff) { + mindiff = diff; + best_n = n; + best_m = m; + best_df = df; + } + } + } + +#ifdef DEBUG + fprintf(stderr,"clk %d, setting to %f, m 0x%02x %d, n 0x%02x %d, df %d\n", clk, + ((best_m + 65.0) / best_n) / (8 >> best_df) * ffref, + best_m, best_m, best_n, best_n, best_df); +#endif + *best_m_out = best_m; + *best_n_out = best_n; + *best_df_out = best_df; +} + +static void IBMRGB52x_init(void) +{ + unsigned char tmp, CR55; +#ifdef INCLUDE_IBMRGB52x_DAC_TEST + int idrev; + + idrev = IBMRGB52x_probe(); + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using IBM RGB 52%d PaletteDAC, revision %d.\n", + (idrev >> 8) == 1 ? 5 : 4, + idrev & 0xff); +#else + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using IBM RGB 52x PaletteDAC.\n"); +#endif + /* set RS2 */ + port_out(0x55, 0x3D4); + CR55 = port_in(0x3D5) & 0xFC; + port_out(CR55 | 0x01, 0x3D5); + + tmp = port_in(IBMRGB_INDEX_CONTROL); + port_out(tmp & ~0x01, IBMRGB_INDEX_CONTROL); /* turn off auto-increment */ + port_out(0, IBMRGB_INDEX_HIGH); /* reset index high */ + + __svgalib_outCR(0x55, CR55); +} + +static int IBMRGB52x_match_programmable_clock(int desiredclock) +{ + int m, n, df; + + IBMRGBSetClock(desiredclock, IBMRGB52x_clk, IBMRGB52x_dacspeed, + IBMRGB52x_fref, &m, &n, &df); + + return ((m + 65.0) / n) / (8 >> df) * IBMRGB52x_fref; +} + +static void IBMRGB52x_initialize_clock_state(unsigned char *regs, int freq) +{ + int m, n, df; + + IBMRGBSetClock(freq, IBMRGB52x_clk, IBMRGB52x_dacspeed, + IBMRGB52x_fref, &m, &n, &df); + + if (__svgalib_driver_report) + fprintf(stderr,"clk %d, setting to %.3f, m 0x%02x %d, n 0x%02x %d, df %d\n", + IBMRGB52x_clk, ((m + 65.0) / n) / (8 >> df) * IBMRGB52x_fref / 1000, + m, m, n, n, df); + + regs[IBMRGB_misc_clock] |= 0x01; + regs[IBMRGB_m0 + 2 * IBMRGB52x_clk] = (df << 6) | (m & 0x3f); + regs[IBMRGB_n0 + 2 * IBMRGB52x_clk] = n; + regs[IBMRGB_pll_ctrl2] &= 0xf0; + regs[IBMRGB_pll_ctrl2] |= IBMRGB52x_clk; + regs[IBMRGB_pll_ctrl1] &= 0xf8; + regs[IBMRGB_pll_ctrl1] |= 0x03; +} + +static void IBMRGB52x_savestate(unsigned char *regs) +{ + int i; + unsigned char tmp; + + /* set RS2 */ + port_out(0x55, 0x3D4); + tmp = port_in(0x3D5) & 0xFC; + port_out(tmp | 0x01, 0x3D5); + + for (i = 0; i < 0x100; i++) { + port_out(i, IBMRGB_INDEX_LOW); /* high index is set to 0 */ + regs[i] = port_in(IBMRGB_INDEX_DATA); + } + regs[0x100] = __svgalib_inCR(0x22); + + __svgalib_outCR(0x55, tmp); +} + +/* SL: not complete, need more work for 525. */ +static void IBMRGB52x_restorestate(const unsigned char *regs) +{ + int i; + unsigned char tmp; + + /* set RS2 */ + port_out(0x55, 0x3D4); + tmp = port_in(0x3D5) & 0xFC; + port_out(tmp | 0x01, 0x3D5); + + for (i = 0; i < 0x100; i++) { + port_out(i, IBMRGB_INDEX_LOW); /* high index is set to 0 */ + port_out(regs[i], IBMRGB_INDEX_DATA); + } + __svgalib_outCR(0x22, regs[0x100]); + + __svgalib_outCR(0x55, tmp); +} + +static int IBMRGB52x_map_clock(int bpp, int pixelclock) +{ + return pixelclock; +} + +static int IBMRGB52x_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ +#ifdef PIXEL_MULTIPLEXING + switch (bpp) { + case 4: + break; + case 8: + return htiming / 2; + case 16: + break; + case 24: + return htiming * 3 / 2; + case 32: + return htiming * 2; + } +#endif + return htiming; +} + +static void IBMRGB52x_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + unsigned char tmp; + + regs[IBMRGB_misc_clock] = (regs[IBMRGB_misc_clock] & 0xf0) | 0x03; + regs[IBMRGB_sync] = 0; + regs[IBMRGB_hsync_pos] = 0; + regs[IBMRGB_pwr_mgmt] = 0; + regs[IBMRGB_dac_op] &= ~0x08; /* no sync on green */ + regs[IBMRGB_dac_op] |= 0x02; /* fast slew */ + regs[IBMRGB_pal_ctrl] = 0; + regs[IBMRGB_misc1] &= ~0x43; + regs[IBMRGB_misc1] |= 1; +#ifdef PIXEL_MULTIPLEXING + if (bpp >= 8) + regs[IBMRGB_misc2] = 0x43; /* use SID bus? 0x47 for DAC_8_BIT */ +#endif + tmp = __svgalib_inCR(0x22); + if (bpp <= 8) /* and 968 */ + __svgalib_outCR(0x22, tmp | 0x08); + else + __svgalib_outCR(0x22, tmp & ~0x08); + + regs[IBMRGB_pix_fmt] &= ~0x07; + switch (bpp) { + case 4: + case 8: + regs[IBMRGB_pix_fmt] |= 0x03; + regs[IBMRGB_8bpp] = 0x00; + break; + case 15: + regs[IBMRGB_pix_fmt] |= 0x04; + regs[IBMRGB_16bpp] = 0x02; + break; + case 16: + regs[IBMRGB_pix_fmt] |= 0x04; + regs[IBMRGB_16bpp] = 0x00; + break; + case 24: + regs[IBMRGB_pix_fmt] |= 0x05; /* SL: guess */ + regs[IBMRGB_24bpp] = 0x00; + break; + case 32: + regs[IBMRGB_pix_fmt] |= 0x06; + regs[IBMRGB_32bpp] = 0x00; + break; + } + IBMRGB52x_initialize_clock_state(regs, + IBMRGB52x_map_clock(bpp, pixelclock)); +} + +static void IBMRGB52x_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + IBMRGB52x_dacspeed = __svgalib_setDacSpeed(dacspeed, 170000); /* 220 MHz version exist also */ + cardspecs->maxPixelClock4bpp = IBMRGB52x_dacspeed; + cardspecs->maxPixelClock8bpp = IBMRGB52x_dacspeed; +#ifdef PIXEL_MULTIPLEXING + cardspecs->maxPixelClock16bpp = IBMRGB52x_dacspeed; + cardspecs->maxPixelClock24bpp = IBMRGB52x_dacspeed * 3 / 2; + cardspecs->maxPixelClock32bpp = IBMRGB52x_dacspeed / 2; +#else + cardspecs->maxPixelClock16bpp = 0; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 0; +#endif + cardspecs->mapClock = IBMRGB52x_map_clock; + cardspecs->matchProgrammableClock = IBMRGB52x_match_programmable_clock; + cardspecs->mapHorizontalCrtc = IBMRGB52x_map_horizontal_crtc; + cardspecs->flags |= CLOCK_PROGRAMMABLE; +} + +DacMethods __svgalib_IBMRGB52x_methods = +{ + IBMRGB52x, + "IBM RGB 52x PaletteDAC", + DAC_HAS_PROGRAMMABLE_CLOCKS, + IBMRGB52x_probe, + IBMRGB52x_init, + IBMRGB52x_qualify_cardspecs, + IBMRGB52x_savestate, + IBMRGB52x_restorestate, + IBMRGB52x_initializestate, + IBMRGB52x_STATESIZE +}; +#endif diff --git a/src/ramdac/IBMRGB52x.h b/src/ramdac/IBMRGB52x.h new file mode 100644 index 0000000..4e479ed --- /dev/null +++ b/src/ramdac/IBMRGB52x.h @@ -0,0 +1,78 @@ +/* + * Taken from XFree86. XFree86 copyrights apply. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/common_hw/IBMRGB.h,v 3.0 1995/06/29 13:32:11 dawes Exp $ */ + +#define IBMRGB_REF_FREQ_1 14.31818 +#define IBMRGB_REF_FREQ_2 50.00000 + +/* #ifdef S3_SERVER */ +/* Direct standard VGA registers, special index and data registers */ + +#define IBMRGB_WRITE_ADDR 0x3C8 /* CR55 low bit == 0 */ +#define IBMRGB_RAMDAC_DATA 0x3C9 /* CR55 low bit == 0 */ +#define IBMRGB_PIXEL_MASK 0x3C6 /* CR55 low bit == 0 */ +#define IBMRGB_READ_ADDR 0x3C7 /* CR55 low bit == 0 */ +#define IBMRGB_INDEX_LOW 0x3C8 /* CR55 low bit == 1 */ +#define IBMRGB_INDEX_HIGH 0x3C9 /* CR55 low bit == 1 */ +#define IBMRGB_INDEX_DATA 0x3C6 /* CR55 low bit == 1 */ +#define IBMRGB_INDEX_CONTROL 0x3C7 /* CR55 low bit == 1 */ +/* #endif */ + +#define IBMRGB_rev 0x00 +#define IBMRGB_id 0x01 +#define IBMRGB_misc_clock 0x02 +#define IBMRGB_sync 0x03 +#define IBMRGB_hsync_pos 0x04 +#define IBMRGB_pwr_mgmt 0x05 +#define IBMRGB_dac_op 0x06 +#define IBMRGB_pal_ctrl 0x07 +#define IBMRGB_sysclk 0x08 /* not RGB525 */ +#define IBMRGB_pix_fmt 0x0a +#define IBMRGB_8bpp 0x0b +#define IBMRGB_16bpp 0x0c +#define IBMRGB_24bpp 0x0d +#define IBMRGB_32bpp 0x0e +#define IBMRGB_pll_ctrl1 0x10 +#define IBMRGB_pll_ctrl2 0x11 +#define IBMRGB_pll_ref_div_fix 0x14 +#define IBMRGB_sysclk_ref_div 0x15 /* not RGB525 */ +#define IBMRGB_sysclk_vco_div 0x16 /* not RGB525 */ +#define IBMRGB_f0 0x20 +#define IBMRGB_m0 0x20 +#define IBMRGB_n0 0x21 +#define IBMRGB_curs 0x30 +#define IBMRGB_curs_xl 0x31 +#define IBMRGB_curs_xh 0x32 +#define IBMRGB_curs_yl 0x33 +#define IBMRGB_curs_yh 0x34 +#define IBMRGB_curs_hot_x 0x35 +#define IBMRGB_curs_hot_y 0x36 +#define IBMRGB_curs_col1_r 0x40 +#define IBMRGB_curs_col1_g 0x41 +#define IBMRGB_curs_col1_b 0x42 +#define IBMRGB_curs_col2_r 0x43 +#define IBMRGB_curs_col2_g 0x44 +#define IBMRGB_curs_col2_b 0x45 +#define IBMRGB_curs_col3_r 0x46 +#define IBMRGB_curs_col3_g 0x47 +#define IBMRGB_curs_col3_b 0x48 +#define IBMRGB_border_col_r 0x60 +#define IBMRGB_border_col_g 0x61 +#define IBMRGB_botder_col_b 0x62 +#define IBMRGB_misc1 0x70 +#define IBMRGB_misc2 0x71 +#define IBMRGB_misc3 0x72 +#define IBMRGB_misc4 0x73 /* not RGB525 */ +#define IBMRGB_dac_sense 0x82 +#define IBMRGB_misr_r 0x84 +#define IBMRGB_misr_g 0x86 +#define IBMRGB_misr_b 0x88 +#define IBMRGB_pll_vco_div_in 0x8e +#define IBMRGB_pll_ref_div_in 0x8f +#define IBMRGB_vram_mask_0 0x90 +#define IBMRGB_vram_mask_1 0x91 +#define IBMRGB_vram_mask_2 0x92 +#define IBMRGB_vram_mask_3 0x93 +#define IBMRGB_curs_array 0x100 diff --git a/src/ramdac/attdacs.c b/src/ramdac/attdacs.c new file mode 100644 index 0000000..a5440e9 --- /dev/null +++ b/src/ramdac/attdacs.c @@ -0,0 +1,224 @@ +/* + * attdacs.c: + * + * RAMDAC definition for industry-standard AT&T20C490/498 DACs and + * compatibles. + */ + +#include +#include +#include "libvga.h" + +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +/* + * RAMDAC definition for industry-standard AT&T20C490 DAC with 8-bit pixel + * port, and compatibles. + * These RAMDACs can do 32K and 64K color mode (16bpp) with doubled VCLK + * and 16M (8-8-8) truecolor with tripled VCLK. + * 0xA0 is written to the Hidden DAC register for 32K, 0xC0 for 64K and + * 0xE0 for 16M. + */ + +#ifdef INCLUDE_ATT20C490_DAC_TEST +static int att20c490_probe(void) +{ + unsigned char oldcomm, notcomm, oldpel, v; + int flag = 0; + + _ramdac_dactocomm(); + oldcomm = port_in(PEL_MSK); + _ramdac_dactopel(); + oldpel = port_in(PEL_MSK); + + notcomm = ~oldcomm; + port_out_r(PEL_MSK, notcomm); + _ramdac_dactocomm(); + v = port_in(PEL_MSK); + if (v != notcomm) { + if ((_ramdac_setcomm(0xe0) & 0xe0) == 0xe0) { + if ((_ramdac_setcomm(0x60) & 0xe0) == 0) { + if ((_ramdac_setcomm(2) & 2) > 0) + flag = 1; /* 20c490 */ + else + flag = 1; /* 20c493 */ + } else { + _ramdac_setcomm(oldcomm); + if (port_in(PEL_MSK) == notcomm) + if (_ramdac_setcomm(0xFF) == 0xFF) + flag = 1; /* 20c491/20c492 */ + } + } + } + _ramdac_dactocomm(); + port_out_r(PEL_MSK, oldcomm); + _ramdac_dactopel(); + port_out_r(PEL_MSK, oldpel); + return flag; +} +#else +#define att20c490_probe 0 +#endif + +#ifdef INCLUDE_ATT20C490_DAC +static void att20c490_init(void) +{ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using AT&T20C490-compatible truecolor DAC.\n"); +#if 0 + dactocomm(); + port_in(PEL_MSK); /* Skip command register. */ + fprintf(stderr,"svgalib: DAC Manufacturer ID = 0x%02X, ", port_in(PEL_MSK)); + fprintf(stderr,"Device ID = 0x%02X.\n", port_in(PEL_MSK)); +#endif +} + +static int __svgalib_att20c490_map_clock(int bpp, int pixelclock) +{ + if (bpp == 16) + return pixelclock * 2; + if (bpp == 24) + return pixelclock * 3; + return pixelclock; +} + +static int __svgalib_att20c490_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + if (bpp == 16) + return htiming * 2; + if (bpp == 24) + return htiming * 3; + return htiming; +} + + +static void att20c490_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + regs[0] = 0; + if (colormode == RGB16_555) + regs[0] = 0xA0; + if (colormode == RGB16_565) + regs[0] = 0xC0; + if (colormode == RGB24_888_B) + regs[0] = 0xE0; +} + +static void att20c490_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 80000); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed / 2; + cardspecs->maxPixelClock24bpp = dacspeed / 3; + cardspecs->maxPixelClock32bpp = 0; + cardspecs->mapClock = __svgalib_att20c490_map_clock; + cardspecs->mapHorizontalCrtc = __svgalib_att20c490_map_horizontal_crtc; +} + +DacMethods __svgalib_ATT20C490_methods = +{ + ATT20C490, + "AT&T-compatible truecolor DAC, 80 MHz rated", + 0, + att20c490_probe, + att20c490_init, + att20c490_qualify_cardspecs, + __svgalib_Sierra_32K_savestate, + __svgalib_Sierra_32K_restorestate, + att20c490_initializestate, + 1 /* State size. */ +}; +#endif + +/* + * RAMDAC definition for industry-standard AT&T20C498 DAC with 16-bit + * pixel port, and compatibles. + * Differently rated versions exist, such as 80, 110, 135 and 170 MHz. + * This code assumes the DAC is actually connected with a 16-bit path. + * (an example of a 498-compatible DAC being used with a 8-bit path + * is the Hercules Stingray Pro/V with the IC Works ZoomDAC). + */ + +#ifdef INCLUDE_ATT20C498_DAC_TEST +static int att20c498_probe(void) +{ + return 0; +} +#else +#define att20c498_probe 0 +#endif + +#ifdef INCLUDE_ATT20C498_DAC +static void att20c498_init(void) +{ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using AT&T20C498-compatible DAC, 80 MHz rated.\n"); +} + +static int att20c498_map_clock(int bpp, int pixelclock) +{ + if (bpp == 8 && pixelclock > 80000) + /* Use 16-bit path, clock doubling at RAMDAC. */ + return pixelclock / 2; + if (bpp == 16) + return pixelclock; + if (bpp == 32) + return pixelclock * 2; + return pixelclock; +} + +static int att20c498_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + /* Not sure. */ + if (bpp == 8 && pixelclock > 80000) + /* Use 16-bit path, clock doubling at RAMDAC. */ + return htiming / 2; + if (bpp == 32) + return htiming * 2; + return htiming; +} + +static void att20c498_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + regs[0] = 0; + if (colormode == CLUT8_8) + regs[0] = 0x02; + if (colormode == RGB16_555) + regs[0] = 0x10; + if (colormode == RGB16_565) + regs[0] = 0x30; + if (colormode == RGB32_888_B) + regs[0] = 0x50; +} + +static void att20c498_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 110000); + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = dacspeed / 2; + cardspecs->mapClock = att20c498_map_clock; + cardspecs->mapHorizontalCrtc = att20c498_map_horizontal_crtc; +} + +DacMethods __svgalib_ATT20C498_methods = +{ + ATT20C498, + "AT&T20C498 DAC", + 0, + att20c498_probe, + att20c498_init, + att20c498_qualify_cardspecs, + __svgalib_Sierra_32K_savestate, + __svgalib_Sierra_32K_restorestate, + att20c498_initializestate, + 1 /* State size. */ +}; +#endif diff --git a/src/ramdac/btdacs.c b/src/ramdac/btdacs.c new file mode 100644 index 0000000..c343118 --- /dev/null +++ b/src/ramdac/btdacs.c @@ -0,0 +1,109 @@ +/* + * btdacs.c: + * + * RAMDAC definition for Bt485 + * + * NON-FUNCTIONAL + */ + +#include +#include +#include "libvga.h" + +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +/* + * RAMDAC definition for industry-standard AT&T20C498 DAC with 16-bit + * pixel port, and compatibles. + * Differently rated versions exist, such as 80, 110, 135 and 170 MHz. + * This code assumes the DAC is actually connected with a 16-bit path. + * (an example of a 498-compatible DAC being used with a 8-bit path + * is the Hercules Stingray Pro/V with the IC Works ZoomDAC). + */ + +#ifdef INCLUDE_BT485_DAC_TEST +static int bt485_probe(void) +{ + return 0; +} +#else +#define bt485_probe 0 +#endif + +#ifdef INCLUDE_BT485_DAC +static void bt485_init(void) +{ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using BT485 DAC, 135 MHz rated.\n"); +} + +static int bt485_map_clock(int bpp, int pixelclock) +{ + return pixelclock; + + if (bpp == 8 && pixelclock > 80000) + /* Use 16-bit path, clock doubling at RAMDAC. */ + return pixelclock / 2; + if (bpp == 16) + return pixelclock; + if (bpp == 32) + return pixelclock * 2; + return pixelclock; +} + +static int bt485_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + return htiming + + /* Not sure. */ + if (bpp == 8 && pixelclock > 80000) + /* Use 16-bit path, clock doubling at RAMDAC. */ + return htiming / 2; + if (bpp == 32) + return htiming * 2; + return htiming; +} + +static void bt485_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + regs[0] = 0; + if (colormode == CLUT8_8) + regs[0] = 0x02; + if (colormode == RGB16_555) + regs[0] = 0x10; + if (colormode == RGB16_565) + regs[0] = 0x30; + if (colormode == RGB32_888_B) + regs[0] = 0x50; +} + +static void 485_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 135000); + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = dacspeed ; + cardspecs->mapClock = bt485_map_clock; + cardspecs->mapHorizontalCrtc = att20c498_map_horizontal_crtc; +} + +DacMethods __svgalib_BT485_methods = +{ + BT485, + "BT485 DAC", + 0, + bt485_probe, + bt485_init, + bt485_qualify_cardspecs, + __svgalib_Sierra_32K_savestate, + __svgalib_Sierra_32K_restorestate, + bt485_initializestate, + 1 /* State size. */ +}; +#endif diff --git a/src/ramdac/ics_gendac.c b/src/ramdac/ics_gendac.c new file mode 100644 index 0000000..1d25bdc --- /dev/null +++ b/src/ramdac/ics_gendac.c @@ -0,0 +1,261 @@ +/* + * ics_gendac.c: + * + * This works only with ARK, since it has ARK specific code. + */ + +#include +#include "libvga.h" +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +/* SDAC/GENDAC registers */ +#define SDAC_COMMAND 0 +#define GENDAC_COMMAND 0 +#define SDAC_PLL_WRITEINDEX 1 +#define SDAC_PLL_READINDEX 2 +#define SDAC_PLL_M 3 /* f2 programmed clock */ +#define SDAC_PLL_N1_N2 4 +#define SDAC_PLL_CONTROL 5 + +#define GENDAC_STATESIZE 6 + +static void GENDAC_init(void) +{ +} + + +/* + * From XFree86 common_hw/S3gendac.c and S3gendac.h. + * + * Progaming of the S3 gendac programable clocks, from the S3 Gendac + * programing documentation by S3 Inc. + * Jon Tombs + * + * Returns nonzero if success, 0 if failure. + */ +#define BASE_FREQ 14.31818 /* MHz */ + +#define DEBUG_FINDCLOCK 0 + +static int S3dacsFindClock(int freq_in, int min_n2, int freq_min, int freq_max, + int *best_m_out, int *best_n1_out, int *best_n2_out) +{ + double ffreq_in, ffreq_min, ffreq_max; + double ffreq_out, diff, best_diff; + unsigned int m; + unsigned char n1, n2; + unsigned char best_n1 = 16 + 2, best_n2 = 2, best_m = 125 + 2; + +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: Trying to match clock of %0.3f MHz\n", freq_in / 1000.0); +#endif + + ffreq_in = freq_in / 1000.0 / BASE_FREQ; + ffreq_min = freq_min / 1000.0 / BASE_FREQ; + ffreq_max = freq_max / 1000.0 / BASE_FREQ; + + /* Check if getting freq_in is possible at all */ + if (freq_in < freq_min / 8) { +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: %0.3f MHz is too low (lowest is %0.3f MHz)\n", + freq_in / 1000.0, freq_min / 1000.0 / 8); +#endif + return 0; + } + if (freq_in > freq_max / (1 << min_n2)) { +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: %0.3f MHz is too high (highest is %0.3f MHz)\n", + freq_in / 1000.0, freq_max / 1000.0 / (1 << min_n2)); +#endif + return 0; + } + + /* work out suitable timings */ + best_diff = ffreq_in; + for (n2 = min_n2; n2 <= 3; n2++) { + for (n1 = 1 + 2; n1 <= 31 + 2; n1++) { + m = (int) (ffreq_in * n1 * (1 << n2) + 0.5); + if (m < 1 + 2 || m > 127 + 2) + continue; + ffreq_out = (double) (m) / (double) (n1); + if ((ffreq_out >= ffreq_min) && (ffreq_out <= ffreq_max)) { + diff = ffreq_in - ffreq_out / (1 << n2); + if (diff < 0.0) + diff = -diff; + if (diff < best_diff) { + best_diff = diff; + best_m = m; + best_n1 = n1; + best_n2 = n2; + } + } + } + } + +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: clock wanted %1.6f MHz, found %1.6f MHz (m %d, n1 %d, n2 %d)\n", + freq_in / 1000.0, + best_m / ((double) best_n1 * (1 << best_n2)) * BASE_FREQ, + best_m, best_n1, best_n2); +#endif + + *best_m_out = best_m; + *best_n1_out = best_n1; + *best_n2_out = best_n2; + + return 1; +} + +static int GENDAC_match_programmable_clock(int desiredclock) +{ + int min_m, min_n1, n2; + + /* Note: For ICS5342, min_n2 parameter should be one. */ + if (!S3dacsFindClock(desiredclock, 0, 100000, 250000, &min_m, &min_n1, &n2)) + return 0; + + return ((float) (min_m) / (float) (min_n1) / (1 << n2)) * BASE_FREQ * 1000; +} + +static void GENDAC_initialize_clock_state(unsigned char *regs, int freq) +{ + int min_m, min_n1, n2; + int n, m; + + if (!S3dacsFindClock(freq, 0, 100000, 250000, &min_m, &min_n1, &n2)) { + fprintf(stderr,"Bad dot clock %0.3f MHz.\n", freq / 1000.0); + return; + } + + n = (min_n1 - 2) | (n2 << 5); + m = min_m - 2; + regs[SDAC_PLL_M] = m; + regs[SDAC_PLL_N1_N2] = n; +#if 0 + if (__svgalib_driver_report) + fprintf(stderr,"Initializing DAC PLL values; 0x%02X, 0x%02X.\n", m, n); +#endif +} + +static void GENDAC_savestate(unsigned char *regs) +{ + unsigned char tmp; + tmp = __svgalib_inSR(0x1c); + __svgalib_outSR(0x1c, tmp | 0x80); + + regs[SDAC_COMMAND] = port_in(0x3c6); + regs[SDAC_PLL_WRITEINDEX] = port_in(0x3c8); /* PLL write index */ + regs[SDAC_PLL_READINDEX] = port_in(0x3c7); /* PLL read index */ + port_out_r(0x3c7, 2); /* index to f2 reg */ + regs[SDAC_PLL_M] = port_in(0x3c9); /* f2 PLL M divider */ + regs[SDAC_PLL_N1_N2] = port_in(0x3c9); /* f2 PLL N1/N2 divider */ + port_out_r(0x3c7, 0x0e); /* index to PLL control */ + regs[SDAC_PLL_CONTROL] = port_in(0x3c9); /* PLL control */ + + __svgalib_outSR(0x1c, tmp & ~0x80); +} + +static void GENDAC_restorestate(const unsigned char *regs) +{ + unsigned char tmp; + + tmp = __svgalib_inseq(0x1c); + __svgalib_outseq(0x1c, tmp | 0x80); + + port_out_r(0x3c6, regs[SDAC_COMMAND]); + port_out_r(0x3c8, 2); /* index to f2 reg */ + port_out_r(0x3c9, regs[SDAC_PLL_M]); /* f2 PLL M divider */ + port_out_r(0x3c9, regs[SDAC_PLL_N1_N2]); /* f2 PLL N1/N2 divider */ + port_out_r(0x3c8, 0x0e); /* index to PLL control */ + port_out_r(0x3c9, regs[SDAC_PLL_CONTROL]); /* PLL control */ + port_out_r(0x3c8, regs[SDAC_PLL_WRITEINDEX]); /* PLL write index */ + port_out_r(0x3c7, regs[SDAC_PLL_READINDEX]); /* PLL read index */ + + __svgalib_outseq(0x1c, tmp); +} + +/* + * SDAC: 16-bit DAC, 110 MHz raw clock limit. + * + * The 135 MHz version supports pixel multiplexing in 8bpp modes with a + * halved raw clock. (SL: at least mine doesn't.) + */ + +static int GENDAC_probe(void) +{ + int i; + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + i=port_in(0x3c6); + if(i==177) return 1; + return 0; +} + +static int GENDAC_map_clock(int bpp, int pixelclock) +{ + if (bpp == 16) + return pixelclock * 2; + if (bpp == 24) + return pixelclock * 3; + if (bpp == 32) + return pixelclock * 4; + return pixelclock; +} + +static int GENDAC_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + /* XXXX Not sure. */ + if (bpp == 24) + return htiming * 3; + if (bpp == 16) + return htiming * 2; + return htiming; +} + +static void GENDAC_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + int daccomm; /* DAC command register. */ + daccomm = 0; + if (colormode == RGB16_555) + daccomm = 0x20; + else if (colormode == RGB16_565) + daccomm = 0x60; + else if (colormode == RGB24_888_B) + daccomm = 0x40; + regs[GENDAC_COMMAND] = daccomm; + GENDAC_initialize_clock_state(regs, + GENDAC_map_clock(bpp, pixelclock)); +} + +static void GENDAC_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 110000); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed / 2; + cardspecs->maxPixelClock24bpp = dacspeed / 3; + cardspecs->maxPixelClock32bpp = 0; + cardspecs->mapClock = GENDAC_map_clock; + cardspecs->matchProgrammableClock = GENDAC_match_programmable_clock; + cardspecs->mapHorizontalCrtc = GENDAC_map_horizontal_crtc; + cardspecs->flags |= CLOCK_PROGRAMMABLE; +} + +DacMethods __svgalib_ICS_GENDAC_methods = +{ + S3_GENDAC, + "ICS-GENDAC (5342)", + DAC_HAS_PROGRAMMABLE_CLOCKS, + GENDAC_probe, + GENDAC_init, + GENDAC_qualify_cardspecs, + GENDAC_savestate, + GENDAC_restorestate, + GENDAC_initializestate, + GENDAC_STATESIZE +}; diff --git a/src/ramdac/icw.c b/src/ramdac/icw.c new file mode 100644 index 0000000..fef42c5 --- /dev/null +++ b/src/ramdac/icw.c @@ -0,0 +1,119 @@ +/* + * icw.c: + * + * RAMDAC definition for IC Works DACs. + * This version only supports the 16-bit ZoomDAC (w30C516), which + * is compatible with the AT&T 20C498. + * This DAC exists in 110, 135 and 170 MHz versions. + * It can do packed 24-bit color (BG-RB-GR). + * The 170 MHz version has a PCLK limit of 135 MHz + * (170 pixel clock for 16-bit path for 8bpp LUT). + */ + +#include +#include +#include "libvga.h" + +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +#ifdef INCLUDE_ICW_DAC_TEST +static int ICW_probe(void) +{ + unsigned char mi, di; + + _ramdac_dactocomm(); + port_in(PEL_MSK); /* Control register 0. */ + mi = port_in(PEL_MSK); /* Manufacturer ID. */ + di = port_in(PEL_MSK); /* Device ID. */ + if (mi == 0x84) { + if (di == 0x98) + return 1; + fprintf(stderr,"svgalib: ICW_probe: Unknown IC Works DAC.\n"); + } + return 0; +} +#else +#define ICW_probe 0 +#endif + +#ifdef INCLUDE_ICW_DAC +static void ICW_init(void) +{ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using IC Works DAC (AT&T20C498-compatible).\n"); +} + +static int ICW_map_clock(int bpp, int pixelclock) +{ + if (bpp == 8 && pixelclock > 80000) + /* Use 16-bit path, clock doubling at RAMDAC. */ + return pixelclock / 2; + if (bpp == 16) + return pixelclock; + if (bpp == 24) + /* Use the packed 24-bit mode. */ + return pixelclock * 3 / 2; + if (bpp == 32) + return pixelclock * 2; + return pixelclock; +} + +static int ICW_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + /* Not sure. */ + if (bpp == 8 && pixelclock > 80000) + /* Use 16-bit path, clock doubling at RAMDAC. */ + return htiming / 2; + if (bpp == 24) + return htiming * 3 / 2; + if (bpp == 32) + return htiming * 2; + return htiming; +} + +static void ICW_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + regs[0] = 0; + if (colormode == CLUT8_8) + regs[0] = 0x02; + if (colormode == RGB16_555) + regs[0] = 0x10; + if (colormode == RGB16_565) + regs[0] = 0x30; + if (colormode == RGB24_888_B) + /* Packed mode. */ + regs[0] = 0xB0; + if (colormode == RGB32_888_B) + regs[0] = 0x50; +} + +static void ICW_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 110000); + cardspecs->maxPixelClock4bpp = 0; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed; + cardspecs->maxPixelClock24bpp = dacspeed * 2 / 3; + cardspecs->maxPixelClock32bpp = dacspeed / 2; + cardspecs->mapClock = ICW_map_clock; + cardspecs->mapHorizontalCrtc = ICW_map_horizontal_crtc; +} + +DacMethods __svgalib_ICW_methods = +{ + IC_WORKS, + "IC Works DAC", + 0, + ICW_probe, + ICW_init, + ICW_qualify_cardspecs, + __svgalib_Sierra_32K_savestate, + __svgalib_Sierra_32K_restorestate, + ICW_initializestate, + 1 /* State size. */ +}; +#endif diff --git a/src/ramdac/normal.c b/src/ramdac/normal.c new file mode 100644 index 0000000..84ecc7a --- /dev/null +++ b/src/ramdac/normal.c @@ -0,0 +1,82 @@ +/* + * normal.c: + * + * RAMDAC definition for normal VGA DAC. + * Max dot clock is set at 80 MHz. + */ + +#include +#include +#include "libvga.h" + +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +#ifdef INCLUDE_NORMAL_DAC_TEST +static int normal_dac_probe(void) +{ + return 1; +} +#else +#define normal_dac_probe 0 +#endif + +#ifdef INCLUDE_NORMAL_DAC +static void normal_dac_init(void) +{ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using Normal VGA RAMDAC.\n"); +} + +static int normal_dac_map_clock(int bpp, int pixelclock) +{ + return pixelclock; +} + +static int normal_dac_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + return htiming; +} + +static void normal_dac_savestate(unsigned char *regs) +{ +} + +static void normal_dac_restorestate(const unsigned char *regs) +{ +} + +static void normal_dac_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + /* Nothing to do. */ +} + +static void normal_dac_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 80000); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = 0; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 0; + cardspecs->mapClock = normal_dac_map_clock; + cardspecs->mapHorizontalCrtc = normal_dac_map_horizontal_crtc; +} + +DacMethods __svgalib_normal_dac_methods = +{ + NORMAL_DAC, + "Normal VGA DAC", + 0, + normal_dac_probe, + normal_dac_init, + normal_dac_qualify_cardspecs, + normal_dac_savestate, + normal_dac_restorestate, + normal_dac_initializestate, + 0 /* State size. */ +}; +#endif diff --git a/src/ramdac/ramdac.c b/src/ramdac/ramdac.c new file mode 100644 index 0000000..a1dc732 --- /dev/null +++ b/src/ramdac/ramdac.c @@ -0,0 +1,122 @@ +/* + * ramdac.c: + * + * This file contains RAMDAC definitions of type DacMethods for + * various DACs. + * + * Note that the restoreState function is the only function that + * should program the DAC registers; the initializeState function + * should merely define the values that will be written in a + * subsequent call of the restore funtion. + */ + +#include +#include +#include "libvga.h" + +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +/* + * The following function probes the DACs in daclist, which must be + * terminated by NULL. It returns the detected DAC if successful, NULL + * otherwise. The detected DAC is also initialized. + */ + +DacMethods *__svgalib_probeDacs(DacMethods ** dacs_to_probe) +{ + /* Probe for a RAMDAC. */ + for (;;) { + DacMethods *dac; + dac = *dacs_to_probe; + if (dac == NULL) + /* None found. */ + return NULL; + if (dac->probe()) { + dac->initialize(); + return dac; + } + dacs_to_probe++; + } +} + +int __svgalib_setDacSpeed(int dacspeed, int defspeed) +{ + if (!dacspeed) { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Assuming %dMHz DAC.\n", defspeed / 1000); + dacspeed = defspeed; + } else { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: DAC speed set to %dMHz.\n", dacspeed / 1000); + } + return dacspeed; +} + +#ifndef __OPTIMIZE__ /* otherwise inlined from ramdac.h */ +void _ramdac_dactocomm(void) +{ + port_in(PEL_IW); + port_in(PEL_MSK); + port_in(PEL_MSK); + port_in(PEL_MSK); + port_in(PEL_MSK); +} + +void _ramdac_dactopel(void) +{ + port_in(PEL_IW); +} + +unsigned char _ramdac_setcomm(unsigned char data) +{ + _ramdac_dactocomm(); + port_out_r(PEL_MSK, data); + _ramdac_dactocomm(); + return port_in(PEL_MSK); +} +#endif + +/* + * List of all DACs. + */ + +DacMethods *__svgalib_all_dacs[] = +{ +#ifdef INCLUDE_NORMAL_DAC + &__svgalib_normal_dac_methods, +#endif +#ifdef INCLUDE_S3_SDAC_DAC + &__svgalib_S3_SDAC_methods, +#endif +#ifdef INCLUDE_S3_GENDAC_DAC + &__svgalib_S3_GENDAC_methods, +#endif +#ifdef INCLUDE_S3_TRIO64_DAC + &__svgalib_Trio64_methods, +#endif +#ifdef INCLUDE_SIERRA_DAC + &__svgalib_Sierra_32K_methods, +#endif +#ifdef INCLUDE_SC15025_DAC + &__svgalib_SC15025_methods, +#endif +#ifdef INCLUDE_ATT20C490_DAC + &__svgalib_ATT20C490_methods, +#endif +#ifdef INCLUDE_ATT20C498_DAC + &__svgalib_ATT20C498_methods, +#endif +#ifdef INCLUDE_ICW_DAC + &__svgalib_ICW_methods, +#endif +#ifdef INCLUDE_SC1148X_DAC + &__svgalib_SC1148X_methods, +#endif +#ifdef INCLUDE_ICS_GENDAC_DAC + &__svgalib_ICS_GENDAC_methods, +#endif + NULL +}; diff --git a/src/ramdac/ramdac.h b/src/ramdac/ramdac.h new file mode 100644 index 0000000..ff34036 --- /dev/null +++ b/src/ramdac/ramdac.h @@ -0,0 +1,166 @@ +/* + * ramdac.h: + * + * Structures and functions for programmable ramdac support. + */ + +/* DacMethods type. */ + +typedef struct { + int id; + char *name; + int flags; + /* + * The following function tries to detect the DAC; + * returns nonzero if succesful. + */ + int (*probe) (void); + /* + * The following function initializes the DAC; it is usually + * called once after detection. + */ + void (*initialize) (void); + /* + * The following function fills in dot clock limits, and + * mapping functions for the raw clock and horizontal + * CRTC timing, in the cardspecs structure. + * + * dacspeed is the max pixel clock in kHz the dac can handle, + * or 0 for default. + */ + void (*qualifyCardSpecs) (CardSpecs * cardspecs, int dacspeed); + /* + * The following function saves RAMDAC registers into regs. + */ + void (*saveState) (unsigned char *regs); + /* + * The following function sets the RAMDAC registers with the + * values from regs. + */ + void (*restoreState) (const unsigned char *regs); + /* + * The following function sets up the RAMDAC register values + * for the desired color operating mode. If the DAC has + * programmable clocks, it should also program the clock. + */ + void (*initializeState) (unsigned char *regs, int bpp, int colormode, + int pixelclock); + int stateSize; /* Size in bytes of the state (saved registers). */ +} DacMethods; + +/* IDs */ + +#define NORMAL_DAC 1 +#define S3_GENDAC 2 /* S3-GenDAC (8-bit DAC). */ +#define S3_SDAC 3 /* S3-SDAC (16-bit DAC). */ +#define TRIO64 4 /* Trio64 internal DAC. */ +#define SIERRA_32K 5 /* Basic DAC with 32K color mode support. */ +#define ATT20C490 6 /* Standard AT&T 8-bit DAC with truecolor. */ +#define ATT20C498 7 /* Standard AT&T 16-bit DAC. */ +#define IC_WORKS 8 /* IC Works DAC (16-bit ZoomDac). */ +#define SIERRA_15025 9 /* Sierra SC15025/26 DAC. */ +#define IBMRGB52x 10 /* IBM RGB52x Palette DAC. */ +#define SIERRA_1148X 11 /* Sierra SC1148x DAC. */ + +/* Flags. */ + +#define DAC_HAS_PROGRAMMABLE_CLOCKS 0x1 + +/* Color modes. */ + +#define CLUT8_6 0 +#define CLUT8_8 1 +#define RGB16_555 2 +#define RGB16_565 3 +#define RGB24_888_B 4 /* 3 bytes per pixel, blue byte first. */ +#define RGB32_888_B 5 /* 4 bytes per pixel. */ + +/* State size */ +#define MAX_DAC_STATE 0x101 /* IBMRGB has this many */ + +/* RAMDAC methods */ + +#ifdef INCLUDE_NORMAL_DAC +extern DacMethods __svgalib_normal_dac_methods; +#endif +#ifdef INCLUDE_S3_SDAC_DAC +extern DacMethods __svgalib_S3_SDAC_methods; +#endif +#ifdef INCLUDE_S3_GENDAC_DAC +extern DacMethods __svgalib_S3_GENDAC_methods; +#endif +#ifdef INCLUDE_S3_TRIO64_DAC +extern DacMethods __svgalib_Trio64_methods; +#endif +#ifdef INCLUDE_SIERRA_DAC +extern DacMethods __svgalib_Sierra_32K_methods; +#endif +#ifdef INCLUDE_SC15025_DAC +extern DacMethods __svgalib_SC15025_methods; +#endif +#ifdef INCLUDE_ATT20C490_DAC +extern DacMethods __svgalib_ATT20C490_methods; +#endif +#ifdef INCLUDE_ATT20C498_DAC +extern DacMethods __svgalib_ATT20C498_methods; +#endif +#ifdef INCLUDE_ICW_DAC +extern DacMethods __svgalib_ICW_methods; +#endif +#ifdef INCLUDE_IBMRGB52x_DAC +extern DacMethods __svgalib_IBMRGB52x_methods; +#endif +#ifdef INCLUDE_SC1148X_DAC +extern DacMethods __svgalib_SC1148X_methods; +#endif +#ifdef INCLUDE_ICS_GENDAC_DAC +extern DacMethods __svgalib_ICS_GENDAC_methods; +#endif + +extern DacMethods *__svgalib_all_dacs[]; /* List of all defined DACs. */ + +/* Functions defined in ramdac.c. */ + +/* + * The following function probes the DACs in daclist, which must be + * terminated by NULL. It returns the detected DAC if succesful, NULL + * otherwise. The detected DAC is also initialized. + */ + +DacMethods *__svgalib_probeDacs(DacMethods ** daclist); + +/* + * Internal functions (not meant for export, but no such mechanism in C) + */ +int __svgalib_setDacSpeed(int dacspeed, int defspeed); + +void __svgalib_Sierra_32K_savestate(unsigned char *regs); +void __svgalib_Sierra_32K_restorestate(const unsigned char *regs); + +#ifdef __OPTIMIZE__ +static __inline__ void _ramdac_dactocomm(void) +{ + port_in(PEL_IW); + port_in(PEL_MSK); + port_in(PEL_MSK); + port_in(PEL_MSK); + port_in(PEL_MSK); +} + +static __inline__ void _ramdac_dactopel(void) +{ + port_in(PEL_IW); +} + +static __inline__ unsigned char _ramdac_setcomm(unsigned char data) +{ + _ramdac_dactocomm(); + port_out_r(PEL_MSK, data); + _ramdac_dactocomm(); + return port_in(PEL_MSK); +} +#else +void _ramdac_dactocomm(void); +void _ramdac_dactopel(void); +unsigned char _ramdac_setcomm(unsigned char data); +#endif diff --git a/src/ramdac/s3dacs.c b/src/ramdac/s3dacs.c new file mode 100644 index 0000000..061847a --- /dev/null +++ b/src/ramdac/s3dacs.c @@ -0,0 +1,757 @@ +/* + * s3dacs.c: + * + * RAMDAC definitions for the S3-SDAC (86C716), S3-GENDAC, and Trio64. + * + * These contain S3-specific code. + */ + +#include +#include "libvga.h" +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +/* SDAC/GENDAC registers */ +#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC) +#define SDAC_COMMAND 0 /* Register offsets into state. */ +#define GENDAC_COMMAND 0 +#define SDAC_PLL_WRITEINDEX 1 +#define SDAC_PLL_READINDEX 2 +#define SDAC_PLL_M 3 /* f2 programmed clock */ +#define SDAC_PLL_N1_N2 4 +#define SDAC_PLL_CONTROL 5 + +#define SDAC_STATESIZE 6 /* 6 registers. */ +#define GENDAC_STATESIZE 6 +#endif + +#if defined(INCLUDE_S3_SDAC_DAC_TEST) || defined(INCLUDE_S3_GENDAC_DAC_TEST) +static int GENDAC_SDAC_probe(void) +{ +/* Taken from XFree86, accel/s3.c. */ +/* Return 1 if GENDAC found, 2 if SDAC, 0 otherwise. */ + /* probe for S3 GENDAC or SDAC */ + /* + * S3 GENDAC and SDAC have two fixed read only PLL clocks + * CLK0 f0: 25.255MHz M-byte 0x28 N-byte 0x61 + * CLK0 f1: 28.311MHz M-byte 0x3d N-byte 0x62 + * which can be used to detect GENDAC and SDAC since there is no chip-id + * for the GENDAC. + * + * NOTE: for the GENDAC on a MIRO 10SD (805+GENDAC) reading PLL values + * for CLK0 f0 and f1 always returns 0x7f (but is documented "read only") + */ + + unsigned char saveCR55, savelut[6]; + int i; + int clock01, clock23; + + saveCR55 = __svgalib_inCR(0x55); + __svgalib_outbCR(0x55, saveCR55 & ~1); + + port_out_r(0x3c7, 0); + for (i = 0; i < 2 * 3; i++) /* save first two LUT entries */ + savelut[i] = port_in(0x3c9); + port_out_r(0x3c8, 0); + for (i = 0; i < 2 * 3; i++) /* set first two LUT entries to zero */ + port_out_r(0x3c9, 0); + + __svgalib_outbCR(0x55, saveCR55 | 1); + + port_out_r(0x3c7, 0); + for (i = clock01 = 0; i < 4; i++) + clock01 = (clock01 << 8) | (port_in(0x3c9) & 0xff); + for (i = clock23 = 0; i < 4; i++) + clock23 = (clock23 << 8) | (port_in(0x3c9) & 0xff); + + __svgalib_outbCR(0x55, saveCR55 & ~1); + + port_out_r(0x3c8, 0); + for (i = 0; i < 2 * 3; i++) /* restore first two LUT entries */ + port_out_r(0x3c9, savelut[i]); + + __svgalib_outbCR(0x55, saveCR55); + + if (clock01 == 0x28613d62 || + (clock01 == 0x7f7f7f7f && clock23 != 0x7f7f7f7f)) { + + port_in(0x3c8); /* dactopel */ + + port_in(0x3c6); + port_in(0x3c6); + port_in(0x3c6); + + /* the forth read will show the SDAC chip ID and revision */ + if (((i = port_in(0x3c6)) & 0xf0) == 0x70) { + return 2; /* SDAC found. */ + } else { + return 1; /* GENDAC found. */ + } + port_in(0x3c8); /* dactopel */ + } + return 0; +} +#endif + +#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC) +static void GENDAC_SDAC_init(void) +{ + unsigned char val; + int m, n, n1, n2, MCLK; + val = __svgalib_inCR(0x55); + __svgalib_outbCR(0x55, val | 0x01); + + port_out_r(0x3C7, 10); /* Read MCLK. */ + m = port_in(0x3C9); + n = port_in(0x3C9); + + __svgalib_outbCR(0x55, val); /* Restore CR55. */ + + m &= 0x7f; + n1 = n & 0x1f; + n2 = (n >> 5) & 0x03; + /* Calculate MCLK in kHz. */ + MCLK = 14318 * (m + 2) / (n1 + 2) / (1 << n2); + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: S3-GENDAC/SDAC: MCLK = %d.%03d MHz\n", + MCLK / 1000, MCLK % 1000); +} +#endif + + +#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC) || defined(INCLUDE_S3_TRIO64_DAC) +/* + * From XFree86 common_hw/S3gendac.c and S3gendac.h. + * + * Progaming of the S3 gendac programable clocks, from the S3 Gendac + * programing documentation by S3 Inc. + * Jon Tombs + * + * Returns nonzero if success, 0 if failure. + */ +#define BASE_FREQ 14.31818 /* MHz */ + +#define DEBUG_FINDCLOCK 0 + +static int S3dacsFindClock(int freq_in, int min_n2, int freq_min, int freq_max, + int *best_m_out, int *best_n1_out, int *best_n2_out) +{ + double ffreq_in, ffreq_min, ffreq_max; + double ffreq_out, diff, best_diff; + unsigned int m; + unsigned char n1, n2; + unsigned char best_n1 = 16 + 2, best_n2 = 2, best_m = 125 + 2; + +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: Trying to match clock of %0.3f MHz\n", freq_in / 1000.0); +#endif + + ffreq_in = freq_in / 1000.0 / BASE_FREQ; + ffreq_min = freq_min / 1000.0 / BASE_FREQ; + ffreq_max = freq_max / 1000.0 / BASE_FREQ; + + /* Check if getting freq_in is possible at all */ + if (freq_in < freq_min / 8) { +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: %0.3f MHz is too low (lowest is %0.3f MHz)\n", + freq_in / 1000.0, freq_min / 1000.0 / 8); +#endif + return 0; + } + if (freq_in > freq_max / (1 << min_n2)) { +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: %0.3f MHz is too high (highest is %0.3f MHz)\n", + freq_in / 1000.0, freq_max / 1000.0 / (1 << min_n2)); +#endif + return 0; + } + + /* work out suitable timings */ + best_diff = ffreq_in; + for (n2 = min_n2; n2 <= 3; n2++) { + for (n1 = 1 + 2; n1 <= 31 + 2; n1++) { + m = (int) (ffreq_in * n1 * (1 << n2) + 0.5); + if (m < 1 + 2 || m > 127 + 2) + continue; + ffreq_out = (double) (m) / (double) (n1); + if ((ffreq_out >= ffreq_min) && (ffreq_out <= ffreq_max)) { + diff = ffreq_in - ffreq_out / (1 << n2); + if (diff < 0.0) + diff = -diff; + if (diff < best_diff) { + best_diff = diff; + best_m = m; + best_n1 = n1; + best_n2 = n2; + } + } + } + } + +#if DEBUG_FINDCLOCK + fprintf(stderr,"S3dacsFindClock: clock wanted %1.6f MHz, found %1.6f MHz (m %d, n1 %d, n2 %d)\n", + freq_in / 1000.0, + best_m / ((double) best_n1 * (1 << best_n2)) * BASE_FREQ, + best_m, best_n1, best_n2); +#endif + + *best_m_out = best_m; + *best_n1_out = best_n1; + *best_n2_out = best_n2; + + return 1; +} +#endif + +#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC) +static int GENDAC_SDAC_match_programmable_clock(int desiredclock) +{ + int min_m, min_n1, n2; + + /* Note: For ICS5342, min_n2 parameter should be one. */ + if (!S3dacsFindClock(desiredclock, 0, 100000, 250000, &min_m, &min_n1, &n2)) + return 0; + + return ((float) (min_m) / (float) (min_n1) / (1 << n2)) * BASE_FREQ * 1000; +} + +#if 0 /* Retained for reference. */ +static void setdacpll(reg, data1, data2) +int reg; +unsigned char data1; +unsigned char data2; +{ + unsigned char tmp, tmp1; + int vgaCRIndex = vgaIOBase + 4; + int vgaCRReg = vgaIOBase + 5; + + /* set RS2 via CR55, yuck */ + tmp = __svgalib_inCR(0x55) & 0xFC; + __svgalib_outCR(tmp | 0x01); + tmp1 = port_in(GENDAC_INDEX); + + port_out_r(GENDAC_INDEX, reg); + port_out_r(GENDAC_DATA, data1); + port_out_r(GENDAC_DATA, data2); + + /* Now clean up our mess */ + port_out_r(GENDAC_INDEX, tmp1); + __svgalib_outbCR(0x55, tmp); +} +#endif + +static void GENDAC_SDAC_initialize_clock_state(unsigned char *regs, int freq) +{ + int min_m, min_n1, n2; + int n, m; + + if (!S3dacsFindClock(freq, 0, 100000, 250000, &min_m, &min_n1, &n2)) { + fprintf(stderr,"Bad dot clock %0.3f MHz.\n", freq / 1000.0); + return; + } + + n = (min_n1 - 2) | (n2 << 5); + m = min_m - 2; + regs[SDAC_PLL_M] = m; + regs[SDAC_PLL_N1_N2] = n; + if (__svgalib_driver_report) + fprintf(stderr,"Initializing DAC PLL values; 0x%02X, 0x%02X.\n", m, n); +} + +static void GENDAC_SDAC_savestate(unsigned char *regs) +{ + unsigned char tmp; + tmp = __svgalib_inCR(0x55); + __svgalib_outbCR(0x55, tmp | 1); + + regs[SDAC_COMMAND] = port_in(0x3c6); + regs[SDAC_PLL_WRITEINDEX] = port_in(0x3c8); /* PLL write index */ + regs[SDAC_PLL_READINDEX] = port_in(0x3c7); /* PLL read index */ + port_out_r(0x3c7, 2); /* index to f2 reg */ + regs[SDAC_PLL_M] = port_in(0x3c9); /* f2 PLL M divider */ + regs[SDAC_PLL_N1_N2] = port_in(0x3c9); /* f2 PLL N1/N2 divider */ + port_out_r(0x3c7, 0x0e); /* index to PLL control */ + regs[SDAC_PLL_CONTROL] = port_in(0x3c9); /* PLL control */ + + __svgalib_outbCR(0x55, tmp & ~1); +} + +static void GENDAC_SDAC_restorestate(const unsigned char *regs) +{ + unsigned char tmp; + + /* set RS2 via CR55, yuck */ + tmp = __svgalib_inCR(0x55) & 0xFC; + __svgalib_outbCR(0x55, tmp | 0x01); + +#ifdef DEBUG + do { + int m, n1, n2, clk; + + m = regs[SDAC_PLL_M] & 0x7f; + n1 = regs[SDAC_PLL_N1_N2] & 0x1f; + n2 = (regs[SDAC_PLL_N1_N2] & 0x60) >> 5; + + clk = 14318 * (m + 2) / (n1 + 2) / (1 << n2); + fprintf(stderr,"SDAC.restorestate, setting clock 0x%02X 0x%02X (%d.%3dMHz)\n", + regs[SDAC_PLL_M], + regs[SDAC_PLL_N1_N2], clk / 1000, clk % 1000); + } while (0); +#endif + + port_out_r(0x3c6, regs[SDAC_COMMAND]); + port_out_r(0x3c8, 2); /* index to f2 reg */ + port_out_r(0x3c9, regs[SDAC_PLL_M]); /* f2 PLL M divider */ + port_out_r(0x3c9, regs[SDAC_PLL_N1_N2]); /* f2 PLL N1/N2 divider */ + port_out_r(0x3c8, 0x0e); /* index to PLL control */ + port_out_r(0x3c9, regs[SDAC_PLL_CONTROL]); /* PLL control */ + port_out_r(0x3c8, regs[SDAC_PLL_WRITEINDEX]); /* PLL write index */ + port_out_r(0x3c7, regs[SDAC_PLL_READINDEX]); /* PLL read index */ + + __svgalib_outbCR(0x55, tmp); +} + +#endif /* defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC) */ + +/* + * SDAC: 16-bit DAC, 110 MHz raw clock limit. + * + * The 135 MHz version supports pixel multiplexing in 8bpp modes with a + * halved raw clock. (SL: at least mine doesn't.) + */ + +#ifdef INCLUDE_S3_SDAC_DAC_TEST +static int SDAC_probe(void) +{ + return GENDAC_SDAC_probe() == 2; +} +#else +#define SDAC_probe 0 +#endif + +#ifdef INCLUDE_S3_SDAC_DAC +static int SDAC_map_clock(int bpp, int pixelclock) +{ + switch (bpp) { + case 4: + case 8: +#ifdef SDAC_8BPP_PIXMUX /* SL: AFAIK it doesn't work */ + if (pixelclock >= 67500) + /* Use pixel multiplexing. */ + return pixelclock / 2; +#endif + break; + case 24: + return pixelclock * 3 / 2; + case 32: + return pixelclock * 2; + } + return pixelclock; +} + +static int SDAC_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + switch (bpp) { + case 16: + return htiming * 2; + case 24: + return htiming * 3; + case 32: + return htiming * 4; + } + return htiming; +} + +static void SDAC_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + int pixmux; /* SDAC command register. */ + pixmux = 0; + switch (colormode) { + case CLUT8_6: +#ifdef SDAC_8BPP_PIXMUX + if (pixelclock >= 67500) + pixmux = 0x10; +#endif + break; + case RGB16_555: + pixmux = 0x30; + break; + case RGB16_565: + pixmux = 0x50; + break; + case RGB24_888_B: + /* Use 0x40 for 3 VCLK/pixel. Change SDAC_map_clock and CR67 as well. */ + pixmux = 0x90; + break; + case RGB32_888_B: + pixmux = 0x70; + break; + } + regs[SDAC_COMMAND] = pixmux; + GENDAC_SDAC_initialize_clock_state(regs, + SDAC_map_clock(bpp, pixelclock)); +} + +static void SDAC_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 110000); /* most can do 135MHz. */ + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed; + cardspecs->maxPixelClock24bpp = dacspeed * 2 / 3; + cardspecs->maxPixelClock32bpp = dacspeed / 2; + cardspecs->mapClock = SDAC_map_clock; + cardspecs->matchProgrammableClock = GENDAC_SDAC_match_programmable_clock; + cardspecs->mapHorizontalCrtc = SDAC_map_horizontal_crtc; + cardspecs->flags |= CLOCK_PROGRAMMABLE; +} + +DacMethods __svgalib_S3_SDAC_methods = +{ + S3_SDAC, + "S3-SDAC (86C716)", + DAC_HAS_PROGRAMMABLE_CLOCKS, + SDAC_probe, + GENDAC_SDAC_init, + SDAC_qualify_cardspecs, + GENDAC_SDAC_savestate, + GENDAC_SDAC_restorestate, + SDAC_initializestate, + SDAC_STATESIZE +}; +#endif + + +/* S3-GENDAC, 8-bit DAC. */ + +#ifdef INCLUDE_S3_GENDAC_DAC_TEST +static int GENDAC_probe(void) +{ + return GENDAC_SDAC_probe() == 1; +} +#else +#define GENDAC_probe 0 +#endif + +#ifdef INCLUDE_S3_GENDAC_DAC +static int GENDAC_map_clock(int bpp, int pixelclock) +{ + if (bpp == 16) + return pixelclock * 2; + if (bpp == 24) + return pixelclock * 3; + if (bpp == 32) + return pixelclock * 4; + return pixelclock; +} + +static int GENDAC_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + /* XXXX Not sure. */ + if (bpp == 24) + return htiming * 3; + if (bpp == 16) + return htiming * 2; + return htiming; +} + +static void GENDAC_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + int daccomm; /* DAC command register. */ + daccomm = 0; + if (colormode == RGB16_555) + daccomm = 0x20; + else if (colormode == RGB16_565) + daccomm = 0x60; + else if (colormode == RGB24_888_B) + daccomm = 0x40; + regs[GENDAC_COMMAND] = daccomm; + GENDAC_SDAC_initialize_clock_state(regs, + GENDAC_map_clock(bpp, pixelclock)); +} + +static void GENDAC_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 110000); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed / 2; + cardspecs->maxPixelClock24bpp = dacspeed / 3; + cardspecs->maxPixelClock32bpp = 0; + cardspecs->mapClock = GENDAC_map_clock; + cardspecs->matchProgrammableClock = GENDAC_SDAC_match_programmable_clock; + cardspecs->mapHorizontalCrtc = GENDAC_map_horizontal_crtc; + cardspecs->flags |= CLOCK_PROGRAMMABLE; +} + +DacMethods __svgalib_S3_GENDAC_methods = +{ + S3_GENDAC, + "S3-GENDAC (86C708)", + DAC_HAS_PROGRAMMABLE_CLOCKS, + GENDAC_probe, + GENDAC_SDAC_init, + GENDAC_qualify_cardspecs, + GENDAC_SDAC_savestate, + GENDAC_SDAC_restorestate, + GENDAC_initializestate, + GENDAC_STATESIZE +}; +#endif + + +#ifdef INCLUDE_S3_TRIO64_DAC +/* S3-Trio64, 16-bit integrated DAC. */ + +#define TRIO64_SR15 0 +#define TRIO64_SR18 1 +#define TRIO64_PLL_N1_N2 2 +#define TRIO64_PLL_M 3 +#define TRIO64_CR67 4 +#define TRIO64_SRB 5 +#define TRIO64_STATESIZE 6 + +/* Note: s3.c also defines CR67, but doesn't use it for the Trio64. */ + +extern int __svgalib_s3_s3Mclk; + +static int Trio64_get_mclk(void) +{ + unsigned char sr8; + int m, n, n1, n2; + + port_out_r(0x3c4, 0x08); + sr8 = port_in(0x3c5); + port_out_r(0x3c5, 0x06); + + port_out_r(0x3c4, 0x11); + m = port_in(0x3c5); + port_out_r(0x3c4, 0x10); + n = port_in(0x3c5); + + port_out_r(0x3c4, 0x08); + port_out_r(0x3c5, sr8); + + m &= 0x7f; + n1 = n & 0x1f; + n2 = (n >> 5) & 0x03; + /* Calculate MCLK in kHz. */ + return ((1431818 * (m + 2)) / (n1 + 2) / (1 << n2) + 50) / 100; +} + +#if 0 +static void Trio64_set_mclk(int khz) +/* Doesn't work. Locks computer up. Why? */ +{ + int sr8; + int min_m, min_n1, n2; + + if (!S3dacsFindClock(khz, 0, 40000, 70000, &min_m, &min_n1, &n2)) { + fprintf(stderr,"Bad MCLK %0.3f MHz.\n", khz / 1000.0); + return; + } + + fprintf(stderr,"%0.3f MHz MCLK, m = %d, n = %d, r = %d\n", khz / 1000.0, min_m - 2, min_n1 - 2, n2); + port_out_r(0x3C4, 0x08); + sr8 = port_in(0x3C5); + port_out_r(0x3C5, 0x06); /* Unlock. */ + + port_out_r(0x3c4, 0x15); + port_out_r(0x3c5, port_in(0x3c5) & ~0x20); + + /* MCLK. */ + __svgalib_outSR(0x10, (min_n1 - 2) | (n2 << 5)); + __svgalib_outSR(0x11, min_m - 2); + + port_out_r(0x3c4, 0x15); + port_out_r(0x3c5, port_in(0x3c5) | 0x20); + port_out_r(0x3c5, port_in(0x3c5) & ~0x20); + + __svgalib_outSR(0x08, sr8); +} +#endif + +static void Trio64_init(void) +{ + int mclk; + + mclk = Trio64_get_mclk(); + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: RAMDAC: Trio64: MCLK = %0.3f MHz\n", + mclk / 1000.0); + __svgalib_s3_s3Mclk = mclk; +} + +static int Trio64_map_clock(int bpp, int pixelclock) +{ + if (bpp == 8 && pixelclock >= 67500) /* use pixel doubling */ + return pixelclock / 2; + if (bpp == 24) + return pixelclock * 3; + return pixelclock; +} + +static int Trio64_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + if (bpp == 16) + return htiming * 2; + /* Normal mapping for 8bpp and 32bpp. */ + return htiming; +} + +static void Trio64_initialize_clock_state(unsigned char *regs, int freq) +{ + int min_m, min_n1, n2; + int n, m; + + if (!S3dacsFindClock(freq, 0, 130000, 270000, &min_m, &min_n1, &n2)) { + fprintf(stderr,"Bad dot clock %0.3f MHz.\n", freq / 1000.0); + return; + } + + n = (min_n1 - 2) | (n2 << 5); + m = min_m - 2; + regs[TRIO64_PLL_M] = m; + regs[TRIO64_PLL_N1_N2] = n; +} + +static int Trio64_match_programmable_clock(int desiredclock) +{ + int min_m, min_n1, n2; + + if (!S3dacsFindClock(desiredclock, 0, 130000, 270000, &min_m, &min_n1, &n2)) + return 0; + + return ((float) (min_m) / (float) (min_n1) / (1 << n2)) * BASE_FREQ * 1000; +} + +static void Trio64_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + int pixmux, reserved_CR67_1; + + regs[TRIO64_SR15] &= ~0x50; + regs[TRIO64_SR18] &= ~0x80; + pixmux = 0; + reserved_CR67_1 = 0; + if (bpp == 8 && pixelclock >= 67500) { + pixmux = 0x10; + reserved_CR67_1 = 2; + regs[TRIO64_SR15] |= 0x50; + regs[TRIO64_SR18] |= 0x80; + } else if (bpp == 16) { + /* moderegs[S3_CR33] |= 0x08; *//* done in s3.c. */ + if (colormode == RGB16_555) + pixmux = 0x30; + else + pixmux = 0x50; + reserved_CR67_1 = 2; + } else if (colormode == RGB24_888_B) { + /* remember to adjust SRB as well. */ + pixmux = 0x00; + } else if (colormode == RGB32_888_B) { + pixmux = 0xD0; /* 32-bit color, 2 VCLKs/pixel. */ + reserved_CR67_1 = 2; + } + regs[TRIO64_CR67] = pixmux | reserved_CR67_1; + + Trio64_initialize_clock_state(regs, pixelclock); +} + +static void Trio64_savestate(unsigned char *regs) +{ + unsigned char sr8; + port_out_r(0x3C4, 0x08); + sr8 = port_in(0x3C5); + port_out_r(0x3C5, 0x06); /* Unlock. */ + + regs[TRIO64_SR15] = __svgalib_inSR(0x15); + regs[TRIO64_SR18] = __svgalib_inSR(0x18); + regs[TRIO64_PLL_N1_N2] = __svgalib_inSR(0x12); + regs[TRIO64_PLL_M] = __svgalib_inSR(0x13); + regs[TRIO64_CR67] = __svgalib_inCR(0x67); + + __svgalib_outSR(0x08, sr8); +} + +static void Trio64_restorestate(const unsigned char *regs) +{ + unsigned char sr8, tmp; + + port_out_r(0x3C4, 0x08); + sr8 = port_in(0x3C5); + port_out_r(0x3C5, 0x06); /* Unlock. */ + + __svgalib_outCR(0x67, regs[TRIO64_CR67]); + + __svgalib_outSR(0x15, regs[TRIO64_SR15]); + __svgalib_outSR(0x18, regs[TRIO64_SR18]); + + /* Clock. */ + __svgalib_outSR(0x12, regs[TRIO64_PLL_N1_N2]); + __svgalib_outSR(0x13, regs[TRIO64_PLL_M]); + +#if 0 + /* + * XFree86 XF86_S3 (common_hw/gendac.c) has this, but it looks + * incorrect, it should flip the bit by writing to 0x3c5, not + * 0x3c4. + */ + port_out_r(0x3c4, 0x15); + tmp = port_in(0x3c5); + port_out_r(0x3c4, tmp & ~0x20); + port_out_r(0x3c4, tmp | 0x20); + port_out_r(0x3c4, tmp & ~0x20); +#else + port_out_r(0x3c4, 0x15); + tmp = port_in(0x3c5); + port_out_r(0x3c5, tmp & ~0x20); + port_out_r(0x3c5, tmp | 0x20); + port_out_r(0x3c5, tmp & ~0x20); +#endif + + __svgalib_outSR(0x08, sr8); +} + + +static void Trio64_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + if (dacspeed) { + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: using 'dacspeed' not recommended for this RAMDAC.\n"); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = 135000; + cardspecs->maxPixelClock16bpp = dacspeed; + cardspecs->maxPixelClock24bpp = 0; /* dacspeed / 3; *//* How to program? */ + cardspecs->maxPixelClock32bpp = 50000; + } else { + cardspecs->maxPixelClock4bpp = 80000; + cardspecs->maxPixelClock8bpp = 135000; + cardspecs->maxPixelClock16bpp = 80000; + cardspecs->maxPixelClock24bpp = 0; /* 25000; *//* How to program? */ + cardspecs->maxPixelClock32bpp = 50000; + } + cardspecs->mapClock = Trio64_map_clock; + cardspecs->matchProgrammableClock = Trio64_match_programmable_clock; + cardspecs->mapHorizontalCrtc = Trio64_map_horizontal_crtc; + cardspecs->flags |= CLOCK_PROGRAMMABLE; +} + +DacMethods __svgalib_Trio64_methods = +{ + TRIO64, + "S3-Trio64 internal DAC", + DAC_HAS_PROGRAMMABLE_CLOCKS, + NULL, /* probe */ + Trio64_init, + Trio64_qualify_cardspecs, + Trio64_savestate, + Trio64_restorestate, + Trio64_initializestate, + TRIO64_STATESIZE +}; +#endif diff --git a/src/ramdac/sierra.c b/src/ramdac/sierra.c new file mode 100644 index 0000000..dd0bbbc --- /dev/null +++ b/src/ramdac/sierra.c @@ -0,0 +1,368 @@ +/* + * sierra.c: + * + * RAMDAC definition for basic Sierra, SC15025 and SC1148x. + */ + +#include +#include +#include "libvga.h" + +#include "timing.h" +#include "vgaregs.h" +#include "driver.h" /* for __svgalib_driver_report */ +#include "ramdac.h" + +/* + * RAMDAC definition for basic Sierra-type DAC + * that can do 32K (5-5-5) color mode (16bpp) with doubled VCLK. + * A value of 0x80 is written to the Hidden DAC register for this mode. + */ + +#ifdef INCLUDE_SIERRA_DAC_TEST +static int Sierra_32K_probe(void) +{ + /* Should return 1 for any Sierra-type DAC. */ + return 0; +} +#else +#define Sierra_32K_probe 0 +#endif + +#ifdef INCLUDE_SIERRA_DAC +static void Sierra_32K_init(void) +{ + /* Should probe the exact DAC type. */ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using Sierra 32K DAC.\n"); +} + +static int Sierra_32K_map_clock(int bpp, int pixelclock) +{ + if (bpp == 16) + return pixelclock * 2; + return pixelclock; +} + +static int Sierra_32K_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + if (bpp == 16) + return htiming * 2; + return htiming; +} +#endif + +#if defined(INCLUDE_SIERRA_DAC) || defined(INCLUDE_ICW_DAC) || \ + defined(INCLUDE_ATT20C490_DAC) || defined(INCLUDE_ATT20C498_DAC) +void __svgalib_Sierra_32K_savestate(unsigned char *regs) +{ + _ramdac_dactocomm(); + regs[0] = port_in(PEL_MSK); +} + +void __svgalib_Sierra_32K_restorestate(const unsigned char *regs) +{ + _ramdac_dactocomm(); + port_out_r(PEL_MSK, regs[0]); +} + +#endif + +#ifdef INCLUDE_SIERRA_DAC +static void Sierra_32K_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + regs[0] = 0; + if (colormode == RGB16_555) + regs[0] = 0x80; +} + +static void Sierra_32K_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 80000); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed / 2; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 0; + cardspecs->mapClock = Sierra_32K_map_clock; + cardspecs->mapHorizontalCrtc = Sierra_32K_map_horizontal_crtc; + cardspecs->flags |= NO_RGB16_565; +} + +DacMethods __svgalib_Sierra_32K_methods = +{ + SIERRA_32K, + "Sierra 32K colors VGA DAC", + 0, + Sierra_32K_probe, + Sierra_32K_init, + Sierra_32K_qualify_cardspecs, + __svgalib_Sierra_32K_savestate, + __svgalib_Sierra_32K_restorestate, + Sierra_32K_initializestate, + 1 /* State size. */ +}; +#endif + + +/* + * RAMDAC definition for Sierra 15025/26 + */ + +#ifdef INCLUDE_SC15025_DAC_TEST +static unsigned char SC15025_Rev; + +static int SC15025_probe(void) +{ + unsigned char c, id[4]; + int i, flag = 0; + + _ramdac_dactocomm(); + c = port_in(PEL_MSK); + _ramdac_setcomm(c | 0x10); + for (i = 0; i < 4; i++) { + port_out_r(PEL_IR, 0x9 + i); + id[i] = port_in(PEL_IW); + } + _ramdac_setcomm(c); + _ramdac_dactopel(); + if (id[0] == 'S' && /* Sierra */ + ((id[1] << 8) | id[2]) == 15025) { /* unique for the SC 15025/26 */ + flag = 1; + SC15025_Rev = id[3]; + } + return flag; +} +#else +#define SC15025_probe 0 +#define SC15025_Rev ' ' +#endif + +#ifdef INCLUDE_SC15025_DAC +static void SC15025_init(void) +{ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using Sierra 15025/26%c truecolor DAC.\n", SC15025_Rev); +} + +static void SC15025_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + regs[0] = 0; + regs[1] = 0; + regs[2] = 0; + if (colormode == RGB16_555) { + regs[0] = 0x80; + regs[1] = 1; + } else if (colormode == RGB16_565) { + regs[0] = 0xC0; + regs[1] = 1; + } else if (colormode == RGB32_888_B) { + regs[0] = 0x40; + regs[1] = 1; + regs[2] = 1; + } + /* ARI: FIXME: regs[1] should be 1 for CLUT8_8 */ + /* also: OR 8 to regs[0] to enable gamma correction */ +} + +static void SC15025_savestate(unsigned char *regs) +{ + _ramdac_dactocomm(); + regs[0] = port_in(PEL_MSK); + _ramdac_setcomm(regs[0] | 0x10); + _ramdac_dactocomm(); + port_out_r(PEL_IR, 8); + regs[1] = port_in(PEL_IW); /* Aux control */ + port_out_r(PEL_IR, 16); + regs[2] = port_in(PEL_IW); /* Pixel Repack */ + _ramdac_setcomm(regs[0]); +} + +static void SC15025_restorestate(const unsigned char *regs) +{ + unsigned char c; + + _ramdac_dactocomm(); + c = port_in(PEL_MSK); + _ramdac_setcomm(c | 0x10); + _ramdac_dactocomm(); + port_out_r(PEL_IR, 8); + port_out_r(PEL_IW, regs[1]); /* Aux control */ + port_out_r(PEL_IR, 16); + port_out_r(PEL_IW, regs[2]); /* Pixel Repack */ + _ramdac_setcomm(c); + _ramdac_setcomm(regs[0]); +} + +static int SC15025_map_clock(int bpp, int pixelclock) +{ + if (bpp == 32) + return pixelclock * 2; + return pixelclock; +} + +static int SC15025_map_horizontal_crtc(int bpp, int pixelclock, int htiming) +{ + if (bpp == 16) + return htiming * 2; + if (bpp == 32) + return htiming * 4; + return htiming; +} + +static void SC15025_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 110000); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed / 2; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = dacspeed / 3; + cardspecs->mapClock = SC15025_map_clock; + cardspecs->mapHorizontalCrtc = SC15025_map_horizontal_crtc; +} + +DacMethods __svgalib_SC15025_methods = +{ + SIERRA_15025, + "Sierra SC15025/6 DAC", + 0, + SC15025_probe, + SC15025_init, + SC15025_qualify_cardspecs, + SC15025_savestate, + SC15025_restorestate, + SC15025_initializestate, + 3 /* State size. */ +}; +#endif + +/* + * RAMDAC definition for Sierra 1148x Series. + * 11482, 83, and 84 (Mark 2) can do 32K (5-5-5) color mode (16bpp). + * 11485, 87, and 89 (Mark 3) additionally can do 64K (5-6-5) color mode, + * but are not autodetected since they cannot be distinguished from Mark 2. + * 11486 really is a Sierra 32K dac, and should have been set by user. + * + * Note that these dacs are different from 'Sierra 32K', since they can be + * detected as such, while there are clones that work compatible to the + * Sierra dacs, but cannot be autodetected. To avoid such dacs to fail + * the type 'Sierra 32K' still refers to them, while this new type + * 'SC1148x Series' refers to original Sierra dacs. + * + * ATTENTION: THIS TEST MUST BE LAST IN CHAIN, SINCE MANY BETTER DACS + * IMPLEMENT 32K MODES COMPATIBLE TO THIS ONE AND WOULD BE DETECTED AS + * SIERRA! + * + */ + +#ifdef INCLUDE_SC1148X_DAC_TEST +static int SC1148X_probe(void) +{ + unsigned char oc, op, tmp, tmp2; + int flag = 0; + + _ramdac_dactopel(); + tmp = port_in(PEL_MSK); + do { + tmp2 = tmp; + tmp = port_in(PEL_MSK); + } while (tmp2 != tmp); + port_in(PEL_IW); + port_in(PEL_MSK); + port_in(PEL_MSK); + port_in(PEL_MSK); + for (tmp2 = 9; tmp != 0x8E && tmp2 > 0; tmp2--) + tmp = port_in(PEL_MSK); + if (tmp != 0x8E) { + _ramdac_dactocomm(); + oc = port_in(PEL_MSK); + _ramdac_dactopel(); + op = port_in(PEL_MSK); + tmp = oc ^ 0xFF; + port_out_r(PEL_MSK, tmp); + _ramdac_dactocomm(); + tmp2 = port_in(PEL_MSK); + if (tmp2 != tmp) { + tmp = _ramdac_setcomm(tmp = oc ^ 0x60); + if ((tmp & 0xe0) == (tmp2 & 0xe0)) { + tmp = port_in(PEL_MSK); + _ramdac_dactopel(); + if (tmp != port_in(PEL_MSK)) + flag = 1; /* Sierra Mark 2 or 3 */ + } else { + /* We have a Sierra SC11486 */ +#ifdef INCLUDE_SIERRA_DAC + flag = 1; + /* We do some ugly trickery here to patch SC1148X Series + descriptor with values from Sierra 32K descriptor, since + this is what whe really have detected! */ + __svgalib_SC1148X_methods.id = SIERRA_32K; + __svgalib_SC1148X_methods.name = __svgalib_Sierra_32K_methods.name; + __svgalib_SC1148X_methods.initialize = __svgalib_Sierra_32K_methods.initialize; + __svgalib_SC1148X_methods.qualifyCardSpecs = __svgalib_Sierra_32K_methods.qualifyCardSpecs ; + __svgalib_SC1148X_methods.initializeState = __svgalib_Sierra_32K_methods.initializeState ; +#endif + } + _ramdac_dactocomm(); + port_out_r(PEL_MSK, oc); + } + _ramdac_dactopel(); + port_out_r(PEL_MSK, op); + } else { + _ramdac_dactopel(); + /* Diamond SS2410 */ + } + return flag; +} +#else +#define SC1148x_probe 0 +#endif + +#ifdef INCLUDE_SC1148X_DAC +static void SC1148X_init(void) +{ + if (__svgalib_driver_report) + fprintf(stderr,"svgalib: Using Sierra 1148x series 32K DAC.\n"); +} + +static void SC1148X_initializestate(unsigned char *regs, int bpp, int colormode, + int pixelclock) +{ + regs[0] = 0; + if (colormode == RGB16_555) + regs[0] = 0xA0; + /* Mark 3 (not autodetected) */ + else if (colormode == RGB16_565) + regs[0] = 0xE0; +} + +static void SC1148X_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed) +{ + dacspeed = __svgalib_setDacSpeed(dacspeed, 110000); + cardspecs->maxPixelClock4bpp = dacspeed; + cardspecs->maxPixelClock8bpp = dacspeed; + cardspecs->maxPixelClock16bpp = dacspeed / 2; + cardspecs->maxPixelClock24bpp = 0; + cardspecs->maxPixelClock32bpp = 0; + cardspecs->mapClock = Sierra_32K_map_clock; + cardspecs->mapHorizontalCrtc = Sierra_32K_map_horizontal_crtc; + cardspecs->flags |= NO_RGB16_565; /* Mark 3 (11485,87, and higher) can */ +} + +DacMethods __svgalib_SC1148X_methods = +{ + SIERRA_1148X, + "Sierra SC1148x series 32K colors VGA DAC", + 0, + SC1148X_probe, + SC1148X_init, + SC1148X_qualify_cardspecs, + __svgalib_Sierra_32K_savestate, + __svgalib_Sierra_32K_restorestate, + SC1148X_initializestate, + 1 /* State size. */ +}; +#endif diff --git a/src/regextr.c b/src/regextr.c new file mode 100644 index 0000000..ac38c71 --- /dev/null +++ b/src/regextr.c @@ -0,0 +1,516 @@ +/* + ** regextr.c - extract graphics modes and register information + ** from C source file + ** + ** This file is part of SVGALIB (C) 1993 by Tommy Frandsen and + ** Harm Hanemaayer + ** + ** Copyright (C) 1993 by Hartmut Schirmer + ** + */ + +#include +#include +#include +#include + +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +#ifndef FALSE +#define FALSE (1==0) +#endif +#ifndef TRUE +#define TRUE (1==1) +#endif + +#define WordLen 100 +typedef char WordStr[WordLen]; + +typedef struct ML { + WordStr x, y, c; + int mnum; + int equ; + void *regs; + struct ML *nxt; +} ModeList; + +static void * + Malloc(size_t bytes) +{ + void *res; + + res = (void *) malloc(bytes); + if (res == NULL) { + fprintf(stderr, "regextr.c: Can't allocate memory\n"); + exit(1); + } + return res; +} + +static void store_equ(ModeList ** root, char *x1, char *y1, char *c1, + int mnum, char *x2, char *y2, char *c2) +{ + ModeList *p; + + p = *root; + while (p != NULL) { + if (strcmp(p->x, x1) == 0 + && strcmp(p->y, y1) == 0 + && strcmp(p->c, c1) == 0) { + fprintf(stderr, "regextr.c: Duplicate g%sx%sx%s_regs !\n", x1, y1, c1); + exit(1); + } + p = p->nxt; + } + p = (ModeList *) Malloc(sizeof(ModeList)); + strcpy(p->x, x1); + strcpy(p->y, y1); + strcpy(p->c, c1); + p->mnum = mnum; + p->equ = TRUE; + p->nxt = *root; + *root = p; + p = (ModeList *) Malloc(sizeof(ModeList)); + strcpy(p->x, x2); + strcpy(p->y, y2); + strcpy(p->c, c2); + p->mnum = 0; + p->equ = FALSE; + p->regs = NULL; + p->nxt = NULL; + (*root)->regs = (void *) p; +} + +static int check_new_mode(ModeList * p, char *x, char *y, char *c) +{ + while (p != NULL) { + if (strcmp(p->x, x) == 0 + && strcmp(p->y, y) == 0 + && strcmp(p->c, c) == 0) + return FALSE; + p = p->nxt; + } + return TRUE; +} + +static void store_regs(ModeList ** root, char *x, char *y, char *c, int mnum, const unsigned char *r) +{ + ModeList *p; + + if (!check_new_mode(*root, x, y, c)) { + fprintf(stderr, "regextr.c: Duplicate g%sx%sx%s_regs !\n", x, y, c); + exit(1); + } + p = (ModeList *) Malloc(sizeof(ModeList)); + strcpy(p->x, x); + strcpy(p->y, y); + strcpy(p->c, c); + p->mnum = mnum; + p->equ = FALSE; + p->regs = (void *) r; + p->nxt = *root; + *root = p; +} + + +static void __store_regs(ModeList ** root, int mnum, const char *r) +{ + WordStr x, y, c; + + sprintf(x, "%d", infotable[mnum].xdim); + sprintf(y, "%d", infotable[mnum].ydim); + switch (infotable[mnum].colors) { + case 1 << 15: + strcpy(c, "32K"); + break; + case 1 << 16: + strcpy(c, "64K"); + break; + case 1 << 24: + strcpy(c, "16M"); + break; + default: + sprintf(c, "%d", infotable[mnum].colors); + } + if (check_new_mode(*root, x, y, c)) + store_regs(root, x, y, c, mnum, r); +} + + +static char * + mode2name(char *x, char *y, char *c) +{ + static char mn[WordLen]; + + sprintf(mn, "G%sx%sx%s", x, y, c); + return mn; +} + +/* -------------------------------------- Scanner --- */ +static int get_nextchar(FILE * inp) +{ + int nch; + + nch = fgetc(inp); + if (nch == '\\') { + int nnch; + nnch = fgetc(inp); + if (nnch == '\n') + return ' '; + ungetc(nnch, inp); + } + if (isspace(nch)) + return ' '; + return nch; +} + +static int next_ch = ' '; + +static int get_char(FILE * inp) +{ + int ch; + + do { + ch = next_ch; + do + next_ch = get_nextchar(inp); + while (ch == ' ' && next_ch == ' '); + if (ch != '/' || next_ch != '*') + return ch; + do { + ch = next_ch; + next_ch = get_nextchar(inp); + } + while (ch != EOF && !(ch == '*' && next_ch == '/')); + next_ch = get_nextchar(inp); + } + while (1); +} + +static char * + get_word(FILE * inp) +{ + int ch; + static char buf[1000]; + char *p; + + do + ch = get_char(inp); + while (ch == ' '); + p = buf; + switch (ch) { + case '[': + case ']': + case '{': + case '}': + case ',': + case ';': + case '=': + case '(': + case ')': + *(p++) = ch; + *p = '\0'; + return buf; + case EOF: + buf[0] = '\0'; + return buf; + } + for (;;) { + *(p++) = ch; + switch (next_ch) { + case EOF: + case '[': + case ']': + case '{': + case '}': + case ',': + case ';': + case '=': + case '(': + case ')': + case ' ': + *p = '\0'; + return buf; + } + ch = get_char(inp); + } +} + +/* ----------------------------------------------- parser -- */ +static int is_res(char *rp, char *x, char *y, char *c, int *mnum) +{ + char *p; + + if (*(rp++) != 'g') + return FALSE; + /* X resolution */ + p = x; + if (!isdigit(*rp)) + return FALSE; + *(p++) = *(rp++); + if (!isdigit(*rp)) + return FALSE; + *(p++) = *(rp++); + if (!isdigit(*rp)) + return FALSE; + *(p++) = *(rp++); + if (isdigit(*rp)) + *(p++) = *(rp++); + if (*(rp++) != 'x') + return FALSE; + *p = '\0'; + + /* Y resolution */ + p = y; + if (!isdigit(*rp)) + return FALSE; + *(p++) = *(rp++); + if (!isdigit(*rp)) + return FALSE; + *(p++) = *(rp++); + if (!isdigit(*rp)) + return FALSE; + *(p++) = *(rp++); + if (isdigit(*rp)) + *(p++) = *(rp++); + if (*(rp++) != 'x') + return FALSE; + *p = '\0'; + + /* colors */ + p = c; + *(p++) = *rp; + switch (*(rp++)) { + case '1': + *(p++) = *rp; + if (*(rp++) != '6') + return FALSE; + if (*rp == 'M') + *(p++) = *(rp++); + break; + case '2': + if (*rp == '5' && *(rp + 1) == '6') { + *(p++) = *(rp++); + *(p++) = *(rp++); + } + break; + case '3': + if (*rp != '2') + return FALSE; + *(p++) = *(rp++); + if (*rp != 'k' && *rp != 'K') + return FALSE; + *(p++) = 'K'; + ++rp; + break; + case '6': + if (*rp != '4') + return FALSE; + *(p++) = *(rp++); + if (*rp != 'k' && *rp != 'K') + return FALSE; + *(p++) = 'K'; + ++rp; + break; + default: + return FALSE; + } + *p = '\0'; + *mnum = __svgalib_name2number(mode2name(x, y, c)); + if (*mnum < 0) { + int cols = 0; + int xbytes = 0; + + if (strcmp("16M", c) == 0) { + cols = 1 << 24; + xbytes = atoi(x) * 3; + } else if (strcmp("32K", c) == 0) { + cols = 1 << 15; + xbytes = atoi(x) * 2; + } else if (strcmp("64K", c) == 0) { + cols = 1 << 16; + xbytes = atoi(x) * 2; + } else if (strcmp("256", c) == 0) { + cols = 256; + xbytes = atoi(x); + } else if (strcmp("16", c) == 0) { + cols = 16; + xbytes = atoi(x) / 4; + } else + return FALSE; + *mnum = __svgalib_addmode(atoi(x), atoi(y), cols, xbytes, xbytes / atoi(x)); + } + return (*mnum > TEXT && *mnum != GPLANE16); +} + +static int read_regs(FILE * inp, unsigned char **regs) +{ + unsigned char r[MAX_REGS]; + char *w; + int c; + unsigned u; + + if (strcmp("[", get_word(inp)) != 0) + return 0; + if (strcmp("]", get_word(inp)) != 0) + if (strcmp("]", get_word(inp)) != 0) + return 0; + if (strcmp("=", get_word(inp)) != 0) + return 0; + if (strcmp("{", get_word(inp)) != 0) + return 0; + + c = 0; + do { + w = get_word(inp); + if (strcmp(w, "}") == 0) + continue; + if (sscanf(w, "%x", &u) == EOF) + if (sscanf(w, "%u", &u) == EOF) { + fprintf(stderr, "regextr.c: Invalid register value %s\n", w); + exit(1); + } + r[c++] = u; + w = get_word(inp); + } + while (strcmp(",", w) == 0); + *regs = (unsigned char *) Malloc(c); + memcpy(*regs, r, c); + return c; +} + + +void __svgalib_readmodes(FILE * inp, ModeTable ** mt, int *dac, unsigned *clocks) +{ + WordStr x1, y1, c1, x2, y2, c2; + WordStr w1, w2; + int mnum1, mnum2; + ModeList *modes = NULL; + ModeList *p, *q, *cmp; + int regs_count = -1; + int change; + int mode_cnt, i; + + /* read the register information from file */ + while (!feof(inp)) { + char *wp; + + wp = get_word(inp); + if (strcmp(wp, "#define") == 0) { + strcpy(w1, get_word(inp)); + strcpy(w2, get_word(inp)); + if (clocks != NULL && strcmp(w1, "CLOCK_VALUES") == 0) { + unsigned freq; + + if (strcmp(w2, "{") == 0) { + do { + strcpy(w2, get_word(inp)); + if (sscanf(w2, "%u", &freq) == EOF) + if (sscanf(w2, "%x", &freq) == EOF) { + fprintf(stderr, "regextr.c: Invalid clock definition (%s)\n", w2); + exit(1); + } + *(clocks++) = freq; + strcpy(w1, get_word(inp)); + } + while (strcmp(",", w1) == 0); + clocks = NULL; + } + } else if (dac != NULL && strcmp(w1, "DAC_TYPE") == 0) { + int new_dac; + + if (sscanf(w2, "%d", &new_dac) == EOF) + if (sscanf(w2, "%x", &new_dac) == EOF) { + fprintf(stderr, "regextr.c: Invalid dac definition (%s)\n", w2); + exit(1); + } + *dac = new_dac; + } else if (is_res(w1, x1, y1, c1, &mnum1)) { + if (is_res(w2, x2, y2, c2, &mnum2)) + store_equ(&modes, x1, y1, c1, mnum1, x2, y2, c2); + else if (strcmp(w2, "DISABLE_MODE") == 0) + store_regs(&modes, x1, y1, c1, mnum1, DISABLE_MODE); + } + } else if (strcmp(wp, "char") == 0) { + strcpy(w1, get_word(inp)); + if (is_res(w1, x1, y1, c1, &mnum1)) { + unsigned char *regs; + int rv; + + rv = read_regs(inp, ®s); + if (rv == 0) + continue; + if (regs_count > 0 && rv != regs_count) { + fprintf(stderr, "regextr.c: Expected %d register values in %s, found %d\n", + regs_count, w1, rv); + exit(1); + } + regs_count = rv; + store_regs(&modes, x1, y1, c1, mnum1, regs); + } + } + } + /* resolve all equates */ + do { + change = FALSE; + p = modes; + while (p != NULL) { + if (p->equ) { + q = modes; + cmp = (ModeList *) p->regs; + while (q != NULL) { + if (!q->equ && + !strcmp(q->x, cmp->x) && + !strcmp(q->y, cmp->y) && + !strcmp(q->c, cmp->c)) { + free(p->regs); + p->regs = q->regs; + p->equ = FALSE; + change = TRUE; + break; + } + q = q->nxt; + } + } + p = p->nxt; + } + } + while (change); + /* Store modes from *mt */ + if (*mt != NULL) + while ((*mt)->regs != NULL) { + __store_regs(&modes, (*mt)->mode_number, (*mt)->regs); + (*mt)++; + } + /* Check equates, count modes */ + mode_cnt = 0; + p = modes; + while (p != NULL) { + if (p->equ) { + fprintf(stderr, "regextr.c: Unresolved equate (%sx%sx%s)\n", p->x, p->y, p->c); + exit(1); + } + p = p->nxt; + ++mode_cnt; + } + ++mode_cnt; + /* Now generate the mode table */ + *mt = (ModeTable *) Malloc(mode_cnt * sizeof(ModeTable)); + i = 0; + p = modes; + while (p != NULL) { + + DPRINTF("Found mode %2d: %s\n", p->mnum, mode2name(p->x, p->y, p->c)); + + (*mt)[i].mode_number = p->mnum; + (*mt)[i].regs = p->regs; + q = p; + p = p->nxt; + free(q); + ++i; + } + (*mt)[i].mode_number = 0; + (*mt)[i].regs = NULL; +} diff --git a/src/regs/ali.regs b/src/regs/ali.regs new file mode 100644 index 0000000..b288bac --- /dev/null +++ b/src/regs/ali.regs @@ -0,0 +1,856 @@ +#if 0 +/* old regsets */ +static const unsigned char g640x480x256_regs[69] = +{ + 0x5F, 0x4F, 0x52, 0x9f, 0x53, 0x1f, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x40, 0xE7, 0x04, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x00, 0x01, 0x14, 0x02, 0x03, 0x00 +}; + +static const unsigned char g800x600x256_regs[69] = +{ + 0x7C, 0x63, 0x64, 0x9F, 0x6A, 0x93, 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x59, 0x8B, 0x57, 0x32, 0x40, 0x58, 0x6F, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xEF, + 0x02, 0x90, 0x00, 0x00, 0x01, 0x14, 0x02, 0x05, 0x00 +}; + +static const unsigned char g1024x768x256_regs[69] = +{ + 0xA4, 0x7F, 0x80, 0x80, 0x86, 0x00, 0x26, 0xFD, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x2A, 0xFF, 0x40, 0x40, 0x04, 0x20, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x00, 0x00, 0x34, 0x02, 0x04, 0x00 +}; + +static const unsigned char g640x480x16M_regs[69] = +{ + /* CRT 3d4 */ + 0x27, 0xEF, 0xF2, 0x88, 0xF8, 0x9B, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x80, 0x40, 0xE7, 0x04, 0xA3, + /* ATT 3c0 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + /* GRA 3ce */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + /* SEQ 3c4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + /* MIS 3c2/3cc w/r */ + 0xE3, + /* EXT= + 3d4/19 3d4/1a 3d4/28 3d4/2a 3ce/0b 3ce/0c 3c6 3d6 3d7 */ + 0x82, 0x90, 0x00, 0x01, 0x00, 0x31, 0x82, 0x02, 0x00 +}; + +#endif + +/* BIOS mode 0x100 */ +static const unsigned char g640x400x256_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x20, 0x01, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x101 */ +static const unsigned char g640x480x256_regs[69] = +{ + 0x60, 0x4F, 0x54, 0x9F, 0x53, 0x1F, 0x0A, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE7, 0x89, 0xDF, 0x28, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x20, 0x01, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x102 */ +/* !!! xbytes=100 */ +static const unsigned char g800x600x16_regs[69] = +{ + 0x7C, 0x63, 0x64, 0x9F, 0x6A, 0x93, 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x59, 0x8B, 0x57, 0x32, 0x00, 0x58, 0x6F, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xEF, + 0x02, 0x90, 0x08, 0x28, 0x01, 0x05, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x103 */ +static const unsigned char g800x600x256_regs[69] = +{ + 0x7A, 0x63, 0x64, 0x9D, 0x67, 0x97, 0x71, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x59, 0x8B, 0x57, 0x32, 0x40, 0x58, 0x6F, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x2F, + 0x02, 0x90, 0x08, 0x28, 0x01, 0x35, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x104 */ +/* !!! xbytes=128 */ +static const unsigned char g1024x768x16_regs[69] = +{ + 0x99, 0x7F, 0x80, 0x9C, 0x84, 0x18, 0x97, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x88, 0x7F, 0x80, 0x00, 0x80, 0x97, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0x2B, + 0x03, 0x90, 0x20, 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, +}; + +#if 0 +/* this one is interlaced :( */ +/* BIOS mode 0x105 */ +static const unsigned char g1024x768x256_regs[69] = +{ + 0x99, 0x7F, 0x80, 0x9C, 0x84, 0x18, 0x97, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x88, 0x7F, 0x80, 0x40, 0x80, 0x97, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x2B, + 0x03, 0x90, 0x20, 0x00, 0x00, 0x15, 0x02, 0x00, 0x00, +}; +#endif + +/* non-interlaced 60hz mode */ +static const unsigned char g1024x768x256_regs[69] = +{ + 0xA4, 0x7F, 0x80, 0x80, 0x86, 0x00, 0x26, 0xFD, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x2A, 0xFF, 0x40, 0x40, 0x04, 0x20, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x00, 0x00, 0x34, 0x02, 0x04, 0x00 +}; + + +/* BIOS mode 0x106 */ +/* !!! xbytes=160 */ +static const unsigned char g1280x1024x16_regs[69] = +{ + 0xBD, 0x9F, 0xA0, 0x80, 0xA4, 0x12, 0x22, 0xB2, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x8F, 0xFF, 0xA0, 0x00, 0x03, 0x20, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0x23, + 0x03, 0x90, 0x00, 0x28, 0x28, 0x25, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x109 */ +/* !!! xbytes=264 */ +static const unsigned char g132x25x16_regs[69] = +{ + 0x9F, 0x83, 0x84, 0x02, 0x8A, 0x98, 0xBF, 0x1F, 0x00, 0x4D, 0x0B, 0x0C, + 0x00, 0x00, 0x00, 0x00, 0x81, 0x85, 0x5D, 0x42, 0x1F, 0x61, 0xBC, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x08, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0xFF, + 0x03, 0x01, 0x03, 0x00, 0x02, + 0xAF, + 0x00, 0x80, 0x00, 0x28, 0x01, 0x25, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x10A */ +/* !!! xbytes=264 */ +static const unsigned char g132x43x16_regs[69] = +{ + 0x9F, 0x83, 0x84, 0x02, 0x8A, 0x98, 0xB3, 0x1F, 0x00, 0x47, 0x06, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x7A, 0x8E, 0x57, 0x42, 0x1F, 0x5A, 0xB1, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x08, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0xFF, + 0x03, 0x01, 0x03, 0x00, 0x02, + 0x6F, + 0x00, 0x80, 0x00, 0x28, 0x01, 0x25, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x10D */ +/* !!! xbytes=640 */ +static const unsigned char g320x200x32K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x20, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x10E */ +static const unsigned char g320x200x64K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x20, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x10F */ +static const unsigned char g320x200x16M_regs[69] = +{ + 0x91, 0x77, 0x7D, 0x8C, 0x7D, 0x06, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x3C, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x82, 0x90, 0x28, 0x00, 0x01, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x110 */ +/* !!! xbytes=1280 */ +static const unsigned char g640x480x32K_regs[69] = +{ + 0xC1, 0x9F, 0xA8, 0x9F, 0xA2, 0x9A, 0x0A, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x50, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x08, 0x00, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x111 */ +static const unsigned char g640x480x64K_regs[69] = +{ + 0xC1, 0x9F, 0xA8, 0x9F, 0xA2, 0x9A, 0x0A, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x50, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x08, 0x00, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x112 */ +/* !!! xbytes=2048 */ +static const unsigned char g640x480x16M_regs[69] = +{ + 0x24, 0xEF, 0xFC, 0x9F, 0xF2, 0x16, 0x0A, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x80, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x82, 0x90, 0x00, 0x01, 0x00, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x113 */ +/* !!! xbytes=1600 */ +static const unsigned char g800x600x32K_regs[69] = +{ + 0xFD, 0xC7, 0xC9, 0x9F, 0xD1, 0x80, 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x59, 0x8B, 0x57, 0x64, 0x40, 0x58, 0x6F, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xEF, + 0x02, 0x90, 0x08, 0x28, 0x00, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x114 */ +static const unsigned char g800x600x64K_regs[69] = +{ + 0xFD, 0xC7, 0xC9, 0x9F, 0xD1, 0x80, 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x59, 0x8B, 0x57, 0x64, 0x40, 0x58, 0x6F, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xEF, + 0x02, 0x90, 0x08, 0x28, 0x00, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x11C */ +static const unsigned char g640x350x256_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x40, 0x62, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xA3, + 0x02, 0x90, 0x20, 0x20, 0x01, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x11D */ +/* !!! xbytes=1280 */ +static const unsigned char g640x350x32K_regs[69] = +{ + 0xC3, 0x9F, 0xA8, 0x84, 0xA8, 0x0E, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x50, 0x40, 0x62, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xA3, + 0x02, 0x90, 0x20, 0x28, 0x00, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x11E */ +/* !!! xbytes=1280 */ +static const unsigned char g640x400x32K_regs[69] = +{ + 0xC3, 0x9F, 0xA8, 0x84, 0xA8, 0x0E, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x50, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x28, 0x00, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x11F */ +static const unsigned char g640x350x64K_regs[69] = +{ + 0xC3, 0x9F, 0xA8, 0x84, 0xA8, 0x0E, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x50, 0x40, 0x62, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xA3, + 0x02, 0x90, 0x20, 0x28, 0x00, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x120 */ +static const unsigned char g640x400x64K_regs[69] = +{ + 0xC3, 0x9F, 0xA8, 0x84, 0xA8, 0x0E, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x50, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x28, 0x00, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x121 */ +/* !!! xbytes=2048 */ +static const unsigned char g640x350x16M_regs[69] = +{ + 0x27, 0xEF, 0xFB, 0x85, 0xFC, 0x85, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x80, 0x40, 0x62, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xA3, + 0x82, 0x90, 0x20, 0x01, 0x00, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x122 */ +/* !!! xbytes=2048 */ +static const unsigned char g640x400x16M_regs[69] = +{ + 0x27, 0xEF, 0xFB, 0x85, 0xFC, 0x85, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x80, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x82, 0x90, 0x28, 0x01, 0x00, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x12D */ +static const unsigned char g512x384x256_regs[69] = +{ + 0x4C, 0x3F, 0x40, 0x88, 0x44, 0x07, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x86, 0x7F, 0x20, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x6F, + 0x02, 0x90, 0x28, 0x20, 0x03, 0x35, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x12E */ +/* !!! xbytes=640 */ +static const unsigned char g320x240x32K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0x0B, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x20, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x12F */ +/* !!! xbytes=640 */ +static const unsigned char g320x400x32K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x20, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x130 */ +/* !!! xbytes=640 */ +static const unsigned char g320x480x32K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x20, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x131 */ +/* !!! xbytes=720 */ +static const unsigned char g360x200x32K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x2D, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x67, + 0x02, 0x90, 0x28, 0x28, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x132 */ +/* !!! xbytes=720 */ +static const unsigned char g360x240x32K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0x0B, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x2D, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x28, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x133 */ +/* !!! xbytes=720 */ +static const unsigned char g360x400x32K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x2D, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x67, + 0x02, 0x90, 0x28, 0x28, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x134 */ +/* !!! xbytes=720 */ +static const unsigned char g360x480x32K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x2D, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x28, 0x01, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x135 */ +/* !!! xbytes=1024 */ +static const unsigned char g512x384x32K_regs[69] = +{ + 0x9D, 0x7F, 0x80, 0x90, 0x88, 0x0E, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x86, 0x7F, 0x40, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x6F, + 0x02, 0x90, 0x28, 0x00, 0x01, 0x35, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x136 */ +static const unsigned char g320x240x64K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0x0B, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x20, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x137 */ +static const unsigned char g320x400x64K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x20, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x138 */ +static const unsigned char g320x480x64K_regs[69] = +{ + 0x5F, 0x4F, 0x54, 0x80, 0x54, 0x97, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x20, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x139 */ +static const unsigned char g360x200x64K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x2D, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x67, + 0x02, 0x90, 0x28, 0x28, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x13A */ +static const unsigned char g360x240x64K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0x0B, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x2D, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x28, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x13B */ +static const unsigned char g360x400x64K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x2D, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x67, + 0x02, 0x90, 0x28, 0x28, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x13C */ +static const unsigned char g360x480x64K_regs[69] = +{ + 0x6B, 0x59, 0x5B, 0x84, 0x5E, 0x81, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x2D, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x28, 0x01, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x13D */ +static const unsigned char g512x384x64K_regs[69] = +{ + 0x9D, 0x7F, 0x80, 0x90, 0x88, 0x0E, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x86, 0x7F, 0x40, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x6F, + 0x02, 0x90, 0x28, 0x00, 0x01, 0x35, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x13E */ +static const unsigned char g320x240x16M_regs[69] = +{ + 0x91, 0x77, 0x7D, 0x8C, 0x7D, 0x06, 0x0B, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x3C, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x82, 0x90, 0x00, 0x00, 0x01, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x13F */ +static const unsigned char g320x400x16M_regs[69] = +{ + 0x91, 0x77, 0x7D, 0x8C, 0x7D, 0x06, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x3C, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x82, 0x90, 0x28, 0x00, 0x01, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x140 */ +static const unsigned char g320x480x16M_regs[69] = +{ + 0x91, 0x77, 0x7D, 0x8C, 0x7D, 0x06, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x3C, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x82, 0x90, 0x00, 0x00, 0x01, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x145 */ +static const unsigned char g512x384x16M_regs[69] = +{ + 0xEE, 0xBF, 0xC0, 0x97, 0xCC, 0x15, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x94, 0x86, 0x7F, 0x60, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x67, + 0x82, 0x90, 0x28, 0x20, 0x00, 0x35, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x14F */ +static const unsigned char g400x300x256_regs[69] = +{ + 0x3B, 0x31, 0x32, 0x9E, 0x35, 0x9C, 0x99, 0xF0, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0x8E, 0x57, 0x19, 0x40, 0x58, 0x93, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x08, 0x01, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x150 */ +/* !!! xbytes=800 */ +static const unsigned char g400x300x32K_regs[69] = +{ + 0x7C, 0x63, 0x64, 0x9D, 0x6A, 0x99, 0x99, 0xF0, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0x8E, 0x57, 0x32, 0x40, 0x58, 0x93, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x28, 0x00, 0x15, 0xA2, 0x00, 0x00, +}; + +/* BIOS mode 0x151 */ +static const unsigned char g400x300x64K_regs[69] = +{ + 0x7C, 0x63, 0x64, 0x9D, 0x6A, 0x99, 0x99, 0xF0, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0x8E, 0x57, 0x32, 0x40, 0x58, 0x93, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x28, 0x00, 0x15, 0xC2, 0x00, 0x00, +}; + +/* BIOS mode 0x152 */ +static const unsigned char g400x300x16M_regs[69] = +{ + 0xBC, 0x95, 0x96, 0x9D, 0x9F, 0x95, 0x99, 0xF0, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0x8E, 0x57, 0x4B, 0x40, 0x58, 0x93, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xEF, + 0x82, 0x90, 0x00, 0x08, 0x00, 0x15, 0xE2, 0x00, 0x00, +}; + +/* BIOS mode 0x162 */ +/* !!! xbytes=80 */ +static const unsigned char g640x480x16_regs[69] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xE3, + 0x02, 0x90, 0x00, 0x28, 0x01, 0x05, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x163 */ +static const unsigned char g320x200x256_regs[69] = +{ + 0x2D, 0x27, 0x2A, 0x8F, 0x2B, 0x8E, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x164 */ +static const unsigned char g320x240x256_regs[69] = +{ + 0x2D, 0x27, 0x2A, 0x8F, 0x2B, 0x8E, 0x0B, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x14, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x165 */ +static const unsigned char g320x400x256_regs[69] = +{ + 0x2D, 0x27, 0x2A, 0x8F, 0x2B, 0x8E, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63, + 0x02, 0x90, 0x28, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x166 */ +static const unsigned char g320x480x256_regs[69] = +{ + 0x2D, 0x27, 0x2A, 0x8F, 0x2B, 0x8E, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x14, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE3, + 0x02, 0x90, 0x00, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x167 */ +/* !!! xbytes=368 */ +static const unsigned char g360x200x256_regs[69] = +{ + 0x33, 0x2C, 0x2E, 0x96, 0x30, 0x93, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x17, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x67, + 0x02, 0x90, 0x28, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x168 */ +/* !!! xbytes=368 */ +static const unsigned char g360x240x256_regs[69] = +{ + 0x33, 0x2C, 0x2E, 0x96, 0x30, 0x93, 0x0B, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x17, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x169 */ +/* !!! xbytes=368 */ +static const unsigned char g360x400x256_regs[69] = +{ + 0x33, 0x2C, 0x2E, 0x96, 0x30, 0x93, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x17, 0x40, 0x95, 0xB8, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x67, + 0x02, 0x90, 0x28, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; + +/* BIOS mode 0x16A */ +/* !!! xbytes=368 */ +static const unsigned char g360x480x256_regs[69] = +{ + 0x33, 0x2C, 0x2E, 0x96, 0x30, 0x93, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x17, 0x40, 0xE6, 0x03, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0xE7, + 0x02, 0x90, 0x00, 0x08, 0x03, 0x15, 0x02, 0x00, 0x00, +}; diff --git a/src/regs/et3000.regs b/src/regs/et3000.regs new file mode 100644 index 0000000..b23da70 --- /dev/null +++ b/src/regs/et3000.regs @@ -0,0 +1,112 @@ + +/* + ( File generated by tseng3.exe ) + + tseng3 v1.2, Copyright (C) 1993 Tommy Frandsen, Harm Hanemaayer + and Hartmut Schirmer + + Permission is granted to any individual or institution to use, copy, or + redistribute this executable so long as it is not modified and that it is + not sold for profit. + + LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND COMES WITH + NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL + THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF + THIS SOFTWARE. + */ + + +/* generating ET3000 register set */ + +/* EXT CRT : EXT+0x00 .. EXT+0x02 */ +/* EXT SEQ : EXT+0x03 .. EXT+0x04 */ +/* EXT MISC: EXT+0x05 .. EXT+0x05 */ +/* EXT ATT : EXT+0x06 .. EXT+0x06 */ + +/* ET3000 BIOS mode 0x2E -- 640x480x256 */ +/* Video timing: Vertical frequency : 60.0Hz + Horizontal frequency : 31.5KHz */ +static unsigned char g640x480x256_regs[67] = +{ + 0x5F, 0x4F, 0x50, 0x02, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x02, 0x03, 0x0F, 0x00, 0x06, + 0xE3, + 0x00, 0x00, 0x00, 0x00, 0xA8, 0x40, 0x10 +}; + +/* ET3000 BIOS mode 0x29 -- 800x600x16 */ +/* Video timing: Vertical frequency : 59.4Hz + Horizontal frequency : 37.6KHz */ +static unsigned char g800x600x16_regs[67] = +{ + 0x80, 0x63, 0x64, 0x03, 0x67, 0x1C, 0x77, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x82, 0x57, 0x32, 0x00, 0x5B, 0x75, 0xC3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x02, 0x01, 0x0F, 0x00, 0x06, + 0xEB, + 0x00, 0x00, 0x00, 0x00, 0xA8, 0x40, 0x00 +}; + +/* ET3000 BIOS mode 0x30 -- 800x600x256 */ +/* Video timing: Vertical frequency : 59.4Hz + Horizontal frequency : 37.6KHz */ +static unsigned char g800x600x256_regs[67] = +{ + 0x80, 0x63, 0x64, 0x03, 0x67, 0x1C, 0x77, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x82, 0x57, 0x32, 0x00, 0x5B, 0x75, 0xC3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x02, 0x01, 0x0F, 0x00, 0x06, + 0xEB, + 0x00, 0x00, 0x00, 0x00, 0xA8, 0x40, 0x10 +}; + +/* ET3000 BIOS mode 0x37 -- 1024x768x16 */ +/* Video timing: Vertical frequency : 86.9Hz (interlaced) + Horizontal frequency : 35.5KHz */ +static unsigned char g1024x768x16_regs[67] = +{ + 0x4A, 0x3F, 0x3F, 0x0E, 0x44, 0x0E, 0x97, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, 0x7F, 0x20, 0x00, 0x7F, 0x98, 0xC3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0xFF, + 0x02, 0x03, 0x0F, 0x00, 0x06, + 0x2F, + 0x00, 0x00, 0x80, 0x00, 0xE8, 0x40, 0x10 +}; + +/* ET3000 BIOS mode 0x38 -- 1024x768x256 : NOT SUPPORTED */ + +/* ET3000 BIOS mode 0x3D -- 1280x1024x16 : NOT SUPPORTED */ + +/* VESA mode 0x107 -- 1280x1024x256 : NOT SUPPORTED */ + +/* --- ET3000 specific modes */ +#ifdef _DYNAMIC_ONLY_ + +/* ET3000 BIOS mode 0x2D -- 640x350x256 */ +/* Video timing: Vertical frequency : 70.1Hz + Horizontal frequency : 31.5KHz */ +static unsigned char g640x350x256_regs[67] = +{ + 0x5F, 0x4F, 0x50, 0x02, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x00, 0x63, 0xBA, 0xC3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x02, 0x03, 0x0F, 0x00, 0x06, + 0xA3, + 0x00, 0x00, 0x00, 0x00, 0xA8, 0x40, 0x10 +}; + +/* ET3000 BIOS mode 0x2F -- 640x400x256 : NOT SUPPORTED */ + +#endif /* defined(_DYNAMIC_ONLY_ALL_) */ diff --git a/src/regs/gvga6400.regs b/src/regs/gvga6400.regs new file mode 100644 index 0000000..fb8768e --- /dev/null +++ b/src/regs/gvga6400.regs @@ -0,0 +1,26 @@ + +/* GVGA6400 BIOS mode 0x5C 640x480x256 */ +static char g640x480x256_regs[71] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x53, 0x9F, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEB, 0x8E, 0xDF, 0x28, 0x00, 0xE4, 0x08, 0xC3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xE3, + 0x01, 0x37, 0x64, 0x06, 0x20, 0x24, 0x08, 0x00, 0x00, 0x00, 0x02 +}; + +/* GVGA6400 BIOS mode 0x5E 800x600x256 */ +static char g800x600x256_regs[71] = +{ + 0x7A, 0x63, 0x64, 0x9C, 0x6A, 0x91, 0x74, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5A, 0x8C, 0x57, 0x32, 0x00, 0x5B, 0x6D, 0xC3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xEB, + 0x01, 0x37, 0x7F, 0x07, 0x20, 0x24, 0x08, 0x00, 0x00, 0x00, 0x02 +}; diff --git a/src/regs/oak.regs b/src/regs/oak.regs new file mode 100644 index 0000000..fc69a43 --- /dev/null +++ b/src/regs/oak.regs @@ -0,0 +1,200 @@ + +/* Oak Techologies OTI-067/077/087 mode definitions + + * 12 September 1994 Christopher M. Wiles (a0017097@wsuaix.csc.wsu.edu) + * The below mode definitions work just fine on my '87 board. As I + * do not have either a '67 or a '77 to play with, I cannot guarantee + * that any or all of these modes will work with cards based on those + * chips. Therefore, use at your own risk (and let me know if they work). + * + * NB: If any of these modes are displaced horizontally, change the fifth + * byte (in units of 8) of the CRTC section in the definition in + * question. Increment the value to move the screen left, decrement to + * move the screen right. + */ + +#define PATCH1 /* g640x480x256_regs */ +#define PATCH2 /* g800x600x16_regs */ +#define PATCH3 /* still g800x600x16_regs */ +#define PATCH4 /* g800x600x256_regs */ + +static const unsigned char g640x480x256_regs[79] = +{ + /* CRTC */ + 0x63, 0x4F, 0x50, 0x86, 0x58, 0x81, 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8b, 0xDF, 0x28, 0x00, 0xE4, 0x01, 0xC3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ +#ifdef PATCH1 +/* SEQ reg 1 bit 3 broke my 067. It may now break the 87s, for all I know! */ + 0x03, 0x01, 0x0f, 0x00, 0x0e, +#else + 0x03, 0x09, 0x0f, 0x00, 0x0e, +#endif + /* Misc. output */ + 0xE3, + /* Extended registers */ + 0xC0, 0x8F, 0x80, 0x00, 0x01, 0x00, 0x00, 0xFF, + /* 087 native registers */ + 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00 + +}; + +static const unsigned char g800x600x16_regs[79] = +{ + /* CRTC */ + 0x7f, 0x63, 0x64, 0x82, 0x6c, 0x1f, 0x72, 0xf0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8c, 0x57, 0x32, 0x0f, 0x58, 0x6e, 0xe3, + /* ATC */ +#ifdef PATCH2 +/* There is something wrong with my palette in this mode. Setting the + palette-regs to the first entries in the 256-color table seems + to lessen the problem (but not remove it). */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, +#else + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x01, 0x00, 0x0f, 0x00, 0x00, +#endif + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x06, + /* Misc. output */ + 0xeb, + /* Extended registers */ +#ifdef PATCH3 +/* Setting all bits in 3de reg E broke my 67. Only bit 7 is documented + anyway, so this should also work on 87's. I hope. */ + 0x00, 0x28, 0x80, 0x00, 0xff, 0x00, 0x00, 0xff, +#else + 0x00, 0x28, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, +#endif + /* 087 Native registers */ + 0x06, 0x00, 0x40, 0x00, 0x0f, 0x03, 0x00, 0x08, + 0x00, 0x00, 0x00 + +}; + +static const unsigned char g800x600x256_regs[79] = +{ + /* CRTC */ + 0x7f, 0x63, 0x64, 0x82, 0x6c, 0x1f, 0x72, 0xf0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8c, 0x57, 0x32, 0x0f, 0x58, 0x6e, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0xeb, + /* Extended registers */ +/* Setting all bits in 3de reg e broke my 67. Only bit 7 is documented + anyway, so this should also work on 87's. I hope. */ +#ifdef PATCH4 + 0x00, 0x2e, 0x80, 0x00, 0xff, 0x00, 0x40, 0xff, +#else + 0x00, 0x2e, 0xff, 0x00, 0xff, 0x00, 0x40, 0xff, +#endif + /* 087 native registers */ + 0x06, 0x00, 0x40, 0x00, 0x0f, 0x06, 0x04, 0x08, + 0x00, 0x00, 0x00 + +}; + +static const unsigned char g1024x768x256_regs[79] = +{ + /* CRTC */ + 0xa3, 0x7f, 0x80, 0x86, 0x89, 0x9a, 0x24, 0xfd, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, 0xff, 0x40, 0x0f, 0x02, 0x20, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0x2b, + /* Extended registers */ + 0x00, 0x0d, 0xff, 0x00, 0xff, 0x00, 0x4f, 0xff, + /* 087 native registers */ + 0x0b, 0x00, 0x4f, 0x00, 0x0f, 0x05, 0x04, 0x04, + 0x00, 0x00, 0x00 + +}; + +static const unsigned char g640x480x32K_regs[79] = +{ + /* CRTC */ + 0xcb, 0x9f, 0xa1, 0x8d, 0xad, 0x0f, 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe8, 0x8b, 0xdf, 0x50, 0x00, 0xe4, 0x01, 0xc3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0xe3, + /* Extended registers */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 087 native registers */ + 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x04, 0x08, + 0x00, 0x00, 0xa0 +}; + +static const unsigned char g800x600x32K_regs[79] = +{ + /* CRTC */ + 0xff, 0xc7, 0xc9, 0x81, 0xd9, 0x04, 0x72, 0xf0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8c, 0x57, 0x64, 0x0f, 0x58, 0x6e, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0xeb, + /* Extended registers */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 087 native registers */ + 0x0a, 0x00, 0x00, 0x00, 0x0f, 0x0a, 0x04, 0x08, + 0x00, 0x00, 0xa0 + +}; + +static const unsigned char g1280x1024x16_regs[79] = +{ + /* CRTC */ + 0xc3, 0x9f, 0xa0, 0x86, 0xa2, 0x17, 0x2e, 0xb2, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x9c, 0xff, 0x50, 0x0f, 0x04, 0x29, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x06, + /* Misc. output */ + 0x2b, + /* Extended registers */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 087 native registers */ + 0x0a, 0x80, 0x4f, 0x00, 0x0f, 0x05, 0x00, 0x08, + 0x00, 0x00, 0x00 + +}; + +/* HighRes 16 color modes based on 256 color modes */ +#define g1024x768x16_regs g1024x768x256_regs diff --git a/src/regs/paradise.regs b/src/regs/paradise.regs new file mode 100644 index 0000000..7dd7b43 --- /dev/null +++ b/src/regs/paradise.regs @@ -0,0 +1,100 @@ +/* Western Digital Paradise WD90C31 driver for VGAlib */ +/* (c) 1998 Petr Kulhavy */ +/* */ +/* This driver is absolutely free software. You can redistribute */ +/* and/or it modify without any restrictions. But it's WITHOUT ANY */ +/* WARRANTY. */ + +#define REGCOUNT 88 /* standard */ + +/* Paradise SVGA 640x480 256 colors 512kB */ +static const unsigned char g640x480x256_regs[REGCOUNT] = +{ + /* CRTC */ + 0x5f, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0xe3, + /* 26 extra registers */ + 0x00, 0x0f, 0xf8, 0xe1, 0x65, 0x04, 0x10, 0x00, 0x00, 0x00, 0x84, 0x02, + 0x00, 0x01, 0x15, 0x85, 0xb0, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x30, 0x00, + /* extra 2 VGA registers 0x3d4,0x18, 0x3c0,0x20 */ + 0xff, 0xf +}; + +/* Paradise SVGA mode 800x600 16 colors 512 kB */ +static const unsigned char g800x600x16_regs[REGCOUNT] = +{ + /* CRTC */ + 0x7b, 0x63, 0x64, 0x9e, 0x69, 0x92, 0x6f, 0xf0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8a, 0x57, 0x32, 0x00, 0x58, 0x6f, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x06, + /* Misc. output */ + 0xef, + /* 26 extra registers */ + 0x00, 0x0f, 0xf8, 0xe1, 0x65, 0x04, 0x10, 0x00, 0x00, 0x00, 0x84, 0x02, + 0x00, 0x00, 0x15, 0x85, 0xb0, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x30, 0x00, + /* extra 2 VGA registers 0x3d4,0x18, 0x3c0,0x20 (last CRTC, last ATC) */ + 0xff, 0xf +}; + +/* Paradise SVGA mode 800x600 256 colors 512 kB */ +static const unsigned char g800x600x256_regs[REGCOUNT] = +{ + /* CRTC */ + 0x7b, 0x63, 0x64, 0x9e, 0x69, 0x92, 0x6f, 0xf0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8a, 0x57, 0x64, 0x40, 0x58, 0x6f, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x03, 0x0e, + /* Misc. output */ + 0xef, + /* 26 extra registers */ + 0x03, 0x0f, 0xf8, 0xb1, 0x65, 0x04, 0x10, 0x00, 0x00, 0x00, 0x84, 0x02, + 0x00, 0x01, 0x15, 0x85, 0xb0, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x30, 0x00, + /* extra 2 VGA registers 0x3d4,0x18, 0x3c0,0x20 (last CRTC, last ATC) */ + 0xff, 0xf +}; + +/* Paradise SVGA mode 1024x768 16 colors 512 kB */ +static const unsigned char g1024x768x16_regs[REGCOUNT] = +{ + /* CRTC */ + 0xa3, 0x7f, 0x80, 0x06, 0x87, 0x98, 0x24, 0xf1, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x85, 0xff, 0x40, 0x00, 0xff, 0x23, 0xe3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x01, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x03, 0x01, 0x0f, 0x00, 0x06, + /* Misc. output */ + 0xeb, + /* 26 extra registers */ + 0x00, 0x0f, 0xf8, 0xe1, 0x65, 0x04, 0x10, 0x00, 0x00, 0x00, 0x84, 0x02, + 0x00, 0x00, 0x15, 0x85, 0xb0, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, + 0x30, 0x00, + /* extra 2 VGA registers 0x3d4,0x18, 0x3c0,0x20 */ + 0xff, 0xf +}; diff --git a/src/regs/tvga8900.regs b/src/regs/tvga8900.regs new file mode 100644 index 0000000..9b8bbfe --- /dev/null +++ b/src/regs/tvga8900.regs @@ -0,0 +1,163 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* TVGA 8900c code taken from tvgalib by Toomas Losin */ + + +#define REGCOUNT 72 + +/* Trident SVGA mode 5d - 640x480x256 1M NI */ +static const unsigned char g640x480x256_regs[REGCOUNT] = +{ + /* CRTC */ + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x01, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0x63, + /* 7 extra CRT registers */ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + /* Extra Sequencer old and new mode registers 13 and 14 */ + 0x30, 0xa8, 0x00, 0x42, + 0x00 +}; + +/* Trident SVGA mode 5d - 640x480x256 512k + 1M I */ +static const unsigned char g640x480x256i_regs[REGCOUNT] = +{ + 0xc3, 0x9f, 0xa1, 0x84, 0xa6, 0x00, 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xa3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Seq. */ + 0x01, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0xeb, + /* extra CRT regs */ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + /* Extra seq. regs */ + 0x00, 0xa8, 0x01, 0x02, + 0x00 +}; + +/* Trident SVGA mode 5e - 800x600x256 1M NI */ +static const unsigned char g800x600x256_regs[REGCOUNT] = +{ + /* CRTC */ + 0x7e, 0x63, 0x64, 0x81, 0x6b, 0x18, 0x99, 0xf0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6e, 0x84, 0x57, 0x32, 0x40, 0x5e, 0x93, 0xa3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x01, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0x2b, + /* Extra CRT registers */ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + /* Seq. old and new mode registers */ + 0x10, 0xa8, 0x01, 0x02, + 0x00 +}; + + +/* Trident SVGA mode 5e - 800x600x256 512k */ +static const unsigned char g800x600x256i1_regs[REGCOUNT] = +{ + /* CRTC */ + 0xeb, 0xc7, 0xc9, 0x8d, 0xcb, 0x86, 0x4a, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2f, 0x81, 0x2b, 0xc8, 0x40, 0x2f, 0x47, 0xa3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x01, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0xa3, + /* extra CRTC */ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, + /* extra Seq. */ + 0x00, 0xa8, 0x01, 0x02, + 0x00 +}; + +/* Trident SVGA mode 5e - 800x600x256 1M I */ +static const unsigned char g800x600x256i_regs[REGCOUNT] = +{ + /* CRTC */ + 0x7b, 0x63, 0x64, 0x9e, 0x69, 0x92, 0x6f, 0xf0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8a, 0x57, 0x32, 0x40, 0x58, 0x6f, 0xa3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Seq. */ + 0x01, 0x01, 0x0f, 0x00, 0x0e, + 0xef, + /* extra CRTC */ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x30, 0xa8, 0x00, 0x42, + 0x00 +}; + + +/* Trident SVGA mode 62 - 1024x768x256 1M I */ +static const unsigned char g1024x768x256i_regs[REGCOUNT] = +{ + /* CRTC */ + 0x99, 0x7f, 0x81, 0x1b, 0x83, 0x19, 0x98, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0x0f, 0x7f, 0x80, 0x40, 0x83, 0x95, 0xa3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x01, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0x2b, + /* Extra CRTC regs */ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, + /* Ext. sequencer */ + 0x10, 0xa8, 0x00, 0x02, + 0x00 +}; + +/* Trident SVGA mode 62 - 1024x768x256 1M NI */ +static const unsigned char g1024x768x256_regs[REGCOUNT] = +{ + /* CRTC */ + 0xa2, 0x7f, 0x80, 0x85, 0x87, 0x90, 0x2c, 0xfd, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x81, 0xff, 0x40, 0x40, 0x07, 0x26, 0xa3, + /* ATC */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x41, 0x00, 0x0f, 0x00, 0x00, + /* Graphics */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, + /* Sequencer */ + 0x01, 0x01, 0x0f, 0x00, 0x0e, + /* Misc. output */ + 0x27, + /* Extended CRTC regs */ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + /* Ext. seq. */ + 0x10, 0xa8, 0x01, 0x02, + 0x00 +}; diff --git a/src/regs/tvga9440.regs b/src/regs/tvga9440.regs new file mode 100644 index 0000000..43ca51c --- /dev/null +++ b/src/regs/tvga9440.regs @@ -0,0 +1,312 @@ +/* TVGA 9440 code added by ARK 29-OCT-97 */ +/* (root@ark.dyn.ml.org, ark@lhq.com) [nitc?] */ +/* updated 9-NOV-97 to support more regs */ +/* this should alllow it to work on 9680's as well */ + +/* The 9440 now uses 84 and 2 pads */ +/* EXT+11 and 12 are not used, because vga.c will clobber them */ +#define REG94 86 + +/* I used _regs94 for the 9440 sets so they don't */ +/* interfere with the old 8900 sets */ + +/* BIOS mode 0x5B - 800x600x16 */ +static const unsigned char g800x600x16_regs94[REG94]={ + 0x7F,0x63,0x64,0x82,0x6C,0x1C,0x72,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x8C,0x57,0x32,0x00,0x58,0x72,0xE3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x06, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x10,0x1F,0x08,0x01,0x10,0x00, /*Trident CRC*/ + 0x90,0x22, /*Trident GRFX*/ + 0x30,0x14,0x07,0x05,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x5D - 640x480x256 */ +static const unsigned char g640x480x256_regs94[REG94]={ + 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xEA,0x8C,0xDF,0x50,0x40,0xE0,0x0B,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x10,0x00, /*Trident CRC*/ + 0x96,0x22, /*Trident GRFX*/ + 0xC2,0x19,0x07,0x05,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x5E - 800x600x256 */ +static const unsigned char g800x600x256_regs94[REG94]={ + 0x7F,0x63,0x64,0x82,0x6B,0x1B,0x72,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x8C,0x57,0x64,0x40,0x58,0x72,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x10,0x00, /*Trident CRC*/ + 0x96,0x22, /*Trident GRFX*/ + 0x30,0x14,0x07,0x05,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x5F - 1024x768x16 */ +static const unsigned char g1024x768x16_regs94[REG94]={ + 0x99,0x7F,0x80,0x1C,0x84,0x1A,0x97,0x1F, /*CRTC*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x84,0x7F,0x40,0x00,0x80,0x97,0xE3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x06, /*SEQ*/ + 0x2B, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x84,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x10,0x1F,0x08,0x01,0x10,0x00, /*Trident CRC*/ + 0x94,0x26, /*Trident GRFX*/ + 0xBD,0x14,0x07,0x05,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x62 - 1024x768x256 */ +static const unsigned char g1024x768x256_regs94[REG94]={ + 0x99,0x7F,0x80,0x1C,0x83,0x19,0x97,0x1F, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x84,0x7F,0x80,0x40,0x80,0x97,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x84,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x10,0x00, /*Trident CRC*/ + 0x96,0x26, /*Trident GRFX*/ + 0xBD,0x14,0x07,0x05,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x63 - 1280x1024x16 */ +static const unsigned char g1280x1024x16_regs94[REG94]={ + 0xCF,0x9F,0xA0,0x92,0xA9,0x13,0x15,0xB2, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x84,0xFF,0x50,0x00,0x01,0x13,0xE3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x06, /*SEQ*/ + 0x2B, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x84,0x13,0x10,0x8A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x10,0x1F,0x08,0x01,0x10,0x00, /*Trident CRC*/ + 0x94,0x26, /*Trident GRFX*/ + 0x45,0x06,0x07,0x05,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x65 - 1600x1200x16 */ +static const unsigned char g1600x1200x16_regs94[REG94]={ + 0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F, /*CRTC*/ + 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00, + 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x0C,0x00,0x0F,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00, /*GRFX*/ + 0xFF, + 0x03,0x00,0x03,0x00,0x02, /*SEQ*/ + 0x67, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x00,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x10,0x1F,0x08,0x01,0x10,0x00, /*Trident CRC*/ + 0x90,0x22, /*Trident GRFX*/ + 0x45,0x06,0x07,0x05,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x6B - 320x200x16M */ +static const unsigned char g320x200x16M_regs94[REG94]={ + 0x30,0x27,0x28,0x93,0x2B,0x90,0xBF,0x1F, /*CRTC*/ + 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9C,0x8E,0x8F,0x78,0x40,0x96,0xB9,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x6B, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x8A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x18,0x00, /*Trident CRC*/ + 0xD6,0x22, /*Trident GRFX*/ + 0x30,0x14,0x07,0x05,0xD0 /*Trident Specific*/ +}; + +/* BIOS mode 0x6C - 640x480x16M */ +static const unsigned char g640x480x16M_regs94[REG94]={ + 0x5F,0x4F,0x50,0x82,0x52,0x80,0x0B,0x3E, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xEA,0x8C,0xDF,0xF0,0x40,0xE7,0x04,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF0,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x05,0x18,0x00, /*Trident CRC*/ + 0xD6,0x22, /*Trident GRFX*/ + 0x22,0x03,0x07,0x05,0xD0 /*Trident Specific*/ +}; + +/* BIOS mode 0x74 - 640x480x32K */ +static const unsigned char g640x480x32K_regs94[REG94]={ + 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xEA,0x8C,0xDF,0xA0,0x40,0xE0,0x0B,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x14,0x00, /*Trident CRC*/ + 0x9E,0x22, /*Trident GRFX*/ + 0x29,0x06,0x07,0x05,0x10 /*Trident Specific*/ +}; + +/* BIOS mode 0x75 - 640x480x64K */ +static const unsigned char g640x480x64K_regs94[REG94]={ + 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xEA,0x8C,0xDF,0xA0,0x40,0xE0,0x0B,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x14,0x00, /*Trident CRC*/ + 0x9E,0x22, /*Trident GRFX*/ + 0x29,0x06,0x07,0x05,0x30 /*Trident Specific*/ +}; + +/* BIOS mode 0x76 - 800x600x32K */ +static const unsigned char g800x600x32K_regs94[REG94]={ + 0x7F,0x63,0x64,0x82,0x69,0x1A,0x72,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x8C,0x57,0xC8,0x40,0x58,0x72,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF0,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x05,0x14,0x00, /*Trident CRC*/ + 0x9E,0x22, /*Trident GRFX*/ + 0x30,0x04,0x07,0x05,0x10 /*Trident Specific*/ +}; + +/* BIOS mode 0x77 - 800x600x64K */ +static const unsigned char g800x600x64K_regs94[REG94]={ + 0x7E,0x63,0x64,0x81,0x68,0x1A,0x72,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x8C,0x57,0xC8,0x40,0x58,0x72,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xE3,0x00,0xF0,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x05,0x14,0x00, /*Trident CRC*/ + 0x9E,0x22, /*Trident GRFX*/ + 0x30,0x04,0x07,0x05,0x30 /*Trident Specific*/ +}; + +/* BIOS mode 0x7E - 320x200x32K */ +static const unsigned char g320x200x32K_regs94[REG94]={ + 0x2D,0x27,0x28,0x90,0x2A,0x80,0xBF,0x1F, /*CRTC*/ + 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9C,0x8E,0x8F,0x50,0x40,0x96,0xB9,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x6B, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x14,0x00, /*Trident CRC*/ + 0x9E,0x22, /*Trident GRFX*/ + 0xC2,0x19,0x07,0x05,0x10 /*Trident Specific*/ +}; + +/* BIOS mode 0x7F - 320x200x64K */ +static const unsigned char g320x200x64K_regs94[REG94]={ + 0x2D,0x27,0x28,0x90,0x2A,0x80,0xBF,0x1F, /*CRTC*/ + 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9C,0x8E,0x8F,0x50,0x40,0x96,0xB9,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x6B, /*MISC*/ + 0xE3,0x00,0xF2,0xB3, /*Trident SEQ*/ + 0x40,0x80,0x13,0x10,0x0A,0x00,0x2C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x50,0x1F,0x0F,0x01,0x14,0x00, /*Trident CRC*/ + 0x9E,0x22, /*Trident GRFX*/ + 0xC2,0x19,0x07,0x05,0x30 /*Trident Specific*/ +}; + diff --git a/src/regs/tvga9680.regs b/src/regs/tvga9680.regs new file mode 100644 index 0000000..8e9a914 --- /dev/null +++ b/src/regs/tvga9680.regs @@ -0,0 +1,417 @@ +/* TVGA 9440 code added by ARK 29-OCT-97 */ +/* (root@ark.dyn.ml.org, ark@lhq.com) [nitc?] */ +/* updated 9-NOV-97 to support more regs */ +/* this should alllow it to work on 9680's as well */ + +/* Thanks to Albert Erdmann (theone@miami.gdi.net) */ +/* for blindly testing files and mailing me results */ +/* for the 9680 registers */ + +/* The 9680 also uses 84 and 2 pads */ +/* EXT+11 and 12 are not used, because vga.c will clobber them */ +#define REG96 86 + +/* I used _regs96 for the 9680 sets so they don't */ +/* interfere with the old 8900 or 9440 sets */ + + +/* BIOS mode 0x5B - 800x600x16 */ +static const unsigned char g800x600x16_regs96[REG96]={ + 0x7F,0x63,0x64,0x82,0x69,0x13,0x6F,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x0B,0x57,0x32,0x00,0x58,0x6F,0xE3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x06, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x02,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x16,0x0F,0x0F,0x00,0x10,0x00, /*Trident CRC*/ + 0x10,0x23, /*Trident GRFX*/ + 0x4B,0x05,0x80,0x00,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x5D - 640x480x256 */ +static const unsigned char g640x480x256_regs96[REG96]={ + 0x64,0x4F,0x50,0x87,0x54,0x9C,0xF2,0x1F, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE0,0x83,0xDF,0x50,0x40,0xE0,0xF2,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xD3,0x32,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x0F,0x00,0x00,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0xA4,0x11,0x80,0x00,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x5E - 800x600x256 */ +static const unsigned char g800x600x256_regs96[REG96]={ + 0x7F,0x63,0x64,0x82,0x68,0x12,0x6F,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x0B,0x57,0x64,0x40,0x58,0x6F,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x32,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x0F,0x00,0x00,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0x4B,0x05,0x80,0x00,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x5F - 1024x768x16 */ +static const unsigned char g1024x768x16_regs96[REG96]={ + 0x9F,0x7F,0x80,0x82,0x85,0x91,0x1E,0xFD, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x03,0xFF,0x40,0x00,0x00,0x1E,0xE3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x06, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x00,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x16,0x0F,0x00,0x00,0x10,0x00, /*Trident CRC*/ + 0x14,0x23, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x62 - 1024x768x256 */ +static const unsigned char g1024x768x256_regs96[REG96]={ + 0x9F,0x7F,0x80,0x82,0x84,0x90,0x1E,0xFD, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x03,0xFF,0x80,0x40,0x00,0x1E,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x30,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x00,0x04,0x00,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x63 - 1280x1024x16 */ +static const unsigned char g1280x1024x16_regs96[REG96]={ + 0xCF,0x9F,0xA0,0x12,0xA8,0x12,0x15,0xB2, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x07,0xFF,0x50,0x00,0x01,0x15,0xE3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x06, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x00,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x84,0x17,0xCF,0x87,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x16,0x0F,0x00,0x00,0x10,0x00, /*Trident CRC*/ + 0x14,0x27, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x64 - 1280x1024x256 */ +static const unsigned char g1280x1024x256_regs96[REG96]={ + 0x65,0x4F,0x50,0x88,0x54,0xB9,0x15,0xB2, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x83,0xFF,0xA0,0x40,0x01,0x15,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x02,0xC2,0xF5, /*Trident SEQ*/ + 0x28,0x84,0x17,0xCF,0x87,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x00,0x04,0x01,0x00, /*Trident CRC*/ + 0x16,0x27, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x20 /*Trident Specific*/ +}; + +/* BIOS mode 0x65 - 1600x1200x16 */ +static const unsigned char g1600x1200x16_regs96[REG96]={ + 0x82,0x63,0x64,0x85,0x68,0x13,0x89,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x61,0x04,0x57,0x64,0x00,0x5B,0x84,0xE3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x01,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x06, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x00,0xC2,0xF5, /*Trident SEQ*/ + 0x28,0x84,0x27,0xCF,0x87,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x16,0x0F,0x00,0x00,0x10,0x00, /*Trident CRC*/ + 0x1C,0x27, /*Trident GRFX*/ + 0xBA,0x02,0x80,0x00,0x00 /*Trident Specific*/ +}; + +/* BIOS mode 0x66 - 1600x1200x256 */ +static const unsigned char g1600x1200x256_regs96[REG96]={ + 0x82,0x63,0x64,0x85,0x68,0x13,0x89,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x61,0x04,0x57,0xC8,0x40,0x5B,0x84,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x32,0xC2,0xF5, /*Trident SEQ*/ + 0x28,0x84,0x27,0xCF,0x87,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x00,0x00,0x01,0x00, /*Trident CRC*/ + 0x16,0x27, /*Trident GRFX*/ + 0xBA,0x02,0x80,0x00,0x20 /*Trident Specific*/ +}; + +/* BIOS mode 0x6B - 320x200x16M */ +static const unsigned char g320x200x16M_regs96[REG96]={ + 0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F, /*CRTC*/ + 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00, + 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x0C,0x00,0x0F,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00, /*GRFX*/ + 0xFF, + 0x03,0x00,0x03,0x00,0x02, /*SEQ*/ + 0x67, /*MISC*/ + 0xD3,0x00,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x00,0x27,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x16,0x0F,0x0F,0x00,0x09,0x00, /*Trident CRC*/ + 0x10,0x23, /*Trident GRFX*/ + 0xBA,0x02,0x80,0x00,0xD0 /*Trident Specific*/ +}; + +/* BIOS mode 0x6C - 640x480x16M */ +static const unsigned char g640x480x16M_regs96[REG96]={ + 0x64,0x4F,0x50,0x87,0x54,0x9C,0xF2,0x1F, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE0,0x83,0xDF,0x40,0x40,0xE0,0xF2,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xD3,0x30,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x1C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x00,0x00,0x09,0x00, /*Trident CRC*/ + 0x1E,0x23, /*Trident GRFX*/ + 0xA4,0x11,0x80,0x00,0xD0 /*Trident Specific*/ +}; + +/* BIOS mode 0x6D - 800x600x16M */ +static const unsigned char g800x600x16M_regs96[REG96]={ + 0x7F,0x63,0x64,0x82,0x6B,0x1B,0x72,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x8C,0x57,0x90,0x40,0x58,0x6F,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x30,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x47,0xCF,0x87,0x00,0x1C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x00,0x04,0x09,0x00, /*Trident CRC*/ + 0x1E,0x23, /*Trident GRFX*/ + 0x30,0x04,0x80,0x00,0xD0 /*Trident Specific*/ +}; + +/* BIOS mode 0x74 - 640x480x32K */ +static const unsigned char g640x480x32K_regs96[REG96]={ + 0x64,0x4F,0x50,0x87,0x54,0x9C,0xF2,0x1F, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE0,0x83,0xDF,0xA0,0x40,0xE0,0xF2,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xD3,0x32,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x0F,0x00,0x05,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0xA4,0x11,0x80,0x00,0x10 /*Trident Specific*/ +}; + +/* BIOS mode 0x75 - 640x480x64K */ +static const unsigned char g640x480x64K_regs96[REG96]={ + 0x64,0x4F,0x50,0x87,0x54,0x9C,0xF2,0x1F, /*CRTC*/ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE0,0x83,0xDF,0xA0,0x40,0xE0,0xF2,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0xEB, /*MISC*/ + 0xD3,0x32,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x0F,0x00,0x05,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0xA4,0x11,0x80,0x00,0x30 /*Trident Specific*/ +}; + +/* BIOS mode 0x76 - 800x600x32K */ +static const unsigned char g800x600x32K_regs96[REG96]={ + 0x7F,0x63,0x64,0x82,0x68,0x12,0x6F,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x0B,0x57,0xC8,0x40,0x58,0x6F,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x32,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x0F,0x00,0x05,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0x4B,0x05,0x80,0x00,0x10 /*Trident Specific*/ +}; + +/* BIOS mode 0x77 - 800x600x64K */ +static const unsigned char g800x600x64K_regs96[REG96]={ + 0x7F,0x63,0x64,0x82,0x68,0x12,0x6F,0xF0, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x0B,0x57,0xC8,0x40,0x58,0x6F,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x32,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x0F,0x00,0x05,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0x4B,0x05,0x80,0x00,0x30 /*Trident Specific*/ +}; + +/* BIOS mode 0x78 - 1024x768x32K */ +static const unsigned char g1024x768x32K_regs96[REG96]={ + 0x9F,0x7F,0x80,0x82,0x84,0x90,0x1E,0xFD, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x03,0xFF,0x00,0x40,0x00,0x1E,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x30,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x87,0x00,0x1C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x00,0x04,0x05,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x10 /*Trident Specific*/ +}; + +/* BIOS mode 0x79 - 1024x768x64K */ +static const unsigned char g1024x768x64K_regs96[REG96]={ + 0x9F,0x7F,0x80,0x82,0x84,0x90,0x1E,0xFD, /*CRTC*/ + 0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x03,0xFF,0x00,0x40,0x00,0x1E,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /*ATC*/ + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x41,0x00,0x0F,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F, /*GRFX*/ + 0xFF, + 0x03,0x01,0x0F,0x00,0x0E, /*SEQ*/ + 0x2B, /*MISC*/ + 0xD3,0x30,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x80,0x87,0xCF,0x87,0x00,0x1C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x56,0x1F,0x00,0x04,0x05,0x00, /*Trident CRC*/ + 0x16,0x23, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x30 /*Trident Specific*/ +}; + +/* BIOS mode 0x7E - 320x200x32K */ +static const unsigned char g320x200x32K_regs96[REG96]={ + 0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F, /*CRTC*/ + 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00, + 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x0C,0x00,0x0F,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00, /*GRFX*/ + 0xFF, + 0x03,0x00,0x03,0x00,0x02, /*SEQ*/ + 0x67, /*MISC*/ + 0xD3,0x00,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x00,0x27,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x16,0x0F,0x0F,0x00,0x05,0x00, /*Trident CRC*/ + 0x10,0x23, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x10 /*Trident Specific*/ +}; + +/* BIOS mode 0x7F - 320x200x64K */ +static const unsigned char g320x200x64K_regs96[REG96]={ + 0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F, /*CRTC*/ + 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00, + 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3, + 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, /*ATC*/ + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x0C,0x00,0x0F,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00, /*GRFX*/ + 0xFF, + 0x03,0x00,0x03,0x00,0x02, /*SEQ*/ + 0x67, /*MISC*/ + 0xD3,0x00,0xC2,0xF5, /*Trident SEQ*/ + 0x4A,0x00,0x27,0xCF,0x07,0x00,0x0C, /*Trident CRTC*/ + 0x00,0x00, /*Pad for 8900 in vga.c*/ + 0x16,0x0F,0x0F,0x00,0x05,0x00, /*Trident CRC*/ + 0x10,0x23, /*Trident GRFX*/ + 0x45,0x06,0x80,0x00,0x30 /*Trident Specific*/ +}; + diff --git a/src/timing.c b/src/timing.c new file mode 100644 index 0000000..5c6f836 --- /dev/null +++ b/src/timing.c @@ -0,0 +1,905 @@ +/* + * Generic mode timing module. + */ +#include + +#include "timing.h" /* Types. */ + +#include "driver.h" /* for __svgalib_monitortype (remove me) */ + +/* Standard mode timings. */ + +/* HDG: set this to use Xorg's builtin default timings for 640x480 @ 72Hz + instead of svgalib's old default timings. svgalib's timings + cause my monitor to go in powersaving mode. */ +#define USE_XORG_DEFAULT_TIMINGS + +MonitorModeTiming __svgalib_standard_timings[] = +{ +#define S __svgalib_standard_timings +/* 320x200 @ 70 Hz, 31.5 kHz hsync */ + {12588, 320, 336, 384, 400, 200, 204, 206, 225, DOUBLESCAN, S + 1}, +/* 320x200 @ 83 Hz, 37.5 kHz hsync */ + {13333, 320, 336, 384, 400, 200, 204, 206, 225, DOUBLESCAN, S + 2}, +/* 320x240 @ 60 Hz, 31.5 kHz hsync */ + {12588, 320, 336, 384, 400, 240, 245, 247, 263, DOUBLESCAN, S + 3}, +/* 320x240 @ 72Hz, 38.5 kHz hsync */ + {15000, 320, 336, 384, 400, 240, 244, 246, 261, DOUBLESCAN, S + 4}, +/* 320x400 @ 70 Hz, 31.5 kHz hsync */ + {12588, 320, 336, 384, 400, 400, 408, 412, 450, 0, S + 5}, +/* 320x400 @ 83 Hz, 37.5 kHz hsync */ + {13333, 320, 336, 384, 400, 400, 408, 412, 450, 0, S + 6}, +/* 320x480 @ 60 Hz, 31.5 kHz hsync */ + {12588, 320, 336, 384, 400, 480, 490, 494, 526, 0, S + 7}, +/* 320x480 @ 72Hz, 38.5 kHz hsync */ + {15000, 320, 336, 384, 400, 480, 488, 492, 522, 0, S + 8}, +/* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ + {18000, 400, 416, 448, 512, 300, 301, 302, 312, DOUBLESCAN, S+9}, +/* 400x300 @ 60 Hz, 37.8 kHz hsync */ + {20000, 400, 416, 480, 528, 300, 301, 303, 314, DOUBLESCAN, S+10}, +/* 400x300 @ 72 Hz, 48.0 kHz hsync*/ + {25000, 400, 424, 488, 520, 300, 319, 322, 333, DOUBLESCAN, S+11}, +/* 400x600 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ + {18000, 400, 416, 448, 512, 600, 602, 604, 624, 0, S+12}, +/* 400x600 @ 60 Hz, 37.8 kHz hsync */ + {20000, 400, 416, 480, 528, 600, 602, 606, 628, 0, S+13}, +/* 400x600 @ 72 Hz, 48.0 kHz hsync*/ + {25000, 400, 424, 488, 520, 600, 639, 644, 666, 0, S+14}, +/* 512x384 @ 67Hz */ + {19600, 512, 522, 598, 646, 384, 418, 426, 454, 0, S+15 }, +/* 512x384 @ 86Hz */ + {25175, 512, 522, 598, 646, 384, 418, 426, 454,0, S+16}, +/* 512x480 @ 55Hz */ + {19600, 512, 522, 598, 646, 480, 500, 510, 550, 0, S+17}, +/* 512x480 @ 71Hz */ + {25175, 512, 522, 598, 646, 480, 500, 510, 550,0, S+18}, +/* 640x400 at 70 Hz, 31.5 kHz hsync */ + {25175, 640, 664, 760, 800, 400, 409, 411, 450, 0, S + 19}, +/* 640x480 at 60 Hz, 31.5 kHz hsync */ + {25175, 640, 664, 760, 800, 480, 491, 493, 525, 0, S + 20}, +/* 640x480 at 72 Hz, 36.5 kHz hsync */ +#ifdef USE_XORG_DEFAULT_TIMINGS + {31500, 640, 664, 704, 832, 480, 489, 491, 520, 0, S + 21}, +#else + {31500, 640, 680, 720, 864, 480, 488, 491, 521, 0, S + 21}, +#endif +/* 800x600 at 56 Hz, 35.15 kHz hsync */ + {36000, 800, 824, 896, 1024, 600, 601, 603, 625, 0, S + 22}, +/* 800x600 at 60 Hz, 37.8 kHz hsync */ + {40000, 800, 840, 968, 1056, 600, 601, 605, 628, PHSYNC | PVSYNC, S + 23}, +/* 800x600 at 72 Hz, 48.0 kHz hsync */ + {50000, 800, 856, 976, 1040, 600, 637, 643, 666, PHSYNC | PVSYNC, S + 24}, +/* 960x720 @ 70Hz */ + {66000, 960, 984, 1112, 1248, 720, 723, 729, 756, NHSYNC | NVSYNC, S+25}, +/* 960x720* interlaced, 35.5 kHz hsync */ + {40000, 960, 984, 1192, 1216, 720, 728, 784, 817, INTERLACED, S + 26}, +/* 1024x768 at 87 Hz interlaced, 35.5 kHz hsync */ + {44900, 1024, 1048, 1208, 1264, 768, 776, 784, 817, INTERLACED, S + 27}, +/* 1024x768 at 100 Hz, 40.9 kHz hsync */ + {55000, 1024, 1048, 1208, 1264, 768, 776, 784, 817, INTERLACED, S + 28}, +/* 1024x768 at 60 Hz, 48.4 kHz hsync */ + {65000, 1024, 1032, 1176, 1344, 768, 771, 777, 806, NHSYNC | NVSYNC, S + 29}, +/* 1024x768 at 70 Hz, 56.6 kHz hsync */ + {75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, NHSYNC | NVSYNC, S + 30}, +/* 1152x864 at 59.3Hz */ + {85000, 1152, 1214, 1326, 1600, 864, 870, 885, 895, 0, S+31}, +/* 1280x1024 at 87 Hz interlaced, 51 kHz hsync */ + {80000, 1280, 1296, 1512, 1568, 1024, 1025, 1037, 1165, INTERLACED, S + 32}, +/* 1024x768 at 76 Hz, 62.5 kHz hsync */ + {85000, 1024, 1032, 1152, 1360, 768, 784, 787, 823, 0, S + 33}, +/* 1280x1024 at 60 Hz, 64.3 kHz hsync */ + {110000, 1280, 1328, 1512, 1712, 1024, 1025, 1028, 1054, 0, S + 34}, +/* 1280x1024 at 74 Hz, 78.9 kHz hsync */ + {135000, 1280, 1312, 1456, 1712, 1024, 1027, 1030, 1064, 0, S + 35}, +/* 1600x1200 at 60Hz */ + {162000, 1600, 1668, 1860, 2168, 1200, 1201, 1204, 1250, 0, S + 36}, +/* 1600x1200 at 68Hz */ + {188500, 1600, 1792, 1856, 2208, 1200, 1202, 1205, 1256, 0, S + 37}, +/* 1600x1200 at 75 Hz */ + {198000, 1600, 1616, 1776, 2112, 1200, 1201, 1204, 1250, 0, S + 38}, +/* 720x540 at 56 Hz, 35.15 kHz hsync */ + {32400, 720, 744, 808, 920, 540, 541, 543, 563, 0, S + 39}, +/* 720x540 at 60 Hz, 37.8 kHz hsync */ + {36000, 720, 760, 872, 952, 540, 541, 545, 565, 0, S + 40}, +/* 720x540 at 72 Hz, 48.0 kHz hsync */ + {45000, 720, 768, 880, 936, 540, 552, 558, 599, 0, S + 41}, +/* 1072x600 at 57 Hz interlaced, 35.5 kHz hsync */ + {44900, 1072, 1096, 1208, 1264, 600, 602, 604, 625, 0, S + 42}, +/* 1072x600 at 65 Hz, 40.9 kHz hsync */ + {55000, 1072, 1096, 1208, 1264, 600, 602, 604, 625, 0, S + 43}, +/* 1072x600 at 78 Hz, 48.4 kHz hsync */ + {65000, 1072, 1088, 1184, 1344, 600, 603, 607, 625, NHSYNC | NVSYNC, S + 44}, +/* 1072x600 at 90 Hz, 56.6 kHz hsync */ + {75000, 1072, 1096, 1200, 1328, 768, 603, 607, 625, NHSYNC | NVSYNC, S + 45}, +/* 1072x600 at 100 Hz, 62.5 kHz hsync */ + {85000, 1072, 1088, 1160, 1360, 768, 603, 607, 625, 0, NULL}, +#undef S +}; + +#define NUMBER_OF_STANDARD_MODES \ + (sizeof(__svgalib_standard_timings) / sizeof(__svgalib_standard_timings[0])) + +static MonitorModeTiming *user_timings = NULL; +static MonitorModeTiming *current_timing, *force_timing = NULL, new_timing; +static void GTF_calcTimings(double hPixels,double vLines,double freq, + int type,int wantMargins,int wantInterlace, int wantDblscan, + MonitorModeTiming *mmt); +/* + * SYNC_ALLOWANCE is in percent + * 1% corresponds to a 315 Hz deviation at 31.5 kHz, 1 Hz at 100 Hz + */ +#define SYNC_ALLOWANCE 1 + +#define INRANGE(x,y) \ + ((x) > __svgalib_##y.min * (1.0f - SYNC_ALLOWANCE / 100.0f) && \ + (x) < __svgalib_##y.max * (1.0f + SYNC_ALLOWANCE / 100.0f)) + +/* + * Check monitor spec. + */ +static int timing_within_monitor_spec(MonitorModeTiming * mmtp) +{ + float hsf; /* Horz. sync freq in Hz */ + float vsf; /* Vert. sync freq in Hz */ + + hsf = mmtp->pixelClock * 1000.0f / mmtp->HTotal; + vsf = hsf / mmtp->VTotal; + if ((mmtp->flags & INTERLACED)) + vsf *= 2.0f; + if ((mmtp->flags & DOUBLESCAN)) + vsf /= 2.0f; + + DPRINTF("hsf = %f (in:%d), vsf = %f (in:%d)\n", + hsf / 1000, (int) INRANGE(hsf, horizsync), + vsf, (int) INRANGE(vsf, vertrefresh)); + + return INRANGE(hsf, horizsync) && INRANGE(vsf, vertrefresh); +} + +void __svgalib_addusertiming(MonitorModeTiming * mmtp) +{ + MonitorModeTiming *newmmt; + + if (!(newmmt = malloc(sizeof(*newmmt)))) + return; + *newmmt = *mmtp; + if(newmmt->VSyncStartVDisplay+1)newmmt->VSyncStart=newmmt->VDisplay+1; + if(newmmt->VSyncEndVSyncStart+1)newmmt->VSyncEnd=newmmt->VSyncStart+1; + newmmt->next = user_timings; + user_timings = newmmt; +} + +/* + * The __svgalib_getmodetiming function looks up a mode in the standard mode + * timings, choosing the mode with the highest dot clock that matches + * the requested svgalib mode, and is supported by the hardware + * (card limits, and monitor type). cardlimits points to a structure + * of type CardSpecs that describes the dot clocks the card supports + * at different depths. Returns non-zero if no mode is found. + */ + +/* + * findclock is an auxilliary function that checks if a close enough + * pixel clock is provided by the card. Returns clock number if + * succesful (a special number if a programmable clock must be used), -1 + * otherwise. + */ + +/* + * Clock allowance in 1/1000ths. 10 (1%) corresponds to a 250 kHz + * deviation at 25 MHz, 1 MHz at 100 MHz + */ +#define CLOCK_ALLOWANCE 10 + +#define PROGRAMMABLE_CLOCK_MAGIC_NUMBER 0x1234 + +static int findclock(int clock, CardSpecs * cardspecs) +{ + int i; + /* Find a clock that is close enough. */ + for (i = 0; i < cardspecs->nClocks; i++) { + int diff; + diff = cardspecs->clocks[i] - clock; + if (diff < 0) + diff = -diff; + if (diff * 1000 / clock < CLOCK_ALLOWANCE) + return i; + } + /* Try programmable clocks if available. */ + if (cardspecs->flags & CLOCK_PROGRAMMABLE) { + int diff; + diff = cardspecs->matchProgrammableClock(clock) - clock; + if (diff < 0) + diff = -diff; + if (diff * 1000 / clock < CLOCK_ALLOWANCE) + return PROGRAMMABLE_CLOCK_MAGIC_NUMBER; + } + /* No close enough clock found. */ + return -1; +} + +static MonitorModeTiming *search_mode(MonitorModeTiming * timings, + int maxclock, + ModeInfo * modeinfo, + CardSpecs * cardspecs) +{ + int bestclock = 0; + MonitorModeTiming *besttiming = NULL, *t; + + /* + * bestclock is the highest pixel clock found for the resolution + * in the mode timings, within the spec of the card and + * monitor. + * besttiming holds a pointer to timing with this clock. + */ + + /* Search the timings for the best matching mode. */ + for (t = timings; t; t = t->next) + if (t->HDisplay == modeinfo->width + && t->VDisplay == modeinfo->height + && ( (!(t->flags&INTERLACED)) || (!(cardspecs->flags&NO_INTERLACE)) ) + && timing_within_monitor_spec(t) + && t->pixelClock <= maxclock + && t->pixelClock > bestclock + && cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel, + t->pixelClock, + t->HTotal) + <= cardspecs->maxHorizontalCrtc + /* Find the clock (possibly scaled by mapClock). */ + && findclock(cardspecs->mapClock(modeinfo->bitsPerPixel, + t->pixelClock), cardspecs) != -1 + ) { + bestclock = t->pixelClock; + besttiming = t; + } + return besttiming; +} + +int __svgalib_getmodetiming(ModeTiming * modetiming, ModeInfo * modeinfo, + CardSpecs * cardspecs) +{ + int maxclock, desiredclock; + MonitorModeTiming *besttiming=NULL; + + if(force_timing){ + if(timing_within_monitor_spec(force_timing) && + force_timing->HDisplay == modeinfo->width && + force_timing->VDisplay == modeinfo->height) + { + besttiming=force_timing; + }; + }; + + /* Get the maximum pixel clock for the depth of the requested mode. */ + if (modeinfo->bitsPerPixel == 4) + maxclock = cardspecs->maxPixelClock4bpp; + else if (modeinfo->bitsPerPixel == 8) + maxclock = cardspecs->maxPixelClock8bpp; + else if (modeinfo->bitsPerPixel == 16) { + if ((cardspecs->flags & NO_RGB16_565) + && modeinfo->greenWeight == 6) + return 1; /* No 5-6-5 RGB. */ + maxclock = cardspecs->maxPixelClock16bpp; + } else if (modeinfo->bitsPerPixel == 24) + maxclock = cardspecs->maxPixelClock24bpp; + else if (modeinfo->bitsPerPixel == 32) + maxclock = cardspecs->maxPixelClock32bpp; + else + maxclock = 0; + + /* + * Check user defined timings first. + * If there is no match within these, check the standard timings. + */ + if(!besttiming) + besttiming = search_mode(user_timings, maxclock, modeinfo, cardspecs); + if (!besttiming) { + besttiming = search_mode(__svgalib_standard_timings, maxclock, modeinfo, cardspecs); + if (!besttiming) + return 1; + } + /* + * Copy the selected timings into the result, which may + * be adjusted for the chipset. + */ + + modetiming->flags = besttiming->flags; + modetiming->pixelClock = besttiming->pixelClock; /* Formal clock. */ + + /* + * We know a close enough clock is available; the following is the + * exact clock that fits the mode. This is probably different + * from the best matching clock that will be programmed. + */ + desiredclock = cardspecs->mapClock(modeinfo->bitsPerPixel, + besttiming->pixelClock); + + /* Fill in the best-matching clock that will be programmed. */ + modetiming->selectedClockNo = findclock(desiredclock, cardspecs); + if (modetiming->selectedClockNo == PROGRAMMABLE_CLOCK_MAGIC_NUMBER) { + modetiming->programmedClock = + cardspecs->matchProgrammableClock(desiredclock); + modetiming->flags |= USEPROGRCLOCK; + } else + modetiming->programmedClock = cardspecs->clocks[ + modetiming->selectedClockNo]; + modetiming->HDisplay = besttiming->HDisplay; + modetiming->HSyncStart = besttiming->HSyncStart; + modetiming->HSyncEnd = besttiming->HSyncEnd; + modetiming->HTotal = besttiming->HTotal; + if (cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel, + modetiming->programmedClock, + besttiming->HTotal) + != besttiming->HTotal) { + /* Horizontal CRTC timings are scaled in some way. */ + modetiming->CrtcHDisplay = + cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel, + modetiming->programmedClock, + besttiming->HDisplay); + modetiming->CrtcHSyncStart = + cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel, + modetiming->programmedClock, + besttiming->HSyncStart); + modetiming->CrtcHSyncEnd = + cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel, + modetiming->programmedClock, + besttiming->HSyncEnd); + modetiming->CrtcHTotal = + cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel, + modetiming->programmedClock, + besttiming->HTotal); + modetiming->flags |= HADJUSTED; + } else { + modetiming->CrtcHDisplay = besttiming->HDisplay; + modetiming->CrtcHSyncStart = besttiming->HSyncStart; + modetiming->CrtcHSyncEnd = besttiming->HSyncEnd; + modetiming->CrtcHTotal = besttiming->HTotal; + } + modetiming->VDisplay = besttiming->VDisplay; + modetiming->VSyncStart = besttiming->VSyncStart; + modetiming->VSyncEnd = besttiming->VSyncEnd; + modetiming->VTotal = besttiming->VTotal; + if (modetiming->flags & DOUBLESCAN){ + modetiming->VDisplay <<= 1; + modetiming->VSyncStart <<= 1; + modetiming->VSyncEnd <<= 1; + modetiming->VTotal <<= 1; + } + modetiming->CrtcVDisplay = modetiming->VDisplay; + modetiming->CrtcVSyncStart = modetiming->VSyncStart; + modetiming->CrtcVSyncEnd = modetiming->VSyncEnd; + modetiming->CrtcVTotal = modetiming->VTotal; + if (((modetiming->flags & INTERLACED) + && (cardspecs->flags & INTERLACE_DIVIDE_VERT)) + || (modetiming->VTotal >= 1024 + && (cardspecs->flags & GREATER_1024_DIVIDE_VERT))) { + /* + * Card requires vertical CRTC timing to be halved for + * interlaced modes, or for all modes with vertical + * timing >= 1024. + */ + modetiming->CrtcVDisplay /= 2; + modetiming->CrtcVSyncStart /= 2; + modetiming->CrtcVSyncEnd /= 2; + modetiming->CrtcVTotal /= 2; + modetiming->flags |= VADJUSTED; + } + current_timing=besttiming; + return 0; /* Succesful. */ +} + +int vga_getcurrenttiming(int *pixelClock, + int *HDisplay, + int *HSyncStart, + int *HSyncEnd, + int *HTotal, + int *VDisplay, + int *VSyncStart, + int *VSyncEnd, + int *VTotal, + int *flags) +{ + if(current_timing){ + *pixelClock=current_timing->pixelClock; + *HDisplay=current_timing->HDisplay; + *HSyncStart=current_timing->HSyncStart; + *HSyncEnd=current_timing->HSyncEnd; + *HTotal=current_timing->HTotal; + *VDisplay=current_timing->VDisplay; + *VSyncStart=current_timing->VSyncStart; + *VSyncEnd=current_timing->VSyncEnd; + *VTotal=current_timing->VTotal; + *flags=current_timing->flags; + return 0; + } + return 1; +}; + +int vga_changetiming(int pixelClock, + int HDisplay, + int HSyncStart, + int HSyncEnd, + int HTotal, + int VDisplay, + int VSyncStart, + int VSyncEnd, + int VTotal, + int flags) { + if(current_timing){ + new_timing=*current_timing; + new_timing.pixelClock+=pixelClock; + new_timing.HDisplay+=HDisplay; + new_timing.HSyncStart+=HSyncStart; + new_timing.HSyncEnd+=HSyncEnd; + new_timing.HTotal+=HTotal; + new_timing.VDisplay+=VDisplay; + new_timing.VSyncStart+=VSyncStart; + new_timing.VSyncEnd+=VSyncEnd; + new_timing.VTotal+=VTotal; + force_timing=&new_timing; + vga_setmode(CM|0x8000); + force_timing=NULL; + }; + + return 1; +}; + +static int find_up_timing(int x, int y, int *bestx, int *besty, MonitorModeTiming **bestmodetiming) +{ + MonitorModeTiming *t; + int bestclock=0; + int mode_ar; + + *bestmodetiming=NULL; + *bestx=*besty=4096; + for (t = user_timings; t; t = t->next) { + if ((mode_ar=1000*t->VDisplay/t->HDisplay)<=765 + && mode_ar>=735 + && t->HDisplay >= x + && t->VDisplay >= y + && timing_within_monitor_spec(t) + && t->HDisplay <= *bestx + && t->VDisplay <= *besty + && t->pixelClock>=bestclock + ) { + bestclock = t->pixelClock; + *bestx=t->HDisplay; + *besty=t->VDisplay; + *bestmodetiming = t; + }; + }; + for (t = __svgalib_standard_timings; t; t = t->next) { + if (t->HDisplay >= x + && t->VDisplay >= y + && timing_within_monitor_spec(t) + && t->HDisplay <= *bestx + && t->VDisplay <= *besty + && t->pixelClock>=bestclock + ) { + bestclock = t->pixelClock; + *bestx=t->HDisplay; + *besty=t->VDisplay; + *bestmodetiming = t; + }; + }; + return *bestmodetiming!=NULL; +}; + +static int find_down_timing(int x, int y, int *bestx, int *besty, MonitorModeTiming **bestmodetiming) +{ + MonitorModeTiming *t; + int bestclock=0; + int mode_ar; + + *bestmodetiming=NULL; + *bestx=*besty=0; + for (t = user_timings; t; t = t->next) { + if ((mode_ar=1000*t->VDisplay/t->HDisplay)<=765 + && mode_ar>=735 + && t->HDisplay <= x + && t->VDisplay <= y + && timing_within_monitor_spec(t) + && t->HDisplay >= *bestx + && t->VDisplay >= *besty + && t->pixelClock>=bestclock + ) { + bestclock = t->pixelClock; + *bestx=t->HDisplay; + *besty=t->VDisplay; + *bestmodetiming = t; + }; + }; + for (t = __svgalib_standard_timings; t; t = t->next) { + if (t->HDisplay <= x + && t->VDisplay <= y + && timing_within_monitor_spec(t) + && t->HDisplay >= *bestx + && t->VDisplay >= *besty + && t->pixelClock>=bestclock + ) { + bestclock = t->pixelClock; + *bestx=t->HDisplay; + *besty=t->VDisplay; + *bestmodetiming = t; + }; + }; + return *bestmodetiming!=NULL; +}; + +int vga_guesstiming(int x, int y, int clue, int arg) +{ +/* This functions tries to add timings that fit a specific mode, + by changing the timings of a similar mode + +currently only works for x:y = 4:3, clue means: +0- scale down timing of a higher res mode +1- scale up timings of a lower res mode +*/ + + MonitorModeTiming mmt, *bestmodetiming = NULL ; + int bestx, besty, flag, mx, my /*, bestclock */ ; + + int aspect_ratio=1000*y/x; + switch(clue) { + case 0: /* 0,1 only 4:3 ratio, find close mode, and up/down scale timing */ + case 1: + if((aspect_ratio>765)||(aspect_ratio<735))return 0; + if(clue==0)find_up_timing(x,y,&bestx,&besty,&bestmodetiming); + if(clue==1)find_down_timing(x,y,&bestx,&besty,&bestmodetiming); + if(bestmodetiming){ + + mmt=*bestmodetiming; + + mmt.pixelClock=(mmt.pixelClock*x)/bestx; + mmt.HDisplay=x; + mmt.VDisplay=y; + mmt.HSyncStart=(mmt.HSyncStart*x)/bestx; + mmt.HSyncEnd=(mmt.HSyncEnd*x)/bestx; + mmt.HTotal=(mmt.HTotal*x)/bestx; + mmt.VSyncStart=(mmt.VSyncStart*x)/bestx; + mmt.VSyncEnd=(mmt.VSyncEnd*x)/bestx; + mmt.VTotal=(mmt.VTotal*x)/bestx; + __svgalib_addusertiming(&mmt); + return 1; + }; + break; + case 2: /* Use GTF, caller provides all parameters. */ + flag = arg>>16; + GTF_calcTimings(x , y, arg&0xffff, flag&3, flag&4, flag&8, flag&16, &mmt); + __svgalib_addusertiming(&mmt); + return 1; + + + case 256: /* 256,257: find a 4:3 mode with y close to requested, and */ + case 257: /* up/down scale timing */ + mx=y*4/3; + if((clue&1)==0)find_up_timing(mx,y,&bestx,&besty,&bestmodetiming); + if((clue&1)==1)find_down_timing(mx,y,&bestx,&besty,&bestmodetiming); + if(bestmodetiming){ + + mmt=*bestmodetiming; + + mmt.pixelClock=(mmt.pixelClock*x)/bestx; + mmt.HDisplay=x; + mmt.HSyncStart=(mmt.HSyncStart*x)/bestx; + mmt.HSyncEnd=(mmt.HSyncEnd*x)/bestx; + mmt.HTotal=(mmt.HTotal*x)/bestx; + mmt.VDisplay=y; + mmt.VSyncStart=(mmt.VSyncStart*mx)/bestx; + mmt.VSyncEnd=(mmt.VSyncEnd*mx)/bestx; + mmt.VTotal=(mmt.VTotal*mx)/bestx; + __svgalib_addusertiming(&mmt); + return 1; + }; + break; + case 258: /* 258,259: find a 4:3 mode with x close to requested, and */ + case 259: /* up/down scale timing */ + my=(x*3)>>2; + if((clue&1)==0)find_up_timing(x,my,&bestx,&besty,&bestmodetiming); + if((clue&1)==1)find_down_timing(x,my,&bestx,&besty,&bestmodetiming); + if(bestmodetiming){ + + mmt=*bestmodetiming; + + mmt.pixelClock=(mmt.pixelClock*x)/bestx; + mmt.HDisplay=x; + mmt.HSyncStart=(mmt.HSyncStart*x)/bestx; + mmt.HSyncEnd=(mmt.HSyncEnd*x)/bestx; + mmt.HTotal=(mmt.HTotal*x)/bestx; + mmt.VDisplay=y; + mmt.VSyncStart=(mmt.VSyncStart*y)/besty; + mmt.VSyncEnd=(mmt.VSyncEnd*y)/besty; + mmt.VTotal=(mmt.VTotal*y)/besty; + __svgalib_addusertiming(&mmt); + return 1; + }; + break; + }; + return 0; +}; + +/* Everything from here to the end of the file is copyright by +scitechsoft. See their original program in utils/gtf subdirectory */ + +typedef struct { + double margin; /* Margin size as percentage of display */ + double cellGran; /* Character cell granularity */ + double minPorch; /* Minimum front porch in lines/chars */ + double vSyncRqd; /* Width of V sync in lines */ + double hSync; /* Width of H sync as percent of total */ + double minVSyncBP; /* Minimum vertical sync + back porch (us) */ + double m; /* Blanking formula gradient */ + double c; /* Blanking formula offset */ + double k; /* Blanking formula scaling factor */ + double j; /* Blanking formula scaling factor weight */ +} GTF_constants; + +static GTF_constants GC = { + 1.8, /* Margin size as percentage of display */ + 8, /* Character cell granularity */ + 1, /* Minimum front porch in lines/chars */ + 3, /* Width of V sync in lines */ + 8, /* Width of H sync as percent of total */ + 550, /* Minimum vertical sync + back porch (us) */ + 600, /* Blanking formula gradient */ + 40, /* Blanking formula offset */ + 128, /* Blanking formula scaling factor */ + 20, /* Blanking formula scaling factor weight */ +}; + +static double round(double v) +{ + double u=v; + int j; + + if(u<0) u=-u; + u=u+0.5; + j=u; + if(v<0) j=-j; + + return j; +} + +static double sqrt(double u) +{ + double v,w; + int i; + v=0; + + if(u==0) return 0; + if(u<0) u=-u; + w=u; + if(u<1) w=1; + for(i=0;i<50;i++){ + w=w/2; + if(v*v==u)break; + if(v*vu)v=v-w; + }; + + return v; +} +static void GetInternalConstants(GTF_constants *c) +{ + c->margin = GC.margin; + c->cellGran = round(GC.cellGran); + c->minPorch = round(GC.minPorch); + c->vSyncRqd = round(GC.vSyncRqd); + c->hSync = GC.hSync; + c->minVSyncBP = GC.minVSyncBP; + if (GC.k == 0) + c->k = 0.001; + else + c->k = GC.k; + c->m = (c->k / 256) * GC.m; + c->c = (GC.c - GC.j) * (c->k / 256) + GC.j; + c->j = GC.j; +} + +static void GTF_calcTimings(double hPixels,double vLines,double freq, + int type,int wantMargins,int wantInterlace, int wantDblscan, + MonitorModeTiming *mmt) +{ + double interlace,vFieldRate,hPeriod=0; + double topMarginLines,botMarginLines; + double leftMarginPixels,rightMarginPixels; + double hPeriodEst=0,vSyncBP=0,vBackPorch=0; + double vTotalLines=0,vFieldRateEst; + double hTotalPixels,hTotalActivePixels,hBlankPixels; + double idealDutyCycle=0,hSyncWidth,hSyncBP,hBackPorch; + double idealHPeriod; + double vFreq,hFreq,dotClock; + GTF_constants c; + + /* Get rounded GTF constants used for internal calculations */ + GetInternalConstants(&c); + + /* Move input parameters into appropriate variables */ + vFreq = hFreq = dotClock = freq; + + /* Round pixels to character cell granularity */ + hPixels = round(hPixels / c.cellGran) * c.cellGran; + + /* For interlaced mode halve the vertical parameters, and double + * the required field refresh rate. + */ + + if(wantDblscan) vLines = vLines * 2; + if (wantInterlace) { + vLines = round(vLines / 2); + vFieldRate = vFreq * 2; + dotClock = dotClock * 2; + interlace = 0.5; + } + else { + vFieldRate = vFreq; + interlace = 0; + } + + /* Determine the lines for margins */ + if (wantMargins) { + topMarginLines = round(c.margin / 100 * vLines); + botMarginLines = round(c.margin / 100 * vLines); + } + else { + topMarginLines = 0; + botMarginLines = 0; + } + + if (type != GTF_lockPF) { + if (type == GTF_lockVF) { + /* Estimate the horizontal period */ + hPeriodEst = ((1/vFieldRate) - (c.minVSyncBP/1000000)) / + (vLines + (2*topMarginLines) + c.minPorch + interlace) * 1000000; + + /* Find the number of lines in vSync + back porch */ + vSyncBP = round(c.minVSyncBP / hPeriodEst); + } + else if (type == GTF_lockHF) { + /* Find the number of lines in vSync + back porch */ + vSyncBP = round((c.minVSyncBP * hFreq) / 1000); + } + + /* Find the number of lines in the V back porch alone */ + vBackPorch = vSyncBP - c.vSyncRqd; + + /* Find the total number of lines in the vertical period */ + vTotalLines = vLines + topMarginLines + botMarginLines + vSyncBP + + interlace + c.minPorch; + + if (type == GTF_lockVF) { + /* Estimate the vertical frequency */ + vFieldRateEst = 1000000 / (hPeriodEst * vTotalLines); + + /* Find the actual horizontal period */ + hPeriod = (hPeriodEst * vFieldRateEst) / vFieldRate; + + /* Find the actual vertical field frequency */ + vFieldRate = 1000000 / (hPeriod * vTotalLines); + } + else if (type == GTF_lockHF) { + /* Find the actual vertical field frequency */ + vFieldRate = (hFreq / vTotalLines) * 1000; + } + } + + /* Find the number of pixels in the left and right margins */ + if (wantMargins) { + leftMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran); + rightMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran); + } + else { + leftMarginPixels = 0; + rightMarginPixels = 0; + } + + /* Find the total number of active pixels in image + margins */ + hTotalActivePixels = hPixels + leftMarginPixels + rightMarginPixels; + + if (type == GTF_lockVF) { + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - ((c.m * hPeriod) / 1000); + } + else if (type == GTF_lockHF) { + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - (c.m / hFreq); + } + else if (type == GTF_lockPF) { + /* Find ideal horizontal period from blanking duty cycle formula */ + idealHPeriod = (((c.c - 100) + (sqrt(((100-c.c)*(100-c.c)) + + (0.4 * c.m * (hTotalActivePixels + rightMarginPixels + + leftMarginPixels) / dotClock)))) / (2 * c.m)) * 1000; + + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - ((c.m * idealHPeriod) / 1000); + } + + /* Find the number of pixels in blanking time */ + hBlankPixels = round((hTotalActivePixels * idealDutyCycle) / + ((100 - idealDutyCycle) * 2 * c.cellGran)) * (2 * c.cellGran); + + /* Find the total number of pixels */ + hTotalPixels = hTotalActivePixels + hBlankPixels; + + /* Find the horizontal back porch */ + hBackPorch = round((hBlankPixels / 2) / c.cellGran) * c.cellGran; + + /* Find the horizontal sync width */ + hSyncWidth = round(((c.hSync/100) * hTotalPixels) / c.cellGran) * c.cellGran; + + /* Find the horizontal sync + back porch */ + hSyncBP = hBackPorch + hSyncWidth; + + if (type == GTF_lockPF) { + /* Find the horizontal frequency */ + hFreq = (dotClock / hTotalPixels) * 1000; + + /* Find the horizontal period */ + hPeriod = 1000 / hFreq; + + /* Find the number of lines in vSync + back porch */ + vSyncBP = round((c.minVSyncBP * hFreq) / 1000); + + /* Find the number of lines in the V back porch alone */ + vBackPorch = vSyncBP - c.vSyncRqd; + + /* Find the total number of lines in the vertical period */ + vTotalLines = vLines + topMarginLines + botMarginLines + vSyncBP + + interlace + c.minPorch; + + /* Find the actual vertical field frequency */ + vFieldRate = (hFreq / vTotalLines) * 1000; + } + else { + if (type == GTF_lockVF) { + /* Find the horizontal frequency */ + hFreq = 1000 / hPeriod; + } + else if (type == GTF_lockHF) { + /* Find the horizontal frequency */ + hPeriod = 1000 / hFreq; + } + + /* Find the pixel clock frequency */ + dotClock = hTotalPixels / hPeriod; + } + + /* Find the vertical frame frequency */ + if (wantInterlace) { + vFreq = vFieldRate / 2; + } + else + vFreq = vFieldRate; + + mmt->pixelClock = dotClock; + + /* Determine the vertical timing parameters */ + mmt->HTotal = hTotalPixels; + mmt->HDisplay = hTotalActivePixels; + mmt->HSyncStart = mmt->HTotal - hSyncBP; + mmt->HSyncEnd = mmt->HTotal - hBackPorch; + + /* Determine the vertical timing parameters */ + mmt->VTotal = vTotalLines; + mmt->VDisplay = vLines; + mmt->VSyncStart = mmt->VTotal - vSyncBP; + mmt->VSyncEnd = mmt->VTotal - vBackPorch; + + if(wantDblscan) { + mmt->VTotal >>= 1; + mmt->VDisplay >>= 1 ; + mmt->VSyncStart >>= 1 ; + mmt->VSyncEnd >>= 1 ; + }; + + if(wantInterlace) { + mmt->VTotal <<= 1; + mmt->VDisplay <<= 1 ; + mmt->VSyncStart <<= 1 ; + mmt->VSyncEnd <<= 1 ; + }; + + mmt->flags = NHSYNC | PVSYNC | ((wantInterlace) ? INTERLACED : 0) + | ((wantDblscan) ? DOUBLESCAN : 0); +} + diff --git a/src/timing.h b/src/timing.h new file mode 100644 index 0000000..6e457c0 --- /dev/null +++ b/src/timing.h @@ -0,0 +1,170 @@ + +#ifndef TIMING_H +#define TIMING_H + +/* + * Generic mode timing module. + */ + +/* This is the type of a basic (monitor-oriented) mode timing. */ +typedef struct _MMT_S MonitorModeTiming; +struct _MMT_S { + int pixelClock; /* Pixel clock in kHz. */ + int HDisplay; /* Horizontal Timing. */ + int HSyncStart; + int HSyncEnd; + int HTotal; + int VDisplay; /* Vertical Timing. */ + int VSyncStart; + int VSyncEnd; + int VTotal; + int flags; + MonitorModeTiming *next; +}; + +/* This is for the hardware (card)-adjusted mode timing. */ +typedef struct { + int pixelClock; /* Pixel clock in kHz. */ + int HDisplay; /* Horizontal Timing. */ + int HSyncStart; + int HSyncEnd; + int HTotal; + int VDisplay; /* Vertical Timing. */ + int VSyncStart; + int VSyncEnd; + int VTotal; + int flags; +/* The following field are optionally filled in according to card */ +/* specific parameters. */ + int programmedClock; /* Actual clock to be programmed. */ + int selectedClockNo; /* Index number of fixed clock used. */ + int CrtcHDisplay; /* Actual programmed horizontal CRTC timing. */ + int CrtcHSyncStart; + int CrtcHSyncEnd; + int CrtcHTotal; + int CrtcVDisplay; /* Actual programmed vertical CRTC timing. */ + int CrtcVSyncStart; + int CrtcVSyncEnd; + int CrtcVTotal; +} ModeTiming; + +/* Flags in ModeTiming. */ +#define PHSYNC 0x1 /* Positive hsync polarity. */ +#define NHSYNC 0x2 /* Negative hsync polarity. */ +#define PVSYNC 0x4 /* Positive vsync polarity. */ +#define NVSYNC 0x8 /* Negative vsync polarity. */ +#define INTERLACED 0x10 /* Mode has interlaced timing. */ +#define DOUBLESCAN 0x20 /* Mode uses VGA doublescan (see note). */ +#define HADJUSTED 0x40 /* Horizontal CRTC timing adjusted. */ +#define VADJUSTED 0x80 /* Vertical CRTC timing adjusted. */ +#define USEPROGRCLOCK 0x100 /* A programmable clock is used. */ +#define TVMODE 0x200 +#define TVPAL 0x400 +#define TVNTSC 0x800 + +/* + * Note: Double scan implies that each scanline is displayed twice. The + * vertical CRTC timings are programmed to double the effective vertical + * resolution (the CRT still displays 400 scanlines for a 200 line + * resolution). + */ + +/* Cards specifications. */ +typedef struct { + int videoMemory; /* Video memory in kilobytes. */ + int maxPixelClock4bpp; /* Maximum pixel clocks in kHz for each depth. */ + int maxPixelClock8bpp; + int maxPixelClock16bpp; + int maxPixelClock24bpp; + int maxPixelClock32bpp; + int flags; /* Flags (e.g. programmable clocks). */ + int nClocks; /* Number of fixed clocks. */ + int *clocks; /* Pointer to array of fixed clock values. */ + int maxHorizontalCrtc; + /* + * The following function maps from a pixel clock and depth to + * the raw clock frequency required. + */ + int (*mapClock) (int bpp, int pixelclock); + /* + * The following function maps from a requested clock value + * to the closest clock that the programmable clock device + * can produce. + */ + int (*matchProgrammableClock) (int desiredclock); + /* + * The following function maps from a pixel clock, depth and + * horizontal CRTC timing parameter to the horizontal timing + * that has to be programmed. + */ + int (*mapHorizontalCrtc) (int bpp, int pixelclock, int htiming); +} CardSpecs; + +/* Card flags. */ +/* The card has programmable clocks (matchProgrammableClock is valid). */ +#define CLOCK_PROGRAMMABLE 0x1 +/* For interlaced modes, the vertical timing must be divided by two. */ +#define INTERLACE_DIVIDE_VERT 0x2 +/* For modes with vertical timing greater or equal to 1024, vertical */ +/* timing must be divided by two. */ +#define GREATER_1024_DIVIDE_VERT 0x4 +/* The DAC doesn't support 64K colors (5-6-5) at 16bpp, just 5-5-5. */ +#define NO_RGB16_565 0x8 +/* Card (or driver) can't do interlaced modes */ +#define NO_INTERLACE 0x10 +/* Don't have banked memory - emulated with mmap from linear memory */ +#define EMULATE_BANK 0x20 + +/* Mode info. */ +typedef struct { +/* Basic properties. */ + short width; /* Width of the screen in pixels. */ + short height; /* Height of the screen in pixels. */ + char bytesPerPixel; /* Number of bytes per pixel. */ + char bitsPerPixel; /* Number of bits per pixel. */ + char colorBits; /* Number of significant bits in pixel. */ + char __padding1; +/* Truecolor pixel specification. */ + char redWeight; /* Number of significant red bits. */ + char greenWeight; /* Number of significant green bits. */ + char blueWeight; /* Number of significant blue bits. */ + char __padding2; + char redOffset; /* Offset in bits of red value into pixel. */ + char blueOffset; /* Offset of green value. */ + char greenOffset; /* Offset of blue value. */ + char __padding3; + unsigned redMask; /* Pixel mask of read value. */ + unsigned blueMask; /* Pixel mask of green value. */ + unsigned greenMask; /* Pixel mask of blue value. */ +/* Structural properties of the mode. */ + int lineWidth; /* Offset in bytes between scanlines. */ + short realWidth; /* Real on-screen resolution. */ + short realHeight; /* Real on-screen resolution. */ + int flags; +} ModeInfo; + + +/* Prototypes of functions defined in timing.c. */ + +/* + * This function will look up mode timings for a mode matching ModeInfo + * that is within monitor spec and matches the capabilities (clocks etc.) + * of the card. + */ + +int __svgalib_getmodetiming( + ModeTiming *, /* Resulting mode timing. */ + ModeInfo *, /* Structural mode info. */ + CardSpecs * /* Card specs (dot clocks etc.). */ +); + +void __svgalib_addusertiming( + MonitorModeTiming * +); + +/* GTF constants */ +#define GTF_lockVF 1 /* Lock to vertical frequency */ +#define GTF_lockHF 2 /* Lock to horizontal frequency */ +#define GTF_lockPF 3 /* Lock to pixel clock frequency*/ + +#endif diff --git a/src/vga.c b/src/vga.c new file mode 100644 index 0000000..00b50c9 --- /dev/null +++ b/src/vga.c @@ -0,0 +1,4440 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright (C) 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ +/* Changes by Michael Weller. */ +/* Modified by Don Secrest to include Tseng ET6000 handling */ +/* Changes around the config things by 101 (Attila Lendvai) */ + +/* The code is a bit of a mess; also note that the drawing functions */ +/* are not speed optimized (the gl functions are much faster). */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef INCLUDE_VESA_DRIVER +#include +#include "lrmi.h" +#endif + +#include +#include +#include "libvga.h" +#include "driver.h" +#include "vgapci.h" +#include "vganullio.h" +#include "vgaio.h" +#include "vga_console.h" +#include "mouse/vgamouse.h" +#include "keyboard/vgakeyboard.h" +#include "vgaversion.h" +#include "svgalib_helper.h" + +/* Delay in microseconds after a mode is set (screen is blanked during this */ +/* time), allows video signals to stabilize */ +#define MODESWITCHDELAY 150000 + +/* Define this to disable video output during mode switches, in addition to */ +/* 'turning off the screen', which is always done. */ +/* Doesn't look very nice on my Cirrus. */ +/* #define DISABLE_VIDEO_OUTPUT */ + +/* #define DONT_WAIT_VC_ACTIVE */ + +/* Use /dev/tty instead of /dev/tty0 (the previous behaviour may have been + * silly). */ +#define USE_DEVTTY + +//#define SET_TERMIO + +#define SETSIG(sa, sig, fun) {\ + sa.sa_handler = fun; \ + sa.sa_flags = SA_RESTART; \ + zero_sa_mask(&(sa.sa_mask)); \ + sigaction(sig, &sa, NULL); \ +} + +#undef SAVEREGS +#ifdef SAVEREGS +static unsigned char graph_regs[16384]; +#endif + +/* variables used to shift between monchrome and color emulation */ +int __svgalib_CRT_I; /* current CRT index register address */ +int __svgalib_CRT_D; /* current CRT data register address */ +int __svgalib_IS1_R; /* current input status register address */ +static int color_text; /* true if color text emulation */ + +uint8_t *BANKED_POINTER=NULL, *LINEAR_POINTER=NULL; +uint8_t *MMIO_POINTER; +uint8_t *SPARSE_MMIO; +static int mmio_mapped=0, mem_mapped=0; +unsigned long __svgalib_banked_mem_base, __svgalib_banked_mem_size; +unsigned long __svgalib_mmio_base, __svgalib_mmio_size=0; +unsigned long __svgalib_linear_mem_base=0, __svgalib_linear_mem_size=0; +unsigned long __svgalib_linear_mem_phys_addr=0; +int __svgalib_linear_mem_fd = -1; + +#ifdef _SVGALIB_LRMI +LRMI_callbacks * __svgalib_LRMI_callbacks = NULL; +#endif + +/* If == 0 then nothing is defined by the user... */ +int __svgalib_default_mode = 0; + +struct vgainfo infotable[] = +{ + {80, 25, 16, 160, 0}, /* VGAlib VGA modes */ + {320, 200, 16, 40, 0}, + {640, 200, 16, 80, 0}, + {640, 350, 16, 80, 0}, + {640, 480, 16, 80, 0}, + {320, 200, 256, 320, 1}, + {320, 240, 256, 80, 0}, + {320, 400, 256, 80, 0}, + {360, 480, 256, 90, 0}, + {640, 480, 2, 80, 0}, + + {640, 480, 256, 640, 1}, /* VGAlib SVGA modes */ + {800, 600, 256, 800, 1}, + {1024, 768, 256, 1024, 1}, + {1280, 1024, 256, 1280, 1}, + + {320, 200, 1 << 15, 640, 2}, /* Hicolor/truecolor modes */ + {320, 200, 1 << 16, 640, 2}, + {320, 200, 1 << 24, 320 * 3, 3}, + {640, 480, 1 << 15, 640 * 2, 2}, + {640, 480, 1 << 16, 640 * 2, 2}, + {640, 480, 1 << 24, 640 * 3, 3}, + {800, 600, 1 << 15, 800 * 2, 2}, + {800, 600, 1 << 16, 800 * 2, 2}, + {800, 600, 1 << 24, 800 * 3, 3}, + {1024, 768, 1 << 15, 1024 * 2, 2}, + {1024, 768, 1 << 16, 1024 * 2, 2}, + {1024, 768, 1 << 24, 1024 * 3, 3}, + {1280, 1024, 1 << 15, 1280 * 2, 2}, + {1280, 1024, 1 << 16, 1280 * 2, 2}, + {1280, 1024, 1 << 24, 1280 * 3, 3}, + + {800, 600, 16, 100, 0}, /* SVGA 16-color modes */ + {1024, 768, 16, 128, 0}, + {1280, 1024, 16, 160, 0}, + + {720, 348, 2, 90, 0}, /* Hercules emulation mode */ + + {320, 200, 1 << 24, 320 * 4, 4}, + {640, 480, 1 << 24, 640 * 4, 4}, + {800, 600, 1 << 24, 800 * 4, 4}, + {1024, 768, 1 << 24, 1024 * 4, 4}, + {1280, 1024, 1 << 24, 1280 * 4, 4}, + + {1152, 864, 16, 144, 0}, + {1152, 864, 256, 1152, 1}, + {1152, 864, 1 << 15, 1152 * 2, 2}, + {1152, 864, 1 << 16, 1152 * 2, 2}, + {1152, 864, 1 << 24, 1152 * 3, 3}, + {1152, 864, 1 << 24, 1152 * 4, 4}, + + {1600, 1200, 16, 200, 0}, + {1600, 1200, 256, 1600, 1}, + {1600, 1200, 1 << 15, 1600 * 2, 2}, + {1600, 1200, 1 << 16, 1600 * 2, 2}, + {1600, 1200, 1 << 24, 1600 * 3, 3}, + {1600, 1200, 1 << 24, 1600 * 4, 4}, + + {320, 240, 256, 320, 1}, + {320, 240, 1<<15, 320*2, 2}, + {320, 240, 1<<16, 320*2, 2}, + {320, 240, 1<<24, 320*3, 3}, + {320, 240, 1<<24, 320*4, 4}, + + {400, 300, 256, 400, 1}, + {400, 300, 1<<15, 400*2, 2}, + {400, 300, 1<<16, 400*2, 2}, + {400, 300, 1<<24, 400*3, 3}, + {400, 300, 1<<24, 400*4, 4}, + + {512, 384, 256, 512, 1}, + {512, 384, 1<<15, 512*2, 2}, + {512, 384, 1<<16, 512*2, 2}, + {512, 384, 1<<24, 512*3, 3}, + {512, 384, 1<<24, 512*4, 4}, + + {960, 720, 256, 960, 1}, + {960, 720, 1<<15, 960*2, 2}, + {960, 720, 1<<16, 960*2, 2}, + {960, 720, 1<<24, 960*3, 3}, + {960, 720, 1<<24, 960*4, 4}, + + {1920, 1440, 256, 1920, 1}, + {1920, 1440, 1<<15, 1920*2, 2}, + {1920, 1440, 1<<16, 1920*2, 2}, + {1920, 1440, 1<<24, 1920*3, 3}, + {1920, 1440, 1<<24, 1920*4, 4}, + + {320, 400, 1<<8, 320, 1}, + {320, 400, 1<<15, 320*2, 2}, + {320, 400, 1<<16, 320*2, 2}, + {320, 400, 1<<24, 320*3, 3}, + {320, 400, 1<<24, 320*4, 4}, + + {640, 400, 256, 640, 1}, + {640, 400, 1<<15, 640*2, 2}, + {640, 400, 1<<16, 640*2, 2}, + {640, 400, 1<<24, 640*3, 3}, + {640, 400, 1<<24, 640*4, 4}, + + {320, 480, 256, 320, 1}, + {320, 480, 1<<15, 320*2, 2}, + {320, 480, 1<<16, 320*2, 2}, + {320, 480, 1<<24, 320*3, 3}, + {320, 480, 1<<24, 320*4, 4}, + + {720, 540, 256, 720, 1}, + {720, 540, 1<<15, 720*2, 2}, + {720, 540, 1<<16, 720*2, 2}, + {720, 540, 1<<24, 720*3, 3}, + {720, 540, 1<<24, 720*4, 4}, + + {848, 480, 256, 848, 1}, + {848, 480, 1<<15, 848*2, 2}, + {848, 480, 1<<16, 848*2, 2}, + {848, 480, 1<<24, 848*3, 3}, + {848, 480, 1<<24, 848*4, 4}, + + {1072, 600, 256, 1072, 1}, + {1072, 600, 1<<15, 1072*2, 2}, + {1072, 600, 1<<16, 1072*2, 2}, + {1072, 600, 1<<24, 1072*3, 3}, + {1072, 600, 1<<24, 1072*4, 4}, + + {1280, 720, 256, 1280, 1}, + {1280, 720, 1<<15, 1280*2, 2}, + {1280, 720, 1<<16, 1280*2, 2}, + {1280, 720, 1<<24, 1280*3, 3}, + {1280, 720, 1<<24, 1280*4, 4}, + + {1360, 768, 256, 1360, 1}, + {1360, 768, 1<<15, 1360*2, 2}, + {1360, 768, 1<<16, 1360*2, 2}, + {1360, 768, 1<<24, 1360*3, 3}, + {1360, 768, 1<<24, 1360*4, 4}, + + {1800, 1012, 256, 1800, 1}, + {1800, 1012, 1<<15, 1800*2, 2}, + {1800, 1012, 1<<16, 1800*2, 2}, + {1800, 1012, 1<<24, 1800*3, 3}, + {1800, 1012, 1<<24, 1800*4, 4}, + + {1920, 1080, 256, 1920, 1}, + {1920, 1080, 1<<15, 1920*2, 2}, + {1920, 1080, 1<<16, 1920*2, 2}, + {1920, 1080, 1<<24, 1920*3, 3}, + {1920, 1080, 1<<24, 1920*4, 4}, + + {2048, 1152, 256, 2048, 1}, + {2048, 1152, 1<<15, 2048*2, 2}, + {2048, 1152, 1<<16, 2048*2, 2}, + {2048, 1152, 1<<24, 2048*3, 3}, + {2048, 1152, 1<<24, 2048*4, 4}, + + {2048, 1536, 256, 2048, 1}, + {2048, 1536, 1<<15, 2048*2, 2}, + {2048, 1536, 1<<16, 2048*2, 2}, + {2048, 1536, 1<<24, 2048*3, 3}, + {2048, 1536, 1<<24, 2048*4, 4}, + + {512, 480, 256, 512, 1}, + {512, 480, 1<<15, 512*2, 2}, + {512, 480, 1<<16, 512*2, 2}, + {512, 480, 1<<24, 512*3, 3}, + {512, 480, 1<<24, 512*4, 4}, + + {400, 600, 256, 400, 1}, + {400, 600, 1<<15, 400*2, 2}, + {400, 600, 1<<16, 400*2, 2}, + {400, 600, 1<<24, 400*3, 3}, + {400, 600, 1<<24, 400*4, 4}, + + {400, 300, 256, 100, 0}, + {320, 200, 256, 320, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} +}; + +#define MAX_MODES (sizeof(infotable) / sizeof(struct vgainfo)) + +void (*__svgalib_go_to_background) (void) = 0; +void (*__svgalib_come_from_background) (void) = 0; +static int release_acquire=0; + +unsigned char __svgalib_novga = 0; /* Does not have VGA circuitry on board */ +unsigned char __svgalib_vesatext = 0; +unsigned char __svgalib_textprog = 0; /* run a program when returning to text mode */ +unsigned char __svgalib_secondary = 0; /* this is not the main card with VC'S ) */ +unsigned char __svgalib_emulatepage = 0; /* don't use 0xa0000 memory */ +unsigned char __svgalib_novccontrol = 0; /* this is not the main card with VC'S */ +unsigned char __svgalib_ragedoubleclock = 0; +unsigned char __svgalib_simple = 0; +unsigned char __svgalib_neolibretto100 = 0; +unsigned char __svgalib_nohelper = 0; +static unsigned char __svgalib_nohelper_secure = 1; +unsigned char __svgalib_fbdev_novga = 0; + +int biosparams=0; +int biosparam[16]; + +/* default palette values */ +static const unsigned char default_red[256] += +{0, 0, 0, 0, 42, 42, 42, 42, 21, 21, 21, 21, 63, 63, 63, 63, + 0, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 40, 45, 50, 56, 63, + 0, 16, 31, 47, 63, 63, 63, 63, 63, 63, 63, 63, 63, 47, 31, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 39, 47, 55, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 55, 47, 39, 31, 31, 31, 31, 31, 31, 31, 31, + 45, 49, 54, 58, 63, 63, 63, 63, 63, 63, 63, 63, 63, 58, 54, 49, + 45, 45, 45, 45, 45, 45, 45, 45, 0, 7, 14, 21, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 21, 14, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 17, 21, 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 24, 21, 17, + 14, 14, 14, 14, 14, 14, 14, 14, 20, 22, 24, 26, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 26, 24, 22, 20, 20, 20, 20, 20, 20, 20, 20, + 0, 4, 8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, 8, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 12, 14, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 14, 12, 10, 8, 8, 8, 8, 8, 8, 8, 8, + 11, 12, 13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 13, 12, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0}; +static const unsigned char default_green[256] += +{0, 0, 42, 42, 0, 0, 21, 42, 21, 21, 63, 63, 21, 21, 63, 63, + 0, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 40, 45, 50, 56, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 31, 47, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 47, 31, 16, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 39, 47, 55, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, 47, 39, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 49, 54, 58, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 58, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 14, 21, 29, 28, 28, 28, 28, 28, 28, 28, 28, 21, 14, 7, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 17, 21, 24, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 24, 21, 17, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 22, 24, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 24, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 12, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 10, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 13, 12, 0, 0, 0, 0, 0, 0, 0, 0}; +static const unsigned char default_blue[256] += +{0, 42, 0, 42, 0, 42, 0, 42, 21, 63, 21, 63, 21, 63, 21, 63, + 0, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 40, 45, 50, 56, 63, + 63, 63, 63, 63, 63, 47, 31, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 31, 47, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, 47, 39, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 39, 47, 55, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 58, 54, 49, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 49, 54, 58, 63, 63, 63, 63, 28, 28, 28, 28, 28, 21, 14, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 14, 21, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 24, 21, 17, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 17, 21, 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 24, 22, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 22, 24, 26, 28, 28, 28, 28, + 16, 16, 16, 16, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 12, 14, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 13, 12, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 13, 15, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0}; + +static unsigned char text_regs[MAX_REGS]; /* VGA registers for saved text mode */ + +char *__svgalib_TextProg_argv[16]; /* should be enough */ +char *__svgalib_TextProg; + +/* saved text mode palette values */ +static unsigned char text_red[256]; +static unsigned char text_green[256]; +static unsigned char text_blue[256]; + +/* saved graphics mode palette values */ +static unsigned char graph_red[256]; +static unsigned char graph_green[256]; +static unsigned char graph_blue[256]; + +static int prv_mode = TEXT; /* previous video mode */ +static int flip_mode = TEXT; /* flipped video mode */ + +int CM = TEXT; /* current video mode */ +struct vgainfo CI; /* current video parameters */ +int COL; /* current color */ + +static int initialized = 0; /* flag: initialize() called ? */ +static int flip = 0; /* flag: executing vga_flip() ? */ +static int background_fd = -1; + +/* svgalib additions: */ +int __svgalib_chipset = UNDEFINED; +int __svgalib_driver_report = 1; + /* report driver used after chipset detection */ +int __svgalib_videomemoryused = -1; +int __svgalib_modeX = 0; /* true after vga_setmodeX() */ +int __svgalib_modeflags = 0; /* copy of flags for current mode */ +int __svgalib_critical = 0; /* indicates blitter is busy */ +int __svgalib_screenon = 1; /* screen visible if != 0 */ +int __svgalib_vgacolormode = 1; /* assume color for now. needs to be + config file option */ + +static int __svgalib_savemem=0; + +RefreshRange __svgalib_horizsync = +{31500U, 0U}; /* horz. refresh (Hz) min, max */ +RefreshRange __svgalib_vertrefresh = +{50U, 70U}; /* vert. refresh (Hz) min, max */ +int __svgalib_bandwidth=50000; /* monitor maximum bandwidth (kHz) */ +int __svgalib_grayscale = 0; /* grayscale vs. color mode */ +int __svgalib_modeinfo_linearset = 0; /* IS_LINEAR handled via extended vga_modeinfo */ +const int __svgalib_max_modes = MAX_MODES; /* Needed for dynamical allocated tables in mach32.c */ + +static unsigned __svgalib_maxhsync[] = +{ + 31500, 35100, 35500, 37900, 48300, 56000, 60000 +}; + +static int minx=0, miny=0, maxx=99999, maxy=99999; +static int lastmodenumber = __GLASTMODE; /* Last defined mode */ +static int my_pid = 0; /* process PID, used with atexit() */ +static int __svgalib_readpage = -1; +static int __svgalib_writepage = -1; +static int vga_page_offset = 0; /* offset to add to all vga_set*page() calls */ +static int currentlogicalwidth; +static int currentdisplaystart; +static int mouse_support = 0; +int mouse_open = 0; +static int mouse_mode = 0; +static int mouse_type = -1; +static int mouse_modem_ctl = 0; +char *__svgalib_mouse_device = "/dev/mouse"; +int __svgalib_mouse_flag; +static char *helper_device = "/dev/svga"; +static int __svgalib_oktowrite = 1; +static int modeinfo_mask = ~0; +static int configfile_chipset = UNDEFINED; +static int configfile_params = 0; +static int configfile_par1 = 0; +static int configfile_par2 = 0; + +int __svgalib_mem_fd = -1; /* /dev/svga file descriptor */ +int __svgalib_tty_fd = -1; /* /dev/tty file descriptor */ +int __svgalib_nosigint = 0; /* Don't generate SIGINT in graphics mode */ +int __svgalib_runinbackground = 0; +int __svgalib_startup_vc = -1; +static int __svgalib_security_revokeallprivs = 1; +static int __svgalib_security_norevokeprivs = 0; +static unsigned fontbufsize = 8192; /* compatibility */ + +/* Dummy buffer for mmapping grahics memory; points to 64K VGA framebuffer. */ +unsigned char *GM; +/* Exported variable (read-only) is shadowed from internal variable, for */ +/* better shared library performance. */ +unsigned char *graph_mem; + +void *__svgalib_physaddr; +int __svgalib_linear_memory_size; + +static unsigned long graph_buf_size = 0; +static unsigned char *graph_buf = NULL; /* saves graphics data during flip */ + +/* The format of the fontdata seems to differ between banked and LFB access, + so we save both in case emulatepage gets set between saving and restoring. + This can happen when using runinbackground in nohelper secure mode. */ +static unsigned char *font_buf1_banked=NULL; /* saved font data - plane 2 */ +static unsigned char *font_buf2_banked=NULL; /* saved font data - plane 3 */ +static unsigned char *font_buf1_linear=NULL; /* saved font data - plane 2 */ +static unsigned char *font_buf2_linear=NULL; /* saved font data - plane 3 */ +static unsigned char *text_buf1=NULL; /* saved text data - plane 0 */ +static unsigned char *text_buf2=NULL; /* saved text data - plane 1 */ + +struct termios __svgalib_text_termio; /* text mode termio parameters */ +struct termios __svgalib_graph_termio; /* graphics mode termio parameters */ + +int __svgalib_flipchar = '\x1b'; /* flip character - initially ESCAPE */ + +/* Chipset specific functions */ + +DriverSpecs *__svgalib_driverspecs = &__svgalib_vga_driverspecs; + +static void (*__svgalib_setpage) (int); /* gives little faster vga_setpage() */ +static void (*__svgalib_setrdpage) (int) = NULL; +static void (*__svgalib_setwrpage) (int) = NULL; + +int (*__svgalib_inmisc)(void); +void (*__svgalib_outmisc)(int); +int (*__svgalib_incrtc)(int); +void (*__svgalib_outcrtc)(int,int); +int (*__svgalib_inseq)(int); +void (*__svgalib_outseq)(int,int); +int (*__svgalib_ingra)(int); +void (*__svgalib_outgra)(int,int); +int (*__svgalib_inatt)(int); +void (*__svgalib_outatt)(int,int); +void (*__svgalib_attscreen)(int); +void (*__svgalib_inpal)(int,int*,int*,int*); +void (*__svgalib_outpal)(int,int,int,int); +int (*__svgalib_inis1)(void); + +static void readconfigfile(void); +inline void vga_setpage(int p); + +DriverSpecs *__svgalib_driverspecslist[] = +{ + NULL, /* chipset undefined */ + &__svgalib_vga_driverspecs, +#ifdef INCLUDE_ET4000_DRIVER + &__svgalib_et4000_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_CIRRUS_DRIVER + &__svgalib_cirrus_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_TVGA_DRIVER + &__svgalib_tvga8900_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_OAK_DRIVER + &__svgalib_oak_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_EGA_DRIVER + &__svgalib_ega_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_S3_DRIVER + &__svgalib_s3_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_ET3000_DRIVER + &__svgalib_et3000_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_MACH32_DRIVER + &__svgalib_mach32_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_GVGA6400_DRIVER + &__svgalib_gvga6400_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_ARK_DRIVER + &__svgalib_ark_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_ATI_DRIVER + &__svgalib_ati_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_ALI_DRIVER + &__svgalib_ali_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_MACH64_DRIVER + &__svgalib_mach64_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_CHIPS_DRIVER + &__svgalib_chips_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_APM_DRIVER + &__svgalib_apm_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_NV3_DRIVER + &__svgalib_nv3_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_ET6000_DRIVER + &__svgalib_et6000_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_VESA_DRIVER + &__svgalib_vesa_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_MX_DRIVER + &__svgalib_mx_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_PARADISE_DRIVER + &__svgalib_paradise_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_RAGE_DRIVER + &__svgalib_rage_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_BANSHEE_DRIVER + &__svgalib_banshee_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_SIS_DRIVER + &__svgalib_sis_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_I740_DRIVER + &__svgalib_i740_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_NEO_DRIVER + &__svgalib_neo_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_LAGUNA_DRIVER + &__svgalib_laguna_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_FBDEV_DRIVER + &__svgalib_fbdev_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_G400_DRIVER + &__svgalib_g400_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_R128_DRIVER + &__svgalib_r128_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_SAVAGE_DRIVER + &__svgalib_savage_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_MILLENNIUM_DRIVER + &__svgalib_mil_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_I810_DRIVER + &__svgalib_i810_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_TRIDENT_DRIVER + &__svgalib_trident_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_RENDITION_DRIVER + &__svgalib_rendition_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_G450C2_DRIVER + &__svgalib_g450c2_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_PM2_DRIVER + &__svgalib_pm2_driverspecs, +#else + NULL, +#endif +#ifdef INCLUDE_UNICHROME_DRIVER + &__svgalib_unichrome_driverspecs, +#else + NULL, +#endif +}; + +static char *driver_names[] = +{ +"", +"VGA", +"ET4000", +"Cirrus", +"TVGA", +"Oak", +"EGA", +"S3", +"ET3000", +"Mach32", +"GVGA6400", +"ARK", +"ATI", +"ALI", +"Mach64", +"C&T", +"APM", +"NV3", +"ET6000", +"VESA", +"MX", +"PARADISE", +"RAGE", +"BANSHEE", +"SIS", +"I740", +"NEOMAGIC", +"LAGUNA", +"FBDev", +"G400", +"R128", +"SAVAGE", +"MILLENNIUM", +"I810", +"TRIDENT", +"RENDITION", +"G450C2", +"PM2", +"UNICHROME", + NULL}; + +/* Chipset drivers */ + +/* vgadrv Standard VGA (also used by drivers below) */ +/* et4000 Tseng ET4000 (from original vgalib) */ +/* cirrus Cirrus Logic GD542x */ +/* tvga8900 Trident TVGA 8900/9000 (derived from tvgalib) */ +/* oak Oak Technologies 037/067/077 */ +/* egadrv IBM EGA (subset of VGA) */ +/* s3 S3 911 */ +/* mach32 ATI MACH32 */ +/* ark ARK Logic */ +/* gvga6400 Genoa 6400 (old SVGA) */ +/* ati ATI */ +/* ali ALI2301 */ +/* mach64 ATI MACH64 */ +/* chips chips & technologies*/ +/* et6000 Tseng ET6000 */ /* DS */ + +/*#define DEBUG */ + +/* Debug config file parsing.. */ +/*#define DEBUG_CONF */ + +/* open /dev/svga */ +static void open_mem(void) +{ + /* Ensure that the open will get a file descriptor greater + * than 2, else problems can occur with stdio functions + * under certain strange conditions: */ + if ((fcntl(0,F_GETFD) == -1) && (open("/dev/null", O_RDONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + if ((fcntl(1,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + if ((fcntl(2,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + + if (__svgalib_mem_fd == -1) + { + const char *device; + if (__svgalib_nohelper) + device = "/dev/mem"; + else + device = helper_device; + if ((__svgalib_mem_fd = open(device, O_RDWR)) == -1) { + fprintf(stderr,"svgalib: Cannot open %s\n%s\n", device, + __svgalib_nohelper? + "Are you running this program as root or suid-root?": + "Is svgalib_helper module loaded?"); + exit(1); + } + } + + /* Ensure this file is closed if we ever exec something else... */ + if (fcntl(__svgalib_mem_fd, F_SETFD, 1) == -1) { + perror("fcntl 808"); + exit(-1); + } + + if (__svgalib_linear_mem_fd == -1) + __svgalib_linear_mem_fd = __svgalib_mem_fd; +} + +static void __svgalib_get_perm(void) +{ + static int done = 0; + + /* Only do this once. */ + if (done) + return; + done = 1; + + /* special case FBDEV without standard VGA modes */ + if ((CHIPSET==FBDEV) && __svgalib_fbdev_novga) + { + __svgalib_emulatepage=1; + __svgalib_novga=1; + __svgalib_nohelper=1; + } + else + { + if (__svgalib_nohelper) + { + iopl(3); + ioperm(0, 0x400, 1); + } + + /* Open /dev/svga */ + open_mem(); + } + + __svgalib_open_devconsole(); + + /* color or monochrome text emulation? */ + if (CHIPSET != EGA && !__svgalib_novga) + color_text = __svgalib_vgacolor(); + else + color_text = 1; /* EGA is assumed color */ + + /* chose registers for color/monochrome emulation */ + if (color_text) { + __svgalib_CRT_I = CRT_IC; + __svgalib_CRT_D = CRT_DC; + __svgalib_IS1_R = IS1_RC; + } else { + __svgalib_CRT_I = CRT_IM; + __svgalib_CRT_D = CRT_DM; + __svgalib_IS1_R = IS1_RM; + } +} + +static void __svgalib_giveup_perm(void) +{ + if (CHIPSET != FBDEV) { + __svgalib_linear_mem_phys_addr = __svgalib_linear_mem_base; + /* Try get a pure handle to the LFB which can safely be left open + at all times, this will only work with 2.6 kernels. + This could be done in helper mode too, but we don't know the + real pci ID there, only the helper module id. Also this + is not usefull in helpermode since mem_fd must always be left + open in helpermode. */ + if (__svgalib_nohelper) { + unsigned int bus, device, fn; + char buf[256]; + FILE *f; + int i, fd; + + bus=(__svgalib_pci_card_found_at&0xff00)>>8; + device=(__svgalib_pci_card_found_at&0xf8)>>3; + fn=__svgalib_pci_card_found_at&0x07; + snprintf(buf, 256, "/sys/bus/pci/devices/0000:%02u:%02x.%u/resource", + bus, device, fn); + + f = fopen(buf, "r"); + if (f) { + for (i=0; fgets(buf, 256, f); i++) { + if (strtoul(buf, NULL, 16) == __svgalib_linear_mem_base) { + snprintf(buf, 256, + "/sys/bus/pci/devices/0000:%02u:%02x.%u/resource%i", + bus, device, fn, i); + fd = open(buf, O_RDWR); + if (fd != -1) { + __svgalib_linear_mem_fd = fd; + __svgalib_linear_mem_base = 0; +#ifdef DEBUG + fprintf(stderr, "svgalib: debug: Opened: %s as LFB\n", + buf); +#endif + } + break; + } + } + fclose(f); + } + } + } + + /* mmap graphics memory */ + map_mem(); + map_mmio(); + + if(__svgalib_nohelper && __svgalib_nohelper_secure && + (__svgalib_mem_fd != -1)) + { + close(__svgalib_mem_fd); + if (__svgalib_linear_mem_fd == __svgalib_mem_fd) + __svgalib_linear_mem_fd = -1; + __svgalib_mem_fd = -1; + } + + if ((__svgalib_linear_mem_fd == -1) && __svgalib_emulatepage) + { + fprintf(stderr, + "svgalib: Warning your config requires banking to be emulated. This is not\n" + " possible in NoHelper mode, applications which use bankedmode even if LFB\n" + " is available will fail!\n"); + } + + __svgalib_setpage = __svgalib_driverspecs->__svgalib_setpage; + if (!__svgalib_emulatepage) + { + __svgalib_setrdpage = __svgalib_driverspecs->__svgalib_setrdpage; + __svgalib_setwrpage = __svgalib_driverspecs->__svgalib_setwrpage; + } + + /* DEBUG, REMOVEME force banking to test setpage workarounds */ + /* __svgalib_modeinfo_linearset &= ~LINEAR_USE; */ +} + +void __svgalib_delay(void) +{ + int i; + for (i = 0; i < 10; i++); +} + +static void slowcpy(unsigned char *dest, unsigned char *src, unsigned bytes) +{ + if(dest==NULL || src==NULL || (long)dest==-1L || (long)src==-1L) return; + while (bytes > 0) { + *(uint32_t *)dest = *(uint32_t *)src; + dest+=4; + src+=4; + bytes-=4; + } +} + +#define TEXT_SIZE 65536 + +static unsigned char *vmem_buf; + +static void restore_text(void) +{ + + __svgalib_outseq(0x02,0x01); + + slowcpy(GM, text_buf1, TEXT_SIZE); + + __svgalib_outseq(0x02,0x02); + + slowcpy(GM, text_buf2, TEXT_SIZE); + + if(__svgalib_savemem) + memcpy(LINEAR_POINTER,vmem_buf,__svgalib_savemem); +}; + +static void save_text(void) +{ + + text_buf1 = malloc(TEXT_SIZE * 2); + + text_buf2 = text_buf1 + TEXT_SIZE; + + __svgalib_outgra(0x04,0x00); + + slowcpy(text_buf1, GM, TEXT_SIZE); + + /* save font data in plane 3 */ + __svgalib_outgra(0x04,0x01); + + slowcpy(text_buf2, GM, TEXT_SIZE); + + if(__svgalib_savemem) { + vmem_buf=malloc(__svgalib_savemem); + memcpy(vmem_buf,LINEAR_POINTER,__svgalib_savemem); + } +}; + +int __svgalib_saveregs(unsigned char *regs) +{ + int i; + + if (__svgalib_chipset == EGA || __svgalib_novga) { + /* Special case: Don't save standard VGA registers. */ + return chipset_saveregs(regs); + } + /* save VGA registers */ + for (i = 0; i < CRT_C; i++) { + regs[CRT + i] = __svgalib_incrtc(i); + } + for (i = 0; i < ATT_C; i++) { + regs[ATT + i] = __svgalib_inatt(i); + } + for (i = 0; i < GRA_C; i++) { + regs[GRA + i] = __svgalib_ingra(i); + } + for (i = 0; i < SEQ_C; i++) { + regs[SEQ + i] = __svgalib_inseq(i); + } + regs[MIS] = __svgalib_inmisc(); + + i = chipset_saveregs(regs); /* save chipset-specific registers */ + /* i : additional registers */ + if (!SCREENON) { /* We turned off the screen */ + __svgalib_attscreen(0x20); + } + return CRT_C + ATT_C + GRA_C + SEQ_C + 1 + i; +} + + +int __svgalib_setregs(const unsigned char *regs) +{ + int i; + + if(__svgalib_novga) return 1; + + if (__svgalib_chipset == EGA) { + /* Enable graphics register modification */ + port_out(0x00, GRA_E0); + port_out(0x01, GRA_E1); + } + /* update misc output register */ + __svgalib_outmisc(regs[MIS]); + + /* synchronous reset on */ + __svgalib_outseq(0x00,0x01); + + /* write sequencer registers */ + __svgalib_outseq(0x01,regs[SEQ + 1] | 0x20); + for (i = 2; i < SEQ_C; i++) { + __svgalib_outseq(i,regs[SEQ + i]); + } + + /* synchronous reset off */ + __svgalib_outseq(0x00,0x03); + + if (__svgalib_chipset != EGA) { + /* deprotect CRT registers 0-7 */ + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + } + /* write CRT registers */ + for (i = 0; i < CRT_C; i++) { + __svgalib_outcrtc(i,regs[CRT + i]); + } + + /* write graphics controller registers */ + for (i = 0; i < GRA_C; i++) { + __svgalib_outgra(i,regs[GRA+i]); + } + + /* write attribute controller registers */ + for (i = 0; i < ATT_C; i++) { + __svgalib_outatt(i,regs[ATT+i]); + } + + return 0; +} + +/* We invoke the old interrupt handler after setting text mode */ +/* We catch all signals that cause an exit by default (aka almost all) */ +static char sig2catch[] = +{SIGHUP, SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGIOT, SIGBUS, SIGFPE, + SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, + SIGXCPU, SIGXFSZ, SIGVTALRM, +/* SIGPROF ,*/ SIGPWR}; +static struct sigaction old_signal_handler[sizeof(sig2catch)]; + +struct vt_mode __svgalib_oldvtmode; + +static void restoretextmode(void) +{ + /* handle unexpected interrupts - restore text mode and exit */ + keyboard_close(); + /* Restore a setting screwed by keyboard_close (if opened in graphicsmode) */ + __svgalib_set_texttermio(); + if (CM != TEXT) + vga_setmode(TEXT); + + if (!__svgalib_screenon) + vga_screenon(); + + if (__svgalib_tty_fd >= 0) { + if (!__svgalib_secondary) { + ioctl(__svgalib_tty_fd, KDSETMODE, KD_TEXT); + ioctl(__svgalib_tty_fd, VT_SETMODE, &__svgalib_oldvtmode); + } + } + + if((__svgalib_textprog&3)==3){ + pid_t child; + if((child=fork())==0){ + execv(__svgalib_TextProg,__svgalib_TextProg_argv); + } else { + waitpid(child,NULL,0); + }; + }; +} + +static void idle_accel(void) { + /* wait for the accel to finish, we assume one of the both interfaces suffices */ + if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL) & ACCELFLAG_SYNC) + vga_accel(ACCEL_SYNC); + else if (vga_getmodeinfo(CM)->haveblit & HAVE_BLITWAIT) + vga_blitwait(); +} + +static void signal_handler(int v) +{ + int i; + + /* If we have accelerated functions, possibly wait for the + * blitter to finish. I hope the PutBitmap functions disable + * interrupts while writing data to the screen, otherwise + * this will cause an infinite loop. + */ + idle_accel(); + + restoretextmode(); + fprintf(stderr,"svgalib: Signal %d: %s received%s.\n", v, strsignal(v), + (v == SIGINT) ? " (ctrl-c pressed)" : ""); + + for (i = 0; i < sizeof(sig2catch); i++) + if (sig2catch[i] == v) { + sigaction(v, old_signal_handler + i, NULL); + raise(v); + break; + } + if (i >= sizeof(sig2catch)) { + fprintf(stderr,"svgalib: Aieeee! Illegal call to signal_handler, raising segfault.\n"); + raise(SIGSEGV); + } +} + +int __svgalib_getchipset(void) +{ + readconfigfile(); /* Make sure the config file is read. */ + +#ifdef _SVGALIB_LRMI + if (!__svgalib_LRMI_callbacks) + vga_set_LRMI_callbacks(&__svgalib_default_LRMI_callbacks); +#endif + + if (CHIPSET != UNDEFINED) + return CHIPSET; + +/* Unlike the others, the FBDev test needs to be before __svgalib_get_perm() */ +#ifdef INCLUDE_FBDEV_DRIVER_TEST + if (!__svgalib_driverspecslist[FBDEV]->disabled && + __svgalib_fbdev_driverspecs.test()) + CHIPSET = FBDEV; +#endif + + __svgalib_get_perm(); + + if (CHIPSET == UNDEFINED) { + CHIPSET = VGA; /* Protect against recursion */ +#ifdef INCLUDE_NV3_DRIVER_TEST + if (!__svgalib_driverspecslist[NV3]->disabled && __svgalib_nv3_driverspecs.test()) + CHIPSET = NV3; + else +#endif +#ifdef INCLUDE_TRIDENT_DRIVER_TEST + if (!__svgalib_driverspecslist[TRIDENT]->disabled && __svgalib_trident_driverspecs.test()) + CHIPSET = TRIDENT; + else +#endif +#ifdef INCLUDE_RENDITION_DRIVER_TEST + if (!__svgalib_driverspecslist[RENDITION]->disabled && __svgalib_rendition_driverspecs.test()) + CHIPSET = RENDITION; + else +#endif +#ifdef INCLUDE_G400_DRIVER_TEST + if (!__svgalib_driverspecslist[G400]->disabled && __svgalib_g400_driverspecs.test()) + CHIPSET = G400; + else +#endif +#ifdef INCLUDE_PM2_DRIVER_TEST + if (!__svgalib_driverspecslist[PM2]->disabled && __svgalib_pm2_driverspecs.test()) + CHIPSET = PM2; + else +#endif +#ifdef INCLUDE_UNICHROME_DRIVER_TEST + if (!__svgalib_driverspecslist[UNICHROME]->disabled && __svgalib_unichrome_driverspecs.test()) + CHIPSET = UNICHROME; + else +#endif +#ifdef INCLUDE_SAVAGE_DRIVER_TEST + if (!__svgalib_driverspecslist[SAVAGE]->disabled && __svgalib_savage_driverspecs.test()) + CHIPSET = SAVAGE; + else +#endif +#ifdef INCLUDE_MILLENNIUM_DRIVER_TEST + if (!__svgalib_driverspecslist[MILLENNIUM]->disabled && __svgalib_mil_driverspecs.test()) + CHIPSET = MILLENNIUM; + else +#endif +#ifdef INCLUDE_R128_DRIVER_TEST + if (!__svgalib_driverspecslist[R128]->disabled && __svgalib_r128_driverspecs.test()) + CHIPSET = R128; + else +#endif +#ifdef INCLUDE_BANSHEE_DRIVER_TEST + if (!__svgalib_driverspecslist[BANSHEE]->disabled && __svgalib_banshee_driverspecs.test()) + CHIPSET = BANSHEE; + else +#endif +#ifdef INCLUDE_SIS_DRIVER_TEST + if (!__svgalib_driverspecslist[SIS]->disabled && __svgalib_sis_driverspecs.test()) + CHIPSET = SIS; + else +#endif +#ifdef INCLUDE_I740_DRIVER_TEST + if (!__svgalib_driverspecslist[I740]->disabled && __svgalib_i740_driverspecs.test()) + CHIPSET = I740; + else +#endif +#ifdef INCLUDE_I810_DRIVER_TEST + if (!__svgalib_driverspecslist[I810]->disabled && __svgalib_i810_driverspecs.test()) + CHIPSET = I810; + else +#endif +#ifdef INCLUDE_LAGUNA_DRIVER_TEST + if (!__svgalib_driverspecslist[LAGUNA]->disabled && __svgalib_laguna_driverspecs.test()) + CHIPSET = LAGUNA; + else +#endif +#ifdef INCLUDE_RAGE_DRIVER_TEST + if (!__svgalib_driverspecslist[RAGE]->disabled && __svgalib_rage_driverspecs.test()) + CHIPSET = RAGE; + else +#endif +#ifdef INCLUDE_MX_DRIVER_TEST + if (!__svgalib_driverspecslist[MX]->disabled && __svgalib_mx_driverspecs.test()) + CHIPSET = MX; + else +#endif +#ifdef INCLUDE_NEO_DRIVER_TEST + if (!__svgalib_driverspecslist[NEOMAGIC]->disabled && __svgalib_neo_driverspecs.test()) + CHIPSET = NEOMAGIC; + else +#endif +#ifdef INCLUDE_CHIPS_DRIVER_TEST + if (!__svgalib_driverspecslist[CHIPS]->disabled && __svgalib_chips_driverspecs.test()) + CHIPSET = CHIPS; + else +#endif +#ifdef INCLUDE_MACH64_DRIVER_TEST + if (!__svgalib_driverspecslist[MACH64]->disabled && __svgalib_mach64_driverspecs.test()) + CHIPSET = MACH64; + else +#endif +#ifdef INCLUDE_MACH32_DRIVER_TEST + if (!__svgalib_driverspecslist[MACH32]->disabled && __svgalib_mach32_driverspecs.test()) + CHIPSET = MACH32; + else +#endif +#ifdef INCLUDE_EGA_DRIVER_TEST + if (!__svgalib_driverspecslist[EGA]->disabled && __svgalib_ega_driverspecs.test()) + CHIPSET = EGA; + else +#endif +#ifdef INCLUDE_ET6000_DRIVER_TEST /* DS */ + if (!__svgalib_driverspecslist[ET6000]->disabled && __svgalib_et6000_driverspecs.test()) /* This must be before */ + CHIPSET = ET6000; /* ET4000 or the card */ + else /* will be called et4k */ +#endif +#ifdef INCLUDE_ET4000_DRIVER_TEST + if (!__svgalib_driverspecslist[ET4000]->disabled && __svgalib_et4000_driverspecs.test()) + CHIPSET = ET4000; + else +#endif +#ifdef INCLUDE_TVGA_DRIVER_TEST + if (!__svgalib_driverspecslist[TVGA8900]->disabled && __svgalib_tvga8900_driverspecs.test()) + CHIPSET = TVGA8900; + else +#endif +#ifdef INCLUDE_CIRRUS_DRIVER_TEST + /* The Cirrus detection is not very clean. */ + if (!__svgalib_driverspecslist[CIRRUS]->disabled && __svgalib_cirrus_driverspecs.test()) + CHIPSET = CIRRUS; + else +#endif +#ifdef INCLUDE_OAK_DRIVER_TEST + if (!__svgalib_driverspecslist[OAK]->disabled && __svgalib_oak_driverspecs.test()) + CHIPSET = OAK; + else +#endif +#ifdef INCLUDE_PARADISE_DRIVER_TEST + if (!__svgalib_driverspecslist[PARADISE]->disabled && __svgalib_paradise_driverspecs.test()) + CHIPSET = PARADISE; + else +#endif +#ifdef INCLUDE_S3_DRIVER_TEST + if (!__svgalib_driverspecslist[S3]->disabled && __svgalib_s3_driverspecs.test()) + CHIPSET = S3; + else +#endif +#ifdef INCLUDE_ET3000_DRIVER_TEST + if (!__svgalib_driverspecslist[ET3000]->disabled && __svgalib_et3000_driverspecs.test()) + CHIPSET = ET3000; + else +#endif +#ifdef INCLUDE_ARK_DRIVER_TEST + if (!__svgalib_driverspecslist[ARK]->disabled && __svgalib_ark_driverspecs.test()) + CHIPSET = ARK; + else +#endif +#ifdef INCLUDE_GVGA6400_DRIVER_TEST + if (!__svgalib_driverspecslist[GVGA6400]->disabled && __svgalib_gvga6400_driverspecs.test()) + CHIPSET = GVGA6400; + else +#endif +#ifdef INCLUDE_ATI_DRIVER_TEST + if (!__svgalib_driverspecslist[ATI]->disabled && __svgalib_ati_driverspecs.test()) + CHIPSET = ATI; + else +#endif +#ifdef INCLUDE_ALI_DRIVER_TEST + if (!__svgalib_driverspecslist[ALI]->disabled && __svgalib_ali_driverspecs.test()) + CHIPSET = ALI; + else +#endif +#ifdef INCLUDE_APM_DRIVER_TEST +/* Note: On certain cards this may toggle the video signal on/off which + is ugly. Hence we test this last. */ + if (!__svgalib_driverspecslist[APM]->disabled && __svgalib_apm_driverspecs.test()) + CHIPSET = APM; + else +#endif +#ifdef INCLUDE_VESA_DRIVER_TEST + if (!__svgalib_driverspecslist[VESA]->disabled && __svgalib_vesa_driverspecs.test()) + CHIPSET = VESA; + else +#endif + if (!__svgalib_driverspecslist[VGA]->disabled && __svgalib_vga_driverspecs.test()) + CHIPSET = VGA; + else + /* else */ + { + fprintf(stderr, "svgalib: Cannot find EGA or VGA graphics device.\n"); + exit(1); + } + } + __svgalib_giveup_perm(); + return CHIPSET; +} + +void vga_setchipset(int c) +{ + CHIPSET = c; + + DPRINTF("Setting chipset\n"); + + if (c == UNDEFINED) + return; + + if (__svgalib_driverspecslist[c] == NULL) { + fprintf(stderr,"svgalib: Invalid chipset. The driver may not be compiled in.\n"); + CHIPSET = UNDEFINED; + return; + } + + /* we need to read the configfile here to get the correct value + for __svgalib_nohelper and __svgalib_nohelper_secure */ + readconfigfile(); + +#ifdef _SVGALIB_LRMI + if (!__svgalib_LRMI_callbacks) + vga_set_LRMI_callbacks(&__svgalib_default_LRMI_callbacks); +#endif + __svgalib_driverspecslist[c]->disabled = 0; + __svgalib_get_perm(); + __svgalib_driverspecslist[c]->init(0, 0, 0); + __svgalib_giveup_perm(); +} + +void vga_setchipsetandfeatures(int c, int par1, int par2) +{ + CHIPSET = c; + + DPRINTF("Forcing chipset and features\n"); + + /* we need to read the configfile here to get the correct value + for __svgalib_nohelper and __svgalib_nohelper_secure */ + readconfigfile(); + +#ifdef _SVGALIB_LRMI + if (!__svgalib_LRMI_callbacks) + vga_set_LRMI_callbacks(&__svgalib_default_LRMI_callbacks); +#endif + __svgalib_get_perm(); + __svgalib_driverspecslist[c]->init(1, par1, par2); + __svgalib_giveup_perm(); + + DPRINTF("Finished forcing chipset and features\n"); +} + +void vga_disablechipset(int c) +{ + DPRINTF("Disabling chipset %i\n", c); + + if (c == UNDEFINED) + return; + __svgalib_driverspecslist[c]->disabled = 1; +} + + +static void savepalette(unsigned char *red, unsigned char *green, + unsigned char *blue) +{ + int i; + + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->savepalette) + return (__svgalib_driverspecs->emul->savepalette(red, green, blue)); + + if (CHIPSET == EGA || __svgalib_novga) + return; + + /* save graphics mode palette */ + + for (i = 0; i < 256; i++) { + int r,g,b; + __svgalib_inpal(i,&r,&g,&b); + *(red++) = r; + *(green++) = g; + *(blue++) = b; + } +} + +static void restorepalette(const unsigned char *red, + const unsigned char *green, const unsigned char *blue) +{ + int i; + + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->restorepalette) + return (__svgalib_driverspecs->emul->restorepalette(red, green, blue)); + + if (CHIPSET == EGA || __svgalib_novga) + return; + + /* restore saved palette */ + /* read RGB components - index is autoincremented */ + for (i = 0; i < 256; i++) { + __svgalib_outpal(i,*(red++),*(green++),*(blue++)); + } +} + +/* Virtual console switching */ +static int forbidvtrelease = 0; +static int forbidvtacquire = 0; +static int lock_count = 0; +static int release_flag = 0; + +static void __svgalib_takevtcontrol(void); + +void __svgalib_flipaway(void); +static void __svgalib_flipback(void); + +int inrestore; + +static void __svgalib_releasevt_signal(int n) +{ + DPRINTF("Release request. r_a=%i %i\n", release_acquire, inrestore); + + if (lock_count) { + release_flag = 1; + return; + } + + release_acquire=!release_acquire; + forbidvtacquire = 1; + if (forbidvtrelease) { + forbidvtacquire = 0; + ioctl(__svgalib_tty_fd, VT_RELDISP, 0); + return; + } + + if (__svgalib_go_to_background) (__svgalib_go_to_background) (); + + __svgalib_flipaway(); + + if((__svgalib_textprog&3)==3){ + pid_t child; + if((child=fork())==0){ + execv(__svgalib_TextProg,__svgalib_TextProg_argv); + } else { + waitpid(child,NULL,0); + }; + }; + + ioctl(__svgalib_tty_fd, VT_RELDISP, 1); + + DPRINTF("Finished release.\n"); + + forbidvtacquire = 0; + + /* Suspend program until switched to again. */ + if (!__svgalib_runinbackground) { + DPRINTF("Suspended.\n"); + __svgalib_oktowrite = 0; + __svgalib_waitvtactive(); + DPRINTF("Waked.\n"); + } +} + +static void __svgalib_acquirevt_signal(int n) +{ + DPRINTF("Acquisition request. r_a=%i %i\n",release_acquire, inrestore); + + release_acquire=!release_acquire; + + forbidvtrelease = 1; + if (forbidvtacquire) { + forbidvtrelease = 0; + return; + } + + __svgalib_flipback(); + ioctl(__svgalib_tty_fd, VT_RELDISP, VT_ACKACQ); + + DPRINTF("Finished acquisition.\n"); + + forbidvtrelease = 0; + if (__svgalib_come_from_background) + (__svgalib_come_from_background) (); + __svgalib_oktowrite = 1; +} + +void __svgalib_takevtcontrol(void) +{ + struct sigaction siga; + struct vt_mode newvtmode; + + ioctl(__svgalib_tty_fd, VT_GETMODE, &__svgalib_oldvtmode); + newvtmode = __svgalib_oldvtmode; + newvtmode.mode = VT_PROCESS; /* handle VT changes */ + newvtmode.relsig = SVGALIB_RELEASE_SIG; /* I didn't find SIGUSR1/2 anywhere */ + newvtmode.acqsig = SVGALIB_ACQUIRE_SIG; /* in the kernel sources, so I guess */ + /* they are free */ + SETSIG(siga, SVGALIB_RELEASE_SIG, __svgalib_releasevt_signal); + SETSIG(siga, SVGALIB_ACQUIRE_SIG, __svgalib_acquirevt_signal); + ioctl(__svgalib_tty_fd, VT_SETMODE, &newvtmode); +} + +#ifdef LINEAR_DEBUG +void dump_mem(unsigned char *name) +{ + unsigned char bu[128]; + sprintf(bu,"cat /proc/%d/maps > /tmp/%s",getpid(),name); + system(bu); +} +#endif + +static void __vga_map(void) +{ + GM = (unsigned char *) BANKED_POINTER; + graph_mem = GM; /* Exported variable. */ +} + +static void __vga_atexit(void) +{ + if (getpid() == my_pid) /* protect against forked processes */ + restoretextmode(); + if (__svgalib_tty_fd >= 0 && __svgalib_startup_vc > 0) + ioctl(__svgalib_tty_fd, VT_ACTIVATE, __svgalib_startup_vc); +} + +static void setcoloremulation(void) +{ + /* shift to color emulation */ + __svgalib_CRT_I = CRT_IC; + __svgalib_CRT_D = CRT_DC; + __svgalib_IS1_R = IS1_RC; + __svgalib_vgacolormode=1; + if (CHIPSET != EGA && !__svgalib_novga) + __svgalib_outmisc(__svgalib_inmisc()|0x01); +} + +static void initialize(void) +{ + int i; + struct sigaction siga; + + DTP((stderr, "initialize\n")); + +#ifdef _SVGALIB_LRMI + if (!__svgalib_LRMI_callbacks) + vga_set_LRMI_callbacks(&__svgalib_default_LRMI_callbacks); +#endif + + __svgalib_open_devconsole(); + if ((!__svgalib_novccontrol)&&(__svgalib_tty_fd < 0)) { + exit(1); + } + + /* Make sure that textmode is restored at exit(). */ + if (my_pid == 0) + my_pid = getpid(); + atexit(__vga_atexit); + +#ifndef DONT_WAIT_VC_ACTIVE + __svgalib_waitvtactive(); +#endif + +#ifndef SET_TERMIO + /* save text mode termio parameters */ + ioctl(0, TCGETS, &__svgalib_text_termio); + + __svgalib_graph_termio = __svgalib_text_termio; + + /* change termio parameters to allow our own I/O processing */ + __svgalib_graph_termio.c_iflag &= ~(BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF); + __svgalib_graph_termio.c_iflag |= (IGNBRK | IGNPAR); + + __svgalib_graph_termio.c_oflag &= ~(ONOCR); + + __svgalib_graph_termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH); + + if (__svgalib_nosigint) + __svgalib_graph_termio.c_lflag &= ~ISIG; /* disable interrupt */ + else + __svgalib_graph_termio.c_lflag |= ISIG; /* enable interrupt */ + + __svgalib_graph_termio.c_cc[VMIN] = 1; + __svgalib_graph_termio.c_cc[VTIME] = 0; + __svgalib_graph_termio.c_cc[VSUSP] = 0; /* disable suspend */ +#endif + + __svgalib_disable_interrupt(); /* Is reenabled later by set_texttermio */ + + __svgalib_getchipset(); /* make sure a chipset has been selected */ + chipset_unlock(); + + /* disable text output to console */ + if (!__svgalib_secondary) { + ioctl(__svgalib_tty_fd, KDSETMODE, KD_GRAPHICS); + } + + __svgalib_takevtcontrol(); /* HH: Take control over VT */ + + __vga_map(); + + /* disable video */ + vga_screenoff(); + + /* Sanity check: (from painful experience) */ + i = __svgalib_saveregs(text_regs); + if (i > MAX_REGS) { + fprintf(stderr,"svgalib: FATAL internal error:\n"); + fprintf(stderr,"Set MAX_REGS at least to %d in src/driver.h and recompile everything.\n", + i); + exit(1); + } + + /* This appears to fix the Trident 8900 rebooting problem. */ + if (__svgalib_chipset == TVGA8900) { + text_regs[EXT + 11] = __svgalib_inseq(0x0c); + text_regs[EXT + 12] = __svgalib_incrtc(0x1f); + } + + /* save text mode palette */ + savepalette(text_red, text_green, text_blue); + + /* shift to color emulation */ + setcoloremulation(); + + /* save font data - first select a 16 color graphics mode */ + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->savefont) { + __svgalib_driverspecs->emul->savefont(); + } else if(!__svgalib_novga) { +#if 1 + __svgalib_driverspecs->setmode(GPLANE16, prv_mode); + save_text(); + + /* Allocate space for textmode font. */ + if (!__svgalib_emulatepage) + { + font_buf1_banked = malloc(FONT_SIZE * 2); + font_buf2_banked = font_buf1_banked + FONT_SIZE; + } + if (LINEAR_POINTER) + { + font_buf1_linear = malloc(FONT_SIZE * 2); + font_buf2_linear = font_buf1_linear + FONT_SIZE; + } + + /* save font data in plane 2 */ + __svgalib_outgra(0x04,0x02); + if (!__svgalib_emulatepage) + slowcpy(font_buf1_banked, GM, FONT_SIZE); + if (LINEAR_POINTER) + slowcpy(font_buf1_linear, LINEAR_POINTER, FONT_SIZE); + + /* save font data in plane 3 */ + __svgalib_outgra(0x04,0x03); + if (!__svgalib_emulatepage) + slowcpy(font_buf2_banked, GM, FONT_SIZE); + if (LINEAR_POINTER) + slowcpy(font_buf2_linear, LINEAR_POINTER, FONT_SIZE); +#endif + } + initialized = 1; + + /* do our own interrupt handling */ + for (i = 0; i < sizeof(sig2catch); i++) { + siga.sa_handler = signal_handler; + siga.sa_flags = 0; + zero_sa_mask(&(siga.sa_mask)); + sigaction((int) sig2catch[i], &siga, old_signal_handler + i); + } + + /* vga_unlockvc(); */ +} + +inline void vga_setpage(int p) +{ + p += vga_page_offset; + + if ((p == __svgalib_readpage) && (p == __svgalib_writepage)) + return; + + if (__svgalib_emulatepage) { + unsigned long offset = __svgalib_linear_mem_base; + if (__svgalib_linear_mem_fd == -1) { /* oops */ + + fprintf(stderr, + "svgalib: Warning: cannot change page when emulating banking in NoHelper mode.\n"); + return; + } +#ifdef __alpha__ + if (offset) + offset += 0x300000000ULL; +#endif + mmap(BANKED_POINTER, 65536, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, + __svgalib_linear_mem_fd, offset + (p << 16)); + + } else { + (*__svgalib_setpage) (p); + } + + __svgalib_readpage = p; + __svgalib_writepage = p; +} + + +void vga_setreadpage(int p) +{ + p += vga_page_offset; + if (p == __svgalib_readpage) + return; + if (!__svgalib_setrdpage || __svgalib_runinbackground) + { + fprintf(stderr, + "svgalib: Warning: vga_setreadpage is not supported with your config. Program\n" + " should check vga_getmodeinfo(mode)->flags before calling vga_setreadpage\n"); + return; + } + (*__svgalib_setrdpage) (p); + __svgalib_readpage = p; +} + + +void vga_setwritepage(int p) +{ + p += vga_page_offset; + if (p == __svgalib_writepage) + return; + if (!__svgalib_setwrpage || __svgalib_runinbackground) + { + fprintf(stderr, + "svgalib: Warning: vga_setwritepage is not supported with your config. Program\n" + " should check vga_getmodeinfo(mode)->flags before calling vga_setwritepage\n"); + return; + } + (*__svgalib_setwrpage) (p); + __svgalib_writepage = p; +} + +void vga_safety_fork(void (*shutdown_routine) (void)) +{ + pid_t childpid; + int child_status, oldkbmode; + + if (initialized) { + fprintf(stderr,"svgalib: warning: vga_safety_fork() called when already initialized\n"); + goto no_fork; + } + initialize(); + + /* + * get current keyboard mode: + * If this didn't suffice we claim we are on an old system and just don't + * need to restore it. + */ + ioctl(__svgalib_tty_fd, KDGKBMODE, &oldkbmode); + + childpid = fork(); + if (childpid < 0) { + no_fork: + fprintf(stderr,"svgalib: warning: can't fork to enhance reliability; proceeding anyway"); + return; + } + if (childpid) { + ioctl(__svgalib_tty_fd, (int) TIOCNOTTY, (char *)0); + for (;;) { + while (waitpid(childpid, &child_status, WUNTRACED) != childpid); + + if (shutdown_routine) + shutdown_routine(); + + vga_setmode(TEXT); /* resets termios as well */ + ioctl(__svgalib_tty_fd, KDSKBMODE, oldkbmode); + + if (WIFEXITED(child_status)) + exit(WEXITSTATUS(child_status)); + + if (WCOREDUMP(child_status)) + fprintf(stderr,"svgalib:vga_safety_fork: Core dumped!\n"); + + if (WIFSIGNALED(child_status)) { + fprintf(stderr,"svgalib:vga_safety_fork: Killed by signal %d, %s.\n", + WTERMSIG(child_status), + strsignal(WTERMSIG(child_status))); + exit(1); + } + if (WIFSTOPPED(child_status)) { + fprintf(stderr,"svgalib:vga_safety_fork: Stopped by signal %d, %s.\n", + WSTOPSIG(child_status), + strsignal(WSTOPSIG(child_status))); + fprintf(stderr,"\aWARNING! Continue stopped svgalib application at own risk. You are better\n" + "off killing it NOW!\n"); + continue; + } + } + } + /* These need to be done again because the child doesn't inherit them. */ + __svgalib_get_perm(); + + /* + * Actually the mmap's are inherited anyway (and not all are remade here), + * but it does not really harm. + */ + __vga_map(); + + /* + * We might still want to do vc switches. + */ + + __svgalib_takevtcontrol(); +} + +static void prepareforfontloading(void) +{ + if (__svgalib_chipset == CIRRUS) { + __svgalib_outseq(0x0f, __svgalib_inseq(0x0f) | 0x40 ); + } +} + +static void fontloadingcomplete(void) +{ + if (__svgalib_chipset == CIRRUS) { + __svgalib_outseq(0x0f, __svgalib_inseq(0x0f) & 0xbf ); + } +} + + +int vga_setmode(int mode) +{ + int modeflags=mode&0xfffff000; + + DPRINTF("setmode %i from %i\n", mode, CM); + + if(mode==-1)return vga_version; + + mode&=0xfff; + + if (!initialized) + initialize(); + + if (!vga_hasmode(mode)) + return -1; + +/* if (!flip) + vga_lockvc(); */ + if(CM)vga_waitretrace(); + __svgalib_disable_interrupt(); + + prv_mode = CM; + CM = mode; + + /* disable video */ + vga_screenoff(); + + if (!__svgalib_secondary && (prv_mode==TEXT) && (mode!=TEXT)) { + ioctl(__svgalib_tty_fd, KDSETMODE, KD_GRAPHICS); + } + + if(!__svgalib_novga) { + /* Should be more robust (eg. grabbed X modes) */ + if (__svgalib_getchipset() == ET4000 + && prv_mode != G640x480x256 + && SVGAMODE(prv_mode)) + chipset_setmode(G640x480x256, prv_mode); + + /* This is a hack to get around the fact that some C&T chips + * are programmed to ignore syncronous resets. So if we are + * a C&T wait for retrace start + */ + if (__svgalib_getchipset() == CHIPS) { + while ((__svgalib_inis1() & 0x08) == 0x08 );/* wait VSync off */ + while ((__svgalib_inis1() & 0x08) == 0 ); /* wait VSync on */ + __svgalib_outseq(0x07,0x00); /* reset hsync - just in case... */ + } + } + + if (mode == TEXT) { + /* Returning to textmode. */ + + if (SVGAMODE(prv_mode)) + vga_setpage(0); + + /* The extended registers are restored either by the */ + /* chipset setregs function, or the chipset setmode function. */ + + /* restore font data - first select a 16 color graphics mode */ + /* Note: this should restore the old extended registers if */ + /* setregs is not defined for the chipset. */ + if (__svgalib_novga) __svgalib_driverspecs->setmode(TEXT, prv_mode); + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->restorefont) { + __svgalib_driverspecs->emul->restorefont(); + chipset_setregs(text_regs, mode); + } else if(!__svgalib_novga) { +#if 1 + __svgalib_driverspecs->setmode(GPLANE16, prv_mode); + if (CHIPSET != EGA) + /* restore old extended regs */ + chipset_setregs(text_regs, mode); +#if 1 + /* disable Set/Reset Register */ + __svgalib_outgra(0x01,0x00); + + prepareforfontloading(); + + restore_text(); + + /* restore font data in plane 2 - necessary for all VGA's */ + __svgalib_outseq(0x02,0x04); + + if (__svgalib_emulatepage) + slowcpy(LINEAR_POINTER, font_buf1_linear, FONT_SIZE); + else + slowcpy(GM, font_buf1_banked, FONT_SIZE); + + /* restore font data in plane 3 - necessary for Trident VGA's */ + __svgalib_outseq(0x02,0x08); + if (__svgalib_emulatepage) + slowcpy(LINEAR_POINTER, font_buf2_linear, FONT_SIZE); + else + slowcpy(GM, font_buf2_banked, FONT_SIZE); + fontloadingcomplete(); +#endif + /* change register adresses if monochrome text mode */ + /* EGA is assumed to use color emulation. */ + if (!color_text) { + __svgalib_CRT_I = CRT_IM; + __svgalib_CRT_D = CRT_DM; + __svgalib_IS1_R = IS1_RM; + __svgalib_vgacolormode=0; + __svgalib_outmisc(__svgalib_inmisc() & 0xfe); + } +#else + __svgalib_driverspecs->setmode(TEXT, prv_mode); + if (CHIPSET != EGA) + /* restore old extended regs */ + chipset_setregs(text_regs, mode); + __svgalib_outseq(0,1); + __svgalib_outseq(2,4); + __svgalib_outseq(4,7); + __svgalib_outseq(0,3); + __svgalib_outgra(4,2); + __svgalib_outgra(5,0); + __svgalib_outgra(6,0); + if (__svgalib_emulatepage) + slowcpy(LINEAR_POINTER, font_buf1_linear, FONT_SIZE); + else + slowcpy(GM, font_buf1_banked, FONT_SIZE); + __svgalib_outseq(2,2); + slowcpy(GM, text_buf2, FONT_SIZE); + __svgalib_outseq(2,1); + if (__svgalib_emulatepage) + slowcpy(LINEAR_POINTER, font_buf1_linear, FONT_SIZE); + else + slowcpy(GM, font_buf1_banked, FONT_SIZE); + __svgalib_outseq(0,1); + __svgalib_outseq(2,3); + __svgalib_outseq(4,3); + __svgalib_outseq(0,3); + __svgalib_outgra(4,0); + __svgalib_outgra(5,16); + __svgalib_outgra(6,14); + +#endif + } else chipset_setregs(text_regs, mode); + + /* restore text mode VGA registers */ + __svgalib_setregs(text_regs); + + /* restore saved palette */ + restorepalette(text_red, text_green, text_blue); + + /* Set VMEM to some minimum value .. probably pointless.. */ + { + vga_claimvideomemory(12); + } + + /* if (!flip) */ + /* enable text output - restores the screen contents */ + + if (!__svgalib_secondary) { + ioctl(__svgalib_tty_fd, KDSETMODE, KD_TEXT); + } + + /* now wait for signal to stabilize, but don't do it on C&T chips. */ + /* This is needed to restore correct text mode stretching. */ +#ifdef MODESWITCH_DELAY + if (__svgalib_chipset != CHIPS) + usleep(MODESWITCHDELAY); +#endif + + /* enable video */ + vga_screenon(); + + if (!flip) + /* restore text mode termio */ + __svgalib_set_texttermio(); + } else { /* Setting a graphics mode. */ + vga_modeinfo *modeinfo; +#if 0 + if(prv_mode == TEXT) { + __svgalib_outseq(0,1); + __svgalib_outseq(2,4); + __svgalib_outseq(4,7); + __svgalib_outseq(0,3); + __svgalib_outgra(4,2); + __svgalib_outgra(5,0); + __svgalib_outgra(6,0); + if (__svgalib_emulatepage) + slowcpy(font_buf1_linear, LINEAR_POINTER, FONT_SIZE); + else + slowcpy(font_buf1_banked, GM, FONT_SIZE); + __svgalib_outgra(4,1); + slowcpy(text_buf2, GM, FONT_SIZE); + __svgalib_outseq(4,0); + if (__svgalib_emulatepage) + slowcpy(font_buf1_linear, LINEAR_POINTER, FONT_SIZE); + else + slowcpy(font_buf1_banked, GM, FONT_SIZE); + __svgalib_outseq(0,1); + __svgalib_outseq(2,3); + __svgalib_outseq(4,3); + __svgalib_outseq(0,3); + __svgalib_outgra(4,0); + __svgalib_outgra(5,16); + __svgalib_outgra(6,14); + } +#endif + /* disable text output */ +#if 0 + if (!__svgalib_secondary) { + ioctl(__svgalib_tty_fd, KDSETMODE, KD_GRAPHICS); + } +#endif + if (SVGAMODE(prv_mode)) { + /* The current mode is an SVGA mode, and we now want to */ + /* set a standard VGA mode. Make sure the extended regs */ + /* are restored. */ + /* Also used when setting another SVGA mode to hopefully */ + /* eliminate lock-ups. */ + vga_setpage(0); + chipset_setregs(text_regs, mode); + /* restore old extended regs */ + } + /* shift to color emulation */ + setcoloremulation(); + + CI.xdim = infotable[mode].xdim; + CI.ydim = infotable[mode].ydim; + CI.colors = infotable[mode].colors; + CI.xbytes = infotable[mode].xbytes; + CI.bytesperpixel = infotable[mode].bytesperpixel; + + if (chipset_setmode(mode, prv_mode)) { + /* Darn setmode failed, this really shouldn't happen, + but alas it does (atleast for fbdev) */ + /* Force CM to an svgalib mode so that vga_setpage(0) gets + called by vga_setmode(TEXT) */ + CM = G640x480x256; + vga_setmode(TEXT); + fprintf(stderr, "svgalib: error: vga_setmode(chipset_setmode) failed," + " textmode has been restored\n"); + return -1; + } + + modeinfo = vga_getmodeinfo(mode); + MODEX = ((MODEFLAGS = modeinfo->flags) & IS_MODEX); + + /* Set default claimed memory (moved here from initialize - Michael.) */ + if (mode == G320x200x256) + VMEM = 65536; + else if (STDVGAMODE(mode)) + VMEM = 256 * 1024; /* VGA cards have 256KB ram. */ + else { + VMEM = modeinfo->linewidth * modeinfo->height; + CI.xbytes = modeinfo->linewidth; + } + + if (!flip) { + /* set default palette */ + if (CI.colors <= 256) + restorepalette(default_red, default_green, default_blue); + + /* clear screen (sets current color to 15) */ + __svgalib_readpage = __svgalib_writepage = -1; + if(!(modeflags&0x8000))vga_clear(); + + if (SVGAMODE(CM)) + vga_setpage(0); + } + __svgalib_readpage = __svgalib_writepage = -1; + currentlogicalwidth = CI.xbytes; + currentdisplaystart = 0; + +#ifdef MODESWITCH_DELAY + usleep(MODESWITCHDELAY); /* wait for signal to stabilize */ +#endif + + /* enable video */ + if (!flip) + vga_screenon(); + + if (mouse_support && mouse_open) { + /* vga_lockvc(); */ + mouse_setxrange(0, CI.xdim - 1); + mouse_setyrange(0, CI.ydim - 1); + mouse_setwrap(MOUSE_NOWRAP); + mouse_mode = mode; + } + if (__svgalib_emulatepage && (modeinfo->flags & CAPABLE_LINEAR) && + !(modeinfo->flags & LINEAR_USE)) { + __svgalib_driverspecs->linear(LINEAR_ENABLE, 0); + } + + if (!flip) /* set graphics mode termio */ + __svgalib_set_graphtermio(); + else if (__svgalib_kbd_fd < 0) + __svgalib_enable_interrupt(); + } + + /* if (!flip) + * vga_unlockvc(); */ + return 0; +} + +void vga_gettextfont(void *font) +{ + unsigned int getsize; + unsigned char *font_buf1; + + if (__svgalib_emulatepage) + font_buf1 = font_buf1_linear; + else + font_buf1 = font_buf1_banked; + + /* robert@debian.org, May, 26th 2002: check for valid font_buf buffer */ + if (!font_buf1) { + syslog(LOG_DEBUG, "svgalib: uninitialized variable: font_buf1"); + return; + } + + getsize = fontbufsize; + if (getsize > FONT_SIZE) + getsize = FONT_SIZE; + memcpy(font, font_buf1, getsize); + if (fontbufsize > getsize) + memset(((char *)font) + getsize, 0, (size_t)(fontbufsize - getsize)); +} + +void vga_puttextfont(void *font) +{ + unsigned int putsize; + unsigned char *font_buf1, *font_buf2; + + if (__svgalib_emulatepage) { + font_buf1 = font_buf1_linear; + font_buf2 = font_buf2_linear; + } else { + font_buf1 = font_buf1_banked; + font_buf2 = font_buf2_banked; + } + + /* robert@debian.org, May, 26th 2002: check for valid font_buf buffer */ + if (!font_buf1 || !font_buf2) { + syslog(LOG_DEBUG, "svgalib: uninitialized variable: font_buf1 or font_buf2"); + return; + } + + putsize = fontbufsize; + if (putsize > FONT_SIZE) + putsize = FONT_SIZE; + memcpy(font_buf1, font, putsize); + memcpy(font_buf2, font, putsize); + if (putsize < FONT_SIZE) { + memset(font_buf1 + putsize, 0, (size_t)(FONT_SIZE - putsize)); + memset(font_buf2 + putsize, 0, (size_t)(FONT_SIZE - putsize)); + } + +} + +void vga_gettextmoderegs(void *regs) +{ + memcpy(regs, text_regs, MAX_REGS); +} + +void vga_settextmoderegs(void *regs) +{ + memcpy(text_regs, regs, MAX_REGS); +} + +int vga_getcurrentmode(void) +{ + return CM; +} + +int vga_getcurrentchipset(void) +{ + return __svgalib_getchipset(); +} + +void vga_disabledriverreport(void) +{ + DREP = 0; +} + +vga_modeinfo *vga_getmodeinfo(int mode) +{ + static vga_modeinfo modeinfo; + int is_modeX = (CM == mode) && MODEX; + + DTP((stderr,"getmodeinfo %i\n",mode)); + + modeinfo.linewidth = infotable[mode].xbytes; + __svgalib_getchipset(); + if (mode > vga_lastmodenumber()) + return NULL; + modeinfo.width = infotable[mode].xdim; + modeinfo.height = infotable[mode].ydim; + modeinfo.bytesperpixel = infotable[mode].bytesperpixel; + modeinfo.colors = infotable[mode].colors; + if (is_modeX) { + modeinfo.linewidth = modeinfo.width / 4; + modeinfo.bytesperpixel = 0; + } + if (mode == TEXT) { + modeinfo.flags = HAVE_EXT_SET; + return &modeinfo; + } + modeinfo.flags = 0; + if ((STDVGAMODE(mode) && mode != G320x200x256) || is_modeX) + __svgalib_vga_driverspecs.getmodeinfo(mode, &modeinfo); + else + /* Get chipset specific info for SVGA modes and */ + /* 320x200x256 (chipsets may support more pages) */ + chipset_getmodeinfo(mode, &modeinfo); + + if (modeinfo.colors == 256 && modeinfo.bytesperpixel == 0) + modeinfo.flags |= IS_MODEX; + if (mode > __GLASTMODE) + modeinfo.flags |= IS_DYNAMICMODE; + if (__svgalib_emulatepage || __svgalib_runinbackground) + modeinfo.flags &= ~HAVE_RWPAGE; + + /* Maskout CAPABLE_LINEAR if requested by config file */ + modeinfo.flags &= modeinfo_mask; + + /* Many cards have problems with linear 320x200x256 mode */ + if(mode==G320x200x256)modeinfo.flags &= (~CAPABLE_LINEAR) & (~LINEAR_USE); + + /* Signal if linear support has been enabled */ + if (modeinfo.flags & CAPABLE_LINEAR) { + modeinfo.flags |= __svgalib_modeinfo_linearset; + } + + return &modeinfo; +} + +int vga_hasmode(int mode) +{ + vga_modeinfo *modeinfo; + DTP((stderr,"hasmode %i\n",mode)); + + __svgalib_getchipset(); /* Make sure the chipset is known. */ + if (mode == TEXT) + return 1; + + if (mode < 0 || mode > lastmodenumber) + return 0; + + if(infotable[mode].xdimmaxx || + infotable[mode].ydimmaxy) + return 0; + + if(__svgalib_emulatepage && STDVGAMODE(mode) && (mode!=G320x200x256)) + return 0; + + if (!chipset_modeavailable(mode)) + return 0; + + modeinfo = vga_getmodeinfo(mode); + if (__svgalib_emulatepage && (mode!=G320x200x256) && + !(modeinfo->flags & (CAPABLE_LINEAR))) + return 0; + + return 1; +} + + +int vga_lastmodenumber(void) +{ + __svgalib_getchipset(); + return lastmodenumber; +} + + +int __svgalib_addmode(int xdim, int ydim, int cols, int xbytes, int bytespp) +{ + int i; + + for (i = 0; i <= lastmodenumber; ++i) + if (infotable[i].xdim == xdim && + infotable[i].ydim == ydim && + infotable[i].colors == cols && + infotable[i].bytesperpixel == bytespp && + infotable[i].xbytes == xbytes) + return i; + if (lastmodenumber >= MAX_MODES - 1) + return -1; /* no more space available */ + + if(xdimmaxx || ydimmaxy) + return -1; + + ++lastmodenumber; + infotable[lastmodenumber].xdim = xdim; + infotable[lastmodenumber].ydim = ydim; + infotable[lastmodenumber].colors = cols; + infotable[lastmodenumber].xbytes = xbytes; + infotable[lastmodenumber].bytesperpixel = bytespp; + + return lastmodenumber; +} + +int vga_setcolor(int color) +{ + switch (CI.colors) { + case 2: + if (color != 0) + color = 15; + case 16: /* update set/reset register */ + __svgalib_outgra(0x00,color&0x0f); + break; + default: + COL = color; + break; + } + return 0; +} + + +int vga_screenoff(void) +{ + int tmp = 0; + + SCREENON = 0; + + if(__svgalib_novga) return 0; + + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->screenoff) { + tmp = __svgalib_driverspecs->emul->screenoff(); + } else { + /* turn off screen for faster VGA memory acces */ + if ((CHIPSET != EGA) && !__svgalib_novga) { + __svgalib_outseq(0x01,__svgalib_inseq(0x01) | 0x20); + } + /* Disable video output */ +#ifdef DISABLE_VIDEO_OUTPUT + __svgalib_attscreen(0); +#endif + } + + return tmp; +} + + +int vga_screenon(void) +{ + int tmp = 0; + + SCREENON = 1; + if(__svgalib_novga) return 0; + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->screenon) { + tmp = __svgalib_driverspecs->emul->screenon(); + } else { + /* turn screen back on */ + if ((CHIPSET != EGA) && !__svgalib_novga) { + __svgalib_outseq(0x01,__svgalib_inseq(0x01) & 0xdf); + } +/* #ifdef DISABLE_VIDEO_OUTPUT */ + /* enable video output */ + __svgalib_attscreen(0x20); +/* #endif */ + } + + return 0; +} + + +int vga_getxdim(void) +{ + return CI.xdim; +} + + +int vga_getydim(void) +{ + return CI.ydim; +} + + +int vga_getcolors(void) +{ + return CI.colors; +} + +int vga_white(void) +{ + switch (CI.colors) { + case 2: + case 16: + case 256: + return 15; + case 1 << 15: + return 32767; + case 1 << 16: + return 65535; + case 1 << 24: + return (1 << 24) - 1; + } + return CI.colors - 1; +} + +int vga_claimvideomemory(int m) +{ + vga_modeinfo *modeinfo; + int cardmemory; + + modeinfo = vga_getmodeinfo(CM); + if (m < VMEM) + return 0; + if (modeinfo->colors == 16) + cardmemory = modeinfo->maxpixels / 2; + else + cardmemory = (modeinfo->maxpixels * modeinfo->bytesperpixel + + 2) & 0xffff0000; + /* maxpixels * bytesperpixel can be 2 less than video memory in */ + /* 3 byte-per-pixel modes; assume memory is multiple of 64K */ + if (m > cardmemory) + return -1; + VMEM = m; + return 0; +} + +int vga_setmodeX(void) +{ + switch (CM) { + case TEXT: +/* case G320x200x256: */ + case G320x240x256: + case G320x400x256: + case G360x480x256: + case G400x300x256X: + return 0; + } + if (CI.colors == 256 && VMEM < 256 * 1024) { + __svgalib_outseq(0x04, (__svgalib_inseq(0x04) & 0xf7) | 0x04); + __svgalib_outcrtc(0x14, __svgalib_incrtc(0x14) & 0xbf ); + __svgalib_outcrtc(0x17, __svgalib_incrtc(0x17) | 0x40); + CI.xbytes = CI.xdim / 4; + vga_setpage(0); + MODEX = 1; + return 1; + } + return 0; +} + +static int saved_readpage = -1; +static int saved_writepage = -1; +static int saved_logicalwidth=0; +static int saved_displaystart=0; +static int saved_modeX=0; +static int saved_linear=0; +static unsigned char saved_crtc[CRT_C]; +static int saved_lfb_fd=-1; +static unsigned long saved_lfb_base=0; +static unsigned long saved_lfb_size=0; +static int saved_emulatepage=0; + +static void alloc_graph_buf(int size) { + if(__svgalib_runinbackground) { + char filename[256]; + snprintf(filename, 255, "/tmp/.svga.bgr.%i.%li",getpid(),random()); + background_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IREAD|S_IWRITE); + unlink(filename); + ftruncate(background_fd, size); + graph_buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, + background_fd, 0); + } else { + if ((graph_buf = malloc(size)) == NULL) { + fprintf(stderr,"Cannot allocate memory for VGA state\n"); + vga_setmode(TEXT); + exit(1); + } + } + graph_buf_size= size; +} + +static void free_graph_buf(void) { + if(__svgalib_runinbackground) { + munmap(graph_buf, graph_buf_size); + close(background_fd); + } else { + free(graph_buf); + } + graph_buf=NULL; + graph_buf_size=0; +} + +static void savestate(void) +{ + int i; + + vga_screenoff(); + + savepalette(graph_red, graph_green, graph_blue); + + saved_readpage = __svgalib_readpage; + saved_writepage = __svgalib_writepage; + saved_logicalwidth = currentlogicalwidth; + saved_displaystart = currentdisplaystart; + saved_modeX = MODEX; + saved_linear = __svgalib_modeinfo_linearset&IS_LINEAR; + + if(STDVGAMODE(CM)) { + vga_getcrtcregs(saved_crtc); /* save for tweaked modes */ + } + + if (CM == G320x200x256 && VMEM <= 65536) { + /* 320x200x256 is a special case; only 64K is addressable */ + /* (unless more has been claimed, in which case we assume */ + /* SVGA bank-switching) */ + alloc_graph_buf(GRAPH_SIZE); + memcpy(graph_buf, GM, GRAPH_SIZE); + } else if (MODEX || CM == G800x600x16 || (STDVGAMODE(CM) && CM != G320x200x256)) { + /* for planar VGA modes, save the full 256K */ + __svgalib_vga_driverspecs.setmode(GPLANE16, prv_mode); + alloc_graph_buf(4*GRAPH_SIZE); + for (i = 0; i < 4; i++) { + /* save plane i */ + __svgalib_outgra(4,i); + memcpy(graph_buf + i * GRAPH_SIZE, GM, GRAPH_SIZE); + } + } else if (CI.colors == 16) { + int page, size, sbytes; + unsigned char *sp; + + size = VMEM; + alloc_graph_buf(4*size); + sp = graph_buf; + for (page = 0; size > 0; ++page) { + vga_setpage(page); + sbytes = (size > GRAPH_SIZE) ? GRAPH_SIZE : size; + for (i = 0; i < 4; i++) { + /* save plane i */ + __svgalib_outgra(4,i); + memcpy(sp, GM, sbytes); + sp += sbytes; + } + size -= sbytes; + } + } else { /* SVGA, and SVGA 320x200x256 if videomemoryused > 65536 */ + int size; + int page; + + size = VMEM; + alloc_graph_buf(size); + if( CAN_USE_LINEAR ) { + memcpy(graph_buf, LINEAR_POINTER, size); + } else { + page = 0; + while (size >= 65536) { + vga_setpage(page); + memcpy(graph_buf + page * 65536, GM, 65536); + page++; + size -= 65536; + } + if (size > 0) { + vga_setpage(page); + memcpy(graph_buf + page * 65536, GM, size); + } + } + } +} + +static void restorestate(void) +{ + int i; + vga_modeinfo *modeinfo; + + vga_screenoff(); + + if (saved_modeX) + vga_setmodeX(); + + if(STDVGAMODE(CM)) { + vga_setcrtcregs(saved_crtc); /* restore tweaked modes */ + } + + restorepalette(graph_red, graph_green, graph_blue); + + if(saved_linear) + vga_setlinearaddressing(); + + modeinfo = vga_getmodeinfo(CM); + if (__svgalib_emulatepage && (modeinfo->flags & CAPABLE_LINEAR) && + !(modeinfo->flags & LINEAR_USE)) { + __svgalib_driverspecs->linear(LINEAR_ENABLE, 0); + } + + if (CM == G320x200x256 && VMEM <= 65536) { + memcpy(GM, graph_buf, 65536); + } else if (MODEX || CM == G800x600x16 || (STDVGAMODE(CM) && CM != G320x200x256)) { + int setresetreg, planereg; + /* disable Set/Reset Register */ + setresetreg = __svgalib_ingra(0x01); + __svgalib_outgra(0x01,0x00); + planereg = __svgalib_ingra(0x02); + + for (i = 0; i < 4; i++) { + /* restore plane i */ + __svgalib_outseq(0x02,1< 0; ++page) { + vga_setpage(page); + rbytes = (size > GRAPH_SIZE) ? GRAPH_SIZE : size; + for (i = 0; i < 4; i++) { + /* save plane i */ + __svgalib_outseq(0x02,1<= 65536) { + vga_setpage(page); + memcpy(GM, graph_buf + page * 65536, 65536); + size -= 65536; + page++; + } + if (size > 0) { + vga_setpage(page); + memcpy(GM, graph_buf + page * 65536, size); + } + } + } + + if (saved_logicalwidth != CI.xbytes) + vga_setlogicalwidth(saved_logicalwidth); + if ((saved_readpage == saved_writepage) && (saved_readpage != -1)) + vga_setpage(saved_readpage); + else + { + if (saved_readpage != -1) + vga_setreadpage(saved_readpage); + if (saved_writepage != -1) + vga_setwritepage(saved_writepage); + } + if (saved_displaystart != 0) { + if (CHIPSET != VGA && CHIPSET != EGA) { + currentdisplaystart = saved_displaystart; + __svgalib_driverspecs->setdisplaystart(saved_displaystart); + } + } + + vga_screenon(); + + free_graph_buf(); +} + + +int vga_getch(void) +{ + int fd; + char c; + + if (CM == TEXT) + return -1; + + fd = __svgalib_novccontrol ? fileno(stdin) : __svgalib_tty_fd; + + while ((read(fd, &c, 1) < 0) && (errno == EINTR)); + + return c; +} + +/* I have kept the slightly funny 'flip' terminology. */ + +void __svgalib_flipaway(void) +{ + /* Leaving console. */ +#ifdef MODESWITCH_DELAY + usleep(10); +#endif + flip_mode = CM; + + __joystick_flip_vc(0); + + if (CM != TEXT) { + /* wait for any blitter operation to finish */ + idle_accel(); + /* Save state and go to textmode. */ +#ifdef SAVEREGS + chipset_saveregs(graph_regs); + __svgalib_saveregs(graph_regs); +#endif + savestate(); + flip = 1; + if(!__svgalib_secondary)vga_setmode(TEXT); + flip = 0; + + if (__svgalib_runinbackground) { + /* Save current lfb settings, make lfb-settings + point to background_fd, force emulatepage */ + saved_lfb_fd = __svgalib_linear_mem_fd; + saved_lfb_base = __svgalib_linear_mem_base; + saved_lfb_size = __svgalib_linear_mem_size; + saved_emulatepage = __svgalib_emulatepage; + __svgalib_linear_mem_fd = background_fd; + __svgalib_linear_mem_base = 0; + __svgalib_linear_mem_size = graph_buf_size; + __svgalib_emulatepage = 1; + /* savestate may have changed the page, so restore + the saved page pointer */ + __svgalib_readpage = __svgalib_writepage = saved_readpage; + /* map background_fd over BANKED_POINTER and LINEAR_POINTER */ + map_banked(MAP_FIXED); + map_linear(MAP_FIXED); + } + } +} + +static void __svgalib_flipback(void) +{ + /* Entering console. */ + /* Hmmm... and how about unlocking anything someone else locked? */ + __joystick_flip_vc(1); + + chipset_unlock(); + if (flip_mode != TEXT) { + if (__svgalib_runinbackground) { + /* make lfb-settings point to real lfb-fd */ + __svgalib_linear_mem_fd = saved_lfb_fd; + __svgalib_linear_mem_base = saved_lfb_base; + __svgalib_linear_mem_size = saved_lfb_size; + __svgalib_emulatepage = saved_emulatepage; + /* we've been running in the background so the current + readpage is the correct one to restore not the saved one. */ + saved_readpage = saved_writepage = __svgalib_readpage; + /* map the real memory over BANKED and LINEAR_POINTER */ + map_banked(MAP_FIXED); + map_linear(MAP_FIXED); + } + /* Restore graphics mode and state. */ + if(!__svgalib_secondary) { + flip = 1; + vga_setmode(flip_mode); + flip = 0; +#ifdef SAVEREGS + chipset_setregs(graph_regs,flip_mode); + __svgalib_setregs(graph_regs); +#endif + restorestate(); + if(__svgalib_cursor_status>=0) __svgalib_cursor_restore(); + } + } +} + +int vga_flip(void) +{ + if (CM != TEXT) { /* save state and go to textmode */ + savestate(); + flip_mode = CM; + flip = 1; + vga_setmode(TEXT); + flip = 0; + } else { /* restore graphics mode and state */ + flip = 1; + vga_setmode(flip_mode); + flip = 0; + restorestate(); + } + return 0; +} + +int vga_setflipchar(int c) +/* This function is obsolete. Retained for VGAlib compatibility. */ +{ + __svgalib_flipchar = c; + + return 0; +} + +void vga_setlogicalwidth(int w) +{ + __svgalib_driverspecs->setlogicalwidth(w); + currentlogicalwidth = w; +} + +void vga_setdisplaystart(int a) +{ + currentdisplaystart = a; + if (CHIPSET != VGA && CHIPSET != EGA) + if (MODEX || CI.colors == 16) { + /* We are currently using a Mode X-like mode on a */ + /* SVGA card, use the standard VGA function */ + /* that works properly for Mode X. */ + /* Same goes for 16 color modes. */ + __svgalib_vga_driverspecs.setdisplaystart(a); + return; + } + /* Call the regular display start function for the chipset */ + if( (MODEFLAGS & IOCTL_SETDISPLAY) && !__svgalib_nohelper) + ioctl(__svgalib_mem_fd, SVGAHELPER_SETDISPLAYSTART, a); + else + __svgalib_driverspecs->setdisplaystart(a); +} + +void vga_bitblt(int srcaddr, int destaddr, int w, int h, int pitch) +{ + __svgalib_driverspecs->bitblt(srcaddr, destaddr, w, h, pitch); +} + +void vga_imageblt(void *srcaddr, int destaddr, int w, int h, int pitch) +{ + __svgalib_driverspecs->imageblt(srcaddr, destaddr, w, h, pitch); +} + +void vga_fillblt(int destaddr, int w, int h, int pitch, int c) +{ + __svgalib_driverspecs->fillblt(destaddr, w, h, pitch, c); +} + +void vga_hlinelistblt(int ymin, int n, int *xmin, int *xmax, int pitch, + int c) +{ + __svgalib_driverspecs->hlinelistblt(ymin, n, xmin, xmax, pitch, c); +} + +void vga_blitwait(void) +{ + __svgalib_driverspecs->bltwait(); +} + +int vga_ext_set(unsigned what,...) +{ + va_list params; + register int retval = 0; + + switch(what) { + case VGA_EXT_AVAILABLE: + /* Does this use of the arglist corrupt non-AVAIL_ACCEL ext_set? */ + va_start(params, what); + switch (va_arg(params, int)) { + case VGA_AVAIL_ACCEL: + if (__svgalib_driverspecs->accelspecs != NULL) + retval = __svgalib_driverspecs->accelspecs->operations; + break; + case VGA_AVAIL_ROP: + if (__svgalib_driverspecs->accelspecs != NULL) + retval = __svgalib_driverspecs->accelspecs->ropOperations; + break; + case VGA_AVAIL_TRANSPARENCY: + if (__svgalib_driverspecs->accelspecs != NULL) + retval = __svgalib_driverspecs->accelspecs->transparencyOperations; + break; + case VGA_AVAIL_ROPMODES: + if (__svgalib_driverspecs->accelspecs != NULL) + retval = __svgalib_driverspecs->accelspecs->ropModes; + break; + case VGA_AVAIL_TRANSMODES: + if (__svgalib_driverspecs->accelspecs != NULL) + retval = __svgalib_driverspecs->accelspecs->transparencyModes; + break; + case VGA_AVAIL_SET: + retval = (1 << VGA_EXT_PAGE_OFFSET) | + (1 << VGA_EXT_FONT_SIZE); /* These are handled by us */ + break; + } + va_end(params); + break; + case VGA_EXT_PAGE_OFFSET: + /* Does this use of the arglist corrupt it? */ + va_start(params, what); + retval = vga_page_offset; + vga_page_offset = va_arg(params, int); + va_end(params); + return retval; + case VGA_EXT_FONT_SIZE: + va_start(params, what); + what = va_arg(params, unsigned int); + va_end(params); + if (!what) + return FONT_SIZE; + retval = fontbufsize; + fontbufsize = what; + return retval; + } + if ((CM != TEXT) && (MODEFLAGS & HAVE_EXT_SET)) { + va_start(params, what); + retval |= __svgalib_driverspecs->ext_set(what, params); + va_end(params); + } + return retval; +} + +/* Parse a string for options.. str is \0-terminated source, + commands is an array of char ptrs (last one is NULL) containing commands + to parse for. (if first char is ! case sensitive), + func is called with ind the index of the detected command. + func has to return the ptr to the next unhandled __svgalib_token returned by token(&nptr). + Use __svgalib_token(&nptr) to get the next token from the file.. + mode is 1 when reading from conffile and 0 when parsing the env-vars. This is to + allow disabling of dangerous (hardware damaging) options when reading the ENV-Vars + of Joe user. + Note: We use strtok, that is str is destroyed! */ + +char *__svgalib_token(char **ptr) +{ + char *p=*ptr; + + if (!p) + return NULL; + + while(*p==' ')p++; + + if(*p != '\0' ) { + char *t; + t=p; + while((*t != '\0') && (*t != ' '))t++; + if(*t==' ') { + *t='\0'; + t++; + } + *ptr=t; + return p; + } else { + *ptr=NULL; + return NULL; + } +} + +static void parse_string(char *str, char **commands, char *(*func) (int ind, int mode, char **nptr), int mode) +{ + int index; + char *ptr, **curr, **nptr, *tmp; + + /*Pass one, delete comments,ensure only whitespace is ' ' */ + for (ptr = str; *ptr; ptr++) { + if (*ptr == '#') { + while (*ptr && (*ptr != '\n')) { + *ptr++ = ' '; + } + if (*ptr) + *ptr = ' '; + } else if (isspace(*ptr)) { + *ptr = ' '; + } + } + /*Pass two, parse commands */ + nptr=&tmp; + tmp=str; + ptr = __svgalib_token(nptr); + while (ptr) { +#ifdef DEBUG_CONF + fprintf(stderr,"Parsing: %s\n", ptr); +#endif + for (curr = commands, index = 0; *curr; curr++, index++) { +#ifdef DEBUG_CONF + fprintf(stderr,"Checking: %s\n", *curr); +#endif + if (**curr == '!') { + if (!strcmp(*curr + 1, ptr)) { + ptr = (*func) (index, mode, nptr); + break; + } + } else { + if (!strcasecmp(*curr, ptr)) { + ptr = (*func) (index, mode, nptr); + break; + } + } + } + if (!*curr) /*unknown command */ + ptr = __svgalib_token(nptr); /* skip silently til' next command */ + } +} + +static int allowoverride = 0; /* Allow dangerous options in ENV-Var or in */ + /* the $HOME/.svgalibrc */ + +static void process_config_file(FILE *file, int mode, char **commands, + char *(*func)(int ind, int mode, char **nptr)) { + struct stat st; + char *buf, *ptr; + int i; + + fstat(fileno(file), &st); /* Some error analysis may be fine here.. */ + if ( (buf = alloca(st.st_size + 1)) == 0) { /* + a final \0 */ + fprintf(stderr,"svgalib: out of mem while parsing config file !\n"); + return; + } + fread(buf, 1, st.st_size, file); + for (i = 0, ptr = buf; i < st.st_size; i++, ptr++) { + if (!*ptr) + *ptr = ' '; /* Erase any maybe embedded \0 */ + } + *ptr = 0; /* Trailing \0 */ + parse_string(buf, commands, func, mode); /* parse config file */ +} + +/* This is a service function for drivers. Commands and func are as above. + The following config files are parsed in this order: + - /etc/vga/libvga.conf (#define SVGALIB_CONFIG_FILE) + - ~/.svgalibrc + - the file where env variavle SVGALIB_CONFIG_FILE points + - the env variable SVGALIB_CONFIG (for compatibility, but I would remove + it, we should be more flexible... Opinions ?) + - MW: I'd rather keep it, doesn't do too much harm and is sometimes nice + to have. +*/ +void __svgalib_read_options(char **commands, char *(*func) (int ind, int mode, char **nptr)) { + FILE *file=NULL; + char *buf = NULL, *ptr; + int i; + + if ((ptr = getenv("SVGALIB_CARD"))) { + char configfilename[256]; + snprintf(configfilename, 256, "%s.%s", SVGALIB_CONFIG_FILE, ptr); + file = fopen(configfilename, "r"); + if (!file) + fprintf(stderr, "svgalib: Warning config file \'%s\' not found,\n" + "using default configfile \'%s\'\n", configfilename, SVGALIB_CONFIG_FILE); + } + if (!file) + file = fopen(SVGALIB_CONFIG_FILE, "r"); + if (file) { +#ifdef DEBUG_CONF + fprintf(stderr,"Processing config file\n"); +#endif + process_config_file(file, 1, commands, func); + fclose(file); + } else { + fprintf(stderr, "svgalib: Error: configuration file \'%s\' not found.\n", SVGALIB_CONFIG_FILE); + exit(1); + } + + if ( (ptr = getenv("HOME")) != 0) { + char *filename; + + filename = alloca(strlen(ptr) + 20); + if (!filename) { + fprintf(stderr,"svgalib: out of mem while parsing SVGALIB_CONFIG_FILE !\n"); + } else { + strcpy(filename, ptr); + strcat(filename, "/.svgalibrc"); + if ( (file = fopen(filename, "r")) != 0) { +#ifdef DEBUG_CONF + fprintf(stderr,"Processing config file \'%s\'\n", filename); +#endif + process_config_file(file, allowoverride, commands, func); + fclose(file); + } + } + } + + if ( (ptr = getenv("SVGALIB_CONFIG_FILE")) != 0) { + if ( (file = fopen(ptr, "r")) != 0) { +#ifdef DEBUG_CONF + fprintf(stderr,"Processing config file \'%s\'\n", ptr); +#endif + process_config_file(file, allowoverride, commands, func); + fclose(file); + } else { + fprintf(stderr, "svgalib: warning: config file \'%s\', pointed to by SVGALIB_CONFIG_FILE, not found !\n", ptr); + } + } + + if ( (ptr = getenv("SVGALIB_CONFIG")) != 0 && (i = strlen(ptr)) != 0) { + buf = alloca(i + 1); + if (!buf) { + fprintf(stderr,"svgalib: out of mem while parsing SVGALIB_CONFIG !\n"); + } else { + strcpy(buf, ptr); /* Copy for safety and strtok!! */ +#ifdef DEBUG_CONF + fprintf(stderr,"Parsing env variable \'SVGALIB_CONFIG\'\n"); +#endif + parse_string(buf, commands, func, allowoverride); + } + } +} + +static void map_vgaio(void) +{ + __svgalib_inmisc=__svgalib_vga_inmisc; + __svgalib_outmisc=__svgalib_vga_outmisc; + __svgalib_incrtc=__svgalib_vga_incrtc; + __svgalib_outcrtc=__svgalib_vga_outcrtc; + __svgalib_inseq=__svgalib_vga_inseq; + __svgalib_outseq=__svgalib_vga_outseq; + __svgalib_ingra=__svgalib_vga_ingra; + __svgalib_outgra=__svgalib_vga_outgra; + __svgalib_inatt=__svgalib_vga_inatt; + __svgalib_outatt=__svgalib_vga_outatt; + __svgalib_attscreen=__svgalib_vga_attscreen; + __svgalib_inpal=__svgalib_vga_inpal; + __svgalib_outpal=__svgalib_vga_outpal; + __svgalib_inis1=__svgalib_vga_inis1; +}; + +static void map_vganullio(void) +{ + __svgalib_inmisc=__svgalib_vganull_inmisc; + __svgalib_outmisc=__svgalib_vganull_outmisc; + __svgalib_incrtc=__svgalib_vganull_incrtc; + __svgalib_outcrtc=__svgalib_vganull_outcrtc; + __svgalib_inseq=__svgalib_vganull_inseq; + __svgalib_outseq=__svgalib_vganull_outseq; + __svgalib_ingra=__svgalib_vganull_ingra; + __svgalib_outgra=__svgalib_vganull_outgra; + __svgalib_inatt=__svgalib_vganull_inatt; + __svgalib_outatt=__svgalib_vganull_outatt; + __svgalib_attscreen=__svgalib_vganull_attscreen; + __svgalib_inpal=__svgalib_vganull_inpal; + __svgalib_outpal=__svgalib_vganull_outpal; + __svgalib_inis1=__svgalib_vganull_inis1; +}; +/* Configuration file, mouse interface, initialization. */ + +static int configfileread = 0; /* Boolean. */ + +/* What are these m0 m1 m... things ? Shouldn't they be removed ? */ +static char *vga_conf_commands[] = { +/* 0 */ "mouse", "monitor", "!m", "!M", "chipset", "overrideenable", +/* 6 */ "!m0", "!m1", "!m2", "!m3", "!m4", "!m9", +/* 12 */ "!M0", "!M1", "!M2", "!M3", "!M4", "!M5", "!M6", +/* 19 */ "nolinear", "linear", +/* 21 */ "!C0", "!C1", "!C2", "!C3", "!C4", "!C5", "!C6", "!C7", "!C8", "!C9", +/* 31 */ "!c0", "!c1", "monotext", "colortext", "!m5", +/* 36 */ "leavedtr", "cleardtr", "setdtr", "leaverts", "clearrts", +/* 41 */ "setrts", "grayscale", "horizsync", "vertrefresh", "modeline", +/* 46 */ "security","mdev", "default_mode", "nosigint", "sigint", +/* 51 */ "joystick0", "joystick1", "joystick2", "joystick3", +/* 55 */ "textprog", "vesatext", "vesasave", "secondary", "bandwidth", +/* 60 */ "novccontrol", "newmode", "noprocpci", "vesatextmode", "device", +/* 65 */ "ragedoubleclock", "include", "nullio", "helper", "biosparams", +/* 70 */ "pcistart", "dimensions", "neomagiclibretto100", +/* 73 */ "nohelper", "nohelper_insecure", "fbdev_novga", + NULL}; + +static char *conf_mousenames[] = +{ + "Microsoft", "MouseSystems", "MMSeries", "Logitech", "Busmouse", "PS2", + "MouseMan", "gpm", "Spaceball", "none", "IntelliMouse", "IMPS2", "pnp", + "WacomGraphire", "DRMOUSE4DS", "ExplorerPS2", "unconfigured", NULL}; + +static int check_digit(char *ptr, char *digits) +{ + if (ptr == NULL) + return 0; + return strlen(ptr) == strspn(ptr, digits); +} + +static char *param_needed(int command) +{ + fprintf(stderr, + "svgalib: config: \'%s\' requires parameter(s)", + vga_conf_commands[command]); + return NULL; +} + +static char *check_digit_fail(int command, char *ptr, char *usage) +{ + if (!ptr) + return param_needed(command); + fprintf(stderr, + "svgalib: config: Error \'%s\' parameter: %s, is not a number)\n%s", + vga_conf_commands[command], ptr, usage? usage:""); + + return ptr; /* Allow a second parse of str */ +} + +static char *override_denied(int command, char **nptr) +{ + fprintf(stderr, + "svgalib: config: \'%s\' override from environment or .svgalibrc denied.\n", + vga_conf_commands[command]); + return __svgalib_token(nptr); +} + +static char *process_option(int command, int mode, char **nptr) +{ + static char digits[] = ".0123456789"; + char *ptr, **tabptr, *ptb; + int i, j; + float f; + +#ifdef DEBUG_CONF + fprintf(stderr,"command %d detected.\n", command); +#endif + switch (command) { + case 5: + if (!mode) + return override_denied(command, nptr); +#ifdef DEBUG_CONF + fprintf(stderr,"Allow override\n"); +#endif + allowoverride = 1; + break; + case 0: /* mouse */ + case 2: /* m */ + if (!(ptr = __svgalib_token(nptr))) + return param_needed(command); + + if (check_digit(ptr, digits + 1) && + ((i=atoi(ptr)) >= 0) && + (i<=9)) { + mouse_type = i; + } else { /* parse for symbolic name.. */ + for (i = 0, tabptr = conf_mousenames; *tabptr; tabptr++, i++) { + if (!strcasecmp(ptr, *tabptr)) { + mouse_type = i; +#ifdef DEBUG_DRMOUSE4DS + fprintf(stderr, "mouse type: %d: %s \n", i, conf_mousenames[i]); +#endif + return __svgalib_token(nptr); + } + } + fprintf(stderr,"svgalib: config: Illegal mouse setting: {mouse|m} %s\n" + "Correct usage: {mouse|m} mousetype\n" + "where mousetype is one of 0, 1, 2, 3, 4, 5, 6, 7, 9,\n", + ptr); + for (tabptr = conf_mousenames, i = 0; *tabptr; tabptr++, i++) { + if (i == MOUSE_NONE) + continue; + fprintf(stderr,"%s, ", *tabptr); + } + fprintf(stderr,"or none.\n"); + return ptr; /* Allow a second parse of str */ + } + break; + case 1: /* monitor */ + case 3: /* M */ + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits + 1)) { /* It is an int.. */ + if (!mode) + return override_denied(command, nptr); + i = atoi(ptr); + if (i < 7) { + __svgalib_horizsync.max = __svgalib_maxhsync[i]; + } else { + __svgalib_horizsync.max = i * 1000.0f; + } + } else if (check_digit(ptr, digits)) { /* It is a float.. */ + if (!mode) + return override_denied(command, nptr); + f = atof(ptr); + __svgalib_horizsync.max = f * 1000.0f; + } else { + return check_digit_fail(command, ptr, + "Correct usage: {monitor|M} monitortype\n" + "where monitortype is one of 0, 1, 2, 3, 4, 5, 6, or\n" + "maximal horz. scan frequency in khz.\n" + "Example: monitor 36.5\n"); + } + break; + case 4: /* chipset */ + if (CHIPSET != UNDEFINED) + return NULL; + + if (!(ptr = __svgalib_token(nptr))) + return param_needed(command); + /*First param is chipset */ + for (i = 0, tabptr = driver_names; *tabptr; tabptr++, i++) { + if (!strcasecmp(ptr, *tabptr)) { + if (!__svgalib_driverspecslist[i]) { + fprintf(stderr,"svgalib: config: Warning chipset driver %s is NOT compiled in.\n", + ptr); + return __svgalib_token(nptr); + } + if (__svgalib_driverspecslist[i]->disabled) { + fprintf(stderr,"svgalib: config: Warning chipset driver %s has been disabled.\n", + ptr); + return __svgalib_token(nptr); + } + ptr = __svgalib_token(nptr); + if (!check_digit(ptr, digits + 1)) { + if (!mode) + return override_denied(command, nptr); + configfile_chipset = i; + return ptr; + } + j = atoi(ptr); + ptr = __svgalib_token(nptr); + if (!check_digit(ptr, digits + 1)) + return check_digit_fail(command, ptr, + "Correct usage: chipset driver [par1 par2]\n"); + if (!mode) + return override_denied(command, nptr); + + configfile_chipset = i; + configfile_params = 1; + configfile_par1 = j; + configfile_par2 = atoi(ptr); + return __svgalib_token(nptr); + } + } + fprintf(stderr,"svgalib: config: Illegal chipset setting: chipset %s\n", ptr); + fprintf(stderr,"Correct usage: chipset driver [par1 par2]\n" + "where driver is one of:\n"); + ptb = "%s"; + for (i = 0, tabptr = driver_names; *tabptr; tabptr++, i++) { + if (__svgalib_driverspecslist[i] != NULL) { + fprintf(stderr,ptb, *tabptr); + ptb = ", %s"; + } + } + fprintf(stderr,"\npar1 and par2 are driver dependant integers.\n" + "Example: Chipset VGA or\n" + "Chipset VGA 0 512\n"); + return ptr; /* Allow a second parse of str */ + case 6: /* oldstyle config: m0-m4 */ + case 7: + case 8: + case 9: + case 10: + mouse_type = command - 6; + break; + case 11: /* m9 */ + mouse_type = MOUSE_NONE; + break; + case 12: /* oldstyle config: M0-M6 */ + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + if (!mode) + return override_denied(command, nptr); + __svgalib_horizsync.max = __svgalib_maxhsync[command - 12]; + break; + case 19: /*nolinear */ + modeinfo_mask &= ~CAPABLE_LINEAR; + break; + case 20: /*linear */ + modeinfo_mask |= CAPABLE_LINEAR; + break; + case 21: /* oldstyle chipset C0 - C9 */ + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + if (!mode) + return override_denied(command, nptr); + vga_setchipset(command - 21); + break; + case 31: /* c0-c1 color-text selection */ + if (!mode) + return override_denied(command, nptr); + color_text = 0; + break; + case 32: + if (!mode) + return override_denied(command, nptr); + color_text = 1; + break; + case 33: + case 34: + if (!mode) + return override_denied(command, nptr); + color_text = command - 32; + break; + case 35: /* Mouse type 5 - "PS2". */ + mouse_type = 5; + break; + case 36: + mouse_modem_ctl &= ~(MOUSE_CHG_DTR | MOUSE_DTR_HIGH); + break; + case 37: + mouse_modem_ctl &= ~MOUSE_DTR_HIGH; + mouse_modem_ctl |= MOUSE_CHG_DTR; + break; + case 38: + mouse_modem_ctl |= (MOUSE_CHG_RTS | MOUSE_RTS_HIGH); + break; + case 39: + mouse_modem_ctl &= ~(MOUSE_CHG_RTS | MOUSE_RTS_HIGH); + break; + case 40: + mouse_modem_ctl &= ~MOUSE_RTS_HIGH; + mouse_modem_ctl |= MOUSE_CHG_RTS; + break; + case 41: + mouse_modem_ctl |= (MOUSE_CHG_RTS | MOUSE_RTS_HIGH); + break; + case 42: /* grayscale */ + __svgalib_grayscale = 1; + break; + case 43: /* horizsync */ + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits)) + { + f = atof(ptr); + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits)) + { + __svgalib_horizsync.min = f * 1000; + __svgalib_horizsync.max = atof(ptr) * 1000; + break; + } + } + return check_digit_fail(command, ptr, + "Correct usage: HorizSync min_kHz max_kHz\n" + "Example: HorizSync 31.5 36.5\n"); + case 44: /* vertrefresh */ + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits)) + { + f = atof(ptr); + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits)) + { + __svgalib_vertrefresh.min = f; + __svgalib_vertrefresh.max = atof(ptr); + break; + } + } + return check_digit_fail(command, ptr, + "Correct usage: VertRefresh min_Hz max_Hz\n" + "Example: VertRefresh 50 70\n"); + case 45:{ /* modeline */ + MonitorModeTiming mmt; + const struct { + char *name; + int val; + } options[] = { + { + "-hsync", NHSYNC + }, + { + "+hsync", PHSYNC + }, + { + "-vsync", NVSYNC + }, + { + "+vsync", PVSYNC + }, + { + "interlace", INTERLACED + }, + { + "interlaced", INTERLACED + }, + { + "doublescan", DOUBLESCAN + }, + { + "tvmode", TVMODE + }, + { + "tvpal", TVPAL + }, + { + "tvntsc", TVNTSC + } + }; +#define ML_NR_OPTS (sizeof(options)/sizeof(*options)) + + /* Skip the name of the mode */ + if (!(ptr = __svgalib_token(nptr))) + return param_needed(command); + + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits)) + mmt.pixelClock = atof(ptr) * 1000; + else + return check_digit_fail(command, ptr, NULL); + +#define ML_GETINT(x) \ + ptr = __svgalib_token(nptr); \ + if (check_digit(ptr, digits+1)) \ + x = atoi(ptr); \ + else \ + return check_digit_fail(command, ptr, NULL); + + ML_GETINT(mmt.HDisplay); + ML_GETINT(mmt.HSyncStart); + ML_GETINT(mmt.HSyncEnd); + ML_GETINT(mmt.HTotal); + ML_GETINT(mmt.VDisplay); + ML_GETINT(mmt.VSyncStart); + ML_GETINT(mmt.VSyncEnd); + ML_GETINT(mmt.VTotal); + mmt.flags = 0; + while ((ptr = __svgalib_token(nptr))) { + for (i = 0; i < ML_NR_OPTS; i++) + if (!strcasecmp(ptr, options[i].name)) + { + mmt.flags |= options[i].val; + break; + } + if (i == ML_NR_OPTS) + break; + } +#undef ML_GETINT +#undef ML_NR_OPTS + + __svgalib_addusertiming(&mmt); + return ptr; /* no modeline option so most likely new config command */ + } + case 46: + if ( (ptr = __svgalib_token(nptr)) ) { + if (!strcasecmp("revoke-all-privs", ptr)) { + if (!mode) + return override_denied(command, nptr); + __svgalib_security_revokeallprivs = 1; + break; + } else if (!strcasecmp("compat", ptr)) { + if (!mode) + return override_denied(command, nptr); + __svgalib_security_revokeallprivs = 0; + break; + } + fprintf(stderr, + "svgalib: config: Illegal security setting: Security %s\n", + ptr); + return ptr; /* Allow a second parse of str */ + } + return param_needed(command); + case 47: + ptr = __svgalib_token(nptr); + if (ptr) { + __svgalib_mouse_device = strdup(ptr); + if (__svgalib_mouse_device == NULL) { + fprintf(stderr,"svgalib: Fatal error: out of memory.\n"); + exit(1); + } + } else + return param_needed(command); + break; + case 48: /* default_mode */ + if ( (ptr = __svgalib_token(nptr)) != 0) { + int mode = vga_getmodenumber(ptr); + if (mode != -1) { + __svgalib_default_mode = mode; + } else { + fprintf(stderr,"svgalib: config: illegal mode \'%s\' for \'%s\'\n", + ptr, vga_conf_commands[command]); + return ptr; /* Allow a second parse of str */ + } + } else + return param_needed(command); + break; + case 49: /* nosigint */ + __svgalib_nosigint = 1; + break; + case 50: /* sigint */ + __svgalib_nosigint = 0; + break; + case 51: /* joystick0 */ + case 52: /* joystick1 */ + case 53: /* joystick2 */ + case 54: /* joystick3 */ + if (! (ptr = __svgalib_token(nptr)) ) + return param_needed(command); + + if (__joystick_devicenames[command - 51]) + free(__joystick_devicenames[command - 51]); + __joystick_devicenames[command - 51] = strdup(ptr); + if (!__joystick_devicenames[command - 51]) { + fprintf(stderr,"svgalib: Fatal error: out of memory.\n"); + exit(1); + } + break; + case 55: /* TextProg */ + if (!(ptr = __svgalib_token(nptr))) + return param_needed(command); + + if (!mode && __svgalib_nohelper) { + /* skip textprog args */ + while(((ptr=__svgalib_token(nptr))!=NULL) && strcmp(ptr,"END")) {} + return override_denied(command, nptr); + } + + __svgalib_textprog|=2; + __svgalib_TextProg = strdup(ptr); + if (!__svgalib_TextProg) { + fprintf(stderr,"svgalib: Fatal error: out of memory.\n"); + exit(1); + } + i=1; + while(((ptr=__svgalib_token(nptr))!=NULL) && + (i< ((sizeof(__svgalib_TextProg_argv) / sizeof(char *)) + 1)) && + strcmp(ptr,"END")){ + __svgalib_TextProg_argv[i]=strdup(ptr); + if (!__svgalib_TextProg_argv[i]) { + fprintf(stderr,"svgalib: Fatal error: out of memory.\n"); + exit(1); + } + i++; + }; + __svgalib_TextProg_argv[i]=NULL; + ptb=strrchr(__svgalib_TextProg,'/'); + __svgalib_TextProg_argv[0]=ptb?ptb + 1:__svgalib_TextProg; + break; + case 56: +#ifdef INCLUDE_VESA_DRIVER + __svgalib_vesatext=1; + break; +#else + fprintf(stderr,"svgalib: Warning: VESA support not enabled!\n"); + break; +#endif + case 57: /* Vesa save bitmap */ +#ifdef INCLUDE_VESA_DRIVER + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1)) { + j = atoi(ptr); + __svgalib_VESA_savebitmap=j; + } else + return check_digit_fail(command, ptr, NULL); +#else + fprintf(stderr,"svgalib: Warning: VESA support not enabled!\n"); +#endif + break; + case 58: + __svgalib_secondary=1; + break; + case 59: /* max bandwidth */ + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits+1)) { + int f = atoi(ptr); + if (!mode) + return override_denied(command, nptr); + if (f<31000)f=31000; + __svgalib_bandwidth = f; + } else + return check_digit_fail(command, ptr, + "Correct usage: Bandwidth bandwidth\n" + "Example: Bandwidth 50000\n"); + break; + case 60: + __svgalib_novccontrol=1; + break; + case 61: { + int x,y,c,p,b; + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1)) + x = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1)) + y = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1)) + c = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1)) + p = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1)) + b = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + vga_addmode(x,y,c,p,b); + }; + break; + case 62: + fprintf(stderr,"svgalib: config: Warning: Direct PCI access is not available anymore, so option \"noprocpci\" ignored\n"); + break; + case 63: /* Vesa text mode number */ +#ifdef INCLUDE_VESA_DRIVER + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1)){ + if (!mode) + return override_denied(command, nptr); + j = atoi(ptr); + __svgalib_VESA_textmode=j; + } else return check_digit_fail(command, ptr, NULL); +#else + fprintf(stderr,"svgalib: Warning: VESA support not enabled!\n"); +#endif + break; + case 64: /* device number */ + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits+1) && ((j = atoi(ptr)) >= 0) && (j <= 16)){ + __svgalib_pci_helper_idev=j; + } else return check_digit_fail(command, ptr, NULL); + break; + case 65: + if (!mode) return override_denied(command, nptr); + __svgalib_ragedoubleclock=1; + break; + case 66: { /* include, beware of loops */ + FILE *file; + if (!(ptr = __svgalib_token(nptr))) + return param_needed(command); + if ( (file = fopen(ptr, "r")) != 0) { +#ifdef DEBUG_CONF + fprintf(stderr,"Processing config file \'%s\'\n", ptr); +#endif + process_config_file(file, mode, vga_conf_commands, process_option); + fclose(file); + } else { + fprintf(stderr, "svgalib: config: file \'%s\' not found.\n", ptr); + } + } + break; + case 67: + map_vganullio(); /* drivers may override this */ + break; + case 68: /* helper */ + ptr = __svgalib_token(nptr); + if (ptr) { + helper_device = strdup(ptr); + if (helper_device == NULL) { + fputs("svgalib: Fatal error: out of memory.\n",stderr); + exit(1); + } + } else + return param_needed(command); + break; + case 69: + for (i=0; i<16; i++) { + ptr=__svgalib_token(nptr); + if(!check_digit(ptr,digits+1)) { + if (mode) + biosparams=i; + return ptr; + } + if (mode) + biosparam[i]=atoi(ptr); + } + if (mode) + biosparams=1; + else + return override_denied(command, nptr); + break; + case 70: /* pci initial values */ + ptr = __svgalib_token(nptr); + if(check_digit(ptr, digits+1) && + ((i = atoi(ptr)) < 16) && + (i >= 0)) { + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits+1) && + ((j = atoi(ptr)) < 256) && + (j >= 0)) { + __svgalib_pci_nohelper_idev = i*256 + j; + break; + } + } + check_digit_fail(command, ptr, + "Correct usage: PCIStart initial_bus initial_dev" + "Example: PCIStart 1 0\n"); + break; + case 71: { /* dimemsions */ + int _minx, _miny, _maxx, _maxy; + + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits+1)) + _minx = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits+1)) + _miny = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits+1)) + _maxx = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + ptr = __svgalib_token(nptr); + if (check_digit(ptr, digits+1)) + _maxy = atoi(ptr); + else return check_digit_fail(command, ptr, NULL); + + if (!mode) return override_denied(command, nptr); + + minx = _minx; + miny = _miny; + maxx = _maxx; + maxy = _maxy; + } + break; + case 72: + if (!mode) + return override_denied(command, nptr); + __svgalib_neolibretto100=1; + break; + case 73: + if (!mode) + return override_denied(command, nptr); + __svgalib_nohelper = 1; + break; + case 74: + if (!mode) + return override_denied(command, nptr); + __svgalib_nohelper = 1; + __svgalib_nohelper_secure = 0; + break; + case 75: + __svgalib_fbdev_novga=1; + break; + } + + return __svgalib_token(nptr); +} + +static void readconfigfile(void) +{ + if (configfileread) + return; + + configfileread = 1; + mouse_type = -1; + + map_vgaio(); + + __svgalib_read_options(vga_conf_commands, process_option); + +#ifndef __PPC + if(__svgalib_secondary) +#endif + __svgalib_emulatepage=1; + + /* Can't access /dev/mem after init, so we can't do vga modes with fbdev. + Note we must do this check before calling setchipset! */ + if(__svgalib_nohelper && __svgalib_nohelper_secure) + __svgalib_fbdev_novga = 1; + + if ((CHIPSET == UNDEFINED) && (configfile_chipset != UNDEFINED)) + { + if (configfile_params) + vga_setchipsetandfeatures(configfile_chipset, configfile_par1, + configfile_par2); + else + vga_setchipset(configfile_chipset); + } + if (mouse_type == -1) { + mouse_type = MOUSE_MICROSOFT; /* Default. */ + fprintf(stderr,"svgalib: Assuming Microsoft mouse.\n"); + } + if (__svgalib_horizsync.max == 0U) { + /* Default monitor is low end SVGA/8514. */ + __svgalib_horizsync.min = 31500U; + __svgalib_horizsync.max = 35500U; + fprintf(stderr,"svgalib: Assuming low end SVGA/8514 monitor (35.5 KHz).\n"); + } +#ifdef DEBUG_CONF + fprintf(stderr,"Mouse is: %d Monitor is: H(%5.1f, %5.1f) V(%u,%u)\n", mouse_type, + __svgalib_horizsync.min / 1000.0, __svgalib_horizsync.max / 1000.0, + __svgalib_vertrefresh.min, __svgalib_vertrefresh.max); + fprintf(stderr,"Mouse device is: %s",__svgalib_mouse_device); +#endif + +} + +int vga_getmousetype(void) +{ + readconfigfile(); + return mouse_type | mouse_modem_ctl; +} + +int vga_getmonitortype(void) +{ /* obsolete */ + int i; + readconfigfile(); + for (i = 1; i <= MON1024_72; i++) + if (__svgalib_horizsync.max < __svgalib_maxhsync[i]) + return i - 1; + + return MON1024_72; +} + +void vga_setmousesupport(int s) +{ + DTP((stderr,"setmousesupport %i\n",s)); + mouse_support = s; +} + +void vga_lockvc(void) +{ + lock_count++; + if (flip) + __svgalib_waitvtactive(); +} + +void vga_unlockvc(void) +{ + if (--lock_count <= 0) { + lock_count = 0; + if (release_flag) { + release_flag = 0; + __svgalib_releasevt_signal(SVGALIB_RELEASE_SIG); + } + } +} + +void vga_runinbackground(int stat, ...) +{ + va_list params; + + va_start(params,stat); + + /* getchipset opens, maps and perhaps closes the LFB, + we need an open LFB to be able to runinbackground. + Also we need to know the chipset for getmodeinfo(). */ + __svgalib_getchipset(); + + if(__svgalib_novccontrol)return; + + switch (stat) { + case VGA_GOTOBACK: + __svgalib_go_to_background = va_arg(params, void *); + break; + case VGA_COMEFROMBACK: + __svgalib_come_from_background = va_arg(params, void *); + break; + default: + if ( ( stat && __svgalib_runinbackground) || + (!stat && !__svgalib_runinbackground) ) + break; /* nothing todo */ + if (stat) { + if (__svgalib_readpage != __svgalib_writepage) { + fprintf(stderr, + "svgalib: Warning runinbackground does not support seperate\n" + "read- and writepages, ignoring runinbackground request.\n"); + break; + } + /* If we don't have /dev/mem available we can't do runinbackground + * with the real banked mem, see if we do have an fd for the LFB + * and if it is ok to switch to emulating pages. */ + if (__svgalib_mem_fd == -1) { + int hasmode = 0; + if (__svgalib_linear_mem_fd != -1) + { + if (!__svgalib_emulatepage) + { + /* see if we can do CM with emulatepage */ + __svgalib_emulatepage = 1; + hasmode = vga_hasmode(CM); + if (hasmode) { + __svgalib_setrdpage=NULL; + __svgalib_setwrpage=NULL; + if (CM != TEXT) { + vga_modeinfo *modeinfo = vga_getmodeinfo(CM); + (*__svgalib_setpage)(vga_page_offset); + if ((modeinfo->flags & CAPABLE_LINEAR) && + !(modeinfo->flags & LINEAR_USE)) { + __svgalib_driverspecs->linear(LINEAR_ENABLE, 0); + } + } + map_banked(MAP_FIXED); + } + else + __svgalib_emulatepage = 0; + } + else + hasmode = 1; + } + if (!hasmode) { + fprintf(stderr, + "svgalib: Warning runinbackground not supported " + "in nohelper mode, ignoring\n" + " runinbackground request. Program should check " + "vga_runinbackground_version\n" + " before calling vga_runinbackground\n"); + break; + } + } + } + else /* if (!stat) */ + __svgalib_waitvtactive(); + + __svgalib_runinbackground = stat; + } +} + +/* Program can check, if it is safe to in background. */ +int vga_runinbackground_version(void) +{ + const int runinbackground_version = 3; + int hasmode; + + /* getchipset opens, maps and perhaps closes the LFB, + we need an open LFB to be able to runinbackground. + Also we need to know the chipset for getmodeinfo(). */ + __svgalib_getchipset(); + + if (__svgalib_mem_fd != -1) + return runinbackground_version; + + /* we don't have /dev/mem available so we can't do runinbackground + with the real banked mem, see if we do have an fd for the LFB + and if it is ok to switch to emulating pages. */ + if (__svgalib_linear_mem_fd == -1) + return 0; + + if (__svgalib_emulatepage) + return runinbackground_version; + + /* see if we can do CM with emulatepage */ + __svgalib_emulatepage = 1; + hasmode = vga_hasmode(CM); + __svgalib_emulatepage = 0; + if (hasmode) + return runinbackground_version; + + return 0; +} + +int vga_oktowrite(void) +{ + if(__svgalib_secondary)return 1; + return __svgalib_oktowrite; +} + +void vga_chipset_setregs(unsigned char regs[]) +{ + chipset_setregs(regs, TEXT); /* Why TEXT? Can't think of smthg else*/ +} + +void vga_chipset_saveregs(unsigned char regs[]) +{ + chipset_saveregs(regs); +} + +#ifdef _SVGALIB_LRMI +int vga_set_LRMI_callbacks(LRMI_callbacks * LRMI) { + + if (__svgalib_LRMI_callbacks) + return 0; + + __svgalib_LRMI_callbacks = LRMI; + + return 1; +} +#endif + +int vga_simple_init(void) +{ + + __svgalib_simple = 1; + __svgalib_novccontrol = 1; + __svgalib_driver_report=0; + return vga_init(); + +} + +int vga_initf(int flags) { + if(flags&1) + __svgalib_novccontrol=2; + if(flags&2) + __svgalib_secondary=2; + return vga_init(); +} + +int vga_init(void) +{ + int retval = -1; + + if(initialized) return 0; + + /* + * Make sure we know where our stdout/stderr are going + * (based on code by Kevin Vajk) + */ + if ((fcntl(0,F_GETFD) == -1) && (open("/dev/null", O_RDONLY) == -1)){ + perror("/dev/null"); + goto bail; + } + if ((fcntl(1,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + goto bail; + } + if ((fcntl(2,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + goto bail; + } + retval = 0; + + DTP((stderr,"init\n")); + + /* Make sure the chipset is known. This will also: + -read the config file + -set the default LRMI callbacks + -call open_mem() + -call __svgalib_open_devconsole(); */ + __svgalib_getchipset(); + + if(__svgalib_driver_report) { + fprintf(stderr,"svgalib %s\n", versionstr); + } + +#ifdef SET_TERMIO + if(!__svgalib_novccontrol) { + /* save text mode termio parameters */ + ioctl(0, TCGETS, &__svgalib_text_termio); + + __svgalib_graph_termio = __svgalib_text_termio; + + /* change termio parameters to allow our own I/O processing */ + __svgalib_graph_termio.c_iflag &= ~(BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF); + __svgalib_graph_termio.c_iflag |= (IGNBRK | IGNPAR); + + __svgalib_graph_termio.c_oflag &= ~(ONOCR); + + __svgalib_graph_termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH); + if (__svgalib_nosigint) + __svgalib_graph_termio.c_lflag &= ~ISIG; /* disable interrupt */ + else + __svgalib_graph_termio.c_lflag |= ISIG; /* enable interrupt */ + + __svgalib_graph_termio.c_cc[VMIN] = 1; + __svgalib_graph_termio.c_cc[VTIME] = 0; + __svgalib_graph_termio.c_cc[VSUSP] = 0; /* disable suspend */ + } +#endif + + DPRINTF("svgalib: Opening mouse (type = %x).\n", mouse_type | mouse_modem_ctl); + + if(mouse_type != MOUSE_NONE ) { + __svgalib_mouse_flag=mouse_type | mouse_modem_ctl; + if (mouse_init(__svgalib_mouse_device, mouse_type | mouse_modem_ctl, MOUSE_DEFAULTSAMPLERATE)) + fprintf(stderr,"svgalib: Failed to initialize mouse.\n"); + else + mouse_open = 1; + } + + /* Michael: I assume this is a misunderstanding, when svgalib was developed, + there were no saved uids, thus setting effective uid sufficed... */ +bail: + if ( !__svgalib_security_norevokeprivs ) { + if ( __svgalib_security_revokeallprivs == 1 ) { + setuid(getuid()); + setgid(getgid()); + } + seteuid(getuid()); + setegid(getgid()); + } + + return retval; +} + +void vga_norevokeprivs(void) { + __svgalib_security_norevokeprivs = 1; +} + +int vga_addtiming( int pixelClock, + int HDisplay, + int HSyncStart, + int HSyncEnd, + int HTotal, + int VDisplay, + int VSyncStart, + int VSyncEnd, + int VTotal, + int flags) { + + MonitorModeTiming mmt; + + mmt.pixelClock=pixelClock; + mmt.HDisplay=HDisplay; + mmt.HSyncStart=HSyncStart; + mmt.HSyncEnd=HSyncEnd; + mmt.HTotal=HTotal; + mmt.VDisplay=VDisplay; + mmt.VSyncStart=VSyncStart; + mmt.VSyncEnd=VSyncEnd; + mmt.VTotal=VTotal; + mmt.flags=flags; + + __svgalib_addusertiming(&mmt); + + return 1; + +}; + +int vga_addmode(int xdim, int ydim, int cols, + int xbytes, int bytespp) +{ + int i; + + i=__svgalib_addmode(xdim, ydim, cols, xbytes, bytespp); + + return i; +}; + +int vga_getcrtcregs(unsigned char *regs) { + int i; + + for (i = 0; i < CRT_C; i++) { + regs[i] = __svgalib_incrtc(i); + } + return 0; +} + +int vga_setcrtcregs(unsigned char *regs) { + int i; + + if(!STDVGAMODE(CM)) return -1; + + __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); + for (i = 0; i < CRT_C; i++) { + __svgalib_outcrtc(i,regs[i]); + } + + return 0; +} + +int __svgalib_vgacolor(void) +{ + if (__svgalib_vgacolormode==-1) + __svgalib_vgacolormode=__svgalib_inmisc()& 0x01; + return __svgalib_vgacolormode; +}; + +void vga_dpms(int i) { + int s1, c17; + switch(i) { + case 1: /* standby - not on vga */ + s1=0x20; + c17=0x80; + break; + case 2: /* suspend - not on vga */ + s1=0x20; + c17=0x80; + break; + case 3: /* display off */ + s1=0x20; + c17=0; + break; + default: /* display on */ + s1=0; + c17=0x80; + break; + } + __svgalib_outseq(0,1); + s1|=__svgalib_inseq(1)&~0x20; + __svgalib_outseq(1,s1); + c17|=__svgalib_incrtc(0x17)&~0x80; + usleep(10000); + __svgalib_outcrtc(0x17,c17); + __svgalib_outseq(0,3); +} + +void map_mmio() { + unsigned long offset; + + if(mmio_mapped) return; + +#ifdef __alpha__ + offset = 0x300000000ULL; +#else + offset = 0; +#endif + + if(__svgalib_mmio_size) { + mmio_mapped=1; + MMIO_POINTER=mmap( 0, __svgalib_mmio_size, PROT_READ | PROT_WRITE, + MAP_SHARED, __svgalib_mem_fd, (off_t) __svgalib_mmio_base + offset); +#ifdef __alpha__ + SPARSE_MMIO=mmap(0, __svgalib_mmio_size<<5, PROT_READ | PROT_WRITE, + MAP_SHARED, __svgalib_mem_fd, + (off_t) 0x200000000LL + (__svgalib_mmio_base<<5)); + +#endif + } else { + MMIO_POINTER=NULL; + SPARSE_MMIO=NULL; + } +} + +void map_mem() { + if(mem_mapped) return; + map_banked(0); + map_linear(0); + mem_mapped=1; +} + +void map_banked(int flags) { + if(__svgalib_banked_mem_size==0)__svgalib_banked_mem_size=0x10000; + if (__svgalib_emulatepage) + { + unsigned long offset = __svgalib_linear_mem_base; +#ifdef __alpha__ + if (offset) + offset += 0x300000000ULL; +#endif + if(__svgalib_readpage == -1) + __svgalib_readpage = __svgalib_writepage = 0; + + BANKED_POINTER=mmap(BANKED_POINTER, 65536, PROT_READ|PROT_WRITE, + MAP_SHARED|flags, __svgalib_linear_mem_fd, + offset + (__svgalib_readpage<<16)); + } else { + unsigned long offset; + +#ifdef __alpha__ + offset = 0x300000000ULL; +#else + offset = 0; +#endif + BANKED_POINTER=mmap(BANKED_POINTER, __svgalib_banked_mem_size, + PROT_READ|PROT_WRITE, MAP_SHARED|flags, __svgalib_mem_fd, + (off_t) __svgalib_banked_mem_base + offset); + } +} + +void map_linear(int flags){ + /* If we're called for the inital mmap (flags==0) check there + * is linear memory, otherwise check if we did the initial mmap */ + if((!flags && __svgalib_linear_mem_size) || LINEAR_POINTER) { + unsigned long offset = __svgalib_linear_mem_base; +#ifdef __alpha__ + if (offset) + offset += 0x300000000ULL; +#endif + LINEAR_POINTER=mmap(LINEAR_POINTER, __svgalib_linear_mem_size, + PROT_READ | PROT_WRITE, MAP_SHARED|flags, + __svgalib_linear_mem_fd, offset); + } +} + +void unmap_linear(void) { + munmap(LINEAR_POINTER, __svgalib_linear_mem_size); + __svgalib_linear_mem_size = 0; + LINEAR_POINTER = NULL; +} diff --git a/src/vga.h b/src/vga.h new file mode 100644 index 0000000..c75dd60 --- /dev/null +++ b/src/vga.h @@ -0,0 +1,607 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Extended for svgalib by Harm Hanemaayer and Hartmut Schirmer */ + +#ifndef VGA_H +#define VGA_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SVGALIB_VER 0x010922 + +#define TEXT 0 /* Compatible with VGAlib v1.2 */ +#define G320x200x16 1 +#define G640x200x16 2 +#define G640x350x16 3 +#define G640x480x16 4 +#define G320x200x256 5 +#define G320x240x256 6 +#define G320x400x256 7 +#define G360x480x256 8 +#define G640x480x2 9 + +#define G640x480x256 10 +#define G800x600x256 11 +#define G1024x768x256 12 + +#define G1280x1024x256 13 /* Additional modes. */ + +#define G320x200x32K 14 +#define G320x200x64K 15 +#define G320x200x16M 16 +#define G640x480x32K 17 +#define G640x480x64K 18 +#define G640x480x16M 19 +#define G800x600x32K 20 +#define G800x600x64K 21 +#define G800x600x16M 22 +#define G1024x768x32K 23 +#define G1024x768x64K 24 +#define G1024x768x16M 25 +#define G1280x1024x32K 26 +#define G1280x1024x64K 27 +#define G1280x1024x16M 28 + +#define G800x600x16 29 +#define G1024x768x16 30 +#define G1280x1024x16 31 + +#define G720x348x2 32 /* Hercules emulation mode */ + +#define G320x200x16M32 33 /* 32-bit per pixel modes. */ +#define G640x480x16M32 34 +#define G800x600x16M32 35 +#define G1024x768x16M32 36 +#define G1280x1024x16M32 37 + +/* additional resolutions */ +#define G1152x864x16 38 +#define G1152x864x256 39 +#define G1152x864x32K 40 +#define G1152x864x64K 41 +#define G1152x864x16M 42 +#define G1152x864x16M32 43 + +#define G1600x1200x16 44 +#define G1600x1200x256 45 +#define G1600x1200x32K 46 +#define G1600x1200x64K 47 +#define G1600x1200x16M 48 +#define G1600x1200x16M32 49 + +#define G320x240x256V 50 +#define G320x240x32K 51 +#define G320x240x64K 52 +#define G320x240x16M 53 +#define G320x240x16M32 54 + +#define G400x300x256 55 +#define G400x300x32K 56 +#define G400x300x64K 57 +#define G400x300x16M 58 +#define G400x300x16M32 59 + +#define G512x384x256 60 +#define G512x384x32K 61 +#define G512x384x64K 62 +#define G512x384x16M 63 +#define G512x384x16M32 64 + +#define G960x720x256 65 +#define G960x720x32K 66 +#define G960x720x64K 67 +#define G960x720x16M 68 +#define G960x720x16M32 69 + +#define G1920x1440x256 70 +#define G1920x1440x32K 71 +#define G1920x1440x64K 72 +#define G1920x1440x16M 73 +#define G1920x1440x16M32 74 + +/* The following modes have been introduced by SciTech Display Doctor */ + +#define G320x400x256V 75 +#define G320x400x32K 76 +#define G320x400x64K 77 +#define G320x400x16M 78 +#define G320x400x16M32 79 + +#define G640x400x256 80 +#define G640x400x32K 81 +#define G640x400x64K 82 +#define G640x400x16M 83 +#define G640x400x16M32 84 + +#define G320x480x256 85 +#define G320x480x32K 86 +#define G320x480x64K 87 +#define G320x480x16M 88 +#define G320x480x16M32 89 + +#define G720x540x256 90 +#define G720x540x32K 91 +#define G720x540x64K 92 +#define G720x540x16M 93 +#define G720x540x16M32 94 + +#define G848x480x256 95 +#define G848x480x32K 96 +#define G848x480x64K 97 +#define G848x480x16M 98 +#define G848x480x16M32 99 + +#define G1072x600x256 100 +#define G1072x600x32K 101 +#define G1072x600x64K 102 +#define G1072x600x16M 103 +#define G1072x600x16M32 104 + +#define G1280x720x256 105 +#define G1280x720x32K 106 +#define G1280x720x64K 107 +#define G1280x720x16M 108 +#define G1280x720x16M32 109 + +#define G1360x768x256 110 +#define G1360x768x32K 111 +#define G1360x768x64K 112 +#define G1360x768x16M 113 +#define G1360x768x16M32 114 + +#define G1800x1012x256 115 +#define G1800x1012x32K 116 +#define G1800x1012x64K 117 +#define G1800x1012x16M 118 +#define G1800x1012x16M32 119 + +#define G1920x1080x256 120 +#define G1920x1080x32K 121 +#define G1920x1080x64K 122 +#define G1920x1080x16M 123 +#define G1920x1080x16M32 124 + +#define G2048x1152x256 125 +#define G2048x1152x32K 126 +#define G2048x1152x64K 127 +#define G2048x1152x16M 128 +#define G2048x1152x16M32 129 + +#define G2048x1536x256 130 +#define G2048x1536x32K 131 +#define G2048x1536x64K 132 +#define G2048x1536x16M 133 +#define G2048x1536x16M32 134 + +#define G512x480x256 135 +#define G512x480x32K 136 +#define G512x480x64K 137 +#define G512x480x16M 138 +#define G512x480x16M32 139 + +#define G400x600x256 140 +#define G400x600x32K 141 +#define G400x600x64K 142 +#define G400x600x16M 143 +#define G400x600x16M32 144 + +#define G400x300x256X 145 + +#define G320x200x256V 146 + +#define __GLASTMODE G320x200x256V +#define GLASTMODE vga_lastmodenumber() + +#define IS_IN_STANDARD_VGA_DRIVER(mode) ( \ + ((mode) < G640x480x256) || ((mode) == G720x348x2) || \ + ( ((mode) >= G400x300x256X) && ((mode) <= G400x300x256X) ) ) + + extern int vga_version; + + extern int vga_setmode(int mode); + extern int vga_hasmode(int mode); + extern int vga_setflipchar(int c); + + extern int vga_clear(void); + extern int vga_flip(void); + + extern int vga_getxdim(void); + extern int vga_getydim(void); + extern int vga_getcolors(void); + + extern int vga_setpalette(int index, int red, int green, int blue); + extern int vga_getpalette(int index, int *red, int *green, int *blue); + extern int vga_setpalvec(int start, int num, int *pal); + extern int vga_getpalvec(int start, int num, int *pal); + + extern int vga_screenoff(void); + extern int vga_screenon(void); + + extern int vga_setcolor(int color); + extern int vga_drawpixel(int x, int y); + extern int vga_drawline(int x1, int y1, int x2, int y2); + extern int vga_drawscanline(int line, unsigned char *colors); + extern int vga_drawscansegment(unsigned char *colors, int x, int y, int length); + extern int vga_getpixel(int x, int y); /* Added. */ + extern int vga_getscansegment(unsigned char *colors, int x, int y, int length); + + extern int vga_getch(void); + + extern int vga_dumpregs(void); + + +/* Extensions to VGAlib v1.2: */ + +/* blit flags */ +#define HAVE_BITBLIT 1 +#define HAVE_FILLBLIT 2 +#define HAVE_IMAGEBLIT 4 +#define HAVE_HLINELISTBLIT 8 +#define HAVE_BLITWAIT 16 + +/* other flags */ +#define HAVE_RWPAGE 1 /* vga_setreadpage() / vga_setwritepage() available */ +#define IS_INTERLACED 2 /* mode is interlaced */ +#define IS_MODEX 4 /* ModeX style 256 colors */ +#define IS_DYNAMICMODE 8 /* Dynamic defined mode */ +#define CAPABLE_LINEAR 16 /* Can go to linear addressing mode. */ +#define IS_LINEAR 32 /* Linear addressing has been set by vga_setlinearaddressing. */ +#define EXT_INFO_AVAILABLE 64 /* Returned modeinfo contains valid extended fields */ +#define RGB_MISORDERED 128 /* Mach32 32bpp uses 0BGR instead of BGR0. */ +#define HAVE_EXT_SET 256 /* vga_ext_set() available */ +#define LINEAR_CAN 512 /* Linear mode can be used (even if not set). */ +#define IOCTL_SETDISPLAY 1024 /* The card supports ioctl method for setting display + start at next vertical blank time */ +#define LINEAR_USE (IS_LINEAR|LINEAR_CAN) + +/* Don't use linear in vga modes (even 320x200x256). It does not work with some + * cards. */ +#define CAN_USE_LINEAR ((__svgalib_modeinfo_linearset & LINEAR_USE) && !STDVGAMODE(CM)) + + typedef struct { + int width; + int height; + int bytesperpixel; + int colors; + int linewidth; /* scanline width in bytes */ + int maxlogicalwidth; /* maximum logical scanline width */ + int startaddressrange; /* changeable bits set */ + int maxpixels; /* video memory / bytesperpixel */ + int haveblit; /* mask of blit functions available */ + int flags; /* other flags */ + + /* Extended fields: */ + + int chiptype; /* Chiptype detected */ + int memory; /* videomemory in KB */ + int linewidth_unit; /* Use only a multiple of this as parameter for set_logicalwidth and + set_displaystart */ + char *linear_aperture; /* points to mmap secondary mem aperture of card (NULL if unavailable) */ + int aperture_size; /* size of aperture in KB if size>=videomemory. 0 if unavail */ + void (*set_aperture_page) (int page); + /* if aperture_size= has bits set for mouse/keyboard events detected. + * mouse and raw keyboard events are already handled and their bits removed + * from *in when vga_waitevent returns. + * VGA_KEYEVENT relates to vga_getch NOT vga_getkey. + * return values < 0 signal errors. In this case check errno. + */ + +/* Background running */ +extern void vga_runinbackground(int stat, ...); +#define VGA_GOTOBACK -1 +#define VGA_COMEFROMBACK -2 +extern int vga_runinbackground_version(void); +extern void vga_waitvtactive(void); + +#ifdef _SVGALIB_LRMI +typedef struct { + int (*rm_init)(void); + int (*rm_call)(struct LRMI_regs *r); + int (*rm_int)(int interrupt, struct LRMI_regs *r); + void * (*rm_alloc_real)(int size); + void (*rm_free_real)(void *m); +} LRMI_callbacks; +extern int vga_set_LRMI_callbacks(LRMI_callbacks * LRMI); +#endif + +#ifdef __cplusplus +} + +#endif +#endif /* VGA_H */ diff --git a/src/vga_console.c b/src/vga_console.c new file mode 100644 index 0000000..cf58ecf --- /dev/null +++ b/src/vga_console.c @@ -0,0 +1,212 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "vgapci.h" +#include "vgaio.h" +#include "mouse/vgamouse.h" +#include "keyboard/vgakeyboard.h" + +extern struct termios __svgalib_text_termio; /* text mode termio parameters */ +extern struct termios __svgalib_graph_termio; /* graphics mode termio parameters */ +int __svgalib_vc=-1; +extern int __svgalib_startup_vc; + +void vga_waitvtactive() { + + if(__svgalib_novccontrol)return; + return __svgalib_waitvtactive(); +} + +void __svgalib_set_graphtermio(void) +{ + /* Leave keyboard alone when rawkeyboard is enabled! */ + if (__svgalib_kbd_fd < 0) { + /* set graphics mode termio parameters */ + ioctl(0, TCSETSW, &__svgalib_graph_termio); + } +} + + +void __svgalib_set_texttermio(void) +{ + + DTP((stderr,"set_texttermio\n")); + /* Leave keyboard alone when rawkeyboard is enabled! */ + if (__svgalib_kbd_fd < 0) { + /* restore text mode termio parameters */ + ioctl(0, TCSETSW, &__svgalib_text_termio); + } +} + + +void __svgalib_disable_interrupt(void) +{ + struct termios cur_termio; + + /* Well, one could argue that sigint is not enabled at all when in __svgalib_nosigint + but sometimes they *still* are enabled b4 graph_termio is set.. */ + ioctl(0, TCGETS, &cur_termio); + cur_termio.c_lflag &= ~ISIG; + ioctl(0, TCSETSW, &cur_termio); +} + + +void __svgalib_enable_interrupt(void) +{ + struct termios cur_termio; + + if (__svgalib_nosigint) /* do not reenable, they are often reenabled by text_termio */ + return; + ioctl(0, TCGETS, &cur_termio); + cur_termio.c_lflag |= ISIG; + ioctl(0, TCSETSW, &cur_termio); +} + +/* The following is rather messy and inelegant. The only solution I can */ +/* see is getting a extra free VT for graphics like XFree86 does. */ + +void __svgalib_waitvtactive(void) +{ + if (__svgalib_tty_fd < 0) + return; /* Not yet initialized */ + + while (ioctl(__svgalib_tty_fd, VT_WAITACTIVE, __svgalib_vc) < 0) { + if ((errno != EAGAIN) && (errno != EINTR)) { + perror("ioctl(VT_WAITACTIVE)"); + exit(1); + } +// usleep(150000); + } +} + +static int check_owner(int vc) +{ + struct stat sbuf; + char fname[30]; + +#ifdef ROOT_VC_SHORTCUT + if (!getuid()) + return 1; /* root can do it always */ +#endif + sprintf(fname, "/dev/tty%d", vc); + if ((stat(fname, &sbuf) >= 0) && (getuid() == sbuf.st_uid)) { + return 1; + } + fprintf(stderr,"You must be the owner of the current console to use svgalib.\n"); + return 0; +} + +void __svgalib_open_devconsole(void) +{ + struct vt_mode vtm; + struct vt_stat vts; + struct stat sbuf; + char fname[30]; + + if(__svgalib_novccontrol) { + return; + } + + if (__svgalib_tty_fd >= 0) + return; + + /* The code below assumes file descriptors 0, 1, and 2 + * are already open; make sure that's true. */ + if ((fcntl(0,F_GETFD) == -1) && (open("/dev/null", O_RDONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + if ((fcntl(1,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + if ((fcntl(2,F_GETFD) == -1) && (open("/dev/null", O_WRONLY) == -1)){ + perror("/dev/null"); + exit(1); + } + + /* + * Now, it would be great if we could use /dev/tty and see what it is connected to. + * Alas, we cannot find out reliably what VC /dev/tty is bound to. Thus we parse + * stdin through stderr for a reliable VC + */ + for (__svgalib_tty_fd = 0; __svgalib_tty_fd < 3; __svgalib_tty_fd++) { + if (fstat(__svgalib_tty_fd, &sbuf) < 0) + continue; + if (ioctl(__svgalib_tty_fd, VT_GETMODE, &vtm) < 0) + continue; + if ((sbuf.st_rdev & 0xff00) != 0x400) + continue; + if (!(sbuf.st_rdev & 0xff)) + continue; + __svgalib_vc = sbuf.st_rdev & 0xff; + return; /* perfect */ + } + + if ((__svgalib_tty_fd = open("/dev/console", O_RDWR)) < 0) { + fprintf(stderr,"svgalib: can't open /dev/console \n"); + exit(1); + } + if (ioctl(__svgalib_tty_fd, VT_OPENQRY, &__svgalib_vc) < 0) + goto error; + if (__svgalib_vc <= 0) + goto error; + sprintf(fname, "/dev/tty%d", __svgalib_vc); + close(__svgalib_tty_fd); + /* change our control terminal: */ + setpgid(0,getppid()); + setsid(); + /* We must use RDWR to allow for output... */ + if (((__svgalib_tty_fd = open(fname, O_RDWR)) >= 0) && + (ioctl(__svgalib_tty_fd, VT_GETSTATE, &vts) >= 0)) { + if (!check_owner(vts.v_active)) { + + goto error; + } + /* success, redirect all stdios */ + if (DREP) + fprintf(stderr,"[svgalib: allocated virtual console #%d]\n", __svgalib_vc); + fflush(stdin); + fflush(stdout); + fflush(stderr); + close(0); + close(1); + close(2); + dup(__svgalib_tty_fd); + dup(__svgalib_tty_fd); + dup(__svgalib_tty_fd); + /* clear screen and switch to it */ + fwrite("\e[H\e[J", 6, 1, stderr); + fflush(stderr); + if (__svgalib_vc != vts.v_active) { + __svgalib_startup_vc = vts.v_active; + ioctl(__svgalib_tty_fd, VT_ACTIVATE, __svgalib_vc); + __svgalib_waitvtactive(); + } + } else { +error: + if (__svgalib_tty_fd > 2) + close(__svgalib_tty_fd); + __svgalib_tty_fd = - 1; + fprintf(stderr,"Not running in a graphics capable console,\n" + "and unable to find one.\n"); + } +} + diff --git a/src/vga_console.h b/src/vga_console.h new file mode 100644 index 0000000..509317b --- /dev/null +++ b/src/vga_console.h @@ -0,0 +1,9 @@ + +extern void __svgalib_set_graphtermio(void); +extern void __svgalib_enable_interrupt(void); +extern void __svgalib_disable_interrupt(void); +extern void __svgalib_waitvtactive(void); +extern void __svgalib_open_devconsole(void); +extern void __svgalib_set_texttermio(void); + + diff --git a/src/vga_helper.c b/src/vga_helper.c new file mode 100644 index 0000000..0c2c4b0 --- /dev/null +++ b/src/vga_helper.c @@ -0,0 +1,121 @@ +#include +#include +#include "svgalib_helper.h" +#include "libvga.h" + +void __svgalib_port_rep_outb(unsigned char* string, int length, int port) +{ + if(__svgalib_nohelper) + { + outsb(port, string, length); + } + else + { + io_string_t iostr; + + iostr.port = port; + iostr.string = string; + iostr.length = length; + + ioctl(__svgalib_mem_fd,SVGAHELPER_REPOUTB,&iostr); + } +} + +void __svgalib_port_out(int value, int port) +{ + if(__svgalib_nohelper) + { + outb(value, port); + } + else + { + io_t iov; + + iov.val=value; + iov.port=port; + ioctl(__svgalib_mem_fd,SVGAHELPER_OUTB,&iov); + } +} + +void __svgalib_port_outw(int value, int port) +{ + if(__svgalib_nohelper) + { + outw(value, port); + } + else + { + io_t iov; + + iov.val=value; + iov.port=port; + ioctl(__svgalib_mem_fd,SVGAHELPER_OUTW,&iov); + } +} + +void __svgalib_port_outl(int value, int port) +{ + if(__svgalib_nohelper) + { + outl(value, port); + } + else + { + io_t iov; + + iov.val=value; + iov.port=port; + ioctl(__svgalib_mem_fd,SVGAHELPER_OUTL,&iov); + } +} + +int __svgalib_port_in(int port) +{ + if(__svgalib_nohelper) + { + return inb(port); + } + else + { + io_t iov; + + iov.port=port; + ioctl(__svgalib_mem_fd,SVGAHELPER_INB,&iov); + + return iov.val; + } +} + +int __svgalib_port_inw(int port) +{ + if(__svgalib_nohelper) + { + return inw(port); + } + else + { + io_t iov; + + iov.port=port; + ioctl(__svgalib_mem_fd,SVGAHELPER_INW,&iov); + + return iov.val; + } +} + +int __svgalib_port_inl(int port) +{ + if(__svgalib_nohelper) + { + return inl(port); + } + else + { + io_t iov; + + iov.port=port; + ioctl(__svgalib_mem_fd,SVGAHELPER_INL,&iov); + + return iov.val; + } +} diff --git a/src/vgaaccel.c b/src/vgaaccel.c new file mode 100644 index 0000000..a0b49e7 --- /dev/null +++ b/src/vgaaccel.c @@ -0,0 +1,173 @@ +/* Written by Michael Weller and Harm Hanemaayer. */ + + +#include +#include "vga.h" +#include "driver.h" +#include "timing.h" +#include "accel.h" + + +/* + * This calls one of the acceleration interface functions. + */ + +int vga_accel(unsigned operation,...) +{ + va_list params; + + va_start(params, operation); + /* This is the fast interface which I thought of first: */ + if (__svgalib_driverspecs->accel) { + int retval; + + retval = (*(__svgalib_driverspecs->accel))(operation, params); + va_end(params); + return retval; + } + + /* Do a quick availability check to avoid disasters. */ + if (__svgalib_driverspecs->accelspecs == 0) + return -1; + /* Check for operation availability flag. */ + if (!(__svgalib_driverspecs->accelspecs->operations & (1 << (operation - 1)))) + return -1; + + vga_lockvc(); + + /* + * gcc doesn't produce glorious code here, it's much better with + * only one va_arg traversal in a function. + */ + + switch (operation) { + case ACCEL_FILLBOX: + { + int x, y, w, h; + x = va_arg(params, int); + y = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + (*__svgalib_driverspecs->accelspecs->FillBox) (x, y, w, h); + break; + } + case ACCEL_SCREENCOPY: + { + int x1, y1, x2, y2, w, h; + x1 = va_arg(params, int); + y1 = va_arg(params, int); + x2 = va_arg(params, int); + y2 = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + (*__svgalib_driverspecs->accelspecs->ScreenCopy) (x1, y1, x2, y2, w, h); + break; + } + case ACCEL_PUTIMAGE: + { + int x, y, w, h; + void *p; + x = va_arg(params, int); + y = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + p = va_arg(params, void *); + (*__svgalib_driverspecs->accelspecs->PutImage) (x, y, w, h, p); + break; + } + case ACCEL_DRAWLINE: + { + int x1, x2, y1, y2; + x1 = va_arg(params, int); + y1 = va_arg(params, int); + x2 = va_arg(params, int); + y2 = va_arg(params, int); + (*__svgalib_driverspecs->accelspecs->DrawLine) (x1, y1, x2, y2); + break; + } + case ACCEL_SETFGCOLOR: + { + int c; + c = va_arg(params, int); + (*__svgalib_driverspecs->accelspecs->SetFGColor) (c); + break; + } + case ACCEL_SETBGCOLOR: + { + int c; + c = va_arg(params, int); + (__svgalib_driverspecs->accelspecs->SetBGColor) (c); + break; + } + case ACCEL_SETTRANSPARENCY: + { + int m, c; + m = va_arg(params, int); + c = va_arg(params, int); + (*__svgalib_driverspecs->accelspecs->SetTransparency) (m, c); + break; + } + case ACCEL_SETRASTEROP: + { + int r; + r = va_arg(params, int); + (*__svgalib_driverspecs->accelspecs->SetRasterOp) (r); + break; + } + case ACCEL_PUTBITMAP: + { + int x, y, w, h; + void *p; + x = va_arg(params, int); + y = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + p = va_arg(params, void *); + (*__svgalib_driverspecs->accelspecs->PutBitmap) (x, y, w, h, p); + break; + } + case ACCEL_SCREENCOPYBITMAP: + { + int x1, y1, x2, y2, w, h; + x1 = va_arg(params, int); + y1 = va_arg(params, int); + x2 = va_arg(params, int); + y2 = va_arg(params, int); + w = va_arg(params, int); + h = va_arg(params, int); + (*__svgalib_driverspecs->accelspecs->ScreenCopyBitmap) (x1, y1, x2, y2, w, h); + break; + } + case ACCEL_DRAWHLINELIST: + { + int y, n, *x1, *x2; + y = va_arg(params, int); + n = va_arg(params, int); + x1 = va_arg(params, int *); + x2 = va_arg(params, int *); + (*__svgalib_driverspecs->accelspecs->DrawHLineList) (y, n, x1, x2); + break; + } + case ACCEL_SETMODE: + { + int m; + /* This isn't sent to the chipset-specific driver. */ + m = va_arg(params, int); + if ((__svgalib_accel_mode & BLITS_IN_BACKGROUND) + && !(m & BLITS_IN_BACKGROUND)) + /* Make sure background blits are finished. */ + (*__svgalib_driverspecs->accelspecs->Sync) (); + __svgalib_accel_mode = m; + break; + } + case ACCEL_SYNC: + (*__svgalib_driverspecs->accelspecs->Sync) (); + break; + } /* switch */ + + va_end(params); + + vga_unlockvc(); + + return 0; +} diff --git a/src/vgaclear.c b/src/vgaclear.c new file mode 100644 index 0000000..c48f54c --- /dev/null +++ b/src/vgaclear.c @@ -0,0 +1,69 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "ppcmemset.h" + +int vga_clear(void) +{ + vga_screenoff(); + if (MODEX) + goto modeX; + switch (CM) { + case G320x200x256: + case G320x240x256: + case G320x400x256: + case G360x480x256: + case G400x300x256X: + modeX: + + /* write to all planes */ + __svgalib_outseq(0x02,0x0f); + + /* clear video memory */ + memset(GM, 0, 65536); + break; + + default: + switch (CI.colors) { + case 2: + case 16: + vga_setcolor(0); + + /* write to all bits */ + __svgalib_outseq(0x08,0xff); + + default: + { + int i; + int pages = (CI.ydim * CI.xbytes + 65535) >> 16; + if ( CAN_USE_LINEAR ) { + memset(LINEAR_POINTER, 0, pages<<16); + } else { + for (i = 0; i < pages; ++i) { + vga_setpage(i); + /* clear video memory */ + memset(GM, 0, 65536); + } + } + } + break; + } + break; + } + + vga_setcolor(15); + vga_screenon(); + + return 0; +} diff --git a/src/vgacol.c b/src/vgacol.c new file mode 100644 index 0000000..ceda2d7 --- /dev/null +++ b/src/vgacol.c @@ -0,0 +1,60 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +#include + +#include "vga.h" +#include "libvga.h" + +int vga_setrgbcolor(int r, int g, int b) +{ + switch (CI.colors) { + case 32768: + COL = + (b >> 3) + + ((g >> 3) << 5) + + ((r >> 3) << 10); + break; + case 65536: + COL = + (b >> 3) + + ((g >> 2) << 5) + + ((r >> 3) << 11); + break; + case 1 << 24: + COL = b + (g << 8) + (r << 16); + break; + default: + return 0; + } + return COL; +} + +static const unsigned char ega_red[16] = +{0, 0, 0, 0, 168, 168, 168, 168, 84, 84, 84, 84, 255, 255, 255, 255}; +static const unsigned char ega_green[16] = +{0, 0, 168, 168, 0, 0, 84, 168, 84, 84, 255, 255, 84, 84, 255, 255}; +static const unsigned char ega_blue[16] = +{0, 168, 0, 168, 0, 168, 0, 168, 84, 255, 84, 255, 84, 255, 84, 255}; + +int vga_setegacolor(int c) +{ + if (c < 0) + c = 0; + else if (c > 15) + c = 15; + switch (CI.colors) { + case 1 << 15: + case 1 << 16: + case 1 << 24: + return vga_setrgbcolor(ega_red[c], ega_green[c], ega_blue[c]); + } + vga_setcolor(c); + return c; +} diff --git a/src/vgaconvplanar.c b/src/vgaconvplanar.c new file mode 100644 index 0000000..56e3bb0 --- /dev/null +++ b/src/vgaconvplanar.c @@ -0,0 +1,199 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* These svgalib additions by Harm Hanemaayer. */ + +#include +#include "vga.h" +#include "libvga.h" + +#if defined(NO_ASSEMBLY) +#undef USE_ASM +#else +#define USE_ASM +#endif + +/* This function copies a linear virtual screen in system memory to a */ +/* planar (Mode X-like) 256 color mode. */ + +/* Note that voffset is the video address of the top of the area to be */ +/* copied, that is, you can only use every fourth pixel as a destination. */ +/* Similarly, vpitch is the logical video address width of the screen. */ +/* Also, the width must be a multiple of 4. */ + +void vga_copytoplanar256(unsigned char *virtual, int pitch, int voffset, + int vpitch, int w, int h) +{ + unsigned char *virtualp; +#ifdef USE_ASM + unsigned char *voffsetp; + int dummy; +#else + int voff; +#endif + int plane, x = 0, y; + + for (plane = 0; plane < 4; plane++) { + /* Copy pixels that belong in plane. */ + port_out_r(SEQ_I, 0x02); + port_out_r(SEQ_D, 1 << plane); + virtualp = virtual; +#ifdef USE_ASM + voffsetp = GM + voffset; +#else + voff = voffset; +#endif + for (y = 0; y < h; y++) { + /* Unrolled loop. */ +#ifdef USE_ASM + __asm__ __volatile__( + "xorl %0,%0\n\t" + "jmp 2f\n\t" + ".align 2,0x90\n\t" + + "1:\n\t" + "movb (%4,%0,4),%%al\n\t" /* pixel 0 */ + "movb 4(%4,%0,4),%%ah\n\t" /* pixel 1 */ + "movw %%ax,(%3,%0)\n\t" /* write */ + "movb 8(%4,%0,4),%%al\n\t" /* pixel 2 */ + "movb 12(%4,%0,4),%%ah\n\t" /* pixel 3 */ + "movw %%ax,2(%3,%0)\n\t" + "movb 16(%4,%0,4),%%al\n\t" /* pixel 4 */ + "movb 20(%4,%0,4),%%ah\n\t" /* pixel 5 */ + "movw %%ax,4(%3,%0)\n\t" + "movb 24(%4,%0,4),%%al\n\t" /* pixel 6 */ + "movb 28(%4,%0,4),%%ah\n\t" /* pixel 7 */ + "movw %%ax,6(%3,%0)\n\t" + "addl $8,%0\n\t" + + "2:\n\t" + "leal 32(,%0,4),%%eax\n\t" /* x * 4 + 32 */ + "cmpl %5,%%eax\n\t" /* < w? */ + "jl 1b\n\t" + + /* Do remaining pixels. */ + "jmp 3f\n\t" + ".align 2,0x90\n\t" + + "4:\n\t" + "movb (%4,%0,4),%%al\n\t" + "movb %%al,(%3,%0)\n\t" + "incl %0\n\t" + "3:\n\t" + "leal (,%0,4),%%eax\n\t" /* x * 4 */ + "cmpl %5,%%eax\n\t" /* < w? */ + "jl 4b\n\t" + + : /* output */ + "=r"(x), "=a"(dummy) + : /* input */ + "0"(x), + "r"(voffsetp), + "r"(virtualp + plane), + "rm"(w), "1"(0) + /*:*/ /* modified */ + /***rjr*** "ax", "0" ***/ + ); +#else + x = 0; + while (x * 4 + 32 < w) { + gr_writeb(virtualp[x * 4 + plane + 0], + voff + x + 0); + gr_writeb(virtualp[x * 4 + plane + 4], + voff + x + 1); + gr_writeb(virtualp[x * 4 + plane + 8], + voff + x + 2); + gr_writeb(virtualp[x * 4 + plane + 12], + voff + x + 3); + gr_writeb(virtualp[x * 4 + plane + 16], + voff + x + 4); + gr_writeb(virtualp[x * 4 + plane + 20], + voff + x + 5); + gr_writeb(virtualp[x * 4 + plane + 24], + voff + x + 6); + gr_writeb(virtualp[x * 4 + plane + 28], + voff + x + 7); + x += 8; + } + while (x * 4 < w) { + gr_writeb(virtualp[x * 4 + plane], voff + x); + x++; + } +#endif + virtualp += pitch; /* Next line. */ +#ifdef USE_ASM + voffsetp += vpitch; +#else + voff += vpitch; +#endif + } + } +} + + +/* This is the equivalent function for planar 16 color modes; pixels are */ +/* assumed to be stored in individual bytes ranging from 0 to 15 in the */ +/* virtual screen. It's very slow compared to the Mode X one. */ + +/* Here width must be a multiple of 8; video addresses are in units of 8 */ +/* pixels. */ + +void vga_copytoplanar16(unsigned char *virtual, int pitch, int voffset, + int vpitch, int w, int h) +{ + vga_copytoplane(virtual, pitch, voffset, vpitch, w, h, 0); + vga_copytoplane(virtual, pitch, voffset, vpitch, w, h, 1); + vga_copytoplane(virtual, pitch, voffset, vpitch, w, h, 2); + vga_copytoplane(virtual, pitch, voffset, vpitch, w, h, 3); +} + + +void vga_copytoplane(unsigned char *virtual, int pitch, int voffset, + int vpitch, int w, int h, int plane) +{ + int x, y; + unsigned char planemask; + unsigned char *virtualp; + + port_out_r(GRA_I, 0x01); /* Disable set/reset. */ + port_out_r(GRA_D, 0x00); + + port_out_r(GRA_I, 0x08); /* Write to all bits. */ + port_out_r(GRA_D, 0xff); + + /* Copy pixels that belong in plane. */ + planemask = 1 << plane; + virtualp = virtual; + port_out_r(SEQ_I, 0x02); + port_out_r(SEQ_D, planemask); + for (y = 0; y < h; y++) { + x = 0; + while (x * 8 < w) { + unsigned char val; + val = 0; + if (virtualp[x * 8] & planemask) + val += 0x80; + if (virtualp[x * 8 + 1] & planemask) + val += 0x40; + if (virtualp[x * 8 + 2] & planemask) + val += 0x20; + if (virtualp[x * 8 + 3] & planemask) + val += 0x10; + if (virtualp[x * 8 + 4] & planemask) + val += 0x08; + if (virtualp[x * 8 + 5] & planemask) + val += 0x04; + if (virtualp[x * 8 + 6] & planemask) + val += 0x02; + if (virtualp[x * 8 + 7] & planemask) + val += 0x01; + gr_writeb(val, voffset + x); + x++; + } + virtualp += pitch; /* Next line. */ + voffset += vpitch; + } +} diff --git a/src/vgacursor.c b/src/vgacursor.c new file mode 100644 index 0000000..0588cd1 --- /dev/null +++ b/src/vgacursor.c @@ -0,0 +1,261 @@ +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +static unsigned char *cursors[16]; +static int formats[16]; + +static struct { + unsigned char c8; + unsigned short c15; + unsigned short c16; + unsigned int c32; +} cursor_colors[16*2]; + +static unsigned char *buf, *dbuf; +static int cur_x, cur_y; +static int cursor; +static int cur_show; +int __svgalib_software_cursor, __svgalib_cursor_status=-1; +static int palette[768]; +static int pal=1; + +static int sx, sy, sp; + +static int findcolor(int rgb) { + int i,j,k,l=0; + + if(pal)vga_getpalvec(0,256,palette); + pal=0; + k=0xffffff; + for(i=0;i<256;i++) { + j=((rgb&0xff)-(palette[i*3+2]<<2))*((rgb&0xff)-(palette[i*3+2]<<2))+ + (((rgb>>8)&0xff)-(palette[i*3+1]<<2))*(((rgb>>8)&0xff)-(palette[i*3+1]<<2))+ + (((rgb>>16)&0xff)-(palette[i*3]<<2))*(((rgb>>16)&0xff)-(palette[i*3]<<2)); + if(j==0) { + return i; + } + if(j 0; y++, p += w) + vga_drawscansegment(p, cur_x, y, cw); +} + +static void get_cursor(unsigned char *p) +{ + int y; + int w = CI.bytesperpixel * 32; + int cw = (cur_x + 32 < CI.xdim ? 32 : CI.xdim - cur_x) * CI.bytesperpixel; + int ch = cur_y + 32 < CI.ydim ? 32 : CI.ydim - cur_y; + + for (y = cur_y; ch-- > 0; y++, p += w) + vga_getscansegment(p, cur_x, y, cw); +} + +static int software_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { + int i, j; + unsigned short *ps, c0, c1; + unsigned int *pi, *pattern; + + switch(cmd) { + case CURSOR_INIT: + buf=(unsigned char *)malloc(32*32*4); + dbuf=(unsigned char *)malloc(32*32*4); + cursor=0; + return 0; + break; + case CURSOR_HIDE: + if(cur_show==1) { + draw_cursor(buf); + cur_show=0; + } + break; + case CURSOR_SHOW: + if(cur_show==0) { + pattern=(unsigned int *)cursors[cursor]; + get_cursor(buf); + memcpy(dbuf,buf,CI.bytesperpixel*32*32); + switch(CI.bytesperpixel) { + case 1: + for(i=0;i<32;i++) { + unsigned int l1,l2; + l1=*(pattern+i); + l2=*(pattern+i+32); + for(j=0;j<32;j++) { + if(l2&0x80000000) { + *(dbuf+i*32+j)=l1&0x80000000 ? + cursor_colors[cursor*2+1].c8 : cursor_colors[cursor*2].c8; + } + l1<<=1; + l2<<=1; + } + } + draw_cursor(dbuf); + break; + case 2: + ps=(unsigned short *)dbuf; + if(CI.colors==32768) { + c0=cursor_colors[cursor*2].c15; + c1=cursor_colors[cursor*2+1].c15; + } else { + c0=cursor_colors[cursor*2].c16; + c1=cursor_colors[cursor*2+1].c16; + } + for(i=0;i<32;i++) { + unsigned int l1,l2; + l1=*(pattern+i); + l2=*(pattern+i+32); + for(j=0;j<32;j++) { + if(l2&0x80000000) { + *(ps+i*32+j)=l1&0x80000000 ? c1 : c0; + } + l1<<=1; + l2<<=1; + } + } + draw_cursor(dbuf); + break; + case 3: + for(i=0;i<32;i++) { + unsigned int l1,l2; + l1=*(pattern+i); + l2=*(pattern+i+32); + for(j=0;j<32;j++) { + if(l2&0x80000000) { + *(dbuf+i*96+3*j)=l1&0x80000000 ? + cursor_colors[cursor*2+1].c32&0xff : cursor_colors[cursor*2].c32&0xff; + *(dbuf+i*96+3*j+1)=l1&0x80000000 ? + (cursor_colors[cursor*2+1].c32>>8)&0xff : (cursor_colors[cursor*2].c32>>8)&0xff; + *(dbuf+i*96+3*j+2)=l1&0x80000000 ? + (cursor_colors[cursor*2+1].c32>>16)&0xff:(cursor_colors[cursor*2].c32>>16)&0xff; + } + l1<<=1; + l2<<=1; + } + } + draw_cursor(dbuf); + break; + case 4: + pi=(unsigned int *)dbuf; + for(i=0;i<32;i++) { + unsigned int l1,l2; + l1=*(pattern+i); + l2=*(pattern+i+32); + for(j=0;j<32;j++) { + if(l2&0x80000000) { + *(pi+i*32+j)=l1&0x80000000 ? + cursor_colors[cursor*2+1].c32 : cursor_colors[cursor*2].c32; + } + l1<<=1; + l2<<=1; + } + } + draw_cursor(dbuf); + break; + } + cur_show=1; + } + break; + case CURSOR_POSITION: + if(cur_show) { + software_cursor(CURSOR_HIDE,0,0,0,0,NULL); + cur_x=p1; + cur_y=p2; + software_cursor(CURSOR_SHOW,0,0,0,0,NULL); + } else { + cur_x=p1; + cur_y=p2; + } + break; + case CURSOR_SELECT: + cursor=p1; + break; + case CURSOR_IMAGE: + switch(p2){ + case 0: + if(cursors[p1]!=NULL) { + free(cursors[p1]); + } + cursors[p1]=malloc(256); + memcpy(cursors[p1],p5,256); + cursor_colors[p1*2].c8=findcolor(p3); + cursor_colors[p1*2].c32=p3; + cursor_colors[p1*2].c16=((p3&0xf80000)>>8)|((p3&0xfc00)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2].c15=((p3&0xf80000)>>9)|((p3&0xf800)>>5)|((p3&0xf8)>>3); + cursor_colors[p1*2+1].c8=findcolor(p4); + cursor_colors[p1*2+1].c32=p4; + cursor_colors[p1*2+1].c16=((p4&0xf80000)>>8)|((p4&0xfc00)>>5)|((p4&0xf8)>>3); + cursor_colors[p1*2+1].c15=((p4&0xf80000)>>9)|((p4&0xf800)>>5)|((p4&0xf8)>>3); + break; + } + } + return 0; +} + +void vga_showcursor(int show) { + if(chipset_cursor==software_cursor) { + show&=1; + } + if(show==1) chipset_cursor(CURSOR_SHOW,0,0,0,0,NULL); + else if(show==0) chipset_cursor(CURSOR_HIDE,0,0,0,0,NULL); + __svgalib_cursor_status=show; +} + +void vga_setcursorposition(int x, int y) { + sx=x; + sy=y; + chipset_cursor(CURSOR_POSITION,x,y,0,0,NULL); +} + +void vga_setcursorimage(int cur, int format, int c0, int c1, unsigned char *buf) { + if(chipset_cursor!=software_cursor) { + /* save cursor for restoring on VT switch */ + software_cursor(CURSOR_IMAGE,cur,format,c0,c1,buf); + formats[cur]=format; + } + chipset_cursor(CURSOR_IMAGE,cur,format,c0,c1,buf); +} + +void vga_selectcursor(int cur) { + sp=cur; + chipset_cursor(CURSOR_SELECT,cur,0,0,0,NULL); +} + +int vga_initcursor(int sw) { + int i; + cur_show=0; + for (i=0;i<16;i++)cursors[i]=NULL; + __svgalib_cursor_status=0; + + if(sw || (chipset_cursor==NULL)) chipset_cursor=software_cursor; + i=chipset_cursor(CURSOR_INIT,0,0,0,0,NULL); + if(!i) chipset_cursor=software_cursor; + return chipset_cursor!=software_cursor; +} + +void __svgalib_cursor_restore() { + int i; + + vga_selectcursor(sp); + vga_setcursorposition(sx, sy); + for (i=0;i<16;i++)if(cursors[i]!=NULL) { + chipset_cursor(CURSOR_IMAGE,i,formats[i],cursor_colors[i*2].c32,cursor_colors[i*2+1].c32,cursors[i]); + } + vga_showcursor(__svgalib_cursor_status&1); +} + diff --git a/src/vgadraw.c b/src/vgadraw.c new file mode 100644 index 0000000..66ac799 --- /dev/null +++ b/src/vgadraw.c @@ -0,0 +1,569 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* 21 January 1995 - added vga_readscanline(), added support for */ +/* non 8-pixel aligned scanlines in 16 color mode. billr@rastergr.com */ +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +/* used to decompose color value into bits (for fast scanline drawing) */ +union bits { + struct { + unsigned char bit3; + unsigned char bit2; + unsigned char bit1; + unsigned char bit0; + } b; + unsigned int i; +}; + +/* color decompositions */ +static union bits color16[16] = +{ + {{0, 0, 0, 0}}, + {{0, 0, 0, 1}}, + {{0, 0, 1, 0}}, + {{0, 0, 1, 1}}, + {{0, 1, 0, 0}}, + {{0, 1, 0, 1}}, + {{0, 1, 1, 0}}, + {{0, 1, 1, 1}}, + {{1, 0, 0, 0}}, + {{1, 0, 0, 1}}, + {{1, 0, 1, 0}}, + {{1, 0, 1, 1}}, + {{1, 1, 0, 0}}, + {{1, 1, 0, 1}}, + {{1, 1, 1, 0}}, + {{1, 1, 1, 1}} +}; + +/* mask for end points in plane buffer mode */ +static unsigned char mask[8] = +{ + 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 +}; + +/* display plane buffers (for fast scanline drawing) */ +/* 256 bytes -> max 2048 pixel per line (2/16 colors) */ +static unsigned char plane0[256]; +static unsigned char plane1[256]; +static unsigned char plane2[256]; +static unsigned char plane3[256]; + +static inline void shifted_memcpy(void *dest_in, void *source_in, int len) +{ + int *dest = dest_in; + int *source = source_in; + + len >>= 2; + + while (len--) + *dest++ = (*source++ << 8); +} + +/* RGB_swapped_memcopy returns the amount of bytes unhandled */ +static inline int RGB_swapped_memcpy(uint8_t *dest, uint8_t *source, int len) +{ + int rest, tmp; + + tmp = len / 3; + rest = len - 3 * tmp; + len = tmp; + + while (len--) { + *dest++ = source[2]; + *dest++ = source[1]; + *dest++ = source[0]; + source += 3; + } + + return rest; +} + +int vga_drawscanline(int line, unsigned char *colors) +{ + if ((CI.colors == 2) || (CI.colors > 256)) + return vga_drawscansegment(colors, 0, line, CI.xbytes); + else + return vga_drawscansegment(colors, 0, line, CI.xdim); +} + +#ifdef LIBC_MEMCPY +#define MEMCPY memcpy +#else +void MEMCPY(unsigned char *dst, unsigned char *src, size_t n) { + unsigned char *e; + e=src+n; + while(src length) + last = length; + for (j = first; j < last; j++, i++) + bytes.i = (bytes.i << 1) | color16[colors[j]&15].i; + plane0[k] = bytes.b.bit0; + plane1[k] = bytes.b.bit1; + plane2[k] = bytes.b.bit2; + plane3[k++] = bytes.b.bit3; + ioffs = 0; + } + if (eoffs) { + /* fixup last byte */ + k--; + bytes.i <<= (8 - eoffs); + plane0[k] = bytes.b.bit0; + plane1[k] = bytes.b.bit1; + plane2[k] = bytes.b.bit2; + plane3[k++] = bytes.b.bit3; + } + offset = (y * CI.xdim + x) / 8; + vga_setpage((page = offset >> 16)); + l1 = 0x10000 - (offset &= 0xffff); + /* k currently contains number of bytes to write */ + if (l1 > k) + l1 = k; + l2 = k - l1; + /* make k the index of the last byte to write */ + k--; + + address = GM + offset; + + /* disable Set/Reset Register */ + __svgalib_outgra(0x01,0x00); + + /* write to all bits */ + __svgalib_outgra(0x08,0xff); + + /* select write map mask register */ + __svgalib_outseq(0x02,0x01); + + /* select read map mask register */ + __svgalib_outgra(0x04,0x00); + if (soffs) + plane0[0] |= *address & ~mask[soffs]; + if (eoffs && l2 == 0) + plane0[k] |= *(address + l1 - 1) & mask[eoffs]; + MEMCPY(address, plane0, l1); + + /* write plane 1 */ + __svgalib_outseq(0x02,0x02); + /* read plane 1 */ + __svgalib_outgra(0x04,0x01); + if (soffs) + plane1[0] |= *address & ~mask[soffs]; + if (eoffs && l2 == 0) + plane1[k] |= *(address + l1 - 1) & mask[eoffs]; + MEMCPY(address, plane1, l1); + + /* write plane 2 */ + __svgalib_outseq(0x02,0x04); + /* read plane 2 */ + __svgalib_outgra(0x04,0x02); + if (soffs) + plane2[0] |= *address & ~mask[soffs]; + if (eoffs && l2 == 0) + plane2[k] |= *(address + l1 - 1) & mask[eoffs]; + MEMCPY(address, plane2, l1); + + /* write plane 3 */ + __svgalib_outseq(0x02,0x08); + /* read plane 3 */ + __svgalib_outgra(0x04,0x03); + if (soffs) + plane3[0] |= *address & ~mask[soffs]; + if (eoffs && l2 == 0) + plane3[k] |= *(address + l1 - 1) & mask[eoffs]; + MEMCPY(address, plane3, l1); + + if (l2 > 0) { + vga_setpage(page + 1); + + /* write plane 0 */ + __svgalib_outseq(0x02,0x01); + if (eoffs) { + /* read plane 0 */ + __svgalib_outgra(0x04,0x00); + plane0[k] |= *(GM + l2 - 1) & mask[eoffs]; + } + MEMCPY(GM, &plane0[l1], l2); + + /* write plane 1 */ + __svgalib_outseq(0x02,0x02); + if (eoffs) { + /* read plane 1 */ + __svgalib_outgra(0x04,0x01); + plane1[k] |= *(GM + l2 - 1) & mask[eoffs]; + } + MEMCPY(GM, &plane1[l1], l2); + + /* write plane 2 */ + __svgalib_outseq(0x02,0x04); + if (eoffs) { + /* read plane 2 */ + __svgalib_outgra(0x04,0x02); + plane2[k] |= *(GM + l2 - 1) & mask[eoffs]; + } + MEMCPY(GM, &plane2[l1], l2); + + /* write plane 3 */ + __svgalib_outseq(0x02,0x08); + if (eoffs) { + /* read plane 3 */ + __svgalib_outgra(0x04,0x03); + plane3[k] |= *(GM + l2 - 1) & mask[eoffs]; + } + MEMCPY(GM, &plane3[l1], l2); + } + /* restore map mask register */ + __svgalib_outseq(0x02,0x0f); + + /* enable Set/Reset Register */ + __svgalib_outgra(0x01,0x0f); + } + break; + case 2: { + /* disable Set/Reset Register */ + __svgalib_outgra(0x01,0x00); + + /* write to all bits */ + __svgalib_outgra(0x08,0xff); + + /* write to all planes */ + __svgalib_outseq(0x02,0x0f); + + MEMCPY(GM + (y * CI.xdim + x) / 8, colors, length); + + /* restore map mask register */ + __svgalib_outseq(0x02,0x0f); + + /* enable Set/Reset Register */ + __svgalib_outgra(0x01,0x0f); + } + break; + case 256: { + switch (CM) { + case G320x200x256: /* linear addressing - easy and fast */ + MEMCPY(GM + (y * CI.xdim + x), colors, length); + return 0; + case G320x240x256: + case G320x400x256: + case G360x480x256: + case G400x300x256X: +modeX: + { + int first, offset, pixel, plane; + + for (plane = 0; plane < 4; plane++) { + /* select plane */ + __svgalib_outseq(0x02,1 << plane ); + + pixel = ((4 - (x & 3) + plane) & 3); + first = (y * CI.xdim + x) / 4; + if((x & 3) + pixel > 3) + first++; + for (offset = first; pixel < length; offset++) { + *(GM+offset) = colors[pixel]; + pixel += 4; + } + } + } + return 0; + } + { + unsigned int offset; + int segment, free; + +SegmentedCopy: + offset = y * CI.xbytes + x; + if ( CAN_USE_LINEAR ) { + MEMCPY(LINEAR_POINTER+offset, colors, length); + } else { + segment = offset >> 16; + free = ((segment + 1) << 16) - offset; + offset &= 0xFFFF; + + if (free < length) { + vga_setpage(segment); + MEMCPY(GM + offset, colors, free); + vga_setpage(segment + 1); + MEMCPY(GM, colors + free, length - free); + } else { + vga_setpage(segment); + MEMCPY(GM + offset, colors, length); + } + } + } + } + break; + case 32768: + case 65536: + x *= 2; + goto SegmentedCopy; + case 1 << 24: + if (__svgalib_cur_info.bytesperpixel == 4) { + x <<= 2; + if (MODEFLAGS & RGB_MISORDERED) { + unsigned int offset; + int segment, free; + + offset = y * CI.xbytes + x; + if ( CAN_USE_LINEAR ) { + shifted_memcpy(LINEAR_POINTER+offset, colors, length); + } else { + segment = offset >> 16; + free = ((segment + 1) << 16) - offset; + offset &= 0xFFFF; + + if (free < length) { + vga_setpage(segment); + shifted_memcpy(GM + offset, colors, free); + vga_setpage(segment + 1); + shifted_memcpy(GM, colors + free, length - free); + } else { + vga_setpage(segment); + shifted_memcpy(GM + offset, colors, length); + } + } + } else { + goto SegmentedCopy; + } + break; + } + x *= 3; + if (MODEFLAGS & RGB_MISORDERED) { + unsigned int offset; + int segment, free; + + offset = y * CI.xbytes + x; + if ( CAN_USE_LINEAR ) { + RGB_swapped_memcpy(LINEAR_POINTER+offset, colors, length); + } else { + segment = offset >> 16; + free = ((segment + 1) << 16) - offset; + offset &= 0xFFFF; + + if (free < length) { + int i; + + vga_setpage(segment); + i = RGB_swapped_memcpy(GM + offset, colors, free); + colors += (free - i); + + switch (i) { + case 2: + *(GM+0xfffe) = colors[2]; + *(GM+0xffff) = colors[1]; + break; + case 1: + *(GM+0xffff) = colors[2]; + break; + } + + vga_setpage(segment + 1); + + switch (i) { + case 1: + *(GM+1) = colors[0]; + *(GM) = colors[1]; + i = 3 - i; + free += i; + colors += 3; + break; + case 2: + *(GM) = colors[0]; + i = 3 - i; + free += i; + colors += 3; + break; + } + RGB_swapped_memcpy(GM + i, colors, length - free); + } else { + vga_setpage(segment); + RGB_swapped_memcpy(GM + offset, colors, length); + } + } + } else { + goto SegmentedCopy; + } + } + return 0; +} + +int vga_getscansegment(unsigned char *colors, int x, int y, int length) +{ + + if (MODEX) + goto modeX2; + switch (CI.colors) { + case 16: { + int i, k, page, l1, l2; + int offset, eoffs, soffs, nbytes, bit; + unsigned char *address; + unsigned char color; + + k = 0; + soffs = (x & 0x7); /* starting offset into first byte */ + eoffs = (x + length) & 0x7; /* ending offset into last byte */ + offset = (y * CI.xdim + x) / 8; + vga_setpage((page = offset >> 16)); + l1 = 0x10000 - (offset &= 0xffff); + if (soffs) + nbytes = (length - (8 - soffs)) / 8 + 1; + else + nbytes = length / 8; + if (eoffs) + nbytes++; + if (l1 > nbytes) + l1 = nbytes; + l2 = nbytes - l1; + address = GM + offset; + /* disable Set/Reset Register */ + __svgalib_outgra(0x01,0x00); + /* read plane 0 */ + __svgalib_outgra(0x04,0x00); + memcpy(plane0, address, l1); + /* read plane 1 */ + __svgalib_outgra(0x04,0x01); + memcpy(plane1, address, l1); + /* read plane 2 */ + __svgalib_outgra(0x04,0x02); + memcpy(plane2, address, l1); + /* read plane 3 */ + __svgalib_outgra(0x04,0x03); + memcpy(plane3, address, l1); + if (l2 > 0) { + vga_setpage(page + 1); + /* read plane 0 */ + __svgalib_outgra(0x04,0x00); + memcpy(&plane0[l1], GM, l2); + /* read plane 1 */ + __svgalib_outgra(0x04,0x01); + memcpy(&plane1[l1], GM, l2); + /* read plane 2 */ + __svgalib_outgra(0x04,0x02); + memcpy(&plane2[l1], GM, l2); + /* read plane 3 */ + __svgalib_outgra(0x04,0x03); + memcpy(&plane3[l1], GM, l2); + } + /* enable Set/Reset Register */ + __svgalib_outgra(0x01,0x0f); + k = 0; + for (i = 0; i < length;) { + for (bit = 7 - soffs; bit >= 0 && i < length; bit--, i++) { + color = (plane0[k] & (1 << bit) ? 1 : 0); + color |= (plane1[k] & (1 << bit) ? 1 : 0) << 1; + color |= (plane2[k] & (1 << bit) ? 1 : 0) << 2; + color |= (plane3[k] & (1 << bit) ? 1 : 0) << 3; + colors[i] = color; + } + k++; + soffs = 0; + } + } + break; + case 2: + /* disable Set/Reset Register */ + __svgalib_outgra(0x01,0x00); + /* read from plane 0 */ + __svgalib_outseq(0x04,0x00); + memcpy(colors, GM + (y * CI.xdim + x) / 8, length); + /* enable Set/Reset Register */ + __svgalib_outgra(0x01,0x0f); + break; + case 256: + switch (CM) { + case G320x200x256: /* linear addressing - easy and fast */ + memcpy(colors, GM + y * CI.xdim + x, length); + return 0; + case G320x240x256: + case G320x400x256: + case G360x480x256: + case G400x300x256X: +modeX2: + { + int first, offset, pixel, plane; + for (plane = 0; plane < 4; plane++) { + /* select plane */ + __svgalib_outgra(0x04, plane); + pixel = ((4 - (x & 3) + plane) & 3); + first = (y * CI.xdim + x) / 4; + if((x & 3) + pixel > 3) + first++; + for (offset = first; pixel < length; offset++) { + colors[pixel] = gr_readb(offset); + pixel += 4; + } + } + } + return 0; + } + { + unsigned int offset; + int segment, free; +SegmentedCopy2: + offset = y * CI.xbytes + x; + if ( CAN_USE_LINEAR ) { + memcpy(colors, LINEAR_POINTER+offset, length); + } else { + segment = offset >> 16; + free = ((segment + 1) << 16) - offset; + offset &= 0xFFFF; + if (free < length) { + vga_setpage(segment); + memcpy(colors, GM + offset, free); + vga_setpage(segment + 1); + memcpy(colors + free, GM, length - free); + } else { + vga_setpage(segment); + memcpy(colors, GM + offset, length); + } + } + } + break; + case 32768: + case 65536: + x *= 2; + goto SegmentedCopy2; + case 1 << 24: + if (__svgalib_cur_info.bytesperpixel == 4) { + x<<=2; + } else { + x *= 3; + } + goto SegmentedCopy2; + } + return 0; +} + diff --git a/src/vgadrv.c b/src/vgadrv.c new file mode 100644 index 0000000..884769e --- /dev/null +++ b/src/vgadrv.c @@ -0,0 +1,322 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + + +#include /* for NULL */ +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +/* BIOS mode 0Dh - 320x200x16 */ +static const unsigned char g320x200x16_regs[60] = +{ + 0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x20, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x09, 0x0F, 0x00, 0x06, + 0x63 +}; + +/* BIOS mode 0Eh - 640x200x16 */ +static const unsigned char g640x200x16_regs[60] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x20, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0x63 +}; + +/* BIOS mode 10h - 640x350x16 */ +static const unsigned char g640x350x16_regs[60] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x20, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xA3 +}; + +/* BIOS mode 12h - 640x480x16 */ +static const unsigned char g640x480x16_regs[60] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x20, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xE3 +}; + +/* BIOS mode 13h - 320x200x256 */ +static const unsigned char g320x200x256_regs[60] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x0E, + 0x63 +}; + +/* non-BIOS mode - 320x240x256 */ +static const unsigned char g320x240x256_regs[60] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0D, 0x3E, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0xAC, 0xDF, 0x28, 0x00, 0xE7, 0x06, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xE3 +}; + +/* non-BIOS mode - 320x400x256 */ +static const unsigned char g320x400x256_regs[60] = +{ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0x63 +}; + +/* non-BIOS mode - 360x480x256 */ +static const unsigned char g360x480x256_regs[60] = +{ + 0x6B, 0x59, 0x5A, 0x8E, 0x5E, 0x8A, 0x0D, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0xAC, 0xDF, 0x2D, 0x00, 0xE7, 0x06, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xE7 +}; + +/* monochrome mode based on BIOS mode 12h - 640x480x2 */ +#define g640x480x2_regs g640x480x16_regs + +/* non BIOS mode - 720x348x2 based on mode 10h */ +static const unsigned char g720x348x2_regs[60] = +{ + 0x6B, 0x59, 0x5A, 0x8E, 0x5E, 0x8A, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x2D, 0x0F, 0x63, 0xBA, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x20, 0x00, 0x00, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xA7 +}; + +/* non-BIOS mode - 400x300x256 - added by Ark 28-JAN-2001 */ +static const unsigned char g400x300x256X_regs[60] = +{ + 0x71, 0x63, 0x64, 0x92, 0x65, 0x82, 0x46, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x2B, 0x32, 0x00, 0x2F, 0x44, 0xE3, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + 0x03, 0x01, 0x0F, 0x00, 0x06, + 0xA7 +}; + + +/* Mode table */ +static ModeTable vga_modes[] = +{ +/* *INDENT-OFF* */ + OneModeEntry(640x480x2), + OneModeEntry(720x348x2), + OneModeEntry(320x200x16), + OneModeEntry(640x200x16), + OneModeEntry(640x350x16), + OneModeEntry(640x480x16), + OneModeEntry(320x200x256), + OneModeEntry(320x240x256), + OneModeEntry(320x400x256), + OneModeEntry(360x480x256), + OneModeEntry(400x300x256X), +#ifdef G720x350x16 + OneModeEntry(720x350x16), +#endif + END_OF_MODE_TABLE +/* *INDENT-ON* */ +}; + + +/* Fill in chipset-specific modeinfo */ + +static void getmodeinfo(int mode, vga_modeinfo * modeinfo) +{ + if (modeinfo->bytesperpixel == 1) { /* 320x200x256 linear mode */ + modeinfo->maxpixels = 65536; + modeinfo->startaddressrange = 0xffff; + } else + switch (modeinfo->colors) { + case 16: /* 4-plane 16 color mode */ + modeinfo->maxpixels = 65536 * 8; + modeinfo->startaddressrange = 0x7ffff; + break; + case 256: /* 4-plane 256 color mode */ + modeinfo->maxpixels = 65536 * 4; + modeinfo->startaddressrange = 0x3ffff; + break; + } + modeinfo->maxlogicalwidth = 2040; + modeinfo->haveblit = 0; + modeinfo->flags &= ~(IS_INTERLACED | HAVE_RWPAGE); +} + +static void nothing(void) +{ +} + +static int saveregs(unsigned char regs[]) +{ + return 0; +} + +static void setregs(const unsigned char regs[], int mode) +{ +} + +/* Return nonzero if mode available */ + +static int modeavailable(int mode) +{ + const unsigned char *regs; + + regs = LOOKUPMODE(vga_modes, mode); + if (regs != NULL && regs != DISABLE_MODE) + return STDVGADRV; + return 0; +} + + +/* Set a mode */ + +static int lastmode; + +static int setmode(int mode, int prv_mode) +{ +/* standard VGA driver: setmode */ + const unsigned char *regs; + + if (mode == TEXT) + return 0; /* Do nothing. */ + + regs = LOOKUPMODE(vga_modes, mode); + if (regs == NULL || regs == DISABLE_MODE) + return 1; + lastmode = mode; + __svgalib_setregs(regs); + return 0; +} + +/* Set display start */ + +static void setdisplaystart(int address) +{ + vga_modeinfo *modeinfo; + modeinfo = vga_getmodeinfo(lastmode); + if (modeinfo->bytesperpixel == 0) /* not 320x200x256 linear */ + switch (modeinfo->colors) { + case 16: /* planar 16-color mode */ + __svgalib_outatt(0x33,(__svgalib_inatt(0x33)&0xf0) | (address & 7)); + /* write sa0-2 to bits 0-2 */ + address >>= 3; + break; + case 256: /* planar 256-color mode */ + /* write sa0-1 to bits 1-2 */ + __svgalib_outatt(0x33,(__svgalib_inatt(0x33)&0xf0) | ((address & 3)<<1) ); + address >>= 2; + break; + } + __svgalib_outcrtc(0x0d, address & 0x00ff); + __svgalib_outcrtc(0x0c, (address & 0xff00) >> 8); +} + +static void setlogicalwidth(int width) +{ + __svgalib_outcrtc(0x13, width >> 3); +} + +static int vgadrv_init(int, int, int); + +static int vga_test(void) +{ + unsigned char save, back; + + /* Check if a DAC is present */ + save = port_in(PEL_IW); + __svgalib_delay(); + port_out_r(PEL_IW, ~save); + __svgalib_delay(); + back = port_in(PEL_IW); + __svgalib_delay(); + port_out_r(PEL_IW, save); + save = ~save; + if (back == save) { + vgadrv_init(0, 0, 0); + return 1; + } + return 0; +} + + +DriverSpecs __svgalib_vga_driverspecs = +{ /* standard VGA */ + saveregs, + setregs, + nothing, /* unlock */ + nothing, /* lock */ + vga_test, + vgadrv_init, + (void (*)(int)) nothing, /* __svgalib_setpage */ + (void (*)(int)) nothing, /* __svgalib_setrdpage */ + (void (*)(int)) nothing, /* __svgalib_setwrpage */ + setmode, + modeavailable, + setdisplaystart, + setlogicalwidth, + getmodeinfo, + 0, /* bitblt */ + 0, /* imageblt */ + 0, /* fillblt */ + 0, /* hlinelistblt */ + 0, /* bltwait */ + 0, /* extset */ + 0, + 0, /* linear */ + NULL, /* Accelspecs */ + NULL, /* Emulation */ +}; + +/* Initialize chipset (called after detection) */ + +static int vgadrv_init(int force, int par1, int par2) +{ + if (__svgalib_driver_report) + fprintf(stderr,"Using VGA driver.\n"); + __svgalib_driverspecs = &__svgalib_vga_driverspecs; + __svgalib_banked_mem_base=0xa0000; + __svgalib_banked_mem_size=0x10000; + + return 0; +} diff --git a/src/vgadump.c b/src/vgadump.c new file mode 100644 index 0000000..a6b2a9d --- /dev/null +++ b/src/vgadump.c @@ -0,0 +1,81 @@ +/* + * vgadump.c: + * + * Dump vga registers. + * + * Rewritten Feb 1996 by Stephen Lee. Copyright 1996 Stephen Lee. + * This file is part of SVGAlib. Original copyrights: + * + * VGAlib version 1.2 - (c) 1993 Tommy Frandsen + * + * This library is free software; you can redistribute it and/or + * modify it without any restrictions. This library is distributed + * in the hope that it will be useful, but without any warranty. + * + * Multi-chipset support Copyright 1993 Harm Hanemaayer + */ + +#include +#include +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +static void dumpregs(const unsigned char regs[], int n, const char *fmt, ...) +{ + int i; + va_list ap; + + if (!n) + return; + i = 0; + printf(" "); + while (i < n) { + printf("0x%02X,", regs[i]); + i++; + if (i % 8 == 0 || i == n) { + if (i <= 8) { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } + printf("\n"); + if (i != n) + printf(" "); + } + } +} + +/* + * dump VGA registers. Note the output has a comma at the end + * (it's simpler to code and the standard allows it) + */ +void __svgalib_dumpregs(const unsigned char regs[], int n) +{ + printf("static unsigned char regs[%d] = {\n", n); + + dumpregs(regs + CRT, CRT_C, "\t/* CR00-CR%02x */", CRT_C); + dumpregs(regs + ATT, ATT_C, "\t/* AR00-AR%02x */", ATT_C); + dumpregs(regs + GRA, GRA_C, "\t/* GR00-GR%02x */", SEQ_C); + dumpregs(regs + SEQ, SEQ_C, "\t\t\t/* SR00-SR%02x */", SEQ_C); + dumpregs(regs + MIS, MIS_C, "\t\t\t\t\t\t/* MISC_OUT */"); + n -= EXT; + if (n) { + printf(" /* Extended (count = 0x%02x) */\n", n); + dumpregs(regs + EXT, n, ""); + } + printf("};\n"); +} + +int vga_dumpregs(void) +{ + unsigned char regs[MAX_REGS]; + int n; + + __svgalib_getchipset(); + + n = __svgalib_saveregs(regs); + __svgalib_dumpregs(regs, n); + + return 0; +} diff --git a/src/vgaio.c b/src/vgaio.c new file mode 100644 index 0000000..c953428 --- /dev/null +++ b/src/vgaio.c @@ -0,0 +1,147 @@ +#include "libvga.h" +#include + +int __svgalib_vga_inmisc(void) +{ + return port_in(MIS_R); +} + +void __svgalib_vga_outmisc(int i) +{ + port_out_r(MIS_W,i); +} + +int __svgalib_vga_incrtc(int i) +{ + port_out_r(__svgalib_CRT_I,i); + return port_in(__svgalib_CRT_D); +} + +void __svgalib_vga_outcrtc(int i, int d) +{ + port_out_r(__svgalib_CRT_I, i); + port_out_r(__svgalib_CRT_D, d); +} + +int __svgalib_vga_inseq(int index) +{ + port_out_r(SEQ_I, index); + return port_in(SEQ_D); +} + +void __svgalib_vga_outseq(int index, int val) +{ + port_out_r(SEQ_I, index); + port_out_r(SEQ_D, val); +} + +int __svgalib_vga_ingra(int index) +{ + port_out_r(GRA_I, index); + return port_in(GRA_D); +} + +void __svgalib_vga_outgra(int index, int val) +{ + port_out_r(GRA_I, index); + port_out_r(GRA_D, val); +} + +int __svgalib_vga_inis1(void) +{ + return port_in(__svgalib_IS1_R); +} + +#ifdef NO_DELAY + +int __svgalib_vga_inatt(int index) +{ + __svgalib_vga_inis1(); + port_out_r(ATT_IW, index); + return port_in(ATT_R); +} + +void __svgalib_vga_outatt(int index, int val) +{ + __svgalib_vga_inis1(); + port_out_r(ATT_IW, index); + port_out_r(ATT_IW, val); +} + +void __svgalib_vga_attscreen(int i) +{ + __svgalib_vga_inis1(); + port_out_r(ATT_IW, i); +} + +void __svgalib_vga_inpal(int i, int *r, int *g, int *b) +{ + port_out_r(PEL_IR,i); + *r=port_in(PEL_D); + *g=port_in(PEL_D); + *b=port_in(PEL_D); +} + +void __svgalib_vga_outpal(int i, int r, int g, int b) +{ + + port_out_r(PEL_IW,i); + port_out_r(PEL_D,r); + port_out_r(PEL_D,g); + port_out_r(PEL_D,b); +} + +#else /* NO_DELAY */ + +int __svgalib_vga_inatt(int index) +{ + __svgalib_delay(); + __svgalib_vga_inis1(); + __svgalib_delay(); + port_out_r(ATT_IW, index); + __svgalib_delay(); + return port_in(ATT_R); +} + +void __svgalib_vga_outatt(int index, int val) +{ + __svgalib_delay(); + __svgalib_vga_inis1(); + __svgalib_delay(); + port_out_r(ATT_IW, index); + __svgalib_delay(); + port_out_r(ATT_IW, val); +} + +void __svgalib_vga_attscreen(int i) +{ + __svgalib_delay(); + __svgalib_vga_inis1(); + __svgalib_delay(); + port_out_r(ATT_IW, i); +} + +void __svgalib_vga_inpal(int i, int *r, int *g, int *b) +{ + port_out_r(PEL_IR,i); + __svgalib_delay(); + *r=port_in(PEL_D); + __svgalib_delay(); + *g=port_in(PEL_D); + __svgalib_delay(); + *b=port_in(PEL_D); +} + +void __svgalib_vga_outpal(int i, int r, int g, int b) +{ + + port_out_r(PEL_IW,i); + __svgalib_delay(); + port_out_r(PEL_D,r); + __svgalib_delay(); + port_out_r(PEL_D,g); + __svgalib_delay(); + port_out_r(PEL_D,b); +} + +#endif /* NO_DELAY */ diff --git a/src/vgaio.h b/src/vgaio.h new file mode 100644 index 0000000..f7639ee --- /dev/null +++ b/src/vgaio.h @@ -0,0 +1,16 @@ +#include "libvga.h" + +extern int __svgalib_vga_inmisc(void); +extern void __svgalib_vga_outmisc(int i); +extern int __svgalib_vga_incrtc(int i); +extern void __svgalib_vga_outcrtc(int i, int d); +extern int __svgalib_vga_inseq(int i); +extern void __svgalib_vga_outseq(int i, int d); +extern int __svgalib_vga_ingra(int i); +extern void __svgalib_vga_outgra(int i, int d); +extern int __svgalib_vga_inis1(void); +extern int __svgalib_vga_inatt(int i); +extern void __svgalib_vga_outatt(int i, int d); +extern void __svgalib_vga_attscreen(int i); +extern void __svgalib_vga_inpal(int i, int *r, int *g, int *b); +extern void __svgalib_vga_outpal(int i, int r, int g, int b); diff --git a/src/vgaline.c b/src/vgaline.c new file mode 100644 index 0000000..8c7b378 --- /dev/null +++ b/src/vgaline.c @@ -0,0 +1,57 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +#include +#include "vga.h" +#include "libvga.h" + +#define ABS(a) (((a)<0) ? -(a) : (a)) + +int vga_drawline(int x1, int y1, int x2, int y2) +{ + int dx = x2 - x1; + int dy = y2 - y1; + int ax = ABS(dx) << 1; + int ay = ABS(dy) << 1; + int sx = (dx >= 0) ? 1 : -1; + int sy = (dy >= 0) ? 1 : -1; + + int x = x1; + int y = y1; + + if (ax > ay) { + int d = ay - (ax >> 1); + while (x != x2) { + vga_drawpixel(x, y); + + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } else { + int d = ax - (ay >> 1); + while (y != y2) { + vga_drawpixel(x, y); + + if (d > 0 || (d == 0 && sy == 1)) { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } + vga_drawpixel(x, y); + + return 0; +} + diff --git a/src/vgamisc.c b/src/vgamisc.c new file mode 100644 index 0000000..b7a4fad --- /dev/null +++ b/src/vgamisc.c @@ -0,0 +1,225 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vga.h" +#include "libvga.h" +#include "driver.h" +#include "mouse/vgamouse.h" +#include "keyboard/vgakeyboard.h" +#include "svgalib_helper.h" + +vga_cardinfo *vga_getcardinfo(void) { + vga_cardinfo *vci; + + vci = malloc(sizeof(vga_cardinfo)); + if(vci==NULL) return vci; + vci->version = 0x200; + vci->size = sizeof(vga_cardinfo); + vci->chipset = __svgalib_chipset; + vci->physmem = __svgalib_linear_mem_phys_addr; + vci->physmemsize = __svgalib_linear_mem_size; + vci->linearmem = LINEAR_POINTER; + + return vci; +} + +void vga_waitretrace(void) +{ +#if 0 + if(!__svgalib_nohelper) + ioctl(__svgalib_mem_fd, SVGAHELPER_WAITRETRACE, NULL); + else +#endif + { + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->waitretrace) { + __svgalib_driverspecs->emul->waitretrace(); + } else { + while (!(__svgalib_inis1() & 8)); + while (__svgalib_inis1() & 8); + } + } +} + +/* + * The way IS_LINEAR gets indicated is rather convoluted; if the driver + * is CAPABLE_LINEAR, setlinearaddressing will enable + * the flag in __svgalib_linearset which gets set in the modeinfo by + * vga_getmodeinfo(). The driver must turn off the flag in + * __svgalib_linearset if linear addressing gets disabled (e.g. when + * setting another mode). + * + * For any driver, the chipset getmodeinfo flag can examine a hardware + * register and set the IS_LINEAR flag if linear addressing is enabled. + */ + +unsigned char * + vga_getgraphmem(void) +{ + + DTP((stderr,"getgraphmem\n")); + + if (__svgalib_modeinfo_linearset & IS_LINEAR ) + return LINEAR_POINTER; + + return GM; +} + +/* + * This function is to be called after a SVGA graphics mode set + * in banked mode. Probing in VGA-compatible textmode is not a good + * idea. + */ + +/* cf. vga_waitretrace, M.Weller */ +int vga_setlinearaddressing(void) +{ + int (*lfn) (int op, int param) = __svgalib_driverspecs->linear; + vga_modeinfo *modeinfo; + + DTP((stderr,"setlinearaddressing\n")); + + modeinfo = vga_getmodeinfo(CM); + if (!(modeinfo->flags&CAPABLE_LINEAR)) return -1; + + (*lfn) (LINEAR_ENABLE, 0); + + if (LINEAR_POINTER==NULL) { + /* Shouldn't happen. */ + (*lfn) (LINEAR_DISABLE, 0); + __svgalib_modeinfo_linearset &= ~(IS_LINEAR); + return -1; + } + + __svgalib_modeinfo_linearset |= IS_LINEAR; + + graph_mem = LINEAR_POINTER; + + return __svgalib_linear_mem_size; /* Who cares? */ +} + +#if 1 + +/* + * The other code doesn't work under Linux/Alpha (I think + * it should). For now, this is a quick work-around). + */ + +int vga_getkey(void) +{ + struct timeval tv; + fd_set fds; + int fd = fileno(stdin); + char c; + + tv.tv_sec = tv.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(fd, &fds); + if (select(fd + 1, &fds, 0, 0, &tv) > 0) { + if (read(fileno(stdin), &c, 1) != 1) { + return 0; + } + return c; + } + return 0; +} + +#else + +int vga_getkey(void) +{ + struct termio zap, original; + int e; + char c; + + ioctl(fileno(stdin), TCGETA, &original); /* Get termio */ + zap = original; + zap.c_cc[VMIN] = 0; /* Modify termio */ + zap.c_cc[VTIME] = 0; + zap.c_lflag = 0; + ioctl(fileno(stdin), TCSETA, &zap); /* Set new termio */ + e = read(fileno(stdin), &c, 1); /* Read one char */ + ioctl(fileno(stdin), TCSETA, &original); /* Restore termio */ + if (e != 1) + return 0; /* No key pressed. */ + return c; /* Return key. */ +} + +#endif + +int vga_waitevent(int which, fd_set * in, fd_set * out, fd_set * except, + struct timeval *timeout) +{ + fd_set infdset; + int fd, retval; + + if (!in) { + in = &infdset; + FD_ZERO(in); + } + fd = __svgalib_mouse_fd; /* __svgalib_mouse_fd might change on + vc switch!! */ + if ((which & VGA_MOUSEEVENT) && (fd >= 0)) + FD_SET(fd, in); + if (which & VGA_KEYEVENT) { + if(__svgalib_novccontrol) { + fd=fileno(stdin); + FD_SET(fd, in); + } else { + fd = __svgalib_kbd_fd; + if (fd >= 0) { /* we are in raw mode */ + FD_SET(fd, in); + } else { + FD_SET(__svgalib_tty_fd, in); + } + } + } + if (select(FD_SETSIZE, in, out, except, timeout) < 0) + return -1; + retval = 0; + fd = __svgalib_mouse_fd; + if ((which & VGA_MOUSEEVENT) && (fd >= 0)) { + if (FD_ISSET(fd, in)) { + retval |= VGA_MOUSEEVENT; + FD_CLR(fd, in); + mouse_update(); + } + } + if (which & VGA_KEYEVENT) { + if(__svgalib_novccontrol) { + fd=fileno(stdin); + if(FD_ISSET(fd, in)) { + FD_CLR(fd, in); + retval |= VGA_KEYEVENT; + } + } else { + fd = __svgalib_kbd_fd; + if (fd >= 0) { /* we are in raw mode */ + if (FD_ISSET(fd, in)) { + FD_CLR(fd, in); + retval |= VGA_KEYEVENT; + keyboard_update(); + } + } else if (FD_ISSET(__svgalib_tty_fd, in)) { + FD_CLR(__svgalib_tty_fd, in); + retval |= VGA_KEYEVENT; + } + } + } + return retval; +} + diff --git a/src/vgammvgaio.c b/src/vgammvgaio.c new file mode 100644 index 0000000..e82c259 --- /dev/null +++ b/src/vgammvgaio.c @@ -0,0 +1,109 @@ +#include "libvga.h" +#include "io.h" + +int __svgalib_vgammbase; + +int __svgalib_mm_inmisc(void) +{ + return v_readb(__svgalib_vgammbase+MIS_R); +} + +void __svgalib_mm_outmisc(int i) +{ + v_writeb(i, __svgalib_vgammbase+MIS_W); +} + +int __svgalib_mm_incrtc(int i) +{ + v_writeb(i, __svgalib_vgammbase+__svgalib_CRT_I); + return v_readb(__svgalib_vgammbase+__svgalib_CRT_D); +} + +void __svgalib_mm_outcrtc(int i, int d) +{ + v_writeb(i, __svgalib_vgammbase+__svgalib_CRT_I); + v_writeb(d, __svgalib_vgammbase+__svgalib_CRT_D); +} + +int __svgalib_mm_inseq(int i) +{ + v_writeb(i, __svgalib_vgammbase+SEQ_I); + return v_readb(__svgalib_vgammbase+SEQ_D); +} + +void __svgalib_mm_outseq(int i, int val) +{ + v_writeb(i, __svgalib_vgammbase+SEQ_I); + v_writeb(val, __svgalib_vgammbase+SEQ_D); +} + +int __svgalib_mm_ingra(int index) +{ + v_writeb(index, __svgalib_vgammbase+GRA_I); + return v_readb(__svgalib_vgammbase+GRA_D); +} + +void __svgalib_mm_outgra(int index, int val) +{ + v_writeb(index, __svgalib_vgammbase+GRA_I); + v_writeb(val, __svgalib_vgammbase+GRA_D); +} + +int __svgalib_mm_inis1(void) +{ + return v_readb(__svgalib_vgammbase+__svgalib_IS1_R); +} + +int __svgalib_mm_inatt(int index) +{ + __svgalib_mm_inis1(); + v_writeb(index, __svgalib_vgammbase+ATT_IW); + return v_readb(__svgalib_vgammbase+ATT_R); +} + +void __svgalib_mm_outatt(int index, int val) +{ + __svgalib_mm_inis1(); + v_writeb(index, __svgalib_vgammbase+ATT_IW); + v_writeb(val, __svgalib_vgammbase+ATT_IW); +} + +void __svgalib_mm_attscreen(int i) +{ + __svgalib_mm_inis1(); + v_writeb(i, __svgalib_vgammbase+ATT_IW); +} + +void __svgalib_mm_inpal(int i, int *r, int *g, int *b) +{ + v_writeb(i, __svgalib_vgammbase+PEL_IR); + *r=v_readb(__svgalib_vgammbase+PEL_D); + *g=v_readb(__svgalib_vgammbase+PEL_D); + *b=v_readb(__svgalib_vgammbase+PEL_D); +} + +void __svgalib_mm_outpal(int i, int r, int g, int b) +{ + v_writeb(i, __svgalib_vgammbase+PEL_IW); + v_writeb(r, __svgalib_vgammbase+PEL_D); + v_writeb(g, __svgalib_vgammbase+PEL_D); + v_writeb(b, __svgalib_vgammbase+PEL_D); +} + +void __svgalib_mm_io_mapio(void) +{ + __svgalib_inmisc=__svgalib_mm_inmisc; + __svgalib_outmisc=__svgalib_mm_outmisc; + __svgalib_incrtc=__svgalib_mm_incrtc; + __svgalib_outcrtc=__svgalib_mm_outcrtc; + __svgalib_inseq=__svgalib_mm_inseq; + __svgalib_outseq=__svgalib_mm_outseq; + __svgalib_ingra=__svgalib_mm_ingra; + __svgalib_outgra=__svgalib_mm_outgra; + __svgalib_inatt=__svgalib_mm_inatt; + __svgalib_outatt=__svgalib_mm_outatt; + __svgalib_attscreen=__svgalib_mm_attscreen; + __svgalib_inis1=__svgalib_mm_inis1; + __svgalib_inpal=__svgalib_mm_inpal; + __svgalib_outpal=__svgalib_mm_outpal; +} diff --git a/src/vgammvgaio.h b/src/vgammvgaio.h new file mode 100644 index 0000000..c26d9fc --- /dev/null +++ b/src/vgammvgaio.h @@ -0,0 +1,2 @@ +extern int __svgalib_vgammbase; +extern void __svgalib_mm_io_mapio(void); diff --git a/src/vgamodesel.c b/src/vgamodesel.c new file mode 100644 index 0000000..c0620e5 --- /dev/null +++ b/src/vgamodesel.c @@ -0,0 +1,120 @@ + +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +#include +#include +#include + +#include "vga.h" +#include "libvga.h" + + +#define MODENAME_LENGTH 20 + +/* This is set by vga.c if there's a 'default_mode' line in the config */ +extern int __svgalib_default_mode; + +/* This one won't type an error message ... */ +int __svgalib_name2number(char *m) +{ + int i; + + for (i = G320x200x16; i <= GLASTMODE; i++) { + if (strcasecmp(m, vga_getmodename(i)) == 0) /* check name */ + return i; + } + return -1; +} + +int vga_getmodenumber(char *m) +{ + int i; + char s[3]; + + __svgalib_getchipset(); /* Do initialisation first */ + i = __svgalib_name2number(m); + if (i > 0) + return i; + + for (i = G320x200x16; i <= GLASTMODE; i++) { + sprintf(s, "%d", i); + if (strcasecmp(m, s) == 0) /* check number */ + return i; + } + if (strcasecmp(m, "PROMPT") == 0) + return -1; + + fprintf(stderr, "Invalid graphics mode \'%s\'.\n", m); + return -1; +} + +char * + vga_getmodename(int m) +{ + static char modename[MODENAME_LENGTH]; + int x, y, c; + + if (m <= TEXT || m > GLASTMODE) + return ""; + x = __svgalib_infotable[m].xdim; + y = __svgalib_infotable[m].ydim; + switch (c = __svgalib_infotable[m].colors) { + case 1 << 15: + sprintf(modename, "G%dx%dx32K", x, y); + break; + case 1 << 16: + sprintf(modename, "G%dx%dx64K", x, y); + break; + case 1 << 24: + sprintf(modename, (__svgalib_infotable[m].bytesperpixel == 3) ? + "G%dx%dx16M" : "G%dx%dx16M32", x, y); + break; + default: + sprintf(modename, "G%dx%dx%d", x, y, c); + break; + } + return modename; +} + +int vga_getdefaultmode(void) { + char *stmp = getenv("SVGALIB_DEFAULT_MODE"); + +/* Process env var first so mode might be overridden by it. */ + if (stmp != NULL && strcmp(stmp, "") != 0) { + int mode; + if ( (mode = vga_getmodenumber(stmp)) != -1) + return mode; + } else if (__svgalib_default_mode) { + return __svgalib_default_mode; + } + return 10; /* Default */ +} + +/* find the mode with minimal resolution (defined as num of pixels) that +can display x*y */ +int vga_getoptmode(int x, int y, int colors, int bytesperpixel, int c) +{ + int i; + int cur,size; + + cur=-1; + size=1<<24; + + for(i=0;i=x)&& + (infotable[i].ydim>=y)&& + (infotable[i].ydim*infotable[i].xdim + +int __svgalib_vganull_inmisc(void) +{ + return 0; +} + +void __svgalib_vganull_outmisc(int i) +{ +} + +int __svgalib_vganull_incrtc(int i) +{ + return 0; +} + +void __svgalib_vganull_outcrtc(int i, int d) +{ +} + +int __svgalib_vganull_inseq(int index) +{ + return 0; +} + +void __svgalib_vganull_outseq(int index, int val) +{ +} + +int __svgalib_vganull_ingra(int index) +{ + return 0; +} + +void __svgalib_vganull_outgra(int index, int val) +{ +} + +int __svgalib_vganull_inis1(void) +{ + return 0; +} + +int __svgalib_vganull_inatt(int index) +{ + return 0; +} + +void __svgalib_vganull_outatt(int index, int val) +{ +} + +void __svgalib_vganull_attscreen(int i) +{ +} + +void __svgalib_vganull_inpal(int i, int *r, int *g, int *b) +{ +} + +void __svgalib_vganull_outpal(int i, int r, int g, int b) +{ +} diff --git a/src/vganullio.h b/src/vganullio.h new file mode 100644 index 0000000..896a34d --- /dev/null +++ b/src/vganullio.h @@ -0,0 +1,17 @@ +#include "libvga.h" + +extern int __svgalib_vganull_inmisc(void); +extern void __svgalib_vganull_outmisc(int i); +extern int __svgalib_vganull_incrtc(int i); +extern void __svgalib_vganull_outcrtc(int i, int d); +extern int __svgalib_vganull_inseq(int i); +extern void __svgalib_vganull_outseq(int i, int d); +extern int __svgalib_vganull_ingra(int i); +extern void __svgalib_vganull_outgra(int i, int d); +extern int __svgalib_vganull_inis1(void); +extern int __svgalib_vganull_inatt(int i); +extern void __svgalib_vganull_outatt(int i, int d); +extern void __svgalib_vganull_attscreen(int i); +extern void __svgalib_vganull_inpal(int i, int *r, int *g, int *b); +extern void __svgalib_vganull_outpal(int i, int r, int g, int b); + diff --git a/src/vgapal.c b/src/vgapal.c new file mode 100644 index 0000000..8dece17 --- /dev/null +++ b/src/vgapal.c @@ -0,0 +1,149 @@ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* Converted to especially ugly code and seriously hacked for Mach32: */ +/* M. Weller in 1994 */ +#include + +#include "vga.h" +#include "vgaio.h" +#include "libvga.h" +#include "driver.h" + +/* + * In grayscale mode, we convert RGB colors to a Y component on the + * green-channel (the Y component is used in grayscale TV sets for the + * same purpose and corresponds to the "brightness" of the color as + * perceived by the human eye. In order to be able to return to the + * user the original green-component, we save a backup copy of the + * green channel in __svgalib_green_backup: + */ +int __svgalib_green_backup[256]; + + +static int set_lut(int index, int red, int green, int blue) +{ + if (__svgalib_novga) return 1; + + /* prevents lockups */ + if ((__svgalib_chipset == MACH64)) { + port_out_r(0x02ec+0x5c00,index); + port_out_r(0x02ec+0x5c01,red); + port_out_r(0x02ec+0x5c01,green); + port_out_r(0x02ec+0x5c01,blue); + return 0; + } + + __svgalib_outpal(index,red,green,blue); + + return 0; +} + + +static int get_lut(int index, int *red, int *green, int *blue) +{ + if (__svgalib_novga) return 0; + + /* prevents lockups on mach64 */ + if ((__svgalib_chipset == MACH64)) { + port_out_r(0x02ec+0x5c00,index); + *red=port_in(0x02ec+0x5c01); + *green=port_in(0x02ec+0x5c01); + *blue=port_in(0x02ec+0x5c01); + return 0; + } + + __svgalib_inpal(index,red,green,blue); + + return 0; +} + +int vga_setpalette(int index, int red, int green, int blue) +{ + + DTP((stderr,"setpalette %i %i %i %i\n",index,red,green,blue)); + + if (__svgalib_grayscale) { + if ((unsigned) index >= sizeof(__svgalib_green_backup) / sizeof(__svgalib_green_backup[0])) { + fprintf(stderr,"vga_setpalette: color index %d out of range\n", index); + } + __svgalib_green_backup[index] = green; + + green = 0.299 * red + 0.587 * green + 0.114 * blue; + if (green < 0) + green = 0; + if (green > 255) + green = 255; + } + + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->setpalette) { + return __svgalib_driverspecs->emul->setpalette(index, red, green, blue); + } else { + return set_lut(index, red, green, blue); + } +} + +int vga_getpalette(int index, int *red, int *green, int *blue) +{ + if (__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->getpalette) + __svgalib_driverspecs->emul->getpalette(index, red, green, blue); + else get_lut(index, red, green, blue); + if (__svgalib_grayscale) { + if ((unsigned) index >= sizeof(__svgalib_green_backup) / sizeof(__svgalib_green_backup[0])) { + fprintf(stderr,"vga_getpalette: color index %d out of range\n", index); + } + *green = __svgalib_green_backup[index]; + } + return 0; +} + + +int vga_setpalvec(int start, int num, int *pal) +{ + int i; + + DTP((stderr,"setpalvec %i %i %x\n",start,num,pal)); + + if ((__svgalib_driverspecs->emul && __svgalib_driverspecs->emul->setpalette) || + (__svgalib_outpal!=__svgalib_vga_outpal)) { + for (i = start; i < start + num; ++i) { + vga_setpalette(i, pal[0], pal[1], pal[2]); + pal += 3; + } + } else { + unsigned char string[768]; + + if ( num > 256 ) + return 0; + + for (i = 0; i < num * 3; i++) + string[i] = pal[i]; + + port_out ( start, 0x3c8 ); +#if 0 + port_rep_outb( string, num * 3, 0x3c9 ); +#else + for(i=0;i +#include +#include +#include +#include +#include "endianess.h" +#include "libvga.h" +#include "svgalib_helper.h" +#include "vgapci.h" + +int __svgalib_pci_helper_idev=0; +int __svgalib_pci_nohelper_idev=0; +int __svgalib_pci_card_found_at=0; + +static void proc_pci_read_config(int device, unsigned int *buf, int size) +{ + int i; + + for(i=0;i>16)&0xffff)==0x0300)) { /* VGA Class */ + proc_pci_read_config(device,conf,16); + __svgalib_pci_card_found_at = device; + return device; + } + } + + return 0; +} + +unsigned int __svgalib_pci_read_config_dword(int pos, int address) +{ + if(__svgalib_nohelper) { + int f; + unsigned int n, d; + int bus, device, fn; + char filename[256]; + + bus=(pos&0xff00)>>8; + device=(pos&0xf8)>>3; + fn=pos&0x07; + sprintf(filename,"/proc/bus/pci/%02i/%02x.%i",bus,device,fn); + f=open(filename,O_RDONLY); + lseek(f, address, SEEK_SET); + read(f, &n, 4); + close(f); + d=LE32(n); + return d; + } else { + pcic_t p; + + p.pcipos = pos; + p.address = address; + + if(ioctl( __svgalib_mem_fd, SVGAHELPER_PCIINL, &p)) return -1; + + return p.val; + } +} + +unsigned long __svgalib_pci_read_aperture_len(int pos, int address) +{ + if(__svgalib_nohelper) { + FILE *f; + char buf[512]; + + f=fopen("/proc/bus/pci/devices", "r"); + while (fgets(buf, sizeof(buf)-1, f)) { + int cnt; + unsigned int dev, di; + unsigned long lens[6], dl; + cnt = sscanf(buf, "%x %x %x %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx", + &dev, &di, &di, + &dl, &dl, &dl, &dl, &dl, &dl, &dl, + &lens[0], &lens[1], &lens[2], &lens[3], &lens[4], &lens[5], + &dl); + if(dev==pos) + return lens[address]; + } + } else { + pcic_t p; + + p.pcipos = pos; + p.address = address; + + if(ioctl( __svgalib_mem_fd, SVGAHELPER_PCIAPLEN, &p)) return -1; + + return p.val; + } + + return -1; +} + +void __svgalib_pci_write_config_dword(int pos, int address, unsigned int data) +{ + if(__svgalib_nohelper) + { + int f; + unsigned int d; + int bus, device, fn; + char filename[256]; + + d=LE32(data); + bus=(pos&0xff00)>>8; + device=(pos&0xf8)>>3; + fn=pos&0x07; + sprintf(filename,"/proc/bus/pci/%02i/%02x.%i",bus,device,fn); + f=open(filename,O_WRONLY); + lseek(f, address, SEEK_SET); + write(f, &d, 4); + close(f); + } + else + { + pcic_t p; + + p.pcipos = pos; + p.address = address; + p.val = data; + + ioctl( __svgalib_mem_fd, SVGAHELPER_PCIOUTL, &p); + } +} + +int memorytest(uint32_t *m, int max_mem) { + unsigned char sav[1024]; + int i, j; + + max_mem*=4; + for(i=0;i=0;i--) { + *(m+64*1024*i)=i; + } + for(i=0;i +#include "vga.h" +#include "libvga.h" +#include "driver.h" + +static inline void read_write(int off) +{ + *(GM+off)=*(GM+off)+1; +} + +int vga_drawpixel(int x, int y) +{ + int c, offset; + + if (MODEX) { + /* select plane */ + __svgalib_outseq(0x02,1 << (x & 3)); + /* write color to pixel */ + *(GM+y * CI.xbytes + (x >> 2))=COL; + return 0; + } + switch (__svgalib_cur_info.bytesperpixel) { + case 0: /* Must be 2 or 16 color mode. */ + /* set up video page */ + offset = y * CI.xbytes + (x >> 3); + vga_setpage(offset >> 16); + offset &= 0xffff; + + /* select bit */ + __svgalib_outgra(0x08, 0x80 >> (x & 7)); + + /* read into latch and write dummy back */ + read_write(offset); + break; + case 1: + offset = y * CI.xbytes + x; + + if ( CAN_USE_LINEAR ) { + *(LINEAR_POINTER+offset)=COL; + } else { + /* select segment */ + vga_setpage(offset >> 16); + + /* write color to pixel */ + *(GM+(offset&0xffff))=COL; + } + break; + case 2: + offset = y * CI.xbytes + x * 2; + if ( CAN_USE_LINEAR ) { + *(uint16_t *)(LINEAR_POINTER+offset)=COL; + } else { + vga_setpage(offset >> 16); + *(uint16_t *)(GM+(offset&0xffff))=COL; + } + break; + case 3: + c = COL; + offset = y * CI.xbytes + x * 3; + if ( CAN_USE_LINEAR ) { + /* Only on little endian */ + *(LINEAR_POINTER+offset)=COL&0xff; + *(LINEAR_POINTER+offset+1)=(COL&0xff00)>>8; + *(LINEAR_POINTER+offset+2)=(COL&0xff0000)>>16; + } else { + vga_setpage(offset >> 16); + switch (offset & 0xffff) { + case 0xfffe: + *(GM+0xfffe)=COL&0xff; + *(GM+0xffff)=(COL&0xff00)>>8; + vga_setpage((offset >> 16) + 1); + *(GM)=(COL&0xff0000)>>16; + break; + case 0xffff: + *(GM+0xffff)=COL&0xff; + vga_setpage((offset >> 16) + 1); + *(GM)=(COL&0xff00)>>8; + *(GM+1)=(COL&0xff0000)>>16; + break; + default: + offset &= 0xffff; + *(GM+offset)=COL&0xff; + *(GM+offset+1)=(COL&0xff00)>>8; + *(GM+offset+2)=(COL&0xff0000)>>16; + break; + } + } + break; + case 4: + offset = y * __svgalib_cur_info.xbytes + x * 4; + if ( CAN_USE_LINEAR ) { + *(uint32_t *)(LINEAR_POINTER+offset)=COL; + } else { + vga_setpage(offset >> 16); + *(uint32_t *)(GM+(offset&0xffff))=COL; + } + break; + } + return 0; +} + +int vga_getpixel(int x, int y) +{ + unsigned char mask; + int offset, pix = 0; + + if (MODEX) { + /* select plane */ + __svgalib_outseq(0x02, 1 << (x & 3) ); + return gr_readb(y * CI.xbytes + (x >> 2)); + } + switch (__svgalib_cur_info.bytesperpixel) { + case 0: /* Must be 2 or 16 color mode. */ + /* set up video page */ + offset = y * CI.xbytes + (x >> 3); + vga_setpage(offset >> 16); + offset &= 0xffff; + + /* select bit */ + mask = 0x80 >> (x & 7); + pix = 0; + __svgalib_outgra(0x04,0); + if (gr_readb(offset) & mask) + pix |= 0x01; + __svgalib_outgra(0x04,1); + if (gr_readb(offset) & mask) + pix |= 0x02; + __svgalib_outgra(0x04,2); + if (gr_readb(offset) & mask) + pix |= 0x04; + __svgalib_outgra(0x04,3); + if (gr_readb(offset) & mask) + pix |= 0x08; + return pix; + case 1: + offset = y * CI.xbytes + x; + if ( CAN_USE_LINEAR ) { + return *(LINEAR_POINTER+offset); + } + /* select segment */ + vga_setpage(offset >> 16); + return gr_readb(offset & 0xffff); + case 2: + offset = y * CI.xbytes + x * 2; + if ( CAN_USE_LINEAR ) { + return *(uint16_t *)(LINEAR_POINTER+offset); + } + vga_setpage(offset >> 16); + return gr_readw(offset & 0xffff); + case 3: + offset = y * CI.xbytes + x * 3; + if ( CAN_USE_LINEAR ) { + return (*(LINEAR_POINTER+offset)) + (*(LINEAR_POINTER+offset+1)<<8) + + (*(LINEAR_POINTER+offset+2)<<16); + } + vga_setpage(offset >> 16); + switch (offset & 0xffff) { + case 0xfffe: + pix = gr_readw(0xfffe); + vga_setpage((offset >> 16) + 1); + return pix + (gr_readb(0) << 16); + case 0xffff: + pix = gr_readb(0xffff); + vga_setpage((offset >> 16) + 1); + return pix + (gr_readw(0) << 8); + default: + offset &= 0xffff; + return gr_readw(offset) + (gr_readb(offset + 2) << 16); + } + break; + case 4: + offset = y * __svgalib_cur_info.xbytes + x * 4; + if ( CAN_USE_LINEAR ) { + return *(uint32_t *)(LINEAR_POINTER+offset); + } + vga_setpage(offset >> 16); + return gr_readl(offset & 0xffff); + } + return 0; +} + diff --git a/src/vgaregs.c b/src/vgaregs.c new file mode 100644 index 0000000..1fc7efc --- /dev/null +++ b/src/vgaregs.c @@ -0,0 +1,122 @@ + +#include "timing.h" +#include "vgaregs.h" + + +/* + * Setup VGA registers for SVGA mode timing. Adapted from XFree86, + * vga256/vga/vgaHW.c vgaHWInit(). + * + * Note that VGA registers are set up in a way that is common for + * SVGA modes. This is not particularly useful for standard VGA + * modes, since VGA does not have a clean packed-pixel mode. + */ + +void __svgalib_setup_VGA_registers(unsigned char *moderegs, ModeTiming * modetiming, + ModeInfo * modeinfo) +{ + int i; +/* Sync Polarities */ + if ((modetiming->flags & (PHSYNC | NHSYNC)) && + (modetiming->flags & (PVSYNC | NVSYNC))) { + /* + * If both horizontal and vertical polarity are specified, + * set them as specified. + */ + moderegs[VGA_MISCOUTPUT] = 0x23; + if (modetiming->flags & NHSYNC) + moderegs[VGA_MISCOUTPUT] |= 0x40; + if (modetiming->flags & NVSYNC) + moderegs[VGA_MISCOUTPUT] |= 0x80; + } else { + /* + * Otherwise, calculate the polarities according to + * monitor standards. + */ + if (modetiming->VDisplay < 400) + moderegs[VGA_MISCOUTPUT] = 0xA3; + else if (modetiming->VDisplay < 480) + moderegs[VGA_MISCOUTPUT] = 0x63; + else if (modetiming->VDisplay < 768) + moderegs[VGA_MISCOUTPUT] = 0xE3; + else + moderegs[VGA_MISCOUTPUT] = 0x23; + } + +/* Sequencer */ + moderegs[VGA_SR0] = 0x00; + if (modeinfo->bitsPerPixel == 4) + moderegs[VGA_SR0] = 0x02; + moderegs[VGA_SR1] = 0x01; + moderegs[VGA_SR2] = 0x0F; /* Bitplanes. */ + moderegs[VGA_SR3] = 0x00; + moderegs[VGA_SR4] = 0x0E; + if (modeinfo->bitsPerPixel == 4) + moderegs[VGA_SR4] = 0x06; + +/* CRTC Timing */ + moderegs[VGA_CR0] = (modetiming->CrtcHTotal / 8) - 5; + moderegs[VGA_CR1] = (modetiming->CrtcHDisplay / 8) - 1; + moderegs[VGA_CR2] = (modetiming->CrtcHSyncStart / 8) - 1; + moderegs[VGA_CR3] = ((modetiming->CrtcHSyncEnd / 8) & 0x1F) | 0x80; + moderegs[VGA_CR4] = (modetiming->CrtcHSyncStart / 8); + moderegs[VGA_CR5] = (((modetiming->CrtcHSyncEnd / 8) & 0x20) << 2) + | ((modetiming->CrtcHSyncEnd / 8) & 0x1F); + moderegs[VGA_CR6] = (modetiming->CrtcVTotal - 2) & 0xFF; + moderegs[VGA_CR7] = (((modetiming->CrtcVTotal - 2) & 0x100) >> 8) + | (((modetiming->CrtcVDisplay - 1) & 0x100) >> 7) + | ((modetiming->CrtcVSyncStart & 0x100) >> 6) + | (((modetiming->CrtcVSyncStart) & 0x100) >> 5) + | 0x10 + | (((modetiming->CrtcVTotal - 2) & 0x200) >> 4) + | (((modetiming->CrtcVDisplay - 1) & 0x200) >> 3) + | ((modetiming->CrtcVSyncStart & 0x200) >> 2); + moderegs[VGA_CR8] = 0x00; + moderegs[VGA_CR9] = ((modetiming->CrtcVSyncStart & 0x200) >> 4) | 0x40; + if (modetiming->flags & DOUBLESCAN) + moderegs[VGA_CR9] |= 0x80; + moderegs[VGA_CRA] = 0x00; + moderegs[VGA_CRB] = 0x00; + moderegs[VGA_CRC] = 0x00; + moderegs[VGA_CRD] = 0x00; + moderegs[VGA_CRE] = 0x00; + moderegs[VGA_CRF] = 0x00; + moderegs[VGA_CR10] = modetiming->CrtcVSyncStart & 0xFF; + moderegs[VGA_CR11] = (modetiming->CrtcVSyncEnd & 0x0F) | 0x20; + moderegs[VGA_CR12] = (modetiming->CrtcVDisplay - 1) & 0xFF; + moderegs[VGA_CR13] = modeinfo->lineWidth >> 4; /* Just a guess. */ + moderegs[VGA_CR14] = 0x00; + moderegs[VGA_CR15] = modetiming->CrtcVSyncStart & 0xFF; + moderegs[VGA_CR16] = (modetiming->CrtcVSyncStart + 1) & 0xFF; + moderegs[VGA_CR17] = 0xC3; + if (modeinfo->bitsPerPixel == 4) + moderegs[VGA_CR17] = 0xE3; + moderegs[VGA_CR18] = 0xFF; + +/* Graphics Controller */ + moderegs[VGA_GR0] = 0x00; + moderegs[VGA_GR1] = 0x00; + moderegs[VGA_GR2] = 0x00; + moderegs[VGA_GR3] = 0x00; + moderegs[VGA_GR4] = 0x00; + moderegs[VGA_GR5] = 0x40; + if (modeinfo->bitsPerPixel == 4) + moderegs[VGA_GR5] = 0x02; + moderegs[VGA_GR6] = 0x05; + moderegs[VGA_GR7] = 0x0F; + moderegs[VGA_GR8] = 0xFF; + +/* Attribute Controller */ + for (i = 0; i < 16; i++) + moderegs[VGA_AR0 + i] = i; + moderegs[VGA_AR10] = 0x41; + if (modeinfo->bitsPerPixel == 4) + moderegs[VGA_AR10] = 0x01; /* was 0x81 */ + /* Attribute register 0x11 is the overscan color. + Should have no affect in svga modes. */ + moderegs[VGA_AR11] = 0x00; + moderegs[VGA_AR12] = 0x0F; + moderegs[VGA_AR13] = 0x00; + moderegs[VGA_AR14] = 0x00; +} + diff --git a/src/vgaregs.h b/src/vgaregs.h new file mode 100644 index 0000000..49ffc6c --- /dev/null +++ b/src/vgaregs.h @@ -0,0 +1,116 @@ + + +/* Register indices into mode state array. */ + +#define VGA_CRTC_COUNT 24 +#define VGA_ATC_COUNT 21 +#define VGA_GRAPHICS_COUNT 9 +#define VGA_SEQUENCER_COUNT 5 + +#define VGA_CRTC_OFFSET 0 /* 24 registers */ +#define VGA_ATC_OFFSET 24 /* 21 registers */ +#define VGA_GRAPHICS_OFFSET 45 /* 9 registers. */ +#define VGA_SEQUENCER_OFFSET 54 /* 5 registers. */ +#define VGA_MISCOUTPUT 59 /* (single register) */ +#define VGA_TOTAL_REGS 60 + +/* Total of 60 registers. */ + +#define VGAREG_CR(i) (i) +#define VGAREG_AR(i) (i + VGA_ATC_OFFSET) +#define VGAREG_GR(i) (i + VGA_GRAPHICS_OFFSET) +#define VGAREG_SR(i) (i + VGA_SEQUENCER_OFFSET) + +#define VGA_CR0 VGAREG_CR(0x00) +#define VGA_CR1 VGAREG_CR(0x01) +#define VGA_CR2 VGAREG_CR(0x02) +#define VGA_CR3 VGAREG_CR(0x03) +#define VGA_CR4 VGAREG_CR(0x04) +#define VGA_CR5 VGAREG_CR(0x05) +#define VGA_CR6 VGAREG_CR(0x06) +#define VGA_CR7 VGAREG_CR(0x07) +#define VGA_CR8 VGAREG_CR(0x08) +#define VGA_CR9 VGAREG_CR(0x09) +#define VGA_CRA VGAREG_CR(0x0A) +#define VGA_CRB VGAREG_CR(0x0B) +#define VGA_CRC VGAREG_CR(0x0C) +#define VGA_CRD VGAREG_CR(0x0D) +#define VGA_CRE VGAREG_CR(0x0E) +#define VGA_CRF VGAREG_CR(0x0F) +#define VGA_CR10 VGAREG_CR(0x10) +#define VGA_CR11 VGAREG_CR(0x11) +#define VGA_CR12 VGAREG_CR(0x12) +#define VGA_CR13 VGAREG_CR(0x13) +#define VGA_SCANLINEOFFSET VGAREG_CR(0x13) +#define VGA_CR14 VGAREG_CR(0x14) +#define VGA_CR15 VGAREG_CR(0x15) +#define VGA_CR16 VGAREG_CR(0x16) +#define VGA_CR17 VGAREG_CR(0x17) +#define VGA_CR18 VGAREG_CR(0x18) + +#define VGA_AR0 VGAREG_AR(0x00) +#define VGA_AR10 VGAREG_AR(0x10) +#define VGA_AR11 VGAREG_AR(0x11) +#define VGA_AR12 VGAREG_AR(0x12) +#define VGA_AR13 VGAREG_AR(0x13) +#define VGA_AR14 VGAREG_AR(0x14) + +#define VGA_GR0 VGAREG_GR(0x00) +#define VGA_GR1 VGAREG_GR(0x01) +#define VGA_GR2 VGAREG_GR(0x02) +#define VGA_GR3 VGAREG_GR(0x03) +#define VGA_GR4 VGAREG_GR(0x04) +#define VGA_GR5 VGAREG_GR(0x05) +#define VGA_GR6 VGAREG_GR(0x06) +#define VGA_GR7 VGAREG_GR(0x07) +#define VGA_GR8 VGAREG_GR(0x08) + +#define VGA_SR0 VGAREG_SR(0x00) +#define VGA_SR1 VGAREG_SR(0x01) +#define VGA_SR2 VGAREG_SR(0x02) +#define VGA_SR3 VGAREG_SR(0x03) +#define VGA_SR4 VGAREG_SR(0x04) + + +/* + * Set the bits bytemask in variable bytevar with the value of bits + * valuemask in value (masks must match, but may be shifted relative + * to eachother). With proper masks, should optimize into shifts. + */ + +#define SETBITSFROMVALUE(bytevar, bytemask, value, valuemask) \ + if (valuemask > bytemask) \ + bytevar = (bytevar & (~(unsigned char)bytemask)) \ + | (((value) & valuemask) / (valuemask / bytemask)); \ + else \ + bytevar = (bytevar & (~(unsigned char)bytemask)) \ + | (((value) & valuemask) * (bytemask / valuemask)); + +/* + * Set bits bytemask in bytevar, with value bits (no shifting). + */ + +#define SETBITS(bytevar, bytemask, bits) \ + bytevar = (bytevar & (~(unsigned char)bytemask)) + bits; + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define LIMIT(var, lim) if (var > lim) var = lim; + + +/* Prototypes of functions defined in vgaregs.c. */ + +void __svgalib_setup_VGA_registers( + unsigned char *moderegs, + ModeTiming * modetiming, + ModeInfo * modeinfo +); + +#define __svgalib_inGR __svgalib_ingra +#define __svgalib_outGR __svgalib_outgra +#define __svgalib_outbGR __svgalib_outgra +#define __svgalib_inSR __svgalib_inseq +#define __svgalib_outSR __svgalib_outseq +#define __svgalib_outbSR __svgalib_outseq +#define __svgalib_inCR __svgalib_incrtc +#define __svgalib_outCR __svgalib_outcrtc +#define __svgalib_outbCR __svgalib_outcrtc diff --git a/src/vgarelvgaio.c b/src/vgarelvgaio.c new file mode 100644 index 0000000..c3214d5 --- /dev/null +++ b/src/vgarelvgaio.c @@ -0,0 +1,166 @@ +#include "libvga.h" + +int __svgalib_io_reloc; + +int __svgalib_rel_inmisc(void) +{ + return port_in(MIS_R+__svgalib_io_reloc); +} + +void __svgalib_rel_outmisc(int i) +{ + port_out_r(MIS_W+__svgalib_io_reloc,i); +} + +int __svgalib_rel_incrtc(int i) +{ + port_out_r(__svgalib_CRT_I+__svgalib_io_reloc,i); + return port_in(__svgalib_CRT_D+__svgalib_io_reloc); +} + +void __svgalib_rel_outcrtc(int i, int d) +{ + port_out_r(__svgalib_CRT_I+__svgalib_io_reloc, i); + port_out_r(__svgalib_CRT_D+__svgalib_io_reloc, d); +} + +int __svgalib_rel_inseq(int index) +{ + port_out_r(SEQ_I+__svgalib_io_reloc, index); + return port_in(SEQ_D+__svgalib_io_reloc); +} + +void __svgalib_rel_outseq(int index, int val) +{ + port_out_r(SEQ_I+__svgalib_io_reloc, index); + port_out_r(SEQ_D+__svgalib_io_reloc, val); +} + +int __svgalib_rel_ingra(int index) +{ + port_out_r(GRA_I+__svgalib_io_reloc, index); + return port_in(GRA_D+__svgalib_io_reloc); +} + +void __svgalib_rel_outgra(int index, int val) +{ + port_out_r(GRA_I+__svgalib_io_reloc, index); + port_out_r(GRA_D+__svgalib_io_reloc, val); +} + +int __svgalib_rel_inis1(void) +{ + return port_in(__svgalib_IS1_R+__svgalib_io_reloc); +} + +#ifdef NO_DELAY + +int __svgalib_rel_inatt(int index) +{ + __svgalib_rel_inis1(); + port_out_r(ATT_IW+__svgalib_io_reloc, index); + return port_in(ATT_R+__svgalib_io_reloc); +} + +void __svgalib_rel_outatt(int index, int val) +{ + __svgalib_rel_inis1(); + port_out_r(ATT_IW+__svgalib_io_reloc, index); + port_out_r(ATT_IW+__svgalib_io_reloc, val); +} + +void __svgalib_rel_attscreen(int i) +{ + __svgalib_rel_inis1(); + port_out_r(ATT_IW+__svgalib_io_reloc, i); +} + +void __svgalib_rel_inpal(int i, int *r, int *g, int *b) +{ + port_out_r(PEL_IR+__svgalib_io_reloc,i); + *r=port_in(PEL_D+__svgalib_io_reloc); + *g=port_in(PEL_D+__svgalib_io_reloc); + *b=port_in(PEL_D+__svgalib_io_reloc); +} + +void __svgalib_rel_outpal(int i, int r, int g, int b) +{ + + port_out_r(PEL_IW+__svgalib_io_reloc,i); + port_out_r(PEL_D+__svgalib_io_reloc,r); + port_out_r(PEL_D+__svgalib_io_reloc,g); + port_out_r(PEL_D+__svgalib_io_reloc,b); +} + +#else /* NO_DELAY */ + +int __svgalib_rel_inatt(int index) +{ + __svgalib_delay(); + __svgalib_rel_inis1(); + __svgalib_delay(); + port_out_r(ATT_IW+__svgalib_io_reloc, index); + __svgalib_delay(); + return port_in(ATT_R+__svgalib_io_reloc); +} + +void __svgalib_rel_outatt(int index, int val) +{ + __svgalib_delay(); + __svgalib_rel_inis1(); + __svgalib_delay(); + port_out_r(ATT_IW+__svgalib_io_reloc, index); + __svgalib_delay(); + port_out_r(ATT_IW+__svgalib_io_reloc, val); +} + +void __svgalib_rel_attscreen(int i) +{ + __svgalib_delay(); + __svgalib_rel_inis1(); + __svgalib_delay(); + port_out_r(ATT_IW+__svgalib_io_reloc, i); +} + +void __svgalib_rel_inpal(int i, int *r, int *g, int *b) +{ + port_out_r(PEL_IR+__svgalib_io_reloc,i); + __svgalib_delay(); + *r=port_in(PEL_D+__svgalib_io_reloc); + __svgalib_delay(); + *g=port_in(PEL_D+__svgalib_io_reloc); + __svgalib_delay(); + *b=port_in(PEL_D+__svgalib_io_reloc); +} + +void __svgalib_rel_outpal(int i, int r, int g, int b) +{ + + port_out_r(PEL_D+__svgalib_io_reloc,i); + __svgalib_delay(); + port_out_r(PEL_D+__svgalib_io_reloc,r); + __svgalib_delay(); + port_out_r(PEL_D+__svgalib_io_reloc,g); + __svgalib_delay(); + port_out_r(PEL_D+__svgalib_io_reloc,b); +} + +#endif /* NO_DELAY */ + +void __svgalib_rel_io_mapio(void) +{ + __svgalib_inmisc=__svgalib_rel_inmisc; + __svgalib_outmisc=__svgalib_rel_outmisc; + __svgalib_incrtc=__svgalib_rel_incrtc; + __svgalib_outcrtc=__svgalib_rel_outcrtc; + __svgalib_inseq=__svgalib_rel_inseq; + __svgalib_outseq=__svgalib_rel_outseq; + __svgalib_ingra=__svgalib_rel_ingra; + __svgalib_outgra=__svgalib_rel_outgra; + __svgalib_inatt=__svgalib_rel_inatt; + __svgalib_outatt=__svgalib_rel_outatt; + __svgalib_attscreen=__svgalib_rel_attscreen; + __svgalib_inis1=__svgalib_rel_inis1; + __svgalib_inpal=__svgalib_rel_inpal; + __svgalib_outpal=__svgalib_rel_outpal; +} diff --git a/src/vgarelvgaio.h b/src/vgarelvgaio.h new file mode 100644 index 0000000..61dc014 --- /dev/null +++ b/src/vgarelvgaio.h @@ -0,0 +1,2 @@ +extern int __svgalib_io_reloc; +extern void __svgalib_rel_io_mapio(void); diff --git a/src/vgaversion.h b/src/vgaversion.h new file mode 100644 index 0000000..144211d --- /dev/null +++ b/src/vgaversion.h @@ -0,0 +1,2 @@ +int vga_version=0x1925; +static char versionstr[32]="1.9.25"; diff --git a/svgalib.lsm b/svgalib.lsm new file mode 100644 index 0000000..647dddd --- /dev/null +++ b/svgalib.lsm @@ -0,0 +1,16 @@ +Begin3 +Title: svgalib +Version: 1.4.2 +Entered-date: 99XXX99 +Description: Low-level graphics library that provides VGA and SVGA + modes in a console. It is not intended as an alternative + to X for apps, but rather a set of tools for things like + VGA games, image viewing in modes that X cannot support, etc. +Keywords: graphics, VGA, SVGA, library +Author: hhanemaa@cs.ruu.nl (Harm Hanemaayer) et al. +Maintained-by: Matan Ziv-Av +Primary-site: sunsite.unc.edu /pub/Linux/libs/graphics +Alternate-site: +Platform: Linux/Intel (too many vgacards to list here); +Copying-policy: Freely distributable. +End diff --git a/threeDKit/0-CHANGES b/threeDKit/0-CHANGES new file mode 100644 index 0000000..d4285fe --- /dev/null +++ b/threeDKit/0-CHANGES @@ -0,0 +1,35 @@ +v1.3 + + (2 June 1997) Reorganised triangle code. Triangle code + now works with any bpp. + +v1.2 + + (1 feb 1996) Added surface wrapping demo. + added swtriangle + +v1.1 + + (Jan 1996) Added wtriangle routine to draw from bitmap. + added striangle. + +v1.0 + + (Jan 1996) Plane demo fully working in all 256c modes. + 3dkit.c extensively rewritten with many more features. + triangle.c optimised to write to frame buffer directly. + +v0.9 + + (Jan 1996) Ported plane demo from DOS compiler to Linux. + triangle.c written to replace 8088 assembly code. + +Prior to 0.9: + + (1994) Created plane demo with page flipping. + + (+-1993) 3dkit written in C for DOS. Triangle and line drawing + routines written in assembly language in 320x400x256. + + + diff --git a/threeDKit/0-COPYING b/threeDKit/0-COPYING new file mode 100644 index 0000000..161a3d1 --- /dev/null +++ b/threeDKit/0-COPYING @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/threeDKit/0-README b/threeDKit/0-README new file mode 100644 index 0000000..ff06a91 --- /dev/null +++ b/threeDKit/0-README @@ -0,0 +1,58 @@ +This is version 1.3 of 3DKIT, a super fast on-the-fly rendering library for +living 3D animation, written in C by Paul Sheer. + +The 3DKIT library is free software. See the file 0-COPYING for copying +permission. + +The library consists of the following files: + + 3dinit.h + 3dinit.c + 3dkit.h + 3dkit.c + wrapsurf.c + triangle.h + striangle.c + swtriangle.c + triangle.c + wtriangle.c + trisetpixel.c + tri.c + triangl.c + quickmath.c + quickmath.h + +For demonstration, two additional programs are included: + + planukit.c: + A greyscale-shaded rendered-on-the-fly turbo-prop that you can rotate + and scale however you like. + + wrapdemo.c: + Demonstrates surface wrapping of bitmaps in a similar fashion. + +For details, please read the manual pages: + man 6 planukit + man 6 wrapdemo + man 3 triangle + man 3 striangle + man 3 wtriangle + man 3 swtriangle + man 3 trisetcolorlookup + man 3 trigetcolorlookup + man 3 trisetdrawpoint + man 7 threedkit + +CONTACTING THE AUTHOR +--------------------- + +email: psheer@icon.co.za + +paper mail: P O BOX 890507 + Lyndhurst + Johannesburg 2106 + South Africa + +Donations (by check or postal order) will be appreciated and will encourage +further development of this software. However this is strictly on a voluntary +basis where this software falls under the GNU LIBRARY GENERAL PUBLIC LICENSE. diff --git a/threeDKit/3dinit.c b/threeDKit/3dinit.c new file mode 100644 index 0000000..2caeac0 --- /dev/null +++ b/threeDKit/3dinit.c @@ -0,0 +1,334 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + + +/* + +File: 3dinit.c + +Contains the utility function initcolor for initialising the normal color +vectors of a surface, and the a function to initialise a 3D ellipse. + + +This file is incomplete and should contain a number of useful +tools to initialise different 3D primitives. + +*/ + + + +#include +#include +#include +#include + +#ifndef DO_NOT_USE_VGALIB +#include +#endif + +#include +#include "./3dkit.h" +#include "./3dinit.h" + + +double mag (Vec v) +{ + double r; + if ((r = sqrt (v.x * v.x + v.y * v.y + v.z * v.z)) == 0) + return 1; + return r; +} + + +/* adds the normal vector to v at point (i,j), calculated from the + panel d. d is one of the four panels at (i,j). + i +--> + +0|3 | +-+- | j +1|2 v + +*/ + + +void norm_vec (TD_Surface * surf, int i, int j, Vec * v, int d) +{ + int i1 = 0, i2 = 0, j1 = 0, j2 = 0, w = surf->w; + double x, y, z, r; + double x1, y1, z1; + double x2, y2, z2; + Vec u; + + switch (d & 3) { + case 0: + j1 = -1; + i2 = -1; + break; + case 1: + i1 = -1; + j2 = 1; + break; + case 2: + j1 = 1; + i2 = 1; + break; + case 3: + i1 = 1; + j2 = -1; + break; + } + + x = surf->point[i + j * w].x; + y = surf->point[i + j * w].y; + z = surf->point[i + j * w].z; + + x1 = surf->point[i + i1 + (j + j1) * w].x - x; + y1 = surf->point[i + i1 + (j + j1) * w].y - y; + z1 = surf->point[i + i1 + (j + j1) * w].z - z; + + x2 = surf->point[i + i2 + (j + j2) * w].x - x; + y2 = surf->point[i + i2 + (j + j2) * w].y - y; + z2 = surf->point[i + i2 + (j + j2) * w].z - z; + + u.x = y1 * z2 - z1 * y2; + u.y = z1 * x2 - x1 * z2; + u.z = x1 * y2 - y1 * x2; + + r = mag(u); + + v->x += u.x / r; + v->y += u.y / r; + v->z += u.z / r; + +} + +/*Following routine initialise a surface's normal vectors*/ +/*(FIXME: this doesn't work 100% at the edges, I think it + needs Frenet-Sneret (spelling?) formula) */ + +/* n gives the brightness of the surface and the direction of the normal. + normally +256 or -256 (can be less to give a darker surface) */ + +void TD_initcolor (TD_Surface * surf, int n) +{ + int i, j, k, w = surf->w, l = surf->l, m; + + double r, ru; + int w0, ww; + int l0, ll; + + Vec v, u; + + + if (w > 2) { + w0 = 1; + ww = w - 1; + } else { + w0 = 0; + ww = w; + } + + + if (l > 2) { + l0 = 1; + ll = l - 1; + } else { + l0 = 0; + ll = l; + } + + + for (j = 0; j < l; j++) + for (i = 0; i < w; i++) { + +/* normal at a point is the average of the four cross products + except at the edge points where the gradient of the normal near + the edge is considered as well */ + + v.x = v.y = v.z = 0; + u.x = u.y = u.z = 0; + m = 0; + + if (i == 0) { + m = 1; + if (j != 0) { + norm_vec (surf, i, j, &v, 3); + norm_vec (surf, w0, j, &u, 3); + } + if (j != (l - 1)) { + norm_vec (surf, i, j, &v, 2); + norm_vec (surf, w0, j, &u, 2); + } + } + if (i == (w - 1)) { + m = 1; + if (j != 0) { + norm_vec (surf, i, j, &v, 0); + norm_vec (surf, ww, j, &u, 0); + } + if (j != (l - 1)) { + norm_vec (surf, i, j, &v, 1); + norm_vec (surf, ww, j, &u, 1); + } + } + if (j == 0) { + m = 1; + if (i != 0) { + norm_vec (surf, i, j, &v, 1); + norm_vec (surf, i, l0, &u, 1); + } + if (i != (w - 1)) { + norm_vec (surf, i, j, &v, 2); + norm_vec (surf, i, l0, &u, 2); + } + } + if (j == (l - 1)) { + m = 1; + if (i != 0) { + norm_vec (surf, i, j, &v, 0); + norm_vec (surf, i, ll, &u, 0); + } + if (i != (w - 1)) { + norm_vec (surf, i, j, &v, 3); + norm_vec (surf, i, ll, &u, 3); + } + } + if (m) { + + r = mag (v); + ru = mag (u); + + v.x = (float) 3 * v.x / (2 * r) - u.x / (2 * ru); + v.y = (float) 3 * v.y / (2 * r) - u.y / (2 * ru); + v.z = (float) 3 * v.z / (2 * r) - u.z / (2 * ru); + + } else { + for (k = 0; k < 4; k++) + norm_vec (surf, i, j, &v, k); + + } + + r = mag (v); + + surf->point[i + j * w].dirx = (double) v.x * n / r; + surf->point[i + j * w].diry = (double) v.y * n / r; + surf->point[i + j * w].dirz = (double) v.z * n / r; + } + +} + + + +static inline void fxchg (double *a, double *b) +{ + double t = *a; + *a = *b; + *b = t; +} + + +void TD_initellipsoidpart (TD_Surface * surf, int x, int y, int z, + int a, int b, int c, int w, int dir, int col) +{ + int i, j; + Vec v; + float r; + surf->w = surf->l = 2 * w + 1; + + for (i = -w; i <= w; i++) + for (j = -w; j <= w; j++) { + v.x = (float) j / w; + v.y = (float) i / w; + v.z = 1; + + switch (dir) { + case 0: + v.z = -v.z; + fxchg (&v.x, &v.y); + break; + case 1: + v.y = -v.y; + fxchg (&v.x, &v.z); + break; + case 2: + v.z = -v.z; + fxchg (&v.x, &v.z); + break; + case 3: + v.y = -v.y; + fxchg (&v.y, &v.z); + break; + case 4: + v.z = -v.z; + fxchg (&v.y, &v.z); + break; + } + + r = mag (v); + v.x *= (float) a / r; + v.y *= (float) b / r; + v.z *= (float) c / r; + + surf->point[i + w + (j + w) * surf->w].x = v.x + x; + surf->point[i + w + (j + w) * surf->w].y = v.y + y; + surf->point[i + w + (j + w) * surf->w].z = v.z + z; + + v.x /= (float) a * a; /*normal vector*/ + v.y /= (float) b * b; + v.z /= (float) c * c; + + r = mag (v); + + surf->point[i + w + (j + w) * surf->w].dirx = (float) col * v.x / r; + surf->point[i + w + (j + w) * surf->w].diry = (float) col * v.y / r; + surf->point[i + w + (j + w) * surf->w].dirz = (float) col * v.z / r; + + } +} + + + +void TD_initellipsoid (TD_Surface * surf1, TD_Surface * surf2, TD_Surface * surf3, + TD_Surface * surf4, TD_Surface * surf5, TD_Surface * surf6, int x, + int y, int z, int a, int b, int c, int w, int col) +{ + TD_initellipsoidpart (surf1, x, y, z, a, b, c, w, 0, col); + TD_initellipsoidpart (surf2, x, y, z, a, b, c, w, 1, col); + TD_initellipsoidpart (surf3, x, y, z, a, b, c, w, 2, col); + TD_initellipsoidpart (surf4, x, y, z, a, b, c, w, 3, col); + TD_initellipsoidpart (surf5, x, y, z, a, b, c, w, 4, col); + TD_initellipsoidpart (surf6, x, y, z, a, b, c, w, 5, col); +} + + +void TD_initsellipsoid (TD_Solid *s, int n, int x, + int y, int z, int a, int b, int c, int w, int col) +{ + TD_initellipsoid(&s->surf[n], &s->surf[n+1], &s->surf[n+2], + &s->surf[n+3], &s->surf[n+4], &s->surf[n+5], x, y, z, + a, b, c, w, col); +} + + diff --git a/threeDKit/3dinit.h b/threeDKit/3dinit.h new file mode 100644 index 0000000..cd52631 --- /dev/null +++ b/threeDKit/3dinit.h @@ -0,0 +1,43 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + +/* + +File: 3dinit.h + +*/ + +#include "quickmath.h" + +void TD_initcolor (TD_Surface * surf, int n); + +void TD_initellipsoidpart (TD_Surface * surf, int x, int y, int z, + int a, int b, int c, int w, int dir, int col); +void TD_initellipsoid (TD_Surface * surf1, TD_Surface * surf2, TD_Surface * surf3, + TD_Surface * surf4, TD_Surface * surf5, TD_Surface * surf6, int x, + int y, int z, int a, int b, int c, int w, int col); +void TD_initsellipsoid (TD_Solid *s, int n, int x, + int y, int z, int a, int b, int c, int w, int col); + + diff --git a/threeDKit/3dkit.c b/threeDKit/3dkit.c new file mode 100644 index 0000000..94d2943 --- /dev/null +++ b/threeDKit/3dkit.c @@ -0,0 +1,670 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + + +/* + +File: 3dkit.c + +Comments or suggestions welcome. + +This 3D graphics tool prints an object in three dimensions on the screen. +The object must be made up of one or more surfaces passed in a structure. +The algorithm calculates the light intensity at each point and does a color +interpolation so that surfaces appear uniform with smooth colour +graduations. + +The TD_Object structure contains an array of surfaces comprising the object. +When printing, the surfaces are sorted from furthest to closest by +determining the distance from the eye point of their respective centres. +This removes hidden features. + +The points of a surface are assumed to form a contorted rectangular mesh +having a length and a width - the number of points along the longitudinal +edges and lateral edges respectively. Although the surfaces are restricted +to rectangles, they can be infinitely contorted into spheres, triangles +etc., possibly with a whole side compressed into a single point. +It is advisable however to make up complex surfaces out of several less +contorted surfaces so that the sorting routine can place the correct parts +of the surface in front of one another. A sphere for example can be +defined as eight surfaces, each a triangular octant. + +Besides defining each 3D coord point of each surface array, the user must +also define the unit normal at each point. so that shading can be calculated. +The function TD_initcolor may be called to do this for you. + +The surfaces are drawn on the screen using one of the following methods. +The integer surf.render determines the method. + +0 : Interpolated trangles are drawn with each rectangle outlined. +1 : A wire frame is drawn of the edges of the surface only. +2 : Interpolated triangles only. +3 : Mesh - each rectangle outlined only. + +The demo planukit.c demostrates usage in detail. + +This code represents a complete re-write of the previous version, which +I wrote when I was first learning C (an excuse). It is far more structured, +efficient and readable. An important additional feature is that the 3D +camera position can now be defined, so that this code can be used as a +VR tool. Hence an object can be displayed as an object at the screen +centre, or as a 3D world. (See plane.h for how to modify the demo). + + +*/ + + +#define TD_MULCONSTANT 4096 + +#include +#include +#include +#include +#include +#include "3dkit.h" + +#define max(x,y) (((x) > (y)) ? (x) : (y)) +#define min(x,y) (((x) < (y)) ? (x) : (y)) + + +/*global for holding a surface temporarily:*/ +TD_Short_Point *temp; + + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + +/* The optimisation comes from svgalib-1.2.9/gl/line.c: */ + +/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ +/* line.c Line drawing */ + +#ifdef __alpha__ + +static inline int muldiv64 (int m1, int m2, int d) +{ + return (int) m1 *(int) m2 / (int) d; +} + +#else + +#ifdef __i386__ + +/* We use the 32-bit to 64-bit multiply and 64-bit to 32-bit divide of the */ +/* 386 (which gcc doesn't know well enough) to efficiently perform integer */ +/* scaling without having to worry about overflows. */ + +static inline int muldiv64 (int m1, int m2, int d) +{ +/* int32 * int32 -> int64 / int32 -> int32 */ + int result; + int dummy; + __asm__ ( + "imull %%edx\n\t" + "idivl %4\n\t" + : "=a" (result), "=d"(dummy) /* out */ + : "0" (m1), "1" (m2), "g" (d) /* in */ + /***rjr***: "ax", "dx"*/ /* mod */ + ); + return result; +} + +#else + +static inline int muldiv64(int m1, int m2, int d) +{ + return (double) m1 * (double) m2 / ((double) d); +} + +#endif /* !__i386__ */ +#endif /* !__alpha__ */ + +#else + +#define muldiv64(a,b,c) ((int) ((double) a * (double) b / ((double) c))) + +#endif + +void TD_translate (TD_Solid * s, TD_Point * p, TD_Short_Point * scr) +{ +/* the following rotational transformation avoids floating point + calculations entirely */ + + if (s->option_flags & TDOPTION_32BIT_SURFACES) { +/* for super accuracy */ + double x = p->x + s->x_cam; + double y = p->y + s->y_cam; + double z = p->z + s->z_cam; + double yt = x * s->a21 + y * s->a22 + z * s->a23 + s->s_cam; + + if (yt < 1) { + scr->x = scr->y = 32767; + return; + } else { + double xt = x * s->a11 + y * s->a12 + z * s->a13; + double zt = x * s->a31 + y * s->a32 + z * s->a33; + scr->x = ((int) ((double) s->posx + xt * s->xscale / yt)) >> 16; + scr->y = ((int) ((double) s->posy - zt * s->yscale / yt)) >> 16; + return; + } + } else { + int x = p->x + s->x_cam; + int y = p->y + s->y_cam; + int z = p->z + s->z_cam; + int yt = x * s->a21 + y * s->a22 + z * s->a23 + s->s_cam; + +/*(FIXME:) There may be problems if yt overflows, this just checks if the point + is behind the cam: */ + if (yt < 1) { + scr->x = scr->y = 32767; /*line and triangle routines must + reject these values. */ + return; + } else { + int xt = x * s->a11 + y * s->a12 + z * s->a13; + int zt = x * s->a31 + y * s->a32 + z * s->a33; + scr->x = s->posx + muldiv64 (xt, s->xscale, yt); + scr->y = s->posy - muldiv64 (zt, s->yscale, yt); + return; + } + } +} + + + +int TD_finddistance (TD_Solid * s, TD_Point * p) +{ +/* the following rotational transformation avoids floating point + calculations entirely */ + + if (s->option_flags & TDOPTION_32BIT_SURFACES) { +/* for super accuracy */ + double x = p->x + s->x_cam; + double y = p->y + s->y_cam; + double z = p->z + s->z_cam; + return ((int) ((double) x * s->a21 + y * s->a22 + z * s->a23 + s->s_cam)) >> 16; + } else { + int x = p->x + s->x_cam; + int y = p->y + s->y_cam; + int z = p->z + s->z_cam; + return (x * s->a21 + y * s->a22 + z * s->a23 + s->s_cam); + } +} + + + +int TD_findcolor (TD_Solid * s, TD_Point * p, int which) +{ + int c, shadow = s->surf[which].shadow; + + /*this you can fool around with to get different shadowing effects. */ + /*c starts off as a signed 28 bit integer. Brightest = -2^28, darkest = +2^28 */ + + if (s->option_flags & TDOPTION_LIGHT_SOURCE_CAM) { +/* do product of translated normal vector with lighting vector: */ + c = ((p->dirx * s->a11 + p->diry * s->a12 + p->dirz * s->a13) * s->xlight + + (p->dirx * s->a21 + p->diry * s->a22 + p->dirz * s->a23) * s->ylight + + (p->dirx * s->a31 + p->diry * s->a32 + p->dirz * s->a33) * s->zlight); + c = (c >> 20) + 256; + } else { + c = p->dirx * s->xlight + + p->diry * s->ylight + + p->dirz * s->zlight; + c = (c >> 8) + 256; + } + + /*c now 9 bits */ + +/* + c = s->surf[which].maxcolor + - ((c * c) >> (16 - s->surf[which].depth_per_color)); +*/ + /*:responds quadratically to light or.*/ + + c = s->surf[which].maxcolor - (c >> (8 - s->surf[which].depth_per_color)); + + /*:responds linearly to light.*/ + + if (c < shadow) + return shadow; + else + return c; +} + + +void TD_calc_rotation_matrix (TD_Solid * s) +{ +/* This matrix comes from "Dynamics of Atmospheric Flight" by Bernard Etkin, + John Wiley & Sons, Inc., and is much easier to copy down than to + derive yourself. */ + + float tsi = s->alpha, theta = s->beta, phi = s->gamma; + + s->a22 = (float) TD_MULCONSTANT * (cos (theta) * cos (tsi)); + s->a21 = (float) TD_MULCONSTANT * (cos (theta) * sin (tsi)); + s->a23 = (float) TD_MULCONSTANT * (-sin (theta)); + + s->a12 = (float) TD_MULCONSTANT * (sin (phi) * sin (theta) * cos (tsi) - cos (phi) * sin (tsi)); + s->a11 = (float) TD_MULCONSTANT * (sin (phi) * sin (theta) * sin (tsi) + cos (phi) * cos (tsi)); + s->a13 = (float) TD_MULCONSTANT * (sin (phi) * cos (theta)); + + s->a32 = (float) TD_MULCONSTANT * (cos (phi) * sin (theta) * cos (tsi) + sin (phi) * sin (tsi)); + s->a31 = (float) TD_MULCONSTANT * (cos (phi) * sin (theta) * sin (tsi) - sin (phi) * cos (tsi)); + s->a33 = (float) TD_MULCONSTANT * (cos (phi) * cos (theta)); + +/* this is the classical rotations matrix of aerodynamics */ +/* + s->a11 = (float) TD_MULCONSTANT * (cos (s->alpha) * cos (s->gamma)); + s->a12 = (float) TD_MULCONSTANT * (cos (s->alpha) * sin (s->gamma)); + s->a13 = (float) TD_MULCONSTANT * (-sin (s->alpha)); + + s->a21 = (float) TD_MULCONSTANT * (sin (s->beta) * sin (s->alpha) * cos (s->gamma) - cos (s->beta) * sin (s->gamma)); + s->a22 = (float) TD_MULCONSTANT * (sin (s->beta) * sin (s->alpha) * sin (s->gamma) - cos (s->beta) * cos (s->gamma)); + s->a23 = (float) TD_MULCONSTANT * (sin (s->beta) * cos (s->alpha)); + + s->a31 = (float) TD_MULCONSTANT * (cos (s->beta) * sin (s->alpha) * cos (s->gamma) + sin (s->beta) * sin (s->gamma)); + s->a32 = (float) TD_MULCONSTANT * (cos (s->beta) * sin (s->alpha) * sin (s->gamma) + sin (s->beta) * cos (s->gamma)); + s->a33 = (float) TD_MULCONSTANT * (cos (s->beta) * cos (s->alpha)); +*/ + +/*results are 14 bit + sign integers*/ +} + + +void TD_drawwire (TD_Solid * s, int which) +{ + TD_Surface *surf = &s->surf[which]; + int w = surf->w; + int l = surf->l; + int i = 0, j = 0, c = surf->mesh_color; + void (*dl) (int, int, int, int, int) = s->draw_line; + + while (j < w - 1) + TD_translate (s, &surf->point[j++], &temp[i++]); + + while (j < (w * l - 1)) { + TD_translate (s, &surf->point[j], &temp[i++]); + j += w; + } + + while (j > w * (l - 1)) + TD_translate (s, &surf->point[j--], &temp[i++]); + + while (j >= 0) { + TD_translate (s, &surf->point[j], &temp[i++]); + j -= w; + } + + for (j = 0; j < i - 1; j++) { + (*dl) (temp[j].x, temp[j].y, temp[j + 1].x, temp[j + 1].y, c); + + } +} + + +void TD_drawmesh (TD_Solid * s, int which) +{ + TD_Surface *surf = &s->surf[which]; + int w = surf->w; + int l = surf->l; + int i = 0, j = 0, k = 0, c = surf->mesh_color; + void (*dl) (int, int, int, int, int) = s->draw_line; + + while (j < l * w) { + TD_translate (s, &surf->point[j], &temp[j]); + j++; + } + + for (j = 0; j < l - 1; j++, k++) { + for (i = 0; i < w - 1; i++, k++) { + (*dl) (temp[k + 1].x, temp[k + 1].y, temp[k].x, temp[k].y, c); + (*dl) (temp[k + w].x, temp[k + w].y, temp[k].x, temp[k].y, c); + } + (*dl) (temp[k + w].x, temp[k + w].y, temp[k].x, temp[k].y, c); + + } + + for (i = 0; i < w - 1; i++, k++) + (*dl) (temp[k + 1].x, temp[k + 1].y, temp[k].x, temp[k].y, c); + +} + + +void xchg (int *a, int *b) +{ + int t = *a; + *a = *b; + *b = t; +} + + +void TD_drawsurface (TD_Solid * s, int which) +{ + + TD_Surface *surf = &s->surf[which]; + int w = surf->w; + int l = surf->l; + int i = 0, j = 0, k = 0, c = surf->mesh_color; + void (*dl) (int, int, int, int, int) = s->draw_line; + void (*dt) (int, int, int, int, int, int, int, int, int, int) = s->draw_triangle; + void (*ds) (int, int, int, int, int, int, int, int) = s->draw_striangle; + int mesh; + int d1, d2, d3, d4, d; + int x1, y1, c1; + int x2, y2, c2; + int x3, y3, c3; + int x4, y4, c4; + int furthest, clockwise = 0; + TD_tridata tri; + + tri.bitmap1 = surf->bitmap1; + tri.bitmap2 = surf->bitmap2; + + if (s->option_flags & TDOPTION_ALL_SAME_RENDER) + mesh = (s->render == TD_MESH_AND_SOLID); + else + mesh = (surf->render == TD_MESH_AND_SOLID); + +/*distance of four corners (numbered clockwise): */ + d1 = TD_finddistance (s, &surf->point[0]); + d2 = TD_finddistance (s, &surf->point[w - 1]); + d3 = TD_finddistance (s, &surf->point[w * l - 1]); + d4 = TD_finddistance (s, &surf->point[w * (l - 1)]); + +/*find furthest point */ + furthest = 1; + + d = d1; + + if (d2 > d) { + furthest = 2; + d = d2; + } + if (d3 > d) { + furthest = 3; + d = d3; + } + if (d4 > d) + furthest = 4; + + +/*draw scanning from the furthest point to the second furthest point */ +/*there are eight possibilities: */ + + switch (furthest) { + case 1: + if (d2 > d4) { + clockwise = 0; + for (j = 0; j < l; j++) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 1; + for (j = 0; j < l; j++) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + + case 2: + if (d1 > d3) { + clockwise = 1; + for (j = 0; j < l; j++) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 0; + for (j = l - 1; j >= 0; j--) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + + case 3: + if (d4 > d2) { + clockwise = 0; + for (j = l - 1; j >= 0; j--) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 1; + for (j = l - 1; j >= 0; j--) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + + case 4: + if (d3 > d1) { + clockwise = 1; + for (j = l - 1; j >= 0; j--) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 0; + for (j = 0; j < l; j++) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + } + + if (!surf->backfacing) + clockwise = 2; + + for (k = 0, j = 0; j < l - 1; j++, k++) { + for (i = 0; i < w - 1; i++, k++) { + +/*define the grid square we are currently drawing: */ + x1 = temp[k].x; + y1 = temp[k].y; + c1 = temp[k].c; + + x2 = temp[k + 1].x; + y2 = temp[k + 1].y; + c2 = temp[k + 1].c; + + x3 = temp[k + w + 1].x; + y3 = temp[k + w + 1].y; + c3 = temp[k + w + 1].c; + + x4 = temp[k + w].x; + y4 = temp[k + w].y; + c4 = temp[k + w].c; + + /*draw with two triangles */ + + + + + if (furthest & 1) { /*draw with hypotenuse from point 1 to point 3 */ + if (s->option_flags & TDOPTION_FLAT_TRIANGLE) { + c1 = (c1 + c2 + c3 + c4) >> 2; + (*ds) (x1, y1, x2, y2, x3, y3, c1, clockwise); + (*ds) (x1, y1, x3, y3, x4, y4, c1, clockwise); + } else { + (*dt) (x1, y1, c1, x2, y2, c2, x3, y3, c3, clockwise); + (*dt) (x1, y1, c1, x3, y3, c3, x4, y4, c4, clockwise); + } + } else { /*draw with hypotenuse from point 2 to point 4 */ + if (s->option_flags & TDOPTION_FLAT_TRIANGLE) { + c1 = (c1 + c2 + c3 + c4) >> 2; + (*ds) (x1, y1, x2, y2, x4, y4, c1, clockwise); + (*ds) (x2, y2, x3, y3, x4, y4, c1, clockwise); + } else { + (*dt) (x1, y1, c1, x2, y2, c2, x4, y4, c4, clockwise); + (*dt) (x2, y2, c2, x3, y3, c3, x4, y4, c4, clockwise); + } + } + + if (mesh) { + (*dl) (x1, y1, x2, y2, c); + (*dl) (x1, y1, x4, y4, c); + } + } + if (mesh) + (*dl) (temp[k + w].x, temp[k + w].y, temp[k].x, temp[k].y, c); + } + + if (mesh) { + for (i = 0; i < w - 1; i++, k++) + (*dl) (temp[k + 1].x, temp[k + 1].y, temp[k].x, temp[k].y, c); + } +} + + +int compare (const void *vp, const void *vq) +{ + const int *p = vp; + const int *q = vq; + int diff = *p - *q; + return ((diff >= 0) ? ((diff > 0) ? -1 : 0) : +1); +} + +struct disttype { + int distance; + int number; +}; + + +void TD_draw_solid (TD_Solid * s) +{ + int n = s->num_surfaces, w, l, i, j, render, num_existing_surfaces; + int max = 0; + + struct disttype *sortarray = NULL; + temp = NULL; + + gl_trisetdrawpoint(s->draw_point); + + if ((sortarray = malloc (s->num_surfaces * sizeof (struct disttype))) == NULL) { + fprintf (stderr, "1. Error allocating memory.\n"); + goto fin; + } + if (s->option_flags & TDOPTION_INIT_ROTATION_MATRIX) + TD_calc_rotation_matrix (s); + + for (j = 0, i = 0; i < n; i++) { + if((s->surf[i].point)) { + sortarray[j++].number = i; + w = s->surf[i].w; + if (max < w) + max = w; + l = s->surf[i].l; /*find the largest surface */ + if (max < l) + max = l; + } + } + + num_existing_surfaces = j; + if(!num_existing_surfaces) goto fin; + + if (s->option_flags & TDOPTION_SORT_SURFACES) { + for (j = 0, i = 0; i < n; i++) { + if((s->surf[i].point)) { + sortarray[j++].distance = + TD_finddistance (s, &s->surf[i].point[s->surf[i].w / 2 + + s->surf[i].w * (s->surf[i].l / 2)]); + /*the distance of the middle point of the surface */ + } + } + qsort (sortarray, num_existing_surfaces, sizeof (struct disttype), compare); + } + + max++; + + if ((temp = malloc (max * max * sizeof (TD_Short_Point))) == NULL) { + fprintf (stderr, "2. Error allocating memory.\n"); + goto fin; + } + if (s->option_flags & TDOPTION_ROTATE_OBJECT) { + s->x_cam = 0; + s->y_cam = 0; + s->z_cam = 0; + s->s_cam = s->distance * TD_MULCONSTANT; + } else { + s->s_cam = 0; + } + + + for (i = 0; i < num_existing_surfaces; i++) { + if (s->option_flags & TDOPTION_ALL_SAME_RENDER) + render = s->render; + else + render = s->surf[sortarray[i].number].render; + + switch (render) { + case TD_SOLID: + case TD_MESH_AND_SOLID: + if ((long) s->surf[sortarray[i].number].bitmap1 + | (long) s->surf[sortarray[i].number].bitmap2) + TD_drawwrapsurface (s, sortarray[i].number); + else + TD_drawsurface (s, sortarray[i].number); + break; + case TD_EDGES_ONLY: + TD_drawwire (s, sortarray[i].number); + break; + case TD_MESH: + TD_drawmesh (s, sortarray[i].number); + break; + default: + TD_drawmesh (s, sortarray[i].number); + } + } + + fin: + + if(temp) + free (temp); + if(sortarray) + free (sortarray); + +} diff --git a/threeDKit/3dkit.h b/threeDKit/3dkit.h new file mode 100644 index 0000000..c18ac0d --- /dev/null +++ b/threeDKit/3dkit.h @@ -0,0 +1,193 @@ +/* + + 3DKIT version 1.2 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + + +/* + +File 3dkit.h + +*/ + +#ifndef THREEDKIT_H +#define THREEDKIT_H 1 + +#include "triangle.h" + +#define TD_DEFAULT_MAXCOLOR 63 +#define TD_DEFAULT_COLOR 0 +#define TD_DEFAULT_SHADOW 7 + +#define TD_MESH 1 +#define TD_MESH_AND_SOLID 2 +#define TD_SOLID 3 +#define TD_EDGES_ONLY 4 +#define TD_PI 3.14159 +#define TDOPTION_INIT_ROTATION_MATRIX 1 +#define TDOPTION_ALL_SAME_RENDER 2 +#define TDOPTION_SORT_SURFACES 4 + +/*Two ways to display the object: +1. Angles refer to camera view; camera position is specified + in x_cam, y_cam, z_cam. +2. Origin at screen centre; object s_cam away; angles refer to + rotation of object:*/ +#define TDOPTION_ROTATE_OBJECT 8 + +/* Tells that the surface data are signed 32 bit values. + otherwise ussumes 16 bit values. + This can be used to avoid working with cumbersome 32 bits + unless the surface arrays have some other use and need the + accuracy, eg. CAD. + If set, distance x_cam, y_cam and z_cam are also treated as 32 bit. + (32/16 bit has nothing to do with the code itself) */ +#define TDOPTION_32BIT_SURFACES 16 + +/* The light source is relative to the angle of the camera: */ +#define TDOPTION_LIGHT_SOURCE_CAM 32 +/* Otherwise it is fixed relative to the object. */ + +/*use flat triangle instead of interpolated triangles (slight speed increase)*/ +#define TDOPTION_FLAT_TRIANGLE 64 + +typedef struct { +int x; +int y; +int z; +int dirx; +int diry; +int dirz; +} TD_Point; + + +typedef struct { +int w; /*grid width and length*/ +int l; +int bitmapwidth; /*bitmap width and length*/ +int bitmaplength; +int maxcolor; /*There 256 colors divided into n scales. + maxcolor must point to the top of the scale you want + less a few for roundoff*/ +int shadow; /*must point to the bottom of the scale plus a few for roundoff + so that none of the previous scale is printed. */ +int depth_per_color; /*number of colors in a scale = depth_per_color ^ 2*/ +int mesh_color; /*color of mesh if mesh is drawn*/ +int render; /*how it must be rendered*/ +int backfacing; /*enable backfacing*/ +unsigned char *bitmap1; /*1 byte per pixel bitmap data: triangle front side*/ +unsigned char *bitmap2; /*1 byte per pixel bitmap data: triangle back side*/ +TD_Point *point; /*3D data and normals*/ +} TD_Surface; + + +typedef struct { +int num_surfaces; /*number of surfaces*/ + +TD_Surface *surf; /*array of surfaces*/ + +int a11, a12, a13; /*rotation matrix*/ +int a21, a22, a23; +int a31, a32, a33; + +float alpha, beta, gamma; /*eulerian rotation angles in radians*/ + +int xlight, ylight, zlight; /*lighting vector. Magnitude of this + vector must be less than 255*/ + +int xscale; /*determines the size of the object*/ +int yscale; + +int distance; /* distance of the camera from origin (always 16 bit)*/ + +int x_cam; /* position of the camera */ +int y_cam; +int z_cam; + +int s_cam; + +int posx; /*position of camera optical axis on screen*/ +int posy; + +int option_flags; + +int render; /*if option ALL_SAME_RENDER is set then all surfaces are rendered + using this var. Else render is checked on each surface.*/ + +void (*draw_point) (int, int, int); + +void (*draw_wtriangle) (int, int, int, int, int, \ + int, int, int, int, int, \ + int, int, int, int, int, \ + TD_tridata *); + +void (*draw_swtriangle) (int, int, int, int, \ + int, int, int, int, \ + int, int, int, int, int, \ + TD_tridata *); + +void (*draw_striangle) (int, int, int, int, int, int, int, int); +void (*draw_triangle) (int, int, int, int, int, int, int, int, int, int); +void (*draw_line) (int, int, int, int, int ); + +} TD_Solid; + + + +typedef struct { +int x; +int y; +int color; +} TD_temppoint; + + +/*used internally*/ +typedef struct { +int x, y, c, u, v; +} TD_Short_Point; + + +/*used internally*/ +void TD_translate (TD_Solid * s, TD_Point * p, TD_Short_Point * scr); +int TD_finddistance (TD_Solid * s, TD_Point * p); +int TD_findcolor (TD_Solid * s, TD_Point * p, int which); +void TD_calc_rotation_matrix (TD_Solid * s); +void TD_drawwire (TD_Solid * s, int which); +void TD_drawmesh (TD_Solid * s, int which); +void TD_drawsurface (TD_Solid * s, int which); +void TD_drawwrapsurface (TD_Solid * s, int which); + + +/*Draws a 3D solid object composed of a number of surfaces, with +hidden surface elimination*/ +void TD_draw_solid (TD_Solid * s); + +/*initialises the color normal vectors to a surface*/ +void TD_initcolor (TD_Surface * surf, int n); + + +#endif + + + + + diff --git a/threeDKit/3dtext.c b/threeDKit/3dtext.c new file mode 100644 index 0000000..2fc3347 --- /dev/null +++ b/threeDKit/3dtext.c @@ -0,0 +1,482 @@ +/* + Copyright (C) 1996, 1997 Paul Sheer + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* 3dtext */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "app_glob.c" +#include "coolwidget.h" +#include "widget3d.h" +#include "quickmath.h" +#include "dialog.h" + +/* + + this processes a text file into a 3d world + the text file contains the following commands seperated + by zero or more newlines. Charaacters after a # at the + beginning of a line are ignored. + + +# x, y, z, a, b, h, w, and c are floats. (x,y,z) is a vector. + +scale a +# specifies the absolute value of the maximum extent of the scene in 3D space +# (after offset has been subtracted (see next)). This must come first. + +offset x y z +# specifies the a vector that is to be subtracted from the given position of +# forthcoming object. Must also come before any drawing commands. + +cylinder x y z a b c r +# draws a cylinder beginning at (a,b,c) ending at (a,b,c)+(x,y,z) of radius r + +cappedcylinder x y z a b c r +# draws a cylinder beginning at (a,b,c) ending at (a,b,c)+(x,y,z) of radius r +# with closed ends. + +surface a b x y z x y z x y z ... x y z +# draws a surface of grid size a by b there must be a*b (x, y, z) points. + +trapezium x y z a b c u v w p q r +# draws a trapezium with one corner at (x,y,z) and the other three at (x,y,z)+(a,b,c) etc. + +pipe r a x y z x y z x y z x y z ... x y z +# draw a pipe with corners at (x,y,z) the pipe diameter is r and the corner radii are a +* the first (x,y,z) is the start the last is the finish. Points mus be more than 2a appart + +cappedpipe r a x y z x y z x y z x y z ... x y z +# same with closed ends + +rectangle a b c x y z +# rectangle with (height,width,depth) = (x,y,z), corner at (a,b,c) + +ellipse a b c x y z +# an ellipse with (height,width,depth) = (x,y,z), centre at (a,b,c) + +density a +# will set the density of the grid making up any of the specific surfaces above. +# can be called before each surface command. + +*/ + +/* globals: */ + +int GridDensity = 6; +double DimensionScale = 1; +Vec DimensionOffset = {0, 0, 0}; + +static inline void assignTD (TD_Point *p, Vec v) +{ + p->x = (double) (v.x + DimensionOffset.x) * DimensionScale; + p->y = (double) (v.y + DimensionOffset.y) * DimensionScale; + p->z = (double) (v.z + DimensionOffset.z) * DimensionScale; +} + + + + +static void third_cyl (double t, TD_Point * p, Vec A, Vec X, Vec r1, Vec r2, int g, double f) +{ + int i = 0; + double h; + double alpha = t; + Vec rv; + while (alpha < (2 * PI / 3 + t + 0.001)) { + for (h = 0; h <= 1; h += 0.5) { + rv = plus (plus (plus (times (r1, cos (alpha) * (1 + h * (f - 1))), times (r2, sin (alpha) * (1 + h * (f - 1)))), A), times (X, h)); + assignTD(&(p[i]), rv); + i++; + } + alpha += (2 * PI / 3) / g; + } +} + + + +void Cdraw3d_cone (const char *ident, double x, double y, double z, double a, double b, double c, double ra, double rb) +{ + int g = 4 * GridDensity / 3; + TD_Point *p = Cmalloc ((g + 1) * 3 * sizeof (TD_Point)); + Vec r1; + Vec r2; + Vec A, X; + double f = rb / ra; + A.x = a; + A.y = b; + A.z = c; + X.x = x; + X.y = y; + X.z = z; + + orth_vectors (X, &r1, &r2, ra); + + third_cyl (0, p, A, X, r1, r2, g, f); + Cinit_surf_points (ident, 3, g + 1, p); + third_cyl (2 * PI / 3, p, A, X, r1, r2, g, f); + Cinit_surf_points (ident, 3, g + 1, p); + third_cyl (4 * PI / 3, p, A, X, r1, r2, g, f); + Cinit_surf_points (ident, 3, g + 1, p); + + free (p); +} + + + + +void Cdraw3d_cylinder (const char *ident, double x, double y, double z, double a, double b, double c, double r) +{ + Cdraw3d_cone (ident, x, y, z, a, b, c, r, r); +} + + + +void Cdraw3d_roundplate (const char *ident, double x, double y, double z, double a, double b, double c, double r) +{ + TD_Point *p = Cmalloc ((GridDensity * 4 + 1) * 2 * sizeof (TD_Point)); + double alpha = 0; + Vec r1; + Vec r2; + Vec rv; + Vec A; + Vec X; + int i = 0; + A.x = a; + A.y = b; + A.z = c; + X.x = x; + X.y = y; + X.z = z; + + orth_vectors (X, &r1, &r2, r); + + while (alpha < (2 * PI + 0.001)) { + rv = plus (plus (times (r1, cos (alpha)), times (r2, sin (alpha))), A); + assignTD (&p[i], rv); + i++; + assignTD (&p[i], A); + i++; + alpha += (2 * PI) / (GridDensity * 4); + } + Cinit_surf_points (ident, 2, GridDensity * 4 + 1, p); + free (p); +} + + +void Cdraw3d_cappedcylinder (const char *ident, double x, double y, double z, double a, double b, double c, double r) +{ + Cdraw3d_cylinder (ident, x, y, z, a, b, c, r); + Cdraw3d_roundplate (ident, -x, -y, -z, a, b, c, r); + Cdraw3d_roundplate (ident, x, y, z, x + a, y + b, z + c, r); +} + + +void textformaterror (int line, const char *ident) +{ + Cerrordialog (CMain, 20, 20, " Compile text to 3D ", " A text format error was encounted at line %d,\nwhile trying to draw 3d item to widget %s.\n ", line, ident); +} + + +void Cdraw3d_scale (const char *ident, double a) +{ + DimensionScale = 32767 / a; +} + +void Cdraw3d_offset (const char *ident, double x, double y, double z) +{ + DimensionOffset.x = x; + DimensionOffset.y = y; + DimensionOffset.z = z; +} + +void Cdraw3d_density (const char *ident, double a) +{ + GridDensity = a; +} + +void draw3d_surface(const char *ident, int w, int h, Vec *v) +{ + int i; + TD_Point *p = Cmalloc (w * h * sizeof (TD_Point)); + for(i=0;i +#include +#include +#include "vga.h" +#include "vgagl.h" +#include "./3dkit.h" +#include "./plane.h" + +extern int DENS; +extern int DENS2; + +float rib[20][3] = + {{-29.7, 0, 0}, {-29.5, 1, 0}, {-29, 2, 0}, + {-28, 3, 0}, {-25, 5.3, 0}, {-20, 6.7, 0}, {-12, 8, 0}, + {1, 9, 0}, {19, 9, 0}, {39, 7.5, 0}, {59, 4.5, 0}, {82, 0, 0}}; + + +void initwing (TD_Surface * surf, int lsf, int usd, int half) +{ + int i, k; + float j; + int LSC = 110; + int widtth, length; + + surf->l = widtth = 12; + surf->w = length = DENS2 + 1; + + for (k = 0; k < length; k++) + for (i = 0; i < widtth; i++) { + j = k; + if (lsf * usd == -1) + j = length - k - 1; + j = j / 4 + (float) DENS2 *half / 4; + surf->point[i * length + k].x = (float) ((float) j / DENS2 * (SPAN / 2 - FRAD) + FRAD) * lsf * PL_METER; + surf->point[i * length + k].y = -(float) rib[i][0] / LSC * CHORD * (1 - (float) j / DENS2 * (1 - TAPER)) * PL_METER; + surf->point[i * length + k].z = ((float) rib[i][1] / LSC * CHORD * usd * (1 - (float) j / DENS2 * (1 - TAPER)) + / ((float) 1.5 - (float) usd / 2) - WH + (float) j / DENS2 * DIHEDRAL * SPAN / 2) * PL_METER; + } +} + + +void inittips (TD_Surface * surf, int lsf) +{ + int i, k, j, usd; + int LSC = 110; + int widtth, length; + + surf->l = widtth = 12; + surf->w = length = 2; + + for (j = 0, k = -1; k < 2; k += 2, j++) + for (i = 0; i < widtth; i++) { + usd = -k * lsf; + surf->point[i * length + j].x = (float) ((float) (SPAN / 2 - FRAD) + FRAD) * lsf * PL_METER; + surf->point[i * length + j].y = -(float) rib[i][0] / LSC * CHORD * (1 - (float) (1 - TAPER)) * PL_METER; + surf->point[i * length + j].z = ((float) rib[i][1] / LSC * CHORD * usd * (1 - (float) (1 - TAPER)) / + ((float) 1.5 - (float) usd / 2) - WH + (float) DIHEDRAL * SPAN / 2) * PL_METER; + } +} + +void initstab (TD_Surface * surf, int lsf, int usd) +{ + int i, j, k; + int LSC = 110; + int widtth, length; + + surf->l = widtth = 12; + surf->w = length = DENS2 + 1; + + for (k = 0; k < length; k++) + for (i = 0; i < widtth; i++) { + j = k; + if (lsf * usd == -1) + j = length - k - 1; + + surf->point[i * length + k].x = (float) j / DENS2 * TSPAN / 2 * lsf * PL_METER; + surf->point[i * length + k].y = (-(float) rib[i][0] / LSC * TCHORD * (1 - (float) j / DENS2 * (1 - TTAPER)) - FB - FD) * PL_METER; + surf->point[i * length + k].z = ((float) rib[i][1] / LSC * TCHORD * usd * (1 - (float) j / DENS2 * (1 - TTAPER)) / 2 + TAILHEIGHT + (float) j / DENS2 * TDIHEDRAL * TSPAN / 2) * PL_METER; + } +} + + +void initfin (TD_Surface * surf, int usd) +{ + int i, j, k; + int LSC = 110; + int widtth, length; + float locrad; + + surf->l = widtth = 12; + surf->w = length = DENS2 + 1; + + locrad = (sin ((float) M_PI / 2 * VCHORD / FD)) * FRAD; + + for (k = 0; k < length; k++) + for (i = 0; i < widtth; i++) { + j = k; + if (usd == 1) + j = length - k - 1; + + surf->point[i * length + k].x = ((float) rib[i][1] / LSC * VCHORD * usd * (1 - (float) j / DENS2 * (1 - VTAPER)) / 2) * PL_METER; + surf->point[i * length + k].y = (-(float) rib[i][0] / LSC * VCHORD * (1 - (float) j / DENS2 * (1 - VTAPER)) - FB - FD - (float) VCHORD / 2 * ((float) j / DENS2 - 1)) * PL_METER; + surf->point[i * length + k].z = ((float) j / DENS2 * (TAILHEIGHT - locrad) + locrad) * PL_METER; + } +} + + + +void initfus (TD_Surface * surf, float quart) +{ + int i, j; + int widtth, length; + float locrad; + + surf->w = widtth = surf->l = length = DENS + 1; + + for (j = length - 1; j >= 0; j--) + for (i = 0; i < widtth; i++) { + locrad = (sin ((float) M_PI / 2 * j / DENS + .02)) * FRAD; + surf->point[i + j * widtth].x = (float) cos ((float) i / DENS * M_PI / 2 + quart) * PL_METER * locrad; + surf->point[i + j * widtth].y = ((float) j / DENS * FD - FB - FD) * PL_METER; + surf->point[i + j * widtth].z = (float) sin ((float) i / DENS * M_PI / 2 + quart) * PL_METER * locrad; + } + +} + + +void initfus1 (TD_Surface * surf, float quart) +{ + int i, j; + int widtth, length; + float locrad; + + surf->w = widtth = surf->l = length = DENS + 1; + + for (j = length - 1; j >= 0; j--) + for (i = 0; i < widtth; i++) { + locrad = FRAD; + surf->point[i + j * widtth].x = (float) cos ((float) i / DENS * M_PI / 2 + quart) * PL_METER * locrad; + surf->point[i + j * widtth].y = ((float) j / DENS * (FA + FB) - FB) * PL_METER; + surf->point[i + j * widtth].z = (float) sin ((float) i / DENS * M_PI / 2 + quart) * PL_METER * locrad; + } +} + +void initfus2 (TD_Surface * surf, float quart) +{ + int i, j; + int widtth, length; + float locrad, ya, q; + + surf->w = widtth = surf->l = length = DENS + 1; + + + for (j = length - 1; j >= 0; j--) + for (i = 0; i < widtth; i++) { + ya = ((float) j / DENS * FC + FA); + locrad = (cos ((float) PRAT * j / DENS)) * FRAD; + q = (ya - FA) / FC * QM; + surf->point[i + j * widtth].x = ((float) cos ((float) i / DENS * M_PI / 2 + quart) * locrad) * PL_METER; + surf->point[i + j * widtth].y = ya * PL_METER; + surf->point[i + j * widtth].z = ((float) sin ((float) i / DENS * M_PI / 2 + quart) * locrad - q) * PL_METER; + } + +} + +void initfus3 (TD_Surface * surf, float quart) +{ + int i, j; + int widtth, length; + float ya, locrad, q; + + surf->w = widtth = surf->l = length = DENS + 1; + + for (j = length - 1; j >= 0; j--) + for (i = 0; i < widtth; i++) { + ya = ((float) j / DENS * FE + (float) FA + (float) FC); + locrad = (cos ((float) PRAT)) * FRAD * sqrt ((float) ((float) FE - ya + (float) FA + (float) FC + .01) / FE); + q = QM + (ya - FA - FC) / FE * QM2; + surf->point[i + j * widtth].x = ((float) cos ((float) i / DENS * M_PI / 2 + quart) * locrad) * PL_METER; + surf->point[i + j * widtth].y = ya * PL_METER; + surf->point[i + j * widtth].z = ((float) sin ((float) i / DENS * M_PI / 2 + quart) * locrad - q) * PL_METER; + } + +} + +void initnacelle (TD_Surface * surf, float quart, int lor) +{ + int i, j; + int widtth, length; + float xa, ya, za, locrad, q, nz, ny; + + surf->w = widtth = surf->l = length = DENS + 1; + + nz = (float) DIHEDRAL *PROPSPAN - WH + NACHEIGHT; + ny = (float) .27 *CHORD - (.27 * CHORD * PROPSPAN / SPAN / 2); + + for (j = length - 1; j >= 0; j--) + for (i = 0; i < widtth; i++) { + ya = ((float) j / DENS * NACLEN + ny); + locrad = (float) NACRAD *sqrt ((float) ((float) NACLEN + ny - ya + .01) / NACLEN); + q = 0; + xa = (float) cos ((float) i / DENS * M_PI / 2 + quart) * locrad; + surf->point[i + j * widtth].x = (xa + lor * PROPSPAN) * PL_METER; + surf->point[i + j * widtth].y = ya * PL_METER; + if (quart > 1.6) { + za = (float) sin ((float) i / DENS * M_PI / 2 + quart) * locrad * 2.5 - q; /*%%%%%%%%%% */ + } else { + za = (float) sin ((float) i / DENS * M_PI / 2 + quart) * locrad - q; /*%%%%%%%%%% */ + } + surf->point[i + j * widtth].z = (za + nz) * PL_METER; + + } + +} + + +void initnacelle2 (TD_Surface * surf, float quart, int lor) +{ + int i, j; + int widtth, length; + float xa, ya, za, locrad, q, nz, ny; + + surf->w = widtth = surf->l = length = DENS + 1; + + nz = (float) DIHEDRAL *PROPSPAN - WH + NACHEIGHT; + ny = (float) .27 *CHORD - (.27 * CHORD * PROPSPAN / SPAN / 2); + + for (j = 0; j < length; j++) + for (i = 0; i < widtth; i++) { + ya = ((float) -j / DENS * RNACLEN + ny); + locrad = (float) NACRAD *sqrt ((float) -((float) -RNACLEN + ny - ya - .01) / RNACLEN); + q = 0; + xa = (float) cos ((float) i / DENS * M_PI / 2 + quart) * locrad; + surf->point[i * length + j].x = (xa + lor * PROPSPAN) * PL_METER; + surf->point[i * length + j].y = ya * PL_METER; + za = (float) sin ((float) i / DENS * M_PI / 2 + quart) * locrad - q; + surf->point[i * length + j].z = (za + nz) * PL_METER; + } +} + + + + + + + + + + diff --git a/threeDKit/planukit.c b/threeDKit/planukit.c new file mode 100644 index 0000000..26dade0 --- /dev/null +++ b/threeDKit/planukit.c @@ -0,0 +1,644 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + 1996 Paul Sheer psheer@icon.co.za + + This file is an example program demonstrating the use of the + 3dkit library. It is not part of the library and is not copyright. + + The author takes no responsibility, for the results + of compilation, execution or other usage of this program. + +*/ + + +/* +File: planukit.c + +comments or suggestions welcome, send to: psheer@icon.co.za + +Demo of 3D graphics tool for drawing shaded 3D surfaces with a light source. +This demo sets up the surfaces (in a crude fashion) and the function +drawobject from 3dkit.c draws them at the specified angle of azimuth, +rotation and elevation. The surfaces are sorted from furthest to closest +and drawn from their furthest corner forward toward their second furthest +corner. So any object made up of reasonable surfaces will be drawn solid +with hidden surfaces properly removed. Backfaced triangles are not drawn +to improve speed. + +This demo draws a turbo-prop aeroplane (done originally for a 3rd year +aeronautical engineering design project). + +see the handle_key function below for what all the keys do. + +*/ + +#include +#include +#include /*for stderr */ +#include +#include + +#include +#include +#include "3dkit.h" +#include "3dinit.h" +#include "plane.h" + +#ifdef WORLD_VIEW + +#define PL_TDOPTION_ROTATE_OBJECT 0 +#define PL_TDOPTION_LIGHT_SOURCE_CAM 0 + +#else + +#define PL_TDOPTION_ROTATE_OBJECT TDOPTION_ROTATE_OBJECT + + /*Lighting vector follows camera: */ +#define PL_TDOPTION_LIGHT_SOURCE_CAM TDOPTION_LIGHT_SOURCE_CAM + +#endif + + +/*closer to 1.25 on my screen: */ +#define PL_SCREEN_ASPECT 1.333 + +/*Number of surfaces in ths plane */ +#ifdef WORLD_VIEW +#define PL_NUMSURFACES 62 +#else +#define PL_NUMSURFACES 52 +/*52 */ +#endif + +/*maximum width or length of a surface (for malloc) */ +#define PL_SURF_SIZE 20 + + + +/*globals used for initialisation of surfaces */ + +/*width and breadth of body surfaces (in grid points) */ +int DENS = 2; + +/*width of wing surfaces (in grid points). */ +int DENS2 = 2; + +/* length of wing surfaces is inherent in the following + made-up aerofoil: */ + + +int gmode; +int PL_screen_width; +int PL_screen_height; + + +/*A trivial example of how to initialise a surface: */ +void initplate (TD_Surface * surf, float xstart, float ystart, float zstart, float x, float y, int w, int l) +{ + int i, k, j; + +/*setup width and length */ + surf->w = w + 1; + surf->l = l + 1; + +/*initialise a 6 meter square plate with its centre at the origin */ + for (k = 0; k < w + 1; k++) + for (i = 0; i < l + 1; i++) { + j = l - i; + surf->point[i * (w + 1) + k].x = (float) PL_METER *(xstart + (float) x * k / w); + surf->point[i * (w + 1) + k].y = (float) PL_METER *(ystart + (float) y * j / l); + surf->point[i * (w + 1) + k].z = (float) PL_METER *zstart; + } +} + + +/*exchanges the x and y values of a surface, making y negative */ +/* This is a patch to get the coords aligned with flight-dynamic's + axes. */ +void xchgxy (TD_Surface * surf) +{ + int j; + int t; + + for (j = 0; j < surf->l * surf->w; j++) { + t = surf->point[j].x; + surf->point[j].x = surf->point[j].y; + surf->point[j].y = -t; + } +} + +/* +void gl_triangle (int x1, int y1, int z1, int x2, int y2, int z2, + int x3, int y3, int z3, int bf); +void gl_striangle (int x1, int y1, int x2, int y2, int x3, int y3, + int c, int bf); +*/ + +/*returns 0 on error */ +TD_Solid *PL_init_solid (void) +{ + TD_Solid *plane_demo; + int i; + int n = PL_NUMSURFACES; + + if ((plane_demo = malloc (sizeof (TD_Solid))) == NULL) + return 0; + memset (plane_demo, 0, sizeof (TD_Solid)); + + plane_demo->num_surfaces = n; + + if ((plane_demo->surf = calloc (n , sizeof (TD_Surface))) == NULL) + return 0; + + for (i = 0; i < n; i++) { + if ((plane_demo->surf[i].point + = malloc (PL_SURF_SIZE * PL_SURF_SIZE * sizeof (TD_Point))) == NULL) + return 0; + /* plane_demo->surf[i].render = TD_MESH_AND_SOLID; *//*can leave out and set option ALL_SAME_RENDER */ + plane_demo->surf[i].shadow = TD_DEFAULT_COLOR + TD_DEFAULT_SHADOW; + plane_demo->surf[i].maxcolor = TD_DEFAULT_COLOR + TD_DEFAULT_MAXCOLOR; + plane_demo->surf[i].mesh_color = 191; /*navy blue in from the palette set */ + plane_demo->surf[i].backfacing = 1; /*don't draw any of surface that faces away */ + plane_demo->surf[i].depth_per_color = 6; /*2^6 = 64 colors in the grey scale */ + } + + plane_demo->alpha = 0; /* begin all at zero (flight dynamics */ + plane_demo->beta = 0; /* says plane is level */ + plane_demo->gamma = 0; + + plane_demo->xlight = -147; /* lighting out of the screen,... */ + plane_demo->ylight = -147; /* ...to the right,... */ + plane_demo->zlight = 147; /* ...and from the top. */ + + plane_demo->distance = PL_METER * 35; /* distance of the camera from the */ + /* origin, PL_METER * meters. */ + +/*if PL_TDOPTION_ROTATE_OBJECT is set to zero then we need to + define the full camera position instead: */ + plane_demo->x_cam = PL_METER * 35; + plane_demo->y_cam = PL_METER * 0; + plane_demo->z_cam = PL_METER * 0; + +/* These two are scale factors for the screen: */ +/* xscale is now calculated so that the maximum volume (-2^15 to 2^15 or + -2^31 to 2^31) will just fit inside the screen width at this distance: */ + plane_demo->xscale = (int) plane_demo->distance * PL_screen_width / (32768 * 2); + plane_demo->yscale = (float) plane_demo->xscale * PL_SCREEN_ASPECT + * PL_screen_height / PL_screen_width; /*to get display aspect square */ + +/*The above gives an average (not to telescopic, and not to wide angle) view */ + +/*use any triangle or linedrawing routine: */ + plane_demo->draw_triangle = gl_triangle; + plane_demo->draw_striangle = gl_striangle; + plane_demo->draw_line = gl_line; + +/* very important to set TDOPTION_INIT_ROTATION_MATRIX if you don't + calculate the rotation matrix yourself. */ + + plane_demo->option_flags = TDOPTION_INIT_ROTATION_MATRIX + | TDOPTION_ALL_SAME_RENDER | TDOPTION_SORT_SURFACES + | PL_TDOPTION_ROTATE_OBJECT | PL_TDOPTION_LIGHT_SOURCE_CAM; + + plane_demo->render = TD_MESH_AND_SOLID; /*how we want to render it */ + + return plane_demo; +} + +void PL_init_surfaces (TD_Solid * plane) +{ + int i; + +/* To see what an example of the ellipsoid initialisation: */ +/* + TD_initsellipsoid (plane, 0, 0, 0, 0, + PL_METER * 8, PL_METER * 4, PL_METER * 4, 3); + for(i=0;i<6;i++) + TD_initcolor (&plane->surf[i], -256); + return; + */ + + for (i = 0; i < 4; i++) { + initfus (&plane->surf[i], i * TD_PI / 2); + } + + for (i = 0; i < 4; i++) { + initfus1 (&plane->surf[i + 4], i * TD_PI / 2); + } + + for (i = 0; i < 4; i++) { + initfus2 (&plane->surf[i + 8], i * TD_PI / 2); + } + + initwing (&plane->surf[12], 1, 1, 0); + initwing (&plane->surf[13], -1, 1, 0); + initwing (&plane->surf[14], 1, -1, 0); + initwing (&plane->surf[15], -1, -1, 0); + initwing (&plane->surf[16], 1, 1, 1); + initwing (&plane->surf[17], -1, 1, 1); + initwing (&plane->surf[18], 1, -1, 1); + initwing (&plane->surf[19], -1, -1, 1); + initwing (&plane->surf[20], 1, 1, 2); + initwing (&plane->surf[21], -1, 1, 2); + initwing (&plane->surf[22], 1, -1, 2); + initwing (&plane->surf[23], -1, -1, 2); + initwing (&plane->surf[24], 1, 1, 3); + initwing (&plane->surf[25], -1, 1, 3); + initwing (&plane->surf[26], 1, -1, 3); + initwing (&plane->surf[27], -1, -1, 3); + initstab (&plane->surf[28], 1, 1); + initstab (&plane->surf[29], -1, 1); + initstab (&plane->surf[30], 1, -1); + initstab (&plane->surf[31], -1, -1); + initfin (&plane->surf[32], 1); + initfin (&plane->surf[33], -1); + + for (i = 0; i < 4; i++) { + initfus3 (&plane->surf[i + 34], i * TD_PI / 2); + } + + for (i = 0; i < 4; i++) { + initnacelle (&plane->surf[i + 38], i * TD_PI / 2, -1); + } + + for (i = 0; i < 4; i++) { + initnacelle (&plane->surf[i + 42], i * TD_PI / 2, 1); + } + + for (i = 0; i < 2; i++) { + initnacelle2 (&plane->surf[i + 46], i * TD_PI / 2, -1); + } + + for (i = 0; i < 2; i++) { + initnacelle2 (&plane->surf[i + 48], i * TD_PI / 2, 1); + } + + inittips (&plane->surf[50], 1); + inittips (&plane->surf[51], -1); + +#ifdef WORLD_VIEW + for (i = 0; i < 10; i++) + initplate (&plane->surf[i + 52], -20 + (float) i * 4.44, -20, -3.5, 0.4, 40, 1, 10); +#endif + + for (i = 0; i < PL_NUMSURFACES; i++) { + xchgxy (&plane->surf[i]); + + TD_initcolor (&plane->surf[i], -256); + /*initialises the color vector (vector normal to each point) */ + } +} + + +/*returns 1 on error */ + +int PL_init_plane (TD_Solid ** plane) +{ + if (!(*plane = PL_init_solid ())) + return 1; + PL_init_surfaces (*plane); + return 0; +} + + +void PL_init_palette (void) +{ +/* Here the depth_per_color is 5 (for 64 colors). + 256 / 64 gives 4 colors so TD_Surface->color + can be 0, 64, 128, OR 192 */ + + int i; + unsigned char palette[768]; + + for (i = 0; i < 64; i++) { + palette[i * 3] = i; + palette[i * 3 + 1] = i; + palette[i * 3 + 2] = 16 + i / 2; + } + + for (i = 0; i < 64; i++) { + palette[(i + 64) * 3 + 0] = i; + palette[(i + 64) * 3 + 1] = 0; + palette[(i + 64) * 3 + 2] = 0; + } + + for (i = 0; i < 64; i++) { + palette[(i + 128) * 3 + 0] = 0; + palette[(i + 128) * 3 + 1] = i; + palette[(i + 128) * 3 + 2] = 0; + } + + for (i = 0; i < 64; i++) { + palette[(i + 192) * 3 + 0] = 0; + palette[(i + 192) * 3 + 1] = 0; + palette[(i + 192) * 3 + 2] = i; + } + + gl_setpalette (&palette); +} + + + + +/*returns 1 if exit key is pressed */ +int PL_handle_key (TD_Solid * plane) +{ + static float incr = 0.1047198; + int finished = 0; + int c; + +/*plane->gamma += incr; + plane->beta = -0.5; + plane->render = TD_SOLID; + return 0; *//*---> a screen saver*/ + + + switch (c = getchar ()) { + case 'q': + plane->alpha += incr; + break; + case 'a': + plane->alpha -= incr; + break; + case 'o': + plane->beta += incr; + break; + case 'p': + plane->beta -= incr; + break; + case 'z': + plane->gamma += incr; + break; + case 'x': + plane->gamma -= incr; + break; + case 't': + plane->z_cam += PL_METER; + break; + case 'v': + plane->z_cam -= PL_METER; + break; + case 'g': + plane->x_cam += PL_METER; + break; + case 'f': + plane->x_cam -= PL_METER; + break; + case 'w': + plane->distance += PL_METER; + plane->y_cam += PL_METER; + break; + case 's': + plane->distance -= PL_METER; + plane->y_cam -= PL_METER; + break; + case 'c': + finished = 1; + break; + case 'i': + plane->gamma = 0; + plane->alpha = 0; + plane->beta = 0; + break; + case ' ': + switch (plane->render) { + case TD_MESH: + plane->render = TD_MESH_AND_SOLID; + break; + case TD_MESH_AND_SOLID: + plane->render = TD_SOLID; + break; + case TD_SOLID: + plane->render = TD_EDGES_ONLY; + break; + case TD_EDGES_ONLY: + plane->render = TD_MESH; + break; + } + break; + case 'r': + if (plane->option_flags & TDOPTION_FLAT_TRIANGLE) + plane->option_flags &= 0xFFFFFFFF - TDOPTION_FLAT_TRIANGLE; + else + plane->option_flags |= TDOPTION_FLAT_TRIANGLE; + break; + case '1': + incr += .01047198; + break; + case '2': + incr -= .01047198; + break; + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + DENS = c - '2'; + PL_init_surfaces (plane); + } + + if (incr < 0) + incr = 0; + + return (finished); +} + + +/*WRITE-PAGE FLIPPING*/ + +/* + The following routines redirect the setpage functions to take advantage + of the vga memory: writing graphics functions to one half of the memory + while viewing + the other. This saves us a copyscreen, while costing the extra + time it takes to draw to vga memory instead of linear (i.e. the + virtual screen) memory. vga.c should have the minor modification + that would allow this to be done more simply. The following was the + only way that seemed to work without altering vga.c. We will + call the method "Write-page Flipping", as apposed to "Page Flipping" + where pages are flipped, but writing is done to a virtual screen + which is then copied to the vga memory not being viewed. Write-page + Flipping writes directly to the vga memory not being viewed. + + The method even works on my TVGA8900CL/D in 320x200 (though it's not + supposed to), and doesn't work in 640x480 (where it is supposed to) + so I have given both options at startup. Note that Write-page flipping + can only work on linear or paged modes (320x200, 640x480, 800x600, + 1024x768) since graphics functions to write directly to planar + modes are not supported by svgalib. +*/ + +GraphicsContext physcr, virscr; +int winflipping, vgawindow = 0; +int Startpage[2]; +int gmode, chipset; + +void PL_redraw (TD_Solid * plane) +{ + gl_clearscreen (64); + TD_draw_solid (plane); +} + + +void PL_cleanup (TD_Solid * plane) +{ +/*this function should free all allocated memory*/ + return; +} + + +void winpointto (int win) +{ + if (chipset == TVGA8900 && gmode == G320x200x256) { + /*trident has 4 bpp in this mode */ + vga_ext_set(VGA_EXT_PAGE_OFFSET, (Startpage[win] * 4) >> 16); + } else { + vga_ext_set(VGA_EXT_PAGE_OFFSET, Startpage[win] >> 16); + } + + vga_setpage (0); +} + + +void winview (int win) +{ + vga_waitretrace (); + vga_setdisplaystart (Startpage[win] * win); +} + +void winflip (void) +{ + winview (vgawindow); + vgawindow = 1 - vgawindow; + winpointto (vgawindow); +} + + +void PL_animate (TD_Solid * plane, void (*PL_redraw_callback) (TD_Solid *), + int (*PL_key_callback) (TD_Solid *)) +{ + do { + PL_redraw_callback (plane); + if(winflipping) { + winflip (); + } else { + gl_setscreenoffset( HEIGHT * WIDTH * currentcontext.flippage ); + gl_copyscreen (&physcr); + } + } while (!(int *) PL_key_callback (plane)); +} + +int pl_getchar (void) +{ + int c = 0; + while (c == 0 || c == '\n') { + c = vga_getkey (); + } + if (c >= 'a' && c <= 'z') + c += 'A' - 'a'; + return c; +} + + +int main (void) +{ + int mode[7] = + {5, 6, 7, 8, 10, 11, 12}; + int Winflipping[7] = + {1, 0, 0, 0, 1, 1, 1}; + int Winflippages[7] = + {65536, 0, 0, 0, 8 * 65536, 8 * 65536, 16 * 256}; + int c, c2; + vga_modeinfo *ginfo; + TD_Solid *plane; + +/* Note that in this demo, graphics are written to all modes as + virtual modes, so that the triangle routine optimisations will + operate all the time (see triangle.c). */ + + vga_init (); + if (!(vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_SET) & (1 << VGA_EXT_PAGE_OFFSET))) { + puts("You need at least svgalib 1.2.10 to run this program!\n"); + exit(1); + } + do { + printf ("\n256 color modes:\n\n1: 320x200\n2: 320x240\n3: 320x400\n"); + printf ("4: 360x480\n5: 640x480\n6: 800x600\n7: 1024x768\n"); + printf ("\nWhich? "); + c = pl_getchar () - '1'; + printf ("\n"); + } while (c < 0 || c > 6); + + printf("Want (W)rite-page flipping, normal (P)age flipping\n"); + printf("using copyscreen, or (N)o page flipping (W/F/N)\n"); + printf("(W is faster but may not work, N will always work\n"); + printf("but sometimes looks tacky) ?\n"); + + c2 = pl_getchar(); + + printf ("\n"); + + gmode = mode[c]; + winflipping = Winflipping[c]; + + if (!vga_hasmode (gmode)) { + fprintf (stderr, "Mode not available.\n"); + exit (-1); + } + + vga_setmode (gmode); + gl_setcontextvga (gmode); + + ginfo = vga_getmodeinfo (gmode); + + PL_screen_width = ginfo->width; + PL_screen_height = ginfo->height; + + if (PL_init_plane (&plane)) { + fprintf (stderr, "Unable to intialise data structures.\n"); + } + + plane->posx = PL_screen_width / 2; /*Where origin will be printed */ + plane->posy = PL_screen_height / 2; + + PL_init_palette (); + +/* to see what the palette looks like: */ +/* for(i=0;i<256;i++) gl_line(0,i,PL_screen_width,i,i); getchar(); */ + + + /* Allow write flipping + on 320x200 even though ginfo doesn't report more + than 64k of memory:*/ + if ((PL_screen_width * PL_screen_height * 2 > ginfo->maxpixels + && gmode != G320x200x256) || c2 != 'W') + winflipping = 0; + + if (winflipping) { + printf("Using Write-page Flipping.\n"); + Startpage[0] = 0; /*define pages offsets into memory*/ + Startpage[1] = Winflippages[c]; + + winflip (); + } else { + gl_getcontext (&physcr); + gl_setcontextvgavirtual (gmode); + gl_getcontext (&virscr); + if(c2 != 'N') { + if(gl_enablepageflipping (&physcr)) + printf("Using Page Flipping.\n"); + } + } + + gl_enableclipping (); + PL_animate (plane, PL_redraw, PL_handle_key); + + PL_cleanup (plane); + vga_setmode (TEXT); + return 0; +} diff --git a/threeDKit/quickmath.c b/threeDKit/quickmath.c new file mode 100644 index 0000000..5e68e83 --- /dev/null +++ b/threeDKit/quickmath.c @@ -0,0 +1,118 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + + +#include +#include "quickmath.h" + +inline double fsqr (double x) +{ + return x * x; +} + +inline int lsqr (int x) +{ + return (int) x * x; +} + +inline double fmax (double a, double b) +{ + return max(a, b); +} + +inline double fmin (double a, double b) +{ + return min(a, b); +} + +inline double fsgn (double a) +{ + return (a == 0.0 ? 0.0 : (a > 0.0 ? 1.0 : -1.0)); +} + +inline double dot (Vec a, Vec b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +Vec cross (Vec a, Vec b) +{ + Vec c; + c.x = a.y * b.z - a.z * b.y; + c.y = a.z * b.x - a.x * b.z; + c.z = a.x * b.y - a.y * b.x; + return c; +} + +Vec plus (Vec a, Vec b) +{ + Vec c; + c.x = a.x + b.x; + c.y = a.y + b.y; + c.z = a.z + b.z; + return c; +} + +Vec minus (Vec a, Vec b) +{ + Vec c; + c.x = a.x - b.x; + c.y = a.y - b.y; + c.z = a.z - b.z; + return c; +} + +Vec times (Vec a, double f) +{ + Vec c; + c.x = a.x * f; + c.y = a.y * f; + c.z = a.z * f; + return c; +} + +double norm (Vec a) +{ + return sqrt (sqr(a.x) + sqr(a.y) + sqr(a.z)); +} + +void orth_vectors(Vec X, Vec *r1, Vec *r2, double r) +{ + if (X.x == 0 && X.y == 0) { + r1->x = 1; + r1->y = 0; + r1->z = 0; + } else { + r1->x = X.y / sqrt (X.x * X.x + X.y * X.y); + r1->y = -X.x / sqrt (X.x * X.x + X.y * X.y); + r1->z = 0; + } + *r1 = times (*r1, r); /* r1 now has length r */ + + *r2 = cross (X, *r1); + *r2 = times (*r2, r / norm (*r2)); /* r2 now has length r */ + +/* r1 and r2 are now two vectors prependicular to each other and to (x,y,z) */ +} + diff --git a/threeDKit/quickmath.h b/threeDKit/quickmath.h new file mode 100644 index 0000000..c14b1b2 --- /dev/null +++ b/threeDKit/quickmath.h @@ -0,0 +1,155 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + +#ifndef QUICK_MATH_H +#define QUICK_MATH_H + +#if 0 +#ifndef SVGALIB +#include "../config.h" +#endif +#endif + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +typedef struct { + double x, y, z; +} Vec; + + +#define sqr(x) ((x)*(x)) + +#define fswap(a, b) \ +{ \ + double __t_var = (a); \ + (a) = (b); \ + (b) = __t_var; \ +} + + +#define swap(a, b) \ +{ \ + int __t_var = (a); \ + (a) = (b); \ + (b) = __t_var; \ +} + +#define max(x,y) (((x) > (y)) ? (x) : (y)) +#define min(x,y) (((x) < (y)) ? (x) : (y)) + +#ifndef __GNUC__ + +double fsqr (double x); +int lsqr (int x); +double fmax (double a, double b); +double fmin (double a, double b); +double fsgn (double a); +double dot (Vec a, Vec b); +Vec cross (Vec a, Vec b); +Vec plus (Vec a, Vec b); +Vec minus (Vec a, Vec b); +Vec times (Vec a, double f); +double norm (Vec a); + +#else + +extern inline double fsqr (double x) +{ + return x * x; +} + +extern inline int lsqr (int x) +{ + return (int) x *x; +} + +extern inline double fmax (double a, double b) +{ + return max (a, b); +} + +extern inline double fmin (double a, double b) +{ + return min (a, b); +} + +extern inline double fsgn (double a) +{ + return (a == 0.0 ? 0.0 : (a > 0.0 ? 1.0 : -1.0)); +} + +extern inline double dot (Vec a, Vec b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +extern inline Vec cross (Vec a, Vec b) +{ + Vec c; + c.x = a.y * b.z - a.z * b.y; + c.y = a.z * b.x - a.x * b.z; + c.z = a.x * b.y - a.y * b.x; + return c; +} + +extern inline Vec plus (Vec a, Vec b) +{ + Vec c; + c.x = a.x + b.x; + c.y = a.y + b.y; + c.z = a.z + b.z; + return c; +} + +extern inline Vec minus (Vec a, Vec b) +{ + Vec c; + c.x = a.x - b.x; + c.y = a.y - b.y; + c.z = a.z - b.z; + return c; +} + +extern inline Vec times (Vec a, double f) +{ + Vec c; + c.x = a.x * f; + c.y = a.y * f; + c.z = a.z * f; + return c; +} + +extern inline double norm (Vec a) +{ + return sqrt (sqr (a.x) + sqr (a.y) + sqr (a.z)); +} + +#endif + +void orth_vectors (Vec X, Vec * r1, Vec * r2, double r); + +#endif + diff --git a/threeDKit/striangle.c b/threeDKit/striangle.c new file mode 100644 index 0000000..bdefa89 --- /dev/null +++ b/threeDKit/striangle.c @@ -0,0 +1,3 @@ +#define SOLID +#include "triangl.c" + diff --git a/threeDKit/susannaRUBENS.bmp b/threeDKit/susannaRUBENS.bmp new file mode 100644 index 0000000..cddeb1c Binary files /dev/null and b/threeDKit/susannaRUBENS.bmp differ diff --git a/threeDKit/swtriangle.c b/threeDKit/swtriangle.c new file mode 100644 index 0000000..e306730 --- /dev/null +++ b/threeDKit/swtriangle.c @@ -0,0 +1,3 @@ +#define SOLID +#define WRAP +#include "triangl.c" diff --git a/threeDKit/tri.c b/threeDKit/tri.c new file mode 100644 index 0000000..4f467a2 --- /dev/null +++ b/threeDKit/tri.c @@ -0,0 +1,366 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + +#include + +#ifdef WRAP +#ifdef INTERP +void gl_wtriangle (int x0, int y0, int xd0, int yd0, int z0, + int x1, int y1, int xd1, int yd1, int z1, + int x2, int y2, int xd2, int yd2, int z2, + TD_tridata * tri) +#else +void gl_swtriangle (int x0, int y0, int xd0, int yd0, + int x1, int y1, int xd1, int yd1, + int x2, int y2, int xd2, int yd2, int z0, + TD_tridata * tri) +#endif +#else +#ifdef INTERP +void gl_triangle (int x0, int y0, int z0, + int x1, int y1, int z1, + int x2, int y2, int z2, int bf) +#else +void gl_striangle (int x0, int y0, + int x1, int y1, + int x2, int y2, int z0, int bf) +#endif +#endif +{ + void (*colhline_pos) (void); + void (*colhline_neg) (void); + + int dir; + int X; + + int nz; + int g0, g1h = 0, g1l = 0; +#ifdef INTERP + int c0; + int c_y; +#endif +#ifdef WRAP + int X0, Y0; + int bf = tri->bf; + int xd_y, yd_y; +#endif + + dir = 1; + +/*Max triangle size in the order of (2^31) >> SHLB)^(.5) : */ + + if ((nz = (x0 - x1) * (y0 - y2) - (y0 - y1) * (x0 - x2)) == 0) + return; /*the points are collinear. */ + +#ifdef INTERP + c_x = -(((y0 - y1) * (z0 - z2) - (z0 - z1) * (y0 - y2)) << SHLB) / nz; + c_y = -(((z0 - z1) * (x0 - x2) - (x0 - x1) * (z0 - z2)) << SHLB) / nz; +#endif + +#ifdef WRAP + xd_x = -(((y0 - y1) * (xd0 - xd2) - (xd0 - xd1) * (y0 - y2)) << SHLB) / nz; + xd_y = -(((xd0 - xd1) * (x0 - x2) - (x0 - x1) * (xd0 - xd2)) << SHLB) / nz; + + yd_x = -(((y0 - y1) * (yd0 - yd2) - (yd0 - yd1) * (y0 - y2)) << SHLB) / nz; + yd_y = -(((yd0 - yd1) * (x0 - x2) - (x0 - x1) * (yd0 - yd2)) << SHLB) / nz; +#endif + +#ifdef INTERP + if ((abs (c_x) > (6 << SHLB)) || (abs (c_y) > (6 << SHLB))) { + int tz0, tz1; + + /*so that high colour gradients don't screw up at the edges. */ + /*4 is the maximum gradient per pixel. */ + + c_x >>= 2; + c_y >>= 2; + tz0 = ((2 * z0 + z1 + z2) << SHLB) / 4; + tz1 = ((z0 + 2 * z1 + z2) << SHLB) / 4; + z2 = ((z0 + z1 + 2 * z2) << SHLB) / 4; + z0 = tz0; + z1 = tz1; + } else { + z0 <<= SHLB; + z1 <<= SHLB; + z2 <<= SHLB; + } +#endif + +/************** BOOLEAN LOGIC HERE ************/ +/* The following allows a triangle to have a different picture on either side */ +/* To print triangles that don't appear when viewed from behind use bf = 0|1 */ +/* To print triangles that appear with a different picture when viewed from */ +/* behind use bf = 2|3 */ + +#ifdef WRAP + dat = tri->bitmap1; + if (nz > 0) { /* nz is the cross product of the vectors of the two sides + it indicates whether the points were ordered clockwise + or anti-clockwise (you can find out which way by testing) */ + if (bf == 1) + return; + if (bf == 3) + dat = tri->bitmap1; + dir++; + } else { + if (!bf) + return; + if (bf == 2) + dat = tri->bitmap2; + } +#else + if (nz > 0) { + if (bf == 1) + return; + dir++; + } else { + if (!bf) + return; + } +#endif + +#define Xchg(a,b) {X=(a);(a)=(b);(b)=X;} + + if (y1 < y0) { + Xchg (y0, y1); + Xchg (x0, x1); +#ifdef INTERP + Xchg (z0, z1); +#endif +#ifdef WRAP + Xchg (xd0, xd1); + Xchg (yd0, yd1); +#endif + dir++; + } + if (y2 < y1) { + Xchg (y2, y1); + Xchg (x2, x1); +#ifdef INTERP + Xchg (z2, z1); +#endif +#ifdef WRAP + Xchg (xd2, xd1); + Xchg (yd2, yd1); +#endif + + dir++; + } + if (y1 < y0) { + Xchg (y0, y1); + Xchg (x0, x1); +#ifdef INTERP + Xchg (z0, z1); +#endif +#ifdef WRAP + Xchg (xd0, xd1); + Xchg (yd0, yd1); +#endif + dir++; + } + _color_lookup = color_lookup; +#ifdef INTERP + c0 = z0; +#else + if(BYTESPERPIXEL == 1) { + c = z0; + } else { + c = _color_lookup[z0]; + } +#endif + +#ifdef WRAP + X0 = xd0 << SHLB; + Y0 = yd0 << SHLB; +#endif + + if (y2 == y0) + return; + g0 = ((int) (x2 - x0) << SHLB) / (y2 - y0); + if (y1 != y0) + g1h = ((int) (x1 - x0) << SHLB) / (y1 - y0); + if (y2 != y1) + g1l = ((int) (x2 - x1) << SHLB) / (y2 - y1); + + dir = dir & 1; + + +/* Very large triangles (larger than the screen) sometimes become a problem, + if so: */ + if (__clip) { + if (((abs (x0 - x1) + abs (x1 - x2) + abs (x0 - x2)) > + ((__clipx2 - __clipx1) * 2)) || ((y2 - y0) > (__clipy2 - __clipy1))) + return; + if (y2 < __clipy1 || y0 > __clipy2 || + (x0 < __clipx1 && x1 < __clipx1 && x2 < __clipx1) || + (x0 > __clipx2 && x1 > __clipx2 && x2 > __clipx2)) + return; + } + dx0 = x0; + dy0 = y0; + + if(tri_drawpoint) { + _tri_drawpoint = tri_drawpoint; + colhline_pos = linefuncs[(7 * 2) + (BYTESPERPIXEL - 1) * 16]; + colhline_neg = linefuncs[(7 * 2) + (BYTESPERPIXEL - 1) * 16 + 1]; + } else { + _tri_drawpoint = gl_setpixel; + colhline_pos = linefuncs[(MODETYPE * 2) + (BYTESPERPIXEL - 1) * 16]; + colhline_neg = linefuncs[(MODETYPE * 2) + (BYTESPERPIXEL - 1) * 16 + 1]; + } + +#ifdef tri_set_color +#undef tri_set_color +#endif + + + +#ifdef WRAP +#ifdef INTERP +#define tri_set_color \ + xd = X0 + xd_x * px1 + xd_y * py; \ + yd = Y0 + yd_x * px1 + yd_y * py; \ + c = c0 + c_x * px1 + c_y * py; +#else +#define tri_set_color \ + xd = X0 + xd_x * px1 + xd_y * py; \ + yd = Y0 + yd_x * px1 + yd_y * py; +#endif +#else +#ifdef INTERP +#define tri_set_color \ + c = c0 + c_x * px1 + c_y * py; +#else +#define tri_set_color +#endif +#endif + + if (dir == 1) { + if (y1 != y0) { + py = 0; + if (x1 < x0) { + px1 = 0; + px2 = -((abs (g1h) >> 1)) >> SHLB; + } else { + px1 = ((abs (g0) >> 1)) >> SHLB; + px2 = 0; + } + tri_set_color; + + colhline_neg (); + if ((py = 1) < y1 - y0) + for (; py < y1 - y0; py++) { + px1 = ((g0 * py) + (abs (g0) >> 1)) >> SHLB; + px2 = ((g1h * py) - (abs (g1h) >> 1)) >> SHLB; + tri_set_color; + + colhline_neg (); + } + px1 = min (((g0 * py) + (abs (g0) >> 1)) >> SHLB, max (x2, x0) - x0); + px2 = x1 - x0; + tri_set_color; + colhline_neg (); + } else { + py = 0; + px1 = 0; + px2 = x1 - x0; + tri_set_color; + + colhline_neg (); + } + if (y1 != y2) { + if ((py = y1 - y0 + 1) < y2 - y0) + for (; py < y2 - y0; py++) { + px1 = ((g0 * py) + (abs (g0) >> 1)) >> SHLB; + px2 = (((g1l * (py - y1 + y0)) - (abs (g1l) >> 1)) >> SHLB) + x1 - x0; + tri_set_color; + + colhline_neg (); + } + if (x1 < x2) { + px1 = x2 - x0; + px2 = x2 - x0 - ((abs (g1l) >> 1) >> SHLB); + } else { + px1 = x2 - x0 + ((abs (g0) >> 1) >> SHLB); + px2 = x2 - x0; + } + tri_set_color; + + colhline_neg (); + } + } else { + if (y1 != y0) { + py = 0; + if (x1 > x0) { + px1 = 0; + px2 = ((abs (g1h) >> 1)) >> SHLB; + } else { + px1 = -((abs (g0) >> 1)) >> SHLB; + px2 = 0; + } + tri_set_color; + + colhline_pos (); + if ((py = 1) < y1 - y0) + for (; py < y1 - y0; py++) { + px1 = ((g0 * py) - (abs (g0) >> 1)) >> SHLB; + px2 = ((g1h * py) + (abs (g1h) >> 1)) >> SHLB; + tri_set_color; + + colhline_pos (); + } + px1 = max (((g0 * py) - (abs (g0) >> 1)) >> SHLB, min (x2, x0) - x0); + px2 = x1 - x0; + tri_set_color; + colhline_pos (); + } else { + py = 0; + px1 = 0; + px2 = x1 - x0; + tri_set_color; + colhline_pos (); + } + if (y1 != y2) { + if ((py = y1 - y0 + 1) < y2 - y0) + for (; py < y2 - y0; py++) { + px1 = ((g0 * py) - (abs (g0) >> 1)) >> SHLB; + px2 = (((g1l * (py - y1 + y0)) + (abs (g1l) >> 1)) >> SHLB) + x1 - x0; + tri_set_color; + + colhline_pos (); + } + if (x1 > x2) { + px1 = x2 - x0; + px2 = x2 - x0 + ((abs (g1l) >> 1) >> SHLB); + } else { + px1 = x2 - x0 - ((abs (g0) >> 1) >> SHLB); + px2 = x2 - x0; + } + + tri_set_color; + + colhline_pos (); + } + } +} diff --git a/threeDKit/triangl.c b/threeDKit/triangl.c new file mode 100644 index 0000000..15da154 --- /dev/null +++ b/threeDKit/triangl.c @@ -0,0 +1,298 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + +#include + +#ifndef DO_NOT_USE_VGALIB +#include +#endif + +#include + + +#include "triangle.h" +#include + +#define SHLB 8 +#define SHC 0 +#ifdef WRAP +#define S_MASK 0x01ff00 +#endif + + +#ifdef byte +#undef byte +#endif +#define byte unsigned char + +#ifdef word +#undef word +#endif +#define word unsigned short + +#ifdef quad_t +#undef quad_t +#endif + +#ifdef INT_IS_16_BITS +#define quad_t unsigned long +#else +#define quad_t unsigned int +#endif + + +/* this assumes that BYTEWIDTH is not necessarily equal to bytes-per-pixel times WIDTH */ + +#define assignvpoffset8(x, y, vp) vp = (y) * BYTEWIDTH + (x); +#define assignvpoffset16(x, y, vp) vp = (y) * BYTEWIDTH + ((x) << 1); +#define assignvpoffset24(x, y, vp) vp = (y) * BYTEWIDTH + (x) * 3; +#define assignvpoffset32(x, y, vp) vp = (y) * BYTEWIDTH + ((x) << 2); + +#define declarevp8 byte *vpbyte = (byte *) VBUF +#define declarevp16 word *vpword = (word *) VBUF +#define declarevp24 byte *vpbyte = (byte *) VBUF +#define declarevp32 quad_t *vpquad = (quad_t *) VBUF + +#define assignvp8(x, y, vp) vpbyte = (byte *) VBUF + (y) * BYTEWIDTH + (x); +#define assignvp16(x, y, vp) vpword = (word *) ((byte *) VBUF + (y) * BYTEWIDTH) + (x); +#define assignvp24(x, y, vp) vpbyte = (byte *) VBUF + (y) * BYTEWIDTH + (x) * 3; +#define assignvp32(x, y, vp) vpquad = (quad_t *) ((byte *) VBUF + (y) * BYTEWIDTH) + (x); + +/* here we would like to have a single void pointer and cast it to byte, word or +quad_t, but ansi does not allow casts on LHS :( */ + +#define decvp8 *(--(vpbyte)) = lookup(color) +#define incvp8 *((vpbyte)++) = lookup(color) +#define decvp16 *(--(vpword)) = lookup(color) +#define incvp16 *((vpword)++) = lookup(color) +#define decvp24 *(--(vpbyte)) = lookup(color) >> 16; \ + *(--(vpbyte)) = lookup(color) >> 8; \ + *(--(vpbyte)) = lookup(color); +#define incvp24 *((vpbyte)++) = lookup(color); \ + *((vpbyte)++) = lookup(color) >> 8; \ + *((vpbyte)++) = lookup(color) >> 16; +#define decvp32 *(--(vpquad)) = lookup(color) +#define incvp32 *((vpquad)++) = lookup(color) + +#define decvpoffset8 \ + if (!offst--) \ + vga_setpage (--pg); \ + *(vpbyte + offst) = lookup(color); +#define incvpoffset8 \ + *(vpbyte + offst) = lookup(color); \ + if (!(++offst)) \ + vga_setpage (++pg); +#define decvpoffset16 \ + if (!offst) \ + vga_setpage (--pg); \ + offst -= 2; \ + *(vpword + offst) = lookup(color); +#define incvpoffset16 \ + *(vpword + offst) = lookup(color); \ + offst += 2; \ + if (!offst) \ + vga_setpage (++pg); +#define decvpoffset24 \ + if (!offst--) \ + vga_setpage (--pg); \ + *(vpbyte + offst) = lookup(color) >> 16; \ + if (!offst--) \ + vga_setpage (--pg); \ + *(vpbyte + offst) = lookup(color) >> 8; \ + if (!offst--) \ + vga_setpage (--pg); \ + *(vpbyte + offst) = lookup(color); +#define incvpoffset24 \ + *(vpbyte + offst) = lookup(color); \ + if (!(++offst)) \ + vga_setpage (++pg); \ + *(vpbyte + offst) = lookup(color) >> 8; \ + if (!(++offst)) \ + vga_setpage (++pg); \ + *(vpbyte + offst) = lookup(color) >> 16; \ + if (!(++offst)) \ + vga_setpage (++pg); +#define decvpoffset32 \ + if (!offst) \ + vga_setpage (--pg); \ + offst -= 4; \ + *(vpquad + offst) = lookup(color); +#define incvpoffset32 \ + *(vpquad + offst) = lookup(color); \ + offst += 4; \ + if (!offst) \ + vga_setpage (++pg); + + +static int px1, px2, py; +static int c; + +#ifdef INTERP +static int c_x; +#endif + +#ifdef WRAP +static int xd, xd_x, yd, yd_x; +static unsigned char *dat; +#endif + +static int dx0, dy0; + +#if defined(WRAP) && defined(INTERP) + +/* this must only occur once */ + +int color_lookup[TRIANGLE_COLOR_LOOKUP_TABLE_SIZE]; +static int *_color_lookup; + +void gl_trisetcolorlookup (int i, int c) +{ + if(i < TRIANGLE_COLOR_LOOKUP_TABLE_SIZE) + color_lookup[i] = c; +} + +int gl_trigetcolorlookup (int i) +{ + if(i < TRIANGLE_COLOR_LOOKUP_TABLE_SIZE) + return color_lookup[i]; + return 0; +} + +void (*tri_drawpoint) (int, int, int); +static void (*_tri_drawpoint) (int, int, int); + +void gl_trisetdrawpoint(void (*draw_point) (int, int, int)) +{ + tri_drawpoint = draw_point; +} + +#else + +extern int color_lookup[TRIANGLE_COLOR_LOOKUP_TABLE_SIZE]; +static int *_color_lookup; +extern void (*tri_drawpoint) (int, int, int); +static void (*_tri_drawpoint) (int, int, int); + +#endif /* this static is just because static is faster than ordinary array (so I hear) in DLL's */ + + +#define TRI_BPP 8 +#include "trisetpixel.c" + +#undef TRI_BPP +#define TRI_BPP 16 +#include "trisetpixel.c" + +#undef TRI_BPP +#define TRI_BPP 24 +#include "trisetpixel.c" + +#undef TRI_BPP +#define TRI_BPP 32 +#include "trisetpixel.c" + +#undef TRI_BPP + + +/* + #define CONTEXT_VIRTUAL 0x0 + #define CONTEXT_PAGED 0x1 + #define CONTEXT_LINEAR 0x2 + #define CONTEXT_MODEX 0x3 + #define CONTEXT_PLANAR16 0x4 + */ + +static void (*linefuncs[64]) (void) = +{ + colhline_pos_direct8, + colhline_neg_direct8, + colhline_pos_paged8, + colhline_neg_paged8, /*2 */ + colhline_pos_direct8, + colhline_neg_direct8, + colhline_pos_setpixel8, + colhline_neg_setpixel8, /*4 */ + colhline_pos_setpixel8, + colhline_neg_setpixel8, + colhline_pos_setpixel8, + colhline_neg_setpixel8, /*6 */ + colhline_pos_setpixel8, + colhline_neg_setpixel8, + colhline_pos_setpixel8, + colhline_neg_setpixel8, /*8 */ + + colhline_pos_direct16, + colhline_neg_direct16, + colhline_pos_paged16, + colhline_neg_paged16, /*2 */ + colhline_pos_direct16, + colhline_neg_direct16, + colhline_pos_setpixel16, + colhline_neg_setpixel16, /*4 */ + colhline_pos_setpixel16, + colhline_neg_setpixel16, + colhline_pos_setpixel16, + colhline_neg_setpixel16, /*6 */ + colhline_pos_setpixel16, + colhline_neg_setpixel16, + colhline_pos_setpixel16, + colhline_neg_setpixel16, /*8 */ + + colhline_pos_direct24, + colhline_neg_direct24, + colhline_pos_paged24, + colhline_neg_paged24, /*2 */ + colhline_pos_direct24, + colhline_neg_direct24, + colhline_pos_setpixel24, + colhline_neg_setpixel24, /*4 */ + colhline_pos_setpixel24, + colhline_neg_setpixel24, + colhline_pos_setpixel24, + colhline_neg_setpixel24, /*6 */ + colhline_pos_setpixel24, + colhline_neg_setpixel24, + colhline_pos_setpixel24, + colhline_neg_setpixel24, /*8 */ + + colhline_pos_direct32, + colhline_neg_direct32, + colhline_pos_paged32, + colhline_neg_paged32, /*2 */ + colhline_pos_direct32, + colhline_neg_direct32, + colhline_pos_setpixel32, + colhline_neg_setpixel32, /*4 */ + colhline_pos_setpixel32, + colhline_neg_setpixel32, + colhline_pos_setpixel32, + colhline_neg_setpixel32, /*6 */ + colhline_pos_setpixel32, + colhline_neg_setpixel32, + colhline_pos_setpixel32, + colhline_neg_setpixel32, /*8 */ +}; + + +#include "tri.c" diff --git a/threeDKit/triangle.c b/threeDKit/triangle.c new file mode 100644 index 0000000..51a4049 --- /dev/null +++ b/threeDKit/triangle.c @@ -0,0 +1,3 @@ +#define INTERP +#include "triangl.c" + diff --git a/threeDKit/triangle.h b/threeDKit/triangle.h new file mode 100644 index 0000000..5cf8b77 --- /dev/null +++ b/threeDKit/triangle.h @@ -0,0 +1,29 @@ + +#define max(x,y) (((x) > (y)) ? (x) : (y)) +#define min(x,y) (((x) < (y)) ? (x) : (y)) + +#define TRIANGLE_COLOR_LOOKUP_TABLE_SIZE 4096 + +/* triangle interpolation definitions: */ +typedef struct { + unsigned char *bitmap1; + unsigned char *bitmap2; + int bf; +} TD_tridata; + +void gl_triangle (int x0, int y0, int z0, int x1, int y1, int z1, int x2, int y2, int z2, int bf); +void gl_wtriangle (int x0, int y0, int xd0, int yd0, int z0, \ + int x1, int y1, int xd1, int yd1, int z1, \ + int x2, int y2, int xd2, int yd2, int z2, \ + TD_tridata * tri); /* This does not alter tri structure. */ +void gl_swtriangle (int x0, int y0, int xd0, int yd0, \ + int x1, int y1, int xd1, int yd1, \ + int x2, int y2, int xd2, int yd2, int c, \ + TD_tridata * tri); /* This does not alter tri structure. */ + +void gl_striangle (int x0, int y0, int x1, int y1, int x2, int y2, int color, int bf); + +void gl_trisetcolorlookup (int i, int c); +int gl_trigetcolorlookup (int i); + +void gl_trisetdrawpoint (void (setpixelfunc) (int, int, int)); diff --git a/threeDKit/trisetpixel.c b/threeDKit/trisetpixel.c new file mode 100644 index 0000000..f5ef462 --- /dev/null +++ b/threeDKit/trisetpixel.c @@ -0,0 +1,462 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + +#ifdef lookup +#undef lookup +#endif + +#if (TRI_BPP==8) || !defined(INTERP) +#define lookup(x) x +#else +#define lookup(x) _color_lookup[x] +#endif + + +#ifdef assignvp +#undef declarevp +#undef assignvp +#undef assignvpoffset +#undef incvp +#undef incvpoffset +#undef decvp +#undef decvpoffset +#endif + + +#if TRI_BPP==8 +#define declarevp declarevp8 +#define assignvp assignvp8 +#define assignvpoffset assignvpoffset8 +#define incvp incvp8 +#define incvpoffset incvpoffset8 +#define decvp decvp8 +#define decvpoffset decvpoffset8 +#endif +#if TRI_BPP==16 +#define declarevp declarevp16 +#define assignvp assignvp16 +#define assignvpoffset assignvpoffset16 +#define incvp incvp16 +#define incvpoffset incvpoffset16 +#define decvp decvp16 +#define decvpoffset decvpoffset16 +#endif +#if TRI_BPP==24 +#define declarevp declarevp24 +#define assignvp assignvp24 +#define assignvpoffset assignvpoffset24 +#define incvp incvp24 +#define incvpoffset incvpoffset24 +#define decvp decvp24 +#define decvpoffset decvpoffset24 +#endif +#if TRI_BPP==32 +#define declarevp declarevp32 +#define assignvp assignvp32 +#define assignvpoffset assignvpoffset32 +#define incvp incvp32 +#define incvpoffset incvpoffset32 +#define decvp decvp32 +#define decvpoffset decvpoffset32 +#endif + + +#ifdef color +#undef color +#endif + +#ifdef WRAP +#ifdef INTERP +#define color \ + (dat[(xd >> SHLB) + (yd & S_MASK)] + (c >> (SHLB + SHC))) +#else +#define color \ + (dat[(xd >> SHLB) + (yd & S_MASK)] + c) +#endif +#else +#ifdef INTERP +#define color \ + (c >> (SHLB + SHC)) +#else +#define color \ + c +#endif +#endif + + +/* these are actually all the same except for 8 */ +#if TRI_BPP==8 +static void colhline_neg_setpixel8 (void) +#endif +#if TRI_BPP==16 +static void colhline_neg_setpixel16 (void) +#endif +#if TRI_BPP==24 +static void colhline_neg_setpixel24 (void) +#endif +#if TRI_BPP==32 +static void colhline_neg_setpixel32 (void) +#endif +{ + int count, y = py + dy0, x1 = px1 + dx0, x2 = px2 + dx0; + if (__clip) { + if (y < __clipy1 || y > __clipy2) + return; + if (x1 > __clipx2 + 1) { +#ifdef WRAP + xd -= (x1 - __clipx2 - 1) * xd_x; + yd -= (x1 - __clipx2 - 1) * yd_x; +#endif +#ifdef INTERP + c -= (x1 - __clipx2 - 1) * c_x; +#endif + x1 = __clipx2 + 1; + } + if (x2 < __clipx1) { + x2 = __clipx1; + } + } + count = x1 - x2; + if (count > 0) { + do { + _tri_drawpoint (--x1, y, lookup(color)); +#ifdef WRAP + yd -= yd_x; + xd -= xd_x; +#endif +#ifdef INTERP + c -= c_x; +#endif + } while (--count); + } +} + + +#if TRI_BPP==8 +static void colhline_pos_setpixel8 (void) +#endif +#if TRI_BPP==16 +static void colhline_pos_setpixel16 (void) +#endif +#if TRI_BPP==24 +static void colhline_pos_setpixel24 (void) +#endif +#if TRI_BPP==32 +static void colhline_pos_setpixel32 (void) +#endif +{ + int count, y = py + dy0, x1 = px1 + dx0, x2 = px2 + dx0; + if (__clip) { + if (y < __clipy1 || y > __clipy2) + return; + if (x1 < __clipx1) { +#ifdef WRAP + xd += (__clipx1 - x1) * xd_x; + yd += (__clipx1 - x1) * yd_x; +#endif +#ifdef INTERP + c += (__clipx1 - x1) * c_x; +#endif + x1 = __clipx1; + } + if (x2 > __clipx2 + 1) { + x2 = __clipx2 + 1; + } + } + count = x2 - x1; + if (count > 0) { + do { + _tri_drawpoint (x1++, y, lookup(color)); +#ifdef WRAP + yd += yd_x; + xd += xd_x; +#endif +#ifdef INTERP + c += c_x; +#endif + } while (--count); + } +} + +#ifndef DO_NOT_USE_VGALIB +/*draw to 64k vga buffer setting vga page appropriately: */ + +#if TRI_BPP==8 +static void colhline_neg_paged8 (void) +#endif +#if TRI_BPP==16 +static void colhline_neg_paged16 (void) +#endif +#if TRI_BPP==24 +static void colhline_neg_paged24 (void) +#endif +#if TRI_BPP==32 +static void colhline_neg_paged32 (void) +#endif +{ + int count, y = py + dy0, x1 = px1 + dx0, x2 = px2 + dx0; + unsigned short offst; + int pg; + declarevp; + int vp = 0; + if (__clip) { + if (y < __clipy1 || y > __clipy2) + return; + + if (x1 > __clipx2 + 1) { +#ifdef WRAP + xd -= (x1 - __clipx2 - 1) * xd_x; + yd -= (x1 - __clipx2 - 1) * yd_x; +#endif +#ifdef INTERP + c -= (x1 - __clipx2 - 1) * c_x; +#endif + x1 = __clipx2 + 1; + } + if (x2 < __clipx1) { + x2 = __clipx1; + } + } + count = x1 - x2; + assignvpoffset (x1, y, vp); + pg = vp >> 16; + vga_setpage (pg); + offst = vp; + if (count > 0) { + do { + decvpoffset; +#ifdef WRAP + yd -= yd_x; + xd -= xd_x; +#endif +#ifdef INTERP + c -= c_x; +#endif + } while (--count); + } +} + + +#if TRI_BPP==8 +static void colhline_pos_paged8 (void) +#endif +#if TRI_BPP==16 +static void colhline_pos_paged16 (void) +#endif +#if TRI_BPP==24 +static void colhline_pos_paged24 (void) +#endif +#if TRI_BPP==32 +static void colhline_pos_paged32 (void) +#endif +{ + int count, y = py + dy0, x1 = px1 + dx0, x2 = px2 + dx0; + unsigned short offst; + int pg; + declarevp; + int vp = 0; + if (__clip) { + if (y < __clipy1 || y > __clipy2) + return; + + if (x1 < __clipx1) { +#ifdef WRAP + xd += (__clipx1 - x1) * xd_x; + yd += (__clipx1 - x1) * yd_x; +#endif +#ifdef INTERP + c += (__clipx1 - x1) * c_x; +#endif + x1 = __clipx1; + } + if (x2 > __clipx2 + 1) { + x2 = __clipx2 + 1; + } + } + count = x2 - x1; + assignvpoffset (x1, y, vp); + pg = vp >> 16; + vga_setpage (pg); + offst = vp; + if (count > 0) { + do { + incvpoffset; +#ifdef WRAP + yd += yd_x; + xd += xd_x; +#endif +#ifdef INTERP + c += c_x; +#endif + } while (--count); + } +} + + +#else + + +/*draw to 64k vga buffer setting vga page appropriately: */ + +#if TRI_BPP==8 +static void colhline_neg_paged8 (void) +#endif +#if TRI_BPP==16 +static void colhline_neg_paged16 (void) +#endif +#if TRI_BPP==24 +static void colhline_neg_paged24 (void) +#endif +#if TRI_BPP==32 +static void colhline_neg_paged32 (void) +#endif +{ +} + + +#if TRI_BPP==8 +static void colhline_pos_paged8 (void) +#endif +#if TRI_BPP==16 +static void colhline_pos_paged16 (void) +#endif +#if TRI_BPP==24 +static void colhline_pos_paged24 (void) +#endif +#if TRI_BPP==32 +static void colhline_pos_paged32 (void) +#endif +{ +} + + +#endif + +/*draw to a linear address space (320x200 or virtual screen): */ +#if TRI_BPP==8 +static void colhline_neg_direct8 (void) +#endif +#if TRI_BPP==16 +static void colhline_neg_direct16 (void) +#endif +#if TRI_BPP==24 +static void colhline_neg_direct24 (void) +#endif +#if TRI_BPP==32 +static void colhline_neg_direct32 (void) +#endif +{ + int count, y = py + dy0, x1 = px1 + dx0, x2 = px2 + dx0; + declarevp; + if (__clip) { + if (y < __clipy1 || y > __clipy2) + return; + if (x1 > __clipx2 + 1) { +#ifdef WRAP + xd -= (x1 - __clipx2 - 1) * xd_x; + yd -= (x1 - __clipx2 - 1) * yd_x; +#endif +#ifdef INTERP + c -= (x1 - __clipx2 - 1) * c_x; +#endif + x1 = __clipx2 + 1; + } + if (x2 < __clipx1) + x2 = __clipx1; + } + count = x1 - x2; + assignvp (x1, y, vp); + if (count > 0) { + do { + decvp; +#ifdef WRAP + yd -= yd_x; + xd -= xd_x; +#endif +#ifdef INTERP + c -= c_x; +#endif + } while (--count); + } +} + + +#if TRI_BPP==8 +static void colhline_pos_direct8 (void) +#endif +#if TRI_BPP==16 +static void colhline_pos_direct16 (void) +#endif +#if TRI_BPP==24 +static void colhline_pos_direct24 (void) +#endif +#if TRI_BPP==32 +static void colhline_pos_direct32 (void) +#endif +{ + int count, y = py + dy0, x1 = px1 + dx0, x2 = px2 + dx0; + declarevp; + if (__clip) { + if (y < __clipy1 || y > __clipy2) + return; + if (x1 < __clipx1) { +#ifdef WRAP + xd += (__clipx1 - x1) * xd_x; + yd += (__clipx1 - x1) * yd_x; +#endif +#ifdef INTERP + c += (__clipx1 - x1) * c_x; +#endif + x1 = __clipx1; + } + if (x2 > __clipx2 + 1) + x2 = __clipx2 + 1; + } + count = x2 - x1; + assignvp (x1, y, vp); + if (count > 0) { + do { + incvp; +#ifdef WRAP + yd += yd_x; + xd += xd_x; +#endif +#ifdef INTERP + c += c_x; +#endif + } while (--count); + } +} + +/*The following have not yet been implemented */ + +/* Draws to planar 256 (these could be complicated) */ +/*static void colhline_neg_planar (void); +static void colhline_pos_planar (void);*/ + +/* Draws using accelerated */ +/*static void colhline_neg_accel (void); +static void colhline_pos_accel (void);*/ + + diff --git a/threeDKit/wrapdemo.c b/threeDKit/wrapdemo.c new file mode 100644 index 0000000..0890979 --- /dev/null +++ b/threeDKit/wrapdemo.c @@ -0,0 +1,630 @@ +/* + + 3DKIT version 1.3 + High speed 3D graphics and rendering library for Linux. + + 1996 Paul Sheer psheer@icon.co.za + + This file is an example program demonstrating the use of the + 3dkit library. It is not part of the library and is not copyright. + + The author takes no responsibility, for the results + of compilation, execution or other usage of this program. +*/ + +/* + +File: wrapdemo.c + +comments or suggestions welcome. + +This program wraps a portrait by Rubens of Susanna Lunden (1622 to 1625) +around an ellipsoid. Because the ellipsoid is defined by six surfaces, +each with the same bitmap the pattern is repeated over the ellipse. + +*/ + +#include +#include +#include /*for stderr */ +#include + +#include +#include +#include "3dkit.h" +#include "3dinit.h" +#include "wrapdemo.h" + +#ifdef WORLD_VIEW + +#define EL_TDOPTION_ROTATE_OBJECT 0 +#define EL_TDOPTION_LIGHT_SOURCE_CAM 0 + +#else + +#define EL_TDOPTION_ROTATE_OBJECT TDOPTION_ROTATE_OBJECT + + /*Lighting vector follows camera: */ +#define EL_TDOPTION_LIGHT_SOURCE_CAM TDOPTION_LIGHT_SOURCE_CAM + +#endif + + +/*closer to 1.25 on my screen: */ +#define EL_SCREEN_ASPECT 1.333 + +/*Number of surfaces in ths ellip */ +#define EL_NUMSURFACES 6 + +/*maximum width or length of a surface (for malloc) */ +#define EL_SURF_SIZE 20 + + + +/*globals used for initialisation of surfaces */ +unsigned char *susanna; + +/*width and breadth of body surfaces (in grid points) */ +int DENS = 2; + +/*width of wing surfaces (in grid points). */ +int DENS2 = 2; + +/* length of wing surfaces is inherent in the following + made-up aerofoil: */ + + +int gmode; +int EL_screen_width; +int EL_screen_height; + + +/*A trivial example of how to initialise a surface: */ +void initplate (TD_Surface * surf, float xstart, float ystart, float zstart, float x, float y, int w, int l) +{ + int i, k, j; + +/*setup width and length */ + surf->w = w + 1; + surf->l = l + 1; + +/*initialise a 6 meter square plate with its centre at the origin */ + for (k = 0; k < w + 1; k++) + for (i = 0; i < l + 1; i++) { + j = l - i; + surf->point[i * (w + 1) + k].x = (float) EL_METER *(xstart + (float) x * k / w); + surf->point[i * (w + 1) + k].y = (float) EL_METER *(ystart + (float) y * j / l); + surf->point[i * (w + 1) + k].z = (float) EL_METER *zstart; + } +} + + +/*exchanges the x and y values of a surface, making y negative */ +/* This is a patch to get the coords aligned with flight-dynamic's + axes. */ +void xchgxy (TD_Surface * surf) +{ + int j; + int t; + + for (j = 0; j < surf->l * surf->w; j++) { + t = surf->point[j].x; + surf->point[j].x = surf->point[j].y; + surf->point[j].y = -t; + } +} + + +/*returns 0 on error */ +TD_Solid *EL_init_solid (void) +{ + TD_Solid *ellip_demo; + int i; + int n = EL_NUMSURFACES; + + if ((ellip_demo = malloc (sizeof (TD_Solid))) == NULL) + return 0; + + ellip_demo->num_surfaces = n; + + if ((ellip_demo->surf = malloc (n * sizeof (TD_Surface))) == NULL) + return 0; + + for (i = 0; i < n; i++) { + if ((ellip_demo->surf[i].point + = malloc (EL_SURF_SIZE * EL_SURF_SIZE * sizeof (TD_Point))) == NULL) + return 0; + /* ellip_demo->surf[i].render = TD_MESH_AND_SOLID; *//*can leave out and set option ALL_SAME_RENDER */ + ellip_demo->surf[i].shadow = 1; + ellip_demo->surf[i].maxcolor = 15; + ellip_demo->surf[i].mesh_color = 111; + ellip_demo->surf[i].backfacing = 1; + ellip_demo->surf[i].depth_per_color = 4; /*2^4 = 16 colors in + the grey scale */ + ellip_demo->surf[i].bitmap1 = susanna + 245 + 256 * 8; /*skip + header and an unsightly border*/ + ellip_demo->surf[i].bitmap2 = NULL; /*no bitmap on reverse + side of surface*/ + ellip_demo->surf[i].bitmapwidth = 244; /*skip border on sides*/ + ellip_demo->surf[i].bitmaplength = 352; /*and on bottom*/ + } + + ellip_demo->alpha = 0; /* begin all at zero (flight dynamics */ + ellip_demo->beta = 0; /* says plane is level */ + ellip_demo->gamma = 0; + + ellip_demo->xlight = -147; /* lighting out of the screen,... */ + ellip_demo->ylight = -147; /* ...to the right,... */ + ellip_demo->zlight = 147; /* ...and from the top. */ + + ellip_demo->distance = EL_METER * 35; /* distance of the camera from the */ + /* origin, EL_METER * meters. */ + +/*if EL_TDOPTION_ROTATE_OBJECT is set to zero then we need to + define the full camera position instead: */ + ellip_demo->x_cam = EL_METER * 35; + ellip_demo->y_cam = EL_METER * 0; + ellip_demo->z_cam = EL_METER * 0; + +/* These two are scale factors for the screen: */ +/* xscale is now calculated so that the maximum volume (-2^15 to 2^15 or + -2^31 to 2^31) will just fit inside the screen width at this distance: */ + ellip_demo->xscale = (int) ellip_demo->distance * EL_screen_width / (32768 * 2); + ellip_demo->yscale = (float) ellip_demo->xscale * EL_SCREEN_ASPECT + * EL_screen_height / EL_screen_width; /*to get display aspect square */ + +/*The above gives an average (not to telescopic, and not to wide angle) view */ + +/*use any triangle or linedrawing routine: */ + ellip_demo->draw_triangle = gl_triangle; + ellip_demo->draw_striangle = gl_striangle; + ellip_demo->draw_wtriangle = gl_wtriangle; + ellip_demo->draw_swtriangle = gl_swtriangle; + ellip_demo->draw_line = gl_line; + + ellip_demo->draw_point = gl_setpixel; +/* very important to set TDOPTION_INIT_ROTATION_MATRIX if you don't + calculate the rotation matrix yourself. */ + + ellip_demo->option_flags = TDOPTION_INIT_ROTATION_MATRIX + | TDOPTION_ALL_SAME_RENDER | TDOPTION_SORT_SURFACES + | EL_TDOPTION_ROTATE_OBJECT | EL_TDOPTION_LIGHT_SOURCE_CAM; + + ellip_demo->render = TD_MESH_AND_SOLID; /*how we want to render it */ + + return ellip_demo; +} + + + +void EL_init_surfaces (TD_Solid * ellip) +{ +/* To see what an example of the ellipsoid initialisation: */ + + TD_initsellipsoid (ellip, 0, 0, 0, 0, + EL_METER * 12, EL_METER * 8, EL_METER * 8, 6, -256); + +/* initplate (&ellip->surf[6], -10, -14.3, -10, 20, 28.7, 2, 3); + TD_initcolor (&ellip->surf[6], -256);*/ + + /*initialises the color vector (vector normal to each point) */ +} + + + +/*returns 1 on error */ + +int EL_init_ellip (TD_Solid ** ellip) +{ + if (!(*ellip = EL_init_solid ())) + return 1; + EL_init_surfaces (*ellip); + return 0; +} + + +void EL_init_palette2 (void) +{ +/* Here the depth_per_color is 5 (for 64 colors). + 256 / 64 gives 4 colors so TD_Surface->color + can be 0, 64, 128, OR 192 */ + + int i; + unsigned char palette[768]; + + for (i = 0; i < 64; i++) { + palette[i * 3] = i; + palette[i * 3 + 1] = i; + palette[i * 3 + 2] = 16 + i / 2; + } + + for (i = 0; i < 64; i++) { + palette[(i + 64) * 3 + 1] = i; + palette[(i + 64) * 3 + 2] = 0; + palette[(i + 64) * 3 + 3] = 0; + } + + for (i = 0; i < 64; i++) { + palette[(i + 128) * 3 + 1] = 0; + palette[(i + 128) * 3 + 2] = i; + palette[(i + 128) * 3 + 3] = 0; + } + + for (i = 0; i < 64; i++) { + palette[(i + 192) * 3 + 1] = 0; + palette[(i + 192) * 3 + 2] = 0; + palette[(i + 192) * 3 + 3] = i; + } + + gl_setpalette (&palette); +} + + + +void EL_init_palette (void) +{ + +/* Here the depth_per_color is 4 (for 16 colors). + 256 / 16 gives 16 colors so TD_Surface->color + can be 0, 16, 32, 48,... */ + + unsigned char pal16susanna[16][3] = + { + {40, 47, 47}, + {98, 96, 129}, + {114, 60, 59}, + {138, 143, 159}, + {70, 73, 71}, + {117, 105, 111}, + {142, 160, 195}, + {61, 58, 70}, + {145, 129, 137}, + {62, 54, 53}, + {166, 173, 219}, + {110, 83, 86}, + {160, 152, 161}, + {150, 115, 105}, + {83, 87, 90}, + {120, 124, 140} + }; + + unsigned char palette[768]; + + int i, j, k; + int max = 0; + + for (i = 0; i < 16; i++) + for (j = 0; j < 3; j++) + if (max < pal16susanna[i][j]) + max = pal16susanna[i][j]; + + for (i = 0; i < 16; i++) /*through all 16 susanna */ + for (j = 0; j < 16; j++) /*through all shades */ + for (k = 0; k < 3; k++) /*through red green and blue */ + palette[((i * 16) + j) * 3 + k] = + (int) pal16susanna[i][k] * ( (16 - (15 - j)*12/15 ) * 4 - 1) / max; + + gl_setpalette (&palette); +} + + + + +/*returns 1 if exit key is pressed */ +int EL_handle_key (TD_Solid * ellip) +{ + static float incr = 0.1047198; + int finished = 0; + int c; + +/*ellip->gamma += incr; + ellip->beta = -0.5; + ellip->render = TD_SOLID; + return 0; *//*---> a screen saver*/ + + + switch (c = getchar ()) { + case 'q': + ellip->alpha += incr; + break; + case 'a': + ellip->alpha -= incr; + break; + case 'o': + ellip->beta += incr; + break; + case 'p': + ellip->beta -= incr; + break; + case 'z': + ellip->gamma += incr; + break; + case 'x': + ellip->gamma -= incr; + break; + case 't': + ellip->z_cam += EL_METER; + break; + case 'v': + ellip->z_cam -= EL_METER; + break; + case 'g': + ellip->x_cam += EL_METER; + break; + case 'f': + ellip->x_cam -= EL_METER; + break; + case 'w': + ellip->distance += EL_METER; + ellip->y_cam += EL_METER; + break; + case 's': + ellip->distance -= EL_METER; + ellip->y_cam -= EL_METER; + break; + case 'c': + finished = 1; + break; + case 'i': + ellip->gamma = 0; + ellip->alpha = 0; + ellip->beta = 0; + break; + case ' ': + switch (ellip->render) { + case TD_MESH: + ellip->render = TD_MESH_AND_SOLID; + break; + case TD_MESH_AND_SOLID: + ellip->render = TD_SOLID; + break; + case TD_SOLID: + ellip->render = TD_EDGES_ONLY; + break; + case TD_EDGES_ONLY: + ellip->render = TD_MESH; + break; + } + break; + case 'r': + if (ellip->option_flags & TDOPTION_FLAT_TRIANGLE) + ellip->option_flags &= 0xFFFFFFFF - TDOPTION_FLAT_TRIANGLE; + else + ellip->option_flags |= TDOPTION_FLAT_TRIANGLE; + break; + case '1': + incr += .01047198; + break; + case '2': + incr -= .01047198; + break; + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + DENS = c - '2'; + EL_init_surfaces (ellip); + } + + if (incr < 0) + incr = 0; + + return (finished); +} + + +/*WRITE-PAGE FLIPPING*/ + +GraphicsContext physcr, virscr; +int winflipping, vgawindow = 0; +int Startpage[2]; +int gmode, chipset; + +void EL_redraw (TD_Solid * ellip) +{ + gl_clearscreen (0); + TD_draw_solid (ellip); +} + + +void EL_cleanup (TD_Solid * ellip) +{ +/*this function should free all allocated memory*/ + return; +} + + + +void winpointto (int win) +{ + if (chipset == TVGA8900 && gmode == G320x200x256) { + /*trident has 4 bpp in this mode */ + vga_ext_set(VGA_EXT_PAGE_OFFSET, (Startpage[win] * 4) >> 16); + } else { + vga_ext_set(VGA_EXT_PAGE_OFFSET, Startpage[win] >> 16); + } + + vga_setpage (0); +} + + +void winview (int win) +{ + vga_waitretrace(); + vga_setdisplaystart (Startpage[win] * win); +} + +void winflip (void) +{ + winview (vgawindow); + vgawindow = 1 - vgawindow; + winpointto (vgawindow); +} + + +void EL_animate (TD_Solid * ellip, void (*EL_redraw_callback) (TD_Solid *), + int (*EL_key_callback) (TD_Solid *)) +{ + do { + EL_redraw_callback (ellip); + if(winflipping) { + winflip (); + } else { + gl_setscreenoffset( HEIGHT * WIDTH * currentcontext.flippage ); + gl_copyscreen (&physcr); + } + } while (!(int *) EL_key_callback (ellip)); +} + +int el_getchar (void) +{ + int c = 0; + while (c == 0 || c == '\n') { + c = vga_getkey (); + } + if (c >= 'a' && c <= 'z') + c += 'A' - 'a'; + return c; +} + + +int main (void) +{ + int i; + int mode[7] = {5, 6, 7, 8, 10, 11, 12}; + int Winflipping[7] = {1, 0, 0, 0, 1, 1, 1}; + int Winflippages[7] = {65536, 0, 0, 0, 8 * 65536, 8 * 65536, 16 * 256}; + int c, c2; + vga_modeinfo *ginfo; + TD_Solid *ellip; + FILE *in; + +/* Call vga_init as early as possible to get rid of root priv when reading files. */ + + vga_init (); + if (!(vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_SET) & (1 << VGA_EXT_PAGE_OFFSET))) { + puts("You need at least svgalib 1.2.10 to run this program!\n"); + exit(1); + } + if((susanna = malloc(150000))==NULL) { + fprintf(stderr, "Error returned from malloc.\n"); + exit(1); + } + +/*susanna[109000] = 'A';*/ + + if ((in = fopen ("susannaRUBENS.bmp", "rb")) == NULL) { + fprintf (stderr, "Cannot open input file."); + exit (1); + } + + i = 0; + + while ((c = fgetc (in)) != EOF) { + +/*to prevent picture aliasing, use random():*/ + if(random() & 1) { + susanna[i++] = c & 0xf0; + susanna[i++] = (c >> 4) & 0x0f; + } else { + susanna[i++] = (c >> 4) & 0x0f; + susanna[i++] = c & 0xf0; + } + } + + fclose (in); + +/*printf("\n\n%d\n\n\n", susanna[109000]);*/ + + +/* Note that in this demo, graphics are written to all modes as + virtual modes, so that the triangle routine optimisations will + operate all the time (see triangle.c). */ + + do { + printf ("\n256 color modes:\n\n1: 320x200\n2: 320x240\n3: 320x400\n"); + printf ("4: 360x480\n5: 640x480\n6: 800x600\n7: 1024x768\n"); + printf ("\nWhich? "); + c = el_getchar () - '1'; + printf ("\n"); + } while (c < 0 || c > 6); + + printf("Want (W)rite-page flipping, normal (P)age flipping\n"); + printf("using copyscreen, or (N)o page flipping (W/F/N)\n"); + printf("(W is faster but may not work, N will always work\n"); + printf("but sometimes looks tacky) ?\n"); + + c2 = el_getchar(); + + printf ("\n"); + + gmode = mode[c]; + winflipping = Winflipping[c]; + + if (!vga_hasmode (gmode)) { + fprintf (stderr, "Mode not available.\n"); + exit (-1); + } + + vga_setmode (gmode); + gl_setcontextvga (gmode); + + ginfo = vga_getmodeinfo (gmode); + + EL_screen_width = ginfo->width; + EL_screen_height = ginfo->height; + + if (EL_init_ellip (&ellip)) { + fprintf (stderr, "Unable to intialise data structures.\n"); + } + + ellip->posx = EL_screen_width / 2; /*Where origin will be printed */ + ellip->posy = EL_screen_height / 2; + + EL_init_palette (); + +/* to see what the palette looks like: */ +/* for(i=0;i<256;i++) gl_line(0,i,EL_screen_width,i,i); el_getchar(); */ + +/*to see the bitmap*/ +/* +for (j = 0; j < (EL_screen_height < 416 ? EL_screen_height : 416); j++) + for (i = 0; i < 256; i++) + gl_setpixel (i, j, 15 + susanna[240 + i + (j << 8)]); +el_getchar (); +*/ + + /* My trident 8900CL/D will allow write flipping + on 320x200 even though ginfo doesn't report more + than 64k of memory:*/ + if ((EL_screen_width * EL_screen_height * 2 > ginfo->maxpixels + && gmode != G320x200x256) || c2 != 'W') + winflipping = 0; + + if (winflipping) { + printf("Using Write-page Flipping.\n"); + Startpage[0] = 0; /*define pages offsets into memory*/ + Startpage[1] = Winflippages[c]; + + winflip (); + } else { + gl_getcontext (&physcr); + gl_setcontextvgavirtual (gmode); + gl_getcontext (&virscr); + if(c2 != 'N') { + if(gl_enablepageflipping (&physcr)) + printf("Using Page Flipping.\n"); + } + } + + gl_enableclipping (); + + EL_animate (ellip, EL_redraw, EL_handle_key); + + EL_cleanup (ellip); + vga_setmode (TEXT); + return; +} diff --git a/threeDKit/wrapdemo.h b/threeDKit/wrapdemo.h new file mode 100644 index 0000000..c251b72 --- /dev/null +++ b/threeDKit/wrapdemo.h @@ -0,0 +1,30 @@ +/* + + 3DKIT version 1.2 + High speed 3D graphics and rendering library for Linux. + + 1996 Paul Sheer psheer@icon.co.za + + This file is an example program demonstrating the use of the + 3dkit library. It is not part of the library and is not copyright. + +*/ + +/* +File: wrapdemo.h +*/ + +/*choose method (see 3dkit.h for explanation)*/ +/*comment out for real world-like view:*/ +/*#define WORLD_VIEW 0*/ + +#ifdef WORLD_VIEW +#define EL_METER 1200 + /* In this demo EL_METER is about a meter + so the wing is 20 * 1200 = 24000 units across, + within the 65536 limit. */ +#else +#define EL_METER 2400 +#endif + + diff --git a/threeDKit/wrapsurf.c b/threeDKit/wrapsurf.c new file mode 100644 index 0000000..514e9d3 --- /dev/null +++ b/threeDKit/wrapsurf.c @@ -0,0 +1,315 @@ +/* + + 3DKIT version 1.2 + High speed 3D graphics and rendering library for Linux. + + Copyright (C) 1996, 1997 Paul Sheer psheer@icon.co.za + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +*/ + + + +/* + +File: wrapsurf.c + +Comments or suggestions welcome. + +This function wraps a bitmap over a surface. +See wrapdemo.c for a demonstration of its use. +Use bitmap data of only 256x512 (see wtriangle.c) +although any region within the bitmap can be drawn +to the full extents of the surface, so multiple +small bitmaps can reside in one image and be +used for different surfaces. + +*/ + + + +#define TD_MULCONSTANT 4096 + +#include +#include +#include +#include + +#ifndef DO_NOT_USE_VGALIB +#include +#endif + +#include +#include "3dkit.h" + + +/*global for holding a surface temporarily:*/ +extern TD_Short_Point *temp; + + +static void xchg (int *a, int *b) +{ + int t = *a; + *a = *b; + *b = t; +} + + +void TD_drawwrapsurface (TD_Solid * s, int which) +{ + + TD_Surface *surf = &s->surf[which]; + int w = surf->w; + int l = surf->l; + int bitmapwidth = surf->bitmapwidth; + int bitmaplength = surf->bitmaplength; + int i = 0, j = 0, k = 0, c = surf->mesh_color; + void (*dl) (int, int, int, int, int) = s->draw_line; + + void (*dsw) (int, int, int, int, + int, int, int, int, + int, int, int, int, int, + TD_tridata *) = s->draw_swtriangle; + + void (*dw) (int, int, int, int, int, + int, int, int, int, int, + int, int, int, int, int, + TD_tridata *) = s->draw_wtriangle; + int mesh; + int d1, d2, d3, d4, d; + int x1, y1, c1; + int x2, y2, c2; + int x3, y3, c3; + int x4, y4, c4; + int u1, v1; + int u2, v2; + int u3, v3; + int u4, v4; + int furthest, clockwise = 0; + TD_tridata tri; + + tri.bitmap1 = surf->bitmap1; + tri.bitmap2 = surf->bitmap2; + + if (s->option_flags & TDOPTION_ALL_SAME_RENDER) + mesh = (s->render == TD_MESH_AND_SOLID); + else + mesh = (surf->render == TD_MESH_AND_SOLID); + +/*distance of four corners (numbered clockwise): */ + d1 = TD_finddistance (s, &surf->point[0]); + d2 = TD_finddistance (s, &surf->point[w - 1]); + d3 = TD_finddistance (s, &surf->point[w * l - 1]); + d4 = TD_finddistance (s, &surf->point[w * (l - 1)]); + + +/*find furthest point */ + furthest = 1; + + d = d1; + + if (d2 > d) { + furthest = 2; + d = d2; + } + if (d3 > d) { + furthest = 3; + d = d3; + } + if (d4 > d) + furthest = 4; + + +/*draw scanning from the furthest point to the second furthest point */ +/*there are eight possibilities: */ + + switch (furthest) { + case 1: + if (d2 > d4) { + clockwise = 0; + for (j = 0; j < l; j++) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].u = i * bitmapwidth / (w - 1); + temp[k].v = j * bitmaplength / (l - 1); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 1; + for (j = 0; j < l; j++) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].u = j * bitmapwidth / (l - 1); + temp[k].v = i * bitmaplength / (w - 1); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + + case 2: + if (d1 > d3) { + clockwise = 1; + for (j = 0; j < l; j++) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].u = i * bitmapwidth / (w - 1); + temp[k].v = j * bitmaplength / (l - 1); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 0; + for (j = l - 1; j >= 0; j--) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].u = j * bitmapwidth / (l - 1); + temp[k].v = i * bitmaplength / (w - 1); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + + case 3: + if (d4 > d2) { + clockwise = 0; + for (j = l - 1; j >= 0; j--) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].u = i * bitmapwidth / (w - 1); + temp[k].v = j * bitmaplength / (l - 1); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 1; + for (j = l - 1; j >= 0; j--) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].u = j * bitmapwidth / (l - 1); + temp[k].v = i * bitmaplength / (w - 1); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + + case 4: + if (d3 > d1) { + clockwise = 1; + for (j = l - 1; j >= 0; j--) + for (i = 0; i < w; i++) { + TD_translate (s, &surf->point[i + j * w], &temp[k]); + temp[k].u = i * bitmapwidth / (w - 1); + temp[k].v = j * bitmaplength / (l - 1); + temp[k].c = TD_findcolor (s, &surf->point[i + j * w], which); + k++; + } + } else { + xchg (&l, &w); + clockwise = 0; + for (j = 0; j < l; j++) + for (i = w - 1; i >= 0; i--) { + TD_translate (s, &surf->point[i * l + j], &temp[k]); + temp[k].u = j * bitmapwidth / (l - 1); + temp[k].v = i * bitmaplength / (w - 1); + temp[k].c = TD_findcolor (s, &surf->point[i * l + j], which); + k++; + } + } + break; + } + + if (!surf->backfacing) + clockwise += 2; /*Otherwise a different bitmap on either side*/ + + tri.bf = clockwise; + + for (k = 0, j = 0; j < l - 1; j++, k++) { + for (i = 0; i < w - 1; i++, k++) { + +/*define the grid square we are currently drawing: */ + x1 = temp[k].x; + y1 = temp[k].y; + u1 = temp[k].u; + v1 = temp[k].v; + c1 = temp[k].c; + + x2 = temp[k + 1].x; + y2 = temp[k + 1].y; + u2 = temp[k + 1].u; + v2 = temp[k + 1].v; + c2 = temp[k + 1].c; + + x3 = temp[k + w + 1].x; + y3 = temp[k + w + 1].y; + u3 = temp[k + w + 1].u; + v3 = temp[k + w + 1].v; + c3 = temp[k + w + 1].c; + + x4 = temp[k + w].x; + y4 = temp[k + w].y; + u4 = temp[k + w].u; + v4 = temp[k + w].v; + c4 = temp[k + w].c; + + /*draw with two triangles */ + + + + if (furthest & 1) { /*draw with hypotenuse from point 1 to point 3*/ + if (s->option_flags & TDOPTION_FLAT_TRIANGLE) { + c1 = (c1 + c2 + c3 + c4) >> 2; + (*dsw) (x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, c1, &tri); + (*dsw) (x1, y1, u1, v1, x3, y3, u3, v3, x4, y4, u4, v4, c1, &tri); + } else { + (*dw) (x1, y1, u1, v1, c1, x2, y2, u2, v2, c2, x3, y3, u3, v3, c3, &tri); + (*dw) (x1, y1, u1, v1, c1, x3, y3, u3, v3, c3, x4, y4, u4, v4, c4, &tri); + } + } else { /*draw with hypotenuse from point 2 to point 4*/ + if (s->option_flags & TDOPTION_FLAT_TRIANGLE) { + c1 = (c1 + c2 + c3 + c4) >> 2; + (*dsw) (x1, y1, u1, v1, x2, y2, u2, v2, x4, y4, u4, v4, c1, &tri); + (*dsw) (x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, c1, &tri); + } else { + (*dw) (x1, y1, u1, v1, c1, x2, y2, u2, v2, c2, x4, y4, u4, v4, c4, &tri); + (*dw) (x2, y2, u2, v2, c2, x3, y3, u3, v3, c3, x4, y4, u4, v4, c4, &tri); + } + } + + + if (mesh) { + (*dl) (x1, y1, x2, y2, c); + (*dl) (x1, y1, x4, y4, c); + } + } + if (mesh) + (*dl) (temp[k + w].x, temp[k + w].y, temp[k].x, temp[k].y, c); + } + + if (mesh) { + for (i = 0; i < w - 1; i++, k++) + (*dl) (temp[k + 1].x, temp[k + 1].y, temp[k].x, temp[k].y, c); + } +} + + diff --git a/threeDKit/wtriangle.c b/threeDKit/wtriangle.c new file mode 100644 index 0000000..9aad22f --- /dev/null +++ b/threeDKit/wtriangle.c @@ -0,0 +1,3 @@ +#define WRAP +#define INTERP +#include "triangl.c" diff --git a/utils/0-README b/utils/0-README new file mode 100644 index 0000000..d5a033f --- /dev/null +++ b/utils/0-README @@ -0,0 +1 @@ +Please read the resp. manual pages on each of the utilities in here. diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 0000000..a04c220 --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,69 @@ +#---------------------------------------------------------------------- +# Makefile for SVGAlib utilities. +# +# This file is a part of SVGAlib. +#---------------------------------------------------------------------- + +include ../Makefile.cfg + +srcdir = .. +VPATH = $(srcdir)/utils + +#---------------------------------------------------------------------- +# Compiler Section (overrides Makefile.cfg) +#---------------------------------------------------------------------- + +CFLAGS = $(WARN) $(OPTIMIZE) -I../include -L../sharedlib +#Use the next one for the Alpha/AXP if you need it +#LDFLAGS = -L../staticlib +LIBS = -lvga -lm + +#---------------------------------------------------------------------- +# Rules Section +#---------------------------------------------------------------------- + +UTILPROGS = restorefont convfont restoretextmode restorepalette dumpreg gtfcalc +OBJECTS = restorefont.o convfont.o restoretextmode.o restorepalette.o dumpreg.o + +ifeq ($(ARCH),i386) +UTILPROGS += fix132x43 setmclk +OBJECTS += fix132x43.o setmclk.o +endif + +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.o: + $(CC) $(CFLAGS) $(LDFLAGS) -o $* $*.o $(LIBS) + chmod 4755 $* + +all: $(UTILPROGS) +.PHONY: all clean cleanbin dep + +$(OBJECTS): .depend + +convfont: convfont.o + $(CC) $(CFLAGS) $(LDFLAGS) -o convfont convfont.o $(LIBS) + +gtfcalc: gtf/gtfcalc.c + $(CC) $(CFLAGS) $(LDFLAGS) -o gtfcalc -DTESTING_GTF gtf/gtfcalc.c $(LIBS) + +clean: + rm -f $(UTILPROGS) *.o *~ UVCONFIG.CRT + +dep: + rm -f .depend + make .depend + +install: + $(INSTALLPROG) $(UTILPROGS) $(UTILINSTALLDIR) + +.depend: + gcc $(INCLUDES) -MM $(patsubst %.o,$(srcdir)/utils/%.c,$(OBJECTS)) >.depend + +# +# include a dependency file if one exists +# +ifeq (.depend.src,$(wildcard .depend.src)) +include .depend.src +endif diff --git a/utils/convfont.c b/utils/convfont.c new file mode 100644 index 0000000..8270238 --- /dev/null +++ b/utils/convfont.c @@ -0,0 +1,81 @@ +/* Convert standard binary font to codepage format */ + + +#include +#include + + +int fontheight; +int sfontsize; +int font_nuchars; +unsigned char sfontbuf[32 * 256]; +unsigned char tfontbuf[32 * 256]; +FILE *sf; +FILE *tf; + + +int +main (int argc, char **argv) +{ + int i; + if (argc != 4) + { + printf ("Syntax: convfont fontfile fontheight vgafontfile\n"); + printf ( + "\nconvfont - convert standard format binary font to codepage format\n" + "The converted font is written to vgafontfile.\n"); + printf ( + "A binary font file of any number of characters up to 256 can be used, although\n" + "at least defining the first 128 characters is a good idea. The fontheight\n" + "should be in the range 1-32.\n" + ); + return 1; + } + if ((sf = fopen (argv[1], "rb")) == NULL) + { + printf ("convfont: Unable to open file.\n"); + return 1; + } + if ((tf = fopen (argv[3], "wb")) == NULL) + { + printf ("convfont: Unable to create file.\n"); + return 1; + } + fontheight = atoi (argv[2]); + if (fontheight < 1 || fontheight > 32) + { + printf ("convfont: Invalid fontheight.\n"); + return 1; + } + + fseek (sf, 0, SEEK_END); + sfontsize = ftell (sf); + fseek (sf, 0, SEEK_SET); + font_nuchars = sfontsize / fontheight; + printf ("Converting %d characters\n", font_nuchars); + if (font_nuchars < 1 || font_nuchars > 256) + { + printf ("convfont: Invalid number of characters in font.\n"); + return 1; + } + fread (sfontbuf, 1, sfontsize, sf); + fclose (sf); + for (i = 0; i < font_nuchars; i++) + { + int j; + + for (j = 0; j < fontheight; j++) + tfontbuf[i * 32 + j] = + sfontbuf[i * fontheight + j]; + + for (j = 0; j < 32 - fontheight; j++) + tfontbuf[i * 32 + fontheight] = 0; + } + /* clear remaining characters */ + for (i = font_nuchars * 32; i < 32 * 256; i++) + tfontbuf[i] = 0; + printf ("Writing font file.\n"); + fwrite (tfontbuf, 1, 32 * 256, tf); + fclose (tf); + return 0; +} diff --git a/utils/dumpreg.c b/utils/dumpreg.c new file mode 100644 index 0000000..19452e2 --- /dev/null +++ b/utils/dumpreg.c @@ -0,0 +1,14 @@ +#include + + +int +main (void) +{ + /* We can't call vga_init, because register dumping should work */ + /* from within X, and vga_init will exit in that case. */ + vga_init(); + vga_dumpregs (); + vga_screenon (); + /* vga_setmode(TEXT); Hack to unblank screen. */ + return 0; +} diff --git a/utils/fix132x43.c b/utils/fix132x43.c new file mode 100644 index 0000000..c042098 --- /dev/null +++ b/utils/fix132x43.c @@ -0,0 +1,219 @@ +/* + This file assumes 132 column textmode :-). + + This program tries to fix problems with extended textmodes on some cards. The problem is that for 132x43 textmode, some + BIOSes set the vertical display end register to 349 (350), instead of 343 (344 = 3 * 8 scanlines). Because in Linux textmode + video memory is usually filled with old text that has already scrolled away (this includes the area below the 43rd textmode + line, which changes when the console scrolls), the top half of a constantly changing irrelevant text line is visible + at the bottom of the screen, which is very annoying. + + This program sets the VGA Vertical Display End register to the proper value. + + The problem is at least present in the BIOS of most Cirrus Logic 542x based cards, and some WD90C03x based cards. + + + You can also change the number scanlines and number of lines per character of 132x43 textmode to improve readability. + + + VGA CRTC 0x12 bits 0-7 Vertical Display End Register bits 0-7 + VGA CRTC 0x07 bit 1 Vertical Display End Register bit 8 + + Cirrus 542x BIOS v1.10 132x43: 0x15d (349) (this is the wrong value that the BIOS sets) + Correct value for 132x43: 0x157 (343) + Correct value for 132x44: 0x15f (351) + + + VGA CRTC 0x09 bits 0-4 Number of scanlines in a textmode font character. + VGA MiscOut bits 6-7 Indicates number of scanlines: 1 = 400, 2 = 350, 3 = 480. + VGA CRTC 0x06 bits 0-7 Vertical Total register bits 0-7 (should be #scanlines - 2) + Bit 8 is in VGA CRTC 0x07, bit 0 + Bit 9 is in VGA CRTC 0x07, bit 5 + VGA CRTC 0x10 bits 0-7 Vertical Retrace Start + Bit 8 is in VGA CRTC 0x07, bit 2 + Bit 9 is in VGA CRTC 0x07, bit 7 + VGA CRTC 0x11 bits 0-3 Vertical Retrace End (last 4 bits) + VGA CRTC 0x15 bits 0-7 Vertical Blank Start + Bit 8 is in VGA CRTC 0x07 bit 3 + + */ + + +/* Comment this out if setting graphics modes is undesirable. You can load proper fonts with restorefont. */ +#define FIX_FONT + + +#include +#include +#include +#include +#include +#include "sys/io.h" /* For port I/O macros. */ +#define OUTB(a,d) outb(d,a) + +static void fixfont (int); + +int +main (int argc, char *argv[]) +{ + int vgaIOBase; + unsigned char val; + int lines; + + vga_disabledriverreport (); + vga_setchipset (VGA); + vga_init (); + + if (argc == 1) + { + printf ("Fiddle with 132x43 textmode VGA registers.\n"); + printf ("Syntax: fix132x43 option (one at a time).\n"); + printf (" -f Fix problem of annoying changing line of text at bottom of screen.\n"); + printf (" -v Switch to 9 line characters (400 line frame, 70 Hz).\n"); +#ifdef INCLUDE_480LINEMODE + printf (" -w Switch to 11 line characters (480 line frame, 60 Hz).\n"); +#endif + printf (" -r Switch to 8 line characters again (350 line frame, 70 Hz).\n"); + printf ("LINES environment variable is used to detect 43 or 44 line console.\n"); + return 0; + } + + if (argv[1][0] != '-') + { + printf ("Must specify -f, -v or -r.\n"); + return 1; + } + + if (argv[1][1] != 'f' && argv[1][1] != 'v' && argv[1][1] != 'w' && argv[1][1] != 'r') + { + printf ("Must specify -f, -v, or -r.\n"); + return 1; + } + + lines = atoi (getenv ("LINES")); + printf ("Lines: %d\n", lines); + + /* Deprotect CRT registers 0-7. */ + vgaIOBase = (inb (0x3cc) & 0x01) ? 0x3D0 : 0x3B0; + OUTB (vgaIOBase + 4, 0x11); + val = inb (vgaIOBase + 5); + OUTB (vgaIOBase + 5, val & 0x7f); + + if (argv[1][1] == 'f') + { + /* Fix stupid bottom line. */ + OUTB (vgaIOBase + 4, 0x12); + OUTB (vgaIOBase + 5, 0x57); /* Value for 43 lines (343). */ + } + + if (argv[1][1] == 'r') + { + /* Set 8 line characters, 350 line frame (344 used). */ + + OUTB (vgaIOBase + 4, 0x09); + val = inb (vgaIOBase + 5); + OUTB (vgaIOBase + 5, (val & 0xe0) | 7); /* Set 8-line characters. */ + + val = inb (0x3cc); + OUTB (0x3c2, (val & 0x3f) | (2 << 6)); /* 350 scanlines. */ + + OUTB (vgaIOBase + 4, 0x12); /* Vertical Display End */ + if (lines == 44) + OUTB (vgaIOBase + 5, 0x60); /* Value for 44 lines (352). */ + else + OUTB (vgaIOBase + 5, 0x57); /* Value for 43 lines (343). */ + + OUTB (vgaIOBase + 4, 0x10); /* Retrace Start */ + OUTB (vgaIOBase + 5, 0x83); /* Value for 350 line frame. */ + + OUTB (vgaIOBase + 4, 0x11); /* Retrace End */ + val = inb (vgaIOBase + 5); + OUTB (vgaIOBase + 5, (val & 0xf0) | 0x05); + + OUTB (vgaIOBase + 4, 0x15); /* Vertical Blank Start */ + OUTB (vgaIOBase + 5, 0x63); /* Value for 350 line frame. */ + } + + if (argv[1][1] == 'v') + { + /* Set 9 line characters, 400 line frame (387 used). */ + + OUTB (vgaIOBase + 4, 0x09); + val = inb (vgaIOBase + 5); + OUTB (vgaIOBase + 5, (val & 0xe0) | 8); /* Set 9-line characters. */ + + val = inb (0x3cc); + OUTB (0x3c2, (val & 0x3f) | (1 << 6)); /* 400 scanlines. */ + + OUTB (vgaIOBase + 4, 0x12); + if (lines == 44) + OUTB (vgaIOBase + 5, 0x8b); /* End scanline is 44 * 9 - 1 = 395 */ + else + OUTB (vgaIOBase + 5, 0x82); /* End scanline is 43 * 9 - 1 = 386 */ + + OUTB (vgaIOBase + 4, 0x10); /* Retrace Start */ + OUTB (vgaIOBase + 5, 0x9c); /* Value for 400 line frame. */ + + OUTB (vgaIOBase + 4, 0x11); /* Retrace End */ + val = inb (vgaIOBase + 5); + OUTB (vgaIOBase + 5, (val & 0xf0) | 0x0e); + + OUTB (vgaIOBase + 4, 0x15); /* Vertical Blank Start */ + OUTB (vgaIOBase + 5, 0x95); /* Value for 400 line frame. */ + +#ifdef FIX_FONT + fixfont (9); +#endif + } + +#ifdef INCLUDE_480LINEMODE + if (argv[1][1] == 'w') + { + /* Set 11 line characters, 480 line frame (473 used). */ + + OUTB (vgaIOBase + 4, 0x09); + val = inb (vgaIOBase + 5); + OUTB (vgaIOBase + 5, (val & 0xe0) | 10); /* Set 11-line characters. */ + + OUTB (0x3c2, 0xeb); + + OUTB (vgaIOBase + 4, 0x12); + OUTB (vgaIOBase + 5, 0xd8); /* End scanline is 43 * 11 - 1 = 472 */ + + OUTB (vgaIOBase + 4, 0x10); /* Retrace Start */ + OUTB (vgaIOBase + 5, 0xf4 /*0xea */ ); /* Value for 480 line frame. ?? */ + + OUTB (vgaIOBase + 4, 0x11); /* Retrace End */ + val = inb (vgaIOBase + 5); + OUTB (vgaIOBase + 5, (val & 0xf0) | 0x0c); + + OUTB (vgaIOBase + 4, 0x15); /* Vertical Blank Start */ + OUTB (vgaIOBase + 5, 0xf4 /*0xe7 */ ); /* Value for 480 line frame. */ + +#ifdef FIX_FONT + fixfont (11); +#endif + } +#endif + + return 0; +} + + + +/* Clear offsets 8-31 of each character bitmap (the BIOS usually leaves some trash here from the 16 line font that was loaded */ +/* prior to setting 132x43 (8 line font) textmode). */ + +static void +fixfont (int lines) +{ + unsigned char font[8192]; + int i; + vga_setmode (G640x480x16); + vga_gettextfont (font); + + for (i = 0; i < 256; i++) + memset (font + i * 32 + 8, 0, 32 - 8); /* Clear remaining part of character bitmap buffer. */ + + vga_puttextfont (font); + vga_setmode (TEXT); +} diff --git a/utils/font14 b/utils/font14 new file mode 100644 index 0000000..d4c5af0 Binary files /dev/null and b/utils/font14 differ diff --git a/utils/font16 b/utils/font16 new file mode 100644 index 0000000..365611e Binary files /dev/null and b/utils/font16 differ diff --git a/utils/font8 b/utils/font8 new file mode 100644 index 0000000..bd7c107 Binary files /dev/null and b/utils/font8 differ diff --git a/utils/gtf/gtf.h b/utils/gtf/gtf.h new file mode 100644 index 0000000..ef74af7 --- /dev/null +++ b/utils/gtf/gtf.h @@ -0,0 +1,152 @@ +/**************************************************************************** +* +* VESA Generalized Timing Formula (GTF) +* Version 1.0 +* +* ======================================================================== +* +* The contents of this file are subject to the SciTech MGL Public +* License Version 1.0 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.scitechsoft.com/mgl-license.txt +* +* Software distributed under the License is distributed on an +* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. +* +* The Initial Developer of the Original Code is SciTech Software, Inc. +* All Rights Reserved. +* +* ======================================================================== +* +* Developed by: SciTech Software, Inc. +* +* Language: ANSI C +* Environment: Any +* +* Description: Header file for generating GTF compatible timings given a +* set of input requirements. Translated from the original GTF +* 1.14 spreadsheet definition. +* +* +****************************************************************************/ + +#ifndef __GTF_H +#define __GTF_H + +#ifndef __SCITECH_H +#include "scitech.h" +#endif + +/*---------------------- Macros and type definitions ----------------------*/ + +/* Define the structures for holding the horizontal and vertical + * CRTC parameters for a mode. + * + * Note: The sync timings are defined in both VGA compatible timings + * (sync start and sync end positions) and also in GTF compatible + * modes with the front porch, sync width and back porch defined. + */ + +typedef struct { + int hTotal; /* Horizontal total */ + int hDisp; /* Horizontal displayed */ + int hSyncStart; /* Horizontal sync start */ + int hSyncEnd; /* Horizontal sync end */ + int hFrontPorch; /* Horizontal front porch */ + int hSyncWidth; /* Horizontal sync width */ + int hBackPorch; /* Horizontal back porch */ + } GTF_hCRTC; + +typedef struct { + int vTotal; /* Vertical total */ + int vDisp; /* Vertical displayed */ + int vSyncStart; /* Vertical sync start */ + int vSyncEnd; /* Vertical sync end */ + int vFrontPorch; /* Vertical front porch */ + int vSyncWidth; /* Vertical sync width */ + int vBackPorch; /* Vertical back porch */ + } GTF_vCRTC; + +/* Define the main structure for holding generated GTF timings */ + +typedef struct { + GTF_hCRTC h; /* Horizontal CRTC paremeters */ + GTF_vCRTC v; /* Vertical CRTC parameters */ + char hSyncPol; /* Horizontal sync polarity */ + char vSyncPol; /* Vertical sync polarity */ + char interlace; /* 'I' for Interlace, 'N' for Non */ + double vFreq; /* Vertical frequency (Hz) */ + double hFreq; /* Horizontal frequency (KHz) */ + double dotClock; /* Pixel clock (Mhz) */ + } GTF_timings; + +/* Define the structure for holding standard GTF formula constants */ + +typedef struct { + double margin; /* Margin size as percentage of display */ + double cellGran; /* Character cell granularity */ + double minPorch; /* Minimum front porch in lines/chars */ + double vSyncRqd; /* Width of V sync in lines */ + double hSync; /* Width of H sync as percent of total */ + double minVSyncBP; /* Minimum vertical sync + back porch (us) */ + double m; /* Blanking formula gradient */ + double c; /* Blanking formula offset */ + double k; /* Blanking formula scaling factor */ + double j; /* Blanking formula scaling factor weight */ + } GTF_constants; + +#define GTF_lockVF 1 /* Lock to vertical frequency */ +#define GTF_lockHF 2 /* Lock to horizontal frequency */ +#define GTF_lockPF 3 /* Lock to pixel clock frequency */ + +/*-------------------------- Function Prototypes --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/* Generate a set of timings for a mode from the GTF formulas. This will + * allow you to generate a set of timings by specifying the type as: + * + * 1. Vertical frequency + * 2. Horizontal frequency + * 3. Pixel clock + * + * Generally if you want to find the timings for a specific vertical + * frequency, you may want to generate a first set of timings given the + * desired vertical frequency, which will give you a specific horizontal + * frequency and dot clock. You can then adjust the dot clock to a value + * that is known to be available on the underlying hardware, and then + * regenerate the timings for that particular dot clock to determine what + * the exact final timings will be. + * + * Alternatively if you only have a fixed set of dot clocks available such + * as on older controllers, you can simply run through the set of available + * dot clocks, and generate a complete set of all available timings that + * can be generated with the set of available dot clocks (and filter out + * unuseable values say < 60Hz and > 120Hz). + */ + +void GTF_calcTimings(double hPixels,double vLines,double freq,int type, + ibool wantMargins,ibool wantInterlace,GTF_timings *timings); + +/* Functions to read and write the current set of GTF formula constants. + * These constants should be left in the default state that is defined + * by the current version of the GTF specification. However newer DDC + * monitos that support the GTF specification may be able to pass back a + * table of GTF constants to fine tune the GTF timings for their particular + * requirements. + */ + +void GTF_getConstants(GTF_constants *constants); +void GTF_setConstants(GTF_constants *constants); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif + +#endif /* __GTF_H */ diff --git a/utils/gtf/gtfcalc.c b/utils/gtf/gtfcalc.c new file mode 100644 index 0000000..217eac7 --- /dev/null +++ b/utils/gtf/gtfcalc.c @@ -0,0 +1,441 @@ +/**************************************************************************** +* +* VESA Generalized Timing Formula (GTF) +* Version 1.1 +* +* ======================================================================== +* +* The contents of this file are subject to the SciTech MGL Public +* License Version 1.0 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.scitechsoft.com/mgl-license.txt +* +* Software distributed under the License is distributed on an +* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. +* +* The Initial Developer of the Original Code is SciTech Software, Inc. +* All Rights Reserved. +* +* ======================================================================== +* +* Developed by: SciTech Software, Inc. +* +* Language: ANSI C +* Environment: Any. +* +* Description: C module for generating GTF compatible timings given a set +* of input requirements. Translated from the original GTF +* 1.14 spreadsheet definition. +* +* Compile with #define TESTING to build a command line test +* program. +* +* NOTE: The code in here has been written for clarity and +* to follow the original GTF spec as closely as +* possible. +* +****************************************************************************/ + +#include +#include +#include +#include +#include +#include "gtf.h" + +/*------------------------- Global Variables ------------------------------*/ + +static GTF_constants GC = { + 1.8, /* Margin size as percentage of display */ + 8, /* Character cell granularity */ + 1, /* Minimum front porch in lines/chars */ + 3, /* Width of V sync in lines */ + 8, /* Width of H sync as percent of total */ + 550, /* Minimum vertical sync + back porch (us) */ + 600, /* Blanking formula gradient */ + 40, /* Blanking formula offset */ + 128, /* Blanking formula scaling factor */ + 20, /* Blanking formula scaling factor weight */ + }; + +/*-------------------------- Implementation -------------------------------*/ + +static double round(double v) +{ + return floor(v + 0.5); +} + +static void GetInternalConstants(GTF_constants *c) +/**************************************************************************** +* +* Function: GetInternalConstants +* Parameters: c - Place to store the internal constants +* +* Description: Calculates the rounded, internal set of GTF constants. +* These constants are different to the real GTF constants +* that can be set up for the monitor. The calculations to +* get these real constants are defined in the 'Work Area' +* after the constants are defined in the Excel spreadsheet. +* +****************************************************************************/ +{ + c->margin = GC.margin; + c->cellGran = round(GC.cellGran); + c->minPorch = round(GC.minPorch); + c->vSyncRqd = round(GC.vSyncRqd); + c->hSync = GC.hSync; + c->minVSyncBP = GC.minVSyncBP; + if (GC.k == 0) + c->k = 0.001; + else + c->k = GC.k; + c->m = (c->k / 256) * GC.m; + c->c = (GC.c - GC.j) * (c->k / 256) + GC.j; + c->j = GC.j; +} + +void GTF_calcTimings(double hPixels,double vLines,double freq, + int type,ibool wantMargins,ibool wantInterlace,GTF_timings *t) +/**************************************************************************** +* +* Function: GTF_calcTimings +* Parameters: hPixels - X resolution +* vLines - Y resolution +* freq - Frequency (Hz, KHz or MHz depending on type) +* type - 1 - vertical, 2 - horizontal, 3 - dot clock +* margins - True if margins should be generated +* interlace - True if interlaced timings to be generated +* t - Place to store the resulting timings +* +* Description: Calculates a set of GTF timing parameters given a specified +* resolution and vertical frequency. The horizontal frequency +* and dot clock will be automatically generated by this +* routines. +* +* For interlaced modes the CRTC parameters are calculated for +* a single field, so will be half what would be used in +* a non-interlaced mode. +* +****************************************************************************/ +{ + double interlace,vFieldRate,hPeriod; + double topMarginLines,botMarginLines; + double leftMarginPixels,rightMarginPixels; + double hPeriodEst,vSyncBP,vBackPorch; + double vTotalLines,vFieldRateEst; + double hTotalPixels,hTotalActivePixels,hBlankPixels; + double idealDutyCycle,hSyncWidth,hSyncBP,hBackPorch; + double idealHPeriod; + double vFreq,hFreq,dotClock; + GTF_constants c; + + /* Get rounded GTF constants used for internal calculations */ + GetInternalConstants(&c); + + /* Move input parameters into appropriate variables */ + vFreq = hFreq = dotClock = freq; + + /* Round pixels to character cell granularity */ + hPixels = round(hPixels / c.cellGran) * c.cellGran; + + /* For interlaced mode halve the vertical parameters, and double + * the required field refresh rate. + */ + if (wantInterlace) { + vLines = round(vLines / 2); + vFieldRate = vFreq * 2; + dotClock = dotClock * 2; + interlace = 0.5; + } + else { + vFieldRate = vFreq; + interlace = 0; + } + + /* Determine the lines for margins */ + if (wantMargins) { + topMarginLines = round(c.margin / 100 * vLines); + botMarginLines = round(c.margin / 100 * vLines); + } + else { + topMarginLines = 0; + botMarginLines = 0; + } + + if (type != GTF_lockPF) { + if (type == GTF_lockVF) { + /* Estimate the horizontal period */ + hPeriodEst = ((1/vFieldRate) - (c.minVSyncBP/1000000)) / + (vLines + (2*topMarginLines) + c.minPorch + interlace) * 1000000; + + /* Find the number of lines in vSync + back porch */ + vSyncBP = round(c.minVSyncBP / hPeriodEst); + } + else if (type == GTF_lockHF) { + /* Find the number of lines in vSync + back porch */ + vSyncBP = round((c.minVSyncBP * hFreq) / 1000); + } + + /* Find the number of lines in the V back porch alone */ + vBackPorch = vSyncBP - c.vSyncRqd; + + /* Find the total number of lines in the vertical period */ + vTotalLines = vLines + topMarginLines + botMarginLines + vSyncBP + + interlace + c.minPorch; + + if (type == GTF_lockVF) { + /* Estimate the vertical frequency */ + vFieldRateEst = 1000000 / (hPeriodEst * vTotalLines); + + /* Find the actual horizontal period */ + hPeriod = (hPeriodEst * vFieldRateEst) / vFieldRate; + + /* Find the actual vertical field frequency */ + vFieldRate = 1000000 / (hPeriod * vTotalLines); + } + else if (type == GTF_lockHF) { + /* Find the actual vertical field frequency */ + vFieldRate = (hFreq / vTotalLines) * 1000; + } + } + + /* Find the number of pixels in the left and right margins */ + if (wantMargins) { + leftMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran); + rightMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran); + } + else { + leftMarginPixels = 0; + rightMarginPixels = 0; + } + + /* Find the total number of active pixels in image + margins */ + hTotalActivePixels = hPixels + leftMarginPixels + rightMarginPixels; + + if (type == GTF_lockVF) { + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - ((c.m * hPeriod) / 1000); + } + else if (type == GTF_lockHF) { + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - (c.m / hFreq); + } + else if (type == GTF_lockPF) { + /* Find ideal horizontal period from blanking duty cycle formula */ + idealHPeriod = (((c.c - 100) + (sqrt((pow(100-c.c,2)) + + (0.4 * c.m * (hTotalActivePixels + rightMarginPixels + + leftMarginPixels) / dotClock)))) / (2 * c.m)) * 1000; + + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - ((c.m * idealHPeriod) / 1000); + } + + /* Find the number of pixels in blanking time */ + hBlankPixels = round((hTotalActivePixels * idealDutyCycle) / + ((100 - idealDutyCycle) * 2 * c.cellGran)) * (2 * c.cellGran); + + /* Find the total number of pixels */ + hTotalPixels = hTotalActivePixels + hBlankPixels; + + /* Find the horizontal back porch */ + hBackPorch = round((hBlankPixels / 2) / c.cellGran) * c.cellGran; + + /* Find the horizontal sync width */ + hSyncWidth = round(((c.hSync/100) * hTotalPixels) / c.cellGran) * c.cellGran; + + /* Find the horizontal sync + back porch */ + hSyncBP = hBackPorch + hSyncWidth; + + if (type == GTF_lockPF) { + /* Find the horizontal frequency */ + hFreq = (dotClock / hTotalPixels) * 1000; + + /* Find the horizontal period */ + hPeriod = 1000 / hFreq; + + /* Find the number of lines in vSync + back porch */ + vSyncBP = round((c.minVSyncBP * hFreq) / 1000); + + /* Find the number of lines in the V back porch alone */ + vBackPorch = vSyncBP - c.vSyncRqd; + + /* Find the total number of lines in the vertical period */ + vTotalLines = vLines + topMarginLines + botMarginLines + vSyncBP + + interlace + c.minPorch; + + /* Find the actual vertical field frequency */ + vFieldRate = (hFreq / vTotalLines) * 1000; + } + else { + if (type == GTF_lockVF) { + /* Find the horizontal frequency */ + hFreq = 1000 / hPeriod; + } + else if (type == GTF_lockHF) { + /* Find the horizontal frequency */ + hPeriod = 1000 / hFreq; + } + + /* Find the pixel clock frequency */ + dotClock = hTotalPixels / hPeriod; + } + + /* Find the vertical frame frequency */ + if (wantInterlace) { + vFreq = vFieldRate / 2; + dotClock = dotClock / 2; + } + else + vFreq = vFieldRate; + + /* Return the computed frequencies */ + t->vFreq = vFreq; + t->hFreq = hFreq; + t->dotClock = dotClock; + + /* Determine the vertical timing parameters */ + t->h.hTotal = hTotalPixels; + t->h.hDisp = hTotalActivePixels; + t->h.hSyncStart = t->h.hTotal - hSyncBP; + t->h.hSyncEnd = t->h.hTotal - hBackPorch; + t->h.hFrontPorch = t->h.hSyncStart - t->h.hDisp; + t->h.hSyncWidth = hSyncWidth; + t->h.hBackPorch = hBackPorch; + + /* Determine the vertical timing parameters */ + t->v.vTotal = vTotalLines; + t->v.vDisp = vLines; + t->v.vSyncStart = t->v.vTotal - vSyncBP; + t->v.vSyncEnd = t->v.vTotal - vBackPorch; + t->v.vFrontPorch = t->v.vSyncStart - t->v.vDisp; + t->v.vSyncWidth = c.vSyncRqd; + t->v.vBackPorch = vBackPorch; + + /* Mark as GTF timing using the sync polarities */ + t->interlace = (wantInterlace) ? 'I' : 'N'; + t->hSyncPol = '-'; + t->vSyncPol = '+'; +} + +void GTF_getConstants(GTF_constants *constants) +{ *constants = GC; } + +void GTF_setConstants(GTF_constants *constants) +{ GC = *constants; } + +#ifdef TESTING_GTF + +int main(int argc,char *argv[]) +{ + FILE *f; + double xPixels,yPixels,freq; + ibool interlace; + GTF_timings t; + + if (argc != 5 && argc != 6) { + printf("Usage: GTFCALC [[Hz] [KHz] [MHz]] [I]\n"); + printf("\n"); + printf("where is the horizontal resolution of the mode, is the\n"); + printf("vertical resolution of the mode. The value will be the frequency to\n"); + printf("drive the calculations, and will be either the vertical frequency (in Hz)\n"); + printf("the horizontal frequency (in KHz) or the dot clock (in MHz). To generate\n"); + printf("timings for an interlaced mode, add 'I' to the end of the command line.\n"); + printf("\n"); + printf("For example to generate timings for 640x480 at 60Hz vertical:\n"); + printf("\n"); + printf(" GTFCALC 640 480 60 Hz\n"); + printf("\n"); + printf("For example to generate timings for 640x480 at 31.5KHz horizontal:\n"); + printf("\n"); + printf(" GTFCALC 640 480 31.5 KHz\n"); + printf("\n"); + printf("For example to generate timings for 640x480 with a 25.175Mhz dot clock:\n"); + printf("\n"); + printf(" GTFCALC 640 480 25.175 MHz\n"); + printf("\n"); + printf("GTFCALC will print a summary of the results found, and dump the CRTC\n"); + printf("values to the UVCONFIG.CRT file in the format used by SciTech Display Doctor.\n"); + return 1; + } + + /* Get values from command line */ + xPixels = atof(argv[1]); + yPixels = atof(argv[2]); + freq = atof(argv[3]); + interlace = ((argc == 6) && (argv[5][0] == 'I')); + + /* Compute the CRTC timings */ + if (toupper(argv[4][0]) == 'H') + GTF_calcTimings(xPixels,yPixels,freq,GTF_lockVF,false,interlace,&t); + else if (toupper(argv[4][0]) == 'K') + GTF_calcTimings(xPixels,yPixels,freq,GTF_lockHF,false,interlace,&t); + else if (toupper(argv[4][0]) == 'M') + GTF_calcTimings(xPixels,yPixels,freq,GTF_lockPF,false,interlace,&t); + else { + printf("Unknown command line!\n"); + return 1; + } + + /* Dump summary info to standard output */ + printf("CRTC values for %.0fx%.0f @ %.2f %s\n", xPixels, yPixels, freq, argv[4]); + printf("\n"); + printf(" hTotal = %-4d vTotal = %-4d\n", + t.h.hTotal, t.v.vTotal); + printf(" hDisp = %-4d vDisp = %-4d\n", + t.h.hDisp, t.v.vDisp); + printf(" hSyncStart = %-4d vSyncStart = %-4d\n", + t.h.hSyncStart, t.v.vSyncStart); + printf(" hSyncEnd = %-4d vSyncEnd = %-4d\n", + t.h.hSyncEnd, t.v.vSyncEnd); + printf(" hFrontPorch = %-4d vFrontPorch = %-4d\n", + t.h.hFrontPorch, t.v.vFrontPorch); + printf(" hSyncWidth = %-4d vSyncWidth = %-4d\n", + t.h.hSyncWidth, t.v.vSyncWidth); + printf(" hBackPorch = %-4d vBackPorch = %-4d\n", + t.h.hBackPorch, t.v.vBackPorch); + printf("\n"); + printf(" Interlaced = %s\n", (t.interlace == 'I') ? "Yes" : "No"); + printf(" H sync pol = %c\n", t.hSyncPol); + printf(" V sync pol = %c\n", t.vSyncPol); + printf("\n"); + printf(" Vert freq = %.2f Hz\n", t.vFreq); + printf(" Horiz freq = %.2f KHz\n", t.hFreq); + printf(" Dot Clock = %.2f Mhz\n", t.dotClock); + fprintf(stderr,"Modeline %c%ix%i@%.0f%c %.3f %i %i %i %i %i %i %i %i %s %chsync %cvsync\n", + '"',t.h.hDisp,t.v.vDisp,t.vFreq,'"', + t.dotClock, + t.h.hDisp, + t.h.hSyncStart, + t.h.hSyncEnd, + t.h.hTotal, + t.v.vDisp, + t.v.vSyncStart, + t.v.vSyncEnd, + t.v.vTotal, + (t.interlace == 'I') ? "Interlace" : "", + t.hSyncPol, + t.vSyncPol + ); + + /* Dump to file in format used by SciTech Display Doctor */ + if ((f = fopen("UVCONFIG.CRT","wt")) != NULL) { + fprintf(f, "[%.0f %.0f]\n", xPixels, yPixels); + fprintf(f, "%d %d %d %d '%c' %s\n", + t.h.hTotal, t.h.hDisp, + t.h.hSyncStart, t.h.hSyncEnd, + t.hSyncPol, (t.interlace == 'I') ? "I" : "NI"); + fprintf(f, "%d %d %d %d '%c'\n", + t.v.vTotal, t.v.vDisp, + t.v.vSyncStart, t.v.vSyncEnd, + t.vSyncPol); + fprintf(f, "%.2f\n", t.dotClock); + fclose(f); + } + return 0; +} + +#endif /* TESTING */ diff --git a/utils/gtf/scitech.h b/utils/gtf/scitech.h new file mode 100644 index 0000000..1ec7d42 --- /dev/null +++ b/utils/gtf/scitech.h @@ -0,0 +1,506 @@ +/**************************************************************************** +* +* SciTech Multi-platform Graphics Library +* +* ======================================================================== +* +* The contents of this file are subject to the SciTech MGL Public +* License Version 1.0 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.scitechsoft.com/mgl-license.txt +* +* Software distributed under the License is distributed on an +* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. +* +* The Initial Developer of the Original Code is SciTech Software, Inc. +* All Rights Reserved. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: any +* +* Description: General header file for operating system portable code. +* +****************************************************************************/ + +#ifndef __SCITECH_H +#define __SCITECH_H + +/* We have the following defines to identify the compilation environment: + * + * __16BIT__ Compiling for 16 bit code (any environment) + * __32BIT__ Compiling for 32 bit code (any environment) + * __MSDOS__ Compiling for MS-DOS (includes __WINDOWS16__, __WIN386__) + * __REALDOS__ Compiling for MS-DOS (excludes __WINDOWS16__) + * __MSDOS16__ Compiling for 16 bit MS-DOS + * __MSDOS32__ Compiling for 32 bit MS-DOS + * __WINDOWS__ Compiling for Windows + * __WINDOWS16__ Compiling for 16 bit Windows (__MSDOS__ also defined) + * __WINDOWS32__ Compiling for 32 bit Windows + * __WIN32_VXD__ Compiling for a 32-bit C based VxD + * __OS2__ Compiling for OS/2 + * __OS2_16__ Compiling for 16 bit OS/2 + * __OS2_32__ Compiling for 32 bit OS/2 + * __UNIX__ Compiling for Unix + * __QNX__ Compiling for the QNX realtime OS (Unix compatible) + * __LINUX__ Compiling for the Linux OS (Unix compatible) + * __FREEBSD__ Compiling for the FreeBSD OS (Unix compatible) + * __BEOS__ Compiling for the BeOS (Unix compatible) + * __SMX32__ Compiling for the SMX 32-bit Real Time OS + * __DRIVER__ Compiling for a 32-bit binary compatible driver + * + * __INTEL__ Compiling for Intel CPU's + * __ALPHA__ Compiling for DEC Alpha CPU's + * __MIPS__ Compiling for MIPS CPU's + * __PPC__ Compiling for PowerPC CPU's + * __MC68K__ Compiling for Motorola 680x0 + * + */ + +#ifdef __SC__ +#if __INTSIZE == 4 +#define __SC386__ +#endif +#endif + +#ifdef __GNUC__ +#if !defined(__BEOS__) +#define __cdecl /* GCC doesn't know about __cdecl modifiers */ +#endif +#define __FLAT__ /* GCC is always 32 bit flat model */ +#define __HAS_BOOL__ /* Latest GNU C++ has ibool type */ +#include /* Bring in for definition of NULL */ +#endif + +#ifdef __BORLANDC__ +#if (__BORLANDC__ >= 0x500) || defined(CLASSLIB_DEFS_H) +#define __HAS_BOOL__ /* Borland C++ 5.0 and later define ibool type */ +#endif +#endif + +/*--------------------------------------------------------------------------- + * Determine the compile time environment. This must be done for each + * supported platform so that we can determine at compile time the target + * environment, hopefully without requiring #define's from the user. + *-------------------------------------------------------------------------*/ + +/* 32-bit binary compatible driver. Compiled as Win32, but as OS neutral */ +#ifdef __DRIVER__ +#ifndef __32BIT__ +#define __32BIT__ +#endif +#undef __WINDOWS__ +#undef _WIN32 +#undef __WIN32__ +#undef __NT__ + +/* 32-bit Windows VxD compile environment */ +#elif defined(__vtoolsd_h_) || defined(VTOOLSD) +#include +#define __WIN32_VXD__ +#ifndef __32BIT__ +#define __32BIT__ +#endif +#define _MAX_PATH 256 +#ifndef __WINDOWS32__ +#define __WINDOWS32__ +#endif + +/* 32-bit SMX compile environment */ +#elif defined(__SMX32__) +#ifndef __MSDOS__ +#define __MSDOS__ +#endif +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __REALDOS__ +#define __REALDOS__ +#endif + +/* 32-bit extended DOS compile environment */ +#elif defined(__MSDOS__) || defined(__MSDOS32__) || defined(__DOS__) || defined(__DPMI32__) || (defined(M_I86) && !defined(__SC386__)) || defined(TNT) +#ifndef __MSDOS__ +#define __MSDOS__ +#endif +#if defined(__MSDOS32__) || defined(__386__) || defined(__FLAT__) || defined(__NT__) || defined(__SC386__) +#ifndef __MSDOS32__ +#define __MSDOS32__ +#endif +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __REALDOS__ +#define __REALDOS__ +#endif + +/* 16-bit Windows compile environment */ +#elif (defined(_Windows) || defined(_WINDOWS)) && !defined(__DPMI16__) +#ifndef __16BIT__ +#define __16BIT__ +#endif +#ifndef __WINDOWS16__ +#define __WINDOWS16__ +#endif +#ifndef __WINDOWS__ +#define __WINDOWS__ +#endif +#ifndef __MSDOS__ +#define __MSDOS__ +#endif + +/* 16-bit DOS compile environment */ +#else +#ifndef __16BIT__ +#define __16BIT__ +#endif +#ifndef __MSDOS16__ +#define __MSDOS16__ +#endif +#ifndef __REALDOS__ +#define __REALDOS__ +#endif +#endif + +/* 32-bit Windows compile environment */ +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __WINDOWS32__ +#define __WINDOWS32__ +#endif +#ifndef _WIN32 +#define _WIN32 /* Microsoft Win32 SDK headers use _WIN32 */ +#endif +#ifndef WIN32 +#define WIN32 /* OpenGL headers use WIN32 */ +#endif +#ifndef __WINDOWS__ +#define __WINDOWS__ +#endif + +/* 16-bit OS/2 compile environment */ +#elif defined(__OS2_16__) +#ifndef __OS2__ +#define __OS2__ +#endif +#ifndef __16BIT__ +#define __16BIT__ +#endif + +/* 32-bit OS/2 compile environment */ +#elif defined(__OS2__) || defined(__OS2_32__) +#ifndef __OS2__ +#define __OS2__ +#endif +#ifndef __OS2_32__ +#define __OS2_32__ +#endif +#ifndef __32BIT__ +#define __32BIT__ +#endif + +/* 32-bit QNX compile environment */ +#elif defined(__QNX__) +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __UNIX__ +#define __UNIX__ +#endif + +/* 32-bit Linux compile environment */ +#elif defined(__LINUX__) || defined(linux) +#ifndef __LINUX__ +#define __LINUX__ +#endif +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __UNIX__ +#define __UNIX__ +#endif + +/* 32-bit FreeBSD compile environment */ +#elif defined(__FREEBSD__) +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __UNIX__ +#define __UNIX__ +#endif + +/* 32-bit BeOS compile environment */ +#elif defined(__BEOS__) +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __UNIX__ +#define __UNIX__ +#endif +#else +#error This platform is not currently supported! +#endif + +/* Determine the CPU type that we are compiling for */ + +#if defined(__M_ALPHA) || defined(__ALPHA_) || defined(__ALPHA) || defined(__alpha) +#ifndef __ALPHA__ +#define __ALPHA__ +#endif +#elif defined(__M_PPC) || defined(__POWERC) +#ifndef __PPC__ +#define __PPC__ +#endif +#elif defined(__M_MRX000) +#ifndef __MIPS__ +#define __MIPS__ +#endif +#else +#ifndef __INTEL__ +#define __INTEL__ /* Assume Intel if nothing found */ +#endif +#endif + +/* We have the following defines to define the calling conventions for + * publicly accesible functions: + * + * _PUBAPI - Compiler default calling conventions for all public 'C' functions + * _ASMAPI - Calling conventions for all public assembler functions + * _DLLAPI - Calling conventions for all DLL exported functions + * _DLLVAR - Modifier to export/import globals in 32 bit DLL's + * _EXPORT - Expands to _export when compiling a DLL + * _VARAPI - Modifiers for variables; Watcom C++ mangles C++ globals + */ + +#if defined(_MSC_VER) && defined(_WIN32) && !defined(__SC__) +#define __PASCAL __stdcall +#define __export +#define __import +#else +#define __PASCAL __pascal +#endif + +#ifdef __WATCOMC__ +#if (__WATCOMC__ >= 1050) +#define _VARAPI __cdecl +#else +#define _VARAPI +#endif +#else +#define _VARAPI +#endif + +#if defined(__IBMC__) || defined(__IBMCPP__) +#define PTR_DECL_IN_FRONT +#endif + +#if defined(__WINDOWS__) +#ifdef BUILD_DLL +#define _DLLASM __export __cdecl +#define _EXPORT __export +#ifdef __WINDOWS32__ +#define _DLLAPI __export __PASCAL +#define _DLLVAR __export +#else +#define _DLLAPI __export __far __pascal +#define _DLLVAR +#endif +#else +#define _DLLASM __cdecl +#define _EXPORT +#ifdef __WINDOWS32__ +#define _DLLAPI __PASCAL +#define _DLLVAR __import +#else +#define _DLLAPI __far __pascal +#define _DLLVAR +#endif +#endif +#else +#if !defined(__BEOS__) +#define _EXPORT +#endif +#define _DLLAPI +#define _DLLVAR +#endif + +/* Define the calling conventions for all public functions. For simplicity + * we define all public functions as __cdecl calling conventions, so that + * they are the same across all compilers and runtime DLL's. + */ + +#define _PUBAPI __cdecl +#define _ASMAPI __cdecl + +/* Determine the syntax for declaring a function pointer with a + * calling conventions override. Most compilers require the calling + * convention to be declared in front of the '*', but others require + * it to be declared after the '*'. We handle both in here depending + * on what the compiler requires. + */ + +#ifdef PTR_DECL_IN_FRONT +#define _DLLAPIP * _DLLAPI +#define _DLLASMP * _DLLASM +#define _PUBAPIP * _PUBAPI +#define _ASMAPIP * _ASMAPI +#else +#define _DLLAPIP _DLLAPI * +#define _DLLASMP _DLLASM * +#define _PUBAPIP _PUBAPI * +#define _ASMAPIP _ASMAPI * +#endif + +/* Useful macros */ + +#define PRIVATE static +#define PUBLIC + +/* This HAS to be 0L for 16-bit real mode code to work!!! */ + +#ifndef NULL +# define NULL 0L +#endif + +#ifndef MAX +# define MAX(a,b) ( ((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +# define MIN(a,b) ( ((a) < (b)) ? (a) : (b)) +#endif +#ifndef ABS +# define ABS(a) ((a) >= 0 ? (a) : -(a)) +#endif +#ifndef SIGN +# define SIGN(a) ((a) > 0 ? 1 : -1) +#endif + +/* General typedefs */ + +#ifndef __GENDEFS +#define __GENDEFS +#if defined(__BEOS__) +#include +#else +#ifdef __LINUX__ +#include +#ifdef __STRICT_ANSI__ +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned int uint; +#endif +#else +#if !(defined(__QNXNTO__) && defined(GENERAL_STRUCT)) +typedef unsigned short ushort; +typedef unsigned long ulong; +#endif +typedef unsigned int uint; +#endif +typedef unsigned char uchar; +#endif +typedef int ibool; /* Integer boolean type */ +#ifdef USE_BOOL /* Only for older code */ +#ifndef __cplusplus +#define bool ibool /* Standard C */ +#else +#ifndef __HAS_BOOL__ +#define bool ibool /* Older C++ compilers */ +#endif +#endif /* __cplusplus */ +#endif /* USE_BOOL */ +#endif /* __GENDEFS */ + +/* Boolean truth values */ + +#undef false +#undef true +#undef NO +#undef YES +#undef FALSE +#undef TRUE +#define false 0 +#define true 1 +#define NO 0 +#define YES 1 +#define FALSE 0 +#define TRUE 1 + +/* Inline debugger interrupts for Watcom C++ and Borland C++ */ + +#ifdef __WATCOMC__ +void DebugInt(void); +#pragma aux DebugInt = \ + "int 3"; +void DebugVxD(void); +#pragma aux DebugVxD = \ + "int 1"; +#elif defined(__BORLANDC__) +#define DebugInt() __emit__(0xCC) +#define DebugVxD() {__emit__(0xCD); __emit__(0x01);} +#elif defined(_MSC_VER) +#define DebugInt() _asm int 0x3 +#define DebugVxD() _asm int 0x1 +#else +#define DebugInt() +#define DebugVxD() +#endif + +/*--------------------------------------------------------------------------- + * Set of debugging macros used by the libraries. If the debug flag is + * set, they are turned on depending on the setting of the flag. User code + * can override the default functions called when a check fails, and the + * MGL does this so it can restore the system from graphics mode to display + * an error message. These functions also log information to the + * scitech.log file in the root directory of the hard drive when problems + * show up. + * + * If you set the value of CHECKED to be 2, it will also enable code to + * insert hard coded debugger interrupt into the source code at the line of + * code where the check fail. This is useful if you run the code under a + * debugger as it will break inside the debugger before exiting with a + * failure condition. + * + * Also for code compiled to run under Windows, we also call the + * OutputDebugString function to send the message to the system debugger + * such as Soft-ICE or WDEB386. Hence if you get any non-fatal warnings you + * will see those on the debugger terminal as well as in the log file. + *-------------------------------------------------------------------------*/ + +extern void (*_CHK_fail)(int fatal,const char *msg,const char *cond,const char *file,int line); +void _CHK_defaultFail(int fatal,const char *msg,const char *cond,const char *file,int line); + +#ifdef CHECKED +# define CHK(x) x +#if CHECKED > 1 +# define CHECK(p) \ + ((p) ? (void)0 : DebugInt(), \ + _CHK_fail(1,"Check failed: '%s', file %s, line %d\n", \ + #p, __FILE__, __LINE__)) +# define WARN(p) \ + ((p) ? (void)0 : DebugInt(), \ + _CHK_fail(0,"Warning: '%s', file %s, line %d\n", \ + #p, __FILE__, __LINE__)) +#else +# define CHECK(p) \ + ((p) ? (void)0 : \ + _CHK_fail(1,"Check failed: '%s', file %s, line %d\n", \ + #p, __FILE__, __LINE__)) +# define WARN(p) \ + ((p) ? (void)0 : \ + _CHK_fail(0,"Warning: '%s', file %s, line %d\n", \ + #p, __FILE__, __LINE__)) +#endif +#else +# define CHK(x) +# define CHECK(p) ((void)0) +# define WARN(p) ((void)0) +#endif + +#endif /* __SCITECH_H */ diff --git a/utils/restorefont.c b/utils/restorefont.c new file mode 100644 index 0000000..cfcf2d9 --- /dev/null +++ b/utils/restorefont.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include "../src/libvga.h" + +/* + * Note: Observe that when writing the font to a file, the file to write is + * opened after vga_init has been called (so that root permissions have been + * given up). This means that there is no major security hole lurking here. + */ + +int main(int argc, char *argv[]) +{ + FILE *f; + unsigned char *font; + size_t font_size = FONT_SIZE; /* buffer size in 1.2.11 and before */ + int can_set = 0; + struct stat statbuf; + + if (argc == 1) { + printf("Restore corrupted textmode font.\n"); + printf("Syntax: restorefont option filename\n"); + printf(" -r filename Restore VGA font from file.\n"); + printf(" -w filename Write current VGA font to file.\n"); + return 0; + } + if (argv[1][0] != '-') { + printf("Must specify -r or -w.\n"); + return 1; + } + switch (argv[1][1]) { + case 'r': + case 'w': + if (argc != 3) { + printf("Must specify filename.\n"); + return 1; + } + break; + default: + printf("Invalid option. Must specify -r or -w.\n"); + return 1; + } + vga_disabledriverreport(); + vga_setchipset(VGA); /* avoid SVGA detection */ + vga_init(); + /* we are in TEXT mode. Check for availability of vga_ext_set: */ + if (vga_getmodeinfo(TEXT)->flags & HAVE_EXT_SET) { + if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_SET) & + (1 << VGA_EXT_FONT_SIZE)) { + can_set = 1; + /* Query the preferred data size: */ + font_size = vga_ext_set(VGA_EXT_FONT_SIZE, 0); + if (font_size < FONT_SIZE) { + font_size = FONT_SIZE; + } + } + } + + /* We never need more than that memory: */ + font = malloc((size_t)font_size); + if (!font) { + puts("restorefont: out of memory."); + goto ex_no_errno; + } + + vga_setmode(G640x350x16); + switch (argv[1][1]) { + case 'r': + f = fopen(argv[2], "rb"); + if (f == NULL) { + error: + perror("restorefont"); + ex_no_errno: + vga_setmode(TEXT); + return 1; + } + if (fstat(fileno(f), &statbuf)) + goto error; + font_size = statbuf.st_size; + /* Check for sensible sizes: */ + switch (font_size) { + case 0x2000: + case 0x2000 * 4: + case 0x2000 * 8: + if (can_set) + vga_ext_set(VGA_EXT_FONT_SIZE, font_size); + break; + default: + corrupt: + puts("restorefont: input file corrupted."); + goto ex_no_errno; + } + + if (1 != fread(font, font_size, 1, f)) { + if (errno) + goto error; + goto corrupt; + } + fclose(f); + vga_puttextfont(font); + break; + case 'w': + /* save as much as we have.. */ + if (can_set) + vga_ext_set(VGA_EXT_FONT_SIZE, font_size); + vga_gettextfont(font); + f = fopen(argv[2], "wb"); + if (f == NULL) + goto error; + if (1 != fwrite(font, font_size, 1, f)) + goto error; + if (fclose(f)) + goto error; + break; + } + vga_setmode(TEXT); + return 0; +} diff --git a/utils/restorepalette.c b/utils/restorepalette.c new file mode 100644 index 0000000..89b1084 --- /dev/null +++ b/utils/restorepalette.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include /* strerror */ +#include "../src/libvga.h" + + +/* default palette values */ + +static char default_red[256] += +{0, 0, 0, 0, 42, 42, 42, 42, 21, 21, 21, 21, 63, 63, 63, 63, + 0, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 40, 45, 50, 56, 63, + 0, 16, 31, 47, 63, 63, 63, 63, 63, 63, 63, 63, 63, 47, 31, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 39, 47, 55, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 55, 47, 39, 31, 31, 31, 31, 31, 31, 31, 31, + 45, 49, 54, 58, 63, 63, 63, 63, 63, 63, 63, 63, 63, 58, 54, 49, + 45, 45, 45, 45, 45, 45, 45, 45, 0, 7, 14, 21, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 21, 14, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 17, 21, 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 24, 21, 17, + 14, 14, 14, 14, 14, 14, 14, 14, 20, 22, 24, 26, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 26, 24, 22, 20, 20, 20, 20, 20, 20, 20, 20, + 0, 4, 8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, 8, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 12, 14, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 14, 12, 10, 8, 8, 8, 8, 8, 8, 8, 8, + 11, 12, 13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 13, 12, + 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0}; +static char default_green[256] += +{0, 0, 42, 42, 0, 0, 21, 42, 21, 21, 63, 63, 21, 21, 63, 63, + 0, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 40, 45, 50, 56, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 31, 47, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 47, 31, 16, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 39, 47, 55, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, 47, 39, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 49, 54, 58, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 58, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 14, 21, 29, 28, 28, 28, 28, 28, 28, 28, 28, 21, 14, 7, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 17, 21, 24, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 24, 21, 17, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 22, 24, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 24, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 12, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 10, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 13, 12, 0, 0, 0, 0, 0, 0, 0, 0}; +static char default_blue[256] += +{0, 42, 0, 42, 0, 42, 0, 42, 21, 63, 21, 63, 21, 63, 21, 63, + 0, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 40, 45, 50, 56, 63, + 63, 63, 63, 63, 63, 47, 31, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 31, 47, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, 47, 39, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 39, 47, 55, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 58, 54, 49, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 49, 54, 58, 63, 63, 63, 63, 28, 28, 28, 28, 28, 21, 14, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 14, 21, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 24, 21, 17, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 17, 21, 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 24, 22, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 22, 24, 26, 28, 28, 28, 28, + 16, 16, 16, 16, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 12, 14, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 13, 12, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 13, 15, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0}; + +void +delay (void) +{ + int i; + for (i = 0; i < 10; i++); +} + +/* Modifications to restorepalette to allow custom palette setting from a file. + * The format of the file is simply a table of color number -> color mappings: + * + * By Charles Blake, chuckb@alice.wonderland.caltech.edu + */ + +void +process_palette_file (char **argv) +{ + int i, n, r, g, b; + FILE *palette_file; + + if ((palette_file = fopen (argv[1], "r")) == NULL) + { + fprintf (stderr, "%s opening %s: %s\n", argv[0], argv[1], strerror (errno)); + exit (1); + } +/* + * NOTE:The tricky %*[^\n] conversion specifier allows arbitrary text following + * any line with a valid entry on it. This is a simple comment syntax device. + */ + for (n = 1; fscanf (palette_file, "%d %d %d %d %*[^\n]", &i, &r, &g, &b) == 4; n++) + { + default_red[i] = r; /* deferred assignment prevents partial */ + default_green[i] = g; /* assignment in case of in-line errors */ + default_blue[i] = b; + } + if (!feof (palette_file)) + { + fprintf (stderr, "%s parse error: %s: line %d\n", argv[0], argv[1], n); + exit (1); + } +} + +int +main (int argc, char *argv[]) +{ + int i; + + vga_init (); + if (argc > 1) + process_palette_file (argv); + + if (vga_getcurrentchipset () != EGA) + { + /* Restore textmode/16-color mode palette */ + if (vga_getcurrentchipset() != FBDEV) + for (i = 0; i < 16; i++) + { + port_in (IS1_RC); + delay (); + port_out (i, ATT_IW); /* set palette color number */ + delay (); + port_out (i, ATT_IW); /* set palette color value */ + delay (); + } + + /* Restore 256-color VGA RGB look-up table */ + for (i = 0; i < 256; i++) + vga_setpalette (i, default_red[i], default_green[i], + default_blue[i]); + + if (vga_getcurrentchipset() != FBDEV) { + port_in (IS1_RC); + delay (); + port_out (0x20, ATT_IW); /* enable display */ + } + } + return 0; +} diff --git a/utils/restoretextmode.c b/utils/restoretextmode.c new file mode 100644 index 0000000..b3c660f --- /dev/null +++ b/utils/restoretextmode.c @@ -0,0 +1,90 @@ + +#include +#include +#include +#include "../src/driver.h" +#include + + +/* + * Note: Observe that when writing the font to a file, the file to write is + * opened after vga_init has been called (so that root permissions have been + * given up). This means that there is no major security hole lurking here. + */ + +unsigned char regs[MAX_REGS]; + +int +main (int argc, char *argv[]) +{ + vga_init (); + if (argc == 1) + { + printf ("Save/restore textmode registers.\n"); + printf ("Syntax: restoretextmode option filename\n"); + printf (" -r filename Restore registers from file.\n"); + printf (" -w filename Write registers to file.\n"); + return 0; + } + if (argv[1][0] != '-') + { + printf ("Must specify -r or -w.\n"); + return 1; + } + switch (argv[1][1]) + { + case 'r': + case 'w': + if (argc != 3) + { + printf ("Must specify filename.\n"); + return 1; + } + break; + default: + printf ("Invalid option. Must specify -r or -w.\n"); + return 1; + } + if (argv[1][1] == 'r') + { + FILE *f; + f = fopen (argv[2], "rb"); + if (f == NULL) + { + error: + perror ("restoretextmode"); + return 1; + } + if (1 != fread (regs, MAX_REGS, 1, f)) + { + if (errno) + goto error; + puts ("restoretextmode: input file corrupted."); + return 1; + } + fclose (f); + } + vga_setmode (G640x350x16); + switch (argv[1][1]) + { + case 'r': + vga_settextmoderegs (regs); + break; + case 'w': + vga_gettextmoderegs (regs); + break; + } + vga_setmode (TEXT); + if (argv[1][1] == 'w') + { + FILE *f; + f = fopen (argv[2], "wb"); + if (f == NULL) + goto error; + if (1 != fwrite (regs, MAX_REGS, 1, f)) + goto error; + if (fclose (f)) + goto error; + } + return 0; +} diff --git a/utils/runx b/utils/runx new file mode 100755 index 0000000..5cad616 --- /dev/null +++ b/utils/runx @@ -0,0 +1,12 @@ +#!/bin/sh +# Script to save VGA textmode font, run X, and restore VGA textmode font. + +# A more rigorous alternative is to run the 'savetextmode' script before +# running X, and 'textmode' after. This will restore the textmode registers +# and the VGA palette in addition to the VGA font. + +echo Saving font in /tmp/fontdata +restorefont -w /tmp/fontdata +startx +echo Restoring font from /tmp/fontdata +restorefont -r /tmp/fontdata diff --git a/utils/savetextmode b/utils/savetextmode new file mode 100755 index 0000000..e50b290 --- /dev/null +++ b/utils/savetextmode @@ -0,0 +1,4 @@ +#!/bin/sh +rm -f /etc/vga/textregs /etc/vga/fontdata +restoretextmode -w /etc/vga/textregs +restorefont -w /etc/vga/fontdata diff --git a/utils/setmclk.c b/utils/setmclk.c new file mode 100644 index 0000000..a059cc6 --- /dev/null +++ b/utils/setmclk.c @@ -0,0 +1,89 @@ +/* + Note: Previously this program did not unlock the extended registers, + so it only worked if the registers happened to be unlocked. + + This program sets the 'memory clock' of Cirrus 5424/26/28 cards. + The first three values could be set by utility programs that + came with my card (AVGA3), but somewhat higher values seem to work (on my + card at least). It may be that better and more recent Cirrus cards use a + higher value as boot-up default. It should depend on DRAM speed, but it + seems to be more dependant on the card logic. + + I have the impression that many Cirrus 542x cards suffer from horrible + BIOS version/DRAM timing misconfigurations. Perhaps even some versions of + MS-Windows drivers change the MCLK register. In any case, the boot-up BIOS + default (0x1c) may be inappropriately low for the type of DRAM timing most + cards use. + + Using a higher memory clock gives a very significant performance improvement; + with high dot clock modes (like 640x480x16M or 1150x900x256) performance can + be more than twice that of the standard 50 MHz clock. This goes for both + (VLB) framebuffer access and accelerated features (bitblt). This also helps + XFree86 server performance, but only if the XFree86 Cirrus driver doesn't + set the memory clock register (it should work for XFree86 1.3 and 2.0). + Use at your own risk! + + Note that the 'dot clock' is something entirely different. There does not + seem to be much correlation between the two (i.e. if a high dot clock gives + screen problems, using a high memory clock is not likely to fix it, other + than improving speed). + + */ + + +#define NEW_MCLK 0x1C /* Default value */ + /* #define NEW_MCLK 0x26 *//* High value to test XFree86 */ + + +#include +#include +#include +#include +#include /* For port I/O macros. */ +#define OUTB(a,d) outb(d,a) + +int +main (void) +{ + vga_init (); + if (vga_getcurrentchipset () != CIRRUS) + { + printf ("Not a Cirrus.\n"); + printf ("Continue anyway (y/n)?\n"); + if (getchar () != 'y') + return -1; + } + + /* Unlock extended registers. */ + OUTB (0x3c4, 0x06); + OUTB (0x3c5, 0x12); + + + /* + Tested on VLB AVGA3 CL-GD5426 on 40MHz VLB + 0x1c 50 MHz (boot-up default) + 0x21 59 + 0x22 62 + 0x23 OK + 0x24 OK + 0x25 OK + 0x26 OK [This corresponds to the highest value + mentioned in the databook (which does + not mean that it is supposed to work + on all cards); the book also says the + parts are not specified for more than + 50 MHz]. + 0x27 occasional loose pixels + 0x28 occasional problems + 0x29 some problems + 0x2A 16M/textmode problems + 0x2c 256/32k color problems + */ + OUTB (0x3c4, 0x1f); + printf ("Old MCLK value: %02x\n", inb (0x3c5)); + OUTB (0x3c4, 0x1f); + OUTB (0x3c5, NEW_MCLK); + printf ("New MCLK value: %02x\n", NEW_MCLK); + + return 0; +} diff --git a/utils/svgakeymap b/utils/svgakeymap new file mode 100755 index 0000000..ebdd47d --- /dev/null +++ b/utils/svgakeymap @@ -0,0 +1,98 @@ +#!/usr/bin/perl +# +# svgakeymap - by Brion Vibber (brion@pobox.com), 6/30 - 7/3/1998 +# Generates a keymap conversion file for svgalib from two keytable definitions. +# +# Usage: +# svgakeymap [physical_map [program_map]] > output.keymap +# +# The conversion map is output to stdout; you may wish to redirect it. +# Keymaps are searched for in /usr/lib/kbd/keytables and are automatically +# filtered through gzip if necessary. +# +# Read the file README.keymap from the svgalib distribution for more info. + +$ktd = "/usr/lib/kbd/keytables/"; +if(scalar(@ARGV) > 0) { + $inmap = $ARGV[0]; +} else { + $inmap = "us"; +} +if(scalar(@ARGV) > 1) { + $outmap = $ARGV[1]; +} else { + $outmap = $inmap; +} + + +foreach $bob ($inmap, $outmap) { + #print "$bob\n"; + unless(-e $bob) { + # Tack the keytable dir on it + $bob = $ktd . $bob; + #print "$bob\n"; + + unless(-e $bob) { + # Tack a .gz on it + $bob .= ".map"; + #print "$bob\n"; + + unless(-e $bob) { + # Tack a .gz on it + $bob .= ".gz"; + #print "$bob\n"; + + unless(-e $bob) { + die "Couldn't find $bob\n."; + } + } + } + } +} + +if($inmap =~ m/\.gz$/) { + # Filter thru gzip + open INMAP, "gzip -dc $inmap |" or die "Could not open $inmap!\n"; +} else { + open INMAP, "<$inmap" or die "Could not open $inmap!\n"; +} + +if($outmap =~ m/\.gz$/) { + # Filter thru gzip + open OUTMAP, "gzip -dc $outmap |" or die "Could not open $outmap!\n"; +} else { + open OUTMAP, "<$outmap" or die "Could not open $outmap!\n"; +} + +print "# This is a svgalib scancode conversion map generated by svgakeymap.\n", + "# Read the file README.keymap from the svgalib distribution for more info.\n#\n", + "# Physical keyboard layout: $inmap\n", + "# Program's expected keyboard layout: $outmap\n#\n", + "# physical_scancode program_scancode key_name\n"; + + +while($kc = ) { + if($kc =~ m/^keycode\s+([0-9]+)\s*\=\s*(\S+)/) { + # Store scancodes and names for future reference + #print stderr "- $1 - $2 -\n"; + $keys{$1} = $2; + $keys{$2} = $1; + } else { + # We ignore anything else - including modifiers + } +} + +while($kc = ) { + if($kc =~ m/^keycode\s+([0-9]+)\s*\=\s*(\S+)/) { + if($keys{$2}) { + # Matching scancodes! + #unless($keys{$1} eq $2) { + # Find the other code with the same key... + #print "$1 $keys{$2}\t# $keys{$1} <-> $2\n"; + #print "$1 $keys{$2}\t# $2\n"; + print "$1 $keys{$2} $2\n"; + #} + } + } +} + diff --git a/utils/textmode b/utils/textmode new file mode 100755 index 0000000..bc34a5f --- /dev/null +++ b/utils/textmode @@ -0,0 +1,4 @@ +#!/bin/sh +restoretextmode -r /etc/vga/textregs +restorefont -r /etc/vga/fontdata +restorepalette