"outl %0, %1\n\t" \
:: "a" ((uint32_t)(src)), "dN" ((uint16_t)(port)))
+/* delay for about 1us */
#define iodelay() outb(0, 0x80)
*/
#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
#include "contty.h"
#include "serial.h"
#include "asmops.h"
break;
default:
- ptr = (uint16_t*)TEXT_ADDR;
- ptr[(cursor_y + start_line) * NCOLS + cursor_x] = VMEM_CHAR(c, txattr);
+ con_putchar_scr(cursor_x, cursor_y, c);
if(++cursor_x >= NCOLS) {
linefeed();
#endif
}
+void con_putchar_scr(int x, int y, int c)
+{
+ uint16_t *ptr = (uint16_t*)TEXT_ADDR;
+ ptr[(y + start_line) * NCOLS + x] = VMEM_CHAR(c, txattr);
+}
+
+void con_printf(int x, int y, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[81];
+ char *ptr = buf;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, 80, fmt, ap);
+ va_end(ap);
+
+ while(*ptr && x < 80) {
+ con_putchar_scr(x++, y, *ptr++);
+ }
+}
+
static void scroll(void)
{
int new_line;
void con_clear(void);
void con_putchar(int c);
+void con_putchar_scr(int x, int y, int c);
+
#endif /* CONTTY_H_ */
--- /dev/null
+/*
+pcboot - bootable PC demo/game kernel
+Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY, without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef KBREGS_H_
+#define KBREGS_H_
+
+#define KB_IRQ 1
+#define PSAUX_IRQ 12
+
+#define KB_DATA_PORT 0x60
+#define KB_CMD_PORT 0x64
+#define KB_STATUS_PORT 0x64
+
+#define KB_ACK 0xfa
+#define KB_NACK 0xfe
+
+#define KB_STAT_OUTBUF_FULL 0x01
+#define KB_STAT_INBUF_FULL 0x02
+#define KB_STAT_SYSFLAG 0x04
+#define KB_STAT_CMD 0x08
+#define KB_STAT_ACTIVE 0x10
+#define KB_STAT_AUX 0x20
+#define KB_STAT_TIMEOUT 0x40
+#define KB_STAT_PAR_ERROR 0x80
+
+/* keyboard commands */
+#define KB_CMD_GET_CMDBYTE 0x20
+#define KB_CMD_SET_CMDBYTE 0x60
+#define KB_CMD_AUX_ENABLE 0xa8
+#define KB_CMD_READ_OUTPORT 0xd0
+#define KB_CMD_WRITE_OUTPORT 0xd1
+#define KB_CMD_PSAUX 0xd4
+#define KB_CMD_PULSE_RESET 0xfe
+
+/* controller command byte bits */
+#define KB_CCB_KB_INTREN 0x01
+#define KB_CCB_AUX_INTREN 0x02
+#define KB_CCB_SYSFLAG 0x04
+#define KB_CCB_KB_DISABLE 0x10
+#define KB_CCB_AUX_DISABLE 0x20
+#define KB_CCB_KB_XLAT 0x40
+
+/* psaux commands (use with d4 prefix) */
+#define AUX_CMD_ENABLE 0xf4
+#define AUX_CMD_DEFAULTS 0xf6
+
+#define AUX_PKT0_LEFTBN 0x01
+#define AUX_PKT0_RIGHTBN 0x02
+#define AUX_PKT0_MIDDLEBN 0x04
+#define AUX_PKT0_ALWAYS1 0x08
+#define AUX_PKT0_XSIGN 0x10
+#define AUX_PKT0_YSIGN 0x20
+#define AUX_PKT0_XOVF 0x40
+#define AUX_PKT0_YOVF 0x80
+
+#define AUX_PKT0_OVF_BITS (AUX_PKT0_XOVF | AUX_PKT0_YOVF)
+#define AUX_PKT0_BUTTON_BITS \
+ (AUX_PKT0_LEFTBN | AUX_PKT0_RIGHTBN | AUX_PKT0_MIDDLEBN)
+
+#endif /* KBREGS_H_ */
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <stdio.h>
#include <string.h>
#include "keyb.h"
#include "intr.h"
#include "asmops.h"
+#include "kbregs.h"
-#define KB_IRQ 1
-#define KB_PORT 0x60
/* table with rough translations from set 1 scancodes to ASCII-ish */
static int scantbl[] = {
buffer[buf_ridx] = key;
}
+int kb_wait_write(void)
+{
+ int i;
+ for(i=0; i<32768; i++) {
+ if(!(inb(KB_STATUS_PORT) & KB_STAT_INBUF_FULL)) {
+ return 1;
+ }
+ iodelay();
+ }
+ /*printf("kb_wait_write timeout\n");*/
+ return 0;
+}
+
+int kb_wait_read(void)
+{
+ int i;
+ for(i=0; i<32768; i++) {
+ if((inb(KB_STATUS_PORT) & KB_STAT_OUTBUF_FULL)) {
+ return 1;
+ }
+ iodelay();
+ }
+ /*printf("kb_wait_read timeout\n");*/
+ return 0;
+}
+
+void kb_send_cmd(unsigned char cmd)
+{
+ kb_wait_write();
+ outb(cmd, KB_CMD_PORT);
+}
+
+void kb_send_data(unsigned char data)
+{
+ kb_wait_write();
+ outb(data, KB_DATA_PORT);
+}
+
+unsigned char kb_read_data(void)
+{
+ kb_wait_read();
+ return inb(KB_DATA_PORT);
+}
+
static void kbintr()
{
unsigned char code;
int key, press;
- code = inb(KB_PORT);
+ code = inb(KB_DATA_PORT);
if(code >= 128) {
press = 0;
void kb_putback(int key);
+/* returns 1 if the keyboard controller is ready to read/write
+ * returns 0 if the wait times out
+ */
+int kb_wait_write(void);
+int kb_wait_read(void);
+
+void kb_send_cmd(unsigned char cmd);
+void kb_send_data(unsigned char data);
+unsigned char kb_read_data(void);
+
#endif /* KEYB_H_ */
#include "intr.h"
#include "mem.h"
#include "keyb.h"
+#include "psaux.h"
#include "timer.h"
#include "contty.h"
#include "video.h"
con_init();
kb_init();
+ init_psaux();
init_mem();
break;
}
if(isprint(c)) {
- printf("key: %d '%c' \n", c, (char)c);
+ printf("key: %d '%c'\n", c, (char)c);
} else {
- printf("key: %d \n", c);
+ printf("key: %d\n", c);
}
}
if((nticks % 250) == 0) {
- printf("ticks: %ld\r", nticks);
+ con_printf(71, 0, "[%ld]", nticks);
}
}
}
#include <string.h>
#include <inttypes.h>
#include "pci.h"
+#include "intr.h"
#include "int86.h"
#include "asmops.h"
#include "panic.h"
void init_pci(void)
{
int i, count = 0;
+ int intrflag;
struct int86regs regs;
+ intrflag = get_intr_flag();
+
memset(®s, 0, sizeof regs);
regs.eax = 0xb101;
int86(0x1a, ®s);
+ /* restore interrupt state in case bios changed it */
+ set_intr_flag(intrflag);
+
/* PCI BIOS present if CF=0, AH=0, and EDX has the "PCI " sig FOURCC */
if((regs.flags & FLAGS_CARRY) || (regs.eax & 0xff00) || regs.edx != PCI_SIG) {
printf("No PCI BIOS present\n");
--- /dev/null
+/*
+pcboot - bootable PC demo/game kernel
+Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY, without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include "psaux.h"
+#include "intr.h"
+#include "asmops.h"
+#include "keyb.h"
+#include "kbregs.h"
+
+static void init_mouse();
+static void psaux_intr();
+
+static int mx, my;
+static unsigned int bnstate;
+static int present;
+static int bounds[4];
+
+void init_psaux(void)
+{
+ interrupt(IRQ_TO_INTR(12), psaux_intr);
+
+ set_mouse_bounds(0, 0, 319, 199);
+
+ init_mouse();
+}
+
+static void init_mouse()
+{
+ unsigned char val;
+
+ kb_send_cmd(KB_CMD_AUX_ENABLE);
+ if(kb_wait_read()) {
+ val = kb_read_data();
+ printf("aux enable: %02x\n", (unsigned int)val);
+ }
+
+ kb_send_cmd(KB_CMD_GET_CMDBYTE);
+ val = kb_read_data();
+ val &= ~KB_CCB_AUX_DISABLE;
+ val |= KB_CCB_AUX_INTREN;
+ kb_send_cmd(KB_CMD_SET_CMDBYTE);
+ kb_send_data(val);
+
+ if(kb_wait_read()) {
+ val = kb_read_data();
+ printf("set cmdbyte: %02x\n", (unsigned int)val);
+ }
+
+ kb_send_cmd(KB_CMD_PSAUX);
+ kb_send_data(AUX_CMD_DEFAULTS);
+ val = kb_read_data();
+
+ kb_send_cmd(KB_CMD_PSAUX);
+ kb_send_data(AUX_CMD_ENABLE);
+ val = kb_read_data();
+
+ present = (val == KB_ACK) ? 1 : 0;
+ printf("init_mouse: %spresent\n", present ? "" : "not ");
+}
+
+int have_mouse(void)
+{
+ return present;
+}
+
+void set_mouse_bounds(int x0, int y0, int x1, int y1)
+{
+ bounds[0] = x0;
+ bounds[1] = y0;
+ bounds[2] = x1;
+ bounds[3] = y1;
+}
+
+unsigned int mouse_state(int *xp, int *yp)
+{
+ *xp = mx;
+ *yp = my;
+ return bnstate;
+}
+
+static void psaux_intr()
+{
+ static unsigned char data[3];
+ static int idx;
+ int dx, dy;
+
+ if(!(inb(KB_STATUS_PORT) & KB_STAT_AUX)) {
+ /* no mouse data pending, ignore interrupt */
+ return;
+ }
+
+ data[idx] = kb_read_data();
+ if(++idx >= 3) {
+ idx = 0;
+
+ if(data[0] & AUX_PKT0_OVF_BITS) {
+ /* consensus seems to be that if overflow bits are set, something is
+ * fucked, and it's best to re-initialize the mouse
+ */
+ init_mouse();
+ } else {
+ /*
+ printf("psaux data packet: %02x %02x %02x\n", (unsigned int)data[0],
+ (unsigned int)data[1], (unsigned int)data[2]);
+ */
+
+ bnstate = data[0] & AUX_PKT0_BUTTON_BITS;
+ dx = data[1];
+ dy = data[2];
+
+ if(data[0] & AUX_PKT0_XSIGN) {
+ dx |= 0xffffff00;
+ }
+ if(data[0] & AUX_PKT0_YSIGN) {
+ dy |= 0xffffff00;
+ }
+
+ mx += dx;
+ my -= dy;
+
+ if(mx < bounds[0]) mx = bounds[0];
+ if(mx > bounds[2]) mx = bounds[2];
+ if(my < bounds[1]) my = bounds[1];
+ if(my > bounds[3]) my = bounds[3];
+
+ /*
+ printf("mouse: %d,%d [%c%c%c]\n", mx, my, bnstate & AUX_PKT0_LEFTBN ? '1' : '0',
+ bnstate & AUX_PKT0_MIDDLEBN ? '1' : '0', bnstate & AUX_PKT0_RIGHTBN ? '1' : '0');
+ */
+ }
+ }
+}
--- /dev/null
+/*
+pcboot - bootable PC demo/game kernel
+Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY, without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef PSAUX_H_
+#define PSAUX_H_
+
+#define MOUSE_LBN_BIT 1
+#define MOUSE_RBN_BIT 2
+#define MOUSE_MBN_BIT 4
+
+void init_psaux(void);
+
+int have_mouse(void);
+
+void set_mouse_bounds(int x0, int y0, int x1, int y1);
+unsigned int mouse_state(int *xp, int *yp);
+
+#endif /* PSAUX_H_ */
void ser_putc(int fd, char c)
{
int base = ports[fd].base;
+
+ if(c == '\n') {
+ ser_putc(fd, '\r');
+ }
+
while(!can_send(fd));
while((inb(base + UART_MSTAT) & MST_CTS) == 0);
outb(c, base + UART_DATA);
.extern kb_getkey
# move the stack to the top of the conventional memory
+ cli
movl $0x80000, %esp
# zero the BSS section
#include "video.h"
#include "asmops.h"
#include "keyb.h"
+#include "psaux.h"
#include "contty.h"
+static void draw_cursor(int x, int y, uint16_t col);
+
static uint16_t *framebuf;
+#define CURSOR_XSZ 12
+#define CURSOR_YSZ 16
+static uint16_t cursor[] = {
+ 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0x0001, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0001, 0xffff, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
int vbetest(void)
{
- int i, j, nmodes;
+ int i, j, nmodes, mx, my;
+ unsigned int st;
struct video_mode vi;
uint16_t *fbptr;
}
}
+ set_mouse_bounds(0, 0, 639, 479);
+
+ /* empty the kb queue */
while(kb_getkey() != -1);
- while(kb_getkey() == -1) {
+
+ for(;;) {
+ if(kb_getkey() != -1) {
+ break;
+ }
+
+ st = mouse_state(&mx, &my);
+ draw_cursor(mx, my, st & 1 ? 0xf800 : (st & 2 ? 0x7e0 : (st & 4 ? 0x00ff : 0)));
+
halt_cpu();
}
con_clear();
return 0;
}
+
+static void draw_cursor(int x, int y, uint16_t col)
+{
+ static uint16_t saved[CURSOR_XSZ * CURSOR_YSZ];
+ static int saved_x = -1, saved_y, saved_w, saved_h;
+
+ int i, j, w, h;
+ uint16_t *dest, *src, *savp;
+
+ if(saved_x >= 0) {
+ dest = framebuf + saved_y * 640 + saved_x;
+ src = saved;
+
+ for(i=0; i<saved_h; i++) {
+ for(j=0; j<saved_w; j++) {
+ *dest++ = *src++;
+ }
+ src += CURSOR_XSZ - saved_w;
+ dest += 640 - saved_w;
+ }
+ }
+
+ dest = framebuf + y * 640 + x;
+ src = cursor;
+ savp = saved;
+
+ w = 640 - x;
+ if(w > CURSOR_XSZ) w = CURSOR_XSZ;
+ h = 480 - y;
+ if(h > CURSOR_YSZ) h = CURSOR_YSZ;
+
+ saved_x = x;
+ saved_y = y;
+ saved_w = w;
+ saved_h = h;
+
+ for(i=0; i<h; i++) {
+ for(j=0; j<w; j++) {
+ uint16_t c = *src++;
+ *savp++ = *dest;
+ if(c) {
+ if(c == 1) c = col;
+ *dest = c;
+ }
+ dest++;
+ }
+ src += CURSOR_XSZ - w;
+ dest += 640 - w;
+ savp += CURSOR_XSZ - w;
+ }
+}