/*- * Copyright (c) 2007 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "cons.h" #include "emul.h" #include "vars.h" #include #include /* * Register variables used by WWIV when interfacing with the BIOS. */ unsigned int _AX; unsigned short _AH; unsigned short _AL; unsigned int _BX; unsigned short _BH; unsigned short _BL; unsigned int _CX; unsigned short _CH; unsigned short _CL; unsigned int _DX; unsigned short _DH; unsigned short _DL; unsigned int _DS; unsigned int _SS; unsigned int _SP; /* * Interrupt 16 operations: keyboard. */ #define INT16_KEYCHECK 0x01 /* * Simulated interrupt vector table. */ // static void (*intr)(void)[256]; void geninterrupt(int intr_num) { struct timeval tv; struct tm tm; time_t t; if (intr_num == 0x21 && _AH == 0x2a) { /* * Retrieve system date. */ if (gettimeofday(&tv, NULL) < 0) panic("geninterrupt: gettimeofday: %s", strerror(errno)); t = tv.tv_sec; localtime_r(&t, &tm); _CX = tm.tm_year - 80; _DH = tm.tm_mon; _DL = tm.tm_mday; _AL = tm.tm_wday; return; } panic("geninterrupt(0x%02x): %s", intr_num, strerror(ENOSYS)); } void setvect(int intr_num, void (*intr)(void)) { } void * getvect(int intr_num) { return (NULL); } /* * my_video_int() is a wrapper for int10, the BIOS video interrupt. */ void _VideoInt(void) { switch (_AH) { case 0x02: cons_setxy(_DL, _DH); return; case 0x03: _DL = cons_getx(); _DH = cons_gety(); _AX = 0x0000; return; case 0x06: //printf("0x06 %d (%d, %d) (%d %d)\n", _AL, _CH, _CL, _DH, _DL); /* * Scroll up window. */ if (_AL == 0) cons_winclear(_CL, _CH, _DL, _DH); else cons_winscrollup(_CL, _CH, _DL, _DH, _AL); return; case 0x07: if (_AL == 0) cons_winclear(_CL, _CH, _DL, _DH); else cons_winscrolldown(_CL, _CH, _DL, _DH, _AL); return; case 0x09: cons_putchar(_AL); return; case 0x0f: _AH = cons_getwidth(); _AL = 3; _BH = 0; return; } panic("my_video_int(%d): %s", _AH, strerror(ENOSYS)); } static int video_int(union REGS *regs) { switch (regs->h.ah) { case 0x0f: /* * Return video mode information. */ regs->h.ah = 80; /* Columns. */ regs->h.al = 3; /* Video mode. */ return (regs->w.ax); } panic("video_int(0x%02x): %s", regs->h.ah, strerror(ENOSYS)); } static int keyboard_int(union REGS *regs) { switch (regs->h.ah) { case 0x01: /* * Has a key been hit? */ if (cons_keycheck() == 0) regs->x.flags |= 64; else regs->x.flags &= ~64; return (regs->w.ax); } panic("keyboard_int(0x%02x): %s", regs->h.ah, strerror(ENOSYS)); } static int dos_int(union REGS *regs) { switch (regs->h.ah) { case 0x06: /* * Direct console input. */ if (regs->h.dl == 0xff) { if (cons_keycheck() == 0) { regs->h.al = 0x00; regs->x.flags |= 64; } else { regs->h.al = cons_keyget(); regs->x.flags &= ~64; } } else { regs->h.al = cons_keyget(); regs->x.flags &= ~64; } return (regs->w.ax); case 0x33: /* * Disable Ctrl-Break handling. * * XXXRW: Currently not implemented. Should disable * SIGINT? */ if (regs->h.al != 0x01) break; //signal(SIGINT, SIG_IGN); return (regs->w.ax); } panic("dos_int(0x%02x): %s", regs->h.ah, strerror(ENOSYS)); } int int86(int ivec, union REGS *in, union REGS *out) { *out = *in; switch (ivec) { case 0x10: return (video_int(out)); case 0x16: return (keyboard_int(out)); case 0: case 0x21: return (dos_int(out)); } panic("int86 (ivec 0x%02x ah 0x%02x): %s", ivec, in->h.ah, strerror(ENOSYS)); } int int86x(int ivec, union REGS *in, union REGS *out, struct SREGS *seg) { /* * XXXRW: This may not work. */ #if 0 errno = ENOSYS; errx(-1, "int86x"); #else return (int86(ivec, in, out)); #endif } unsigned char inportb(unsigned short port) { panic("inportb: %s", strerror(ENOSYS)); } unsigned char outportb(unsigned short port, unsigned char data) { panic("outportb: %s", strerror(ENOSYS)); } void disable(void) { } void enable(void) { } /* * setbeep() turns on or off the system speaker. */ void setbeep(int i) { if (i) cons_beep(); } void bios_init(void) { }