|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /* Copyright (c) 1992-96 NeXT Software, Inc. All rights reserved.
25: *
26: * IOFrameBufferDisplay.m - Implements common methods for "standard" frame
27: * buffers.
28: *
29: *
30: * HISTORY
31: * 26 Oct 95 Dean Reece
32: * Moved strtol() out of this class into its own file (strtol.c)
33: * 24 Oct 95 Rakesh Dubey
34: * Added mode change feature.
35: * 01 Sep 92 Joe Pasqua
36: * Created.
37: */
38:
39: #define KERNEL_PRIVATE 1
40: #define DRIVER_PRIVATE 1
41:
42: /* Notes:
43: * The definition of a standard frame buffer is anything with direct
44: * 32 bit access to a 2 & 8 bit gray, 8 & 16 & 32 bit color. For 16 bit
45: * displays we support both 4/4/4 and 5/5/5 samples per channel.
46: *
47: * This class implements the evScreen protocol for all StdFBDisplays. Well,
48: * almost. The setBrightness method doesn't do anything. Subclasses must
49: * override this and implement it as appropriate for the device.
50: *
51: * To find things that need to be fixed, search for FIX, to find questions
52: * to be resolved, search for ASK, to find stuff that still needs to be
53: * done, search for TO DO.
54: */
55:
56: #import <string.h>
57: #import <stdlib.h>
58: #ifdef i386
59: #import <bsd/dev/i386/FBConsole.h>
60: #endif
61:
62: #ifdef ppc
63: #import <bsd/dev/ppc/FBConsole.h>
64: #endif
65:
66: #import <driverkit/EventDriver.h>
67: #import <bsd/dev/evio.h>
68:
69: #ifdef i386
70: #import <bsd/dev/i386/kmDevice.h>
71: #endif
72: #ifdef ppc
73: #import <bsd/dev/ppc/kmDevice.h>
74: #endif
75:
76: #import <driverkit/KernBus.h>
77: #import <driverkit/KernBusMemory.h>
78: #import <driverkit/IODisplayPrivate.h>
79: #import <driverkit/IOFrameBufferDisplay.h>
80: #import <driverkit/IOFrameBufferShared.h>
81: #import <driverkit/IODirectDevicePrivate.h>
82: #import <driverkit/displayDefs.h>
83: #ifdef i386
84: #import <driverkit/i386/directDevice.h>
85: #import <driverkit/i386/driverTypes.h>
86: #endif
87: #ifdef ppc
88: #import <driverkit/ppc/directDevice.h>
89: #import <driverkit/ppc/driverTypes.h>
90: #endif
91:
92: #define CLEARSEMA(shmem) ev_unlock(&shmem->cursorSema)
93: #define SETSEMA(shmem) \
94: if (!ev_try_lock(&shmem->cursorSema)) return self;
95: #define TOUCHBOUNDS(one, two) \
96: (((one.minx < two.maxx) && (two.minx < one.maxx)) && \
97: ((one.miny < two.maxy) && (two.miny < one.maxy)))
98:
99: #define RBMASK 0xF0F0 /* Short, or 16 bit format */
100: #define GAMASK 0x0F0F /* Short, or 16 bit format */
101: #define AMASK 0x000F /* Short, or 16 bit format */
102:
103: #define GetShmem(instance) ((StdFBShmem_t *)(instance->priv))
104:
105: extern long int strtol(const char *nptr, char **endptr, int base);
106:
107: @interface IOFrameBufferDisplay(Private)
108: - (BOOL)_commitToPendingMode;
109: @end
110:
111: @implementation IOFrameBufferDisplay
112:
113: //
114: // BEGIN: Generic utility routines and methods
115: //
116: - (IOReturn)_registerWithED
117: // Description: Register this display device with the event driver.
118: {
119: int token;
120: int shmem_size;
121: Bounds bounds;
122: StdFBShmem_t *shmem;
123:
124: token = [[EventDriver instance] registerScreen:self
125: bounds:&bounds
126: shmem:&(self->priv)
127: size:&shmem_size];
128: shmem = GetShmem(self);
129: if ( token == -1 )
130: return IO_R_INVALID_ARG;
131: // We allow the shmem_size to be less than sizeof(StdFBShmem_t)
132: // so that we need not consume the extra space that some of the
133: // larger cursor variants require if we are really a lower bitdepth.
134: if ( shmem_size > sizeof(StdFBShmem_t) )
135: {
136: IOLog("%s: shmem_size > sizeof (StdFBShmem_t)(%d<>%d)\n",
137: [self name], shmem_size, sizeof (StdFBShmem_t));
138: [[EventDriver instance] unregisterScreen:token];
139: return IO_R_INVALID_ARG;
140: }
141: // Init shared memory area
142: memset((char *)shmem, 0, shmem_size);
143: shmem->cursorShow = 1;
144: shmem->screenBounds = bounds;
145: [self setToken:token];
146:
147: return IO_R_SUCCESS;
148: }
149:
150: #define short34to35WithGamma(x) \
151: ( (_bm34To35SampleTable[((x) & 0x00F0) >> 4]) \
152: | (_bm34To35SampleTable[((x) & 0x0F00) >> 8] << 5) \
153: | (_bm34To35SampleTable[(x) >> 12] << 10) )
154:
155: #define short35to34WithGamma(x) \
156: ( 0x000F \
157: | (_bm35To34SampleTable[x & 0x001F] << 4) \
158: | (_bm35To34SampleTable[(x & 0x03E0) >> 5] << 8) \
159: | (_bm35To34SampleTable[(x & 0x7C00) >> 10] << 12) )
160:
161: static void StdFBDisplayCursor16(IOFrameBufferDisplay *inst)
162: // Description: Displays the cursor on the framebuffer by first saving
163: // what's underneath the cursor, then drawing the cursor there.
164: // NOTE:The topleft of the cursorRect passed in is not
165: // necessarily the cursor location.The cursorRect is adjusted to
166: // compensate for the cursor hotspot.If the frame buffer is
167: // cacheable, flush at the end of the drawing operation. A
168: // saveRect is stored which defines the actual area of the screen
169: // that is saved.This is used by RemoveCursor in restoring the
170: // screen data later.
171: {
172: IODisplayInfo *dpy;
173: StdFBShmem_t *shmem;
174: vm_offset_t startPtr; /* Starting screen data pointer */
175: unsigned int vramRow;
176: Bounds saveRect;
177: short i, j, width, cursRow;
178: unsigned short *vramPtr; /* screen data pointer */
179: unsigned short *savePtr; /* saved screen data pointer */
180: unsigned short s, d, f;
181: volatile unsigned short *cursPtr;
182: unsigned char *_bm34To35SampleTable;
183: unsigned char *_bm35To34SampleTable;
184:
185: dpy = [inst displayInfo];
186: shmem = GetShmem(inst);
187: saveRect = shmem->cursorRect;
188: /* Clip saveRect vertical within screen bounds */
189: if (saveRect.miny < shmem->screenBounds.miny)
190: saveRect.miny = shmem->screenBounds.miny;
191: if (saveRect.maxy > shmem->screenBounds.maxy)
192: saveRect.maxy = shmem->screenBounds.maxy;
193: if (saveRect.minx < shmem->screenBounds.minx)
194: saveRect.minx = shmem->screenBounds.minx;
195: if (saveRect.maxx > shmem->screenBounds.maxx)
196: saveRect.maxx = shmem->screenBounds.maxx;
197: shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */
198:
199: vramRow = dpy->totalWidth; /* Scanline width in pixels */
200: vramPtr = (unsigned short *)dpy->frameBuffer +
201: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) +
202: (saveRect.minx - shmem->screenBounds.minx);
203: startPtr = (vm_offset_t) vramPtr;
204: width = saveRect.maxx - saveRect.minx;
205: vramRow -= width;
206:
207: cursRow = CURSORWIDTH - width;
208: savePtr = shmem->cursor.rgb.save;
209: cursPtr = shmem->cursor.rgb.image[shmem->frame];
210: cursPtr += (saveRect.miny - shmem->cursorRect.miny) * CURSORWIDTH +
211: (saveRect.minx - shmem->cursorRect.minx);
212:
213: if (dpy->bitsPerPixel == IO_12BitsPerPixel)
214: {
215: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) {
216: for (j = width; --j != -1; ) {
217: d = *savePtr++ = *vramPtr;
218: if ( (s = *cursPtr++) == 0 )
219: { /* Transparent black area. Leave dst as is. */
220: ++vramPtr;
221: continue;
222: }
223: if ( (f = (~s) & (unsigned int)AMASK) == 0 )
224: { /* Opaque cursor pixel. Mark it. */
225: *vramPtr++ = s;
226: continue;
227: }
228: /* Alpha is not 0 or 1.0. Sover the cursor. */
229: *vramPtr++ = s + (((((d & RBMASK)>>4)*f + GAMASK) & RBMASK)
230: | ((((d & GAMASK)*f+GAMASK)>>4) & GAMASK));
231: }
232: cursPtr += cursRow; /* starting point of next cursor line */
233: vramPtr += vramRow; /* starting point of next screen line */
234: }
235: }
236: else // dpy->bitsPerPixel == IO_15BitsPerPixel
237: {
238: // These tables should always be set by the Window Server before
239: // it enables cursor drawing. If they're not set, it's an error.
240: if ( (_bm34To35SampleTable = inst->_bm34To35SampleTable) == NULL
241: || (_bm35To34SampleTable = inst->_bm35To34SampleTable) == NULL )
242: return;
243: for (i = saveRect.maxy - saveRect.miny; --i>=0; ) {
244: for (j = width; --j>=0; ) {
245: d = *savePtr++ = *vramPtr;
246: if ( (s = *cursPtr++) == 0 )
247: { /* Transparent black area. Leave dst as is. */
248: ++vramPtr;
249: continue;
250: }
251: if ( (f = (~s) & (unsigned int)AMASK) == 0 )
252: { /* Opaque cursor pixel. Mark it. */
253: *vramPtr++ = short34to35WithGamma(s);
254: continue;
255: }
256: /* Alpha is not 0 or 1.0. Sover the cursor. */
257: d = short35to34WithGamma(d);
258: d = s + (((((d & RBMASK)>>4)*f + GAMASK) & RBMASK)
259: | ((((d & GAMASK)*f+GAMASK)>>4) & GAMASK));
260: *vramPtr++ = short34to35WithGamma(d);
261: }
262: cursPtr += cursRow; /* starting point of next cursor line */
263: vramPtr += vramRow; /* starting point of next screen line */
264: }
265: }
266: }
267:
268: static inline unsigned int MUL32(unsigned int a, unsigned int b)
269: {
270: unsigned int v, w;
271:
272: v = ((a & 0xff00ff00) >> 8) * b;
273: v += ((v & 0xff00ff00) >> 8) + 0x00010001;
274: w = (a & 0x00ff00ff) * b;
275: w += ((w & 0xff00ff00) >> 8) + 0x00010001;
276:
277: return (v & 0xff00ff00) | ((w >> 8) & 0x00ff00ff);
278: }
279:
280: static inline unsigned char map32to256( unsigned char *directToLogical, unsigned int s)
281: {
282: unsigned char logicalValue;
283:
284: if ((s ^ (s>>8)) & 0x00ffff00) {
285: logicalValue = directToLogical[(s>>24) + 0] +
286: directToLogical[((s>>16)&0xff) + 256] +
287: directToLogical[((s>>8)&0xff) + 512];
288: } else {
289: logicalValue = directToLogical[(s>>24) + 768];
290: }
291: return( directToLogical[ logicalValue + 1024 ]); // final conversion from NeXT palette
292: // to actual palette
293: }
294:
295: static void StdFBDisplayCursor8(IOFrameBufferDisplay *inst)
296: // Description: Displays the cursor on the framebuffer by first saving
297: // what's underneath the cursor, then drawing the cursor there.
298: // NOTE:The topleft of the cursorRect passed in is not
299: // necessarily the cursor location.The cursorRect is adjusted to
300: // compensate for the cursor hotspot.If the frame buffer is
301: // cacheable, flush at the end of the drawing operation. A
302: // saveRect is stored which defines the actual area of the screen
303: // that is saved.This is used by RemoveCursor in restoring the
304: // screen data later.
305: {
306: IODisplayInfo *dpy;
307: StdFBShmem_t *shmem;
308: vm_offset_t startPtr; /* Starting screen data pointer */
309: unsigned int vramRow;
310: Bounds saveRect;
311: short i, j, width, cursRow;
312: unsigned char *vramPtr; /* screen data pointer */
313: unsigned char *savePtr; /* saved screen data pointer */
314: unsigned short s, d;
315: unsigned char dst, alpha;
316: unsigned int rgb32val;
317: volatile unsigned char *cursPtr;
318: volatile unsigned char *maskPtr; /* cursor mask pointer */
319: unsigned int *_bm256To38SampleTable = inst->_bm256To38SampleTable;
320: unsigned char *_bm38To256SampleTable = inst->_bm38To256SampleTable;
321:
322: dpy = [inst displayInfo];
323: shmem = GetShmem(inst);
324: saveRect = shmem->cursorRect;
325: /* Clip saveRect vertical within screen bounds */
326: if (saveRect.miny < shmem->screenBounds.miny)
327: saveRect.miny = shmem->screenBounds.miny;
328: if (saveRect.maxy > shmem->screenBounds.maxy)
329: saveRect.maxy = shmem->screenBounds.maxy;
330: if (saveRect.minx < shmem->screenBounds.minx)
331: saveRect.minx = shmem->screenBounds.minx;
332: if (saveRect.maxx > shmem->screenBounds.maxx)
333: saveRect.maxx = shmem->screenBounds.maxx;
334: shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */
335:
336: vramRow = dpy->totalWidth; /* Scanline width in pixels */
337: vramPtr = (unsigned char *)dpy->frameBuffer +
338: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) +
339: (saveRect.minx - shmem->screenBounds.minx);
340: startPtr = (vm_offset_t) vramPtr;
341: width = saveRect.maxx - saveRect.minx;
342: vramRow -= width;
343:
344: cursRow = CURSORWIDTH - width;
345: savePtr = shmem->cursor.bw8.save;
346: cursPtr = shmem->cursor.bw8.image[shmem->frame];
347: maskPtr = shmem->cursor.bw8.mask[shmem->frame];
348: i = (saveRect.miny - shmem->cursorRect.miny) * CURSORWIDTH +
349: (saveRect.minx - shmem->cursorRect.minx);
350: cursPtr += i;
351: maskPtr += i;
352:
353: if (dpy->colorSpace == IO_OneIsWhiteColorSpace) {
354: for (i = saveRect.maxy - saveRect.miny; --i>=0; ) {
355: for (j = width; --j>=0; ) {
356: int t;
357: d = *savePtr++ = *vramPtr;
358: s = *cursPtr++;
359: t = d * (255 - *maskPtr++);
360: d = s + ((t + (t >> 8) + 1) >> 8);
361: *vramPtr++ = d;
362: }
363: cursPtr += cursRow; /* starting point of next cursor line */
364: maskPtr += cursRow;
365: vramPtr += vramRow; /* starting point of next screen line */
366: }
367: } else { // dpy->colorSpace == IO_RGBColorSpace
368: for (i = saveRect.maxy - saveRect.miny; --i>=0; ) {
369: for (j = width; --j>=0; savePtr++,maskPtr++,cursPtr++,vramPtr++) {
370: *savePtr = *vramPtr;
371: if (alpha = *maskPtr) {
372: dst = *cursPtr;
373: if (alpha = ~alpha) {
374: rgb32val = _bm256To38SampleTable[*vramPtr];
375: rgb32val = (_bm256To38SampleTable[dst] & ~0xff) +
376: MUL32(rgb32val, alpha);
377: dst = map32to256(_bm38To256SampleTable, rgb32val);
378: }
379: *vramPtr = dst;
380: }
381: }
382: cursPtr += cursRow; /* starting point of next cursor line */
383: maskPtr += cursRow;
384: vramPtr += vramRow; /* starting point of next screen line */
385: }
386: }
387: }
388:
389: static void StdFBRemoveCursor16(IOFrameBufferDisplay *inst)
390: // Description: RemoveCursor erases the cursor by replacing the background
391: // image that was saved by the previous call to DisplayCursor.
392: // If the frame buffer is cacheable, flush at the end of the
393: // drawing operation.
394: {
395: IODisplayInfo *dpy;
396: StdFBShmem_t *shmem;
397: short i, j, width;
398: vm_offset_t startPtr;
399: unsigned int vramRow;
400: Bounds saveRect;
401: unsigned short *vramPtr;
402: unsigned short *savePtr;
403:
404: dpy = [inst displayInfo];
405: shmem = GetShmem(inst);
406: saveRect = shmem->saveRect;
407: vramRow = dpy->totalWidth; /* Scanline width in pixels */
408: vramPtr = (unsigned short *)dpy->frameBuffer +
409: (vramRow * (saveRect.miny - shmem->screenBounds.miny))
410: + (saveRect.minx - shmem->screenBounds.minx);
411: width = saveRect.maxx - saveRect.minx;
412: vramRow -= width;
413: savePtr = shmem->cursor.rgb.save;
414: startPtr = (vm_offset_t) vramPtr;
415: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) {
416: for (j = width; --j != -1; )
417: *vramPtr++ = *savePtr++;
418: vramPtr += vramRow;
419: }
420: }
421:
422: static void StdFBRemoveCursor8(IOFrameBufferDisplay *inst)
423: // Description: RemoveCursor erases the cursor by replacing the background
424: // image that was saved by the previous call to DisplayCursor.
425: // If the frame buffer is cacheable, flush at the end of the
426: // drawing operation.
427: {
428: IODisplayInfo *dpy;
429: StdFBShmem_t *shmem;
430: short i, j, width;
431: vm_offset_t startPtr;
432: unsigned int vramRow;
433: Bounds saveRect;
434: unsigned char *vramPtr;
435: unsigned char *savePtr;
436:
437: dpy = [inst displayInfo];
438: shmem = GetShmem(inst);
439: saveRect = shmem->saveRect;
440: vramRow = dpy->totalWidth; /* Scanline width in pixels */
441: vramPtr = (unsigned char *)dpy->frameBuffer +
442: (vramRow * (saveRect.miny - shmem->screenBounds.miny))
443: + (saveRect.minx - shmem->screenBounds.minx);
444: width = saveRect.maxx - saveRect.minx;
445: vramRow -= width;
446: savePtr = shmem->cursor.bw8.save;
447: startPtr = (vm_offset_t) vramPtr;
448: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) {
449: for (j = width; --j != -1; )
450: *vramPtr++ = *savePtr++;
451: vramPtr += vramRow;
452: }
453: }
454:
455: static void StdFBDisplayCursor32(IOFrameBufferDisplay *inst)
456: {
457: IODisplayInfo *dpy;
458: StdFBShmem_t *shmem;
459: unsigned int vramRow;
460: Bounds saveRect;
461: int i, j, width, cursRow;
462: unsigned int *vramPtr; /* screen data pointer */
463: unsigned int *savePtr; /* saved screen data pointer */
464: unsigned int s, d, f;
465: volatile unsigned int *cursPtr;
466:
467: dpy = [inst displayInfo];
468: shmem = GetShmem(inst);
469: saveRect = shmem->cursorRect;
470: /* Clip saveRect vertical within screen bounds */
471: if (saveRect.miny < shmem->screenBounds.miny)
472: saveRect.miny = shmem->screenBounds.miny;
473: if (saveRect.maxy > shmem->screenBounds.maxy)
474: saveRect.maxy = shmem->screenBounds.maxy;
475: if (saveRect.minx < shmem->screenBounds.minx)
476: saveRect.minx = shmem->screenBounds.minx;
477: if (saveRect.maxx > shmem->screenBounds.maxx)
478: saveRect.maxx = shmem->screenBounds.maxx;
479: shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */
480:
481: vramRow = dpy->totalWidth; /* Scanline width in pixels */
482: vramPtr = (unsigned int *)dpy->frameBuffer +
483: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) +
484: (saveRect.minx - shmem->screenBounds.minx);
485: width = saveRect.maxx - saveRect.minx;
486: vramRow -= width;
487:
488: cursRow = CURSORWIDTH - width;
489: savePtr = shmem->cursor.rgb24.save;
490: cursPtr = shmem->cursor.rgb24.image[shmem->frame];
491: cursPtr += (saveRect.miny - shmem->cursorRect.miny) * CURSORWIDTH +
492: (saveRect.minx - shmem->cursorRect.minx);
493:
494: if (dpy->pixelEncoding[0] == IO_SampleTypeAlpha ||
495: dpy->pixelEncoding[0] == IO_SampleTypeSkip) {
496: /* Pixel format is Axxx */
497: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) {
498: for (j = width; --j != -1; ) {
499: d = *savePtr++ = *vramPtr;
500: s = *cursPtr++;
501: f = s >> 24;
502: if (f) {
503: if (f == 0xff) // Opaque pixel
504: *vramPtr++ = s;
505: else { // SOVER the cursor pixel
506: s <<= 8; d <<= 8; /* Now pixels are xxxA */
507: f ^= 0xFF;
508: d = s+(((((d&0xFF00FF00)>>8)*f+0x00FF00FF)&0xFF00FF00)
509: | ((((d & 0x00FF00FF)*f+0x00FF00FF)>>8) &
510: 0x00FF00FF));
511: *vramPtr++ = (d>>8) | 0xff000000;
512: }
513: } else // Transparent cursor pixel
514: vramPtr++;
515: }
516: cursPtr += cursRow; /* starting point of next cursor line */
517: vramPtr += vramRow; /* starting point of next screen line */
518: }
519: } else {
520: /* Pixel format is xxxA */
521: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) {
522: for (j = width; --j != -1; ) {
523: d = *savePtr++ = *vramPtr;
524: s = *cursPtr++;
525: f = s & (unsigned int)0xFF;
526: if (f) {
527: if (f == 0xff) // Opaque pixel
528: *vramPtr++ = s;
529: else { // SOVER the cursor pixel
530: f ^= 0xFF;
531: d = s+(((((d&0xFF00FF00)>>8)*f+0x00FF00FF)&0xFF00FF00)
532: | ((((d & 0x00FF00FF)*f+0x00FF00FF)>>8) &
533: 0x00FF00FF));
534: *vramPtr++ = d;
535: }
536: } else // Transparent cursor pixel
537: vramPtr++;
538: }
539: cursPtr += cursRow; /* starting point of next cursor line */
540: vramPtr += vramRow; /* starting point of next screen line */
541: }
542: }
543: }
544:
545: static void StdFBRemoveCursor32(IOFrameBufferDisplay *inst)
546: {
547: IODisplayInfo *dpy;
548: StdFBShmem_t *shmem;
549: int i, j, width;
550: unsigned int vramRow;
551: Bounds saveRect;
552: unsigned int *vramPtr;
553: unsigned int *savePtr;
554:
555: dpy = [inst displayInfo];
556: shmem = GetShmem(inst);
557: saveRect = shmem->saveRect;
558: vramRow = dpy->totalWidth; /* Scanline width in pixels */
559: vramPtr = (unsigned int *)dpy->frameBuffer +
560: (vramRow * (saveRect.miny - shmem->screenBounds.miny))
561: + (saveRect.minx - shmem->screenBounds.minx);
562: width = saveRect.maxx - saveRect.minx;
563: vramRow -= width;
564: savePtr = (unsigned int *)shmem->cursor.rgb24.save;
565: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) {
566: for (j = width; --j != -1; )
567: *vramPtr++ = *savePtr++;
568: vramPtr += vramRow;
569: }
570: }
571:
572: static inline void StdFBDisplayCursor(IOFrameBufferDisplay *inst)
573: {
574: switch ([inst displayInfo]->bitsPerPixel) {
575: default:
576: case IO_12BitsPerPixel:
577: case IO_15BitsPerPixel:
578: StdFBDisplayCursor16(inst);
579: break;
580: case IO_8BitsPerPixel:
581: StdFBDisplayCursor8(inst);
582: break;
583: case IO_24BitsPerPixel:
584: StdFBDisplayCursor32(inst);
585: break;
586: }
587: }
588:
589: static inline void StdFBRemoveCursor(IOFrameBufferDisplay *inst)
590: {
591: switch ([inst displayInfo]->bitsPerPixel) {
592: default:
593: case IO_12BitsPerPixel:
594: case IO_15BitsPerPixel:
595: StdFBRemoveCursor16(inst);
596: break;
597: case IO_8BitsPerPixel:
598: StdFBRemoveCursor8(inst);
599: break;
600: case IO_24BitsPerPixel:
601: StdFBRemoveCursor32(inst);
602: break;
603: }
604: }
605:
606:
607: #define RemoveCursor(inst) StdFBRemoveCursor(inst)
608: static inline void DisplayCursor(IOFrameBufferDisplay *inst)
609: {
610: Point hs;
611: StdFBShmem_t *shmem;
612:
613: shmem = GetShmem(inst);
614: hs = shmem->hotSpot[shmem->frame];
615: shmem->cursorRect.maxx =
616: (shmem->cursorRect.minx = (shmem->cursorLoc).x - hs.x) + 16;
617: shmem->cursorRect.maxy =
618: (shmem->cursorRect.miny = (shmem->cursorLoc).y - hs.y) + 16;
619: StdFBDisplayCursor(inst);
620: shmem->oldCursorRect = shmem->cursorRect;
621: }
622:
623: static inline void SysHideCursor(IOFrameBufferDisplay *inst)
624: {
625: if (!GetShmem(inst)->cursorShow++)
626: RemoveCursor(inst);
627: }
628:
629: static inline void SysShowCursor(IOFrameBufferDisplay *inst)
630: {
631: if (GetShmem(inst)->cursorShow)
632: if (!--(GetShmem(inst)->cursorShow))
633: DisplayCursor(inst);
634: }
635:
636: static inline void CheckShield(IOFrameBufferDisplay *inst)
637: {
638: Point hs;
639: int intersect;
640: Bounds tempRect;
641: StdFBShmem_t *shmem;
642:
643: shmem = GetShmem(inst);
644: /* Calculate temp cursorRect */
645: hs = shmem->hotSpot[shmem->frame];
646: tempRect.maxx = (tempRect.minx = (shmem->cursorLoc).x - hs.x) + 16;
647: tempRect.maxy = (tempRect.miny = (shmem->cursorLoc).y - hs.y) + 16;
648:
649: intersect = TOUCHBOUNDS(tempRect, shmem->shieldRect);
650: if (intersect != shmem->shielded)
651: (shmem->shielded = intersect) ?
652: SysHideCursor(inst) : SysShowCursor(inst);
653: }
654: //
655: // END: Generic utility routines
656: //
657:
658:
659: //
660: // BEGIN: Implementation of the evScreen protocol
661: //
662: - hideCursor: (int)token
663: {
664: SETSEMA(GetShmem(self));
665: SysHideCursor(self);
666: CLEARSEMA(GetShmem(self));
667: return self;
668: }
669:
670: - moveCursor:(Point*)cursorLoc frame:(int)frame token:(int)t
671: {
672: StdFBShmem_t *shmem;
673:
674: shmem = GetShmem(self);
675: SETSEMA(shmem);
676: shmem->frame = frame;
677: shmem->cursorLoc = *cursorLoc;
678: if (!shmem->cursorShow++)
679: RemoveCursor(self);
680: if (shmem->cursorObscured) {
681: shmem->cursorObscured = 0;
682: if (shmem->cursorShow)
683: --shmem->cursorShow;
684: }
685: if (shmem->shieldFlag) CheckShield(self);
686: if (shmem->cursorShow)
687: if (!--shmem->cursorShow)
688: DisplayCursor(self);
689: CLEARSEMA(shmem);
690: return self;
691: }
692:
693: - showCursor:(Point*)cursorLoc frame:(int)frame token:(int)t
694: {
695: StdFBShmem_t *shmem;
696:
697: shmem = GetShmem(self);
698: SETSEMA(GetShmem(self));
699: shmem->frame = frame;
700: shmem->cursorLoc = *cursorLoc;
701: if (shmem->shieldFlag) CheckShield(self);
702: SysShowCursor(self);
703: CLEARSEMA(shmem);
704: return self;
705: }
706:
707: - setBrightness:(int)level token:(int)t
708: {
709: if ( level < EV_SCREEN_MIN_BRIGHTNESS
710: || level > EV_SCREEN_MAX_BRIGHTNESS )
711: {
712: IOLog("%s: Invalid arg to setBrightness:%d\n",
713: [self name], level );
714: }
715: return self;
716: }
717: //
718: // END: Implementation of the evScreen protocol
719: //
720: //
721: // BEGIN: EXPORTED Methods
722: //
723: + (BOOL)probe:deviceDescription
724: {
725: IOFrameBufferDisplay *inst;
726:
727: // Create an instance and initialize some basic instance variables.
728: inst = [[self alloc] initFromDeviceDescription:deviceDescription];
729: if (inst == nil)
730: return NO;
731:
732: [inst setDeviceKind:"Linear Framebuffer"];
733:
734: [inst registerDevice];
735:
736: return YES;
737: }
738:
739: - initFromDeviceDescription:deviceDescription
740: {
741: extern int sprintf(char *s, const char *format, ...);
742: static int nextUnit = 0;
743: char nameBuf[20];
744:
745: if ([super initFromDeviceDescription:deviceDescription] == nil)
746: return [super free];
747:
748: _currentDisplayMode = _pendingDisplayMode = -1;
749: _displayModeCount = -1; _displayModes = NULL;
750:
751: sprintf(nameBuf, "Display%d", nextUnit);
752: [self setUnit: nextUnit++];
753: [self setName:nameBuf];
754: return self;
755: }
756:
757: - (IOConsoleInfo *)allocateConsoleInfo;
758: // Description: Allocates a console support info structure based on this
759: // display. This structure, and the functions in it, are used
760: // to display alert and console windows.
761: {
762: return FBAllocateConsole([self displayInfo]);
763: }
764:
765: static const char *
766: find_parameter(const char *parameter, const char *string)
767: {
768: int c;
769: size_t length;
770:
771: length = strlen(parameter);
772: while (*string != 0) {
773: if (strncmp(string, parameter, length) == 0) {
774: string += length;
775: while ((c = *string) != '\0' && (c == ' ' || c == '\t'))
776: string++;
777: return (c != 0) ? string : 0;
778: }
779: string++;
780: }
781: return 0;
782: }
783:
784:
785: // Description: Get parameters for the display object. These include support
786: // for getting the frame buffer parameters, registering it
787: // with the event system, returning the registration token.
788:
789: - (IOReturn)getIntValues:(unsigned *)parameterArray
790: forParameter:(IOParameterName)parameterName
791: count:(unsigned int *)count
792: {
793: unsigned int fb_dimensions[STDFB_FB_DIMENSIONS_SIZE];
794: IOReturn r;
795: int i;
796: unsigned *returnedCount = count;
797: unsigned maxCount = *count;
798:
799: if (strcmp(parameterName, STDFB_FB_MAP) == 0) {
800: parameterArray[0] = 0;
801: [self revertToVGAMode]; // start from a well-defined state
802: [self enterLinearMode];
803: [kmId registerDisplay:self];
804: *returnedCount = 1;
805: return IO_R_SUCCESS;
806:
807: } else if (strcmp(parameterName, STDFB_FB_DIMENSIONS) == 0) {
808: IODisplayInfo *display = [self displayInfo];
809:
810: fb_dimensions[STDFB_FB_WIDTH] = display->width;
811: fb_dimensions[STDFB_FB_HEIGHT] = display->height;
812: fb_dimensions[STDFB_FB_ROWBYTES] = display->rowBytes;
813: fb_dimensions[STDFB_FB_FLAGS] = display->flags;
814: switch (display->bitsPerPixel) {
815: case IO_2BitsPerPixel:
816: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 2; break;
817: case IO_8BitsPerPixel:
818: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 8; break;
819: case IO_12BitsPerPixel:
820: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 12; break;
821: case IO_15BitsPerPixel:
822: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 15; break;
823: case IO_24BitsPerPixel:
824: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 32; break;
825: default:
826: /* Should return an error. */
827: break;
828: }
829:
830: *returnedCount = 0;
831: for( i=0; i<STDFB_FB_DIMENSIONS_SIZE; i++) {
832: if (*returnedCount == maxCount)
833: break;
834: parameterArray[i] = fb_dimensions[i];
835: (*returnedCount)++;
836: }
837: return IO_R_SUCCESS;
838:
839: } else if (strcmp(parameterName, STDFB_FB_REGISTER) == 0) {
840: r = [self _registerWithED];
841: *returnedCount = 0;
842: if (maxCount > 0) {
843: *returnedCount = 1;
844: parameterArray[0] = [self token];
845: }
846: return r;
847:
848: } else if (strcmp(parameterName, IO_GET_DISPLAY_INFO) == 0) {
849: const IODisplayInfo *displayInfo;
850: if ((*count != 5) && (*count != 7))
851: return IO_R_INVALID_ARG;
852: displayInfo = [self displayInfo];
853: parameterArray[0] = displayInfo->width;
854: parameterArray[1] = displayInfo->height;
855: parameterArray[2] = displayInfo->refreshRate;
856: parameterArray[3] = (unsigned)displayInfo->bitsPerPixel;
857: parameterArray[4] = (unsigned)displayInfo->colorSpace;
858: if (*count == 7) {
859: parameterArray[5] = displayInfo->totalWidth;
860: parameterArray[6] = displayInfo->rowBytes;
861: }
862: return IO_R_SUCCESS;
863:
864: } else if (strcmp(parameterName, IO_GET_DISPLAY_MODE_NUM) == 0) {
865: if (*count != 1)
866: return IO_R_INVALID_ARG;
867: parameterArray[0] = [self displayModeCount];
868: return IO_R_SUCCESS;
869: } else if (strncmp(parameterName, IO_GET_DISPLAY_MODE_INFO,
870: sizeof(IO_GET_DISPLAY_MODE_INFO)-1) == 0) {
871: const IODisplayInfo *displayInfo, *displayModes;
872: const char *s;
873: int mode;
874:
875: if (*count != 14) {
876: return IO_R_INVALID_ARG;
877: }
878: s = find_parameter(IO_GET_DISPLAY_MODE_INFO, parameterName);
879: if (s == 0) {
880: return IO_R_INVALID_ARG;
881: }
882: mode = strtol(s, 0, 10);
883: if (mode < 0 || mode >= [self displayModeCount])
884: return IO_R_INVALID_ARG;
885:
886: displayModes = [self displayModes];
887: displayInfo = &displayModes[mode];
888:
889: parameterArray[0] = displayInfo->width;
890: parameterArray[1] = displayInfo->height;
891: parameterArray[2] = displayInfo->refreshRate;
892: parameterArray[3] = (unsigned)displayInfo->bitsPerPixel;
893: parameterArray[4] = (unsigned)displayInfo->colorSpace;
894: parameterArray[5] = displayInfo->totalWidth;
895: parameterArray[6] = displayInfo->rowBytes;
896:
897: parameterArray[7] = displayInfo->memorySize;
898: parameterArray[8] = displayInfo->scanRate;
899: parameterArray[9] = 0;
900: parameterArray[10] = displayInfo->dotClockRate;
901: parameterArray[11] = displayInfo->screenWidth;
902: parameterArray[12] = displayInfo->screenHeight;
903: parameterArray[13] = displayInfo->modeUnavailableFlag;
904:
905: return IO_R_SUCCESS;
906: } else if (strcmp(parameterName, IO_GET_DISPLAY_MEMORY) == 0) {
907: if (*count != 1)
908: return IO_R_INVALID_ARG;
909: parameterArray[0] = [self displayMemorySize];
910: return IO_R_SUCCESS;
911: } else if (strcmp(parameterName, IO_GET_RAMDAC_SPEED) == 0) {
912: if (*count != 1)
913: return IO_R_INVALID_ARG;
914: parameterArray[0] = [self ramdacSpeed];
915: return IO_R_SUCCESS;
916: } else if (strcmp(parameterName, IO_GET_CURRENT_DISPLAY_MODE) == 0) {
917: if (*count != 1)
918: return IO_R_INVALID_ARG;
919: if (_currentDisplayMode >= 0) {
920: parameterArray[0] = _currentDisplayMode;
921: return IO_R_SUCCESS;
922: } else {
923: return IO_R_UNDEFINED_MODE;
924: }
925: } else if (strcmp(parameterName, IO_GET_PENDING_DISPLAY_MODE) == 0) {
926: if (*count != 1)
927: return IO_R_INVALID_ARG;
928: if (_pendingDisplayMode >= 0) {
929: parameterArray[0] = _pendingDisplayMode;
930: return IO_R_SUCCESS;
931: } else {
932: return IO_R_UNDEFINED_MODE;
933: }
934:
935: } else if (strncmp(parameterName, IO_SET_PENDING_DISPLAY_MODE,
936: sizeof(IO_SET_PENDING_DISPLAY_MODE) - 1 ) == 0) {
937: const char *s;
938: int mode;
939:
940: if (*count != 0) {
941: return IO_R_INVALID_ARG;
942: }
943: s = find_parameter(IO_SET_PENDING_DISPLAY_MODE, parameterName);
944: if (s == 0) {
945: return IO_R_INVALID_ARG;
946: }
947: mode = strtol(s, 0, 10);
948:
949: if ([self setPendingDisplayMode:mode] == YES) {
950: return IO_R_SUCCESS;
951: } else {
952: return IO_R_FAILED_TO_SET_MODE;
953: }
954:
955: } else {
956: return [super getIntValues:parameterArray
957: forParameter:parameterName
958: count:count];
959: }
960: }
961:
962:
963: /* Set parameters for the display object. This can be used to unregister the
964: * frame buffer as well as to set the transfer function.
965: */
966: - (IOReturn)setIntValues:(unsigned *)parameterArray
967: forParameter:(IOParameterName)parameterName
968: count:(unsigned int)count
969: {
970: int i;
971:
972: if (strcmp(parameterName, STDFB_FB_UNMAP) == 0) {
973: [self revertToVGAMode];
974: //[self unMapFrameBuffer];
975: return IO_R_SUCCESS;
976:
977: } else if (strcmp(parameterName, STDFB_FB_UNREGISTER) == 0) {
978: if (count != 1)
979: return IO_R_INVALID_ARG;
980: [[EventDriver instance] unregisterScreen:parameterArray[0]];
981: return IO_R_SUCCESS;
982:
983: } else if (strcmp(parameterName, IO_SET_TRANSFER_TABLE) == 0) {
984: switch ([self displayInfo]->bitsPerPixel) {
985: case IO_2BitsPerPixel:
986: if (count != IO_2BPP_TRANSFER_TABLE_SIZE)
987: return IO_R_INVALID_ARG;
988: break;
989: case IO_8BitsPerPixel:
990: if (count != IO_8BPP_TRANSFER_TABLE_SIZE)
991: return IO_R_INVALID_ARG;
992: break;
993: case IO_12BitsPerPixel:
994: if (count != IO_12BPP_TRANSFER_TABLE_SIZE)
995: return IO_R_INVALID_ARG;
996: break;
997: case IO_15BitsPerPixel:
998: if (count != IO_15BPP_TRANSFER_TABLE_SIZE)
999: return IO_R_INVALID_ARG;
1000: break;
1001: case IO_24BitsPerPixel:
1002: if (count != IO_24BPP_TRANSFER_TABLE_SIZE)
1003: return IO_R_INVALID_ARG;
1004: break;
1005: default:
1006: return IO_R_INVALID_ARG;
1007: }
1008: [self setTransferTable:parameterArray count:count];
1009: return IO_R_SUCCESS;
1010:
1011: } else if (strcmp(parameterName, STDFB_BM256_TO_BM38_MAP) == 0) {
1012: if (count != STDFB_BM256_TO_BM38_MAP_SIZE)
1013: return IO_R_INVALID_ARG;
1014: if (_bm256To38SampleTable == NULL)
1015: _bm256To38SampleTable = (unsigned int *)
1016: IOMalloc(STDFB_BM256_TO_BM38_MAP_SIZE * sizeof(int));
1017: for (i = 0; i < count; i++)
1018: _bm256To38SampleTable[i] = parameterArray[i];
1019: return IO_R_SUCCESS;
1020:
1021: } else if (strcmp(parameterName, STDFB_BM38_TO_BM256_MAP) == 0) {
1022:
1023: // For NeXT logical palette to real palette conversion, an additional
1024: // 256 bytes can be added to the table
1025: #define STDFB_BM38_TO_256_WITH_LOGICAL_SIZE (STDFB_BM38_TO_BM256_MAP_SIZE + (256/sizeof(int)))
1026:
1027: if ((count != STDFB_BM38_TO_BM256_MAP_SIZE) && (count != STDFB_BM38_TO_256_WITH_LOGICAL_SIZE))
1028: return IO_R_INVALID_ARG;
1029: if (_bm38To256SampleTable == NULL) {
1030: _bm38To256SampleTable = (unsigned char *)
1031: IOMalloc(STDFB_BM38_TO_256_WITH_LOGICAL_SIZE * sizeof(int));
1032: }
1033: if( count != STDFB_BM38_TO_256_WITH_LOGICAL_SIZE)
1034: for (i = 0; i < 256; i++)
1035: _bm38To256SampleTable[ 1024 + i ] = i;
1036: for (i = 0; i < count; i++)
1037: *(((unsigned int *)_bm38To256SampleTable) + i) = parameterArray[i];
1038: return IO_R_SUCCESS;
1039:
1040: } else if (strcmp(parameterName, IO_SET_PENDING_DISPLAY_MODE) == 0) {
1041: if (count != 1)
1042: return IO_R_INVALID_ARG;
1043: if ([self setPendingDisplayMode:parameterArray[0]] == YES) {
1044: return IO_R_SUCCESS;
1045: } else {
1046: return IO_R_FAILED_TO_SET_MODE;
1047: }
1048: } else {
1049: return [super setIntValues:parameterArray forParameter:parameterName
1050: count:count];
1051: }
1052: }
1053:
1054: /*
1055: * This is the first message sent by the windowserver. If there is a pending
1056: * display mode then we commit to it (i.e. update our IODisplayInfo
1057: * structure).
1058: */
1059: #define IO_POSTSCRIPT_DRIVER "PostScript Driver"
1060:
1061: /* Get parameters for the display object.
1062: */
1063: - (IOReturn)getCharValues:(unsigned char *)parameterArray
1064: forParameter:(IOParameterName)parameterName
1065: count:(unsigned *)count
1066: {
1067: if (strcmp(parameterName, STDFB_FB_PIXEL_ENCODING) == 0) {
1068: if (*count != STDFB_FB_PIXEL_ENCODING_SIZE)
1069: return IO_R_INVALID_ARG;
1070:
1071: /* Copy the format string out of the display structure */
1072: strncpy(parameterArray, [self displayInfo]->pixelEncoding,
1073: STDFB_FB_PIXEL_ENCODING_SIZE);
1074: return IO_R_SUCCESS;
1075: } else if (strcmp(parameterName, IO_POSTSCRIPT_DRIVER) == 0) {
1076: /*
1077: * FIXME: This is a temporary hack till WS gets fixed. At that time
1078: * WS will use IO_COMMIT_TO_PENDING_DISPLAY_MODE and this code can be
1079: * deleted. -- rkd.
1080: */
1081: if (_pendingDisplayMode >= 0) {
1082: (void) [self _commitToPendingMode];
1083: _pendingDisplayMode = -1; /* mode switch is complete */
1084: }
1085: return [super getCharValues:parameterArray
1086: forParameter:parameterName
1087: count:count];
1088: } else {
1089: return [super getCharValues:parameterArray
1090: forParameter:parameterName
1091: count:count];
1092: }
1093: }
1094:
1095: // Description: Set parameters for the display object. This can be used
1096: // to set the mapping tables used for conversion between
1097: // 4 BPS and 5 BPS data in 5-5-5 frame buffer support,
1098: // and bm256 <--> bm38 conversion tables as well.
1099: //
1100: - (IOReturn)setCharValues:(unsigned char *)parameterArray
1101: forParameter:(IOParameterName)parameterName
1102: count:(unsigned int)count
1103: {
1104: int i, mode;
1105:
1106: if (strcmp(parameterName, STDFB_4BPS_TO_5BPS_MAP) == 0) {
1107: if (count != STDFB_4BPS_TO_5BPS_MAP_SIZE)
1108: return IO_R_INVALID_ARG;
1109: if (_bm34To35SampleTable == NULL)
1110: _bm34To35SampleTable = IOMalloc(STDFB_4BPS_TO_5BPS_MAP_SIZE);
1111: for (i = 0; i < count; i++)
1112: _bm34To35SampleTable[i] = parameterArray[i];
1113: return IO_R_SUCCESS;
1114:
1115: } else if (strcmp(parameterName, STDFB_5BPS_TO_4BPS_MAP) == 0) {
1116: if (count != STDFB_5BPS_TO_4BPS_MAP_SIZE)
1117: return IO_R_INVALID_ARG;
1118: if (_bm35To34SampleTable == NULL)
1119: _bm35To34SampleTable = IOMalloc(STDFB_5BPS_TO_4BPS_MAP_SIZE);
1120: for (i = 0; i < count; i++)
1121: _bm35To34SampleTable[i] = parameterArray[i];
1122: return IO_R_SUCCESS;
1123: } else if (strcmp(parameterName, IO_COMMIT_TO_PENDING_DISPLAY_MODE) == 0) {
1124: if (_pendingDisplayMode >= 0) {
1125: (void) [self _commitToPendingMode];
1126: _pendingDisplayMode = -1; /* mode switch is complete */
1127: return IO_R_SUCCESS;
1128: } else {
1129: return IO_R_UNSUPPORTED;
1130: }
1131: } else {
1132: return [super setCharValues:parameterArray
1133: forParameter:parameterName
1134: count:count];
1135: }
1136: }
1137:
1138: - (void)enterLinearMode;
1139: // Description: Put the display into linear framebuffer mode. This typically
1140: // happens when the window server starts running. This method
1141: // is implemented by subclasses in a device specific way. The
1142: // value returned is a pointer to the framebuffer in user space.
1143: {
1144: }
1145:
1146: - (void)revertToVGAMode;
1147: // Description: Get the device out of whatever advanced linear mode it was
1148: // using and back into a state where it can be used as a standard
1149: // VGA device. This method is implemented by subclasses in a
1150: // device specific way.
1151: {
1152: }
1153:
1154: - (BOOL)setPendingDisplayMode:(int)displayMode
1155: {
1156: IODisplayInfo *displayInfo;
1157:
1158: displayInfo = [self displayInfo]; // current mode
1159:
1160: if (displayMode < 0 || displayMode >= [self displayModeCount]) {
1161: IOLog("%s: Invalid display mode: %d\n", [self name], displayMode);
1162: return NO;
1163: }
1164: if (displayInfo->modeUnavailableFlag != 0) {
1165: IOLog("%s: Display mode %d not available (error 0x%0x)\n",
1166: [self name], displayMode, displayInfo->modeUnavailableFlag);
1167: return NO;
1168: }
1169: _pendingDisplayMode = displayMode;
1170: return YES;
1171: }
1172:
1173: - (int)pendingDisplayMode
1174: {
1175: return _pendingDisplayMode;
1176: }
1177:
1178: /*
1179: * The subclass must implement these two methods if it want display mode
1180: * changes.
1181: */
1182: - (unsigned int)displayModeCount
1183: {
1184: return _displayModeCount;
1185: }
1186:
1187: - (IODisplayInfo *)displayModes
1188: {
1189: return _displayModes;
1190: }
1191:
1192: /*
1193: * Subclass should override and supply appropriate values.
1194: */
1195: - (unsigned int)displayMemorySize
1196: {
1197: return 0;
1198: }
1199:
1200: - (unsigned int)ramdacSpeed
1201: {
1202: return 0;
1203: }
1204:
1205: - (vm_address_t)mapFrameBufferAtPhysicalAddress:(unsigned int)addr
1206: length:(int)length;
1207: // Description: Look up the physical memory location for this device instance
1208: // and map it into VM for use by the device driver. If problems
1209: // occur, the method returns (vm_address_t)0. If addr is not 0,
1210: // then it is used as the physical memory address and
1211: // length is used as the length.
1212: {
1213: vm_address_t vmLocation;
1214: IOReturn result = IO_R_SUCCESS;
1215: IOCache cacheType;
1216:
1217: switch ([self displayInfo]->flags & IO_DISPLAY_CACHE_MASK) {
1218: default:
1219: case IO_DISPLAY_CACHE_WRITETHROUGH:
1220: cacheType = IO_WriteThrough;
1221: break;
1222: case IO_DISPLAY_CACHE_COPYBACK:
1223: cacheType = IO_CopyBack;
1224: break;
1225: case IO_DISPLAY_CACHE_OFF:
1226: cacheType = IO_CacheOff;
1227: break;
1228: }
1229:
1230: if (addr != 0) // Override configuration XXX BOGUS!!!
1231: {
1232: // This is totally bogus. I cannot believe that it is
1233: // public API. NB: This mapping cannot be freed using
1234: // unmapMemoryRange:from: in IOEISADirectDevice.
1235: if (_KernBusMemoryCreateMapping(addr,
1236: length,
1237: &vmLocation,
1238: current_task_EXTERNAL(),
1239: YES,
1240: cacheType) != KERN_SUCCESS)
1241: result = IO_R_NO_MEMORY;
1242: }
1243: else
1244: {
1245: result = [self mapMemoryRange:0
1246: to:&vmLocation
1247: findSpace:YES
1248: cache:cacheType];
1249: }
1250:
1251: if (result != IO_R_SUCCESS)
1252: {
1253: IOLog(
1254: "IOFrameBufferDisplay/mapFrameBuffer: Can't map memory (%s)\n",
1255: [self stringFromReturn:result]);
1256: return (vm_address_t)0;
1257: }
1258:
1259: return vmLocation;
1260: }
1261:
1262: #if 0
1263: - (vm_address_t)mapFrameBufferAtPhysicalAddress:(unsigned int)addr
1264: length:(int)length;
1265: // Description: Look up the physical memory location for this device instance
1266: // and map it into VM for use by the device driver. If problems
1267: // occur, the method returns (vm_address_t)0. If addr is not 0,
1268: // then it is used as the physical memory address and
1269: // length is used as the length.
1270: {
1271: vm_address_t vmLocation;
1272: IOReturn result = IO_R_SUCCESS;
1273: IOCache cacheType;
1274: IORange *range;
1275:
1276: /* The default is no cache */
1277: switch ([self displayInfo]->flags & IO_DISPLAY_CACHE_MASK) {
1278: default:
1279: case IO_DISPLAY_CACHE_WRITETHROUGH:
1280: cacheType = IO_WriteThrough;
1281: break;
1282: case IO_DISPLAY_CACHE_COPYBACK:
1283: cacheType = IO_CopyBack;
1284: break;
1285: case IO_DISPLAY_CACHE_OFF:
1286: cacheType = IO_CacheOff;
1287: break;
1288: }
1289:
1290: range = [[self deviceDescription] memoryRangeList];
1291:
1292: if (addr == 0)
1293: addr = range[0].start;
1294: if (length == 0)
1295: length = range[0].size;
1296:
1297: /*
1298: * The framebuffer must be contained in memory range 0.
1299: */
1300: if ((addr < range[0].start) ||
1301: (addr+length > range[0].start + range[0].size)) {
1302: IOLog("%s: framebuffer is not contained in first memory range\n",
1303: [self name]);
1304: return IO_R_NO_MEMORY;
1305: }
1306:
1307: result = [self mapMemoryRange:0
1308: to:&vmLocation
1309: findSpace:YES
1310: cache:cacheType];
1311: IOLog("%s: Mapped framed buffer at 0x%x\n", [self name],
1312: vmLocation);
1313:
1314: if (result != IO_R_SUCCESS) {
1315: IOLog(
1316: "IOFrameBufferDisplay/mapFrameBuffer: Can't map memory (%s)\n",
1317: [self stringFromReturn:result]);
1318: return (vm_address_t)0;
1319: }
1320:
1321: return vmLocation + (addr - range[0].start);
1322: }
1323:
1324: - (void)unMapFrameBuffer:(unsigned int)addr length:(int)length
1325: {
1326: void *vmLocation;
1327: IORange *range;
1328:
1329: range = [[self deviceDescription] memoryRangeList];
1330:
1331: if (addr == 0)
1332: addr = range[0].start;
1333: if (length == 0)
1334: length = range[0].size;
1335:
1336: /*
1337: * The framebuffer must be contained in memory range 0.
1338: */
1339: if ((addr < range[0].start) ||
1340: (addr+length > range[0].start + range[0].size)) {
1341: IOLog("%s: framebuffer is not contained in first memory range\n",
1342: [self name]);
1343: return IO_R_NO_MEMORY;
1344: }
1345:
1346: vmLocation = [self displayInfo]->frameBuffer - (addr - range[0].start);
1347:
1348: if (vmLocation) {
1349: [self unmapMemoryRange:0 from:(vm_address_t)vmLocation];
1350: }
1351: }
1352: #endif 0
1353:
1354:
1355: - (int)selectMode:(const IODisplayInfo *)modeList count:(int)count
1356: valid:(const BOOL *)isValid modeString:(const char *)modeString
1357: {
1358: const char *displayMode;
1359: IOConfigTable *configTable;
1360: int k, width, height;
1361: int screenWidth, screenHeight, memorySize, ramdacSpeed;
1362: int scanRate;
1363: unsigned int modeUnavailableFlag;
1364: IOBitsPerPixel bitsPerPixel;
1365: IOColorSpace colorSpace;
1366: int refreshRate;
1367: const char *s;
1368:
1369: _displayModeCount = count;
1370: _displayModes = modeList;
1371:
1372: /* Get the string describing the display mode. */
1373:
1374: if (modeString == NULL) {
1375:
1376: configTable = [[self deviceDescription] configTable];
1377: if (configTable == nil)
1378: return -1;
1379:
1380: displayMode = [configTable valueForStringKey:"Display Mode"];
1381: if (displayMode == 0) {
1382: /* Historical: for 3.1 drivers only. */
1383: displayMode = [configTable valueForStringKey:"DisplayMode"];
1384: if (displayMode == 0)
1385: return -1;
1386: }
1387: } else {
1388: displayMode = modeString;
1389: }
1390:
1391: /* Parse the string. It should be of the form
1392: * Width:# Height:# ColorSpace:(BW:#|RGB:###/#) Refresh:# Hz
1393: * where `Width' and `Height' specify the width and height of the
1394: * framebuffer, `ColorSpace' specifies the color space for the
1395: * framebuffer, and `Refresh' specifies the refresh rate in Hz.
1396: * The color space parameter should be either BW followed by the
1397: * bits/pixel, or RGB followed by the bits/component for each
1398: * component followed by the bits/pixel.
1399: *
1400: * For example, here is the display mode specification for the
1401: * RGB mode of the S3:
1402: * Width: 800 Height: 600 ColorSpace: RGB:555/16 Refresh: 60 Hz
1403: */
1404:
1405: height = width = 0;
1406: s = find_parameter("Width:", displayMode);
1407: if (s != 0) {
1408: width = strtol(s, 0, 10);
1409: }
1410:
1411: s = find_parameter("Height:", displayMode);
1412: if (s != 0) {
1413: height = strtol(s, 0, 10);
1414: }
1415:
1416: s = find_parameter("Refresh:", displayMode);
1417: if (s == 0)
1418: return -1;
1419: refreshRate = strtol(s, 0, 10);
1420:
1421: s = find_parameter("ColorSpace:", displayMode);
1422: if (s == 0)
1423: return -1;
1424: if (strncmp(s, "BW:2", 4) == 0) {
1425: bitsPerPixel = IO_2BitsPerPixel;
1426: colorSpace = IO_OneIsBlackColorSpace;
1427: } else if (strncmp(s, "BW:8", 4) == 0) {
1428: bitsPerPixel = IO_8BitsPerPixel;
1429: colorSpace = IO_OneIsWhiteColorSpace;
1430: } else if (strncmp(s, "RGB:256/8", 9) == 0) {
1431: bitsPerPixel = IO_8BitsPerPixel;
1432: colorSpace = IO_RGBColorSpace;
1433: } else if (strncmp(s, "RGB:444/16", 10) == 0) {
1434: bitsPerPixel = IO_12BitsPerPixel;
1435: colorSpace = IO_RGBColorSpace;
1436: } else if (strncmp(s, "RGB:555/16", 10) == 0) {
1437: bitsPerPixel = IO_15BitsPerPixel;
1438: colorSpace = IO_RGBColorSpace;
1439: } else if (strncmp(s, "RGB:888/32", 10) == 0) {
1440: bitsPerPixel = IO_24BitsPerPixel;
1441: colorSpace = IO_RGBColorSpace;
1442: } else {
1443: return -1;
1444: }
1445:
1446: /*
1447: * Now look for 4.0 style optional parameters. The display mode
1448: * specification looks like "Resolution:1280x1024 Screen:1600x1200
1449: * Refresh:60Hz ColorSpace:RGB:444/16 Memory:4MB RAMDAC:175Hz Sync:100Hz";
1450: */
1451:
1452: s = find_parameter("Resolution:", displayMode);
1453: if (s != 0) {
1454: char *end;
1455: width = strtol(s, &end, 10);
1456: height = strtol(end+1, 0, 10);
1457: }
1458:
1459: if ((height == 0) || (width == 0))
1460: return -1;
1461:
1462: s = find_parameter("Screen:", displayMode);
1463: if (s != 0) {
1464: char *end;
1465: screenWidth = strtol(s, &end, 10);
1466: screenHeight = strtol(end+1, 0, 10);
1467: } else {
1468: screenWidth = width;
1469: screenHeight = height;
1470: }
1471:
1472: /* These parameters are not used by the superclass. */
1473: s = find_parameter("Memory:", displayMode);
1474: if (s != 0) {
1475: memorySize = strtol(s, 0, 10);
1476: }
1477:
1478: s = find_parameter("RAMDAC:", displayMode);
1479: if (s != 0) {
1480: ramdacSpeed = strtol(s, 0, 10);
1481: }
1482:
1483: s = find_parameter("Sync:", displayMode);
1484: if (s != 0) {
1485: scanRate = strtol(s, 0, 10);
1486: }
1487:
1488: modeUnavailableFlag = 0;
1489: s = find_parameter("Available:", displayMode);
1490: if (s != 0) {
1491: modeUnavailableFlag = strtol(s, 0, 10);
1492: }
1493:
1494: /* Now try to match these parameters with the list of modes. */
1495: for (k = 0; k < count; k++) {
1496:
1497: if (isValid != 0 && !isValid[k])
1498: continue;
1499: if (modeUnavailableFlag != 0)
1500: continue;
1501: if (modeList[k].width == width
1502: && modeList[k].height == height
1503: && modeList[k].colorSpace == colorSpace
1504: && modeList[k].bitsPerPixel == bitsPerPixel
1505: && modeList[k].refreshRate == refreshRate) {
1506: switch (bitsPerPixel) {
1507: case IO_2BitsPerPixel: s = "BW:2"; break;
1508: case IO_8BitsPerPixel:
1509: if (colorSpace == IO_RGBColorSpace) s = "RGB:256/8";
1510: else s = "BW:8";
1511: break;
1512: case IO_12BitsPerPixel: s = "RGB:444/16"; break;
1513: case IO_15BitsPerPixel: s = "RGB:555/16"; break;
1514: case IO_24BitsPerPixel: s = "RGB:888/32"; break;
1515: default: s = "Unknown color space"; break;
1516: }
1517: IOLog("Display: Mode selected: %d x %d @ %d Hz (%s)\n",
1518: width, height, refreshRate, s);
1519: _currentDisplayMode = k;
1520: return k;
1521: }
1522: }
1523: IOLog("Display: Requested mode is not available.\n");
1524: return -1;
1525: }
1526:
1527: - (int)selectMode: (const IODisplayInfo *)modeList count:(int)count
1528: {
1529: return [self selectMode:modeList count:count valid:0 modeString:NULL];
1530: }
1531:
1532: - (int)selectMode:(const IODisplayInfo *)modeList count:(int)count
1533: valid:(const BOOL *)isValid
1534: {
1535: return [self selectMode:modeList count:count valid:isValid modeString:NULL];
1536: }
1537:
1538: - setTransferTable:(const unsigned int *)table count:(int)count
1539: {
1540: return self;
1541: }
1542:
1543: @end
1544:
1545:
1546: //
1547: // BEGIN: PRIVATE Methods
1548: //
1549: @implementation IOFrameBufferDisplay(Private)
1550:
1551: - (BOOL)_commitToPendingMode
1552: {
1553: IODisplayInfo *displayInfo, *displayModes;
1554: int mode = _pendingDisplayMode;
1555:
1556: displayInfo = [self displayInfo]; // current mode
1557:
1558: displayModes = [self displayModes]; // all possible modes
1559: if (displayModes == NULL)
1560: return NO;
1561:
1562: bzero(displayInfo->pixelEncoding, IO_MAX_PIXEL_BITS);
1563: strncpy(displayInfo->pixelEncoding, displayModes[mode].pixelEncoding,
1564: strlen(displayModes[mode].pixelEncoding));
1565: displayInfo->width = displayModes[mode].width;
1566: displayInfo->height = displayModes[mode].height;
1567: displayInfo->totalWidth = displayModes[mode].totalWidth;
1568: displayInfo->rowBytes = displayModes[mode].rowBytes;
1569: displayInfo->refreshRate = displayModes[mode].refreshRate;
1570: displayInfo->bitsPerPixel = displayModes[mode].bitsPerPixel;
1571: displayInfo->colorSpace = displayModes[mode].colorSpace;
1572: displayInfo->parameters = displayModes[mode].parameters;
1573:
1574: displayInfo->screenWidth = displayModes[mode].screenWidth;
1575: displayInfo->screenHeight = displayModes[mode].screenHeight;
1576: displayInfo->scanRate = displayModes[mode].scanRate;
1577: displayInfo->memorySize = displayModes[mode].memorySize;
1578: displayInfo->dotClockRate = displayModes[mode].dotClockRate;
1579: displayInfo->modeUnavailableFlag = displayModes[mode].modeUnavailableFlag;
1580:
1581: /*
1582: * If the driver defined the flag use it else chhose a default behavior.
1583: */
1584: if (displayModes[mode].flags != 0) {
1585: displayInfo->flags = displayModes[mode].flags;
1586: } else {
1587: if (displayInfo->bitsPerPixel == IO_8BitsPerPixel) {
1588: displayInfo->flags = IO_DISPLAY_HAS_TRANSFER_TABLE;
1589: } else {
1590: displayInfo->flags = IO_DISPLAY_NEEDS_SOFTWARE_GAMMA_CORRECTION;
1591: }
1592: }
1593: _currentDisplayMode = mode;
1594:
1595: return YES;
1596: }
1597:
1598: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
1599: {
1600: strcpy( classes, IOClassFramebuffer);
1601: return( self);
1602: }
1603:
1604: @end
1605:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.