MassCommit(tm) to fix the MCA ESDI driver, clean up all RLL-ESDI stuff, rename HDD-related files, and another version of the AHA-1640, which now works. Not done yet, but getting close!
This commit is contained in:
451
src/mouse_bus.c
451
src/mouse_bus.c
@@ -32,11 +32,11 @@
|
||||
* Based on an early driver for MINIX 1.5.
|
||||
* Based on the 86Box PS/2 mouse driver as a framework.
|
||||
*
|
||||
* Version: @(#)mouse_bus.c 1.0.7 2017/07/27
|
||||
* Version: @(#)mouse_bus.c 1.0.8 2017/08/03
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* TheCollector1995,
|
||||
* Copyright 1989-2017 Fred N. van Kempen, TheCollector1995.
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* TheCollector1995
|
||||
* Copyright 1989-2017 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -47,6 +47,395 @@
|
||||
#include "mouse.h"
|
||||
|
||||
|
||||
#define BUSMOUSE_PORT 0x023c
|
||||
#define BUSMOUSE_PORTLEN 4
|
||||
#define BUSMOUSE_IRQ 5
|
||||
|
||||
|
||||
#define ENABLE_3BTN 1 /* enable 3-button mode */
|
||||
|
||||
|
||||
/* Our mouse device. */
|
||||
typedef struct mouse_bus {
|
||||
int8_t type;
|
||||
uint8_t flags; /* device flags */
|
||||
uint16_t port; /* I/O port range start */
|
||||
uint16_t portlen; /* length of I/O port range */
|
||||
int8_t irq; /* IRQ channel to use */
|
||||
|
||||
uint8_t r_magic; /* MAGIC register */
|
||||
uint8_t r_ctrl; /* CONTROL register (WR) */
|
||||
uint8_t r_intr; /* INTSTAT register (RO) */
|
||||
uint8_t r_conf; /* CONFIG register */
|
||||
|
||||
int8_t x, y; /* current mouse status */
|
||||
uint8_t but;
|
||||
|
||||
uint8_t (*read)(struct mouse_bus *, uint16_t);
|
||||
void (*write)(struct mouse_bus *, uint16_t, uint8_t);
|
||||
} mouse_bus_t;
|
||||
#define MOUSE_ENABLED 0x80 /* device is enabled for use */
|
||||
#define MOUSE_FROZEN 0x01 /* do not update counters */
|
||||
|
||||
|
||||
/* Definitions for Logitech. */
|
||||
#define LTMOUSE_DATA 0 /* DATA register */
|
||||
#define LTMOUSE_MAGIC 1 /* signature magic register */
|
||||
# define MAGIC_BYTE1 0xa5 /* most drivers use this */
|
||||
# define MAGIC_BYTE2 0x5a /* some drivers use this */
|
||||
#define LTMOUSE_CTRL 2 /* CTRL register */
|
||||
# define CTRL_FREEZE 0x80 /* do not sample when set */
|
||||
# define CTRL_RD_Y_HI 0x60 /* plus FREEZE */
|
||||
# define CTRL_RD_Y_LO 0x40 /* plus FREEZE */
|
||||
# define CTRL_RD_X_HI 0x20 /* plus FREEZE */
|
||||
# define CTRL_RD_X_LO 0x00 /* plus FREEZE */
|
||||
# define CTRL_RD_MASK 0x60
|
||||
# define CTRL_IDIS 0x10
|
||||
# define CTRL_IENB 0x00
|
||||
#define LTMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
/* Definitions for Microsoft. */
|
||||
#define MSMOUSE_CTRL 0 /* CTRL register */
|
||||
# define MSCTRL_RESET 0x80
|
||||
# define MSCTRL_MODE 0x07
|
||||
# define MSCTRL_RD_Y 0x02
|
||||
# define MSCTRL_RD_X 0x01
|
||||
# define MSCTRL_RD_BUT 0x00
|
||||
#define MSMOUSE_DATA 1 /* DATA register */
|
||||
# define MSDATA_BASE 0x10
|
||||
# define MSDATA_IRQ 0x01
|
||||
#define MSMOUSE_MAGIC 2 /* MAGIC register */
|
||||
# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */
|
||||
# define MAGIC_MSBYTE2 0xad
|
||||
#define MSMOUSE_CONFIG 3 /* CONFIG register */
|
||||
|
||||
|
||||
/* Handle a WRITE to a LOGITECH register. */
|
||||
static void
|
||||
lt_write(mouse_bus_t *ms, uint16_t port, uint8_t val)
|
||||
{
|
||||
uint8_t b = (ms->r_ctrl ^ val);
|
||||
|
||||
#if 0
|
||||
pclog("BUSMOUSE: lt_write(%d,%02x)\n", port, val);
|
||||
#endif
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
if (val == MAGIC_BYTE1 || val == MAGIC_BYTE2) {
|
||||
ms->r_magic = val;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
if (b & CTRL_FREEZE) {
|
||||
if (val & CTRL_FREEZE) {
|
||||
/* Hold the sampling while we do something. */
|
||||
ms->flags |= MOUSE_FROZEN;
|
||||
} else {
|
||||
/* Reset current state. */
|
||||
ms->x = ms->y = 0;
|
||||
if (ms->but)
|
||||
/* One more POLL for button-release. */
|
||||
ms->but = 0x80;
|
||||
ms->flags &= ~MOUSE_FROZEN;
|
||||
}
|
||||
}
|
||||
|
||||
if (b & CTRL_IDIS) {
|
||||
/* Disable or enable interrupts. */
|
||||
/* (we don't do anything for that here..) */
|
||||
}
|
||||
|
||||
/* Save new register value. */
|
||||
ms->r_ctrl = val;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
ms->r_conf = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ from a LOGITECH register. */
|
||||
static uint8_t
|
||||
lt_read(mouse_bus_t *ms, uint16_t port)
|
||||
{
|
||||
uint8_t r = 0xff;
|
||||
|
||||
switch (port) {
|
||||
case LTMOUSE_DATA: /* [00] data register */
|
||||
if (! (ms->r_ctrl & CTRL_FREEZE)) {
|
||||
r = 0x00;
|
||||
} else switch(ms->r_ctrl & CTRL_RD_MASK) {
|
||||
case CTRL_RD_X_LO: /* X, low bits */
|
||||
/*
|
||||
* Some drivers expect the buttons to
|
||||
* be in this byte. Others want it in
|
||||
* the Y-LO byte. --FvK
|
||||
*/
|
||||
r = 0x07;
|
||||
if (ms->but & 0x01) /*LEFT*/
|
||||
r &= ~0x04;
|
||||
if (ms->but & 0x02) /*RIGHT*/
|
||||
r &= ~0x01;
|
||||
#if ENABLE_3BTN
|
||||
if (ms->but & 0x04) /*MIDDLE*/
|
||||
r &= ~0x02;
|
||||
#endif
|
||||
r <<= 5;
|
||||
r |= (ms->x & 0x0f);
|
||||
break;
|
||||
|
||||
case CTRL_RD_X_HI: /* X, high bits */
|
||||
r = (ms->x >> 4) & 0x0f;
|
||||
break;
|
||||
|
||||
case CTRL_RD_Y_LO: /* Y, low bits */
|
||||
r = (ms->y & 0x0f);
|
||||
break;
|
||||
|
||||
case CTRL_RD_Y_HI: /* Y, high bits */
|
||||
/*
|
||||
* Some drivers expect the buttons to
|
||||
* be in this byte. Others want it in
|
||||
* the X-LO byte. --FvK
|
||||
*/
|
||||
r = 0x07;
|
||||
if (ms->but & 0x01) /*LEFT*/
|
||||
r &= ~0x04;
|
||||
if (ms->but & 0x02) /*RIGHT*/
|
||||
r &= ~0x01;
|
||||
#if ENABLE_3BTN
|
||||
if (ms->but & 0x04) /*MIDDLE*/
|
||||
r &= ~0x02;
|
||||
#endif
|
||||
r <<= 5;
|
||||
r |= (ms->y >> 4) & 0x0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_MAGIC: /* [01] magic data register */
|
||||
/*
|
||||
* Logitech drivers start out by blasting their magic
|
||||
* value (0xA5) into this register, and then read it
|
||||
* back to see if that worked. If it did (and we do
|
||||
* support this) the controller is assumed to be a
|
||||
* Logitech-protocol one, and not InPort.
|
||||
*/
|
||||
r = ms->r_magic;
|
||||
break;
|
||||
|
||||
case LTMOUSE_CTRL: /* [02] control register */
|
||||
/*
|
||||
* This is the weird stuff mentioned in the file header
|
||||
* above. Microsoft's "mouse.exe" does some whacky stuff
|
||||
* to extract the configured IRQ channel from the board.
|
||||
*
|
||||
* First, it reads the current value, and then re-reads
|
||||
* it another 10,000 (yes, really) times. It keeps track
|
||||
* of whether or not the data has changed, most likely
|
||||
* to de-bounce reading of a DIP switch for example. This
|
||||
* first value is assumed to be the 2's complement of the
|
||||
* actual IRQ value.
|
||||
* Next, it does this a second time, but now with the
|
||||
* IDIS bit clear (so, interrupts enabled), which is
|
||||
* our cue to return the regular (not complemented) value
|
||||
* to them.
|
||||
*
|
||||
* Since we have to fake the initial value and the settling
|
||||
* of the data a bit later on, we first return a bunch of
|
||||
* invalid ("random") data, and then the real value.
|
||||
*
|
||||
* Yes, this is weird. --FvK
|
||||
*/
|
||||
if (ms->r_intr++ < 250)
|
||||
/* Still settling, return invalid data. */
|
||||
r = (ms->r_ctrl&CTRL_IDIS)?0xff:0x00;
|
||||
else {
|
||||
/* OK, all good, return correct data. */
|
||||
r = (ms->r_ctrl&CTRL_IDIS)?-ms->irq:ms->irq;
|
||||
ms->r_intr = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTMOUSE_CONFIG: /* [03] config register */
|
||||
r = ms->r_conf;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
pclog("BUSMOUSE: lt_read(%d): %02x\n", port, r);
|
||||
#endif
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the Logitech Bus Mouse interface. */
|
||||
static void
|
||||
lt_init(mouse_bus_t *ms)
|
||||
{
|
||||
pclog("Logitech Bus Mouse, I/O=%04x, IRQ=%d\n", ms->port, ms->irq);
|
||||
|
||||
/* Initialize registers. */
|
||||
ms->r_magic = 0x00;
|
||||
ms->r_conf = 0x91; /* 8255 controller config */
|
||||
ms->r_ctrl = (CTRL_IDIS);
|
||||
|
||||
/* Initialize I/O handlers. */
|
||||
ms->read = lt_read;
|
||||
ms->write = lt_write;
|
||||
|
||||
/* All done. */
|
||||
ms->flags = 0x00;
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
busmouse_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
mouse_bus_t *ms = (mouse_bus_t *)priv;
|
||||
|
||||
ms->write(ms, port-ms->port, val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
busmouse_read(uint16_t port, void *priv)
|
||||
{
|
||||
mouse_bus_t *ms = (mouse_bus_t *)priv;
|
||||
uint8_t r;
|
||||
|
||||
r = ms->read(ms, port-ms->port);
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/* The emulator calls us with an update on the host mouse device. */
|
||||
static uint8_t
|
||||
busmouse_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
mouse_bus_t *ms = (mouse_bus_t *)priv;
|
||||
|
||||
/* Return early if nothing to do. */
|
||||
if (!x && !y && !z && (ms->but == b)) return(1);
|
||||
|
||||
/* If we are not interested, return. */
|
||||
if (!(ms->flags & MOUSE_ENABLED) || (ms->flags & MOUSE_FROZEN)) return(0);
|
||||
|
||||
#if 0
|
||||
pclog("BUSMOUSE: poll(%d,%d,%d, %02x)\n", x, y, z, b);
|
||||
#endif
|
||||
|
||||
/* Add the delta to our state. */
|
||||
x += ms->x;
|
||||
if (x > 127)
|
||||
x = 127;
|
||||
if (x < -128)
|
||||
x = -128;
|
||||
ms->x = (int8_t)x;
|
||||
|
||||
y += ms->y;
|
||||
if (y > 127)
|
||||
y = 127;
|
||||
if (y < -128)
|
||||
y = -128;
|
||||
ms->y = (int8_t)y;
|
||||
|
||||
ms->but = b;
|
||||
|
||||
/* All set, generate an interrupt. */
|
||||
if (! (ms->r_ctrl & CTRL_IDIS))
|
||||
picint(1 << ms->irq);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void
|
||||
busmouse_close(void *priv)
|
||||
{
|
||||
mouse_bus_t *ms = (mouse_bus_t *)priv;
|
||||
|
||||
/* Release our I/O range. */
|
||||
io_removehandler(ms->port, ms->portlen,
|
||||
busmouse_read, NULL, NULL, busmouse_write, NULL, NULL, ms);
|
||||
|
||||
free(ms);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
busmouse_init(int type)
|
||||
{
|
||||
mouse_bus_t *ms;
|
||||
|
||||
ms = (mouse_bus_t *)malloc(sizeof(mouse_bus_t));
|
||||
memset(ms, 0x00, sizeof(mouse_bus_t));
|
||||
ms->type = type;
|
||||
ms->port = BUSMOUSE_PORT;
|
||||
ms->portlen = BUSMOUSE_PORTLEN;
|
||||
#if BUSMOUSE_IRQ
|
||||
ms->irq = BUSMOUSE_IRQ;
|
||||
#else
|
||||
ms->irq = -1;
|
||||
#endif
|
||||
|
||||
switch(ms->type) {
|
||||
case MOUSE_TYPE_LOGIBUS:
|
||||
lt_init(ms);
|
||||
break;
|
||||
|
||||
case MOUSE_TYPE_INPORT:
|
||||
// ms_init(ms);
|
||||
break;
|
||||
}
|
||||
ms->flags |= MOUSE_ENABLED;
|
||||
|
||||
/* Request an I/O range. */
|
||||
io_sethandler(ms->port, ms->portlen,
|
||||
busmouse_read, NULL, NULL, busmouse_write, NULL, NULL, ms);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(ms);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
logibus_init(void)
|
||||
{
|
||||
return(busmouse_init(MOUSE_TYPE_LOGIBUS));
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
inport_init(void)
|
||||
{
|
||||
return(busmouse_init(MOUSE_TYPE_LOGIBUS));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
@@@@
|
||||
|
||||
#define BUS_MOUSE_IRQ 5
|
||||
#define IRQ_MASK ((1<<5) >> BUS_MOUSE_IRQ)
|
||||
|
||||
@@ -394,44 +783,6 @@ static uint8_t busmouse_poll(int x, int y, int z, int b, void *priv)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Release all resources held by the device. */
|
||||
static void busmouse_close(void *priv)
|
||||
{
|
||||
mouse_bus_t *busmouse = (mouse_bus_t *)priv;
|
||||
|
||||
/* Release our I/O range. */
|
||||
io_removehandler(0x023C, 0x0004, busmouse_read, NULL, NULL, busmouse_write, NULL, NULL, busmouse);
|
||||
|
||||
free(busmouse);
|
||||
}
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *busmouse_init(void)
|
||||
{
|
||||
mouse_bus_t *busmouse;
|
||||
|
||||
busmouse = (mouse_bus_t *)malloc(sizeof(mouse_bus_t));
|
||||
memset(busmouse, 0x00, sizeof(mouse_bus_t));
|
||||
|
||||
busmouse->is_inport = 0;
|
||||
busmouse->irq = BUS_MOUSE_IRQ;
|
||||
|
||||
/* Initialize registers. */
|
||||
busmouse->control_val = 0x1f; /* The control port value */
|
||||
busmouse->config_val = 0x0e; /* The config port value */
|
||||
|
||||
/* Common. */
|
||||
busmouse->command_val = 0;
|
||||
busmouse->toggle_counter = 0;
|
||||
busmouse->interrupts = 0;
|
||||
|
||||
/* Request an I/O range. */
|
||||
io_sethandler(0x023C, 0x0004, busmouse_read, NULL, NULL, busmouse_write, NULL, NULL, busmouse);
|
||||
timer_add(busmouse_timer_handler, &busmouse->timer_index, TIMER_ALWAYS_ENABLED, busmouse);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(busmouse);
|
||||
}
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *inport_init(void)
|
||||
@@ -460,21 +811,21 @@ static void *inport_init(void)
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(inport);
|
||||
}
|
||||
#endif
|
||||
|
||||
mouse_t mouse_bus_logitech =
|
||||
{
|
||||
|
||||
mouse_t mouse_bus_logitech = {
|
||||
"Logitech Bus Mouse",
|
||||
"msbus",
|
||||
"logibus",
|
||||
MOUSE_TYPE_LOGIBUS,
|
||||
busmouse_init,
|
||||
logibus_init,
|
||||
busmouse_close,
|
||||
busmouse_poll
|
||||
};
|
||||
|
||||
mouse_t mouse_bus_msinport =
|
||||
{
|
||||
"InPort Mouse",
|
||||
"inport",
|
||||
mouse_t mouse_bus_msinport = {
|
||||
"Microsoft Bus Mouse (InPort)",
|
||||
"msbus",
|
||||
MOUSE_TYPE_INPORT,
|
||||
inport_init,
|
||||
busmouse_close,
|
||||
|
||||
Reference in New Issue
Block a user