clang-format in src/device/
This commit is contained in:
@@ -62,76 +62,69 @@
|
||||
#include <86box/ui.h>
|
||||
#include <86box/bugger.h>
|
||||
|
||||
|
||||
/* BugBugger registers. */
|
||||
#define BUG_CTRL 0
|
||||
# define CTRL_RLED 0x00 /* write to the RED LED block */
|
||||
# define CTRL_GLED 0x01 /* write to the GREEN LED block */
|
||||
# define CTRL_SEG1 0x02 /* write to the RIGHT 7SEG displays */
|
||||
# define CTRL_SEG2 0x04 /* write to the LEFT 7SEG displays */
|
||||
# define CTRL_SPORT 0x20 /* enable the serial port */
|
||||
# define CTRL_SPCFG 0x40 /* set up the serial port */
|
||||
# define CTRL_INIT 0x80 /* enable and reset the card */
|
||||
# define CTRL_RESET 0xff /* this resets the board */
|
||||
#define BUG_DATA 1
|
||||
#define BUG_CTRL 0
|
||||
#define CTRL_RLED 0x00 /* write to the RED LED block */
|
||||
#define CTRL_GLED 0x01 /* write to the GREEN LED block */
|
||||
#define CTRL_SEG1 0x02 /* write to the RIGHT 7SEG displays */
|
||||
#define CTRL_SEG2 0x04 /* write to the LEFT 7SEG displays */
|
||||
#define CTRL_SPORT 0x20 /* enable the serial port */
|
||||
#define CTRL_SPCFG 0x40 /* set up the serial port */
|
||||
#define CTRL_INIT 0x80 /* enable and reset the card */
|
||||
#define CTRL_RESET 0xff /* this resets the board */
|
||||
#define BUG_DATA 1
|
||||
|
||||
static uint8_t bug_ctrl, /* control register */
|
||||
bug_data, /* data register */
|
||||
bug_ledr, bug_ledg, /* RED and GREEN LEDs */
|
||||
bug_seg1, bug_seg2, /* LEFT and RIGHT 7SEG displays */
|
||||
bug_spcfg; /* serial port configuration */
|
||||
#define FIFO_LEN 256
|
||||
static uint8_t bug_buff[FIFO_LEN], /* serial port data buffer */
|
||||
*bug_bptr;
|
||||
#define UISTR_LEN 24
|
||||
static char bug_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
static uint8_t bug_ctrl, /* control register */
|
||||
bug_data, /* data register */
|
||||
bug_ledr, bug_ledg, /* RED and GREEN LEDs */
|
||||
bug_seg1, bug_seg2, /* LEFT and RIGHT 7SEG displays */
|
||||
bug_spcfg; /* serial port configuration */
|
||||
# define FIFO_LEN 256
|
||||
static uint8_t bug_buff[FIFO_LEN], /* serial port data buffer */
|
||||
*bug_bptr;
|
||||
# define UISTR_LEN 24
|
||||
static char bug_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
|
||||
extern void ui_sb_bugui(char *__str);
|
||||
|
||||
extern void ui_sb_bugui(char *__str);
|
||||
|
||||
#ifdef ENABLE_BUGGER_LOG
|
||||
int bugger_do_log = ENABLE_BUGGER_LOG;
|
||||
|
||||
|
||||
static void
|
||||
bugger_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (bugger_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define bugger_log(fmt, ...)
|
||||
# define bugger_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Update the system's UI with the actual Bugger status. */
|
||||
static void
|
||||
bug_setui(void)
|
||||
{
|
||||
/* Format all current info in a string. */
|
||||
sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c",
|
||||
bug_seg2, bug_seg1,
|
||||
(bug_ledg&0x80)?'G':'g', (bug_ledg&0x40)?'G':'g',
|
||||
(bug_ledg&0x20)?'G':'g', (bug_ledg&0x10)?'G':'g',
|
||||
(bug_ledg&0x08)?'G':'g', (bug_ledg&0x04)?'G':'g',
|
||||
(bug_ledg&0x02)?'G':'g', (bug_ledg&0x01)?'G':'g',
|
||||
(bug_ledr&0x80)?'R':'r', (bug_ledr&0x40)?'R':'r',
|
||||
(bug_ledr&0x20)?'R':'r', (bug_ledr&0x10)?'R':'r',
|
||||
(bug_ledr&0x08)?'R':'r', (bug_ledr&0x04)?'R':'r',
|
||||
(bug_ledr&0x02)?'R':'r', (bug_ledr&0x01)?'R':'r');
|
||||
bug_seg2, bug_seg1,
|
||||
(bug_ledg & 0x80) ? 'G' : 'g', (bug_ledg & 0x40) ? 'G' : 'g',
|
||||
(bug_ledg & 0x20) ? 'G' : 'g', (bug_ledg & 0x10) ? 'G' : 'g',
|
||||
(bug_ledg & 0x08) ? 'G' : 'g', (bug_ledg & 0x04) ? 'G' : 'g',
|
||||
(bug_ledg & 0x02) ? 'G' : 'g', (bug_ledg & 0x01) ? 'G' : 'g',
|
||||
(bug_ledr & 0x80) ? 'R' : 'r', (bug_ledr & 0x40) ? 'R' : 'r',
|
||||
(bug_ledr & 0x20) ? 'R' : 'r', (bug_ledr & 0x10) ? 'R' : 'r',
|
||||
(bug_ledr & 0x08) ? 'R' : 'r', (bug_ledr & 0x04) ? 'R' : 'r',
|
||||
(bug_ledr & 0x02) ? 'R' : 'r', (bug_ledr & 0x01) ? 'R' : 'r');
|
||||
|
||||
/* Send formatted string to the UI. */
|
||||
ui_sb_bugui(bug_str);
|
||||
}
|
||||
|
||||
|
||||
/* Flush the serial port. */
|
||||
static void
|
||||
bug_spflsh(void)
|
||||
@@ -141,7 +134,6 @@ bug_spflsh(void)
|
||||
bug_bptr = bug_buff;
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the Serial Port Data register. */
|
||||
static void
|
||||
bug_wsport(uint8_t val)
|
||||
@@ -152,9 +144,9 @@ bug_wsport(uint8_t val)
|
||||
bug_ctrl &= ~CTRL_SPORT;
|
||||
|
||||
/* Delay while processing byte.. */
|
||||
if (bug_bptr == &bug_buff[FIFO_LEN-1]) {
|
||||
/* Buffer full, gotta flush. */
|
||||
bug_spflsh();
|
||||
if (bug_bptr == &bug_buff[FIFO_LEN - 1]) {
|
||||
/* Buffer full, gotta flush. */
|
||||
bug_spflsh();
|
||||
}
|
||||
|
||||
/* Write (store) the byte. */
|
||||
@@ -166,7 +158,6 @@ bug_wsport(uint8_t val)
|
||||
bugger_log("BUGGER- sport %02x\n", val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the Serial Port Configuration register. */
|
||||
static void
|
||||
bug_wspcfg(uint8_t val)
|
||||
@@ -176,50 +167,48 @@ bug_wspcfg(uint8_t val)
|
||||
bugger_log("BUGGER- spcfg %02x\n", bug_spcfg);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the control register. */
|
||||
static void
|
||||
bug_wctrl(uint8_t val)
|
||||
{
|
||||
if (val == CTRL_RESET) {
|
||||
/* User wants us to reset. */
|
||||
bug_ctrl = CTRL_INIT;
|
||||
bug_spcfg = 0x00;
|
||||
bug_bptr = NULL;
|
||||
/* User wants us to reset. */
|
||||
bug_ctrl = CTRL_INIT;
|
||||
bug_spcfg = 0x00;
|
||||
bug_bptr = NULL;
|
||||
} else {
|
||||
/* If turning off the serial port, flush it. */
|
||||
if ((bug_ctrl & CTRL_SPORT) && !(val & CTRL_SPORT))
|
||||
bug_spflsh();
|
||||
/* If turning off the serial port, flush it. */
|
||||
if ((bug_ctrl & CTRL_SPORT) && !(val & CTRL_SPORT))
|
||||
bug_spflsh();
|
||||
|
||||
/* FIXME: did they do this using an XOR of operation bits? --FvK */
|
||||
/* FIXME: did they do this using an XOR of operation bits? --FvK */
|
||||
|
||||
if (val & CTRL_SPCFG) {
|
||||
/* User wants to configure the serial port. */
|
||||
bug_ctrl &= ~(CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SPCFG;
|
||||
} else if (val & CTRL_SPORT) {
|
||||
/* User wants to talk to the serial port. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SEG2|CTRL_SEG1|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SPORT;
|
||||
if (bug_bptr == NULL)
|
||||
bug_bptr = bug_buff;
|
||||
} else if (val & CTRL_SEG2) {
|
||||
/* User selected SEG2 (LEFT, Plus only) for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG1|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SEG2;
|
||||
} else if (val & CTRL_SEG1) {
|
||||
/* User selected SEG1 (RIGHT) for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SEG1;
|
||||
} else if (val & CTRL_GLED) {
|
||||
/* User selected the GREEN LEDs for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1);
|
||||
bug_ctrl |= CTRL_GLED;
|
||||
} else {
|
||||
/* User selected the RED LEDs for output. */
|
||||
bug_ctrl &=
|
||||
~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED);
|
||||
}
|
||||
if (val & CTRL_SPCFG) {
|
||||
/* User wants to configure the serial port. */
|
||||
bug_ctrl &= ~(CTRL_SPORT | CTRL_SEG2 | CTRL_SEG1 | CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SPCFG;
|
||||
} else if (val & CTRL_SPORT) {
|
||||
/* User wants to talk to the serial port. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG | CTRL_SEG2 | CTRL_SEG1 | CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SPORT;
|
||||
if (bug_bptr == NULL)
|
||||
bug_bptr = bug_buff;
|
||||
} else if (val & CTRL_SEG2) {
|
||||
/* User selected SEG2 (LEFT, Plus only) for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG1 | CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SEG2;
|
||||
} else if (val & CTRL_SEG1) {
|
||||
/* User selected SEG1 (RIGHT) for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG2 | CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SEG1;
|
||||
} else if (val & CTRL_GLED) {
|
||||
/* User selected the GREEN LEDs for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG2 | CTRL_SEG1);
|
||||
bug_ctrl |= CTRL_GLED;
|
||||
} else {
|
||||
/* User selected the RED LEDs for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG2 | CTRL_SEG1 | CTRL_GLED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the UI with active settings. */
|
||||
@@ -227,7 +216,6 @@ bug_wctrl(uint8_t val)
|
||||
bug_setui();
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the data register. */
|
||||
static void
|
||||
bug_wdata(uint8_t val)
|
||||
@@ -235,27 +223,26 @@ bug_wdata(uint8_t val)
|
||||
bug_data = val;
|
||||
|
||||
if (bug_ctrl & CTRL_SPCFG)
|
||||
bug_wspcfg(val);
|
||||
else if (bug_ctrl & CTRL_SPORT)
|
||||
bug_wsport(val);
|
||||
else {
|
||||
if (bug_ctrl & CTRL_SEG2)
|
||||
bug_seg2 = val;
|
||||
else if (bug_ctrl & CTRL_SEG1)
|
||||
bug_seg1 = val;
|
||||
else if (bug_ctrl & CTRL_GLED)
|
||||
bug_ledg = val;
|
||||
else
|
||||
bug_ledr = val;
|
||||
bug_wspcfg(val);
|
||||
else if (bug_ctrl & CTRL_SPORT)
|
||||
bug_wsport(val);
|
||||
else {
|
||||
if (bug_ctrl & CTRL_SEG2)
|
||||
bug_seg2 = val;
|
||||
else if (bug_ctrl & CTRL_SEG1)
|
||||
bug_seg1 = val;
|
||||
else if (bug_ctrl & CTRL_GLED)
|
||||
bug_ledg = val;
|
||||
else
|
||||
bug_ledr = val;
|
||||
|
||||
bugger_log("BUGGER- data %02x\n", bug_data);
|
||||
bugger_log("BUGGER- data %02x\n", bug_data);
|
||||
}
|
||||
|
||||
/* Update the UI with active settings. */
|
||||
bug_setui();
|
||||
}
|
||||
|
||||
|
||||
/* Reset the ISA BusBugger controller. */
|
||||
static void
|
||||
bug_reset(void)
|
||||
@@ -264,71 +251,70 @@ bug_reset(void)
|
||||
bug_data = 0x00;
|
||||
|
||||
/* Clear the RED and GREEN LEDs. */
|
||||
bug_ledr = 0x00; bug_ledg = 0x00;
|
||||
bug_ledr = 0x00;
|
||||
bug_ledg = 0x00;
|
||||
|
||||
/* Clear both 7SEG displays. */
|
||||
bug_seg1 = 0x00; bug_seg2 = 0x00;
|
||||
bug_seg1 = 0x00;
|
||||
bug_seg2 = 0x00;
|
||||
|
||||
/* Reset the control register (updates UI.) */
|
||||
bug_wctrl(CTRL_RESET);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bug_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
switch (port-BUGGER_ADDR) {
|
||||
case BUG_CTRL: /* control register */
|
||||
if (val == CTRL_RESET) {
|
||||
/* Perform a full reset. */
|
||||
bug_reset();
|
||||
} else if (bug_ctrl & CTRL_INIT) {
|
||||
/* Only allow writes if initialized. */
|
||||
bug_wctrl(val);
|
||||
}
|
||||
break;
|
||||
|
||||
case BUG_DATA: /* data register */
|
||||
if (bug_ctrl & CTRL_INIT) {
|
||||
bug_wdata(val);
|
||||
}
|
||||
break;
|
||||
switch (port - BUGGER_ADDR) {
|
||||
case BUG_CTRL: /* control register */
|
||||
if (val == CTRL_RESET) {
|
||||
/* Perform a full reset. */
|
||||
bug_reset();
|
||||
} else if (bug_ctrl & CTRL_INIT) {
|
||||
/* Only allow writes if initialized. */
|
||||
bug_wctrl(val);
|
||||
}
|
||||
break;
|
||||
|
||||
case BUG_DATA: /* data register */
|
||||
if (bug_ctrl & CTRL_INIT) {
|
||||
bug_wdata(val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bug_read(uint16_t port, void *priv)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (bug_ctrl & CTRL_INIT) switch (port-BUGGER_ADDR) {
|
||||
case BUG_CTRL: /* control register */
|
||||
ret = bug_ctrl;
|
||||
break;
|
||||
if (bug_ctrl & CTRL_INIT)
|
||||
switch (port - BUGGER_ADDR) {
|
||||
case BUG_CTRL: /* control register */
|
||||
ret = bug_ctrl;
|
||||
break;
|
||||
|
||||
case BUG_DATA: /* data register */
|
||||
if (bug_ctrl & CTRL_SPCFG) {
|
||||
ret = bug_spcfg;
|
||||
} else if (bug_ctrl & CTRL_SPORT) {
|
||||
ret = 0x00; /* input not supported */
|
||||
} else {
|
||||
/* Just read the DIP switch. */
|
||||
ret = bug_data;
|
||||
}
|
||||
break;
|
||||
case BUG_DATA: /* data register */
|
||||
if (bug_ctrl & CTRL_SPCFG) {
|
||||
ret = bug_spcfg;
|
||||
} else if (bug_ctrl & CTRL_SPORT) {
|
||||
ret = 0x00; /* input not supported */
|
||||
} else {
|
||||
/* Just read the DIP switch. */
|
||||
ret = bug_data;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the ISA BusBugger emulator. */
|
||||
static void *
|
||||
bug_init(const device_t *info)
|
||||
@@ -339,31 +325,30 @@ bug_init(const device_t *info)
|
||||
bug_reset();
|
||||
|
||||
io_sethandler(BUGGER_ADDR, BUGGER_ADDRLEN,
|
||||
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
|
||||
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
|
||||
|
||||
/* Just so its not NULL. */
|
||||
return(&bug_ctrl);
|
||||
return (&bug_ctrl);
|
||||
}
|
||||
|
||||
|
||||
/* Remove the ISA BusBugger emulator from the system. */
|
||||
static void
|
||||
bug_close(UNUSED(void *priv))
|
||||
{
|
||||
io_removehandler(BUGGER_ADDR, BUGGER_ADDRLEN,
|
||||
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
|
||||
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
const device_t bugger_device = {
|
||||
.name = "ISA/PCI Bus Bugger",
|
||||
.name = "ISA/PCI Bus Bugger",
|
||||
.internal_name = "bugger",
|
||||
.flags = DEVICE_ISA | DEVICE_AT,
|
||||
.local = 0,
|
||||
.init = bug_init,
|
||||
.close = bug_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_ISA | DEVICE_AT,
|
||||
.local = 0,
|
||||
.init = bug_init,
|
||||
.close = bug_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
@@ -29,43 +29,36 @@
|
||||
#include <86box/machine.h>
|
||||
#include <86box/cartridge.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t * buf;
|
||||
uint32_t base;
|
||||
uint8_t *buf;
|
||||
uint32_t base;
|
||||
} cart_t;
|
||||
|
||||
char cart_fns[2][512];
|
||||
|
||||
char cart_fns[2][512];
|
||||
|
||||
|
||||
static cart_t carts[2];
|
||||
|
||||
static mem_mapping_t cart_mappings[2];
|
||||
static cart_t carts[2];
|
||||
|
||||
static mem_mapping_t cart_mappings[2];
|
||||
|
||||
#ifdef ENABLE_CARTRIDGE_LOG
|
||||
int cartridge_do_log = ENABLE_CARTRIDGE_LOG;
|
||||
|
||||
|
||||
static void
|
||||
cartridge_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
if (cartridge_do_log)
|
||||
{
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
if (cartridge_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define cartridge_log(fmt, ...)
|
||||
# define cartridge_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static uint8_t
|
||||
cart_read(uint32_t addr, void *priv)
|
||||
{
|
||||
@@ -74,22 +67,20 @@ cart_read(uint32_t addr, void *priv)
|
||||
return dev->buf[addr - dev->base];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cart_load_error(int drive, char *fn)
|
||||
{
|
||||
cartridge_log("Cartridge: could not load '%s'\n",fn);
|
||||
cartridge_log("Cartridge: could not load '%s'\n", fn);
|
||||
memset(cart_fns[drive], 0, sizeof(cart_fns[drive]));
|
||||
ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cart_image_close(int drive)
|
||||
{
|
||||
if (carts[drive].buf != NULL) {
|
||||
free(carts[drive].buf);
|
||||
carts[drive].buf = NULL;
|
||||
free(carts[drive].buf);
|
||||
carts[drive].buf = NULL;
|
||||
}
|
||||
|
||||
carts[drive].base = 0x00000000;
|
||||
@@ -97,11 +88,10 @@ cart_image_close(int drive)
|
||||
mem_mapping_disable(&cart_mappings[drive]);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cart_image_load(int drive, char *fn)
|
||||
{
|
||||
FILE *f;
|
||||
FILE *f;
|
||||
uint32_t size;
|
||||
uint32_t base = 0x00000000;
|
||||
|
||||
@@ -109,32 +99,32 @@ cart_image_load(int drive, char *fn)
|
||||
|
||||
f = fopen(fn, "rb");
|
||||
if (fseek(f, 0, SEEK_END) == -1)
|
||||
fatal("cart_image_load(): Error seeking to the end of the file\n");
|
||||
fatal("cart_image_load(): Error seeking to the end of the file\n");
|
||||
size = ftell(f);
|
||||
if (size < 0x1200) {
|
||||
cartridge_log("cart_image_load(): File size %i is too small\n", size);
|
||||
cart_load_error(drive, fn);
|
||||
return;
|
||||
cartridge_log("cart_image_load(): File size %i is too small\n", size);
|
||||
cart_load_error(drive, fn);
|
||||
return;
|
||||
}
|
||||
if (size & 0x00000fff) {
|
||||
size -= 0x00000200;
|
||||
fseek(f, 0x000001ce, SEEK_SET);
|
||||
(void) !fread(&base, 1, 2, f);
|
||||
base <<= 4;
|
||||
fseek(f, 0x00000200, SEEK_SET);
|
||||
carts[drive].buf = (uint8_t *) malloc(size);
|
||||
memset(carts[drive].buf, 0x00, size);
|
||||
(void) !fread(carts[drive].buf, 1, size, f);
|
||||
fclose(f);
|
||||
size -= 0x00000200;
|
||||
fseek(f, 0x000001ce, SEEK_SET);
|
||||
(void) !fread(&base, 1, 2, f);
|
||||
base <<= 4;
|
||||
fseek(f, 0x00000200, SEEK_SET);
|
||||
carts[drive].buf = (uint8_t *) malloc(size);
|
||||
memset(carts[drive].buf, 0x00, size);
|
||||
(void) !fread(carts[drive].buf, 1, size, f);
|
||||
fclose(f);
|
||||
} else {
|
||||
base = drive ? 0xe0000 : 0xd0000;
|
||||
if (size == 32768)
|
||||
base += 0x8000;
|
||||
fseek(f, 0x00000000, SEEK_SET);
|
||||
carts[drive].buf = (uint8_t *) malloc(size);
|
||||
memset(carts[drive].buf, 0x00, size);
|
||||
(void) !fread(carts[drive].buf, 1, size, f);
|
||||
fclose(f);
|
||||
base = drive ? 0xe0000 : 0xd0000;
|
||||
if (size == 32768)
|
||||
base += 0x8000;
|
||||
fseek(f, 0x00000000, SEEK_SET);
|
||||
carts[drive].buf = (uint8_t *) malloc(size);
|
||||
memset(carts[drive].buf, 0x00, size);
|
||||
(void) !fread(carts[drive].buf, 1, size, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
cartridge_log("cart_image_load(): %s at %08X-%08X\n", fn, base, base + size - 1);
|
||||
@@ -144,7 +134,6 @@ cart_image_load(int drive, char *fn)
|
||||
mem_mapping_set_p(&cart_mappings[drive], &(carts[drive]));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cart_load_common(int drive, char *fn, uint8_t hard_reset)
|
||||
{
|
||||
@@ -153,28 +142,26 @@ cart_load_common(int drive, char *fn, uint8_t hard_reset)
|
||||
cartridge_log("Cartridge: loading drive %d with '%s'\n", drive, fn);
|
||||
|
||||
if (!fn)
|
||||
return;
|
||||
return;
|
||||
f = plat_fopen(fn, "rb");
|
||||
if (f) {
|
||||
fclose(f);
|
||||
strcpy(cart_fns[drive], fn);
|
||||
cart_image_load(drive, cart_fns[drive]);
|
||||
/* On the real PCjr, inserting a cartridge causes a reset
|
||||
in order to boot from the cartridge. */
|
||||
if (!hard_reset)
|
||||
resetx86();
|
||||
fclose(f);
|
||||
strcpy(cart_fns[drive], fn);
|
||||
cart_image_load(drive, cart_fns[drive]);
|
||||
/* On the real PCjr, inserting a cartridge causes a reset
|
||||
in order to boot from the cartridge. */
|
||||
if (!hard_reset)
|
||||
resetx86();
|
||||
} else
|
||||
cart_load_error(drive, fn);
|
||||
cart_load_error(drive, fn);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cart_load(int drive, char *fn)
|
||||
{
|
||||
cart_load_common(drive, fn, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cart_close(int drive)
|
||||
{
|
||||
@@ -185,7 +172,6 @@ cart_close(int drive)
|
||||
ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cart_reset(void)
|
||||
{
|
||||
@@ -195,14 +181,14 @@ cart_reset(void)
|
||||
cart_image_close(0);
|
||||
|
||||
if (!machine_has_cartridge(machine))
|
||||
return;
|
||||
return;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
mem_mapping_add(&cart_mappings[i], 0x000d0000, 0x00002000,
|
||||
cart_read,NULL,NULL,
|
||||
NULL,NULL,NULL,
|
||||
NULL, MEM_MAPPING_EXTERNAL, NULL);
|
||||
mem_mapping_disable(&cart_mappings[i]);
|
||||
mem_mapping_add(&cart_mappings[i], 0x000d0000, 0x00002000,
|
||||
cart_read, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, MEM_MAPPING_EXTERNAL, NULL);
|
||||
mem_mapping_disable(&cart_mappings[i]);
|
||||
}
|
||||
|
||||
cart_load_common(0, cart_fns[0], 1);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -27,78 +27,75 @@
|
||||
#include "cpu.h"
|
||||
#include <86box/clock.h>
|
||||
|
||||
|
||||
#ifdef ENABLE_ICS9xxx_LOG
|
||||
int ics9xxx_do_log = ENABLE_ICS9xxx_LOG;
|
||||
|
||||
|
||||
static void
|
||||
ics9xxx_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (ics9xxx_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#define ICS9xxx_MODEL(model) [model] = {.name = #model,
|
||||
# define ICS9xxx_MODEL(model) [model] = { .name = # model,
|
||||
#else
|
||||
#define ics9xxx_log(fmt, ...)
|
||||
#define ICS9xxx_MODEL(model) [model] = {
|
||||
# define ics9xxx_log(fmt, ...)
|
||||
# define ICS9xxx_MODEL(model) [model] = {
|
||||
#endif
|
||||
#define ICS9xxx_MODEL_END() },
|
||||
#define agp_div ram_mult /* temporarily saves space while neither field matters */
|
||||
|
||||
|
||||
#define ICS9xxx_MODEL_END() \
|
||||
} \
|
||||
,
|
||||
#define agp_div ram_mult /* temporarily saves space while neither field matters */
|
||||
|
||||
typedef struct {
|
||||
uint16_t bus: 15;
|
||||
uint8_t ram_mult: 2; /* change to full float when this becomes useful */
|
||||
uint8_t pci_div: 3;
|
||||
uint16_t bus : 15;
|
||||
uint8_t ram_mult : 2; /* change to full float when this becomes useful */
|
||||
uint8_t pci_div : 3;
|
||||
} ics9xxx_frequency_t;
|
||||
|
||||
typedef struct {
|
||||
#if defined(ENABLE_ICS9xxx_LOG) || defined(ENABLE_ICS9xxx_DETECT)
|
||||
const char *name; /* populated by macro */
|
||||
const char *name; /* populated by macro */
|
||||
#endif
|
||||
uint8_t max_reg: 3; /* largest register index */
|
||||
uint8_t regs[7]; /* default registers */
|
||||
struct { /* for each hardware frequency select bit [FS0:FS4]: */
|
||||
uint8_t normal_reg: 3; /* which register (or -1) for non-inverted input (FSn) */
|
||||
uint8_t normal_bit: 3; /* which bit (0-7) for non-inverted input (FSn) */
|
||||
uint8_t inv_reg: 3; /* which register (or -1) for inverted input (FSn#) */
|
||||
uint8_t inv_bit: 3; /* which bit (0-7) for inverted input (FSn#) */
|
||||
uint8_t max_reg : 3; /* largest register index */
|
||||
uint8_t regs[7]; /* default registers */
|
||||
struct { /* for each hardware frequency select bit [FS0:FS4]: */
|
||||
uint8_t normal_reg : 3; /* which register (or -1) for non-inverted input (FSn) */
|
||||
uint8_t normal_bit : 3; /* which bit (0-7) for non-inverted input (FSn) */
|
||||
uint8_t inv_reg : 3; /* which register (or -1) for inverted input (FSn#) */
|
||||
uint8_t inv_bit : 3; /* which bit (0-7) for inverted input (FSn#) */
|
||||
} fs_regs[5];
|
||||
uint8_t normal_bits_fixed: 1; /* set to 1 if the non-inverted bits are straps (hardware select only) */
|
||||
struct { /* hardware select bit, which should be cleared for hardware select (latched inputs), or set for programming */
|
||||
uint8_t normal_reg: 3; /* which register (or -1) */
|
||||
uint8_t normal_bit: 3; /* which bit (0-7) */
|
||||
uint8_t normal_bits_fixed : 1; /* set to 1 if the non-inverted bits are straps (hardware select only) */
|
||||
struct { /* hardware select bit, which should be cleared for hardware select (latched inputs), or set for programming */
|
||||
uint8_t normal_reg : 3; /* which register (or -1) */
|
||||
uint8_t normal_bit : 3; /* which bit (0-7) */
|
||||
} hw_select;
|
||||
|
||||
uint8_t frequencies_ref; /* which other model to use the frequency table from (or 0) */
|
||||
const ics9xxx_frequency_t *frequencies; /* frequency table, if not using another model's table */
|
||||
uint8_t frequencies_ref; /* which other model to use the frequency table from (or 0) */
|
||||
const ics9xxx_frequency_t *frequencies; /* frequency table, if not using another model's table */
|
||||
} ics9xxx_model_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t model_idx;
|
||||
uint8_t model_idx;
|
||||
ics9xxx_model_t *model;
|
||||
device_t *dyn_device;
|
||||
device_t *dyn_device;
|
||||
|
||||
ics9xxx_frequency_t *frequencies_ptr;
|
||||
uint8_t regs[7];
|
||||
int8_t addr_register: 4;
|
||||
uint8_t relevant_regs: 7;
|
||||
uint8_t bus_match: 5;
|
||||
uint8_t regs[7];
|
||||
int8_t addr_register : 4;
|
||||
uint8_t relevant_regs : 7;
|
||||
uint8_t bus_match : 5;
|
||||
} ics9xxx_t;
|
||||
|
||||
|
||||
static const ics9xxx_model_t ics9xxx_models[] = {
|
||||
#ifdef ENABLE_ICS9xxx_DETECT
|
||||
ICS9xxx_MODEL(ICS9xxx_xx)
|
||||
.max_reg = 6
|
||||
ICS9xxx_MODEL_END()
|
||||
.max_reg
|
||||
= 6 ICS9xxx_MODEL_END()
|
||||
#endif
|
||||
ICS9xxx_MODEL(ICS9150_08)
|
||||
.max_reg = 5,
|
||||
@@ -910,13 +907,11 @@ static const ics9xxx_model_t ics9xxx_models[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* Don't enable the detection device here. Enable it further up near logging. */
|
||||
#ifdef ENABLE_ICS9xxx_DETECT
|
||||
static uint16_t detect_bus = 0;
|
||||
static uint8_t detect_reg = 0;
|
||||
static uint8_t discarded[ICS9xxx_MAX] = {0};
|
||||
|
||||
static uint16_t detect_bus = 0;
|
||||
static uint8_t detect_reg = 0;
|
||||
static uint8_t discarded[ICS9xxx_MAX] = { 0 };
|
||||
|
||||
static void
|
||||
ics9xxx_detect_reset(void *priv)
|
||||
@@ -924,71 +919,69 @@ ics9xxx_detect_reset(void *priv)
|
||||
pclog("Please enter the frequency set in the BIOS (7500 for 75.00 MHz)\nAnswer 0 if unsure or set to auto, I'll ask again next reset.\n");
|
||||
scanf("%hu", &detect_bus);
|
||||
if ((detect_bus > 0) && (detect_bus < 1000))
|
||||
detect_bus *= 100;
|
||||
detect_bus *= 100;
|
||||
pclog("Frequency interpreted as %d\n", detect_bus);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ics9xxx_detect(ics9xxx_t *dev)
|
||||
{
|
||||
if (!detect_bus) {
|
||||
pclog("Frequency not entered on this reset, ignoring change.\n");
|
||||
return;
|
||||
pclog("Frequency not entered on this reset, ignoring change.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((detect_reg == 0) && (dev->regs[detect_reg] >= 0xfe)) {
|
||||
pclog("Register %d set to %02X, probably not it, trying %d instead\n", detect_reg, dev->regs[detect_reg], 3);
|
||||
detect_reg = 3;
|
||||
dev->relevant_regs = 1 << detect_reg;
|
||||
return;
|
||||
pclog("Register %d set to %02X, probably not it, trying %d instead\n", detect_reg, dev->regs[detect_reg], 3);
|
||||
detect_reg = 3;
|
||||
dev->relevant_regs = 1 << detect_reg;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(dev->regs[detect_reg] & 0x40))
|
||||
pclog("Bit 3 of register %d is clear, probably in hardware select mode!\n", detect_reg);
|
||||
pclog("Bit 3 of register %d is clear, probably in hardware select mode!\n", detect_reg);
|
||||
|
||||
uint8_t i = 0, matches = 0, val, bitmask;
|
||||
uint8_t i = 0, matches = 0, val, bitmask;
|
||||
ics9xxx_frequency_t *frequencies_ptr;
|
||||
uint32_t delta;
|
||||
uint32_t delta;
|
||||
for (uint8_t j = 0; j < ICS9xxx_MAX; j++) {
|
||||
if (discarded[j])
|
||||
continue;
|
||||
discarded[j] = 1;
|
||||
if (discarded[j])
|
||||
continue;
|
||||
discarded[j] = 1;
|
||||
|
||||
frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_models[ics9xxx_models[j].frequencies_ref ? ics9xxx_models[j].frequencies_ref : j].frequencies;
|
||||
if (!frequencies_ptr)
|
||||
continue;
|
||||
frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_models[ics9xxx_models[j].frequencies_ref ? ics9xxx_models[j].frequencies_ref : j].frequencies;
|
||||
if (!frequencies_ptr)
|
||||
continue;
|
||||
|
||||
while (frequencies_ptr[i].bus) {
|
||||
delta = ABS((int32_t) (detect_bus - frequencies_ptr[i].bus));
|
||||
if (delta <= 100) {
|
||||
val = bitmask = 0;
|
||||
for (uint8_t k = 0; k < sizeof(ics9xxx_models[j].fs_regs) / sizeof(ics9xxx_models[j].fs_regs[0]); k++) {
|
||||
if (ics9xxx_models[j].fs_regs[k].normal_reg == detect_reg) {
|
||||
bitmask |= 1 << k;
|
||||
val |= (1 << k) * !!(dev->regs[detect_reg] & (1 << ics9xxx_models[j].fs_regs[k].normal_bit));
|
||||
}
|
||||
}
|
||||
if (bitmask && (val == (i & bitmask))) {
|
||||
matches++;
|
||||
discarded[j] = 0;
|
||||
pclog("> Potential match for %s (frequency %d index %d)\n", ics9xxx_models[j].name, frequencies_ptr[i].bus, val);
|
||||
}
|
||||
}
|
||||
while (frequencies_ptr[i].bus) {
|
||||
delta = ABS((int32_t) (detect_bus - frequencies_ptr[i].bus));
|
||||
if (delta <= 100) {
|
||||
val = bitmask = 0;
|
||||
for (uint8_t k = 0; k < sizeof(ics9xxx_models[j].fs_regs) / sizeof(ics9xxx_models[j].fs_regs[0]); k++) {
|
||||
if (ics9xxx_models[j].fs_regs[k].normal_reg == detect_reg) {
|
||||
bitmask |= 1 << k;
|
||||
val |= (1 << k) * !!(dev->regs[detect_reg] & (1 << ics9xxx_models[j].fs_regs[k].normal_bit));
|
||||
}
|
||||
}
|
||||
if (bitmask && (val == (i & bitmask))) {
|
||||
matches++;
|
||||
discarded[j] = 0;
|
||||
pclog("> Potential match for %s (frequency %d index %d)\n", ics9xxx_models[j].name, frequencies_ptr[i].bus, val);
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
pclog("Found a total of %d matches for register %d value %02X and bus frequency %d\n", matches, detect_reg, dev->regs[detect_reg], detect_bus);
|
||||
if (matches == 0) {
|
||||
pclog("Resetting list of discarded models since there were no matches.\n");
|
||||
memset(discarded, 0, sizeof(discarded));
|
||||
pclog("Resetting list of discarded models since there were no matches.\n");
|
||||
memset(discarded, 0, sizeof(discarded));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static uint8_t
|
||||
ics9xxx_start(void *bus, uint8_t addr, uint8_t read, void *priv)
|
||||
{
|
||||
@@ -1001,53 +994,51 @@ ics9xxx_start(void *bus, uint8_t addr, uint8_t read, void *priv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ics9xxx_read(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
ics9xxx_t *dev = (ics9xxx_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (dev->addr_register < 0) {
|
||||
dev->addr_register = -1;
|
||||
ret = dev->model->max_reg + 1;
|
||||
dev->addr_register = -1;
|
||||
ret = dev->model->max_reg + 1;
|
||||
}
|
||||
#if 0
|
||||
else if ((dev->model_idx == ICS9250_50) && (dev->addr_register == 0))
|
||||
ret = dev->regs[dev->addr_register] & 0x0b; /* -50 reads back revision ID instead */
|
||||
#endif
|
||||
else
|
||||
ret = dev->regs[dev->addr_register];
|
||||
ret = dev->regs[dev->addr_register];
|
||||
|
||||
#ifdef ENABLE_ICS9xxx_LOG
|
||||
if (dev->addr_register < 0)
|
||||
ics9xxx_log("ICS9xxx: read(%s) = %02X\n", (dev->addr_register == -1) ? "blocklen" : "command", ret);
|
||||
ics9xxx_log("ICS9xxx: read(%s) = %02X\n", (dev->addr_register == -1) ? "blocklen" : "command", ret);
|
||||
else
|
||||
ics9xxx_log("ICS9xxx: read(%x) = %02X\n", dev->addr_register, ret);
|
||||
ics9xxx_log("ICS9xxx: read(%x) = %02X\n", dev->addr_register, ret);
|
||||
#endif
|
||||
if (dev->addr_register >= dev->model->max_reg)
|
||||
dev->addr_register = 0; /* roll-over */
|
||||
dev->addr_register = 0; /* roll-over */
|
||||
else
|
||||
dev->addr_register++;
|
||||
dev->addr_register++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ics9xxx_set(ics9xxx_t *dev, uint8_t val)
|
||||
{
|
||||
/* Get the active mode, which determines what to add to the static frequency bits we were passed. */
|
||||
uint8_t hw_select = (dev->model->hw_select.normal_reg < 7) && !(dev->regs[dev->model->hw_select.normal_reg] & (1 << dev->model->hw_select.normal_bit));
|
||||
if (hw_select) {
|
||||
/* Hardware select mode: add strapped frequency bits. */
|
||||
val |= dev->bus_match;
|
||||
/* Hardware select mode: add strapped frequency bits. */
|
||||
val |= dev->bus_match;
|
||||
} else {
|
||||
/* Programmable mode: add register-defined frequency bits. */
|
||||
for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if ((dev->model->fs_regs[i].normal_reg < 7) && (dev->regs[dev->model->fs_regs[i].normal_reg] & (1 << dev->model->fs_regs[i].normal_bit)))
|
||||
val |= 1 << i;
|
||||
}
|
||||
/* Programmable mode: add register-defined frequency bits. */
|
||||
for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if ((dev->model->fs_regs[i].normal_reg < 7) && (dev->regs[dev->model->fs_regs[i].normal_reg] & (1 << dev->model->fs_regs[i].normal_bit)))
|
||||
val |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t bus = dev->frequencies_ptr[val].bus;
|
||||
@@ -1057,7 +1048,6 @@ ics9xxx_set(ics9xxx_t *dev, uint8_t val)
|
||||
ics9xxx_log("ICS9xxx: set(%d) = hw=%d bus=%d ram=%d pci=%d\n", val, hw_select, bus, bus * dev->frequencies_ptr[val].ram_mult, pci);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
{
|
||||
@@ -1065,24 +1055,24 @@ ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
|
||||
#ifdef ENABLE_ICS9xxx_LOG
|
||||
if (dev->addr_register < 0)
|
||||
ics9xxx_log("ICS9xxx: write(%s, %02X)\n", (dev->addr_register == -1) ? "blocklen" : "command", data);
|
||||
ics9xxx_log("ICS9xxx: write(%s, %02X)\n", (dev->addr_register == -1) ? "blocklen" : "command", data);
|
||||
else
|
||||
ics9xxx_log("ICS9xxx: write(%x, %02X)\n", dev->addr_register, data);
|
||||
ics9xxx_log("ICS9xxx: write(%x, %02X)\n", dev->addr_register, data);
|
||||
#endif
|
||||
|
||||
if (dev->addr_register >= 0) {
|
||||
/* Preserve fixed bits. */
|
||||
/* Preserve fixed bits. */
|
||||
#ifdef ENABLE_ICS9xxx_DETECT
|
||||
if (dev->model != ICS9xxx_xx)
|
||||
if (dev->model != ICS9xxx_xx)
|
||||
#endif
|
||||
{
|
||||
for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if (dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg == dev->addr_register))
|
||||
data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].normal_bit)) | (data & ~(1 << dev->model->fs_regs[i].normal_bit));
|
||||
if (dev->model->fs_regs[i].inv_reg == dev->addr_register)
|
||||
data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].inv_bit)) | (data & ~(1 << dev->model->fs_regs[i].inv_bit));
|
||||
}
|
||||
}
|
||||
{
|
||||
for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if (dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg == dev->addr_register))
|
||||
data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].normal_bit)) | (data & ~(1 << dev->model->fs_regs[i].normal_bit));
|
||||
if (dev->model->fs_regs[i].inv_reg == dev->addr_register)
|
||||
data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].inv_bit)) | (data & ~(1 << dev->model->fs_regs[i].inv_bit));
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
switch (dev->addr_register) {
|
||||
@@ -1112,15 +1102,15 @@ ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
dev->regs[dev->addr_register] = data;
|
||||
dev->regs[dev->addr_register] = data;
|
||||
|
||||
/* Update frequency if a relevant register was written to. */
|
||||
if (dev->relevant_regs & (1 << dev->addr_register)) {
|
||||
switch (dev->model_idx) {
|
||||
/* Update frequency if a relevant register was written to. */
|
||||
if (dev->relevant_regs & (1 << dev->addr_register)) {
|
||||
switch (dev->model_idx) {
|
||||
#ifdef ENABLE_ICS9xxx_DETECT
|
||||
case ICS9xxx_xx:
|
||||
ics9xxx_detect(dev);
|
||||
break;
|
||||
case ICS9xxx_xx:
|
||||
ics9xxx_detect(dev);
|
||||
break;
|
||||
#endif
|
||||
#if 0
|
||||
case ICS9250_10:
|
||||
@@ -1138,44 +1128,44 @@ ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
ics9xxx_set(dev, ((cpu_busspeed == 100000000) * 0x02) | ((cpu_busspeed > 100000000) * 0x01));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ics9xxx_set(dev, 0x00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
ics9xxx_set(dev, 0x00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->addr_register >= dev->model->max_reg)
|
||||
dev->addr_register = 0; /* roll-over */
|
||||
dev->addr_register = 0; /* roll-over */
|
||||
else
|
||||
dev->addr_register++;
|
||||
dev->addr_register++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset) {
|
||||
uint8_t best_match = 0;
|
||||
ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset)
|
||||
{
|
||||
uint8_t best_match = 0;
|
||||
uint32_t delta, best_delta = -1;
|
||||
|
||||
#ifdef ENABLE_ICS9xxx_DETECT
|
||||
if (dev->model_idx == ICS9xxx_xx)
|
||||
return 0;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
bus /= 10000;
|
||||
uint8_t i = 0;
|
||||
while (dev->frequencies_ptr[i].bus) {
|
||||
if ((i & preset_mask) == preset) {
|
||||
delta = ABS((int32_t) (bus - dev->frequencies_ptr[i].bus));
|
||||
if (delta < best_delta) {
|
||||
best_match = i;
|
||||
best_delta = delta;
|
||||
}
|
||||
}
|
||||
if ((i & preset_mask) == preset) {
|
||||
delta = ABS((int32_t) (bus - dev->frequencies_ptr[i].bus));
|
||||
if (delta < best_delta) {
|
||||
best_match = i;
|
||||
best_delta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
i++;
|
||||
}
|
||||
|
||||
ics9xxx_log("ICS9xxx: find_match(%s, %d) = match=%d bus=%d\n", dev->model->name, bus, best_match, dev->frequencies_ptr[best_match].bus);
|
||||
@@ -1183,15 +1173,14 @@ ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_
|
||||
return best_match;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ics9xxx_init(const device_t *info)
|
||||
{
|
||||
ics9xxx_t *dev = (ics9xxx_t *) malloc(sizeof(ics9xxx_t));
|
||||
memset(dev, 0, sizeof(ics9xxx_t));
|
||||
|
||||
dev->model_idx = info->local;
|
||||
dev->model = (ics9xxx_model_t *) &ics9xxx_models[dev->model_idx];
|
||||
dev->model_idx = info->local;
|
||||
dev->model = (ics9xxx_model_t *) &ics9xxx_models[dev->model_idx];
|
||||
dev->dyn_device = (device_t *) info;
|
||||
memcpy(&dev->regs, &dev->model->regs, dev->model->max_reg + 1);
|
||||
|
||||
@@ -1200,56 +1189,56 @@ ics9xxx_init(const device_t *info)
|
||||
uint8_t i;
|
||||
#ifdef ENABLE_ICS9xxx_DETECT
|
||||
for (i = ICS9xxx_xx + 1; i < ICS9xxx_MAX; i++) {
|
||||
if (ics9xxx_models[i].frequencies_ref || !ics9xxx_models[i].name)
|
||||
continue;
|
||||
for (uint8_t j = 0; j < i; j++) {
|
||||
if (ics9xxx_models[j].frequencies_ref || !ics9xxx_models[j].name)
|
||||
continue;
|
||||
if (!memcmp(&ics9xxx_models[i].frequencies, &ics9xxx_models[j].frequencies, sizeof(ics9xxx_models[i].frequencies)))
|
||||
pclog("Optimization warning: %s and %s have duplicate tables\n", ics9xxx_models[j].name, ics9xxx_models[i].name);
|
||||
}
|
||||
if (ics9xxx_models[i].frequencies_ref || !ics9xxx_models[i].name)
|
||||
continue;
|
||||
for (uint8_t j = 0; j < i; j++) {
|
||||
if (ics9xxx_models[j].frequencies_ref || !ics9xxx_models[j].name)
|
||||
continue;
|
||||
if (!memcmp(&ics9xxx_models[i].frequencies, &ics9xxx_models[j].frequencies, sizeof(ics9xxx_models[i].frequencies)))
|
||||
pclog("Optimization warning: %s and %s have duplicate tables\n", ics9xxx_models[j].name, ics9xxx_models[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->model_idx == ICS9xxx_xx) { /* detection device */
|
||||
dev->relevant_regs = 1 << 0; /* register 0 matters the most on the detection device */
|
||||
dev->relevant_regs = 1 << 0; /* register 0 matters the most on the detection device */
|
||||
|
||||
ics9xxx_detect_reset(dev);
|
||||
ics9xxx_detect_reset(dev);
|
||||
} else
|
||||
#endif
|
||||
{ /* regular device */
|
||||
dev->frequencies_ptr = (ics9xxx_frequency_t *) (dev->model->frequencies_ref ? ics9xxx_models[dev->model->frequencies_ref].frequencies : dev->model->frequencies);
|
||||
if (!dev->frequencies_ptr)
|
||||
fatal("ICS9xxx: NULL frequency table\n");
|
||||
dev->frequencies_ptr = (ics9xxx_frequency_t *) (dev->model->frequencies_ref ? ics9xxx_models[dev->model->frequencies_ref].frequencies : dev->model->frequencies);
|
||||
if (!dev->frequencies_ptr)
|
||||
fatal("ICS9xxx: NULL frequency table\n");
|
||||
|
||||
/* Determine which frequency bits cannot be strapped (register only). */
|
||||
uint8_t register_only_bits = 0x00;
|
||||
for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if (!dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg < 7)) /* mark a normal, programmable bit as relevant */
|
||||
dev->relevant_regs |= 1 << dev->model->fs_regs[i].normal_reg;
|
||||
if ((dev->model->fs_regs[i].normal_reg == 7) && (dev->model->fs_regs[i].inv_reg == 7)) /* mark as register only */
|
||||
register_only_bits |= 1 << i;
|
||||
}
|
||||
/* Determine which frequency bits cannot be strapped (register only). */
|
||||
uint8_t register_only_bits = 0x00;
|
||||
for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if (!dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg < 7)) /* mark a normal, programmable bit as relevant */
|
||||
dev->relevant_regs |= 1 << dev->model->fs_regs[i].normal_reg;
|
||||
if ((dev->model->fs_regs[i].normal_reg == 7) && (dev->model->fs_regs[i].inv_reg == 7)) /* mark as register only */
|
||||
register_only_bits |= 1 << i;
|
||||
}
|
||||
|
||||
/* Mark the hardware select bit's register as relevant, if there's one. */
|
||||
if (dev->model->hw_select.normal_reg < 7)
|
||||
dev->relevant_regs |= 1 << dev->model->hw_select.normal_reg;
|
||||
/* Mark the hardware select bit's register as relevant, if there's one. */
|
||||
if (dev->model->hw_select.normal_reg < 7)
|
||||
dev->relevant_regs |= 1 << dev->model->hw_select.normal_reg;
|
||||
|
||||
/* Find bus speed match and set default register bits accordingly. */
|
||||
dev->bus_match = ics9xxx_find_bus_match(dev, cpu_busspeed, register_only_bits, 0x00);
|
||||
for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if (dev->model->fs_regs[i].normal_reg < 7) {
|
||||
if (dev->bus_match & (1 << i))
|
||||
dev->regs[dev->model->fs_regs[i].normal_reg] |= 1 << dev->model->fs_regs[i].normal_bit;
|
||||
else
|
||||
dev->regs[dev->model->fs_regs[i].normal_reg] &= ~(1 << dev->model->fs_regs[i].normal_bit);
|
||||
}
|
||||
if (dev->model->fs_regs[i].inv_reg < 7) {
|
||||
if (dev->bus_match & (1 << i))
|
||||
dev->regs[dev->model->fs_regs[i].inv_reg] &= ~(1 << dev->model->fs_regs[i].inv_bit);
|
||||
else
|
||||
dev->regs[dev->model->fs_regs[i].inv_reg] |= 1 << dev->model->fs_regs[i].inv_bit;
|
||||
}
|
||||
}
|
||||
/* Find bus speed match and set default register bits accordingly. */
|
||||
dev->bus_match = ics9xxx_find_bus_match(dev, cpu_busspeed, register_only_bits, 0x00);
|
||||
for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) {
|
||||
if (dev->model->fs_regs[i].normal_reg < 7) {
|
||||
if (dev->bus_match & (1 << i))
|
||||
dev->regs[dev->model->fs_regs[i].normal_reg] |= 1 << dev->model->fs_regs[i].normal_bit;
|
||||
else
|
||||
dev->regs[dev->model->fs_regs[i].normal_reg] &= ~(1 << dev->model->fs_regs[i].normal_bit);
|
||||
}
|
||||
if (dev->model->fs_regs[i].inv_reg < 7) {
|
||||
if (dev->bus_match & (1 << i))
|
||||
dev->regs[dev->model->fs_regs[i].inv_reg] &= ~(1 << dev->model->fs_regs[i].inv_bit);
|
||||
else
|
||||
dev->regs[dev->model->fs_regs[i].inv_reg] |= 1 << dev->model->fs_regs[i].inv_bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i2c_sethandler(i2c_smbus, 0x69, 1, ics9xxx_start, ics9xxx_read, ics9xxx_write, NULL, dev);
|
||||
@@ -1257,7 +1246,6 @@ ics9xxx_init(const device_t *info)
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ics9xxx_close(void *priv)
|
||||
{
|
||||
@@ -1271,21 +1259,20 @@ ics9xxx_close(void *priv)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
device_t *
|
||||
ics9xxx_get(uint8_t model)
|
||||
{
|
||||
device_t *dev = (device_t *) malloc(sizeof(device_t));
|
||||
memset(dev, 0, sizeof(device_t));
|
||||
|
||||
dev->name = "ICS9xxx-xx Clock Generator";
|
||||
dev->name = "ICS9xxx-xx Clock Generator";
|
||||
dev->local = model;
|
||||
dev->flags = DEVICE_ISA;
|
||||
#ifdef ENABLE_ICS9xxx_DETECT
|
||||
if (model == ICS9xxx_xx)
|
||||
dev->reset = ics9xxx_detect_reset;
|
||||
dev->reset = ics9xxx_detect_reset;
|
||||
#endif
|
||||
dev->init = ics9xxx_init;
|
||||
dev->init = ics9xxx_init;
|
||||
dev->close = ics9xxx_close;
|
||||
|
||||
return dev;
|
||||
|
@@ -30,14 +30,16 @@
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/device.h>
|
||||
|
||||
#define HASP_BYTEARRAY(...) {__VA_ARGS__}
|
||||
#define HASP_TYPE(type, password_arr, prodinfo_arr) [type] = { \
|
||||
.password = (const uint8_t[]) password_arr, \
|
||||
.prodinfo = (const uint8_t[]) prodinfo_arr, \
|
||||
.password_size = sizeof((uint8_t[]) password_arr), \
|
||||
.prodinfo_size = sizeof((uint8_t[]) prodinfo_arr) \
|
||||
},
|
||||
|
||||
#define HASP_BYTEARRAY(...) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
#define HASP_TYPE(type, password_arr, prodinfo_arr) [type] = { \
|
||||
.password = (const uint8_t[]) password_arr, \
|
||||
.prodinfo = (const uint8_t[]) prodinfo_arr, \
|
||||
.password_size = sizeof((uint8_t[]) password_arr), \
|
||||
.prodinfo_size = sizeof((uint8_t[]) prodinfo_arr) \
|
||||
},
|
||||
|
||||
enum {
|
||||
HASP_STATE_NONE = 0,
|
||||
@@ -50,30 +52,28 @@ enum {
|
||||
HASP_TYPE_SAVQUEST = 0
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *password, *prodinfo;
|
||||
const uint8_t password_size, prodinfo_size;
|
||||
const uint8_t password_size, prodinfo_size;
|
||||
} hasp_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *lpt;
|
||||
void *lpt;
|
||||
const hasp_type_t *type;
|
||||
|
||||
int index, state, passindex, passmode, prodindex;
|
||||
uint8_t tmppass[0x29], status;
|
||||
int index, state, passindex, passmode, prodindex;
|
||||
uint8_t tmppass[0x29], status;
|
||||
} hasp_t;
|
||||
|
||||
static const hasp_type_t hasp_types[] = {
|
||||
HASP_TYPE(HASP_TYPE_SAVQUEST,
|
||||
HASP_BYTEARRAY(0xc3, 0xd9, 0xd3, 0xfb, 0x9d, 0x89, 0xb9, 0xa1, 0xb3, 0xc1, 0xf1, 0xcd, 0xdf, 0x9d),
|
||||
HASP_BYTEARRAY(0x51, 0x4c, 0x52, 0x4d, 0x53, 0x4e, 0x53, 0x4e, 0x53, 0x49, 0x53, 0x48, 0x53, 0x4b, 0x53, 0x4a,
|
||||
0x53, 0x43, 0x53, 0x45, 0x52, 0x46, 0x53, 0x43, 0x53, 0x41, 0xac, 0x40, 0x53, 0xbc, 0x53, 0x42,
|
||||
0x53, 0x57, 0x53, 0x5d, 0x52, 0x5e, 0x53, 0x5b, 0x53, 0x59, 0xac, 0x58, 0x53, 0xa4))
|
||||
HASP_BYTEARRAY(0xc3, 0xd9, 0xd3, 0xfb, 0x9d, 0x89, 0xb9, 0xa1, 0xb3, 0xc1, 0xf1, 0xcd, 0xdf, 0x9d),
|
||||
HASP_BYTEARRAY(0x51, 0x4c, 0x52, 0x4d, 0x53, 0x4e, 0x53, 0x4e, 0x53, 0x49, 0x53, 0x48, 0x53, 0x4b, 0x53, 0x4a,
|
||||
0x53, 0x43, 0x53, 0x45, 0x52, 0x46, 0x53, 0x43, 0x53, 0x41, 0xac, 0x40, 0x53, 0xbc, 0x53, 0x42,
|
||||
0x53, 0x57, 0x53, 0x5d, 0x52, 0x5e, 0x53, 0x5b, 0x53, 0x59, 0xac, 0x58, 0x53, 0xa4))
|
||||
};
|
||||
|
||||
|
||||
#ifdef ENABLE_HASP_LOG
|
||||
int hasp_do_log = ENABLE_HASP_LOG;
|
||||
|
||||
@@ -83,16 +83,15 @@ hasp_log(const char *fmt, ...)
|
||||
va_list ap;
|
||||
|
||||
if (hasp_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define hasp_log(fmt, ...)
|
||||
# define hasp_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
hasp_write_data(uint8_t val, void *priv)
|
||||
{
|
||||
@@ -101,161 +100,188 @@ hasp_write_data(uint8_t val, void *priv)
|
||||
hasp_log("HASP: write_data(%02X)\n", val);
|
||||
|
||||
switch (dev->index) {
|
||||
case 0:
|
||||
if (val == 0xc6)
|
||||
dev->index++;
|
||||
else
|
||||
dev->index = 0;
|
||||
break;
|
||||
case 0:
|
||||
if (val == 0xc6)
|
||||
dev->index++;
|
||||
else
|
||||
dev->index = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (val == 0xc7)
|
||||
dev->index++;
|
||||
else
|
||||
dev->index = 0;
|
||||
break;
|
||||
case 1:
|
||||
if (val == 0xc7)
|
||||
dev->index++;
|
||||
else
|
||||
dev->index = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (val == 0xc6) {
|
||||
dev->index++;
|
||||
} else {
|
||||
dev->index = 0;
|
||||
dev->state = HASP_STATE_NONE;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (val == 0xc6) {
|
||||
dev->index++;
|
||||
} else {
|
||||
dev->index = 0;
|
||||
dev->state = HASP_STATE_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dev->index = 0;
|
||||
if (val == 0x80) {
|
||||
dev->state = HASP_STATE_PASSWORD_BEGIN;
|
||||
dev->passindex = 0;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
dev->index = 0;
|
||||
if (val == 0x80) {
|
||||
dev->state = HASP_STATE_PASSWORD_BEGIN;
|
||||
dev->passindex = 0;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dev->status = 0;
|
||||
|
||||
if (dev->state == HASP_STATE_READ) {
|
||||
/* different passwords cause different values to be returned
|
||||
but there are really only two passwords of interest
|
||||
passmode 2 is used to verify that the dongle is responding correctly */
|
||||
if (dev->passmode == 2) {
|
||||
switch (val) {
|
||||
case 0x94: case 0x9e: case 0xa4:
|
||||
case 0xb2: case 0xbe: case 0xd0:
|
||||
return;
|
||||
/* different passwords cause different values to be returned
|
||||
but there are really only two passwords of interest
|
||||
passmode 2 is used to verify that the dongle is responding correctly */
|
||||
if (dev->passmode == 2) {
|
||||
switch (val) {
|
||||
case 0x94:
|
||||
case 0x9e:
|
||||
case 0xa4:
|
||||
case 0xb2:
|
||||
case 0xbe:
|
||||
case 0xd0:
|
||||
return;
|
||||
|
||||
case 0x8a: case 0x8e: case 0xca: case 0xd2:
|
||||
case 0xe2: case 0xf0: case 0xfc:
|
||||
/* someone with access to the actual dongle could dump the true values
|
||||
I've never seen it so I just determined the relevant bits instead
|
||||
from the disassembly of the software
|
||||
some of the keys are verified explicitly, the others implicitly
|
||||
I guessed the implicit ones with a bit of trial and error */
|
||||
dev->status = 0x20;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case 0x8a:
|
||||
case 0x8e:
|
||||
case 0xca:
|
||||
case 0xd2:
|
||||
case 0xe2:
|
||||
case 0xf0:
|
||||
case 0xfc:
|
||||
/* someone with access to the actual dongle could dump the true values
|
||||
I've never seen it so I just determined the relevant bits instead
|
||||
from the disassembly of the software
|
||||
some of the keys are verified explicitly, the others implicitly
|
||||
I guessed the implicit ones with a bit of trial and error */
|
||||
dev->status = 0x20;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
/* in passmode 0, some values remain unknown: 8a, 8e (inconclusive), 94, 96, 9a, a4, b2, be, c4, d2, d4 (inconclusive), e2, ec, f8, fc
|
||||
this is less of a concern since the contents seem to decrypt correctly */
|
||||
case 0x88:
|
||||
case 0x94: case 0x98: case 0x9c: case 0x9e:
|
||||
case 0xa0: case 0xa4: case 0xaa: case 0xae:
|
||||
case 0xb0: case 0xb2: case 0xbc: case 0xbe:
|
||||
case 0xc2: case 0xc6: case 0xc8: case 0xce:
|
||||
case 0xd0: case 0xd6: case 0xd8: case 0xdc:
|
||||
case 0xe0: case 0xe6: case 0xea: case 0xee:
|
||||
case 0xf2: case 0xf6:
|
||||
/* again, just the relevant bits instead of the true values */
|
||||
dev->status = 0x20;
|
||||
break;
|
||||
}
|
||||
switch (val) {
|
||||
/* in passmode 0, some values remain unknown: 8a, 8e (inconclusive), 94, 96, 9a, a4, b2, be, c4, d2, d4 (inconclusive), e2, ec, f8, fc
|
||||
this is less of a concern since the contents seem to decrypt correctly */
|
||||
case 0x88:
|
||||
case 0x94:
|
||||
case 0x98:
|
||||
case 0x9c:
|
||||
case 0x9e:
|
||||
case 0xa0:
|
||||
case 0xa4:
|
||||
case 0xaa:
|
||||
case 0xae:
|
||||
case 0xb0:
|
||||
case 0xb2:
|
||||
case 0xbc:
|
||||
case 0xbe:
|
||||
case 0xc2:
|
||||
case 0xc6:
|
||||
case 0xc8:
|
||||
case 0xce:
|
||||
case 0xd0:
|
||||
case 0xd6:
|
||||
case 0xd8:
|
||||
case 0xdc:
|
||||
case 0xe0:
|
||||
case 0xe6:
|
||||
case 0xea:
|
||||
case 0xee:
|
||||
case 0xf2:
|
||||
case 0xf6:
|
||||
/* again, just the relevant bits instead of the true values */
|
||||
dev->status = 0x20;
|
||||
break;
|
||||
}
|
||||
} else if (dev->state == HASP_STATE_PASSWORD_END) {
|
||||
if (val & 1) {
|
||||
if ((dev->passmode == 1) && (val == 0x9d))
|
||||
dev->passmode = 2;
|
||||
dev->state = HASP_STATE_READ;
|
||||
} else if (dev->passmode == 1) {
|
||||
dev->tmppass[dev->passindex++] = val;
|
||||
if (val & 1) {
|
||||
if ((dev->passmode == 1) && (val == 0x9d))
|
||||
dev->passmode = 2;
|
||||
dev->state = HASP_STATE_READ;
|
||||
} else if (dev->passmode == 1) {
|
||||
dev->tmppass[dev->passindex++] = val;
|
||||
|
||||
if (dev->passindex == sizeof(dev->tmppass)) {
|
||||
if ((dev->tmppass[0] == 0x9c) && (dev->tmppass[1] == 0x9e)) {
|
||||
int i = 2;
|
||||
dev->prodindex = 0;
|
||||
if (dev->passindex == sizeof(dev->tmppass)) {
|
||||
if ((dev->tmppass[0] == 0x9c) && (dev->tmppass[1] == 0x9e)) {
|
||||
int i = 2;
|
||||
dev->prodindex = 0;
|
||||
|
||||
do {
|
||||
dev->prodindex = (dev->prodindex << 1) + ((dev->tmppass[i] >> 6) & 1);
|
||||
} while ((i += 3) < sizeof(dev->tmppass));
|
||||
do {
|
||||
dev->prodindex = (dev->prodindex << 1) + ((dev->tmppass[i] >> 6) & 1);
|
||||
} while ((i += 3) < sizeof(dev->tmppass));
|
||||
|
||||
dev->prodindex = (dev->prodindex - 0xc08) << 4;
|
||||
dev->prodindex = (dev->prodindex - 0xc08) << 4;
|
||||
|
||||
hasp_log("HASP: Password prodindex = %d\n", dev->prodindex);
|
||||
hasp_log("HASP: Password prodindex = %d\n", dev->prodindex);
|
||||
|
||||
if (dev->prodindex < (0x38 << 4))
|
||||
dev->passmode = 3;
|
||||
}
|
||||
if (dev->prodindex < (0x38 << 4))
|
||||
dev->passmode = 3;
|
||||
}
|
||||
|
||||
dev->state = HASP_STATE_READ;
|
||||
}
|
||||
}
|
||||
dev->state = HASP_STATE_READ;
|
||||
}
|
||||
}
|
||||
} else if ((dev->state == HASP_STATE_PASSWORD_BEGIN) && (val & 1)) {
|
||||
dev->tmppass[dev->passindex++] = val;
|
||||
dev->tmppass[dev->passindex++] = val;
|
||||
|
||||
if (dev->passindex == dev->type->password_size) {
|
||||
dev->state = HASP_STATE_PASSWORD_END;
|
||||
dev->passindex = 0;
|
||||
dev->passmode = (int) !memcmp(dev->tmppass, dev->type->password, dev->type->password_size);
|
||||
hasp_log("HASP: Password comparison result = %d\n", dev->passmode);
|
||||
}
|
||||
if (dev->passindex == dev->type->password_size) {
|
||||
dev->state = HASP_STATE_PASSWORD_END;
|
||||
dev->passindex = 0;
|
||||
dev->passmode = (int) !memcmp(dev->tmppass, dev->type->password, dev->type->password_size);
|
||||
hasp_log("HASP: Password comparison result = %d\n", dev->passmode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
hasp_read_status(void *priv)
|
||||
{
|
||||
hasp_t *dev = (hasp_t *) priv;
|
||||
|
||||
if ((dev->state == HASP_STATE_READ) && (dev->passmode == 3)) {
|
||||
/* passmode 3 is used to retrieve the product(s) information
|
||||
it comes in two parts: header and product
|
||||
the header has this format:
|
||||
offset range purpose
|
||||
00 01 header type
|
||||
01 01-05 count of used product slots, must be 2
|
||||
02 01-05 count of unused product slots
|
||||
this is assumed to be 6-(count of used slots)
|
||||
but it is not enforced here
|
||||
however a total of 6 structures will be checked
|
||||
03 01-02 unknown
|
||||
04 01-46 country code
|
||||
05-0f 00 reserved
|
||||
the used product slots have this format:
|
||||
(the unused product slots must be entirely zeroes)
|
||||
00-01 0001-000a product ID, one must be 6, the other 0a
|
||||
02 0001-0003 unknown but must be 0001
|
||||
04 01-05 HASP plug country ID
|
||||
05 01-02 unknown but must be 01
|
||||
06 05 unknown
|
||||
07-0a any unknown, not used
|
||||
0b ff unknown
|
||||
0c ff unknown
|
||||
0d-0f 00 reserved
|
||||
the read is performed by accessing an array of 16-bit big-endian values
|
||||
and returning one bit at a time into bit 5 of the result
|
||||
the 16-bit value is then XORed with 0x534d and the register index */
|
||||
/* passmode 3 is used to retrieve the product(s) information
|
||||
it comes in two parts: header and product
|
||||
the header has this format:
|
||||
offset range purpose
|
||||
00 01 header type
|
||||
01 01-05 count of used product slots, must be 2
|
||||
02 01-05 count of unused product slots
|
||||
this is assumed to be 6-(count of used slots)
|
||||
but it is not enforced here
|
||||
however a total of 6 structures will be checked
|
||||
03 01-02 unknown
|
||||
04 01-46 country code
|
||||
05-0f 00 reserved
|
||||
the used product slots have this format:
|
||||
(the unused product slots must be entirely zeroes)
|
||||
00-01 0001-000a product ID, one must be 6, the other 0a
|
||||
02 0001-0003 unknown but must be 0001
|
||||
04 01-05 HASP plug country ID
|
||||
05 01-02 unknown but must be 01
|
||||
06 05 unknown
|
||||
07-0a any unknown, not used
|
||||
0b ff unknown
|
||||
0c ff unknown
|
||||
0d-0f 00 reserved
|
||||
the read is performed by accessing an array of 16-bit big-endian values
|
||||
and returning one bit at a time into bit 5 of the result
|
||||
the 16-bit value is then XORed with 0x534d and the register index */
|
||||
|
||||
if (dev->prodindex <= (dev->type->prodinfo_size * 8))
|
||||
dev->status = ((dev->type->prodinfo[(dev->prodindex - 1) >> 3] >> ((8 - dev->prodindex) & 7)) & 1) << 5; /* return defined info */
|
||||
else
|
||||
dev->status = (((0x534d ^ ((dev->prodindex - 1) >> 4)) >> ((16 - dev->prodindex) & 15)) & 1) << 5; /* then just alternate between the two key values */
|
||||
if (dev->prodindex <= (dev->type->prodinfo_size * 8))
|
||||
dev->status = ((dev->type->prodinfo[(dev->prodindex - 1) >> 3] >> ((8 - dev->prodindex) & 7)) & 1) << 5; /* return defined info */
|
||||
else
|
||||
dev->status = (((0x534d ^ ((dev->prodindex - 1) >> 4)) >> ((16 - dev->prodindex) & 15)) & 1) << 5; /* then just alternate between the two key values */
|
||||
|
||||
hasp_log("HASP: Reading %02X from prodindex %d\n", dev->status, dev->prodindex);
|
||||
hasp_log("HASP: Reading %02X from prodindex %d\n", dev->status, dev->prodindex);
|
||||
|
||||
dev->prodindex++;
|
||||
dev->prodindex++;
|
||||
}
|
||||
|
||||
hasp_log("HASP: read_status() = %02X\n", dev->status);
|
||||
@@ -263,7 +289,6 @@ hasp_read_status(void *priv)
|
||||
return dev->status;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
hasp_init(void *lpt, int type)
|
||||
{
|
||||
@@ -272,7 +297,7 @@ hasp_init(void *lpt, int type)
|
||||
|
||||
hasp_log("HASP: init(%d)\n", type);
|
||||
|
||||
dev->lpt = lpt;
|
||||
dev->lpt = lpt;
|
||||
dev->type = &hasp_types[type];
|
||||
|
||||
dev->status = 0x80;
|
||||
@@ -280,14 +305,12 @@ hasp_init(void *lpt, int type)
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
hasp_init_savquest(void *lpt)
|
||||
{
|
||||
return hasp_init(lpt, HASP_TYPE_SAVQUEST);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hasp_close(void *priv)
|
||||
{
|
||||
@@ -298,15 +321,14 @@ hasp_close(void *priv)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
const lpt_device_t lpt_hasp_savquest_device = {
|
||||
.name = "Protection Dongle for Savage Quest",
|
||||
.name = "Protection Dongle for Savage Quest",
|
||||
.internal_name = "dongle_savquest",
|
||||
.init = hasp_init_savquest,
|
||||
.close = hasp_close,
|
||||
.write_data = hasp_write_data,
|
||||
.write_ctrl = NULL,
|
||||
.read_data = NULL,
|
||||
.read_status = hasp_read_status,
|
||||
.read_ctrl = NULL
|
||||
.init = hasp_init_savquest,
|
||||
.close = hasp_close,
|
||||
.write_data = hasp_write_data,
|
||||
.write_ctrl = NULL,
|
||||
.read_data = NULL,
|
||||
.read_status = hasp_read_status,
|
||||
.read_ctrl = NULL
|
||||
};
|
||||
|
@@ -27,10 +27,8 @@
|
||||
#include <86box/machine.h>
|
||||
#include <86box/hwm.h>
|
||||
|
||||
|
||||
/* Refer to specific hardware monitor implementations for the meaning of hwm_values. */
|
||||
hwm_values_t hwm_values;
|
||||
|
||||
hwm_values_t hwm_values;
|
||||
|
||||
uint16_t
|
||||
hwm_get_vcore()
|
||||
|
@@ -28,69 +28,62 @@
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/hwm.h>
|
||||
|
||||
|
||||
#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
|
||||
#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
|
||||
/* Formulas and factors derived from Linux's gl518sm.c driver. */
|
||||
#define GL518SM_RPM_TO_REG(r, d) ((r) ? CLAMP((480000 + (r) * (d) / 2) / (r) * (d), 1, 255) : 0)
|
||||
#define GL518SM_VOLTAGE_TO_REG(v) ((uint8_t) round((v) / 19.0))
|
||||
#define GL518SM_VDD_TO_REG(v) ((uint8_t) (((v) * 4) / 95.0))
|
||||
|
||||
#define GL518SM_RPM_TO_REG(r, d) ((r) ? CLAMP((480000 + (r) * (d) / 2) / (r) * (d), 1, 255) : 0)
|
||||
#define GL518SM_VOLTAGE_TO_REG(v) ((uint8_t) round((v) / 19.0))
|
||||
#define GL518SM_VDD_TO_REG(v) ((uint8_t) (((v) *4) / 95.0))
|
||||
|
||||
typedef struct {
|
||||
uint32_t local;
|
||||
hwm_values_t *values;
|
||||
uint32_t local;
|
||||
hwm_values_t *values;
|
||||
|
||||
uint16_t regs[32];
|
||||
uint8_t addr_register: 5;
|
||||
uint8_t addr_register : 5;
|
||||
|
||||
uint8_t i2c_addr: 7, i2c_state: 2, i2c_enabled: 1;
|
||||
uint8_t i2c_addr : 7, i2c_state : 2, i2c_enabled : 1;
|
||||
} gl518sm_t;
|
||||
|
||||
|
||||
static uint8_t gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv);
|
||||
static uint8_t gl518sm_i2c_read(void *bus, uint8_t addr, void *priv);
|
||||
static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg);
|
||||
static uint8_t gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val);
|
||||
static void gl518sm_reset(gl518sm_t *dev);
|
||||
|
||||
static uint8_t gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv);
|
||||
static uint8_t gl518sm_i2c_read(void *bus, uint8_t addr, void *priv);
|
||||
static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg);
|
||||
static uint8_t gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val);
|
||||
static void gl518sm_reset(gl518sm_t *dev);
|
||||
|
||||
#ifdef ENABLE_GL518SM_LOG
|
||||
int gl518sm_do_log = ENABLE_GL518SM_LOG;
|
||||
|
||||
|
||||
static void
|
||||
gl518sm_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (gl518sm_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define gl518sm_log(fmt, ...)
|
||||
# define gl518sm_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
gl518sm_remap(gl518sm_t *dev, uint8_t addr)
|
||||
{
|
||||
gl518sm_log("GL518SM: remapping to SMBus %02Xh\n", addr);
|
||||
|
||||
if (dev->i2c_enabled)
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||
|
||||
if (addr < 0x80)
|
||||
i2c_sethandler(i2c_smbus, addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||
i2c_sethandler(i2c_smbus, addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||
|
||||
dev->i2c_addr = addr & 0x7f;
|
||||
dev->i2c_addr = addr & 0x7f;
|
||||
dev->i2c_enabled = !(addr & 0x80);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv)
|
||||
{
|
||||
@@ -101,29 +94,27 @@ gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
gl518sm_i2c_read(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
uint16_t read = gl518sm_read(dev, dev->addr_register);
|
||||
uint8_t ret = 0;
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
uint16_t read = gl518sm_read(dev, dev->addr_register);
|
||||
uint8_t ret = 0;
|
||||
|
||||
if (dev->i2c_state == 0)
|
||||
dev->i2c_state = 1;
|
||||
dev->i2c_state = 1;
|
||||
|
||||
if ((dev->i2c_state == 1) && (dev->addr_register >= 0x07) && (dev->addr_register <= 0x0c)) { /* two-byte registers: read MSB first */
|
||||
dev->i2c_state = 2;
|
||||
ret = read >> 8;
|
||||
dev->i2c_state = 2;
|
||||
ret = read >> 8;
|
||||
} else {
|
||||
ret = read;
|
||||
dev->addr_register++;
|
||||
ret = read;
|
||||
dev->addr_register++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
gl518sm_read(gl518sm_t *dev, uint8_t reg)
|
||||
{
|
||||
@@ -132,34 +123,34 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg)
|
||||
reg &= 0x1f;
|
||||
|
||||
switch (reg) {
|
||||
case 0x04: /* temperature */
|
||||
ret = (dev->values->temperatures[0] + 119) & 0xff;
|
||||
break;
|
||||
case 0x04: /* temperature */
|
||||
ret = (dev->values->temperatures[0] + 119) & 0xff;
|
||||
break;
|
||||
|
||||
case 0x07: /* fan speeds */
|
||||
ret = GL518SM_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x0f] >> 6) & 0x3)) << 8;
|
||||
ret |= GL518SM_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x0f] >> 4) & 0x3));
|
||||
break;
|
||||
case 0x07: /* fan speeds */
|
||||
ret = GL518SM_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x0f] >> 6) & 0x3)) << 8;
|
||||
ret |= GL518SM_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x0f] >> 4) & 0x3));
|
||||
break;
|
||||
|
||||
case 0x0d: /* VIN3 */
|
||||
ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[2]);
|
||||
break;
|
||||
case 0x0d: /* VIN3 */
|
||||
ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[2]);
|
||||
break;
|
||||
|
||||
case 0x13: /* VIN2 */
|
||||
ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[1]);
|
||||
break;
|
||||
case 0x13: /* VIN2 */
|
||||
ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[1]);
|
||||
break;
|
||||
|
||||
case 0x14: /* VIN1 */
|
||||
ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[0]);
|
||||
break;
|
||||
case 0x14: /* VIN1 */
|
||||
ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[0]);
|
||||
break;
|
||||
|
||||
case 0x15: /* VDD */
|
||||
ret = GL518SM_VDD_TO_REG(dev->values->voltages[3]);
|
||||
break;
|
||||
case 0x15: /* VDD */
|
||||
ret = GL518SM_VDD_TO_REG(dev->values->voltages[3]);
|
||||
break;
|
||||
|
||||
default: /* other registers */
|
||||
ret = dev->regs[reg];
|
||||
break;
|
||||
default: /* other registers */
|
||||
ret = dev->regs[reg];
|
||||
break;
|
||||
}
|
||||
|
||||
gl518sm_log("GL518SM: read(%02X) = %04X\n", reg, ret);
|
||||
@@ -167,72 +158,77 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
|
||||
switch (dev->i2c_state++) {
|
||||
case 0:
|
||||
dev->addr_register = data;
|
||||
break;
|
||||
case 0:
|
||||
dev->addr_register = data;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) & 0xff00) | data);
|
||||
break;
|
||||
case 1:
|
||||
gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) & 0xff00) | data);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) << 8) | data);
|
||||
break;
|
||||
case 2:
|
||||
gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) << 8) | data);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev->i2c_state = 3;
|
||||
return 0;
|
||||
default:
|
||||
dev->i2c_state = 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val)
|
||||
{
|
||||
gl518sm_log("GL518SM: write(%02X, %04X)\n", reg, val);
|
||||
|
||||
switch (reg) {
|
||||
case 0x00: case 0x01: case 0x04: case 0x07: case 0x0d: case 0x12: case 0x13: case 0x14: case 0x15:
|
||||
/* read-only registers */
|
||||
return 0;
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x04:
|
||||
case 0x07:
|
||||
case 0x0d:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
/* read-only registers */
|
||||
return 0;
|
||||
|
||||
case 0x0a:
|
||||
dev->regs[0x13] = val & 0xff;
|
||||
break;
|
||||
case 0x0a:
|
||||
dev->regs[0x13] = val & 0xff;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
dev->regs[reg] = val & 0xfc;
|
||||
case 0x03:
|
||||
dev->regs[reg] = val & 0xfc;
|
||||
|
||||
if (val & 0x80) /* Init */
|
||||
gl518sm_reset(dev);
|
||||
break;
|
||||
if (val & 0x80) /* Init */
|
||||
gl518sm_reset(dev);
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
dev->regs[reg] = val & 0xf8;
|
||||
break;
|
||||
case 0x0f:
|
||||
dev->regs[reg] = val & 0xf8;
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
dev->regs[reg] = val & 0x7f;
|
||||
break;
|
||||
case 0x11:
|
||||
dev->regs[reg] = val & 0x7f;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev->regs[reg] = val;
|
||||
break;
|
||||
default:
|
||||
dev->regs[reg] = val;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gl518sm_reset(gl518sm_t *dev)
|
||||
{
|
||||
@@ -252,7 +248,6 @@ gl518sm_reset(gl518sm_t *dev)
|
||||
gl518sm_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gl518sm_close(void *priv)
|
||||
{
|
||||
@@ -263,7 +258,6 @@ gl518sm_close(void *priv)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
gl518sm_init(const device_t *info)
|
||||
{
|
||||
@@ -274,19 +268,24 @@ gl518sm_init(const device_t *info)
|
||||
|
||||
/* Set default values. */
|
||||
hwm_values_t defaults = {
|
||||
{ /* fan speeds */
|
||||
3000, /* usually Chassis */
|
||||
3000 /* usually CPU */
|
||||
}, { /* temperatures */
|
||||
30 /* usually CPU */
|
||||
}, { /* voltages */
|
||||
hwm_get_vcore(), /* Vcore */
|
||||
RESISTOR_DIVIDER(12000, 150, 47), /* +12V (15K/4.7K divider suggested in the datasheet) */
|
||||
3300, /* +3.3V */
|
||||
5000 /* +5V */
|
||||
}
|
||||
{
|
||||
/* fan speeds */
|
||||
3000, /* usually Chassis */
|
||||
3000 /* usually CPU */
|
||||
},
|
||||
{
|
||||
/* temperatures */
|
||||
30 /* usually CPU */
|
||||
},
|
||||
{
|
||||
/* voltages */
|
||||
hwm_get_vcore(), /* Vcore */
|
||||
RESISTOR_DIVIDER(12000, 150, 47), /* +12V (15K/4.7K divider suggested in the datasheet) */
|
||||
3300, /* +3.3V */
|
||||
5000 /* +5V */
|
||||
}
|
||||
};
|
||||
hwm_values = defaults;
|
||||
hwm_values = defaults;
|
||||
dev->values = &hwm_values;
|
||||
|
||||
gl518sm_reset(dev);
|
||||
@@ -297,30 +296,30 @@ gl518sm_init(const device_t *info)
|
||||
|
||||
/* GL518SM on SMBus address 2Ch */
|
||||
const device_t gl518sm_2c_device = {
|
||||
.name = "Genesys Logic GL518SM Hardware Monitor",
|
||||
.name = "Genesys Logic GL518SM Hardware Monitor",
|
||||
.internal_name = "gl518sm_2c",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0x2c,
|
||||
.init = gl518sm_init,
|
||||
.close = gl518sm_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0x2c,
|
||||
.init = gl518sm_init,
|
||||
.close = gl518sm_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
/* GL518SM on SMBus address 2Dh */
|
||||
const device_t gl518sm_2d_device = {
|
||||
.name = "Genesys Logic GL518SM Hardware Monitor",
|
||||
.name = "Genesys Logic GL518SM Hardware Monitor",
|
||||
.internal_name = "gl518sm_2d",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0x2d,
|
||||
.init = gl518sm_init,
|
||||
.close = gl518sm_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0x2d,
|
||||
.init = gl518sm_init,
|
||||
.close = gl518sm_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
@@ -26,30 +26,26 @@
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/hwm.h>
|
||||
|
||||
|
||||
#define LM75_TEMP_TO_REG(t) ((t) << 8)
|
||||
|
||||
#define LM75_TEMP_TO_REG(t) ((t) << 8)
|
||||
|
||||
#ifdef ENABLE_LM75_LOG
|
||||
int lm75_do_log = ENABLE_LM75_LOG;
|
||||
|
||||
|
||||
static void
|
||||
lm75_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (lm75_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define lm75_log(fmt, ...)
|
||||
# define lm75_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm75_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv)
|
||||
{
|
||||
@@ -60,25 +56,23 @@ lm75_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
lm75_read(lm75_t *dev, uint8_t reg)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
if ((reg & 0x7) == 0x0) /* temperature high byte */
|
||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8;
|
||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8;
|
||||
else if ((reg & 0x7) == 0x1) /* temperature low byte */
|
||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]);
|
||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]);
|
||||
else
|
||||
ret = dev->regs[reg & 0x7];
|
||||
ret = dev->regs[reg & 0x7];
|
||||
|
||||
lm75_log("LM75: read(%02X) = %02X\n", reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm75_i2c_read(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
@@ -86,39 +80,38 @@ lm75_i2c_read(void *bus, uint8_t addr, void *priv)
|
||||
uint8_t ret = 0;
|
||||
|
||||
if (dev->i2c_state == 0)
|
||||
dev->i2c_state = 1;
|
||||
dev->i2c_state = 1;
|
||||
|
||||
/* The AS99127F hardware monitor uses its primary LM75 device's
|
||||
address to access some of its proprietary registers. Pass this
|
||||
operation on to the main monitor code, if necessary. */
|
||||
if ((dev->addr_register & 0x80) && dev->as99127f) {
|
||||
ret = lm78_as99127f_read(dev->as99127f, dev->addr_register);
|
||||
ret = lm78_as99127f_read(dev->as99127f, dev->addr_register);
|
||||
} else {
|
||||
switch (dev->addr_register & 0x3) {
|
||||
case 0x0: /* temperature */
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x0 : 0x1);
|
||||
break;
|
||||
switch (dev->addr_register & 0x3) {
|
||||
case 0x0: /* temperature */
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x0 : 0x1);
|
||||
break;
|
||||
|
||||
case 0x1: /* configuration */
|
||||
ret = lm75_read(dev, 0x2);
|
||||
break;
|
||||
case 0x1: /* configuration */
|
||||
ret = lm75_read(dev, 0x2);
|
||||
break;
|
||||
|
||||
case 0x2: /* Thyst */
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x3 : 0x4);
|
||||
break;
|
||||
case 0x3: /* Tos */
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x5 : 0x6);
|
||||
break;
|
||||
}
|
||||
case 0x2: /* Thyst */
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x3 : 0x4);
|
||||
break;
|
||||
case 0x3: /* Tos */
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x5 : 0x6);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->i2c_state < 2)
|
||||
dev->i2c_state++;
|
||||
dev->i2c_state++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
lm75_write(lm75_t *dev, uint8_t reg, uint8_t val)
|
||||
{
|
||||
@@ -127,77 +120,74 @@ lm75_write(lm75_t *dev, uint8_t reg, uint8_t val)
|
||||
uint8_t reg_idx = (reg & 0x7);
|
||||
|
||||
if ((reg_idx <= 0x1) || (reg_idx == 0x7))
|
||||
return 0; /* read-only registers */
|
||||
return 0; /* read-only registers */
|
||||
|
||||
dev->regs[reg_idx] = val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
{
|
||||
lm75_t *dev = (lm75_t *) priv;
|
||||
|
||||
if ((dev->i2c_state > 2) || ((dev->i2c_state == 2) && ((dev->addr_register & 0x3) == 0x1))) {
|
||||
return 0;
|
||||
return 0;
|
||||
} else if (dev->i2c_state == 0) {
|
||||
dev->i2c_state = 1;
|
||||
/* Linux lm75.c driver relies on the address register not changing if bit 2 is set. */
|
||||
if (((dev->addr_register & 0x80) && dev->as99127f) || !(data & 0x04))
|
||||
dev->addr_register = data;
|
||||
return 1;
|
||||
dev->i2c_state = 1;
|
||||
/* Linux lm75.c driver relies on the address register not changing if bit 2 is set. */
|
||||
if (((dev->addr_register & 0x80) && dev->as99127f) || !(data & 0x04))
|
||||
dev->addr_register = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The AS99127F hardware monitor uses its primary LM75 device's
|
||||
address to access some of its proprietary registers. Pass this
|
||||
operation on to the main monitor code, if necessary. */
|
||||
if ((dev->addr_register & 0x80) && dev->as99127f) {
|
||||
return lm78_as99127f_write(dev->as99127f, dev->addr_register, data);
|
||||
return lm78_as99127f_write(dev->as99127f, dev->addr_register, data);
|
||||
} else {
|
||||
switch (dev->addr_register & 0x3) {
|
||||
case 0x0: /* temperature */
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x0 : 0x1, data);
|
||||
break;
|
||||
switch (dev->addr_register & 0x3) {
|
||||
case 0x0: /* temperature */
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x0 : 0x1, data);
|
||||
break;
|
||||
|
||||
case 0x1: /* configuration */
|
||||
lm75_write(dev, 0x2, data);
|
||||
break;
|
||||
case 0x1: /* configuration */
|
||||
lm75_write(dev, 0x2, data);
|
||||
break;
|
||||
|
||||
case 0x2: /* Thyst */
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x3 : 0x4, data);
|
||||
break;
|
||||
case 0x2: /* Thyst */
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x3 : 0x4, data);
|
||||
break;
|
||||
|
||||
case 0x3: /* Tos */
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x5 : 0x6, data);
|
||||
break;
|
||||
}
|
||||
case 0x3: /* Tos */
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x5 : 0x6, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->i2c_state == 1)
|
||||
dev->i2c_state = 2;
|
||||
dev->i2c_state = 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lm75_remap(lm75_t *dev, uint8_t addr)
|
||||
{
|
||||
lm75_log("LM75: remapping to SMBus %02Xh\n", addr);
|
||||
|
||||
if (dev->i2c_enabled)
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||
|
||||
if (addr < 0x80)
|
||||
i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||
i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||
|
||||
dev->i2c_addr = addr & 0x7f;
|
||||
dev->i2c_addr = addr & 0x7f;
|
||||
dev->i2c_enabled = !(addr & 0x80);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lm75_reset(lm75_t *dev)
|
||||
{
|
||||
@@ -207,7 +197,6 @@ lm75_reset(lm75_t *dev)
|
||||
lm75_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lm75_close(void *priv)
|
||||
{
|
||||
@@ -218,7 +207,6 @@ lm75_close(void *priv)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
lm75_init(const device_t *info)
|
||||
{
|
||||
@@ -229,10 +217,10 @@ lm75_init(const device_t *info)
|
||||
|
||||
/* Set default value. */
|
||||
if (dev->local)
|
||||
hwm_values.temperatures[dev->local >> 8] = 30;
|
||||
hwm_values.temperatures[dev->local >> 8] = 30;
|
||||
dev->values = &hwm_values;
|
||||
|
||||
dev->i2c_addr = dev->local & 0x7f;
|
||||
dev->i2c_addr = dev->local & 0x7f;
|
||||
dev->i2c_enabled = 1;
|
||||
|
||||
lm75_reset(dev);
|
||||
@@ -240,35 +228,33 @@ lm75_init(const device_t *info)
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
/* LM75 on SMBus address 4Ah, reporting temperatures[1]. */
|
||||
const device_t lm75_1_4a_device = {
|
||||
.name = "National Semiconductor LM75 Temperature Sensor",
|
||||
.name = "National Semiconductor LM75 Temperature Sensor",
|
||||
.internal_name = "lm75_1_4a",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0x14a,
|
||||
.init = lm75_init,
|
||||
.close = lm75_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0x14a,
|
||||
.init = lm75_init,
|
||||
.close = lm75_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
|
||||
/* LM75 secondary/tertiary temperature sensors built into
|
||||
the Winbond W83781D family. Not to be used stand-alone. */
|
||||
const device_t lm75_w83781d_device = {
|
||||
.name = "Winbond W83781D Secondary Temperature Sensor",
|
||||
.name = "Winbond W83781D Secondary Temperature Sensor",
|
||||
.internal_name = "lm75_w83781d",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = lm75_init,
|
||||
.close = lm75_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = lm75_init,
|
||||
.close = lm75_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -26,94 +26,98 @@
|
||||
#include <86box/io.h>
|
||||
#include <86box/hwm.h>
|
||||
|
||||
|
||||
#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
|
||||
#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
|
||||
/* Formulas and factors derived from Linux's via686a.c driver. */
|
||||
#define VT82C686_RPM_TO_REG(r, d) ((r) ? CLAMP(1350000 / (r * d), 1, 255) : 0)
|
||||
#define VT82C686_TEMP_TO_REG(t) (-1.160370e-10*(t*t*t*t*t*t) + 3.193693e-08*(t*t*t*t*t) - 1.464447e-06*(t*t*t*t) - 2.525453e-04*(t*t*t) + 1.424593e-02*(t*t) + 2.148941e+00*t + 7.275808e+01)
|
||||
#define VT82C686_VOLTAGE_TO_REG(v, f) CLAMP((((v) * (2.628 / (f))) - 120.5) / 25, 0, 255)
|
||||
|
||||
#define VT82C686_RPM_TO_REG(r, d) ((r) ? CLAMP(1350000 / (r * d), 1, 255) : 0)
|
||||
#define VT82C686_TEMP_TO_REG(t) (-1.160370e-10 * (t * t * t * t * t * t) + 3.193693e-08 * (t * t * t * t * t) - 1.464447e-06 * (t * t * t * t) - 2.525453e-04 * (t * t * t) + 1.424593e-02 * (t * t) + 2.148941e+00 * t + 7.275808e+01)
|
||||
#define VT82C686_VOLTAGE_TO_REG(v, f) CLAMP((((v) * (2.628 / (f))) - 120.5) / 25, 0, 255)
|
||||
|
||||
typedef struct {
|
||||
hwm_values_t *values;
|
||||
|
||||
uint8_t enable;
|
||||
uint16_t io_base;
|
||||
uint8_t regs[128];
|
||||
uint8_t enable;
|
||||
uint16_t io_base;
|
||||
uint8_t regs[128];
|
||||
} vt82c686_t;
|
||||
|
||||
static double voltage_factors[5] = { 1.25, 1.25, 1.67, 2.6, 6.3 };
|
||||
|
||||
static double voltage_factors[5] = {1.25, 1.25, 1.67, 2.6, 6.3};
|
||||
|
||||
|
||||
static void vt82c686_reset(vt82c686_t *dev, uint8_t initialization);
|
||||
|
||||
static void vt82c686_reset(vt82c686_t *dev, uint8_t initialization);
|
||||
|
||||
static uint8_t
|
||||
vt82c686_read(uint16_t addr, void *priv)
|
||||
{
|
||||
vt82c686_t *dev = (vt82c686_t *) priv;
|
||||
uint8_t ret;
|
||||
uint8_t ret;
|
||||
|
||||
addr -= dev->io_base;
|
||||
|
||||
switch (addr) {
|
||||
case 0x00 ... 0x0f: case 0x50 ... 0x7f: /* undefined registers */
|
||||
/* Real 686B returns the contents of 0x40. */
|
||||
ret = dev->regs[0x40];
|
||||
break;
|
||||
case 0x00 ... 0x0f:
|
||||
case 0x50 ... 0x7f: /* undefined registers */
|
||||
/* Real 686B returns the contents of 0x40. */
|
||||
ret = dev->regs[0x40];
|
||||
break;
|
||||
|
||||
case 0x1f: case 0x20: case 0x21: /* temperatures */
|
||||
ret = VT82C686_TEMP_TO_REG(dev->values->temperatures[(addr == 0x1f) ? 2 : (addr & 1)]);
|
||||
break;
|
||||
case 0x1f:
|
||||
case 0x20:
|
||||
case 0x21: /* temperatures */
|
||||
ret = VT82C686_TEMP_TO_REG(dev->values->temperatures[(addr == 0x1f) ? 2 : (addr & 1)]);
|
||||
break;
|
||||
|
||||
case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: /* voltages */
|
||||
ret = VT82C686_VOLTAGE_TO_REG(dev->values->voltages[addr - 0x22], voltage_factors[addr - 0x22]);
|
||||
break;
|
||||
case 0x22:
|
||||
case 0x23:
|
||||
case 0x24:
|
||||
case 0x25:
|
||||
case 0x26: /* voltages */
|
||||
ret = VT82C686_VOLTAGE_TO_REG(dev->values->voltages[addr - 0x22], voltage_factors[addr - 0x22]);
|
||||
break;
|
||||
|
||||
case 0x29: case 0x2a: /* fan speeds */
|
||||
ret = VT82C686_RPM_TO_REG(dev->values->fans[addr - 0x29], 1 << ((dev->regs[0x47] >> ((addr == 0x29) ? 4 : 6)) & 0x3));
|
||||
break;
|
||||
case 0x29:
|
||||
case 0x2a: /* fan speeds */
|
||||
ret = VT82C686_RPM_TO_REG(dev->values->fans[addr - 0x29], 1 << ((dev->regs[0x47] >> ((addr == 0x29) ? 4 : 6)) & 0x3));
|
||||
break;
|
||||
|
||||
default: /* other registers */
|
||||
ret = dev->regs[addr];
|
||||
break;
|
||||
default: /* other registers */
|
||||
ret = dev->regs[addr];
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vt82c686_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
vt82c686_t *dev = (vt82c686_t *) priv;
|
||||
uint8_t reg = port & 0x7f;
|
||||
uint8_t reg = port & 0x7f;
|
||||
|
||||
switch (reg) {
|
||||
case 0x00 ... 0x0f:
|
||||
case 0x3f: case 0x41: case 0x42: case 0x4a:
|
||||
case 0x4c ... 0x7f:
|
||||
/* Read-only registers. */
|
||||
return;
|
||||
case 0x00 ... 0x0f:
|
||||
case 0x3f:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
case 0x4a:
|
||||
case 0x4c ... 0x7f:
|
||||
/* Read-only registers. */
|
||||
return;
|
||||
|
||||
case 0x40:
|
||||
/* Reset if requested. */
|
||||
if (val & 0x80) {
|
||||
vt82c686_reset(dev, 1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
/* Reset if requested. */
|
||||
if (val & 0x80) {
|
||||
vt82c686_reset(dev, 1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x48:
|
||||
val &= 0x7f;
|
||||
break;
|
||||
case 0x48:
|
||||
val &= 0x7f;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->regs[reg] = val;
|
||||
}
|
||||
|
||||
|
||||
/* Writes to hardware monitor-related configuration space registers
|
||||
of the VT82C686 power management function are sent here by via_pipc.c */
|
||||
void
|
||||
@@ -122,31 +126,30 @@ vt82c686_hwm_write(uint8_t addr, uint8_t val, void *priv)
|
||||
vt82c686_t *dev = (vt82c686_t *) priv;
|
||||
|
||||
if (dev->io_base)
|
||||
io_removehandler(dev->io_base, 128,
|
||||
vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
||||
io_removehandler(dev->io_base, 128,
|
||||
vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
||||
|
||||
switch (addr) {
|
||||
case 0x70:
|
||||
dev->io_base &= 0xff00;
|
||||
dev->io_base |= val & 0x80;
|
||||
break;
|
||||
case 0x70:
|
||||
dev->io_base &= 0xff00;
|
||||
dev->io_base |= val & 0x80;
|
||||
break;
|
||||
|
||||
case 0x71:
|
||||
dev->io_base &= 0x00ff;
|
||||
dev->io_base |= val << 8;
|
||||
break;
|
||||
case 0x71:
|
||||
dev->io_base &= 0x00ff;
|
||||
dev->io_base |= val << 8;
|
||||
break;
|
||||
|
||||
case 0x74:
|
||||
dev->enable = val & 0x01;
|
||||
break;
|
||||
case 0x74:
|
||||
dev->enable = val & 0x01;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->enable && dev->io_base)
|
||||
io_sethandler(dev->io_base, 128,
|
||||
vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
||||
io_sethandler(dev->io_base, 128,
|
||||
vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vt82c686_reset(vt82c686_t *dev, uint8_t initialization)
|
||||
{
|
||||
@@ -159,10 +162,9 @@ vt82c686_reset(vt82c686_t *dev, uint8_t initialization)
|
||||
dev->regs[0x4b] = 0x15;
|
||||
|
||||
if (!initialization)
|
||||
vt82c686_hwm_write(0x74, 0x00, dev);
|
||||
vt82c686_hwm_write(0x74, 0x00, dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vt82c686_close(void *priv)
|
||||
{
|
||||
@@ -171,7 +173,6 @@ vt82c686_close(void *priv)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
vt82c686_init(const device_t *info)
|
||||
{
|
||||
@@ -181,22 +182,24 @@ vt82c686_init(const device_t *info)
|
||||
/* Set default values. Since this hardware monitor has a complex voltage factor system,
|
||||
the values struct contains voltage values *before* applying their respective factors. */
|
||||
hwm_values_t defaults = {
|
||||
{ /* fan speeds */
|
||||
3000, /* usually CPU */
|
||||
3000 /* usually Chassis */
|
||||
}, { /* temperatures */
|
||||
30, /* usually CPU */
|
||||
30, /* usually System */
|
||||
30
|
||||
}, { /* voltages */
|
||||
hwm_get_vcore(), /* Vcore */
|
||||
2500, /* +2.5V */
|
||||
3300, /* +3.3V */
|
||||
5000, /* +5V */
|
||||
12000 /* +12V */
|
||||
}
|
||||
// clang-format on
|
||||
{ /* fan speeds */
|
||||
3000, /* usually CPU */
|
||||
3000 /* usually Chassis */
|
||||
}, { /* temperatures */
|
||||
30, /* usually CPU */
|
||||
30, /* usually System */
|
||||
30
|
||||
}, { /* voltages */
|
||||
hwm_get_vcore(), /* Vcore */
|
||||
2500, /* +2.5V */
|
||||
3300, /* +3.3V */
|
||||
5000, /* +5V */
|
||||
12000 /* +12V */
|
||||
}
|
||||
// clang-format on
|
||||
};
|
||||
hwm_values = defaults;
|
||||
hwm_values = defaults;
|
||||
dev->values = &hwm_values;
|
||||
|
||||
vt82c686_reset(dev, 0);
|
||||
@@ -205,15 +208,15 @@ vt82c686_init(const device_t *info)
|
||||
}
|
||||
|
||||
const device_t via_vt82c686_hwm_device = {
|
||||
.name = "VIA VT82C686 Integrated Hardware Monitor",
|
||||
.name = "VIA VT82C686 Integrated Hardware Monitor",
|
||||
.internal_name = "via_vt82c686_hwm",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = vt82c686_init,
|
||||
.close = vt82c686_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = vt82c686_init,
|
||||
.close = vt82c686_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
261
src/device/i2c.c
261
src/device/i2c.c
@@ -24,51 +24,45 @@
|
||||
#include <86box/86box.h>
|
||||
#include <86box/i2c.h>
|
||||
|
||||
|
||||
#define NADDRS 128 /* I2C supports 128 addresses */
|
||||
#define NADDRS 128 /* I2C supports 128 addresses */
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
|
||||
typedef struct _i2c_ {
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv);
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv);
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv);
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv);
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv);
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv);
|
||||
|
||||
void *priv;
|
||||
void *priv;
|
||||
|
||||
struct _i2c_ *prev, *next;
|
||||
} i2c_t;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *name;
|
||||
i2c_t *devices[NADDRS], *last[NADDRS];
|
||||
} i2c_bus_t;
|
||||
|
||||
|
||||
void *i2c_smbus;
|
||||
|
||||
|
||||
#ifdef ENABLE_I2C_LOG
|
||||
int i2c_do_log = ENABLE_I2C_LOG;
|
||||
|
||||
|
||||
static void
|
||||
i2c_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (i2c_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define i2c_log(fmt, ...)
|
||||
# define i2c_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
void *
|
||||
i2c_addbus(char *name)
|
||||
{
|
||||
@@ -80,235 +74,226 @@ i2c_addbus(char *name)
|
||||
return bus;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_removebus(void *bus_handle)
|
||||
{
|
||||
int c;
|
||||
i2c_t *p, *q;
|
||||
int c;
|
||||
i2c_t *p, *q;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
|
||||
if (!bus_handle)
|
||||
return;
|
||||
return;
|
||||
|
||||
for (c = 0; c < NADDRS; c++) {
|
||||
p = bus->devices[c];
|
||||
if (!p)
|
||||
continue;
|
||||
while(p) {
|
||||
q = p->next;
|
||||
free(p);
|
||||
p = q;
|
||||
}
|
||||
p = bus->devices[c];
|
||||
if (!p)
|
||||
continue;
|
||||
while (p) {
|
||||
q = p->next;
|
||||
free(p);
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
free(bus);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
i2c_getbusname(void *bus_handle)
|
||||
{
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
|
||||
if (!bus_handle)
|
||||
return(NULL);
|
||||
return (NULL);
|
||||
|
||||
return(bus->name);
|
||||
return (bus->name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
int c;
|
||||
i2c_t *p, *q = NULL;
|
||||
int c;
|
||||
i2c_t *p, *q = NULL;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
|
||||
if (!bus_handle || ((base + size) > NADDRS))
|
||||
return;
|
||||
return;
|
||||
|
||||
for (c = 0; c < size; c++) {
|
||||
p = bus->last[base + c];
|
||||
q = (i2c_t *) malloc(sizeof(i2c_t));
|
||||
memset(q, 0, sizeof(i2c_t));
|
||||
if (p) {
|
||||
p->next = q;
|
||||
q->prev = p;
|
||||
} else {
|
||||
bus->devices[base + c] = q;
|
||||
q->prev = NULL;
|
||||
}
|
||||
p = bus->last[base + c];
|
||||
q = (i2c_t *) malloc(sizeof(i2c_t));
|
||||
memset(q, 0, sizeof(i2c_t));
|
||||
if (p) {
|
||||
p->next = q;
|
||||
q->prev = p;
|
||||
} else {
|
||||
bus->devices[base + c] = q;
|
||||
q->prev = NULL;
|
||||
}
|
||||
|
||||
q->start = start;
|
||||
q->read = read;
|
||||
q->write = write;
|
||||
q->stop = stop;
|
||||
q->start = start;
|
||||
q->read = read;
|
||||
q->write = write;
|
||||
q->stop = stop;
|
||||
|
||||
q->priv = priv;
|
||||
q->next = NULL;
|
||||
q->priv = priv;
|
||||
q->next = NULL;
|
||||
|
||||
bus->last[base + c] = q;
|
||||
bus->last[base + c] = q;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
int c;
|
||||
i2c_t *p, *q;
|
||||
int c;
|
||||
i2c_t *p, *q;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
|
||||
if (!bus_handle || ((base + size) > NADDRS))
|
||||
return;
|
||||
return;
|
||||
|
||||
for (c = 0; c < size; c++) {
|
||||
p = bus->devices[base + c];
|
||||
if (!p)
|
||||
continue;
|
||||
while(p) {
|
||||
q = p->next;
|
||||
if ((p->start == start) && (p->read == read) && (p->write == write) && (p->stop == stop) && (p->priv == priv)) {
|
||||
if (p->prev)
|
||||
p->prev->next = p->next;
|
||||
else
|
||||
bus->devices[base + c] = p->next;
|
||||
if (p->next)
|
||||
p->next->prev = p->prev;
|
||||
else
|
||||
bus->last[base + c] = p->prev;
|
||||
free(p);
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
p = bus->devices[base + c];
|
||||
if (!p)
|
||||
continue;
|
||||
while (p) {
|
||||
q = p->next;
|
||||
if ((p->start == start) && (p->read == read) && (p->write == write) && (p->stop == stop) && (p->priv == priv)) {
|
||||
if (p->prev)
|
||||
p->prev->next = p->next;
|
||||
else
|
||||
bus->devices[base + c] = p->next;
|
||||
if (p->next)
|
||||
p->next->prev = p->prev;
|
||||
else
|
||||
bus->last[base + c] = p->prev;
|
||||
free(p);
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_handler(int set, void *bus_handle, uint8_t base, int size,
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
if (set)
|
||||
i2c_sethandler(bus_handle, base, size, start, read, write, stop, priv);
|
||||
i2c_sethandler(bus_handle, base, size, start, read, write, stop, priv);
|
||||
else
|
||||
i2c_removehandler(bus_handle, base, size, start, read, write, stop, priv);
|
||||
i2c_removehandler(bus_handle, base, size, start, read, write, stop, priv);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_start(void *bus_handle, uint8_t addr, uint8_t read)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
uint8_t ret = 0;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
i2c_t *p;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
return (ret);
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->start) {
|
||||
ret |= p->start(bus_handle, addr, read, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
while (p) {
|
||||
if (p->start) {
|
||||
ret |= p->start(bus_handle, addr, read, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C %s: start(%02X) = %d\n", bus->name, addr, ret);
|
||||
|
||||
return(ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_read(void *bus_handle, uint8_t addr)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
uint8_t ret = 0;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
i2c_t *p;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
return (ret);
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->read) {
|
||||
ret = p->read(bus_handle, addr, p->priv);
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
while (p) {
|
||||
if (p->read) {
|
||||
ret = p->read(bus_handle, addr, p->priv);
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C %s: read(%02X) = %02X\n", bus->name, addr, ret);
|
||||
|
||||
return(ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_write(void *bus_handle, uint8_t addr, uint8_t data)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
i2c_t *p;
|
||||
uint8_t ret = 0;
|
||||
i2c_t *p;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
return (ret);
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->write) {
|
||||
ret |= p->write(bus_handle, addr, data, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
while (p) {
|
||||
if (p->write) {
|
||||
ret |= p->write(bus_handle, addr, data, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C %s: write(%02X, %02X) = %d\n", bus->name, addr, data, ret);
|
||||
|
||||
return(ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_stop(void *bus_handle, uint8_t addr)
|
||||
{
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
i2c_t *p;
|
||||
|
||||
if (!bus)
|
||||
return;
|
||||
return;
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->stop) {
|
||||
p->stop(bus_handle, addr, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
while (p) {
|
||||
if (p->stop) {
|
||||
p->stop(bus_handle, addr, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C %s: stop(%02X)\n", bus->name, addr);
|
||||
|
@@ -24,35 +24,31 @@
|
||||
#include <86box/86box.h>
|
||||
#include <86box/i2c.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *bus_name;
|
||||
void *i2c;
|
||||
uint8_t prev_scl, prev_sda, slave_sda, started,
|
||||
slave_addr_received, slave_addr, slave_read, pos, byte;
|
||||
char *bus_name;
|
||||
void *i2c;
|
||||
uint8_t prev_scl, prev_sda, slave_sda, started,
|
||||
slave_addr_received, slave_addr, slave_read, pos, byte;
|
||||
} i2c_gpio_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_I2C_GPIO_LOG
|
||||
int i2c_gpio_do_log = ENABLE_I2C_GPIO_LOG;
|
||||
|
||||
|
||||
static void
|
||||
i2c_gpio_log(int level, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (i2c_gpio_do_log >= level) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define i2c_gpio_log(fmt, ...)
|
||||
# define i2c_gpio_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
void *
|
||||
i2c_gpio_init(char *bus_name)
|
||||
{
|
||||
@@ -62,14 +58,13 @@ i2c_gpio_init(char *bus_name)
|
||||
i2c_gpio_log(1, "I2C GPIO %s: init()\n", bus_name);
|
||||
|
||||
dev->bus_name = bus_name;
|
||||
dev->i2c = i2c_addbus(dev->bus_name);
|
||||
dev->i2c = i2c_addbus(dev->bus_name);
|
||||
dev->prev_scl = dev->prev_sda = dev->slave_sda = 1;
|
||||
dev->slave_addr = 0xff;
|
||||
dev->slave_addr = 0xff;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_gpio_close(void *dev_handle)
|
||||
{
|
||||
@@ -82,7 +77,6 @@ i2c_gpio_close(void *dev_handle)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
{
|
||||
@@ -91,80 +85,79 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
i2c_gpio_log(3, "I2C GPIO %s: write scl=%d->%d sda=%d->%d read=%d\n", dev->bus_name, dev->prev_scl, scl, dev->prev_sda, sda, dev->slave_read);
|
||||
|
||||
if (dev->prev_scl && scl) {
|
||||
if (dev->prev_sda && !sda) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Start condition\n", dev->bus_name);
|
||||
dev->started = 1;
|
||||
dev->pos = 0;
|
||||
dev->slave_addr = 0xff;
|
||||
dev->slave_read = 2; /* start with address transfer */
|
||||
dev->slave_sda = 1;
|
||||
} else if (!dev->prev_sda && sda) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop condition\n", dev->bus_name);
|
||||
dev->started = 0;
|
||||
if (dev->slave_addr != 0xff)
|
||||
i2c_stop(dev->i2c, dev->slave_addr);
|
||||
dev->slave_addr = 0xff;
|
||||
dev->slave_sda = 1;
|
||||
}
|
||||
if (dev->prev_sda && !sda) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Start condition\n", dev->bus_name);
|
||||
dev->started = 1;
|
||||
dev->pos = 0;
|
||||
dev->slave_addr = 0xff;
|
||||
dev->slave_read = 2; /* start with address transfer */
|
||||
dev->slave_sda = 1;
|
||||
} else if (!dev->prev_sda && sda) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop condition\n", dev->bus_name);
|
||||
dev->started = 0;
|
||||
if (dev->slave_addr != 0xff)
|
||||
i2c_stop(dev->i2c, dev->slave_addr);
|
||||
dev->slave_addr = 0xff;
|
||||
dev->slave_sda = 1;
|
||||
}
|
||||
} else if (!dev->prev_scl && scl && dev->started) {
|
||||
if (dev->pos++ < 8) {
|
||||
if (dev->slave_read == 1) {
|
||||
dev->slave_sda = !!(dev->byte & 0x80);
|
||||
dev->byte <<= 1;
|
||||
} else {
|
||||
dev->byte <<= 1;
|
||||
dev->byte |= sda;
|
||||
}
|
||||
if (dev->pos++ < 8) {
|
||||
if (dev->slave_read == 1) {
|
||||
dev->slave_sda = !!(dev->byte & 0x80);
|
||||
dev->byte <<= 1;
|
||||
} else {
|
||||
dev->byte <<= 1;
|
||||
dev->byte |= sda;
|
||||
}
|
||||
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Bit %d = %d\n", dev->bus_name, 8 - dev->pos, (dev->slave_read == 1) ? dev->slave_sda : sda);
|
||||
}
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Bit %d = %d\n", dev->bus_name, 8 - dev->pos, (dev->slave_read == 1) ? dev->slave_sda : sda);
|
||||
}
|
||||
|
||||
if (dev->pos == 8) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Byte = %02X\n", dev->bus_name, dev->byte);
|
||||
if (dev->pos == 8) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Byte = %02X\n", dev->bus_name, dev->byte);
|
||||
|
||||
/* (N)ACKing here instead of at the 9th bit may sound odd, but is required by the Matrox Mystique Windows drivers. */
|
||||
switch (dev->slave_read) {
|
||||
case 2: /* address transfer */
|
||||
dev->slave_addr = dev->byte >> 1;
|
||||
dev->slave_read = dev->byte & 1;
|
||||
/* (N)ACKing here instead of at the 9th bit may sound odd, but is required by the Matrox Mystique Windows drivers. */
|
||||
switch (dev->slave_read) {
|
||||
case 2: /* address transfer */
|
||||
dev->slave_addr = dev->byte >> 1;
|
||||
dev->slave_read = dev->byte & 1;
|
||||
|
||||
/* slave ACKs? */
|
||||
dev->slave_sda = !i2c_start(dev->i2c, dev->slave_addr, dev->slave_read);
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Slave %02X %s %sACK\n", dev->bus_name, dev->slave_addr, dev->slave_read ? "read" : "write", dev->slave_sda ? "N" : "");
|
||||
/* slave ACKs? */
|
||||
dev->slave_sda = !i2c_start(dev->i2c, dev->slave_addr, dev->slave_read);
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Slave %02X %s %sACK\n", dev->bus_name, dev->slave_addr, dev->slave_read ? "read" : "write", dev->slave_sda ? "N" : "");
|
||||
|
||||
if (!dev->slave_sda && dev->slave_read) /* read first byte on an ACKed read transfer */
|
||||
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
||||
if (!dev->slave_sda && dev->slave_read) /* read first byte on an ACKed read transfer */
|
||||
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
||||
|
||||
dev->slave_read |= 0x80; /* slave_read was overwritten; stop the master ACK read logic from running at the 9th bit if we're reading */
|
||||
break;
|
||||
dev->slave_read |= 0x80; /* slave_read was overwritten; stop the master ACK read logic from running at the 9th bit if we're reading */
|
||||
break;
|
||||
|
||||
case 0: /* write transfer */
|
||||
dev->slave_sda = !i2c_write(dev->i2c, dev->slave_addr, dev->byte);
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Write %02X %sACK\n", dev->bus_name, dev->byte, dev->slave_sda ? "N" : "");
|
||||
break;
|
||||
}
|
||||
} else if (dev->pos == 9) {
|
||||
switch (dev->slave_read) {
|
||||
case 1: /* read transfer (unless we're in an address transfer) */
|
||||
if (!sda) /* master ACKs? */
|
||||
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Read %02X %sACK\n", dev->bus_name, dev->byte, sda ? "N" : "");
|
||||
break;
|
||||
case 0: /* write transfer */
|
||||
dev->slave_sda = !i2c_write(dev->i2c, dev->slave_addr, dev->byte);
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Write %02X %sACK\n", dev->bus_name, dev->byte, dev->slave_sda ? "N" : "");
|
||||
break;
|
||||
}
|
||||
} else if (dev->pos == 9) {
|
||||
switch (dev->slave_read) {
|
||||
case 1: /* read transfer (unless we're in an address transfer) */
|
||||
if (!sda) /* master ACKs? */
|
||||
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Read %02X %sACK\n", dev->bus_name, dev->byte, sda ? "N" : "");
|
||||
break;
|
||||
|
||||
default:
|
||||
dev->slave_read &= 1; /* if we're in an address transfer, clear it */
|
||||
}
|
||||
dev->pos = 0; /* start over */
|
||||
}
|
||||
default:
|
||||
dev->slave_read &= 1; /* if we're in an address transfer, clear it */
|
||||
}
|
||||
dev->pos = 0; /* start over */
|
||||
}
|
||||
} else if (dev->prev_scl && !scl && (dev->pos != 8)) { /* keep (N)ACK computed at the 8th bit when transitioning to the 9th bit */
|
||||
dev->slave_sda = 1;
|
||||
dev->slave_sda = 1;
|
||||
}
|
||||
|
||||
dev->prev_scl = scl;
|
||||
dev->prev_sda = sda;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_gpio_get_scl(void *dev_handle)
|
||||
{
|
||||
@@ -172,7 +165,6 @@ i2c_gpio_get_scl(void *dev_handle)
|
||||
return dev->prev_scl;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_gpio_get_sda(void *dev_handle)
|
||||
{
|
||||
@@ -181,7 +173,6 @@ i2c_gpio_get_sda(void *dev_handle)
|
||||
return dev->prev_sda && dev->slave_sda;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
i2c_gpio_get_bus(void *dev_handle)
|
||||
{
|
||||
|
@@ -29,7 +29,6 @@
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/machine.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t regs[8];
|
||||
|
File diff suppressed because it is too large
Load Diff
1317
src/device/isapnp.c
1317
src/device/isapnp.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -28,23 +28,20 @@
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
int keyboard_scan;
|
||||
void (*keyboard_send)(uint16_t val);
|
||||
|
||||
int keyboard_scan;
|
||||
void (*keyboard_send)(uint16_t val);
|
||||
|
||||
|
||||
static int recv_key[512]; /* keyboard input buffer */
|
||||
static int oldkey[512];
|
||||
static int recv_key[512]; /* keyboard input buffer */
|
||||
static int oldkey[512];
|
||||
#if 0
|
||||
static int keydelay[512];
|
||||
#endif
|
||||
static scancode *scan_table; /* scancode table for keyboard */
|
||||
|
||||
static uint8_t caps_lock = 0;
|
||||
static uint8_t num_lock = 0;
|
||||
static uint8_t scroll_lock = 0;
|
||||
static uint8_t shift = 0;
|
||||
static scancode *scan_table; /* scancode table for keyboard */
|
||||
|
||||
static uint8_t caps_lock = 0;
|
||||
static uint8_t num_lock = 0;
|
||||
static uint8_t scroll_lock = 0;
|
||||
static uint8_t shift = 0;
|
||||
|
||||
void
|
||||
keyboard_init(void)
|
||||
@@ -52,82 +49,78 @@ keyboard_init(void)
|
||||
memset(recv_key, 0x00, sizeof(recv_key));
|
||||
|
||||
keyboard_scan = 1;
|
||||
scan_table = NULL;
|
||||
scan_table = NULL;
|
||||
|
||||
memset(keyboard_set3_flags, 0x00, sizeof(keyboard_set3_flags));
|
||||
keyboard_set3_all_repeat = 0;
|
||||
keyboard_set3_all_break = 0;
|
||||
keyboard_set3_all_break = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
keyboard_set_table(const scancode *ptr)
|
||||
{
|
||||
scan_table = (scancode *) ptr;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
fake_shift_needed(uint16_t scan)
|
||||
{
|
||||
switch(scan) {
|
||||
case 0x147:
|
||||
case 0x148:
|
||||
case 0x149:
|
||||
case 0x14a:
|
||||
case 0x14b:
|
||||
case 0x14d:
|
||||
case 0x14f:
|
||||
case 0x150:
|
||||
case 0x151:
|
||||
case 0x152:
|
||||
case 0x153:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
switch (scan) {
|
||||
case 0x147:
|
||||
case 0x148:
|
||||
case 0x149:
|
||||
case 0x14a:
|
||||
case 0x14b:
|
||||
case 0x14d:
|
||||
case 0x14f:
|
||||
case 0x150:
|
||||
case 0x151:
|
||||
case 0x152:
|
||||
case 0x153:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
key_process(uint16_t scan, int down)
|
||||
{
|
||||
scancode *codes = scan_table;
|
||||
int c;
|
||||
int c;
|
||||
|
||||
if (!keyboard_scan || (keyboard_send == NULL))
|
||||
return;
|
||||
return;
|
||||
|
||||
oldkey[scan] = down;
|
||||
if (down && codes[scan].mk[0] == 0)
|
||||
return;
|
||||
if (down && codes[scan].mk[0] == 0)
|
||||
return;
|
||||
|
||||
if (!down && codes[scan].brk[0] == 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
/* TODO: The keyboard controller needs to report the AT flag to us here. */
|
||||
if (is286 && ((keyboard_mode & 3) == 3)) {
|
||||
if (!keyboard_set3_all_break && !down && !(keyboard_set3_flags[codes[scan].mk[0]] & 2))
|
||||
return;
|
||||
if (!keyboard_set3_all_break && !down && !(keyboard_set3_flags[codes[scan].mk[0]] & 2))
|
||||
return;
|
||||
}
|
||||
|
||||
c = 0;
|
||||
if (down) {
|
||||
/* Send the special code indicating an opening fake shift might be needed. */
|
||||
if (fake_shift_needed(scan))
|
||||
keyboard_send(0x100);
|
||||
while (codes[scan].mk[c] != 0)
|
||||
keyboard_send(codes[scan].mk[c++]);
|
||||
/* Send the special code indicating an opening fake shift might be needed. */
|
||||
if (fake_shift_needed(scan))
|
||||
keyboard_send(0x100);
|
||||
while (codes[scan].mk[c] != 0)
|
||||
keyboard_send(codes[scan].mk[c++]);
|
||||
} else {
|
||||
while (codes[scan].brk[c] != 0)
|
||||
keyboard_send(codes[scan].brk[c++]);
|
||||
/* Send the special code indicating a closing fake shift might be needed. */
|
||||
if (fake_shift_needed(scan))
|
||||
keyboard_send(0x101);
|
||||
while (codes[scan].brk[c] != 0)
|
||||
keyboard_send(codes[scan].brk[c++]);
|
||||
/* Send the special code indicating a closing fake shift might be needed. */
|
||||
if (fake_shift_needed(scan))
|
||||
keyboard_send(0x101);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a keystroke event from the UI layer. */
|
||||
void
|
||||
keyboard_input(int down, uint16_t scan)
|
||||
@@ -135,72 +128,72 @@ keyboard_input(int down, uint16_t scan)
|
||||
/* Translate E0 xx scan codes to 01xx because we use 512-byte arrays for states
|
||||
and scan code sets. */
|
||||
if ((scan >> 8) == 0xe0) {
|
||||
scan &= 0x00ff;
|
||||
scan |= 0x0100; /* extended key code */
|
||||
scan &= 0x00ff;
|
||||
scan |= 0x0100; /* extended key code */
|
||||
} else if ((scan >> 8) != 0x01)
|
||||
scan &= 0x00ff; /* we can receive a scan code whose upper byte is 0x01,
|
||||
this means we're the Win32 version running on windows
|
||||
that already sends us preprocessed scan codes, which
|
||||
means we then use the scan code as is, and need to
|
||||
make sure we do not accidentally strip that upper byte */
|
||||
scan &= 0x00ff; /* we can receive a scan code whose upper byte is 0x01,
|
||||
this means we're the Win32 version running on windows
|
||||
that already sends us preprocessed scan codes, which
|
||||
means we then use the scan code as is, and need to
|
||||
make sure we do not accidentally strip that upper byte */
|
||||
|
||||
if (recv_key[scan & 0x1ff] ^ down) {
|
||||
if (down) {
|
||||
switch(scan & 0x1ff) {
|
||||
case 0x01c: /* Left Ctrl */
|
||||
shift |= 0x01;
|
||||
break;
|
||||
case 0x11c: /* Right Ctrl */
|
||||
shift |= 0x10;
|
||||
break;
|
||||
case 0x02a: /* Left Shift */
|
||||
shift |= 0x02;
|
||||
break;
|
||||
case 0x036: /* Right Shift */
|
||||
shift |= 0x20;
|
||||
break;
|
||||
case 0x038: /* Left Alt */
|
||||
shift |= 0x04;
|
||||
break;
|
||||
case 0x138: /* Right Alt */
|
||||
shift |= 0x40;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(scan & 0x1ff) {
|
||||
case 0x01c: /* Left Ctrl */
|
||||
shift &= ~0x01;
|
||||
break;
|
||||
case 0x11c: /* Right Ctrl */
|
||||
shift &= ~0x10;
|
||||
break;
|
||||
case 0x02a: /* Left Shift */
|
||||
shift &= ~0x02;
|
||||
break;
|
||||
case 0x036: /* Right Shift */
|
||||
shift &= ~0x20;
|
||||
break;
|
||||
case 0x038: /* Left Alt */
|
||||
shift &= ~0x04;
|
||||
break;
|
||||
case 0x138: /* Right Alt */
|
||||
shift &= ~0x40;
|
||||
break;
|
||||
case 0x03a: /* Caps Lock */
|
||||
caps_lock ^= 1;
|
||||
break;
|
||||
case 0x045:
|
||||
num_lock ^= 1;
|
||||
break;
|
||||
case 0x046:
|
||||
scroll_lock ^= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (down) {
|
||||
switch (scan & 0x1ff) {
|
||||
case 0x01c: /* Left Ctrl */
|
||||
shift |= 0x01;
|
||||
break;
|
||||
case 0x11c: /* Right Ctrl */
|
||||
shift |= 0x10;
|
||||
break;
|
||||
case 0x02a: /* Left Shift */
|
||||
shift |= 0x02;
|
||||
break;
|
||||
case 0x036: /* Right Shift */
|
||||
shift |= 0x20;
|
||||
break;
|
||||
case 0x038: /* Left Alt */
|
||||
shift |= 0x04;
|
||||
break;
|
||||
case 0x138: /* Right Alt */
|
||||
shift |= 0x40;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (scan & 0x1ff) {
|
||||
case 0x01c: /* Left Ctrl */
|
||||
shift &= ~0x01;
|
||||
break;
|
||||
case 0x11c: /* Right Ctrl */
|
||||
shift &= ~0x10;
|
||||
break;
|
||||
case 0x02a: /* Left Shift */
|
||||
shift &= ~0x02;
|
||||
break;
|
||||
case 0x036: /* Right Shift */
|
||||
shift &= ~0x20;
|
||||
break;
|
||||
case 0x038: /* Left Alt */
|
||||
shift &= ~0x04;
|
||||
break;
|
||||
case 0x138: /* Right Alt */
|
||||
shift &= ~0x40;
|
||||
break;
|
||||
case 0x03a: /* Caps Lock */
|
||||
caps_lock ^= 1;
|
||||
break;
|
||||
case 0x045:
|
||||
num_lock ^= 1;
|
||||
break;
|
||||
case 0x046:
|
||||
scroll_lock ^= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: Shouldn't this be some sort of bit shift? An array of 8 unsigned 64-bit integers
|
||||
should be enough. */
|
||||
should be enough. */
|
||||
/* recv_key[scan >> 6] |= ((uint64_t) down << ((uint64_t) scan & 0x3fLL)); */
|
||||
|
||||
/* pclog("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */
|
||||
@@ -209,7 +202,6 @@ keyboard_input(int down, uint16_t scan)
|
||||
key_process(scan & 0x1ff, down);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
keyboard_do_break(uint16_t scan)
|
||||
{
|
||||
@@ -217,48 +209,42 @@ keyboard_do_break(uint16_t scan)
|
||||
|
||||
/* TODO: The keyboard controller needs to report the AT flag to us here. */
|
||||
if (is286 && ((keyboard_mode & 3) == 3)) {
|
||||
if (!keyboard_set3_all_break &&
|
||||
!recv_key[scan] &&
|
||||
!(keyboard_set3_flags[codes[scan].mk[0]] & 2))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
if (!keyboard_set3_all_break && !recv_key[scan] && !(keyboard_set3_flags[codes[scan].mk[0]] & 2))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
} else
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Also called by the emulated keyboard controller to update the states of
|
||||
Caps Lock, Num Lock, and Scroll Lock when receving the "Set keyboard LEDs"
|
||||
command. */
|
||||
void
|
||||
keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl)
|
||||
{
|
||||
caps_lock = cl;
|
||||
num_lock = nl;
|
||||
scroll_lock = sl;
|
||||
caps_lock = cl;
|
||||
num_lock = nl;
|
||||
scroll_lock = sl;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
keyboard_get_shift(void)
|
||||
{
|
||||
return shift;
|
||||
return shift;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl)
|
||||
{
|
||||
if (cl)
|
||||
*cl = caps_lock;
|
||||
if (nl)
|
||||
*nl = num_lock;
|
||||
if (sl)
|
||||
*sl = scroll_lock;
|
||||
if (cl)
|
||||
*cl = caps_lock;
|
||||
if (nl)
|
||||
*nl = num_lock;
|
||||
if (sl)
|
||||
*sl = scroll_lock;
|
||||
}
|
||||
|
||||
|
||||
/* Called by the UI to update the states of Caps Lock, Num Lock, and Scroll Lock. */
|
||||
void
|
||||
keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl)
|
||||
@@ -268,68 +254,63 @@ keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl)
|
||||
int i;
|
||||
|
||||
if (caps_lock != cl) {
|
||||
i = 0;
|
||||
while (codes[0x03a].mk[i] != 0)
|
||||
keyboard_send(codes[0x03a].mk[i++]);
|
||||
if (keyboard_do_break(0x03a)) {
|
||||
i = 0;
|
||||
while (codes[0x03a].brk[i] != 0)
|
||||
keyboard_send(codes[0x03a].brk[i++]);
|
||||
}
|
||||
i = 0;
|
||||
while (codes[0x03a].mk[i] != 0)
|
||||
keyboard_send(codes[0x03a].mk[i++]);
|
||||
if (keyboard_do_break(0x03a)) {
|
||||
i = 0;
|
||||
while (codes[0x03a].brk[i] != 0)
|
||||
keyboard_send(codes[0x03a].brk[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
if (num_lock != nl) {
|
||||
i = 0;
|
||||
while (codes[0x045].mk[i] != 0)
|
||||
keyboard_send(codes[0x045].mk[i++]);
|
||||
if (keyboard_do_break(0x045)) {
|
||||
i = 0;
|
||||
while (codes[0x045].brk[i] != 0)
|
||||
keyboard_send(codes[0x045].brk[i++]);
|
||||
}
|
||||
i = 0;
|
||||
while (codes[0x045].mk[i] != 0)
|
||||
keyboard_send(codes[0x045].mk[i++]);
|
||||
if (keyboard_do_break(0x045)) {
|
||||
i = 0;
|
||||
while (codes[0x045].brk[i] != 0)
|
||||
keyboard_send(codes[0x045].brk[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
if (scroll_lock != sl) {
|
||||
i = 0;
|
||||
while (codes[0x046].mk[i] != 0)
|
||||
keyboard_send(codes[0x046].mk[i++]);
|
||||
if (keyboard_do_break(0x046)) {
|
||||
i = 0;
|
||||
while (codes[0x046].brk[i] != 0)
|
||||
keyboard_send(codes[0x046].brk[i++]);
|
||||
}
|
||||
i = 0;
|
||||
while (codes[0x046].mk[i] != 0)
|
||||
keyboard_send(codes[0x046].mk[i++]);
|
||||
if (keyboard_do_break(0x046)) {
|
||||
i = 0;
|
||||
while (codes[0x046].brk[i] != 0)
|
||||
keyboard_send(codes[0x046].brk[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
keyboard_update_states(cl, nl, sl);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
keyboard_recv(uint16_t key)
|
||||
{
|
||||
return recv_key[key];
|
||||
return recv_key[key];
|
||||
}
|
||||
|
||||
|
||||
/* Do we have Control-Alt-PgDn in the keyboard buffer? */
|
||||
int
|
||||
keyboard_isfsexit(void)
|
||||
{
|
||||
return( (recv_key[0x01D] || recv_key[0x11D]) &&
|
||||
(recv_key[0x038] || recv_key[0x138]) &&
|
||||
(recv_key[0x051] || recv_key[0x151]) );
|
||||
return ((recv_key[0x01D] || recv_key[0x11D]) && (recv_key[0x038] || recv_key[0x138]) && (recv_key[0x051] || recv_key[0x151]));
|
||||
}
|
||||
|
||||
|
||||
/* Do we have F8-F12 in the keyboard buffer? */
|
||||
int
|
||||
keyboard_ismsexit(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
/* Windows: F8+F12 */
|
||||
return( recv_key[0x042] && recv_key[0x058] );
|
||||
return (recv_key[0x042] && recv_key[0x058]);
|
||||
#else
|
||||
/* WxWidgets cannot do two regular keys.. CTRL+END */
|
||||
return( (recv_key[0x01D] || recv_key[0x11D]) && (recv_key[0x04F] || recv_key[0x14F]) );
|
||||
return ((recv_key[0x01D] || recv_key[0x11D]) && (recv_key[0x04F] || recv_key[0x14F]));
|
||||
#endif
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -45,15 +45,14 @@
|
||||
#include <86box/video.h>
|
||||
#include <86box/keyboard.h>
|
||||
|
||||
|
||||
#define STAT_PARITY 0x80
|
||||
#define STAT_RTIMEOUT 0x40
|
||||
#define STAT_TTIMEOUT 0x20
|
||||
#define STAT_LOCK 0x10
|
||||
#define STAT_CD 0x08
|
||||
#define STAT_SYSFLAG 0x04
|
||||
#define STAT_IFULL 0x02
|
||||
#define STAT_OFULL 0x01
|
||||
#define STAT_PARITY 0x80
|
||||
#define STAT_RTIMEOUT 0x40
|
||||
#define STAT_TTIMEOUT 0x20
|
||||
#define STAT_LOCK 0x10
|
||||
#define STAT_CD 0x08
|
||||
#define STAT_SYSFLAG 0x04
|
||||
#define STAT_IFULL 0x02
|
||||
#define STAT_OFULL 0x01
|
||||
|
||||
// Keyboard Types
|
||||
#define KBD_TYPE_PC81 0
|
||||
@@ -79,9 +78,9 @@ typedef struct {
|
||||
pc_timer_t send_delay_timer;
|
||||
} xtkbd_t;
|
||||
|
||||
|
||||
/*XT keyboard has no escape scancodes, and no scancodes beyond 53*/
|
||||
const scancode scancode_xt[512] = {
|
||||
// clang-format off
|
||||
{ {0}, {0} }, { {0x01, 0}, {0x81, 0} },
|
||||
{ {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} },
|
||||
{ {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} },
|
||||
@@ -338,43 +337,42 @@ const scancode scancode_xt[512] = {
|
||||
{ {0}, {0} }, { {0}, {0} }, /*1f8*/
|
||||
{ {0}, {0} }, { {0}, {0} },
|
||||
{ {0}, {0} }, { {0}, {0} } /*1fc*/
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
||||
static uint8_t key_queue[16];
|
||||
static int key_queue_start = 0,
|
||||
key_queue_end = 0;
|
||||
static int is_tandy = 0, is_t1x00 = 0,
|
||||
is_amstrad = 0;
|
||||
|
||||
static uint8_t key_queue[16];
|
||||
static int key_queue_start = 0,
|
||||
key_queue_end = 0;
|
||||
static int is_tandy = 0, is_t1x00 = 0,
|
||||
is_amstrad = 0;
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_XT_LOG
|
||||
int keyboard_xt_do_log = ENABLE_KEYBOARD_XT_LOG;
|
||||
|
||||
|
||||
static void
|
||||
kbd_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (keyboard_xt_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define kbd_log(fmt, ...)
|
||||
# define kbd_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static uint8_t
|
||||
get_fdd_switch_settings() {
|
||||
get_fdd_switch_settings()
|
||||
{
|
||||
|
||||
int i, fdd_count = 0;
|
||||
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
if (fdd_get_flags(i))
|
||||
fdd_count++;
|
||||
if (fdd_get_flags(i))
|
||||
fdd_count++;
|
||||
}
|
||||
|
||||
if (!fdd_count)
|
||||
@@ -384,12 +382,13 @@ get_fdd_switch_settings() {
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
get_videomode_switch_settings() {
|
||||
get_videomode_switch_settings()
|
||||
{
|
||||
|
||||
if (video_is_mda())
|
||||
return 0x30;
|
||||
else if (video_is_cga())
|
||||
return 0x20; /* 0x10 would be 40x25 */
|
||||
return 0x20; /* 0x10 would be 40x25 */
|
||||
else
|
||||
return 0x00;
|
||||
}
|
||||
@@ -397,307 +396,304 @@ get_videomode_switch_settings() {
|
||||
static void
|
||||
kbd_poll(void *priv)
|
||||
{
|
||||
xtkbd_t *kbd = (xtkbd_t *)priv;
|
||||
xtkbd_t *kbd = (xtkbd_t *) priv;
|
||||
|
||||
timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC);
|
||||
|
||||
if (!(kbd->pb & 0x40) && (kbd->type != KBD_TYPE_TANDY))
|
||||
return;
|
||||
return;
|
||||
|
||||
if (kbd->want_irq) {
|
||||
kbd->want_irq = 0;
|
||||
kbd->pa = kbd->key_waiting;
|
||||
kbd->blocked = 1;
|
||||
picint(2);
|
||||
kbd->want_irq = 0;
|
||||
kbd->pa = kbd->key_waiting;
|
||||
kbd->blocked = 1;
|
||||
picint(2);
|
||||
#ifdef ENABLE_KEYBOARD_XT_LOG
|
||||
kbd_log("kbd_poll(): keyboard_xt : take IRQ\n");
|
||||
kbd_log("kbd_poll(): keyboard_xt : take IRQ\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((key_queue_start != key_queue_end) && !kbd->blocked) {
|
||||
kbd->key_waiting = key_queue[key_queue_start];
|
||||
kbd_log("XTkbd: reading %02X from the key queue at %i\n",
|
||||
kbd->key_waiting, key_queue_start);
|
||||
key_queue_start = (key_queue_start + 1) & 0x0f;
|
||||
kbd->want_irq = 1;
|
||||
kbd->key_waiting = key_queue[key_queue_start];
|
||||
kbd_log("XTkbd: reading %02X from the key queue at %i\n",
|
||||
kbd->key_waiting, key_queue_start);
|
||||
key_queue_start = (key_queue_start + 1) & 0x0f;
|
||||
kbd->want_irq = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
kbd_adddata(uint16_t val)
|
||||
{
|
||||
/* Test for T1000 'Fn' key (Right Alt / Right Ctrl) */
|
||||
if (is_t1x00) {
|
||||
if (keyboard_recv(0xb8) || keyboard_recv(0x9d)) { /* 'Fn' pressed */
|
||||
t1000_syskey(0x00, 0x04, 0x00); /* Set 'Fn' indicator */
|
||||
switch (val) {
|
||||
case 0x45: /* Num Lock => toggle numpad */
|
||||
t1000_syskey(0x00, 0x00, 0x10); break;
|
||||
case 0x47: /* Home => internal display */
|
||||
t1000_syskey(0x40, 0x00, 0x00); break;
|
||||
case 0x49: /* PgDn => turbo on */
|
||||
t1000_syskey(0x80, 0x00, 0x00); break;
|
||||
case 0x4D: /* Right => toggle LCD font */
|
||||
t1000_syskey(0x00, 0x00, 0x20); break;
|
||||
case 0x4F: /* End => external display */
|
||||
t1000_syskey(0x00, 0x40, 0x00); break;
|
||||
case 0x51: /* PgDn => turbo off */
|
||||
t1000_syskey(0x00, 0x80, 0x00); break;
|
||||
case 0x54: /* SysRQ => toggle window */
|
||||
t1000_syskey(0x00, 0x00, 0x08); break;
|
||||
}
|
||||
} else
|
||||
t1000_syskey(0x04, 0x00, 0x00); /* Reset 'Fn' indicator */
|
||||
if (keyboard_recv(0xb8) || keyboard_recv(0x9d)) { /* 'Fn' pressed */
|
||||
t1000_syskey(0x00, 0x04, 0x00); /* Set 'Fn' indicator */
|
||||
switch (val) {
|
||||
case 0x45: /* Num Lock => toggle numpad */
|
||||
t1000_syskey(0x00, 0x00, 0x10);
|
||||
break;
|
||||
case 0x47: /* Home => internal display */
|
||||
t1000_syskey(0x40, 0x00, 0x00);
|
||||
break;
|
||||
case 0x49: /* PgDn => turbo on */
|
||||
t1000_syskey(0x80, 0x00, 0x00);
|
||||
break;
|
||||
case 0x4D: /* Right => toggle LCD font */
|
||||
t1000_syskey(0x00, 0x00, 0x20);
|
||||
break;
|
||||
case 0x4F: /* End => external display */
|
||||
t1000_syskey(0x00, 0x40, 0x00);
|
||||
break;
|
||||
case 0x51: /* PgDn => turbo off */
|
||||
t1000_syskey(0x00, 0x80, 0x00);
|
||||
break;
|
||||
case 0x54: /* SysRQ => toggle window */
|
||||
t1000_syskey(0x00, 0x00, 0x08);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
t1000_syskey(0x04, 0x00, 0x00); /* Reset 'Fn' indicator */
|
||||
}
|
||||
|
||||
key_queue[key_queue_end] = val;
|
||||
kbd_log("XTkbd: %02X added to key queue at %i\n",
|
||||
val, key_queue_end);
|
||||
val, key_queue_end);
|
||||
key_queue_end = (key_queue_end + 1) & 0x0f;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val))
|
||||
{
|
||||
uint8_t num_lock = 0, shift_states = 0;
|
||||
|
||||
if (!adddata)
|
||||
return;
|
||||
return;
|
||||
|
||||
keyboard_get_states(NULL, &num_lock, NULL);
|
||||
shift_states = keyboard_get_shift() & STATE_LSHIFT;
|
||||
|
||||
if (is_amstrad)
|
||||
num_lock = !num_lock;
|
||||
num_lock = !num_lock;
|
||||
|
||||
/* If NumLock is on, invert the left shift state so we can always check for
|
||||
the the same way flag being set (and with NumLock on that then means it
|
||||
is actually *NOT* set). */
|
||||
if (num_lock)
|
||||
shift_states ^= STATE_LSHIFT;
|
||||
shift_states ^= STATE_LSHIFT;
|
||||
|
||||
switch(val) {
|
||||
case FAKE_LSHIFT_ON:
|
||||
/* If NumLock is on, fake shifts are sent when shift is *NOT* presed,
|
||||
if NumLock is off, fake shifts are sent when shift is pressed. */
|
||||
if (shift_states) {
|
||||
/* Send fake shift. */
|
||||
adddata(num_lock ? 0x2a : 0xaa);
|
||||
}
|
||||
break;
|
||||
case FAKE_LSHIFT_OFF:
|
||||
if (shift_states) {
|
||||
/* Send fake shift. */
|
||||
adddata(num_lock ? 0xaa : 0x2a);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
adddata(val);
|
||||
break;
|
||||
switch (val) {
|
||||
case FAKE_LSHIFT_ON:
|
||||
/* If NumLock is on, fake shifts are sent when shift is *NOT* presed,
|
||||
if NumLock is off, fake shifts are sent when shift is pressed. */
|
||||
if (shift_states) {
|
||||
/* Send fake shift. */
|
||||
adddata(num_lock ? 0x2a : 0xaa);
|
||||
}
|
||||
break;
|
||||
case FAKE_LSHIFT_OFF:
|
||||
if (shift_states) {
|
||||
/* Send fake shift. */
|
||||
adddata(num_lock ? 0xaa : 0x2a);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
adddata(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
kbd_adddata_ex(uint16_t val)
|
||||
{
|
||||
kbd_adddata_process(val, kbd_adddata);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
xtkbd_t *kbd = (xtkbd_t *)priv;
|
||||
xtkbd_t *kbd = (xtkbd_t *) priv;
|
||||
|
||||
switch (port) {
|
||||
case 0x61: /* Keyboard Control Register (aka Port B) */
|
||||
if (!(kbd->pb & 0x40) && (val & 0x40)) {
|
||||
key_queue_start = key_queue_end = 0;
|
||||
kbd->want_irq = 0;
|
||||
kbd->blocked = 0;
|
||||
kbd_adddata(0xaa);
|
||||
}
|
||||
kbd->pb = val;
|
||||
ppi.pb = val;
|
||||
case 0x61: /* Keyboard Control Register (aka Port B) */
|
||||
if (!(kbd->pb & 0x40) && (val & 0x40)) {
|
||||
key_queue_start = key_queue_end = 0;
|
||||
kbd->want_irq = 0;
|
||||
kbd->blocked = 0;
|
||||
kbd_adddata(0xaa);
|
||||
}
|
||||
kbd->pb = val;
|
||||
ppi.pb = val;
|
||||
|
||||
timer_process();
|
||||
timer_process();
|
||||
|
||||
if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) && (cassette != NULL))
|
||||
pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0);
|
||||
if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) && (cassette != NULL))
|
||||
pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0);
|
||||
|
||||
speaker_update();
|
||||
speaker_update();
|
||||
|
||||
speaker_gated = val & 1;
|
||||
speaker_enable = val & 2;
|
||||
speaker_gated = val & 1;
|
||||
speaker_enable = val & 2;
|
||||
|
||||
if (speaker_enable)
|
||||
was_speaker_enable = 1;
|
||||
pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1);
|
||||
if (speaker_enable)
|
||||
was_speaker_enable = 1;
|
||||
pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1);
|
||||
|
||||
if (val & 0x80) {
|
||||
kbd->pa = 0;
|
||||
kbd->blocked = 0;
|
||||
picintc(2);
|
||||
}
|
||||
if (val & 0x80) {
|
||||
kbd->pa = 0;
|
||||
kbd->blocked = 0;
|
||||
picintc(2);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_KEYBOARD_XT_LOG
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82))
|
||||
kbd_log("Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF");
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82))
|
||||
kbd_log("Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF");
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
#ifdef ENABLE_KEYBOARD_XT_LOG
|
||||
case 0x62: /* Switch Register (aka Port C) */
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82))
|
||||
kbd_log("Cassette IN is %i\n", !!(val & 0x10));
|
||||
break;
|
||||
case 0x62: /* Switch Register (aka Port C) */
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82))
|
||||
kbd_log("Cassette IN is %i\n", !!(val & 0x10));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
kbd_read(uint16_t port, void *priv)
|
||||
{
|
||||
xtkbd_t *kbd = (xtkbd_t *)priv;
|
||||
uint8_t ret = 0xff;
|
||||
xtkbd_t *kbd = (xtkbd_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port) {
|
||||
case 0x60: /* Keyboard Data Register (aka Port A) */
|
||||
if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)
|
||||
|| (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)
|
||||
|| (kbd->type == KBD_TYPE_ZENITH))) {
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82))
|
||||
ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00);
|
||||
else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86))
|
||||
ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */
|
||||
else if (kbd->type == KBD_TYPE_ZENITH) {
|
||||
/* Zenith Data Systems Z-151
|
||||
* SW1 switch settings:
|
||||
* bits 6-7: floppy drive number
|
||||
* bits 4-5: video mode
|
||||
* bit 2-3: base memory size
|
||||
* bit 1: fpu enable
|
||||
* bit 0: fdc enable
|
||||
*/
|
||||
ret = get_fdd_switch_settings();
|
||||
case 0x60: /* Keyboard Data Register (aka Port A) */
|
||||
if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_ZENITH))) {
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82))
|
||||
ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00);
|
||||
else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86))
|
||||
ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */
|
||||
else if (kbd->type == KBD_TYPE_ZENITH) {
|
||||
/* Zenith Data Systems Z-151
|
||||
* SW1 switch settings:
|
||||
* bits 6-7: floppy drive number
|
||||
* bits 4-5: video mode
|
||||
* bit 2-3: base memory size
|
||||
* bit 1: fpu enable
|
||||
* bit 0: fdc enable
|
||||
*/
|
||||
ret = get_fdd_switch_settings();
|
||||
|
||||
ret |= get_videomode_switch_settings();
|
||||
ret |= get_videomode_switch_settings();
|
||||
|
||||
/* Base memory size should always be 64k */
|
||||
ret |= 0x0c;
|
||||
/* Base memory size should always be 64k */
|
||||
ret |= 0x0c;
|
||||
|
||||
if (hasfpu)
|
||||
ret |= 0x02;
|
||||
}
|
||||
} else
|
||||
ret = kbd->pa;
|
||||
break;
|
||||
|
||||
case 0x61: /* Keyboard Control Register (aka Port B) */
|
||||
ret = kbd->pb;
|
||||
break;
|
||||
|
||||
case 0x62: /* Switch Register (aka Port C) */
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) {
|
||||
if (kbd->pb & 0x04) /* PB2 */
|
||||
switch (mem_size + isa_mem_size) {
|
||||
case 64:
|
||||
case 48:
|
||||
case 32:
|
||||
case 16:
|
||||
ret = 0x00;
|
||||
break;
|
||||
default:
|
||||
ret = (((mem_size + isa_mem_size) - 64) / 32) & 0x0f;
|
||||
break;
|
||||
if (hasfpu)
|
||||
ret |= 0x02;
|
||||
}
|
||||
else
|
||||
ret = (((mem_size + isa_mem_size) - 64) / 32) >> 4;
|
||||
} else if (kbd->type == KBD_TYPE_OLIVETTI
|
||||
|| kbd->type == KBD_TYPE_ZENITH) {
|
||||
/* Olivetti M19 or Zenith Data Systems Z-151 */
|
||||
if (kbd->pb & 0x04) /* PB2 */
|
||||
ret = kbd->pd & 0xbf;
|
||||
else
|
||||
ret = kbd->pd >> 4;
|
||||
} else {
|
||||
if (kbd->pb & 0x08) /* PB3 */
|
||||
ret = kbd->pd >> 4;
|
||||
else {
|
||||
/* LaserXT = Always 512k RAM;
|
||||
LaserXT/3 = Bit 0: set = 512k, clear = 256k. */
|
||||
} else
|
||||
ret = kbd->pa;
|
||||
break;
|
||||
|
||||
case 0x61: /* Keyboard Control Register (aka Port B) */
|
||||
ret = kbd->pb;
|
||||
break;
|
||||
|
||||
case 0x62: /* Switch Register (aka Port C) */
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) {
|
||||
if (kbd->pb & 0x04) /* PB2 */
|
||||
switch (mem_size + isa_mem_size) {
|
||||
case 64:
|
||||
case 48:
|
||||
case 32:
|
||||
case 16:
|
||||
ret = 0x00;
|
||||
break;
|
||||
default:
|
||||
ret = (((mem_size + isa_mem_size) - 64) / 32) & 0x0f;
|
||||
break;
|
||||
}
|
||||
else
|
||||
ret = (((mem_size + isa_mem_size) - 64) / 32) >> 4;
|
||||
} else if (kbd->type == KBD_TYPE_OLIVETTI
|
||||
|| kbd->type == KBD_TYPE_ZENITH) {
|
||||
/* Olivetti M19 or Zenith Data Systems Z-151 */
|
||||
if (kbd->pb & 0x04) /* PB2 */
|
||||
ret = kbd->pd & 0xbf;
|
||||
else
|
||||
ret = kbd->pd >> 4;
|
||||
} else {
|
||||
if (kbd->pb & 0x08) /* PB3 */
|
||||
ret = kbd->pd >> 4;
|
||||
else {
|
||||
/* LaserXT = Always 512k RAM;
|
||||
LaserXT/3 = Bit 0: set = 512k, clear = 256k. */
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
if (kbd->type == KBD_TYPE_TOSHIBA)
|
||||
ret = ((mem_size == 512) ? 0x0d : 0x0c) | (hasfpu ? 0x02 : 0x00);
|
||||
else
|
||||
if (kbd->type == KBD_TYPE_TOSHIBA)
|
||||
ret = ((mem_size == 512) ? 0x0d : 0x0c) | (hasfpu ? 0x02 : 0x00);
|
||||
else
|
||||
#endif
|
||||
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
|
||||
}
|
||||
}
|
||||
ret |= (ppispeakon ? 0x20 : 0);
|
||||
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
|
||||
}
|
||||
}
|
||||
ret |= (ppispeakon ? 0x20 : 0);
|
||||
|
||||
/* This is needed to avoid error 131 (cassette error).
|
||||
This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) {
|
||||
if (cassette == NULL)
|
||||
ret |= (ppispeakon ? 0x10 : 0);
|
||||
else
|
||||
ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0);
|
||||
}
|
||||
/* This is needed to avoid error 131 (cassette error).
|
||||
This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) {
|
||||
if (cassette == NULL)
|
||||
ret |= (ppispeakon ? 0x10 : 0);
|
||||
else
|
||||
ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0);
|
||||
}
|
||||
|
||||
if (kbd->type == KBD_TYPE_TANDY)
|
||||
ret |= (tandy1k_eeprom_read() ? 0x10 : 0);
|
||||
break;
|
||||
if (kbd->type == KBD_TYPE_TANDY)
|
||||
ret |= (tandy1k_eeprom_read() ? 0x10 : 0);
|
||||
break;
|
||||
|
||||
case 0x63: /* Keyboard Configuration Register (aka Port D) */
|
||||
if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)
|
||||
case 0x63: /* Keyboard Configuration Register (aka Port D) */
|
||||
if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)
|
||||
|| (kbd->type == KBD_TYPE_COMPAQ)
|
||||
|| (kbd->type == KBD_TYPE_TOSHIBA))
|
||||
ret = kbd->pd;
|
||||
break;
|
||||
ret = kbd->pd;
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
kbd_reset(void *priv)
|
||||
{
|
||||
xtkbd_t *kbd = (xtkbd_t *)priv;
|
||||
xtkbd_t *kbd = (xtkbd_t *) priv;
|
||||
|
||||
kbd->want_irq = 0;
|
||||
kbd->blocked = 0;
|
||||
kbd->pa = 0x00;
|
||||
kbd->pb = 0x00;
|
||||
kbd->blocked = 0;
|
||||
kbd->pa = 0x00;
|
||||
kbd->pb = 0x00;
|
||||
|
||||
keyboard_scan = 1;
|
||||
|
||||
key_queue_start = 0,
|
||||
key_queue_end = 0;
|
||||
key_queue_end = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
keyboard_set_is_amstrad(int ams)
|
||||
{
|
||||
is_amstrad = ams;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
kbd_init(const device_t *info)
|
||||
{
|
||||
xtkbd_t *kbd;
|
||||
|
||||
kbd = (xtkbd_t *)malloc(sizeof(xtkbd_t));
|
||||
kbd = (xtkbd_t *) malloc(sizeof(xtkbd_t));
|
||||
memset(kbd, 0x00, sizeof(xtkbd_t));
|
||||
|
||||
io_sethandler(0x0060, 4,
|
||||
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
|
||||
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
|
||||
keyboard_send = kbd_adddata_ex;
|
||||
kbd_reset(kbd);
|
||||
kbd->type = info->local;
|
||||
@@ -707,31 +703,31 @@ kbd_init(const device_t *info)
|
||||
video_reset(gfxcard);
|
||||
|
||||
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)
|
||||
|| (kbd->type == KBD_TYPE_XT82) || (kbd->type <= KBD_TYPE_XT86)
|
||||
|| (kbd->type == KBD_TYPE_COMPAQ)
|
||||
|| (kbd->type == KBD_TYPE_TOSHIBA)
|
||||
|| (kbd->type == KBD_TYPE_OLIVETTI)) {
|
||||
|| (kbd->type == KBD_TYPE_XT82) || (kbd->type <= KBD_TYPE_XT86)
|
||||
|| (kbd->type == KBD_TYPE_COMPAQ)
|
||||
|| (kbd->type == KBD_TYPE_TOSHIBA)
|
||||
|| (kbd->type == KBD_TYPE_OLIVETTI)) {
|
||||
|
||||
/* DIP switch readout: bit set = OFF, clear = ON. */
|
||||
if (kbd->type == KBD_TYPE_OLIVETTI)
|
||||
/* Olivetti M19
|
||||
* Jumpers J1, J2 - monitor type.
|
||||
* 01 - mono (high-res)
|
||||
* 10 - color (low-res, disables 640x400x2 mode)
|
||||
* 00 - autoswitching
|
||||
*/
|
||||
kbd->pd |= 0x00;
|
||||
else
|
||||
/* Switches 7, 8 - floppy drives. */
|
||||
kbd->pd = get_fdd_switch_settings();
|
||||
/* Olivetti M19
|
||||
* Jumpers J1, J2 - monitor type.
|
||||
* 01 - mono (high-res)
|
||||
* 10 - color (low-res, disables 640x400x2 mode)
|
||||
* 00 - autoswitching
|
||||
*/
|
||||
kbd->pd |= 0x00;
|
||||
else
|
||||
/* Switches 7, 8 - floppy drives. */
|
||||
kbd->pd = get_fdd_switch_settings();
|
||||
|
||||
/* Siitches 5, 6 - video card type */
|
||||
kbd->pd |= get_videomode_switch_settings();
|
||||
kbd->pd |= get_videomode_switch_settings();
|
||||
|
||||
/* Switches 3, 4 - memory size. */
|
||||
if ((kbd->type == KBD_TYPE_XT86)
|
||||
|| (kbd->type == KBD_TYPE_COMPAQ)
|
||||
|| (kbd->type == KBD_TYPE_TOSHIBA)) {
|
||||
|| (kbd->type == KBD_TYPE_COMPAQ)
|
||||
|| (kbd->type == KBD_TYPE_TOSHIBA)) {
|
||||
switch (mem_size) {
|
||||
case 256:
|
||||
kbd->pd |= 0x00;
|
||||
@@ -747,9 +743,9 @@ kbd_init(const device_t *info)
|
||||
kbd->pd |= 0x0c;
|
||||
break;
|
||||
}
|
||||
} else if (kbd->type == KBD_TYPE_XT82) {
|
||||
} else if (kbd->type == KBD_TYPE_XT82) {
|
||||
switch (mem_size) {
|
||||
case 64: /* 1x64k */
|
||||
case 64: /* 1x64k */
|
||||
kbd->pd |= 0x00;
|
||||
break;
|
||||
case 128: /* 2x64k */
|
||||
@@ -763,7 +759,7 @@ kbd_init(const device_t *info)
|
||||
kbd->pd |= 0x0c;
|
||||
break;
|
||||
}
|
||||
} else if (kbd->type == KBD_TYPE_PC82) {
|
||||
} else if (kbd->type == KBD_TYPE_PC82) {
|
||||
switch (mem_size) {
|
||||
case 192: /* 3x64k, not supported by stock BIOS due to bugs */
|
||||
kbd->pd |= 0x08;
|
||||
@@ -793,19 +789,19 @@ kbd_init(const device_t *info)
|
||||
default:
|
||||
kbd->pd |= 0x0c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Switch 2 - 8087 FPU. */
|
||||
if (hasfpu)
|
||||
kbd->pd |= 0x02;
|
||||
} else if (kbd-> type == KBD_TYPE_ZENITH) {
|
||||
} else if (kbd->type == KBD_TYPE_ZENITH) {
|
||||
/* Zenith Data Systems Z-151
|
||||
* SW2 switch settings:
|
||||
* bit 7: monitor frequency
|
||||
* bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd)
|
||||
* bits 0-4: installed memory
|
||||
*/
|
||||
* SW2 switch settings:
|
||||
* bit 7: monitor frequency
|
||||
* bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd)
|
||||
* bits 0-4: installed memory
|
||||
*/
|
||||
kbd->pd = 0x20;
|
||||
switch (mem_size) {
|
||||
case 128:
|
||||
@@ -848,14 +844,13 @@ kbd_init(const device_t *info)
|
||||
|
||||
is_amstrad = 0;
|
||||
|
||||
return(kbd);
|
||||
return (kbd);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
kbd_close(void *priv)
|
||||
{
|
||||
xtkbd_t *kbd = (xtkbd_t *)priv;
|
||||
xtkbd_t *kbd = (xtkbd_t *) priv;
|
||||
|
||||
/* Stop the timer. */
|
||||
timer_disable(&kbd->send_delay_timer);
|
||||
@@ -866,149 +861,149 @@ kbd_close(void *priv)
|
||||
keyboard_send = NULL;
|
||||
|
||||
io_removehandler(0x0060, 4,
|
||||
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
|
||||
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
|
||||
|
||||
free(kbd);
|
||||
}
|
||||
|
||||
const device_t keyboard_pc_device = {
|
||||
.name = "IBM PC Keyboard (1981)",
|
||||
.name = "IBM PC Keyboard (1981)",
|
||||
.internal_name = "keyboard_pc",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_PC81,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_PC81,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_pc82_device = {
|
||||
.name = "IBM PC Keyboard (1982)",
|
||||
.name = "IBM PC Keyboard (1982)",
|
||||
.internal_name = "keyboard_pc82",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_PC82,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_PC82,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt_device = {
|
||||
.name = "XT (1982) Keyboard",
|
||||
.name = "XT (1982) Keyboard",
|
||||
.internal_name = "keyboard_xt",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_XT82,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_XT82,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt86_device = {
|
||||
.name = "XT (1986) Keyboard",
|
||||
.name = "XT (1986) Keyboard",
|
||||
.internal_name = "keyboard_xt86",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_XT86,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_XT86,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt_compaq_device = {
|
||||
.name = "Compaq Portable Keyboard",
|
||||
.name = "Compaq Portable Keyboard",
|
||||
.internal_name = "keyboard_xt_compaq",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_COMPAQ,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_COMPAQ,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_tandy_device = {
|
||||
.name = "Tandy 1000 Keyboard",
|
||||
.name = "Tandy 1000 Keyboard",
|
||||
.internal_name = "keyboard_tandy",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_TANDY,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_TANDY,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt_t1x00_device = {
|
||||
.name = "Toshiba T1x00 Keyboard",
|
||||
.name = "Toshiba T1x00 Keyboard",
|
||||
.internal_name = "keyboard_xt_t1x00",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_TOSHIBA,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_TOSHIBA,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
const device_t keyboard_xt_lxt3_device = {
|
||||
.name = "VTech Laser XT3 Keyboard",
|
||||
.name = "VTech Laser XT3 Keyboard",
|
||||
.internal_name = "keyboard_xt_lxt3",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_VTECH,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_VTECH,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
const device_t keyboard_xt_olivetti_device = {
|
||||
.name = "Olivetti XT Keyboard",
|
||||
.name = "Olivetti XT Keyboard",
|
||||
.internal_name = "keyboard_xt_olivetti",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_OLIVETTI,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_OLIVETTI,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt_zenith_device = {
|
||||
.name = "Zenith XT Keyboard",
|
||||
.name = "Zenith XT Keyboard",
|
||||
.internal_name = "keyboard_xt_zenith",
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_ZENITH,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
.flags = 0,
|
||||
.local = KBD_TYPE_ZENITH,
|
||||
.init = kbd_init,
|
||||
.close = kbd_close,
|
||||
.reset = kbd_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
@@ -29,48 +29,46 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/mouse.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
const device_t *device;
|
||||
const device_t *device;
|
||||
} mouse_t;
|
||||
|
||||
|
||||
int mouse_type = 0;
|
||||
int mouse_x,
|
||||
mouse_y,
|
||||
mouse_z,
|
||||
mouse_buttons;
|
||||
int mouse_type = 0;
|
||||
int mouse_x,
|
||||
mouse_y,
|
||||
mouse_z,
|
||||
mouse_buttons;
|
||||
|
||||
static const device_t mouse_none_device = {
|
||||
.name = "None",
|
||||
.name = "None",
|
||||
.internal_name = "none",
|
||||
.flags = 0,
|
||||
.local = MOUSE_TYPE_NONE,
|
||||
.init = NULL,
|
||||
.close = NULL,
|
||||
.reset = NULL,
|
||||
.flags = 0,
|
||||
.local = MOUSE_TYPE_NONE,
|
||||
.init = NULL,
|
||||
.close = NULL,
|
||||
.reset = NULL,
|
||||
{ .poll = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
static const device_t mouse_internal_device = {
|
||||
.name = "Internal",
|
||||
.name = "Internal",
|
||||
.internal_name = "internal",
|
||||
.flags = 0,
|
||||
.local = MOUSE_TYPE_INTERNAL,
|
||||
.init = NULL,
|
||||
.close = NULL,
|
||||
.reset = NULL,
|
||||
.flags = 0,
|
||||
.local = MOUSE_TYPE_INTERNAL,
|
||||
.init = NULL,
|
||||
.close = NULL,
|
||||
.reset = NULL,
|
||||
{ .poll = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
static mouse_t mouse_devices[] = {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
{ &mouse_none_device },
|
||||
{ &mouse_internal_device },
|
||||
{ &mouse_logibus_device },
|
||||
@@ -83,87 +81,82 @@ static mouse_t mouse_devices[] = {
|
||||
{ &mouse_ltserial_device },
|
||||
{ &mouse_ps2_device },
|
||||
{ NULL }
|
||||
// clang-format on
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
||||
static const device_t *mouse_curr;
|
||||
static void *mouse_priv;
|
||||
static int mouse_nbut;
|
||||
static int (*mouse_dev_poll)();
|
||||
|
||||
static const device_t *mouse_curr;
|
||||
static void *mouse_priv;
|
||||
static int mouse_nbut;
|
||||
static int (*mouse_dev_poll)();
|
||||
|
||||
#ifdef ENABLE_MOUSE_LOG
|
||||
int mouse_do_log = ENABLE_MOUSE_LOG;
|
||||
|
||||
|
||||
static void
|
||||
mouse_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (mouse_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define mouse_log(fmt, ...)
|
||||
# define mouse_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Initialize the mouse module. */
|
||||
void
|
||||
mouse_init(void)
|
||||
{
|
||||
/* Initialize local data. */
|
||||
mouse_x = mouse_y = mouse_z = 0;
|
||||
mouse_buttons = 0x00;
|
||||
mouse_buttons = 0x00;
|
||||
|
||||
mouse_type = MOUSE_TYPE_NONE;
|
||||
mouse_curr = NULL;
|
||||
mouse_priv = NULL;
|
||||
mouse_nbut = 0;
|
||||
mouse_type = MOUSE_TYPE_NONE;
|
||||
mouse_curr = NULL;
|
||||
mouse_priv = NULL;
|
||||
mouse_nbut = 0;
|
||||
mouse_dev_poll = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mouse_close(void)
|
||||
{
|
||||
if (mouse_curr == NULL) return;
|
||||
if (mouse_curr == NULL)
|
||||
return;
|
||||
|
||||
mouse_curr = NULL;
|
||||
mouse_priv = NULL;
|
||||
mouse_nbut = 0;
|
||||
mouse_curr = NULL;
|
||||
mouse_priv = NULL;
|
||||
mouse_nbut = 0;
|
||||
mouse_dev_poll = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mouse_reset(void)
|
||||
{
|
||||
if (mouse_curr != NULL)
|
||||
return; /* Mouse already initialized. */
|
||||
return; /* Mouse already initialized. */
|
||||
|
||||
mouse_log("MOUSE: reset(type=%d, '%s')\n",
|
||||
mouse_type, mouse_devices[mouse_type].device->name);
|
||||
mouse_type, mouse_devices[mouse_type].device->name);
|
||||
|
||||
/* Clear local data. */
|
||||
mouse_x = mouse_y = mouse_z = 0;
|
||||
mouse_buttons = 0x00;
|
||||
mouse_buttons = 0x00;
|
||||
|
||||
/* If no mouse configured, we're done. */
|
||||
if (mouse_type == 0) return;
|
||||
if (mouse_type == 0)
|
||||
return;
|
||||
|
||||
mouse_curr = mouse_devices[mouse_type].device;
|
||||
|
||||
if (mouse_curr != NULL)
|
||||
mouse_priv = device_add(mouse_curr);
|
||||
mouse_priv = device_add(mouse_curr);
|
||||
}
|
||||
|
||||
|
||||
/* Callback from the hardware driver. */
|
||||
void
|
||||
mouse_set_buttons(int buttons)
|
||||
@@ -171,98 +164,92 @@ mouse_set_buttons(int buttons)
|
||||
mouse_nbut = buttons;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mouse_process(void)
|
||||
{
|
||||
static int poll_delay = 2;
|
||||
|
||||
if (mouse_curr == NULL)
|
||||
return;
|
||||
return;
|
||||
|
||||
if (--poll_delay) return;
|
||||
if (--poll_delay)
|
||||
return;
|
||||
|
||||
mouse_poll();
|
||||
|
||||
if ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL)) {
|
||||
if (mouse_curr->poll != NULL)
|
||||
mouse_curr->poll(mouse_x,mouse_y,mouse_z,mouse_buttons, mouse_priv);
|
||||
else
|
||||
mouse_dev_poll(mouse_x,mouse_y,mouse_z,mouse_buttons, mouse_priv);
|
||||
if (mouse_curr->poll != NULL)
|
||||
mouse_curr->poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_priv);
|
||||
else
|
||||
mouse_dev_poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_priv);
|
||||
|
||||
/* Reset mouse deltas. */
|
||||
mouse_x = mouse_y = mouse_z = 0;
|
||||
/* Reset mouse deltas. */
|
||||
mouse_x = mouse_y = mouse_z = 0;
|
||||
}
|
||||
|
||||
poll_delay = 2;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mouse_set_poll(int (*func)(int,int,int,int,void *), void *arg)
|
||||
mouse_set_poll(int (*func)(int, int, int, int, void *), void *arg)
|
||||
{
|
||||
if (mouse_type != MOUSE_TYPE_INTERNAL) return;
|
||||
if (mouse_type != MOUSE_TYPE_INTERNAL)
|
||||
return;
|
||||
|
||||
mouse_dev_poll = func;
|
||||
mouse_priv = arg;
|
||||
mouse_priv = arg;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
mouse_get_name(int mouse)
|
||||
{
|
||||
return((char *)mouse_devices[mouse].device->name);
|
||||
return ((char *) mouse_devices[mouse].device->name);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
mouse_get_internal_name(int mouse)
|
||||
{
|
||||
return device_get_internal_name(mouse_devices[mouse].device);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mouse_get_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (mouse_devices[c].device != NULL) {
|
||||
if (! strcmp((char *)mouse_devices[c].device->internal_name, s))
|
||||
return(c);
|
||||
c++;
|
||||
if (!strcmp((char *) mouse_devices[c].device->internal_name, s))
|
||||
return (c);
|
||||
c++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mouse_has_config(int mouse)
|
||||
{
|
||||
if (mouse_devices[mouse].device == NULL) return(0);
|
||||
if (mouse_devices[mouse].device == NULL)
|
||||
return (0);
|
||||
|
||||
return(mouse_devices[mouse].device->config ? 1 : 0);
|
||||
return (mouse_devices[mouse].device->config ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
const device_t *
|
||||
mouse_get_device(int mouse)
|
||||
{
|
||||
return(mouse_devices[mouse].device);
|
||||
return (mouse_devices[mouse].device);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mouse_get_buttons(void)
|
||||
{
|
||||
return(mouse_nbut);
|
||||
return (mouse_nbut);
|
||||
}
|
||||
|
||||
|
||||
/* Return number of MOUSE types we know about. */
|
||||
int
|
||||
mouse_get_ndev(void)
|
||||
{
|
||||
return((sizeof(mouse_devices)/sizeof(mouse_t)) - 1);
|
||||
return ((sizeof(mouse_devices) / sizeof(mouse_t)) - 1);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -24,215 +24,205 @@
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mouse.h>
|
||||
|
||||
|
||||
enum {
|
||||
MODE_STREAM,
|
||||
MODE_REMOTE,
|
||||
MODE_ECHO
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *name; /* name of this device */
|
||||
int8_t type; /* type of this device */
|
||||
const char *name; /* name of this device */
|
||||
int8_t type; /* type of this device */
|
||||
|
||||
int mode;
|
||||
int mode;
|
||||
|
||||
uint8_t flags;
|
||||
uint8_t resolution;
|
||||
uint8_t sample_rate;
|
||||
uint8_t flags;
|
||||
uint8_t resolution;
|
||||
uint8_t sample_rate;
|
||||
|
||||
uint8_t command;
|
||||
uint8_t command;
|
||||
|
||||
int x, y, z, b;
|
||||
int x, y, z, b;
|
||||
|
||||
uint8_t last_data[6];
|
||||
uint8_t last_data[6];
|
||||
} mouse_t;
|
||||
#define FLAG_INTELLI 0x80 /* device is IntelliMouse */
|
||||
#define FLAG_INTMODE 0x40 /* using Intellimouse mode */
|
||||
#define FLAG_SCALED 0x20 /* enable delta scaling */
|
||||
#define FLAG_ENABLED 0x10 /* dev is enabled for use */
|
||||
#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */
|
||||
|
||||
#define FLAG_INTELLI 0x80 /* device is IntelliMouse */
|
||||
#define FLAG_INTMODE 0x40 /* using Intellimouse mode */
|
||||
#define FLAG_SCALED 0x20 /* enable delta scaling */
|
||||
#define FLAG_ENABLED 0x10 /* dev is enabled for use */
|
||||
#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */
|
||||
|
||||
int mouse_scan = 0;
|
||||
|
||||
|
||||
#ifdef ENABLE_MOUSE_PS2_LOG
|
||||
int mouse_ps2_do_log = ENABLE_MOUSE_PS2_LOG;
|
||||
|
||||
|
||||
static void
|
||||
mouse_ps2_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (mouse_ps2_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define mouse_ps2_log(fmt, ...)
|
||||
# define mouse_ps2_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
mouse_clear_data(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
|
||||
dev->flags &= ~FLAG_CTRLDAT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ps2_write(uint8_t val, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t temp;
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
uint8_t temp;
|
||||
|
||||
if (dev->flags & FLAG_CTRLDAT) {
|
||||
dev->flags &= ~FLAG_CTRLDAT;
|
||||
dev->flags &= ~FLAG_CTRLDAT;
|
||||
|
||||
if (val == 0xff)
|
||||
goto mouse_reset;
|
||||
if (val == 0xff)
|
||||
goto mouse_reset;
|
||||
|
||||
switch (dev->command) {
|
||||
case 0xe8: /* set mouse resolution */
|
||||
dev->resolution = val;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
switch (dev->command) {
|
||||
case 0xe8: /* set mouse resolution */
|
||||
dev->resolution = val;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
|
||||
case 0xf3: /* set sample rate */
|
||||
dev->sample_rate = val;
|
||||
keyboard_at_adddata_mouse(0xfa); /* Command response */
|
||||
break;
|
||||
case 0xf3: /* set sample rate */
|
||||
dev->sample_rate = val;
|
||||
keyboard_at_adddata_mouse(0xfa); /* Command response */
|
||||
break;
|
||||
|
||||
default:
|
||||
keyboard_at_adddata_mouse(0xfc);
|
||||
}
|
||||
default:
|
||||
keyboard_at_adddata_mouse(0xfc);
|
||||
}
|
||||
} else {
|
||||
dev->command = val;
|
||||
dev->command = val;
|
||||
|
||||
switch (dev->command) {
|
||||
case 0xe6: /* set scaling to 1:1 */
|
||||
dev->flags &= ~FLAG_SCALED;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
switch (dev->command) {
|
||||
case 0xe6: /* set scaling to 1:1 */
|
||||
dev->flags &= ~FLAG_SCALED;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
|
||||
case 0xe7: /* set scaling to 2:1 */
|
||||
dev->flags |= FLAG_SCALED;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
case 0xe7: /* set scaling to 2:1 */
|
||||
dev->flags |= FLAG_SCALED;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
|
||||
case 0xe8: /* set mouse resolution */
|
||||
dev->flags |= FLAG_CTRLDAT;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
case 0xe8: /* set mouse resolution */
|
||||
dev->flags |= FLAG_CTRLDAT;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
|
||||
case 0xe9: /* status request */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
temp = (dev->flags & 0x30);
|
||||
if (mouse_buttons & 0x01)
|
||||
temp |= 0x01;
|
||||
if (mouse_buttons & 0x02)
|
||||
temp |= 0x02;
|
||||
if (mouse_buttons & 0x04)
|
||||
temp |= 0x03;
|
||||
keyboard_at_adddata_mouse(temp);
|
||||
keyboard_at_adddata_mouse(dev->resolution);
|
||||
keyboard_at_adddata_mouse(dev->sample_rate);
|
||||
break;
|
||||
case 0xe9: /* status request */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
temp = (dev->flags & 0x30);
|
||||
if (mouse_buttons & 0x01)
|
||||
temp |= 0x01;
|
||||
if (mouse_buttons & 0x02)
|
||||
temp |= 0x02;
|
||||
if (mouse_buttons & 0x04)
|
||||
temp |= 0x03;
|
||||
keyboard_at_adddata_mouse(temp);
|
||||
keyboard_at_adddata_mouse(dev->resolution);
|
||||
keyboard_at_adddata_mouse(dev->sample_rate);
|
||||
break;
|
||||
|
||||
case 0xeb: /* Get mouse data */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
case 0xeb: /* Get mouse data */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
|
||||
temp = 0;
|
||||
if (dev->x < 0)
|
||||
temp |= 0x10;
|
||||
if (dev->y < 0)
|
||||
temp |= 0x20;
|
||||
if (mouse_buttons & 1)
|
||||
temp |= 1;
|
||||
if (mouse_buttons & 2)
|
||||
temp |= 2;
|
||||
if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI))
|
||||
temp |= 4;
|
||||
keyboard_at_adddata_mouse(temp);
|
||||
keyboard_at_adddata_mouse(dev->x & 0xff);
|
||||
keyboard_at_adddata_mouse(dev->y & 0xff);
|
||||
if (dev->flags & FLAG_INTMODE)
|
||||
keyboard_at_adddata_mouse(dev->z);
|
||||
break;
|
||||
temp = 0;
|
||||
if (dev->x < 0)
|
||||
temp |= 0x10;
|
||||
if (dev->y < 0)
|
||||
temp |= 0x20;
|
||||
if (mouse_buttons & 1)
|
||||
temp |= 1;
|
||||
if (mouse_buttons & 2)
|
||||
temp |= 2;
|
||||
if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI))
|
||||
temp |= 4;
|
||||
keyboard_at_adddata_mouse(temp);
|
||||
keyboard_at_adddata_mouse(dev->x & 0xff);
|
||||
keyboard_at_adddata_mouse(dev->y & 0xff);
|
||||
if (dev->flags & FLAG_INTMODE)
|
||||
keyboard_at_adddata_mouse(dev->z);
|
||||
break;
|
||||
|
||||
case 0xf2: /* read ID */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
if (dev->flags & FLAG_INTMODE)
|
||||
keyboard_at_adddata_mouse(0x03);
|
||||
else
|
||||
keyboard_at_adddata_mouse(0x00);
|
||||
break;
|
||||
case 0xf2: /* read ID */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
if (dev->flags & FLAG_INTMODE)
|
||||
keyboard_at_adddata_mouse(0x03);
|
||||
else
|
||||
keyboard_at_adddata_mouse(0x00);
|
||||
break;
|
||||
|
||||
case 0xf3: /* set command mode */
|
||||
dev->flags |= FLAG_CTRLDAT;
|
||||
keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */
|
||||
break;
|
||||
case 0xf3: /* set command mode */
|
||||
dev->flags |= FLAG_CTRLDAT;
|
||||
keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */
|
||||
break;
|
||||
|
||||
case 0xf4: /* enable */
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
case 0xf4: /* enable */
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
|
||||
case 0xf5: /* disable */
|
||||
dev->flags &= ~FLAG_ENABLED;
|
||||
mouse_scan = 0;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
case 0xf5: /* disable */
|
||||
dev->flags &= ~FLAG_ENABLED;
|
||||
mouse_scan = 0;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
break;
|
||||
|
||||
case 0xf6: /* set defaults */
|
||||
case 0xff: /* reset */
|
||||
case 0xf6: /* set defaults */
|
||||
case 0xff: /* reset */
|
||||
mouse_reset:
|
||||
dev->mode = MODE_STREAM;
|
||||
dev->flags &= 0x88;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_mouse_reset();
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
if (dev->command == 0xff) {
|
||||
keyboard_at_adddata_mouse(0xaa);
|
||||
keyboard_at_adddata_mouse(0x00);
|
||||
}
|
||||
break;
|
||||
dev->mode = MODE_STREAM;
|
||||
dev->flags &= 0x88;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_mouse_reset();
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
if (dev->command == 0xff) {
|
||||
keyboard_at_adddata_mouse(0xaa);
|
||||
keyboard_at_adddata_mouse(0x00);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
keyboard_at_adddata_mouse(0xfe);
|
||||
}
|
||||
default:
|
||||
keyboard_at_adddata_mouse(0xfe);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->flags & FLAG_INTELLI) {
|
||||
for (temp = 0; temp < 5; temp++)
|
||||
dev->last_data[temp] = dev->last_data[temp + 1];
|
||||
for (temp = 0; temp < 5; temp++)
|
||||
dev->last_data[temp] = dev->last_data[temp + 1];
|
||||
|
||||
dev->last_data[5] = val;
|
||||
dev->last_data[5] = val;
|
||||
|
||||
if (dev->last_data[0] == 0xf3 && dev->last_data[1] == 0xc8 &&
|
||||
dev->last_data[2] == 0xf3 && dev->last_data[3] == 0x64 &&
|
||||
dev->last_data[4] == 0xf3 && dev->last_data[5] == 0x50)
|
||||
dev->flags |= FLAG_INTMODE;
|
||||
if (dev->last_data[0] == 0xf3 && dev->last_data[1] == 0xc8 && dev->last_data[2] == 0xf3 && dev->last_data[3] == 0x64 && dev->last_data[4] == 0xf3 && dev->last_data[5] == 0x50)
|
||||
dev->flags |= FLAG_INTMODE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ps2_poll(int x, int y, int z, int b, void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
uint8_t buff[3] = { 0x08, 0x00, 0x00 };
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
uint8_t buff[3] = { 0x08, 0x00, 0x00 };
|
||||
|
||||
if (!x && !y && !z && (b == dev->b))
|
||||
return(0xff);
|
||||
return (0xff);
|
||||
|
||||
#if 0
|
||||
if (!(dev->flags & FLAG_ENABLED))
|
||||
@@ -240,50 +230,54 @@ ps2_poll(int x, int y, int z, int b, void *priv)
|
||||
#endif
|
||||
|
||||
if (!mouse_scan)
|
||||
return(0xff);
|
||||
return (0xff);
|
||||
|
||||
dev->x += x;
|
||||
dev->y -= y;
|
||||
dev->z -= z;
|
||||
if ((dev->mode == MODE_STREAM) && (dev->flags & FLAG_ENABLED) &&
|
||||
(keyboard_at_mouse_pos() < 13)) {
|
||||
dev->b = b;
|
||||
if ((dev->mode == MODE_STREAM) && (dev->flags & FLAG_ENABLED) && (keyboard_at_mouse_pos() < 13)) {
|
||||
dev->b = b;
|
||||
|
||||
if (dev->x > 255) dev->x = 255;
|
||||
if (dev->x < -256) dev->x = -256;
|
||||
if (dev->y > 255) dev->y = 255;
|
||||
if (dev->y < -256) dev->y = -256;
|
||||
if (dev->z < -8) dev->z = -8;
|
||||
if (dev->z > 7) dev->z = 7;
|
||||
if (dev->x > 255)
|
||||
dev->x = 255;
|
||||
if (dev->x < -256)
|
||||
dev->x = -256;
|
||||
if (dev->y > 255)
|
||||
dev->y = 255;
|
||||
if (dev->y < -256)
|
||||
dev->y = -256;
|
||||
if (dev->z < -8)
|
||||
dev->z = -8;
|
||||
if (dev->z > 7)
|
||||
dev->z = 7;
|
||||
|
||||
if (dev->x < 0)
|
||||
buff[0] |= 0x10;
|
||||
if (dev->y < 0)
|
||||
buff[0] |= 0x20;
|
||||
if (mouse_buttons & 0x01)
|
||||
buff[0] |= 0x01;
|
||||
if (mouse_buttons & 0x02)
|
||||
buff[0] |= 0x02;
|
||||
if (dev->flags & FLAG_INTELLI) {
|
||||
if (mouse_buttons & 0x04)
|
||||
buff[0] |= 0x04;
|
||||
}
|
||||
buff[1] = (dev->x & 0xff);
|
||||
buff[2] = (dev->y & 0xff);
|
||||
if (dev->x < 0)
|
||||
buff[0] |= 0x10;
|
||||
if (dev->y < 0)
|
||||
buff[0] |= 0x20;
|
||||
if (mouse_buttons & 0x01)
|
||||
buff[0] |= 0x01;
|
||||
if (mouse_buttons & 0x02)
|
||||
buff[0] |= 0x02;
|
||||
if (dev->flags & FLAG_INTELLI) {
|
||||
if (mouse_buttons & 0x04)
|
||||
buff[0] |= 0x04;
|
||||
}
|
||||
buff[1] = (dev->x & 0xff);
|
||||
buff[2] = (dev->y & 0xff);
|
||||
|
||||
keyboard_at_adddata_mouse(buff[0]);
|
||||
keyboard_at_adddata_mouse(buff[1]);
|
||||
keyboard_at_adddata_mouse(buff[2]);
|
||||
if (dev->flags & FLAG_INTMODE)
|
||||
keyboard_at_adddata_mouse(dev->z);
|
||||
keyboard_at_adddata_mouse(buff[0]);
|
||||
keyboard_at_adddata_mouse(buff[1]);
|
||||
keyboard_at_adddata_mouse(buff[2]);
|
||||
if (dev->flags & FLAG_INTMODE)
|
||||
keyboard_at_adddata_mouse(dev->z);
|
||||
|
||||
dev->x = dev->y = dev->z = 0;
|
||||
dev->x = dev->y = dev->z = 0;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the device for use by the user.
|
||||
*
|
||||
@@ -293,15 +287,15 @@ void *
|
||||
mouse_ps2_init(const device_t *info)
|
||||
{
|
||||
mouse_t *dev;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
dev = (mouse_t *)malloc(sizeof(mouse_t));
|
||||
dev = (mouse_t *) malloc(sizeof(mouse_t));
|
||||
memset(dev, 0x00, sizeof(mouse_t));
|
||||
dev->name = info->name;
|
||||
dev->type = info->local;
|
||||
|
||||
dev->mode = MODE_STREAM;
|
||||
i = device_get_config_int("buttons");
|
||||
i = device_get_config_int("buttons");
|
||||
if (i > 2)
|
||||
dev->flags |= FLAG_INTELLI;
|
||||
|
||||
@@ -314,14 +308,13 @@ mouse_ps2_init(const device_t *info)
|
||||
mouse_set_buttons((dev->flags & FLAG_INTELLI) ? 3 : 2);
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return(dev);
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ps2_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *)priv;
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
|
||||
/* Unhook from the general AT Keyboard driver. */
|
||||
keyboard_at_set_mouse(NULL, NULL);
|
||||
@@ -330,7 +323,7 @@ ps2_close(void *priv)
|
||||
}
|
||||
|
||||
static const device_config_t ps2_config[] = {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
{
|
||||
.name = "buttons",
|
||||
.description = "Buttons",
|
||||
@@ -353,15 +346,15 @@ static const device_config_t ps2_config[] = {
|
||||
};
|
||||
|
||||
const device_t mouse_ps2_device = {
|
||||
.name = "Standard PS/2 Mouse",
|
||||
.name = "Standard PS/2 Mouse",
|
||||
.internal_name = "ps2",
|
||||
.flags = DEVICE_PS2,
|
||||
.local = MOUSE_TYPE_PS2,
|
||||
.init = mouse_ps2_init,
|
||||
.close = ps2_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_PS2,
|
||||
.local = MOUSE_TYPE_PS2,
|
||||
.init = mouse_ps2_init,
|
||||
.close = ps2_close,
|
||||
.reset = NULL,
|
||||
{ .poll = ps2_poll },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = ps2_config
|
||||
.force_redraw = NULL,
|
||||
.config = ps2_config
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -31,55 +31,50 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/pci.h>
|
||||
|
||||
#define PCI_BRIDGE_DEC_21150 0x10110022
|
||||
#define AGP_BRIDGE_ALI_M5243 0x10b95243
|
||||
#define AGP_BRIDGE_ALI_M5247 0x10b95247
|
||||
#define AGP_BRIDGE_INTEL_440LX 0x80867181
|
||||
#define AGP_BRIDGE_INTEL_440BX 0x80867191
|
||||
#define AGP_BRIDGE_INTEL_440GX 0x808671a1
|
||||
#define AGP_BRIDGE_VIA_597 0x11068597
|
||||
#define AGP_BRIDGE_VIA_598 0x11068598
|
||||
#define AGP_BRIDGE_VIA_691 0x11068691
|
||||
#define AGP_BRIDGE_VIA_8601 0x11068601
|
||||
|
||||
#define PCI_BRIDGE_DEC_21150 0x10110022
|
||||
#define AGP_BRIDGE_ALI_M5243 0x10b95243
|
||||
#define AGP_BRIDGE_ALI_M5247 0x10b95247
|
||||
#define AGP_BRIDGE_INTEL_440LX 0x80867181
|
||||
#define AGP_BRIDGE_INTEL_440BX 0x80867191
|
||||
#define AGP_BRIDGE_INTEL_440GX 0x808671a1
|
||||
#define AGP_BRIDGE_VIA_597 0x11068597
|
||||
#define AGP_BRIDGE_VIA_598 0x11068598
|
||||
#define AGP_BRIDGE_VIA_691 0x11068691
|
||||
#define AGP_BRIDGE_VIA_8601 0x11068601
|
||||
|
||||
#define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9)
|
||||
#define AGP_BRIDGE_INTEL(x) (((x) >> 16) == 0x8086)
|
||||
#define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106)
|
||||
#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_ALI_M5243)
|
||||
|
||||
#define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9)
|
||||
#define AGP_BRIDGE_INTEL(x) (((x) >> 16) == 0x8086)
|
||||
#define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106)
|
||||
#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_ALI_M5243)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t local;
|
||||
uint8_t type, ctl;
|
||||
uint32_t local;
|
||||
uint8_t type, ctl;
|
||||
|
||||
uint8_t regs[256];
|
||||
uint8_t bus_index;
|
||||
int slot;
|
||||
uint8_t regs[256];
|
||||
uint8_t bus_index;
|
||||
int slot;
|
||||
} pci_bridge_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_PCI_BRIDGE_LOG
|
||||
int pci_bridge_do_log = ENABLE_PCI_BRIDGE_LOG;
|
||||
|
||||
|
||||
static void
|
||||
pci_bridge_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (pci_bridge_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define pci_bridge_log(fmt, ...)
|
||||
# define pci_bridge_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
pci_bridge_set_ctl(void *priv, uint8_t ctl)
|
||||
{
|
||||
@@ -88,7 +83,6 @@ pci_bridge_set_ctl(void *priv, uint8_t ctl)
|
||||
dev->ctl = ctl;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -97,266 +91,287 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
pci_bridge_log("PCI Bridge %d: write(%d, %02X, %02X)\n", dev->bus_index, func, addr, val);
|
||||
|
||||
if (func > 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
if ((dev->local == AGP_BRIDGE_ALI_M5247) && (addr >= 0x40))
|
||||
return;
|
||||
return;
|
||||
|
||||
switch (addr) {
|
||||
case 0x00: case 0x01: case 0x02: case 0x03:
|
||||
case 0x06: case 0x08: case 0x09: case 0x0a:
|
||||
case 0x0b: case 0x0e: case 0x0f: case 0x10:
|
||||
case 0x11: case 0x12: case 0x13: case 0x14:
|
||||
case 0x15: case 0x16: case 0x17: case 0x1e:
|
||||
case 0x34: case 0x3d: case 0x67: case 0xdc:
|
||||
case 0xdd: case 0xde: case 0xdf:
|
||||
return;
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
case 0x1e:
|
||||
case 0x34:
|
||||
case 0x3d:
|
||||
case 0x67:
|
||||
case 0xdc:
|
||||
case 0xdd:
|
||||
case 0xde:
|
||||
case 0xdf:
|
||||
return;
|
||||
|
||||
case 0x04:
|
||||
if (AGP_BRIDGE_INTEL(dev->local)) {
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440BX)
|
||||
val &= 0x1f;
|
||||
} else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
val |= 0x02;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
val &= 0xc3;
|
||||
else
|
||||
val &= 0x67;
|
||||
break;
|
||||
case 0x04:
|
||||
if (AGP_BRIDGE_INTEL(dev->local)) {
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440BX)
|
||||
val &= 0x1f;
|
||||
} else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
val |= 0x02;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
val &= 0xc3;
|
||||
else
|
||||
val &= 0x67;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
if (AGP_BRIDGE_INTEL(dev->local))
|
||||
val &= 0x01;
|
||||
else if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x01;
|
||||
else
|
||||
val &= 0x03;
|
||||
break;
|
||||
case 0x05:
|
||||
if (AGP_BRIDGE_INTEL(dev->local))
|
||||
val &= 0x01;
|
||||
else if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x01;
|
||||
else
|
||||
val &= 0x03;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX)
|
||||
dev->regs[addr] &= ~(val & 0x40);
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
dev->regs[addr] &= ~(val & 0xf8);
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
dev->regs[addr] &= ~(val & 0xc0);
|
||||
return;
|
||||
case 0x07:
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX)
|
||||
dev->regs[addr] &= ~(val & 0x40);
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
dev->regs[addr] &= ~(val & 0xf8);
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
dev->regs[addr] &= ~(val & 0xc0);
|
||||
return;
|
||||
|
||||
case 0x0c: case 0x18:
|
||||
/* Parent bus number (0x18) is always 0 on AGP bridges. */
|
||||
if (AGP_BRIDGE(dev->local))
|
||||
return;
|
||||
break;
|
||||
case 0x0c:
|
||||
case 0x18:
|
||||
/* Parent bus number (0x18) is always 0 on AGP bridges. */
|
||||
if (AGP_BRIDGE(dev->local))
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0x0d:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
return;
|
||||
else if (AGP_BRIDGE_INTEL(dev->local))
|
||||
val &= 0xf8;
|
||||
else if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0xf8;
|
||||
break;
|
||||
case 0x0d:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
return;
|
||||
else if (AGP_BRIDGE_INTEL(dev->local))
|
||||
val &= 0xf8;
|
||||
else if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0xf8;
|
||||
break;
|
||||
|
||||
case 0x19:
|
||||
/* Set our bus number. */
|
||||
pci_bridge_log("PCI Bridge %d: remapping from bus %02X to %02X\n", dev->bus_index, dev->regs[addr], val);
|
||||
pci_remap_bus(dev->bus_index, val);
|
||||
break;
|
||||
case 0x19:
|
||||
/* Set our bus number. */
|
||||
pci_bridge_log("PCI Bridge %d: remapping from bus %02X to %02X\n", dev->bus_index, dev->regs[addr], val);
|
||||
pci_remap_bus(dev->bus_index, val);
|
||||
break;
|
||||
|
||||
case 0x1f:
|
||||
if (AGP_BRIDGE_INTEL(dev->local)) {
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX)
|
||||
dev->regs[addr] &= ~(val & 0xf1);
|
||||
else if ((dev->local == AGP_BRIDGE_INTEL_440BX) ||
|
||||
(dev->local == AGP_BRIDGE_INTEL_440GX))
|
||||
dev->regs[addr] &= ~(val & 0xf0);
|
||||
} else if (AGP_BRIDGE_ALI(dev->local))
|
||||
dev->regs[addr] &= ~(val & 0xf0);
|
||||
return;
|
||||
case 0x1f:
|
||||
if (AGP_BRIDGE_INTEL(dev->local)) {
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX)
|
||||
dev->regs[addr] &= ~(val & 0xf1);
|
||||
else if ((dev->local == AGP_BRIDGE_INTEL_440BX) || (dev->local == AGP_BRIDGE_INTEL_440GX))
|
||||
dev->regs[addr] &= ~(val & 0xf0);
|
||||
} else if (AGP_BRIDGE_ALI(dev->local))
|
||||
dev->regs[addr] &= ~(val & 0xf0);
|
||||
return;
|
||||
|
||||
case 0x1c: case 0x1d: case 0x20: case 0x22:
|
||||
case 0x24: case 0x26:
|
||||
val &= 0xf0;
|
||||
break;
|
||||
case 0x1c:
|
||||
case 0x1d:
|
||||
case 0x20:
|
||||
case 0x22:
|
||||
case 0x24:
|
||||
case 0x26:
|
||||
val &= 0xf0;
|
||||
break;
|
||||
|
||||
case 0x3c:
|
||||
if (!(dev->ctl & 0x80))
|
||||
return;
|
||||
break;
|
||||
case 0x3c:
|
||||
if (!(dev->ctl & 0x80))
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0x3e:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
val &= 0x0c;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
val &= 0x0f;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
return;
|
||||
else if (AGP_BRIDGE(dev->local)) {
|
||||
if ((dev->local == AGP_BRIDGE_INTEL_440BX) ||
|
||||
(dev->local == AGP_BRIDGE_INTEL_440GX))
|
||||
val &= 0xed;
|
||||
else
|
||||
val &= 0x0f;
|
||||
}
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0xef;
|
||||
break;
|
||||
case 0x3e:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
val &= 0x0c;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
val &= 0x0f;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
return;
|
||||
else if (AGP_BRIDGE(dev->local)) {
|
||||
if ((dev->local == AGP_BRIDGE_INTEL_440BX) || (dev->local == AGP_BRIDGE_INTEL_440GX))
|
||||
val &= 0xed;
|
||||
else
|
||||
val &= 0x0f;
|
||||
} else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0xef;
|
||||
break;
|
||||
|
||||
case 0x3f:
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX) {
|
||||
dev->regs[addr] = ((dev->regs[addr] & 0x04) | (val & 0x02)) & ~(val & 0x04);
|
||||
return;
|
||||
} else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
return;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
val &= 0x06;
|
||||
else if (AGP_BRIDGE(dev->local))
|
||||
return;
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x0f;
|
||||
break;
|
||||
case 0x3f:
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX) {
|
||||
dev->regs[addr] = ((dev->regs[addr] & 0x04) | (val & 0x02)) & ~(val & 0x04);
|
||||
return;
|
||||
} else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
return;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
val &= 0x06;
|
||||
else if (AGP_BRIDGE(dev->local))
|
||||
return;
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x0f;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x32;
|
||||
break;
|
||||
case 0x40:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x32;
|
||||
break;
|
||||
|
||||
case 0x41:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
val &= 0x7e;
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x07;
|
||||
break;
|
||||
case 0x41:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
val &= 0x7e;
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x07;
|
||||
break;
|
||||
|
||||
case 0x42:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
val &= 0xfe;
|
||||
break;
|
||||
case 0x42:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
val &= 0xfe;
|
||||
break;
|
||||
|
||||
case 0x43:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x03;
|
||||
break;
|
||||
case 0x43:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x03;
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x7e;
|
||||
break;
|
||||
case 0x64:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x7e;
|
||||
break;
|
||||
|
||||
case 0x69:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x3f;
|
||||
break;
|
||||
case 0x69:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x3f;
|
||||
break;
|
||||
|
||||
case 0x86:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x3f;
|
||||
break;
|
||||
case 0x86:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x3f;
|
||||
break;
|
||||
|
||||
case 0x87:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x60;
|
||||
break;
|
||||
case 0x87:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x60;
|
||||
break;
|
||||
|
||||
case 0x88:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x8c;
|
||||
break;
|
||||
case 0x88:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x8c;
|
||||
break;
|
||||
|
||||
case 0x8b:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x0f;
|
||||
break;
|
||||
case 0x8b:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x0f;
|
||||
break;
|
||||
|
||||
case 0x8c:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x83;
|
||||
break;
|
||||
case 0x8c:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x83;
|
||||
break;
|
||||
|
||||
case 0x8d:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
return;
|
||||
break;
|
||||
case 0x8d:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0xe0: case 0xe1:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
break;
|
||||
case 0xe0:
|
||||
case 0xe1:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0xe2:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0x3f;
|
||||
else
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
break;
|
||||
case 0xe3:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0xfe;
|
||||
else
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
break;
|
||||
case 0xe2:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0x3f;
|
||||
else
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
break;
|
||||
case 0xe3:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0xfe;
|
||||
else
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0xe4:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0x03;
|
||||
else
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xe5:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xe4:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0x03;
|
||||
else
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xe5:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xe6:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0xc0;
|
||||
else
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xe6:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (dev->ctl & 0x20)
|
||||
val &= 0xc0;
|
||||
else
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xe7:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xe7:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dev->regs[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
pci_bridge_read(int func, int addr, void *priv)
|
||||
{
|
||||
pci_bridge_t *dev = (pci_bridge_t *) priv;
|
||||
uint8_t ret;
|
||||
uint8_t ret;
|
||||
|
||||
if (func > 0)
|
||||
ret = 0xff;
|
||||
ret = 0xff;
|
||||
else
|
||||
ret = dev->regs[addr];
|
||||
ret = dev->regs[addr];
|
||||
|
||||
pci_bridge_log("PCI Bridge %d: read(%d, %02X) = %02X\n", dev->bus_index, func, addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_bridge_reset(void *priv)
|
||||
{
|
||||
@@ -374,51 +389,51 @@ pci_bridge_reset(void *priv)
|
||||
|
||||
/* command and status */
|
||||
switch (dev->local) {
|
||||
case PCI_BRIDGE_DEC_21150:
|
||||
dev->regs[0x06] = 0x80;
|
||||
dev->regs[0x07] = 0x02;
|
||||
break;
|
||||
case PCI_BRIDGE_DEC_21150:
|
||||
dev->regs[0x06] = 0x80;
|
||||
dev->regs[0x07] = 0x02;
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_ALI_M5243:
|
||||
dev->regs[0x04] = 0x06;
|
||||
dev->regs[0x07] = 0x04;
|
||||
dev->regs[0x0d] = 0x20;
|
||||
dev->regs[0x19] = 0x01;
|
||||
dev->regs[0x1b] = 0x20;
|
||||
dev->regs[0x34] = 0xe0;
|
||||
dev->regs[0x89] = 0x20;
|
||||
dev->regs[0x8a] = 0xa0;
|
||||
dev->regs[0x8e] = 0x20;
|
||||
dev->regs[0x8f] = 0x20;
|
||||
dev->regs[0xe0] = 0x01;
|
||||
pci_remap_bus(dev->bus_index, 0x01);
|
||||
break;
|
||||
case AGP_BRIDGE_ALI_M5243:
|
||||
dev->regs[0x04] = 0x06;
|
||||
dev->regs[0x07] = 0x04;
|
||||
dev->regs[0x0d] = 0x20;
|
||||
dev->regs[0x19] = 0x01;
|
||||
dev->regs[0x1b] = 0x20;
|
||||
dev->regs[0x34] = 0xe0;
|
||||
dev->regs[0x89] = 0x20;
|
||||
dev->regs[0x8a] = 0xa0;
|
||||
dev->regs[0x8e] = 0x20;
|
||||
dev->regs[0x8f] = 0x20;
|
||||
dev->regs[0xe0] = 0x01;
|
||||
pci_remap_bus(dev->bus_index, 0x01);
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_ALI_M5247:
|
||||
dev->regs[0x04] = 0x03;
|
||||
dev->regs[0x08] = 0x01;
|
||||
break;
|
||||
case AGP_BRIDGE_ALI_M5247:
|
||||
dev->regs[0x04] = 0x03;
|
||||
dev->regs[0x08] = 0x01;
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_INTEL_440LX:
|
||||
dev->regs[0x06] = 0xa0;
|
||||
dev->regs[0x07] = 0x02;
|
||||
dev->regs[0x08] = 0x03;
|
||||
break;
|
||||
case AGP_BRIDGE_INTEL_440LX:
|
||||
dev->regs[0x06] = 0xa0;
|
||||
dev->regs[0x07] = 0x02;
|
||||
dev->regs[0x08] = 0x03;
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_INTEL_440BX:
|
||||
case AGP_BRIDGE_INTEL_440GX:
|
||||
dev->regs[0x06] = 0x20;
|
||||
dev->regs[0x07] = dev->regs[0x08] = 0x02;
|
||||
break;
|
||||
case AGP_BRIDGE_INTEL_440BX:
|
||||
case AGP_BRIDGE_INTEL_440GX:
|
||||
dev->regs[0x06] = 0x20;
|
||||
dev->regs[0x07] = dev->regs[0x08] = 0x02;
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_VIA_597:
|
||||
case AGP_BRIDGE_VIA_598:
|
||||
case AGP_BRIDGE_VIA_691:
|
||||
case AGP_BRIDGE_VIA_8601:
|
||||
dev->regs[0x04] = 0x07;
|
||||
dev->regs[0x06] = 0x20;
|
||||
dev->regs[0x07] = 0x02;
|
||||
break;
|
||||
case AGP_BRIDGE_VIA_597:
|
||||
case AGP_BRIDGE_VIA_598:
|
||||
case AGP_BRIDGE_VIA_691:
|
||||
case AGP_BRIDGE_VIA_8601:
|
||||
dev->regs[0x04] = 0x07;
|
||||
dev->regs[0x06] = 0x20;
|
||||
dev->regs[0x07] = 0x02;
|
||||
break;
|
||||
}
|
||||
|
||||
/* class */
|
||||
@@ -428,34 +443,33 @@ pci_bridge_reset(void *priv)
|
||||
|
||||
/* IO BARs */
|
||||
if (AGP_BRIDGE(dev->local))
|
||||
dev->regs[0x1c] = 0xf0;
|
||||
dev->regs[0x1c] = 0xf0;
|
||||
else
|
||||
dev->regs[0x1c] = dev->regs[0x1d] = 0x01;
|
||||
dev->regs[0x1c] = dev->regs[0x1d] = 0x01;
|
||||
|
||||
if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
dev->regs[0x1e] = 0x20;
|
||||
dev->regs[0x1e] = 0x20;
|
||||
else if (!AGP_BRIDGE_VIA(dev->local)) {
|
||||
dev->regs[0x1e] = AGP_BRIDGE(dev->local) ? 0xa0 : 0x80;
|
||||
dev->regs[0x1f] = 0x02;
|
||||
dev->regs[0x1e] = AGP_BRIDGE(dev->local) ? 0xa0 : 0x80;
|
||||
dev->regs[0x1f] = 0x02;
|
||||
}
|
||||
|
||||
/* prefetchable memory limits */
|
||||
if (AGP_BRIDGE(dev->local)) {
|
||||
dev->regs[0x20] = dev->regs[0x24] = 0xf0;
|
||||
dev->regs[0x21] = dev->regs[0x25] = 0xff;
|
||||
dev->regs[0x20] = dev->regs[0x24] = 0xf0;
|
||||
dev->regs[0x21] = dev->regs[0x25] = 0xff;
|
||||
} else {
|
||||
dev->regs[0x24] = dev->regs[0x26] = 0x01;
|
||||
dev->regs[0x24] = dev->regs[0x26] = 0x01;
|
||||
}
|
||||
|
||||
/* power management */
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150) {
|
||||
dev->regs[0x34] = 0xdc;
|
||||
dev->regs[0x43] = 0x02;
|
||||
dev->regs[0xdc] = dev->regs[0xde] = 0x01;
|
||||
dev->regs[0x34] = 0xdc;
|
||||
dev->regs[0x43] = 0x02;
|
||||
dev->regs[0xdc] = dev->regs[0xde] = 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
pci_bridge_init(const device_t *info)
|
||||
{
|
||||
@@ -464,7 +478,7 @@ pci_bridge_init(const device_t *info)
|
||||
pci_bridge_t *dev = (pci_bridge_t *) malloc(sizeof(pci_bridge_t));
|
||||
memset(dev, 0, sizeof(pci_bridge_t));
|
||||
|
||||
dev->local = info->local;
|
||||
dev->local = info->local;
|
||||
dev->bus_index = pci_register_bus();
|
||||
pci_bridge_log("PCI Bridge %d: init()\n", dev->bus_index);
|
||||
|
||||
@@ -473,26 +487,26 @@ pci_bridge_init(const device_t *info)
|
||||
dev->slot = pci_add_card(AGP_BRIDGE(dev->local) ? PCI_ADD_AGPBRIDGE : PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev);
|
||||
|
||||
interrupt_count = sizeof(interrupts);
|
||||
interrupt_mask = interrupt_count - 1;
|
||||
interrupt_mask = interrupt_count - 1;
|
||||
if (dev->slot < 32) {
|
||||
for (i = 0; i < interrupt_count; i++)
|
||||
interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i);
|
||||
for (i = 0; i < interrupt_count; i++)
|
||||
interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i);
|
||||
}
|
||||
pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], interrupts[1], interrupts[2], interrupts[3]);
|
||||
|
||||
if (info->local == PCI_BRIDGE_DEC_21150)
|
||||
slot_count = 9; /* 9 bus masters */
|
||||
slot_count = 9; /* 9 bus masters */
|
||||
else
|
||||
slot_count = 1; /* AGP bridges always have 1 slot */
|
||||
slot_count = 1; /* AGP bridges always have 1 slot */
|
||||
|
||||
for (i = 0; i < slot_count; i++) {
|
||||
/* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */
|
||||
pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, i, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]);
|
||||
pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL,
|
||||
interrupts[i & interrupt_mask],
|
||||
interrupts[(i + 1) & interrupt_mask],
|
||||
interrupts[(i + 2) & interrupt_mask],
|
||||
interrupts[(i + 3) & interrupt_mask]);
|
||||
/* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */
|
||||
pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, i, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]);
|
||||
pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL,
|
||||
interrupts[i & interrupt_mask],
|
||||
interrupts[(i + 1) & interrupt_mask],
|
||||
interrupts[(i + 2) & interrupt_mask],
|
||||
interrupts[(i + 3) & interrupt_mask]);
|
||||
}
|
||||
|
||||
return dev;
|
||||
@@ -500,143 +514,143 @@ pci_bridge_init(const device_t *info)
|
||||
|
||||
/* PCI bridges */
|
||||
const device_t dec21150_device = {
|
||||
.name = "DEC 21150 PCI Bridge",
|
||||
.name = "DEC 21150 PCI Bridge",
|
||||
.internal_name = "dec21150",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = PCI_BRIDGE_DEC_21150,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = PCI_BRIDGE_DEC_21150,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
/* AGP bridges */
|
||||
const device_t ali5243_agp_device = {
|
||||
.name = "ALi M5243 AGP Bridge",
|
||||
.name = "ALi M5243 AGP Bridge",
|
||||
.internal_name = "ali5243_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_ALI_M5243,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_ALI_M5243,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
/* AGP bridges */
|
||||
const device_t ali5247_agp_device = {
|
||||
.name = "ALi M5247 AGP Bridge",
|
||||
.name = "ALi M5247 AGP Bridge",
|
||||
.internal_name = "ali5247_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_ALI_M5247,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_ALI_M5247,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t i440lx_agp_device = {
|
||||
.name = "Intel 82443LX/EX AGP Bridge",
|
||||
.name = "Intel 82443LX/EX AGP Bridge",
|
||||
.internal_name = "i440lx_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_INTEL_440LX,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_INTEL_440LX,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t i440bx_agp_device = {
|
||||
.name = "Intel 82443BX/ZX AGP Bridge",
|
||||
.name = "Intel 82443BX/ZX AGP Bridge",
|
||||
.internal_name = "i440bx_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_INTEL_440BX,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_INTEL_440BX,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t i440gx_agp_device = {
|
||||
.name = "Intel 82443GX AGP Bridge",
|
||||
.name = "Intel 82443GX AGP Bridge",
|
||||
.internal_name = "i440gx_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_INTEL_440GX,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_INTEL_440GX,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t via_vp3_agp_device = {
|
||||
.name = "VIA Apollo VP3 AGP Bridge",
|
||||
.name = "VIA Apollo VP3 AGP Bridge",
|
||||
.internal_name = "via_vp3_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_597,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_597,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t via_mvp3_agp_device = {
|
||||
.name = "VIA Apollo MVP3 AGP Bridge",
|
||||
.name = "VIA Apollo MVP3 AGP Bridge",
|
||||
.internal_name = "via_mvp3_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_598,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_598,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t via_apro_agp_device = {
|
||||
.name = "VIA Apollo Pro AGP Bridge",
|
||||
.name = "VIA Apollo Pro AGP Bridge",
|
||||
.internal_name = "via_apro_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_691,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_691,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t via_vt8601_agp_device = {
|
||||
.name = "VIA Apollo ProMedia AGP Bridge",
|
||||
.name = "VIA Apollo ProMedia AGP Bridge",
|
||||
.internal_name = "via_vt8601_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_8601,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_VIA_8601,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
@@ -11,7 +11,6 @@
|
||||
* Copyright 2020 Tiseno100
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -39,42 +38,38 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type, jumper;
|
||||
uint8_t type, jumper;
|
||||
} phoenix_486_jumper_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_PHOENIX_486_JUMPER_LOG
|
||||
int phoenix_486_jumper_do_log = ENABLE_PHOENIX_486_JUMPER_LOG;
|
||||
|
||||
|
||||
static void
|
||||
phoenix_486_jumper_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (phoenix_486_jumper_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define phoenix_486_jumper_log(fmt, ...)
|
||||
# define phoenix_486_jumper_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
phoenix_486_jumper_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv;
|
||||
phoenix_486_jumper_log("Phoenix 486 Jumper: Write %02x\n", val);
|
||||
if (dev->type == 1)
|
||||
dev->jumper = val & 0xbf;
|
||||
dev->jumper = val & 0xbf;
|
||||
else
|
||||
dev->jumper = val;
|
||||
dev->jumper = val;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
phoenix_486_jumper_read(uint16_t addr, void *priv)
|
||||
{
|
||||
@@ -83,22 +78,20 @@ phoenix_486_jumper_read(uint16_t addr, void *priv)
|
||||
return dev->jumper;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
phoenix_486_jumper_reset(void *priv)
|
||||
{
|
||||
phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv;
|
||||
|
||||
if (dev->type == 1)
|
||||
dev->jumper = 0x00;
|
||||
dev->jumper = 0x00;
|
||||
else {
|
||||
dev->jumper = 0x9f;
|
||||
if (gfxcard != 0x01)
|
||||
dev->jumper |= 0x40;
|
||||
dev->jumper = 0x9f;
|
||||
if (gfxcard != 0x01)
|
||||
dev->jumper |= 0x40;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
phoenix_486_jumper_close(void *priv)
|
||||
{
|
||||
@@ -107,7 +100,6 @@ phoenix_486_jumper_close(void *priv)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
phoenix_486_jumper_init(const device_t *info)
|
||||
{
|
||||
@@ -124,29 +116,29 @@ phoenix_486_jumper_init(const device_t *info)
|
||||
}
|
||||
|
||||
const device_t phoenix_486_jumper_device = {
|
||||
.name = "Phoenix 486 Jumper Readout",
|
||||
.name = "Phoenix 486 Jumper Readout",
|
||||
.internal_name = "phoenix_486_jumper",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = phoenix_486_jumper_init,
|
||||
.close = phoenix_486_jumper_close,
|
||||
.reset = phoenix_486_jumper_reset,
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = phoenix_486_jumper_init,
|
||||
.close = phoenix_486_jumper_close,
|
||||
.reset = phoenix_486_jumper_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t phoenix_486_jumper_pci_device = {
|
||||
.name = "Phoenix 486 Jumper Readout (PCI machines)",
|
||||
.name = "Phoenix 486 Jumper Readout (PCI machines)",
|
||||
.internal_name = "phoenix_486_jumper_pci",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = phoenix_486_jumper_init,
|
||||
.close = phoenix_486_jumper_close,
|
||||
.reset = phoenix_486_jumper_reset,
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = phoenix_486_jumper_init,
|
||||
.close = phoenix_486_jumper_close,
|
||||
.reset = phoenix_486_jumper_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
@@ -29,58 +29,52 @@
|
||||
#include <86box/postcard.h>
|
||||
#include "cpu.h"
|
||||
|
||||
static uint16_t postcard_port;
|
||||
static uint8_t postcard_written;
|
||||
static uint8_t postcard_code, postcard_prev_code;
|
||||
#define UISTR_LEN 13
|
||||
static char postcard_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
static uint16_t postcard_port;
|
||||
static uint8_t postcard_written;
|
||||
static uint8_t postcard_code, postcard_prev_code;
|
||||
#define UISTR_LEN 13
|
||||
static char postcard_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
|
||||
extern void ui_sb_bugui(char *__str);
|
||||
|
||||
extern void ui_sb_bugui(char *__str);
|
||||
|
||||
#ifdef ENABLE_POSTCARD_LOG
|
||||
int postcard_do_log = ENABLE_POSTCARD_LOG;
|
||||
|
||||
|
||||
static void
|
||||
postcard_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (postcard_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int postcard_do_log = 0;
|
||||
|
||||
#define postcard_log(fmt, ...)
|
||||
# define postcard_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
postcard_setui(void)
|
||||
{
|
||||
if (!postcard_written)
|
||||
sprintf(postcard_str, "POST: -- --");
|
||||
sprintf(postcard_str, "POST: -- --");
|
||||
else if (postcard_written == 1)
|
||||
sprintf(postcard_str, "POST: %02X --", postcard_code);
|
||||
sprintf(postcard_str, "POST: %02X --", postcard_code);
|
||||
else
|
||||
sprintf(postcard_str, "POST: %02X %02X", postcard_code, postcard_prev_code);
|
||||
sprintf(postcard_str, "POST: %02X %02X", postcard_code, postcard_prev_code);
|
||||
|
||||
ui_sb_bugui(postcard_str);
|
||||
|
||||
if (postcard_do_log) {
|
||||
/* log same string sent to the UI */
|
||||
postcard_log("[%04X:%08X] %s\n", CS, cpu_state.pc, postcard_str);
|
||||
/* log same string sent to the UI */
|
||||
postcard_log("[%04X:%08X] %s\n", CS, cpu_state.pc, postcard_str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
postcard_reset(void)
|
||||
{
|
||||
@@ -90,65 +84,64 @@ postcard_reset(void)
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
postcard_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
if (postcard_written && (val == postcard_code))
|
||||
return;
|
||||
return;
|
||||
|
||||
postcard_prev_code = postcard_code;
|
||||
postcard_code = val;
|
||||
postcard_code = val;
|
||||
if (postcard_written < 2)
|
||||
postcard_written++;
|
||||
postcard_written++;
|
||||
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
postcard_init(const device_t *info)
|
||||
{
|
||||
postcard_reset();
|
||||
|
||||
if (machine_has_bus(machine, MACHINE_BUS_MCA))
|
||||
postcard_port = 0x680; /* MCA machines */
|
||||
postcard_port = 0x680; /* MCA machines */
|
||||
else if (strstr(machines[machine].name, " PS/2 ") || strstr(machine_getname_ex(machine), " PS/1 "))
|
||||
postcard_port = 0x190; /* ISA PS/2 machines */
|
||||
postcard_port = 0x190; /* ISA PS/2 machines */
|
||||
else if (strstr(machines[machine].name, " IBM XT "))
|
||||
postcard_port = 0x60; /* IBM XT */
|
||||
postcard_port = 0x60; /* IBM XT */
|
||||
else if (strstr(machines[machine].name, " IBM PCjr"))
|
||||
postcard_port = 0x10; /* IBM PCjr */
|
||||
postcard_port = 0x10; /* IBM PCjr */
|
||||
else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI))
|
||||
postcard_port = 0x84; /* ISA Compaq machines */
|
||||
postcard_port = 0x84; /* ISA Compaq machines */
|
||||
else
|
||||
postcard_port = 0x80; /* AT and clone machines */
|
||||
postcard_port = 0x80; /* AT and clone machines */
|
||||
postcard_log("POST card initializing on port %04Xh\n", postcard_port);
|
||||
|
||||
if (postcard_port) io_sethandler(postcard_port, 1,
|
||||
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
|
||||
if (postcard_port)
|
||||
io_sethandler(postcard_port, 1,
|
||||
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
|
||||
|
||||
return postcard_write;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
postcard_close(UNUSED(void *priv))
|
||||
{
|
||||
if (postcard_port) io_removehandler(postcard_port, 1,
|
||||
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
|
||||
if (postcard_port)
|
||||
io_removehandler(postcard_port, 1,
|
||||
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
const device_t postcard_device = {
|
||||
.name = "POST Card",
|
||||
.name = "POST Card",
|
||||
.internal_name = "postcard",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = postcard_init,
|
||||
.close = postcard_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = postcard_init,
|
||||
.close = postcard_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
@@ -38,7 +38,7 @@
|
||||
#include <86box/serial.h>
|
||||
#include <86box/mouse.h>
|
||||
|
||||
serial_port_t com_ports[SERIAL_MAX];
|
||||
serial_port_t com_ports[SERIAL_MAX];
|
||||
|
||||
enum {
|
||||
SERIAL_INT_LSR = 1,
|
||||
|
@@ -29,59 +29,56 @@
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/smbus.h>
|
||||
|
||||
|
||||
#ifdef ENABLE_SMBUS_ALI7101_LOG
|
||||
int smbus_ali7101_do_log = ENABLE_SMBUS_ALI7101_LOG;
|
||||
|
||||
|
||||
static void
|
||||
smbus_ali7101_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (smbus_ali7101_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define smbus_ali7101_log(fmt, ...)
|
||||
# define smbus_ali7101_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static uint8_t
|
||||
smbus_ali7101_read(uint16_t addr, void *priv)
|
||||
{
|
||||
smbus_ali7101_t *dev = (smbus_ali7101_t *) priv;
|
||||
uint8_t ret = 0x00;
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (addr - dev->io_base) {
|
||||
case 0x00:
|
||||
ret = dev->stat;
|
||||
break;
|
||||
case 0x00:
|
||||
ret = dev->stat;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
ret = dev->addr;
|
||||
break;
|
||||
case 0x03:
|
||||
ret = dev->addr;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
ret = dev->data0;
|
||||
break;
|
||||
case 0x04:
|
||||
ret = dev->data0;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
ret = dev->data1;
|
||||
break;
|
||||
case 0x05:
|
||||
ret = dev->data1;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
ret = dev->data[dev->index++];
|
||||
if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
case 0x06:
|
||||
ret = dev->data[dev->index++];
|
||||
if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
ret = dev->cmd;
|
||||
break;
|
||||
case 0x07:
|
||||
ret = dev->cmd;
|
||||
break;
|
||||
}
|
||||
|
||||
smbus_ali7101_log("SMBus ALI7101: read(%02X) = %02x\n", addr, ret);
|
||||
@@ -89,152 +86,150 @@ smbus_ali7101_read(uint16_t addr, void *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
smbus_ali7101_t *dev = (smbus_ali7101_t *) priv;
|
||||
uint8_t smbus_addr, cmd, read, prev_stat;
|
||||
uint16_t timer_bytes = 0;
|
||||
uint8_t smbus_addr, cmd, read, prev_stat;
|
||||
uint16_t timer_bytes = 0;
|
||||
|
||||
smbus_ali7101_log("SMBus ALI7101: write(%02X, %02X)\n", addr, val);
|
||||
|
||||
prev_stat = dev->next_stat;
|
||||
prev_stat = dev->next_stat;
|
||||
dev->next_stat = 0x04;
|
||||
switch (addr - dev->io_base) {
|
||||
case 0x00:
|
||||
dev->stat &= ~(val & 0xf2);
|
||||
/* Make sure IDLE is set if we're not busy or errored. */
|
||||
if (dev->stat == 0x00)
|
||||
dev->stat = 0x04;
|
||||
break;
|
||||
case 0x00:
|
||||
dev->stat &= ~(val & 0xf2);
|
||||
/* Make sure IDLE is set if we're not busy or errored. */
|
||||
if (dev->stat == 0x00)
|
||||
dev->stat = 0x04;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
dev->ctl = val & 0xfc;
|
||||
if (val & 0x04) { /* cancel an in-progress command if KILL is set */
|
||||
if (prev_stat) { /* cancel only if a command is in progress */
|
||||
timer_disable(&dev->response_timer);
|
||||
dev->stat = 0x80; /* raise FAILED */
|
||||
}
|
||||
} else if (val & 0x08) { /* T_OUT_CMD */
|
||||
if (prev_stat) { /* cancel only if a command is in progress */
|
||||
timer_disable(&dev->response_timer);
|
||||
dev->stat = 0x20; /* raise DEVICE_ERR */
|
||||
}
|
||||
}
|
||||
case 0x01:
|
||||
dev->ctl = val & 0xfc;
|
||||
if (val & 0x04) { /* cancel an in-progress command if KILL is set */
|
||||
if (prev_stat) { /* cancel only if a command is in progress */
|
||||
timer_disable(&dev->response_timer);
|
||||
dev->stat = 0x80; /* raise FAILED */
|
||||
}
|
||||
} else if (val & 0x08) { /* T_OUT_CMD */
|
||||
if (prev_stat) { /* cancel only if a command is in progress */
|
||||
timer_disable(&dev->response_timer);
|
||||
dev->stat = 0x20; /* raise DEVICE_ERR */
|
||||
}
|
||||
}
|
||||
|
||||
if (val & 0x80)
|
||||
dev->index = 0;
|
||||
break;
|
||||
if (val & 0x80)
|
||||
dev->index = 0;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
/* dispatch command if START is set */
|
||||
timer_bytes++; /* address */
|
||||
case 0x02:
|
||||
/* dispatch command if START is set */
|
||||
timer_bytes++; /* address */
|
||||
|
||||
smbus_addr = (dev->addr >> 1);
|
||||
read = dev->addr & 0x01;
|
||||
smbus_addr = (dev->addr >> 1);
|
||||
read = dev->addr & 0x01;
|
||||
|
||||
cmd = (dev->ctl >> 4) & 0x7;
|
||||
smbus_ali7101_log("SMBus ALI7101: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1);
|
||||
cmd = (dev->ctl >> 4) & 0x7;
|
||||
smbus_ali7101_log("SMBus ALI7101: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1);
|
||||
|
||||
/* Raise DEV_ERR if no device is at this address, or if the device returned NAK when starting the transfer. */
|
||||
if (!i2c_start(i2c_smbus, smbus_addr, read)) {
|
||||
dev->next_stat = 0x40;
|
||||
break;
|
||||
}
|
||||
/* Raise DEV_ERR if no device is at this address, or if the device returned NAK when starting the transfer. */
|
||||
if (!i2c_start(i2c_smbus, smbus_addr, read)) {
|
||||
dev->next_stat = 0x40;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->next_stat = 0x10; /* raise INTER (command completed) by default */
|
||||
dev->next_stat = 0x10; /* raise INTER (command completed) by default */
|
||||
|
||||
/* Decode the command protocol. */
|
||||
switch (cmd) {
|
||||
case 0x0: /* quick R/W */
|
||||
break;
|
||||
/* Decode the command protocol. */
|
||||
switch (cmd) {
|
||||
case 0x0: /* quick R/W */
|
||||
break;
|
||||
|
||||
case 0x1: /* byte R/W */
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
case 0x1: /* byte R/W */
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x2: /* byte data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
case 0x2: /* byte data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x3: /* word data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
case 0x3: /* word data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
|
||||
if (read) { /* word read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else { /* word write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
}
|
||||
timer_bytes += 2;
|
||||
if (read) { /* word read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else { /* word write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
}
|
||||
timer_bytes += 2;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x4: /* block R/W */
|
||||
timer_bytes++; /* count the SMBus length byte now */
|
||||
case 0x4: /* block R/W */
|
||||
timer_bytes++; /* count the SMBus length byte now */
|
||||
|
||||
/* fall-through */
|
||||
/* fall-through */
|
||||
|
||||
default: /* unknown */
|
||||
dev->next_stat = 0x20; /* raise DEV_ERR */
|
||||
timer_bytes = 0;
|
||||
break;
|
||||
}
|
||||
default: /* unknown */
|
||||
dev->next_stat = 0x20; /* raise DEV_ERR */
|
||||
timer_bytes = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Finish transfer. */
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
break;
|
||||
/* Finish transfer. */
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
dev->addr = val;
|
||||
break;
|
||||
case 0x03:
|
||||
dev->addr = val;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
dev->data0 = val;
|
||||
break;
|
||||
case 0x04:
|
||||
dev->data0 = val;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
dev->data1 = val;
|
||||
break;
|
||||
case 0x05:
|
||||
dev->data1 = val;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
dev->data[dev->index++] = val;
|
||||
if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
case 0x06:
|
||||
dev->data[dev->index++] = val;
|
||||
if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->cmd = val;
|
||||
break;
|
||||
case 0x07:
|
||||
dev->cmd = val;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->next_stat != 0x04) { /* schedule dispatch of any pending status register update */
|
||||
dev->stat = 0x08; /* raise HOST_BUSY while waiting */
|
||||
timer_disable(&dev->response_timer);
|
||||
/* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * 60us period measured on real VIA 686B */
|
||||
timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * 60 * TIMER_USEC);
|
||||
dev->stat = 0x08; /* raise HOST_BUSY while waiting */
|
||||
timer_disable(&dev->response_timer);
|
||||
/* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * 60us period measured on real VIA 686B */
|
||||
timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * 60 * TIMER_USEC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbus_ali7101_response(void *priv)
|
||||
{
|
||||
@@ -244,21 +239,19 @@ smbus_ali7101_response(void *priv)
|
||||
dev->stat = dev->next_stat;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable)
|
||||
{
|
||||
if (dev->io_base)
|
||||
io_removehandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev);
|
||||
io_removehandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev);
|
||||
|
||||
dev->io_base = new_io_base;
|
||||
smbus_ali7101_log("SMBus ALI7101: remap to %04Xh (%sabled)\n", dev->io_base, enable ? "en" : "dis");
|
||||
|
||||
if (enable && dev->io_base)
|
||||
io_sethandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev);
|
||||
io_sethandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbus_ali7101_reset(void *priv)
|
||||
{
|
||||
@@ -268,7 +261,6 @@ smbus_ali7101_reset(void *priv)
|
||||
dev->stat = 0x04;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
smbus_ali7101_init(const device_t *info)
|
||||
{
|
||||
@@ -276,7 +268,7 @@ smbus_ali7101_init(const device_t *info)
|
||||
memset(dev, 0, sizeof(smbus_ali7101_t));
|
||||
|
||||
dev->local = info->local;
|
||||
dev->stat = 0x04;
|
||||
dev->stat = 0x04;
|
||||
/* We save the I2C bus handle on dev but use i2c_smbus for all operations because
|
||||
dev and therefore dev->i2c will be invalidated if a device triggers a hard reset. */
|
||||
i2c_smbus = dev->i2c = i2c_addbus("smbus_ali7101");
|
||||
@@ -286,29 +278,28 @@ smbus_ali7101_init(const device_t *info)
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbus_ali7101_close(void *priv)
|
||||
{
|
||||
smbus_ali7101_t *dev = (smbus_ali7101_t *) priv;
|
||||
|
||||
if (i2c_smbus == dev->i2c)
|
||||
i2c_smbus = NULL;
|
||||
i2c_smbus = NULL;
|
||||
i2c_removebus(dev->i2c);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
const device_t ali7101_smbus_device = {
|
||||
.name = "ALi M7101-compatible SMBus Host Controller",
|
||||
.name = "ALi M7101-compatible SMBus Host Controller",
|
||||
.internal_name = "ali7101_smbus",
|
||||
.flags = DEVICE_AT,
|
||||
.local = 0,
|
||||
.init = smbus_ali7101_init,
|
||||
.close = smbus_ali7101_close,
|
||||
.reset = smbus_ali7101_reset,
|
||||
.flags = DEVICE_AT,
|
||||
.local = 0,
|
||||
.init = smbus_ali7101_init,
|
||||
.close = smbus_ali7101_close,
|
||||
.reset = smbus_ali7101_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
@@ -31,60 +31,58 @@
|
||||
#ifdef ENABLE_SMBUS_PIIX4_LOG
|
||||
int smbus_piix4_do_log = ENABLE_SMBUS_PIIX4_LOG;
|
||||
|
||||
|
||||
static void
|
||||
smbus_piix4_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (smbus_piix4_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define smbus_piix4_log(fmt, ...)
|
||||
# define smbus_piix4_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static uint8_t
|
||||
smbus_piix4_read(uint16_t addr, void *priv)
|
||||
{
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||
uint8_t ret = 0x00;
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (addr - dev->io_base) {
|
||||
case 0x00:
|
||||
ret = dev->stat;
|
||||
break;
|
||||
case 0x00:
|
||||
ret = dev->stat;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
dev->index = 0; /* reading from this resets the block data index */
|
||||
ret = dev->ctl;
|
||||
break;
|
||||
case 0x02:
|
||||
dev->index = 0; /* reading from this resets the block data index */
|
||||
ret = dev->ctl;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
ret = dev->cmd;
|
||||
break;
|
||||
case 0x03:
|
||||
ret = dev->cmd;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
ret = dev->addr;
|
||||
break;
|
||||
case 0x04:
|
||||
ret = dev->addr;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
ret = dev->data0;
|
||||
break;
|
||||
case 0x05:
|
||||
ret = dev->data0;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
ret = dev->data1;
|
||||
break;
|
||||
case 0x06:
|
||||
ret = dev->data1;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
ret = dev->data[dev->index++];
|
||||
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
case 0x07:
|
||||
ret = dev->data[dev->index++];
|
||||
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
smbus_piix4_log("SMBus PIIX4: read(%02X) = %02x\n", addr, ret);
|
||||
@@ -92,232 +90,230 @@ smbus_piix4_read(uint16_t addr, void *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||
uint8_t smbus_addr, cmd, read, block_len, prev_stat;
|
||||
uint16_t timer_bytes = 0, i = 0;
|
||||
uint8_t smbus_addr, cmd, read, block_len, prev_stat;
|
||||
uint16_t timer_bytes = 0, i = 0;
|
||||
|
||||
smbus_piix4_log("SMBus PIIX4: write(%02X, %02X)\n", addr, val);
|
||||
|
||||
prev_stat = dev->next_stat;
|
||||
prev_stat = dev->next_stat;
|
||||
dev->next_stat = 0x00;
|
||||
switch (addr - dev->io_base) {
|
||||
case 0x00:
|
||||
for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) { /* handle clearable bits */
|
||||
if (val & smbus_addr)
|
||||
dev->stat &= ~smbus_addr;
|
||||
}
|
||||
break;
|
||||
case 0x00:
|
||||
for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) { /* handle clearable bits */
|
||||
if (val & smbus_addr)
|
||||
dev->stat &= ~smbus_addr;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
dev->ctl = val & ((dev->local == SMBUS_VIA) ? 0x3f : 0x1f);
|
||||
if (val & 0x02) { /* cancel an in-progress command if KILL is set */
|
||||
if (prev_stat) { /* cancel only if a command is in progress */
|
||||
timer_disable(&dev->response_timer);
|
||||
dev->stat = 0x10; /* raise FAILED */
|
||||
}
|
||||
}
|
||||
if (val & 0x40) { /* dispatch command if START is set */
|
||||
timer_bytes++; /* address */
|
||||
case 0x02:
|
||||
dev->ctl = val & ((dev->local == SMBUS_VIA) ? 0x3f : 0x1f);
|
||||
if (val & 0x02) { /* cancel an in-progress command if KILL is set */
|
||||
if (prev_stat) { /* cancel only if a command is in progress */
|
||||
timer_disable(&dev->response_timer);
|
||||
dev->stat = 0x10; /* raise FAILED */
|
||||
}
|
||||
}
|
||||
if (val & 0x40) { /* dispatch command if START is set */
|
||||
timer_bytes++; /* address */
|
||||
|
||||
smbus_addr = dev->addr >> 1;
|
||||
read = dev->addr & 0x01;
|
||||
smbus_addr = dev->addr >> 1;
|
||||
read = dev->addr & 0x01;
|
||||
|
||||
cmd = (dev->ctl >> 2) & 0xf;
|
||||
smbus_piix4_log("SMBus PIIX4: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1);
|
||||
cmd = (dev->ctl >> 2) & 0xf;
|
||||
smbus_piix4_log("SMBus PIIX4: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1);
|
||||
|
||||
/* Raise DEV_ERR if no device is at this address, or if the device returned NAK. */
|
||||
if (!i2c_start(i2c_smbus, smbus_addr, read)) {
|
||||
dev->next_stat = 0x04;
|
||||
break;
|
||||
}
|
||||
/* Raise DEV_ERR if no device is at this address, or if the device returned NAK. */
|
||||
if (!i2c_start(i2c_smbus, smbus_addr, read)) {
|
||||
dev->next_stat = 0x04;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->next_stat = 0x02; /* raise INTER (command completed) by default */
|
||||
dev->next_stat = 0x02; /* raise INTER (command completed) by default */
|
||||
|
||||
/* Decode the command protocol.
|
||||
VIA-specific modes (0x4 and [0x6:0xf]) are undocumented and required real hardware research. */
|
||||
switch (cmd) {
|
||||
case 0x0: /* quick R/W */
|
||||
break;
|
||||
/* Decode the command protocol.
|
||||
VIA-specific modes (0x4 and [0x6:0xf]) are undocumented and required real hardware research. */
|
||||
switch (cmd) {
|
||||
case 0x0: /* quick R/W */
|
||||
break;
|
||||
|
||||
case 0x1: /* byte R/W */
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
case 0x1: /* byte R/W */
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x2: /* byte data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
case 0x2: /* byte data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
if (read) /* byte read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else /* byte write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
timer_bytes++;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x3: /* word data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
case 0x3: /* word data R/W */
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
|
||||
if (read) { /* word read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else { /* word write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
}
|
||||
timer_bytes += 2;
|
||||
if (read) { /* word read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else { /* word write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
}
|
||||
timer_bytes += 2;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x4: /* process call */
|
||||
if (dev->local != SMBUS_VIA) /* VIA only */
|
||||
goto unknown_protocol;
|
||||
case 0x4: /* process call */
|
||||
if (dev->local != SMBUS_VIA) /* VIA only */
|
||||
goto unknown_protocol;
|
||||
|
||||
if (!read) { /* command write (only when writing) */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
}
|
||||
if (!read) { /* command write (only when writing) */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
}
|
||||
|
||||
/* fall-through */
|
||||
/* fall-through */
|
||||
|
||||
case 0xc: /* I2C process call */
|
||||
if (!read) { /* word write (only when writing) */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
timer_bytes += 2;
|
||||
}
|
||||
case 0xc: /* I2C process call */
|
||||
if (!read) { /* word write (only when writing) */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
timer_bytes += 2;
|
||||
}
|
||||
|
||||
/* word read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||
timer_bytes += 2;
|
||||
/* word read */
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||
timer_bytes += 2;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x5: /* block R/W */
|
||||
timer_bytes++; /* count the SMBus length byte now */
|
||||
case 0x5: /* block R/W */
|
||||
timer_bytes++; /* count the SMBus length byte now */
|
||||
|
||||
/* fall-through */
|
||||
/* fall-through */
|
||||
|
||||
case 0xd: /* I2C block R/W */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
case 0xd: /* I2C block R/W */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
|
||||
if (read) {
|
||||
/* block read [data0] (I2C) or [first byte] (SMBus) bytes */
|
||||
if (cmd == 0x5)
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
for (i = 0; i < dev->data0; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else {
|
||||
if (cmd == 0x5) /* send length [data0] as first byte on SMBus */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
/* block write [data0] bytes */
|
||||
for (i = 0; i < dev->data0; i++) {
|
||||
if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer_bytes += i;
|
||||
if (read) {
|
||||
/* block read [data0] (I2C) or [first byte] (SMBus) bytes */
|
||||
if (cmd == 0x5)
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
for (i = 0; i < dev->data0; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else {
|
||||
if (cmd == 0x5) /* send length [data0] as first byte on SMBus */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
/* block write [data0] bytes */
|
||||
for (i = 0; i < dev->data0; i++) {
|
||||
if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer_bytes += i;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x6: /* I2C with 10-bit address */
|
||||
if (dev->local != SMBUS_VIA) /* VIA only */
|
||||
goto unknown_protocol;
|
||||
case 0x6: /* I2C with 10-bit address */
|
||||
if (dev->local != SMBUS_VIA) /* VIA only */
|
||||
goto unknown_protocol;
|
||||
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
/* command write */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
|
||||
/* fall-through */
|
||||
/* fall-through */
|
||||
|
||||
case 0xe: /* I2C with 7-bit address */
|
||||
if (!read) { /* word write (only when writing) */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
timer_bytes += 2;
|
||||
}
|
||||
case 0xe: /* I2C with 7-bit address */
|
||||
if (!read) { /* word write (only when writing) */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
timer_bytes += 2;
|
||||
}
|
||||
|
||||
/* block read [first byte] bytes */
|
||||
block_len = dev->data[0];
|
||||
for (i = 0; i < block_len; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
timer_bytes += i;
|
||||
/* block read [first byte] bytes */
|
||||
block_len = dev->data[0];
|
||||
for (i = 0; i < block_len; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
timer_bytes += i;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0xf: /* universal */
|
||||
/* block write [data0] bytes */
|
||||
for (i = 0; i < dev->data0; i++) {
|
||||
if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK]))
|
||||
break; /* write NAK behavior is unknown */
|
||||
}
|
||||
timer_bytes += i;
|
||||
case 0xf: /* universal */
|
||||
/* block write [data0] bytes */
|
||||
for (i = 0; i < dev->data0; i++) {
|
||||
if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK]))
|
||||
break; /* write NAK behavior is unknown */
|
||||
}
|
||||
timer_bytes += i;
|
||||
|
||||
/* block read [data1] bytes */
|
||||
for (i = 0; i < dev->data1; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
timer_bytes += i;
|
||||
/* block read [data1] bytes */
|
||||
for (i = 0; i < dev->data1; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
timer_bytes += i;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default: /* unknown */
|
||||
default: /* unknown */
|
||||
unknown_protocol:
|
||||
dev->next_stat = 0x04; /* raise DEV_ERR */
|
||||
timer_bytes = 0;
|
||||
break;
|
||||
}
|
||||
dev->next_stat = 0x04; /* raise DEV_ERR */
|
||||
timer_bytes = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Finish transfer. */
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
}
|
||||
break;
|
||||
/* Finish transfer. */
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
dev->cmd = val;
|
||||
break;
|
||||
case 0x03:
|
||||
dev->cmd = val;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
dev->addr = val;
|
||||
break;
|
||||
case 0x04:
|
||||
dev->addr = val;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
dev->data0 = val;
|
||||
break;
|
||||
case 0x05:
|
||||
dev->data0 = val;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
dev->data1 = val;
|
||||
break;
|
||||
case 0x06:
|
||||
dev->data1 = val;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->data[dev->index++] = val;
|
||||
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
case 0x07:
|
||||
dev->data[dev->index++] = val;
|
||||
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->next_stat) { /* schedule dispatch of any pending status register update */
|
||||
dev->stat = 0x01; /* raise HOST_BUSY while waiting */
|
||||
timer_disable(&dev->response_timer);
|
||||
/* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * bit period in usecs */
|
||||
timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * dev->bit_period * TIMER_USEC);
|
||||
dev->stat = 0x01; /* raise HOST_BUSY while waiting */
|
||||
timer_disable(&dev->response_timer);
|
||||
/* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * bit period in usecs */
|
||||
timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * dev->bit_period * TIMER_USEC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbus_piix4_response(void *priv)
|
||||
{
|
||||
@@ -327,21 +323,19 @@ smbus_piix4_response(void *priv)
|
||||
dev->stat = dev->next_stat;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable)
|
||||
{
|
||||
if (dev->io_base)
|
||||
io_removehandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev);
|
||||
io_removehandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev);
|
||||
|
||||
dev->io_base = new_io_base;
|
||||
smbus_piix4_log("SMBus PIIX4: remap to %04Xh (%sabled)\n", dev->io_base, enable ? "en" : "dis");
|
||||
|
||||
if (enable && dev->io_base)
|
||||
io_sethandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev);
|
||||
io_sethandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
smbus_piix4_setclock(smbus_piix4_t *dev, int clock)
|
||||
{
|
||||
@@ -351,7 +345,6 @@ smbus_piix4_setclock(smbus_piix4_t *dev, int clock)
|
||||
dev->bit_period = 1000000.0 / dev->clock;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
smbus_piix4_init(const device_t *info)
|
||||
{
|
||||
@@ -370,43 +363,42 @@ smbus_piix4_init(const device_t *info)
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbus_piix4_close(void *priv)
|
||||
{
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||
|
||||
if (i2c_smbus == dev->i2c)
|
||||
i2c_smbus = NULL;
|
||||
i2c_smbus = NULL;
|
||||
i2c_removebus(dev->i2c);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
const device_t piix4_smbus_device = {
|
||||
.name = "PIIX4-compatible SMBus Host Controller",
|
||||
.name = "PIIX4-compatible SMBus Host Controller",
|
||||
.internal_name = "piix4_smbus",
|
||||
.flags = DEVICE_AT,
|
||||
.local = SMBUS_PIIX4,
|
||||
.init = smbus_piix4_init,
|
||||
.close = smbus_piix4_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_AT,
|
||||
.local = SMBUS_PIIX4,
|
||||
.init = smbus_piix4_init,
|
||||
.close = smbus_piix4_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t via_smbus_device = {
|
||||
.name = "VIA VT82C686B SMBus Host Controller",
|
||||
.name = "VIA VT82C686B SMBus Host Controller",
|
||||
.internal_name = "via_smbus",
|
||||
.flags = DEVICE_AT,
|
||||
.local = SMBUS_VIA,
|
||||
.init = smbus_piix4_init,
|
||||
.close = smbus_piix4_close,
|
||||
.reset = NULL,
|
||||
.flags = DEVICE_AT,
|
||||
.local = SMBUS_VIA,
|
||||
.init = smbus_piix4_init,
|
||||
.close = smbus_piix4_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
Reference in New Issue
Block a user