summaryrefslogtreecommitdiff
path: root/QemuVGADriver/src
diff options
context:
space:
mode:
Diffstat (limited to 'QemuVGADriver/src')
-rw-r--r--QemuVGADriver/src/DriverDoDriverIO.c603
-rw-r--r--QemuVGADriver/src/DriverGestaltHandler.c45
-rw-r--r--QemuVGADriver/src/DriverQDCalls.c629
-rw-r--r--QemuVGADriver/src/DriverQDCalls.h42
-rw-r--r--QemuVGADriver/src/QemuVga.c267
-rw-r--r--QemuVGADriver/src/QemuVga.h54
-rw-r--r--QemuVGADriver/src/VideoDriver.exp2
-rw-r--r--QemuVGADriver/src/VideoDriverPrivate.h79
-rw-r--r--QemuVGADriver/src/VideoDriverPrototypes.h105
9 files changed, 1826 insertions, 0 deletions
diff --git a/QemuVGADriver/src/DriverDoDriverIO.c b/QemuVGADriver/src/DriverDoDriverIO.c
new file mode 100644
index 0000000..38f861a
--- /dev/null
+++ b/QemuVGADriver/src/DriverDoDriverIO.c
@@ -0,0 +1,603 @@
+/* Simple PCI video driver for use with Mac-On-Linux emulator
+ *
+ * Basically, this driver forward Apple video driver calls to
+ * the emulator via a fake HW (and later, a "sc" based API).
+*/
+
+#include "VideoDriverPrivate.h"
+#include "VideoDriverPrototypes.h"
+#include "DriverQDCalls.h"
+#include "QemuVga.h"
+
+DriverDescription TheDriverDescription = {
+ /*
+ * Signature info
+ */
+ kTheDescriptionSignature, /* OSType driverDescSignature */
+ kInitialDriverDescriptor, /* DriverDescVersion driverDescVersion */
+ QEMU_PCI_VIDEO_NAME,
+ 0x01, 0x01,
+ 0, 0,
+ /*
+ * DriverOSRuntime driverOSRuntimeInfo
+ */
+ 0 /* RuntimeOptions driverRuntime */
+ | (0 * kDriverIsLoadedUponDiscovery) /* Loader runtime options */
+ | (1 * kDriverIsOpenedUponLoad) /* Opened when loaded */
+ | (1 * kDriverIsUnderExpertControl) /* I/O expert handles loads/opens */
+ | (01 * kDriverIsConcurrent) /* concurrent */
+ | (0 * kDriverQueuesIOPB), /* Internally queued */
+ QEMU_PCI_VIDEO_PNAME, /* Str31 driverName (OpenDriver param) */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* UInt32 driverDescReserved[8] */
+ /*
+ * DriverOSService Information. This section contains a vector count followed by
+ * a vector of structures, each defining a driver service.
+ */
+ 1, /* ServiceCount nServices */
+ /*
+ * DriverServiceInfo service[0]
+ */
+ kServiceCategoryNdrvDriver, /* OSType serviceCategory */
+ kNdrvTypeIsVideo, /* OSType serviceType */
+ 1, 0, 0, 0
+};
+
+#pragma internal on
+
+/*
+ * All driver-global information is in a structure defined in NCRDriverPrivate.
+ * Note that "modern" drivers do not have access to their dce. In native Power PC
+ * environments, the global world is created by the Code Fragment Manager (hmm,
+ * perhaps it is created by CFMInitialize).
+ */
+DriverGlobal gDriverGlobal;
+
+/*
+ * DoDriverIO
+ *
+ * In the new driver environment, DoDriverIO performs all driver
+ * functions. It is called with the following parameters:
+ * IOCommandID A unique reference for this driver request. In
+ * the emulated environment, this will be the ParamBlkPtr
+ * passed in from the Device Manager.
+ *
+ * IOCommandContents A union structure that contains information for the
+ * specific request. For the emulated environment, this
+ * will contain the following:
+ * Initialize Driver RefNum and the name registry id for this driver.
+ * Finalize Driver RefNum and the name registry id for this driver.
+ * Others The ParamBlkPtr
+ *
+ * IOCommandCode A switch value that specifies the required function.
+ *
+ * IOCommandKind A bit-mask indicating Synchronous, Asynchronous, and Immediate
+ *
+ * For Synchronous and Immediate commands, DoDriverIO returns the final status to
+ * the Device Manager. For Asynchronous commands, DoDriverIO may return kIOBusyStatus.
+ * If it returns busy status, the driver promises to call IOCommandIsComplete when
+ * the transaction has completed.
+ */
+#pragma internal off
+
+OSStatus
+DoDriverIO( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, IOCommandContents ioCommandContents,
+ IOCommandCode ioCommandCode, IOCommandKind ioCommandKind )
+{
+ OSStatus status;
+
+ /*
+ * Note: Initialize, Open, KillIO, Close, and Finalize are either synchronous
+ * or immediate. Read, Write, Control, and Status may be immediate,
+ * synchronous, or asynchronous.
+ */
+
+ Trace(DoDriverIO);
+
+ switch( ioCommandCode ) {
+ case kInitializeCommand: /* Always immediate */
+ status = DriverInitializeCmd(addressSpaceID, ioCommandContents.initialInfo);
+ CheckStatus(status, "Initialize failed");
+ break;
+ case kFinalizeCommand: /* Always immediate */
+ status = DriverFinalizeCmd(ioCommandContents.finalInfo);
+ break;
+ case kSupersededCommand:
+ status = DriverSupersededCmd(ioCommandContents.supersededInfo, FALSE);
+ break;
+ case kReplaceCommand: /* replace an old driver */
+ status = DriverReplaceCmd(addressSpaceID, ioCommandContents.replaceInfo);
+ break;
+ case kOpenCommand: /* Always immediate */
+ status = DriverOpenCmd(addressSpaceID, ioCommandContents.pb);
+ break;
+ case kCloseCommand: /* Always immediate */
+ status = DriverCloseCmd(ioCommandContents.pb);
+ break;
+ case kControlCommand:
+ /* lprintf("kControlCommand\n"); */
+ status = DriverControlCmd( addressSpaceID, ioCommandID, ioCommandKind,
+ (CntrlParam*)ioCommandContents.pb );
+ break;
+ case kStatusCommand:
+ /* lprintf("kStatusCommand\n"); */
+ status = DriverStatusCmd( ioCommandID, ioCommandKind,
+ (CntrlParam *)ioCommandContents.pb );
+ break;
+ case kReadCommand:
+ status = DriverReadCmd( addressSpaceID, ioCommandID, ioCommandKind,
+ ioCommandContents.pb );
+ break;
+ case kWriteCommand:
+ status = DriverWriteCmd( addressSpaceID, ioCommandID, ioCommandKind,
+ ioCommandContents.pb);
+ break;
+ case kKillIOCommand: /* Always immediate */
+ status = DriverKillIOCmd(ioCommandContents.pb);
+ break;
+ default:
+ status = paramErr;
+ break;
+ }
+ /*
+ * Force a valid result for immediate commands -- they must return a valid
+ * status to the Driver Manager: returning kIOBusyStatus would be a bug..
+ * Non-immediate commands return a status from the lower-level routine. If the
+ * status is kIOBusyStatus, we just return -- an asynchronous I/O completion
+ * routine will eventually complete the request. If it's some other status, the
+ * lower-level routine has completed a non-immediate task, so we call
+ * IOCommandIsComplete and return its (presumably noErr) status.
+ */
+ if( (ioCommandKind & kImmediateIOCommandKind) != 0 ) {
+ ; /* Immediate commands return the operation status */
+ }
+ else if (status == ioInProgress) {
+ /*
+ * An asynchronous operation is in progress. The driver handler promises
+ * to call IOCommandIsComplete when the operation concludes.
+ */
+ status = noErr;
+ } else {
+ /*
+ * Normal command that completed synchronously. Dequeue the user's
+ * parameter block.
+ */
+ status = (OSStatus)IOCommandIsComplete(ioCommandID, (OSErr)status);
+ }
+ return status;
+}
+
+#pragma internal on
+
+/*
+ * DriverInitializeCmd
+ *
+ * The New Driver Manager calls this when the driver is first opened.
+ */
+OSStatus
+DriverInitializeCmd( AddressSpaceID addressSpaceID, DriverInitInfoPtr driverInitInfoPtr )
+{
+ OSStatus status;
+
+ Trace(DriverInitializeCmd);
+
+ GLOBAL.refNum = driverInitInfoPtr->refNum;
+ GLOBAL.openCount = 0;
+ GLOBAL.inInterrupt = false;
+ GLOBAL.hasTimer = false;
+
+ RegistryEntryIDInit( &GLOBAL.deviceEntry );
+ status = RegistryEntryIDCopy( &driverInitInfoPtr->deviceEntry, &GLOBAL.deviceEntry );
+ if( status != noErr )
+ return status;
+
+ GLOBAL.isOpen = false;
+ GLOBAL.qdInterruptsEnable = false;
+ GLOBAL.qdVBLInterrupt = NULL;
+
+ GLOBAL.boardFBAddress = GetDeviceBARAddress(&GLOBAL.deviceEntry,
+ QEMU_PCI_VIDEO_BASE_REG,
+ &GLOBAL.boardFBMappedSize,
+ NULL);
+ if (GLOBAL.boardFBAddress == NULL) {
+ status = paramErr;
+ goto bail;
+ }
+ lprintf("boardFBAddress %08lX boardFBMappedSize %08lX\n",
+ GLOBAL.boardFBAddress, GLOBAL.boardFBMappedSize);
+
+ GLOBAL.boardRegAddress = GetDeviceBARAddress(&GLOBAL.deviceEntry,
+ QEMU_PCI_VIDEO_MMIO_REG,
+ &GLOBAL.boardRegMappedSize,
+ NULL);
+ if (GLOBAL.boardRegAddress == NULL) {
+ status = paramErr;
+ goto bail;
+ }
+ lprintf("boardRegAddress %08lX boardRegMappedSize %08lX\n",
+ GLOBAL.boardRegAddress, GLOBAL.boardRegMappedSize);
+
+
+ status = EnablePCIMemorySpace(&GLOBAL.deviceEntry);
+ if (status != noErr) {
+ lprintf("EnablePCIMemorySpace returned %d\n", status);
+ goto bail;
+ }
+
+ status = QemuVga_Init();
+
+bail:
+ DBG(lprintf("Driver init result: %d\n", status));
+
+ return status;
+}
+
+/*
+ * DriverReplaceCmd
+ *
+ * We are replacing an existing driver -- or are completing an initialization sequence.
+ * Retrieve any state information from the Name Registry (we have none), install
+ * our interrupt handlers, and activate the device.
+ *
+ * We don't use the calledFromInitialize parameter, but it's here so that a driver can
+ * distinguish between initialization (fetch only the NVRAM parameter) and replacement
+ * (fetch state information that may be left-over from the previous incantation).
+ */
+OSStatus
+DriverReplaceCmd( AddressSpaceID addressSpaceID, DriverReplaceInfoPtr driverReplaceInfoPtr )
+{
+ OSStatus status;
+
+ Trace(DriverReplaceCmd);
+
+ GLOBAL.refNum = driverReplaceInfoPtr->refNum;
+ GLOBAL.deviceEntry = driverReplaceInfoPtr->deviceEntry;
+
+ status = DriverInitializeCmd(addressSpaceID, driverReplaceInfoPtr);
+
+ return status;
+}
+
+/*
+ * DriverFinalizeCmd
+ *
+ * Process a DoDriverIO finalize command.
+ */
+OSStatus
+DriverFinalizeCmd( DriverFinalInfoPtr driverFinalInfoPtr )
+{
+ Trace(DriverFinializeCmd);
+ (void) DriverSupersededCmd((DriverSupersededInfoPtr) driverFinalInfoPtr, TRUE);
+ return noErr;
+}
+
+/*
+ * DriverSupersededCmd
+ *
+ * We are shutting down, or being replaced by a later driver. Wait for all I/O to
+ * complete and store volatile state in the Name Registry whree it will be retrieved
+ * by our replacement.
+ */
+OSStatus
+DriverSupersededCmd( DriverSupersededInfoPtr driverSupersededInfoPtr, Boolean calledFromFinalize )
+{
+ Trace(DriverSupersededCmd);
+
+ /*
+ * This duplicates DriverKillIOCmd, the correct algorithm would wait for
+ * concurrent I/O to complete. Hmm, what about "infinite wait" I/O, such
+ * as would be posted by a modem server or socket listener? Note that
+ * this section needs to be extended to handle all pending requests.
+ *
+ * It's safe to call CompleteThisRequest, as that routine uses an atomic
+ * operation that allows it to be called when no request is pending without
+ * any possible problems. Since it's a secondary interrupt handler, we
+ * need to call it through the Driver Services Library.
+ *
+ * Warning: GLOBAL.perRequestDataPtr will be NULL if initialization fails
+ * and the Driver Manager tries to terminate us. When we permit concurrent
+ * requests, this will loop on all per-request records.
+ */
+
+ QemuVga_Exit();
+
+ RegistryEntryIDDispose( &GLOBAL.deviceEntry );
+
+ return noErr;
+}
+
+/*
+ * DriverControlCmd
+ *
+ * Process a PBControl command.
+ */
+OSStatus
+DriverControlCmd( AddressSpaceID addressSpaceID, IOCommandID ioCommandID,
+ IOCommandKind ioCommandKind, CntrlParam *pb )
+{
+ OSStatus status;
+ void *genericPtr;
+
+ /* The 'csParam' field of the 'CntrlParam' stucture is defined as 'short csParam[11]'. This is
+ * meant for 'operation defined parameters.' For the graphics driver, only the first 4 bytes are
+ * used. They are used as a pointer to another structure.
+ * To help code readability, the pointer will be extracted as a generic 'void *' and then cast as
+ * appropriate.
+ */
+
+ genericPtr = (void *) *((UInt32 *) &(pb->csParam[0]));
+
+ Trace(DriverControlCmd);
+
+ switch( pb->csCode ) {
+ case cscReset: // Old obsolete call..return a 'controlErr'
+ status = controlErr;
+ break;
+
+ case cscKillIO: // Old obsolete call..do nothing
+ status = controlErr;
+ break;
+
+ case cscSetMode:
+ status = GraphicsCoreSetMode((VDPageInfo *) genericPtr);
+ break;
+
+ case cscSetEntries:
+ status = GraphicsCoreSetEntries((VDSetEntryRecord *) genericPtr);
+ // if ((status == noErr)&&(GLOBAL.qdDeskServiceCreated)&&(ioCommandKind == kSynchronousIOCommandKind))
+ // VSLWaitOnInterruptService(GLOBAL.qdVBLInterrupt, 1000);
+ break;
+
+ case cscSetGamma:
+ status = GraphicsCoreSetGamma((VDGammaRecord *) genericPtr);
+ break;
+
+ case cscGrayPage:
+ status = GraphicsCoreGrayPage((VDPageInfo *) genericPtr);
+ break;
+
+ case cscSetGray:
+ status = GraphicsCoreSetGray((VDGrayRecord *) genericPtr);
+ break;
+
+ case cscSetInterrupt:
+ status = GraphicsCoreSetInterrupt((VDFlagRecord *) genericPtr);
+ break;
+
+ case cscDirectSetEntries:
+ status = GraphicsCoreDirectSetEntries((VDSetEntryRecord *) genericPtr);
+ break;
+
+ case cscSetDefaultMode:
+ status = controlErr;
+ break;
+
+ case cscSwitchMode:
+ status = GraphicsCoreSwitchMode((VDSwitchInfoRec *) genericPtr);
+ break;
+
+ case cscSetSync:
+ status = GraphicsCoreSetSync((VDSyncInfoRec *) genericPtr);
+ break;
+
+ case cscSavePreferredConfiguration:
+ status = GraphicsCoreSetPreferredConfiguration((VDSwitchInfoRec *) genericPtr);
+ break;
+
+ case cscSetHardwareCursor:
+ status = GraphicsCoreSetHardwareCursor((VDSetHardwareCursorRec *) genericPtr);
+ break;
+
+ case cscDrawHardwareCursor:
+ status = GraphicsCoreDrawHardwareCursor((VDDrawHardwareCursorRec *) genericPtr);
+ break;
+ case cscSetPowerState:
+ status = GraphicsCoreSetPowerState((VDPowerStateRec *) genericPtr);
+ break;
+ default:
+ status = controlErr;
+ break;
+ }
+ if( status )
+ status = controlErr;
+
+ return status;
+}
+
+/*
+ * DriverStatusCmd
+ *
+ * Process a PBStatus command. We support the driver gestalt call and our private
+ * debugging commands.
+ */
+OSStatus
+DriverStatusCmd( IOCommandID ioCommandID, IOCommandKind ioCommandKind, CntrlParam *pb )
+{
+ OSStatus status;
+ void *genericPtr;
+
+ /* The 'csParam' field of the 'CntrlParam' stucture is defined as 'short csParam[11]'. This is
+ * meant for 'operation defined parameters.' For the graphics driver, only the first 4 bytes are
+ * used. They are used as a pointer to another structure.
+ * To help code readability, the pointer will be extracted as a generic 'void *' and then cast as
+ * appropriate.
+ */
+
+ genericPtr = (void *) *((UInt32 *) &(pb->csParam[0]));
+
+ Trace(DriverStatusCmd);
+
+ switch( pb->csCode ) {
+ case cscGetMode:
+ status = GraphicsCoreGetMode((VDPageInfo *) genericPtr);
+ break;
+
+ case cscGetEntries:
+ status = GraphicsCoreGetEntries((VDSetEntryRecord *) genericPtr);
+ break;
+
+ case cscGetPages:
+ status = GraphicsCoreGetPages((VDPageInfo *) genericPtr);
+ break;
+
+ case cscGetBaseAddr:
+ status = GraphicsCoreGetBaseAddress((VDPageInfo *) genericPtr);
+ break;
+
+ case cscGetGray:
+ status = GraphicsCoreGetGray((VDGrayRecord *) genericPtr);
+ break;
+
+ case cscGetInterrupt:
+ status = GraphicsCoreGetInterrupt((VDFlagRecord *) genericPtr);
+ break;
+
+ case cscGetGamma:
+ status = GraphicsCoreGetGamma((VDGammaRecord *) genericPtr);
+ break;
+
+ case cscGetDefaultMode:
+ status = statusErr;
+ break;
+
+ case cscGetCurMode:
+ status = GraphicsCoreGetCurrentMode((VDSwitchInfoRec *) genericPtr);
+ break;
+
+ case cscGetSync:
+ status = GraphicsCoreGetSync((VDSyncInfoRec *) genericPtr);
+ break;
+
+ case cscGetConnection:
+ status = GraphicsCoreGetConnection((VDDisplayConnectInfoRec *) genericPtr);
+ break;
+
+ case cscGetModeTiming:
+ status = GraphicsCoreGetModeTiming((VDTimingInfoRec *) genericPtr);
+ break;
+
+ case cscGetPreferredConfiguration:
+ status = GraphicsCoreGetPreferredConfiguration((VDSwitchInfoRec *) genericPtr);
+ break;
+
+ case cscGetNextResolution:
+ status = GraphicsCoreGetNextResolution((VDResolutionInfoRec *) genericPtr);
+ break;
+
+ case cscGetVideoParameters:
+ status = GraphicsCoreGetVideoParams((VDVideoParametersInfoRec *) genericPtr);
+ break;
+
+ case cscGetGammaInfoList:
+ status = GraphicsCoreGetGammaInfoList((VDGetGammaListRec *) genericPtr);
+ break;
+
+ case cscRetrieveGammaTable:
+ status = GraphicsCoreRetrieveGammaTable((VDRetrieveGammaRec *) genericPtr);
+ break;
+
+ case cscSupportsHardwareCursor:
+ status = GraphicsCoreSupportsHardwareCursor((VDSupportsHardwareCursorRec *) genericPtr);
+ break;
+
+ case cscGetHardwareCursorDrawState:
+ status = GraphicsCoreGetHardwareCursorDrawState((VDHardwareCursorDrawStateRec *) genericPtr);
+ break;
+
+ case kDriverGestaltCode:
+ status = DriverGestaltHandler(pb);
+ break;
+
+ case cscGetPowerState:
+ status = GraphicsCoreGetPowerState((VDPowerStateRec *) genericPtr);
+ break;
+
+ default:
+ status = statusErr;
+ break;
+ }
+ if( status )
+ status = statusErr;
+
+ return status;
+}
+
+/*
+ * DriverKillIOCmd stops all I/O for this chip. It's a big hammer, use it wisely.
+ * This will need revision when we support concurrent I/O as we must stop all
+ * pending requests.
+ */
+OSStatus
+DriverKillIOCmd( ParmBlkPtr pb )
+{
+#define REQUEST (GLOBAL.perRequestData)
+
+ Trace(DriverKillIOCmd);
+ return noErr;
+#undef REQUEST
+}
+
+/*
+ * DriverReadCmd
+ *
+ * The caller passes the data buffer and buffer length in the IOParam record and
+ * a pointer to a SCSI NCRSCSIParam in the ioMisc field.
+ */
+OSStatus
+DriverReadCmd( AddressSpaceID addressSpaceID, IOCommandID ioCommandID,
+ IOCommandKind ioCommandKind, ParmBlkPtr pb )
+{
+ Trace(DriverReadCmd);
+ return paramErr;
+}
+
+
+/*
+ * DriverWriteCmd
+ *
+ * The caller passes the data buffer and buffer length in the IOParam record and
+ * a pointer to a SCSI NCRSCSIParam in the ioMisc field.
+ */
+OSStatus
+DriverWriteCmd( AddressSpaceID addressSpaceID, IOCommandID ioCommandID,
+ IOCommandKind ioCommandKind, ParmBlkPtr pb )
+{
+ Trace(DriverWriteCmd);
+ return paramErr;
+}
+
+/*
+ * DriverCloseCmd does nothing..
+ */
+OSStatus
+DriverCloseCmd( ParmBlkPtr pb )
+{
+ Trace(DriverCloseCmd);
+
+ if( !GLOBAL.openCount )
+ return notOpenErr;
+
+ GLOBAL.openCount--;
+
+ if (!GLOBAL.openCount)
+ QemuVga_Close();
+
+ return noErr;
+}
+
+/*
+ * DriverOpenCmd does nothing: remember that many applications will open a device, but
+ * never close it..
+ */
+OSStatus
+DriverOpenCmd( AddressSpaceID addressSpaceID, ParmBlkPtr pb )
+{
+ Trace(DriverOpenCmd);
+
+ GLOBAL.openCount++;
+ if (GLOBAL.openCount == 1)
+ QemuVga_Open();
+
+ return noErr;
+}
+
+
diff --git a/QemuVGADriver/src/DriverGestaltHandler.c b/QemuVGADriver/src/DriverGestaltHandler.c
new file mode 100644
index 0000000..ca37874
--- /dev/null
+++ b/QemuVGADriver/src/DriverGestaltHandler.c
@@ -0,0 +1,45 @@
+#include "VideoDriverPrivate.h"
+#include "VideoDriverPrototypes.h"
+
+/*
+ * Called on PBStatus, csCode = 43
+ */
+OSStatus
+DriverGestaltHandler( CntrlParam *pb )
+{
+#define PB (*((DriverGestaltParam *) pb))
+#define OPTIONS (TheDriverDescription.driverOSRuntimeInfo)
+
+ OSStatus status;
+ Trace(DriverGestaltHandler);
+
+ PB.driverGestaltResponse = 0;
+ status = noErr;
+
+ switch( PB.driverGestaltSelector ) {
+ case kdgSync:
+ PB.driverGestaltResponse = FALSE; /* We handle asynchronous I/O */
+ break;
+ case kdgVersion:
+ PB.driverGestaltResponse =
+ *((UInt32 *) &TheDriverDescription.driverType.version);
+ break;
+ case kdgDeviceType:
+ PB.driverGestaltResponse = 'QEMU';
+ break;
+ case kdgInterface:
+ PB.driverGestaltResponse = 'pci ';
+ break;
+ case kdgSupportsSwitching: /* Support Power up/down switching? */
+ PB.driverGestaltResponse = FALSE; /* Not supported yet */
+ break;
+ case kdgSupportsPowerCtl: /* TRUE if in high-power mode */
+ PB.driverGestaltResponse = FALSE; /* Power-switching is not supported */
+ break;
+ default:
+ status = statusErr;
+ break;
+ }
+ return status;
+#undef PB
+}
diff --git a/QemuVGADriver/src/DriverQDCalls.c b/QemuVGADriver/src/DriverQDCalls.c
new file mode 100644
index 0000000..2383643
--- /dev/null
+++ b/QemuVGADriver/src/DriverQDCalls.c
@@ -0,0 +1,629 @@
+#include "VideoDriverPrivate.h"
+#include "VideoDriverPrototypes.h"
+#include "DriverQDCalls.h"
+#include "QemuVga.h"
+
+static OSStatus GraphicsCoreDoSetEntries(VDSetEntryRecord *entryRecord, Boolean directDevice, UInt32 start, UInt32 stop, Boolean useValue);
+
+/************************ Color Table Stuff ****************************/
+
+OSStatus
+GraphicsCoreSetEntries(VDSetEntryRecord *entryRecord)
+{
+ Boolean useValue = (entryRecord->csStart < 0);
+ UInt32 start = useValue ? 0UL : (UInt32)entryRecord->csStart;
+ UInt32 stop = start + entryRecord->csCount;
+
+ Trace(GraphicsCoreSetEntries);
+
+ return GraphicsCoreDoSetEntries(entryRecord, false, start, stop, useValue);
+}
+
+OSStatus
+GraphicsCoreDirectSetEntries(VDSetEntryRecord *entryRecord)
+{
+ Boolean useValue = (entryRecord->csStart < 0);
+ UInt32 start = useValue ? 0 : entryRecord->csStart;
+ UInt32 stop = start + entryRecord->csCount;
+
+ Trace(GraphicsCoreDirectSetEntries);
+
+ return GraphicsCoreDoSetEntries(entryRecord, true, start, stop, useValue);
+}
+
+OSStatus
+GraphicsCoreDoSetEntries(VDSetEntryRecord *entryRecord, Boolean directDevice, UInt32 start, UInt32 stop, Boolean useValue)
+{
+ UInt32 i;
+
+ CHECK_OPEN( controlErr );
+ if (GLOBAL.depth != 8)
+ return controlErr;
+ if (NULL == entryRecord->csTable)
+ return controlErr;
+// if (directDevice != (VMODE.depth != 8))
+// return controlErr;
+
+ /* Note that stop value is included in the range */
+ for(i=start;i<=stop;i++) {
+ UInt32 tabIndex = i-start;
+ UInt32 colorIndex = useValue ? entryRecord->csTable[tabIndex].value : tabIndex;
+ QemuVga_SetColorEntry(colorIndex, &entryRecord->csTable[tabIndex].rgb);
+ }
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetEntries(VDSetEntryRecord *entryRecord)
+{
+ Boolean useValue = (entryRecord->csStart < 0);
+ UInt32 start = useValue ? 0UL : (UInt32)entryRecord->csStart;
+ UInt32 stop = start + entryRecord->csCount;
+ UInt32 i;
+
+ Trace(GraphicsCoreGetEntries);
+
+ for(i=start;i<=stop;i++) {
+ UInt32 tabIndex = i-start;
+ UInt32 colorIndex = useValue ? entryRecord->csTable[tabIndex].value : tabIndex;
+ QemuVga_GetColorEntry(colorIndex, &entryRecord->csTable[tabIndex].rgb);
+ }
+
+ return noErr;
+}
+
+/************************ Gamma ****************************/
+
+OSStatus
+GraphicsCoreSetGamma(VDGammaRecord *gammaRec)
+{
+ CHECK_OPEN( controlErr );
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetGammaInfoList(VDGetGammaListRec *gammaList)
+{
+ Trace(GraphicsCoreGammaInfoList);
+
+ return statusErr;
+}
+
+OSStatus
+GraphicsCoreRetrieveGammaTable(VDRetrieveGammaRec *gammaRec)
+{
+ Trace(GraphicsCoreRetrieveGammaTable);
+
+ return statusErr;
+}
+
+OSStatus
+GraphicsCoreGetGamma(VDGammaRecord *gammaRecord)
+{
+ CHECK_OPEN( statusErr );
+
+ Trace(GraphicsCoreGetGamma);
+
+ gammaRecord->csGTable = NULL;
+
+ return noErr;
+}
+
+
+/************************ Gray pages ****************************/
+
+OSStatus
+GraphicsCoreGrayPage(VDPageInfo *pageInfo)
+{
+ CHECK_OPEN( controlErr );
+
+ Trace(GraphicsCoreGrayPage);
+
+ if (pageInfo->csPage != 0)
+ return paramErr;
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreSetGray(VDGrayRecord *grayRecord)
+{
+ CHECK_OPEN( controlErr );
+
+ Trace(GraphicsCoreSetGray);
+
+ GLOBAL.qdLuminanceMapping = grayRecord->csMode;
+ return noErr;
+}
+
+
+OSStatus
+GraphicsCoreGetPages(VDPageInfo *pageInfo)
+{
+/* DepthMode mode; */
+ CHECK_OPEN( statusErr );
+
+ Trace(GraphicsCoreGetPages);
+
+ pageInfo->csPage = 1;
+ return noErr;
+}
+
+
+OSStatus
+GraphicsCoreGetGray(VDGrayRecord *grayRecord)
+{
+ CHECK_OPEN( statusErr );
+
+ Trace(GraphicsCoreGetGray);
+
+ grayRecord->csMode = (GLOBAL.qdLuminanceMapping);
+
+ return noErr;
+}
+
+/************************ Hardware Cursor ****************************/
+
+OSStatus
+GraphicsCoreSupportsHardwareCursor(VDSupportsHardwareCursorRec *hwCursRec)
+{
+ CHECK_OPEN( statusErr );
+
+ Trace(GraphicsCoreSupportsHardwareCursor);
+
+ hwCursRec->csReserved1 = 0;
+ hwCursRec->csReserved2 = 0;
+
+ hwCursRec->csSupportsHardwareCursor = false;
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreSetHardwareCursor(VDSetHardwareCursorRec *setHwCursRec)
+{
+ Trace(GraphicsCoreSetHardwareCursor);
+
+ return controlErr;
+}
+
+OSStatus
+GraphicsCoreDrawHardwareCursor(VDDrawHardwareCursorRec *drawHwCursRec)
+{
+ Trace(GraphicsCoreDrawHardwareCursor);
+
+ return controlErr;
+}
+
+OSStatus
+GraphicsCoreGetHardwareCursorDrawState(VDHardwareCursorDrawStateRec *hwCursDStateRec)
+{
+ Trace(GraphicsCoreGetHardwareCursorDrawState);
+
+ return statusErr;
+}
+
+/************************ Misc ****************************/
+
+OSStatus
+GraphicsCoreSetInterrupt(VDFlagRecord *flagRecord)
+{
+ CHECK_OPEN( controlErr );
+
+ Trace(GraphicsCoreSetInterrupt);
+
+ if (!flagRecord->csMode)
+ QemuVga_EnableInterrupts();
+ else
+ QemuVga_DisableInterrupts();
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetInterrupt(VDFlagRecord *flagRecord)
+{
+ Trace(GraphicsCoreGetInterrupt);
+
+ CHECK_OPEN( statusErr );
+
+ flagRecord->csMode = !GLOBAL.qdInterruptsEnable;
+ return noErr;
+}
+
+/* assume initial state is always "power-on" */
+// XXX FIXME
+static unsigned long MOLVideoPowerState = kAVPowerOn;
+
+OSStatus
+GraphicsCoreSetSync(VDSyncInfoRec *syncInfo)
+{
+ unsigned char syncmask;
+ unsigned long newpowermode;
+
+ Trace(GraphicsCoreSetSync);
+
+ CHECK_OPEN( controlErr );
+
+ syncmask = (!syncInfo->csFlags)? kDPMSSyncMask: syncInfo->csFlags;
+ if (!(syncmask & kDPMSSyncMask)) /* nothing to do */
+ return noErr;
+ switch (syncInfo->csMode & syncmask) {
+ case kDPMSSyncOn:
+ newpowermode = kAVPowerOn;
+ break;
+ case kDPMSSyncStandby:
+ newpowermode = kAVPowerStandby;
+ break;
+ case kDPMSSyncSuspend:
+ newpowermode = kAVPowerSuspend;
+ break;
+ case kDPMSSyncOff:
+ newpowermode = kAVPowerOff;
+ break;
+ default:
+ return paramErr;
+ }
+ if (newpowermode != MOLVideoPowerState) {
+ //OSI_SetVPowerState(newpowermode);
+ MOLVideoPowerState = newpowermode;
+ }
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetSync(VDSyncInfoRec *syncInfo)
+{
+ CHECK_OPEN( statusErr );
+
+ Trace(GraphicsCoreGetSync);
+
+ if (syncInfo->csMode == 0xff) {
+ /* report back the capability */
+ syncInfo->csMode = 0 | ( 1 << kDisableHorizontalSyncBit)
+ | ( 1 << kDisableVerticalSyncBit)
+ | ( 1 << kDisableCompositeSyncBit);
+ } else if (syncInfo->csMode == 0) {
+ /* current sync mode */
+ switch (MOLVideoPowerState) {
+ case kAVPowerOn:
+ syncInfo->csMode = kDPMSSyncOn;
+ break;
+ case kAVPowerStandby:
+ syncInfo->csMode = kDPMSSyncStandby;
+ break;
+ case kAVPowerSuspend:
+ syncInfo->csMode = kDPMSSyncSuspend;
+ break;
+ case kAVPowerOff:
+ syncInfo->csMode = kDPMSSyncOff;
+ break;
+ }
+ } else /* not defined ? */
+ return paramErr;
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreSetPowerState(VDPowerStateRec *powerStateRec)
+{
+ Trace(GraphicsCoreSetPowerState);
+
+ CHECK_OPEN( controlErr );
+
+ if (powerStateRec->powerState > kAVPowerOn)
+ return paramErr;
+
+ if (MOLVideoPowerState != powerStateRec->powerState) {
+ //OSI_SetVPowerState(powerStateRec->powerState);
+ MOLVideoPowerState = powerStateRec->powerState;
+ }
+ powerStateRec->powerFlags = 0;
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetPowerState(VDPowerStateRec *powerStateRec)
+{
+ Trace(GraphicsCoreGetPowerState);
+
+ CHECK_OPEN( statusErr );
+
+ powerStateRec->powerState = MOLVideoPowerState;
+ powerStateRec->powerFlags = 0;
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreSetPreferredConfiguration(VDSwitchInfoRec *switchInfo)
+{
+ Trace(GraphicsCoreSetPreferredConfiguration);
+
+ CHECK_OPEN( controlErr );
+
+ return noErr;
+}
+
+static UInt8 DepthToDepthMode(UInt8 depth)
+{
+ switch (depth) {
+ case 8:
+ return kDepthMode1;
+ case 15:
+ case 16:
+ return kDepthMode2;
+ default:
+ return kDepthMode3;
+ }
+}
+
+static UInt8 DepthModeToDepth(UInt8 mode)
+{
+ switch (mode) {
+ case kDepthMode1:
+ return 8;
+ case kDepthMode2:
+ return 15;
+ default:
+ return 32;
+ }
+}
+
+OSStatus
+GraphicsCoreGetPreferredConfiguration(VDSwitchInfoRec *switchInfo)
+{
+ Trace(GraphicsCoreGetPreferredConfiguration);
+
+ CHECK_OPEN( statusErr );
+
+ switchInfo->csMode = DepthToDepthMode(GLOBAL.bootDepth);
+ switchInfo->csData = GLOBAL.bootMode + 1; /* Modes are 1 based */
+ switchInfo->csPage = 0;
+ switchInfo->csBaseAddr = FB_START;
+
+ return noErr;
+}
+
+// €***************** Misc status calls *********************/
+
+OSStatus
+GraphicsCoreGetBaseAddress(VDPageInfo *pageInfo)
+{
+ Trace(GraphicsCoreGetBaseAddress);
+
+ CHECK_OPEN( statusErr );
+
+ if (pageInfo->csPage != 0)
+ return paramErr;
+
+ pageInfo->csBaseAddr = FB_START;
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetConnection(VDDisplayConnectInfoRec *connectInfo)
+{
+ Trace(GraphicsCoreGetConnection);
+
+ CHECK_OPEN( statusErr );
+
+ connectInfo->csDisplayType = kVGAConnect;
+ connectInfo->csConnectTaggedType = 0;
+ connectInfo->csConnectTaggedData = 0;
+
+ connectInfo->csConnectFlags =
+ (1 << kTaggingInfoNonStandard) | (1 << kUncertainConnection);
+
+ connectInfo->csDisplayComponent = 0;
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetMode(VDPageInfo *pageInfo)
+{
+ Trace(GraphicsCoreGetMode);
+
+ CHECK_OPEN( statusErr );
+
+ //lprintf("GetMode\n");
+ pageInfo->csMode = DepthToDepthMode(GLOBAL.depth);
+ pageInfo->csPage = 0;
+ pageInfo->csBaseAddr = FB_START;
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetCurrentMode(VDSwitchInfoRec *switchInfo)
+{
+ Trace(GraphicsCoreGetCurrentMode);
+
+ CHECK_OPEN( statusErr );
+
+ //lprintf("GetCurrentMode\n");
+ switchInfo->csMode = DepthToDepthMode(GLOBAL.depth);
+ switchInfo->csData = GLOBAL.curMode + 1;
+ switchInfo->csPage = 0;
+ switchInfo->csBaseAddr = FB_START;
+
+ return noErr;
+}
+
+/********************** Video mode *****************************/
+
+OSStatus
+GraphicsCoreGetModeTiming(VDTimingInfoRec *timingInfo)
+{
+ Trace(GraphicsCoreGetModeTiming);
+
+ CHECK_OPEN( statusErr );
+
+ if (timingInfo->csTimingMode < 1 || timingInfo->csTimingMode > GLOBAL.numModes )
+ return paramErr;
+
+ timingInfo->csTimingFlags =
+ (1 << kModeValid) | (1 << kModeDefault) | (1 <<kModeSafe);
+
+ timingInfo->csTimingFormat = kDeclROMtables;
+ timingInfo->csTimingData = timingVESA_640x480_60hz;
+
+ return noErr;
+}
+
+
+OSStatus
+GraphicsCoreSetMode(VDPageInfo *pageInfo)
+{
+ Trace(GraphicsCoreSetMode);
+
+ CHECK_OPEN(controlErr);
+
+ if (pageInfo->csPage != 0)
+ return paramErr;
+
+ QemuVga_SetMode(GLOBAL.curMode, DepthModeToDepth(pageInfo->csMode));
+ pageInfo->csBaseAddr = FB_START;
+
+ return noErr;
+}
+
+
+OSStatus
+GraphicsCoreSwitchMode(VDSwitchInfoRec *switchInfo)
+{
+ UInt32 newMode, newDepth;
+
+ Trace(GraphicsCoreSwitchMode);
+
+ CHECK_OPEN(controlErr);
+
+ if (switchInfo->csPage != 0)
+ return paramErr;
+
+ newMode = switchInfo->csData - 1;
+ newDepth = DepthModeToDepth(switchInfo->csMode);
+
+ if (newMode != GLOBAL.curMode || newDepth != GLOBAL.depth) {
+ if (QemuVga_SetMode(newMode, newDepth))
+ return controlErr;
+ }
+ switchInfo->csBaseAddr = FB_START;
+
+ return noErr;
+}
+
+OSStatus
+GraphicsCoreGetNextResolution(VDResolutionInfoRec *resInfo)
+{
+ UInt32 width, height;
+ int id = resInfo->csPreviousDisplayModeID;
+
+ Trace(GraphicsCoreGetNextResolution);
+
+ CHECK_OPEN(statusErr);
+
+ if (id == kDisplayModeIDFindFirstResolution)
+ id = 0;
+ else if (id == kDisplayModeIDCurrent)
+ id = GLOBAL.curMode;
+ id++;
+
+ if (id == GLOBAL.numModes + 1) {
+ resInfo->csDisplayModeID = kDisplayModeIDNoMoreResolutions;
+ return noErr;
+ }
+ if (id < 1 || id > GLOBAL.numModes)
+ return paramErr;
+
+ if (QemuVga_GetModeInfo(id - 1, &width, &height))
+ return paramErr;
+
+ resInfo->csDisplayModeID = id;
+ resInfo->csHorizontalPixels = width;
+ resInfo->csVerticalLines = height;
+ resInfo->csRefreshRate = 60;
+ resInfo->csMaxDepthMode = kDepthMode3; /* XXX Calculate if it fits ! */
+
+ return noErr;
+}
+
+// Looks quite a bit hard-coded, isn't it ?
+OSStatus
+GraphicsCoreGetVideoParams(VDVideoParametersInfoRec *videoParams)
+{
+ UInt32 width, height, depth;
+ OSStatus err = noErr;
+
+ Trace(GraphicsCoreGetVideoParams);
+
+ CHECK_OPEN(statusErr);
+
+ //lprintf("GetVideoParams(ID=%d, depthMode=%d)\n",
+ // videoParams->csDisplayModeID,
+ // videoParams->csDepthMode);
+
+ if (videoParams->csDisplayModeID < 1 || videoParams->csDisplayModeID > GLOBAL.numModes)
+ return paramErr;
+
+ if (QemuVga_GetModeInfo(videoParams->csDisplayModeID - 1, &width, &height))
+ return paramErr;
+
+ videoParams->csPageCount = 1;
+
+ depth = DepthModeToDepth(videoParams->csDepthMode);
+
+ //lprintf(" -> width=%d, height=%d, depth=%d\n", width, height, depth);
+
+ (videoParams->csVPBlockPtr)->vpBaseOffset = 0; // For us, it's always 0
+ (videoParams->csVPBlockPtr)->vpBounds.top = 0; // Always 0
+ (videoParams->csVPBlockPtr)->vpBounds.left = 0; // Always 0
+ (videoParams->csVPBlockPtr)->vpVersion = 0; // Always 0
+ (videoParams->csVPBlockPtr)->vpPackType = 0; // Always 0
+ (videoParams->csVPBlockPtr)->vpPackSize = 0; // Always 0
+ (videoParams->csVPBlockPtr)->vpHRes = 0x00480000; // Hard coded to 72 dpi
+ (videoParams->csVPBlockPtr)->vpVRes = 0x00480000; // Hard coded to 72 dpi
+ (videoParams->csVPBlockPtr)->vpPlaneBytes = 0; // Always 0
+
+ (videoParams->csVPBlockPtr)->vpBounds.bottom = height;
+ (videoParams->csVPBlockPtr)->vpBounds.right = width;
+ (videoParams->csVPBlockPtr)->vpRowBytes = width * ((depth + 7) / 8);
+
+ switch (depth) {
+ case 8:
+ videoParams->csDeviceType = clutType;
+ (videoParams->csVPBlockPtr)->vpPixelType = 0;
+ (videoParams->csVPBlockPtr)->vpPixelSize = 8;
+ (videoParams->csVPBlockPtr)->vpCmpCount = 1;
+ (videoParams->csVPBlockPtr)->vpCmpSize = 8;
+ (videoParams->csVPBlockPtr)->vpPlaneBytes = 0;
+ break;
+ case 15:
+ case 16:
+ videoParams->csDeviceType = directType;
+ (videoParams->csVPBlockPtr)->vpPixelType = 16;
+ (videoParams->csVPBlockPtr)->vpPixelSize = 16;
+ (videoParams->csVPBlockPtr)->vpCmpCount = 3;
+ (videoParams->csVPBlockPtr)->vpCmpSize = 5;
+ (videoParams->csVPBlockPtr)->vpPlaneBytes = 0;
+ break;
+ case 32:
+ videoParams->csDeviceType = directType;
+ (videoParams->csVPBlockPtr)->vpPixelType = 16;
+ (videoParams->csVPBlockPtr)->vpPixelSize = 32;
+ (videoParams->csVPBlockPtr)->vpCmpCount = 3;
+ (videoParams->csVPBlockPtr)->vpCmpSize = 8;
+ (videoParams->csVPBlockPtr)->vpPlaneBytes = 0;
+ break;
+ default:
+ err = paramErr;
+ break;
+ }
+
+ return err;
+}
diff --git a/QemuVGADriver/src/DriverQDCalls.h b/QemuVGADriver/src/DriverQDCalls.h
new file mode 100644
index 0000000..cca4d28
--- /dev/null
+++ b/QemuVGADriver/src/DriverQDCalls.h
@@ -0,0 +1,42 @@
+#ifndef _DRIVER_QD_CALLS_H__
+#define _DRIVER_QD_CALLS_H__
+
+// ###ĘCONTROL ROUTINES ###
+
+OSStatus GraphicsCoreSetMode(VDPageInfo *pageInfo);
+OSStatus GraphicsCoreSetEntries(VDSetEntryRecord *entryRecord);
+OSStatus GraphicsCoreSetGamma(VDGammaRecord *gammaRec);
+OSStatus GraphicsCoreGrayPage(VDPageInfo *pageInfo);
+OSStatus GraphicsCoreSetGray(VDGrayRecord *grayRecord);
+OSStatus GraphicsCoreSetInterrupt(VDFlagRecord *flagRecord);
+OSStatus GraphicsCoreDirectSetEntries(VDSetEntryRecord *entryRecord);
+OSStatus GraphicsCoreSwitchMode(VDSwitchInfoRec *switchInfo);
+OSStatus GraphicsCoreSetSync(VDSyncInfoRec *syncInfo);
+OSStatus GraphicsCoreSetPreferredConfiguration(VDSwitchInfoRec *switchInfo);
+OSStatus GraphicsCoreSetHardwareCursor(VDSetHardwareCursorRec *setHwCursRec);
+OSStatus GraphicsCoreDrawHardwareCursor(VDDrawHardwareCursorRec *drawHwCursRec);
+OSStatus GraphicsCoreSetPowerState(VDPowerStateRec * powerStateRec);
+
+// ### STATUS ROUTINES ###
+
+OSStatus GraphicsCoreGetMode(VDPageInfo *pageInfo);
+OSStatus GraphicsCoreGetEntries(VDSetEntryRecord *entryRecord);
+OSStatus GraphicsCoreGetPages(VDPageInfo *pageInfo);
+OSStatus GraphicsCoreGetBaseAddress(VDPageInfo *pageInfo);
+OSStatus GraphicsCoreGetGray(VDGrayRecord *grayRecord);
+OSStatus GraphicsCoreGetInterrupt(VDFlagRecord *flagRecord);
+OSStatus GraphicsCoreGetGamma(VDGammaRecord *gammaRecord);
+OSStatus GraphicsCoreGetCurrentMode(VDSwitchInfoRec *switchInfo);
+OSStatus GraphicsCoreGetSync(VDSyncInfoRec *syncInfo);
+OSStatus GraphicsCoreGetConnection(VDDisplayConnectInfoRec *connectInfo);
+OSStatus GraphicsCoreGetModeTiming(VDTimingInfoRec *timingInfo);
+OSStatus GraphicsCoreGetPreferredConfiguration(VDSwitchInfoRec *switchInfo);
+OSStatus GraphicsCoreGetNextResolution(VDResolutionInfoRec *resInfo);
+OSStatus GraphicsCoreGetVideoParams(VDVideoParametersInfoRec *videoParams);
+OSStatus GraphicsCoreGetGammaInfoList(VDGetGammaListRec *gammaList);
+OSStatus GraphicsCoreRetrieveGammaTable(VDRetrieveGammaRec *gammaRec);
+OSStatus GraphicsCoreSupportsHardwareCursor(VDSupportsHardwareCursorRec *hwCursRec);
+OSStatus GraphicsCoreGetHardwareCursorDrawState(VDHardwareCursorDrawStateRec *hwCursDStateRec);
+OSStatus GraphicsCoreGetPowerState(VDPowerStateRec * powerStateRec);
+
+#endif /* DRIVER_QD_CALLS */
diff --git a/QemuVGADriver/src/QemuVga.c b/QemuVGADriver/src/QemuVga.c
new file mode 100644
index 0000000..8c996a7
--- /dev/null
+++ b/QemuVGADriver/src/QemuVga.c
@@ -0,0 +1,267 @@
+#include "VideoDriverPrivate.h"
+#include "VideoDriverPrototypes.h"
+#include "DriverQDCalls.h"
+#include "QemuVga.h"
+
+/* List of supported modes */
+struct vMode {
+ UInt32 width;
+ UInt32 height;
+};
+
+static struct vMode vModes[] = {
+ { 640, 480 },
+ { 800, 600 },
+ { 1024, 768 },
+ { 1280, 1024 },
+ { 1600, 1200 },
+ { 1920, 1080 },
+ { 1920, 1200 },
+ { 0,0 }
+};
+
+static void VgaWriteB(UInt16 port, UInt8 val)
+{
+ UInt8 *ptr;
+
+ ptr = (UInt8 *)((UInt32)GLOBAL.boardRegAddress + port + 0x400 - 0x3c0);
+ *ptr = val;
+ SynchronizeIO();
+}
+
+static UInt8 VgaReadB(UInt16 port)
+{
+ UInt8 *ptr, val;
+
+ ptr = (UInt8 *)((UInt32)GLOBAL.boardRegAddress + port + 0x400 - 0x3c0);
+ val = *ptr;
+ SynchronizeIO();
+ return val;
+}
+
+static void DispiWriteW(UInt16 reg, UInt16 val)
+{
+ UInt16 *ptr;
+
+ ptr = (UInt16 *)((UInt32)GLOBAL.boardRegAddress + (reg << 1) + 0x500);
+ *ptr = EndianSwap16Bit(val);
+ SynchronizeIO();
+}
+
+static UInt16 DispiReadW(UInt16 reg)
+{
+ UInt16 *ptr, val;
+
+ ptr = (UInt16 *)((UInt32)GLOBAL.boardRegAddress + (reg << 1) + 0x500);
+ val = EndianSwap16Bit(*ptr);
+ SynchronizeIO();
+ return val;
+}
+
+static void ExtWriteL(UInt16 reg, UInt32 val)
+{
+ UInt32 *ptr;
+
+ ptr = (UInt32 *)((UInt32)GLOBAL.boardRegAddress + (reg << 2) + 0x600);
+ *ptr = EndianSwap32Bit(val);
+ SynchronizeIO();
+}
+
+static UInt32 ExtReadL(UInt32 reg)
+{
+ UInt32 *ptr, val;
+
+ ptr = (UInt32 *)((UInt32)GLOBAL.boardRegAddress + (reg << 2) + 0x600);
+ val = EndianSwap32Bit(*ptr);
+ SynchronizeIO();
+ return val;
+}
+
+OSStatus QemuVga_Init(void)
+{
+ UInt16 id, i;
+ UInt32 mem, width, height, depth;
+
+ id = DispiReadW(VBE_DISPI_INDEX_ID);
+ mem = DispiReadW(VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
+ mem <<= 16;
+ lprintf("DISPI_ID=%04x VMEM=%d Mb\n", id, mem >> 20);
+ if ((id & 0xfff0) != VBE_DISPI_ID0) {
+ lprintf("Unsupported ID !\n");
+ return controlErr;
+ }
+ if (mem > GLOBAL.boardFBMappedSize)
+ mem = GLOBAL.boardFBMappedSize;
+ GLOBAL.vramSize = mem;
+
+ // XXX Add endian control regs
+
+ width = DispiReadW(VBE_DISPI_INDEX_XRES);
+ height = DispiReadW(VBE_DISPI_INDEX_YRES);
+ depth = DispiReadW(VBE_DISPI_INDEX_BPP);
+ lprintf("Current setting: %dx%dx%d\n", width, height, depth);
+
+ GLOBAL.depth = GLOBAL.bootDepth = depth;
+ for (i = 0; vModes[i].width; i++) {
+ if (width == vModes[i].width && height == vModes[i].height)
+ break;
+ }
+ if (!vModes[i].width) {
+ lprintf("Not found in list ! using default.\n");
+ i = 0;
+ }
+ GLOBAL.curMode = GLOBAL.bootMode = i;
+ GLOBAL.numModes = sizeof(vModes) / sizeof(struct vMode) - 1;
+
+ return noErr;
+}
+
+static OSStatus VBLTimerProc(void *p1, void *p2);
+
+static OSStatus ScheduleVBLTimer(void)
+{
+ /* XXX HACK: Run timer at 20Hz */
+ AbsoluteTime target = AddDurationToAbsolute(50, UpTime());
+
+ return SetInterruptTimer(&target, VBLTimerProc, NULL, &GLOBAL.VBLTimerID);
+}
+
+static OSStatus VBLTimerProc(void *p1, void *p2)
+{
+ GLOBAL.inInterrupt = 1;
+
+ /* This can be called before the service is ready */
+ if (GLOBAL.qdVBLInterrupt && GLOBAL.qdInterruptsEnable)
+ VSLDoInterruptService(GLOBAL.qdVBLInterrupt);
+
+ /* Reschedule */
+ ScheduleVBLTimer();
+
+ GLOBAL.inInterrupt = 0;
+}
+
+OSStatus QemuVga_Open(void)
+{
+ lprintf("QemuVga v1.00\n");
+
+ GLOBAL.isOpen = true;
+
+ /* Schedule the timer now if timers are supported. They aren't on OS X
+ * in which case we must not create the VSL service, otherwise OS X will expect
+ * a VBL and fail to update the cursor when not getting one.
+ */
+ GLOBAL.hasTimer = (ScheduleVBLTimer() == noErr);
+ GLOBAL.qdInterruptsEnable = GLOBAL.hasTimer;
+
+ /* Create VBL if timer works */
+ if (GLOBAL.hasTimer && !GLOBAL.qdVBLInterrupt)
+ VSLNewInterruptService(&GLOBAL.deviceEntry, kVBLInterruptServiceType, &GLOBAL.qdVBLInterrupt);
+
+ if (GLOBAL.hasTimer)
+ lprintf("Using timer to simulate VBL.\n");
+ else
+ lprintf("No timer service (OS X ?), VBL not registered.\n");
+
+ return noErr;
+}
+
+OSStatus QemuVga_Close(void)
+{
+ lprintf("Closing Driver...\n");
+
+ GLOBAL.isOpen = false;
+
+ QemuVga_DisableInterrupts();
+ if (GLOBAL.qdVBLInterrupt)
+ VSLDisposeInterruptService( GLOBAL.qdVBLInterrupt );
+ GLOBAL.qdVBLInterrupt = NULL;
+
+ return noErr;
+}
+
+OSStatus QemuVga_Exit(void)
+{
+ QemuVga_Close();
+
+ return noErr;
+}
+
+void QemuVga_EnableInterrupts(void)
+{
+ GLOBAL.qdInterruptsEnable = true;
+ if (GLOBAL.hasTimer)
+ ScheduleVBLTimer();
+}
+
+void QemuVga_DisableInterrupts(void)
+{
+ AbsoluteTime remaining;
+
+ GLOBAL.qdInterruptsEnable = false;
+ if (GLOBAL.hasTimer)
+ CancelTimer(GLOBAL.VBLTimerID, &remaining);
+}
+
+OSStatus QemuVga_SetColorEntry(UInt32 index, RGBColor *color)
+{
+ //lprintf("SetColorEntry %d, %x %x %x\n", index, color->red, color->green, color->blue);
+ VgaWriteB(0x3c8, index);
+ VgaWriteB(0x3c9, color->red >> 8);
+ VgaWriteB(0x3c9, color->green >> 8);
+ VgaWriteB(0x3c9, color->blue >> 8);
+ return noErr;
+}
+
+OSStatus QemuVga_GetColorEntry(UInt32 index, RGBColor *color)
+{
+ UInt32 r,g,b;
+
+ VgaWriteB(0x3c7, index);
+ r = VgaReadB(0x3c9);
+ g = VgaReadB(0x3c9);
+ b = VgaReadB(0x3c9);
+ color->red = (r << 8) | r;
+ color->green = (g << 8) | g;
+ color->blue = (b << 8) | b;
+
+ return noErr;
+}
+
+OSStatus QemuVga_GetModeInfo(UInt32 index, UInt32 *width, UInt32 *height)
+{
+ if (index >= GLOBAL.numModes)
+ return paramErr;
+ if (width)
+ *width = vModes[index].width;
+ if (height)
+ *height = vModes[index].height;
+ return noErr;
+}
+
+
+OSStatus QemuVga_SetMode(UInt32 mode, UInt32 depth)
+{
+ UInt32 width, height;
+
+ if (mode >= GLOBAL.numModes)
+ return paramErr;
+ width = vModes[mode].width;
+ height = vModes[mode].height;
+
+ lprintf("Set Mode: %dx%dx%d\n", width, height, depth);
+
+ DispiWriteW(VBE_DISPI_INDEX_ENABLE, 0);
+ DispiWriteW(VBE_DISPI_INDEX_BPP, depth);
+ DispiWriteW(VBE_DISPI_INDEX_XRES, width);
+ DispiWriteW(VBE_DISPI_INDEX_YRES, height);
+ DispiWriteW(VBE_DISPI_INDEX_BANK, 0);
+ DispiWriteW(VBE_DISPI_INDEX_VIRT_WIDTH, width);
+ DispiWriteW(VBE_DISPI_INDEX_VIRT_HEIGHT, height);
+ DispiWriteW(VBE_DISPI_INDEX_X_OFFSET, 0);
+ DispiWriteW(VBE_DISPI_INDEX_Y_OFFSET, 0);
+ DispiWriteW(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED | VBE_DISPI_8BIT_DAC);
+ GLOBAL.curMode = mode;
+ GLOBAL.depth = depth;
+
+ return noErr;
+}
diff --git a/QemuVGADriver/src/QemuVga.h b/QemuVGADriver/src/QemuVga.h
new file mode 100644
index 0000000..e401ef3
--- /dev/null
+++ b/QemuVGADriver/src/QemuVga.h
@@ -0,0 +1,54 @@
+#ifndef __QEMU_VGA_H__
+#define __QEMU_VGA_H__
+
+/* --- Qemu/Bochs special registers --- */
+
+#define VBE_DISPI_IOPORT_INDEX 0x01CE
+#define VBE_DISPI_IOPORT_DATA 0x01CF
+
+#define VBE_DISPI_INDEX_ID 0x0
+#define VBE_DISPI_INDEX_XRES 0x1
+#define VBE_DISPI_INDEX_YRES 0x2
+#define VBE_DISPI_INDEX_BPP 0x3
+#define VBE_DISPI_INDEX_ENABLE 0x4
+#define VBE_DISPI_INDEX_BANK 0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+#define VBE_DISPI_INDEX_X_OFFSET 0x8
+#define VBE_DISPI_INDEX_Y_OFFSET 0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+
+#define VBE_DISPI_ID0 0xB0C0
+#define VBE_DISPI_ID1 0xB0C1
+#define VBE_DISPI_ID2 0xB0C2
+#define VBE_DISPI_ID3 0xB0C3
+#define VBE_DISPI_ID4 0xB0C4
+#define VBE_DISPI_ID5 0xB0C5
+
+#define VBE_DISPI_DISABLED 0x00
+#define VBE_DISPI_ENABLED 0x01
+#define VBE_DISPI_GETCAPS 0x02
+#define VBE_DISPI_8BIT_DAC 0x20
+#define VBE_DISPI_LFB_ENABLED 0x40
+#define VBE_DISPI_NOCLEARMEM 0x80
+
+/* --- Internal APIs */
+
+extern OSStatus QemuVga_Init();
+extern OSStatus QemuVga_Exit();
+
+extern OSStatus QemuVga_Open();
+extern OSStatus QemuVga_Close();
+
+extern void QemuVga_EnableInterrupts(void);
+extern void QemuVga_DisableInterrupts(void);
+
+extern OSStatus QemuVga_SetDepth(UInt32 bpp);
+
+extern OSStatus QemuVga_SetColorEntry(UInt32 index, RGBColor *color);
+extern OSStatus QemuVga_GetColorEntry(UInt32 index, RGBColor *color);
+
+extern OSStatus QemuVga_GetModeInfo(UInt32 index, UInt32 *width, UInt32 *height);
+extern OSStatus QemuVga_SetMode(UInt32 modeIndex, UInt32 depth);
+
+#endif
diff --git a/QemuVGADriver/src/VideoDriver.exp b/QemuVGADriver/src/VideoDriver.exp
new file mode 100644
index 0000000..0a102ee
--- /dev/null
+++ b/QemuVGADriver/src/VideoDriver.exp
@@ -0,0 +1,2 @@
+TheDriverDescription
+DoDriverIO
diff --git a/QemuVGADriver/src/VideoDriverPrivate.h b/QemuVGADriver/src/VideoDriverPrivate.h
new file mode 100644
index 0000000..cd4cdba
--- /dev/null
+++ b/QemuVGADriver/src/VideoDriverPrivate.h
@@ -0,0 +1,79 @@
+#ifndef __VideoDriverPrivate_H__
+#define __VideoDriverPrivate_H__
+
+#pragma internal off
+
+#include <VideoServices.h>
+#include <Video.h>
+#include <Displays.h>
+#include <DriverGestalt.h>
+#include <DriverServices.h>
+#include <PCI.h>
+
+#pragma internal on
+
+#ifndef FALSE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define QEMU_PCI_VIDEO_VENDOR_ID 0x1234
+#define QEMU_PCI_VIDEO_DEVICE_ID 0x1111
+#define QEMU_PCI_VIDEO_NAME "\pQemuVgaVideo"
+#define QEMU_PCI_VIDEO_PNAME "\p.QemuVgaVideo"
+
+#define QEMU_PCI_VIDEO_BASE_REG 0x10
+#define QEMU_PCI_VIDEO_MMIO_REG 0x18
+
+#define kDriverGlobalsPropertyName "GLOBALS"
+#define kDriverFailTextPropertyName "FAILURE"
+#define kDriverFailCodePropertyName "FAIL-CODE"
+
+
+/*
+ * Our global storage is defined by this structure. This is not a requirement of the
+ * driver environment, but it collects globals into a coherent structure for debugging.
+ */
+struct DriverGlobal {
+ DriverRefNum refNum; /* Driver refNum for PB... */
+ RegEntryID deviceEntry; /* Name Registry Entry ID */
+ LogicalAddress boardFBAddress;
+ ByteCount boardFBMappedSize;
+ LogicalAddress boardRegAddress;
+ ByteCount boardRegMappedSize;
+
+ volatile Boolean inInterrupt;
+
+ /* Common globals */
+ UInt32 openCount;
+
+ /* Frame buffer configuration */
+ Boolean qdInterruptsEnable; /* Enable VBLs for qd */
+ Boolean qdLuminanceMapping;
+
+ Boolean hasTimer;
+ InterruptServiceIDType qdVBLInterrupt;
+ TimerID VBLTimerID;
+
+ Boolean isOpen;
+
+ UInt32 vramSize;
+ UInt32 depth;
+ UInt32 bootDepth;
+ UInt32 bootMode;
+ UInt32 curMode;
+ UInt32 numModes;
+};
+typedef struct DriverGlobal DriverGlobal, *DriverGlobalPtr;
+
+/*
+ * Globals and functions
+ */
+extern DriverGlobal gDriverGlobal; /* All interesting globals */
+#define GLOBAL (gDriverGlobal) /* GLOBAL.field for references */
+extern DriverDescription TheDriverDescription; /* Exported to the universe */
+
+#define FB_START ((char*)GLOBAL.boardFBAddress)
+#define CHECK_OPEN( error ) if( !GLOBAL.isOpen ) return (error)
+
+#endif
diff --git a/QemuVGADriver/src/VideoDriverPrototypes.h b/QemuVGADriver/src/VideoDriverPrototypes.h
new file mode 100644
index 0000000..b4d6c6f
--- /dev/null
+++ b/QemuVGADriver/src/VideoDriverPrototypes.h
@@ -0,0 +1,105 @@
+#ifndef __VideoDriverPrototypes_H__
+#define __VideoDriverPrototypes_H__
+
+#include <PCI.h>
+#include "logger.h"
+
+/*
+ * The Driver Manager calls DoDriverIO to perform I/O.
+ */
+#pragma internal off
+
+OSStatus
+DoDriverIO( AddressSpaceID addressSpaceID,
+ IOCommandID ioCommandID,
+ IOCommandContents ioCommandContents,
+ IOCommandCode ioCommandCode,
+ IOCommandKind ioCommandKind);
+
+#pragma internal on
+
+#include "MacDriverUtils.h"
+
+/*
+ * Prototypes for the specific driver handlers. These do real work.
+ */
+OSStatus
+DriverInitializeCmd( AddressSpaceID addressSpaceID,
+ DriverInitInfoPtr driverInitInfoPtr);
+
+OSStatus
+DriverFinalizeCmd( DriverFinalInfoPtr driverFinalInfoPtr);
+
+OSStatus
+DriverSupersededCmd( DriverSupersededInfoPtr driverSupersededInfoPtr,
+ Boolean calledFromFinalize);
+
+OSStatus
+DriverReplaceCmd( AddressSpaceID addressSpaceID,
+ DriverReplaceInfoPtr driverReplaceInfoPtr);
+
+OSStatus
+DriverOpenCmd( AddressSpaceID addressSpaceID,
+ ParmBlkPtr pb);
+
+OSStatus
+DriverCloseCmd( ParmBlkPtr pb);
+
+OSStatus
+DriverControlCmd( AddressSpaceID addressSpaceID,
+ IOCommandID ioCommandID,
+ IOCommandKind ioCommandKind,
+ CntrlParam *pb);
+
+OSStatus
+DriverStatusCmd( IOCommandID ioCommandID,
+ IOCommandKind ioCommandKind,
+ CntrlParam *pb);
+
+OSStatus
+DriverKillIOCmd( ParmBlkPtr pb);
+
+OSStatus
+DriverReadCmd(
+ AddressSpaceID addressSpaceID,
+ IOCommandID ioCommandID,
+ IOCommandKind ioCommandKind,
+ ParmBlkPtr pb);
+
+OSStatus
+DriverWriteCmd( AddressSpaceID addressSpaceID,
+ IOCommandID ioCommandID,
+ IOCommandKind ioCommandKind,
+ ParmBlkPtr pb);
+
+/* .___________________________________________________________________________________.
+ | Driver Gestalt handler -- called from the PBStatus handler. |
+ .___________________________________________________________________________________.
+ */
+OSStatus
+DriverGestaltHandler( CntrlParam* pb);
+
+
+#pragma internal on
+
+/* .___________________________________________________________________________________.
+ | Utitlity function to clear a block of memory. |
+ .___________________________________________________________________________________.
+ */
+#ifndef CLEAR
+#define CLEAR(what) BlockZero((char*)&what, sizeof what)
+#endif
+
+/*
+ * This uses the ANSI-C string concatenate and "stringize" operations.
+ */
+#define Trace(what) lprintf("Trace: %s\n", #what)
+
+#if 0
+static void
+CheckStatus( OSStatus value,
+ char* message)
+{}
+#endif
+
+#endif \ No newline at end of file