diff options
Diffstat (limited to 'QemuVGADriver/src')
-rwxr-xr-x[-rw-r--r--] | QemuVGADriver/src/DriverDoDriverIO.c | 52 | ||||
-rwxr-xr-x[-rw-r--r--] | QemuVGADriver/src/DriverGestaltHandler.c | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | QemuVGADriver/src/DriverQDCalls.c | 278 | ||||
-rw-r--r-- | QemuVGADriver/src/QemuVga.c | 187 | ||||
-rwxr-xr-x[-rw-r--r--] | QemuVGADriver/src/QemuVga.h | 17 | ||||
-rwxr-xr-x[-rw-r--r--] | QemuVGADriver/src/VideoDriverPrivate.h | 11 | ||||
-rwxr-xr-x[-rw-r--r--] | QemuVGADriver/src/VideoDriverPrototypes.h | 5 |
7 files changed, 314 insertions, 241 deletions
diff --git a/QemuVGADriver/src/DriverDoDriverIO.c b/QemuVGADriver/src/DriverDoDriverIO.c index 38f861a..d72fd9c 100644..100755 --- a/QemuVGADriver/src/DriverDoDriverIO.c +++ b/QemuVGADriver/src/DriverDoDriverIO.c @@ -25,7 +25,7 @@ DriverDescription TheDriverDescription = { | (0 * kDriverIsLoadedUponDiscovery) /* Loader runtime options */ | (1 * kDriverIsOpenedUponLoad) /* Opened when loaded */ | (1 * kDriverIsUnderExpertControl) /* I/O expert handles loads/opens */ - | (01 * kDriverIsConcurrent) /* concurrent */ + | (0 * 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] */ @@ -42,8 +42,6 @@ DriverDescription TheDriverDescription = { 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 @@ -77,8 +75,6 @@ DriverGlobal gDriverGlobal; * 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 ) @@ -90,8 +86,8 @@ DoDriverIO( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, IOCommandCon * or immediate. Read, Write, Control, and Status may be immediate, * synchronous, or asynchronous. */ - - Trace(DoDriverIO); + + lprintf("DoDriverIO cmdCode=%d\n", ioCommandCode); switch( ioCommandCode ) { case kInitializeCommand: /* Always immediate */ @@ -119,7 +115,6 @@ DoDriverIO( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, IOCommandCon (CntrlParam*)ioCommandContents.pb ); break; case kStatusCommand: - /* lprintf("kStatusCommand\n"); */ status = DriverStatusCmd( ioCommandID, ioCommandKind, (CntrlParam *)ioCommandContents.pb ); break; @@ -138,6 +133,8 @@ DoDriverIO( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, IOCommandCon status = paramErr; break; } + lprintf("Completing with status=%d (kind: %x)\n", status, ioCommandKind); + /* * Force a valid result for immediate commands -- they must return a valid * status to the Driver Manager: returning kIOBusyStatus would be a bug.. @@ -166,8 +163,6 @@ DoDriverIO( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, IOCommandCon return status; } -#pragma internal on - /* * DriverInitializeCmd * @@ -180,6 +175,11 @@ DriverInitializeCmd( AddressSpaceID addressSpaceID, DriverInitInfoPtr driverInit Trace(DriverInitializeCmd); + lprintf("** First call:\n"); + lprintf(" DoDriverIO @ %p\n", DoDriverIO); + lprintf(" DriverStatusCmd @ %p\n", DriverStatusCmd); + lprintf(" DriverControlCmd @ %p\n", DriverControlCmd); + GLOBAL.refNum = driverInitInfoPtr->refNum; GLOBAL.openCount = 0; GLOBAL.inInterrupt = false; @@ -217,6 +217,7 @@ DriverInitializeCmd( AddressSpaceID addressSpaceID, DriverInitInfoPtr driverInit GLOBAL.boardRegAddress, GLOBAL.boardRegMappedSize); + lprintf("Enabling memory space..\n"); status = EnablePCIMemorySpace(&GLOBAL.deviceEntry); if (status != noErr) { lprintf("EnablePCIMemorySpace returned %d\n", status); @@ -224,7 +225,9 @@ DriverInitializeCmd( AddressSpaceID addressSpaceID, DriverInitInfoPtr driverInit } status = QemuVga_Init(); - + if (status != noErr) + goto bail; + bail: DBG(lprintf("Driver init result: %d\n", status)); @@ -330,12 +333,11 @@ DriverControlCmd( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, switch( pb->csCode ) { case cscReset: // Old obsolete call..return a 'controlErr' - status = controlErr; + return controlErr; break; case cscKillIO: // Old obsolete call..do nothing - status = controlErr; - break; + return noErr; case cscSetMode: status = GraphicsCoreSetMode((VDPageInfo *) genericPtr); @@ -368,8 +370,7 @@ DriverControlCmd( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, break; case cscSetDefaultMode: - status = controlErr; - break; + return controlErr; case cscSwitchMode: status = GraphicsCoreSwitchMode((VDSwitchInfoRec *) genericPtr); @@ -394,11 +395,10 @@ DriverControlCmd( AddressSpaceID addressSpaceID, IOCommandID ioCommandID, status = GraphicsCoreSetPowerState((VDPowerStateRec *) genericPtr); break; default: - status = controlErr; break; } - if( status ) - status = controlErr; + if (status) + status = paramErr; return status; } @@ -425,7 +425,7 @@ DriverStatusCmd( IOCommandID ioCommandID, IOCommandKind ioCommandKind, CntrlPara genericPtr = (void *) *((UInt32 *) &(pb->csParam[0])); Trace(DriverStatusCmd); - + lprintf("csCode=%d\n", pb->csCode); switch( pb->csCode ) { case cscGetMode: status = GraphicsCoreGetMode((VDPageInfo *) genericPtr); @@ -510,13 +510,15 @@ DriverStatusCmd( IOCommandID ioCommandID, IOCommandKind ioCommandKind, CntrlPara case cscGetPowerState: status = GraphicsCoreGetPowerState((VDPowerStateRec *) genericPtr); break; - - default: - status = statusErr; + case cscGetClutBehavior: + *(VDClutBehaviorPtr)genericPtr = kSetClutAtSetEntries; + status = noErr; break; + default: + return statusErr; } - if( status ) - status = statusErr; + if (status) + status = paramErr; return status; } diff --git a/QemuVGADriver/src/DriverGestaltHandler.c b/QemuVGADriver/src/DriverGestaltHandler.c index ca37874..84189e0 100644..100755 --- a/QemuVGADriver/src/DriverGestaltHandler.c +++ b/QemuVGADriver/src/DriverGestaltHandler.c @@ -16,6 +16,11 @@ DriverGestaltHandler( CntrlParam *pb ) PB.driverGestaltResponse = 0; status = noErr; + lprintf("DriverGestalt, selector=%c%c%c%c\n", + PB.driverGestaltSelector >> 24, + (PB.driverGestaltSelector >> 16) & 0xff, + (PB.driverGestaltSelector >> 8) & 0xff, + (PB.driverGestaltSelector ) & 0xff); switch( PB.driverGestaltSelector ) { case kdgSync: PB.driverGestaltResponse = FALSE; /* We handle asynchronous I/O */ diff --git a/QemuVGADriver/src/DriverQDCalls.c b/QemuVGADriver/src/DriverQDCalls.c index 2383643..f33a76e 100644..100755 --- a/QemuVGADriver/src/DriverQDCalls.c +++ b/QemuVGADriver/src/DriverQDCalls.c @@ -3,10 +3,60 @@ #include "DriverQDCalls.h" #include "QemuVga.h" -static OSStatus GraphicsCoreDoSetEntries(VDSetEntryRecord *entryRecord, Boolean directDevice, UInt32 start, UInt32 stop, Boolean useValue); +#define MAX_DEPTH_MODE kDepthMode3 + +static UInt8 DepthToDepthMode(UInt8 depth) +{ + switch (depth) { + case 8: + return kDepthMode1; + case 15: + case 16: + return kDepthMode2; + case 24: + case 32: + return kDepthMode3; + default: + return kDepthMode1; + } +} + +static UInt8 DepthModeToDepth(UInt8 mode) +{ + switch (mode) { + case kDepthMode1: + return 32; + case kDepthMode2: + return 15; + case kDepthMode3: + return 32; + default: + return 8; + } +} /************************ Color Table Stuff ****************************/ +static 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; + + /* Note that stop value is included in the range */ + for(i=start;i<=stop;i++) { + UInt32 colorIndex = useValue ? entryRecord->csTable[i].value : i; + QemuVga_SetColorEntry(colorIndex, &entryRecord->csTable[i].rgb); + } + + return noErr; +} + OSStatus GraphicsCoreSetEntries(VDSetEntryRecord *entryRecord) { @@ -32,29 +82,6 @@ GraphicsCoreDirectSetEntries(VDSetEntryRecord *entryRecord) } 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); @@ -64,10 +91,11 @@ GraphicsCoreGetEntries(VDSetEntryRecord *entryRecord) Trace(GraphicsCoreGetEntries); + if (GLOBAL.depth != 8) + return controlErr; 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); + UInt32 colorIndex = useValue ? entryRecord->csTable[i].value : i; + QemuVga_GetColorEntry(colorIndex, &entryRecord->csTable[i].rgb); } return noErr; @@ -117,13 +145,17 @@ GraphicsCoreGetGamma(VDGammaRecord *gammaRecord) OSStatus GraphicsCoreGrayPage(VDPageInfo *pageInfo) { + UInt32 pageCount; + CHECK_OPEN( controlErr ); Trace(GraphicsCoreGrayPage); - if (pageInfo->csPage != 0) + QemuVga_GetModePages(GLOBAL.curMode, GLOBAL.depth, NULL, &pageCount); + if (pageInfo->csPage >= pageCount) return paramErr; - + + /* XXX Make it gray ! */ return noErr; } @@ -142,12 +174,16 @@ GraphicsCoreSetGray(VDGrayRecord *grayRecord) OSStatus GraphicsCoreGetPages(VDPageInfo *pageInfo) { -/* DepthMode mode; */ + UInt32 pageCount, depth; + CHECK_OPEN( statusErr ); Trace(GraphicsCoreGetPages); - pageInfo->csPage = 1; + depth = DepthModeToDepth(pageInfo->csMode); + QemuVga_GetModePages(GLOBAL.curMode, depth, NULL, &pageCount); + pageInfo->csPage = pageCount; + return noErr; } @@ -233,79 +269,22 @@ GraphicsCoreGetInterrupt(VDFlagRecord *flagRecord) 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; + return paramErr; } 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; + return paramErr; } OSStatus @@ -313,18 +292,7 @@ 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; + return paramErr; } OSStatus @@ -332,11 +300,7 @@ GraphicsCoreGetPowerState(VDPowerStateRec *powerStateRec) { Trace(GraphicsCoreGetPowerState); - CHECK_OPEN( statusErr ); - - powerStateRec->powerState = MOLVideoPowerState; - powerStateRec->powerFlags = 0; - return noErr; + return paramErr; } OSStatus @@ -349,30 +313,6 @@ GraphicsCoreSetPreferredConfiguration(VDSwitchInfoRec *switchInfo) 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) @@ -394,14 +334,18 @@ GraphicsCoreGetPreferredConfiguration(VDSwitchInfoRec *switchInfo) OSStatus GraphicsCoreGetBaseAddress(VDPageInfo *pageInfo) { + UInt32 pageCount, pageSize; + Trace(GraphicsCoreGetBaseAddress); CHECK_OPEN( statusErr ); - if (pageInfo->csPage != 0) + QemuVga_GetModePages(GLOBAL.curMode, GLOBAL.depth, &pageSize, &pageCount); + if (pageInfo->csPage >= pageCount) return paramErr; - pageInfo->csBaseAddr = FB_START; + pageInfo->csBaseAddr = FB_START + pageInfo->csPage * pageSize; + return noErr; } @@ -431,11 +375,10 @@ GraphicsCoreGetMode(VDPageInfo *pageInfo) CHECK_OPEN( statusErr ); - //lprintf("GetMode\n"); pageInfo->csMode = DepthToDepthMode(GLOBAL.depth); - pageInfo->csPage = 0; - pageInfo->csBaseAddr = FB_START; - + pageInfo->csPage = GLOBAL.curPage; + pageInfo->csBaseAddr = GLOBAL.curBaseAddress; + return noErr; } @@ -449,8 +392,8 @@ GraphicsCoreGetCurrentMode(VDSwitchInfoRec *switchInfo) //lprintf("GetCurrentMode\n"); switchInfo->csMode = DepthToDepthMode(GLOBAL.depth); switchInfo->csData = GLOBAL.curMode + 1; - switchInfo->csPage = 0; - switchInfo->csBaseAddr = FB_START; + switchInfo->csPage = GLOBAL.curPage; + switchInfo->csBaseAddr = GLOBAL.curBaseAddress; return noErr; } @@ -480,15 +423,25 @@ GraphicsCoreGetModeTiming(VDTimingInfoRec *timingInfo) OSStatus GraphicsCoreSetMode(VDPageInfo *pageInfo) { + UInt32 newDepth, newPage, pageCount; + Trace(GraphicsCoreSetMode); CHECK_OPEN(controlErr); - if (pageInfo->csPage != 0) + newDepth = DepthModeToDepth(pageInfo->csMode); + newPage = pageInfo->csPage; + QemuVga_GetModePages(GLOBAL.curMode, newDepth, NULL, &pageCount); + + lprintf("Requested depth=%d page=%d\n", newDepth, newPage); + if (pageInfo->csPage >= pageCount) return paramErr; - QemuVga_SetMode(GLOBAL.curMode, DepthModeToDepth(pageInfo->csMode)); - pageInfo->csBaseAddr = FB_START; + if (newDepth != GLOBAL.depth || newPage != GLOBAL.curPage) + QemuVga_SetMode(GLOBAL.curMode, newDepth, newPage); + + pageInfo->csBaseAddr = GLOBAL.curBaseAddress; + lprintf("Returning BA: %lx\n", pageInfo->csBaseAddr); return noErr; } @@ -497,23 +450,26 @@ GraphicsCoreSetMode(VDPageInfo *pageInfo) OSStatus GraphicsCoreSwitchMode(VDSwitchInfoRec *switchInfo) { - UInt32 newMode, newDepth; + UInt32 newMode, newDepth, newPage, pageCount; 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)) + newPage = switchInfo->csPage; + QemuVga_GetModePages(GLOBAL.curMode, newDepth, NULL, &pageCount); + + if (newPage >= pageCount) + return paramErr; + + if (newMode != GLOBAL.curMode || newDepth != GLOBAL.depth || + newPage != GLOBAL.curPage) { + if (QemuVga_SetMode(newMode, newDepth, newPage)) return controlErr; } - switchInfo->csBaseAddr = FB_START; + switchInfo->csBaseAddr = GLOBAL.curBaseAddress; return noErr; } @@ -548,7 +504,7 @@ GraphicsCoreGetNextResolution(VDResolutionInfoRec *resInfo) resInfo->csHorizontalPixels = width; resInfo->csVerticalLines = height; resInfo->csRefreshRate = 60; - resInfo->csMaxDepthMode = kDepthMode3; /* XXX Calculate if it fits ! */ + resInfo->csMaxDepthMode = MAX_DEPTH_MODE; /* XXX Calculate if it fits ! */ return noErr; } @@ -557,29 +513,26 @@ GraphicsCoreGetNextResolution(VDResolutionInfoRec *resInfo) OSStatus GraphicsCoreGetVideoParams(VDVideoParametersInfoRec *videoParams) { - UInt32 width, height, depth; + UInt32 width, height, depth, rowBytes, pageCount; 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 (videoParams->csDepthMode > MAX_DEPTH_MODE) + 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); + QemuVga_GetModePages(videoParams->csDisplayModeID - 1, depth, NULL, &pageCount); + videoParams->csPageCount = pageCount; + lprintf("Video Params says %d pages\n", pageCount); + rowBytes = width * ((depth + 7) / 8); (videoParams->csVPBlockPtr)->vpBaseOffset = 0; // For us, it's always 0 (videoParams->csVPBlockPtr)->vpBounds.top = 0; // Always 0 (videoParams->csVPBlockPtr)->vpBounds.left = 0; // Always 0 @@ -589,10 +542,9 @@ GraphicsCoreGetVideoParams(VDVideoParametersInfoRec *videoParams) (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); + (videoParams->csVPBlockPtr)->vpRowBytes = rowBytes; switch (depth) { case 8: diff --git a/QemuVGADriver/src/QemuVga.c b/QemuVGADriver/src/QemuVga.c index 8c996a7..a208ae0 100644 --- a/QemuVGADriver/src/QemuVga.c +++ b/QemuVGADriver/src/QemuVga.c @@ -2,6 +2,7 @@ #include "VideoDriverPrototypes.h" #include "DriverQDCalls.h" #include "QemuVga.h" +#include <Timer.h> /* List of supported modes */ struct vMode { @@ -77,11 +78,82 @@ static UInt32 ExtReadL(UInt32 reg) return val; } +static OSStatus VBLTimerProc(void *p1, void *p2); + +#ifndef USE_DSL_TIMER +static TMTask gLegacyTimer; + +static pascal void legacyTimerCB(TMTaskPtr *inTask) +{ + VBLTimerProc(NULL, NULL); +} + +static const RoutineDescriptor gLegacyTimerDesc = BUILD_ROUTINE_DESCRIPTOR(uppTimerProcInfo, legacyTimerCB); +static const TimerUPP gLegacyTimerProc = (TimerUPP) &gLegacyTimerDesc; +static int gTimerInstalled; + +static OSStatus ScheduleVBLTimer(void) +{ + if (!gTimerInstalled) { + BlockZero(&gLegacyTimer, sizeof(gLegacyTimer)); + gLegacyTimer.tmAddr = gLegacyTimerProc; + gLegacyTimer.qLink = (QElemPtr)'eada'; + InsXTime((QElemPtr)&gLegacyTimer); + gTimerInstalled = true; + } + PrimeTime((QElemPtr)&gLegacyTimer, TIMER_DURATION); + return noErr; +} + +#else + +static OSStatus ScheduleVBLTimer(void) +{ + AbsoluteTime target = AddDurationToAbsolute(TIMER_DURATION, UpTime()); + return SetInterruptTimer(&target, VBLTimerProc, NULL, &GLOBAL.VBLTimerID); +} + +#endif + +static OSStatus VBLTimerProc(void *p1, void *p2) +{ + static UInt32 VBcnt; + + 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; +} + +#ifdef USE_PCI_IRQ +static InterruptMemberNumber PCIInterruptHandler(InterruptSetMember ISTmember, + void *refCon, UInt32 theIntCount) +{ + UInt32 reg; + + reg = ExtReadL(2); + if (!(reg & 1)) + return kIsrIsNotComplete; + if (GLOBAL.qdVBLInterrupt && GLOBAL.qdInterruptsEnable) + VSLDoInterruptService(GLOBAL.qdVBLInterrupt); + ExtWriteL(2, 3); + return kIsrIsComplete; +} +#endif + + OSStatus QemuVga_Init(void) { UInt16 id, i; UInt32 mem, width, height, depth; + lprintf("First MMIO read...\n"); id = DispiReadW(VBE_DISPI_INDEX_ID); mem = DispiReadW(VBE_DISPI_INDEX_VIDEO_MEMORY_64K); mem <<= 16; @@ -110,34 +182,20 @@ OSStatus QemuVga_Init(void) lprintf("Not found in list ! using default.\n"); i = 0; } - GLOBAL.curMode = GLOBAL.bootMode = i; + 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(); + QemuVga_SetMode(GLOBAL.bootMode, depth, 0); - GLOBAL.inInterrupt = 0; +#ifdef USE_PCI_IRQ + if (SetupPCIInterrupt(&GLOBAL.deviceEntry, &GLOBAL.irqInfo, + PCIInterruptHandler, NULL) == noErr) + GLOBAL.hasPCIInterrupt = true; + else +#else + GLOBAL.hasPCIInterrupt = false; +#endif + return noErr; } OSStatus QemuVga_Open(void) @@ -146,22 +204,29 @@ OSStatus QemuVga_Open(void) 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; + if (GLOBAL.hasPCIInterrupt) { + QemuVga_EnableInterrupts(); + lprintf("VBL registered using PCI interrupts\n"); + } else { + /* 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. + */ + lprintf("Testing using timer to simulate VBL..\n"); + GLOBAL.hasTimer = (ScheduleVBLTimer() == noErr); + GLOBAL.qdInterruptsEnable = GLOBAL.hasTimer; + + if (GLOBAL.hasTimer) + lprintf("Using timer to simulate VBL.\n"); + else + lprintf("No timer service (OS X ?), VBL not registered.\n"); + + } - /* Create VBL if timer works */ - if (GLOBAL.hasTimer && !GLOBAL.qdVBLInterrupt) + /* Create VBL if we have a PCI interrupt or timer works */ + if (GLOBAL.hasPCIInterrupt || GLOBAL.hasTimer) 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; } @@ -190,7 +255,11 @@ void QemuVga_EnableInterrupts(void) { GLOBAL.qdInterruptsEnable = true; if (GLOBAL.hasTimer) - ScheduleVBLTimer(); + ScheduleVBLTimer(); + else if (GLOBAL.hasPCIInterrupt) { + GLOBAL.irqInfo.enableFunction(GLOBAL.irqInfo.interruptSetMember, GLOBAL.irqInfo.refCon); + ExtWriteL(2, 3); + } } void QemuVga_DisableInterrupts(void) @@ -200,6 +269,10 @@ void QemuVga_DisableInterrupts(void) GLOBAL.qdInterruptsEnable = false; if (GLOBAL.hasTimer) CancelTimer(GLOBAL.VBLTimerID, &remaining); + else if (GLOBAL.hasPCIInterrupt) { + ExtWriteL(2, 1); + GLOBAL.irqInfo.disableFunction(GLOBAL.irqInfo.interruptSetMember, GLOBAL.irqInfo.refCon); + } } OSStatus QemuVga_SetColorEntry(UInt32 index, RGBColor *color) @@ -238,17 +311,41 @@ OSStatus QemuVga_GetModeInfo(UInt32 index, UInt32 *width, UInt32 *height) return noErr; } +OSStatus QemuVga_GetModePages(UInt32 index, UInt32 depth, + UInt32 *pageSize, UInt32 *pageCount) +{ + UInt32 width, height, pBytes; + + if (index >= GLOBAL.numModes) + return paramErr; + width = vModes[index].width; + height = vModes[index].height; + pBytes = width * ((depth + 7) / 8) * height; + if (pageSize) + *pageSize = pBytes; + if (pageCount) { + if (pBytes <= (GLOBAL.boardFBMappedSize / 2)) + *pageCount = 2; + else + *pageCount = 1; + } + return noErr; +} -OSStatus QemuVga_SetMode(UInt32 mode, UInt32 depth) +OSStatus QemuVga_SetMode(UInt32 mode, UInt32 depth, UInt32 page) { UInt32 width, height; + UInt32 pageSize, numPages; if (mode >= GLOBAL.numModes) return paramErr; + width = vModes[mode].width; height = vModes[mode].height; - - lprintf("Set Mode: %dx%dx%d\n", width, height, depth); + QemuVga_GetModePages(mode, depth, &pageSize, &numPages); + lprintf("Set Mode: %dx%dx%d has %d pages\n", width, height, depth, numPages); + if (page >= numPages) + return paramErr; DispiWriteW(VBE_DISPI_INDEX_ENABLE, 0); DispiWriteW(VBE_DISPI_INDEX_BPP, depth); @@ -256,12 +353,14 @@ OSStatus QemuVga_SetMode(UInt32 mode, UInt32 depth) 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_VIRT_HEIGHT, height * numPages); DispiWriteW(VBE_DISPI_INDEX_X_OFFSET, 0); - DispiWriteW(VBE_DISPI_INDEX_Y_OFFSET, 0); + DispiWriteW(VBE_DISPI_INDEX_Y_OFFSET, height * page); DispiWriteW(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED | VBE_DISPI_8BIT_DAC); GLOBAL.curMode = mode; GLOBAL.depth = depth; + GLOBAL.curPage = page; + GLOBAL.curBaseAddress = FB_START + page * pageSize; return noErr; } diff --git a/QemuVGADriver/src/QemuVga.h b/QemuVGADriver/src/QemuVga.h index e401ef3..d7bf053 100644..100755 --- a/QemuVGADriver/src/QemuVga.h +++ b/QemuVGADriver/src/QemuVga.h @@ -1,6 +1,19 @@ #ifndef __QEMU_VGA_H__ #define __QEMU_VGA_H__ +/* This must be enabled for the MacOS X version of the timer otherwise + * we don't know if the call failed and don't back off to non-VBL ops + */ +#define USE_DSL_TIMER + +/* Pseudo VBL timer duration in ms */ +#define TIMER_DURATION 30 + +/* Enable use of the PCI IRQ as VBL using non-upstream QEMU VGA + * extensions + */ +#undef USE_PCI_IRQ + /* --- Qemu/Bochs special registers --- */ #define VBE_DISPI_IOPORT_INDEX 0x01CE @@ -48,7 +61,9 @@ 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_GetModePages(UInt32 index, UInt32 depth, + UInt32 *pageSize, UInt32 *pageCount); extern OSStatus QemuVga_GetModeInfo(UInt32 index, UInt32 *width, UInt32 *height); -extern OSStatus QemuVga_SetMode(UInt32 modeIndex, UInt32 depth); +extern OSStatus QemuVga_SetMode(UInt32 modeIndex, UInt32 depth, UInt32 page); #endif diff --git a/QemuVGADriver/src/VideoDriverPrivate.h b/QemuVGADriver/src/VideoDriverPrivate.h index cd4cdba..65c161c 100644..100755 --- a/QemuVGADriver/src/VideoDriverPrivate.h +++ b/QemuVGADriver/src/VideoDriverPrivate.h @@ -10,7 +10,7 @@ #include <DriverServices.h> #include <PCI.h> -#pragma internal on +#include "MacDriverUtils.h" #ifndef FALSE #define TRUE 1 @@ -19,8 +19,8 @@ #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_NAME "\pQEMU,VGA" +#define QEMU_PCI_VIDEO_PNAME "\p.Display_Video_QemuVGA" #define QEMU_PCI_VIDEO_BASE_REG 0x10 #define QEMU_PCI_VIDEO_MMIO_REG 0x18 @@ -51,6 +51,9 @@ struct DriverGlobal { Boolean qdInterruptsEnable; /* Enable VBLs for qd */ Boolean qdLuminanceMapping; + Boolean hasPCIInterrupt; + IRQInfo irqInfo; + Boolean hasTimer; InterruptServiceIDType qdVBLInterrupt; TimerID VBLTimerID; @@ -63,6 +66,8 @@ struct DriverGlobal { UInt32 bootMode; UInt32 curMode; UInt32 numModes; + UInt32 curPage; + LogicalAddress curBaseAddress; }; typedef struct DriverGlobal DriverGlobal, *DriverGlobalPtr; diff --git a/QemuVGADriver/src/VideoDriverPrototypes.h b/QemuVGADriver/src/VideoDriverPrototypes.h index b4d6c6f..682671a 100644..100755 --- a/QemuVGADriver/src/VideoDriverPrototypes.h +++ b/QemuVGADriver/src/VideoDriverPrototypes.h @@ -7,7 +7,6 @@ /* * The Driver Manager calls DoDriverIO to perform I/O. */ -#pragma internal off OSStatus DoDriverIO( AddressSpaceID addressSpaceID, @@ -16,8 +15,6 @@ DoDriverIO( AddressSpaceID addressSpaceID, IOCommandCode ioCommandCode, IOCommandKind ioCommandKind); -#pragma internal on - #include "MacDriverUtils.h" /* @@ -80,8 +77,6 @@ OSStatus DriverGestaltHandler( CntrlParam* pb); -#pragma internal on - /* .___________________________________________________________________________________. | Utitlity function to clear a block of memory. | .___________________________________________________________________________________. |