mirror of
https://github.com/86Box/86Box.git
synced 2026-02-21 17:15:32 -07:00
Merge pull request #6788 from akmed772/master
Add IBM Multistation 5550 (1983) machine
This commit is contained in:
@@ -4758,7 +4758,7 @@ static const scancode scancode_set82[512] = {
|
||||
// clang-format on
|
||||
};
|
||||
/* Scancode set 8Ah : IBM 5556 keyboard compatible scancode set used by J-DOS */
|
||||
static scancode scancode_set8a[512] =
|
||||
const scancode scancode_set8a[512] =
|
||||
{
|
||||
// clang-format off
|
||||
{.mk = { 0 }, .brk = { 0 } }, /* 000 */
|
||||
@@ -4817,7 +4817,7 @@ static scancode scancode_set8a[512] =
|
||||
{.mk = { 0x0a, 0 }, .brk = { 0 } }, /* 035 */
|
||||
{.mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 036 RSHIFT */
|
||||
{.mk = { 0x64, 0 }, .brk = { 0 } }, /* 037 * (asterisk) */
|
||||
{.mk = { 0x3A, 0 }, .brk = { 0xba, 0 } }, /* 038 0x3A LALT = Kanji */
|
||||
{.mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 038 0x3A LALT = Kanji */
|
||||
{.mk = { 0x34, 0 }, .brk = { 0 } }, /* 039 */
|
||||
{.mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 03a CAPSLOCK */
|
||||
{.mk = { 0x68, 0 }, .brk = { 0 } }, /* 03b F1 */
|
||||
|
||||
@@ -195,6 +195,8 @@ postcard_init(UNUSED(const device_t *info))
|
||||
postcard_port = 0x190; /* ISA PS/2 machines */
|
||||
else if (strstr(machines[machine].name, " IBM XT "))
|
||||
postcard_port = 0x60; /* IBM XT */
|
||||
else if (strstr(machines[machine].name, " Multistation "))
|
||||
postcard_port = 0xA1; /* IBM 5550 */
|
||||
else if (strstr(machines[machine].name, " IBM PCjr")) {
|
||||
postcard_port = 0x10; /* IBM PCjr */
|
||||
postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */
|
||||
|
||||
13
src/dma.c
13
src/dma.c
@@ -978,10 +978,15 @@ dma_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
|
||||
addr &= 0x0f;
|
||||
dmaregs[2][addr] = val;
|
||||
|
||||
if (addr >= 8)
|
||||
addr = convert[addr & 0x07] | 4;
|
||||
else
|
||||
addr = convert[addr & 0x07];
|
||||
if (machines[machine].init == machine_xt_ibm5550_init) {
|
||||
if (addr >= 4)
|
||||
addr = 8;
|
||||
} else {
|
||||
if (addr >= 8)
|
||||
addr = convert[addr & 0x07] | 4;
|
||||
else
|
||||
addr = convert[addr & 0x07];
|
||||
}
|
||||
|
||||
if (addr < 8) {
|
||||
dma[addr].page_l = val;
|
||||
|
||||
122
src/floppy/fdc.c
122
src/floppy/fdc.c
@@ -664,6 +664,21 @@ real_drive(fdc_t *fdc, int drive)
|
||||
return drive;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_diskchange_interrupt(fdc_t *fdc, int drive)
|
||||
{
|
||||
/*
|
||||
For the IBM 5550 machine to detect the disk in the drive has been changed.
|
||||
A hardware interrupt is caused by the FDC (NEC uPD765A) when the Ready line from the drive changes its state.
|
||||
Other PCs never use the Ready line.
|
||||
*/
|
||||
if (fdc->flags & FDC_FLAG_5550) {
|
||||
fdc->st0 = 0xc0 | (drive & 3);
|
||||
fdc_int(fdc, 1);
|
||||
fdd_changed[drive] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* FDD notifies FDC when seek operation is complete */
|
||||
void
|
||||
fdc_seek_complete_interrupt(fdc_t *fdc, int drive)
|
||||
@@ -822,8 +837,47 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
if (fdc->flags & FDC_FLAG_5550) {
|
||||
val = 0;
|
||||
if (!(val & 0x08)) { /* Drive 2 active */
|
||||
val = 0x42;
|
||||
}
|
||||
if (!(val & 0x04)) { /* Drive 1 active */
|
||||
val &= 0xf0;
|
||||
val |= 0x21;
|
||||
}
|
||||
if (!(val & 0x02)) { /* Drive 0 active */
|
||||
val &= 0xf0;
|
||||
val |= 0x10;
|
||||
}
|
||||
/* Update the DOR because this emulation module depend on it */
|
||||
fdc->dor &= 0x0c;
|
||||
fdc->dor |= val;
|
||||
/* We can now simplify this since each motor now spins separately. */
|
||||
for (int i = 0; i < FDD_NUM; i++) {
|
||||
drive_num = real_drive(fdc, i);
|
||||
if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM))
|
||||
val &= ~(0x10 << drive_num);
|
||||
else
|
||||
fdd_set_motor_enable(i, (val & (0x10 << drive_num)));
|
||||
}
|
||||
drive_num = real_drive(fdc, val & 0x03);
|
||||
current_drive = drive_num;
|
||||
fdc->st0 = (fdc->st0 & 0xf8) | (val & 0x03) | (fdd_get_head(drive_num) ? 4 : 0);
|
||||
fdc_log("val:%x, dor=%x, drv=%x\n", val, fdc->dor, drive_num);
|
||||
}
|
||||
return;
|
||||
case 2: /*DOR*/
|
||||
if (fdc->flags & FDC_FLAG_5550) { /* Reset */
|
||||
fdd_stop(fdc->drive);
|
||||
for (int i = 0; i < FDD_NUM; i++)
|
||||
fdd_set_motor_enable(i, 0); /* Need to restart fdd timer */
|
||||
fdc->stat = 0x00;
|
||||
fdc->pnum = fdc->ptot = 0;
|
||||
fdc_soft_reset(fdc);
|
||||
fdc->dor = 0x0c;
|
||||
return;
|
||||
}
|
||||
if (fdc->flags & FDC_FLAG_PCJR) {
|
||||
if ((fdc->dor & 0x40) && !(val & 0x40)) {
|
||||
timer_set_delay_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC);
|
||||
@@ -903,6 +957,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
return;
|
||||
case 4: /* DSR */
|
||||
if (fdc->flags & FDC_FLAG_5550)
|
||||
picintc(1 << fdc->irq);
|
||||
if (!(fdc->flags & FDC_FLAG_NO_DSR_RESET)) {
|
||||
if (!(val & 0x80)) {
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
@@ -914,6 +970,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->dsr = val;
|
||||
return;
|
||||
case 5: /*Command register*/
|
||||
if (fdc->flags & FDC_FLAG_5550)
|
||||
picintc(1 << fdc->irq);
|
||||
if (fdc->fifointest) {
|
||||
/* Write FIFO buffer in the test mode (PS/55) */
|
||||
fdc_log("FIFO buffer position = %X\n", ((fifo_t *) fdc->fifo_p)->end);
|
||||
@@ -948,7 +1006,33 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
fdc->command = val;
|
||||
fdc->stat |= 0x10;
|
||||
fdc_log("Starting FDC command %02X\n", fdc->command);
|
||||
fdc_log("Starting FDC command %02X ", fdc->command);
|
||||
switch (fdc->command & 0x1f) {
|
||||
case 0x06:
|
||||
fdc_log("READ DATA\n");
|
||||
break;
|
||||
case 0x0a:
|
||||
fdc_log("READ ID\n");
|
||||
break;
|
||||
case 0x07:
|
||||
fdc_log("RECALIB\n");
|
||||
break;
|
||||
case 0x08:
|
||||
fdc_log("SENSE INTERRUPT\n");
|
||||
break;
|
||||
case 0x03:
|
||||
fdc_log("SPECIFY\n");
|
||||
break;
|
||||
case 0x04:
|
||||
fdc_log("SENSE DRIVE\n");
|
||||
break;
|
||||
case 0x0f:
|
||||
fdc_log("SEEK\n");
|
||||
break;
|
||||
default:
|
||||
fdc_log("\n");
|
||||
break;
|
||||
}
|
||||
fdc->error = 0;
|
||||
|
||||
if (((fdc->command & 0x1f) == 0x02) || ((fdc->command & 0x1f) == 0x05) ||
|
||||
@@ -1106,6 +1190,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
if (command_has_drivesel[fdc->command & 0x1F]) {
|
||||
if (fdc->flags & FDC_FLAG_PCJR)
|
||||
fdc->drive = 0;
|
||||
else if (fdc->flags & FDC_FLAG_5550)
|
||||
fdc->drive = fdc->params[0] & 3;
|
||||
else
|
||||
fdc->drive = fdc->dor & 3;
|
||||
fdc->rw_drive = fdc->params[0] & 3;
|
||||
@@ -1115,6 +1201,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
if (fdc->pnum == fdc->ptot) {
|
||||
fdc_log("Got all params %02X\n", fdc->command);
|
||||
for (int i = 0; i < fdc->ptot; i++)
|
||||
fdc_log(" [%d] %02x\n", i, fdc->params[i]);
|
||||
fifo_reset(fdc->fifo_p);
|
||||
fdc->interrupt = fdc->processed_cmd;
|
||||
fdc->reset_stat = 0;
|
||||
@@ -1451,6 +1539,8 @@ fdc_read(uint16_t addr, void *priv)
|
||||
ret = 0xc0;
|
||||
ret |= (fdc->dor & 0x01) << 5; /* Drive Select 0 */
|
||||
ret |= (fdc->dor & 0x30) >> 4; /* Motor Select 1, 0 */
|
||||
} else if (fdc->flags & FDC_FLAG_5550) {
|
||||
ret = 0;
|
||||
} else {
|
||||
if (is486 || !fdc->enable_3f1)
|
||||
ret = 0xff;
|
||||
@@ -1503,9 +1593,13 @@ fdc_read(uint16_t addr, void *priv)
|
||||
ret = (fdc->rwc[drive] << 4) | (fdc->media_id << 6);
|
||||
break;
|
||||
case 4: /*Status*/
|
||||
if (fdc->flags & FDC_FLAG_5550)
|
||||
picintc(1 << fdc->irq);
|
||||
ret = fdc->stat;
|
||||
break;
|
||||
case 5: /*Data*/
|
||||
if (fdc->flags & FDC_FLAG_5550)
|
||||
picintc(1 << fdc->irq);
|
||||
if (fdc->fifointest) {
|
||||
/* Read FIFO buffer in the test mode (PS/55) */
|
||||
ret = fifo_read(fdc->fifo_p);
|
||||
@@ -1733,6 +1827,8 @@ fdc_callback(void *priv)
|
||||
}
|
||||
if (writeprot[fdc->drive])
|
||||
fdc->res[10] |= 0x40;
|
||||
if ((fdc->flags & FDC_FLAG_5550) && drive_empty[fdc->drive])//IBM 5550
|
||||
fdc->res[10] &= 0xdf; /* Set Not Ready */
|
||||
|
||||
fdc->stat = (fdc->stat & 0xf) | 0xd0;
|
||||
fdc->paramstogo = 1;
|
||||
@@ -2349,6 +2445,10 @@ fdc_set_base(fdc_t *fdc, int base)
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_sethandler(base + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else if (fdc->flags & FDC_FLAG_5550) {
|
||||
io_sethandler(base, 0x0003, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
@@ -2383,6 +2483,10 @@ fdc_remove(fdc_t *fdc)
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_removehandler(fdc->base_address + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else if (fdc->flags & FDC_FLAG_5550) {
|
||||
io_removehandler(fdc->base_address, 0x0003, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 4, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 5, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
io_removehandler(fdc->base_address + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
@@ -2534,6 +2638,8 @@ fdc_init(const device_t *info)
|
||||
fdc->irq = FDC_TERTIARY_IRQ;
|
||||
else if (fdc->flags & FDC_FLAG_QUA)
|
||||
fdc->irq = FDC_QUATERNARY_IRQ;
|
||||
else if (fdc->flags & FDC_FLAG_5550)
|
||||
fdc->irq = 4;
|
||||
else
|
||||
fdc->irq = FDC_PRIMARY_IRQ;
|
||||
|
||||
@@ -2686,6 +2792,20 @@ const device_t fdc_xt_umc_um8398_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t fdc_xt_5550_device = {
|
||||
.name = "IBM 5550 Floppy Drive Controller",
|
||||
.internal_name = "fdc_xt_5550",
|
||||
.flags = 0,
|
||||
.local = FDC_FLAG_5550,
|
||||
.init = fdc_init,
|
||||
.close = fdc_close,
|
||||
.reset = fdc_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t fdc_pcjr_device = {
|
||||
.name = "PCjr Floppy Drive Controller",
|
||||
.internal_name = "fdc_pcjr",
|
||||
|
||||
@@ -777,6 +777,10 @@ fdd_poll(void *priv)
|
||||
if (!fdd_notfound)
|
||||
fdc_noidam(fdd_fdc);
|
||||
}
|
||||
|
||||
if (fdd_changed[drive]) {
|
||||
fdc_diskchange_interrupt(fdd_fdc, drive);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define FDC_FLAG_TER 0x40000 /* Is Tertiary */
|
||||
#define FDC_FLAG_QUA 0x80000 /* Is Quaternary */
|
||||
#define FDC_FLAG_SMC661 0x100000 /* SM(s)C FDC37C661 - different TDR enhanced mode */
|
||||
#define FDC_FLAG_5550 0x200000 /* IBM Multistation 5550 */
|
||||
|
||||
typedef struct fdc_t {
|
||||
uint8_t dor;
|
||||
@@ -252,6 +253,7 @@ extern void fdc_reset(void *priv);
|
||||
|
||||
extern uint8_t fdc_get_current_drive(void);
|
||||
extern void fdc_seek_complete_interrupt(fdc_t *fdc, int drive);
|
||||
extern void fdc_diskchange_interrupt(fdc_t *fdc, int drive);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t fdc_xt_device;
|
||||
@@ -262,6 +264,7 @@ extern const device_t fdc_xt_t1x00_device;
|
||||
extern const device_t fdc_xt_tandy_device;
|
||||
extern const device_t fdc_xt_amstrad_device;
|
||||
extern const device_t fdc_xt_umc_um8398_device;
|
||||
extern const device_t fdc_xt_5550_device;
|
||||
extern const device_t fdc_pcjr_device;
|
||||
extern const device_t fdc_at_device;
|
||||
extern const device_t fdc_at_sec_device;
|
||||
|
||||
@@ -170,6 +170,7 @@ extern void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val));
|
||||
extern void kbd_adddata_process_10x(uint16_t val, void (*adddata)(uint16_t val));
|
||||
|
||||
extern const scancode scancode_xt[512];
|
||||
extern const scancode scancode_set8a[512];
|
||||
|
||||
extern uint8_t keyboard_set3_flags[512];
|
||||
extern uint8_t keyboard_set3_all_repeat;
|
||||
|
||||
@@ -1511,6 +1511,10 @@ extern int machine_xt_iskra3104_init(const machine_t *);
|
||||
extern int machine_xt_lxt3_init(const machine_t *);
|
||||
extern int machine_xt_compaq_deskpro_init(const machine_t *);
|
||||
|
||||
/* m_xt_ibm5550.c */
|
||||
|
||||
extern int machine_xt_ibm5550_init(const machine_t *);
|
||||
|
||||
/* m_xt_t1000.c */
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t t1000_video_device;
|
||||
|
||||
@@ -90,6 +90,8 @@ typedef struct pit_intf_t {
|
||||
void (*write)(uint16_t addr, uint8_t val, void *priv);
|
||||
/* Gets a counter's count. */
|
||||
uint16_t (*get_count)(void *data, int counter_id);
|
||||
/* Gets a counter's out. */
|
||||
int (*get_outlevel)(void *data, int counter_id);
|
||||
/* Sets a counter's GATE input. */
|
||||
void (*set_gate)(void *data, int counter_id, int gate);
|
||||
/* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */
|
||||
|
||||
@@ -26,6 +26,7 @@ add_library(mch OBJECT
|
||||
m_europc.c
|
||||
m_elt.c
|
||||
m_xt_olivetti.c
|
||||
m_xt_ibm5550.c
|
||||
m_tandy.c
|
||||
m_v86p.c
|
||||
m_at_t3100e.c
|
||||
|
||||
2132
src/machine/m_xt_ibm5550.c
Normal file
2132
src/machine/m_xt_ibm5550.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3033,6 +3033,49 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
{
|
||||
.name = "[8086] IBM Multistation 5550",
|
||||
.internal_name = "ibm5550",
|
||||
.type = MACHINE_TYPE_8086,
|
||||
.chipset = MACHINE_CHIPSET_DISCRETE,
|
||||
.init = machine_xt_ibm5550_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_8086,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 0,
|
||||
.max_bus = 0,
|
||||
.min_voltage = 0,
|
||||
.max_voltage = 0,
|
||||
.min_multi = 0,
|
||||
.max_multi = 0
|
||||
},
|
||||
.bus_flags = MACHINE_PC,
|
||||
.flags = MACHINE_VIDEO_FIXED | MACHINE_KEYBOARD,
|
||||
.ram = {
|
||||
.min = 256,
|
||||
.max = 640,
|
||||
.step = 128
|
||||
},
|
||||
.nvrmask = 15,
|
||||
.jumpered_ecp_dma = 0,
|
||||
.default_jumpered_ecp_dma = -1,
|
||||
.kbc_device = NULL,
|
||||
.kbc_params = 0x00000000,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = NULL,
|
||||
.kbd_device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = NULL,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
|
||||
/* 286 AT machines */
|
||||
/* Has IBM AT KBC firmware. */
|
||||
|
||||
15
src/pit.c
15
src/pit.c
@@ -420,6 +420,15 @@ pit_ctr_get_count(void *data, int counter_id)
|
||||
return (uint16_t) ctr->l;
|
||||
}
|
||||
|
||||
int
|
||||
pit_ctr_get_outlevel(void *data, int counter_id)
|
||||
{
|
||||
const pit_t *pit = (pit_t *) data;
|
||||
const ctr_t *ctr = &pit->counters[counter_id];
|
||||
|
||||
return (int) ctr->out;
|
||||
}
|
||||
|
||||
void
|
||||
pit_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count))
|
||||
{
|
||||
@@ -1208,6 +1217,11 @@ pit_set_clock(uint32_t clock)
|
||||
CGACONST = (uint64_t) ((cpuclock / (157500000.0 / 88.0)) * (double) (1ULL << 32));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (machines[machine].init == machine_xt_ibm5550_init) {
|
||||
PITCONSTD = (cpuclock / 2000000.0); /* CLK input 2.0 MHz */
|
||||
PITCONST = (uint64_t) (PITCONSTD * (double) (1ULL << 32));
|
||||
}
|
||||
|
||||
ISACONST = (1ULL << 32ULL);
|
||||
}
|
||||
@@ -1263,6 +1277,7 @@ const pit_intf_t pit_classic_intf = {
|
||||
.read = &pit_read,
|
||||
.write = &pit_write,
|
||||
.get_count = &pit_ctr_get_count,
|
||||
.get_outlevel = &pit_ctr_get_outlevel,
|
||||
.set_gate = &pit_ctr_set_gate,
|
||||
.set_using_timer = &pit_ctr_set_using_timer,
|
||||
.set_out_func = &pit_ctr_set_out_func,
|
||||
|
||||
Reference in New Issue
Block a user