|
|
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:
25: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
26: *
27: * VGAConsole.c - VGA Mode 0x12 console implementation.
28: *
29: *
30: * HISTORY
31: * 02 Feb 93 Peter Graffagnino
32: * Created from FBConsole.c
33: */
34:
35: //
36: // Notes:
37: // * Considerations for supporting other VGA modes:
38: // This code uses off screen memory for the save behind area. This
39: // permits the use of write mode 1 to save the data resulting in
40: // a flicker-free restore, and makes the coding somewhat simpler. Care
41: // should be taken that there is enough memory there in other modes,
42: // or allocated storage.
43: //
44: // Since mode 12 fits comfortably in 64K/plane, no bank switching is
45: // currently done in this code. Higher res modes will need this.
46: //
47: // * This module implements the console functionality required by the
48: // ConsoleSupport protocol.
49: // * To find things that need to be fixed, search for FIX, to find questions
50: // to be resolved, search for ASK, to find stuff that still needs to be
51: // done, search for TO DO.
52:
53: #import <sys/syslog.h>
54: #import <bsd/dev/i386/VGAConsole.h>
55: #import <bsd/dev/i386/VGAConsPriv.h>
56: #import <driverkit/i386/displayRegisters.h>
57: #import <architecture/ascii_codes.h>
58:
59: #define NIL (0)
60:
61: #if defined(NX_CURRENT_COMPILER_RELEASE) && (NX_CURRENT_COMPILER_RELEASE < 320)
62: #define SIREG "e"
63: #else
64: #define SIREG "S"
65: #endif
66:
67: /* Window margins */
68: #define BG_MARGIN 2 // pixels of background to leave as margin
69: #define FG_MARGIN 1 // pixels of foreground to leave as margin
70: #define TOTAL_MARGIN (BG_MARGIN + FG_MARGIN)
71:
72: #define SVGA_SAVE_BITS (2 * SVGA_ROWBYTES * SVGA_HEIGHT)
73:
74: /*
75: * Ansi sequence state.
76: */
77: typedef enum {
78: AS_NORMAL,
79: AS_ESCAPE,
80: AS_BRACKET,
81: AS_R
82: } ansi_state_t;
83:
84: #define ANSI_STACK_SIZE 3
85: #define ANSI_STACK_MAX 2
86:
87: typedef struct _t_VGARegisters {
88: unsigned char GC[VGA_NUM_GC_REGS];
89: unsigned char SEQ[VGA_NUM_SEQ_REGS];
90: } VGARegisters;
91:
92: typedef struct _t_Console {
93: ScreenMode window_type;
94:
95: IODisplayInfo display;
96:
97: //
98: // The remaining fields are window parameters. These are only
99: // meaningful for text-type windows (window_type == SCM_TEXT or
100: // SCM_ALERT).
101: //
102:
103: //
104: // Current window origin in pixels, relative to origin of screen.
105: //
106: int window_origin_x;
107: int window_origin_y;
108:
109: //
110: // Window size information, in pixels and in characters.
111: //
112: int chars_per_row;
113: int pixels_per_row;
114: int chars_per_column;
115: int pixels_per_column;
116:
117: //
118: // Cursor location, in characters. Origin is top
119: // left corner of window = {0,0}.
120: //
121: int curr_row; // in characters
122: int curr_column; // in characters
123:
124: //
125: // Misc. video parameters. The background and foreground fields
126: // are slightly dependent on the hardware implementation; they'll
127: // work as long as bits per pixel <= 32.
128: //
129: unsigned int baseground; // bits for base color
130: unsigned int background; // bits for background pixel
131: unsigned int foreground; // bits for foreground pixel
132: unsigned int dark_grey; // bits for dark grey
133: unsigned int light_grey; // bits for light grey
134: boolean_t has_title;
135:
136: //
137: // Storage for saved region under an alert panel.
138: //
139: unsigned char *saveBits;
140: int saveHeight;
141: int saveRowBytes;
142: int saveBytes;
143: unsigned char *saveLocation;
144: VGARegisters savedRegisters; // save for Restore
145: VGARegisters tempRegisters; // save between operations
146:
147: ansi_state_t ansi_state; // track ansi escape sequence state
148: u_char ansi_stack[ANSI_STACK_SIZE];
149: u_char *ansi_stack_p;
150:
151: boolean_t isSVGA; // use SVGA methods
152: } ConsoleRep, *ConsolePtr;
153:
154: #define PLANE_MASK 0x0F // By default, use all planes
155: #define PIXEL_MASK 0xFF // By default, all pixels
156: #define RW_MODE 0x00 // Default VGA read/write mode
157:
158: //
159: // BEGIN: Private utility routines
160: //
161:
162: static inline int isTextMode(ConsolePtr console)
163: {
164: return ((console->window_type == SCM_TEXT) ||
165: (console->window_type == SCM_ALERT));
166: }
167:
168: static void SwapForegroundAndBackground(ConsolePtr console)
169: {
170: int temp_color;
171:
172: temp_color = console->foreground;
173: console->foreground = console->background;
174: console->background = temp_color;
175: }
176:
177: static inline int rread(int port, int index)
178: {
179: outb(port, index);
180: return(inb(port + 1));
181: }
182:
183:
184: static inline void SaveVGARegs(VGARegisters *saved)
185: {
186: int i;
187:
188: for (i = 0; i < VGA_NUM_GC_REGS; i++)
189: saved->GC[i] = rread(VGA_GC_ADDR,i);
190: #if defined(SAVE_ALL_SEQ_REGS)
191: for (i = 0; i < VGA_NUM_SEQ_REGS; i++)
192: saved->SEQ[i] = rread(VGA_SEQ_ADDR,i);
193: #else /* defined(SAVE_ALL_SEQ_REGS) */
194: saved->SEQ[2] = rread(VGA_SEQ_ADDR,2);
195: #endif /* defined(SAVE_ALL_SEQ_REGS) */
196: }
197:
198: static inline void RestoreVGARegs(VGARegisters *saved)
199: {
200: int i;
201:
202: for (i = 0; i < VGA_NUM_GC_REGS; i++)
203: IOWriteRegister(VGA_GC_ADDR,i, saved->GC[i]);
204: #if defined(SAVE_ALL_SEQ_REGS)
205: for (i = 0; i < VGA_NUM_SEQ_REGS; i++)
206: IOWriteRegister(VGA_SEQ_ADDR,i, saved->SEQ[i]);
207: #else /* defined(SAVE_ALL_SEQ_REGS) */
208: IOWriteRegister(VGA_SEQ_ADDR, 2, saved->SEQ[2]);
209: #endif /* defined(SAVE_ALL_SEQ_REGS) */
210: }
211:
212: static void FlipCursor(ConsolePtr console)
213: // Description: Turn cursor on/off. This just inverts every pixel at the
214: // character at (curr_rown, curr_column).
215: {
216:
217: int y;
218: // Screen-relative pixel coordinates of bounds of current character.
219: int start_y = console->window_origin_y +
220: console->curr_row * CHAR_H;
221: int end_y = start_y + CHAR_H;
222: int start_x = console->window_origin_x +
223: console->curr_column * CHAR_W;
224: unsigned char *cp;
225: volatile char mask;
226:
227: IOWriteRegister(VGA_GC_ADDR, 7, 0x0f); /* enable cdc planes */
228: IOWriteRegister(VGA_GC_ADDR, 5, 0x08); /* set read mode 1 */
229: IOWriteRegister(VGA_GC_ADDR, 2, console->background); /* setup color compare */
230: cp = (unsigned char *)console->display.frameBuffer +
231: start_y*console->display.rowBytes + (start_x >> 3);
232: for (y=start_y; y < end_y; y++) {
233: mask = *cp;
234: IOWriteRegister(VGA_GC_ADDR, 0, console->background); /* set color */
235: IOWriteRegister(VGA_GC_ADDR, 8, ~mask); /* set pixel mask */
236: *cp = 0xff;
237: IOWriteRegister(VGA_GC_ADDR, 0, console->foreground); /* set color */
238: IOWriteRegister(VGA_GC_ADDR, 8, mask); /* set pixel mask */
239: mask = *cp;
240: *cp = 0xff;
241: cp += console->display.rowBytes;
242: }
243:
244: IOWriteRegister(VGA_GC_ADDR, 5, RW_MODE); /* set read mode 0 */
245: IOWriteRegister(VGA_GC_ADDR, 8, PIXEL_MASK); /* set pixel mask */
246:
247: }
248:
249: /*
250: * Bank switching is currently not supported.
251: */
252:
253: static inline char SVGASegmentForAddress(register void *addr)
254: {
255: #if NOTYET
256: register char segment;
257: register int offset;
258:
259: offset = ((int)addr) - ((int)SVGA_FRAMEBUFFER_ADDRESS);
260: segment = offset % SVGABANKBYTES;
261: return(segment);
262: #else NOTYET
263: return 0;
264: #endif NOTYET
265: }
266:
267: static inline void SVGASelectSegment(char segment)
268: {
269: #if NOTYET
270: outb(VGA_GCR_SEGS, segment << 4 | segment);
271: #endif NOTYET
272: }
273:
274: static inline void SVGASelectSegmentForAddressIfNecessary(
275: unsigned char *addr,
276: char *currentSegmentPtr
277: )
278: {
279: #if NOTYET
280: char segment;
281:
282: segment = SVGASegmentForAddress(addr);
283:
284: if (segment != *currentSegmentPtr) {
285: SVGASelectSegment(segment);
286: *currentSegmentPtr = segment;
287: }
288: #endif NOTYET
289: }
290:
291:
292: static unsigned char leftMaskArray[] =
293: {0xff, 0x7f, 0x3f, 0x1f, 0xf, 0x7, 0x3, 0x1};
294:
295: static unsigned char rightMaskArray[] =
296: {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
297:
298:
299:
300: static void rect(ConsolePtr console, int x, int y, int w, int h, int c)
301: {
302: int first_byte, last_byte;
303: unsigned char lmask, rmask;
304: int k, midcnt;
305: int x2 = x + w;
306: volatile unsigned char *rowptr;
307: int rowBytes = console->display.rowBytes;
308:
309: IOWriteRegister(VGA_GC_ADDR, 0, c); /* set color */
310: outb(VGA_GC_ADDR, 8); /* point to pixel mask reg */
311: first_byte = x >> 3;
312: last_byte = x2 >> 3;
313: lmask = leftMaskArray[x & 7];
314: rmask = rightMaskArray[x2 & 7];
315:
316: rowptr = (unsigned char *)console->display.frameBuffer +
317: y*rowBytes + first_byte;
318:
319: midcnt = last_byte - first_byte - 1;
320: if (midcnt == -1) { /* i.e. first_word == last_word */
321: outb(VGA_GC_ADDR + 1, rmask & lmask);
322: for(; --h >= 0;rowptr += rowBytes) {
323: volatile char forceReadByte = *rowptr;
324: *rowptr = 0xff;
325: }
326: } else {
327: for(; --h >= 0; rowptr += rowBytes) {
328: volatile unsigned char *p = rowptr;
329: volatile char foo = *p;
330: outb(VGA_GC_ADDR + 1, lmask);
331: *p++ = 0xff;
332: outb(VGA_GC_ADDR + 1, 0xff);
333: for(k = midcnt; --k >= 0;)
334: *p++ = 0xff; // no need to latch data.
335: outb(VGA_GC_ADDR + 1, rmask);
336: foo = *p;
337: *p = 0xff;
338: }
339: }
340: outb(VGA_GC_ADDR + 1, PIXEL_MASK);
341:
342: }
343:
344:
345: static void ClearWindow(ConsolePtr console)
346: // Description: Set contents of entire current window to background.
347: // Preconditions:
348: // * Cursor is off on entry and will remain so on exit.
349: {
350: rect(console, console->window_origin_x, console->window_origin_y,
351: console->pixels_per_row, console->pixels_per_column,
352: console->background);
353: }
354:
355: static void WipeScreen(ConsolePtr console, const unsigned pixel)
356: // Description: Fill the screen with specific pixel value.
357: {
358: rect(console, 0, 0, console->display.totalWidth,
359: console->display.height, pixel);
360: }
361:
362: static void ClearToEOL(ConsolePtr console)
363: // Description: Clear to end of line (within window), including current pos.
364: // Preconditions:
365: // * Cursor is 'off' on entry and will remain so on exit.
366: {
367: unsigned pixel_count;
368: int starting_x; // window-relative 'x' coordinate
369: int y;
370:
371: starting_x = console->window_origin_x +
372: (console->curr_column * CHAR_W);
373: y = console->window_origin_y + (console->curr_row * CHAR_H);
374:
375: pixel_count = console->pixels_per_row -
376: (starting_x - console->window_origin_x);
377:
378: rect(console, starting_x, y, pixel_count, CHAR_H , console->background);
379:
380: }
381:
382: static void Erase(ConsolePtr console)
383: // Description: Erase current cursor location.
384: {
385: // Screen-relative pixel coordinates of bounds of current character.
386: int start_y = console->window_origin_y +
387: console->curr_row * CHAR_H;
388: int start_x = console->window_origin_x +
389: console->curr_column * CHAR_W;
390:
391: rect(console, start_x, start_y, CHAR_W, CHAR_H, console->background);
392: }
393:
394: #define ENCODEBASE ' '
395:
396: static void BltChar(ConsolePtr console, const char c)
397: // Description: Paint one character at (curr_column, curr_row).
398: {
399: unsigned char *glyphbase; // the glyph we're rendering
400: int x,y; // location of upper left corner of glyph
401: int source_y;
402: volatile int tmp;
403: unsigned char *cp;
404:
405: // Erase current contents of {curr_row, curr_column}.
406: Erase(console);
407:
408: // Skip non-printing characters.
409: if (c < ENCODEBASE) {
410: return;
411: }
412:
413: glyphbase = ohlfs12[c - ENCODEBASE];
414: x = console->window_origin_x + console->curr_column * CHAR_W;
415: y = console->window_origin_y + console->curr_row * CHAR_H;
416:
417: IOWriteRegister(VGA_GC_ADDR, 0, console->foreground);/* set color */
418: cp = (unsigned char *)console->display.frameBuffer +
419: y*console->display.rowBytes + (x >> 3);
420: outb(VGA_GC_ADDR, 8); /* point to pixel mask reg */
421:
422: for (source_y = CHAR_H; source_y != 0; source_y--) {
423: outb(VGA_GC_ADDR + 1, *glyphbase++);
424: tmp = *cp;
425: *cp = 0xff;
426: cp += console->display.rowBytes;
427: }
428: outb(VGA_GC_ADDR + 1, PIXEL_MASK); /* restore to default */
429:
430: console->curr_column++;
431: return;
432: }
433:
434: /*
435: * Use bytemove as opposed to memmove. 32bit bus cycles seem to confuse
436: * the VGA.
437: */
438: static inline void bytemove(char *dst, char *src, int cnt)
439: {
440: #if DONT_USE_ASM
441: while(cnt--)
442: *dst++ = *src++;
443: #else DONT_USE_ASM
444: asm("rep; movsb"
445: : /* no outputs */
446: : "&c" (cnt), "D" (dst), SIREG (src)
447: : "ecx", "esi", "edi");
448: #endif DONT_USE_ASM
449: }
450:
451: static void FBPutC(ConsolePtr console, char c)
452: // Write one character to screen. Cursor is 'on' on entry and exit.
453: {
454: int repeat;
455: int i;
456:
457: if (!isTextMode(console))
458: return;
459:
460: /*
461: * First deal with ANSI escape sequences.
462: * This is a very bizarre implementation, copied from the m68k
463: * version.
464: */
465: switch(console->ansi_state) {
466: case AS_NORMAL:
467: if(c == esc) {
468: console->ansi_state = AS_ESCAPE;
469: return;
470: }
471: else {
472: break; // continue
473: }
474:
475: case AS_ESCAPE:
476: switch(c) {
477: case '[':
478: console->ansi_state = AS_BRACKET;
479: return;
480: default:
481: console->ansi_state = AS_NORMAL;
482: break; // continue
483: }
484:
485: case AS_BRACKET:
486: if(c >= '0' && c <= '9') {
487: *console->ansi_stack_p =
488: *console->ansi_stack_p * 10 + (c - '0');
489: return;
490: }
491: else if (c == ';') {
492: if(console->ansi_stack_p <
493: &console->ansi_stack[ANSI_STACK_MAX]) {
494: console->ansi_stack_p++;
495: }
496: return;
497: }
498: else {
499: for(i=0; i<ANSI_STACK_SIZE; i++) {
500: if (console->ansi_stack[i] == 0) {
501: console->ansi_stack[i] = 1;
502: }
503: }
504: repeat = *console->ansi_stack_p;
505: FlipCursor(console); // cursor off
506: switch (c) {
507:
508: case 'A':
509: while (repeat--) {
510: if(console->curr_row) {
511: console->curr_row--;
512: }
513: }
514: break;
515:
516: case 'B':
517: while (repeat--) {
518: console->curr_row++;
519: }
520: break;
521:
522: case 'C': // non destructive space
523: while (repeat--) {
524: console->curr_column++;
525: }
526: break;
527:
528: case 'D': // not in termcap
529: while (repeat--) {
530: if(console->curr_column) {
531: console->curr_column--;
532: }
533: }
534: break;
535:
536: case 'E': // not in termcap
537: console->curr_column = 0;
538: while (repeat--) {
539: console->curr_row++;
540: }
541: break;
542:
543: case 'H': // should be home
544: case 'f': // not in termcap
545: console->curr_column =
546: *console->ansi_stack_p - 1;
547: console->ansi_stack_p--;
548: console->curr_row =
549: *console->ansi_stack_p - 1;
550: console->ansi_stack_p--;
551: break;
552:
553: case 'K':
554: ClearToEOL(console);
555: break;
556:
557: case 'm': /* FIXME */
558: console->ansi_stack_p--;
559: console->ansi_stack_p--;
560:
561: /* prevent washout */
562: if(console->background ==
563: console->foreground) {
564: console->background = VGA_WHITE;
565: console->foreground = VGA_BLACK;
566: }
567: break;
568: }
569: }
570: console->ansi_stack_p = &console->ansi_stack[1];
571: for(i=0; i<ANSI_STACK_SIZE; i++)
572: console->ansi_stack[i] = 0;
573: console->ansi_state = AS_NORMAL;
574: goto proceed;
575: case AS_R:
576: // FIXME
577: break;
578: }
579:
580: FlipCursor(console); // cursor off
581: switch(c) {
582: case '\r': // Carriage return
583: console->curr_column = 0;
584: break;
585:
586: case '\n': // line feed
587: console->curr_column = 0;
588: console->curr_row++;
589: break;
590:
591: case '\b': // backspace
592: if (console->curr_column == 0)
593: break;
594: console->curr_column--;
595: break;
596:
597: case '\t':
598: // tab. Erase all characters up to and including the
599: // next tab stop.
600: {
601: int col, num_cols;
602:
603: num_cols = TAB_SIZE - (console->curr_column % TAB_SIZE);
604: FlipCursor(console); // cursor on
605: for (col = 0; col<num_cols; col++) {
606: FBPutC(console, ' '); // cursor on at return
607: }
608: FlipCursor(console); // cursor off
609: break;
610: }
611:
612: case np: // aka ff, form feed
613: console->curr_row = console->curr_column = 0;
614: ClearWindow(console);
615: break;
616:
617: case del:
618: console->curr_column++;
619: break;
620:
621: default:
622: // Normal case.
623: BltChar(console, c);
624: break;
625: }
626:
627: // Cursor is off.
628: proceed:
629: if (console->curr_column >= console->chars_per_row) {
630: // End-of-line wrap.
631: console->curr_column = 0;
632: console->curr_row++;
633: }
634:
635: if (console->curr_row >= console->chars_per_column) {
636: //
637: // Screen scroll. Copy the whole window down in memory
638: // (pixels_per_row * CHAR_H) pixels, starting at
639: // the first character in row 1.
640: //
641: unsigned char *src;
642: unsigned char *dst;
643: int source_y;
644:
645: console->curr_row = console->chars_per_column - 1;
646:
647: /*
648: * for screen-to-screen scrolling in graphics mode, we use
649: * write mode 1, and pretend its a 1 bit display. We also
650: * exploit the fact the the scrolling area begins and ends
651: * on a 0 mod 8 pixel address.
652: */
653:
654: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x1); /* write mode 1 */
655: src = (unsigned char *)console->display.frameBuffer +
656: (console->window_origin_y + CHAR_H)*console->display.rowBytes +
657: (console->window_origin_x >> 3);
658: dst = src - CHAR_H*console->display.rowBytes;
659: for (source_y = CHAR_H; // top, row 1
660: source_y < console->pixels_per_column; // bottom
661: source_y++) {
662:
663: bytemove(dst, src, console->pixels_per_row>>3);
664: src += console->display.rowBytes;
665: dst += console->display.rowBytes;
666: }
667: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0); // restore write mode
668:
669: console->curr_column = 0;
670: ClearToEOL(console);
671: }
672:
673: // Cursor back on.
674: FlipCursor(console);
675: }
676:
677: static void SetTitle(ConsolePtr console, const char *title)
678: // Description: Draw title bar if none exists, write specified title into it.
679: // Drawing a title bar involves snarfing up row 0 of the window
680: // and decreasing the usable size of the window by one row.
681: // Preconditions:
682: // * Cursor is 'on' on entry and will remain so on exit.
683: {
684: int saved_curr_row = console->curr_row;
685: int saved_curr_column = console->curr_column;
686: int saved_origin_y;
687: int title_len = strlen(title);
688: int pixel_num;
689:
690: if ((title_len == 0) || (title_len > console->chars_per_row)) {
691: IOLog("console: Illegal title length (%d)\n", title_len);
692: return;
693: }
694: FlipCursor(console); // old cursor off
695: if (console->has_title) {
696: // First grow window by two rows - this absorbs the existing
697: // title bar.
698: console->window_origin_y -= CHAR_H * 2;
699: console->chars_per_column += 2;
700: console->pixels_per_column += CHAR_H * 2;
701: saved_curr_row += 2;
702: }
703:
704: // Clear row 0, center new title in it.
705: console->curr_row = 0;
706: rect(console,
707: console->window_origin_x,
708: console->window_origin_y,
709: CHAR_W * console->chars_per_row,
710: CHAR_H * 2 - BG_MARGIN,
711: console->foreground);
712: saved_origin_y = console->window_origin_y;
713: console->window_origin_y += CHAR_H / 2;
714: console->curr_column = (console->chars_per_row - title_len) / 2;
715: FlipCursor(console); // new cursor on
716: SwapForegroundAndBackground(console);
717: while (*title) {
718: FBPutC(console, *title++);
719: }
720: SwapForegroundAndBackground(console);
721: FlipCursor(console); // new cursor off
722: console->window_origin_y = saved_origin_y;
723:
724: // Draw grey lines one pixel away from border of title bar.
725: // Origin is currently at first pixel in top line of title bar.
726:
727: rect(console, // inside top
728: console->window_origin_x - BG_MARGIN,
729: console->window_origin_y - BG_MARGIN,
730: console->pixels_per_row + (BG_MARGIN * 2),
731: BG_MARGIN,
732: console->light_grey);
733: rect(console, // inside bottom
734: console->window_origin_x - BG_MARGIN,
735: console->window_origin_y + CHAR_H * 2 - TOTAL_MARGIN - BG_MARGIN,
736: console->pixels_per_row + BG_MARGIN * 2,
737: BG_MARGIN,
738: console->dark_grey);
739: for (pixel_num = 0; pixel_num < BG_MARGIN; pixel_num++) {
740: rect(console, // left
741: console->window_origin_x - BG_MARGIN + pixel_num,
742: console->window_origin_y - BG_MARGIN + pixel_num,
743: 1,
744: CHAR_H * 2 - 1 - (pixel_num * 2),
745: console->light_grey);
746: }
747: for (pixel_num = 1; pixel_num <= BG_MARGIN; pixel_num++) {
748: rect(console, // right
749: console->window_origin_x + console->pixels_per_row + pixel_num - 1,
750: console->window_origin_y - pixel_num,
751: 1,
752: CHAR_H * 2 - 1 - (BG_MARGIN - pixel_num) * 2,
753: console->dark_grey);
754: }
755: rect(console, // outside bottom
756: console->window_origin_x - TOTAL_MARGIN,
757: console->window_origin_y + CHAR_H * 2 - FG_MARGIN - BG_MARGIN,
758: console->pixels_per_row + TOTAL_MARGIN * 2,
759: FG_MARGIN,
760: console->foreground);
761:
762: // Diminish window size by two rows.
763: console->window_origin_y += CHAR_H * 2;
764: console->chars_per_column -= 2;
765: console->pixels_per_column -= CHAR_H * 2;
766:
767:
768: // Restore old cursor. Careful, the y axis just changed...
769: console->curr_column = saved_curr_column;
770: if (saved_curr_row > 0) {
771: console->curr_row = saved_curr_row - 2;
772: }
773: else {
774: // New row 0 - clear it.
775: ClearToEOL(console);
776: }
777: FlipCursor(console); // old cursor on
778: console->has_title = TRUE;
779: }
780:
781: static void UpdateWindowChars(ConsolePtr console)
782: // Description: Calculate window size in characters. Used when either window
783: // size or font changes.
784: {
785: console->chars_per_row = console->pixels_per_row / CHAR_W;
786: console->chars_per_column =
787: console->pixels_per_column / CHAR_H;
788: }
789:
790:
791: static void InitWindow(ConsolePtr console,
792: int width,
793: int height,
794: const char *title,
795: boolean_t initWindow,
796: boolean_t saveUnder)
797: // Description: Initialize window parameters. If initWindow is TRUE, an empty
798: // window is drawn in the screen, else we assume that a window
799: // already exists. Screen and font parameters must be valid on
800: // entry.
801: {
802:
803: // Truncate specified size to integral mutliple of character size
804: // in both dimensions.
805: width /= CHAR_W; // now in chars
806: height /= CHAR_H;
807: width *= CHAR_W; // now in pixels
808: height *= CHAR_H;
809:
810: // Ensure there's enough room for a border.
811: if (width > (console->display.width - TOTAL_MARGIN * 2))
812: width = console->display.width - TOTAL_MARGIN * 2;
813: if (height > (console->display.height - TOTAL_MARGIN * 2))
814: height = console->display.height - TOTAL_MARGIN * 2;
815:
816: //
817: // Init console window variables. The window is centered in the
818: // screen, minus a pixel or two to guarantee double word alignment
819: // for the first pixel of a row (until further developments...when
820: // we do alert panels, we can enumerate some cases here...).
821: //
822: console->window_origin_x = (console->display.width - width) / 2;
823: console->window_origin_y = (console->display.height - height) / 2;
824: console->pixels_per_row = width;
825: console->pixels_per_column = height;
826: (unsigned)console->window_origin_x &= ~0x07;
827:
828: UpdateWindowChars(console);
829:
830: console->curr_column = 0;
831: console->has_title = FALSE;
832:
833: if (initWindow) {
834: // Before we start drawing anything, save under if needed
835: if (saveUnder) {
836: int i;
837: unsigned char *save, *sp;
838: /*
839: * in saveUnder mode, we take care to preserve the VGA
840: * state we'll mess with during console operations. This
841: * consists of the 9 graphics controller registers
842: * and 5 sequencer registers in the VGA.
843: * We already did this in Init().
844: */
845:
846: /*
847: * load a default set of registers for mode 12
848: */
849: for(i = 0; i < VGA_NUM_GC_REGS; i++)
850: IOWriteRegister(VGA_GC_ADDR,i, defaultGCRegisters[i]);
851:
852: if (console->isSVGA) {
853: char currentSegment = 0;
854:
855: SaveVGARegs(&console->tempRegisters);
856: /*
857: * for SVGA, we use read mode 0 and copy the data to
858: * a global array, not off-screen display memory as with VGA
859: * mode 0x12.
860: */
861: console->saveHeight = height + TOTAL_MARGIN * 2;
862: console->saveRowBytes = width/8 + ((TOTAL_MARGIN + 7) / 8) * 2;
863: console->saveBytes = console->saveHeight*console->saveRowBytes;
864: /* saveBits was allocated when we allocated the console */
865: save = console->saveBits;
866:
867: // Read mode 0
868: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x8, 0x0);
869:
870: // Copy the window contents into the save under.
871:
872: // Plane 0.
873: IOReadModifyWriteRegister(VGA_GC_ADDR, 4, ~0x3, 0x0);
874:
875: sp = console->saveLocation =
876: (unsigned char *)console->display.frameBuffer +
877: (console->window_origin_y - TOTAL_MARGIN) *
878: console->display.rowBytes +
879: (console->window_origin_x>>3) - 1;
880: SVGASelectSegment(currentSegment);
881: for (i = console->saveHeight; i != 0; i--) {
882: SVGASelectSegmentForAddressIfNecessary(sp,
883: ¤tSegment);
884: bytemove(save, sp, console->saveRowBytes);
885: sp += console->display.rowBytes;
886: save += console->saveRowBytes;
887: }
888:
889: // Plane 1.
890: IOReadModifyWriteRegister(VGA_GC_ADDR, 4, ~0x3, 0x1);
891: sp = console->saveLocation =
892: (unsigned char *)console->display.frameBuffer +
893: (console->window_origin_y - TOTAL_MARGIN) *
894: console->display.rowBytes +
895: (console->window_origin_x>>3) - 1;
896: for (i = console->saveHeight; i != 0; i--) {
897: SVGASelectSegmentForAddressIfNecessary(sp,
898: ¤tSegment);
899: bytemove(save, sp, console->saveRowBytes);
900: sp += console->display.rowBytes;
901: save += console->saveRowBytes;
902: }
903: SVGASelectSegment(currentSegment = 0);
904: // restore wr. mode
905: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0);
906:
907: RestoreVGARegs(&console->tempRegisters);
908: } else {
909: /*
910: * for vga, we use write mode 1 and copy the data to
911: * off-screen memory. We save and extra byte on either side
912: * of the popup.
913: */
914: console->saveHeight = height + TOTAL_MARGIN * 2;
915: console->saveRowBytes = width/8 + ((TOTAL_MARGIN + 7) / 8) * 2;
916: console->saveBytes = console->saveHeight*console->saveRowBytes;
917: save = console->saveBits;
918:
919: sp = console->saveLocation =
920: (unsigned char *)console->display.frameBuffer +
921: (console->window_origin_y - TOTAL_MARGIN) *
922: console->display.rowBytes +
923: (console->window_origin_x>>3) - 1;
924:
925: // Copy the window contents into the save under
926: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x1); /* write mode 1 */
927: for (i = console->saveHeight; i != 0; i--) {
928: bytemove(save, sp, console->saveRowBytes);
929: sp += console->display.rowBytes;
930: save += console->saveRowBytes;
931: }
932: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0); /* restore wr. mode*/
933: }
934: }
935:
936: // New window - cursor at origin.
937: console->curr_row = 0;
938: console->has_title = FALSE;
939:
940: // Draw the border. The border goes outside of the specified
941: // window. Outside lines are black; inside lines are
942: // half-tone.
943:
944: rect(console, // outside top
945: console->window_origin_x - TOTAL_MARGIN,
946: console->window_origin_y - TOTAL_MARGIN,
947: width + TOTAL_MARGIN * 2,
948: FG_MARGIN,
949: console->foreground);
950: rect(console, // inside top
951: console->window_origin_x - BG_MARGIN,
952: console->window_origin_y - BG_MARGIN,
953: width + BG_MARGIN * 2,
954: BG_MARGIN,
955: console->background);
956: rect(console, // inside bottom
957: console->window_origin_x - BG_MARGIN,
958: console->window_origin_y + height,
959: width + BG_MARGIN * 2,
960: BG_MARGIN,
961: console->background);
962: rect(console, // outside bottom
963: console->window_origin_x - TOTAL_MARGIN,
964: console->window_origin_y + height + BG_MARGIN,
965: width + TOTAL_MARGIN * 2,
966: FG_MARGIN,
967: console->foreground);
968: rect(console, // outside left
969: console->window_origin_x - TOTAL_MARGIN,
970: console->window_origin_y - TOTAL_MARGIN,
971: FG_MARGIN,
972: height + TOTAL_MARGIN * 2,
973: console->foreground);
974: rect(console, // inside left
975: console->window_origin_x - BG_MARGIN,
976: console->window_origin_y - BG_MARGIN,
977: BG_MARGIN,
978: height + BG_MARGIN * 2,
979: console->background);
980: rect(console, // inside right
981: console->window_origin_x + width,
982: console->window_origin_y - BG_MARGIN,
983: BG_MARGIN,
984: height + BG_MARGIN * 2,
985: console->background);
986: rect(console, // outside right
987: console->window_origin_x + width + BG_MARGIN,
988: console->window_origin_y - TOTAL_MARGIN,
989: FG_MARGIN,
990: height + TOTAL_MARGIN * 2,
991: console->foreground);
992:
993: // Clear the contents of the window and draw a cursor.
994: ClearWindow(console);
995: FlipCursor(console); // cursor on
996: SetTitle(console, title);
997: }
998: else {
999: /* Leave current window contents, just updating title.
1000: * We'll do a newline to make sure we have room for
1001: * our font and proceed.Initial cursor will be at
1002: * lower left corner.
1003: */
1004: console->curr_row = console->chars_per_column - 1;
1005: SetTitle(console, title);
1006: FBPutC(console, '\n');
1007: }
1008: return;
1009: }
1010:
1011: //
1012: // END: Private utility routines
1013: //
1014:
1015: //
1016: // BEGIN: Implementation of IOConsoleInfo functions
1017: //
1018: static void Free(IOConsoleInfo *cso)
1019: // Description: Free a FB Console object
1020: {
1021: ConsolePtr console = (ConsolePtr)cso->priv;
1022: if (console->isSVGA)
1023: IOFree(console->saveBits, SVGA_SAVE_BITS);
1024: IOFree(console, sizeof(ConsoleRep));
1025: IOFree(cso, sizeof(IOConsoleInfo));
1026: }
1027:
1028: static void Init(
1029: IOConsoleInfo *cso,
1030: ScreenMode mode,
1031: boolean_t initScreen,
1032: boolean_t initWindow,
1033: const char *title)
1034: {
1035: ConsolePtr console = (ConsolePtr)cso->priv;
1036: int i;
1037:
1038:
1039: console->background = VGA_WHITE;
1040: console->light_grey = VGA_LTGRAY;
1041: console->dark_grey = VGA_DKGRAY;
1042: console->foreground = VGA_BLACK;
1043: console->baseground = console->dark_grey;
1044:
1045: console->ansi_state = AS_NORMAL;
1046: for(i=0; i<ANSI_STACK_SIZE; i++) {
1047: console->ansi_stack[i] = 0;
1048: }
1049: console->ansi_stack_p = &console->ansi_stack[1]; // FIXME - why not 0?
1050:
1051: // Save these for later in case we need them for Restore().
1052: SaveVGARegs(&console->savedRegisters);
1053:
1054: // In case the display is not in the mode we want...
1055: if ((mode == SCM_TEXT || mode == SCM_GRAPHIC) && initScreen)
1056: VGASetGraphicsMode();
1057:
1058: // Set up VGA registers the way we want them.
1059: // Enable all planes in mask register.
1060: IOWriteRegister(VGA_SEQ_ADDR, 2, PLANE_MASK);
1061: for(i = 0; i < VGA_NUM_GC_REGS; i++)
1062: IOWriteRegister(VGA_GC_ADDR,i, defaultGCRegisters[i]);
1063:
1064: console->window_type = mode;
1065:
1066: // Initialize the screen, if appropriate.
1067: if (initScreen && (console->window_type != SCM_ALERT)) {
1068: WipeScreen(console, console->baseground);
1069: }
1070:
1071: switch(console->window_type) {
1072: case SCM_TEXT:
1073: InitWindow(console, TEXT_WIN_WIDTH, TEXT_WIN_HEIGHT,
1074: title, initWindow, 0 /* Don't save under */);
1075: break;
1076: case SCM_ALERT:
1077: InitWindow(console, ALERT_WIN_WIDTH, ALERT_WIN_HEIGHT,
1078: title, initWindow, 1 /* Save under */);
1079: break;
1080: case SCM_GRAPHIC:
1081: /* do nothing */
1082: break;
1083: default:
1084: panic("VGAConsole/VGAInitConsole: can't init");
1085: }
1086: return;
1087: }
1088:
1089: static int Restore(IOConsoleInfo *cso)
1090: {
1091: ConsolePtr console = (ConsolePtr)cso->priv;
1092: unsigned char *save, *dp;
1093: int i;
1094:
1095: if (console->window_type != SCM_ALERT) {
1096: IOLog("VGAConsole: bogus restore, mode %d\n", console->window_type);
1097: return -1;
1098: }
1099:
1100: if (console->isSVGA) {
1101: char currentSegment;
1102:
1103: // Copy save under bits back onto screen
1104: save = console->saveBits;
1105:
1106: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0); /* write mode 0 */
1107: IOWriteRegister(VGA_GC_ADDR, 1, 0x0); /* disable set/reset write */
1108: IOWriteRegister(VGA_GC_ADDR, 8, 0xff); /* set pixel mask */
1109:
1110: // Plane 0.
1111: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x1); /* map mask for plane 0 */
1112: dp = console->saveLocation;
1113: SVGASelectSegment(currentSegment = 0);
1114: for (i = console->saveHeight; i != 0; i--) {
1115: SVGASelectSegmentForAddressIfNecessary(dp, ¤tSegment);
1116: bytemove(dp, save, console->saveRowBytes);
1117: dp += console->display.rowBytes;
1118: save += console->saveRowBytes;
1119: }
1120:
1121: // Plane 1.
1122: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x2); /* map mask for plane 1 */
1123: dp = console->saveLocation;
1124: for (i = console->saveHeight; i != 0; i--) {
1125: SVGASelectSegmentForAddressIfNecessary(dp, ¤tSegment);
1126: bytemove(dp, save, console->saveRowBytes);
1127: dp += console->display.rowBytes;
1128: save += console->saveRowBytes;
1129: }
1130: SVGASelectSegment(currentSegment = 0);
1131:
1132: } else {
1133: // Copy save under bits back onto screen
1134: save = console->saveBits;
1135: dp = console->saveLocation;
1136: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x1); /* write mode 1 */
1137: for (i = console->saveHeight; i != 0; i--) {
1138: bytemove(dp, save, console->saveRowBytes);
1139: dp += console->display.rowBytes;
1140: save += console->saveRowBytes;
1141: }
1142: }
1143:
1144: RestoreVGARegs(&console->savedRegisters);
1145:
1146: console->window_type = SCM_UNINIT;
1147:
1148: return 0;
1149: }
1150:
1151:
1152: static void
1153: vga_write_bpp2packd32_to_bpp4planar(unsigned int *dst, unsigned short *fb)
1154: {
1155: unsigned int i, dstvalue;
1156: unsigned short fbvalue;
1157: unsigned char fblo, fbhi;
1158:
1159: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x02); // select plane 1
1160:
1161: dstvalue = *dst;
1162: i = dstvalue & 0xAAAA;
1163:
1164: fblo = 0xff ^
1165: (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12) |
1166: ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6) |
1167: ((i & 0x0080) >> 3) | ((i & 0x0020) ) |
1168: ((i & 0x0008) << 3) | ((i & 0x0002) << 6));
1169: i = (dstvalue >> 16) & 0xAAAA;
1170: fbhi = 0xff ^
1171: (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12) |
1172: ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6) |
1173: ((i & 0x0080) >> 3) | ((i & 0x0020) ) |
1174: ((i & 0x0008) << 3) | ((i & 0x0002) << 6));
1175: fbvalue = (((unsigned short)fbhi) << 8) | fblo;
1176: *fb = fbvalue;
1177:
1178: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x01); // select plane 0
1179:
1180: dstvalue = *dst;
1181: i = dstvalue & 0x5555;
1182: fblo = 0xff ^
1183: (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11) |
1184: ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5) |
1185: ((i & 0x0040) >> 2) | ((i & 0x0010) << 1) |
1186: ((i & 0x0004) << 4) | ((i & 0x0001) << 7));
1187: i = (dstvalue >> 16) & 0x5555;
1188: fbhi = 0xff ^
1189: (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11) |
1190: ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5) |
1191: ((i & 0x0040) >> 2) | ((i & 0x0010) << 1) |
1192: ((i & 0x0004) << 4) | ((i & 0x0001) << 7));
1193: fbvalue = (((unsigned short)fbhi) << 8) | fblo;
1194: *fb = fbvalue;
1195:
1196: // restore default plane mask
1197: IOWriteRegister(VGA_SEQ_ADDR, 2, PLANE_MASK);
1198: }
1199:
1200:
1201: // VGABlitRect blits a rect onto the VGA mode 0x12 screen.
1202: // No error checking is done. The screen must be in the proper video
1203: // mode, the data must be in 2 bit format, on a 4 pixel boundary, and
1204: // a multiple of 4 pixels wide. Anything other than 16 pixel boundaries
1205: // is padded with light gray. -sam
1206: static int VGABlitRect(
1207: IOConsoleInfo *cso,
1208: unsigned char *data,
1209: struct km_drawrect *rect
1210: )
1211: {
1212: ConsolePtr console = (ConsolePtr)cso->priv;
1213: int pixel; /* Starting pixel in screen */
1214: int i, x, y;
1215: unsigned char value;
1216: unsigned char *dst = (unsigned char *)console->display.frameBuffer;
1217: unsigned short *tfb;
1218: unsigned int final_value;
1219: int extraLeftBytes;
1220:
1221: pixel = rect->x + (rect->y * console->display.width);
1222:
1223: extraLeftBytes = (rect->x % 16) / 4;
1224: pixel -= extraLeftBytes * 4;
1225:
1226: dst += pixel / 8;
1227:
1228: for ( y = 0; y < rect->height; ++y )
1229: {
1230: int bitShift = 30;
1231: final_value = 0;
1232:
1233: tfb = (unsigned short *) dst;
1234: for ( x = 0; x < rect->width; )
1235: {
1236: if (x == 0)
1237: {
1238: for (i=0; i<extraLeftBytes; i++)
1239: {
1240: final_value = final_value << 8;
1241: final_value |= 0x55;
1242: bitShift -= 8;
1243: }
1244: }
1245:
1246: value = *data++;
1247:
1248: for ( i = 0; i < 8; i += 2 )
1249: {
1250: final_value |= (((value>>(6-i)) & 3) << (30-bitShift));
1251: bitShift -= 2;
1252: }
1253:
1254: x += 4;
1255:
1256: if (bitShift < 0 || x >= rect->width)
1257: {
1258: for (; bitShift >= 0; bitShift -= 2)
1259: final_value |= (0x01 << (30-bitShift));
1260: vga_write_bpp2packd32_to_bpp4planar(&final_value, tfb++);
1261: bitShift = 30;
1262: final_value = 0;
1263: }
1264:
1265: }
1266: dst += 80;
1267: }
1268:
1269: return(0);
1270: }
1271:
1272: /*
1273: * DrawRect assumes that the caller has copied in any data from user space,
1274: * so this function is safe to call directly during kernel shutdown.
1275: */
1276:
1277: static int DrawRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect)
1278: {
1279: ConsolePtr console = (ConsolePtr)cso->priv;
1280: long size; // Size in bytes corresponding to a given 2bpp area
1281: struct km_drawrect *rect = (struct km_drawrect *) km_rect;
1282: int ret = 0;
1283:
1284: if (console->window_type != SCM_GRAPHIC) {
1285: return( -1 );
1286: }
1287:
1288: /* Sanity check */
1289: if ((rect->width > console->display.width) ||
1290: (rect->height) > console->display.height) {
1291: return( -1 );
1292: }
1293:
1294: rect->x &= ~3; // Trunc to 4 pixel bound
1295: rect->width = (rect->width) & ~3; // Round down for safety
1296:
1297: size = (rect->width >> 2) * rect->height; /* size in bytes. */
1298: if ( size <= 0 )
1299: return( -1 );
1300:
1301: IOWriteRegister(VGA_GC_ADDR, 1, 0x00);
1302: VGABlitRect(cso, rect->data.bits, rect);
1303: IOWriteRegister(VGA_GC_ADDR, 1, PLANE_MASK);
1304:
1305: return(ret);
1306: }
1307:
1308: static int EraseRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect)
1309: {
1310: ConsolePtr console = (ConsolePtr)cso->priv;
1311: if (km_rect->x + km_rect->width > console->display.width ||
1312: km_rect->y + km_rect->height > console->display.height)
1313: return -1;
1314: rect(console, km_rect->x, km_rect->y,
1315: km_rect->width, km_rect->height, 3 - (km_rect->data.fill & 3));
1316: return 0;
1317: }
1318:
1319: static void PutC(IOConsoleInfo *cso, char c)
1320: // Write one character to screen. Cursor is 'on' on entry and exit.
1321: {
1322: FBPutC((ConsolePtr)cso->priv, c);
1323: }
1324:
1325: static void GetSize(IOConsoleInfo *cso, struct ConsoleSize *s)
1326: // Return the screen size in pixels.
1327: {
1328: ConsolePtr console = (ConsolePtr)cso->priv;
1329: s->cols = console->chars_per_row;
1330: s->rows = console->chars_per_column;
1331: s->pixel_width = console->display.width;
1332: s->pixel_height = console->display.height;
1333: }
1334: //
1335: // END: Implementation of IOConsoleInfo functions
1336: //
1337:
1338:
1339: //
1340: // BEGIN: Exported routines
1341: //
1342:
1343: IOConsoleInfo *_VGAAllocateConsole(IODisplayInfo *display, boolean_t isSVGA)
1344: {
1345: IOConsoleInfo *cso = (IOConsoleInfo *)IOMalloc(sizeof(IOConsoleInfo));
1346: ConsolePtr console = (ConsolePtr)IOMalloc(sizeof(ConsoleRep));
1347:
1348: if (cso == NIL)
1349: return NIL;
1350: cso->priv = console;
1351: if (cso->priv == NIL) {
1352: IOFree(cso, sizeof(IOConsoleInfo));
1353: return NIL;
1354: }
1355: cso->Free = Free;
1356: cso->Init = Init;
1357: cso->Restore = Restore;
1358: cso->DrawRect = DrawRect;
1359: cso->EraseRect = EraseRect;
1360: cso->PutC = PutC;
1361: cso->GetSize = GetSize;
1362: console->display = *display;
1363: console->isSVGA = isSVGA;
1364:
1365: // Fill in the rest of the display structure...
1366: if (isSVGA) {
1367: // Until the implementation of bank switching support is complete,
1368: // use only top LINESPERBANK lines and thus avoid bank switching.
1369: console->display.height = SVGA_LINESPERBANK;
1370: console->display.frameBuffer = (void *)FRAMEBUFFER_ADDRESS;
1371: console->display.totalWidth = SVGA_TOTALWIDTH;
1372: console->display.rowBytes = SVGA_ROWBYTES;
1373: console->saveBits = (unsigned char *)IOMalloc(SVGA_SAVE_BITS);
1374: if (console->saveBits == NIL) {
1375: IOFree(cso, sizeof(IOConsoleInfo));
1376: IOFree(console, sizeof(ConsoleRep));
1377: return NIL;
1378: }
1379: } else {
1380: console->display.frameBuffer = (void *)FRAMEBUFFER_ADDRESS;
1381: console->display.totalWidth = VGA_TOTALWIDTH;
1382: console->display.rowBytes = VGA_ROWBYTES;
1383: console->saveBits =
1384: (unsigned char *)console->display.frameBuffer +
1385: console->display.rowBytes * console->display.height;
1386: }
1387:
1388: console->window_type = SCM_UNINIT;
1389: return cso;
1390: }
1391:
1392: IOConsoleInfo *SVGAAllocateConsole(IODisplayInfo *display)
1393: {
1394: return _VGAAllocateConsole(display, TRUE);
1395: }
1396: IOConsoleInfo *VGAAllocateConsole(IODisplayInfo *display)
1397: {
1398: return _VGAAllocateConsole(display, FALSE);
1399: }
1400:
1401: //
1402: // END: Exported routines
1403: //
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.