#include <string.h>
#include <ctype.h>
#include "contty.h"
+#include "serial.h"
+
+enum {
+ OUT_DEF,
+ OUT_BUF,
+ OUT_SCR,
+ OUT_SER
+};
extern void pcboot_putchar(int c);
-static void bwrite(char *buf, size_t buf_sz, char *str, int sz);
-static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap);
+static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz);
+static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap);
int putchar(int c)
{
va_list ap;
va_start(ap, fmt);
- res = intern_printf(0, 0, fmt, ap);
+ res = intern_printf(OUT_DEF, 0, 0, fmt, ap);
va_end(ap);
return res;
}
int vprintf(const char *fmt, va_list ap)
{
- return intern_printf(0, 0, fmt, ap);
+ return intern_printf(OUT_DEF, 0, 0, fmt, ap);
}
int sprintf(char *buf, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- res = intern_printf(buf, 0, fmt, ap);
+ res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
va_end(ap);
return res;
}
int vsprintf(char *buf, const char *fmt, va_list ap)
{
- return intern_printf(buf, 0, fmt, ap);
+ return intern_printf(OUT_BUF, buf, 0, fmt, ap);
}
int snprintf(char *buf, size_t sz, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- res = intern_printf(buf, sz, fmt, ap);
+ res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
va_end(ap);
return res;
}
int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
{
- return intern_printf(buf, sz, fmt, ap);
+ return intern_printf(OUT_BUF, buf, sz, fmt, ap);
}
+int ser_printf(const char *fmt, ...)
+{
+ int res;
+ va_list ap;
+
+ va_start(ap, fmt);
+ res = intern_printf(OUT_SER, 0, 0, fmt, ap);
+ va_end(ap);
+ return res;
+}
+
+int ser_vprintf(const char *fmt, va_list ap)
+{
+ return intern_printf(OUT_SER, 0, 0, fmt, ap);
+}
/* intern_printf provides all the functionality needed by all the printf
* variants.
#define BUF(x) ((x) ? (x) + cnum : (x))
#define SZ(x) ((x) ? (x) - cnum : (x))
-static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap)
+static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap)
{
char conv_buf[32];
char *str;
base = 16;
if(alt) {
- bwrite(BUF(buf), SZ(sz), "0x", 2);
+ bwrite(out, BUF(buf), SZ(sz), "0x", 2);
}
case 'u':
base = 8;
if(alt) {
- bwrite(BUF(buf), SZ(sz), "0", 1);
+ bwrite(out, BUF(buf), SZ(sz), "0", 1);
}
}
slen = strlen(conv_buf);
for(i=slen; i<fwidth; i++) {
- bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
+ bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
cnum++;
}
- bwrite(BUF(buf), SZ(sz), conv_buf, strlen(conv_buf));
+ bwrite(out, BUF(buf), SZ(sz), conv_buf, strlen(conv_buf));
cnum += slen;
break;
case 'c':
{
char c = va_arg(ap, int);
- bwrite(BUF(buf), SZ(sz), &c, 1);
+ bwrite(out, BUF(buf), SZ(sz), &c, 1);
cnum++;
}
break;
slen = strlen(str);
for(i=slen; i<fwidth; i++) {
- bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
+ bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
cnum++;
}
- bwrite(BUF(buf), SZ(sz), str, slen);
+ bwrite(out, BUF(buf), SZ(sz), str, slen);
cnum += slen;
break;
fmt++;
}
} else {
- bwrite(BUF(buf), SZ(sz), (char*)fmt++, 1);
+ bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
cnum++;
}
}
/* bwrite is called by intern_printf to transparently handle writing into a
- * buffer (if buf is non-null) or to the terminal (if buf is null).
+ * buffer or to the terminal
*/
-static void bwrite(char *buf, size_t buf_sz, char *str, int sz)
+static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz)
{
- if(buf) {
+ int i;
+
+ if(out == OUT_BUF) {
if(buf_sz && buf_sz <= sz) sz = buf_sz - 1;
memcpy(buf, str, sz);
buf[sz] = 0;
} else {
- int i;
- for(i=0; i<sz; i++) {
- putchar(*str++);
+ switch(out) {
+ case OUT_DEF:
+ for(i=0; i<sz; i++) {
+ putchar(*str++);
+ }
+ break;
+
+ case OUT_SER:
+ for(i=0; i<sz; i++) {
+ ser_putchar(*str++);
+ }
+ break;
+
+ default:
+ /* TODO: OUT_SCR */
+ break;
}
}
}
#include "keyb.h"
#include "kbregs.h"
-static void init_mouse();
+static void init_mouse(void);
+static void proc_mouse_data(unsigned char *data);
static void psaux_intr();
static int mx, my;
static unsigned int bnstate;
static int present;
static int bounds[4];
+static int intr_mode;
void init_psaux(void)
{
interrupt(IRQ_TO_INTR(12), psaux_intr);
- set_mouse_bounds(0, 0, 319, 199);
-
init_mouse();
+ set_mouse_bounds(0, 0, 319, 199);
}
-static void init_mouse()
+static void init_mouse(void)
{
unsigned char val;
printf("aux enable: %02x\n", (unsigned int)val);
}
+ /*
+ kb_send_cmd(KB_CMD_PSAUX);
+ kb_send_data(AUX_CMD_REMOTE_MODE);
+ val = kb_read_data();
+ */
+
kb_send_cmd(KB_CMD_GET_CMDBYTE);
val = kb_read_data();
val &= ~KB_CCB_AUX_DISABLE;
val = kb_read_data();
printf("set cmdbyte: %02x\n", (unsigned int)val);
}
+ intr_mode = 1;
kb_send_cmd(KB_CMD_PSAUX);
kb_send_data(AUX_CMD_DEFAULTS);
unsigned int mouse_state(int *xp, int *yp)
{
+ if(!intr_mode) {
+ poll_mouse();
+ }
+
*xp = mx;
*yp = my;
return bnstate;
}
+/* TODO: poll_mouse doesn't work (enable remote mode and disable interrupt on init to test) */
+#define STAT_AUX_PENDING (KB_STAT_OUTBUF_FULL | KB_STAT_AUX)
+static inline int aux_pending(void)
+{
+ return (inb(KB_STATUS_PORT) & STAT_AUX_PENDING) == STAT_AUX_PENDING ? 1 : 0;
+}
+
+void poll_mouse(void)
+{
+ static int poll_state;
+ static unsigned char pkt[3];
+ unsigned char rd;
+
+ ser_printf("poll_mouse(%d)\n", poll_state);
+
+ switch(poll_state) {
+ case 0: /* send read mouse command */
+ kb_send_cmd(KB_CMD_PSAUX);
+ kb_send_data(AUX_CMD_READ_MOUSE);
+ ++poll_state;
+ break;
+
+ case 1: /* wait for ACK */
+ if(kb_wait_read()) {// && aux_pending()) {
+ if((rd = kb_read_data()) == KB_ACK) {
+ ++poll_state;
+ } else {
+ ser_printf("poll_mouse state 1: expected ack: %02x\n", (unsigned int)rd);
+ }
+ }
+ break;
+
+ case 2: /* read packet data */
+ case 3:
+ case 4:
+ if(kb_wait_read() && aux_pending()) {
+ int i = poll_state++ - 2;
+ pkt[i] = kb_read_data();
+ }
+ if(poll_state == 5) {
+ ser_printf("proc_mouse_data(%02x %02x %02x)\n", (unsigned int)pkt[0],
+ (unsigned int)pkt[1], (unsigned int)pkt[2]);
+ proc_mouse_data(pkt);
+ poll_state = 0;
+ }
+ break;
+
+ default:
+ ser_printf("poll_mouse reached state: %d\n", poll_state);
+ }
+}
+
+static void proc_mouse_data(unsigned char *data)
+{
+ int dx, dy;
+
+ 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 {
+ 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];
+ }
+}
+
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 */
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');
- */
- }
+ proc_mouse_data(data);
}
}