|
|
1.1 root 1: /* Copyright (c) 1993 by NeXT Computer, Inc.
2: * All rights reserved.
3: *
4: * S3SetMode.m -- Mode support for the S3.
5: *
6: * Author: Derek B Clegg 21 May 1993
7: * Based on work by Peter Graffagnino, 31 January 1993.
8: */
9: #import <string.h>
10: #import <driverkit/generalFuncs.h>
11: #import <driverkit/i386/ioPorts.h>
12: #import "S3.h"
13:
14: /* The `S3SetMode' category of `S3'. */
15:
16: @implementation S3 (SetMode)
17:
18: - (void)reportConfiguration
19: {
20: const char *adapterString, *busString, *memString, *dacString;
21:
22: switch (adapter) {
23: case S3_805: adapterString = "86C805"; break;
24: case S3_928: adapterString = "86C928"; break;
25: default: adapterString = "(unknown adapter)"; break;
26: }
27:
28: switch (busConfiguration) {
29: case S3_EISA_BUS: busString = "EISA"; break;
30: case S3_LOCAL_BUS: busString = "Local"; break;
31: case S3_ISA_BUS: busString = "ISA"; break;
32: default: busString = "Unknown"; break;
33: }
34:
35: switch (availableMemory) {
36: case FOUR_MEGABYTES: memString = "4 Mb VRAM"; break;
37: case THREE_MEGABYTES: memString = "3 Mb VRAM"; break;
38: case TWO_MEGABYTES: memString = "2 Mb VRAM"; break;
39: case ONE_MEGABYTE: memString = "1 Mb VRAM"; break;
40: case ONE_MEGABYTE/2: memString = "500 Kb VRAM"; break;
41: default: memString = "(unknown memory size)"; break;
42: }
43:
44: switch (dac) {
45: case Bt484: dacString = "Brooktree 484"; break;
46: case Bt485: dacString = "Brooktree 485"; break;
47: case Bt485A: dacString = "Brooktree 485A"; break;
48: case ATT20C491: dacString = "AT&T 20C491 or compatible"; break;
49: default: dacString = "Unknown"; break;
50: }
51:
52: IOLog("%s: S3 %s; %s bus; %s; %s DAC.\n", [self name], adapterString,
53: busString, memString, dacString);
54: }
55:
56: - determineConfiguration
57: {
58: int value, lockRegisterValue;
59:
60: /* If we turn out not to be an S3, we preserve the old value
61: * of the lock register. */
62:
63: lockRegisterValue = rread(VGA_CRTC_INDEX, S3_REG_LOCK1);
64: rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, S3_LOCK1_KEY);
65:
66: /* Get the adapter type. */
67:
68: value = rread(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX);
69:
70: switch (value & S3_CHIP_ID_MASK) {
71: case S3_CHIP_ID_805:
72: adapter = S3_805;
73: modeTable = S3_805_ModeTable;
74: modeTableCount = S3_805_ModeTableCount;
75: break;
76: case S3_CHIP_ID_928:
77: adapter = S3_928;
78: modeTable = S3_928_ModeTable;
79: modeTableCount = S3_928_ModeTableCount;
80: break;
81: default:
82: IOLog("%s: Unrecognized adapter.\n", [self name]);
83: /* If we're not an S3, reset things to the way we found them.... */
84: rwrite(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX, value);
85: rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, lockRegisterValue);
86: adapter = UnknownAdapter;
87: modeTable = 0;
88: modeTableCount = 0;
89: return nil;
90: break;
91: }
92:
93: /* Get the bus and memory configuration. */
94:
95: value = rread(VGA_CRTC_INDEX, S3_CONFG_REG1_INDEX);
96:
97: busConfiguration = value & S3_BUS_SELECT_MASK;
98:
99: switch (value & S3_MEM_SIZE_MASK) {
100: case S3_HALF_MEG: availableMemory = ONE_MEGABYTE/2; break;
101: case S3_1_MEG: availableMemory = ONE_MEGABYTE; break;
102: case S3_2_MEG: availableMemory = TWO_MEGABYTES; break;
103: case S3_3_MEG: availableMemory = THREE_MEGABYTES; break;
104: case S3_4_MEG: availableMemory = FOUR_MEGABYTES; break;
105: default:
106: IOLog("%s: Unrecognized memory configuration.\n", [self name]);
107: availableMemory = 0;
108: return nil;
109: }
110:
111: [self determineDACType];
112: [self reportConfiguration];
113:
114: S3_lockRegisters();
115: return self;
116: }
117:
118: /* Select a display mode based on the adapter type, the bus configuration,
119: * and the memory configuration. Return the selected mode, or -1 if no mode
120: * is valid.
121: */
122: - selectMode
123: {
124: int k, mode;
125: const S3Mode *modeData;
126: BOOL valid[modeTableCount];
127:
128: for (k = 0; k < modeTableCount; k++) {
129: modeData = modeTable[k].parameters;
130: valid[k] = (modeData->memSize <= availableMemory
131: && modeData->adapter == adapter);
132: }
133:
134: mode = [self selectMode:modeTable count:modeTableCount valid:valid];
135: if (mode < 0) {
136: IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
137: if (adapter == S3_805)
138: mode = S3_805_defaultMode;
139: else
140: mode = S3_928_defaultMode;
141: }
142: *[self displayInfo] = modeTable[mode];
143: return self;
144: }
145:
146: - initializeMode
147: {
148: int k, count;
149: const S3Mode *mode;
150: const IODisplayInfo *displayInfo;
151: unsigned char crtc[VGA_CRTC_COUNT];
152: unsigned char miscOutput[1];
153: unsigned char xcrtc[2*S3_EXTENDED_REGISTER_MAX];
154: unsigned char modeControl[S3_MODE_COUNT];
155: unsigned char advFunctionControl[1];
156:
157: displayInfo = [self displayInfo];
158: mode = displayInfo->parameters;
159:
160: /* Turn off the screen. */
161:
162: outb(VGA_SEQ_DATA, mode->vgaData.seqx[1] | 0x20);
163:
164: /* Sequencer. */
165:
166: for (k = 0; k < VGA_SEQ_COUNT; k++) {
167: if (k == 1)
168: continue;
169: outb(VGA_SEQ_INDEX, k);
170: outb(VGA_SEQ_DATA, mode->vgaData.seqx[k]);
171: }
172:
173: S3_unlockRegisters();
174:
175: /* Unlock the CRTC registers. */
176: rrmw(VGA_CRTC_INDEX, 0x11, ~0x80, 0x00);
177: rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00);
178:
179: /* Set up the CRTC parameters. */
180:
181: count = [self parametersForMode:mode->name
182: forStringKey:"CRTC Registers"
183: parameters:crtc
184: count:sizeof(crtc)];
185: if (count > 0) {
186: IOLog("%s: Using crtc parameters from instance table.\n", [self name]);
187: for (k = 0; k < count; k++)
188: rwrite(VGA_CRTC_INDEX, k, crtc[k]);
189: } else {
190: for (k = 0; k < VGA_CRTC_COUNT; k++)
191: rwrite(VGA_CRTC_INDEX, k, mode->vgaData.crtc[k]);
192: }
193:
194: /* Initialize the address flip-flop for the attribute controller. */
195:
196: inb(VGA_INPUT_STATUS_1);
197: /* Set up the attribute controller registers. */
198: for (k = 0; k < VGA_ATTR_COUNT; k++) {
199: outb(VGA_ATTR_INDEX, k);
200: outb(VGA_ATTR_DATA, mode->vgaData.attr[k]);
201: }
202:
203: /* Start the sequencer. */
204: rwrite(VGA_SEQ_INDEX, 0x00, 0x03);
205:
206: /* Set up the graphics controller registers. */
207: for (k = 0; k < VGA_GRFX_COUNT; k++)
208: rwrite(VGA_GRFX_INDEX, k, mode->vgaData.grfx[k]);
209:
210: /* Set the miscellaneous output register (0x3C2). */
211:
212: count = [self parametersForMode:mode->name
213: forStringKey:"MiscOutput Register"
214: parameters:miscOutput
215: count:sizeof(miscOutput)];
216: if (count > 0) {
217: IOLog("%s: Using miscOutput parameter from instance table.\n",
218: [self name]);
219: outb(VGA_MISC_OUTPUT, miscOutput[0]);
220: } else {
221: outb(VGA_MISC_OUTPUT, mode->vgaData.miscOutput);
222: }
223:
224: /* Reset the address flip-flop for the attribute controller and
225: * enable the palette. */
226: inb(VGA_INPUT_STATUS_1);
227: outb(VGA_ATTR_INDEX, 0x20);
228:
229: /* Set up the extended CRTC registers. */
230:
231: count = [self parametersForMode:mode->name
232: forStringKey:"XCRTC Registers"
233: parameters:xcrtc
234: count:sizeof(xcrtc)];
235: if (count > 0) {
236: IOLog("%s: Using extended crtc parameters from instance table.\n",
237: [self name]);
238: for (k = 0; k < count && xcrtc[k] != 0; k += 2)
239: rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]);
240: } else {
241: for (k = 0; k < S3_XCRTC_COUNT && mode->xcrtc[k] != 0; k += 2)
242: rwrite(VGA_CRTC_INDEX, mode->xcrtc[k], mode->xcrtc[k+1]);
243: }
244:
245: /* Set the mode control register. */
246: count = [self parametersForMode:mode->name
247: forStringKey:"Mode Control Register"
248: parameters:modeControl
249: count:sizeof(modeControl)];
250: if (count > 0) {
251: IOLog("%s: Using mode control parameters from instance table.\n",
252: [self name]);
253: for (k = 0; k < count; k += 2) {
254: if (displayInfo->refreshRate == modeControl[k]/*refreshRate*/) {
255: rwrite(VGA_CRTC_INDEX, 0x42, modeControl[k+1]/*modeControl*/);
256: break;
257: }
258: }
259: if (k >= count)
260: IOLog("%s: Warning: Unable to set the refresh rate.\n",
261: [self name]);
262: } else {
263: for (k = 0; k < S3_MODE_COUNT; k++) {
264: if (displayInfo->refreshRate == mode->modeControl[k].refreshRate) {
265: rwrite(VGA_CRTC_INDEX, 0x42, mode->modeControl[k].modeControl);
266: break;
267: }
268: }
269: if (k == S3_MODE_COUNT)
270: IOLog("%s: Warning: Unable to set the refresh rate.\n",
271: [self name]);
272: }
273:
274: /* Unlock access to the enhanced commands registers. */
275: rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01);
276:
277: /* Set the advanced function control register (0x4AE8). */
278:
279: count = [self parametersForMode:mode->name
280: forStringKey:"Advanced Function Control Register"
281: parameters:advFunctionControl
282: count:sizeof(advFunctionControl)];
283: if (count > 0) {
284: outw(S3_ADVFUNC_CNTL, advFunctionControl[0]);
285: } else {
286: outw(S3_ADVFUNC_CNTL, mode->advFuncCntl);
287: }
288:
289: /* Lock the register set. */
290: rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x00);
291:
292: /* Program the DAC. */
293: [self programDAC];
294:
295: /* Lock the registers. */
296: S3_lockRegisters();
297:
298: /* Enable the screen */
299: rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x00);
300: return self;
301: }
302:
303: - enableLinearFrameBuffer
304: {
305: int lawSize;
306: S3Mode *mode;
307: IODisplayInfo *displayInfo;
308:
309: displayInfo = [self displayInfo];
310: mode = displayInfo->parameters;
311:
312: S3_unlockRegisters();
313:
314: /* Tell the chip where the frame buffer is mapped in. */
315:
316: rwrite(VGA_CRTC_INDEX, S3_LAW_POS_LO, (videoRamAddress >> 16) & 0xFF);
317: rwrite(VGA_CRTC_INDEX, S3_LAW_POS_HI, (videoRamAddress >> 24) & 0xFF);
318:
319: /* Set the linear address window size. */
320:
321: switch (mode->memSize) {
322: case ONE_MEGABYTE:
323: lawSize = S3_LAW_SIZE_1M;
324: break;
325: case TWO_MEGABYTES:
326: lawSize = S3_LAW_SIZE_2M;
327: break;
328: case THREE_MEGABYTES:
329: case FOUR_MEGABYTES:
330: lawSize = S3_LAW_SIZE_4M;
331: break;
332: default:
333: IOLog("%s: Invalid linear address window size for mode `%s'.\n",
334: [self name], mode->name);
335: return nil;
336: }
337:
338: /* Set the linear address window size. */
339: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_SIZE_MASK, lawSize);
340:
341: if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) {
342: /* Wait for the graphics accelerator to stop. */
343: while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK)
344: ;
345: /* Disable 8514 register access. */
346: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK,
347: S3_8514_DISABLE_ACCESS);
348: }
349:
350: /* Turn off mmio. */
351: rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_1, ~S3_MMIO_ACCESS_MASK,
352: S3_DISABLE_MMIO_ACCESS);
353:
354: if (writePostingEnabled) {
355: /* Enable fast write buffer (write posting into FIFO). */
356: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK,
357: S3_WRITE_POST_ENABLE);
358: } else {
359: /* Disable fast write buffer. */
360: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK,
361: S3_WRITE_POST_DISABLE);
362: }
363:
364: if (readAheadCacheEnabled) {
365: /* Enable read-ahead cache. */
366: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK,
367: S3_ENABLE_PREFETCH);
368: /* Max out the read-ahead cache. */
369: rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_2, ~S3_PREFETCH_CTRL_MASK,
370: S3_PREFETCH_MAX);
371: } else {
372: /* Disable read-ahead cache. */
373: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK,
374: S3_DISABLE_PREFETCH);
375: }
376:
377: /* Turn on the linear address window. */
378: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_ENABLE_LAW);
379:
380: S3_lockRegisters();
381:
382: /* Clear the screen. */
383: memset(displayInfo->frameBuffer, 0, mode->memSize);
384: return self;
385: }
386:
387: - resetVGA
388: {
389: int k;
390: static const unsigned char xcrtc[S3_XCRTC_COUNT] = {
391: 0x31, 0x85, 0x32, 0x10, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
392: 0x3A, 0x85, 0x3B, 0x5A, 0x3C, 0x10, 0x40, 0x58, 0x43, 0x00,
393: 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x54, 0x38, 0x56, 0x00,
394: 0x57, 0x00, 0x5C, 0x31, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00,
395: 0x60, 0x07, 0x61, 0x80, 0x62, 0xA1, 0x63, 0xA1,
396: };
397:
398: /* Disable the linear framebuffer. */
399: S3_unlockRegisters();
400:
401: if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) {
402: /* Wait for the graphics accelerator to stop. */
403: while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK)
404: ;
405: /* Disable 8514 register access. */
406: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK,
407: S3_8514_DISABLE_ACCESS);
408: }
409:
410: /* Turn off the linear address window. */
411: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_DISABLE_LAW);
412:
413: /* Turn off the display. */
414: rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x20);
415:
416: /* Unlock the CRTC registers. */
417: rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00);
418:
419: /* Unlock access to the enhanced commands registers. */
420: rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01);
421:
422: /* Set VGA mode. */
423: outw(S3_ADVFUNC_CNTL, 0x02);
424:
425: /* Set the DAC for VGA mode. */
426: [self resetDAC];
427:
428: /* Set up the extended CRTC registers. */
429: for (k = 0; k < S3_XCRTC_COUNT && xcrtc[k] != 0; k += 2)
430: rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]);
431:
432: VGASetMode(0x03);
433:
434: S3_lockRegisters();
435:
436: return self;
437: }
438: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.