diff options
Diffstat (limited to 'kernel/driver')
| -rw-r--r-- | kernel/driver/keyboard.c | 37 | ||||
| -rw-r--r-- | kernel/driver/video.c | 503 |
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(); +} |
