From 60a31f4d8836fca72870682226f2279250cb2d74 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 5 Jan 2026 19:48:47 +0200 Subject: [PATCH] X-Surf IDE port emulation --- expansion.cpp | 12 +++- idecontrollers.cpp | 120 ++++++++++++++++++++++++++++++++++++++- include/idecontrollers.h | 5 ++ qemuvga/ne2000.cpp | 24 ++++++-- 4 files changed, 153 insertions(+), 8 deletions(-) diff --git a/expansion.cpp b/expansion.cpp index 4d5fb4ee..ad52e506 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -5079,6 +5079,12 @@ void ethernet_updateselection(void) } } +static bool xsurf_init_common(struct autoconfig_info *aci) +{ + xsurf_init_ide(aci); + return xsurf_init(aci); +} + static void fastlane_memory_callback(struct romconfig *rc, uae_u8 *ac, int size) { struct zfile *z = read_device_from_romconfig(rc, NULL); @@ -6365,11 +6371,11 @@ const struct expansionromtype expansionroms[] = { }, { _T("xsurf"), _T("X-Surf"), _T("Individual Computers"), - NULL, xsurf_init, NULL, NULL, ROMTYPE_XSURF | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true, + NULL, xsurf_init_common, NULL, xsurf_add_ide_unit, ROMTYPE_XSURF | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true, NULL, 0, - false, EXPANSIONTYPE_NET, + false, EXPANSIONTYPE_NET | EXPANSIONTYPE_IDE, 0, 0, 0, false, NULL, - false, 0, ethernet_settings, + false, 2, ethernet_settings, { 0xc1, 0x17, 0x00, 0x00, 4626 >> 8, 4626 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { diff --git a/idecontrollers.cpp b/idecontrollers.cpp index 7d764658..a666aceb 100644 --- a/idecontrollers.cpp +++ b/idecontrollers.cpp @@ -59,7 +59,8 @@ #define DOTTO_IDE (TANDEM_IDE + MAX_DUPLICATE_EXPANSION_BOARDS) #define DEV_IDE (DOTTO_IDE + MAX_DUPLICATE_EXPANSION_BOARDS) #define RIPPLE_IDE (DEV_IDE + MAX_DUPLICATE_EXPANSION_BOARDS) -#define TOTAL_IDE (RIPPLE_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS) +#define XSURF_IDE (RIPPLE_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS) +#define TOTAL_IDE (XSURF_IDE + MAX_DUPLICATE_EXPANSION_BOARDS) #define ALF_ROM_OFFSET 0x0100 #define GVP_IDE_ROM_OFFSET 0x8000 @@ -126,6 +127,7 @@ static struct ide_board *tandem_board[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ide_board *dotto_board[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ide_board *dev_board[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ide_board *ripple_board[MAX_DUPLICATE_EXPANSION_BOARDS]; +static struct ide_board *xsurf_board[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ide_hdf *idecontroller_drive[TOTAL_IDE * 2]; static struct ide_thread_state idecontroller_its; @@ -517,6 +519,19 @@ static int get_buddha_reg(uaecptr addr, struct ide_board *board, int *portnum, i return reg; } +static int get_xsurf_reg(uaecptr addr, struct ide_board *board, int *portnum) +{ + int reg = -1; + if ((addr & 0xf000) == 0xb000) { + *portnum = 0; + reg = (addr >> 2) & 7; + } else if ((addr & 0xf000) == 0xd000) { + *portnum = 1; + reg = (addr >> 2) & 7; + } + return reg; +} + static int get_rochard_reg(uaecptr addr, struct ide_board *board, int *portnum) { int reg = -1; @@ -723,6 +738,19 @@ static uae_u32 ide_read_byte2(struct ide_board *board, uaecptr addr) v = board->rom[offset]; } + } else if (board->type == XSURF_IDE) { + + int portnum; + int regnum = get_xsurf_reg(addr, board, &portnum); + if (regnum >= 0) { + if (board->ide[portnum]) { + v = get_ide_reg_multi(board, regnum, portnum, 1); + } + } else if ((addr & 0x80ff) == 0x7e) { + v = ide_irq_check(board->ide[0], false) ? 0x80 : 0x00; + v |= ide_irq_check(board->ide[1], false) ? 0x80 : 0x00; + } + } else if (board->type == ALF_IDE || board->type == TANDEM_IDE) { if (addr < 0x1100 || (addr & 1)) { @@ -1203,6 +1231,20 @@ static uae_u32 ide_read_word(struct ide_board *board, uaecptr addr) #endif } + } else if (board->type == XSURF_IDE) { + + int portnum; + int regnum = get_xsurf_reg(addr, board, &portnum); + if (regnum >= 0) { + if (regnum == IDE_DATA) { + if (board->ide[portnum]) + v = get_ide_reg_multi(board, IDE_DATA, portnum, 1); + } else { + v = ide_read_byte(board, addr) << 8; + v |= ide_read_byte(board, addr + 1); + } + } + } else if (board->type == GOLEMFAST_IDE) { if ((addr & 0x8700) == 0x8100) { @@ -1578,6 +1620,16 @@ static void ide_write_byte(struct ide_board *board, uaecptr addr, uae_u8 v) board->flashenabled = false; } + } else if (board->type == XSURF_IDE) { + + int portnum; + int regnum = get_xsurf_reg(addr, board, &portnum); + if (regnum >= 0) { + if (board->ide[portnum]) { + put_ide_reg_multi(board, regnum, v, portnum, 1); + } + } + } else if (board->type == ALF_IDE || board->type == TANDEM_IDE) { int regnum = get_alf_reg(addr, board); @@ -1919,6 +1971,19 @@ static void ide_write_word(struct ide_board *board, uaecptr addr, uae_u16 v) #endif } + } else if (board->type == XSURF_IDE) { + + int portnum; + int regnum = get_xsurf_reg(addr, board, &portnum); + if (regnum >= 0) { + if (regnum == IDE_DATA) { + if (board->ide[portnum]) + put_ide_reg_multi(board, IDE_DATA, v, portnum, 1); + } else { + ide_write_byte(board, addr, v >> 8); + ide_write_byte(board, addr + 1, (uae_u8)v); + } + } } else if (board->type == GOLEMFAST_IDE) { @@ -3366,6 +3431,59 @@ void ripple_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig add_ide_standard_unit(ch, ci, rc, ripple_board, RIPPLE_IDE, false, false, 4); } +bool xsurf_init_ide(struct autoconfig_info *aci) +{ + // xsurf_init() handles autoconfig stuff + + ide_add_reset(); + if (!aci->doinit) { + return true; + } + + struct ide_board *ide = getide(aci); + if (!ide) + return false; + + ide->bank = &ide_bank_generic; + ide->type = XSURF_IDE; + ide->configured = 1; + ide->baseaddress = aci->start; + ide->mask = 0xffff; + ide->intena = true; + + aci->addrbank = ide->bank; + return true; +} + +void xsurf_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) +{ + add_ide_standard_unit(ch, ci, rc, xsurf_board, XSURF_IDE, false, false, 4); +} + +uae_u32 xsurf_ide_read(uaecptr addr, int size) +{ + if (size == 1) { + return ide_generic_bget(addr); + } else if (size == 2) { + return ide_generic_wget(addr); + } else { + uae_u32 v = ide_generic_wget(addr) << 16; + v |= ide_generic_wget(addr + 2); + return v; + } +} +void xsurf_ide_write(uaecptr addr, int size, uae_u32 val) +{ + if (size == 1) { + ide_generic_bput(addr, val); + } else if (size == 2) { + ide_generic_wput(addr, val); + } else { + ide_generic_wput(addr, val >> 16); + ide_generic_wput(addr + 2, val & 0xffff); + } +} + #ifdef WITH_X86 extern void x86_xt_ide_bios(struct zfile*, struct romconfig*); static bool x86_at_hd_init(struct autoconfig_info *aci, int type) diff --git a/include/idecontrollers.h b/include/idecontrollers.h index f21aa5b2..5e03248a 100644 --- a/include/idecontrollers.h +++ b/include/idecontrollers.h @@ -70,6 +70,11 @@ bool dev_hd_init(struct autoconfig_info* aci); void ripple_add_ide_unit(int ch, struct uaedev_config_info* ci, struct romconfig* rc); bool ripple_init(struct autoconfig_info* aci); +void xsurf_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc); +bool xsurf_init_ide(struct autoconfig_info *aci); +uae_u32 xsurf_ide_read(uaecptr addr, int size); +void xsurf_ide_write(uaecptr addr, int size, uae_u32 val); + uae_u32 REGPARAM3 apollo_ide_lget (uaecptr addr) REGPARAM; uae_u32 REGPARAM3 apollo_ide_wget (uaecptr addr) REGPARAM; uae_u32 REGPARAM3 apollo_ide_bget (uaecptr addr) REGPARAM; diff --git a/qemuvga/ne2000.cpp b/qemuvga/ne2000.cpp index dbfe3598..89f2ad63 100644 --- a/qemuvga/ne2000.cpp +++ b/qemuvga/ne2000.cpp @@ -36,6 +36,7 @@ #include "debug.h" #include "sana2.h" #include "devices.h" +#include "idecontrollers.h" #include "qemuuaeglue.h" #include "queue.h" @@ -1609,6 +1610,7 @@ static uae_u8 isapnp_read_data(struct isapnp *pnp) static int toariadne2(struct ne2000_s *ne, uaecptr addr, uae_u32 *vp, int size, bool *bs) { + uaecptr orgaddr = addr; addr &= 0xffff; *bs = false; uae_u32 v = *vp; @@ -1694,14 +1696,20 @@ static int toariadne2(struct ne2000_s *ne, uaecptr addr, uae_u32 *vp, int size, return addr; } } else if (ne->ne2000_romtype == ROMTYPE_XSURF) { - if (addr == 0x7e && size == -1) { - ne->flags &= ~1; - ne->flags |= (v & 0x80) ? 1 : 0; + if ((addr & 0x80ff) == 0x007e) { + if (size == -1) { + ne->flags &= ~1; + ne->flags |= (v & 0x80) ? 1 : 0; + } else if (size == 1) { + *vp = xsurf_ide_read(orgaddr, size); + } else if (size == 2) { + *vp = xsurf_ide_read(orgaddr, 1) << 8; + } } else if (addr == 0xf00) { // driver uses this (undocumented) address to detect if X-Surf or X-Surf 100! *vp = 0xff; return -1; - } else if (addr >= 0x40 && addr < 0x8000) { + } else if ((addr & 0x80ff) == 0x0040) { *vp = ne->ariadne2_irq ? ((1 << 5) | (1 << 7)) : 0; return -1; } @@ -1723,6 +1731,14 @@ static int toariadne2(struct ne2000_s *ne, uaecptr addr, uae_u32 *vp, int size, return isa_addr; } } + if ((addr >= 0xb000 && addr < 0xc000) || (addr >= 0xd000 && addr < 0xe000)) { + if (size > 0) { + *vp = xsurf_ide_read(orgaddr, size); + } else { + xsurf_ide_write(orgaddr, -size, *vp); + } + return -1; + } } else if (ne->ne2000_romtype == ROMTYPE_XSURF100Z2 || ne->ne2000_romtype == ROMTYPE_XSURF100Z3) { int bank = addr >> 8; int baddr = addr & 255; -- 2.47.3