|
|
1.1 root 1: /* Copyright (c) 1993 by NeXT Computer, Inc as an unpublished work.
2: * All rights reserved.
3: *
4: * QVisionSetMode.m -- Mode support for the QVision.
5: *
6: * NOTE: view this file with tabs set to 4 spaces
7: *
8: * Author: Derek B Clegg 21 May 1993
9: * Based on work by Joe Pasqua.
10: * Tue Aug 16 16:53:03 PDT 1994 James C. Lee
11: * Add 3.3 bus support & 8-bit color support.
12: * Thu Sep 22 16:39:18 PDT 1994 James C. Lee
13: * Use the new PCI API that returns IOReturn instead of BOOL.
14: */
15: #import <string.h>
16: #import <driverkit/generalFuncs.h>
17: #import <driverkit/i386/ioPorts.h>
18: #import <driverkit/i386/directDevice.h>
19: #import <driverkit/i386/IOPCIDeviceDescription.h>
20: #import <driverkit/i386/IOPCIDirectDevice.h>
21: #import <string.h>
22: #import <stdio.h>
23: //#import <stdlib.h>
24:
25: #import "QVision.h"
26:
27:
28: /* private interfaces for SetMode category of QVision */
29: /*@interface QVision (SetMode_Private)
30: - (ConfigBusType) determineConfigBusType;
31: - (QVAdapterType) determineVLCardType;
32: - (QVAdapterType) determinePCICardType;
33: - (QVAdapterType) determineEISACardType;
34: @end
35: */
36: /* The `SetMode' category of `QVision'. */
37:
38: @implementation QVision (SetMode)
39:
40: - (ConfigBusType) determineConfigBusType
41: {
42: const char *busTypeName;
43: IOConfigTable *configTable;
44:
45: configTable = [[self deviceDescription] configTable];
46: busTypeName = [configTable valueForStringKey:"Bus Type"];
47: if (strcmp(busTypeName, "PCI")==0) {
48: busType = BusPCI;
49: } else if (strcmp(busTypeName, "EISA")==0) {
50: busType = BusEISA;
51: } else {
52: /* default to ISA or VL */
53: busType = BusISAorVL;
54: }
55: return busType;
56: }
57:
58: /* assume dac type is determined already. This method is called by
59: * determineConfiguration only */
60: - (QVAdapterType) determineVLCardType
61: {
62: QVAdapterType adapterType;
63:
64: adapterType = UnknownAdapter;
65: switch (dac) {
66: case Bt484:
67: adapterType = OrionAdapter;
68: break;
69: case Bt485:
70: case Bt485A:
71: case ATT20C505:
72: adapterType = Orion12Adapter;
73: break;
74: default:
75: break;
76: }
77: return adapterType;
78: }
79:
80: /* TODO: clean up error handling, i.e. return something meaningful rather
81: * than returning [super free]; */
82: - (QVAdapterType) determinePCICardType
83: {
84: unsigned int physicalAddress;
85: int numRanges;
86: IOPCIConfigSpace configSpace;
87: unsigned char devNum, funcNum, busNum;
88: unsigned long vendorDeviceID;
89: unsigned short vendorID, deviceID;
90: char idString[11];
91: id deviceDescription;
92: QVAdapterType adapterType;
93: IOConfigTable *configTable;
94: IORange *oldRange, newRange[3];
95:
96: adapterType = UnknownAdapter;
97: if (![self isPCIPresent]) {
98: IOLog ("%s: No PCI card found.\n", [self name]);
99: return UnknownAdapter;
100: }
101: deviceDescription = [self deviceDescription];
102: [deviceDescription getPCIdevice:&devNum function:&funcNum bus:&busNum];
103: IOLog_dbg(("%s: PCI Dev:%d Func:%d Bus:%d\n", [self name], devNum,
104: funcNum, busNum));
105: [self getPCIConfigData:&vendorDeviceID atRegister:0x00];
106: vendorID = (unsigned short) vendorDeviceID;
107: deviceID = (unsigned short) (vendorDeviceID >> 16);
108: IOLog("%s: vendorID=%04x deviceID=%04x\n", [self name], vendorID,
109: deviceID);
110:
111: /* go through "Auto Detect IDs" and make sure we are okay */
112: configTable = [[self deviceDescription] configTable];
113: sprintf(idString, "%08lx", vendorDeviceID);
114: if (strstr([configTable valueForStringKey:"Auto Detect IDs"], idString)
115: == NULL)
116: {
117: IOLog("%s: VenderDeviceID %08lx not found in instance table.\n",
118: [self name], vendorDeviceID);
119: return UnknownAdapter;
120: } else {
121: /* add more card types here if there are PCI cards other than 1280P
122: * actually, if there are more than one PCI cards, we should determine
123: * which PCI card here */
124: adapterType = QVision1280P;
125: }
126:
127: /* need to do set framebuffer address for PCI */
128: [self getPCIConfigSpace:&configSpace];
129: physicalAddress = configSpace.BaseAddress[0];
130: physicalAddress &= 0xfffffff0; /* mask out lower 4 bits */
131:
132: if (physicalAddress) {
133: IOLog_dbg(("%s: try to set physical address to 0x%08x\n",
134: [self name], physicalAddress));
135: /* PCI does report where the frame buffer address is */
136: oldRange = [deviceDescription memoryRangeList];
137: numRanges = [deviceDescription numMemoryRanges];
138: if (numRanges==3) {
139: int ret;
140: int i;
141:
142: /* replace the address */
143: for (i=0; i<numRanges; i++) {
144: newRange[i] = oldRange[i];
145: }
146: newRange[0].start = physicalAddress;
147: ret = [deviceDescription setMemoryRangeList:newRange num:3];
148: if (ret) {
149: /* can't set to new memory range */
150: IOLog("%s: Can't set memory range, using default.\n",
151: [self name]);
152: for (i=0; i<numRanges; i++) {
153: newRange[i] = oldRange[i];
154: }
155: physicalAddress = newRange[0].start;
156: ret = [deviceDescription setMemoryRangeList:newRange
157: num:3];
158: if (ret) {
159: /* can't set to old range-->major problem! */
160: IOLog("%s: Can't set to default range either!\n",
161: [self name]);
162: return UnknownAdapter;
163: }
164: }
165: } else {
166: IOLog("%s: Incorrect number of address ranges: %d.\n",
167: [self name], numRanges);
168: return UnknownAdapter;
169: }
170: } else {
171: IOLog_dbg(("%s: PCI doesn't tell us the physical address.\n",
172: [self name]));
173: physicalAddress = [deviceDescription memoryRangeList] -> start;
174: configSpace.BaseAddress[0] = physicalAddress;
175: [self setPCIConfigSpace:&configSpace];
176: }
177: return adapterType;
178: }
179:
180:
181: /* helper method to -determineEISACardType */
182: - (QVAdapterType)adapterTypeFromEISAID:(unsigned int)cardID
183: {
184: QVAdapterType adapterType;
185:
186: adapterType = UnknownAdapter;
187: IOLog_dbg(("%s: adapterTypeFromEISAID cardID=0x%08x\n", [self name],
188: cardID));
189: switch (cardID) {
190: case QVISION_EISA_ID:
191: adapterType = QVisionAdapter;
192: break;
193: case ORION_EISA_ID:
194: adapterType = OrionAdapter;
195: break;
196: case ORION12_EISA_ID:
197: adapterType = Orion12Adapter;
198: break;
199: case QVISION_ISA_ID:
200: case ORION_ISA_ID:
201: case ORION12_ISA_ID:
202: IOLog("%s: Sorry, ISA cards are not supported (id=0x%08x).\n",
203: [self name], cardID);
204: break;
205: default:
206: /* We found some other EISA card. Just ignore it. */
207: break;
208: }
209: return adapterType;
210: }
211:
212: /* helper method to -determineEISACardType */
213: - (QVAdapterType)autoScanEISAForCardType
214: {
215: int slot;
216: QVAdapterType adapterType;
217: unsigned int cardID;
218:
219: IOLog_dbg(("%s: doing auto-scan on EISA bus.\n", [self name]));
220:
221: adapterType = UnknownAdapter;
222: for (slot=1; slot<16; slot++) {
223: if ([self getEISAId:&cardID forSlot:slot]) {
224: adapterType = [self adapterTypeFromEISAID:cardID];
225: }
226: if (adapterType != UnknownAdapter) {
227: IOLog_dbg(("%s: found card in slot %d.\n", [self name], slot));
228: return adapterType;
229: }
230: }
231: return UnknownAdapter;
232: }
233:
234: /* can't use atoi() nor sscanf() */
235: - (int) getFirstNumber:(char *)s
236: {
237: char *cptr;
238: int n;
239:
240: cptr = s;
241: n = -1;
242: while(*cptr && ((*cptr<'0') || (*cptr>'9'))) cptr++;
243: while(*cptr && ((*cptr>='0') && (*cptr<='9'))) {
244: if (n==-1) n = 0;
245: n = n*10 + (*cptr - '0');
246: cptr++;
247: }
248: return n;
249: }
250:
251: /* TODO: clean up error handling, i.e. return something meaningful rather
252: * than returning [super free]; */
253: - (QVAdapterType) determineEISACardType
254: {
255: QVAdapterType adapterType;
256: int mySlot;
257: id deviceDescription;
258: const char *slotValue;
259: IOConfigTable *configTable;
260: unsigned int cardID;
261:
262: adapterType = UnknownAdapter;
263: if (![self isEISAPresent]) {
264: IOLog ("%s: Not an EISA system.\n", [self name]);
265: return UnknownAdapter;
266: }
267: deviceDescription = [self deviceDescription];
268: configTable = [[self deviceDescription] configTable];
269:
270: /* see what slot we're supposed be in */
271: slotValue = [configTable valueForStringKey:"Location"];
272: if (strstr(slotValue, "Slot")) {
273: mySlot = [self getFirstNumber:(char *)slotValue];
274: IOLog_dbg(("%s: we should be in slot %d\n", [self name], mySlot));
275: } else {
276: /* instance table doesn't tell us what slot we're in */
277: return [self autoScanEISAForCardType];
278: }
279:
280: /* TODO: need to check for auto detect id's */
281: if (mySlot > 0) {
282: if ([self getEISAId:&cardID forSlot:mySlot]) {
283: adapterType = [self adapterTypeFromEISAID:cardID];
284: } else {
285: /* can't find card in the specified slot, do auto-scan */
286: adapterType = [self autoScanEISAForCardType];
287: }
288: } else {
289: /* slot not specified, do auto-scan */
290: adapterType = [self autoScanEISAForCardType];
291: }
292: return adapterType;
293: }
294:
295: - (void)reportConfiguration
296: {
297: const char *adapterString, *dacString;
298:
299: switch (adapter) {
300: case QVisionAdapter: adapterString = "QVision"; break;
301: case OrionAdapter: adapterString = "Orion"; break;
302: case Orion12Adapter: adapterString = "Orion12"; break;
303: case QVision1280P: adapterString = "QVision1280P"; break;
304: default: adapterString = "unknown"; break;
305: }
306:
307: switch (dac) {
308: case Bt484: dacString = "Brooktree 484"; break;
309: case Bt485: dacString = "Brooktree 485"; break;
310: case Bt485A: dacString = "Brooktree 485A"; break;
311: case ATT20C505: dacString = "AT&T 20C505"; break;
312: default: dacString = "unknown"; break;
313: }
314:
315: IOLog("%s: %s adapter; %s DAC.\n", [self name], adapterString, dacString);
316: }
317:
318: - determineConfiguration
319: {
320: adapter = UnknownAdapter;
321:
322: [self determineConfigBusType];
323: [self determineDACType];
324: switch(busType) {
325: case BusISAorVL:
326: adapter = [self determineVLCardType];
327: break;
328: case BusPCI:
329: adapter = [self determinePCICardType];
330: break;
331: case BusEISA:
332: adapter = [self determineEISACardType];
333: break;
334: }
335: [self reportConfiguration];
336: if (adapter==UnknownAdapter || dac==UnknownDAC) return nil;
337: return self;
338: }
339:
340: - selectMode
341: {
342: int k, mode;
343: const QVisionMode *qvMode;
344: BOOL validModes[QVisionModeTableCount];
345:
346: for (k = 0; k < QVisionModeTableCount; k++) {
347: qvMode = QVisionModeTable[k].parameters;
348: validModes[k] = (qvMode->adapter <= adapter);
349: }
350:
351: mode = [self selectMode:QVisionModeTable count:QVisionModeTableCount
352: valid:validModes];
353:
354: if (mode < 0) {
355: IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
356: switch (adapter) {
357: case Orion12Adapter:
358: mode = DEFAULT_ORION12_MODE;
359: break;
360: case OrionAdapter:
361: mode = DEFAULT_ORION_MODE;
362: break;
363: case QVision1280P:
364: mode = DEFAULT_1280P_MODE;
365: break;
366: case QVisionAdapter:
367: default:
368: mode = DEFAULT_QVISION_MODE;
369: break;
370: }
371: }
372: *[self displayInfo] = QVisionModeTable[mode];
373: return self;
374: }
375:
376: - initializeMode
377: {
378: unsigned int i;
379: const QVisionMode *mode;
380: const IODisplayInfo *displayInfo;
381:
382: displayInfo = [self displayInfo];
383: mode = displayInfo->parameters;
384:
385: /* Turn off video while setting all of the registers. */
386: inb(VGA_INPUT_STATUS_1);
387: outb(VGA_ATTR_INDEX, 0x00);
388:
389: /* Set the sequencer registers. */
390: for (i = 0; i < VGA_SEQ_COUNT; i++) {
391: outb(VGA_SEQ_INDEX, i);
392: outb(VGA_SEQ_DATA, mode->vgaData.seqx[i]);
393: }
394: outb(VGA_SEQ_INDEX, 0x00);
395: outb(VGA_SEQ_DATA, 0x03); /* Restart the sequencer. */
396:
397: /* Unlock extended graphics registers. */
398: outw(VGA_GRFX_INDEX, 0x050f);
399:
400: /* Unlock more extended registers. */
401: outb(VGA_GRFX_INDEX, 0x10);
402: outb(VGA_GRFX_DATA, 0x08);
403:
404: /* Set Advanced VGA mode (set bit 0 of Ctrl Reg 0). */
405: outb(VGA_GRFX_INDEX, 0x40);
406: outb(VGA_GRFX_DATA, 0x01);
407:
408: /* Fix sequencer pixel mask for 8 bits. */
409: outb(VGA_SEQ_INDEX, SEQ_PIXEL_WR_MSK);
410: outb(VGA_SEQ_DATA, 0xff);
411:
412: outb(CTRL_REG_1, mode->ctrlReg1);
413: if (mode->adapter >= OrionAdapter) {
414: /* Set access level & enable high address map. */
415: outb(QVGA_CTL_2, 0x14);
416: /* Select 2 Meg mode. */
417: outb(QVGA_CTL_3, 0x05);
418: }
419:
420: /* Set miscellaneous output register. */
421: outb(VGA_MISC_OUTPUT, mode->vgaData.miscOutput);
422:
423: [self programDAC];
424:
425: /* Load CRTC registers. */
426: outb(VGA_CRTC_INDEX, 0x11); /* Unlock CRTC regs 0-7. */
427: outb(VGA_CRTC_DATA, 0x00);
428: for (i = 0; i < VGA_CRTC_COUNT; i++) {
429: outb(VGA_CRTC_INDEX, i);
430: outb(VGA_CRTC_DATA, mode->vgaData.crtc[i]);
431: }
432:
433: /* Load overflow registers. */
434: outb(VGA_GRFX_INDEX, 0x42);
435: outb(VGA_GRFX_DATA, mode->overflow1);
436: outb(VGA_GRFX_INDEX, 0x51);
437: outb(VGA_GRFX_DATA, mode->overflow2);
438:
439: /* Load attribute registers. */
440:
441: inb(VGA_INPUT_STATUS_1); /* Reset latch. */
442: for (i = 0; i < VGA_ATTR_COUNT; i++) {
443: outb(VGA_ATTR_INDEX, i);
444: outb(VGA_ATTR_DATA, mode->vgaData.attr[i]);
445: }
446:
447: /* Load graphics registers. */
448: for (i = 0; i < VGA_GRFX_COUNT; i++) {
449: outb(VGA_GRFX_INDEX, i);
450: outb(VGA_GRFX_DATA, mode->vgaData.grfx[i]);
451: }
452:
453: [self setGammaTable];
454:
455: /* Re-enable video display. */
456: inb(VGA_INPUT_STATUS_1);
457: outb(VGA_ATTR_INDEX, 0x20);
458:
459: return self;
460: }
461:
462: - enableLinearFrameBuffer
463: {
464: const IODisplayInfo *displayInfo;
465: unsigned char tmp;
466:
467: /* Override the high address map disable, thus allowing access to
468: * the high address map of the current board, even when the board
469: * is disabled. */
470:
471: outb(VGA_GRFX_INDEX, HI_ADDR_MAP+1);
472: tmp = inb(VGA_GRFX_DATA);
473: outb(VGA_GRFX_DATA, tmp | 0x80);
474:
475: /* Map VRAM. Tell the adapter where to decode the framebuffer. */
476:
477: /* Set low 8 bits */
478: outb(VGA_GRFX_INDEX, HI_ADDR_MAP);
479: outb(VGA_GRFX_DATA, (videoRamAddress >> 20) & 0xFF);
480:
481: /* Set upper 4 bits */
482: outb(VGA_GRFX_INDEX, HI_ADDR_MAP + 1);
483: outb(VGA_GRFX_DATA, (videoRamAddress >> 28) & 0x0F);
484:
485: /* Leave them with a nice clear screen. */
486:
487: displayInfo = [self displayInfo];
488: memset(displayInfo->frameBuffer, 0,
489: displayInfo->rowBytes * displayInfo->height);
490:
491: return self;
492: }
493:
494: - resetVGA
495: {
496: const IODisplayInfo *displayInfo;
497: const QVisionMode *mode;
498:
499: displayInfo = [self displayInfo];
500: mode = displayInfo->parameters;
501:
502: /* Clear the QVision extended mode bit. This is bit 0 of CTRL_REG_1. */
503:
504: outb(CTRL_REG_1, inb(CTRL_REG_1) & 0xFE);
505:
506: if (mode != 0 && mode->adapter >= OrionAdapter) {
507: /* Select 1 meg mode. */
508: outb(QVGA_CTL_3, 0x00);
509: /* Reset access level & disable high address map. */
510: outb(QVGA_CTL_2, 0x00);
511: }
512:
513: /* Clear the extended 256 color bit. This is bit 0 of 3CF.40. */
514: outb(VGA_GRFX_INDEX, 0x40);
515: outb(VGA_GRFX_DATA, (inb(VGA_GRFX_DATA) & 0xFE));
516:
517: /* Clear the page registers - 3CF.45 and 3CF.46. */
518: outb(VGA_GRFX_INDEX, PAGE_REG_0);
519: outb(VGA_GRFX_DATA, 0x00);
520: outb(VGA_GRFX_INDEX, PAGE_REG_1);
521: outb(VGA_GRFX_DATA, 0x00);
522:
523: [self resetDAC];
524:
525: /* Clear the overflow registers. */
526: outb(VGA_GRFX_INDEX, 0x42);
527: outb(VGA_GRFX_DATA, 0x00);
528: outb(VGA_GRFX_INDEX, 0x51);
529: outb(VGA_GRFX_DATA, 0x00);
530:
531: VGASetMode(0x03);
532:
533: return self;
534: }
535: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.