|
|
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 by NeXT Computer, Inc.
25: * All rights reserved.
26: *
27: * IOVPCodeDisplay.m -- vpcode video display driver.
28: *
29: * 22 July 1993 Derek B Clegg
30: * Created.
31: */
32:
33: #import <stdio.h>
34: #import <stdlib.h>
35: #import <string.h>
36: #import <driverkit/i386/ioPorts.h>
37: #import <driverkit/i386/IOEISADeviceDescription.h>
38: #import <driverkit/i386/IOVPCodeDisplay.h>
39:
40: @interface IOVPCodeDisplay (Private)
41: - jumpTo:(int)entryPoint withInitialSRegs:(VPInstruction *)initialSRegs;
42: - setGammaTable;
43: - _setDefaultGammaTable:(VPInstruction *)transferTable;
44: - getDisplayInfo;
45: @end
46:
47: @implementation IOVPCodeDisplay
48:
49: - getPixelEncoding
50: {
51: int n, k;
52: unsigned char *p;
53: IODisplayInfo *displayInfo;
54: VPInstruction reg[8];
55:
56: if (_debug)
57: IOLog("%s: Getting pixel encoding.\n", [self name]);
58:
59: if (![self runVPCode:VP_GET_PIXEL_ENCODING withRegs:reg]) {
60: IOLog("%s: Can't obtain pixel encoding.\n", [self name]);
61: return nil;
62: }
63:
64: displayInfo = [self displayInfo];
65: memset(displayInfo->pixelEncoding, 0, sizeof(displayInfo->pixelEncoding));
66:
67: switch (displayInfo->colorSpace) {
68: case IO_OneIsBlackColorSpace:
69: case IO_OneIsWhiteColorSpace:
70: switch (displayInfo->bitsPerPixel) {
71: case IO_2BitsPerPixel:
72: for (k = 0; k < 2; k++)
73: displayInfo->pixelEncoding[k] = reg[0];
74: break;
75: case IO_8BitsPerPixel:
76: for (k = 0; k < 8; k++)
77: displayInfo->pixelEncoding[k] = reg[0];
78: break;
79: default:
80: IOLog("%s: invalid `bitsPerPixel' (%d) for color space %d.\n",
81: [self name], displayInfo->bitsPerPixel,
82: displayInfo->colorSpace);
83: return nil;
84: }
85: break;
86:
87: case IO_RGBColorSpace:
88: switch (displayInfo->bitsPerPixel) {
89: case IO_12BitsPerPixel:
90: if (reg[0] != 'R' || reg[1] != 'G' || reg[2] != 'B'
91: || reg[3] != '-') {
92: IOLog("%s: Sorry, only `RRRRGGGGBBBB----' supported for "
93: "`IO_12BitsPerPixel'.\n", [self name]);
94: return nil;
95: }
96: strcpy(displayInfo->pixelEncoding, "RRRRGGGGBBBB----");
97: break;
98: case IO_15BitsPerPixel:
99: if (reg[0] != '-' || reg[1] != 'R' || reg[2] != 'G'
100: || reg[3] != 'B') {
101: IOLog("%s: Sorry, only `-RRRRRGGGGGBBBBB' supported for "
102: "`IO_15BitsPerPixel'.\n", [self name]);
103: return nil;
104: }
105: strcpy(displayInfo->pixelEncoding, "-RRRRRGGGGGBBBBB");
106: break;
107:
108: case IO_24BitsPerPixel:
109: p = displayInfo->pixelEncoding;
110: for (n = 0; n < 4; n++) {
111: for (k = 0; k < 8; k++) {
112: *p++ = reg[n];
113: }
114: }
115: break;
116: default:
117: IOLog("%s: invalid `bitsPerPixel' (%d) for RGB color space.\n",
118: [self name], displayInfo->bitsPerPixel);
119: break;
120: }
121: break;
122:
123: default:
124: IOLog("%s: Sorry, color space %d is not supported.\n",
125: [self name], displayInfo->colorSpace);
126: return nil;
127: }
128:
129: if (_debug)
130: IOLog("%s: pixelEncoding = `%s'.\n", [self name],
131: displayInfo->pixelEncoding);
132:
133: return self;
134: }
135:
136: - getDisplayInfo
137: {
138: IODisplayInfo *displayInfo;
139: VPInstruction reg[8];
140:
141: /* Verify that the selected mode is valid. */
142:
143: if (_debug)
144: IOLog("%s: verifying selected mode.\n", [self name]);
145:
146: if (![self runVPCode:VP_VERIFY_MODE withRegs:reg]) {
147: IOLog("%s: Failed to verify mode.\n", [self name]);
148: return nil;
149: }
150: if (reg[0] != 0) {
151: IOLog("%s: Selected mode is invalid.\n", [self name]);
152: if (![self runVPCode:VP_SET_DEFAULT_MODE withRegs:0]) {
153: IOLog("%s: Failed to set default mode.\n", [self name]);
154: return nil;
155: }
156: }
157:
158: if (_debug)
159: IOLog("%s: Getting display info.\n", [self name]);
160:
161: if (![self runVPCode:VP_GET_DISPLAY_INFO withRegs:reg]) {
162: IOLog("%s: Failed to obtain display info.\n", [self name]);
163: return nil;
164: }
165: displayInfo = [self displayInfo];
166: displayInfo->width = reg[0];
167: displayInfo->height = reg[1];
168: displayInfo->totalWidth = reg[2];
169: displayInfo->rowBytes = reg[3];
170: displayInfo->refreshRate = reg[4];
171: displayInfo->bitsPerPixel = reg[5];
172: displayInfo->colorSpace = reg[6];
173: displayInfo->flags = reg[7];
174:
175: if ([self getPixelEncoding] == nil)
176: return nil;
177:
178: IOLog("%s: IOVPCodeDisplay: Initialized.\n", [self name]);
179: return self;
180: }
181:
182: /* Put the display into linear framebuffer mode. This typically happens
183: * when the window server starts running.
184: */
185: - (void)enterLinearMode
186: {
187: IODisplayInfo *displayInfo;
188: VPInstruction reg[8];
189:
190: /* Set up the chip to use the selected mode. */
191:
192: if (_debug)
193: IOLog("%s: Initializing video mode.\n", [self name]);
194:
195: if (![self runVPCode:VP_INITIALIZE_MODE withRegs:0]) {
196: IOLog("%s: Failed to initialize mode.\n", [self name]);
197: return;
198: }
199:
200: /* Set the gamma-corrected gray-scale palette if necessary. */
201: [self setGammaTable];
202:
203: /* Enter linear mode. */
204: if (_debug)
205: IOLog("%s: Enabling linear framebuffer: 0x%08x\n", [self name],
206: _videoRamAddress);
207:
208: reg[0] = _videoRamAddress;
209: reg[1] = _videoRamSize;
210: if (![self runVPCode:VP_ENABLE_LINEAR_FRAMEBUFFER withRegs:reg])
211: return;
212:
213: /* Clear the screen. */
214: displayInfo = [self displayInfo];
215: memset(displayInfo->frameBuffer, 0,
216: displayInfo->rowBytes * displayInfo->height);
217: }
218:
219: /* Get the device out of whatever advanced linear mode it was using and back
220: * into a state where it can be used as a standard VGA device.
221: */
222: - (void)revertToVGAMode
223: {
224: /* Reset the VGA parameters. */
225: if (_debug)
226: IOLog("%s: Resetting VGA parameters.\n", [self name]);
227:
228: if (![self runVPCode:VP_RESET_VGA withRegs:0])
229: return;
230:
231: /* Let the superclass do whatever work it needs to do. */
232: [super revertToVGAMode];
233: }
234:
235: /* Set the brightness to `level'.
236: */
237: - setBrightness:(int)level token:(int)t
238: {
239: if (level < EV_SCREEN_MIN_BRIGHTNESS || level > EV_SCREEN_MAX_BRIGHTNESS) {
240: IOLog("QVision: Invalid brightness level `%d'.\n", level);
241: return nil;
242: }
243: brightnessLevel = level;
244: [self setGammaTable];
245: return self;
246: }
247:
248: /* Set the transfer tables.
249: */
250: - setTransferTable:(const unsigned int *)table count:(int)count
251: {
252: int k;
253:
254: if (redTransferTable != 0)
255: IOFree(redTransferTable, 3 * transferTableCount);
256:
257: transferTableCount = count;
258:
259: redTransferTable = IOMalloc(3 * count);
260: greenTransferTable = redTransferTable + count;
261: blueTransferTable = greenTransferTable + count;
262:
263: switch ([self displayInfo]->bitsPerPixel) {
264: case IO_2BitsPerPixel:
265: case IO_8BitsPerPixel:
266: for (k = 0; k < count; k++) {
267: redTransferTable[k] = greenTransferTable[k] =
268: blueTransferTable[k] = table[k] & 0xFF;
269: }
270: break;
271:
272: case IO_12BitsPerPixel:
273: case IO_15BitsPerPixel:
274: case IO_24BitsPerPixel:
275: for (k = 0; k < count; k++) {
276: redTransferTable[k] = (table[k] >> 24) & 0xFF;
277: greenTransferTable[k] = (table[k] >> 16) & 0xFF;
278: blueTransferTable[k] = (table[k] >> 8) & 0xFF;
279: }
280: break;
281:
282: default:
283: IOFree(redTransferTable, 3 * count);
284: redTransferTable = 0;
285: break;
286: }
287: [self setGammaTable];
288: return self;
289: }
290:
291: /* Default gamma precompensation table for color displays.
292: * Gamma 2.2 LUT for P22 phosphor displays (Hitachi, NEC, generic VGA) */
293:
294: static unsigned char gamma2[4] = {
295: 0, 155, 212, 255,
296: };
297:
298: static unsigned char gamma4[16] = {
299: 0, 74, 102, 123, 140, 155, 168, 180,
300: 192, 202, 212, 221, 230, 239, 247, 255,
301: };
302:
303: static unsigned char gamma5[32] = {
304: 0, 54, 73, 88, 101, 111, 121, 130,
305: 138, 145, 152, 159, 166, 172, 178, 183,
306: 189, 194, 199, 204, 209, 214, 218, 223,
307: 227, 231, 235, 239, 243, 247, 251, 255,
308: };
309:
310: static const unsigned char gamma8[256] = {
311: 0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52,
312: 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 74, 76,
313: 78, 79, 81, 82, 84, 85, 87, 88, 90, 91, 93, 94,
314: 95, 97, 98, 99, 100, 102, 103, 104, 105, 107, 108, 109,
315: 110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122,
316: 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
317: 135, 136, 137, 138, 139, 140, 141, 141, 142, 143, 144, 145,
318: 146, 147, 148, 148, 149, 150, 151, 152, 153, 153, 154, 155,
319: 156, 157, 158, 158, 159, 160, 161, 162, 162, 163, 164, 165,
320: 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174,
321: 174, 175, 176, 177, 177, 178, 179, 179, 180, 181, 182, 182,
322: 183, 184, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190,
323: 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198,
324: 199, 200, 200, 201, 201, 202, 203, 203, 204, 205, 205, 206,
325: 206, 207, 208, 208, 209, 210, 210, 211, 211, 212, 213, 213,
326: 214, 214, 215, 216, 216, 217, 217, 218, 218, 219, 220, 220,
327: 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
328: 228, 228, 229, 229, 230, 230, 231, 231, 232, 233, 233, 234,
329: 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240,
330: 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246,
331: 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252,
332: 253, 253, 254, 255,
333: };
334:
335: - _setDefaultGammaTable:(VPInstruction *)transferTable
336: {
337: unsigned int k, g, v;
338: const IODisplayInfo *displayInfo;
339:
340: displayInfo = [self displayInfo];
341:
342: switch (displayInfo->bitsPerPixel) {
343: case IO_2BitsPerPixel:
344: for (g = 0; g < 4; g++) {
345: v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma2[g]);
346: v = (v << 16) | (v << 8) | v;
347: for (k = 0; k < 64; k++) {
348: *transferTable++ = v;
349: }
350: }
351: break;
352:
353: case IO_12BitsPerPixel:
354: for (g = 0; g < 16; g++) {
355: v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma4[g]);
356: v = (v << 16) | (v << 8) | v;
357: for (k = 0; k < 16; k++) {
358: *transferTable++ = v;
359: }
360: }
361: break;
362:
363: case IO_15BitsPerPixel:
364: for (g = 0; g < 32; g++) {
365: v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma5[g]);
366: v = (v << 16) | (v << 8) | v;
367: for (k = 0; k < 8; k++)
368: *transferTable++ = v;
369: }
370: break;
371:
372: case IO_8BitsPerPixel:
373: case IO_24BitsPerPixel:
374: for (g = 0; g < 256; g++) {
375: v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma8[g]);
376: *transferTable++ = (v << 16) | (v << 8) | v;
377: }
378: break;
379:
380: default:
381: return self;
382: }
383: if (![self runVPCode:VP_SET_TRANSFER_TABLE withRegs:0])
384: return nil;
385: return self;
386: }
387:
388: - setGammaTable
389: {
390: unsigned int i, j, r, g, b, v, *transferTable;
391:
392: if (_debug)
393: IOLog("%s: setting transfer table.\n", [self name]);
394:
395: if (_vpCode == 0 || _vpCodeCount <= 0
396: || VP_TRANSFER_TABLE >= _vpCodeCount) {
397: IOLog("%s: Can't set transfer table: no vpcode present.\n",
398: [self name]);
399: return nil;
400: }
401: v = _vpCode[VP_TRANSFER_TABLE];
402: if (v >= _vpCodeCount) {
403: IOLog("%s: transfer table address is out of range: 0x%x.\n",
404: [self name], v);
405: return nil;
406: }
407: if (v == 0)
408: return self;
409:
410: if (_debug)
411: IOLog("%s: using transfer table at 0x%08x.\n", [self name], v);
412:
413: transferTable = &_vpCode[v];
414:
415: if (redTransferTable == 0)
416: return [self _setDefaultGammaTable:transferTable];
417:
418: for (i = 0; i < transferTableCount; i++) {
419: for (j = 0; j < 256/transferTableCount; j++) {
420: r = EV_SCALE_BRIGHTNESS(brightnessLevel, redTransferTable[i]);
421: g = EV_SCALE_BRIGHTNESS(brightnessLevel, greenTransferTable[i]);
422: b = EV_SCALE_BRIGHTNESS(brightnessLevel, blueTransferTable[i]);
423: *transferTable++ = (r << 16) | (g << 8) | b;
424: }
425: }
426:
427: if (_debug) {
428: transferTable = &_vpCode[v];
429: IOLog("%s: Transfer table:\n", [self name]);
430: for (i = 0; i < 64; i++) {
431: IOLog("%s: ", [self name]);
432: for (j = 0; j < 4; j++) {
433: IOLog("%08x ", *transferTable++);
434: }
435: IOLog("\n");
436: }
437: }
438:
439: if (![self runVPCode:VP_SET_TRANSFER_TABLE withRegs:0])
440: return nil;
441: return self;
442: }
443:
444: - initFromDeviceDescription:deviceDescription
445: {
446: const IORange *range;
447: IODisplayInfo *displayInfo;
448:
449: if ([super initFromDeviceDescription:deviceDescription] == nil)
450: return [super free];
451:
452: _debug = NO;
453:
454: range = [deviceDescription memoryRangeList];
455: if (range == 0) {
456: IOLog("%s: No memory range set.\n", [self name]);
457: return [super free];
458: }
459: _videoRamAddress = range[0].start;
460: _videoRamSize = range[0].size;
461:
462: redTransferTable = greenTransferTable = blueTransferTable = 0;
463: transferTableCount = 0;
464: brightnessLevel = EV_SCREEN_MAX_BRIGHTNESS;
465:
466: displayInfo = [self displayInfo];
467: displayInfo->frameBuffer =
468: (void *)[self mapFrameBufferAtPhysicalAddress:0 length:0];
469: if (displayInfo->frameBuffer == 0)
470: return [self free];
471:
472: if (_debug) {
473: IOLog("Video Ram Address = 0x%08x\n", _videoRamAddress);
474: IOLog("Framebuffer Address = 0x%08x\n",
475: (unsigned int)displayInfo->frameBuffer);
476: }
477: return self;
478: }
479:
480: - jumpTo:(int)entryPoint withInitialSRegs:(VPInstruction *)initialSRegs
481: {
482: VPInstruction reg[16]; /* P-machine register set */
483: VPInstruction immediate; /* Immediate value for some instructions. */
484: VPInstruction instruction; /* The current instruction */
485: unsigned int port; /* The port for ins and outs. */
486: BOOL zero; /* Zero condition code. */
487: BOOL positive; /* Positive condition code. */
488: BOOL negative; /* Negative condition code. */
489: int pc; /* The program counter. */
490:
491: if (_vpCode == 0 || _vpCodeCount <= 0) {
492: IOLog("%s: No vpcode to run.\n", [self name]);
493: return nil;
494: }
495:
496: /* Set up the initial registers. */
497:
498: if (initialSRegs == 0) {
499: memset(®[0], 0, 16 * sizeof(reg[0]));
500: } else {
501: memset(®[0], 0, 8 * sizeof(reg[0]));
502: memcpy(®[8], initialSRegs, 8 * sizeof(reg[0]));
503: }
504:
505: immediate = 0;
506: zero = positive = negative = NO;
507: pc = entryPoint;
508:
509: while (1) {
510: if (pc < 0 || pc >= _vpCodeCount) {
511: IOLog("%s: program counter is out of range: 0x%x.\n",
512: [self name], (unsigned)pc);
513: return nil;
514: }
515: instruction = _vpCode[pc++];
516: if (VP_IMMEDIATE_FOLLOWS_OPCODE(instruction))
517: immediate = _vpCode[pc++];
518:
519: switch (VP_OPCODE(instruction)) {
520: case VP_DEBUG:
521: _debug = YES;
522: break;
523:
524: case VP_DELAY:
525: IODelay(immediate);
526: break;
527:
528: case VP_LOAD_CR: /* load constant, reg2 */
529: case VP_LOAD_TR: /* load label, reg2 */
530: reg[VP_REG2(instruction)] = immediate;
531: break;
532:
533: case VP_LOAD_AR: /* load @address, reg2 */
534: if (immediate >= _vpCodeCount) {
535: IOLog("%s: load address is out of range: 0x%x.\n",
536: [self name], immediate);
537: return nil;
538: }
539: reg[VP_REG2(instruction)] = _vpCode[immediate];
540: break;
541:
542: case VP_LOAD_IR: /* load @reg1, reg2 */
543: immediate = reg[VP_REG1(instruction)];
544: if (immediate >= _vpCodeCount) {
545: IOLog("%s: load address is out of range: 0x%x.\n",
546: [self name], immediate);
547: return nil;
548: }
549: reg[VP_REG2(instruction)] = _vpCode[immediate];
550: break;
551:
552: case VP_VLOAD_AR: /* vload @address, reg2 */
553: if (_videoRamAddress == 0 || immediate >= _videoRamSize) {
554: IOLog("%s: invalid video ram address: 0x%x.\n",
555: [self name], _videoRamAddress + immediate);
556: return nil;
557: }
558: reg[VP_REG2(instruction)] =
559: ((VPInstruction *)_videoRamAddress)[immediate];
560: break;
561:
562: case VP_VLOAD_IR: /* vload @reg1, reg2 */
563: immediate = reg[VP_REG1(instruction)];
564: if (_videoRamAddress == 0 || immediate >= _videoRamSize) {
565: IOLog("%s: invalid video ram address: 0x%x.\n",
566: [self name], _videoRamAddress + immediate);
567: return nil;
568: }
569: reg[VP_REG2(instruction)] =
570: ((VPInstruction *)_videoRamAddress)[immediate];
571: break;
572:
573: case VP_STORE_AR: /* store reg1, @address */
574: if (immediate >= _vpCodeCount) {
575: IOLog("%s: store address is out of range: 0x%x.\n",
576: [self name], immediate);
577: return nil;
578: }
579: _vpCode[immediate] = reg[VP_REG1(instruction)];
580: break;
581:
582: case VP_STORE_IR: /* store reg1, @reg2 */
583: immediate = reg[VP_REG2(instruction)];
584: if (immediate >= _vpCodeCount) {
585: IOLog("%s: store address is out of range: 0x%x.\n",
586: [self name], immediate);
587: return nil;
588: }
589: _vpCode[immediate] = reg[VP_REG1(instruction)];
590: break;
591:
592: case VP_VSTORE_AR: /* vstore reg1, @address */
593: if (_videoRamAddress == 0
594: || immediate * sizeof(VPInstruction) >= _videoRamSize) {
595: IOLog("%s: invalid video ram address: 0x%x.\n",
596: [self name], _videoRamAddress + immediate);
597: return nil;
598: }
599: ((VPInstruction *)_videoRamAddress)[immediate] =
600: reg[VP_REG1(instruction)];
601: break;
602:
603: case VP_VSTORE_IR: /* vstore reg1, @reg2 */
604: immediate = reg[VP_REG2(instruction)];
605: if (_videoRamAddress == 0
606: || immediate * sizeof(VPInstruction) >= _videoRamSize) {
607: IOLog("%s: invalid video ram address: 0x%x.\n",
608: [self name], _videoRamAddress + immediate);
609: return nil;
610: }
611: ((VPInstruction *)_videoRamAddress)[immediate] =
612: reg[VP_REG1(instruction)];
613: break;
614:
615: case VP_ADD_CRR: /* add constant, reg1, reg2 */
616: reg[VP_REG2(instruction)] = immediate + reg[VP_REG1(instruction)];
617: break;
618:
619: case VP_ADD_RRR: /* add reg1, reg2, reg3 */
620: reg[VP_REG3(instruction)] =
621: reg[VP_REG1(instruction)] + reg[VP_REG2(instruction)];
622: break;
623:
624: case VP_SUB_RCR: /* sub reg1, constant, reg2 */
625: reg[VP_REG2(instruction)] = reg[VP_REG1(instruction)] - immediate;
626: break;
627:
628: case VP_SUB_CRR: /* sub constant, reg1, reg2 */
629: reg[VP_REG2(instruction)] = immediate - reg[VP_REG1(instruction)];
630: break;
631:
632: case VP_SUB_RRR: /* sub reg1, reg2, reg3 */
633: reg[VP_REG3(instruction)] =
634: reg[VP_REG1(instruction)] - reg[VP_REG2(instruction)];
635: break;
636:
637: case VP_AND_CRR: /* and constant, reg1, reg2 */
638: reg[VP_REG2(instruction)] = immediate & reg[VP_REG1(instruction)];
639: break;
640:
641: case VP_AND_RRR: /* and reg1, reg2, reg3 */
642: reg[VP_REG3(instruction)] =
643: reg[VP_REG1(instruction)] & reg[VP_REG2(instruction)];
644: break;
645:
646: case VP_OR_CRR: /* or constant, reg1, reg2 */
647: reg[VP_REG2(instruction)] = immediate | reg[VP_REG1(instruction)];
648: break;
649:
650: case VP_OR_RRR: /* or reg1, reg2, reg3 */
651: reg[VP_REG3(instruction)] =
652: reg[VP_REG1(instruction)] | reg[VP_REG2(instruction)];
653: break;
654:
655: case VP_XOR_CRR: /* xor constant, reg1, reg2 */
656: reg[VP_REG2(instruction)] = immediate ^ reg[VP_REG1(instruction)];
657: break;
658:
659: case VP_XOR_RRR: /* xor reg1, reg2, reg3 */
660: reg[VP_REG3(instruction)] =
661: reg[VP_REG1(instruction)] ^ reg[VP_REG2(instruction)];
662: break;
663:
664: case VP_LSL_RCR: /* lsl reg1, constant, reg3 */
665: reg[VP_REG3(instruction)] =
666: reg[VP_REG1(instruction)] << VP_FIELD2(instruction);
667: break;
668:
669: case VP_LSR_RCR: /* lsr reg1, constant, reg3 */
670: reg[VP_REG3(instruction)] =
671: reg[VP_REG1(instruction)] >> VP_FIELD2(instruction);
672: break;
673:
674: case VP_MOVE_RR: /* move reg1, reg2 */
675: reg[VP_REG2(instruction)] = reg[VP_REG1(instruction)];
676: break;
677:
678: case VP_TEST_R: /* test reg1 */
679: zero = positive = negative = NO;
680: immediate = reg[VP_REG1(instruction)];
681: set_condition_codes:
682: if (immediate == 0) {
683: zero = YES;
684: } else if ((int)immediate > 0) {
685: positive = YES;
686: } else {
687: negative = YES;
688: }
689: break;
690:
691: case VP_CMP_RC: /* cmp reg1, constant */
692: zero = positive = negative = 0;
693: immediate = reg[VP_REG1(instruction)] - immediate;
694: goto set_condition_codes;
695: break;
696:
697: case VP_CMP_CR: /* cmp constant, reg1 */
698: zero = positive = negative = 0;
699: immediate = immediate - reg[VP_REG1(instruction)];
700: goto set_condition_codes;
701: break;
702:
703: case VP_CMP_RR: /* cmp reg1, reg2 */
704: zero = positive = negative = 0;
705: immediate = reg[VP_REG1(instruction)] - reg[VP_REG2(instruction)];
706: goto set_condition_codes;
707: break;
708:
709: case VP_BR:
710: pc = VP_BRANCH_DEST(instruction);
711: break;
712:
713: case VP_BPOS:
714: if (positive)
715: pc = VP_BRANCH_DEST(instruction);
716: break;
717:
718: case VP_BNEG:
719: if (negative)
720: pc = VP_BRANCH_DEST(instruction);
721: break;
722:
723: case VP_BZERO:
724: if (zero)
725: pc = VP_BRANCH_DEST(instruction);
726: break;
727:
728: case VP_BNPOS:
729: if (!positive)
730: pc = VP_BRANCH_DEST(instruction);
731: break;
732:
733: case VP_BNNEG:
734: if (!negative)
735: pc = VP_BRANCH_DEST(instruction);
736: break;
737:
738: case VP_BNZERO:
739: if (!zero)
740: pc = VP_BRANCH_DEST(instruction);
741: break;
742:
743: case VP_INB_CR:
744: port = VP_PORT(instruction);
745: reg[VP_REG2(instruction)] = 0xFF & inb(port);
746: break;
747:
748: case VP_OUTB_CR:
749: port = VP_PORT(instruction);
750: outb(port, 0xFF & reg[VP_REG2(instruction)]);
751: break;
752:
753: case VP_OUTB_CC:
754: port = VP_PORT(instruction);
755: outb(port, 0xFF & immediate);
756: break;
757:
758: case VP_INW_CR:
759: port = VP_PORT(instruction);
760: reg[VP_REG2(instruction)] = 0xFFFF & inw(port);
761: break;
762:
763: case VP_OUTW_CR:
764: port = VP_PORT(instruction);
765: outw(port, 0xFFFF & reg[VP_REG2(instruction)]);
766: break;
767:
768: case VP_OUTW_CC:
769: port = VP_PORT(instruction);
770: outw(port, 0xFFFF & immediate);
771: break;
772:
773: case VP_CALL:
774: [self jumpTo:VP_BRANCH_DEST(instruction) withInitialSRegs:®[8]];
775: break;
776:
777: case VP_RETURN:
778: /* Store the S-registers in the caller's initial S-register set. */
779: if (initialSRegs != 0)
780: memcpy(&initialSRegs[0], ®[8], 8 * sizeof(reg[0]));
781: return self;
782:
783: default:
784: IOLog("%s: Unrecognized opcode: 0x%08x; pc: 0x%x\n", [self name],
785: instruction, pc);
786: return nil;
787: }
788: }
789: }
790:
791: - runVPCode:(unsigned int)entryPoint withRegs:(VPInstruction *)initialRegs
792: {
793: VPInstruction reg[8];
794:
795: if (_vpCode == 0 || _vpCodeCount <= 0) {
796: IOLog("%s: No vpcode to run.\n", [self name]);
797: return nil;
798: }
799: if (entryPoint >= _vpCodeCount) {
800: IOLog("%s: entry point is out of range: 0x%x.\n", [self name],
801: (unsigned)entryPoint);
802: return nil;
803: }
804: if (_vpCode[entryPoint] == 0)
805: return self;
806: if (_debug) {
807: IOLog("%s: Running vpcode at 0x%x\n", [self name],
808: (unsigned)_vpCode[entryPoint]);
809: }
810: if (initialRegs == 0) {
811: memset(reg, 0, sizeof(reg));
812: initialRegs = reg;
813: }
814: return [self jumpTo:_vpCode[entryPoint] withInitialSRegs:initialRegs];
815: }
816:
817: static const char *
818: find_parameter(const char *parameter, const char *string)
819: {
820: int c;
821: size_t length;
822:
823: length = strlen(parameter);
824: while (*string != 0) {
825: if (strncmp(string, parameter, length) == 0) {
826: string += length;
827: while ((c = *string) != '\0' && (c == ' ' || c == '\t'))
828: string++;
829: return (c != 0) ? string : 0;
830: }
831: string++;
832: }
833: return 0;
834: }
835:
836: - getVPCodeFilename:(char *)parameterArray count:(unsigned int *)count
837: {
838: char buffer[256];
839: IOConfigTable *configTable;
840: const char *s, *displayMode, *color, *filename;
841: int width, height, refreshRate, length;
842:
843: /* Get the string describing the display mode. */
844: configTable = [[self deviceDescription] configTable];
845: if (configTable == nil)
846: return nil;
847:
848: displayMode = [configTable valueForStringKey:"Display Mode"];
849:
850: s = find_parameter("Width:", displayMode);
851: if (s == 0)
852: return nil;
853: width = strtol(s, 0, 10);
854:
855: s = find_parameter("Height:", displayMode);
856: if (s == 0)
857: return nil;
858: height = strtol(s, 0, 10);
859:
860: s = find_parameter("Refresh:", displayMode);
861: if (s == 0)
862: return nil;
863: refreshRate = strtol(s, 0, 10);
864:
865: s = find_parameter("ColorSpace:", displayMode);
866: if (s == 0)
867: return nil;
868: if (strncmp(s, "BW:2", 4) == 0) {
869: color = "BW:2";
870: } else if (strncmp(s, "BW:8", 4) == 0) {
871: color = "BW:8";
872: } else if (strncmp(s, "RGB:444/16", 10) == 0) {
873: color = "RGB:444/16";
874: } else if (strncmp(s, "RGB:555/16", 10) == 0) {
875: color = "RGB:555/16";
876: } else if (strncmp(s, "RGB:888/32", 10) == 0) {
877: color = "RGB:888/32";
878: } else {
879: return nil;
880: }
881: sprintf(buffer, "[%d x %d x %s @ %d]", width, height, color, refreshRate);
882:
883: if (_debug)
884: IOLog("%s: Searching for key `%s'.\n", [self name], buffer);
885:
886: filename = [configTable valueForStringKey:buffer];
887: if (filename == 0)
888: return nil;
889: length = strlen(filename) + 1;
890: if (*count < length)
891: return nil;
892:
893: if (_debug)
894: IOLog("%s: Using vpcode from `%s'.\n", [self name], filename);
895: *count = length;
896: strcpy(parameterArray, filename);
897: return self;
898: }
899:
900: - (IOReturn)getCharValues:(unsigned char *)parameterArray
901: forParameter:(IOParameterName)parameterName
902: count:(unsigned int *)count
903: {
904: if (_debug)
905: IOLog("%s: received parameter `%s'.\n", [self name], parameterName);
906:
907: if (strcmp(parameterName, VP_GET_VPCODE_FILENAME) == 0) {
908: if (![self getVPCodeFilename:parameterArray count:count])
909: return IO_R_UNSUPPORTED;
910: return IO_R_SUCCESS;
911: } else {
912: return [super getCharValues:parameterArray
913: forParameter:parameterName
914: count:count];
915: }
916: }
917:
918: /* Set parameters for the display object.
919: */
920: - (IOReturn)setIntValues:(unsigned *)parameterArray
921: forParameter:(IOParameterName)parameterName
922: count:(unsigned int)count
923: {
924: if (strcmp(parameterName, VP_SET_VPCODE_SIZE) == 0) {
925: if (count != 1)
926: return IO_R_INVALID_ARG;
927: if (_vpCode != 0)
928: IOFree(_vpCode, _vpCodeCount * sizeof(_vpCode[0]));
929: _vpCodeCount = parameterArray[0];
930: _vpCodeReceived = 0;
931: _vpCode = IOMalloc(_vpCodeCount * sizeof(_vpCode[0]));
932: if (_vpCode == 0)
933: return IO_R_NO_MEMORY;
934: IOLog("About to receive %d bytes of VPCode!\n", _vpCodeCount);
935: return IO_R_SUCCESS;
936:
937: } else if (strcmp(parameterName, VP_SET_VPCODE) == 0) {
938: if (_vpCode == 0)
939: return IO_R_NO_MEMORY;
940: if (_vpCodeReceived + count > _vpCodeCount)
941: return IO_R_INVALID_ARG;
942: memcpy(&_vpCode[_vpCodeReceived], parameterArray,
943: count * sizeof(_vpCode[0]));
944: _vpCodeReceived += count;
945: IOLog("Received %d bytes of VPCode!\n", count);
946: return IO_R_SUCCESS;
947:
948: } else if (strcmp(parameterName, VP_END_VPCODE) == 0) {
949: if (![self getDisplayInfo])
950: return IO_R_UNSUPPORTED;
951: return IO_R_SUCCESS;
952: } else {
953: return [super setIntValues:parameterArray
954: forParameter:parameterName
955: count:count];
956: }
957: }
958: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.