diff options
author | dawes <dawes> | 2000-11-30 17:31:29 +0000 |
---|---|---|
committer | dawes <dawes> | 2000-11-30 17:31:29 +0000 |
commit | d129f7fd02961869422c111dd8c3cf824bc54243 (patch) | |
tree | a8616855bbbfea89de0a0584e6d0daade1711bd2 /xc/programs | |
parent | c6fd424b4371a3348ec8a34475cfacad1c8fddb9 (diff) |
Initial revision
Diffstat (limited to 'xc/programs')
-rw-r--r-- | xc/programs/Xserver/hw/darwin/Imakefile | 28 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/darwin/Xdarwin.man | 63 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/darwin/darwin.c | 1071 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/darwin/darwin.h | 38 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/darwin/darwinCursor.c | 705 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/darwin/darwinKeyboard.c | 503 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/darwin/utils/Imakefile | 11 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/darwin/utils/dumpkeymap.c | 879 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/drivers/ark/Imakefile | 49 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/drivers/ark/ark.h | 71 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/drivers/ark/ark_accel.c | 227 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/drivers/ark/ark_driver.c | 1170 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/drivers/ark/ark_reg.h | 88 |
13 files changed, 4903 insertions, 0 deletions
diff --git a/xc/programs/Xserver/hw/darwin/Imakefile b/xc/programs/Xserver/hw/darwin/Imakefile new file mode 100644 index 000000000..2a1f2430a --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/Imakefile @@ -0,0 +1,28 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/darwin/Imakefile,v 1.2 2000/11/16 03:22:18 dawes Exp $ + +#include <Server.tmpl> +#define IHaveSubdirs + +SUBDIRS = utils + +SRCS = darwin.c \ + darwinCursor.c \ + darwinKeyboard.c + +OBJS = darwin.o \ + darwinCursor.o \ + darwinKeyboard.o + +INCLUDES = -I. -I$(SERVERSRC)/mi -I$(SERVERSRC)/mfb -I$(SERVERSRC)/cfb \ + -I$(SERVERSRC)/include -I$(XINCLUDESRC) -I$(SERVERSRC)/os \ + -I$(INCLUDESRC) -I$(FONTINCSRC) + +NormalLibraryObjectRule() +NormalLibraryTarget(darwin,$(OBJS)) + +InstallManPage(Xdarwin,$(MANDIR)) + +DependTarget() + +MakeSubdirs($(SUBDIRS)) +DependSubdirs($(SUBDIRS)) diff --git a/xc/programs/Xserver/hw/darwin/Xdarwin.man b/xc/programs/Xserver/hw/darwin/Xdarwin.man new file mode 100644 index 000000000..aee06c433 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/Xdarwin.man @@ -0,0 +1,63 @@ +.\" $XFree86: xc/programs/Xserver/hw/darwin/Xdarwin.man,v 1.1 2000/11/15 01:36:13 dawes Exp $ +.\" +.TH XDARWIN 1 "Release 6.4" "X Version 11" +.SH NAME +Xdarwin \- X window system server for Darwin operating system +.SH SYNOPSIS +.B Xdarwin +[ options ] ... +.SH DESCRIPTION +.I Xdarwin +is the window server for Version 11 of the X window system on the Darwin +operating system. It uses IOKit services to accesss the display framebuffer, +mouse and keyboard and to provide a layer of hardware abstraction. +.I Xdarwin +will normally be started by the \fIxdm(1)\fP display manager or by a script +that runs the program \fIxinit(1)\fP. +.SH OPTIONS +.PP +In addition to the normal server options described in the \fIXserver(1)\fP +manual page, \fIXdarwin\fP accepts the following command line switches: +.TP 8 +.B \-fakebuttons +Emulates a 3 button mouse using the Command and Option keys. Clicking the +first mouse button while holding down Command will act like clicking +button 2. Holding down Option will simulate button 3. +.TP 8 +.B \-nofakebuttons +Do not emulate a 3 button mouse. This is the default. +.TP 8 +.B "\-size \fIwidth\fP \fIheight\fP" +Sets the screeen resolution for the X server to use. +.TP 8 +.B "\-depth \fIdepth\fP" +Specifies the color bit depth to use. Currently only 8, 15, and 24 color bits +per pixel are supported. +.TP 8 +.B "\-refresh \fIrate\fP" +Gives the refresh rate to use in Hz. For LCD displays this should be 0. +.SH "SEE ALSO" +.PP +X(1), Xserver(1), xdm(1), xinit(1) +.SH BUGS +.I Xdarwin +and this man page still have many limitations. Some of the more obvious +ones are: +.br +- Only one display is supported. +.br +- The display mode can not be changed once the X server has started. +.br +- A screen saver is not supported. +.br +- The X server does not wake from sleep correctly. +.br +- The key repeat rate can not be changed. +.PP +.SH AUTHORS +Original Port to Mac OS X Server - John Carmack +.br +Port to Darwin 1.0 - Dave Zarzycki +.br +Improvements and bug fixes - Torrey T. Lyons + diff --git a/xc/programs/Xserver/hw/darwin/darwin.c b/xc/programs/Xserver/hw/darwin/darwin.c new file mode 100644 index 000000000..a28d07d70 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/darwin.c @@ -0,0 +1,1071 @@ +/************************************************************** + * + * 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 + * + **************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/darwin/darwin.c,v 1.1 2000/11/15 01:36:13 dawes Exp $ */ + +#define NDEBUG 1 + +#include "X.h" +#include "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 <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <pthread.h> + +#include <mach/mach_interface.h> + +#define NO_CFPLUGIN +#include <IOKit/IOKitLib.h> +#include <IOKit/hidsystem/IOHIDShared.h> +#include <IOKit/graphics/IOGraphicsLib.h> +#include <drivers/event_status_driver.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" + +DarwinFramebufferRec dfb; +unsigned char darwinKeyCommandL = 0, darwinKeyOptionL = 0; + +/* Fake button press/release for scroll wheel move. */ +#define SCROLLWHEELUPFAKE 4 +#define SCROLLWHEELDOWNFAKE 5 + +static int darwinEventFD; +static Bool fake3Buttons = FALSE; +static DeviceIntPtr darwinPointer; +static DeviceIntPtr darwinKeyboard; +static UInt32 darwinDesiredWidth = 0, darwinDesiredHeight = 0; +static IOIndex darwinDesiredDepth = -1; +static SInt32 darwinDesiredRefresh = -1; + +// Common pixmap formats +static PixmapFormatRec formats[] = { + { 1, 1, BITMAP_SCANLINE_PAD }, + { 4, 8, BITMAP_SCANLINE_PAD }, + { 8, 8, BITMAP_SCANLINE_PAD }, + { 15, 16, BITMAP_SCANLINE_PAD }, + { 16, 16, BITMAP_SCANLINE_PAD }, + { 24, 32, BITMAP_SCANLINE_PAD } +}; +const int NUMFORMATS = sizeof(formats)/sizeof(formats[0]); + +static Bool DarwinSaveScreen(ScreenPtr pScreen, int on) +{ // FIXME + if (on == SCREEN_SAVER_FORCER) { + } else if (on == SCREEN_SAVER_ON) { + } else { + } + return TRUE; +} + +/* + * DarwinStoreColors + * This is a callback from X to change the hardware colormap + * when using PsuedoColor + */ +static void DarwinStoreColors( + ColormapPtr pmap, + int numEntries, + xColorItem *pdefs) +{ + kern_return_t kr; + int i; + IOColorEntry *newColors; + + 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( dfb.fbService, 0, numEntries, + kSetCLUTByValue, newColors ); + kern_assert( kr ); + + xfree( newColors ); +} + +/* + * DarwinAddScreen + * This is a callback from X during AddScreen() from InitOutput() + */ +static Bool DarwinAddScreen( + int index, + ScreenPtr pScreen, + int argc, + char **argv ) +{ + int bitsPerRGB, i; + VisualPtr visual; + + /* Communicate the information about our initialized screen back to X. */ + bitsPerRGB = dfb.pixelInfo.bitsPerComponent; + + // reset the visual list + miClearVisualTypes(); + + // setup a single visual appropriate for our pixel type + // Note: Darwin kIORGBDirectPixels = X window TrueColor, not DirectColor + if (dfb.pixelInfo.pixelType == kIORGBDirectPixels) { + if (!miSetVisualTypes( dfb.colorBitsPerPixel, TrueColorMask, + bitsPerRGB, TrueColor )) { + return FALSE; + } + } else if (dfb.pixelInfo.pixelType == kIOCLUTPixels) { + if (!miSetVisualTypes( dfb.colorBitsPerPixel, PseudoColorMask, + bitsPerRGB, PseudoColor )) { + return FALSE; + } + } else if (dfb.pixelInfo.pixelType == kIOFixedCLUTPixels) { + if (!miSetVisualTypes( dfb.colorBitsPerPixel, StaticColorMask, + bitsPerRGB, StaticColor )) { + return FALSE; + } + } else { + return FALSE; + } + + // machine independent screen init + // setup _Screen structure in pScreen + if ( dfb.bitsPerPixel == 32 ) { + if (!cfb32ScreenInit(pScreen, + dfb.framebuffer, + dfb.width, dfb.height, + 75, 75, /* screen size in dpi, which we have no accurate knowledge of */ + dfb.pitch / (dfb.bitsPerPixel/8))) { + return FALSE; + } + } else if ( dfb.bitsPerPixel == 16 ) { + if (!cfb16ScreenInit(pScreen, + dfb.framebuffer, + dfb.width, dfb.height, + 75, 75, /* screen size in dpi, which we have no accurate knowledge of */ + dfb.pitch / (dfb.bitsPerPixel/8))) { + return FALSE; + } + } else if ( dfb.bitsPerPixel == 8 ) { + if (!cfbScreenInit(pScreen, + dfb.framebuffer, + dfb.width, dfb.height, + 75, 75, /* screen size in dpi, which we have no accurate knowledge of */ + dfb.pitch / (dfb.bitsPerPixel/8))) { + return FALSE; + } + } else { + return FALSE; + } + + // set the RGB order correctly for TrueColor, it is byte swapped by X + // FIXME: make work on x86 darwin if it ever gets buildable + if (dfb.bitsPerPixel > 8) { + for (i = 0, visual = pScreen->visuals; // someday we may have more than 1 + i < pScreen->numVisuals; i++, visual++) { + if (visual->class == TrueColor) { + visual->offsetRed = bitsPerRGB * 2; + visual->offsetGreen = bitsPerRGB; + visual->offsetBlue = 0; +#if FALSE + visual->redMask = ((1<<bitsPerRGB)-1) << visual->offsetRed; + visual->greenMask = ((1<<bitsPerRGB)-1) << visual->offsetGreen; + visual->blueMask = ((1<<bitsPerRGB)-1) << visual->offsetBlue; +#else + visual->redMask = dfb.pixelInfo.componentMasks[0]; + visual->greenMask = dfb.pixelInfo.componentMasks[1]; + visual->blueMask = dfb.pixelInfo.componentMasks[2]; +#endif + } + } + } + +#ifdef MITSHM + ShmRegisterFbFuncs(pScreen); +#endif + + // setup cursor support, use hardware if possible + if (!DarwinInitCursor(pScreen)) { + return FALSE; + } + + // this must be initialized (why doesn't X have a default?) + pScreen->SaveScreen = DarwinSaveScreen; + + // initialize colormap handling as needed + if (dfb.pixelInfo.pixelType == kIOCLUTPixels) { + pScreen->StoreColors = DarwinStoreColors; + } + + // create and install the default colormap and + // set pScreen->blackPixel / pScreen->white + if (!miCreateDefColormap( pScreen )) { + return FALSE; + } + + return TRUE; +} + +/* + * DarwinShutdownScreen + */ +void DarwinShutdownScreen( void ) +{ +#if 0 + // we must close the HID System first + // because it is a client of the framebuffer + NXCloseEventStatus( dfb.hidParam ); + IOServiceClose( dfb.hidService ); + IOServiceClose( dfb.fbService ); +#endif +} + +/* + ============================================================================= + + mouse callbacks + + ============================================================================= +*/ + +/* + * Set mouse acceleration and thresholding + * FIXME: We currently ignore the threshold in ctrl->threshold. + */ +static void DarwinChangePointerControl( + DeviceIntPtr device, + PtrCtrl *ctrl ) +{ + kern_return_t kr; + double acceleration; + + acceleration = ctrl->num / ctrl->den; + kr = IOHIDSetMouseAcceleration( dfb.hidParam, acceleration ); + if (kr != KERN_SUCCESS) + ErrorF( "Could not set mouse acceleration with kernel return = 0x%x.\n", kr ); +} + + +/* + * Motion history between events is not required to be supported. + */ +static int DarwinGetMotionEvents( DeviceIntPtr pDevice, xTimecoord *buff, + unsigned long start, unsigned long stop, ScreenPtr pScr) +{ + return 0; +} + + +/* + * DarwinMouseProc -- + * Handle the initialization, etc. of a mouse + */ + +static int DarwinMouseProc( DeviceIntPtr pPointer, int what ) { + + char map[6]; + + switch (what) { + + case DEVICE_INIT: + pPointer->public.on = FALSE; + + map[1] = 1; + map[2] = 2; + map[3] = 3; + map[4] = 4; + map[5] = 5; + InitPointerDeviceStruct( (DevicePtr)pPointer, + map, + 5, // numbuttons (4 & 5 are scroll wheel) + DarwinGetMotionEvents, // miPointerGetMotionEvents ?? + DarwinChangePointerControl, + 0 ); + break; + + case DEVICE_ON: + pPointer->public.on = TRUE; + AddEnabledDevice( darwinEventFD ); + return Success; + + case DEVICE_CLOSE: + case DEVICE_OFF: + pPointer->public.on = FALSE; + RemoveEnabledDevice( darwinEventFD ); + return Success; + } + + return Success; +} + +/* + * DarwinKeybdProc + * callback from X + */ +static int DarwinKeybdProc( DeviceIntPtr pDev, int onoff ) +{ + switch ( onoff ) { + case DEVICE_INIT: + DarwinKeyboardInit( pDev ); + break; + case DEVICE_ON: + pDev->public.on = TRUE; + AddEnabledDevice( darwinEventFD ); + break; + case DEVICE_OFF: + pDev->public.on = FALSE; + RemoveEnabledDevice( darwinEventFD ); + break; + case DEVICE_CLOSE: + break; + } + + return Success; +} + +/* +=========================================================================== + + Functions needed to link against device independent X + +=========================================================================== +*/ + +/* + * ProcessInputEvents + * Read events from the event queue + */ +void ProcessInputEvents(void) +{ + xEvent xe; + NXEvent ev; + int r; + struct timeval tv; + struct timezone tz; + + // try to read from our pipe + r = read( darwinEventFD, &ev, sizeof(ev)); + if ((r == -1) && (errno != EAGAIN)) { + ErrorF("read(darwinEventFD) failed, errno=%d: %s\n", errno, strerror(errno)); + return; + } else if ((r == -1) && (errno == EAGAIN)) { + return; + } else if ( r != sizeof( ev ) ) { + ErrorF( "Only read %i bytes from darwinPipe!", r ); + return; + } + + gettimeofday(&tv, &tz); + + // translate it to an X event and post it + memset(&xe, 0, sizeof(xe)); + + xe.u.keyButtonPointer.rootX = ev.location.x; + xe.u.keyButtonPointer.rootY = ev.location.y; + //xe.u.keyButtonPointer.time = ev.time; + xe.u.keyButtonPointer.time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + /* A newer kernel generates multi-button events by NX_SYSDEFINED. + See iokit/Families/IOHIDSystem/IOHIDSystem.cpp version 1.1.1.7, + 2000/08/10 00:23:37 or later. */ + + switch( ev.type ) { + case NX_MOUSEMOVED: + xe.u.u.type = MotionNotify; + (darwinPointer->public.processInputProc)( &xe, darwinPointer, 1 ); + break; + + case NX_LMOUSEDOWN: + // Mimic multi-button mouse with Command and Option + if (fake3Buttons && ev.flags & (NX_COMMANDMASK | NX_ALTERNATEMASK)) { + if (ev.flags & NX_COMMANDMASK) { + // first fool X into forgetting about Command key + xe.u.u.type = KeyRelease; + xe.u.u.detail = darwinKeyCommandL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + // push button 2 + xe.u.u.type = ButtonPress; + xe.u.u.detail = 2; // de.key = button 2 + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + // reset Command key down + xe.u.u.type = KeyPress; + xe.u.u.detail = darwinKeyCommandL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + } else { + // first fool X into forgetting about Option key + xe.u.u.type = KeyRelease; + xe.u.u.detail = darwinKeyOptionL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + // push button 3 + xe.u.u.type = ButtonPress; + xe.u.u.detail = 3; // de.key = button 3 + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + // reset Option key down + xe.u.u.type = KeyPress; + xe.u.u.detail = darwinKeyOptionL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + } + } else { + xe.u.u.detail = 1; //de.key = button 1; + xe.u.u.type = ButtonPress; + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + } + break; + + case NX_LMOUSEUP: + // Mimic multi-button mouse with Command and Option + if (fake3Buttons && ev.flags & (NX_COMMANDMASK | NX_ALTERNATEMASK)) { + if (ev.flags & NX_COMMANDMASK) { + // first fool X into forgetting about Command key + xe.u.u.type = KeyRelease; + xe.u.u.detail = darwinKeyCommandL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + // push button 2 + xe.u.u.type = ButtonRelease; + xe.u.u.detail = 2; // de.key = button 2 + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + // reset Command key down + xe.u.u.type = KeyPress; + xe.u.u.detail = darwinKeyCommandL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + } else { + // first fool X into forgetting about Option key + xe.u.u.type = KeyRelease; + xe.u.u.detail = darwinKeyOptionL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + // push button 3 + xe.u.u.type = ButtonRelease; + xe.u.u.detail = 3; // de.key = button 3 + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + // reset Option key down + xe.u.u.type = KeyPress; + xe.u.u.detail = darwinKeyOptionL; + (darwinKeyboard->public.processInputProc) + ( &xe, darwinKeyboard, 1 ); + } + } else { + xe.u.u.detail = 1; //de.key = button 1; + xe.u.u.type = ButtonRelease; + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + } + break; + +// Button 2 isn't handled correctly by older kernels anyway. Just let +// NX_SYSDEFINED events handle these. + case NX_RMOUSEDOWN: +#if 0 + xe.u.u.detail = 2; //de.key; + xe.u.u.type = ButtonPress; + (darwinPointer->public.processInputProc)( &xe, darwinPointer, 1 ); +#endif + break; + + case NX_RMOUSEUP: +#if 0 + xe.u.u.detail = 2; //de.key; + xe.u.u.type = ButtonRelease; + (darwinPointer->public.processInputProc)( &xe, darwinPointer, 1 ); +#endif + break; + + case NX_KEYDOWN: + xe.u.u.type = KeyPress; + xe.u.u.detail = ev.data.key.keyCode + MIN_KEYCODE; + (darwinKeyboard->public.processInputProc)( &xe, darwinKeyboard, 1 ); + break; + + case NX_KEYUP: + xe.u.u.type = KeyRelease; + xe.u.u.detail = ev.data.key.keyCode + MIN_KEYCODE; + (darwinKeyboard->public.processInputProc)(&xe, darwinKeyboard, 1); + break; + + case NX_FLAGSCHANGED: + { + static int old_state = 0; + int new_on_flags = ~old_state & ev.flags; + int new_off_flags = old_state & ~ev.flags; + old_state = ev.flags; + xe.u.u.detail = ev.data.key.keyCode + MIN_KEYCODE; + + // alphalock is toggled rather than held on, + // so we have to handle it differently + if (new_on_flags & NX_ALPHASHIFTMASK || + new_off_flags & NX_ALPHASHIFTMASK) { + xe.u.u.type = KeyPress; + (darwinKeyboard->public.processInputProc) + (&xe, darwinKeyboard, 1); + xe.u.u.type = KeyRelease; + (darwinKeyboard->public.processInputProc) + (&xe, darwinKeyboard, 1); + break; + } + + if (new_on_flags) { + xe.u.u.type = KeyPress; + } else if (new_off_flags) { + xe.u.u.type = KeyRelease; + } else { + break; + } + (darwinKeyboard->public.processInputProc)(&xe, darwinKeyboard, 1); + break; + } + + case NX_SYSDEFINED: + if (ev.data.compound.subType == 7) { + long hwDelta = ev.data.compound.misc.L[0]; + long hwButtons = ev.data.compound.misc.L[1]; + int i; + + for (i = 1; i < 4; i++) { + if (hwDelta & (1 << i)) { + xe.u.u.detail = i + 1; + if (hwButtons & (1 << i)) { + xe.u.u.type = ButtonPress; + } else { + xe.u.u.type = ButtonRelease; + } + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + } + } + } + break; + + case NX_SCROLLWHEELMOVED: + { + short count = ev.data.scrollWheel.deltaAxis1; + + if (count > 0) { + xe.u.u.detail = SCROLLWHEELUPFAKE; + } else { + xe.u.u.detail = SCROLLWHEELDOWNFAKE; + count = -count; + } + + for (; count; --count) { + xe.u.u.type = ButtonPress; + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + xe.u.u.type = ButtonRelease; + (darwinPointer->public.processInputProc) + ( &xe, darwinPointer, 1 ); + } + break; + } + + default: + ErrorF("unknown event caught: %d\n", ev.type); + ErrorF("\tev.type = %d\n", ev.type); + ErrorF("\tev.location.x,y = %d,%d\n", ev.location.x, ev.location.y); + ErrorF("\tev.time = %ld\n", ev.time); + ErrorF("\tev.flags = 0x%x\n", ev.flags); + ErrorF("\tev.window = %d\n", ev.window); + ErrorF("\tev.data.key.origCharSet = %d\n", ev.data.key.origCharSet); + ErrorF("\tev.data.key.charSet = %d\n", ev.data.key.charSet); + ErrorF("\tev.data.key.charCode = %d\n", ev.data.key.charCode); + ErrorF("\tev.data.key.keyCode = %d\n", ev.data.key.keyCode); + ErrorF("\tev.data.key.origCharCode = %d\n", ev.data.key.origCharCode); + break; + } + + // why isn't this handled automatically by X??? + //miPointerAbsoluteCursor( ev.location.x, ev.location.y, ev.time ); + miPointerAbsoluteCursor( ev.location.x, ev.location.y, + tv.tv_sec * 1000 + tv.tv_usec / 1000 ); + miPointerUpdate(); + +} + +static void *DarwinHIDThread(void *arg); + +/* + * InitInput + * Register the keyboard and mouse devices + */ +void InitInput( int argc, char **argv ) +{ static int initialized = 0; + if (!initialized) { + int fd[2]; + + assert( pipe(fd) == 0 ); + darwinEventFD = fd[0]; + fcntl(darwinEventFD, F_SETFL, O_NONBLOCK); + pthread_create(&dfb.hidThread, NULL, DarwinHIDThread, (void *) fd[1]); + + darwinPointer = AddInputDevice(DarwinMouseProc, TRUE); + RegisterPointerDevice( darwinPointer ); + + darwinKeyboard = AddInputDevice(DarwinKeybdProc, TRUE); + RegisterKeyboardDevice( darwinKeyboard ); + } +} + +EvGlobals * evg; +mach_port_t masterPort; +mach_port_t notificationPort; +IONotificationPortRef NotificationPortRef; + +static void InitIOKit(void) +{ + kern_return_t kr; + + kr = IOMasterPort(bootstrap_port, &masterPort); + kern_assert( kr ); +} + +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; +} + +static void *DarwinHIDThread(void *arg) +{ + int darwinEventWriteFD = (int)arg; + + for (;;) { + IOReturn kr; + NXEvent ev; + NXEQElement *oldHead; + struct { + mach_msg_header_t header; + mach_msg_trailer_t trailer; + } msg; + + kr = mach_msg((mach_msg_header_t*) &msg, MACH_RCV_MSG, 0, + sizeof(msg), notificationPort, 0, MACH_PORT_NULL); + assert(KERN_SUCCESS == kr); + + while (evg->LLEHead != evg->LLETail) { + oldHead = (NXEQElement*)&evg->lleq[evg->LLEHead]; + ev_lock(&oldHead->sema); + ev = oldHead->event; + ClearEvent(&oldHead->event); + evg->LLEHead = oldHead->next; + ev_unlock(&oldHead->sema); + + write(darwinEventWriteFD, &ev, sizeof(ev)); + } + } + return NULL; +} + +void SetupFBandHID(void) +{ + kern_return_t kr; + io_service_t service; + io_iterator_t iter; + io_name_t name; + vm_address_t shmem, vram; + vm_size_t shmemSize; + int i; + UInt32 numModes; + IODisplayModeInformation modeInfo; + IODisplayModeID displayMode, *allModes; + IOIndex displayDepth; + IOFramebufferInformation fbInfo; + StdFBShmem_t *cshmem; + + dfb.fbService = 0; + dfb.hidService = 0; + + // find and open the IOFrameBuffer service + kr = IOServiceGetMatchingServices( masterPort, + IOServiceMatching( IOFRAMEBUFFER_CONFORMSTO ), + &iter ); + kern_assert( kr ); + + assert(service = IOIteratorNext(iter)); + + kr = IOServiceOpen( service, mach_task_self(), + kIOFBServerConnectType, &dfb.fbService ); + if (kr != KERN_SUCCESS) + FatalError("failed to connect as window server!\nMake sure you have quit the Mac OS X window server.\n"); + + IOObjectRelease( service ); + IOObjectRelease( iter ); + + // create the slice of shared memory containing cursor state data + kr = IOFBCreateSharedCursor( dfb.fbService, kIOFBCurrentShmemVersion, + 32, 32 ); + kern_assert( kr ); + + // SET THE SCREEN PARAMETERS + // get the current screen resolution, refresh rate and depth + kr = IOFBGetCurrentDisplayModeAndDepth( dfb.fbService, &displayMode, + &displayDepth ); + kern_assert( kr ); + + // use the current screen resolution if the user + // only wants to change the refresh rate + if (darwinDesiredRefresh != -1 && darwinDesiredWidth == 0) { + kr = IOFBGetDisplayModeInformation( dfb.fbService, displayMode, + &modeInfo ); + kern_assert( kr ); + 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( dfb.fbService, displayMode, + &modeInfo ); + kern_assert( kr ); + if (modeInfo.maxDepthIndex < darwinDesiredDepth) + FatalError("Current screen resolution does not support desired pixel depth!\n"); + + displayDepth = darwinDesiredDepth; + kr = IOFBSetDisplayModeAndDepth( dfb.fbService, displayMode, + displayDepth ); + kern_assert( kr ); + } + + // look for display mode with correct resolution and refresh rate + } else { + + // get an array of all supported display modes + kr = IOFBGetDisplayModeCount( dfb.fbService, &numModes ); + kern_assert( kr ); + assert(allModes = (IODisplayModeID *) + xalloc( numModes * sizeof(IODisplayModeID) )); + kr = IOFBGetDisplayModes( dfb.fbService, numModes, allModes ); + kern_assert( kr ); + + for (i = 0; i < numModes; i++) { + kr = IOFBGetDisplayModeInformation( dfb.fbService, allModes[i], + &modeInfo ); + kern_assert( kr ); + + if (modeInfo.flags & kDisplayModeValidFlag && + modeInfo.nominalWidth == darwinDesiredWidth && + modeInfo.nominalHeight == darwinDesiredHeight) { + + if (darwinDesiredDepth == -1) + darwinDesiredDepth = modeInfo.maxDepthIndex; + if (modeInfo.maxDepthIndex < darwinDesiredDepth) + FatalError("Desired screen resolution does not support desired pixel depth!\n"); + if ((darwinDesiredRefresh == -1 || + (darwinDesiredRefresh << 16) == modeInfo.refreshRate)) { + displayMode = allModes[i]; + displayDepth = darwinDesiredDepth; + kr = IOFBSetDisplayModeAndDepth( dfb.fbService, displayMode, + displayDepth ); + kern_assert( kr ); + break; + } + } + } + + xfree( allModes ); + if (i >= numModes) + FatalError("Desired screen resolution or refresh rate is not supported!\n"); + } + + kr = IOFBGetPixelInformation( dfb.fbService, displayMode, displayDepth, + kIOFBSystemAperture, &dfb.pixelInfo ); + kern_assert( kr ); + +#ifdef OLD_POWERBOOK_G3 + if (dfb.pixelInfo.pixelType == kIOCLUTPixels) + dfb.pixelInfo.pixelType = kIOFixedCLUTPixels; +#endif + + kr = IOFBGetFramebufferInformationForAperture( dfb.fbService, kIOFBSystemAperture, + &fbInfo ); + kern_assert( kr ); + + kr = IOConnectMapMemory( dfb.fbService, kIOFBCursorMemory, + mach_task_self(), (vm_address_t *) &cshmem, + &shmemSize, kIOMapAnywhere ); + kern_assert( kr ); + dfb.cursorShmem = cshmem; + + kr = IOConnectMapMemory( dfb.fbService, kIOFBSystemAperture, mach_task_self(), + &vram, &shmemSize, kIOMapAnywhere ); + kern_assert( kr ); + + dfb.framebuffer = (void*)vram; + dfb.width = fbInfo.activeWidth; + dfb.height = fbInfo.activeHeight; + dfb.pitch = fbInfo.bytesPerRow; + dfb.bitsPerPixel = fbInfo.bitsPerPixel; + dfb.colorBitsPerPixel = dfb.pixelInfo.componentCount * + dfb.pixelInfo.bitsPerComponent; + + // find and open the HID System Service + kr = IOServiceGetMatchingServices( masterPort, + IOServiceMatching( kIOHIDSystemClass ), + &iter ); + kern_assert( kr ); + + assert( service = IOIteratorNext( iter ) ); + + kr = IORegistryEntryGetName( service, name ); + kern_assert( kr ); + + kr = IOServiceOpen( service, mach_task_self(), kIOHIDServerConnectType, + &dfb.hidService ); + kern_assert( kr ); + + IOObjectRelease( service ); + IOObjectRelease( iter ); + + kr = IOHIDCreateSharedMemory( dfb.hidService, kIOHIDCurrentShmemVersion ); + kern_assert( kr ); + + kr = IOHIDSetEventsEnable(dfb.hidService, TRUE); + kern_assert( kr ); + + // Inform the HID system that the framebuffer is also connected to it + kr = IOConnectAddClient( dfb.hidService, dfb.fbService ); + kern_assert( kr ); + + kr = IOHIDSetCursorEnable(dfb.hidService, TRUE); + kern_assert( kr ); + + kr = IOConnectMapMemory( dfb.hidService, 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( dfb.hidService, kIOHIDEventNotification, + notificationPort, 0 ); + kern_assert( kr ); + + evg->movedMask |= NX_MOUSEMOVEDMASK; +} + + +/* + * InitOutput -- + * Initialize screenInfo for all actually accessible framebuffers. + * + * FIXME: why does this get called multiple times when a session is starting? + */ +void InitOutput( ScreenInfo *pScreenInfo, int argc, char **argv ) +{ int i; + static int initialized = 0; +// static PixmapFormatRec darwinFormat; + + // perform one-time-only initialization + if ( !initialized ) { + initialized = 1; + // do our appkit or darwin device driver work to open and map a screen + InitIOKit(); + SetupFBandHID(); + } + + pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + + // list how we want common pixmap formats to be padded + pScreenInfo->numPixmapFormats = NUMFORMATS; + for (i = 0; i < NUMFORMATS; i++) + pScreenInfo->formats[i] = formats[i]; + + + AddScreen( DarwinAddScreen, argc, argv ); +} + +void OsVendorFatalError( void ) +{ ErrorF( " OsVendorFatalError\n" ); +} + +void OsVendorInit(void) +{ +} + +/* + * ddxProcessArgument -- + * Process device-dependent command line args. Returns 0 if argument is + * not device dependent, otherwise Count of number of elements of argv + * that are part of a device dependent commandline option. + */ +int ddxProcessArgument( int argc, char *argv[], int i ) +{ +#if 0 + if ( !strcmp( argv[i], "-screen" ) ) { + if ( i == argc-1 ) { + FatalError( "-screen must be followed by a number" ); + } + darwinScreenNumber = atoi( argv[i+1] ); + ErrorF( "Attempting to use screen number %i\n", darwinScreenNumber ); + return 2; + } +#endif + + if ( !strcmp( argv[i], "-fakebuttons" ) ) { + fake3Buttons = TRUE; + ErrorF( "Faking a three button mouse\n" ); + return 1; + } + + if ( !strcmp( argv[i], "-nofakebuttons" ) ) { + fake3Buttons = FALSE; + ErrorF( "Not faking a three button mouse\n" ); + return 1; + } + + if ( !strcmp( argv[i], "-size" ) ) { + if ( i >= argc-2 ) { + FatalError( "-size must be followed by two numbers" ); + } +#ifdef OLD_POWERBOOK_G3 + ErrorF( "Ignoring unsupported -size option on old PowerBook G3\n"); +#else + darwinDesiredWidth = atoi( argv[i+1] ); + darwinDesiredHeight = atoi( argv[i+2] ); + ErrorF( "Attempting to use width x height = %i x %i\n", + darwinDesiredWidth, darwinDesiredHeight ); +#endif + return 3; + } + + if ( !strcmp( argv[i], "-depth" ) ) { + int bitDepth; + if ( i == argc-1 ) { + FatalError( "-depth must be followed by a number" ); + } +#ifdef OLD_POWERBOOK_G3 + ErrorF( "Ignoring unsupported -depth option on old PowerBook G3\n"); +#else + bitDepth = atoi( argv[i+1] ); + if (bitDepth == 8) + darwinDesiredDepth = 0; + else if (bitDepth == 15) + darwinDesiredDepth = 1; + else if (bitDepth == 24) + darwinDesiredDepth = 2; + else + FatalError( "Unsupported pixel depth. Use 8, 15, or 24 bits" ); + ErrorF( "Attempting to use pixel depth of %i\n", bitDepth ); +#endif + return 2; + } + + if ( !strcmp( argv[i], "-refresh" ) ) { + if ( i == argc-1 ) { + FatalError( "-refresh must be followed by a number" ); + } +#ifdef OLD_POWERBOOK_G3 + ErrorF( "Ignoring unsupported -refresh option on old PowerBook G3\n"); +#else + darwinDesiredRefresh = atoi( argv[i+1] ); + ErrorF( "Attempting to use refresh rate of %i\n", darwinDesiredRefresh ); +#endif + return 2; + } + + return 0; +} + +/* + * ddxUseMsg -- + * Print out correct use of device dependent commandline options. + * Maybe the user now knows what really to do ... + */ +void ddxUseMsg( void ) +{ + ErrorF("\n"); + ErrorF("\n"); + ErrorF("Device Dependent Usage:\n"); + ErrorF("\n"); +#if 0 + ErrorF("-screen <0,1,...> : use this mac screen num.\n" ); +#endif + ErrorF("-fakebuttons : fake a three button mouse with Command and Option keys.\n"); + ErrorF("-nofakebuttons : don't fake a three button mouse.\n"); + ErrorF("-size <height> <width> : use a screen resolution of <height> x <width>.\n"); + ErrorF("-depth <8,15,24> : use this bit depth.\n"); + ErrorF("-refresh <rate> : use a monitor refresh rate of <rate> Hz.\n"); + ErrorF("\n"); +} + +/* + * ddxGiveUp -- + * Device dependent cleanup. Called by dix before normal server death. + */ +void ddxGiveUp( void ) { + ErrorF( " ddxGiveUp\n" ); +} + +/* + * AbortDDX -- + * DDX - specific abort routine. Called by AbortServer(). The attempt is + * made to restore all original setting of the displays. Also all devices + * are closed. + */ +void AbortDDX( void ) { +#if TRUE + ErrorF( " AbortDDX\n" ); + /* + * This is needed for a abnormal server exit, since the normal exit stuff + * MUST also be performed (i.e. the vt must be left in a defined state) + */ + ddxGiveUp(); +#endif +} + +Bool DPMSSupported(void) +{ return 0; +} + +void DPMSSet(void) +{ return; +} diff --git a/xc/programs/Xserver/hw/darwin/darwin.h b/xc/programs/Xserver/hw/darwin/darwin.h new file mode 100644 index 000000000..a114167fa --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/darwin.h @@ -0,0 +1,38 @@ +/* $XFree86: xc/programs/Xserver/hw/darwin/darwin.h,v 1.1 2000/11/15 01:36:13 dawes Exp $ */ + +#ifndef _DARWIN_H +#define _DARWIN_H + +#include <pthread.h> +#include <IOKit/graphics/IOFramebufferShared.h> +#include "inputstr.h" +#include "screenint.h" +#include "extensions/XKB.h" + +typedef struct { + pthread_t hidThread; + io_connect_t fbService; + io_connect_t hidService; + io_connect_t hidParam; + void *framebuffer; + int width; + int height; + int pitch; + int bitsPerPixel; + int colorBitsPerPixel; + IOPixelInformation pixelInfo; + StdFBShmem_t *cursorShmem; +} DarwinFramebufferRec; + +void DarwinKeyboardInit(DeviceIntPtr pDev); +Bool DarwinInitCursor(ScreenPtr pScreen); + +#define assert(x) { if ((x) == 0) \ + FatalError("assert failed on line %d of %s!\n", __LINE__, __FILE__); } +#define kern_assert(x) { if ((x) != KERN_SUCCESS) \ + FatalError("assert failed on line %d of %s with kernel return 0x%x!\n", \ + __LINE__, __FILE__, x); } + +#define MIN_KEYCODE XkbMinLegalKeyCode // unfortunately, this isn't 0... + +#endif /* _DARWIN_H */ diff --git a/xc/programs/Xserver/hw/darwin/darwinCursor.c b/xc/programs/Xserver/hw/darwin/darwinCursor.c new file mode 100644 index 000000000..b6ff35f5b --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/darwinCursor.c @@ -0,0 +1,705 @@ +/************************************************************** + * + * Cursor support for Darwin X Server + * + * Three different cursor modes are possible: + * X (0) - tracking via Darwin kernel, + * display via X machine independent + * Kernel (1) - tracking and display via Darwin kernel + * (not currently supported) + * Hardware (2) - tracking and display via hardware + * + * The X software cursor uses the Darwin software cursor + * routines in IOFramebuffer.cpp to track the cursor, but + * displays the cursor image using the X machine + * independent display cursor routines in midispcur.c. + * + * The kernel cursor uses IOFramebuffer.cpp routines to + * track and display the cursor. This gives better + * performance as the display calls don't have to cross + * the kernel boundary. Unfortunately, this mode has + * synchronization issues with the user land X server + * and isn't currently used. + * + * Hardware cursor support lets the hardware handle these + * details. + * + * Kernel and hardware cursor mode only work for cursors + * up to a certain size, currently 16x16 pixels. If a + * bigger cursor is set, we fallback to X cursor mode. + * + * HISTORY: + * 1.0 by Torrey T. Lyons, October 30, 2000 + * + **************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/darwin/darwinCursor.c,v 1.1 2000/11/15 01:36:13 dawes Exp $ */ + +#include "scrnintstr.h" +#include "cursorstr.h" +#include "micmap.h" +#include <IOKit/graphics/IOGraphicsLib.h> +#include <IOKit/hidsystem/IOHIDLib.h> +#include "darwin.h" +#include "mipointrst.h" + +#define DUMP_DARWIN_CURSOR FALSE + +// The cursors format are documented in IOFramebufferShared.h. +#define RGBto34WithGamma(red, green, blue) \ + ( 0x000F \ + | (((red) & 0xF) << 12) \ + | (((green) & 0xF) << 8) \ + | (((blue) & 0xF) << 4) ) +#define RGBto38WithGamma(red, green, blue) \ + ( 0xFF << 24 \ + | (((red) & 0xFF) << 16) \ + | (((green) & 0xFF) << 8) \ + | (((blue) & 0xFF)) ) +#define HighBitOf32 0x80000000 + +typedef struct { + Bool canHWCursor; + short cursorMode; + RecolorCursorProcPtr RecolorCursor; + InstallColormapProcPtr InstallColormap; + QueryBestSizeProcPtr QueryBestSize; + miPointerSpriteFuncPtr spriteFuncs; + ColormapPtr pInstalledMap; +} DarwinCursorScreenRec, *DarwinCursorScreenPtr; + +extern DarwinFramebufferRec dfb; +static int darwinCursorScreenIndex = -1; +static unsigned long darwinCursorGeneration = 0; + +/* +=========================================================================== + + Pointer sprite functions + +=========================================================================== +*/ + +/* + Realizing the Darwin hardware cursor (ie. converting from the + X representation to the Darwin representation) is complicated + by the fact that we have three different potential cursor + formats to go to, one for each bit depth (8, 15, or 24). + The Darwin formats are documented in IOFramebufferShared.h. + X cursors are represented as two pieces, a source and a mask. + The mask is a bitmap indicating which parts of the cursor are + transparent and which parts are drawn. The source is a bitmap + indicating which parts of the non-transparent portion of the the + cursor should be painted in the foreground color and which should + be painted in the background color. The bitmaps are given in + 32-bit format with least significant byte and bit first. + (This is opposite PowerPC Darwin.) +*/ + +typedef struct { + unsigned char image[CURSORWIDTH*CURSORHEIGHT]; + unsigned char mask[CURSORWIDTH*CURSORHEIGHT]; +} cursorPrivRec, *cursorPrivPtr; + +/* + * DarwinRealizeCursor8 + * Convert the X cursor representation to an 8-bit depth + * format for Darwin. This function assumes the maximum cursor + * width is a multiple of 8. + */ +static Bool +DarwinRealizeCursor8( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + cursorPrivPtr newCursor; + unsigned char *newSourceP, *newMaskP; + CARD32 *oldSourceP, *oldMaskP; + xColorItem fgColor, bgColor; + int index, x, y, rowPad; + int cursorWidth, cursorHeight; + ColormapPtr pmap; + + // check cursor size just to be sure + cursorWidth = pCursor->bits->width; + cursorHeight = pCursor->bits->height; + if (cursorHeight > CURSORHEIGHT || cursorWidth > CURSORWIDTH) + return FALSE; + + // get cursor colors in colormap + index = pScreen->myNum; + pmap = miInstalledMaps[index]; + if (!pmap) return FALSE; + + fgColor.red = pCursor->foreRed; + fgColor.green = pCursor->foreGreen; + fgColor.blue = pCursor->foreBlue; + FakeAllocColor(pmap, &fgColor); + bgColor.red = pCursor->backRed; + bgColor.green = pCursor->backGreen; + bgColor.blue = pCursor->backBlue; + FakeAllocColor(pmap, &bgColor); + FakeFreeColor(pmap, fgColor.pixel); + FakeFreeColor(pmap, bgColor.pixel); + + // allocate memory for new cursor image + newCursor = xalloc( sizeof(cursorPrivRec) ); + if (!newCursor) + return FALSE; + memset( newCursor->image, pScreen->blackPixel, CURSORWIDTH*CURSORHEIGHT ); + memset( newCursor->mask, 0, CURSORWIDTH*CURSORHEIGHT ); + + // convert to 8-bit Darwin cursor format + oldSourceP = (CARD32 *) pCursor->bits->source; + oldMaskP = (CARD32 *) pCursor->bits->mask; + newSourceP = newCursor->image; + newMaskP = newCursor->mask; + rowPad = CURSORWIDTH - cursorWidth; + + for (y = 0; y < cursorHeight; y++) { + for (x = 0; x < cursorWidth; x++) { + if (*oldSourceP & (HighBitOf32 >> x)) + *newSourceP = fgColor.pixel; + else + *newSourceP = bgColor.pixel; + if (*oldMaskP & (HighBitOf32 >> x)) + *newMaskP = 255; + else + *newSourceP = pScreen->blackPixel; + newSourceP++; newMaskP++; + } + oldSourceP++; oldMaskP++; + newSourceP += rowPad; newMaskP += rowPad; + } + + // save the result + pCursor->devPriv[pScreen->myNum] = (pointer) newCursor; + return TRUE; +} + + +/* + * DarwinRealizeCursor15 + * Convert the X cursor representation to an 15-bit depth + * format for Darwin. + */ +static Bool +DarwinRealizeCursor15( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + unsigned short *newCursor; + unsigned short fgPixel, bgPixel; + unsigned short *newSourceP; + CARD32 *oldSourceP, *oldMaskP; + int x, y, rowPad; + int cursorWidth, cursorHeight; + + // check cursor size just to be sure + cursorWidth = pCursor->bits->width; + cursorHeight = pCursor->bits->height; + if (cursorHeight > CURSORHEIGHT || cursorWidth > CURSORWIDTH) + return FALSE; + + // allocate memory for new cursor image + newCursor = xalloc( CURSORWIDTH*CURSORHEIGHT*sizeof(short) ); + if (!newCursor) + return FALSE; + memset( newCursor, 0, CURSORWIDTH*CURSORHEIGHT*sizeof(short) ); + + // calculate pixel values + fgPixel = RGBto34WithGamma( pCursor->foreRed, pCursor->foreGreen, + pCursor->foreBlue ); + bgPixel = RGBto34WithGamma( pCursor->backRed, pCursor->backGreen, + pCursor->backBlue ); + + // convert to 15-bit Darwin cursor format + oldSourceP = (CARD32 *) pCursor->bits->source; + oldMaskP = (CARD32 *) pCursor->bits->mask; + newSourceP = newCursor; + rowPad = CURSORWIDTH - cursorWidth; + + for (y = 0; y < cursorHeight; y++) { + for (x = 0; x < cursorWidth; x++) { + if (*oldMaskP & (HighBitOf32 >> x)) { + if (*oldSourceP & (HighBitOf32 >> x)) + *newSourceP = fgPixel; + else + *newSourceP = bgPixel; + } else { + *newSourceP = 0; + } + newSourceP++; + } + oldSourceP++; oldMaskP++; + newSourceP += rowPad; + } + +#if DUMP_DARWIN_CURSOR + // Write out the cursor + ErrorF("Cursor: 0x%x\n", pCursor); + ErrorF("Width = %i, Height = %i, RowPad = %i\n", cursorWidth, + cursorHeight, rowPad); + for (y = 0; y < cursorHeight; y++) { + newSourceP = newCursor + y*CURSORWIDTH; + for (x = 0; x < cursorWidth; x++) { + if (*newSourceP == fgPixel) + ErrorF("x"); + else if (*newSourceP == bgPixel) + ErrorF("o"); + else + ErrorF(" "); + newSourceP++; + } + ErrorF("\n"); + } +#endif + + // save the result + pCursor->devPriv[pScreen->myNum] = (pointer) newCursor; + return TRUE; +} + + +/* + * DarwinRealizeCursor24 + * Convert the X cursor representation to an 24-bit depth + * format for Darwin. This function assumes the maximum cursor + * width is a multiple of 8. + */ +static Bool +DarwinRealizeCursor24( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + unsigned int *newCursor; + unsigned int fgPixel, bgPixel; + unsigned int *newSourceP; + CARD32 *oldSourceP, *oldMaskP; + int x, y, rowPad; + int cursorWidth, cursorHeight; + + // check cursor size just to be sure + cursorWidth = pCursor->bits->width; + cursorHeight = pCursor->bits->height; + if (cursorHeight > CURSORHEIGHT || cursorWidth > CURSORWIDTH) + return FALSE; + + // allocate memory for new cursor image + newCursor = xalloc( CURSORWIDTH*CURSORHEIGHT*sizeof(int) ); + if (!newCursor) + return FALSE; + memset( newCursor, 0, CURSORWIDTH*CURSORHEIGHT*sizeof(int) ); + + // calculate pixel values + fgPixel = RGBto38WithGamma( pCursor->foreRed, pCursor->foreGreen, + pCursor->foreBlue ); + bgPixel = RGBto38WithGamma( pCursor->backRed, pCursor->backGreen, + pCursor->backBlue ); + + // convert to 24-bit Darwin cursor format + oldSourceP = (CARD32 *) pCursor->bits->source; + oldMaskP = (CARD32 *) pCursor->bits->mask; + newSourceP = newCursor; + rowPad = CURSORWIDTH - cursorWidth; + + for (y = 0; y < cursorHeight; y++) { + for (x = 0; x < cursorWidth; x++) { + if (*oldMaskP & (HighBitOf32 >> x)) { + if (*oldSourceP & (HighBitOf32 >> x)) + *newSourceP = fgPixel; + else + *newSourceP = bgPixel; + } else { + *newSourceP = 0; + } + newSourceP++; + } + oldSourceP++; oldMaskP++; + newSourceP += rowPad; + } + +#if DUMP_DARWIN_CURSOR + // Write out the cursor + ErrorF("Cursor: 0x%x\n", pCursor); + ErrorF("Width = %i, Height = %i, RowPad = %i\n", cursorWidth, + cursorHeight, rowPad); + for (y = 0; y < cursorHeight; y++) { + newSourceP = newCursor + y*CURSORWIDTH; + for (x = 0; x < cursorWidth; x++) { + if (*newSourceP == fgPixel) + ErrorF("x"); + else if (*newSourceP == bgPixel) + ErrorF("o"); + else + ErrorF(" "); + newSourceP++; + } + ErrorF("\n"); + } +#endif + + // save the result + pCursor->devPriv[pScreen->myNum] = (pointer) newCursor; + return TRUE; +} + + +/* + * DarwinRealizeCursor + * + */ +static Bool +DarwinRealizeCursor( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + Bool result; + DarwinCursorScreenPtr ScreenPriv = (DarwinCursorScreenPtr) + pScreen->devPrivates[darwinCursorScreenIndex].ptr; + + if ((pCursor->bits->height > CURSORHEIGHT) || + (pCursor->bits->width > CURSORWIDTH) || + // FIXME: this condition is not needed after kernel cursor works + !ScreenPriv->canHWCursor) { + result = (*ScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCursor); + } else if (dfb.bitsPerPixel == 8) { + result = DarwinRealizeCursor8(pScreen, pCursor); + } else if (dfb.bitsPerPixel == 16) { + result = DarwinRealizeCursor15(pScreen, pCursor); + } else { + result = DarwinRealizeCursor24(pScreen, pCursor); + } + + return result; +} + + +/* + * DarwinUnrealizeCursor + * + */ +static Bool +DarwinUnrealizeCursor( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + Bool result; + DarwinCursorScreenPtr ScreenPriv = (DarwinCursorScreenPtr) + pScreen->devPrivates[darwinCursorScreenIndex].ptr; + + if ((pCursor->bits->height > CURSORHEIGHT) || + (pCursor->bits->width > CURSORWIDTH) || + // FIXME: this condition is not needed after kernel cursor works + !ScreenPriv->canHWCursor) { + result = (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCursor); + } else { + xfree( pCursor->devPriv[pScreen->myNum] ); + result = TRUE; + } + + return result; +} + + +/* + * DarwinSetCursor + * Set the cursor sprite and position + * Use hardware cursor if possible + */ +static void +DarwinSetCursor( + ScreenPtr pScreen, + CursorPtr pCursor, + int x, + int y) +{ + kern_return_t kr; + StdFBShmem_t *cshmem = dfb.cursorShmem; + DarwinCursorScreenPtr ScreenPriv = (DarwinCursorScreenPtr) + pScreen->devPrivates[darwinCursorScreenIndex].ptr; + + // are we supposed to remove the cursor? + if (!pCursor) { + if (ScreenPriv->cursorMode == 0) + (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, 0, x, y); + else { + if (!cshmem->cursorShow) { + cshmem->cursorShow++; + if (cshmem->hardwareCursorActive) { + kr = IOFBSetCursorVisible(dfb.fbService, FALSE); + kern_assert( kr ); + } + } + } + return; + } + + // can we use the kernel or hardware cursor? + if ((pCursor->bits->height <= CURSORHEIGHT) && + (pCursor->bits->width <= CURSORWIDTH) && + // FIXME: condition not needed when kernel cursor works + ScreenPriv->canHWCursor) { + + if (ScreenPriv->cursorMode == 0) // remove the X cursor + (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, 0, x, y); + ScreenPriv->cursorMode = 1; // kernel cursor + + // change the cursor image in shared memory + if (dfb.bitsPerPixel == 8) { + cursorPrivPtr newCursor = + (cursorPrivPtr) pCursor->devPriv[pScreen->myNum]; + memcpy(cshmem->cursor.bw8.image[0], newCursor->image, + CURSORWIDTH*CURSORHEIGHT); + memcpy(cshmem->cursor.bw8.mask[0], newCursor->mask, + CURSORWIDTH*CURSORHEIGHT); + } else if (dfb.bitsPerPixel == 16) { + unsigned short *newCursor = + (unsigned short *) pCursor->devPriv[pScreen->myNum]; + memcpy(cshmem->cursor.rgb.image[0], newCursor, + 2*CURSORWIDTH*CURSORHEIGHT); + } else { + unsigned int *newCursor = + (unsigned int *) pCursor->devPriv[pScreen->myNum]; + memcpy(cshmem->cursor.rgb24.image[0], newCursor, + 4*CURSORWIDTH*CURSORHEIGHT); + } + + // FIXME: We always use a full size cursor, even if the image + // is smaller because I couldn't get the padding to come out + // right otherwise. + cshmem->cursorSize[0].width = CURSORWIDTH; + cshmem->cursorSize[0].height = CURSORHEIGHT; + cshmem->hotSpot[0].x = pCursor->bits->xhot; + cshmem->hotSpot[0].y = pCursor->bits->yhot; + + // try to use a hardware cursor + if (ScreenPriv->canHWCursor) { + kr = IOFBSetNewCursor(dfb.fbService, 0, 0, 0); + // FIXME: this is a fatal error without the kernel cursor + kern_assert( kr ); +#if 0 + if (kr != KERN_SUCCESS) { + ErrorF("Could not set new cursor with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } +#endif + } + + // make the new cursor visible + if (cshmem->cursorShow) + cshmem->cursorShow--; + + if (!cshmem->cursorShow && ScreenPriv->canHWCursor) { + kr = IOFBSetCursorVisible(dfb.fbService, TRUE); + // FIXME: this is a fatal error without the kernel cursor + kern_assert( kr ); +#if 0 + if (kr != KERN_SUCCESS) { + ErrorF("Couldn't set hardware cursor visible with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } else +#endif + ScreenPriv->cursorMode = 2; // hardware cursor + } + + return; + } + + // otherwise we use a software cursor + if (ScreenPriv->cursorMode) { + /* remove the kernel or hardware cursor */ + DarwinSetCursor(pScreen, 0, x, y); + } + + ScreenPriv->cursorMode = 0; + (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, pCursor, x, y); +} + + +/* + * DarwinMoveCursor + * Move the cursor. This is a noop for a kernel or hardware cursor. + */ +static void +DarwinMoveCursor( + ScreenPtr pScreen, + int x, + int y) +{ + DarwinCursorScreenPtr ScreenPriv = (DarwinCursorScreenPtr) + pScreen->devPrivates[darwinCursorScreenIndex].ptr; + + // only the X cursor needs to be explicitly moved + if (!ScreenPriv->cursorMode) + (*ScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y); +} + +static miPointerSpriteFuncRec darwinSpriteFuncsRec = { + DarwinRealizeCursor, + DarwinUnrealizeCursor, + DarwinSetCursor, + DarwinMoveCursor +}; + + +/* +=========================================================================== + + Pointer screen functions + +=========================================================================== +*/ + +/* + * DarwinCursorOffScreen + */ +static Bool DarwinCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) +{ return FALSE; +} + + +/* + * DarwinCrossScreen + */ +static void DarwinCrossScreen(ScreenPtr pScreen, Bool entering) +{ return; +} + + +/* + * DarwinWarpCursor + * Change the cursor position without generating an event or motion history + */ +static void +DarwinWarpCursor( + ScreenPtr pScreen, + int x, + int y) +{ + kern_return_t kr; + + kr = IOHIDSetMouseLocation( dfb.hidService, x, y ); + if (kr != KERN_SUCCESS) { + ErrorF("Could not set cursor position with kernel return 0x%x.\n", kr); + } + miPointerWarpCursor(pScreen, x, y); +} + +static miPointerScreenFuncRec darwinScreenFuncsRec = { + DarwinCursorOffScreen, + DarwinCrossScreen, + DarwinWarpCursor, +}; + + +/* +=========================================================================== + + Other screen functions + +=========================================================================== +*/ + +/* + * DarwinCursorQueryBestSize + * Handle queries for best cursor size + */ +static void +DarwinCursorQueryBestSize( + int class, + unsigned short *width, + unsigned short *height, + ScreenPtr pScreen) +{ + DarwinCursorScreenPtr ScreenPriv = (DarwinCursorScreenPtr) + pScreen->devPrivates[darwinCursorScreenIndex].ptr; + + if (class == CursorShape) { + *width = CURSORWIDTH; + *height = CURSORHEIGHT; + } else + (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); +} + + +/* + * DarwinInitCursor + * Initialize cursor support + */ +Bool +DarwinInitCursor( + ScreenPtr pScreen) +{ + DarwinCursorScreenPtr ScreenPriv; + miPointerScreenPtr PointPriv; + kern_return_t kr; + + // start with no cursor displayed + if (!dfb.cursorShmem->cursorShow++) { + if (dfb.cursorShmem->hardwareCursorActive) { + kr = IOFBSetCursorVisible(dfb.fbService, FALSE); + kern_assert( kr ); + } + } + + // initialize software cursor handling (always needed as backup) + if (!miDCInitialize(pScreen, &darwinScreenFuncsRec)) { + return FALSE; + } + + // allocate private storage for this screen's hardware cursor info + if (darwinCursorGeneration != serverGeneration) { + if ((darwinCursorScreenIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + darwinCursorGeneration = serverGeneration; + } + + ScreenPriv = xcalloc( 1, sizeof(DarwinCursorScreenRec) ); + if (!ScreenPriv) return FALSE; + + pScreen->devPrivates[darwinCursorScreenIndex].ptr = (pointer) ScreenPriv; + + // check if a hardware cursor is supported + if (!dfb.cursorShmem->hardwareCursorCapable) { + ScreenPriv->canHWCursor = FALSE; + ErrorF("Hardware cursor not supported.\n"); + } else { + // we need to make sure that the hardware cursor really works + ScreenPriv->canHWCursor = TRUE; + kr = IOFBSetNewCursor(dfb.fbService, 0, 0, 0); + if (kr != KERN_SUCCESS) { + ErrorF("Could not set hardware cursor with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } + kr = IOFBSetCursorVisible(dfb.fbService, TRUE); + if (kr != KERN_SUCCESS) { + ErrorF("Couldn't set hardware cursor visible with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } + IOFBSetCursorVisible(dfb.fbService, FALSE); + } + + ScreenPriv->cursorMode = 0; + ScreenPriv->pInstalledMap = NULL; + + // override some screen procedures + ScreenPriv->QueryBestSize = pScreen->QueryBestSize; + pScreen->QueryBestSize = DarwinCursorQueryBestSize; +// ScreenPriv->ConstrainCursor = pScreen->ConstrainCursor; +// pScreen->ConstrainCursor = DarwinConstrainCursor; + + // initialize hardware cursor handling + PointPriv = (miPointerScreenPtr) + pScreen->devPrivates[miPointerScreenIndex].ptr; + + ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; + PointPriv->spriteFuncs = &darwinSpriteFuncsRec; + + /* Other routines that might be overridden */ +/* + CursorLimitsProcPtr CursorLimits; + RecolorCursorProcPtr RecolorCursor; +*/ + + return TRUE; +} diff --git a/xc/programs/Xserver/hw/darwin/darwinKeyboard.c b/xc/programs/Xserver/hw/darwin/darwinKeyboard.c new file mode 100644 index 000000000..78506587d --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/darwinKeyboard.c @@ -0,0 +1,503 @@ +//============================================================================= +// +// Keyboard support for the Darwin X Server +// +// By Torrey T. Lyons +// +// The code to parse the Darwin keymap is derived from dumpkeymap.c +// by Eric Sunshine, which includes the following license: +// +//----------------------------------------------------------------------------- +// +// Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com> +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +// NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//============================================================================= + +/* $XFree86: xc/programs/Xserver/hw/darwin/darwinKeyboard.c,v 1.1 2000/11/15 01:36:14 dawes Exp $ */ + +/* +=========================================================================== + + An X keyCode must be in the range XkbMinLegalKeyCode (8) to + XkbMaxLegalKeyCode(255). + + The keyCodes we get from the kernel range from 0 to 127, so we need to + offset the range before passing the keyCode to X. + + An X KeySym is an extended ascii code that is device independent. + + The modifier map is accessed by the keyCode, but the normal map is + accessed by keyCode - MIN_KEYCODE. Sigh. + +=========================================================================== +*/ + +// Define this to get a diagnostic output to stderr which is helpful +// in determining how the X server is interpreting the Darwin keymap. +#undef DUMP_DARWIN_KEYMAP + +#include <drivers/event_status_driver.h> +#include <IOKit/hidsystem/ev_keymap.h> +#include "darwin.h" +extern DarwinFramebufferRec dfb; +extern unsigned char darwinKeyCommandL, darwinKeyOptionL; + +#define XK_TECHNICAL // needed to get XK_Escape +#include "keysym.h" + +#define GLYPHS_PER_KEY 4 +#define NUM_KEYCODES 248 // NX_NUMKEYCODES might be better +#define MAX_KEYCODE NUM_KEYCODES + MIN_KEYCODE - 1 + +#define AltMask Mod1Mask +#define NumLockMask Mod2Mask +#define MetaMask Mod3Mask +#define ScrollLockMask Mod4Mask + +static KeySym const ascii_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, XK_KP_Enter, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_Delete, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, XK_Return, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, +// 128 + XK_Ccedilla, XK_udiaeresis, XK_eacute, XK_acircumflex, + XK_adiaeresis, XK_agrave, XK_aring, XK_ccedilla, + XK_ecircumflex, XK_ediaeresis, XK_egrave, XK_idiaeresis, + XK_icircumflex, XK_igrave, XK_Adiaeresis, XK_Aring, + XK_Eacute, XK_ae, XK_AE, XK_ocircumflex, + XK_odiaeresis, XK_ograve, XK_ntilde, XK_ugrave, + XK_ydiaeresis, XK_Odiaeresis, XK_Udiaeresis, XK_cent, + XK_sterling, XK_yen, XK_paragraph, XK_section, +// 160 + XK_aacute, XK_degree, XK_cent, XK_sterling, + XK_ntilde, XK_Ntilde, XK_paragraph, XK_Greek_BETA, + XK_questiondown,XK_hyphen, XK_notsign, XK_onehalf, + XK_onequarter, XK_exclamdown, XK_guillemotleft,XK_guillemotright, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, +// 192 + XK_questiondown,XK_exclamdown, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, XK_AE, XK_ae, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, +// 224 + XK_Greek_alpha, XK_ssharp, XK_Greek_GAMMA, XK_Greek_pi, + XK_Greek_SIGMA, XK_Greek_sigma, XK_mu, XK_Greek_tau, + XK_Greek_PHI, XK_Greek_THETA, XK_Greek_OMEGA, XK_Greek_delta, + XK_infinity, XK_Ooblique, XK_Greek_epsilon, XK_intersection, + XK_identical, XK_plusminus, XK_greaterthanequal, XK_lessthanequal, + XK_topintegral, XK_botintegral, XK_division, XK_similarequal, + XK_degree, NoSymbol, NoSymbol, XK_radical, + XK_Greek_eta, XK_twosuperior, XK_periodcentered, NoSymbol, + }; + +#define MIN_SYMBOL 0xAC +static KeySym const symbol_to_x[] = { + XK_Left, XK_Up, XK_Right, XK_Down + }; +int const NUM_SYMBOL = sizeof(symbol_to_x) / sizeof(symbol_to_x[0]); + +#define MIN_FUNCKEY 0x20 +static KeySym const funckey_to_x[] = { + XK_F1, XK_F2, XK_F3, XK_F4, + XK_F5, XK_F6, XK_F7, XK_F8, + XK_F9, XK_F10, XK_F11, XK_F12, + XK_Insert, XK_Delete, XK_Home, XK_End, + XK_Page_Up, XK_Page_Down, XK_F13, XK_F14, + XK_F15 + }; +int const NUM_FUNCKEY = sizeof(funckey_to_x) / sizeof(funckey_to_x[0]); + +typedef struct { + KeySym normalSym; + KeySym keypadSym; +} darwinKeyPad_t; + +static darwinKeyPad_t const normal_to_keypad[] = { + { XK_0, XK_KP_0 }, + { XK_1, XK_KP_1 }, + { XK_2, XK_KP_2 }, + { XK_3, XK_KP_3 }, + { XK_4, XK_KP_4 }, + { XK_5, XK_KP_5 }, + { XK_6, XK_KP_6 }, + { XK_7, XK_KP_7 }, + { XK_8, XK_KP_8 }, + { XK_9, XK_KP_9 }, + { XK_equal, XK_KP_Equal }, + { XK_asterisk, XK_KP_Multiply }, + { XK_plus, XK_KP_Add }, + { XK_comma, XK_KP_Separator }, + { XK_minus, XK_KP_Subtract }, + { XK_period, XK_KP_Decimal }, + { XK_slash, XK_KP_Divide } +}; +int const NUM_KEYPAD = sizeof(normal_to_keypad) / sizeof(normal_to_keypad[0]); + +static void DarwinBell( int loud, DeviceIntPtr pDevice, pointer ctrl, int fbclass) { + // FIXME +} + +static void DarwinChangeKeyboardControl( DeviceIntPtr device, KeybdCtrl *ctrl ) { + // keyclick, bell volume / pitch, autorepead, LED's +} + +static CARD8 modMap[MAP_LENGTH]; +static KeySym map[256 * GLYPHS_PER_KEY]; + +//----------------------------------------------------------------------------- +// Data Stream Object +// Can be configured to treat embedded "numbers" as being composed of +// either 1, 2, or 4 bytes, apiece. +//----------------------------------------------------------------------------- +typedef struct _DataStream +{ + unsigned char const *data; + unsigned char const *data_end; + short number_size; // Size in bytes of a "number" in the stream. +} DataStream; + +static DataStream* new_data_stream( unsigned char const* data, int size ) +{ + DataStream* s = (DataStream*)xalloc( sizeof(DataStream) ); + s->data = data; + s->data_end = data + size; + s->number_size = 1; // Default to byte-sized numbers. + return s; +} + +static void destroy_data_stream( DataStream* s ) +{ + xfree(s); +} + +static unsigned char get_byte( DataStream* s ) +{ + assert(s->data + 1 <= s->data_end); + return *s->data++; +} + +static short get_word( DataStream* s ) +{ + short hi, lo; + assert(s->data + 2 <= s->data_end); + hi = *s->data++; + lo = *s->data++; + return ((hi << 8) | lo); +} + +static int get_dword( DataStream* s ) +{ + int b1, b2, b3, b4; + assert(s->data + 4 <= s->data_end); + b4 = *s->data++; + b3 = *s->data++; + b2 = *s->data++; + b1 = *s->data++; + return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); +} + +static int get_number( DataStream* s ) +{ + switch (s->number_size) { + case 4: return get_dword(s); + case 2: return get_word(s); + default: return get_byte(s); + } +} + +//----------------------------------------------------------------------------- +// Utility functions to help parse Darwin keymap +//----------------------------------------------------------------------------- + +/* + * bits_set + * Calculate number of bits set in the modifier mask. + */ +static short bits_set( short mask ) +{ + short n = 0; + + for ( ; mask != 0; mask >>= 1) + if ((mask & 0x01) != 0) + n++; + return n; +} + +/* + * parse_next_char_code + * Read the next character code from the Darwin keymapping + * and write it to the X keymap. + */ +static void parse_next_char_code( + DataStream *s, + KeySym *k ) +{ + const short charSet = get_number(s); + const short charCode = get_number(s); + + if (charSet == 0) { // ascii character + if (charCode >= 0 && charCode < 256) + *k = ascii_to_x[charCode]; + } else if (charSet == 0x01) { // symbol character + if (charCode >= MIN_SYMBOL && + charCode <= MIN_SYMBOL + NUM_SYMBOL) + *k = symbol_to_x[charCode - MIN_SYMBOL]; + } else if (charSet == 0xFE) { // function key + if (charCode >= MIN_FUNCKEY && + charCode <= MIN_FUNCKEY + NUM_FUNCKEY) + *k = funckey_to_x[charCode - MIN_FUNCKEY]; + } +} + +/* + * DarwinKeyboardInit + * Get the Darwin keyboard map and compute an equivalent + * X keyboard map and modifier map. Set the new keyboard + * device structure. + */ +void DarwinKeyboardInit( + DeviceIntPtr pDev ) +{ + KeySym *k; + int i; + short numMods, numKeys, numPadKeys = 0; + KeySymsRec keySyms; + NXKeyMapping keyMap; + DataStream *keyMapStream; + unsigned char const *numPadStart = 0; + + memset( modMap, NoSymbol, sizeof( modMap ) ); + memset( map, 0, sizeof( map ) ); + + // Open a shared connection to the HID System. + // Note that the Event Status Driver is really just a wrapper + // for a kIOHIDParamConnectType connection. + assert( dfb.hidParam = NXOpenEventStatus() ); + + // get the Darwin keyboard map + keyMap.size = NXKeyMappingLength( dfb.hidParam ); + keyMap.mapping = (char*) xalloc( keyMap.size ); + assert( NXGetKeyMapping( dfb.hidParam, &keyMap )); + keyMapStream = new_data_stream( (unsigned char const*)keyMap.mapping, + keyMap.size ); + + // check the type of map + if (get_word(keyMapStream)) { + keyMapStream->number_size = 2; + ErrorF("Current 16-bit keymapping may not be interpreted correctly.\n"); + } + + // Compute the modifier map and + // insert X modifier KeySyms into keyboard map. + numMods = get_number(keyMapStream); + while (numMods-- > 0) { + int left = 1; // first keycode is left + short const charCode = get_number(keyMapStream); + short numKeyCodes = get_number(keyMapStream); + if (charCode == NX_MODIFIERKEY_NUMERICPAD) { + numPadStart = keyMapStream->data; + numPadKeys = numKeyCodes; + } + while (numKeyCodes-- > 0) { + const short keyCode = get_number(keyMapStream); + if (charCode == NX_MODIFIERKEY_ALPHALOCK) { + modMap[keyCode + MIN_KEYCODE] = LockMask; + map[keyCode * GLYPHS_PER_KEY] = XK_Caps_Lock; + } else if (charCode == NX_MODIFIERKEY_SHIFT) { + modMap[keyCode + MIN_KEYCODE] = ShiftMask; + map[keyCode * GLYPHS_PER_KEY] = + (left ? XK_Shift_L : XK_Shift_R); + } else if (charCode == NX_MODIFIERKEY_CONTROL) { + modMap[keyCode + MIN_KEYCODE] = ControlMask; + map[keyCode * GLYPHS_PER_KEY] = + (left ? XK_Control_L : XK_Control_R); + } else if (charCode == NX_MODIFIERKEY_ALTERNATE) { + modMap[keyCode + MIN_KEYCODE] = AltMask; + if (left) { + map[keyCode * GLYPHS_PER_KEY] = XK_Alt_L; + darwinKeyOptionL = keyCode + MIN_KEYCODE; + } else + map[keyCode * GLYPHS_PER_KEY] = XK_Alt_R; + } else if (charCode == NX_MODIFIERKEY_COMMAND) { + modMap[keyCode + MIN_KEYCODE] = MetaMask; + if (left) { + map[keyCode * GLYPHS_PER_KEY] = XK_Meta_L; + darwinKeyCommandL = keyCode + MIN_KEYCODE; + } else + map[keyCode * GLYPHS_PER_KEY] = XK_Meta_R; + } else if (charCode == NX_MODIFIERKEY_NUMERICPAD) { + continue; + } else if (charCode == NX_MODIFIERKEY_HELP) { + map[keyCode * GLYPHS_PER_KEY] = XK_Help; + } else { + break; + } + left = 0; + } + } + + // Convert the Darwin keyboard map to an X keyboard map. + // A key can have shifted and unshifted character codes. + // Other modifiers are ignored although they are + // present in the Darwin keyboard map. + numKeys = get_number(keyMapStream); + for (i = 0, k = map; i < numKeys; i++, k += GLYPHS_PER_KEY) { + short const charGenMask = get_number(keyMapStream); + if (charGenMask != 0xFF) { // is key bound? + short numKeyCodes = 1 << bits_set(charGenMask); + + // If alphalock and shift modifiers produce different codes, + // we only need the shift case since X handles alphalock. + if (charGenMask & 0x01 && charGenMask & 0x02) { + // record unshifted case + parse_next_char_code( keyMapStream, k ); + // skip alphalock case + get_number(keyMapStream); get_number(keyMapStream); + // record shifted case + parse_next_char_code( keyMapStream, k+1 ); + if (k[1] == k[0]) k[1] = NoSymbol; + numKeyCodes -= 3; + // skip the rest + while (numKeyCodes-- > 0) { + get_number(keyMapStream); get_number(keyMapStream); + } + + // If alphalock and shift modifiers produce same code, use it. + } else if (charGenMask & 0x03) { + // record unshifted case + parse_next_char_code( keyMapStream, k ); + // record shifted case + parse_next_char_code( keyMapStream, k+1 ); + if (k[1] == k[0]) k[1] = NoSymbol; + numKeyCodes -= 2; + // skip the rest + while (numKeyCodes-- > 0) { + get_number(keyMapStream); get_number(keyMapStream); + } + + // If neither alphalock or shift produce characters, + // use only one character code for this key, + // but it can be a special character. + } else { + parse_next_char_code( keyMapStream, k ); + numKeyCodes--; + while (numKeyCodes-- > 0) { // skip the rest + get_number(keyMapStream); get_number(keyMapStream); + + } + } + } + } + + // Now we have to go back through the list of keycodes that are on the + // numeric keypad and update the X keymap. + keyMapStream->data = numPadStart; + while(numPadKeys-- > 0) { + const short keyCode = get_number(keyMapStream); + k = &map[keyCode * GLYPHS_PER_KEY]; + for (i = 0; i < NUM_KEYPAD; i++) { + if (*k == normal_to_keypad[i].normalSym) { + k[0] = normal_to_keypad[i].keypadSym; + break; + } + } + } + + // free Darwin keyboard map + destroy_data_stream( keyMapStream ); + xfree( keyMap.mapping ); + +#ifdef DUMP_DARWIN_KEYMAP + ErrorF("Darwin -> X converted keyboard map\n"); + for (i = 0, k = map; i < NX_NUMKEYCODES; i++, k += GLYPHS_PER_KEY) { + int j; + ErrorF("0x%02x:", i); + for (j = 0; j < GLYPHS_PER_KEY; j++) { + if (k[j] == NoSymbol) { + ErrorF("\tNoSym"); + } else { + ErrorF("\t0x%x", k[j]); + } + } + ErrorF("\n"); + } +#endif + + keySyms.map = map; + keySyms.mapWidth = GLYPHS_PER_KEY; + keySyms.minKeyCode = MIN_KEYCODE; + keySyms.maxKeyCode = MAX_KEYCODE; + + assert( InitKeyboardDeviceStruct( (DevicePtr)pDev, &keySyms, modMap, + DarwinBell, + DarwinChangeKeyboardControl )); +} + +/* + * LegalModifier + * This allows the driver level to prevent some keys from being remapped + * as modifier keys. + * I have no idea why this is useful. + */ +Bool LegalModifier(unsigned int key, DevicePtr pDev) +{ + return 1; +} diff --git a/xc/programs/Xserver/hw/darwin/utils/Imakefile b/xc/programs/Xserver/hw/darwin/utils/Imakefile new file mode 100644 index 000000000..7947a14ce --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/utils/Imakefile @@ -0,0 +1,11 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/darwin/utils/Imakefile,v 1.2 2000/11/16 03:22:18 dawes Exp $ + + SRCS = dumpkeymap.c + OBJS = dumpkeymap.o +EXTRA_LOAD_FLAGS = -framework IOKit + +AllTarget(ProgramTargetName(dumpkeymap)) + +SingleProgramTarget(dumpkeymap,$(OBJS),NullParameter,NullParameter) +InstallProgram(dumpkeymap,$(BINDIR)) + diff --git a/xc/programs/Xserver/hw/darwin/utils/dumpkeymap.c b/xc/programs/Xserver/hw/darwin/utils/dumpkeymap.c new file mode 100644 index 000000000..a3b96ea45 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/utils/dumpkeymap.c @@ -0,0 +1,879 @@ +// $XFree86: xc/programs/Xserver/hw/darwin/utils/dumpkeymap.c,v 1.1 2000/11/15 01:36:14 dawes Exp $ +// +//============================================================================= +// +// Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com> +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +// NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//============================================================================= +//----------------------------------------------------------------------------- +// dumpkeymap.c +// +// Prints a textual representation of an Apple/NeXT .keymapping file, or +// the currently active key map in use by the WindowServer and the AppKit +// on the local machine. +// +// KEY MAPPING DESCRIPTION +// +// Types and Data +// -------------- +// The following type definitions are employed throughout this +// discussion: +// +// typedef unsigned char byte; +// typedef unsigned short word; +// typedef unsigned long dword; +// +// Additionally, the type definition `number' is used generically to +// indicate a numeric value. The actual size of the `number' type may be +// one or two bytes depending upon how the data is stored in the key map. +// Although most key maps use byte-sized numeric values, word-sized +// values are also allowed. +// +// Multi-byte values in a key mapping file are stored in big-endian byte +// order. +// +// Key Mapping File and Device Mapping +// ----------------------------------- +// A key mapping file begins with a magic-number and continues with a +// variable number of device-specific key mappings. +// +// struct KeyMappingFile { +// char magic_number[4]; // "KYM1" +// DeviceMapping maps[...] // Variable number of maps +// }; +// +// struct DeviceMapping { +// dword interface; // NX_EVS_DEVICE_INTERFACE_ACE, etc. +// dword handler_id; // Interface subtype (0=101, 1=102 key, etc.) +// dword map_size; // Byte count following this address +// KeyMapping map; +// }; +// +// Together, `interface' and `handler_id' identify the exact keyboard +// hardware to which this mapping applies. The `interface' value +// represents a family of keyboard device types (such as Intel, ADB, +// NeXT, Sun Type5, etc.) and `handler_id' represents a specific keyboard +// layout within that family. On MacOS/X and Darwin, `interface' +// constants can be found in IOHIDTypes.h, whereas on MacOS/X Server, +// OpenStep, and NextStep, they can be found in ev_types.h. Programs +// which display a visual representation of a keyboard layout, match +// `interface' and `handler_id' from the .keymapping file against the +// `interface' and `handler_id' values found in each .keyboard file. +// +// Key Mapping +// ----------- +// A key mapping completely defines the relationship of all scan codes +// with their associated functionality. A KeyMapping structure is +// embedded within the DeviceMapping structure in a KeyMappingFile. The +// currently active key mapping in use by the WindowServer and AppKit is +// also represented by a KeyMapping structure, and can be referred to +// directly by calling NXGetKeyMapping() and accessing the `mapping' data +// member of the returned NXKeyMapping structure. +// +// struct KeyMapping { +// word number_size; // 0=1 byte, non-zero=2 bytes +// number num_modifier_groups; // Modifier groups +// ModifierGroup modifier_groups[...]; +// number num_scan_codes; // Scan groups +// ScanGroup scan_table[...]; +// number num_sequence_lists; // Sequence lists +// Sequence sequence_lists[...]; +// number num_special_keys; // Special keys +// SpecialKey special_key[...]; +// }; +// +// The `number_size' flag determines the size, in bytes, of all remaining +// numeric values (denoted by the type definition `number') within the +// key mapping. If its value is zero, then numbers are represented by a +// single byte. If it is non-zero, then numbers are represented by a +// word (two bytes). +// +// Modifier Group +// -------------- +// A modifier group defines all scan codes which map to a particular type +// of modifier, such as "shift", "control", etc. +// +// enum Modifier { +// ALPHALOCK = 0, +// SHIFT, +// CONTROL, +// ALTERNATE, +// COMMAND, +// KEYPAD, +// HELP +// }; +// +// struct ModifierGroup { +// number modifier; // A Modifier constant +// number num_scan_codes; +// number scan_codes[...]; // Variable number of scan codes +// }; +// +// The scan_codes[] array contains a list of all scan codes which map to +// the specified modifier. The "shift", "command", and "alternate" +// modifiers are frequently mapped to two different scan codes, apiece, +// since these modifiers often appear on both the left and right sides of +// the keyboard. +// +// Scan Group +// ---------- +// There is one ScanGroup for each scan code generated by the given +// keyboard. This number is given by KeyMapping::num_scan_codes. The +// first scan group represents hardware scan code 0, the second +// represents scan code 1, etc. +// +// enum ModifierMask { +// ALPHALOCK_MASK = 1 << 0, +// SHIFT_MASK = 1 << 1, +// CONTROL_MASK = 1 << 2, +// ALTERNATE_MASK = 1 << 3, +// CARRIAGE_RETURN_MASK = 1 << 4 +// }; +// #define NOT_BOUND 0xff +// +// struct ScanGroup { +// number mask; +// Character characters[...]; +// }; +// +// For each scan code, `mask' defines which modifier combinations +// generate characters. If `mask' is NOT_BOUND (0xff) then then this +// scan code does not generate any characters ever, and its characters[] +// array is zero length. Otherwise, the characters[] array contains one +// Character record for each modifier combination. +// +// The number of records in characters[] is determined by computing +// (1 << bits_set_in_mask). In other words, if mask is zero, then zero +// bits are set, so characters[] contains only one record. If `mask' is +// (SHIFT_MASK | CONTROL_MASK), then two bits are set, so characters[] +// contains four records. +// +// The first record always represents the character which is generated by +// that key when no modifiers are active. The remaining records +// represent characters generated by the various modifier combinations. +// Using the example with the "shift" and "control" masks set, record two +// would represent the character with the shift modifier active; record +// three, the control modifier active; and record four, both the shift +// and control modifiers active. +// +// As a special case, ALPHALOCK_MASK implies SHIFT_MASK, though only +// ALPHALOCK_MASK appears in `mask'. In this case the same character is +// generated for both the shift and alpha-lock modifiers, but only needs +// to appear once in the characters[] array. +// +// Character +// --------- +// Each Character record indicates the character generated when this key +// is pressed, as well as the character set which contains the character. +// Well known character Sets are "ASCII" and "Symbol". The character set +// can also be one of the meta values FUNCTION_KEY or KEY_SEQUENCE. If +// it is FUNCTION_KEY then `char_code' represents a generally well-known +// function key such as those enumerated by FunctionKey. If the +// character set is KEY_SEQUENCE then `char_code' represents is a +// zero-base index into KeyMapping::sequence_lists[]. +// +// enum CharacterSet { +// ASCII = 0x00, +// SYMBOL = 0x01, +// ... +// FUNCTION_KEY = 0xfe, +// KEY_SEQUENCE = 0xff +// }; +// +// struct Character { +// number set; // CharacterSet of generated character +// number char_code; // Actual character generated +// }; +// +// enum FunctionKey { +// F1 = 0x20, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, +// INSERT, DELETE, HOME, END, PAGE_UP, PAGE_DOWN, PRINT_SCREEN, +// SCROLL_LOCK, PAUSE, SYS_REQUEST, BREAK, RESET, STOP, MENU, USER, +// SYSTEM, PRINT, CLEAR_LINE, CLEAR_DISPLAY, INSERT_LINE, +// DELETE_LINE, INSERT_CHAR, DELETE_CHAR, PREV, NEXT, SELECT +// }; +// +// Sequence +// -------- +// When Character::set contains the meta value KEY_SEQUENCE, the scan +// code is bound to a sequence of keys rather than a single character. A +// sequence is a series of modifiers and characters which are +// automatically generated when the associated key is depressed. Each +// generated Character is represented as previously described, with the +// exception that MODIFIER_KEY may appear in place of KEY_SEQUENCE. When +// the value of Character::set is MODIFIER_KEY then Character::char_code +// represents a modifier key rather than an actual character. If the +// modifier represented by `char_code' is non-zero, then it indicates +// that the associated modifier key has been depressed. In this case, +// the value is one of the constants enumerated by Modifier (SHIFT, +// CONTROL, ALTERNATE, etc.). If the value is zero then it means that +// the modifier keys have been released. +// +// #define MODIFIER_KEY 0xff +// +// struct Sequence { +// number num_chars; +// Character characters[...]; +// }; +// +// Special Key +// ----------- +// A special key is one which is scanned directly by the Mach kernel +// rather than by the WindowServer. In general, events are not generated +// for special keys. +// +// enum SpecialKeyType { +// VOLUME_UP = 0, +// VOLUME_DOWN, +// BRIGHTNESS_UP, +// BRIGHTNESS_DOWN, +// ALPHA_LOCK, +// HELP, +// POWER, +// SECONDARY_ARROW_UP, +// SECONDARY_ARROW_DOWN +// }; +// +// struct SpecialKey { +// number type; // A SpecialKeyType constant +// number scan_code; // Actual scan code +// }; +// +// COMPILATION INSTRUCTIONS +// +// MacOS/X, Darwin +// cc -Wall -o dumpkeymap dumpkeymap.c -framework IOKit +// +// MacOS/X Server, OpenStep, NextStep +// cc -Wall -o dumpkeymap dumpkeymap.c +// +// USAGE INSTRUCTIONS +// +// Usage: dumpkeymap [path-to-keymap ...] +// +// When provided with no arguments, this program dumps the currently +// active key map. Otherwise, it prints out the contents of each +// .keymapping files mentioned as an argument on the command line. +// +// CONCLUSION +// +// This program and its accompanying documentation were written by Eric +// Sunshine and are copyright (C)1999,2000 by Eric Sunshine +// <sunshine@sunshineco.com>. It is based on information gathered on +// September 3, 1997 by Eric Sunshine and Paul S. McCarthy +// <zarnuk@zarnuk.com> while reverse engineering the NeXT .keymapping +// file format. +// +// HISTORY +// +// 2000/11/13 Eric Sunshine <sunshine@sunshineco.com> +// Converted from C++ to plain-C. +// Now parses and takes into account the "number-size" flag stored +// with each key map. This flag indicates the size, in bytes, of +// all remaining numeric values in the mapping. Updated all code +// to respect the this flag. (Previously, the purpose of this +// field was unknown, and it was thus denoted as +// `KeyMapping::fill[2]'.) +// Updated all documentation; especially the "KEY MAPPING +// DESCRIPTION" section. Added discussion of the "number-size" +// flag and revamped all structure definitions to use the generic +// data type `number' instead of `uchar' or 'byte'. Clarified +// several sections of the documentation and added missing +// discussions about type definitions and the relationship of +// `interface' and `handler_id' to .keymapping and .keyboard +// files. +// Updated compilation instructions to include directions for all +// platforms on which this program might be built. +// Now published under the formal BSD license rather than a +// home-grown license. +// +// 1999/09/08 Eric Sunshine <sunshine@sunshineco.com> +// Created. +//----------------------------------------------------------------------------- +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <drivers/event_status_driver.h> +#include <sys/stat.h> + +#define PROG_NAME "dumpkeymap" +#define PROG_VERSION 2 +#define AUTHOR_NAME "Eric Sunshine" +#define AUTHOR_EMAIL "sunshine@sunshineco.com" +#define AUTHOR_INFO AUTHOR_NAME " <" AUTHOR_EMAIL ">" +#define COPYRIGHT "Copyright (C) 1999,2000 by " AUTHOR_INFO + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned int natural; +typedef unsigned long dword; +typedef dword number; + +#define ASCII_SET 0x00 +#define BIND_FUNCTION 0xfe +#define BIND_SPECIAL 0xff + +//----------------------------------------------------------------------------- +// Translation Tables +//----------------------------------------------------------------------------- +static char const* const SPECIAL_CODE[] = + { + "sound-up", + "sound-down", + "brightness-up", + "brightness-down", + "alpha-lock", + "help", + "power", + "secondary-up-arrow", + "secondary-down-arrow" + }; +#define N_SPECIAL_CODE (sizeof(SPECIAL_CODE) / sizeof(SPECIAL_CODE[0])) + +static char const* const MODIFIER_CODE[] = + { + "alpha-lock", + "shift", + "control", + "alternate", + "command", + "keypad", + "help" + }; +#define N_MODIFIER_CODE (sizeof(MODIFIER_CODE) / sizeof(MODIFIER_CODE[0])) + +static char const* const MODIFIER_MASK[] = + { + "-----", // R = carriage-return + "----L", // A = alternate + "---S-", // C = control + "---SL", // S = shift + "--C--", // L = alpha-lock + "--C-L", + "--CS-", + "--CSL", + "-A---", + "-A--L", + "-A-S-", + "-A-SL", + "-AC--", + "-AC-L", + "-ACS-", + "-ACSL", + "R----", + "R---L", + "R--S-", + "R--SL", + "R-C--", + "R-C-L", + "R-CS-", + "R-CSL", + "RA---", + "RA--L", + "RA-S-", + "RA-SL", + "RAC--", + "RAC-L", + "RACS-", + "RACSL", + }; +#define N_MODIFIER_MASK (sizeof(MODIFIER_MASK) / sizeof(MODIFIER_MASK[0])) + +#define FUNCTION_KEY_FIRST 0x20 +static char const* const FUNCTION_KEY[] = + { + "F1", // 0x20 + "F2", // 0x21 + "F3", // 0x22 + "F4", // 0x23 + "F5", // 0x24 + "F6", // 0x25 + "F7", // 0x26 + "F8", // 0x27 + "F9", // 0x28 + "F10", // 0x29 + "F11", // 0x2a + "F12", // 0x2b + "insert", // 0x2c + "delete", // 0x2d + "home", // 0x2e + "end", // 0x2f + "page up", // 0x30 + "page down", // 0x31 + "print screen", // 0x32 + "scroll lock", // 0x33 + "pause", // 0x34 + "sys-request", // 0x35 + "break", // 0x36 + "reset (HIL)", // 0x37 + "stop (HIL)", // 0x38 + "menu (HIL)", // 0x39 + "user (HIL)", // 0x3a + "system (HIL)", // 0x3b + "print (HIL)", // 0x3c + "clear line (HIL)", // 0x3d + "clear display (HIL)", // 0x3e + "insert line (HIL)", // 0x3f + "delete line (HIL)", // 0x40 + "insert char (HIL)", // 0x41 + "delete char (HIL)", // 0x42 + "prev (HIL)", // 0x43 + "next (HIL)", // 0x44 + "select (HIL)", // 0x45 + }; +#define N_FUNCTION_KEY (sizeof(FUNCTION_KEY) / sizeof(FUNCTION_KEY[0])) + + +//----------------------------------------------------------------------------- +// Data Stream Object +// Can be configured to treat embedded "numbers" as being composed of +// either 1, 2, or 4 bytes, apiece. +//----------------------------------------------------------------------------- +typedef struct _DataStream + { + byte const* data; + byte const* data_end; + natural number_size; // Size in bytes of a "number" in the stream. + } DataStream; + +static DataStream* new_data_stream( byte const* data, int size ) + { + DataStream* s = (DataStream*)malloc( sizeof(DataStream) ); + s->data = data; + s->data_end = data + size; + s->number_size = 1; // Default to byte-sized numbers. + return s; + } + +static void destroy_data_stream( DataStream* s ) + { + free(s); + } + +static int end_of_stream( DataStream* s ) + { + return (s->data >= s->data_end); + } + +static void expect_nbytes( DataStream* s, int nbytes ) + { + if (s->data + nbytes > s->data_end) + { + fprintf( stderr, "Insufficient data in keymapping data stream.\n" ); + exit(-1); + } + } + +static byte get_byte( DataStream* s ) + { + expect_nbytes( s, 1 ); + return *s->data++; + } + +static word get_word( DataStream* s ) + { + word hi, lo; + expect_nbytes( s, 2 ); + hi = *s->data++; + lo = *s->data++; + return ((hi << 8) | lo); + } + +static dword get_dword( DataStream* s ) + { + dword b1, b2, b3, b4; + expect_nbytes( s, 4 ); + b4 = *s->data++; + b3 = *s->data++; + b2 = *s->data++; + b1 = *s->data++; + return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); + } + +static number get_number( DataStream* s ) + { + switch (s->number_size) + { + case 4: return get_dword(s); + case 2: return get_word(s); + default: return get_byte(s); + } + } + + +//----------------------------------------------------------------------------- +// Translation Utility Functions +//----------------------------------------------------------------------------- +static char const* special_code_desc( number n ) + { + if (n < N_SPECIAL_CODE) + return SPECIAL_CODE[n]; + else + return "invalid"; + } + +static char const* modifier_code_desc( number n ) + { + if (n < N_MODIFIER_CODE) + return MODIFIER_CODE[n]; + else + return "invalid"; + } + +static char const* modifier_mask_desc( number n ) + { + if (n < N_MODIFIER_MASK) + return MODIFIER_MASK[n]; + else + return "?????"; + } + +static char const* function_key_desc( number n ) + { + if (n >= FUNCTION_KEY_FIRST && n < N_FUNCTION_KEY + FUNCTION_KEY_FIRST) + return FUNCTION_KEY[ n - FUNCTION_KEY_FIRST ]; + else + return "unknown"; + } + +static number bits_set( number mask ) + { + number n = 0; + for ( ; mask != 0; mask >>= 1) + if ((mask & 0x01) != 0) + n++; + return n; + } + + +//----------------------------------------------------------------------------- +// Unparse a list of Modifier records. +//----------------------------------------------------------------------------- +static void unparse_modifiers( DataStream* s ) + { + number nmod = get_number(s); // Modifier count + printf( "\nMODIFIERS [%lu]\n", nmod ); + while (nmod-- > 0) + { + number nscan; + number const code = get_number(s); + printf( "%s:", modifier_code_desc(code) ); + nscan = get_number(s); + while (nscan-- > 0) + printf( " 0x%02x", (natural)get_number(s) ); + putchar( '\n' ); + } + } + + +//----------------------------------------------------------------------------- +// Unparse a list of Character records. +//----------------------------------------------------------------------------- +typedef void (*UnparseSpecialFunc)( number code ); + +static void unparse_char_codes( + DataStream* s, number ncodes, UnparseSpecialFunc unparse_special ) + { + if (ncodes != 0) + { + while (ncodes-- > 0) + { + number const char_set = get_number(s); + number const code = get_number(s); + putchar(' '); + switch (char_set) + { + case ASCII_SET: + { + int const c = (int)code; + if (isprint(c)) + printf( "\"%c\"", c ); + else if (code < ' ') + printf( "\"^%c\"", c + '@' ); + else + printf( "%02x", c ); + break; + } + case BIND_FUNCTION: + printf( "[%s]", function_key_desc(code) ); + break; + case BIND_SPECIAL: + unparse_special( code ); + break; + default: + printf( "%02x/%02x", (natural)char_set, (natural)code ); + break; + } + } + } + } + + +//----------------------------------------------------------------------------- +// Unparse a list of scan code bindings. +//----------------------------------------------------------------------------- +static void unparse_key_special( number code ) + { + printf( "{seq#%lu}", code ); + } + +static void unparse_keys( DataStream* s ) + { + number const NOT_BOUND = 0xff; + number const nkeys = get_number(s); + number scan; + printf( "\nKEYS [%lu]\n", nkeys ); + for (scan = 0; scan < nkeys; scan++) + { + number const mask = get_number(s); + printf( "scan 0x%02x: ", (natural)scan ); + if (mask == NOT_BOUND) + printf( "not-bound\n" ); + else + { + number const bits = bits_set( mask ); + number const codes = 1 << bits; + printf( "%s ", modifier_mask_desc(mask) ); + unparse_char_codes( s, codes, unparse_key_special ); + putchar( '\n' ); + } + } + } + + +//----------------------------------------------------------------------------- +// Unparse a list of key sequences. +//----------------------------------------------------------------------------- +static void unparse_sequence_special( number code ) + { + printf( "{%s}", (code == 0 ? "unmodify" : modifier_code_desc(code)) ); + } + +static void unparse_sequences( DataStream* s ) + { + number const nseqs = get_number(s); + number seq; + printf( "\nSEQUENCES [%lu]\n", nseqs ); + for (seq = 0; seq < nseqs; seq++) + { + number const nchars = get_number(s); + printf( "sequence %lu: ", seq ); + unparse_char_codes( s, nchars, unparse_sequence_special ); + putchar( '\n' ); + } + } + + +//----------------------------------------------------------------------------- +// Unparse a list of special keys. +//----------------------------------------------------------------------------- +static void unparse_specials( DataStream* s ) + { + number nspecials = get_number(s); + printf( "\nSPECIALS [%lu]\n", nspecials ); + while (nspecials-- > 0) + { + number const special = get_number(s); + number const scan = get_number(s); + printf( "%s: 0x%02x\n", special_code_desc(special), (natural)scan ); + } + } + + +//----------------------------------------------------------------------------- +// Unparse the number-size flag. +//----------------------------------------------------------------------------- +static void unparse_numeric_size( DataStream* s ) + { + word const numbers_are_shorts = get_word(s); + s->number_size = numbers_are_shorts ? 2 : 1; + } + + +//----------------------------------------------------------------------------- +// Unparse an entire key map. +//----------------------------------------------------------------------------- +static void unparse_keymap_data( DataStream* s ) + { + unparse_numeric_size(s); + unparse_modifiers(s); + unparse_keys(s); + unparse_sequences(s); + unparse_specials(s); + } + + +//----------------------------------------------------------------------------- +// Unparse the active key map. +//----------------------------------------------------------------------------- +static int unparse_active_keymap( void ) + { + int rc = 1; + NXEventHandle const h = NXOpenEventStatus(); + if (h == 0) + fprintf( stderr, "Unable to open event status driver.\n" ); + else + { + NXKeyMapping km; + km.size = NXKeyMappingLength(h); + if (km.size <= 0) + fprintf( stderr, "Bad key mapping length (%d).\n", km.size ); + else + { + km.mapping = (char*)malloc( km.size ); + if (NXGetKeyMapping( h, &km ) == 0) + fprintf( stderr, "Unable to get current key mapping.\n" ); + else + { + DataStream* stream = + new_data_stream( (byte const*)km.mapping, km.size ); + unparse_keymap_data( stream ); + destroy_data_stream( stream ); + rc = 0; + } + free( km.mapping ); + } + NXCloseEventStatus(h); + } + return rc; + } + + +//----------------------------------------------------------------------------- +// Unparse one key map from a keymapping file. +//----------------------------------------------------------------------------- +static void unparse_keymap( DataStream* s ) + { + dword const interface = get_dword(s); + dword const handler_id = get_dword(s); + dword const map_size = get_dword(s); + printf( "interface=0x%02lx handler_id=0x%02lx map_size=%lu bytes\n", + interface, handler_id, map_size ); + unparse_keymap_data(s); + } + + +//----------------------------------------------------------------------------- +// Check the magic number of a keymapping file. +//----------------------------------------------------------------------------- +static int check_magic_number( DataStream* s ) + { + return (get_byte(s) == 'K' && + get_byte(s) == 'Y' && + get_byte(s) == 'M' && + get_byte(s) == '1'); + } + + +//----------------------------------------------------------------------------- +// Unparse all key maps within a keymapping file. +//----------------------------------------------------------------------------- +static int unparse_keymaps( DataStream* s ) + { + int rc = 0; + if (check_magic_number(s)) + { + int n = 0; + while (!end_of_stream(s)) + { + printf( "\nKEYMAP #%d: ", n++ ); + unparse_keymap(s); + } + } + else + { + fprintf( stderr, "Bad magic number.\n" ); + rc = 1; + } + return rc; + } + + +//----------------------------------------------------------------------------- +// Unparse a keymapping file. +//----------------------------------------------------------------------------- +static int unparse_keymap_file( char const* const path ) + { + int rc = 1; + FILE* file; + printf( "\nKEYMAP FILE: %s\n", path ); + file = fopen( path, "rb" ); + if (file == 0) + perror( "Unable to open keymap" ); + else + { + struct stat st; + if (fstat( fileno(file), &st ) != 0) + perror( "Unable to determine file size" ); + else + { + byte* buffer = (byte*)malloc( st.st_size ); + if (fread( buffer, st.st_size, 1, file ) != 1) + perror( "Unable to read keymap" ); + else + { + DataStream* stream = new_data_stream(buffer, (int)st.st_size); + fclose( file ); file = 0; + rc = unparse_keymaps( stream ); + destroy_data_stream( stream ); + } + free( buffer ); + } + if (file != 0) + fclose( file ); + } + return rc; + } + + +//----------------------------------------------------------------------------- +// Print an informational banner. +//----------------------------------------------------------------------------- +static void print_banner( void ) + { + printf( "\n" PROG_NAME " v%d by " AUTHOR_INFO "\n" COPYRIGHT "\n", + PROG_VERSION ); + } + + +//----------------------------------------------------------------------------- +// Master dispatcher. +//----------------------------------------------------------------------------- +int main( int const argc, char const* const argv[] ) + { + int rc = 0; + print_banner(); + if (argc == 1) // No arguments, unparse keymap currently in use. + rc = unparse_active_keymap(); + else // Unparse keymaps specified on command line. + { + int i; + for (i = 1; i < argc; i++) + rc |= unparse_keymap_file( argv[i] ); + } + return rc; + } + diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ark/Imakefile b/xc/programs/Xserver/hw/xfree86/drivers/ark/Imakefile new file mode 100644 index 000000000..ba5216709 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/ark/Imakefile @@ -0,0 +1,49 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ark/Imakefile,v 1.5 2000/11/15 23:13:08 dawes Exp $ +/* + * + * Copyright 2000 Ani Joshi <ajoshi@unixbox.com> + * + */ + +#define IHaveModules +#include <Server.tmpl> + +SRCS = ark_driver.c ark_accel.c + +OBJS = ark_driver.o ark_accel.o + +#if defined(XF86DriverSDK) +INCLUDES = -I. -I../../include +#else +INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86OSSRC) \ + -I$(SERVERSRC)/mfb -I$(SERVERSRC)/mi \ + -I$(SERVERSRC)/cfb -I$(XF86SRC)/xaa \ + -I$(XF86SRC)/xf1bpp -I$(XF86SRC)/xf4bpp \ + -I$(XF86SRC)/xf24_32bpp -I$(SERVERSRC)/Xext \ + -I$(XF86SRC)/vgahw -I$(XF86SRC)/ramdac \ + -I$(XF86SRC)/rac -I$(XF86SRC)/int10 \ + -I$(XF86SRC)/fbdevhw -I$(XF86SRC)/ddc \ + -I$(XF86SRC)/i2c \ + -I$(SERVERSRC)/include -I$(XINCLUDESRC) -I$(FONTINCSRC) \ + -I$(EXTINCSRC) -I$(SERVERSRC)/render +#endif + +#if MakeHasPosixVariableSubstitutions +SubdirLibraryRule($(OBJS)) +#endif + +NormalAsmObjectRule() + +ModuleObjectRule() +ObjectModuleTarget(ark, $(OBJS)) + +InstallObjectModule(ark,$(MODULEDIR),drivers) + +DependTarget() + +InstallDriverSDKNonExecFile(Imakefile,$(DRIVERSDKDIR)/drivers/ark) +InstallDriverSDKNonExecFile(ark.h,$(DRIVERSDKDIR)/drivers/ark) +InstallDriverSDKNonExecFile(ark_reg.h,$(DRIVERSDKDIR)/drivers/ark) +InstallDriverSDKNonExecFile(ark_driver.c,$(DRIVERSDKDIR)/drivers/ark) +InstallDriverSDKNonExecFile(ark_accel.c,$(DRIVERSDKDIR)/drivers/ark) + diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ark/ark.h b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark.h new file mode 100644 index 000000000..6a95f8039 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark.h @@ -0,0 +1,71 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ark/ark.h,v 1.1 2000/11/14 17:28:12 dawes Exp $ */ +/* + * ark + */ + +#ifndef _ARK_H +#define _ARK_H + +#include "xf86.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xaa.h" +#include "xf86_ansic.h" +#include "vgaHW.h" + +typedef struct _ARKRegRec { + unsigned char sr10, sr11, sr12, sr13, sr14, + sr15, sr16, sr17, sr18, sr20, + sr21, sr22, sr23, sr24, sr25, + sr26, sr27, sr28, sr29, sr2a, + sr2b; + unsigned char sr1c, sr1d; + unsigned char cr40, cr41, cr42, cr44, cr46; + unsigned char dac_command; + unsigned char stg_17xx[3]; + unsigned char gendac[6]; +} ARKRegRec, *ARKRegPtr; + + +typedef struct _ARKRec { + pciVideoPtr PciInfo; + PCITAG PciTag; + EntityInfoPtr pEnt; + CARD32 IOAddress; + CARD32 FBAddress; + unsigned char * FBBase; + unsigned char * MMIOBase; + unsigned long videoRam; + OptionInfoPtr Options; + unsigned int Flags; + Bool NoAccel; + CARD32 Bus; + XAAInfoRecPtr pXAA; + int Chipset, ChipRev; + int clock_mult; + int dac_width; + int multiplex_threshold; + int ramdac; + ARKRegRec SavedRegs; /* original mode */ + ARKRegRec ModeRegs; /* current mode */ + Bool (*CloseScreen)(int, ScreenPtr); +} ARKRec, *ARKPtr; + + +#define ARKPTR(p) ((ARKPtr)((p)->driverPrivate)) + + +#define DRIVER_NAME "ark" +#define DRIVER_VERSION "0.5.0" +#define VERSION_MAJOR 0 +#define VERSION_MINOR 5 +#define PATCHLEVEL 0 +#define ARK_VERSION ((VERSION_MAJOR << 24) | \ + (VERSION_MINOR << 16) | \ + PATCHLEVEL) + +#define ZOOMDAC 0x404 +#define ATT490 0x101 + + +#endif /* _ARK_H */ diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_accel.c new file mode 100644 index 000000000..c2cefce63 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_accel.c @@ -0,0 +1,227 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ark/ark_accel.c,v 1.4 2000/11/15 23:13:09 dawes Exp $ */ +/* + * Copyright 2000 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for ARK Logic chipset + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation and + * that the name of Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * + * Based on the 3.3.x driver by: + * Harm Hanemaayer <H.Hanemaayer@inter.nl.net> + * + */ + + +#include "Xarch.h" +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "xaa.h" +#include "xf86PciInfo.h" +#include "compiler.h" + +#include "ark.h" +#include "ark_reg.h" + + +int curx, cury, cmd_flags; + + +static void ARKSync(ScrnInfoPtr pScrn) +{ + for (;;) { + if (!(inb(0x3cb) & 0x40)) + break; + } +} + + +static void ARKSetupForSolidFill(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + ARKPtr pARK = ARKPTR(pScrn); + + OUTREG16(FG_COLOR, color); + /* ARK color mix matches X raster-ops */ + OUTREG16(COLOR_MIX_SEL, (rop | (rop << 8))); + switch (pScrn->bitsPerPixel) { + case 8: + if ((planemask & 0xff) == 0xff) + cmd_flags = DISABLE_PLANEMASK; + else { + OUTREG16(WRITE_PLANEMASK, planemask); + cmd_flags = 0; + } + break; + case 16: + if ((planemask & 0xffff) == 0xffff) + cmd_flags = DISABLE_PLANEMASK; + else { + OUTREG16(WRITE_PLANEMASK, planemask); + cmd_flags = 0; + } + break; + case 32: + OUTREG16(FG_COLOR_HI, color >> 16); + if ((planemask & 0xffffff) == 0xffffff) + cmd_flags = DISABLE_PLANEMASK; + else { + OUTREG16(WRITE_PLANEMASK, planemask); + cmd_flags = 0; + } + break; + } + + curx = cury = -1; +} + + +static void ARKSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, + int y, int w, int h) +{ + ARKPtr pARK = ARKPTR(pScrn); + int dst_addr; + + OUTREG(WIDTH, ((h - 1) << 16) | (w - 1)); + if (x != curx || y != cury) { + dst_addr = y * pScrn->displayWidth + x; + OUTREG(DST_ADDR, dst_addr); + curx = x; + cury = y; + } + OUTREG16(COMMAND, SELECT_BG_COLOR | SELECT_FG_COLOR | + STENCIL_ONES | DISABLE_CLIPPING | BITBLT | + cmd_flags); + cury += h; +} + + + +static void ARKSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, + int ydir, int rop, unsigned int planemask, + int trans_color) +{ + ARKPtr pARK = ARKPTR(pScrn); + + cmd_flags = 0; + if (trans_color != -1) { + if (pScrn->bitsPerPixel <= 16) + OUTREG16(TRANS_COLOR, trans_color); + else { + OUTREG16(TRANS_COLOR, trans_color & 0xffff); + OUTREG16(TRANS_COLOR_HI, trans_color >> 16); + } + cmd_flags = STENCIL_GENERATED; + OUTREG16(COLOR_MIX_SEL, rop | 0x0500); + } else { + OUTREG16(COLOR_MIX_SEL, rop | (rop << 8)); + } + + if (ydir < 0) + cmd_flags |= UP; + if (xdir < 0) + cmd_flags |= LEFT; + + /* yes, quite ugly */ + if ((pScrn->bitsPerPixel == 8 && (planemask & 0xff) == 0xff) || + (pScrn->bitsPerPixel == 16 && (planemask & 0xffff) == 0xffff) || + (pScrn->bitsPerPixel == 32 && (planemask & 0xffffff) == 0xffffff)) + cmd_flags |= DISABLE_PLANEMASK; + else + OUTREG16(WRITE_PLANEMASK, planemask); + +} + + + +static void ARKSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, + int x2, int y2, + int w, int h) +{ + ARKPtr pARK = ARKPTR(pScrn); + int src_addr, dst_addr; + + if (cmd_flags & UP) { + src_addr = (y1 + h - 1) * pScrn->displayWidth; + dst_addr = (y2 + h - 1) * pScrn->displayWidth; + } else { + src_addr = y1 * pScrn->displayWidth; + dst_addr = y2 * pScrn->displayWidth; + } + if (cmd_flags & LEFT) { + src_addr += x1 + w - 1; + dst_addr += x2 + w - 1; + } else { + src_addr += x1; + dst_addr += x2; + } + + OUTREG(SRC_ADDR, src_addr); + OUTREG(DST_ADDR, dst_addr); + OUTREG(WIDTH, ((h - 1) << 16) | (w - 1)); + OUTREG16(COMMAND, BG_BITMAP | FG_BITMAP | DISABLE_CLIPPING | + BITBLT | cmd_flags); +} + + + +Bool ARKAccelInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ARKPtr pARK = ARKPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + XAAInfoRecPtr pXAA; + + if (!(pXAA = XAACreateInfoRec())) + return FALSE; + + pXAA->Flags = LINEAR_FRAMEBUFFER; + + pXAA->Sync = ARKSync; + pXAA->SetupForSolidFill = ARKSetupForSolidFill; + pXAA->SubsequentSolidFillRect = ARKSubsequentSolidFillRect; + pXAA->ScreenToScreenCopyFlags = 0; + pXAA->SetupForScreenToScreenCopy = ARKSetupForScreenToScreenCopy; + pXAA->SubsequentScreenToScreenCopy = ARKSubsequentScreenToScreenCopy; + + OUTREG16(COLOR_MIX_SEL, 0x0303); + if (pARK->Chipset == PCI_CHIP_1000PV) { + OUTREG16(WRITE_PLANEMASK, 0xffff); + OUTREG16(TRANS_COLOR_MSK, 0xffff); + } else { + OUTREG16(TRANS_COLOR, 0xffff); + OUTREG16(TRANS_COLOR, 0xffffffff >> 16); + } + if (pARK->Chipset == PCI_CHIP_1000PV && pScrn->bitsPerPixel == 32) { + OUTREG16(STENCIL_PITCH, pScrn->displayWidth * 2); + OUTREG16(SRC_PITCH, pScrn->displayWidth * 2); + OUTREG16(DST_PITCH, pScrn->displayWidth * 2); + } else { + OUTREG16(STENCIL_PITCH, pScrn->displayWidth); + OUTREG16(SRC_PITCH, pScrn->displayWidth); + OUTREG16(DST_PITCH, pScrn->displayWidth); + } + + OUTREG16(BITMAP_CONFIG, LINEAR_STENCIL_ADDR | LINEAR_SRC_ADDR | + LINEAR_DST_ADDR); + + return XAAInit(pScreen, pXAA); +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_driver.c new file mode 100644 index 000000000..b7e765b5c --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_driver.c @@ -0,0 +1,1170 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ark/ark_driver.c,v 1.8 2000/11/15 23:13:09 dawes Exp $ */ +/* + * Copyright 2000 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for ARK Logic chipset + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation and + * that the name of Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * + * Based on the 3.3.x driver by: + * Harm Hanemaayer <H.Hanemaayer@inter.nl.net> + * + */ + + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xf86Version.h" +#include "xf86Resources.h" +#include "xf86fbman.h" +#include "xf86cmap.h" +#include "compiler.h" +#include "xaa.h" +#include "mipointer.h" +#include "micmap.h" +#include "mibstore.h" + +#include "ark.h" + + +/* + * prototypes + */ +static OptionInfoPtr ARKAvailableOptions(int chipid, int busid); +static void ARKIdentify(int flags); +static Bool ARKProbe(DriverPtr drv, int flags); +static Bool ARKPreInit(ScrnInfoPtr pScrn, int flags); +static Bool ARKEnterVT(int scrnIndex, int flags); +static void ARKLeaveVT(int scrnIndex, int flags); +static void ARKSave(ScrnInfoPtr pScrn); +static Bool ARKScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, + char **argv); +static Bool ARKMapMem(ScrnInfoPtr pScrn); +static void ARKUnmapMem(ScrnInfoPtr pScrn); +static Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void ARKAdjustFrame(int scrnIndex, int x, int y, int flags); +Bool ARKSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +Bool ARKCloseScreen(int scrnIndex, ScreenPtr pScreen); +Bool ARKSaveScreen(ScreenPtr pScreen, int mode); +static void ARKFreeScreen(int scrnIndex, int flags); +static void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors, + int *indicies, LOCO *colors, + VisualPtr pVisual); +static void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new); + +/* helpers */ +static unsigned char get_daccomm(); +static unsigned char set_daccom(unsigned char comm); + + +DriverRec ARK = +{ + ARK_VERSION, + DRIVER_NAME, + ARKIdentify, + ARKProbe, + ARKAvailableOptions, + NULL, + 0 +}; + +/* supported chipsets */ +static SymTabRec ARKChipsets[] = { + { PCI_CHIP_1000PV, "ark1000pv" }, + { PCI_CHIP_2000PV, "ark2000pv" }, + { PCI_CHIP_2000MT, "ark2000mt" }, + { -1, NULL } +}; + +static PciChipsets ARKPciChipsets[] = { + { PCI_CHIP_1000PV, PCI_CHIP_1000PV, RES_SHARED_VGA }, + { PCI_CHIP_2000PV, PCI_CHIP_2000PV, RES_SHARED_VGA }, + { PCI_CHIP_2000MT, PCI_CHIP_2000MT, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED } +}; + +typedef enum { + OPTION_NOACCEL +} ARKOpts; + +static OptionInfoRec ARKOptions[] = { + { OPTION_NOACCEL, "noaccel", OPTV_BOOLEAN, {0}, FALSE } +}; + +static const char *fbSymbols[] = { + "fbScreenInit", + NULL +}; + +static const char *vgaHWSymbols[] = { + "vgaHWGetHWRec", + "vgaHWFreeHWRec", + "vgaHWGetIOBase", + "vgaHWSave", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWMapMem", + "vgaHWUnmapMem", + "vgaHWSaveScreen", + "vgaHWLock", + NULL +}; + +static const char *xaaSymbols[] = { + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAInit", + "XAAScreenIndex", + NULL +}; + +#ifdef XFree86LOADER + +MODULESETUPPROTO(ARKSetup); + +static XF86ModuleVersionInfo ARKVersRec = { + "ark", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0, 0, 0, 0} +}; + +XF86ModuleData arkModuleData = { &ARKVersRec, ARKSetup, NULL }; + +pointer ARKSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&ARK, module, 0); + LoaderRefSymLists(fbSymbols, vgaHWSymbols, xaaSymbols, NULL); + return (pointer) 1; + } else { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +#endif /* XFree86LOADER */ + + +static Bool ARKGetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(ARKRec), 1); + + return TRUE; +} + +static void ARKFreeRec(ScrnInfoPtr pScrn) +{ + if (!pScrn->driverPrivate) + return; + + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +static OptionInfoPtr ARKAvailableOptions(int chipid, int busid) +{ + return ARKOptions; +} + +static void ARKIdentify(int flags) +{ + xf86PrintChipsets("ark", "driver (version " DRIVER_VERSION " for ARK Logic chipset", + ARKChipsets); +} + +static Bool ARKProbe(DriverPtr drv, int flags) +{ + int i; + GDevPtr *devSections = NULL; + int *usedChips; + int numDevSections; + int numUsed; + Bool foundScreen = FALSE; + + /* sanity check */ + if ((numDevSections = xf86MatchDevice("ark", &devSections)) <= 0) + return FALSE; + + /* do ISA later */ + numUsed = xf86MatchPciInstances("ark", PCI_VENDOR_ARK, + ARKChipsets, ARKPciChipsets, + devSections, numDevSections, drv, + &usedChips); + + if (devSections) + xfree(devSections); + + if (numUsed <= 0) + return FALSE; + + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i=0; i<numUsed; i++) { + ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0); + + pScrn->driverVersion = VERSION_MAJOR; + pScrn->driverName = DRIVER_NAME; + pScrn->name = "ark"; + pScrn->Probe = ARKProbe; + pScrn->PreInit = ARKPreInit; + pScrn->ScreenInit = ARKScreenInit; + pScrn->SwitchMode = ARKSwitchMode; + pScrn->AdjustFrame = ARKAdjustFrame; + pScrn->EnterVT = ARKEnterVT; + pScrn->LeaveVT = ARKLeaveVT; + pScrn->FreeScreen = ARKFreeScreen; + foundScreen = TRUE; + xf86ConfigActivePciEntity(pScrn, usedChips[i], ARKPciChipsets, + NULL, NULL, NULL, NULL, NULL); + } + + xfree(usedChips); + + return foundScreen; +} + + +static Bool ARKPreInit(ScrnInfoPtr pScrn, int flags) +{ + EntityInfoPtr pEnt; + ARKPtr pARK; + vgaHWPtr hwp; + MessageType from = X_DEFAULT; + int i; + ClockRangePtr clockRanges; + char *mod = NULL; + const char *reqSym = NULL; + rgb zeros = {0, 0, 0}; + Gamma gzeros = {0.0, 0.0, 0.0}; + unsigned char tmp; + + if (flags & PROBE_DETECT) + return FALSE; + + if (!xf86LoadSubModule(pScrn, "vgahw")) + return FALSE; + + xf86LoaderReqSymLists(vgaHWSymbols, NULL); + + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + + pScrn->monitor = pScrn->confScreen->monitor; + + if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | Support32bppFb)) + return FALSE; + else { + switch (pScrn->depth) { + case 8: + case 16: + case 24: + case 32: + /* OK */ + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + } + + xf86PrintDepthBpp(pScrn); + + if (pScrn->depth > 8) { + if (!xf86SetWeight(pScrn, zeros, zeros)) + return FALSE; + } + + if (pScrn->depth == 8) + pScrn->rgbBits = 8; + + if (!xf86SetDefaultVisual(pScrn, -1)) + return FALSE; + + pScrn->progClock = TRUE; + + if (!ARKGetRec(pScrn)) + return FALSE; + + pARK = ARKPTR(pScrn); + + xf86CollectOptions(pScrn, NULL); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ARKOptions); + + if (xf86ReturnOptValBool(ARKOptions, OPTION_NOACCEL, FALSE)) { + pARK->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - acceleration disabled\n"); + } else + pARK->NoAccel = FALSE; + + if (pScrn->numEntities > 1) { + ARKFreeRec(pScrn); + return FALSE; + } + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pEnt->resources) { + xfree(pEnt); + ARKFreeRec(pScrn); + return FALSE; + } + + pARK->PciInfo = xf86GetPciInfoForEntity(pEnt->index); + xf86RegisterResources(pEnt->index, NULL, ResNone); + xf86SetOperatingState(RES_SHARED_VGA, pEnt->index, ResUnusedOpr); + xf86SetOperatingState(resVgaMemShared, pEnt->index, ResDisableOpr); + + if (pEnt->device->chipset && *pEnt->device->chipset) { + pScrn->chipset = pEnt->device->chipset; + pARK->Chipset = xf86StringToToken(ARKChipsets, pScrn->chipset); + } else if (pEnt->device->chipID >= 0) { + pARK->Chipset = pEnt->device->chipID; + pScrn->chipset = (char *)xf86TokenToString(ARKChipsets, + pARK->Chipset); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", + pARK->Chipset); + } else { + pARK->Chipset = pARK->PciInfo->chipType; + pScrn->chipset = (char *)xf86TokenToString(ARKChipsets, + pARK->Chipset); + } + + if (pEnt->device->chipRev >= 0) { + pARK->ChipRev = pEnt->device->chipRev; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", + pARK->ChipRev); + } else + pARK->ChipRev = pARK->PciInfo->chipRev; + + xfree(pEnt); + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Chipset: \"%s\"\n", pScrn->chipset); + + pARK->PciTag = pciTag(pARK->PciInfo->bus, pARK->PciInfo->device, + pARK->PciInfo->func); + + /* unlock CRTC[0-7] */ + outb(hwp->IOBase + 4, 0x11); + tmp = inb(hwp->IOBase + 5); + outb(hwp->IOBase + 5, tmp & 0x7f); + modinx(0x3c4, 0x1d, 0x01, 0x01); + + /* use membase's later on ??? */ + pARK->FBAddress = (rdinx(0x3c4, 0x13) << 16) + + (rdinx(0x3c4, 0x14) << 24); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer @ 0x%x\n", + pARK->FBAddress); + + if (!xf86SetGamma(pScrn, gzeros)) + return FALSE; + + if (!pScrn->videoRam) { + unsigned char sr10; + + sr10 = rdinx(0x3c4, 0x10); + if (pARK->Chipset == PCI_CHIP_1000PV) { + if ((sr10 & 0x40) == 0) + pScrn->videoRam = 1024; + else + pScrn->videoRam = 2048; + } + if (pARK->Chipset == PCI_CHIP_2000PV || + pARK->Chipset == PCI_CHIP_2000MT) { + if ((sr10 & 0xc0) == 0) + pScrn->videoRam = 1024; + else if ((sr10 & 0xc0) == 0x40) + pScrn->videoRam = 2048; + else + pScrn->videoRam = 4096; + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected %d bytes video ram\n", + pScrn->videoRam); + + /* try to detect the RAMDAC */ + { + int man_id, dev_id; + + inb(0x3c6); /* skip command register */ + man_id = inb(0x3c6); /* manufacturer id */ + dev_id = inb(0x3c6); /* device id */ + if (man_id == 0x84 && dev_id == 0x98) { + pARK->ramdac = ZOOMDAC; + pARK->dac_width = 16; + pARK->multiplex_threshold = 40000; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected ZOOMDAC\n"); + } + } + + /* hack for this Bali32 */ + pARK->ramdac = ATT490; + pARK->dac_width = 8; + + pARK->clock_mult = 1; + if (pARK->dac_width == 16) { + if (pScrn->bitsPerPixel == 32) + pARK->clock_mult = 2; + } + + pScrn->numClocks = 1; + pScrn->clock[0] = 80000; /* safe */ + + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = 20000; + clockRanges->maxClock = 80000; + clockRanges->clockIndex = -1; + clockRanges->interlaceAllowed = FALSE; /* ? */ + clockRanges->doubleScanAllowed = FALSE; /* ? */ + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 2048, pScrn->bitsPerPixel, + 128, 2048, pScrn->virtualX, + pScrn->display->virtualY, pARK->videoRam * 1024, + LOOKUP_BEST_REFRESH); + if (i == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes left\n"); + ARKFreeRec(pScrn); + return FALSE; + } + + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes found\n"); + ARKFreeRec(pScrn); + return FALSE; + } + + xf86SetCrtcForModes(pScrn, 0); + pScrn->currentMode = pScrn->modes; + xf86PrintModes(pScrn); + xf86SetDpi(pScrn, 0, 0); + + xf86LoadSubModule(pScrn, "fb"); + xf86LoaderReqSymbols("fbScreenInit", NULL); + + if (!pARK->NoAccel) { + xf86LoadSubModule(pScrn, "xaa"); + xf86LoaderReqSymLists(xaaSymbols, NULL); + } + + return TRUE; +} +} + +static Bool ARKScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, + char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ARKPtr pARK = ARKPTR(pScrn); + BoxRec MemBox; + int i; + + pScrn->fbOffset = 0; + + if (!ARKMapMem(pScrn)) { + ARKFreeRec(pScrn); + return FALSE; + } + + ARKSave(pScrn); + +/* vgaHWBlankScreen(pScrn, TRUE); */ + + if (!ARKModeInit(pScrn, pScrn->currentMode)) + return FALSE; + + ARKSaveScreen(pScreen, SCREEN_SAVER_ON); + + pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + miClearVisualTypes(); + if (pScrn->bitsPerPixel > 8) { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + } else { + if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + } + + if (!fbScreenInit(pScreen, pARK->FBBase, pScrn->virtualX, + pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth, pScrn->bitsPerPixel)) + return FALSE; + + xf86SetBlackWhitePixels(pScreen); + + if (pScrn->bitsPerPixel > 8) { + VisualPtr pVis; + + pVis = pScreen->visuals + pScreen->numVisuals; + while (--pVis >= pScreen->visuals) { + if ((pVis->class | DynamicClass) == DirectColor) { + pVis->offsetRed = pScrn->offset.red; + pVis->offsetGreen = pScrn->offset.green; + pVis->offsetBlue = pScrn->offset.blue; + pVis->redMask = pScrn->mask.red; + pVis->greenMask = pScrn->mask.green; + pVis->blueMask = pScrn->mask.blue; + } + } + } + + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + + if (!pARK->NoAccel) { + if (ARKAccelInit(pScreen)) { + xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Acceleration initialization failed\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); + } + } else { + xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); + } + + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + if (!miCreateDefColormap(pScreen)) + return FALSE; + + if (!xf86HandleColormaps(pScreen, 256, 8, ARKLoadPalette, NULL, + CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + +/* vgaHWBlankScreen(pScrn, TRUE); */ + + pScreen->SaveScreen = ARKSaveScreen; + pARK->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = ARKCloseScreen; + + return TRUE; +} + + + +static void ARKSave(ScrnInfoPtr pScrn) +{ + ARKPtr pARK = ARKPTR(pScrn); + ARKRegPtr save = &pARK->SavedRegs; + vgaHWPtr hwp = VGAHWPTR(pScrn); + int vgaIOBase = hwp->IOBase; + + vgaHWUnlock(hwp); + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); + vgaHWLock(hwp); + + /* set read and write aperture index to 0 */ + wrinx(0x3c4, 0x15, 0x00); + wrinx(0x3c4, 0x16, 0x00); + outb(0x3c8, 0); /* reset DAC register access mode */ + + save->sr10 = rdinx(0x3c4, 0x10); + save->sr11 = rdinx(0x3c4, 0x11); + save->sr12 = rdinx(0x3c4, 0x12); + save->sr13 = rdinx(0x3c4, 0x13); + save->sr14 = rdinx(0x3c4, 0x14); + save->sr15 = rdinx(0x3c4, 0x15); + save->sr16 = rdinx(0x3c4, 0x16); + save->sr17 = rdinx(0x3c4, 0x17); + save->sr18 = rdinx(0x3c4, 0x18); + +#if 0 + save->sr1d = rdinx(0x3c4, 0x1d); + save->sr1c = rdinx(0x3c4, 0x1c); + + save->sr20 = rdinx(0x3c4, 0x20); + save->sr21 = rdinx(0x3c4, 0x21); + save->sr22 = rdinx(0x3c4, 0x22); + save->sr23 = rdinx(0x3c4, 0x23); + save->sr24 = rdinx(0x3c4, 0x24); + save->sr25 = rdinx(0x3c4, 0x25); + save->sr26 = rdinx(0x3c4, 0x26); + save->sr27 = rdinx(0x3c4, 0x27); + save->sr29 = rdinx(0x3c4, 0x29); + save->sr2a = rdinx(0x3c4, 0x2a); + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) { + save->sr28 = rdinx(0x3c4, 0x28); + save->sr2b = rdinx(0x3c4, 0x2b); + } +#endif + + save->cr40 = rdinx(vgaIOBase + 4, 0x40); + save->cr41 = rdinx(vgaIOBase + 4, 0x41); + save->cr42 = rdinx(vgaIOBase + 4, 0x42); + save->cr44 = rdinx(vgaIOBase + 4, 0x44); + + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) + save->cr46 = rdinx(vgaIOBase + 4, 0x46); + + /* save RAMDAC regs here, based on type */ + save->dac_command = get_daccomm(); +} + + + +static Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + ARKPtr pARK = ARKPTR(pScrn); + ARKRegPtr new = &pARK->ModeRegs; + int multiplexing, dac16, modepitch; + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr pVga = &hwp->ModeReg; + int vgaIOBase = hwp->IOBase; + unsigned char tmp; + int offset; + + multiplexing = 0; + + if ((pScrn->bitsPerPixel == 8) && (pARK->dac_width == 16) && + (mode->Clock > pARK->multiplex_threshold)) + multiplexing = 1; + + if (pARK->clock_mult == 2) { + if (!mode->CrtcHAdjusted) { + mode->CrtcHDisplay <<= 1; + mode->CrtcHSyncStart <<= 1; + mode->CrtcHSyncEnd <<= 1; + mode->CrtcHTotal <<= 1; + mode->CrtcHSkew <<= 1; + mode->CrtcHAdjusted = TRUE; + } + } + + if (multiplexing) { + if (!mode->CrtcHAdjusted) { + mode->CrtcHDisplay >>= 1; + mode->CrtcHSyncStart >>= 1; + mode->CrtcHSyncEnd >>= 1; + mode->CrtcHTotal >>= 1; + mode->CrtcHSkew >>= 1; + mode->CrtcHAdjusted = TRUE; + } + } + + if (!vgaHWInit(pScrn, mode)) + return FALSE; + + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) { + new->cr46 = rdinx(vgaIOBase + 4, 0x46) & ~0x04; + dac16 = 0; + if (pScrn->bitsPerPixel > 8) + dac16 = 1; + if (dac16) + new->cr46 |= 0x04; + } + + offset = (pScrn->displayWidth * (pScrn->bitsPerPixel / 8)) >> 3; + pVga->CRTC[0x13] = offset; + pVga->Attribute[0x11] = 0x00; + new->cr41 = (offset & 0x100) >> 5; + + pVga->MiscOutReg |= 0x0c; + + new->sr11 = rdinx(0x3c4, 0x11) & ~0x0f; + switch (pScrn->bitsPerPixel) { + case 8: + new->sr11 |= 0x06; + break; + case 16: + new->sr11 |= 0x0a; + break; + case 24: + new->sr11 |= 0x06; + break; + case 32: + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) + new->sr11 |= 0x0e; + else + new->sr11 |= 0x0a; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported screen depth %d\n", + pScrn->bitsPerPixel); + return FALSE; + } + + switch (pScrn->displayWidth) { + case 640: + modepitch = 0; + break; + case 800: + modepitch = 1; + break; + case 1024: + modepitch = 2; + break; + case 1280: + modepitch = 4; + break; + case 1600: + modepitch = 5; + break; + case 2048: + modepitch = 6; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported screen width %d\n", + pScrn->displayWidth); + return FALSE; + } + + new->sr17 &= ~0xc7; + new->sr17 |= modepitch; + + new->sr10 = rdinx(0x3c4, 0x10) & ~0x1f; + new->sr10 |= 0x1f; + + new->sr13 = pARK->FBAddress >> 16; + new->sr14 = pARK->FBAddress >> 24; + + new->sr12 = rdinx(0x3c4, 0x12) & ~0x03; + switch (pScrn->videoRam) { + case 1024: + new->sr12 |= 0x01; + break; + case 2048: + new->sr12 |= 0x02; + break; + case 4096: + new->sr12 |= 0x03; + break; + default: + new->sr12 |= 0x01; + break; + } + + new->sr15 = new->sr16 = 0; + + tmp = 0; + if ((mode->CrtcVTotal - 2) & 0x400) + tmp |= 0x80; + if ((mode->CrtcVDisplay - 1) & 0x400) + tmp |= 0x40; + if (mode->CrtcVSyncStart & 0x400) + tmp |= 0x10; + new->cr40 = tmp; + + tmp = new->cr41; /* initialized earlier */ + if ((mode->CrtcHTotal / 8 - 5) & 0x100) + tmp |= 0x80; + if ((mode->CrtcHDisplay / 8 - 1) & 0x100) + tmp |= 0x40; + if ((mode->CrtcHSyncStart / 8 - 1) & 0x100) + tmp |= 0x20; + if ((mode->CrtcHSyncStart / 8) & 0x100) + tmp |= 0x10; + new->cr41 |= tmp; + + new->cr44 = rdinx(vgaIOBase + 4, 0x44) & ~0x34; + new->cr44 &= ~0x01; + new->cr42 = 0; + + /* check interlace here later */ + + /* set display FIFO threshold */ + { + int threshold; + unsigned char tmp; + int bandwidthused, percentused; + + /* mostly guesses here as I would need to know more about + * and from the ramdac... + */ + bandwidthused = (mode->Clock / pARK->clock_mult) * + (pScrn->bitsPerPixel / 8); + /* 120000 is another guess */ + percentused = (bandwidthused * 100) / 120000; + tmp = rdinx(0x3c4, 0x18); + if (pARK->Chipset == PCI_CHIP_1000PV) { + threshold = 4; + tmp |= 0x08; /* enable full FIFO (8 deep) */ + tmp &= ~0x07; + tmp |= threshold; + } + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) { + threshold = 12; + if (percentused >= 45) + threshold = 8; + if (percentused >= 70) + threshold = 4; + tmp &= 0x40; + tmp |= 0x10; + tmp |= (threshold & 0x0e) >> 1; + if (threshold & 0x01) + tmp |= 0x80; + if (threshold & 0x10) + tmp |= 0x20; + } + new->sr18 = tmp; + } + + /* setup the RAMDAC regs */ + if (pARK->ramdac == ZOOMDAC) { + new->dac_command = 0x04; + if ((pScrn->bitsPerPixel == 8) && multiplexing) + new->dac_command = 0x24; + if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 16)) + /* assuming green weight is not 5 */ + new->dac_command = 0x34; + if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 8)) + new->dac_command = 0x64; + if ((pScrn->bitsPerPixel == 24) && (pARK->dac_width == 16)) + new->dac_command = 0xb4; /* packed */ + if ((pScrn->bitsPerPixel == 32) && (pARK->dac_width == 16)) + new->dac_command = 0x54; + } else if (pARK->ramdac == ATT490) { + new->dac_command = 0x00; + if (pScrn->bitsPerPixel == 16) + /* assuming green weight is 6 */ + new->dac_command = 0xc0; + if (pScrn->bitsPerPixel == 24) + new->dac_command = 0xe0; + } + + /* hrmm... */ + new->dac_command |= 0x02; + +#if 0 + /* hw cursor regs */ + new->sr20 = rdinx(0x3c4, 0x20); + new->sr21 = rdinx(0x3c4, 0x21); + new->sr22 = rdinx(0x3c4, 0x22); + new->sr23 = rdinx(0x3c4, 0x23); + new->sr24 = rdinx(0x3c4, 0x24); + new->sr25 = rdinx(0x3c4, 0x25); + new->sr26 = rdinx(0x3c4, 0x26); + new->sr27 = rdinx(0x3c4, 0x27); + new->sr29 = rdinx(0x3c4, 0x29); + new->sr2a = rdinx(0x3c4, 0x2a); + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) { + new->sr28 = rdinx(0x3c4, 0x28); + new->sr2b = rdinx(0x3c4, 0x3b); + } +#endif + + + ARKWriteMode(pScrn, pVga, new); + + return TRUE; +} + + +static void ARKAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + ARKPtr pARK = ARKPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + int vgaIOBase = hwp->IOBase; + int base; + + base = ((y * pScrn->displayWidth + x) * + (pScrn->bitsPerPixel / 8)); + + if (((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) && + (pScrn->videoRam >= 2048)) + base >>= 3; + else + base >>= 2; + if (pScrn->bitsPerPixel == 24) + base -= base % 3; + + outw(vgaIOBase + 4, (base & 0x00ff00) | 0x0c); + outw(vgaIOBase + 4, ((base & 0x00ff) << 8) | 0x0d); + + modinx(vgaIOBase + 4, 0x40, 0x07, (base & 0x070000) >> 16); +} + + + +static void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new) +{ + ARKPtr pARK = ARKPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + int vgaIOBase = hwp->IOBase; + + vgaHWProtect(pScrn, TRUE); + + /* set read and write aperture index to 0 */ + wrinx(0x3c4, 0x15, 0x00); + wrinx(0x3c4, 0x16, 0x00); + + /* write the extended registers first so that textmode font + * restoration can suceed + */ + wrinx(0x3c4, 0x10, new->sr10); + modinx(0x3c4, 0x11, 0x3f, new->sr11); + wrinx(0x3c4, 0x12, new->sr12); + wrinx(0x3c4, 0x13, new->sr13); + wrinx(0x3c4, 0x14, new->sr14); + wrinx(0x3c4, 0x15, new->sr15); + wrinx(0x3c4, 0x16, new->sr16); + wrinx(0x3c4, 0x17, new->sr17); + +#if 0 + wrinx(0x3c4, 0x1c, new->sr1c); + wrinx(0x3c4, 0x1d, new->sr1d); + + /* hw cursor regs */ + wrinx(0x3c4, 0x20, new->sr20); + wrinx(0x3c4, 0x21, new->sr21); + wrinx(0x3c4, 0x22, new->sr22); + wrinx(0x3c4, 0x23, new->sr23); + wrinx(0x3c4, 0x24, new->sr24); + wrinx(0x3c4, 0x25, new->sr25); + wrinx(0x3c4, 0x26, new->sr26); + wrinx(0x3c4, 0x27, new->sr27); + wrinx(0x3c4, 0x29, new->sr29); + wrinx(0x3c4, 0x2a, new->sr2a); +#endif + + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) { + wrinx(0x3c4, 0x28, new->sr28); + wrinx(0x3c4, 0x2B, new->sr2b); + } + + wrinx(vgaIOBase + 4, 0x40, new->cr40); + wrinx(vgaIOBase + 4, 0x41, new->cr41); + wrinx(vgaIOBase + 4, 0x42, new->cr42); + wrinx(vgaIOBase + 4, 0x44, new->cr44); + + if ((pARK->Chipset == PCI_CHIP_2000PV) || + (pARK->Chipset == PCI_CHIP_2000MT)) + wrinx(vgaIOBase + 4, 0x46, new->cr46); + + /* RAMDAC regs */ + if (pARK->ramdac == ZOOMDAC) { + set_daccom(new->dac_command); + } + + if (xf86IsPrimaryPci(pARK->PciInfo)) + vgaHWRestore(pScrn, pVga, VGA_SR_ALL); + else + vgaHWRestore(pScrn, pVga, VGA_SR_MODE); + + inb(0x3c8); + outb(0x3c6, 0xff); + + vgaHWProtect(pScrn, FALSE); + +} + + +static Bool ARKEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + if (!ARKModeInit(pScrn, pScrn->currentMode)) + return FALSE; + + ARKAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + return TRUE; +} + + + +static void ARKLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + ARKPtr pARK = ARKPTR(pScrn); + ARKRegPtr old = &pARK->SavedRegs; + vgaHWPtr hwp = VGAHWPTR(pScrn); + + ARKWriteMode(pScrn, &hwp->ModeReg, old); + + vgaHWUnlock(hwp); + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); + vgaHWLock(hwp); + + return; +} + + +static Bool ARKMapMem(ScrnInfoPtr pScrn) +{ + ARKPtr pARK = ARKPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + + /* extended to cover MMIO space at 0xB8000 */ + hwp->MapSize = 0x20000; + + pARK->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, + 0xb8000, 0x8000); + + pARK->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + pARK->PciTag, pARK->FBAddress, + pScrn->videoRam * 1024); + if (!pARK->FBBase) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cound not map framebuffer\n"); + return FALSE; + } + + return TRUE; +} + + +static void ARKUnmapMem(ScrnInfoPtr pScrn) +{ + ARKPtr pARK = ARKPTR(pScrn); + + vgaHWUnmapMem(pScrn); + + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pARK->FBBase, + pScrn->videoRam * 1024); + + return; +} + + +Bool ARKCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + ARKPtr pARK = ARKPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + + if (pScrn->vtSema) { + vgaHWUnlock(hwp); + ARKWriteMode(pScrn, &hwp->SavedReg, &pARK->SavedRegs); + vgaHWLock(hwp); + ARKUnmapMem(pScrn); + } + + pScrn->vtSema = FALSE; + pScreen->CloseScreen = pARK->CloseScreen; + + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + + +Bool ARKSaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + + +Bool ARKSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return ARKModeInit(xf86Screens[scrnIndex], mode); +} + + +static void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors, + int *indicies, LOCO *colors, + VisualPtr pVisual) +{ + int i, index; + + for (i=0; i<numColors; i++) { + index = indicies[i]; + outb(0x3c8, index); + outb(0x3c9, colors[index].red); + outb(0x3c9, colors[index].green); + outb(0x3c9, colors[index].blue); + } +} + + +static void ARKFreeScreen(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + vgaHWFreeHWRec(pScrn); + + ARKFreeRec(pScrn); +} + + +static unsigned char get_daccomm() +{ + unsigned char tmp; + + outb(0x3c8, 0); + inb(0x3c6); + inb(0x3c6); + inb(0x3c6); + inb(0x3c6); + tmp = inb(0x3c6); + outb(0x3c8, 0); + + return tmp; +} + + +static unsigned char set_daccom(unsigned char comm) +{ +#if 0 + outb(0x3c8, 0); +#else + inb(0x3c8); +#endif + inb(0x3c6); + inb(0x3c6); + inb(0x3c6); + inb(0x3c6); + outb(0x3c6, comm); +#if 0 + outb(0x3c8, 0); +#else + inb(0x3c8); +#endif + + return inb(0x3c6); +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_reg.h new file mode 100644 index 000000000..43bb7838f --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/ark/ark_reg.h @@ -0,0 +1,88 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ark/ark_reg.h,v 1.1 2000/11/14 17:28:13 dawes Exp $ */ + +#ifndef _ARK_REG_H +#define _ARK_REG_H + +/* and let there be no 'u' in color */ +#define BG_COLOR 0x00 +#define FG_COLOR 0x02 +#define BG_COLOR_HI 0x04 +#define FG_COLOR_HI 0x06 +#define TRANS_COLOR 0x08 +#define TRANS_COLOR_MSK 0x0a +#define TRANS_COLOR_HI 0x0c +#define TRANS_COLOR_MSK_HI 0x0e +#define COLOR_MIX_SEL 0x18 +#define WRITE_PLANEMASK 0x1a +#define ERROR_TERM 0x50 +#define AXIAL_ERROR_INC 0x54 +#define STENCIL_PITCH 0x60 +#define SRC_PITCH 0x62 +#define DST_PITCH 0x64 +#define STENCIL_ADDR 0x68 +#define STENCIL_X 0x68 +#define STENCIL_Y 0x6a +#define SRC_ADDR 0x6c +#define SRC_X 0x6c +#define SRC_Y 0x6e +#define DST_ADDR 0x70 +#define DST_X 0x70 +#define DST_Y 0x72 +#define WIDTH 0x74 +#define HEIGHT 0x76 +#define BITMAP_CONFIG 0x7c +#define COMMAND 0x7e + + +/* constants for COMMAND register */ + +#define DRAWSTEP 0x0000 +#define LINEDRAW 0x1000 +#define BITBLT 0x2000 +#define TEXTBITBLT 0x3000 +#define USE_PLANEMASK 0x0000 +#define DISABLE_PLANEMASK 0x0800 +#define PATTERN_8X8 0x0400 +#define SELECT_BG_COLOR 0x0000 +#define BG_BITMAP 0x0200 +#define SELECT_FG_COLOR 0x0000 +#define FG_BITMAP 0x0100 +#define STENCIL_ONES 0x0000 +#define STENCIL_GENERATED 0x0040 +#define STENCIL_BITMAP 0x0080 +#define LINE_DRAWALL 0x0000 +#define LINE_SKIP_FIRST 0x0010 +#define LINE_SKIP_LAST 0x0020 +#define ENABLE_CLIPPING 0x0000 +#define DISABLE_CLIPPING 0x0008 +#undef DOWN +#define DOWN 0x0000 +#undef UP +#define UP 0x0002 +#define RIGHT 0x0000 +#define LEFT 0x0004 +#define DX_GREATER_THAN_DY 0x0000 +#define DY_GREATER_THAN_DX 0x0001 + + +/* constants for bitmap config register */ + +#define SWAP_NIBLES 0x2000 +#define SWAP_BITS 0x1000 +#define SYSTEM_STENCIL 0x0200 +#define LINEAR_STENCIL_ADDR 0x0100 +#define SYSTEM_SRC 0x0020 +#define LINEAR_SRC_ADDR 0x0010 +#define SYSTEM_DST 0x0002 +#define LINEAR_DST_ADDR 0x0001 + + +/* IO macros */ + +#define OUTREG16(offset, value) \ + *(unsigned short *)(pARK->MMIOBase + offset) = value +#define OUTREG(offset, value) \ + *(unsigned int *)(pARK->MMIOBase + offset) = value + + +#endif /* _ARK_REG_H */ |