home *** CD-ROM | disk | FTP | other *** search
- /* 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.
- */
-
-
- #include <stdlib.h>
- #include <stdio.h>
- #include "vga.h"
- #include "libvga.h"
- #include "driver.h"
-
- #include "timing.h"
- #include "ramdac.h"
- #include "vgaregs.h"
- #include "interface.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_MEMORY_CONTROL ARK_SR10
- #define ARK_VIDEO_CLOCK_SELECT ARK_SR11
- #define ARK_VLBUS_CONTROL ARK_SR12 /* Unused */
- #define ARK_PAGE_ADDRESS_LOW ARK_SR13 /* Unused */
- #define ARK_PAGE_ADDRESS_HIGH ARK_SR14 /* Unused */
- #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 + 18
- #define ARK_TOTAL_REGS VGA_TOTAL_REGS + 18 + 10
-
-
- #define ARK1000PV 1
- #define ARK2000PV 2
-
- static int ark_chip;
- static int ark_memory;
- static CardSpecs *cardspecs;
- static DacMethods *dac_used;
-
- static int ark_init(int, int, int);
-
-
- static void nothing() { }
-
-
- /* Unlock. */
-
- static void ark_unlock() {
- /* Set bit 0 of SR1D. */
- outSR(0x1D, inSR(0x1D) | 0x01);
- }
-
- /* Fill in chipset specific mode information */
-
- static int ark_getmodeinfo( int mode, vga_modeinfo *modeinfo ) {
- 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;
- return 0;
- }
-
-
- /* Return non-zero if mode is available */
-
- static int ark_modeavailable( int mode ) {
- struct info *info;
- ModeInfo *modeinfo;
- ModeTiming *modetiming;
-
- if ((mode < G640x480x256 || mode == G720x348x2)
- && mode != G320x200x256)
- return vga_driverspecs.modeavailable(mode);
-
- /* Enough memory? */
- info = &__svgalib_infotable[mode];
- if (ark_memory * 1024 < info->ydim * info->xbytes)
- return 0;
-
- modeinfo = createModeInfoStructureForSvgalibMode(mode);
-
- modetiming = malloc(sizeof(ModeTiming));
- if (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] = inSR(0x10);
- regs[ARK_SR11] = inSR(0x11);
- regs[ARK_SR15] = inSR(0x15);
- regs[ARK_SR16] = inSR(0x16);
- regs[ARK_SR18] = inSR(0x18);
- regs[ARK_SR19] = inSR(0x19);
- regs[ARK_SR1C] = inSR(0x1C);
- regs[ARK_SR1D] = inSR(0x1D);
-
- regs[ARK_CR40] = inCR(0x40);
- regs[ARK_CR41] = inCR(0x41);
- regs[ARK_CR42] = inCR(0x42);
- regs[ARK_CR44] = inCR(0x44);
- regs[ARK_CR46] = inCR(0x46);
- regs[ARK_CR50] = inCR(0x50);
-
- dac_used->saveState(regs + ARK_DAC_OFFSET);
- return ARK_DAC_OFFSET - VGA_TOTAL_REGS + dac_used->stateSize;
- }
-
-
- /* Set chipset-specific registers */
-
- static int ark_setregs( const unsigned char regs[], int mode )
- {
- ark_unlock();
-
- /* Write extended registers. */
- outSR(0x10, regs[ARK_SR10]);
- outSR(0x11, regs[ARK_SR11]);
- outSR(0x15, regs[ARK_SR15]);
- outSR(0x16, regs[ARK_SR16]);
- outSR(0x18, regs[ARK_SR18]);
- outSR(0x1C, regs[ARK_SR1C]);
- outSR(0x1D, regs[ARK_SR1D]);
-
- outCR(0x40, regs[ARK_CR40]);
- outCR(0x41, regs[ARK_CR41]);
- outCR(0x42, regs[ARK_CR42]);
- outCR(0x44, regs[ARK_CR44]);
- outCR(0x46, regs[ARK_CR46]);
-
- if (dac_used->id == S3_SDAC) {
- unsigned char CR1;
- printf("DAC clock state: 0x%02X 0x%02X\n",
- regs[ARK_DAC_OFFSET + 3],
- regs[ARK_DAC_OFFSET + 4]);
- /* Blank the screen.*/
- CR1 = inCR(0x01);
- outCR(0x01, CR1 | 0x20);
- dac_used->restoreState(regs + ARK_DAC_OFFSET);
- outCR(0x01, CR1); /* Unblank screen. */
- }
- return 0;
- }
-
-
- /*
- * Initialize register state for a mode.
- */
-
- static void ark_initializemode( unsigned char *moderegs,
- ModeTiming *modetiming, ModeInfo *modeinfo) {
-
- /* Get current values. */
- ark_saveregs(moderegs);
-
- /* Set up the standard VGA registers for a generic SVGA. */
- 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[ARK_MEMORY_CONTROL] &= ~0x0F;
- /* VESA Super VGA memory organisation, no COP. */
- moderegs[ARK_MEMORY_CONTROL] |= 0x03;
-
- moderegs[ARK_VIDEO_CLOCK_SELECT] &= ~0x0F;
- /* Set COP and Giant Shift pixel depth. */
- if (modeinfo->bytesPerPixel == 1)
- moderegs[ARK_VIDEO_CLOCK_SELECT] |= 0x5;
- if (modeinfo->bytesPerPixel == 2)
- moderegs[ARK_VIDEO_CLOCK_SELECT] |= 0xA;
- if (modeinfo->bytesPerPixel >= 3)
- moderegs[ARK_VIDEO_CLOCK_SELECT] |= 0xF;
-
- 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) {
- 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->VDisplay - 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_VERTICAL_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_VERTICAL_OVERFLOW] = val;
- }
- moderegs[ARK_VGA_ENHANCEMENT] &= ~0x04; /* No interlace. */
- 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)
- 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;
- }
-
- if (dac_used->id != NORMAL_DAC) {
- dac_used->initializeState(&moderegs[ARK_DAC_OFFSET],
- modeinfo->bitsPerPixel,
- colorbits_to_colormode(modeinfo->colorBits),
- modetiming->pixelClock);
- printf("DAC clock state: 0x%02X 0x%02X\n",
- moderegs[ARK_DAC_OFFSET + 3],
- moderegs[ARK_DAC_OFFSET + 4]);
- }
- }
-
-
- /* Set a mode */
-
- static int ark_setmode( int mode, int prv_mode ) {
- ModeInfo *modeinfo;
- ModeTiming *modetiming;
- unsigned char *moderegs;
-
- if ((mode < G640x480x256 || mode == G720x348x2)
- && mode != G320x200x256)
- /* Let the standard VGA driver set standard VGA modes. */
- return vga_driverspecs.setmode(mode, prv_mode);
- if (!ark_modeavailable(mode))
- return 1;
-
- modeinfo = createModeInfoStructureForSvgalibMode(mode);
-
- modetiming = malloc(sizeof(ModeTiming));
- if (getmodetiming(modetiming, modeinfo, cardspecs)) {
- free(modetiming);
- free(modeinfo);
- return 1;
- }
-
- moderegs = malloc(ARK_TOTAL_REGS);
-
- ark_initializemode(moderegs, modetiming, modeinfo);
- free(modeinfo);
- free(modetiming);
-
- __vga_setregs(moderegs); /* Set standard regs. */
- ark_setregs(moderegs, mode); /* Set extended regs. */
- free(moderegs);
- return 0;
- }
-
-
- /* Indentify chipset; return non-zero if detected */
-
- static int ark_test() {
- if (ark_init(0, 0, 0))
- return 0;
- return 1;
- }
-
-
- /* Bank switching function - set 64K bank number */
-
- static void ark_setpage( int page ) {
- outw(0x3c4, 0x15 + (page << 8)); /* Aperture Write index. */
- outw(0x3c4, 0x16 + (page << 8)); /* Aperture Read index. */
- }
-
-
- /* Set display start address (not for 16 color modes) */
-
- static int ark_setdisplaystart( int address ) {
- outw(0x3d4, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */
- outw(0x3d4, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */
- inb(0x3da); /* set ATC to addressing mode */
- outb(0x3c0, 0x13 + 0x20); /* select ATC reg 0x13 */
- outb(0x3c0, (inb(0x3c1) & 0xf0) | ((address & 3) << 1));
- /* write sa0-1 to bits 1-2 */
- outb(CRT_I, 0x40);
- outb(CRT_D, (address & 0x1C0000) >> 18); /* sa18-sa20 */
- }
-
-
- /* Set logical scanline length (usually multiple of 8) */
- /* Multiples of 8 to 2040 */
-
- static int ark_setlogicalwidth( int width ) {
- outw(0x3d4, 0x13 + (width >> 3) * 256); /* lw3-lw11 */
- outb(CRT_I, 0x41);
- outb(CRT_D, (inb(CRT_D) & ~0x08) | ((width >> 3) & 0x100));
- return 0;
- }
-
-
- /* Function table (exported) */
-
- DriverSpecs ark_driverspecs = {
- ark_saveregs, /* saveregs */
- ark_setregs, /* setregs */
- (int (*)()) nothing, /* unlock */
- (int (*)()) nothing, /* lock */
- ark_test,
- ark_init,
- (int (*)()) ark_setpage,
- (int (*)()) nothing,
- (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,
- 0, /* linear */
- NULL /* accelspecs */
- };
-
-
- /* Initialize driver (called after detection) */
-
- static char *ark_chipname[] = { "ARK1000PV", "ARK2000PV" };
-
- static DacMethods *dacs_to_probe[] = { &S3_SDAC_methods, &normal_dac_methods,
- NULL };
-
- 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 = inCR(0x50) >> 3;
- if (id == 0x12)
- ark_chip = ARK1000PV;
- else
- if (id == 0x13)
- ark_chip = ARK2000PV;
- else {
- printf("svgalib: ark: Unknown chiptype %d.\n",
- ark_chip);
- return -1;
- }
- val = inSR(0x10);
- if ((val & 0xC0) == 0)
- ark_memory = 1024;
- if ((val & 0xC0) == 0x40)
- ark_memory = 2048;
- else
- ark_memory = 4096;
- }
-
- /* Detect DAC. */
-
- #if 1 /* Use 0 to force SDAC. */
- dac_used = probeDacs(dacs_to_probe);
- #else
- dac_used = &S3_SDAC_methods;
- dac_used->initialize();
- #endif
-
- /* begin: Initialize cardspecs. */
- cardspecs = malloc(sizeof(CardSpecs));
- cardspecs->videoMemory = ark_memory;
- cardspecs->maxHorizontalCrtc = 4088;
- cardspecs->nClocks = 0;
- cardspecs->flags = 0;
-
- dac_used->qualifyCardSpecs(cardspecs);
-
- /* Initialize standard clocks for unknown DAC. */
- if (!(dac_used->flags & CLOCK_PROGRAMMABLE)
- && cardspecs->nClocks == 0) {
- 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 (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);
- }
- /* end: Initialize cardspecs. */
-
- if (__svgalib_driver_report) {
- printf("svgalib: Using ARK driver (%s, %dK).\n",
- ark_chipname[ark_chip], ark_memory);
- }
- driverspecs = &ark_driverspecs;
-
- return 0;
- }
-