|
|
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.