/* 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 #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" #ifdef OSKIT #include "osenv.h" #endif /* 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 VESA 0 #define PCI 1 static 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 unsigned char *mmio_base; 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], 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 ((mode < G640x480x256 || mode == G720x348x2) && mode != G320x200x256) #else if (mode < G640x480x256 || mode == G720x348x2) #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) { 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 void 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(__svgalib_CRT_I, 0x40); outb(__svgalib_CRT_D, (address & 0x1C0000) >> 18); /* sa18-sa20 */ } /* Set logical scanline length (usually multiple of 8) */ /* Multiples of 8 to 2040 */ static void ark_setlogicalwidth(int width) { outw(0x3d4, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ outb(__svgalib_CRT_I, 0x41); outb(__svgalib_CRT_D, (inb(__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); 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); return 0; } if (op == LINEAR_QUERY_BASE) { if (ark_bus == PCI && param == 0) /* Return PCI base address. */ return ark_baseaddress; if (ark_bus == VESA) { 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. */ } /* 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 */ }; /* 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) { /* * 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_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 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 { printf("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) { /* Not supported. */ printf("svgalib: ark: Assuming normal VGA DAC.\n"); #ifdef INCLUDE_NORMAL_DAC dac_used = &__svgalib_normal_dac_methods; #else printf("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. */ #ifdef OSKIT osenv_mem_map_phys(0xB8000, 4096, &mmio_base, 0); #else mmio_base = valloc(4096); mmap(mmio_base, 4096, PROT_WRITE, MAP_FIXED | MAP_SHARED, __svgalib_mem_fd, 0xB8000); #endif if (__svgalib_driver_report) { char *bustype; if (__svgalib_inSR(0x19) & 0x80) { ark_bus = VESA; bustype = "VL bus"; } else { ark_bus = PCI; bustype = "PCI"; ark_baseaddress = (__svgalib_inSR(0x13) << 16) + (__svgalib_inSR(0x14) << 24); } printf("svgalib: Using ARK driver (%s, %dK, %s).", ark_chipname[ark_chip], ark_memory, bustype); if (ark_bus == PCI) printf(" Base address = 0x%08X.", ark_baseaddress); printf("\n"); } __svgalib_driverspecs = &__svgalib_ark_driverspecs; 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_base + BACKGROUNDCOLOR) = c; #define SETFOREGROUNDCOLOR(c) \ *(unsigned short *)(mmio_base + FOREGROUNDCOLOR) = c; #define SETCOLORMIXSELECT(m) \ *(unsigned short *)(mmio_base + COLORMIXSELECT) = m; #define SETWRITEPLANEMASK(m) \ *(unsigned short *)(mmio_base + WRITEPLANEMASK) = m; #define SETSTENCILPITCH(p) \ *(unsigned short *)(mmio_base + STENCILPITCH) = p; #define SETSOURCEPITCH(p) \ *(unsigned short *)(mmio_base + SOURCEPITCH) = p; #define SETDESTPITCH(p) \ *(unsigned short *)(mmio_base + DESTPITCH) = p; #define SETSTENCILADDR(p) \ *(unsigned int *)(mmio_base + STENCILADDR) = p; #define SETSOURCEADDR(p) \ *(unsigned int *)(mmio_base + SOURCEADDR) = p; #define SETSOURCEXY(x, y) \ *(unsigned int *)(mmio_base + SOURCEADDR) = (y << 16) + x; #define SETSOURCEX(x) \ *(unsigned short *)(mmio_base + SOURCEX) = x; #define SETSOURCEY(y) \ *(unsigned short *)(mmio_base + SOURCEY) = y; #define SETDESTADDR(p) \ *(unsigned int *)(mmio_base + DESTADDR) = p; #define SETDESTXY(x, y) \ *(unsigned int *)(mmio_base + DESTADDR) = (y << 16) + x; #define SETDESTX(x) \ *(unsigned short *)(mmio_base + DESTX) = x; #define SETDESTY(y) \ *(unsigned short *)(mmio_base + DESTY) = y; #define SETWIDTH(p) \ *(unsigned short *)(mmio_base + WIDTH) = p - 1; #define SETHEIGHT(p) \ *(unsigned short *)(mmio_base + HEIGHT) = p - 1; #define SETBITMAPCONFIG(p) \ *(unsigned short *)(mmio_base + BITMAPCONFIG) = p; #define SETCOMMAND(p) \ *(unsigned short *)(mmio_base + COMMAND) = p; #define COPISBUSY() (inb(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; }