summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halppc/ppc/pxs3.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halppc/ppc/pxs3.c')
-rw-r--r--private/ntos/nthals/halppc/ppc/pxs3.c677
1 files changed, 677 insertions, 0 deletions
diff --git a/private/ntos/nthals/halppc/ppc/pxs3.c b/private/ntos/nthals/halppc/ppc/pxs3.c
new file mode 100644
index 000000000..78b31675a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxs3.c
@@ -0,0 +1,677 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxs3.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using an S3 video adapter.
+
+Author:
+
+ Jess Botts
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxs3.h"
+#include "string.h"
+#include "pxvgaequ.h"
+
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ );
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ );
+
+// in pxdisp.c
+VOID
+WaitForVSync (
+ VOID
+ );
+
+VOID
+Scroll_Screen (
+ IN UCHAR line
+ );
+
+
+extern ULONG HalpInitPhase;
+extern PUCHAR HalpVideoMemoryBase;
+extern PUCHAR HalpVideoCoprocBase;
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes the S3 display controller chip.
+Arguments:
+ None.
+Return Value:
+ None.
+
+--*/
+{
+//
+// Routine Description:
+//
+// This is the initialization routine for S3 86C911. This routine initializes
+// the S3 86C911 chip in the sequence of VGA BIOS for AT.
+//
+ ULONG DataLong;
+ USHORT i,j;
+ UCHAR DataByte;
+ UCHAR Index;
+// PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ if (HalpInitPhase == 0) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(S3_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+
+ //
+ // IO control space has already been mapped in phase 1 via halpmapiospace
+ //
+
+ }
+
+
+
+ // Enable Video Subsystem
+ // Accordint to chapter 5.4.2 regular VGA setup sequence
+ // HalDisplayString(" Enable Video Subsystem...\n");
+
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
+
+ // HalDisplayString(" Subsystem Enable = 0x10...\n");
+ WRITE_S3_UCHAR(Setup_OP, 0x01);
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
+
+ WRITE_S3_UCHAR(DAC_Mask, 0x0); // Set screen into blank
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ WRITE_S3_UCHAR(Seq_Data, 0x21);
+
+ //=========================================================================
+ //
+ // IBMBJB removed this section because it is not currently used, this
+ // was left commented out instead of deleting it in case we use
+ // a monochrome monitor in the future
+ //
+ // // Check monitor type to decide index address (currently not use)
+ // DataByte = READ_S3_UCHAR(MiscOutR);
+ // ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+ //
+ // if (ColorMonitor) {
+ // Index_3x4 = (PVOID)S3_3D4_Index;
+ // Data_3x5 = (PVOID)S3_3D5_Data;
+ // } else {
+ // Index_3x4 = (PVOID)Mono_3B4;
+ // Data_3x5 = (PVOID)Mono_3B5;
+ // }
+ //
+ //=========================================================================
+
+ //
+ // -- Initialization Process Begin --
+ // According to appendix B-4 "ADVANCED PROGRAMMER'S GUIDE TO THE EGA/VGA"
+ // to set the default values to VGA +3 mode.
+ //
+ WRITE_S3_UCHAR(VSub_EnB,VideoParam[0]);
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // For ATI card(0x63) we may want to change the frequence
+ WRITE_S3_UCHAR(MiscOutW,VideoParam[1]);
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // Sequencer Register
+ for (Index = 1; Index < 5; Index++) {
+ WRITE_S3_UCHAR(Seq_Index, Index);
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+Index]);
+ }
+
+#ifdef POLO // if compiling for a Polo
+
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+
+ if((DataByte & 0xf0) == 0xc0) { // if display adaptor is an S3 864
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte |= 0x01; // use an 8 dot character clock
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+ }
+
+#endif
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+ WRITE_S3_UCHAR(S3_3D4_Index, VERTICAL_RETRACE_END);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte = DataByte & 0x7f;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // CRTC controller CR0 - CR18
+ for (Index = 0; Index < 25; Index++) {
+ WRITE_S3_UCHAR(S3_3D4_Index, Index);
+ WRITE_S3_UCHAR(S3_3D5_Data, VideoParam[CRT_OFFSET+Index]);
+ }
+
+ // attribute write
+ // program palettes and mode register
+ // HalDisplayString(" Program palettes ...\n");
+ for (Index = 0; Index < 21; Index++) {
+ WaitForVSync();
+
+ DataByte = READ_S3_UCHAR(Stat1_In); // Initialize Attr. F/F
+ WRITE_S3_UCHAR(Attr_Index,Index);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Data,VideoParam[ATTR_OFFSET+Index]);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Index,0x20); // Set into normal operation
+ }
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ // graphics controller
+ // HalDisplayString(" Graphics controller...\n");
+ for (Index = 0; Index < 9; Index++) {
+ WRITE_S3_UCHAR(GC_Index, Index);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+Index]);
+ }
+
+ // turn off the text mode cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, CURSOR_START);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x2D);
+
+ // Unlock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x48);
+
+ // Unlock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0xa0);
+
+ // Disable enhanced mode
+ WRITE_S3_UCHAR(ADVFUNC_CNTL, 0x02);
+
+ // Turn off H/W Graphic Cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, SC5);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ //=========================================================================
+ //
+ // IBMBJB S3 errata sheet says that CR40 can not be read correctly after
+ // power up until it has been written to, suggested workaround is
+ // to use the power on default (0xA4) Since the intent of the
+ // existing code was to reset bit 0, 0xA4 will be used to reset
+ // the bit. The other bits that are reset select the desired
+ // default configuration.
+ //
+ // If this register is written by the firmware then this fix is
+ // unneccessary. If future modifications of the firmware were to
+ // remove all writes to this register then this fix would have to
+ // be added here. This is being added now to protect this code
+ // from possible firmware changes.
+ //
+ // // Disable enhanced mode registers access
+ // WRITE_S3_UCHAR(S3_3D4_Index, SC0);
+ // DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ // DataByte &= 0xfe;
+ // DataByte ^= 0x0;
+ //
+ // WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+ //
+
+ WRITE_S3_UCHAR( S3_3D4_Index, SC0 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0xA4 );
+
+ //=========================================================================
+
+ // Set Misc 1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0A);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xc7;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R1);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0x80;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R2 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R2);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Set S3R4 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R4);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xec;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ //=========================================================================
+ //
+ // IBMBJB added this section to eliminate the DAC hardware cursor, this
+ // is done before setting registers 0x50 - 0x62 to default states
+ // so that R55's default state will not be undone.
+ //
+ // this sequence zeros the 2 least signifigant bits in command
+ // register 2 on the DAC
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // set RS[3:2] to 10
+ DataByte = READ_S3_UCHAR( S3_3D5_Data );
+ DataByte &= 0xfc;
+ DataByte |= 0x02;
+ WRITE_S3_UCHAR( S3_3D5_Data, DataByte );
+
+ DataByte = READ_S3_UCHAR( DAC_Data );
+ DataByte &= 0xfc; // zero CR21,20 in DAC command
+ WRITE_S3_UCHAR( DAC_Data, DataByte ); // register 2
+
+ //=========================================================================
+ //
+ // IBMBJB Added code to configure for 18 bit color mode and reload the
+ // palette registers because the firmware configures for 24 bit
+ // color. If this is done when the system driver initializes for
+ // graphics mode then the text mode colors can not be changed
+ // properly.
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // RS[3:2] = 01B to address
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 ); // DAC command register 0
+
+ DataByte = READ_S3_UCHAR( DAC_Mask ); // reset bit 1 in DAC command
+ DataByte &= 0xfd; // register 0 to select 6 bit
+ WRITE_S3_UCHAR( DAC_Mask, DataByte ); // operation (18 bit color)
+
+ // IBMBJB added write to SDAC PLL control register to make sure CLK0
+ // is correct if we have to reinitialize after graphics mode
+ // initialization, this does not bother the 928/Bt485 card
+ // because the Bt485 DAC looks very much like the SDAC
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0x0e ); // select SDAC PLL control reg
+ WRITE_S3_UCHAR( DAC_Data, 0x00 ); // select SDAC CLK0
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // select DAC color palette
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 ); // registers
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0 ); // start load in register 0
+
+ for( i = 0, j = 0; i < 256; ++i ) // load all color registers
+ {
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // red intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // green intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // blue intensity
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added writes to registers 0x50 - 0x62 to set them to a known
+ // state because some of them are set by the firmware and are
+ // not correct for our use
+ //
+ // NOTE: there are some writes to the DAC registers in code that
+ // executes later that depend on R55[1:0] being 00B, if the
+ // default state of R55 is changed make sure that these bits
+ // are not changed
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x50 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x51 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x52 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x53 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x54 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x56 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x57 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x58 );
+#ifdef SAM_256
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x40 );
+#else
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+#endif
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x59 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5a );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x0a );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5B );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5C );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5D );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5E );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5F );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ // IBMBJB changed value written from 0 to 1 for an S3 864 based card to
+ // clear up bad display caused by 864->SDAC FIFO underrun
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x60 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x61 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x62 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ //=========================================================================
+ //
+ // IBMBJB added setting bits 7 and 6 of CR65, errata sheet fix for split
+ // transfer problem in parallel and continuous addressing modes
+ // Note: side effect of setting bit 7 was a garbled firmware screen after
+ // shutdown.
+
+ // Set SR65 bits 7 and 6
+ WRITE_S3_UCHAR(S3_3D4_Index, 0x65);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte |= 0x40;
+// DataByte |= 0xc0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Lock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Lock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+ // HalDisplayString(" Load Fonts into Plane2 ...\n");
+ WRITE_S3_UCHAR(Seq_Index,0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data,0x04); // select plane 2
+
+ WRITE_S3_UCHAR(Seq_Index,0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data,0x06); // access to all planes,
+
+ WRITE_S3_UCHAR(GC_Index,0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data,0x00);
+
+ WRITE_S3_UCHAR(GC_Index,0x06);
+ WRITE_S3_UCHAR(GC_Data,0x04);
+
+ WRITE_S3_UCHAR(GC_Index,0x04);
+ WRITE_S3_UCHAR(GC_Data,0x02);
+
+
+ MemBase = 0xA0000;
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 16; j++) {
+ WRITE_S3_VRAM(MemBase, VGAFont8x16[i*16+j]);
+ MemBase++;
+ }
+ // 32 bytes each character font
+ for (j = 16; j < 32; j++) {
+ WRITE_S3_VRAM(MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_S3_UCHAR(DAC_Mask, 0xff);
+
+ // select plane 0, 1
+ WRITE_S3_UCHAR(Seq_Index, 0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x02]);
+
+ // access to planes 0, 1.
+ WRITE_S3_UCHAR(Seq_Index, 0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x05]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x04);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x06);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x06]);
+
+ //
+ // Set screen into blue
+ //
+ // HalDisplayString(" Set Screen into Blue ...\n");
+ for (DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, 0x20);
+ WRITE_S3_VRAM(DataLong+1, 0x1F);
+ }
+ // End of initialize S3 standard VGA +3 mode
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ //IBMLAN===============================================================
+ // Added the following so that HalQueryDisplayParameters() and
+ // HalSetDisplayParameters() work with either S3 or P9.
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength =
+ HalpScrollLine * (HalpDisplayText - 1);
+
+ //end IBMLAN===========================================================
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of HalpDisplayPpcS3Setup() */
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ Scroll_Screen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterS3(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+ HalpOutputCharacterS3(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterS3() */
+
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < HalpDisplayWidth) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+} /* end of HalpOutputCharacterS3() */
+
+