mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 01:48:21 -07:00
Merge remote-tracking branch 'origin/master' into version/4.1
This commit is contained in:
@@ -70,7 +70,6 @@ typedef struct ali1543_t {
|
||||
sff8038i_t *ide_controller[2];
|
||||
smbus_ali7101_t *smbus;
|
||||
usb_t *usb;
|
||||
usb_params_t usb_params;
|
||||
|
||||
} ali1543_t;
|
||||
|
||||
@@ -1069,7 +1068,7 @@ ali7101_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x40:
|
||||
dev->pmu_conf[addr] = val & 0x1f;
|
||||
pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03));
|
||||
nvr_smi_enable((dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x08), dev->nvr);
|
||||
break;
|
||||
case 0x41:
|
||||
dev->pmu_conf[addr] = val & 0x10;
|
||||
@@ -1080,6 +1079,8 @@ ali7101_write(int func, int addr, uint8_t val, void *priv)
|
||||
/* TODO: Is the status R/W or R/WC? */
|
||||
case 0x42:
|
||||
dev->pmu_conf[addr] &= ~(val & 0x1f);
|
||||
if (val & 0x08)
|
||||
nvr_smi_status_clear(dev->nvr);
|
||||
break;
|
||||
case 0x43:
|
||||
dev->pmu_conf[addr] &= ~(val & 0x10);
|
||||
@@ -1217,8 +1218,8 @@ ali7101_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x77:
|
||||
/* TODO: If bit 1 is clear, then status bit is set even if SMI is disabled. */
|
||||
dev->pmu_conf[addr] = val;
|
||||
pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03));
|
||||
ali1543_log("PMU77: %02X\n", val);
|
||||
nvr_smi_enable((dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x08), dev->nvr);
|
||||
apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10));
|
||||
break;
|
||||
|
||||
@@ -1423,14 +1424,23 @@ ali7101_read(int func, int addr, void *priv)
|
||||
return 0xff;
|
||||
|
||||
/* TODO: C4, C5 = GPIREG (masks: 0D, 0E) */
|
||||
if (addr == 0x43)
|
||||
ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00;
|
||||
else if (addr == 0x7f)
|
||||
ret = 0x80;
|
||||
else if (addr == 0xbc)
|
||||
ret = inb(0x70);
|
||||
else
|
||||
ret = dev->pmu_conf[addr];
|
||||
switch (addr) {
|
||||
default:
|
||||
ret = dev->pmu_conf[addr];
|
||||
break;
|
||||
case 0x42:
|
||||
ret = (dev->pmu_conf[addr] & 0xf7) | (nvr_smi_status(dev->nvr) ? 0x08 : 0x00);
|
||||
break;
|
||||
case 0x43:
|
||||
ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00;
|
||||
break;
|
||||
case 0x7f:
|
||||
ret = 0x80;
|
||||
break;
|
||||
case 0xbc:
|
||||
ret = inb(0x70);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->pmu_conf[0x77] & 0x10) {
|
||||
switch (addr) {
|
||||
@@ -1472,17 +1482,6 @@ ali7101_read(int func, int addr, void *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
ali5237_usb_update_interrupt(usb_t* usb, void *priv)
|
||||
{
|
||||
ali1543_t *dev = (ali1543_t *) priv;
|
||||
|
||||
if (usb->irq_level)
|
||||
pci_set_mirq(4, !!(dev->pci_conf[0x74] & 0x10), &dev->mirq_states[4]);
|
||||
else
|
||||
pci_clear_mirq(4, !!(dev->pci_conf[0x74] & 0x10), &dev->mirq_states[4]);
|
||||
}
|
||||
|
||||
static void
|
||||
ali1543_reset(void *priv)
|
||||
{
|
||||
@@ -1633,10 +1632,7 @@ ali1543_init(const device_t *info)
|
||||
dev->smbus = device_add(&ali7101_smbus_device);
|
||||
|
||||
/* USB */
|
||||
dev->usb_params.parent_priv = dev;
|
||||
dev->usb_params.smi_handle = NULL;
|
||||
dev->usb_params.update_interrupt = ali5237_usb_update_interrupt;
|
||||
dev->usb = device_add_parameters(&usb_device, &dev->usb_params);
|
||||
dev->usb = device_add(&usb_device);
|
||||
|
||||
dev->type = info->local & 0xff;
|
||||
dev->offset = (info->local >> 8) & 0x7f;
|
||||
|
||||
@@ -522,7 +522,7 @@ i420ex_speed_changed(void *priv)
|
||||
if (te)
|
||||
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
|
||||
|
||||
te = timer_is_enabled(&dev->fast_off_timer);
|
||||
te = timer_is_on(&dev->fast_off_timer);
|
||||
|
||||
timer_stop(&dev->fast_off_timer);
|
||||
if (te)
|
||||
|
||||
@@ -66,7 +66,6 @@ typedef struct _piix_ {
|
||||
uint8_t max_func;
|
||||
uint8_t pci_slot;
|
||||
uint8_t no_mirq0;
|
||||
uint8_t usb_irq_state;
|
||||
uint8_t regs[4][256];
|
||||
uint8_t readout_regs[256];
|
||||
uint8_t board_config[2];
|
||||
@@ -84,7 +83,6 @@ typedef struct _piix_ {
|
||||
piix_io_trap_t io_traps[26];
|
||||
port_92_t *port_92;
|
||||
pc_timer_t fast_off_timer;
|
||||
usb_params_t usb_params;
|
||||
} piix_t;
|
||||
|
||||
#ifdef ENABLE_PIIX_LOG
|
||||
@@ -1443,17 +1441,6 @@ piix_fast_off_count(void *priv)
|
||||
dev->regs[0][0xaa] |= 0x20;
|
||||
}
|
||||
|
||||
static void
|
||||
piix_usb_update_interrupt(usb_t* usb, void *priv)
|
||||
{
|
||||
piix_t *dev = (piix_t *) priv;
|
||||
|
||||
if (usb->irq_level)
|
||||
pci_set_irq(dev->pci_slot, PCI_INTD, &dev->usb_irq_state);
|
||||
else
|
||||
pci_clear_irq(dev->pci_slot, PCI_INTD, &dev->usb_irq_state);
|
||||
}
|
||||
|
||||
static void
|
||||
piix_reset(void *priv)
|
||||
{
|
||||
@@ -1554,10 +1541,10 @@ piix_speed_changed(void *priv)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
int te = timer_is_enabled(&dev->fast_off_timer);
|
||||
int to = timer_is_on(&dev->fast_off_timer);
|
||||
|
||||
timer_stop(&dev->fast_off_timer);
|
||||
if (te)
|
||||
if (to)
|
||||
timer_on_auto(&dev->fast_off_timer, ((double) cpu_fast_off_val + 1) * dev->fast_off_period);
|
||||
}
|
||||
|
||||
@@ -1598,12 +1585,8 @@ piix_init(const device_t *info)
|
||||
sff_set_irq_mode(dev->bm[1], 1, 2);
|
||||
}
|
||||
|
||||
if (dev->type >= 3) {
|
||||
dev->usb_params.parent_priv = dev;
|
||||
dev->usb_params.smi_handle = NULL;
|
||||
dev->usb_params.update_interrupt = piix_usb_update_interrupt;
|
||||
dev->usb = device_add_parameters(&usb_device, &dev->usb_params);
|
||||
}
|
||||
if (dev->type >= 3)
|
||||
dev->usb = device_add(&usb_device);
|
||||
|
||||
if (dev->type > 3) {
|
||||
dev->nvr = device_add(&piix4_nvr_device);
|
||||
|
||||
@@ -497,7 +497,7 @@ sio_speed_changed(void *priv)
|
||||
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
|
||||
|
||||
if (dev->id == 0x03) {
|
||||
te = timer_is_enabled(&dev->fast_off_timer);
|
||||
te = timer_is_on(&dev->fast_off_timer);
|
||||
|
||||
timer_stop(&dev->fast_off_timer);
|
||||
if (te)
|
||||
|
||||
@@ -87,9 +87,6 @@ typedef struct sis_5571_t {
|
||||
sff8038i_t *ide_drive[2];
|
||||
smram_t *smram;
|
||||
usb_t *usb;
|
||||
|
||||
usb_params_t usb_params;
|
||||
|
||||
} sis_5571_t;
|
||||
|
||||
static void
|
||||
@@ -669,43 +666,6 @@ pci_isa_bridge_read(int func, int addr, void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sis_5571_usb_update_interrupt(usb_t* usb, void* priv)
|
||||
{
|
||||
sis_5571_t *dev = (sis_5571_t *) priv;
|
||||
|
||||
if (dev->pci_conf_sb[0][0x68] & 0x80) {
|
||||
/* TODO: Is the normal PCI interrupt inhibited when USB IRQ remapping is enabled? */
|
||||
switch (dev->pci_conf_sb[0][0x68] & 0x0F) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x08:
|
||||
case 0x0d:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (usb->irq_level)
|
||||
picint(1 << dev->pci_conf_sb[0][0x68] & 0x0f);
|
||||
else
|
||||
picintc(1 << dev->pci_conf_sb[0][0x68] & 0x0f);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (usb->irq_level)
|
||||
pci_set_irq(dev->sb_slot, PCI_INTA, &dev->usb_irq_state);
|
||||
else
|
||||
pci_clear_irq(dev->sb_slot, PCI_INTA, &dev->usb_irq_state);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
sis_5571_usb_handle_smi(UNUSED(usb_t* usb), UNUSED(void* priv))
|
||||
{
|
||||
/* Left unimplemented for now. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
sis_5571_reset(void *priv)
|
||||
{
|
||||
@@ -790,10 +750,7 @@ sis_5571_init(UNUSED(const device_t *info))
|
||||
dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2);
|
||||
|
||||
/* USB */
|
||||
dev->usb_params.parent_priv = dev;
|
||||
dev->usb_params.update_interrupt = sis_5571_usb_update_interrupt;
|
||||
dev->usb_params.smi_handle = sis_5571_usb_handle_smi;
|
||||
dev->usb = device_add_parameters(&usb_device, &dev->usb_params);
|
||||
dev->usb = device_add(&usb_device);
|
||||
|
||||
sis_5571_reset(dev);
|
||||
|
||||
|
||||
@@ -73,9 +73,6 @@ typedef struct stpc_t {
|
||||
smram_t *smram;
|
||||
usb_t *usb;
|
||||
sff8038i_t *bm[2];
|
||||
|
||||
/* Miscellaneous */
|
||||
usb_params_t usb_params;
|
||||
} stpc_t;
|
||||
|
||||
typedef struct stpc_serial_t {
|
||||
@@ -898,17 +895,6 @@ stpc_setup(stpc_t *dev)
|
||||
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
|
||||
}
|
||||
|
||||
static void
|
||||
stpc_usb_update_interrupt(usb_t* usb, void* priv)
|
||||
{
|
||||
stpc_t *dev = (stpc_t *) priv;
|
||||
|
||||
if (usb->irq_level)
|
||||
pci_set_irq(dev->usb_slot, PCI_INTA, &dev->usb_irq_state);
|
||||
else
|
||||
pci_clear_irq(dev->usb_slot, PCI_INTA, &dev->usb_irq_state);
|
||||
}
|
||||
|
||||
static void
|
||||
stpc_close(void *priv)
|
||||
{
|
||||
@@ -934,12 +920,9 @@ stpc_init(const device_t *info)
|
||||
pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev, &dev->nb_slot);
|
||||
pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev, &dev->sb_slot);
|
||||
if (dev->local == STPC_ATLAS) {
|
||||
dev->usb_params.smi_handle = NULL;
|
||||
dev->usb_params.update_interrupt = stpc_usb_update_interrupt;
|
||||
dev->usb_params.parent_priv = dev;
|
||||
|
||||
pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, stpc_ide_read, stpc_ide_write, dev, &dev->ide_slot);
|
||||
dev->usb = device_add_parameters(&usb_device, &dev->usb_params);
|
||||
|
||||
dev->usb = device_add(&usb_device);
|
||||
pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, stpc_usb_read, stpc_usb_write, dev, &dev->usb_slot);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ static ini_t config;
|
||||
static int backwards_compat = 0;
|
||||
static int backwards_compat2 = 0;
|
||||
|
||||
#define ENABLE_CONFIG_LOG 1
|
||||
#define ENABLE_CONFIG_LOG 1
|
||||
#ifdef ENABLE_CONFIG_LOG
|
||||
int config_do_log = ENABLE_CONFIG_LOG;
|
||||
|
||||
@@ -1254,7 +1254,7 @@ load_floppy_drives(void)
|
||||
path_append_filename(floppyfns[c], usr_path, p);
|
||||
path_normalize(floppyfns[c]);
|
||||
|
||||
#ifdef ENABLE_CONFIG_LOG
|
||||
#if defined(ENABLE_CONFIG_LOG) && (ENABLE_CONFIG_LOG == 2)
|
||||
if (*p != '\0')
|
||||
config_log("Floppy%d: %ls\n", c, floppyfns[c]);
|
||||
#endif
|
||||
@@ -1309,7 +1309,7 @@ load_floppy_and_cdrom_drives(void)
|
||||
path_append_filename(floppyfns[c], usr_path, p);
|
||||
path_normalize(floppyfns[c]);
|
||||
|
||||
#ifdef ENABLE_CONFIG_LOG
|
||||
#if defined(ENABLE_CONFIG_LOG) && (ENABLE_CONFIG_LOG == 2)
|
||||
if (*p != '\0')
|
||||
config_log("Floppy%d: %ls\n", c, floppyfns[c]);
|
||||
#endif
|
||||
|
||||
@@ -369,7 +369,7 @@ exec386_2386(int cycs)
|
||||
}
|
||||
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process_inline();
|
||||
timer_process();
|
||||
|
||||
#ifdef USE_GDBSTUB
|
||||
if (gdbstub_instruction())
|
||||
|
||||
@@ -256,7 +256,7 @@ update_tsc(void)
|
||||
|
||||
if (cycdiff > 0) {
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process_inline();
|
||||
timer_process();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -782,7 +782,7 @@ exec386_dynarec(int cycs)
|
||||
|
||||
if (cycdiff > 0) {
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process_inline();
|
||||
timer_process();
|
||||
}
|
||||
|
||||
# ifdef USE_GDBSTUB
|
||||
@@ -943,7 +943,7 @@ exec386(int cycs)
|
||||
}
|
||||
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process_inline();
|
||||
timer_process();
|
||||
|
||||
#ifdef USE_GDBSTUB
|
||||
if (gdbstub_instruction())
|
||||
|
||||
@@ -363,7 +363,7 @@ serial_update_speed(serial_t *dev)
|
||||
if (dev->transmit_enabled & 3)
|
||||
timer_on_auto(&dev->transmit_timer, dev->transmit_period);
|
||||
|
||||
if (timer_is_enabled(&dev->timeout_timer))
|
||||
if (timer_is_on(&dev->timeout_timer))
|
||||
timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period);
|
||||
}
|
||||
|
||||
|
||||
@@ -1939,7 +1939,7 @@ ide_status(ide_t *ide, ide_t *ide_other, int ch)
|
||||
if ((ide->type == IDE_NONE) && ((ide_other->type == IDE_NONE) || !(ch & 1)))
|
||||
return 0x7f; /* Bit 7 pulled down, all other bits pulled up, per the spec. */
|
||||
else if ((ide->type == IDE_NONE) && (ch & 1))
|
||||
return 0x00; /* On real hardware, a slave with a present master always returns a status of 0x00. */
|
||||
return 0x7f /*0x00*/; /* On real hardware, a slave with a present master always returns a status of 0x00. */
|
||||
else if (ide->type == IDE_ATAPI)
|
||||
return (ide->sc->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
|
||||
else
|
||||
|
||||
@@ -127,5 +127,8 @@ extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr);
|
||||
extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr);
|
||||
extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr);
|
||||
extern void nvr_irq_set(int irq, nvr_t *nvr);
|
||||
extern void nvr_smi_enable(int enable, nvr_t *nvr);
|
||||
extern uint8_t nvr_smi_status(nvr_t *nvr);
|
||||
extern void nvr_smi_status_clear(nvr_t *nvr);
|
||||
|
||||
#endif /*EMU_NVR_H*/
|
||||
|
||||
@@ -122,7 +122,7 @@ timer_is_enabled(pc_timer_t *timer)
|
||||
static __inline int
|
||||
timer_is_on(pc_timer_t *timer)
|
||||
{
|
||||
return ((timer->flags & TIMER_ENABLED) && (timer->period > 0.0));
|
||||
return ((timer->flags & TIMER_SPLIT) && (timer->flags & TIMER_ENABLED));
|
||||
}
|
||||
|
||||
/*Return integer timestamp of timer*/
|
||||
@@ -184,45 +184,8 @@ timer_set_p(pc_timer_t *timer, void *priv)
|
||||
|
||||
/* The API for big timer periods starts here. */
|
||||
extern void timer_stop(pc_timer_t *timer);
|
||||
extern void timer_advance_ex(pc_timer_t *timer, int start);
|
||||
extern void timer_on(pc_timer_t *timer, double period, int start);
|
||||
extern void timer_on_auto(pc_timer_t *timer, double period);
|
||||
|
||||
extern void timer_remove_head(void);
|
||||
|
||||
extern pc_timer_t *timer_head;
|
||||
extern int timer_inited;
|
||||
|
||||
static __inline void
|
||||
timer_process_inline(void)
|
||||
{
|
||||
pc_timer_t *timer;
|
||||
|
||||
if (!timer_head)
|
||||
return;
|
||||
|
||||
while (1) {
|
||||
timer = timer_head;
|
||||
|
||||
if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc))
|
||||
break;
|
||||
|
||||
timer_head = timer->next;
|
||||
if (timer_head)
|
||||
timer_head->prev = NULL;
|
||||
|
||||
timer->next = timer->prev = NULL;
|
||||
timer->flags &= ~TIMER_ENABLED;
|
||||
|
||||
if (timer->flags & TIMER_SPLIT)
|
||||
timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */
|
||||
else if (timer->callback != NULL) /* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */
|
||||
timer->callback(timer->priv);
|
||||
}
|
||||
|
||||
timer_target = timer_head->ts.ts32.integer;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for the Distributed DMA emulation.
|
||||
* Definitions for the Distributed DMA emulation.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
|
||||
#ifndef USB_H
|
||||
@@ -22,188 +22,21 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct usb_t usb_t;
|
||||
typedef struct usb_device_t usb_device_t;
|
||||
|
||||
enum usb_pid
|
||||
typedef struct
|
||||
{
|
||||
USB_PID_OUT = 0xE1,
|
||||
USB_PID_IN = 0x69,
|
||||
USB_PID_SETUP = 0x2D
|
||||
};
|
||||
|
||||
enum usb_errors
|
||||
{
|
||||
USB_ERROR_NO_ERROR = 0,
|
||||
USB_ERROR_NAK = 1,
|
||||
USB_ERROR_OVERRUN = 2,
|
||||
USB_ERROR_UNDERRUN = 3
|
||||
};
|
||||
|
||||
enum usb_bus_types
|
||||
{
|
||||
USB_BUS_OHCI = 0,
|
||||
USB_BUS_UHCI = 1,
|
||||
USB_BUS_MAX = 2
|
||||
};
|
||||
|
||||
/* USB device creation parameters struct */
|
||||
typedef struct usb_params_t
|
||||
{
|
||||
void (*update_interrupt)(usb_t*, void*);
|
||||
/* Handle (but do not raise) SMI. Returns 1 if SMI can be raised, 0 otherwise. */
|
||||
uint8_t (*smi_handle)(usb_t*, void*);
|
||||
void* parent_priv;
|
||||
} usb_params_t;
|
||||
|
||||
typedef union {
|
||||
uint32_t l;
|
||||
uint16_t w[2];
|
||||
uint8_t b[4];
|
||||
} ohci_mmio_t;
|
||||
|
||||
/* USB Host Controller device struct */
|
||||
typedef struct usb_t {
|
||||
uint8_t uhci_io[32];
|
||||
ohci_mmio_t ohci_mmio[1024];
|
||||
uint8_t uhci_io[32], ohci_mmio[4096];
|
||||
uint16_t uhci_io_base;
|
||||
int uhci_enable;
|
||||
int ohci_enable;
|
||||
int uhci_enable, ohci_enable;
|
||||
uint32_t ohci_mem_base;
|
||||
uint32_t irq_level;
|
||||
mem_mapping_t ohci_mmio_mapping;
|
||||
pc_timer_t ohci_frame_timer;
|
||||
pc_timer_t ohci_port_reset_timer[2];
|
||||
uint8_t ohci_interrupt_counter : 3;
|
||||
usb_device_t *ohci_devices[2];
|
||||
usb_device_t *uhci_devices[2];
|
||||
uint8_t ohci_usb_buf[4096];
|
||||
uint8_t ohci_initial_start;
|
||||
|
||||
usb_params_t *usb_params;
|
||||
} usb_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* Base USB descriptor struct. */
|
||||
typedef struct usb_desc_base_t {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
} usb_desc_base_t;
|
||||
|
||||
enum usb_desc_setup_req_types {
|
||||
USB_SETUP_TYPE_DEVICE = 0x0,
|
||||
USB_SETUP_TYPE_INTERFACE = 0x1,
|
||||
USB_SETUP_TYPE_ENDPOING = 0x2,
|
||||
USB_SETUP_TYPE_OTHER = 0x3,
|
||||
};
|
||||
|
||||
#define USB_SETUP_TYPE_MAX 0x1F
|
||||
|
||||
#define USB_SETUP_DEV_TO_HOST 0x80
|
||||
|
||||
typedef struct usb_desc_setup_t {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} usb_desc_setup_t;
|
||||
|
||||
typedef struct usb_desc_endpoint_t {
|
||||
usb_desc_base_t base;
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmAttributes;
|
||||
uint16_t wMaxPacketSize;
|
||||
uint8_t bInterval;
|
||||
} usb_desc_endpoint_t;
|
||||
|
||||
typedef struct usb_desc_hid_t {
|
||||
usb_desc_base_t base;
|
||||
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wDescriptorLength;
|
||||
} usb_desc_hid_t;
|
||||
|
||||
typedef struct usb_desc_interface_t {
|
||||
usb_desc_base_t base;
|
||||
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bAlternateSetting;
|
||||
uint8_t bNumEndpoints;
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
uint8_t iInterface;
|
||||
} usb_desc_interface_t;
|
||||
|
||||
typedef struct usb_desc_string_t {
|
||||
usb_desc_base_t base;
|
||||
uint16_t bString[];
|
||||
} usb_desc_string_t;
|
||||
|
||||
typedef struct usb_desc_conf_t {
|
||||
usb_desc_base_t base;
|
||||
|
||||
uint16_t wTotalLength;
|
||||
uint8_t bNumInterfaces;
|
||||
uint8_t bConfigurationValue;
|
||||
uint8_t iConfiguration;
|
||||
uint8_t bmAttributes;
|
||||
uint8_t bMaxPower;
|
||||
} usb_desc_conf_t;
|
||||
|
||||
typedef struct usb_desc_device_t {
|
||||
usb_desc_base_t base;
|
||||
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} usb_desc_device_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* USB endpoint device struct. Incomplete and unused. */
|
||||
typedef struct usb_device_t {
|
||||
usb_desc_device_t device_desc;
|
||||
struct {
|
||||
usb_desc_conf_t conf_desc;
|
||||
usb_desc_base_t* other_descs[16];
|
||||
} conf_desc_items;
|
||||
|
||||
/* General-purpose function for I/O. Non-zero value indicates error. */
|
||||
uint8_t (*device_process)(void* priv, uint8_t* data, uint32_t *len, uint8_t pid_token, uint8_t endpoint, uint8_t underrun_not_allowed);
|
||||
/* Device reset. */
|
||||
void (*device_reset)(void* priv);
|
||||
/* Get address. */
|
||||
uint8_t (*device_get_address)(void* priv);
|
||||
|
||||
void* priv;
|
||||
} usb_device_t;
|
||||
|
||||
/* Global variables. */
|
||||
extern const device_t usb_device;
|
||||
extern usb_t* usb_device_inst;
|
||||
|
||||
/* Functions. */
|
||||
extern void uhci_update_io_mapping(usb_t *dev, uint8_t base_l, uint8_t base_h, int enable);
|
||||
extern void ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, int enable);
|
||||
/* Attach USB device to a port of a USB bus. Returns the port to which it got attached to. */
|
||||
extern uint8_t usb_attach_device(usb_t *dev, usb_device_t* device, uint8_t bus_type);
|
||||
/* Detach USB device from a port. */
|
||||
extern void usb_detach_device(usb_t *dev, uint8_t port, uint8_t bus_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
35
src/nvr_at.c
35
src/nvr_at.c
@@ -307,7 +307,7 @@ typedef struct local_t {
|
||||
uint8_t wp_0d;
|
||||
uint8_t wp_32;
|
||||
uint8_t irq_state;
|
||||
uint8_t pad0;
|
||||
uint8_t smi_status;
|
||||
|
||||
uint8_t addr[8];
|
||||
uint8_t wp[2];
|
||||
@@ -317,6 +317,8 @@ typedef struct local_t {
|
||||
int16_t count;
|
||||
int16_t state;
|
||||
|
||||
int32_t smi_enable;
|
||||
|
||||
uint64_t ecount;
|
||||
uint64_t rtc_time;
|
||||
pc_timer_t update_timer;
|
||||
@@ -444,6 +446,10 @@ timer_update_irq(nvr_t *nvr)
|
||||
if (irq) {
|
||||
nvr->regs[RTC_REGC] |= REGC_IRQF;
|
||||
picintlevel(1 << nvr->irq, &local->irq_state);
|
||||
if (local->smi_enable) {
|
||||
smi_raise();
|
||||
local->smi_status = 1;
|
||||
}
|
||||
} else {
|
||||
nvr->regs[RTC_REGC] &= ~REGC_IRQF;
|
||||
picintclevel(1 << nvr->irq, &local->irq_state);
|
||||
@@ -981,6 +987,33 @@ nvr_irq_set(int irq, nvr_t *nvr)
|
||||
nvr->irq = irq;
|
||||
}
|
||||
|
||||
void
|
||||
nvr_smi_enable(int enable, nvr_t *nvr)
|
||||
{
|
||||
local_t *local = (local_t *) nvr->data;
|
||||
|
||||
local->smi_enable = enable;
|
||||
|
||||
if (!enable)
|
||||
local->smi_status = 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
nvr_smi_status(nvr_t *nvr)
|
||||
{
|
||||
local_t *local = (local_t *) nvr->data;
|
||||
|
||||
return local->smi_status;
|
||||
}
|
||||
|
||||
void
|
||||
nvr_smi_status_clear(nvr_t *nvr)
|
||||
{
|
||||
local_t *local = (local_t *) nvr->data;
|
||||
|
||||
local->smi_status = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvr_at_reset(void *priv)
|
||||
{
|
||||
|
||||
@@ -639,7 +639,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
}
|
||||
} else {
|
||||
/*Don't stop the timer until it finishes the transfer*/
|
||||
if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
||||
if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) &&
|
||||
!timer_is_on(&ncr_dev->timer)) {
|
||||
ncr_log("Continuing DMA mode\n");
|
||||
ncr_timer_on(ncr_dev, ncr, 0);
|
||||
}
|
||||
@@ -671,7 +672,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
if (dev->buffer_length > 0) {
|
||||
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
|
||||
|
||||
ncr_log("DMA send timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer));
|
||||
ncr_log("DMA send timer start, enabled? = %i\n", timer_is_on(&ncr_dev->timer));
|
||||
ncr_dev->t128.block_count = dev->buffer_length >> 9;
|
||||
ncr_dev->t128.block_loaded = 1;
|
||||
|
||||
@@ -679,7 +680,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
ncr_dev->t128.status |= 0x04;
|
||||
}
|
||||
} else {
|
||||
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
||||
if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) {
|
||||
memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length));
|
||||
|
||||
ncr_log("DMA send timer on\n");
|
||||
@@ -693,7 +694,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
/*a Read 6/10 has occurred, start the timer when the block count is loaded*/
|
||||
ncr->dma_mode = DMA_INITIATOR_RECEIVE;
|
||||
if (ncr_dev->type == 3) {
|
||||
ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n", timer_is_enabled(&ncr_dev->timer), ncr->command[0], dev->buffer_length);
|
||||
ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n",
|
||||
timer_is_on(&ncr_dev->timer), ncr->command[0], dev->buffer_length);
|
||||
if (dev->buffer_length > 0) {
|
||||
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
|
||||
|
||||
@@ -709,7 +711,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
timer_on_auto(&ncr_dev->timer, 0.02);
|
||||
}
|
||||
} else {
|
||||
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
||||
if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) {
|
||||
memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length));
|
||||
|
||||
ncr_log("DMA receive timer start\n");
|
||||
|
||||
@@ -1055,7 +1055,7 @@ spock_callback(void *priv)
|
||||
spock_process_scsi(scsi, scb);
|
||||
|
||||
period = 0.2 * ((double) scsi->temp_period);
|
||||
timer_on(&scsi->callback_timer, (scsi->media_period + period + 10.0), 0);
|
||||
timer_on_auto(&scsi->callback_timer, (scsi->media_period + period + 10.0));
|
||||
spock_log("Temporary period: %lf us (%" PRIi64 " periods)\n", scsi->callback_timer.period, scsi->temp_period);
|
||||
}
|
||||
|
||||
|
||||
@@ -1293,7 +1293,7 @@ x54x_cmd_callback(void *priv)
|
||||
}
|
||||
|
||||
period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period);
|
||||
timer_on(&dev->timer, dev->media_period + period + 10.0, 0);
|
||||
timer_on_auto(&dev->timer, dev->media_period + period + 10.0);
|
||||
#if 0
|
||||
x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period);
|
||||
#endif
|
||||
|
||||
138
src/timer.c
138
src/timer.c
@@ -15,10 +15,13 @@ pc_timer_t *timer_head = NULL;
|
||||
/* Are we initialized? */
|
||||
int timer_inited = 0;
|
||||
|
||||
static void timer_advance_ex(pc_timer_t *timer);
|
||||
|
||||
void
|
||||
timer_enable(pc_timer_t *timer)
|
||||
{
|
||||
pc_timer_t *timer_node = timer_head;
|
||||
int ret = 0;
|
||||
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
@@ -29,59 +32,63 @@ timer_enable(pc_timer_t *timer)
|
||||
if (timer->next || timer->prev)
|
||||
fatal("timer_enable - timer->next\n");
|
||||
|
||||
timer->flags |= TIMER_ENABLED;
|
||||
|
||||
/*List currently empty - add to head*/
|
||||
if (!timer_head) {
|
||||
timer_head = timer;
|
||||
timer->next = timer->prev = NULL;
|
||||
timer_target = timer_head->ts.ts32.integer;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TIMER_LESS_THAN(timer, timer_head)) {
|
||||
ret = 1;
|
||||
} else if (TIMER_LESS_THAN(timer, timer_head)) {
|
||||
timer->next = timer_head;
|
||||
timer->prev = NULL;
|
||||
timer_head->prev = timer;
|
||||
timer_head = timer;
|
||||
timer_target = timer_head->ts.ts32.integer;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!timer_head->next) {
|
||||
ret = 1;
|
||||
} else if (!timer_head->next) {
|
||||
timer_head->next = timer;
|
||||
timer->prev = timer_head;
|
||||
return;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
pc_timer_t *prev = timer_head;
|
||||
timer_node = timer_head->next;
|
||||
if (ret == 0) {
|
||||
pc_timer_t *prev = timer_head;
|
||||
timer_node = timer_head->next;
|
||||
|
||||
while (1) {
|
||||
/*Timer expires before timer_node. Add to list in front of timer_node*/
|
||||
if (TIMER_LESS_THAN(timer, timer_node)) {
|
||||
timer->next = timer_node;
|
||||
timer->prev = prev;
|
||||
timer_node->prev = timer;
|
||||
prev->next = timer;
|
||||
return;
|
||||
while (1) {
|
||||
/*Timer expires before timer_node. Add to list in front of timer_node*/
|
||||
if (TIMER_LESS_THAN(timer, timer_node)) {
|
||||
timer->next = timer_node;
|
||||
timer->prev = prev;
|
||||
timer_node->prev = timer;
|
||||
prev->next = timer;
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*timer_node is last in the list. Add timer to end of list*/
|
||||
if (!timer_node->next) {
|
||||
timer_node->next = timer;
|
||||
timer->prev = timer_node;
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
prev = timer_node;
|
||||
timer_node = timer_node->next;
|
||||
}
|
||||
|
||||
/*timer_node is last in the list. Add timer to end of list*/
|
||||
if (!timer_node->next) {
|
||||
timer_node->next = timer;
|
||||
timer->prev = timer_node;
|
||||
return;
|
||||
}
|
||||
|
||||
prev = timer_node;
|
||||
timer_node = timer_node->next;
|
||||
}
|
||||
|
||||
/* Do not mark it as enabled if it has failed every single condition. */
|
||||
if (ret == 1)
|
||||
timer->flags |= TIMER_ENABLED;
|
||||
}
|
||||
|
||||
void
|
||||
timer_disable(pc_timer_t *timer)
|
||||
{
|
||||
pc_timer_t *cur, *temp;
|
||||
|
||||
if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED))
|
||||
return;
|
||||
|
||||
@@ -120,13 +127,15 @@ timer_process(void)
|
||||
timer->next = timer->prev = NULL;
|
||||
timer->flags &= ~TIMER_ENABLED;
|
||||
|
||||
timer->flags |= TIMER_PROCESS;
|
||||
if (timer->flags & TIMER_SPLIT)
|
||||
timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */
|
||||
else if (timer->callback != NULL) {/* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */
|
||||
timer->flags |= TIMER_PROCESS;
|
||||
timer_advance_ex(timer); /* We're splitting a > 1 s period into
|
||||
multiple <= 1 s periods. */
|
||||
else if (timer->callback != NULL) /* Make sure it's not NULL, so that we can
|
||||
have a NULL callback when no operation
|
||||
is needed. */
|
||||
timer->callback(timer->priv);
|
||||
timer->flags &= ~TIMER_PROCESS;
|
||||
}
|
||||
timer->flags &= ~TIMER_PROCESS;
|
||||
}
|
||||
|
||||
timer_target = timer_head->ts.ts32.integer;
|
||||
@@ -182,60 +191,47 @@ timer_stop(pc_timer_t *timer)
|
||||
return;
|
||||
|
||||
timer->period = 0.0;
|
||||
timer_disable(timer);
|
||||
if (timer_is_enabled(timer))
|
||||
timer_disable(timer);
|
||||
timer->flags &= ~TIMER_SPLIT;
|
||||
}
|
||||
|
||||
static void
|
||||
timer_do_period(pc_timer_t *timer, uint64_t period, int start)
|
||||
timer_do_period(pc_timer_t *timer, uint64_t period)
|
||||
{
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
|
||||
if (start)
|
||||
timer_set_delay_u64(timer, period);
|
||||
else
|
||||
if (timer->flags & TIMER_PROCESS)
|
||||
timer_advance_u64(timer, period);
|
||||
else
|
||||
timer_set_delay_u64(timer, period);
|
||||
}
|
||||
|
||||
void
|
||||
timer_advance_ex(pc_timer_t *timer, int start)
|
||||
static void
|
||||
timer_advance_ex(pc_timer_t *timer)
|
||||
{
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
double dusec = ((double) TIMER_USEC);
|
||||
double period;
|
||||
|
||||
if (timer->period > MAX_USEC) {
|
||||
timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start);
|
||||
timer->period -= MAX_USEC;
|
||||
timer->flags |= TIMER_SPLIT;
|
||||
} else {
|
||||
if (timer->period > 0.0)
|
||||
timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start);
|
||||
else
|
||||
timer_disable(timer);
|
||||
timer->period = 0.0;
|
||||
period = (timer->period > MAX_USEC) ? MAX_USEC64 : timer->period;
|
||||
|
||||
if (timer->period > 0.0) {
|
||||
timer_do_period(timer, (uint64_t) (period * dusec));
|
||||
timer->period -= period;
|
||||
timer->flags = (timer->flags & ~TIMER_SPLIT) | ((timer->period > MAX_USEC) ? TIMER_SPLIT : 0);
|
||||
} else if (timer_is_enabled(timer)) {
|
||||
timer_disable(timer);
|
||||
timer->flags &= ~TIMER_SPLIT;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
timer_on(pc_timer_t *timer, double period, int start)
|
||||
{
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
|
||||
timer->period = period;
|
||||
timer_advance_ex(timer, start);
|
||||
}
|
||||
|
||||
void
|
||||
timer_on_auto(pc_timer_t *timer, double period)
|
||||
{
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
|
||||
if (period > 0.0)
|
||||
timer_on(timer, period, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0));
|
||||
else
|
||||
if (period > 0.0) {
|
||||
timer->period = period;
|
||||
timer_advance_ex(timer);
|
||||
} else if (timer_is_on(timer))
|
||||
timer_stop(timer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user