diff options
Diffstat (limited to 'hw/darwin/iokit/xfIOKit.c')
-rw-r--r-- | hw/darwin/iokit/xfIOKit.c | 773 |
1 files changed, 0 insertions, 773 deletions
diff --git a/hw/darwin/iokit/xfIOKit.c b/hw/darwin/iokit/xfIOKit.c deleted file mode 100644 index 0feb8ccb0..000000000 --- a/hw/darwin/iokit/xfIOKit.c +++ /dev/null @@ -1,773 +0,0 @@ -/************************************************************** - * - * IOKit support for the Darwin X Server - * - * HISTORY: - * Original port to Mac OS X Server by John Carmack - * Port to Darwin 1.0 by Dave Zarzycki - * Significantly rewritten for XFree86 4.0.1 by Torrey Lyons - * - **************************************************************/ -/* - * Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#include <dix-config.h> - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "os.h" -#include "servermd.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "mi.h" -#include "mibstore.h" -#include "mipointer.h" -#include "micmap.h" -#include "shadow.h" - -#include <sys/types.h> -#include <sys/time.h> -#include <unistd.h> -#include <fcntl.h> -#include <pthread.h> -#include <assert.h> - -#include <mach/mach_interface.h> - -#define NO_CFPLUGIN -#include <IOKit/IOKitLib.h> -#include <IOKit/hidsystem/IOHIDShared.h> -#include <IOKit/hidsystem/event_status_driver.h> -#include <IOKit/graphics/IOGraphicsLib.h> - -// Define this to work around bugs in the display drivers for -// older PowerBook G3's. If the X server starts without this -// #define, you don't need it. -#undef OLD_POWERBOOK_G3 - -#include "darwin.h" -#include "xfIOKit.h" - -// Globals -int xfIOKitScreenIndex = 0; -io_connect_t xfIOKitInputConnect = 0; - -static pthread_t inputThread; -static EvGlobals * evg; -static mach_port_t masterPort; -static mach_port_t notificationPort; -static IONotificationPortRef NotificationPortRef; -static mach_port_t pmNotificationPort; -static io_iterator_t fbIter; - - -/* - * XFIOKitStoreColors - * This is a callback from X to change the hardware colormap - * when using PsuedoColor. - */ -static void XFIOKitStoreColors( - ColormapPtr pmap, - int numEntries, - xColorItem *pdefs) -{ - kern_return_t kr; - int i; - IOColorEntry *newColors; - ScreenPtr pScreen = pmap->pScreen; - XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); - - assert( newColors = (IOColorEntry *) - xalloc( numEntries*sizeof(IOColorEntry) )); - - // Convert xColorItem values to IOColorEntry - // assume the colormap is PsuedoColor - // as we do not support DirectColor - for (i = 0; i < numEntries; i++) { - newColors[i].index = pdefs[i].pixel; - newColors[i].red = pdefs[i].red; - newColors[i].green = pdefs[i].green; - newColors[i].blue = pdefs[i].blue; - } - - kr = IOFBSetCLUT( iokitScreen->fbService, 0, numEntries, - kSetCLUTByValue, newColors ); - kern_assert( kr ); - - xfree( newColors ); -} - - -/* - * DarwinModeBell - * FIXME - */ -void DarwinModeBell( - int loud, - DeviceIntPtr pDevice, - pointer ctrl, - int fbclass) -{ -} - - -/* - * DarwinModeGiveUp - * Closes the connections to IOKit services - */ -void DarwinModeGiveUp( void ) -{ - int i; - - // we must close the HID System first - // because it is a client of the framebuffer - NXCloseEventStatus( darwinParamConnect ); - IOServiceClose( xfIOKitInputConnect ); - for (i = 0; i < screenInfo.numScreens; i++) { - XFIOKitScreenPtr iokitScreen = - XFIOKIT_SCREEN_PRIV(screenInfo.screens[i]); - IOServiceClose( iokitScreen->fbService ); - } -} - - -/* - * ClearEvent - * Clear an event from the HID System event queue - */ -static void ClearEvent(NXEvent * ep) -{ - static NXEvent nullEvent = {NX_NULLEVENT, {0, 0 }, 0, -1, 0 }; - - *ep = nullEvent; - ep->data.compound.subType = ep->data.compound.misc.L[0] = - ep->data.compound.misc.L[1] = 0; -} - - -/* - * XFIOKitHIDThread - * Read the HID System event queue, translate it to an X event, - * and queue it for processing. - */ -static void *XFIOKitHIDThread(void *unused) -{ - for (;;) { - NXEQElement *oldHead; - mach_msg_return_t kr; - mach_msg_empty_rcv_t msg; - - kr = mach_msg((mach_msg_header_t*) &msg, MACH_RCV_MSG, 0, - sizeof(msg), notificationPort, 0, MACH_PORT_NULL); - kern_assert(kr); - - while (evg->LLEHead != evg->LLETail) { - NXEvent ev; - xEvent xe; - - // Extract the next event from the kernel queue - oldHead = (NXEQElement*)&evg->lleq[evg->LLEHead]; - ev_lock(&oldHead->sema); - ev = oldHead->event; - ClearEvent(&oldHead->event); - evg->LLEHead = oldHead->next; - ev_unlock(&oldHead->sema); - - memset(&xe, 0, sizeof(xe)); - - // These fields should be filled in for every event - xe.u.keyButtonPointer.rootX = ev.location.x; - xe.u.keyButtonPointer.rootY = ev.location.y; - xe.u.keyButtonPointer.time = GetTimeInMillis(); - - switch( ev.type ) { - case NX_MOUSEMOVED: - xe.u.u.type = MotionNotify; - break; - - case NX_LMOUSEDOWN: - xe.u.u.type = ButtonPress; - xe.u.u.detail = 1; - break; - - case NX_LMOUSEUP: - xe.u.u.type = ButtonRelease; - xe.u.u.detail = 1; - break; - - // A newer kernel generates multi-button events with - // NX_SYSDEFINED. Button 2 isn't handled correctly by - // older kernels anyway. Just let NX_SYSDEFINED events - // handle these. -#if 0 - case NX_RMOUSEDOWN: - xe.u.u.type = ButtonPress; - xe.u.u.detail = 2; - break; - - case NX_RMOUSEUP: - xe.u.u.type = ButtonRelease; - xe.u.u.detail = 2; - break; -#endif - - case NX_KEYDOWN: - xe.u.u.type = KeyPress; - xe.u.u.detail = ev.data.key.keyCode; - break; - - case NX_KEYUP: - xe.u.u.type = KeyRelease; - xe.u.u.detail = ev.data.key.keyCode; - break; - - case NX_FLAGSCHANGED: - xe.u.u.type = kXDarwinUpdateModifiers; - xe.u.clientMessage.u.l.longs0 = ev.flags; - break; - - case NX_SYSDEFINED: - if (ev.data.compound.subType == 7) { - xe.u.u.type = kXDarwinUpdateButtons; - xe.u.clientMessage.u.l.longs0 = - ev.data.compound.misc.L[0]; - xe.u.clientMessage.u.l.longs1 = - ev.data.compound.misc.L[1]; - } else { - continue; - } - break; - - case NX_SCROLLWHEELMOVED: - xe.u.u.type = kXDarwinScrollWheel; - xe.u.clientMessage.u.s.shorts0 = - ev.data.scrollWheel.deltaAxis1; - break; - - default: - continue; - } - - DarwinEQEnqueue(&xe); - } - } - - return NULL; -} - - -/* - * XFIOKitPMThread - * Handle power state notifications - */ -static void *XFIOKitPMThread(void *arg) -{ - ScreenPtr pScreen = (ScreenPtr)arg; - XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); - - for (;;) { - mach_msg_return_t kr; - mach_msg_empty_rcv_t msg; - - kr = mach_msg((mach_msg_header_t*) &msg, MACH_RCV_MSG, 0, - sizeof(msg), pmNotificationPort, 0, MACH_PORT_NULL); - kern_assert(kr); - - // display is powering down - if (msg.header.msgh_id == 0) { - IOFBAcknowledgePM( iokitScreen->fbService ); - xf86SetRootClip(pScreen, FALSE); - } - // display just woke up - else if (msg.header.msgh_id == 1) { - xf86SetRootClip(pScreen, TRUE); - } - } - return NULL; -} - - -/* - * SetupFBandHID - * Setup an IOFramebuffer service and connect the HID system to it. - */ -static Bool SetupFBandHID( - int index, - DarwinFramebufferPtr dfb, - XFIOKitScreenPtr iokitScreen) -{ - kern_return_t kr; - io_service_t service; - io_connect_t fbService; - vm_address_t vram; - vm_size_t shmemSize; - int i; - UInt32 numModes; - IODisplayModeInformation modeInfo; - IODisplayModeID displayMode, *allModes; - IOIndex displayDepth; - IOFramebufferInformation fbInfo; - IOPixelInformation pixelInfo; - StdFBShmem_t *cshmem; - - // find and open the IOFrameBuffer service - service = IOIteratorNext(fbIter); - if (service == 0) - return FALSE; - - kr = IOServiceOpen( service, mach_task_self(), - kIOFBServerConnectType, &iokitScreen->fbService ); - IOObjectRelease( service ); - if (kr != KERN_SUCCESS) { - ErrorF("Failed to connect as window server to screen %i.\n", index); - return FALSE; - } - fbService = iokitScreen->fbService; - - // create the slice of shared memory containing cursor state data - kr = IOFBCreateSharedCursor( fbService, - kIOFBCurrentShmemVersion, - 32, 32 ); - if (kr != KERN_SUCCESS) - return FALSE; - - // Register for power management events for the framebuffer's device - kr = IOCreateReceivePort(kOSNotificationMessageID, &pmNotificationPort); - kern_assert(kr); - kr = IOConnectSetNotificationPort( fbService, 0, - pmNotificationPort, 0 ); - if (kr != KERN_SUCCESS) { - ErrorF("Power management registration failed.\n"); - } - - // SET THE SCREEN PARAMETERS - // get the current screen resolution, refresh rate and depth - kr = IOFBGetCurrentDisplayModeAndDepth( fbService, - &displayMode, - &displayDepth ); - if (kr != KERN_SUCCESS) - return FALSE; - - // use the current screen resolution if the user - // only wants to change the refresh rate - if (darwinDesiredRefresh != -1 && darwinDesiredWidth == 0) { - kr = IOFBGetDisplayModeInformation( fbService, - displayMode, - &modeInfo ); - if (kr != KERN_SUCCESS) - return FALSE; - darwinDesiredWidth = modeInfo.nominalWidth; - darwinDesiredHeight = modeInfo.nominalHeight; - } - - // use the current resolution and refresh rate - // if the user doesn't have a preference - if (darwinDesiredWidth == 0) { - - // change the pixel depth if desired - if (darwinDesiredDepth != -1) { - kr = IOFBGetDisplayModeInformation( fbService, - displayMode, - &modeInfo ); - if (kr != KERN_SUCCESS) - return FALSE; - if (modeInfo.maxDepthIndex < darwinDesiredDepth) { - ErrorF("Discarding screen %i:\n", index); - ErrorF("Current screen resolution does not support desired pixel depth.\n"); - return FALSE; - } - - displayDepth = darwinDesiredDepth; - kr = IOFBSetDisplayModeAndDepth( fbService, displayMode, - displayDepth ); - if (kr != KERN_SUCCESS) - return FALSE; - } - - // look for display mode with correct resolution and refresh rate - } else { - - // get an array of all supported display modes - kr = IOFBGetDisplayModeCount( fbService, &numModes ); - if (kr != KERN_SUCCESS) - return FALSE; - assert(allModes = (IODisplayModeID *) - xalloc( numModes * sizeof(IODisplayModeID) )); - kr = IOFBGetDisplayModes( fbService, numModes, allModes ); - if (kr != KERN_SUCCESS) - return FALSE; - - for (i = 0; i < numModes; i++) { - kr = IOFBGetDisplayModeInformation( fbService, allModes[i], - &modeInfo ); - if (kr != KERN_SUCCESS) - return FALSE; - - if (modeInfo.flags & kDisplayModeValidFlag && - modeInfo.nominalWidth == darwinDesiredWidth && - modeInfo.nominalHeight == darwinDesiredHeight) { - - if (darwinDesiredDepth == -1) - darwinDesiredDepth = modeInfo.maxDepthIndex; - if (modeInfo.maxDepthIndex < darwinDesiredDepth) { - ErrorF("Discarding screen %i:\n", index); - ErrorF("Desired screen resolution does not support desired pixel depth.\n"); - return FALSE; - } - - if ((darwinDesiredRefresh == -1 || - (darwinDesiredRefresh << 16) == modeInfo.refreshRate)) { - displayMode = allModes[i]; - displayDepth = darwinDesiredDepth; - kr = IOFBSetDisplayModeAndDepth(fbService, - displayMode, - displayDepth); - if (kr != KERN_SUCCESS) - return FALSE; - break; - } - } - } - - xfree( allModes ); - if (i >= numModes) { - ErrorF("Discarding screen %i:\n", index); - ErrorF("Desired screen resolution or refresh rate is not supported.\n"); - return FALSE; - } - } - - kr = IOFBGetPixelInformation( fbService, displayMode, displayDepth, - kIOFBSystemAperture, &pixelInfo ); - if (kr != KERN_SUCCESS) - return FALSE; - -#ifdef __i386__ - /* x86 in 8bit mode currently needs fixed color map... */ - if (pixelInfo.bitsPerComponent == 8 && - pixelInfo.componentCount == 1) - { - pixelInfo.pixelType = kIOFixedCLUTPixels; - } -#endif - -#ifdef OLD_POWERBOOK_G3 - if (pixelInfo.pixelType == kIOCLUTPixels) - pixelInfo.pixelType = kIOFixedCLUTPixels; -#endif - - kr = IOFBGetFramebufferInformationForAperture( fbService, - kIOFBSystemAperture, - &fbInfo ); - if (kr != KERN_SUCCESS) - return FALSE; - - // FIXME: 1x1 IOFramebuffers are sometimes used to indicate video - // outputs without a monitor connected to them. Since IOKit Xinerama - // does not really work, this often causes problems on PowerBooks. - // For now we explicitly check and ignore these screens. - if (fbInfo.activeWidth <= 1 || fbInfo.activeHeight <= 1) { - ErrorF("Discarding screen %i:\n", index); - ErrorF("Invalid width or height.\n"); - return FALSE; - } - - kr = IOConnectMapMemory( fbService, kIOFBCursorMemory, - mach_task_self(), (vm_address_t *) &cshmem, - &shmemSize, kIOMapAnywhere ); - if (kr != KERN_SUCCESS) - return FALSE; - iokitScreen->cursorShmem = cshmem; - - kr = IOConnectMapMemory( fbService, kIOFBSystemAperture, - mach_task_self(), &vram, &shmemSize, - kIOMapAnywhere ); - if (kr != KERN_SUCCESS) - return FALSE; - - iokitScreen->framebuffer = (void*)vram; - dfb->x = cshmem->screenBounds.minx; - dfb->y = cshmem->screenBounds.miny; - dfb->width = fbInfo.activeWidth; - dfb->height = fbInfo.activeHeight; - dfb->pitch = fbInfo.bytesPerRow; - dfb->bitsPerPixel = fbInfo.bitsPerPixel; - dfb->colorBitsPerPixel = pixelInfo.componentCount * - pixelInfo.bitsPerComponent; - dfb->bitsPerComponent = pixelInfo.bitsPerComponent; - - // allocate shadow framebuffer - iokitScreen->shadowPtr = xalloc(dfb->pitch * dfb->height); - dfb->framebuffer = iokitScreen->shadowPtr; - - // Note: Darwin kIORGBDirectPixels = X TrueColor, not DirectColor - if (pixelInfo.pixelType == kIORGBDirectPixels) { - dfb->colorType = TrueColor; - } else if (pixelInfo.pixelType == kIOCLUTPixels) { - dfb->colorType = PseudoColor; - } else if (pixelInfo.pixelType == kIOFixedCLUTPixels) { - dfb->colorType = StaticColor; - } - - // Inform the HID system that the framebuffer is also connected to it. - kr = IOConnectAddClient( xfIOKitInputConnect, fbService ); - kern_assert( kr ); - - // We have to have added at least one screen - // before we can enable the cursor. - kr = IOHIDSetCursorEnable(xfIOKitInputConnect, TRUE); - kern_assert( kr ); - - return TRUE; -} - - -/* - * DarwinModeAddScreen - * IOKit specific initialization for each screen. - */ -Bool DarwinModeAddScreen( - int index, - ScreenPtr pScreen) -{ - DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); - XFIOKitScreenPtr iokitScreen; - - // allocate space for private per screen storage - iokitScreen = xalloc(sizeof(XFIOKitScreenRec)); - XFIOKIT_SCREEN_PRIV(pScreen) = iokitScreen; - - // setup hardware framebuffer - iokitScreen->fbService = 0; - if (! SetupFBandHID(index, dfb, iokitScreen)) { - if (iokitScreen->fbService) { - IOServiceClose(iokitScreen->fbService); - } - return FALSE; - } - - return TRUE; -} - - -/* - * XFIOKitShadowUpdate - * Update the damaged regions of the shadow framebuffer on the screen. - */ -static void XFIOKitShadowUpdate(ScreenPtr pScreen, - shadowBufPtr pBuf) -{ - DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); - XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); - RegionPtr damage = &pBuf->damage; - int numBox = REGION_NUM_RECTS(damage); - BoxPtr pBox = REGION_RECTS(damage); - int pitch = dfb->pitch; - int bpp = dfb->bitsPerPixel/8; - - // Loop through all the damaged boxes - while (numBox--) { - int width, height, offset; - unsigned char *src, *dst; - - width = (pBox->x2 - pBox->x1) * bpp; - height = pBox->y2 - pBox->y1; - offset = (pBox->y1 * pitch) + (pBox->x1 * bpp); - src = iokitScreen->shadowPtr + offset; - dst = iokitScreen->framebuffer + offset; - - while (height--) { - memcpy(dst, src, width); - dst += pitch; - src += pitch; - } - - // Get the next box - pBox++; - } -} - - -/* - * DarwinModeSetupScreen - * Finalize IOKit specific initialization of each screen. - */ -Bool DarwinModeSetupScreen( - int index, - ScreenPtr pScreen) -{ - DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); - pthread_t pmThread; - - // initalize cursor support - if (! XFIOKitInitCursor(pScreen)) { - return FALSE; - } - - // initialize shadow framebuffer support - if (! shadowInit(pScreen, XFIOKitShadowUpdate, NULL)) { - ErrorF("Failed to initalize shadow framebuffer for screen %i.\n", - index); - return FALSE; - } - - // initialize colormap handling as needed - if (dfb->colorType == PseudoColor) { - pScreen->StoreColors = XFIOKitStoreColors; - } - - // initialize power manager handling - pthread_create( &pmThread, NULL, XFIOKitPMThread, - (void *) pScreen ); - - return TRUE; -} - - -/* - * DarwinModeInitOutput - * One-time initialization of IOKit output support. - */ -void DarwinModeInitOutput( - int argc, - char **argv) -{ - static unsigned long generation = 0; - kern_return_t kr; - io_iterator_t iter; - io_service_t service; - vm_address_t shmem; - vm_size_t shmemSize; - - ErrorF("Display mode: IOKit\n"); - - // Allocate private storage for each screen's IOKit specific info - if (generation != serverGeneration) { - xfIOKitScreenIndex = AllocateScreenPrivateIndex(); - generation = serverGeneration; - } - - kr = IOMasterPort(bootstrap_port, &masterPort); - kern_assert( kr ); - - // Find and open the HID System Service - // Do this now to be sure the Mac OS X window server is not running. - kr = IOServiceGetMatchingServices( masterPort, - IOServiceMatching( kIOHIDSystemClass ), - &iter ); - kern_assert( kr ); - - assert( service = IOIteratorNext( iter ) ); - - kr = IOServiceOpen( service, mach_task_self(), kIOHIDServerConnectType, - &xfIOKitInputConnect ); - if (kr != KERN_SUCCESS) { - ErrorF("Failed to connect to the HID System as the window server!\n"); -#ifdef DARWIN_WITH_QUARTZ - FatalError("Quit the Mac OS X window server or use the -quartz option.\n"); -#else - FatalError("Make sure you have quit the Mac OS X window server.\n"); -#endif - } - - IOObjectRelease( service ); - IOObjectRelease( iter ); - - // Setup the event queue in memory shared by the kernel and X server - kr = IOHIDCreateSharedMemory( xfIOKitInputConnect, - kIOHIDCurrentShmemVersion ); - kern_assert( kr ); - - kr = IOConnectMapMemory( xfIOKitInputConnect, kIOHIDGlobalMemory, - mach_task_self(), &shmem, &shmemSize, - kIOMapAnywhere ); - kern_assert( kr ); - - evg = (EvGlobals *)(shmem + ((EvOffsets *)shmem)->evGlobalsOffset); - - assert(sizeof(EvGlobals) == evg->structSize); - - NotificationPortRef = IONotificationPortCreate( masterPort ); - - notificationPort = IONotificationPortGetMachPort(NotificationPortRef); - - kr = IOConnectSetNotificationPort( xfIOKitInputConnect, - kIOHIDEventNotification, - notificationPort, 0 ); - kern_assert( kr ); - - evg->movedMask |= NX_MOUSEMOVEDMASK; - - // find number of framebuffers - kr = IOServiceGetMatchingServices( masterPort, - IOServiceMatching( IOFRAMEBUFFER_CONFORMSTO ), - &fbIter ); - kern_assert( kr ); - - darwinScreensFound = 0; - while ((service = IOIteratorNext(fbIter))) { - IOObjectRelease( service ); - darwinScreensFound++; - } - IOIteratorReset(fbIter); -} - - -/* - * DarwinModeInitInput - * One-time initialization of IOKit input support. - */ -void DarwinModeInitInput( - int argc, - char **argv) -{ - kern_return_t kr; - int fd[2]; - - kr = IOHIDSetEventsEnable(xfIOKitInputConnect, TRUE); - kern_assert( kr ); - - // Start event passing thread - assert( pipe(fd) == 0 ); - darwinEventReadFD = fd[0]; - darwinEventWriteFD = fd[1]; - fcntl(darwinEventReadFD, F_SETFL, O_NONBLOCK); - pthread_create(&inputThread, NULL, - XFIOKitHIDThread, NULL); - -} - - -/* - * DarwinModeProcessEvent - * Process IOKit specific events. - */ -void DarwinModeProcessEvent( - xEvent *xe) -{ - // No mode specific events - ErrorF("Unknown X event caught: %d\n", xe->u.u.type); -} |