📄 ark.c
字号:
/* 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 <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/mman.h>#include <signal.h>#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 1static int ark_chip;static int ark_memory;static int ark_bus;static int ark_baseaddress; /* 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 ((mode < G640x480x256 || mode == G720x348x2) && mode != G320x200x256) {#else if (mode < G640x480x256 || mode == G720x348x2) {#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; if ((__svgalib_inSR(0x12) & 0x03) != 0) modeinfo->flags |= IS_LINEAR;}/* Return non-zero if mode is available */static int ark_modeavailable(int mode){ struct info *info; ModeInfo *modeinfo; ModeTiming *modetiming;#ifdef SVGA_STYLE_320x200x256 if ((mode < G640x480x256 || mode == G720x348x2) && mode != G320x200x256)#else if (mode < G640x480x256 || mode == G720x348x2)#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); inb(0x3C8); regs[ARK_PELMASK] = inb(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]); inb(0x3C8); outb(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. */ 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; 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) { 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) 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],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -