|
|
1.1 root 1: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
2: *
3: * CirrusLogicGD542X.m
4: *
5: */
6:
7:
8: #import <driverkit/i386/IOEISADeviceDescription.h>
9: #import "CirrusLogicGD542X.h"
10: #import <kernserv/kern_server_types.h>
11: #import <driverkit/i386/displayRegisters.h>
12: #import <stdio.h>
13: #import <string.h>
14:
15: #define MIN(a,b) (((a)<(b))?(a):(b))
16:
17:
18: //
19: // typedef used to store arrays of register index and values.
20: // -1 as index indicates end of the set...
21: //
22: typedef struct _SVGAIndexValuePair {
23: signed short index;
24: unsigned char value;
25: } SVGAIndexValuePair;
26:
27:
28: //
29: // typedef defining a given graphics mode. A graphics mode
30: // consists of all the register/value pairs that, when set,
31: // completely define a mode of operation.
32: //
33: typedef struct _CirrusLogicGD542XMode {
34: const char *name; /* human-readable mode name */
35: const SVGAIndexValuePair *generalRegisters;
36: const SVGAIndexValuePair *sequencerRegisters;
37: const SVGAIndexValuePair *crtControllerRegisters;
38: const SVGAIndexValuePair *graphicsControllerRegisters;
39: const SVGAIndexValuePair *attributeControllerRegisters;
40: } CirrusLogicGD542XMode;
41:
42:
43: /***************************************
44: * CirrusLogicGD542X_1024x768x2x60hz mode
45: ***************************************/
46:
47: static const SVGAIndexValuePair
48: CirrusLogicGD542X_1024x768x2x60hz_generalRegisters[] = {
49: {0, 0x3F},
50: {-1, 0}
51: };
52:
53: static const SVGAIndexValuePair
54: CirrusLogicGD542X_1024x768x2x60hz_sequencerRegisters[] = {
55: {0, 0x03}, {1, 0x01}, {2, 0x0F}, {3, 0x00}, {4, 0x06},
56: {-1, 0}
57: };
58:
59: static const SVGAIndexValuePair
60: CirrusLogicGD542X_1024x768x2x60hz_crtControllerRegisters[] = {
61: {0x11,0x00}, // Turn off lock allowing changing 0..7
62: {0x00,0xA1}, {0x01,0x7F}, {0x02,0x80}, {0x03,0x04}, {0x04,0x88},
63: {0x05,0x9E}, {0x06,0x26}, {0x07,0xFD}, {0x08,0x00}, {0x09,0x60},
64: {0x0A,0x00}, {0x0B,0x00}, {0x0C,0x00}, {0x0D,0x00}, {0x0E,0x00},
65: {0x0F,0x00}, {0x10,0x08}, {0x11,0x8A}, {0x12,0xFF}, {0x13,0x40},
66: {0x14,0x00}, {0x15,0x04}, {0x16,0x22}, {0x17,0xC3}, {0x18,0xFF},
67: {0x1b,0x02},
68: {-1, 0}
69: };
70:
71: static const SVGAIndexValuePair
72: CirrusLogicGD542X_1024x768x2x60hz_graphicsControllerRegisters[] = {
73: {0x00,0x00}, {0x01,0x00}, {0x02,0x00}, {0x03,0x00}, {0x04,0x00},
74: {0x05,0x00}, {0x06,0x05}, {0x07,0x0F}, {0x08,0xFF},
75: {-1, 0}
76: };
77:
78: static const SVGAIndexValuePair
79: CirrusLogicGD542X_1024x768x2x60hz_attributeControllerRegisters[] = {
80: {0x00,0x00}, {0x01,0x01}, {0x02,0x02}, {0x03,0x03}, {0x04,0x04},
81: {0x05,0x05}, {0x06,0x14}, {0x07,0x07}, {0x08,0x38}, {0x09,0x39},
82: {0x0A,0x3A}, {0x0B,0x3B}, {0x0C,0x3C}, {0x0D,0x3D}, {0x0E,0x3E},
83: {0x0F,0x3F}, {0x10,0x01}, {0x11,0x00}, {0x12,0x0F}, {0x13,0x00},
84: {0x14,0x00},
85: {-1, 0}
86: };
87:
88:
89: static const CirrusLogicGD542XMode
90: CirrusLogicGD542X_1024x768x2x60hz = {
91: "1024x768x2x60hz",
92: CirrusLogicGD542X_1024x768x2x60hz_generalRegisters,
93: CirrusLogicGD542X_1024x768x2x60hz_sequencerRegisters,
94: CirrusLogicGD542X_1024x768x2x60hz_crtControllerRegisters,
95: CirrusLogicGD542X_1024x768x2x60hz_graphicsControllerRegisters,
96: CirrusLogicGD542X_1024x768x2x60hz_attributeControllerRegisters
97: };
98:
99:
100: /**************************************
101: * Framebuffer characteristics.
102: **************************************/
103:
104: #define FRAMEBUFFER_ADDRESS ((void *) 0xa0000)
105:
106: static const IODisplayInfo modeTable[] = {
107: {
108: //
109: // CirrusLogicGD542X 1024 x 768 x 2 x 60hz
110: //
111: 1024, 768, 1024,
112:
113: //
114: // rowbytes =
115: // #bytes/scanline =
116: // ((pixels/line) * (2 bits/pixel) * (byte/8 bits)) =
117: // (pixel width / 4)
118: //
119: 256, 60, 0, IO_2BitsPerPixel, IO_OneIsBlackColorSpace,
120: "WW", 0, (void *)&CirrusLogicGD542X_1024x768x2x60hz
121: }
122: /* Add more modes here. */
123: };
124: #define modeTableCount (sizeof(modeTable) / sizeof(IODisplayInfo))
125:
126:
127: @implementation CirrusLogicGD542X
128:
129:
130: //
131: // BEGIN: Implementation of private routines for SVGA
132: //
133:
134:
135: static void SetBrightness(unsigned int level)
136: // Description: Sets the screen's brightness. This implementation
137: // uses a fixed gamma value. It sets the palette
138: // values according to the brightness level.
139: {
140: unsigned char val;
141:
142: val = EV_SCALE_BRIGHTNESS(level, WHITE_PALETTE_VALUE);
143: outb(WRIT_COLR_PEL_AWMR, (unsigned char)WHITE_INDEX);
144: outb(WRIT_COLR_PEL_DATA, val);
145: outb(WRIT_COLR_PEL_DATA, val);
146: outb(WRIT_COLR_PEL_DATA, val);
147:
148: val = EV_SCALE_BRIGHTNESS(level, LIGHT_GRAY_PALETTE_VALUE);
149: outb(WRIT_COLR_PEL_AWMR, (unsigned char)LIGHT_GRAY_INDEX);
150: outb(WRIT_COLR_PEL_DATA, val);
151: outb(WRIT_COLR_PEL_DATA, val);
152: outb(WRIT_COLR_PEL_DATA, val);
153:
154: val = EV_SCALE_BRIGHTNESS(level, DARK_GRAY_PALETTE_VALUE);
155: outb(WRIT_COLR_PEL_AWMR, (unsigned char)DARK_GRAY_INDEX);
156: outb(WRIT_COLR_PEL_DATA, val);
157: outb(WRIT_COLR_PEL_DATA, val);
158: outb(WRIT_COLR_PEL_DATA, val);
159:
160: val = EV_SCALE_BRIGHTNESS(level, BLACK_PALETTE_VALUE);
161: outb(WRIT_COLR_PEL_AWMR, (unsigned char)BLACK_INDEX);
162: outb(WRIT_COLR_PEL_DATA, val);
163: outb(WRIT_COLR_PEL_DATA, val);
164: outb(WRIT_COLR_PEL_DATA, val);
165: }
166:
167:
168: static void setColorMapToLinearMonochrome()
169: // Description: Sets the color map to linear monochrome by zeroing
170: // out the entire table, then setting the first four
171: // palette values correctly.
172: {
173: int i;
174:
175: for (i = 0; i < 256; i++) {
176: outb(WRIT_COLR_PEL_AWMR, i);
177: outb(WRIT_COLR_PEL_DATA, 0x00);
178: outb(WRIT_COLR_PEL_DATA, 0x00);
179: outb(WRIT_COLR_PEL_DATA, 0x00);
180: }
181: outb(WRIT_COLR_PEL_AWMR, WHITE_INDEX);
182: outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE);
183: outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE);
184: outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE);
185:
186: outb(WRIT_COLR_PEL_AWMR, LIGHT_GRAY_INDEX);
187: outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE);
188: outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE);
189: outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE);
190:
191: outb(WRIT_COLR_PEL_AWMR, DARK_GRAY_INDEX);
192: outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE);
193: outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE);
194: outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE);
195:
196: outb(WRIT_COLR_PEL_AWMR, BLACK_INDEX);
197: outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE);
198: outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE);
199: outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE);
200: }
201:
202:
203: - (void) _selectMode
204: // Description: During initialization, this selects the configured mode
205: // and sets the display info accordingly.
206: {
207: selectedMode = [self selectMode:modeTable count:modeTableCount valid:NULL];
208:
209: if (selectedMode < 0) {
210: IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
211: selectedMode = 0;
212: }
213:
214: *[self displayInfo] = modeTable[selectedMode];
215: }
216:
217:
218: - (void)_SVGASetGeneralRegistersForMode:
219: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
220: // Description: Set all the general registers for the given mode.
221: {
222: const SVGAIndexValuePair *regInfo;
223:
224: regInfo = cirrusLogicGD542XMode->generalRegisters;
225: while (regInfo->index != -1) {
226: outb(WRIT_EIDR_GEN_MISC_OP, regInfo->value);
227: regInfo++;
228: }
229: }
230:
231:
232: - (void)_SVGASetSequencerRegistersForMode:
233: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
234: // Description: Set all the sequencer registers for the given mode.
235: {
236: const SVGAIndexValuePair *regInfo;
237:
238: regInfo = cirrusLogicGD542XMode->sequencerRegisters;
239: while (regInfo->index != -1) {
240: IOWriteRegister(EIDR_SEQ_ADDR, (char)(regInfo->index), regInfo->value);
241: regInfo++;
242: }
243: }
244:
245:
246: - (void)_SVGASetCrtControllerRegistersForMode:
247: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
248: // Description: Set all the crt controller registers for the given mode.
249: {
250: const SVGAIndexValuePair *regInfo;
251:
252: regInfo = cirrusLogicGD542XMode->crtControllerRegisters;
253: while (regInfo->index != -1) {
254: IOWriteRegister(COLR_CRT_ADDR, (char)(regInfo->index), regInfo->value);
255: regInfo++;
256: }
257: }
258:
259:
260: - (void)_SVGASetGraphicsControllerRegistersForMode:
261: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
262: // Description: Set all the graphics controller registers for the given mode.
263: {
264: const SVGAIndexValuePair *regInfo;
265:
266: regInfo = cirrusLogicGD542XMode->graphicsControllerRegisters;
267: while (regInfo->index != -1) {
268: IOWriteRegister(EIDR_GCR_ADDR, (char)(regInfo->index), regInfo->value);
269: regInfo++;
270: }
271: }
272:
273:
274: - (void)_SVGASetAttributeControllerRegistersForMode:
275: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
276: // Description: Set all the attribute controller registers for the given mode.
277: {
278: const SVGAIndexValuePair *regInfo;
279:
280: regInfo = cirrusLogicGD542XMode->attributeControllerRegisters;
281: while (regInfo->index != -1) {
282: char tmpi;
283: inb(READ_COLR_GEN_IN_ST_1);
284: tmpi = inb(READ_TOGL_ACR_ADDR);
285: tmpi &= ~ACR_MSK;
286: tmpi |= (regInfo->index & ACR_MSK);
287: outb(WRIT_TOGL_ACR_ADDR, tmpi);
288: outb(WRIT_TOGL_ACR_DATA, regInfo->value);
289: regInfo++;
290: }
291: }
292:
293:
294: //
295: // END: Implementation of private routines for SVGA
296: //
297:
298:
299: //
300: // BEGIN: EXPORTED methods
301: //
302:
303:
304: - (void)setReadSegment: (unsigned char)segmentNum
305: // Description: Select which 64K segment we intend to read from.
306: {
307: outb(0x03ce,0x09);
308: outb(0x03cf,(segmentNum << 4));
309: }
310:
311:
312: - (void)setWriteSegment: (unsigned char)segmentNum
313: // Description: Select which 64K segment we intend to write to.
314: {
315: outb(0x03ce,0x09);
316: outb(0x03cf,(segmentNum << 4));
317: }
318:
319:
320: - (void)setReadPlane: (unsigned char)planeNum
321: // Description: Select which of 4 bit planes to read from in planar
322: // modes - only one plane can be active at a time.
323: {
324: char tmp;
325:
326: /* Select plane we are reading from */
327: tmp = IOReadRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS);
328: tmp &= ~GCR_AT_RMS;
329: tmp |= (planeNum & GCR_AT_RMS);
330: IOWriteRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS, tmp);
331: }
332:
333:
334: - (void)setWritePlane: (unsigned char)planeNum
335: // Description: Select one of 4 bit planes to write to in planar modes.
336: // Although more than one plane can be active at a time,
337: // this routine only allows access to 1 plane at a time.
338: {
339: char tmp, plane = 0x01;
340:
341: //
342: // Convert plane num to bit enable.
343: //
344: plane = plane << (planeNum & 0x03);
345:
346: //
347: // Select plane we are writing to
348: //
349: tmp = IOReadRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK);
350: tmp &= ~(SEQ_AT_EM3 | SEQ_AT_EM2 | SEQ_AT_EM1 | SEQ_AT_EM0);
351: tmp |= plane;
352: IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK, tmp);
353: }
354:
355:
356: - (void)savePlaneAndSegmentSettings
357: // Description: Saves the current plane and segment settings.
358: // This is not a stack push, so we can only save/
359: // restore one group of settings at a time.
360: {
361: writePlaneMask = IOReadRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK);
362: readPlaneMask = IOReadRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS);
363: outb(0x3ce,0x09);
364: readSegment = inb(0x3cf);
365: writeSegment=readSegment=(readSegment >> 4);
366: }
367:
368:
369: - (void)restorePlaneAndSegmentSettings
370: // Description: Restores the current plane and segment settings.
371: // This is not a stack pop, so we can only save/
372: // restore one group of settings at a time.
373: {
374: IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK, writePlaneMask);
375: IOWriteRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS, readPlaneMask);
376: outb(0x3ce, 0x09);
377: outb(0x3cf, (readSegment << 4));
378: }
379:
380:
381: - (void)enterSVGAMode
382: // Description: Put the display into SVGA mode selectedMode. This
383: // typically happens when the window server starts running.
384: // We set up all the registers necessary for the given
385: // mode and then clear the screen.
386: {
387: IODisplayInfo *displayInfo;
388: int totalScreenBytes, bytesLeftToClear, writeSegmentToClear;
389:
390: [self _SVGASetGeneralRegistersForMode:
391: modeTable[selectedMode].parameters];
392: [self _SVGASetSequencerRegistersForMode:
393: modeTable[selectedMode].parameters];
394: [self _SVGASetCrtControllerRegistersForMode:
395: modeTable[selectedMode].parameters];
396: [self _SVGASetGraphicsControllerRegistersForMode:
397: modeTable[selectedMode].parameters];
398: [self _SVGASetAttributeControllerRegistersForMode:
399: modeTable[selectedMode].parameters];
400:
401: //
402: // re-enable timing sequencer
403: //
404: IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_CRS, 0x00);
405: setColorMapToLinearMonochrome();
406:
407: //
408: // Clear the screen.
409: //
410: displayInfo = [self displayInfo];
411: totalScreenBytes = displayInfo->rowBytes * displayInfo->height;
412: for ( bytesLeftToClear = totalScreenBytes, writeSegmentToClear = 0;
413: bytesLeftToClear > 0;
414: bytesLeftToClear -= 0x20000, writeSegmentToClear++) {
415: [self setWriteSegment:writeSegmentToClear];
416: memset(displayInfo->frameBuffer, 0, MIN(0x20000, bytesLeftToClear));
417: }
418:
419: [self setWriteSegment:0];
420: }
421:
422:
423: - (void)revertToVGAMode
424: // Description: Put the display into VGA mode. This typically happens
425: // when SoftPC enters full-screen mode. We set up all the
426: // registers necessary for the given mode.
427: {
428: outb(WRIT_EIDR_GEN_MISC_OP, 0xE3);
429: }
430:
431:
432: - initFromDeviceDescription:deviceDescription
433: // Description: IODevice method. Initialize the current instance as
434: // per the deviceDescription. Most importantly, this
435: // includes selecting the mode and mapping the frame buffer.
436: {
437: IODisplayInfo *displayInfo;
438: const IORange *range;
439: const CirrusLogicGD542XMode *cirrusLogicGD542XMode;
440:
441: if ([super initFromDeviceDescription:deviceDescription] == nil)
442: return [super free];
443:
444: [self _selectMode];
445:
446: range = [deviceDescription memoryRangeList];
447: if (range == 0) {
448: IOLog("%s: No memory range set.\n", [self name]);
449: return [super free];
450: }
451: videoRamAddress = range[0].start;
452:
453: displayInfo = [self displayInfo];
454: cirrusLogicGD542XMode = displayInfo->parameters;
455:
456: displayInfo->frameBuffer =
457: (void *)[self mapFrameBufferAtPhysicalAddress:videoRamAddress
458: length:0x20000]; //SCOTT--fix this
459:
460: if (displayInfo->frameBuffer == 0)
461: return [super free];
462:
463: IOLog("%s: Initialized `%s' @ %d Hz.\n", [self name],
464: cirrusLogicGD542XMode->name, displayInfo->refreshRate);
465:
466: return self;
467: }
468:
469:
470: - setBrightness:(int)level token:(int)t
471: // Description: This is from the evScreen protocol. We override our superclass
472: // on this since it doesn't know how to set our brightness.
473: {
474: if ( level < EV_SCREEN_MIN_BRIGHTNESS
475: || level > EV_SCREEN_MAX_BRIGHTNESS )
476: {
477: IOLog("%s: Invalid arg to setBrightness:%d\n",
478: [self name], level );
479:
480: if (level < EV_SCREEN_MIN_BRIGHTNESS) {
481: level = EV_SCREEN_MIN_BRIGHTNESS;
482: } else {
483: level = EV_SCREEN_MAX_BRIGHTNESS;
484: }
485: }
486: SetBrightness(level);
487:
488: return self;
489: }
490:
491:
492: //
493: // END: EXPORTED methods
494: //
495:
496: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.