summaryrefslogtreecommitdiff
path: root/kernel/driver
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/driver')
-rw-r--r--kernel/driver/keyboard.c37
-rw-r--r--kernel/driver/video.c503
2 files changed, 540 insertions, 0 deletions
diff --git a/kernel/driver/keyboard.c b/kernel/driver/keyboard.c
new file mode 100644
index 0000000..7410171
--- /dev/null
+++ b/kernel/driver/keyboard.c
@@ -0,0 +1,37 @@
+//+----------------------------------------------------------------------------
+//
+// File: keyboard.c
+//
+// Module:
+//
+// Synopsis:
+//
+// Created: sgasch 21 Oct 2003
+//
+//+----------------------------------------------------------------------------
+
+#include "kernel.h"
+#include "hal.h"
+#include "rtl.h"
+#include "interrupts.h"
+
+void
+HalKeyboardInt(INTERRUPT_STATE *is)
+{
+ BYTE c;
+ BYTE k;
+
+ HalDisableInterrupts();
+
+ c = in(0x64);
+ HalIoDelay();
+ if (c & 1)
+ {
+ k = in(0x60);
+ HalIoDelay();
+ HalVideoPrint("Testing %x.\n\0", 1);
+ }
+
+ HalEnableInterrupts();
+}
+
diff --git a/kernel/driver/video.c b/kernel/driver/video.c
new file mode 100644
index 0000000..a63331b
--- /dev/null
+++ b/kernel/driver/video.c
@@ -0,0 +1,503 @@
+//+----------------------------------------------------------------------------
+//
+// File: video.c
+//
+// Module: Video driver
+//
+// Synopsis: low-level interface to video memory
+//
+// Created: sgasch 5 Jul 2003
+//
+//+----------------------------------------------------------------------------
+
+#include <stdarg.h>
+
+#include "kernel.h"
+#include "hal.h"
+#include "rtl.h"
+#include "video.h"
+
+extern BIOS_HARDWARE_BLOCK g_BiosHardwareBlock;
+
+//
+// Local #defines
+//
+#define FG_BG_TO_ATTRIB_BYTE(fg,bg) ((fg&0x0F)|((bg&0x0F)<<4))
+#define LINES (0)
+#define COLS (1)
+#define CRT_ADDR_REG (0x3D4)
+#define CRT_DATA_REG (0x3D5)
+#define CRT_CURSOR_LOC_HIGH_REG (0x0E)
+#define CRT_CURSOR_LOC_LOW_REG (0x0F)
+#define ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(L,C)\
+ (((g_bScreenResolution[COLS] << 1) * (L)) + ((C) << 1))
+#define ZERO_BASED_LINE_COL_TO_ULONG_OFFSET(L,C)\
+ (ZERO_BASED_LINE_COL_TO_BYTE_OFFSET((L),(C)) >> 2)
+
+//
+// Global identifiers
+//
+BYTE *g_pVideoMemory = NULL;
+BYTE g_bScreenResolution[2] = { 0, 0 };
+BYTE g_bSoftCursor[2] = { 0, 0 };
+BYTE g_bColorAttribute = FG_BG_TO_ATTRIB_BYTE(BLACK, WHITE);
+
+typedef struct _VIDEO_LOOKUP_ENTRY
+{
+ CHAR *szBoardName;
+ BYTE *pStartOfVideoMemory;
+ BYTE uScreenLines[3];
+}
+VIDEO_LOOKUP_ENTRY;
+
+static VIDEO_LOOKUP_ENTRY g_VideoLookupTable[] =
+{
+ { "No video adapter",
+ (BYTE *)0x000B0000,
+ { 25, 25, 25 } },
+ { "Monochrome display adapter",
+ (BYTE *)0x000B0000,
+ { 25, 25, 25 } },
+ { "CGA",
+ (BYTE *)0x000B8000,
+ { 25, 25, 25 } },
+ { "Code 3: Undefined",
+ (BYTE *)0x000B0000,
+ { 25, 25, 25 } },
+ { "EGA with color display",
+ (BYTE *)0x000B8000,
+ { 43, 25, 25 } },
+ { "EGA with mono display",
+ (BYTE *)0x000B0000,
+ { 43, 25, 25 } },
+ { "Code 6: Undefined",
+ (BYTE *)0x000B0000,
+ { 25, 25, 25 } },
+ { "VGA with mono display",
+ (BYTE *)0x000B0000,
+ { 50, 27, 25 } },
+ { "VGA with color display",
+ (BYTE *)0x000B8000,
+ { 50, 27, 25 } },
+ { "Code 9: Undefined",
+ (BYTE *)0x000B0000,
+ { 25, 25, 25 } },
+ { "MCGA with digital color",
+ (BYTE *)0x000B8000,
+ { 25, 25, 25 } },
+ { "MCGA with monochrome",
+ (BYTE *)0x000B0000,
+ { 25, 25, 25 } },
+ { "MCGA with analog color",
+ (BYTE *)0x000B8000,
+ { 25, 25, 25 } }
+};
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: VideopInitialize
+//
+// Synopsis:
+//
+// Arguments: void
+//
+// Returns: STATUS
+//
+//+----------------------------------------------------------------------------
+STATUS
+VideopInitialize(void)
+{
+ BYTE uType = g_BiosHardwareBlock.bDisplayType;
+ BYTE uIndex = 2;
+
+ //
+ // Based on the font size (width in pixels), set the index into the
+ // screen lines lookup table
+ //
+ switch(g_BiosHardwareBlock.bFontSize)
+ {
+ case 8:
+ uIndex = 0;
+ break;
+ case 14:
+ uIndex = 1;
+ break;
+ case 16:
+ uIndex = 2;
+ break;
+ }
+
+ //
+ // If the display type returned by BIOS is known to us, use the
+ // lookup table to populate some globals here.
+ //
+ if (uType <= ARRAY_LENGTH(g_VideoLookupTable))
+ {
+ g_pVideoMemory = g_VideoLookupTable[uType].pStartOfVideoMemory;
+ g_bScreenResolution[LINES] =
+ g_VideoLookupTable[uType].uScreenLines[uIndex];
+ }
+
+ //
+ // Otherwise make some guesses
+ //
+ else
+ {
+ g_pVideoMemory = (BYTE *)0x000B8000;
+ g_bScreenResolution[LINES] = 25;
+ }
+ g_bScreenResolution[COLS] = 80;
+
+ //
+ // Set color to WHITE on BLACK
+ //
+ VideoSetCurrentColorAttribute(WHITE, BLACK);
+
+ //
+ // Clear the screen and thus synchronize the hardware and soft cursor
+ // position.
+ //
+ VideoClearScreen();
+ return(STATUS_SUCCESS);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: VideoDriverMain
+//
+// Synopsis:
+//
+// Arguments: UINT uEvent
+//
+// Returns: STATUS
+//
+//+----------------------------------------------------------------------------
+STATUS
+VideoDriverMain(UINT uEvent)
+{
+ switch(uEvent)
+ {
+ case DEVICE_DRIVER_INITIALIZATION:
+ return(VideopInitialize());
+
+ case DEVICE_DETATCH:
+ ASSERT(FALSE);
+ return(STATUS_NOT_SUPPORTED);
+
+ case DEVICE_DRIVER_SHUTDOWN:
+ g_fVideoEnabled = FALSE;
+ return(STATUS_SUCCESS);
+
+ default:
+ }
+ return(TRUE);
+}
+
+STATUS
+VideoDriverRead(UINT uAddress,
+ void *pBuffer,
+ UINT uBufferLength);
+
+STATUS
+VideoDriverWrite(UINT uAddress,
+ void *pBuffer,
+ UINT uBufferLength);
+
+STATUS
+VideoDriverIoctl(UINT uIoctlCode,
+ void *pBuffer,
+ UINT uBufferLength);
+
+
+//
+// Move the hardware cursor on the screen to sync up with the software
+// cursor position in g_bSoftwareCursor
+//
+void
+VideoSetHardwareCursor(void)
+{
+ WORD wOffset; // byte offset into video mem
+ BYTE bOrig; // original port contents holder
+
+ //
+ // Cursor is zero-based (e.g. line 24 is the last one)
+ //
+ ASSERT(g_bSoftCursor[LINES] < g_bScreenResolution[LINES]);
+ ASSERT(g_bSoftCursor[COLS] < g_bScreenResolution[COLS]);
+
+ wOffset = ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bSoftCursor[LINES],
+ g_bSoftCursor[COLS]);
+ ASSERT(wOffset <= (g_bScreenResolution[LINES] *
+ g_bScreenResolution[COLS]) * 2 - 2);
+
+ //
+ // Save original contents of CRT address register.
+ //
+ bOrig = in(CRT_ADDR_REG);
+
+ //
+ // Set the high cursor location byte
+ //
+ out(CRT_ADDR_REG, CRT_CURSOR_LOC_HIGH_REG);
+ out(CRT_DATA_REG, (wOffset >> 8) & 0xFF);
+ IoDelay();
+
+ //
+ // Set the low cursor location byte
+ //
+ out(CRT_ADDR_REG, CRT_CURSOR_LOC_LOW_REG);
+ IoDelay();
+ out(CRT_DATA_REG, (wOffset & 0xFF));
+ IoDelay();
+
+ //
+ // Restore contents of the CRT address register
+ //
+ out(CRT_ADDR_REG, bOrig);
+ IoDelay();
+}
+
+void
+VideoSetCurrentColorAttribute(BYTE bFg, BYTE bBg)
+{
+ bFg &= 0x0F; // restrict these guys to colors
+ bBg &= 0x0F; // and the high intense bit
+
+ g_bColorAttribute = FG_BG_TO_ATTRIB_BYTE(bFg, bBg);
+}
+
+void
+VideoClearScreen(void)
+{
+ ULONG *p = (ULONG *)g_pVideoMemory;
+ ULONG uFill;
+ ULONG uCount;
+
+ //
+ // Start uCount at the number of ULONGs in visible video memory
+ //
+ uCount = ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bScreenResolution[LINES] - 1,
+ g_bScreenResolution[COLS] - 1);
+ uCount += 2;
+ uCount >>= 2;
+
+ //
+ // Construct a fill ULONG: blank attrib blank attrib
+ //
+ uFill = 0;
+ uFill |= (ULONG)g_bColorAttribute;
+ uFill |= ((ULONG)g_bColorAttribute) << 16;
+
+ //
+ // Blast uFills into video memory
+ //
+ while(uCount)
+ {
+ *p++ = uFill;
+ uCount--;
+ }
+
+ //
+ // Set cursor position to 0,0
+ //
+ g_bSoftCursor[LINES] = g_bSoftCursor[COLS] = 0;
+ VideoSetHardwareCursor();
+}
+
+
+void
+VideoScroll(void)
+{
+ ULONG *p = (ULONG *)g_pVideoMemory;
+ ULONG uUlongsPerLine = (g_bScreenResolution[COLS] >> 1); // 2X/4
+ ULONG i, j;
+ ULONG uFill;
+
+ ASSERT(sizeof(ULONG) == 4);
+ ASSERT(sizeof(BYTE) == 1);
+
+ for (i = 0;
+ i < (g_bScreenResolution[LINES] - 2);
+ i++)
+ {
+ //
+ // Start at i, 0. Copy a ULONG up from i+1, 0. Do the whole line i.
+ //
+ for (j = 0;
+ j < uUlongsPerLine;
+ j++)
+ {
+ *p = *(p + uUlongsPerLine);
+ p++;
+ }
+ }
+
+ //
+ // Construct a fill ULONG: blank attrib blank attrib
+ //
+ uFill = 0;
+ uFill |= (ULONG)g_bColorAttribute;
+ uFill |= ((ULONG)g_bColorAttribute) << 16;
+
+ //
+ // Blank the last line
+ //
+ p = (ULONG *)(g_pVideoMemory +
+ ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bScreenResolution[LINES] - 1, 0));
+ for (i = 0;
+ i < uUlongsPerLine;
+ i++)
+ {
+ *p = uFill;
+ p++;
+ }
+}
+
+void
+VideoPutChar(BYTE c)
+{
+ BYTE *p = (g_pVideoMemory +
+ ZERO_BASED_LINE_COL_TO_BYTE_OFFSET(g_bSoftCursor[LINES],
+ g_bSoftCursor[COLS]));
+ switch(c)
+ {
+ case '\n':
+ g_bSoftCursor[LINES]++;
+ if (g_bSoftCursor[LINES] >= g_bScreenResolution[LINES])
+ {
+ VideoScroll();
+ g_bSoftCursor[LINES] = g_bScreenResolution[LINES] - 1;
+ }
+ g_bSoftCursor[COLS] = 0;
+ return;
+ default:
+ *p = c;
+ p++;
+ *p = g_bColorAttribute;
+ p++;
+ g_bSoftCursor[COLS]++;
+ if (g_bSoftCursor[COLS] >= g_bScreenResolution[COLS])
+ {
+ g_bSoftCursor[COLS] = 0;
+ g_bSoftCursor[LINES]++;
+ if (g_bSoftCursor[LINES] >= g_bScreenResolution[LINES])
+ {
+ VideoScroll();
+ g_bSoftCursor[LINES] = g_bScreenResolution[LINES] - 1;
+ }
+ }
+ }
+}
+
+void
+VideoPutNullTerminatedString(BYTE *s)
+{
+ ULONG uSafety = 0;
+
+ while (*s != 0)
+ {
+ VideoPutChar(*s);
+ s++;
+ uSafety++;
+
+ if (uSafety > 256)
+ {
+ VideoPutNullTerminatedString("RUNAWAYSTRING!?!\n\0");
+ break;
+ }
+ }
+ VideoSetHardwareCursor();
+}
+
+void
+VideoSetCursorPosition(BYTE bLine, BYTE bCol)
+{
+ if (bLine >= g_bScreenResolution[LINES])
+ {
+ bLine = g_bScreenResolution[LINES] - 1;
+ }
+ if (bCol >= g_bScreenResolution[COLS])
+ {
+ bCol = g_bScreenResolution[COLS] - 1;
+ }
+
+ g_bSoftCursor[LINES] = bLine;
+ g_bSoftCursor[COLS] = bCol;
+ VideoSetHardwareCursor();
+}
+
+void
+VideoGetCursorPosition(BYTE *pbLine, BYTE *pbCol)
+{
+ *pbLine = g_bSoftCursor[LINES];
+ *pbCol = g_bSoftCursor[COLS];
+}
+
+void
+VideoPrint(CHAR *szFormat, ...)
+{
+ CHAR *p = szFormat;
+ CHAR *q;
+ CHAR buf[32];
+ va_list args;
+ INT iVal;
+ UINT uVal;
+ CHAR *szVal;
+
+ va_start(args, szFormat);
+ while (*p != '\0')
+ {
+ switch (*p)
+ {
+ case '%':
+ p++;
+ switch (*p)
+ {
+ case '\0':
+ goto done;
+ case '%':
+ VideoPutChar('%');
+ break;
+ case 'd':
+ iVal = va_arg(args, int);
+ q = RtlIntToAscii(iVal, buf, ARRAY_LENGTH(buf), 10);
+ ASSERT(strlen(q) < 20);
+ VideoPutNullTerminatedString(q);
+ break;
+ case 'u':
+ uVal = va_arg(args, unsigned int);
+ q = RtlIntToAscii(uVal, buf, ARRAY_LENGTH(buf), 10);
+ ASSERT(strlen(q) < 20);
+ VideoPutNullTerminatedString(q);
+ break;
+ case 'x':
+ uVal = va_arg(args, unsigned int);
+ q = RtlIntToAscii(uVal, buf, ARRAY_LENGTH(buf), 16);
+ ASSERT(strlen(q) < 20);
+ VideoPutNullTerminatedString(q);
+ break;
+ case 's':
+ szVal = va_arg(args, char *);
+ VideoPutNullTerminatedString(szVal);
+ break;
+ case 'c':
+ iVal = va_arg(args, int);
+ VideoPutChar(iVal & 0xFF);
+ break;
+ default:
+ VideoPutChar(*p);
+ break;
+ }
+ break;
+ default:
+ VideoPutChar(*p);
+ break;
+ }
+ p++;
+ }
+ done:
+ va_end(args);
+ VideoSetHardwareCursor();
+}