clang-format in src/device/

This commit is contained in:
Jasmine Iwanek
2022-09-18 17:13:28 -04:00
parent 3753a9f8b2
commit 9a3cabbe85
29 changed files with 7451 additions and 7355 deletions

View File

@@ -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
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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
};

View File

@@ -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()

View File

@@ -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
};

View File

@@ -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

View File

@@ -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
};

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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

View File

@@ -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
};

View File

@@ -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
};

View File

@@ -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
};

View File

@@ -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,

View File

@@ -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
};

View File

@@ -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
};