|
|
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) 1993 NeXT Computer, Inc. All rights reserved.
25: *
26: * IOSVGADisplay.m - Implements common methods for SVGA display driver class.
27: *
28: *
29: * HISTORY
30: * 07 July 93 Scott Forstall
31: * Created from earlier work by Joe Pasqua and Gary Crum.
32: */
33:
34: #define KERNEL_PRIVATE 1
35: #define DRIVER_PRIVATE 1
36:
37: /* Notes:
38: * This class implements the evScreen protocol for all IOSVGADisplays. Well,
39: * almost. The setBrightness method doesn't do anything. Subclasses must
40: * override this and implement it as appropriate for the device.
41: *
42: * To find things that need to be fixed, search for FIX, to find questions
43: * to be resolved, search for QUESTION, to find stuff that still needs to be
44: * done, search for TO DO.
45: */
46:
47: #import <string.h>
48: #import <stdlib.h>
49: #import <bsd/dev/i386/VGAConsole.h>
50: #import <stdio.h>
51: #import <driverkit/EventDriver.h>
52: #import <bsd/dev/evio.h>
53: #import <bsd/dev/i386/kmDevice.h>
54: #import <driverkit/KernBus.h>
55: #import <driverkit/KernBusMemory.h>
56: #import <driverkit/IODisplayPrivate.h>
57: #import <driverkit/IOSVGADisplay.h>
58: #import <driverkit/IOVGAShared.h>
59: #import <driverkit/i386/directDevice.h>
60: #import <driverkit/i386/driverTypes.h>
61:
62:
63: //
64: // BEGIN: Defines used in this file
65: //
66:
67: #define CURSOR_WIDTH_IN_PIXELS 16
68: #define PPXMASK ((unsigned int)0x0000000f)
69:
70: #if (SWAPBITS == DEVICE_CONSISTENT)
71: #define LSHIFT >>
72: #define RSHIFT <<
73: #define LSHIFTEQ >>=
74: #define RSHIFTEQ <<=
75: #else (SWAPBITS == DEVICE_CONSISTENT)
76: #define LSHIFT <<
77: #define RSHIFT >>
78: #define LSHIFTEQ <<=
79: #define RSHIFTEQ >>=
80: #endif (SWAPBITS == DEVICE_CONSISTENT)
81:
82: #define CLEAR_SEMAPHORE(shmem) \
83: ev_unlock(&shmem->cursorSema)
84: #define SET_SEMAPHORE(shmem) \
85: if (!ev_try_lock(&shmem->cursorSema)) return self
86: #define RECTS_INTERSECT(one, two) \
87: (((one.minx < two.maxx) && (two.minx < one.maxx)) && \
88: ((one.miny < two.maxy) && (two.miny < one.maxy)))
89:
90: //
91: // END: Defines used in this file
92: //
93:
94:
95: @implementation IOSVGADisplay
96:
97: //
98: // BEGIN: Implementation of private routines for SVGA
99: //
100:
101:
102: - (VGAShmem_t *)_shmem
103: // Description: Return IOSVGADisplay's shared memory which is
104: // stored in a private instance variable.
105: {
106: return (VGAShmem_t *)_priv;
107: }
108:
109:
110: - (IOReturn)_registerWithED
111: // Description: Register this display device with the event driver.
112: // Set up and initialize the shared memory.
113: {
114: int shmem_size;
115: Bounds bounds;
116: int token;
117: VGAShmem_t *shmem;
118:
119: token = [[EventDriver instance] registerScreen:self
120: bounds:&bounds
121: shmem:&(self->_priv)
122: size:&shmem_size];
123: shmem = [self _shmem];
124:
125: if ( token == -1 ) {
126: return IO_R_INVALID_ARG;
127: }
128:
129: // We allow the shmem_size to be less than sizeof(VGAShmem_t)
130: // so that we need not consume the extra space that some of the
131: // larger cursor variants require if we are really a lower bitdepth.
132: if ( shmem_size > sizeof(VGAShmem_t) ) {
133: IOLog("%s: shmem_size > sizeof (VGAShmem_t)(%d<>%d)\n",
134: [self name], shmem_size, sizeof (VGAShmem_t));
135: [[EventDriver instance] unregisterScreen:token];
136: return IO_R_INVALID_ARG;
137: }
138:
139: // Init shared memory area
140: bzero( (char *)shmem, shmem_size );
141: shmem->cursorShow = 1;
142: shmem->screenBounds = bounds;
143: [self setToken:token];
144:
145: return IO_R_SUCCESS;
146: }
147:
148:
149: - (void)_readBpp4planar: (unsigned short *)fb toBpp2packed32: (unsigned int *)dst
150: // Description: reads in a 4-planar representation, converts it into a
151: // packed-32 representation, and writes the result into
152: // dst.
153: {
154: unsigned int v, i;
155:
156: [self setReadPlane: 1];
157: i = 0xffff ^ *fb;
158: v = (i & 0x8000) << 2 | (i & 0x4000) << 5 | (i & 0x2000) << 8
159: | (i & 0x1000) << 11 | (i & 0x0800) << 14 | (i & 0x0400) << 17
160: | (i & 0x0200) << 20 | (i & 0x0100) << 23 | (i & 0x0080) >> 6
161: | (i & 0x0040) >> 3 | (i & 0x0020) | (i & 0x0010) << 3
162: | (i & 0x0008) << 6 | (i & 0x0004) << 9 | (i & 0x0002) << 12
163: | (i & 0x0001) << 15;
164:
165: [self setReadPlane: 0];
166: i = 0xffff ^ *fb;
167: v |= (i & 0x8000) << 1 | (i & 0x4000) << 4 | (i & 0x2000) << 7
168: | (i & 0x1000) << 10 | (i & 0x0800) << 13 | (i & 0x0400) << 16
169: | (i & 0x0200) << 19 | (i & 0x0100) << 22 | (i & 0x0080) >> 7
170: | (i & 0x0040) >> 4 | (i & 0x0020) >> 1 | (i & 0x0010) << 2
171: | (i & 0x0008) << 5 | (i & 0x0004) << 8 | (i & 0x0002) << 11
172: | (i & 0x0001) << 14;
173:
174: *dst = v;
175: }
176:
177: - (void)_writeBpp2packed32: (unsigned int *)dst toBpp4planar: (unsigned short *)fb
178: // Description: reads in a packed-32 representation, converts it into a
179: // 4-planar representation, and writes the result into
180: // fb.
181: {
182: unsigned int i, dstvalue;
183: unsigned short fbvalue;
184: unsigned char fblo, fbhi;
185:
186: [self setWritePlane: 1];
187: dstvalue = *dst;
188: i = dstvalue & 0xAAAA;
189: fblo = 0xff ^ (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12)
190: | ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6)
191: | ((i & 0x0080) >> 3) | (i & 0x0020)
192: | ((i & 0x0008) << 3) | ((i & 0x0002) << 6));
193: i = (dstvalue >> 16) & 0xAAAA;
194: fbhi = 0xff ^ (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12)
195: | ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6)
196: | ((i & 0x0080) >> 3) | (i & 0x0020)
197: | ((i & 0x0008) << 3) | ((i & 0x0002) << 6));
198: fbvalue = (((unsigned short)fbhi) << 8) | fblo;
199: *fb = fbvalue;
200:
201: [self setWritePlane: 0];
202: dstvalue = *dst;
203: i = dstvalue & 0x5555;
204: fblo = 0xff ^ (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11)
205: | ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5)
206: | ((i & 0x0040) >> 2) | ((i & 0x0010) << 1)
207: | ((i & 0x0004) << 4) | ((i & 0x0001) << 7));
208: i = (dstvalue >> 16) & 0x5555;
209: fbhi = 0xff ^ (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11)
210: | ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5)
211: | ((i & 0x0040) >> 2) | ((i & 0x0010) << 1)
212: | ((i & 0x0004) << 4) | ((i & 0x0001) << 7));
213: fbvalue = (((unsigned short)fbhi) << 8) | fblo;
214: *fb = fbvalue;
215: }
216:
217:
218: - (void)_VGADisplayCursor: (IODisplayInfo *)dpy shmem: (VGAShmem_t *)shmem
219: // Description: Displays the cursor on the framebuffer by first saving
220: // what's underneath the cursor, then drawing the cursor there.
221: // NOTE:The topleft of the cursorRect passed in is not
222: // necessarily the cursor location.The cursorRect is adjusted to
223: // compensate for the cursor hotspot.If the frame buffer is
224: // cacheable, flush at the end of the drawing operation. A
225: // saveRect is stored which defines the actual area of the screen
226: // that is saved.This is used by RemoveCursor in restoring the
227: // screen data later.
228: {
229: Bounds screenBounds = shmem->screenBounds;
230: Bounds saveRect; /* cursor save rectangle (local) */
231: unsigned int *cursPtr; /* cursor data pointer */
232: unsigned int *vramPtr; /* screen data pointer */
233: unsigned int *savePtr; /* saved screen data pointer */
234: unsigned int *maskPtr; /* cursor mask pointer */
235: int i, doLeft, doRight, skew, rSkew;
236: static unsigned int vramBuf[2];
237: unsigned short *this_segment, *fb;
238: unsigned int fb_x_offset_shorts;
239: unsigned int fb_shorts_per_line;
240: unsigned int fb_lines_per_segment;
241: unsigned int fb_segment;
242: unsigned int fb_next_segment_y;
243: int y;
244: int miny, maxy; /* absolute min and max y--not relative address */
245: /* e.g. 0 <= miny <= SCREEN_HEIGHT */
246:
247: [self savePlaneAndSegmentSettings];
248:
249: saveRect = shmem->cursorRect;
250: vramPtr = (unsigned int *)vramBuf;
251:
252: //
253: // Clip saveRect vertical within screen bounds
254: //
255: if (saveRect.miny < screenBounds.miny) {
256: saveRect.miny = screenBounds.miny;
257: }
258: if (saveRect.maxy > screenBounds.maxy) {
259: saveRect.maxy = screenBounds.maxy;
260: }
261: i = shmem->cursorRect.minx - screenBounds.minx;
262: saveRect.minx = i - (i & PPXMASK) + screenBounds.minx;
263: saveRect.maxx = saveRect.minx + CURSORWIDTH*2;
264: shmem->saveRect = saveRect;
265:
266: //
267: // skew is in bits
268: //
269: skew = (shmem->cursorRect.minx & PPXMASK)<<1;
270: rSkew = 32-skew;
271:
272: //
273: // Set up pointers for saving and drawing
274: //
275: cursPtr = shmem->cursor.bw.image[shmem->frame];
276: maskPtr = shmem->cursor.bw.mask[shmem->frame];
277: savePtr = shmem->cursor.bw.save;
278: i = saveRect.miny - shmem->cursorRect.miny;
279: cursPtr += i;
280: maskPtr += i;
281:
282: //
283: // Since we are drawing an int at a time, and it may
284: // cross an int boundary, we draw it in two pieces (left
285: // and right) which are offset by skew.
286: //
287: doLeft = (saveRect.minx >= screenBounds.minx);
288: doRight = (saveRect.maxx <= screenBounds.maxx);
289:
290: //
291: // VGA related assignments
292: //
293: // QUESTION--isn't this a little fishy?? Should this be the address we mapped?
294: this_segment = (unsigned short *)(0xa0000);
295: fb_x_offset_shorts = (saveRect.minx - screenBounds.minx) >> 4;
296: fb_shorts_per_line = dpy->width >> 4;
297: fb_lines_per_segment = 0x10000 / (dpy->width >> 3);
298:
299: miny = saveRect.miny - screenBounds.miny;
300: maxy = saveRect.maxy - screenBounds.miny;
301:
302: fb = this_segment +
303: ((miny % fb_lines_per_segment) * fb_shorts_per_line) +
304: fb_x_offset_shorts;
305: fb_segment = miny / fb_lines_per_segment;
306: fb_next_segment_y = (fb_lines_per_segment * (fb_segment + 1));
307:
308: [self setWriteSegment: fb_segment];
309: [self setReadSegment: fb_segment];
310:
311: for ( y = miny;
312: y < maxy;
313: y++) {
314: register unsigned int workreg;
315:
316: //
317: // Change VGA segment if necessary.
318: //
319: if (y == fb_next_segment_y) {
320: fb = this_segment +
321: ((y % fb_lines_per_segment) * fb_shorts_per_line) +
322: fb_x_offset_shorts;
323: fb_segment++;
324: fb_next_segment_y += fb_lines_per_segment;
325:
326: [self setWriteSegment: fb_segment];
327: [self setReadSegment: fb_segment];
328: }
329:
330: if (doLeft) {
331: [self _readBpp4planar:fb toBpp2packed32:vramPtr];
332: *savePtr++ = workreg = *vramPtr;
333: *vramPtr = (workreg&(~((*maskPtr) RSHIFT skew))) |
334: ((*cursPtr) RSHIFT skew);
335: [self _writeBpp2packed32:vramPtr toBpp4planar:fb];
336: }
337: if (doRight) {
338: if (!skew) {
339: savePtr++;
340: } else {
341: [self _readBpp4planar:(fb+1) toBpp2packed32:(vramPtr+1)];
342: *savePtr++ = workreg = *(vramPtr+1);
343: *(vramPtr+1)= (workreg&(~((*maskPtr) LSHIFT rSkew))) |
344: ((*cursPtr) LSHIFT rSkew);
345: [self _writeBpp2packed32:(vramPtr+1) toBpp4planar:(fb+1)];
346: }
347: }
348:
349: //
350: // Advance fb (pointer into VGA framebuffer) one line.
351: //
352: fb += fb_shorts_per_line;
353:
354: cursPtr++;
355: maskPtr++;
356: }
357:
358: [self restorePlaneAndSegmentSettings];
359: }
360:
361:
362: - (void)_VGARemoveCursor: (IODisplayInfo *)dpy shmem: (VGAShmem_t *)shmem
363: // Description: RemoveCursor erases the cursor by replacing the background
364: // image that was saved by the previous call to DisplayCursor.
365: // If the frame buffer is cacheable, flush at the end of the
366: // drawing operation.
367: {
368: int doLeft, doRight;
369: unsigned int lmask = 0, rmask = 0;
370: unsigned int *vramPtr;
371: unsigned int *savePtr;
372: Bounds screenBounds = shmem->screenBounds;
373: Bounds saveRect = shmem->saveRect;
374: #if __BIG_ENDIAN__
375: static const unsigned int mask_array[16] = {
376: 0xFFFFFFFF,0x3FFFFFFF,0x0FFFFFFF,0x03FFFFFF,
377: 0x00FFFFFF,0x003FFFFF,0x000FFFFF,0x0003FFFF,
378: 0x0000FFFF,0x00003FFF,0x00000FFF,0x000003FF,
379: 0x000000FF,0x0000003f,0x0000000F,0x00000003
380: };
381: #else
382: static unsigned int mask_array[17] = {
383: 0xFFFFFFFF,0xFFFFFFFC,0xFFFFFFF0,0xFFFFFFC0,
384: 0xFFFFFF00,0xFFFFFC00,0xFFFFF000,0xFFFFC000,
385: 0xFFFF0000,0xFFFC0000,0xFFF00000,0xFFC00000,
386: 0xFF000000,0xFC000000,0xF0000000,0xC0000000,0x00000000};
387: #endif
388: static unsigned int vramBuf[2];
389: unsigned short *this_segment, *fb;
390: unsigned int fb_x_offset_shorts;
391: unsigned int fb_shorts_per_line;
392: unsigned int fb_lines_per_segment;
393: unsigned int fb_segment;
394: unsigned int fb_next_segment_y;
395: int y;
396: int skew;
397: int miny, maxy; /* absolute min and max y--not relative address */
398: /* e.g. 0 <= miny <= SCREEN_HEIGHT */
399:
400: [self savePlaneAndSegmentSettings];
401:
402: vramPtr = (unsigned int *)vramBuf;
403:
404: //
405: // VGA related assignments
406: //
407: // QUESTION--isn't this a little fishy?? Should this be the address we mapped?
408: this_segment = (unsigned short *)(0xa0000);
409: fb_x_offset_shorts = (saveRect.minx - screenBounds.minx) >> 4;
410: fb_shorts_per_line = dpy->width >> 4;
411:
412: miny = saveRect.miny - screenBounds.miny;
413: maxy = saveRect.maxy - screenBounds.miny;
414:
415: //
416: // VGA bank size is 64K
417: //
418: fb_lines_per_segment = 0x10000 / (dpy->width >> 3);
419: fb = this_segment +
420: ((miny % fb_lines_per_segment) * fb_shorts_per_line) +
421: fb_x_offset_shorts;
422: fb_segment = miny / fb_lines_per_segment;
423: fb_next_segment_y = (fb_lines_per_segment * (fb_segment + 1));
424:
425: [self setWriteSegment: fb_segment];
426: [self setReadSegment: fb_segment];
427:
428: //
429: // skew is in bits
430: //
431: skew = (shmem->cursorRect.minx & PPXMASK)<<1;
432:
433: savePtr = shmem->cursor.bw.save;
434: if (doLeft = (saveRect.minx >= screenBounds.minx)) {
435: lmask = mask_array[shmem->oldCursorRect.minx - saveRect.minx];
436: }
437: if (doRight = (saveRect.maxx <= screenBounds.maxx)) {
438: rmask = ~mask_array[16-(saveRect.maxx - shmem->oldCursorRect.maxx)];
439: }
440:
441: for ( y = miny;
442: y < maxy;
443: y++) {
444:
445: //
446: // Change VGA segment if necessary.
447: //
448: if (y == fb_next_segment_y) {
449: fb = this_segment +
450: ((y % fb_lines_per_segment) * fb_shorts_per_line) +
451: fb_x_offset_shorts;
452: fb_segment++;
453: fb_next_segment_y += fb_lines_per_segment;
454:
455: [self setWriteSegment: fb_segment];
456: [self setReadSegment: fb_segment];
457: }
458:
459: if (doLeft) {
460: [self _readBpp4planar:fb toBpp2packed32:vramPtr];
461: *vramPtr = (*vramPtr&(~lmask))|(*savePtr++&lmask);
462: [self _writeBpp2packed32:vramPtr toBpp4planar:fb];
463: }
464:
465: if (doRight) {
466: if (!skew) {
467: savePtr++;
468: } else {
469: [self _readBpp4planar:(fb+1) toBpp2packed32:(vramPtr+1)];
470: *(vramPtr+1)=(*(vramPtr+1)&(~rmask))|(*savePtr++&rmask);
471: [self _writeBpp2packed32:(vramPtr+1) toBpp4planar:(fb+1)];
472: }
473: }
474:
475: //
476: // Advance fb (pointer into VGA framebuffer) one line.
477: //
478: fb += fb_shorts_per_line;
479:
480: }
481:
482: [self restorePlaneAndSegmentSettings];
483: }
484:
485: - (void)_displayCursor: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem
486: // Description: Private routine to display the cursor. Sets up the
487: // cursor rect.
488: {
489: Point hs;
490: hs = shmem->hotSpot[shmem->frame];
491: shmem->cursorRect.maxx =
492: (shmem->cursorRect.minx = (shmem->cursorLoc).x - hs.x) + 16;
493: shmem->cursorRect.maxy =
494: (shmem->cursorRect.miny = (shmem->cursorLoc).y - hs.y) + 16;
495: [self _VGADisplayCursor:d shmem:shmem];
496: shmem->oldCursorRect = shmem->cursorRect;
497: }
498:
499: - (void)_sysHideCursor: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem
500: // Description: Private routing to hide the cursor.
501: {
502: if (!shmem->cursorShow++) {
503: [self _VGARemoveCursor:d shmem:shmem];
504: }
505: }
506:
507: - (void)_sysShowCursor: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem
508: // Description: Private routine to show the cursor
509: {
510: if (shmem->cursorShow)
511: if (!--shmem->cursorShow)
512: [self _displayCursor:d shmem:shmem];
513: }
514:
515: - (void)_checkShield: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem
516: // Description: QUESTION
517: {
518: Point hs;
519: int intersect;
520: Bounds tempRect;
521:
522: //
523: // Calculate temp cursorRect
524: //
525: hs = shmem->hotSpot[shmem->frame];
526: tempRect.maxx = (tempRect.minx = (shmem->cursorLoc).x - hs.x) + 16;
527: tempRect.maxy = (tempRect.miny = (shmem->cursorLoc).y - hs.y) + 16;
528:
529: intersect = RECTS_INTERSECT(tempRect, shmem->shieldRect);
530: if (intersect != shmem->shielded) {
531: (shmem->shielded = intersect) ? [self _sysHideCursor:d shmem:shmem] :
532: [self _sysShowCursor:d shmem:shmem];
533: }
534: }
535:
536:
537: static const char *
538: find_parameter(const char *parameter, const char *string)
539: // Description: Find parameter in string and return what follows
540: // it. E.g. for string = "Width: 10" and
541: // parameter = "Width:" return "10".
542: {
543: int c;
544: size_t length;
545:
546: length = strlen(parameter);
547: while (*string != 0) {
548: if (strncmp(string, parameter, length) == 0) {
549: string += length;
550: while ((c = *string) != '\0' && (c == ' ' || c == '\t'))
551: string++;
552: return (c != 0) ? string : 0;
553: }
554: string++;
555: }
556: return 0;
557: }
558:
559:
560: - (void)_generateName: (char *)name andUnit:(IOObjectNumber *)unit
561: // Description: Used to generate a name for a new Display object.
562: // "name" is a char array of size IO_STRING_LENGTH
563: {
564: static int nextSVGAUnit = 0;
565:
566: *unit = nextSVGAUnit++;
567: sprintf(name, "SVGADisplay%d", *unit);
568: }
569:
570:
571: //
572: // END: Implementation of private routines for SVGA
573: //
574:
575:
576:
577: //
578: // BEGIN: Implementation of the evScreen protocol
579: //
580:
581:
582: - hideCursor: (int)token
583: {
584: SET_SEMAPHORE([self _shmem]);
585: [self _sysHideCursor:[self displayInfo] shmem:[self _shmem]];
586: CLEAR_SEMAPHORE([self _shmem]);
587: return self;
588: }
589:
590: - moveCursor:(Point*)cursorLoc frame:(int)frame token:(int)t
591: {
592: VGAShmem_t *shmem;
593:
594: shmem = [self _shmem];
595: SET_SEMAPHORE(shmem);
596: shmem->frame = frame;
597: shmem->cursorLoc = *cursorLoc;
598: if (!shmem->cursorShow++) {
599: [self _VGARemoveCursor:[self displayInfo] shmem:shmem];
600: }
601: if (shmem->cursorObscured) {
602: shmem->cursorObscured = 0;
603: if (shmem->cursorShow)
604: --shmem->cursorShow;
605: }
606: if (shmem->shieldFlag) {
607: [self _checkShield:[self displayInfo] shmem:shmem];
608: }
609: if (shmem->cursorShow) {
610: if (!--shmem->cursorShow) {
611: [self _displayCursor:[self displayInfo] shmem:shmem];
612: }
613: }
614: CLEAR_SEMAPHORE(shmem);
615: return self;
616: }
617:
618: - showCursor:(Point*)cursorLoc frame:(int)frame token:(int)t
619: {
620: VGAShmem_t *shmem;
621:
622: shmem = [self _shmem];
623: SET_SEMAPHORE(shmem);
624: shmem->frame = frame;
625: shmem->cursorLoc = *cursorLoc;
626: if (shmem->shieldFlag) {
627: [self _checkShield:[self displayInfo] shmem:shmem];
628: }
629: [self _sysShowCursor:[self displayInfo] shmem:shmem];
630: CLEAR_SEMAPHORE(shmem);
631: return self;
632: }
633:
634: //
635: // END: Implementation of the evScreen protocol
636: //
637:
638:
639: //
640: // BEGIN: EXPORTED methods
641: //
642:
643: - (void)setReadSegment: (unsigned char)segmentNum
644: // Description: Select which 64K segment we intend to read from -
645: // this must be overridden by a subclasser.
646: {
647: }
648:
649:
650: - (void)setWriteSegment: (unsigned char)segmentNum
651: // Description: Select which 64K segment we intend to write from -
652: // this must be overridden by a subclasser.
653: {
654: }
655:
656:
657: - (void)setReadPlane: (unsigned char)planeNum
658: // Description: Select which of 4 bit planes to read from in planar
659: // modes - only one plane can be active at a time.
660: {
661: }
662:
663:
664: - (void)setWritePlane: (unsigned char)planeNum
665: // Description: Select one of 4 bit planes to write to in planar modes,
666: // although more than one plane can be active at a time,
667: // this routine only allows access to 1 plane at a time.
668: {
669: }
670:
671:
672: - (void)savePlaneAndSegmentSettings
673: // Description: Save plane and segment settings. These methods must
674: // be implemented by subclasses in a device specific way.
675: {
676: }
677:
678:
679: - (void)restorePlaneAndSegmentSettings
680: // Description: Restore plane and segment settings. These methods must
681: // be implemented by subclasses in a device specific way.
682: {
683: }
684:
685:
686: - (void)enterSVGAMode
687: // Description: Put the display into SVGA mode. This typically happens
688: // when the window server starts running. This method is
689: // implemented by subclasses in a device specific way.
690: {
691: }
692:
693:
694: - (void)revertToVGAMode
695: // Description: Get the device out of whatever advanced mode it was using
696: // and back into a state where it can be used as a standard
697: // VGA device. This method is implemented by subclasses in a
698: // device specific way.
699: {
700: }
701:
702:
703: task_t (task_self)(void); // from /NextDeveloper/Headers/mach/mach_traps.h
704:
705: - (vm_address_t)mapFrameBufferAtPhysicalAddress:(unsigned int)addr
706: length:(int)length;
707: // Description: Look up the physical memory location for this device instance
708: // and map it into VM for use by the device driver. If problems
709: // occur, the method returns (vm_address_t)0. If addr is not 0,
710: // then it is used as the physical memory address and
711: // length is used as the length.
712: {
713: vm_address_t vmLocation;
714: IOReturn result = IO_R_SUCCESS;
715:
716: if (addr != 0) // Override configuration XXX BOGUS!!!
717: {
718: // This is totally bogus. I cannot believe that it is
719: // public API. NB: This mapping cannot be freed using
720: // unmapMemoryRange:from: in IOEISADirectDevice.
721: if (_KernBusMemoryCreateMapping(addr,
722: length,
723: &vmLocation,
724: current_task_EXTERNAL(),
725: YES,
726: IO_WriteThrough) != KERN_SUCCESS)
727: result = IO_R_NO_MEMORY;
728: }
729: else
730: {
731: result = [self mapMemoryRange:0 //QUESTION--what is this???
732: to:&vmLocation
733: findSpace:YES
734: cache:IO_WriteThrough];
735: }
736:
737: if (result != IO_R_SUCCESS)
738: {
739: IOLog("IOSVGADisplay/mapFrameBuffer: Can't map memory (%s)\n",
740: [self stringFromReturn:result]);
741: return (vm_address_t)0;
742: }
743:
744: return vmLocation;
745: }
746:
747:
748:
749: - (int)selectMode:(const IODisplayInfo *)modeList
750: count:(int)count
751: valid:(const BOOL *)isValid
752: // Description: Choose a mode from the list `modeList' (containing `count'
753: // modes) based on the value of the `DisplayMode' key in the
754: // device's config table. If `isValid' is nonzero, each element
755: // specifies whether or not the corresponding mode is valid.
756: {
757: const char *displayMode;
758: IOConfigTable *configTable;
759: int k, width, height;
760: int screenWidth, screenHeight, memorySize, ramdacSpeed;
761: int scanRate;
762: unsigned int modeUnavailableFlag;
763: IOBitsPerPixel bitsPerPixel;
764: IOColorSpace colorSpace;
765: int refreshRate;
766: const char *s;
767:
768: /* Get the string describing the display mode. */
769:
770: configTable = [[self deviceDescription] configTable];
771: if (configTable == nil)
772: return -1;
773: displayMode = [configTable valueForStringKey:"Display Mode"];
774: if (displayMode == 0) {
775: /* Historical: for 3.1 drivers only. */
776: displayMode = [configTable valueForStringKey:"DisplayMode"];
777: if (displayMode == 0)
778: return -1;
779: }
780:
781: /* Parse the string. It should be of the form
782: * Width:# Height:# ColorSpace:(BW:#|RGB:###/#) Refresh:# Hz
783: * where `Width' and `Height' specify the width and height of the
784: * framebuffer, `ColorSpace' specifies the color space for the
785: * framebuffer, and `Refresh' specifies the refresh rate in Hz.
786: * The color space parameter should be either BW followed by the
787: * bits/pixel, or RGB followed by the bits/component for each
788: * component followed by the bits/pixel.
789: *
790: * For example, here is the display mode specification for the
791: * RGB mode of the S3:
792: * Width: 800 Height: 600 ColorSpace: RGB:555/16 Refresh: 60 Hz
793: */
794:
795: height = width = 0;
796: s = find_parameter("Width:", displayMode);
797: if (s != 0) {
798: width = strtol(s, 0, 10);
799: }
800:
801: s = find_parameter("Height:", displayMode);
802: if (s != 0) {
803: height = strtol(s, 0, 10);
804: }
805:
806: s = find_parameter("Refresh:", displayMode);
807: if (s == 0)
808: return -1;
809: refreshRate = strtol(s, 0, 10);
810:
811: s = find_parameter("ColorSpace:", displayMode);
812: if (s == 0)
813: return -1;
814: if (strncmp(s, "BW:2", 4) == 0) {
815: bitsPerPixel = IO_2BitsPerPixel;
816: colorSpace = IO_OneIsBlackColorSpace;
817: } else if (strncmp(s, "BW:8", 4) == 0) {
818: bitsPerPixel = IO_8BitsPerPixel;
819: colorSpace = IO_OneIsWhiteColorSpace;
820: } else if (strncmp(s, "RGB:256/8", 9) == 0) {
821: bitsPerPixel = IO_8BitsPerPixel;
822: colorSpace = IO_RGBColorSpace;
823: } else if (strncmp(s, "RGB:444/16", 10) == 0) {
824: bitsPerPixel = IO_12BitsPerPixel;
825: colorSpace = IO_RGBColorSpace;
826: } else if (strncmp(s, "RGB:555/16", 10) == 0) {
827: bitsPerPixel = IO_15BitsPerPixel;
828: colorSpace = IO_RGBColorSpace;
829: } else if (strncmp(s, "RGB:888/32", 10) == 0) {
830: bitsPerPixel = IO_24BitsPerPixel;
831: colorSpace = IO_RGBColorSpace;
832: } else {
833: return -1;
834: }
835:
836:
837: /*
838: * Now look for 4.0 style optional parameters. The display mode
839: * specification looks like "Resolution:1280x1024 Screen:1600x1200
840: * Refresh:60Hz ColorSpace:RGB:444/16 Memory:4MB RAMDAC:175Hz Sync:1000";
841: */
842:
843: s = find_parameter("Resolution:", displayMode);
844: if (s != 0) {
845: char *end;
846: width = strtol(s, &end, 10);
847: height = strtol(end+1, 0, 10);
848: }
849:
850: if ((height == 0) || (width == 0))
851: return -1;
852:
853: s = find_parameter("Screen:", displayMode);
854: if (s != 0) {
855: char *end;
856: screenWidth = strtol(s, &end, 10);
857: height = strtol(end+1, 0, 10);
858: } else {
859: screenWidth = width;
860: screenHeight = height;
861: }
862:
863: /* These parameters are not used by the superclass. */
864: s = find_parameter("Memory:", displayMode);
865: if (s != 0) {
866: memorySize = strtol(s, 0, 10);
867: }
868:
869: s = find_parameter("RAMDAC:", displayMode);
870: if (s != 0) {
871: ramdacSpeed = strtol(s, 0, 10);
872: }
873:
874: s = find_parameter("Sync:", displayMode);
875: if (s != 0) {
876: scanRate = strtol(s, 0, 10);
877: }
878:
879: modeUnavailableFlag = 0;
880: s = find_parameter("Available:", displayMode);
881: if (s != 0) {
882: modeUnavailableFlag = strtol(s, 0, 10);
883: }
884:
885:
886: /* Now try to match these parameters with the list of modes. */
887: for (k = 0; k < count; k++) {
888: if (isValid != 0 && !isValid[k])
889: continue;
890: if (modeUnavailableFlag != 0)
891: continue;
892: if (modeList[k].width == width
893: && modeList[k].height == height
894: && modeList[k].colorSpace == colorSpace
895: && modeList[k].bitsPerPixel == bitsPerPixel
896: && modeList[k].refreshRate == refreshRate) {
897: switch (bitsPerPixel) {
898: case IO_2BitsPerPixel: s = "BW:2"; break;
899: case IO_8BitsPerPixel:
900: if (colorSpace == IO_RGBColorSpace) s = "RGB:256/8";
901: else s = "BW:8";
902: break;
903: case IO_12BitsPerPixel: s = "RGB:444/16"; break;
904: case IO_15BitsPerPixel: s = "RGB:555/16"; break;
905: case IO_24BitsPerPixel: s = "RGB:888/32"; break;
906: default: s = "Unknown color space"; break;
907: }
908: IOLog("Display: Mode selected: %d x %d @ %d Hz (%s)\n",
909: width, height, refreshRate, s);
910: return k;
911: }
912: }
913: IOLog("Display: Requested mode is not available.\n");
914: return -1;
915: }
916:
917:
918: - (int)selectMode: (const IODisplayInfo *)modeList count:(int)count
919: // Description: Equivalent to the above with `isValid' set to zero.
920: {
921: return [self selectMode:modeList count:count valid:0];
922: }
923:
924:
925: + (BOOL)probe:deviceDescription
926: // Description: Create an instance of subclass to be associated with
927: // specified deviceDescription. Returns whether or not
928: // successful.
929: {
930: IOSVGADisplay *inst;
931:
932: // Create an instance and initialize some basic instance variables.
933: inst = [[self alloc] initFromDeviceDescription:deviceDescription];
934: if (inst == nil) {
935: return NO;
936: }
937:
938: [inst setDeviceKind:"frame buffer"];
939:
940: [inst registerDevice];
941:
942: return YES;
943: }
944:
945:
946:
947:
948: - initFromDeviceDescription:deviceDescription
949: // Description: Initialize per specified deviceDescription. Returns
950: // nil on error
951: {
952: char name[IO_STRING_LENGTH];
953: IOObjectNumber unit;
954:
955: if ([super initFromDeviceDescription:deviceDescription] == nil) {
956: return [super free];
957: }
958:
959: [self _generateName:name andUnit:&unit];
960: [self setUnit:unit];
961: [self setName:name];
962: return self;
963: }
964:
965:
966:
967: - setBrightness:(int)level token:(int)t
968: // Description: Setting the brighness is a device-specific operation
969: // which must be implemented by a subclass. This just
970: // checks if a legal level was sent.
971: {
972: if ( level < EV_SCREEN_MIN_BRIGHTNESS
973: || level > EV_SCREEN_MAX_BRIGHTNESS )
974: {
975: IOLog("%s: Invalid arg to setBrightness:%d\n",
976: [self name], level );
977: }
978: return self;
979: }
980:
981: - (IOReturn)getIntValues:(unsigned *)parameterArray
982: forParameter:(IOParameterName)parameterName
983: count:(unsigned int *)count
984: // Description: Get and set parameters. These include support
985: // for getting the frame buffer parameters, registering it
986: // with the event system, returning the registration token.
987: {
988: unsigned int fb_dimensions[VGA_FB_DIMENSIONS_SIZE];
989: IOReturn r;
990: int i;
991: unsigned *returnedCount = count;
992: unsigned maxCount = *count;
993:
994: if ( strcmp(parameterName, VGA_FB_MAP) == 0 )
995: {
996: parameterArray[0] = 0;
997: [self enterSVGAMode];
998: [kmId registerDisplay:self];
999: *returnedCount = 1;
1000: return IO_R_SUCCESS;
1001: }
1002: else if ( strcmp(parameterName, VGA_FB_DIMENSIONS) == 0 )
1003: {
1004: IODisplayInfo *display = [self displayInfo];
1005:
1006: fb_dimensions[VGA_FB_WIDTH] = display->width;
1007: fb_dimensions[VGA_FB_HEIGHT] = display->height;
1008: fb_dimensions[VGA_FB_ROWBYTES] = display->rowBytes;
1009:
1010: *returnedCount = 0;
1011: for( i=0; i<VGA_FB_DIMENSIONS_SIZE; i++) {
1012: if (*returnedCount == maxCount)
1013: break;
1014: parameterArray[i] = fb_dimensions[i];
1015: (*returnedCount)++;
1016: }
1017: return IO_R_SUCCESS;
1018:
1019: }
1020: else if ( strcmp(parameterName, VGA_FB_REGISTER) == 0 )
1021: {
1022: r = [self _registerWithED];
1023: *returnedCount = 0;
1024: if ( maxCount > 0 )
1025: {
1026: *returnedCount = 1;
1027: parameterArray[0] = [self token];
1028: }
1029: return r;
1030: }
1031: else
1032: {
1033: r = [super getIntValues:parameterArray
1034: forParameter:parameterName
1035: count:returnedCount];
1036: return r;
1037: }
1038: }
1039:
1040:
1041: - (IOReturn)setIntValues:(unsigned *)parameterArray
1042: forParameter:(IOParameterName)parameterName
1043: count:(unsigned int)count
1044: // Description: Set parameters. This can be used to unregister the frame
1045: // buffer as well as set the transfer function.
1046: {
1047: if ( strcmp(parameterName, VGA_FB_UNMAP) == 0 ) {
1048: // [self _unmap];
1049: [self revertToVGAMode];
1050: return IO_R_SUCCESS;
1051: } else if ( strcmp(parameterName, VGA_FB_UNREGISTER) == 0 ) {
1052: if ( count != 1 )
1053: return IO_R_INVALID_ARG;
1054: [[EventDriver instance] unregisterScreen:parameterArray[0]];
1055: return IO_R_SUCCESS;
1056:
1057: } else {
1058: return [super setIntValues:parameterArray
1059: forParameter:parameterName
1060: count:count];
1061: }
1062: }
1063:
1064: - (IOConsoleInfo *)allocateConsoleInfo;
1065: // Description: Allocates a console support info structure based on this
1066: // display. This structure, and the functions in it, are used
1067: // to display alert and console windows.
1068: {
1069: return SVGAAllocateConsole([self displayInfo]);
1070: }
1071:
1072: //
1073: // END: EXPORTED methods
1074: //
1075:
1076: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.