SvgaLib/obsolete/mach/mach64.c

1092 lines
30 KiB
C
Raw Normal View History

/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#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]);
}
}