#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86Pci.h"
#include "xf86PciInfo.h"
#include "xf86Version.h"
#include "xf86Resources.h"
#include "xf86fbman.h"
#include "xf86cmap.h"
#include "compiler.h"
#include "xaa.h"
#include "mipointer.h"
#include "micmap.h"
#include "mibstore.h"
#include "fb.h"
#include "ark.h"
static const OptionInfoRec * ARKAvailableOptions(int chipid, int busid);
static void ARKIdentify(int flags);
static Bool ARKProbe(DriverPtr drv, int flags);
static Bool ARKPreInit(ScrnInfoPtr pScrn, int flags);
static Bool ARKEnterVT(int scrnIndex, int flags);
static void ARKLeaveVT(int scrnIndex, int flags);
static void ARKSave(ScrnInfoPtr pScrn);
static Bool ARKScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
char **argv);
static Bool ARKMapMem(ScrnInfoPtr pScrn);
static void ARKUnmapMem(ScrnInfoPtr pScrn);
static Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
static void ARKAdjustFrame(int scrnIndex, int x, int y, int flags);
Bool ARKSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
Bool ARKCloseScreen(int scrnIndex, ScreenPtr pScreen);
Bool ARKSaveScreen(ScreenPtr pScreen, int mode);
static void ARKFreeScreen(int scrnIndex, int flags);
static void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors,
int *indicies, LOCO *colors,
VisualPtr pVisual);
static void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new);
static unsigned char get_daccomm(IOADDRESS);
static unsigned char set_daccom(IOADDRESS, unsigned char comm);
DriverRec ARK =
{
ARK_VERSION,
DRIVER_NAME,
ARKIdentify,
ARKProbe,
ARKAvailableOptions,
NULL,
0
};
static SymTabRec ARKChipsets[] = {
{ PCI_CHIP_1000PV, "ark1000pv" },
{ PCI_CHIP_2000PV, "ark2000pv" },
{ PCI_CHIP_2000MT, "ark2000mt" },
{ -1, NULL }
};
static PciChipsets ARKPciChipsets[] = {
{ PCI_CHIP_1000PV, PCI_CHIP_1000PV, RES_SHARED_VGA },
{ PCI_CHIP_2000PV, PCI_CHIP_2000PV, RES_SHARED_VGA },
{ PCI_CHIP_2000MT, PCI_CHIP_2000MT, RES_SHARED_VGA },
{ -1, -1, RES_UNDEFINED }
};
typedef enum {
OPTION_NOACCEL
} ARKOpts;
static const OptionInfoRec ARKOptions[] = {
{ OPTION_NOACCEL, "noaccel", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
static const char *fbSymbols[] = {
"fbPictureInit",
"fbScreenInit",
NULL
};
static const char *vgaHWSymbols[] = {
"vgaHWFreeHWRec",
"vgaHWGetHWRec",
"vgaHWGetIOBase",
"vgaHWGetIndex",
"vgaHWInit",
"vgaHWLock",
"vgaHWProtect",
"vgaHWRestore",
"vgaHWSave",
"vgaHWSaveScreen",
"vgaHWUnlock",
"vgaHWUnmapMem",
NULL
};
static const char *xaaSymbols[] = {
"XAACreateInfoRec",
"XAAInit",
NULL
};
#ifdef XFree86LOADER
MODULESETUPPROTO(ARKSetup);
static XF86ModuleVersionInfo ARKVersRec = {
"ark",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{0, 0, 0, 0}
};
XF86ModuleData arkModuleData = { &ARKVersRec, ARKSetup, NULL };
pointer ARKSetup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = FALSE;
if (!setupDone) {
setupDone = TRUE;
xf86AddDriver(&ARK, module, 0);
LoaderRefSymLists(fbSymbols, vgaHWSymbols, xaaSymbols, NULL);
return (pointer) 1;
} else {
if (errmaj)
*errmaj = LDR_ONCEONLY;
return NULL;
}
}
#endif
static Bool ARKGetRec(ScrnInfoPtr pScrn)
{
if (pScrn->driverPrivate)
return TRUE;
pScrn->driverPrivate = xnfcalloc(sizeof(ARKRec), 1);
return TRUE;
}
static void ARKFreeRec(ScrnInfoPtr pScrn)
{
if (!pScrn->driverPrivate)
return;
xfree(pScrn->driverPrivate);
pScrn->driverPrivate = NULL;
}
static const OptionInfoRec * ARKAvailableOptions(int chipid, int busid)
{
return ARKOptions;
}
static void ARKIdentify(int flags)
{
xf86PrintChipsets("ARK", "driver (version " DRIVER_VERSION " for ARK Logic chipset",
ARKChipsets);
}
static Bool ARKProbe(DriverPtr drv, int flags)
{
int i;
GDevPtr *devSections;
int *usedChips;
int numDevSections;
int numUsed;
Bool foundScreen = FALSE;
if ((numDevSections = xf86MatchDevice("ark", &devSections)) <= 0)
return FALSE;
numUsed = xf86MatchPciInstances("ark", PCI_VENDOR_ARK,
ARKChipsets, ARKPciChipsets,
devSections, numDevSections, drv,
&usedChips);
xfree(devSections);
if (numUsed <= 0)
return FALSE;
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else for (i=0; i<numUsed; i++) {
ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0);
pScrn->driverVersion = VERSION_MAJOR;
pScrn->driverName = DRIVER_NAME;
pScrn->name = "ark";
pScrn->Probe = ARKProbe;
pScrn->PreInit = ARKPreInit;
pScrn->ScreenInit = ARKScreenInit;
pScrn->SwitchMode = ARKSwitchMode;
pScrn->AdjustFrame = ARKAdjustFrame;
pScrn->EnterVT = ARKEnterVT;
pScrn->LeaveVT = ARKLeaveVT;
pScrn->FreeScreen = ARKFreeScreen;
foundScreen = TRUE;
xf86ConfigActivePciEntity(pScrn, usedChips[i], ARKPciChipsets,
NULL, NULL, NULL, NULL, NULL);
}
xfree(usedChips);
return foundScreen;
}
static Bool ARKPreInit(ScrnInfoPtr pScrn, int flags)
{
EntityInfoPtr pEnt;
ARKPtr pARK;
vgaHWPtr hwp;
int i;
ClockRangePtr clockRanges;
rgb zeros = {0, 0, 0};
Gamma gzeros = {0.0, 0.0, 0.0};
unsigned char tmp;
if (flags & PROBE_DETECT)
return FALSE;
if (!xf86LoadSubModule(pScrn, "vgahw"))
return FALSE;
xf86LoaderReqSymLists(vgaHWSymbols, NULL);
if (!vgaHWGetHWRec(pScrn))
return FALSE;
hwp = VGAHWPTR(pScrn);
vgaHWGetIOBase(hwp);
pScrn->monitor = pScrn->confScreen->monitor;
if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb))
return FALSE;
else {
switch (pScrn->depth) {
case 8:
case 16:
case 24:
case 32:
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given depth (%d) is not supported by this driver\n",
pScrn->depth);
return FALSE;
}
}
xf86PrintDepthBpp(pScrn);
if (pScrn->depth > 8) {
if (!xf86SetWeight(pScrn, zeros, zeros))
return FALSE;
}
if (pScrn->depth == 8)
pScrn->rgbBits = 8;
if (!xf86SetDefaultVisual(pScrn, -1))
return FALSE;
pScrn->progClock = TRUE;
if (!ARKGetRec(pScrn))
return FALSE;
pARK = ARKPTR(pScrn);
xf86CollectOptions(pScrn, NULL);
if (!(pARK->Options = xalloc(sizeof(ARKOptions))))
return FALSE;
memcpy(pARK->Options, ARKOptions, sizeof(ARKOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pARK->Options);
if (xf86ReturnOptValBool(pARK->Options, OPTION_NOACCEL, FALSE)) {
pARK->NoAccel = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - acceleration disabled\n");
} else
pARK->NoAccel = FALSE;
if (pScrn->numEntities > 1) {
ARKFreeRec(pScrn);
return FALSE;
}
pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (pEnt->resources) {
xfree(pEnt);
ARKFreeRec(pScrn);
return FALSE;
}
pARK->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
xf86RegisterResources(pEnt->index, NULL, ResNone);
xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr);
xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr);
if (pEnt->device->chipset && *pEnt->device->chipset) {
pScrn->chipset = pEnt->device->chipset;
pARK->Chipset = xf86StringToToken(ARKChipsets, pScrn->chipset);
} else if (pEnt->device->chipID >= 0) {
pARK->Chipset = pEnt->device->chipID;
pScrn->chipset = (char *)xf86TokenToString(ARKChipsets,
pARK->Chipset);
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
pARK->Chipset);
} else {
pARK->Chipset = pARK->PciInfo->chipType;
pScrn->chipset = (char *)xf86TokenToString(ARKChipsets,
pARK->Chipset);
}
if (pEnt->device->chipRev >= 0) {
pARK->ChipRev = pEnt->device->chipRev;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
pARK->ChipRev);
} else
pARK->ChipRev = pARK->PciInfo->chipRev;
xfree(pEnt);
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Chipset: \"%s\"\n", pScrn->chipset);
pARK->PciTag = pciTag(pARK->PciInfo->bus, pARK->PciInfo->device,
pARK->PciInfo->func);
outb(hwp->PIOOffset + hwp->IOBase + 4, 0x11);
tmp = inb(hwp->PIOOffset + hwp->IOBase + 5);
outb(hwp->PIOOffset + hwp->IOBase + 5, tmp & 0x7f);
modinx(hwp->PIOOffset + 0x3c4, 0x1d, 0x01, 0x01);
pARK->FBAddress = (rdinx(hwp->PIOOffset + 0x3c4, 0x13) << 16) +
(rdinx(hwp->PIOOffset + 0x3c4, 0x14) << 24);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer @ 0x%lx\n",
(unsigned long)pARK->FBAddress);
if (!xf86SetGamma(pScrn, gzeros))
return FALSE;
if (!pScrn->videoRam) {
unsigned char sr10;
sr10 = rdinx(hwp->PIOOffset + 0x3c4, 0x10);
if (pARK->Chipset == PCI_CHIP_1000PV) {
if ((sr10 & 0x40) == 0)
pScrn->videoRam = 1024;
else
pScrn->videoRam = 2048;
}
if (pARK->Chipset == PCI_CHIP_2000PV ||
pARK->Chipset == PCI_CHIP_2000MT) {
if ((sr10 & 0xc0) == 0)
pScrn->videoRam = 1024;
else if ((sr10 & 0xc0) == 0x40)
pScrn->videoRam = 2048;
else
pScrn->videoRam = 4096;
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected %d bytes video ram\n",
pScrn->videoRam);
}
{
int man_id, dev_id;
inb(hwp->PIOOffset + 0x3c6);
man_id = inb(hwp->PIOOffset + 0x3c6);
dev_id = inb(hwp->PIOOffset + 0x3c6);
if (man_id == 0x84 && dev_id == 0x98) {
pARK->ramdac = ZOOMDAC;
pARK->dac_width = 16;
pARK->multiplex_threshold = 40000;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Detected ZOOMDAC\n");
}
}
pARK->ramdac = ATT490;
pARK->dac_width = 8;
pARK->clock_mult = 1;
if (pARK->dac_width == 16) {
if (pScrn->bitsPerPixel == 32)
pARK->clock_mult = 2;
}
pScrn->numClocks = 1;
pScrn->clock[0] = 80000;
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
clockRanges->next = NULL;
clockRanges->minClock = 20000;
clockRanges->maxClock = 80000;
clockRanges->clockIndex = -1;
clockRanges->interlaceAllowed = FALSE;
clockRanges->doubleScanAllowed = FALSE;
i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
pScrn->display->modes, clockRanges,
NULL, 256, 2048, pScrn->bitsPerPixel,
128, 2048, pScrn->display->virtualX,
pScrn->display->virtualY, pARK->videoRam * 1024,
LOOKUP_BEST_REFRESH);
if (i == -1) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes left\n");
ARKFreeRec(pScrn);
return FALSE;
}
xf86PruneDriverModes(pScrn);
if (i == 0 || pScrn->modes == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes found\n");
ARKFreeRec(pScrn);
return FALSE;
}
xf86SetCrtcForModes(pScrn, 0);
pScrn->currentMode = pScrn->modes;
xf86PrintModes(pScrn);
xf86SetDpi(pScrn, 0, 0);
if (!xf86LoadSubModule(pScrn, "fb")) {
ARKFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(fbSymbols, NULL);
if (!pARK->NoAccel) {
if (!xf86LoadSubModule(pScrn, "xaa")) {
ARKFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(xaaSymbols, NULL);
}
return TRUE;
}
static Bool ARKScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
char **argv)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
ARKPtr pARK = ARKPTR(pScrn);
pScrn->fbOffset = 0;
if (!ARKMapMem(pScrn)) {
ARKFreeRec(pScrn);
return FALSE;
}
ARKSave(pScrn);
vgaHWBlankScreen(pScrn, TRUE);
if (!ARKModeInit(pScrn, pScrn->currentMode))
return FALSE;
ARKSaveScreen(pScreen, SCREEN_SAVER_ON);
pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
miClearVisualTypes();
if (pScrn->bitsPerPixel > 8) {
if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
pScrn->rgbBits, pScrn->defaultVisual))
return FALSE;
} else {
if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
pScrn->rgbBits, pScrn->defaultVisual))
return FALSE;
}
miSetPixmapDepths ();
if (!fbScreenInit(pScreen, pARK->FBBase, pScrn->virtualX,
pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
pScrn->displayWidth, pScrn->bitsPerPixel))
return FALSE;
xf86SetBlackWhitePixels(pScreen);
if (pScrn->bitsPerPixel > 8) {
VisualPtr pVis;
pVis = pScreen->visuals + pScreen->numVisuals;
while (--pVis >= pScreen->visuals) {
if ((pVis->class | DynamicClass) == DirectColor) {
pVis->offsetRed = pScrn->offset.red;
pVis->offsetGreen = pScrn->offset.green;
pVis->offsetBlue = pScrn->offset.blue;
pVis->redMask = pScrn->mask.red;
pVis->greenMask = pScrn->mask.green;
pVis->blueMask = pScrn->mask.blue;
}
}
}
fbPictureInit (pScreen, 0, 0);
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
if (!pARK->NoAccel) {
if (ARKAccelInit(pScreen)) {
xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
} else {
xf86DrvMsg(scrnIndex, X_ERROR, "Acceleration initialization failed\n");
xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
}
} else {
xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
}
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
if (!miCreateDefColormap(pScreen))
return FALSE;
if (!xf86HandleColormaps(pScreen, 256, 8, ARKLoadPalette, NULL,
CMAP_RELOAD_ON_MODE_SWITCH))
return FALSE;
vgaHWBlankScreen(pScrn, FALSE);
pScreen->SaveScreen = ARKSaveScreen;
pARK->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = ARKCloseScreen;
return TRUE;
}
static void ARKSave(ScrnInfoPtr pScrn)
{
ARKPtr pARK = ARKPTR(pScrn);
ARKRegPtr save = &pARK->SavedRegs;
vgaHWPtr hwp = VGAHWPTR(pScrn);
IOADDRESS isaIOBase = hwp->PIOOffset;
IOADDRESS vgaIOBase = isaIOBase + hwp->IOBase;
vgaHWUnlock(hwp);
vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
vgaHWLock(hwp);
wrinx(isaIOBase + 0x3c4, 0x15, 0x00);
wrinx(isaIOBase + 0x3c4, 0x16, 0x00);
outb(isaIOBase + 0x3c8, 0);
save->sr10 = rdinx(isaIOBase + 0x3c4, 0x10);
save->sr11 = rdinx(isaIOBase + 0x3c4, 0x11);
save->sr12 = rdinx(isaIOBase + 0x3c4, 0x12);
save->sr13 = rdinx(isaIOBase + 0x3c4, 0x13);
save->sr14 = rdinx(isaIOBase + 0x3c4, 0x14);
save->sr15 = rdinx(isaIOBase + 0x3c4, 0x15);
save->sr16 = rdinx(isaIOBase + 0x3c4, 0x16);
save->sr17 = rdinx(isaIOBase + 0x3c4, 0x17);
save->sr18 = rdinx(isaIOBase + 0x3c4, 0x18);
#if 0
save->sr1d = rdinx(isaIOBase + 0x3c4, 0x1d);
save->sr1c = rdinx(isaIOBase + 0x3c4, 0x1c);
save->sr20 = rdinx(isaIOBase + 0x3c4, 0x20);
save->sr21 = rdinx(isaIOBase + 0x3c4, 0x21);
save->sr22 = rdinx(isaIOBase + 0x3c4, 0x22);
save->sr23 = rdinx(isaIOBase + 0x3c4, 0x23);
save->sr24 = rdinx(isaIOBase + 0x3c4, 0x24);
save->sr25 = rdinx(isaIOBase + 0x3c4, 0x25);
save->sr26 = rdinx(isaIOBase + 0x3c4, 0x26);
save->sr27 = rdinx(isaIOBase + 0x3c4, 0x27);
save->sr29 = rdinx(isaIOBase + 0x3c4, 0x29);
save->sr2a = rdinx(isaIOBase + 0x3c4, 0x2a);
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT)) {
save->sr28 = rdinx(isaIOBase + 0x3c4, 0x28);
save->sr2b = rdinx(isaIOBase + 0x3c4, 0x2b);
}
#endif
save->cr40 = rdinx(vgaIOBase + 4, 0x40);
save->cr41 = rdinx(vgaIOBase + 4, 0x41);
save->cr42 = rdinx(vgaIOBase + 4, 0x42);
save->cr44 = rdinx(vgaIOBase + 4, 0x44);
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT))
save->cr46 = rdinx(vgaIOBase + 4, 0x46);
save->dac_command = get_daccomm(isaIOBase);
}
static Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
ARKPtr pARK = ARKPTR(pScrn);
ARKRegPtr new = &pARK->ModeRegs;
int multiplexing, dac16, modepitch;
vgaHWPtr hwp = VGAHWPTR(pScrn);
vgaRegPtr pVga = &hwp->ModeReg;
IOADDRESS isaIOBase = hwp->PIOOffset;
IOADDRESS vgaIOBase = isaIOBase + hwp->IOBase;
unsigned char tmp;
int offset;
multiplexing = 0;
if ((pScrn->bitsPerPixel == 8) && (pARK->dac_width == 16) &&
(mode->Clock > pARK->multiplex_threshold))
multiplexing = 1;
if (pARK->clock_mult == 2) {
if (!mode->CrtcHAdjusted) {
mode->CrtcHDisplay <<= 1;
mode->CrtcHSyncStart <<= 1;
mode->CrtcHSyncEnd <<= 1;
mode->CrtcHTotal <<= 1;
mode->CrtcHSkew <<= 1;
mode->CrtcHAdjusted = TRUE;
}
}
if (multiplexing) {
if (!mode->CrtcHAdjusted) {
mode->CrtcHDisplay >>= 1;
mode->CrtcHSyncStart >>= 1;
mode->CrtcHSyncEnd >>= 1;
mode->CrtcHTotal >>= 1;
mode->CrtcHSkew >>= 1;
mode->CrtcHAdjusted = TRUE;
}
}
if (!vgaHWInit(pScrn, mode))
return FALSE;
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT)) {
new->cr46 = rdinx(vgaIOBase + 4, 0x46) & ~0x04;
dac16 = 0;
if (pScrn->bitsPerPixel > 8)
dac16 = 1;
if (dac16)
new->cr46 |= 0x04;
}
offset = (pScrn->displayWidth * (pScrn->bitsPerPixel / 8)) >> 3;
pVga->CRTC[0x13] = offset;
new->cr41 = (offset & 0x100) >> 5;
new->sr11 = 0x90;
switch (pScrn->bitsPerPixel) {
case 8:
new->sr11 |= 0x06;
break;
case 16:
new->sr11 |= 0x0a;
break;
case 24:
new->sr11 |= 0x06;
break;
case 32:
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT))
new->sr11 |= 0x0e;
else
new->sr11 |= 0x0a;
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Unsupported screen depth %d\n",
pScrn->bitsPerPixel);
return FALSE;
}
switch (pScrn->displayWidth) {
case 640:
modepitch = 0;
break;
case 800:
modepitch = 1;
break;
case 1024:
modepitch = 2;
break;
case 1280:
modepitch = 4;
break;
case 1600:
modepitch = 5;
break;
case 2048:
modepitch = 6;
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Unsupported screen width %d\n",
pScrn->displayWidth);
return FALSE;
}
new->sr17 &= ~0xc7;
new->sr17 |= modepitch;
new->sr10 = rdinx(isaIOBase + 0x3c4, 0x10) & ~0x1f;
new->sr10 |= 0x1f;
new->sr13 = pARK->FBAddress >> 16;
new->sr14 = pARK->FBAddress >> 24;
new->sr12 = rdinx(isaIOBase + 0x3c4, 0x12) & ~0x03;
switch (pScrn->videoRam) {
case 1024:
new->sr12 |= 0x01;
break;
case 2048:
new->sr12 |= 0x02;
break;
case 4096:
new->sr12 |= 0x03;
break;
default:
new->sr12 |= 0x01;
break;
}
new->sr15 = new->sr16 = 0;
tmp = 0;
if ((mode->CrtcVTotal - 2) & 0x400)
tmp |= 0x80;
if ((mode->CrtcVDisplay - 1) & 0x400)
tmp |= 0x40;
if (mode->CrtcVSyncStart & 0x400)
tmp |= 0x10;
new->cr40 = tmp;
tmp = new->cr41;
if ((mode->CrtcHTotal / 8 - 5) & 0x100)
tmp |= 0x80;
if ((mode->CrtcHDisplay / 8 - 1) & 0x100)
tmp |= 0x40;
if ((mode->CrtcHSyncStart / 8 - 1) & 0x100)
tmp |= 0x20;
if ((mode->CrtcHSyncStart / 8) & 0x100)
tmp |= 0x10;
new->cr41 |= tmp;
new->cr44 = rdinx(vgaIOBase + 4, 0x44) & ~0x34;
new->cr44 &= ~0x01;
new->cr42 = 0;
{
int threshold;
int bandwidthused, percentused;
bandwidthused = (mode->Clock / pARK->clock_mult) *
(pScrn->bitsPerPixel / 8);
percentused = (bandwidthused * 100) / 120000;
tmp = rdinx(isaIOBase + 0x3c4, 0x18);
if (pARK->Chipset == PCI_CHIP_1000PV) {
threshold = 4;
tmp |= 0x08;
tmp &= ~0x07;
tmp |= threshold;
}
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT)) {
threshold = 12;
if (percentused >= 45)
threshold = 8;
if (percentused >= 70)
threshold = 4;
tmp &= 0x40;
tmp |= 0x10;
tmp |= (threshold & 0x0e) >> 1;
if (threshold & 0x01)
tmp |= 0x80;
if (threshold & 0x10)
tmp |= 0x20;
}
new->sr18 = tmp;
}
if (pARK->ramdac == ZOOMDAC) {
new->dac_command = 0x04;
if ((pScrn->bitsPerPixel == 8) && multiplexing)
new->dac_command = 0x24;
if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 16))
new->dac_command = 0x34;
if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 8))
new->dac_command = 0x64;
if ((pScrn->bitsPerPixel == 24) && (pARK->dac_width == 16))
new->dac_command = 0xb4;
if ((pScrn->bitsPerPixel == 32) && (pARK->dac_width == 16))
new->dac_command = 0x54;
} else if (pARK->ramdac == ATT490) {
new->dac_command = 0x00;
if (pScrn->bitsPerPixel == 16)
new->dac_command = 0xc0;
if (pScrn->bitsPerPixel == 24)
new->dac_command = 0xe0;
}
#if 0
new->sr20 = rdinx(isaIOBase + 0x3c4, 0x20);
new->sr21 = rdinx(isaIOBase + 0x3c4, 0x21);
new->sr22 = rdinx(isaIOBase + 0x3c4, 0x22);
new->sr23 = rdinx(isaIOBase + 0x3c4, 0x23);
new->sr24 = rdinx(isaIOBase + 0x3c4, 0x24);
new->sr25 = rdinx(isaIOBase + 0x3c4, 0x25);
new->sr26 = rdinx(isaIOBase + 0x3c4, 0x26);
new->sr27 = rdinx(isaIOBase + 0x3c4, 0x27);
new->sr29 = rdinx(isaIOBase + 0x3c4, 0x29);
new->sr2a = rdinx(isaIOBase + 0x3c4, 0x2a);
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT)) {
new->sr28 = rdinx(isaIOBase + 0x3c4, 0x28);
new->sr2b = rdinx(isaIOBase + 0x3c4, 0x3b);
}
#endif
ARKWriteMode(pScrn, pVga, new);
return TRUE;
}
static void ARKAdjustFrame(int scrnIndex, int x, int y, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
ARKPtr pARK = ARKPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
IOADDRESS vgaIOBase = hwp->PIOOffset + hwp->IOBase;
int base;
base = ((y * pScrn->displayWidth + x) *
(pScrn->bitsPerPixel / 8));
if (((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT)) &&
(pScrn->videoRam >= 2048))
base >>= 3;
else
base >>= 2;
if (pScrn->bitsPerPixel == 24)
base -= base % 3;
outw(vgaIOBase + 4, (base & 0x00ff00) | 0x0c);
outw(vgaIOBase + 4, ((base & 0x00ff) << 8) | 0x0d);
modinx(vgaIOBase + 4, 0x40, 0x07, (base & 0x070000) >> 16);
}
static void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new)
{
ARKPtr pARK = ARKPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
IOADDRESS isaIOBase = hwp->PIOOffset;
IOADDRESS vgaIOBase = isaIOBase + hwp->IOBase;
vgaHWProtect(pScrn, TRUE);
wrinx(isaIOBase + 0x3c4, 0x15, 0x00);
wrinx(isaIOBase + 0x3c4, 0x16, 0x00);
wrinx(isaIOBase + 0x3c4, 0x10, new->sr10);
wrinx(isaIOBase + 0x3c4, 0x11, new->sr11);
wrinx(isaIOBase + 0x3c4, 0x12, new->sr12);
wrinx(isaIOBase + 0x3c4, 0x13, new->sr13);
wrinx(isaIOBase + 0x3c4, 0x14, new->sr14);
wrinx(isaIOBase + 0x3c4, 0x15, new->sr15);
wrinx(isaIOBase + 0x3c4, 0x16, new->sr16);
wrinx(isaIOBase + 0x3c4, 0x17, new->sr17);
#if 0
wrinx(isaIOBase + 0x3c4, 0x1c, new->sr1c);
wrinx(isaIOBase + 0x3c4, 0x1d, new->sr1d);
wrinx(isaIOBase + 0x3c4, 0x20, new->sr20);
wrinx(isaIOBase + 0x3c4, 0x21, new->sr21);
wrinx(isaIOBase + 0x3c4, 0x22, new->sr22);
wrinx(isaIOBase + 0x3c4, 0x23, new->sr23);
wrinx(isaIOBase + 0x3c4, 0x24, new->sr24);
wrinx(isaIOBase + 0x3c4, 0x25, new->sr25);
wrinx(isaIOBase + 0x3c4, 0x26, new->sr26);
wrinx(isaIOBase + 0x3c4, 0x27, new->sr27);
wrinx(isaIOBase + 0x3c4, 0x29, new->sr29);
wrinx(isaIOBase + 0x3c4, 0x2a, new->sr2a);
#endif
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT)) {
wrinx(isaIOBase + 0x3c4, 0x28, new->sr28);
wrinx(isaIOBase + 0x3c4, 0x2B, new->sr2b);
}
wrinx(vgaIOBase + 4, 0x40, new->cr40);
wrinx(vgaIOBase + 4, 0x41, new->cr41);
wrinx(vgaIOBase + 4, 0x42, new->cr42);
wrinx(vgaIOBase + 4, 0x44, new->cr44);
if ((pARK->Chipset == PCI_CHIP_2000PV) ||
(pARK->Chipset == PCI_CHIP_2000MT))
wrinx(vgaIOBase + 4, 0x46, new->cr46);
if (pARK->ramdac == ZOOMDAC) {
set_daccom(isaIOBase, new->dac_command);
}
if (xf86IsPrimaryPci(pARK->PciInfo))
vgaHWRestore(pScrn, pVga, VGA_SR_ALL);
else
vgaHWRestore(pScrn, pVga, VGA_SR_MODE);
vgaHWProtect(pScrn, FALSE);
}
static Bool ARKEnterVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
if (!ARKModeInit(pScrn, pScrn->currentMode))
return FALSE;
ARKAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
return TRUE;
}
static void ARKLeaveVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
ARKPtr pARK = ARKPTR(pScrn);
ARKRegPtr old = &pARK->SavedRegs;
vgaHWPtr hwp = VGAHWPTR(pScrn);
ARKWriteMode(pScrn, &hwp->ModeReg, old);
vgaHWUnlock(hwp);
vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
vgaHWLock(hwp);
}
static Bool ARKMapMem(ScrnInfoPtr pScrn)
{
ARKPtr pARK = ARKPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
hwp->MapSize = 0x20000;
pARK->MMIOBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO,
pARK->PciTag, 0xb8000, 0x8000);
pARK->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
pARK->PciTag, pARK->FBAddress,
pScrn->videoRam * 1024);
if (!pARK->FBBase) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Cound not map framebuffer\n");
return FALSE;
}
return TRUE;
}
static void ARKUnmapMem(ScrnInfoPtr pScrn)
{
ARKPtr pARK = ARKPTR(pScrn);
vgaHWUnmapMem(pScrn);
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pARK->FBBase,
pScrn->videoRam * 1024);
}
Bool ARKCloseScreen(int scrnIndex, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
ARKPtr pARK = ARKPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
if (pScrn->vtSema) {
vgaHWUnlock(hwp);
ARKWriteMode(pScrn, &hwp->SavedReg, &pARK->SavedRegs);
vgaHWLock(hwp);
ARKUnmapMem(pScrn);
}
pScrn->vtSema = FALSE;
pScreen->CloseScreen = pARK->CloseScreen;
return (*pScreen->CloseScreen)(scrnIndex, pScreen);
}
Bool ARKSaveScreen(ScreenPtr pScreen, int mode)
{
return vgaHWSaveScreen(pScreen, mode);
}
Bool ARKSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
return ARKModeInit(xf86Screens[scrnIndex], mode);
}
static void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors,
int *indicies, LOCO *colors,
VisualPtr pVisual)
{
IOADDRESS isaIOBase = pScrn->domainIOBase;
int i, index;
for (i=0; i<numColors; i++) {
index = indicies[i];
outb(isaIOBase + 0x3c8, index);
outb(isaIOBase + 0x3c9, colors[index].red);
outb(isaIOBase + 0x3c9, colors[index].green);
outb(isaIOBase + 0x3c9, colors[index].blue);
}
}
static void ARKFreeScreen(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
vgaHWFreeHWRec(pScrn);
ARKFreeRec(pScrn);
}
static unsigned char get_daccomm(IOADDRESS isaIOBase)
{
unsigned char tmp;
outb(isaIOBase + 0x3c8, 0);
inb(isaIOBase + 0x3c6);
inb(isaIOBase + 0x3c6);
inb(isaIOBase + 0x3c6);
inb(isaIOBase + 0x3c6);
tmp = inb(isaIOBase + 0x3c6);
outb(isaIOBase + 0x3c8, 0);
return tmp;
}
static unsigned char set_daccom(IOADDRESS isaIOBase, unsigned char comm)
{
#if 0
outb(isaIOBase + 0x3c8, 0);
#else
inb(isaIOBase + 0x3c8);
#endif
inb(isaIOBase + 0x3c6);
inb(isaIOBase + 0x3c6);
inb(isaIOBase + 0x3c6);
inb(isaIOBase + 0x3c6);
outb(isaIOBase + 0x3c6, comm);
#if 0
outb(isaIOBase + 0x3c8, 0);
#else
inb(isaIOBase + 0x3c8);
#endif
return inb(isaIOBase + 0x3c6);
}