From c50f63bafe28e581efa736d7b4ba955cb8fcbd03 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 12 Feb 2026 00:13:36 +0900 Subject: [PATCH 01/66] corrected readonly conf flags --- src/machine/m_xt_ibm5550.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index e1c842ecb..fe398cefd 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -428,7 +428,7 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) // epoch->attrc[epoch->attraddr & 0x3f] = val; // break; default: - epoch_iolog("epoch? Out addr %03X val %02X\n", addr, val); + // epoch_iolog("epoch? Out addr %03X val %02X\n", addr, val); break; } } @@ -482,8 +482,8 @@ epoch_in(uint16_t addr, void *priv) if(epoch->cgastat & 8) temp &= 0x7f; } - temp &= 0xfe;/* equipment ? color or monochrome monitor */ - // temp |= 0x01; + temp |= 0x01; /* monitor mono or !color */ + // temp &= 0xfe; /* color */ break; } if (addr != 0x3DA) @@ -1117,14 +1117,14 @@ static void epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // epoch_log("epoch_vram_writeb: Write to %x, val %x\n", addr, val); + // epoch_log("%04X:%04X epoch_vram_writeb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); cycles -= video_timing_write_b; epoch_vram_write(addr, val, epoch); } static void epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) { - // epoch_log("epoch_vram_writ ew: Write to %x, val %x\n", addr, val); + // epoch_log("%04X:%04X epoch_vram_writew: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); epoch_t *epoch = (epoch_t *) priv; cycles -= video_timing_write_w; epoch_vram_write(addr, val & 0xff, epoch); @@ -1311,23 +1311,23 @@ xxxx xxx1: Memory or parity error? break; /* I/O A2h R: -xxxx 0x0x: Color CRT +xxxx 0x0x: Color 16 CRT xxxx 1x0x: Mono 24 CRT ? -xxxx xx1x: 16 pixel CRT +xxxx xx1x: Mono 16 CRT xx1x xxxx: No hard drive x1xx xxxx: No floppy drive 1xxx xxxx: No (bootable?) hard drive */ case 0xA2: ret = 0xA8;/* Mono 24 */ - // ret = 0xA8;/* Mono 16 */ + // ret = 0xA2;/* Mono 16 */ break; /* I/O A3h R: -xxxx x001: Main RAM 256 KB? -xxxx x011: Main RAM 384 KB? -xxxx x111: Main RAM 512 KB? -xxxx x000: Main RAM 640 KB? +xxxx x111: Main RAM 256 KB +xxxx x110: Main RAM 384 KB +xxxx x100: Main RAM 512 KB +xxxx x000: Main RAM 640 KB xxxx 1xxx: Serial port 3f8h xxx1 xxxx: Serial port 2f8h */ @@ -1940,7 +1940,7 @@ epoch_init(UNUSED(const device_t *info)) epoch->vram = calloc(1, 256* 1024); epoch->cram = calloc(1, 4 * 1024); // epoch->fontcard.rom = calloc(1, EPOCH_FONTROM_SIZE); - //epoch_video_load_font("roms/machines/ibm5550/GEN1FONT.BIN", epoch); + // epoch_video_load_font("roms/machines/ibm5550/GEN1FONT.BIN", epoch); epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); From 9366beda68db19be981c34a0220c504e906fbac5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 12 Feb 2026 21:08:40 +0100 Subject: [PATCH 02/66] Qt Software Renderer: Apply DPI scaling to processed screenshots, fixes #6807. --- src/qt/qt_softwarerenderer.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_softwarerenderer.cpp b/src/qt/qt_softwarerenderer.cpp index d9e217ed3..854d53433 100644 --- a/src/qt/qt_softwarerenderer.cpp +++ b/src/qt/qt_softwarerenderer.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include "qt_util.hpp" extern "C" { #include <86box/86box.h> @@ -114,16 +116,30 @@ SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) plat_tempfile(fn, NULL, (char *) ".png"); strcat(path, fn); + qreal win_scale = util::screenOfWidget(this)->devicePixelRatio(); + QSize qs = RendererCommon::parentWidget->size(); QPixmap pixmap(RendererCommon::parentWidget->size()); RendererCommon::parentWidget->render(&pixmap); - QImage image = pixmap.toImage(); + QImage image; + if (win_scale == 1.0) + image = pixmap.toImage(); + else + image = pixmap.toImage().scaled(qs * win_scale, Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); image.save(path, "png"); monitors[r_monitor_index].mon_screenshots--; } if (monitors[r_monitor_index].mon_screenshots_clipboard) { + qreal win_scale = util::screenOfWidget(this)->devicePixelRatio(); + QSize qs = RendererCommon::parentWidget->size(); QPixmap pixmap(RendererCommon::parentWidget->size()); RendererCommon::parentWidget->render(&pixmap); - QImage image = pixmap.toImage(); + QImage image; + if (win_scale == 1.0) + image = pixmap.toImage(); + else + image = pixmap.toImage().scaled(qs * win_scale, Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); QClipboard *clipboard = QApplication::clipboard(); clipboard->setImage(image, QClipboard::Clipboard); monitors[r_monitor_index].mon_screenshots_clipboard--; From 283d9b4fcc7ed0fee22812bb9a92a070af3e8f41 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 12 Feb 2026 21:09:59 +0100 Subject: [PATCH 03/66] Network switch: Fix warning. --- src/network/net_switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_switch.c b/src/network/net_switch.c index ced2f0392..a2f8c23db 100644 --- a/src/network/net_switch.c +++ b/src/network/net_switch.c @@ -505,7 +505,7 @@ net_switch_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, char if (netcard->secret[0] != '\0') { uint8_t temp[32]; - net_switch_secret_hash((const uint8_t *)netcard->secret, (uint8_t *) temp); + net_switch_secret_hash((const char *) netcard->secret, (uint8_t *) temp); memcpy(netswitch->secret_hash, temp, 32); netswitch->secret_enabled = 1; } else { From d2c1b00750c0336583b6e316e5abd2939122f52c Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Thu, 12 Feb 2026 13:19:22 -0800 Subject: [PATCH 04/66] Qt: Always change floppy type's first column on changing type Thanks to DFXThomas on Discord for pointing out this bug. --- src/qt/qt_settingsfloppycdrom.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index d896614d8..17587e652 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -434,7 +434,8 @@ void SettingsFloppyCDROM::on_comboBoxFloppyType_activated(int index) { auto currentIndex = ui->tableViewFloppy->selectionModel()->currentIndex(); - setFloppyType(ui->tableViewFloppy->model(), currentIndex, index); + auto typeIndex = currentIndex.siblingAtColumn(0); + setFloppyType(ui->tableViewFloppy->model(), typeIndex, index); // Trigger row changed to rebuild audio profile list onFloppyRowChanged(currentIndex); From 42c5c2a73fe865348d4e6b1537e3d9b07adbaae9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 13 Feb 2026 11:27:33 +0100 Subject: [PATCH 05/66] OpenGL Renderer: Pad the line pitch to the nearest dword when taking non-raw screenshots, fixed messed up screenshots. --- src/qt/qt_openglrenderer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 788a74744..56bf51479 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -1726,7 +1726,8 @@ OpenGLRenderer::render() glw.glFinish(); glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb); - QImage image((uchar*)rgb, width, height, width * 3, QImage::Format_RGB888); + int pitch_adj = (4 - ((width * 3) & 3)) & 3; + QImage image((uchar*)rgb, width, height, (width * 3) + pitch_adj, QImage::Format_RGB888); image.mirrored(false, true).save(path, "png"); monitors[r_monitor_index].mon_screenshots--; free(rgb); @@ -1739,7 +1740,8 @@ OpenGLRenderer::render() glw.glFinish(); glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb); - QImage image((uchar*)rgb, width, height, width * 3, QImage::Format_RGB888); + int pitch_adj = (4 - ((width * 3) & 3)) & 3; + QImage image((uchar*)rgb, width, height, (width * 3) + pitch_adj, QImage::Format_RGB888); QClipboard *clipboard = QApplication::clipboard(); clipboard->setImage(image.mirrored(false, true), QClipboard::Clipboard); monitors[r_monitor_index].mon_screenshots_clipboard--; From b044891562b628030287a9ed9791b438cc5287c8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 14 Feb 2026 23:20:43 +0100 Subject: [PATCH 06/66] Active indictator: Make it a bit brighter in order to stand out more. --- src/qt/icons/active.ico | Bin 9622 -> 9622 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/qt/icons/active.ico b/src/qt/icons/active.ico index ebd5bb4524a62656d27c8598b103f52f77c8db5c..69c6c5945a7f79c3004896d4cb7ef2da6e2d256e 100644 GIT binary patch literal 9622 zcmeHMy-veG40c5YLJV~1(5)F6c>_A}983s_m*~idcnT&YHbz)@3Wf@H#K?d!pOgFA z>#r_pnySc_EGKtoe|KLK`*Ia&Nn1J{fz9NqEpjd*-EMLJv@i02wqCEezd01SJQB&W z;{G0fpBQ@rA6z0r(GDX6_^l}le`?uKDtB)aE#jobfZyZ0>hnZ}RF5~#?Und59s`HWue6o&Z1lV2{?pG3d)+z%&Ok#9==YiGS6_8> zJg?Sn{UyZe7PioG3T558z+QR-64x$X*9B8wO`Dxj$a$=5v8|k=iLs*I5oaw7k58r- z+fDOhs4Fn?@1N9fx5X4xu9b7gi+>^z&3G@Olt}DE*e#V+Q?{Q7zek-=)dRIq{ zo}CfaXmvWqTXr4lxbak`*^ys`Hs zo3GZ6<0xoG8jZcXGjI3Bo>^~1TGEzIM_@C#Zi`%qNVi+uKkth?p{>^|?r#r8u8u^q zthj%G-zUbN!Uva#P_)Cy0DfzV!k=0;l*-M^M2k3SG2nOiu6pt~(L7dajBWedD#ILX z9j0OaY3t{xY5v&i))}bGfPSdz8*~_{-CKKtSe`+;$@7inE0cTVsG5YiCbm^WPjb)n zdt|Z8$%1^s+*B$r5!K_3b9*KJjK{zs^DAwoJRAKkx&QR@!d|z|fHTk#1Nwcg`qft* z9nY(^TYm|$x`i#YoIzQ)F0q&1fW)!{d|b z#dg#D80rd){QD>M+imd*iq?R^T2C9EomHOceZa`$#WvmBM>+$}fHSbO45%Kc{_d&% zw6MpLd9`-yw{aE3_F)-x0OdYxXa|?g3HM~NZ34Z(i|Y!ntDmu^&U;+bxZjHHxZc%K zqi1J?HCmmH@s?eOI&M7GC)>m?flW?o<-qZipS^#{zr95zo`G7QJ-)%)#*a8ymWMX- z9l`a}f(QN<#G}o5xBez1%wvq%6mAo1a|~y|8E^)i0cXG&*l7lE0MW-EKsaO=;jrNq UhYqGg97xP6`)r(zH^24e4?=A9M*si- From 6a62568e97f55f41ef3d8397e5f61e3ceed72b69 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 14 Feb 2026 23:26:03 +0100 Subject: [PATCH 07/66] And again, now they should stand out even more. --- src/qt/icons/active.ico | Bin 9622 -> 9622 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/qt/icons/active.ico b/src/qt/icons/active.ico index 69c6c5945a7f79c3004896d4cb7ef2da6e2d256e..999c94ee69db88edce89163a7cdf91f5fb985dc6 100644 GIT binary patch literal 9622 zcmeHMJ5Iwu5S@q!geXXnB3)ckasyIv4l2YkQc@v~fhedc;SM=KBzlyR0x`U?_c@!d z){f%{G$W11-rbqE`(n?mHzFPBO0OrdncQ_nu0^EZFYaHDMPAT07!>#Sry{p!B3V}4 zKf&)4V=v%?OGGHzVPpiq9Yx_!tr|+@S?5~BNs9r$$xQWOGS@s-YK%ks+bY8xY#pXy z{%Pyys73zR>ed;k&47NW>N|8Csoh(9f>@qGy2$_mASnZf5v0rkolFiR-TQ1m)w8xd10?xXTTX~i2?n(Qk@M|r{}9` z?bcsGtZrcoEtgQ%tsCs6_aJfY;&oFn&DFH!8HJq3x)$5oIhq(->K$=*!tnTHdcEB@ zKZd#mBme$M{dQZwf}%BGu-4OtXJ?yddLJQ|DdQH14-zTh_ZKYV`7q zutuxXG2W)@P{)m@=H!t06|l)kqZ~MX^0W6Z`M0;I!ZXn5v&T31(D)GtoAS_Jz9YDP zTJXT%f_St!@7CXjgn5*hZQ-`DHpg%VoB?OR8E^)ifj`Xv4j_j30|_A}983s_m*~idcnT&YHbz)@3Wf@H#K?d!pOgFA z>#r_pnySc_EGKtoe|KLK`*Ia&Nn1J{fz9NqEpjd*-EMLJv@i02wqCEezd01SJQB&W z;{G0fpBQ@rA6z0r(GDX6_^l}le`?uKDtB)aE#jobfZyZ0>hnZ}RF5~#?Und59s`HWue6o&Z1lV2{?pG3d)+z%&Ok#9==YiGS6_8> zJg?Sn{UyZe7PioG3T558z+QR-64x$X*9B8wO`Dxj$a$=5v8|k=iLs*I5oaw7k58r- z+fDOhs4Fn?@1N9fx5X4xu9b7gi+>^z&3G@Olt}DE*e#V+Q?{Q7zek-=)dRIq{ zo}CfaXmvWqTXr4lxbak Date: Sun, 15 Feb 2026 13:44:51 +0900 Subject: [PATCH 08/66] Added a mouse controller for IBM 5550 --- src/machine/m_xt_ibm5550.c | 327 ++++++++++++++++++++++++++++++------ src/machine/machine_table.c | 2 +- 2 files changed, 277 insertions(+), 52 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index fe398cefd..68dd15a39 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -57,6 +57,7 @@ #include <86box/plat_unused.h> #define EMU_DEVICE_H #include <86box/pit.h> +#include <86box/mouse.h> // #define EPOCH_FONTROM_SIZE (1024 * 1024) // #define EPOCH_FONTROM_MASK 0xffff @@ -155,11 +156,12 @@ enum epoch_nvr_ADDR { }; #ifndef RELEASE_BUILD -// #define ENABLE_EPOCH_LOG 1 +#define ENABLE_EPOCH_LOG 1 #endif #ifdef ENABLE_EPOCH_LOG -// # define ENABLE_EPOCH_DEBUGIO 1 +// #define ENABLE_EPOCH_DEBUGIO 1 +#define ENABLE_EPOCH_DEBUGKBD 1 int epoch_do_log = ENABLE_EPOCH_LOG; static void @@ -181,6 +183,12 @@ epoch_log(const char *fmt, ...) #else # define epoch_iolog(fmt, ...) #endif +#ifdef ENABLE_EPOCH_DEBUGKBD +# define epoch_kbdlog epoch_log +#else +# define epoch_kbdlog(fmt, ...) +#endif + typedef struct epoch_t { mem_mapping_t cmapping; @@ -332,7 +340,7 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) case LC_START_ADDRESS_HIGH: case LC_CURSOR_LOC_HIGH: case LC_LIGHT_PEN_HIGH: - val &= 0x3F; + val &= 0x3F; /* this is required for the IPL BAT test */ break; } epoch->crtc[epoch->crtcaddr] = val; @@ -1417,14 +1425,22 @@ typedef struct epochkbd_t { uint8_t pa; uint8_t pb; - uint8_t clock; + // uint8_t clock; + uint8_t clk_hold; + // uint8_t clk_in; + // uint8_t clk_ff; + int mouse_enabled; + uint8_t mouse_queue[4]; + int mouse_queue_num; + // int mouse_ackwaiting; uint8_t key_waiting; - uint8_t reset_step; + uint8_t kbd_reset_step; + uint8_t mouse_reset_step; pc_timer_t send_delay_timer; } epochkbd_t; -static uint8_t key_queue[16]; +static uint8_t key_queue[16]; /* buffer in the keyboard */ static int key_queue_start = 0; static int key_queue_end = 0; @@ -1435,25 +1451,53 @@ kbd_epoch_poll(void *priv) timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC); - if (kbd->pb & 0x04) + // if (kbd->clock & 0x04) + // return; + if (kbd->pb & 0x04) /* controller is sending something to keyboard */ + return; + + if (!(kbd->pb & 0x08)) /* keyboard interrupt is disabled */ return; if (kbd->want_irq) { kbd->want_irq = 0; kbd->pa = kbd->key_waiting; - kbd->pb &= 0xF7; + // kbd->clock |= 0x04; kbd->blocked = 1; picint(EPOCH_IRQ3_BIT); - epoch_log("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n"); + epoch_kbdlog("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n"); } - if ((key_queue_start != key_queue_end) && !kbd->blocked) { - kbd->key_waiting = key_queue[key_queue_start]; - epoch_log("epochkbd: 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; + if (!kbd->blocked) { + // if (kbd->mouse_queue_num > 0 && kbd->mouse_ackwaiting == 0) { + if (kbd->mouse_queue_num > 0) { + kbd->mouse_queue_num--; + // if (kbd->mouse_queue_num & 1) { + // kbd->key_waiting = 0x61; + // } else { + kbd->key_waiting = kbd->mouse_queue[kbd->mouse_queue_num]; + // } + epoch_kbdlog("epochkbd: reading %02X from the mouse queue at %i\n", kbd->key_waiting, kbd->mouse_queue_num); + kbd->want_irq = 1; + // if (kbd->mouse_queue_num == 0) + // kbd->mouse_ackwaiting = 1; + } + else if (key_queue_start != key_queue_end) { + kbd->key_waiting = key_queue[key_queue_start]; + epoch_kbdlog("epochkbd: 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; + + } } + + // if (kbd->clk_in > 0) { + // // epoch_kbdlog("Clock awaken\n"); + // kbd->clk_in--; + // kbd->clk_ff = 2 * 9; + // } else + // kbd->clk_ff = 0; } static void @@ -1481,7 +1525,7 @@ static void kbd_epoch_adddata(uint16_t val) { key_queue[key_queue_end] = val; - epoch_log("XTkbd: %02X added to key queue at %i\n", + epoch_kbdlog("epochkbd: %02X added to key queue at %i\n", val, key_queue_end); key_queue_end = (key_queue_end + 1) & 0x0f; } @@ -1493,35 +1537,68 @@ kbd_adddata_ex(uint16_t val) kbd_epoch_adddata_process(val, kbd_epoch_adddata); } +/* +I/O 61h W: +xxxx xxx1: ? (used by kbd interrupt in DOS) +xxxx xx1x: Beep +xxxx x1xx: Hold clock line low (used to reset kbd) +xxxx 1xxx: Enable kbd? +xxx1 xxxx: Send data from system to kbd +1xxx xxxx: Clear buffer? +*/ static void kbd_write(uint16_t port, uint8_t val, void *priv) { epochkbd_t *kbd = (epochkbd_t *) priv; uint8_t new_clock; - epoch_log("%04X:%04X epochkbd: Port %04X out: %02X\n", cs >> 4, cpu_state.pc, port, val); + epoch_kbdlog("%04X:%04X epochkbd: Port %02X out: %02X BX: %04x", cs >> 4, cpu_state.pc, port, val,BX); + epoch_kbdlog(" Clk: %x %x\n", kbd->blocked,kbd->clk_hold); switch (port) { + case 0x60: + if ((kbd->pb & 0x10) && (val & 0xf0) == 0xd0) { + kbd->mouse_enabled = 1; + epoch_kbdlog("epochkbd: Mouse is enabled.\n"); + } + break; case 0x61: /* Keyboard Control Register (aka Port B) */ - if (val & 0x08) { + kbd->pb = val; + + if ((val & 0x18) == 0x08) { new_clock = !(val & 0x04); - if (kbd->clock && new_clock) { + /* Trigger kbd reset after the clk line is reset to a high level */ + if (kbd->clk_hold && new_clock) { key_queue_start = key_queue_end = 0; kbd->want_irq = 0; kbd->blocked = 0; - kbd->reset_step = 0; - /* Specific 5556 keyboards send three bytes of identification code, - but this simply sends AAh that can pass the IPL and DOS K3.4 init. */ - kbd_epoch_adddata(0xaa); - } else if (!(kbd->pb & 0x08)) { - kbd->pa = 0; - kbd->blocked = 0; + kbd->kbd_reset_step = 0; + // kbd->clock = 0; + // kbd->clk_in = 0; + kbd->clk_hold = 0; + kbd->mouse_enabled = 0; + kbd->mouse_queue_num = 0; + // kbd->mouse_ackwaiting = 0; + epoch_kbdlog("epochkbd: Starting keyboard reset sequence.\n"); + } + // else if (!(kbd->pb & 0x08)) { + // kbd->pa = 0; + // kbd->blocked = 0; + // } + } else if ((val & 0x18) == 0x18) { + new_clock = !(val & 0x04); + if (kbd->clk_hold && new_clock) { + kbd->mouse_reset_step = 0; + epoch_kbdlog("epochkbd: Starting mouse reset sequence.\n"); } } - kbd->pb = val; if (kbd->pb & 0x08) - kbd->clock = !!(kbd->pb & 0x04); - ppi.pb = val; + kbd->clk_hold = !!(kbd->pb & 0x04); + // else + // kbd->mouse_ackwaiting = 0; + + // if (kbd->clk_hold) + // kbd->clock |= 0x04; timer_process(); @@ -1534,6 +1611,14 @@ kbd_write(uint16_t port, uint8_t val, void *priv) was_speaker_enable = 1; pit_devs[0].set_gate(pit_devs[0].data, TIMER_CTR_2, val & 2); + if (val & 0x80) { + /* clear buffer */ + kbd->pa = 0; + kbd->blocked = 0; + /* IRQ will be cleared by the software */ + // picintc(EPOCH_IRQ3_BIT); + } + break; default: @@ -1541,11 +1626,17 @@ kbd_write(uint16_t port, uint8_t val, void *priv) } } +/* +I/O 61h R +xxxx xx1x: Beep input? +xxxx x1xx: KB -CLK? +xxxx 1xxx: KB -DATA? +*/ static uint8_t kbd_read(uint16_t port, void *priv) { epochkbd_t *kbd = (epochkbd_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0; switch (port) { case 0x60: /* Keyboard Data Register (aka Port A) */ @@ -1553,36 +1644,67 @@ kbd_read(uint16_t port, void *priv) break; case 0x61: /* Keyboard Control Register (aka Port B) */ - /* Bit 3 and 2: Keyboard Data and Clk line ? */ - if (kbd->reset_step < 18) { + ret = kbd->pb & 0xf0;/* reset sense bit */ + ret |= 0x0c; /* reset sense bit */ + if (kbd->kbd_reset_step < 18) { ret &= 0xf3; - if (kbd->reset_step & 1) + if (!!(kbd->kbd_reset_step & 1)) ret |= 0x04; - switch (kbd->reset_step) { /* AAh (1010 1010) in serial data */ - case 3: - case 7: - case 11: - case 15: - ret |= 0x00; - break; - default: + switch (kbd->kbd_reset_step >> 1) { /* AAh (0 1010 1010) in serial data */ + case 0: + // case 1: + case 2: + // case 3: + case 4: + // case 5: + case 6: + // case 7: + case 8: + // case 9: ret |= 0x08; break; + default: + ret |= 0x00; + break; } - kbd->reset_step += 1; + epoch_kbdlog(" reset step: %d %x %x", kbd->kbd_reset_step, ret & 0x08, ret & 0x04); + epoch_kbdlog(" Clk: %x %x\n", kbd->blocked, kbd->clk_hold); + kbd->kbd_reset_step++; + /* Specific 5556 keyboards send three bytes of identification code, + but this simply sends AAh that can pass the IPL and DOS K3.4 init. */ + if (kbd->kbd_reset_step == 18) + // kbd->pa = 0xaa; + kbd_epoch_adddata(0xaa); + } else if (kbd->mouse_reset_step < 20) { + ret &= 0xf3; + if (!!(kbd->mouse_reset_step & 1)) + ret |= 0x04; + epoch_kbdlog(" reset step: %d %x %x\n", kbd->mouse_reset_step, ret & 0x08, ret & 0x04); + kbd->mouse_reset_step++; + } else { + // if (kbd->pb & 0x04) + // ret |= kbd->clk_hold & 0x04; + // if (kbd->clk_ff > 0 && (!(kbd->pb & 0x04))) { + // // kbd->clk_in -= 1;/* invert clk bit */ + // // epoch_kbdlog("ff%\n", kbd->clk_ff); + // if (kbd->clk_ff & 0x1) { + // ret ^= 0x04; + // } + // kbd->clk_ff--; + // } } /* Bit 1: Timer 2 (Speaker) out state */ - if (pit_devs[0].get_outlevel(pit_devs[0].data, TIMER_CTR_2) && speaker_enable) - ret &= 0xfd;/* 1111 1101 */ + if (pit_devs[0].get_outlevel(pit_devs[0].data, TIMER_CTR_2) && speaker_enable) + ret &= 0xfd; /* 1111 1101 */ else ret |= 0x02; + + // ret |= kbd->clock; break; - default: break; } - // epoch_log("%04X:%04X epochkbd: Port %04X in : %02X BX:%04x\n", cs >> 4, cpu_state.pc, port, ret, BX); - + epoch_kbdlog("%04X:%04X epochkbd: Port %02X in : %02X pb: %02x CX: %04x\n", cs >> 4, cpu_state.pc, port, ret, kbd->pb, CX); return ret; } @@ -1595,11 +1717,22 @@ kbd_reset(void *priv) kbd->blocked = 0; kbd->pa = 0x00; kbd->pb = 0x00; + // kbd->clock = 0; + // kbd->clk_hold = 0; + // kbd->clk_in = 0; + // kbd->clk_ff = 0; + kbd->kbd_reset_step = 0xff; + kbd->mouse_reset_step = 0xff; keyboard_scan = 1; key_queue_start = 0; key_queue_end = 0; + + kbd->mouse_enabled = 0; + kbd->mouse_queue_num = 0; + // kbd->mouse_ackwaiting = 0; + kbd_epoch_adddata(0xaa); } static void * @@ -1614,7 +1747,7 @@ kbd_init(const device_t *info) keyboard_send = kbd_adddata_ex; kbd_reset(kbd); - key_queue_start = key_queue_end = 0; + //key_queue_start = key_queue_end = 0; timer_add(&kbd->send_delay_timer, kbd_epoch_poll, kbd, 1); @@ -1657,6 +1790,91 @@ static const device_t kbc_epoch_device = { .config = NULL }; +/* +The IBM 5550 DOS K3.44 comes with a mouse driver +for the M1 and P1 keyboards that have a built-in mouse adapter. +The mouse adapter for the expansion slot was also available, +but it may require the bundled driver. (not confirmed) + +IBM 5550 DOS K3.4 Mouse Driver (Int 0Bh and 33h) +61h <- 1st kbd indata +[si+4Ch] status <- 2nd kbd indata +1xxx xxxx negative dX +x1xx xxxx bit 9 of dX +xx1x xxxx negative dY +xxx1 xxxx bit 9 of dY +xxxx x1xx cursor moved +xxxx xx1x right button +xxxx xxx1 left button +[si+4Dh] previous button status <- [si+4Ch] +[si+4Eh] dX <- 3rd kbd indata +[si+50h] dY <- 4th kbd indata +*/ +static int +epoch_mouse_poll(void *priv) +{ + epochkbd_t *kbd = (epochkbd_t *) priv; + int dat = mouse_get_buttons_ex(); + int dx, dy; + + if (!kbd->mouse_enabled) + return 0; + + // if (kbd->blocked && !(kbd->pb & 0x10)) + // return 0; + + // if (kbd->blocked && !(kbd->pb & 0x10)) + // return 0; + + // kbd->clk_in = 2; + + // if (!(kbd->pb & 0x80)) + // return 0; + + if (kbd->mouse_queue_num > 0) + return 0; + + if (kbd->pb & 0x10) + return 0; + + dat &= 0x03; + if (!mouse_moved()) { + // kbd_adddata_ex(0x61); + // kbd_adddata_ex(dat); + kbd->mouse_queue[1] = 0x61; + kbd->mouse_queue[0] = dat; + kbd->mouse_queue_num = 2; + } else { + dat |= 0x04; + mouse_subtract_x(&dx, NULL, -512, 511, 0); + mouse_clear_x(); + if (dx < 0) + dat |= 0x20; + if (dx & 0x100) + dat |= 0x10; + mouse_subtract_y(&dy, NULL, -512, 511, 0, 0); + mouse_clear_y(); + if (dy < 0) + dat |= 0x80; + if (dy & 0x100) + dat |= 0x40; + // dy = 0; + // kbd_adddata_ex(0x61); + // keyboard_send(dat); + // kbd_adddata_ex(0x61); + // keyboard_send(dx & 0xff); + // kbd_adddata_ex(0x61); + // keyboard_send(dy & 0xff); + epoch_log("Mouse moved %x %x %x\n", dat, dx, dy); + kbd->mouse_queue[3] = 0x61; + kbd->mouse_queue[2] = dat; + kbd->mouse_queue[1] = dx & 0xff; + kbd->mouse_queue[0] = dy & 0xff; + kbd->mouse_queue_num = 4; + } + return 0; +} + static void epoch_nvr_time_set(uint8_t *regs, struct tm *tm) { @@ -1963,7 +2181,7 @@ epoch_init(UNUSED(const device_t *info)) io_sethandler(0x44, 0x0001, epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); - io_sethandler(0xA0, 0x0005, + io_sethandler(0xA0, 0x0006, epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); io_sethandler(0x310, 0x0008, epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); @@ -2051,7 +2269,7 @@ epoch_force_redraw(void *priv) } static const device_t epoch_device = { - .name = "IBM 5550 Video Controller (Epoch)", + .name = "IBM 5550 (Epoch) Video Controller", .internal_name = "ibm5550vid", .flags = DEVICE_ISA, .local = 0, @@ -2115,7 +2333,7 @@ machine_xt_ibm5550_init(const machine_t *model) device_add(&fdc_xt_5550_device); - device_add(&kbc_epoch_device); + epochkbd_t *kbc = device_add(&kbc_epoch_device); pic_init(); dma_init(); @@ -2128,5 +2346,12 @@ machine_xt_ibm5550_init(const machine_t *model) serial_t *uart = device_add(&ns8250_device); serial_setup(uart, 0x3f8, 1);/* Use IRQ 1 */ + if (mouse_type == MOUSE_TYPE_INTERNAL) { + /* Tell mouse driver about our internal mouse. */ + mouse_reset(); + mouse_set_buttons(2); + mouse_set_poll(epoch_mouse_poll, kbc); + } + return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 66d119520..85b09676e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2710,7 +2710,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PC, - .flags = MACHINE_VIDEO_FIXED | MACHINE_KEYBOARD, + .flags = MACHINE_VIDEO_FIXED | MACHINE_FDC | MACHINE_KEYBOARD | MACHINE_MOUSE, .ram = { .min = 256, .max = 640, From 640d94441dbc2510f3e60ed3b1a49b00701094a1 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:50:31 +0900 Subject: [PATCH 09/66] cleanup (m_xt_ibm5550.c) --- src/machine/m_xt_ibm5550.c | 84 ++------------------------------------ 1 file changed, 3 insertions(+), 81 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 68dd15a39..feda36af9 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -156,12 +156,12 @@ enum epoch_nvr_ADDR { }; #ifndef RELEASE_BUILD -#define ENABLE_EPOCH_LOG 1 +// #define ENABLE_EPOCH_LOG 1 #endif #ifdef ENABLE_EPOCH_LOG // #define ENABLE_EPOCH_DEBUGIO 1 -#define ENABLE_EPOCH_DEBUGKBD 1 +// #define ENABLE_EPOCH_DEBUGKBD 1 int epoch_do_log = ENABLE_EPOCH_LOG; static void @@ -1425,14 +1425,10 @@ typedef struct epochkbd_t { uint8_t pa; uint8_t pb; - // uint8_t clock; uint8_t clk_hold; - // uint8_t clk_in; - // uint8_t clk_ff; int mouse_enabled; uint8_t mouse_queue[4]; int mouse_queue_num; - // int mouse_ackwaiting; uint8_t key_waiting; uint8_t kbd_reset_step; uint8_t mouse_reset_step; @@ -1451,8 +1447,6 @@ kbd_epoch_poll(void *priv) timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC); - // if (kbd->clock & 0x04) - // return; if (kbd->pb & 0x04) /* controller is sending something to keyboard */ return; @@ -1469,18 +1463,11 @@ kbd_epoch_poll(void *priv) } if (!kbd->blocked) { - // if (kbd->mouse_queue_num > 0 && kbd->mouse_ackwaiting == 0) { if (kbd->mouse_queue_num > 0) { kbd->mouse_queue_num--; - // if (kbd->mouse_queue_num & 1) { - // kbd->key_waiting = 0x61; - // } else { kbd->key_waiting = kbd->mouse_queue[kbd->mouse_queue_num]; - // } epoch_kbdlog("epochkbd: reading %02X from the mouse queue at %i\n", kbd->key_waiting, kbd->mouse_queue_num); kbd->want_irq = 1; - // if (kbd->mouse_queue_num == 0) - // kbd->mouse_ackwaiting = 1; } else if (key_queue_start != key_queue_end) { kbd->key_waiting = key_queue[key_queue_start]; @@ -1491,13 +1478,6 @@ kbd_epoch_poll(void *priv) } } - - // if (kbd->clk_in > 0) { - // // epoch_kbdlog("Clock awaken\n"); - // kbd->clk_in--; - // kbd->clk_ff = 2 * 9; - // } else - // kbd->clk_ff = 0; } static void @@ -1572,18 +1552,11 @@ kbd_write(uint16_t port, uint8_t val, void *priv) kbd->want_irq = 0; kbd->blocked = 0; kbd->kbd_reset_step = 0; - // kbd->clock = 0; - // kbd->clk_in = 0; kbd->clk_hold = 0; kbd->mouse_enabled = 0; kbd->mouse_queue_num = 0; - // kbd->mouse_ackwaiting = 0; epoch_kbdlog("epochkbd: Starting keyboard reset sequence.\n"); } - // else if (!(kbd->pb & 0x08)) { - // kbd->pa = 0; - // kbd->blocked = 0; - // } } else if ((val & 0x18) == 0x18) { new_clock = !(val & 0x04); if (kbd->clk_hold && new_clock) { @@ -1594,14 +1567,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv) if (kbd->pb & 0x08) kbd->clk_hold = !!(kbd->pb & 0x04); - // else - // kbd->mouse_ackwaiting = 0; - - // if (kbd->clk_hold) - // kbd->clock |= 0x04; timer_process(); - speaker_update(); speaker_gated = val & 2; @@ -1620,7 +1587,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv) } break; - default: break; } @@ -1652,15 +1618,10 @@ kbd_read(uint16_t port, void *priv) ret |= 0x04; switch (kbd->kbd_reset_step >> 1) { /* AAh (0 1010 1010) in serial data */ case 0: - // case 1: case 2: - // case 3: case 4: - // case 5: case 6: - // case 7: case 8: - // case 9: ret |= 0x08; break; default: @@ -1681,25 +1642,14 @@ kbd_read(uint16_t port, void *priv) ret |= 0x04; epoch_kbdlog(" reset step: %d %x %x\n", kbd->mouse_reset_step, ret & 0x08, ret & 0x04); kbd->mouse_reset_step++; - } else { - // if (kbd->pb & 0x04) - // ret |= kbd->clk_hold & 0x04; - // if (kbd->clk_ff > 0 && (!(kbd->pb & 0x04))) { - // // kbd->clk_in -= 1;/* invert clk bit */ - // // epoch_kbdlog("ff%\n", kbd->clk_ff); - // if (kbd->clk_ff & 0x1) { - // ret ^= 0x04; - // } - // kbd->clk_ff--; - // } } + /* Bit 1: Timer 2 (Speaker) out state */ if (pit_devs[0].get_outlevel(pit_devs[0].data, TIMER_CTR_2) && speaker_enable) ret &= 0xfd; /* 1111 1101 */ else ret |= 0x02; - // ret |= kbd->clock; break; default: break; @@ -1717,10 +1667,6 @@ kbd_reset(void *priv) kbd->blocked = 0; kbd->pa = 0x00; kbd->pb = 0x00; - // kbd->clock = 0; - // kbd->clk_hold = 0; - // kbd->clk_in = 0; - // kbd->clk_ff = 0; kbd->kbd_reset_step = 0xff; kbd->mouse_reset_step = 0xff; @@ -1731,7 +1677,6 @@ kbd_reset(void *priv) kbd->mouse_enabled = 0; kbd->mouse_queue_num = 0; - // kbd->mouse_ackwaiting = 0; kbd_epoch_adddata(0xaa); } @@ -1747,8 +1692,6 @@ kbd_init(const device_t *info) keyboard_send = kbd_adddata_ex; kbd_reset(kbd); - //key_queue_start = key_queue_end = 0; - timer_add(&kbd->send_delay_timer, kbd_epoch_poll, kbd, 1); keyboard_set_table(scancode_set8a); @@ -1767,7 +1710,6 @@ kbd_close(void *priv) /* Disable scanning. */ keyboard_scan = 0; - keyboard_send = NULL; io_removehandler(0x0060, 2, @@ -1820,17 +1762,6 @@ epoch_mouse_poll(void *priv) if (!kbd->mouse_enabled) return 0; - // if (kbd->blocked && !(kbd->pb & 0x10)) - // return 0; - - // if (kbd->blocked && !(kbd->pb & 0x10)) - // return 0; - - // kbd->clk_in = 2; - - // if (!(kbd->pb & 0x80)) - // return 0; - if (kbd->mouse_queue_num > 0) return 0; @@ -1839,8 +1770,6 @@ epoch_mouse_poll(void *priv) dat &= 0x03; if (!mouse_moved()) { - // kbd_adddata_ex(0x61); - // kbd_adddata_ex(dat); kbd->mouse_queue[1] = 0x61; kbd->mouse_queue[0] = dat; kbd->mouse_queue_num = 2; @@ -1858,13 +1787,6 @@ epoch_mouse_poll(void *priv) dat |= 0x80; if (dy & 0x100) dat |= 0x40; - // dy = 0; - // kbd_adddata_ex(0x61); - // keyboard_send(dat); - // kbd_adddata_ex(0x61); - // keyboard_send(dx & 0xff); - // kbd_adddata_ex(0x61); - // keyboard_send(dy & 0xff); epoch_log("Mouse moved %x %x %x\n", dat, dx, dy); kbd->mouse_queue[3] = 0x61; kbd->mouse_queue[2] = dat; From c508054cc3ee452308c29299572ab30d68d50f2b Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 15 Feb 2026 14:02:53 +0900 Subject: [PATCH 10/66] formatting (m_xt_ibm5550.c) --- src/machine/m_xt_ibm5550.c | 50 ++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index feda36af9..fed353344 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -1426,12 +1426,12 @@ typedef struct epochkbd_t { uint8_t pa; uint8_t pb; uint8_t clk_hold; - int mouse_enabled; - uint8_t mouse_queue[4]; - int mouse_queue_num; uint8_t key_waiting; uint8_t kbd_reset_step; uint8_t mouse_reset_step; + int mouse_enabled; + int mouse_queue_num; + uint8_t mouse_queue[4]; pc_timer_t send_delay_timer; } epochkbd_t; @@ -1456,8 +1456,7 @@ kbd_epoch_poll(void *priv) if (kbd->want_irq) { kbd->want_irq = 0; kbd->pa = kbd->key_waiting; - // kbd->clock |= 0x04; - kbd->blocked = 1; + kbd->blocked = 1; picint(EPOCH_IRQ3_BIT); epoch_kbdlog("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n"); } @@ -1465,17 +1464,15 @@ kbd_epoch_poll(void *priv) if (!kbd->blocked) { if (kbd->mouse_queue_num > 0) { kbd->mouse_queue_num--; - kbd->key_waiting = kbd->mouse_queue[kbd->mouse_queue_num]; + kbd->key_waiting = kbd->mouse_queue[kbd->mouse_queue_num]; epoch_kbdlog("epochkbd: reading %02X from the mouse queue at %i\n", kbd->key_waiting, kbd->mouse_queue_num); kbd->want_irq = 1; - } - else if (key_queue_start != key_queue_end) { + } else if (key_queue_start != key_queue_end) { kbd->key_waiting = key_queue[key_queue_start]; epoch_kbdlog("epochkbd: 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; - } } } @@ -1530,13 +1527,13 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { epochkbd_t *kbd = (epochkbd_t *) priv; - uint8_t new_clock; - epoch_kbdlog("%04X:%04X epochkbd: Port %02X out: %02X BX: %04x", cs >> 4, cpu_state.pc, port, val,BX); - epoch_kbdlog(" Clk: %x %x\n", kbd->blocked,kbd->clk_hold); + uint8_t new_clock; + epoch_kbdlog("%04X:%04X epochkbd: Port %02X out: %02X BX: %04x", cs >> 4, cpu_state.pc, port, val, BX); + epoch_kbdlog(" Clk: %x %x\n", kbd->blocked, kbd->clk_hold); switch (port) { - case 0x60: - if ((kbd->pb & 0x10) && (val & 0xf0) == 0xd0) { + case 0x60: /* Diagnostic Output */ + if ((kbd->pb & 0x10) && ((val & 0xf0) == 0xd0)) { kbd->mouse_enabled = 1; epoch_kbdlog("epochkbd: Mouse is enabled.\n"); } @@ -1551,7 +1548,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) key_queue_start = key_queue_end = 0; kbd->want_irq = 0; kbd->blocked = 0; - kbd->kbd_reset_step = 0; + kbd->kbd_reset_step = 0; kbd->clk_hold = 0; kbd->mouse_enabled = 0; kbd->mouse_queue_num = 0; @@ -1602,7 +1599,7 @@ static uint8_t kbd_read(uint16_t port, void *priv) { epochkbd_t *kbd = (epochkbd_t *) priv; - uint8_t ret = 0; + uint8_t ret = 0; switch (port) { case 0x60: /* Keyboard Data Register (aka Port A) */ @@ -1610,18 +1607,18 @@ kbd_read(uint16_t port, void *priv) break; case 0x61: /* Keyboard Control Register (aka Port B) */ - ret = kbd->pb & 0xf0;/* reset sense bit */ - ret |= 0x0c; /* reset sense bit */ + ret = kbd->pb & 0xf0; /* reset sense bit */ + ret |= 0x0c; /* reset sense bit */ if (kbd->kbd_reset_step < 18) { ret &= 0xf3; if (!!(kbd->kbd_reset_step & 1)) ret |= 0x04; switch (kbd->kbd_reset_step >> 1) { /* AAh (0 1010 1010) in serial data */ case 0: - case 2: - case 4: - case 6: - case 8: + case 2: + case 4: + case 6: + case 8: ret |= 0x08; break; default: @@ -1631,10 +1628,9 @@ kbd_read(uint16_t port, void *priv) epoch_kbdlog(" reset step: %d %x %x", kbd->kbd_reset_step, ret & 0x08, ret & 0x04); epoch_kbdlog(" Clk: %x %x\n", kbd->blocked, kbd->clk_hold); kbd->kbd_reset_step++; - /* Specific 5556 keyboards send three bytes of identification code, - but this simply sends AAh that can pass the IPL and DOS K3.4 init. */ + /* Specific 5556 keyboards send three bytes of identification code, + but this simply sends AAh that can pass the IPL and DOS K3.4 init. */ if (kbd->kbd_reset_step == 18) - // kbd->pa = 0xaa; kbd_epoch_adddata(0xaa); } else if (kbd->mouse_reset_step < 20) { ret &= 0xf3; @@ -1643,13 +1639,13 @@ kbd_read(uint16_t port, void *priv) epoch_kbdlog(" reset step: %d %x %x\n", kbd->mouse_reset_step, ret & 0x08, ret & 0x04); kbd->mouse_reset_step++; } - + /* Bit 1: Timer 2 (Speaker) out state */ if (pit_devs[0].get_outlevel(pit_devs[0].data, TIMER_CTR_2) && speaker_enable) ret &= 0xfd; /* 1111 1101 */ else ret |= 0x02; - + break; default: break; From eb20365cec66491344586d905ecb5aa7ebb6bae6 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:26:59 -0600 Subject: [PATCH 11/66] Cirrus: Give the Commodore SL386SX/25 its own 5402 device and make the original onboard device not load a VBIOS. Tandy 1000 RSX now loads the correct VBIOS from the system ROM. --- src/include/86box/video.h | 1 + src/machine/m_at_386sx.c | 2 +- src/machine/machine_table.c | 2 +- src/video/vid_cl54xx.c | 16 ++++++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index b7f86ac18..32e1ace03 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -375,6 +375,7 @@ extern const device_t gd5401_isa_device; extern const device_t gd5401_onboard_device; extern const device_t gd5402_isa_device; extern const device_t gd5402_onboard_device; +extern const device_t gd5402_onboard_commodore_device; extern const device_t gd5420_isa_device; extern const device_t gd5420_onboard_device; extern const device_t gd5422_isa_device; diff --git a/src/machine/m_at_386sx.c b/src/machine/m_at_386sx.c index 6b5c4414c..d996a14bc 100644 --- a/src/machine/m_at_386sx.c +++ b/src/machine/m_at_386sx.c @@ -586,7 +586,7 @@ machine_at_cmdsl386sx25_init(const machine_t *model) return ret; if (gfxcard[0] == VID_INTERNAL) - device_add(&gd5402_onboard_device); + device_add(&gd5402_onboard_commodore_device); machine_at_common_init_ex(model, 2); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 66d119520..e05477c96 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5905,7 +5905,7 @@ const machine_t machines[] = { .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &gd5402_onboard_device, + .vid_device = &gd5402_onboard_commodore_device, .snd_device = NULL, .net_device = NULL }, diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 0a3060467..007d47db7 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4284,6 +4284,8 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5402: if (info->local & 0x200) + romfn = NULL; + else if (info->local & 0x100) romfn = BIOS_GD5402_ONBOARD_PATH; else romfn = BIOS_GD5402_PATH; @@ -5032,6 +5034,20 @@ const device_t gd5402_onboard_device = { .config = NULL, }; +const device_t gd5402_onboard_commodore_device = { + .name = "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2) (On-Board) (Commodore)", + .internal_name = "cl_gd5402_onboard_commodore", + .flags = DEVICE_ISA16, + .local = CIRRUS_ID_CLGD5402 | 0x100, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + .available = NULL, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = NULL, +}; + const device_t gd5420_isa_device = { .name = "Cirrus Logic GD5420 (ISA)", .internal_name = "cl_gd5420_isa", From e6f6b7da21f7a9e12b1b501f89c62fd94124b19c Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:31:06 -0600 Subject: [PATCH 12/66] Cirrus: Give both the ISA and VLB CL-GD5428s the onboard flag --- src/video/vid_cl54xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 007d47db7..2e2224103 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -5264,7 +5264,7 @@ const device_t gd5428_onboard_device = { .name = "Cirrus Logic GD5428 (ISA) (On-Board)", .internal_name = "cl_gd5428_onboard", .flags = DEVICE_ISA16, - .local = CIRRUS_ID_CLGD5428, + .local = CIRRUS_ID_CLGD5428 | 0x200, .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, @@ -5278,7 +5278,7 @@ const device_t gd5428_vlb_onboard_device = { .name = "Cirrus Logic GD5428 (VLB) (On-Board)", .internal_name = "cl_gd5428_vlb_onboard", .flags = DEVICE_VLB, - .local = CIRRUS_ID_CLGD5428, + .local = CIRRUS_ID_CLGD5428 | 0x200, .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, From b12782ace9197d0a2cb45addd9df563148615eac Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:35:15 -0600 Subject: [PATCH 13/66] Cirrus: Add code to load the 5428 VBIOS from the system ROM for the Acer A1G, HP Vectra 486VL and Siemens-Nixdorf D824 --- src/video/vid_cl54xx.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 2e2224103..71ded9010 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -53,6 +53,9 @@ #define BIOS_GD5428_DIAMOND_B1_VLB_PATH "roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin" #define BIOS_GD5428_ISA_PATH "roms/video/cirruslogic/5428.bin" #define BIOS_GD5428_MCA_PATH "roms/video/cirruslogic/SVGA141.ROM" +#define BIOS_GD5428_ONBOARD_ACER_PATH "roms/machines/acera1g/4alo001.bin" +#define BIOS_GD5428_ONBOARD_HP_PATH "roms/machines/vect486vl/aa0500.ami" +#define BIOS_GD5428_ONBOARD_SNI_PATH "roms/machines/d824/fts-biosupdated824noflashbiosepromv320-320334-160.bin" #define BIOS_GD5428_PATH "roms/video/cirruslogic/vlbusjapan.BIN" #define BIOS_GD5428_BOCA_ISA_PATH_1 "roms/video/cirruslogic/boca_gd5428_1.30b_1.bin" #define BIOS_GD5428_BOCA_ISA_PATH_2 "roms/video/cirruslogic/boca_gd5428_1.30b_2.bin" @@ -4328,7 +4331,14 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5428: if (info->local & 0x200) { - romfn = NULL; + if (machines[machine].init == machine_at_vect486vl_init) + romfn = BIOS_GD5428_ONBOARD_HP_PATH; + else if (machines[machine].init == machine_at_d824_init) + romfn = BIOS_GD5428_ONBOARD_SNI_PATH; + else if (machines[machine].init == machine_at_acera1g_init) + romfn = BIOS_GD5428_ONBOARD_ACER_PATH; + else + romfn = NULL; gd54xx->has_bios = 0; } else if (info->local & 0x100) if (gd54xx->vlb) From 9831ded525a7bea66baf02d4c63744b665bac1b4 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:41:52 -0600 Subject: [PATCH 14/66] OPTi 499: ROMCS# enable bits in register 2Dh override 22h bit 5 ROMCS# disable, fixes Alaris Cobalt LPX VBIOS --- src/chipset/opti499.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c index 132754ac7..d9fc61907 100644 --- a/src/chipset/opti499.c +++ b/src/chipset/opti499.c @@ -84,7 +84,10 @@ opti499_recalc(opti499_t *dev) base = 0xd0000 + (i << 14); if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && (dev->regs[0x23] & (1 << i))) { - shflags = MEM_READ_INTERNAL; + if (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) + shflags = MEM_READ_EXTANY; + else + shflags = MEM_READ_INTERNAL; shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; } else { if (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) From 4ea89bb216755b65595f635eecf55d386937f0f9 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:58:03 -0600 Subject: [PATCH 15/66] Intel Monsoon: Give the machine a version of the Phoenix jumper device, fixes onboard video --- src/device/phoenix_486_jumper.c | 31 ++++++++++++++++++++++++++++++- src/include/86box/chipset.h | 1 + src/machine/m_at_socket2.c | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index ed4349082..905af1149 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -52,11 +52,19 @@ Bit 0 = ???? */ +/* + Intel Monsoon bit meanings: + Bit 4 = Onboard video: 1 = disabled, 0 = enabled + Bit 3 = CMOS Setup enable +*/ + typedef struct phoenix_486_jumper_t { uint8_t type; uint8_t jumper; } phoenix_486_jumper_t; +#define ENABLE_PHOENIX_486_JUMPER_LOG 1 + #ifdef ENABLE_PHOENIX_486_JUMPER_LOG int phoenix_486_jumper_do_log = ENABLE_PHOENIX_486_JUMPER_LOG; @@ -84,6 +92,8 @@ phoenix_486_jumper_write(UNUSED(uint16_t addr), uint8_t val, void *priv) dev->jumper = val & 0xbf; else if (dev->type == 2) /* PB600 */ dev->jumper = ((val & 0xbf) | 0x02); + else if (dev->type == 3) /* Intel Monsoon */ + dev->jumper = val | 0x08; else dev->jumper = val; } @@ -106,7 +116,11 @@ phoenix_486_jumper_reset(void *priv) dev->jumper = 0x00; else if (dev->type == 2) /* PB600 */ dev->jumper = 0x02; - else { + else if (dev->type == 3) { /* Intel Monsoon */ + dev->jumper = 0xef; + if (gfxcard[0] != 0x01) + dev->jumper |= 0x10; + } else { dev->jumper = 0x9f; if (gfxcard[0] != 0x01) dev->jumper |= 0x40; @@ -176,3 +190,18 @@ const device_t phoenix_486_jumper_pci_pb600_device = { .force_redraw = NULL, .config = NULL }; + +const device_t phoenix_486_jumper_monsoon_device = { + .name = "Phoenix 486 Jumper Readout (Monsoon)", + .internal_name = "phoenix_486_jumper_monsoon", + .flags = 0, + .local = 3, + .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 +}; + diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 4ded831bd..6fa7881ca 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -234,6 +234,7 @@ extern const device_t nec_mate_unk_device; extern const device_t phoenix_486_jumper_device; extern const device_t phoenix_486_jumper_pci_device; extern const device_t phoenix_486_jumper_pci_pb600_device; +extern const device_t phoenix_486_jumper_monsoon_device; extern const device_t ast_readout_device; extern const device_t ast_nvr_device; diff --git a/src/machine/m_at_socket2.c b/src/machine/m_at_socket2.c index 5c4a19f17..5b871d298 100644 --- a/src/machine/m_at_socket2.c +++ b/src/machine/m_at_socket2.c @@ -389,6 +389,7 @@ machine_at_monsoon_init(const machine_t *model) device_add_params(&fdc37c6xx_device, (void *) (FDC37C651 | FDC37C6XX_IDE_PRI)); device_add(&intel_flash_bxt_device); + device_add(&phoenix_486_jumper_monsoon_device); if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); From 1c67127d1d13e55bb709935a4850b92f8f7b77cf Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:57:23 +0900 Subject: [PATCH 16/66] ps55da2: avoid resizing when video output is disabled --- src/video/vid_ps55da2.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 3df73f92c..a1d7fe25f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2352,12 +2352,8 @@ da2_recalctimings(da2_t *da2) da2->render = da2_render_blank; /* determine display mode */ // if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) - /* if output disabled or VGA passthrough */ - if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { - da2->render = da2_render_blank; - // return; /* 16 color graphics mode */ - } else if (!(da2->ioctl[LS_MODE] & 0x01)) { + if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { @@ -2383,6 +2379,9 @@ da2_recalctimings(da2_t *da2) da2->hdisp *= 13; da2->char_width = 13; } + /* if output disabled or VGA passthrough */ + if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) + da2->render = da2_render_blank; if (da2->vblankstart < da2->dispend) da2->dispend = da2->vblankstart; From 5d3c3baaa81a77d8ab4285f27f5b45485e48e085 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:11:34 -0600 Subject: [PATCH 17/66] Intel Monsoon: Improve jumper implementation, BIOS password is no longer disabled --- src/device/phoenix_486_jumper.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index 905af1149..b4300981e 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -54,8 +54,10 @@ /* Intel Monsoon bit meanings: + Bit 5 = Password enable Bit 4 = Onboard video: 1 = disabled, 0 = enabled Bit 3 = CMOS Setup enable + Bit 2 = CMOS clear: 1 = normal, 0 = clear CMOS */ typedef struct phoenix_486_jumper_t { @@ -63,8 +65,6 @@ typedef struct phoenix_486_jumper_t { uint8_t jumper; } phoenix_486_jumper_t; -#define ENABLE_PHOENIX_486_JUMPER_LOG 1 - #ifdef ENABLE_PHOENIX_486_JUMPER_LOG int phoenix_486_jumper_do_log = ENABLE_PHOENIX_486_JUMPER_LOG; @@ -92,9 +92,11 @@ phoenix_486_jumper_write(UNUSED(uint16_t addr), uint8_t val, void *priv) dev->jumper = val & 0xbf; else if (dev->type == 2) /* PB600 */ dev->jumper = ((val & 0xbf) | 0x02); - else if (dev->type == 3) /* Intel Monsoon */ - dev->jumper = val | 0x08; - else + else if (dev->type == 3) { /* Intel Monsoon */ + dev->jumper = ((val & 0xef) | 0x2c); + if (gfxcard[0] != 0x01) + dev->jumper |= 0x10; + } else dev->jumper = val; } @@ -117,7 +119,7 @@ phoenix_486_jumper_reset(void *priv) else if (dev->type == 2) /* PB600 */ dev->jumper = 0x02; else if (dev->type == 3) { /* Intel Monsoon */ - dev->jumper = 0xef; + dev->jumper = 0x2c; if (gfxcard[0] != 0x01) dev->jumper |= 0x10; } else { From 017ce1f7731636507d1fed77f924d4a0ce67e446 Mon Sep 17 00:00:00 2001 From: Paradyx0392 Date: Mon, 16 Feb 2026 10:24:48 +0800 Subject: [PATCH 18/66] Update nl-NL.po --- src/qt/languages/nl-NL.po | 68 +++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index e48409dcd..fced0fe84 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -55,10 +55,10 @@ msgid "&Resizeable window" msgstr "&Venster met aanpasbare grootte" msgid "R&emember size && position" -msgstr "&Onthoud grootte && positie" +msgstr "&Onthoud grootte en positie" msgid "Remember size && position" -msgstr "Onthoud grootte && positie" +msgstr "Onthoud grootte en positie" msgid "Re&nderer" msgstr "Re&nderer" @@ -73,7 +73,7 @@ msgid "&VNC" msgstr "&VNC" msgid "Specify &dimensions…" -msgstr "Afmetingen opgeven…" +msgstr "&Afmetingen opgeven…" msgid "Force &4:3 display ratio" msgstr "Forceer &4:3 beeldverhouding" @@ -154,7 +154,7 @@ msgid "VGA screen &type" msgstr "VGA-scherm &type" msgid "RGB &Color" -msgstr "RGB &Kleur" +msgstr "RGB &kleur" msgid "RGB (no brown)" msgstr "RGN (geen bruin)" @@ -421,7 +421,7 @@ msgid "IBM 8514/A Graphics" msgstr "IBM 8514/A-graphics" msgid "XGA Graphics" -msgstr "XGA Graphics" +msgstr "XGA-graphics" msgid "IBM PS/55 Display Adapter Graphics" msgstr "IBM PS/55 Display Adapter Graphics" @@ -469,13 +469,13 @@ msgid "Sound card #4:" msgstr "Geluidskaart #4:" msgid "MIDI Out Device:" -msgstr "MIDI Uitvoerapparaat:" +msgstr "MIDI uitvoerapparaat:" msgid "MIDI In Device:" -msgstr "MIDI Invoerapparaat:" +msgstr "MIDI invoerapparaat:" msgid "MIDI Out:" -msgstr "Midi Uit:" +msgstr "Midi uit:" msgid "Standalone MPU-401" msgstr "Standalone MPU-401" @@ -580,7 +580,7 @@ msgid "Hard disks:" msgstr "Harde schijven:" msgid "Firmware Version" -msgstr "Firmware Versie" +msgstr "Firmware versie" msgid "&New…" msgstr "&Nieuw…" @@ -673,10 +673,10 @@ msgid "Generic ISA ROM Board" msgstr "Generieke ISA ROM-kaart" msgid "Generic Dual ISA ROM Board" -msgstr "Generieke Dubbele ISA ROM-kaart" +msgstr "Generieke dubbele ISA ROM-kaart" msgid "Generic Quad ISA ROM Board" -msgstr "Generieke Viervoudige ISA ROM-kaart" +msgstr "Generieke viervoudige ISA ROM-kaart" msgid "ISABugger device" msgstr "ISABugger-apparaat" @@ -1006,7 +1006,7 @@ msgid "About %1" msgstr "Over %1" msgid "An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Een emulator van oude computers\n\nAuteurs: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nMet eerdere bijdragen van Sarah Walker, leilei, JohnElliott, greatpsycho en anderen.\n\nUitgebracht onder de GNU General Public License versie 2 of later. Zie LICENSE voor meer informatie." +msgstr "Een emulator van oude computers\n\nAuteurs: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, en anderen.\n\nMet eerdere bijdragen van Sarah Walker, leilei, JohnElliott, greatpsycho en anderen.\n\nUitgebracht onder de GNU General Public License versie 2 of later. Zie LICENSE voor meer informatie." msgid "Hardware not available" msgstr "Hardware niet beschikbaar" @@ -1312,7 +1312,7 @@ msgid "An error has occurred while checking for updates: %1" msgstr "Er is een fout opgetreden tijdens het controleren op updates: %1" msgid "An update to 86Box is available!" -msgstr " Een update van 86Box is beschikbaar!" +msgstr "Een update van 86Box is beschikbaar!" msgid "Warning" msgstr "Waarschuwing" @@ -2065,7 +2065,7 @@ msgid "Dynamic Sample Loading" msgstr "Dynamische sample-lading" msgid "Reverb Output Gain" -msgstr "Reverbuitgang Versterking" +msgstr "Reverbuitgang versterking" msgid "Reversed stereo" msgstr "Omgekeerde stereo" @@ -2362,7 +2362,7 @@ msgid "Always at selected speed" msgstr "Altijd op geselecteerde snelheid" msgid "BIOS setting + Hotkeys (off during POST)" -msgstr "BIOS-instelling + Sneltoetsen (niet actief tijdens POST)" +msgstr "BIOS-instelling + sneltoetsen (niet actief tijdens POST)" msgid "64 KB starting from F0000" msgstr "64 KB vanaf F0000" @@ -2401,16 +2401,16 @@ msgid "Wheel" msgstr "Wiel" msgid "Five + Wheel" -msgstr "Vijf + Wiel" +msgstr "Vijf + wiel" msgid "Five + 2 Wheels" -msgstr "Vijf + 2 Wielen" +msgstr "Vijf + 2 wielen" msgid "A3 - SMT2 Serial / SMT3(R)V" -msgstr "A3 - SMT2 Serieel / SMT3(R)V" +msgstr "A3 - SMT2 serieel / SMT3(R)V" msgid "Q1 - SMT3(R) Serial" -msgstr "Q1 - SMT3(R) Serieel" +msgstr "Q1 - SMT3(R) serieel" msgid "8 KB" msgstr "8 KB" @@ -2482,7 +2482,7 @@ msgid "Green Monochrome" msgstr "Groen monochroom" msgid "Amber Monochrome" -msgstr "Amber Monochroom" +msgstr "Amber monochroom" msgid "Gray Monochrome" msgstr "Grijs monochroom" @@ -2551,7 +2551,7 @@ msgid "Color" msgstr "Kleur" msgid "U.S. English" -msgstr "Amerikaans Engels" +msgstr "Amerikaans engels" msgid "Scandinavian" msgstr "Scandinavisch" @@ -2566,16 +2566,16 @@ msgid "Apply overscan deltas" msgstr "Overscan-delta’s toepassen" msgid "Mono Interlaced" -msgstr "Mono Interlaced" +msgstr "Mono interlaced" msgid "Mono Non-Interlaced" -msgstr "Mono Niet-Interlaced" +msgstr "Mono niet-interlaced" msgid "Color Interlaced" -msgstr "Kleur Interlaced" +msgstr "Kleur interlaced" msgid "Color Non-Interlaced" -msgstr "Kleur Niet-Interlaced" +msgstr "Kleur niet-interlaced" msgid "3Dfx Voodoo Graphics" msgstr "3Dfx Voodoo Graphics" @@ -2635,7 +2635,7 @@ msgid "Passthrough Mode" msgstr "Doorgeefmodus" msgid "Host Serial Device" -msgstr "Host Serieel Apparaat" +msgstr "Host serieel apparaat" msgid "Name of pipe" msgstr "Naam van de pipe" @@ -2650,10 +2650,10 @@ msgid "Baud Rate of Passthrough" msgstr "Baud-snelheid van doorvoer" msgid "Named Pipe (Server)" -msgstr "Named Pipe (Server)" +msgstr "Genoemd pipe (server)" msgid "Named Pipe (Client)" -msgstr "Named Pipe (Client)" +msgstr "Genoemd pipe (client)" msgid "Host Serial Passthrough" msgstr "Host seriële doorgave" @@ -2833,10 +2833,10 @@ msgid "SoundFont files" msgstr "SoundFont-bestanden" msgid "Local Switch" -msgstr "Lokale Switch" +msgstr "Lokale-switch" msgid "Remote Switch" -msgstr "Externe Switch" +msgstr "Externe-switch" msgid "Shared secret:" msgstr "Gedeeld geheim:" @@ -2869,16 +2869,16 @@ msgid "An error occurred trying to wipe the NVRAM contents of the virtual machin msgstr "Fout bij Wissen van NVRAM-inhoud van de virtuele machine \"%1\"" msgid "%1 VM Manager" -msgstr "%1 VM Beheerder" +msgstr "%1 VM-beheerder" msgid "%n disk(s)" msgstr "%n schijf/schijven" msgid "Unknown Status" -msgstr "Onbekende Status" +msgstr "Onbekende status" msgid "No Machines Found!" -msgstr "Geen Machines Gevonden!" +msgstr "Geen machines gevonden!" msgid "Check for updates on startup" msgstr "Controleer op updates bij starten" @@ -2932,7 +2932,7 @@ msgid "Checking for updates…" msgstr "Controleren op updates…" msgid "86Box Update" -msgstr "86Box Update" +msgstr "86Box-update" msgid "Release notes:" msgstr "Release-opmerkingen:" From 953c8a27e29106ee305d4ab227147bdc89fb00b5 Mon Sep 17 00:00:00 2001 From: Paradyx0392 Date: Mon, 16 Feb 2026 19:16:15 +0800 Subject: [PATCH 19/66] Update fr-FR.po --- src/qt/languages/fr-FR.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 453b52de4..e8eee00c1 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -1006,7 +1006,7 @@ msgid "About %1" msgstr "À propos de %1" msgid "An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Un émulateur d'ordinateurs du passé\n\nAuteurs : Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nAvec les contributions de Sarah Walker, leilei, JohnElliott, greatpsycho et d'autres.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE." +msgstr "Un émulateur d'ordinateurs du passé\n\nAuteurs : Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne et d'autres.\n\nAvec les contributions de Sarah Walker, leilei, JohnElliott, greatpsycho et d'autres.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE." msgid "Hardware not available" msgstr "Matériel non disponible" From 5b4b486afc515e0c6ce15fff71d400a642231b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Tue, 17 Feb 2026 00:29:30 +0100 Subject: [PATCH 20/66] Fix a MOV in vid_voodoo_codegen_x86-64.h that should have been an ADD --- src/include/86box/vid_voodoo_codegen_x86-64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/vid_voodoo_codegen_x86-64.h b/src/include/86box/vid_voodoo_codegen_x86-64.h index 0e43c15bd..b7028c7d7 100644 --- a/src/include/86box/vid_voodoo_codegen_x86-64.h +++ b/src/include/86box/vid_voodoo_codegen_x86-64.h @@ -1300,7 +1300,7 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0x35); /*XOR EAX, 0xff*/ addlong(0xff); } - addbyte(0x8e); /*ADD EAX, 1*/ + addbyte(0x83); /*ADD EAX, 1*/ addbyte(0xc0); addbyte(1); addbyte(0x0f); /*IMUL EAX, EBX*/ From dfee5d88d328e02a26ebab20351e6ec222f54887 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Mon, 16 Feb 2026 20:37:59 -0600 Subject: [PATCH 21/66] Cirrus: Make CL-GD5402 VRAM configurable with options for 256KB and 512KB --- src/video/vid_cl54xx.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 71ded9010..9f33a9d89 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1330,7 +1330,10 @@ gd54xx_in(uint16_t addr, void *priv) /* Scratch Pad 1 (Memory size for 5402/542x) */ ret = svga->seqregs[0x0a] & ~0x1a; if (svga->crtc[0x27] == CIRRUS_ID_CLGD5402) { - ret |= 0x01; /*512K of memory*/ + if ((gd54xx->vram_size >> 10) == 512) + ret |= 0x01; /*512K of memory*/ + else + ret &= 0xfe; /*256K of memory*/ } else if (svga->crtc[0x27] > CIRRUS_ID_CLGD5402) { switch (gd54xx->vram_size >> 10) { case 512: @@ -4443,8 +4446,6 @@ gd54xx_init(const device_t *info) vram = 1024; else if (id == CIRRUS_ID_CLGD5401) vram = 256; - else if (id == CIRRUS_ID_CLGD5402) - vram = 512; else vram = device_get_config_int("memory"); @@ -4780,6 +4781,25 @@ gd54xx_force_redraw(void *priv) } // clang-format off +static const device_config_t gd5402_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 512, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "256 KB", .value = 256 }, + { .description = "512 KB", .value = 512 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + static const device_config_t gd542x_config[] = { { .name = "memory", @@ -5027,7 +5047,7 @@ const device_t gd5402_isa_device = { .available = gd5402_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = NULL, + .config = gd5402_config, }; const device_t gd5402_onboard_device = { @@ -5041,7 +5061,7 @@ const device_t gd5402_onboard_device = { .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = NULL, + .config = gd5402_config, }; const device_t gd5402_onboard_commodore_device = { @@ -5055,7 +5075,7 @@ const device_t gd5402_onboard_commodore_device = { .available = NULL, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = NULL, + .config = gd5402_config, }; const device_t gd5420_isa_device = { From 9bdfe5cbea2d3c86939a8083ea1c9cba37894d88 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Mon, 16 Feb 2026 20:40:39 -0600 Subject: [PATCH 22/66] Cirrus: All machines using the CL-GD5428 ISA as an onboard device only support 512KB/1MB configs --- src/video/vid_cl54xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 9f33a9d89..e7de99863 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -5301,7 +5301,7 @@ const device_t gd5428_onboard_device = { .available = gd5428_isa_available, .speed_changed = gd54xx_speed_changed, .force_redraw = gd54xx_force_redraw, - .config = gd5426_config + .config = gd542x_config }; const device_t gd5428_vlb_onboard_device = { From 3621e0b33500a02200e0bbd19507f6d25a62cf9f Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:10:55 -0600 Subject: [PATCH 23/66] Move the Intel Monsoon and Tandy Sensation II/3100/MMPC machine over to the 512KB/1MB 5428 VLB variant and rename it since it's no longer specific to a Dell machine --- src/machine/machine_table.c | 4 ++-- src/video/vid_cl54xx.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index fd7f5b1f0..bdc8571a0 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8620,7 +8620,7 @@ const machine_t machines[] = { .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &gd5428_vlb_onboard_device, + .vid_device = &gd5428_onboard_vlb_device, .snd_device = NULL, .net_device = NULL }, @@ -8708,7 +8708,7 @@ const machine_t machines[] = { .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &gd5428_vlb_onboard_device, + .vid_device = &gd5428_onboard_vlb_device, .snd_device = NULL, .net_device = NULL }, diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index e7de99863..4445def97 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -5319,7 +5319,7 @@ const device_t gd5428_vlb_onboard_device = { }; const device_t gd5428_onboard_vlb_device = { - .name = "Cirrus Logic GD5428 (VLB) (On-Board) (Dell)", + .name = "Cirrus Logic GD5428 (VLB) (On-Board) (1MB)", .internal_name = "cl_gd5428_onboard_vlb", .flags = DEVICE_VLB, .local = CIRRUS_ID_CLGD5428 | 0x200, From 38e5f2a374b4051f943145a9cb1336be0ad86bc4 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:12:59 -0600 Subject: [PATCH 24/66] Sensation audio: Initialize ret in sensation_visdac_read, should fix a compiler warning --- src/sound/snd_sensation.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/snd_sensation.c b/src/sound/snd_sensation.c index ea87c8391..aeb58fb46 100644 --- a/src/sound/snd_sensation.c +++ b/src/sound/snd_sensation.c @@ -808,6 +808,7 @@ sensation_visdac_read(uint16_t port, void *priv) sensation_t *visdac = (sensation_t *) priv; uint8_t ret; + ret = 0xff; switch (port & 0xF) { case 0x00: From ca9f9d7fc366866b2042aa7251098a4311cc62e3 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:19:00 -0600 Subject: [PATCH 25/66] Tandy Sensations: Remove the MACHINE_APM flag since the chipset these machines use lacks SMI functionality --- src/machine/machine_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bdc8571a0..654934e6c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -7893,7 +7893,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE | MACHINE_SOUND | MACHINE_GAMEPORT | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_SOUND | MACHINE_GAMEPORT, .ram = { .min = 2048, .max = 32768, @@ -8690,7 +8690,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 2048, .max = 65536, From 9a5ec04ec51407204de62e2693f90b6c15813e4f Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Mon, 16 Feb 2026 22:00:19 -0600 Subject: [PATCH 26/66] Tandy Sensation II: After further research the Tandy 3100 and MMPC series have a different BIOS and some board differences so rename the machine to reflect this Also add a new Cirrus 5428 device with a fixed 1MB VRAM config for this machine --- src/include/86box/video.h | 1 + src/machine/machine_table.c | 4 ++-- src/video/vid_cl54xx.c | 18 +++++++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 32e1ace03..d7369af28 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -387,6 +387,7 @@ extern const device_t gd5426_vlb_device; extern const device_t gd5426_onboard_device; extern const device_t gd5428_isa_device; extern const device_t gd5428_vlb_onboard_device; +extern const device_t gd5428_vlb_onboard_tandy_device; extern const device_t gd5428_vlb_device; extern const device_t gd5428_diamond_speedstar_pro_b1_vlb_device; extern const device_t gd5428_boca_isa_device; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 654934e6c..f1006ffb4 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8670,7 +8670,7 @@ const machine_t machines[] = { }, /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ { - .name = "[VLSI 82C486] Tandy Sensation! II (25-1651)/3100/MMPC", + .name = "[VLSI 82C486] Tandy Sensation! II (25-1651)", .internal_name = "sensation2", .type = MACHINE_TYPE_486_S2, .chipset = MACHINE_CHIPSET_VLSI_VL82C486, @@ -8708,7 +8708,7 @@ const machine_t machines[] = { .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &gd5428_onboard_vlb_device, + .vid_device = &gd5428_vlb_onboard_tandy_device, .snd_device = NULL, .net_device = NULL }, diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 4445def97..c02f5191a 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4442,7 +4442,9 @@ gd54xx_init(const device_t *info) gd54xx->vram_size = vram << 10; } else { if (id <= CIRRUS_ID_CLGD5428) { - if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200)) + if ((id == CIRRUS_ID_CLGD5428) && (info->local & 0x200) && (info->local & 0x1000)) + vram = 1024; + else if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200)) vram = 1024; else if (id == CIRRUS_ID_CLGD5401) vram = 256; @@ -5332,6 +5334,20 @@ const device_t gd5428_onboard_vlb_device = { .config = gd542x_config }; +const device_t gd5428_vlb_onboard_tandy_device = { + .name = "Cirrus Logic GD5428 (VLB) (On-Board) (Tandy)", + .internal_name = "cl_gd5428_vlb_onboard_tandy", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5428 | 0x200 | 0x1000, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + .available = NULL, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = NULL +}; + const device_t gd5429_isa_device = { .name = "Cirrus Logic GD5429 (ISA)", .internal_name = "cl_gd5429_isa", From b072b84e9ada3134dea47b2f3bf17321cac312b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 18 Feb 2026 00:40:54 +0100 Subject: [PATCH 27/66] ASUS P5A: Reverse the order of the first 4 PCI slots (fixes Voodoo 2 SLI) and correctly declare device 0x06 as reserved for on-board audio. --- src/machine/m_at_sockets7.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 550da59b9..725874a07 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -59,12 +59,12 @@ machine_at_p5a_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x06, PCI_CARD_SOUND, 3, 4, 1, 2); device_add(&ali1541_device); device_add(&ali1543c_device); /* +0 */ From 16e8384bdb952a0d1487e121e16fbc6bd598f44e Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:51:50 -0600 Subject: [PATCH 28/66] Cirrus: Revert to the old behavior of loading the generic ISA VBIOS on the Vectra 486VL and Siemens-Nixdorf D824, fixes Windows 3.1 drivers --- src/video/vid_cl54xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index c02f5191a..32dbaca13 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4335,9 +4335,9 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5428: if (info->local & 0x200) { if (machines[machine].init == machine_at_vect486vl_init) - romfn = BIOS_GD5428_ONBOARD_HP_PATH; + romfn = BIOS_GD5428_ISA_PATH; else if (machines[machine].init == machine_at_d824_init) - romfn = BIOS_GD5428_ONBOARD_SNI_PATH; + romfn = BIOS_GD5428_ISA_PATH; else if (machines[machine].init == machine_at_acera1g_init) romfn = BIOS_GD5428_ONBOARD_ACER_PATH; else From 84ab3315a54712c18b5e8359b4c56e990450a062 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:22:10 -0600 Subject: [PATCH 29/66] HP Vectra 486VL: Give the machine its correct Cirrus CL-GD5426 ISA onboard video --- src/include/86box/video.h | 1 + src/machine/machine_table.c | 2 +- src/video/vid_cl54xx.c | 27 +++++++++++++++++++++------ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index d7369af28..a83aa9371 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -384,6 +384,7 @@ extern const device_t gd5424_onboard_device; extern const device_t gd5426_isa_device; extern const device_t gd5426_diamond_speedstar_pro_a1_isa_device; extern const device_t gd5426_vlb_device; +extern const device_t gd5426_onboard_isa_device; extern const device_t gd5426_onboard_device; extern const device_t gd5428_isa_device; extern const device_t gd5428_vlb_onboard_device; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f1006ffb4..03df2d9df 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -7779,7 +7779,7 @@ const machine_t machines[] = { .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ - .vid_device = &gd5428_onboard_device, + .vid_device = &gd5426_onboard_isa_device, .snd_device = NULL, .net_device = NULL }, diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 32dbaca13..ae2da7e15 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -4317,7 +4317,10 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5426: if (info->local & 0x200) - romfn = NULL; + if (machines[machine].init == machine_at_vect486vl_init) + romfn = BIOS_GD5428_ISA_PATH; + else + romfn = NULL; else { if (info->local & 0x100) romfn = BIOS_GD5426_DIAMOND_A1_ISA_PATH; @@ -4334,9 +4337,7 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5428: if (info->local & 0x200) { - if (machines[machine].init == machine_at_vect486vl_init) - romfn = BIOS_GD5428_ISA_PATH; - else if (machines[machine].init == machine_at_d824_init) + if (machines[machine].init == machine_at_d824_init) romfn = BIOS_GD5428_ISA_PATH; else if (machines[machine].init == machine_at_acera1g_init) romfn = BIOS_GD5428_ONBOARD_ACER_PATH; @@ -4444,7 +4445,7 @@ gd54xx_init(const device_t *info) if (id <= CIRRUS_ID_CLGD5428) { if ((id == CIRRUS_ID_CLGD5428) && (info->local & 0x200) && (info->local & 0x1000)) vram = 1024; - else if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200)) + else if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200) && (info->local & 0x1000)) vram = 1024; else if (id == CIRRUS_ID_CLGD5401) vram = 256; @@ -5193,11 +5194,25 @@ const device_t gd5426_vlb_device = { .config = gd5426_config }; +const device_t gd5426_onboard_isa_device = { + .name = "Cirrus Logic GD5426 (ISA) (On-Board)", + .internal_name = "cl_gd5426_onboard", + .flags = DEVICE_ISA16, + .local = CIRRUS_ID_CLGD5426 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + .available = gd5428_isa_available, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd542x_config +}; + const device_t gd5426_onboard_device = { .name = "Cirrus Logic GD5426 (VLB) (On-Board)", .internal_name = "cl_gd5426_onboard", .flags = DEVICE_VLB, - .local = CIRRUS_ID_CLGD5426 | 0x200, + .local = CIRRUS_ID_CLGD5426 | 0x200 | 0x1000, .init = gd54xx_init, .close = gd54xx_close, .reset = gd54xx_reset, From c3db24162131f7dba9b76b3015f1ddb0a55ccd45 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:00:09 +0900 Subject: [PATCH 30/66] IBM 5550: Added font 16 emulation --- src/include/86box/machine.h | 4 +- src/machine/m_xt_ibm5550.c | 392 ++++++++++++++++++++++++++++++------ src/machine/machine_table.c | 2 +- 3 files changed, 331 insertions(+), 67 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index af39e17e4..8a631f40a 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -1521,7 +1521,9 @@ extern int machine_xt_lxt3_init(const machine_t *); extern int machine_xt_compaq_deskpro_init(const machine_t *); /* m_xt_ibm5550.c */ - +#ifdef EMU_DEVICE_H +extern const device_t ibm5550_vid_device; +#endif extern int machine_xt_ibm5550_init(const machine_t *); /* m_xt_t1000.c */ diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index fed353344..089de761f 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -74,6 +74,8 @@ #define EPOCH_MASK_VRAM 0x3ffff /* 0xFFFFF */ // #define EPOCH_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ #define EPOCH_PIXELCLOCK 40000000.0 /* 40 MHz interlaced */ +#define EPOCH_CONFIG_MONO16 0 /* Model 5551-Axx (Font 16, monochrome) */ +#define EPOCH_CONFIG_MONO24 1 /* Model 5551-Bxx (Font 24, monochrome) */ #define LC_INDEX 0x3D0 #define LC_DATA 0x3D1 @@ -156,11 +158,11 @@ enum epoch_nvr_ADDR { }; #ifndef RELEASE_BUILD -// #define ENABLE_EPOCH_LOG 1 +#define ENABLE_EPOCH_LOG 1 #endif #ifdef ENABLE_EPOCH_LOG -// #define ENABLE_EPOCH_DEBUGIO 1 +#define ENABLE_EPOCH_DEBUGIO 1 // #define ENABLE_EPOCH_DEBUGKBD 1 int epoch_do_log = ENABLE_EPOCH_LOG; @@ -236,6 +238,7 @@ typedef struct epoch_t { int cursorvisible, cursoron, blink; int scrollcache; int char_width; + int font24; int firstline, lastline; int firstline_draw, lastline_draw; @@ -307,6 +310,30 @@ The IBM 5550 has different IRQ assignments like the 6580 Displaywriter System. | FC000h | ROM | */ +#ifdef ENABLE_EPOCH_LOG +// #include +// static int dumpno = 0x61; +// static void +// epoch_dumpvram(void *priv) +// { +// FILE *fp; +// epoch_t *epoch = (epoch_t *) priv; +// char str1[64] = "epoch_vramvm_"; +// char str2[3] = {0x30, 0x30, 0}; +// if (!isalnum(dumpno)) +// return; +// str2[0] = dumpno; +// dumpno++; +// str2[1] = (epoch->crtmode & 0xf) + 0x30; +// strcat(str1,str2); +// fp = fopen(str1, "wb"); +// if (fp != NULL) { +// fwrite(epoch->vram, EPOCH_SIZE_VRAM, 1, fp); +// fclose(fp); +// } +// } +#endif + static void epoch_out(uint16_t addr, uint16_t val, void *priv) { @@ -370,7 +397,11 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) // mem_mapping_enable(&epoch->paritymap); break; case 0x3D8: + /* Bit 3: Font access in read, Bit 1: graphic mode, Bit 0: Font access in write */ epoch->crtmode = val; +#ifdef ENABLE_EPOCH_LOG + // epoch_dumpvram(epoch); +#endif epoch_recalctimings(epoch); // epoch->attrff ^= 1; break; @@ -613,22 +644,43 @@ epoch_inw(uint16_t addr, void *priv) return temp; } -/* Get character line pattern from jfont rom or gaiji volatile memory */ +/* Get font pattern in a line from video memory */ static uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void *priv) { - epoch_t *epoch = (epoch_t *) priv; + epoch_t *epoch = (epoch_t *) priv; uint32_t font = 0; - if (code < 1536) { - code *= 0x80; - font = epoch->vram[code + line * 4]; - font <<= 8; - font |= epoch->vram[code + line * 4 + 1]; - font <<= 8; - font |= epoch->vram[code + line * 4 + 2]; - font <<= 8; - font |= epoch->vram[code + line * 4 + 3]; - } else + if (code < 1536) { + code *= 0x80; + code += line * 4; + if (epoch->font24) { /* Font 24 (2 x 13 x 29) */ + font = epoch->vram[code]; + font <<= 8; + code++; + font |= epoch->vram[code]; + font <<= 8; + code++; + font |= epoch->vram[code]; + font <<= 8; + code++; + font |= epoch->vram[code]; + } else { /* Font 16 (2 x 9 x 21) */ + int bitnum = code & 0x7; + font = epoch->vram[code]; + font <<= 8; + font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ + // font &= 0xffffff80; + // font |= epoch->vram[code + line * 4 + 1]; + font <<= 8; + code++; + font |= epoch->vram[code]; + font <<= 8; + bitnum = code & 0x7; + font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ + font &= 0xff80ff80; + // font |= epoch->vram[code + line * 4 + 3]; + } + } else font = EPOCH_INVALIDACCESS32; return font; } @@ -676,12 +728,13 @@ epoch_render_text(epoch_t *epoch) uint8_t chr, attr; int fg, bg; uint32_t chr_dbcs; + int underscore_y = (epoch->font24) ? 28 : 20; int chr_wide = 0; // int colormode = ((epoch->attrc[LV_PAS_STATUS_CNTRL] & 0x80) == 0x80); int colormode = 0; // epoch_log("displ: %x, first: %x, epochma: %x, epochsc: %x\n", // epoch->displine , epoch->firstline_draw, epoch->memaddr, epoch->scanline); - for (x = 0; x < epoch->hdisp; x += 13) { + for (x = 0; x < epoch->hdisp; x += epoch->char_width) { chr = epoch->cram[(epoch->memaddr) & EPOCH_MASK_CRAM]; attr = epoch->cram[(epoch->memaddr + 1) & EPOCH_MASK_CRAM]; // if(chr!=0x20) epoch_log("chr: %x, attr: %x ", chr, attr); @@ -713,7 +766,7 @@ epoch_render_text(epoch_t *epoch) // if(chr!=0x20) epoch_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, epoch->egapal[fg], epoch->pallook[epoch->egapal[fg]]); } /* Draw character */ - for (uint32_t n = 0; n < 13; n++) + for (uint32_t n = 0; n < epoch->char_width; n++) p[n] = epoch->pallook[epoch->egapal[bg]]; /* draw blank */ /* SBCS or DBCS left half */ if (chr_wide == 0) { @@ -729,23 +782,37 @@ epoch_render_text(epoch_t *epoch) /* Get the font pattern */ uint32_t font = getfont_ps55dbcs(chr_dbcs, epoch->scanline, epoch); /* Draw 13 dots */ - for (uint32_t n = 0; n < 13; n++) { + for (uint32_t n = 0; n < epoch->char_width; n++) { p[n] = epoch->pallook[epoch->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } } else { /* the char code is SBCS (ANK) */ uint32_t fontbase; + uint16_t font; if (attr & 0x02) /* second map of SBCS font */ fontbase = EPOCH_VRAM_SBEX; else fontbase = EPOCH_VRAM_SBCS; - uint16_t font = epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4]; /* w13xh29 font */ - font <<= 8; - font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 1]; /* w13xh29 font */ + if (epoch->font24) { + font = epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 2]; /* w13xh29 font */ + font <<= 8; + font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; + } else { + int bitnum; + fontbase = (fontbase & 0x1ffff) + chr * 0x80 + epoch->scanline * 4; + bitnum = fontbase & 0x7; + font = epoch->vram[fontbase + 2]; /* w9xh21 font */ + font <<= 8; + // font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; + fontbase >>= 3; + fontbase += 0x20000; /* real: C0000h */ + font |= epoch->vram[fontbase] << (8 + 7 - bitnum); + // if(chr!=0x20) epoch_log("faddr: %x, scline: %x, chr: %x, font: %x ", fontbase + chr * 0x80 + epoch->scanline * 4, epoch->scanline, chr, font); + } // if(chr!=0x20) epoch_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", epoch->memaddr, epoch->scanline, chr, font); /* Draw 13 dots */ - for (uint32_t n = 0; n < 13; n++) { + for (uint32_t n = 0; n < epoch->char_width; n++) { p[n] = epoch->pallook[epoch->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } @@ -755,15 +822,15 @@ epoch_render_text(epoch_t *epoch) else { uint32_t font = getfont_ps55dbcs(chr_dbcs, epoch->scanline, epoch); /* Draw 13 dots */ - for (uint32_t n = 0; n < 13; n++) { + for (uint32_t n = 0; n < epoch->char_width; n++) { p[n] = epoch->pallook[epoch->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } chr_wide = 0; } /* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */ - if (epoch->scanline == 28 && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ - for (uint32_t n = 0; n < 13; n++) + if (epoch->scanline == underscore_y && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ + for (uint32_t n = 0; n < epoch->char_width; n++) p[n] = epoch->pallook[epoch->egapal[fg]]; /* under line (white) */ } /* Column 1 (Vertical Line) */ @@ -771,14 +838,14 @@ epoch_render_text(epoch_t *epoch) p[0] = epoch->pallook[epoch->egapal[2]]; /* vertical line (white) */ } if (epoch->scanline == 0 && attr & 0x20) { /* HGrid */ - for (uint32_t n = 0; n < 13; n++) + for (uint32_t n = 0; n < epoch->char_width; n++) p[n] = epoch->pallook[epoch->egapal[2]]; /* horizontal line (white) */ } /* Drawing text cursor */ drawcursor = ((epoch->memaddr == epoch->cursoraddr) && epoch->cursorvisible && epoch->cursoron); if (drawcursor && epoch->scanline >= epoch->crtc[LC_CURSOR_ROW_START] && epoch->scanline <= epoch->crtc[LC_CURSOR_ROW_END]) { // int cursorwidth = (epoch->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorwidth = 13; + int cursorwidth = epoch->char_width; int cursorcolor = 2; /* Choose color 2 if mode 8 */ fg = ((attr & 0x08) ? 3 : 2); bg = 0; @@ -793,7 +860,7 @@ epoch_render_text(epoch_t *epoch) p[n] = (p[n] == epoch->pallook[epoch->egapal[bg]]) ? epoch->pallook[epoch->egapal[cursorcolor]] : p[n]; } epoch->memaddr += 2; - p += 13; + p += epoch->char_width; } } } @@ -905,8 +972,13 @@ epoch_recalctimings(epoch_t *epoch) /* determine display mode */ if (epoch->crtmode & 0x02) { - epoch->hdisp *= 16; - epoch->char_width = 16; + if (epoch->font24) { + epoch->hdisp *= 16; + epoch->char_width = 16; + } else { + epoch->hdisp *= 11; + epoch->char_width = 11; + } /* PS/55 8-color */ epoch_log("Set videomode to PS/55 4 bpp graphics.\n"); epoch->render = epoch_render_color_4bpp; @@ -916,8 +988,13 @@ epoch_recalctimings(epoch_t *epoch) epoch_log("Set videomode to PS/55 Mode 8/E text.\n"); epoch->render = epoch_render_text; epoch->vram_display_mask = EPOCH_MASK_CRAM; - epoch->hdisp *= 13; - epoch->char_width = 13; + if (epoch->font24) { + epoch->hdisp *= 13; + epoch->char_width = 13; + } else { + epoch->hdisp *= 9; + epoch->char_width = 9; + } } if (epoch->crtmode & 0x08) epoch->render = epoch_render_blank; @@ -1114,55 +1191,211 @@ epoch_vram_write(uint32_t addr, uint8_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; // if ((addr & ~0xfff) != 0xE0000) return; - addr -= 0xA0000; + // epoch_log("epoch_vw: %x %x\n", addr, val); addr &= EPOCH_MASK_VRAM; epoch->vram[addr] = val; epoch->fullchange = changeframecount; // if(val == 0x66) // epoch_log("66 %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI,ES,DI); } -static void -epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) -{ - epoch_t *epoch = (epoch_t *) priv; - // epoch_log("%04X:%04X epoch_vram_writeb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); - cycles -= video_timing_write_b; - epoch_vram_write(addr, val, epoch); -} -static void -epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) -{ - // epoch_log("%04X:%04X epoch_vram_writew: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); - epoch_t *epoch = (epoch_t *) priv; - cycles -= video_timing_write_w; - epoch_vram_write(addr, val & 0xff, epoch); - epoch_vram_write(addr + 1, val >> 8, epoch); -} - static uint8_t epoch_vram_read(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) // return epoch_INVALIDACCESS8; - addr -= 0xA0000; addr &= EPOCH_MASK_VRAM; return epoch->vram[addr]; } + +static void +epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; +// epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); + cycles -= video_timing_write_b; + // return; +// epoch_vram_write(addr, val, epoch); +} +static void +epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // uint8_t convert[8] = {0, 2, 8, 8, 1, 3, 8, 8};/* only even chars */ + //uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even chars */ + // uint8_t convert[8] = {0, 1, 2, 3, 4, 5, 6, 7};/* all but alt */ + // uint8_t convert[8] = {0, 1, 2, 3, 8, 8, 8, 8};/* even alt */ + // uint8_t convert[8] = {8, 8, 8, 8, 0, 1, 2, 3};/* even alt */ + // uint8_t convert[8] = {0, 4, 1, 5, 2, 6, 3, 7};/* all but pos+-1 */ + // uint8_t convert[8] = {8, 8, 4, 6, 8, 8, 5, 7};/* only odd (0) */ + // uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even */ + // uint8_t convert[8] = {4, 6, 8, 8, 5, 7, 8, 8};/* only odd (0) */ + // uint8_t convert[8] = {8, 4, 6, 8, 8, 5, 7, 8};/* none */ + // epoch_log("%04X:%04X epoch_vww: %x, val %x DS %x SI %x ES %x DI %x %x\n", cs >> 4, cpu_state.pc, addr, val,DS,SI,ES,DI, epoch->crtc[LC_INTERLACE_AND_SKEW]); + epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); + cycles -= video_timing_write_w; + addr -= 0xA0000; + // addr &= 0xfffffffe; + // if (0) { + if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { + uint32_t toaddr, bitnum; + // if (addr < 0xd0000) { + // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // addr += 0xA0000 + 84 * index; + // epoch_log("%x %x\n", addr, index); + // } else if (addr >= 0xD8000) { + // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // if (addr & 2) return; + // addr >>= 1; + // addr += 0xC0000 + 42 * index; + // epoch_log("%x %x\n", addr, index); + // } else + // return; + + // if (addr < 0xd0000) { + // addr -= 0xA0000; + // if (addr & 2) + // return; + // addr >>= 1; + // addr += 0xA0000; + // } else if (addr >= 0xD8000) { + // addr -= 0xD8000; + // if (addr & 2) + // return; + // addr >>= 1; + // addr += 0xD8000; + // } else + // return; + + // addr >>= 1; + // if(addr & 0x02) + // addr--; + // addr ^= 0x06; + //addr &= 0xffffd;/* 1101 */ + // addr >>= 1; + + // if (convert[(addr + 0) & 7] > 7) + // return; + // epoch_vram_write((addr & 0xffff8) + convert[(addr + 0) & 7], val & 0xff, epoch); + // epoch_vram_write((addr & 0xffff8) + convert[(addr + 1) & 7], val >> 8, epoch); + + /* rw one word with 9 bits */ + /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ + toaddr = addr; + if (addr & 2) + toaddr--; + if (addr & 0x20000) + toaddr+=2; + toaddr &= 0xdffff; + + //addr >>= 1; + + epoch_vram_write(toaddr, val & 0xff, epoch); + // epoch_log("%x %x ", toaddr, val); + /* get 9th bit */ + bitnum = addr & 0x7; + val >>= 15; + val <<= bitnum; + addr >>= 3; + addr += 0x20000; /* real: C0000h */ + val |= epoch_vram_read(addr, epoch) & ~(1 << bitnum);/* mask to update one bit */ + epoch_vram_write(addr, val, epoch); + // epoch_log("%x %x\n", addr, val); + } else {/* is graphic mode */ + epoch_vram_write(addr, val & 0xff, epoch); + epoch_vram_write(addr + 1, val >> 8, epoch); + } + // epoch_log("%x %x\n", addr, addr + 1); +} + static uint8_t epoch_vram_readb(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; cycles -= video_timing_read_b; - return epoch_vram_read(addr, epoch); + // return 0xff; + // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); + // return epoch_vram_read(addr, epoch); } static uint16_t epoch_vram_readw(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; + // uint8_t convert[8] = {0, 2, 4, 6, 1, 3, 5, 7};/* all but pos+-1 */ + // uint8_t convert[8] = {0, 4, 8, 8, 8, 8, 8, 8};/* all but pos+-1 */ cycles -= video_timing_read_w; - return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); + addr -= 0xA0000; + epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", + cs >> 4, cpu_state.pc, addr, epoch->crtmode); + // addr &= 0xfffffffe; + //read 0->0,1 2->2,3 4->4,5 6->6,7 + //read 0->0,2 2->1,3 4->4,6 6->5,7 + // if (0) { + if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { + uint16_t ret; + uint32_t bitnum; + uint32_t toaddr; + // if (addr < 0xd0000) { + // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // addr += 0xA0000 + 84 * index; + // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); + // } else if (addr >= 0xD8000) { + // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ + // addr &= 0x007f; + // if (addr & 2) return EPOCH_INVALIDACCESS16; + // addr >>= 1; + // addr += 0xC0000 + 42 * index; + // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); + // } else + // return EPOCH_INVALIDACCESS16; + + // if (addr < 0xd0000) { + // addr -= 0xA0000; + // if (addr & 2) + // return EPOCH_INVALIDACCESS16; + // addr >>= 1; + // addr += 0xA0000; + // } else if (addr >= 0xD8000) { + // addr -= 0xD8000; + // if (addr & 2) + // return EPOCH_INVALIDACCESS16; + // addr >>= 1; + // addr += 0xD8000; + // } else + // return EPOCH_INVALIDACCESS16; + + // if(addr & 0x02) + // addr--; + // // addr ^= 0x06; + // addr >>= 1; + + // if (convert[(addr + 0) & 7] > 7) + // return 0; + // return epoch_vram_read((addr & 0xffff8) + convert[addr & 7], epoch) | (epoch_vram_read((addr & 0xffff8) + convert[(addr + 1) & 7], epoch) << 8); + + /* rw one word with 9 bits */ + /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ + toaddr = addr; /* 1101 */ + if (addr & 2) + toaddr--; + if (addr & 0x20000) + toaddr+=2; + toaddr &= 0xdffff; + ret = epoch_vram_read(toaddr, epoch); + /* get 9th bit */ + bitnum = addr & 0x7; + addr >>= 3; + addr += 0x20000; /* real: C0000h */ + ret |= (epoch_vram_read(addr, epoch) << (8 + 7 - bitnum)) & 0x8000; + return ret; + // return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); + } else {/* is graphic mode */ + return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); + } } @@ -1327,8 +1560,10 @@ x1xx xxxx: No floppy drive 1xxx xxxx: No (bootable?) hard drive */ case 0xA2: - ret = 0xA8;/* Mono 24 */ - // ret = 0xA2;/* Mono 16 */ + if (epoch->font24) + ret = 0xA8; /* Mono 24 */ + else + ret = 0xA2; /* Mono 16 */ break; /* I/O A3h R: @@ -1502,7 +1737,7 @@ static void kbd_epoch_adddata(uint16_t val) { key_queue[key_queue_end] = val; - epoch_kbdlog("epochkbd: %02X added to key queue at %i\n", + epoch_log("epochkbd: %02X added to key queue at %i\n", val, key_queue_end); key_queue_end = (key_queue_end + 1) & 0x0f; } @@ -1703,6 +1938,7 @@ kbd_close(void *priv) /* Stop the timer. */ timer_disable(&kbd->send_delay_timer); + mouse_close(); /* Disable scanning. */ keyboard_scan = 0; @@ -1967,10 +2203,12 @@ epoch_reset(void *priv) epoch->parityenabled = 1; epoch->lowmemorydisabled = 1; epoch->crtioenabled = 0; + mem_mapping_disable(&epoch->cmap); + mem_mapping_disable(&epoch->vmap); // epoch->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ epoch->crtc[LC_HORIZONTAL_TOTAL] = 103; /* Horizontal Total */ epoch->crtc[LC_VERTICAL_TOTAL] = 26; /* Vertical Total (These two must be set before the timer starts.) */ - epoch->crtmode = 0x08; + epoch->crtmode = 0; epoch->vram_display_mask = EPOCH_MASK_CRAM; // epoch->plane_mask = 1; epoch->oddeven = 0; @@ -2080,8 +2318,6 @@ epoch_init(UNUSED(const device_t *info)) epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); - epoch_reset(epoch); - mem_mapping_add(&epoch->cmap, 0xE0000, 0x1000, epoch_cram_readb, epoch_cram_readw, NULL, epoch_cram_writeb, epoch_cram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); mem_mapping_add(&epoch->vmap, 0xA0000, 0x40000, epoch_vram_readb, epoch_vram_readw, NULL, @@ -2089,8 +2325,6 @@ epoch_init(UNUSED(const device_t *info)) // mem_mapping_add(&epoch->fontcard.map, 0xF0000, 0xC000, epoch_font_readb, NULL, NULL, // epoch_font_writeb, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); - mem_mapping_disable(&epoch->cmap); - mem_mapping_disable(&epoch->vmap); // mem_mapping_disable(&epoch->fontcard.map); mem_mapping_add(&epoch->paritymap, 0, 0xA0000, epoch_parity_readb, epoch_parity_readw, NULL, epoch_parity_writeb, epoch_parity_writew, NULL, NULL, MEM_MAPPING_CACHE, epoch); @@ -2106,10 +2340,14 @@ epoch_init(UNUSED(const device_t *info)) // io_sethandler(0x160, 0x0010, // epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); + epoch_reset(epoch); + timer_add(&epoch->timer, epoch_poll, epoch, 1); epoch_nvr_init(epoch, 17); + epoch->font24 = device_get_config_int("model"); + return epoch; } @@ -2138,6 +2376,7 @@ epoch_close(void *priv) // } fp = fopen("epoch_daregs.txt", "w"); if (fp != NULL) { + fprintf(fp, "3d8(crtmode) %02X\n", epoch->crtmode); // for (uint8_t i = 0; i < 0x10; i++) // fprintf(fp, "3e1(ioctl) %02X: %4X %d\n", i, epoch->ioctl[i], epoch->ioctl[i]); // for (uint8_t i = 0; i < 0x20; i++) @@ -2186,8 +2425,31 @@ epoch_force_redraw(void *priv) epoch->fullchange = changeframecount; } -static const device_t epoch_device = { - .name = "IBM 5550 (Epoch) Video Controller", +static const device_config_t epoch_config[] = { + // clang-format off + { + .name = "model", + .description = "Model", + .type = CONFIG_SELECTION, + .default_int = EPOCH_CONFIG_MONO24, + .selection = { + { + .description = "A (Font 16)", + .value = EPOCH_CONFIG_MONO16 + }, + { + .description = "B (Font 24)", + .value = EPOCH_CONFIG_MONO24 + }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibm5550_vid_device = { + .name = "IBM 5550 Video Adapter", .internal_name = "ibm5550vid", .flags = DEVICE_ISA, .local = 0, @@ -2197,7 +2459,7 @@ static const device_t epoch_device = { .available = NULL, .speed_changed = epoch_speed_changed, .force_redraw = epoch_force_redraw, - .config = NULL + .config = epoch_config }; static void @@ -2258,7 +2520,7 @@ machine_xt_ibm5550_init(const machine_t *model) pit_ibm5550_init(); nmi_mask = 0; - device_add(&epoch_device); + device_add(&ibm5550_vid_device); device_add(&lpt_port_device); serial_t *uart = device_add(&ns8250_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 85b09676e..2e76f5a24 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2728,7 +2728,7 @@ const machine_t machines[] = { .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &ibm5550_vid_device, .snd_device = NULL, .net_device = NULL }, From 0a4b44184affb8abf55017e933b2079b57577e2f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:04:37 +0900 Subject: [PATCH 31/66] IBM 5550: comment out unused code --- src/machine/m_xt_ibm5550.c | 54 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 089de761f..ff369dede 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -79,8 +79,6 @@ #define LC_INDEX 0x3D0 #define LC_DATA 0x3D1 -#define LS_ENABLE 0x3D2 -#define LS_DISABLE 0x3D3 #define LC_HORIZONTAL_TOTAL 0x00 /* -1 */ #define LC_HORIZONTAL_DISPLAYED 0x01 #define LC_H_SYNC_POSITION 0x02 @@ -99,6 +97,10 @@ #define LC_CURSOR_LOC_LOWJ 0x0F #define LC_LIGHT_PEN_HIGH 0x10 #define LC_LIGHT_PEN_LOW 0x11 +#define LS_ENABLE 0x3D2 +#define LS_DISABLE 0x3D3 +#define LS_MODE 0x3D8 +#define LS_MONSENSE 0x3DA // #define LV_PORT 0x3E8 // #define LV_PALETTE_0 0x00 // #define LV_MODE_CONTROL 0x10 @@ -396,8 +398,8 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) mem_mapping_disable(&epoch->vmap); // mem_mapping_enable(&epoch->paritymap); break; - case 0x3D8: - /* Bit 3: Font access in read, Bit 1: graphic mode, Bit 0: Font access in write */ + case LS_MODE: + /* Bit 3: Video output enable, Bit 1: Graphic mode (switch 16 / 9 bit word in Font 16 system) */ epoch->crtmode = val; #ifdef ENABLE_EPOCH_LOG // epoch_dumpvram(epoch); @@ -515,7 +517,7 @@ epoch_in(uint16_t addr, void *priv) // // epoch_iolog("epoch In %04X(%02X) %04X %04X:%04X\n", addr, epoch->attraddr, temp, cs >> 4, cpu_state.pc); // epoch->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ // break; - case 0x3DA: + case LS_MONSENSE: temp = 0xff; if (!(epoch->crtmode & 0x08)) {/* The video out is active */ if(epoch->cgastat & 8) @@ -525,7 +527,7 @@ epoch_in(uint16_t addr, void *priv) // temp &= 0xfe; /* color */ break; } - if (addr != 0x3DA) + if (addr != LS_MONSENSE) epoch_iolog("%04X:%04X epoch In %04X %04X\n", cs >> 4, cpu_state.pc, addr, temp); return temp; } @@ -1208,15 +1210,15 @@ epoch_vram_read(uint32_t addr, void *priv) return epoch->vram[addr]; } -static void -epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) -{ - epoch_t *epoch = (epoch_t *) priv; -// epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); - cycles -= video_timing_write_b; - // return; -// epoch_vram_write(addr, val, epoch); -} +// static void +// epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) +// { +// epoch_t *epoch = (epoch_t *) priv; +// // epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); +// cycles -= video_timing_write_b; +// // return; +// // epoch_vram_write(addr, val, epoch); +// } static void epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) { @@ -1310,15 +1312,15 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) // epoch_log("%x %x\n", addr, addr + 1); } -static uint8_t -epoch_vram_readb(uint32_t addr, void *priv) -{ - epoch_t *epoch = (epoch_t *) priv; - cycles -= video_timing_read_b; - // return 0xff; - // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); - // return epoch_vram_read(addr, epoch); -} +// static uint8_t +// epoch_vram_readb(uint32_t addr, void *priv) +// { +// epoch_t *epoch = (epoch_t *) priv; +// cycles -= video_timing_read_b; +// // return 0xff; +// // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); +// // return epoch_vram_read(addr, epoch); +// } static uint16_t epoch_vram_readw(uint32_t addr, void *priv) @@ -2320,8 +2322,8 @@ epoch_init(UNUSED(const device_t *info)) mem_mapping_add(&epoch->cmap, 0xE0000, 0x1000, epoch_cram_readb, epoch_cram_readw, NULL, epoch_cram_writeb, epoch_cram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); - mem_mapping_add(&epoch->vmap, 0xA0000, 0x40000, epoch_vram_readb, epoch_vram_readw, NULL, - epoch_vram_writeb, epoch_vram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); + mem_mapping_add(&epoch->vmap, 0xA0000, 0x40000, NULL, epoch_vram_readw, NULL, + NULL, epoch_vram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); // mem_mapping_add(&epoch->fontcard.map, 0xF0000, 0xC000, epoch_font_readb, NULL, NULL, // epoch_font_writeb, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); From 5e6e81353ecf5844b10164709f298e2df602f79c Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:25:38 -0600 Subject: [PATCH 32/66] VL82C48x: Implement ROMSET register ROMMOV/ROMCS# functionality --- src/chipset/vl82c480.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index cf3682754..e5e904567 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -77,6 +77,14 @@ vl82c480_recalc_shadow(vl82c480_t *dev) } } + /* Implement ROMCS# disable portion of ROMMOV behavior */ + if ((dev->regs[0x11] == 0x00) && ((dev->regs[0x0c] & 0x20) || (dev->regs[0x0c] & 0x10))) + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + if (!(dev->regs[0x0f] & 0x0f) && !(dev->regs[0x0c] & 0x20)) { + mem_set_mem_state(0xc0000, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + if (!(dev->regs[0x0f] & 0xf0) && !((dev->regs[0x0c] & 0x30) == 0x30)) { + mem_set_mem_state(0xc8000, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + flushmmucache(); } @@ -146,6 +154,10 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) case 0x07: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); break; + case 0x0c: + dev->regs[dev->idx] = val; + vl82c480_recalc_shadow(dev); + break; case 0x0d ... 0x12: dev->regs[dev->idx] = val; vl82c480_recalc_shadow(dev); From 58323156c1b29537ed76265d43aa715d18be2290 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:35:39 -0600 Subject: [PATCH 33/66] VL82C48x: Add logging and fix a compile-breaking mistake --- src/chipset/vl82c480.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index e5e904567..fccf8f1ab 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -12,11 +12,17 @@ * * Copyright 2020 Miran Grca. */ + +#ifdef ENABLE_VL82C48X_LOG +#include +#endif + #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/timer.h> @@ -27,11 +33,31 @@ #include <86box/nmi.h> #include <86box/port_92.h> #include <86box/chipset.h> +#include <86box/log.h> + +#ifdef ENABLE_VL82C48X_LOG +int vl82c48x_do_log = ENABLE_VL82C48X_LOG; + +static void +vl82c48x_log(void *priv, const char *fmt, ...) +{ + if (vl82c48x_do_log) { + va_list ap; + va_start(ap, fmt); + log_out(priv, fmt, ap); + va_end(ap); + } +} +#else +# define vl82c48x_log(fmt, ...) +#endif typedef struct vl82c480_t { uint8_t idx; uint8_t regs[256]; uint32_t banks[4]; + + void * log; // New logging system } vl82c480_t; static int @@ -80,9 +106,9 @@ vl82c480_recalc_shadow(vl82c480_t *dev) /* Implement ROMCS# disable portion of ROMMOV behavior */ if ((dev->regs[0x11] == 0x00) && ((dev->regs[0x0c] & 0x20) || (dev->regs[0x0c] & 0x10))) mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - if (!(dev->regs[0x0f] & 0x0f) && !(dev->regs[0x0c] & 0x20)) { + if (!(dev->regs[0x0f] & 0x0f) && !(dev->regs[0x0c] & 0x20)) mem_set_mem_state(0xc0000, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - if (!(dev->regs[0x0f] & 0xf0) && !((dev->regs[0x0c] & 0x30) == 0x30)) { + if (!(dev->regs[0x0f] & 0xf0) && !((dev->regs[0x0c] & 0x30) == 0x30)) mem_set_mem_state(0xc8000, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); flushmmucache(); @@ -124,6 +150,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) { vl82c480_t *dev = (vl82c480_t *) priv; + vl82c48x_log(dev->log, "[%04X:%08X] VL82c48x: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + switch (addr) { case 0xec: dev->idx = val; @@ -207,6 +235,8 @@ vl82c480_read(uint16_t addr, void *priv) break; } + vl82c48x_log(dev->log, "[%04X:%08X] VL82c48x: [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + return ret; } @@ -215,6 +245,11 @@ vl82c480_close(void *priv) { vl82c480_t *dev = (vl82c480_t *) priv; + if (dev->log != NULL) { + log_close(dev->log); + dev->log = NULL; + } + free(dev); } @@ -229,6 +264,8 @@ vl82c480_init(const device_t *info) uint8_t min_j = (machines[machine].init == machine_at_monsoon_init) ? 2 : 2; uint8_t max_j = (machines[machine].init == machine_at_monsoon_init) ? 7 : 7; + dev->log = log_open("VL82c48x"); + dev->regs[0x00] = info->local; dev->regs[0x01] = 0xff; dev->regs[0x02] = 0x8a; From 4bab8b1fc5a66f53ad09c23d5646a76585bf0d67 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Wed, 18 Feb 2026 23:35:51 -0600 Subject: [PATCH 34/66] Mirror the ROMs for the HP Vectra 486VL and Siemens-Nixdorf D824 and remove the now unneeded Cirrus VBIOS hacks for them --- src/machine/m_at_socket1.c | 26 ++++++++++++++++++++++++-- src/video/vid_cl54xx.c | 11 ++--------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/machine/m_at_socket1.c b/src/machine/m_at_socket1.c index 563227f2e..7bb69d368 100644 --- a/src/machine/m_at_socket1.c +++ b/src/machine/m_at_socket1.c @@ -294,11 +294,13 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems int ret; ret = bios_load_linear("roms/machines/vect486vl/aa0500.ami", - 0x000e0000, 131072, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) return ret; + memcpy(&rom[0x00020000], rom, 131072); + if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); @@ -311,6 +313,15 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems device_add(&ide_isa_device); device_add_params(&fdc37c6xx_device, (void *) (FDC37C651 | FDC37C6XX_IDE_PRI)); + video_reset(gfxcard[0]); + + if (gfxcard[0] != VID_INTERNAL) { + for (uint16_t i = 0; i < 32768; i++) + rom[i] = mem_readb_phys(0x000c0000 + i); + } + mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000); + mem_mapping_set_exec(&bios_mapping, rom); + return ret; } @@ -321,11 +332,13 @@ machine_at_d824_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/d824/fts-biosupdated824noflashbiosepromv320-320334-160.bin", - 0x000e0000, 131072, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) return ret; + memcpy(&rom[0x00020000], rom, 131072); + if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); @@ -342,6 +355,15 @@ machine_at_d824_init(const machine_t *model) device_add(&ide_isa_device); device_add_params(&fdc37c6xx_device, (void *) FDC37C651); + video_reset(gfxcard[0]); + + if (gfxcard[0] != VID_INTERNAL) { + for (uint16_t i = 0; i < 32768; i++) + rom[i] = mem_readb_phys(0x000c0000 + i); + } + mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000); + mem_mapping_set_exec(&bios_mapping, rom); + return ret; } diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index ae2da7e15..edf49fe88 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -54,8 +54,6 @@ #define BIOS_GD5428_ISA_PATH "roms/video/cirruslogic/5428.bin" #define BIOS_GD5428_MCA_PATH "roms/video/cirruslogic/SVGA141.ROM" #define BIOS_GD5428_ONBOARD_ACER_PATH "roms/machines/acera1g/4alo001.bin" -#define BIOS_GD5428_ONBOARD_HP_PATH "roms/machines/vect486vl/aa0500.ami" -#define BIOS_GD5428_ONBOARD_SNI_PATH "roms/machines/d824/fts-biosupdated824noflashbiosepromv320-320334-160.bin" #define BIOS_GD5428_PATH "roms/video/cirruslogic/vlbusjapan.BIN" #define BIOS_GD5428_BOCA_ISA_PATH_1 "roms/video/cirruslogic/boca_gd5428_1.30b_1.bin" #define BIOS_GD5428_BOCA_ISA_PATH_2 "roms/video/cirruslogic/boca_gd5428_1.30b_2.bin" @@ -4317,10 +4315,7 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5426: if (info->local & 0x200) - if (machines[machine].init == machine_at_vect486vl_init) - romfn = BIOS_GD5428_ISA_PATH; - else - romfn = NULL; + romfn = NULL; else { if (info->local & 0x100) romfn = BIOS_GD5426_DIAMOND_A1_ISA_PATH; @@ -4337,9 +4332,7 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5428: if (info->local & 0x200) { - if (machines[machine].init == machine_at_d824_init) - romfn = BIOS_GD5428_ISA_PATH; - else if (machines[machine].init == machine_at_acera1g_init) + if (machines[machine].init == machine_at_acera1g_init) romfn = BIOS_GD5428_ONBOARD_ACER_PATH; else romfn = NULL; From b77f0dfe339ab56317f1b4240d9bb51d28436b9e Mon Sep 17 00:00:00 2001 From: WNT50 <173389620+WNT50@users.noreply.github.com> Date: Thu, 19 Feb 2026 17:16:40 +0800 Subject: [PATCH 35/66] Floppy and hard disk fixes for IBM PS/2 model 30-286 --- src/device/kbc_at.c | 6 ++++-- src/disk/hdc_xta_ps1.c | 3 --- src/machine/m_ps2_isa.c | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index d50dfb5d1..06824fe5e 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2184,7 +2184,7 @@ read_p1(atkbc_t *dev) ----------------- IBM PS/1: xxxxxxxx IBM PS/2 MCA: xxxxx1xx - IBM PS/2 Model 30-286: xxxxx1xx + IBM PS/2 Model 30-286: x0xxx1xx Intel AMI Pentium BIOS'es with AMI MegaKey KB-5 keyboard controller: x1x1xxxx Acer: xxxxx0xx Packard Bell PB450: xxxxx1xx @@ -2199,7 +2199,8 @@ read_p1(atkbc_t *dev) Acer: Pull down bit 6 if primary display is MDA. Pull down bit 2 always (must be so to enable CMOS Setup). IBM PS/1: Pull down bit 6 if current floppy drive is 3.5". - IBM PS/2 Model 30-286: Pull down bits 5 and 4 based on planar memory size. + IBM PS/2 Model 30-286: Pull down bit 6 always (for 1.44M floppy). + Pull down bits 5 and 4 based on planar memory size. Epson Action Tower 2600: Pull down bit 3 always (for Epson logo). NCR: Pull down bit 5 always (power-on default speed = high). Pull down bit 3 if there is no FPU. @@ -2215,6 +2216,7 @@ read_p1(atkbc_t *dev) Bit 6: Mostly, display: 0 = CGA, 1 = MDA, inverted on Xi8088 and Acer KBC's; Intel AMI MegaKey KB-5: Used for green features, SMM handler expects it to be set; IBM PS/1 Model 2011: 0 = current FDD is 3.5", 1 = current FDD is 5.25"; + IBM PS/2 Model 30-286: 0 = drive A is 1.44M, 1 = drive A is 720k; Compaq: 0 = Compaq dual-scan display, 1 = non-Compaq display. Bit 5: Mostly, manufacturing jumper: 0 = installed (infinite loop at POST), 1 = not installed; NCR: power-on default speed: 0 = high, 1 = low; diff --git a/src/disk/hdc_xta_ps1.c b/src/disk/hdc_xta_ps1.c index 4a4273333..38f49fa67 100644 --- a/src/disk/hdc_xta_ps1.c +++ b/src/disk/hdc_xta_ps1.c @@ -937,9 +937,6 @@ do_send: break; case CMD_WRITE_VERIFY: - no_data = 1; - fallthrough; - case CMD_WRITE_SECTORS: if (!drive->present) { dev->ssb.not_ready = 1; diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 64a8da2ed..ec3a53894 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -264,18 +264,18 @@ machine_ps2_isa_p1_handler(void) switch (mem_size / 1024) { case 0: /*256Kx2*/ - mem_p1 = 0xf0; + mem_p1 = 0xb0; break; case 1: /*256Kx4*/ - mem_p1 = 0xe0; + mem_p1 = 0xa0; break; case 2: /*1Mx2*/ case 3: - mem_p1 = 0xd0; + mem_p1 = 0x90; break; case 4: /*1Mx4*/ default: - mem_p1 = 0xc0; + mem_p1 = 0x80; break; } From 4284f155747e944e902bc7be34ebfe6e7fab1617 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:03:45 +0900 Subject: [PATCH 36/66] Keyboard: Fix a bug in IBM 5576-001 emulation Fix a bug that the make code is sent when the 5576-001 emulation is enabled and the key is released. --- src/device/keyboard.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index e77a5fc1d..ea8bcc1e7 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -216,22 +216,24 @@ key_process(uint16_t scan, int down) */ if (key5576mode) { int i = 0; - if (!down) { - /* Do and exit the 5576-001 emulation when a key is pressed other than trigger keys. */ - if (scan != 0x1d && scan != 0x2a && scan != 0x138) - { + if (down) { + while (scconv55_8a[i].sc != 0) { + if (scconv55_8a[i].sc == scan) { + while (scconv55_8a[i].mk[c] != 0) + keyboard_send(scconv55_8a[i].mk[c++]); + } + i++; + } + } + /* Do and exit the 5576-001 emulation when a key is pressed other than trigger keys. */ + if (scan != 0x1d && scan != 0x2a && scan != 0x138) { + if (!down) { key5576mode = 0; kbc_at_log("5576-001 key emulation disabled.\n"); } - } - while (scconv55_8a[i].sc != 0) - { - if (scconv55_8a[i].sc == scan) { - while (scconv55_8a[i].mk[c] != 0) - keyboard_send(scconv55_8a[i].mk[c++]); - return; - } - i++; + /* If the key is found in the table, the scancode has been sent. + Or else, do nothing. */ + return; } } From c1661b5a90121cb37952c29db6901c29c747fa8a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:06:33 +0900 Subject: [PATCH 37/66] IBM 5550: Fix the screen res in graphic mode --- src/machine/m_xt_ibm5550.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index ff369dede..35edec8f3 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -305,7 +305,7 @@ The IBM 5550 has different IRQ assignments like the 6580 Displaywriter System. | 40000h | 128 KB Expansion RAM Card | | 60000h | 128 KB Expansion RAM Card | | 80000h | 128 KB Expansion RAM Card | -| A0000h | 256 KB Video RAM | +| A0000h | Video RAM (Font 16: 144 KB, Font 24: 256 KB) | | E0000h | 4 KB Code/Attribute Buffer | | E8000h | ? KB Hard Disk Control Local Memory (not implemented) | | F0000h | Kanji Font Card (not implemented) | @@ -917,13 +917,15 @@ epoch_render_color_4bpp(epoch_t *epoch) /* INT 10h video modes supported in DOS K3.44. Mode Type Colors Text Base Address PELs Render - 2 A/N 3 80 x 25 E0000h 1040 x 725 text - 8 A/N/K 3 80 x 25 E0000h 1040 x 725 text + 2 A/N 3 80 x 25 E0000h 1040 x 725* text + 8 A/N/K 3 80 x 25 E0000h 1040 x 725* text + 9 APA 2 80 x 25 A0000h 720 x 512 color_4bpp Ah APA 2 78 x 25 A0000h 1024 x 768 color_4bpp Bh APA 16 40 x 25 A0000h 360 x 512 n/a Ch APA 16 80 x 25 A0000h 720 x 512 n/a Dh APA 16 78 x 25 A0000h 1024 x 768 n/a - Eh A/N/K 16 80 x 25 E0000h 1040 x 725 n/a + Eh A/N/K 16 80 x 25 E0000h 1040 x 725* n/a + (* 720 x 525 in the Font 16 system.) */ static void epoch_recalctimings(epoch_t *epoch) @@ -978,8 +980,8 @@ epoch_recalctimings(epoch_t *epoch) epoch->hdisp *= 16; epoch->char_width = 16; } else { - epoch->hdisp *= 11; - epoch->char_width = 11; + epoch->hdisp *= 12; + epoch->char_width = 12; } /* PS/55 8-color */ epoch_log("Set videomode to PS/55 4 bpp graphics.\n"); From 45c300a566b43af67a0da631bfc435d580532a46 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:10:16 +0900 Subject: [PATCH 38/66] IBM 5550: Change method to store 9th bit into memory --- src/machine/m_xt_ibm5550.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 35edec8f3..f13ccd6be 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -1236,7 +1236,7 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) // uint8_t convert[8] = {4, 6, 8, 8, 5, 7, 8, 8};/* only odd (0) */ // uint8_t convert[8] = {8, 4, 6, 8, 8, 5, 7, 8};/* none */ // epoch_log("%04X:%04X epoch_vww: %x, val %x DS %x SI %x ES %x DI %x %x\n", cs >> 4, cpu_state.pc, addr, val,DS,SI,ES,DI, epoch->crtc[LC_INTERLACE_AND_SKEW]); - epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); + // epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); cycles -= video_timing_write_w; addr -= 0xA0000; // addr &= 0xfffffffe; @@ -1291,21 +1291,21 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) if (addr & 2) toaddr--; if (addr & 0x20000) - toaddr+=2; - toaddr &= 0xdffff; + toaddr += 2; + toaddr &= 0x1ffff; //addr >>= 1; epoch_vram_write(toaddr, val & 0xff, epoch); // epoch_log("%x %x ", toaddr, val); /* get 9th bit */ - bitnum = addr & 0x7; + bitnum = toaddr & 0x7; + toaddr >>= 3; + toaddr += 0x20000; /* real: C0000h */ val >>= 15; val <<= bitnum; - addr >>= 3; - addr += 0x20000; /* real: C0000h */ - val |= epoch_vram_read(addr, epoch) & ~(1 << bitnum);/* mask to update one bit */ - epoch_vram_write(addr, val, epoch); + val |= epoch_vram_read(toaddr, epoch) & ~(1 << bitnum);/* mask to update one bit */ + epoch_vram_write(toaddr, val, epoch); // epoch_log("%x %x\n", addr, val); } else {/* is graphic mode */ epoch_vram_write(addr, val & 0xff, epoch); @@ -1332,8 +1332,7 @@ epoch_vram_readw(uint32_t addr, void *priv) // uint8_t convert[8] = {0, 4, 8, 8, 8, 8, 8, 8};/* all but pos+-1 */ cycles -= video_timing_read_w; addr -= 0xA0000; - epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", - cs >> 4, cpu_state.pc, addr, epoch->crtmode); + // epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", cs >> 4, cpu_state.pc, addr, epoch->crtmode); // addr &= 0xfffffffe; //read 0->0,1 2->2,3 4->4,5 6->6,7 //read 0->0,2 2->1,3 4->4,6 6->5,7 @@ -1387,14 +1386,14 @@ epoch_vram_readw(uint32_t addr, void *priv) if (addr & 2) toaddr--; if (addr & 0x20000) - toaddr+=2; - toaddr &= 0xdffff; + toaddr += 2; + toaddr &= 0x1ffff; ret = epoch_vram_read(toaddr, epoch); /* get 9th bit */ - bitnum = addr & 0x7; - addr >>= 3; - addr += 0x20000; /* real: C0000h */ - ret |= (epoch_vram_read(addr, epoch) << (8 + 7 - bitnum)) & 0x8000; + bitnum = toaddr & 0x7; + toaddr >>= 3; + toaddr += 0x20000; /* real: C0000h */ + ret |= (epoch_vram_read(toaddr, epoch) << (8 + 7 - bitnum)) & 0x8000; return ret; // return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); } else {/* is graphic mode */ @@ -1806,7 +1805,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_process(); speaker_update(); - + // if(!speaker_enable && (val & 2)) epoch_log("Buz!\n"); speaker_gated = val & 2; speaker_enable = val & 2; From 25d208cb8ef8d7b1443d05a7ed3c3213c27811be Mon Sep 17 00:00:00 2001 From: skiretic Date: Thu, 19 Feb 2026 20:03:03 -0500 Subject: [PATCH 39/66] Fix macOS toolbar label disappearing on mouse capture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BSD swprintf fails (returns -1) when the format string or a %ls argument contains non-ASCII wide characters under the C locale. On macOS, QKeySequence::NativeText produces Unicode key symbols (⌘ U+2318, ⌫ U+232B) in the release-mouse string, causing swprintf to zero out mouse_msg[1]. This made the title bar label collapse to empty during mouse capture. Avoid swprintf for non-ASCII content on macOS: store message suffixes with wcsncpy and build the title string via wcsncat at the update site. --- src/86box.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/86box.c b/src/86box.c index cf992df4c..0f72ddef1 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1870,6 +1870,27 @@ update_mouse_msg(void) (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls", EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu); +#else +#ifdef __APPLE__ + /* + * On macOS, BSD swprintf fails (returns -1) when the format string + * or a %ls argument contains non-ASCII wide characters (e.g. the + * native key symbols ⌘ U+2318, ⌫ U+232B) and the C locale is + * active. Store just the message suffixes here; the title update + * path in pc_render_monitor_dispatch() builds the full string + * without swprintf. + */ + wcsncpy(mouse_msg[0], plat_get_string(STRING_MOUSE_CAPTURE), sizeof_w(mouse_msg[0]) - 1); + mouse_msg[0][sizeof_w(mouse_msg[0]) - 1] = L'\0'; + + { + wchar_t *rel = (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) + : plat_get_string(STRING_MOUSE_RELEASE_MMB); + wcsncpy(mouse_msg[1], rel, sizeof_w(mouse_msg[1]) - 1); + mouse_msg[1][sizeof_w(mouse_msg[1]) - 1] = L'\0'; + } + + mouse_msg[2][0] = L'\0'; #else swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i%%%% - %ls", plat_get_string(STRING_MOUSE_CAPTURE)); @@ -1877,6 +1898,7 @@ update_mouse_msg(void) (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); wcsncpy(mouse_msg[2], L"%i%%", sizeof_w(mouse_msg[2])); #endif +#endif } void @@ -2009,11 +2031,20 @@ pc_run(void) else fps = ((fps + 20) / 50) * 50; #endif - swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps / (force_10ms ? 1 : 10)); #ifdef __APPLE__ + /* + * mouse_msg[] stores suffixes only on macOS (see update_mouse_msg). + * Build the title without passing non-ASCII chars through swprintf. + */ + swprintf(temp, sizeof_w(temp), L"%i%%", fps / (force_10ms ? 1 : 10)); + if (mouse_msg[mouse_msg_idx][0]) { + wcsncat(temp, L" - ", sizeof_w(temp) - wcslen(temp) - 1); + wcsncat(temp, mouse_msg[mouse_msg_idx], sizeof_w(temp) - wcslen(temp) - 1); + } /* Needed due to modifying the UI on the non-main thread is a big no-no. */ dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title); #else + swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps / (force_10ms ? 1 : 10)); ui_window_title(temp); #endif title_update = 0; From 617be3b135e6a89a4f6c973aba14f16b745d1a03 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:51:00 +0900 Subject: [PATCH 40/66] IBM 5550: Fix a bug in Font 16 drawing --- src/machine/m_xt_ibm5550.c | 78 +++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index f13ccd6be..2edb547a4 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -646,6 +646,18 @@ epoch_inw(uint16_t addr, void *priv) return temp; } +static uint32_t +getaddr_9bitword(int32_t addr) +{ + int32_t bit9addr = addr; + if (bit9addr & 2) + bit9addr--; + if (bit9addr & 0x20000) + bit9addr += 2; + bit9addr &= 0x1ffff; + return bit9addr; +} + /* Get font pattern in a line from video memory */ static uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void *priv) @@ -667,19 +679,22 @@ getfont_ps55dbcs(int32_t code, int32_t line, void *priv) code++; font |= epoch->vram[code]; } else { /* Font 16 (2 x 9 x 21) */ - int bitnum = code & 0x7; + int32_t bit9addr = getaddr_9bitword(code); + int bitnum = bit9addr & 7; + bit9addr >>= 3; + bit9addr += 0x20000; /* real: C0000h */ font = epoch->vram[code]; font <<= 8; - font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ - // font &= 0xffffff80; + font |= (epoch->vram[bit9addr] << (7 - bitnum)) & 0x80; /* get 9th bit */ + // font &= 0xff80; // font |= epoch->vram[code + line * 4 + 1]; font <<= 8; code++; font |= epoch->vram[code]; font <<= 8; bitnum = code & 0x7; - font |= (epoch->vram[(code >> 3) + 0x20000 ] << (7 - bitnum)) & 0xff; /* get 9th bit */ - font &= 0xff80ff80; + font |= (epoch->vram[bit9addr] << (7 - bitnum)) & 0x80; /* get 9th bit */ + // font &= 0xff80ff80; // font |= epoch->vram[code + line * 4 + 3]; } } else @@ -801,15 +816,17 @@ epoch_render_text(epoch_t *epoch) font <<= 8; font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; } else { - int bitnum; - fontbase = (fontbase & 0x1ffff) + chr * 0x80 + epoch->scanline * 4; - bitnum = fontbase & 0x7; + uint32_t bitnum, bit9addr; + fontbase += chr * 0x80 + epoch->scanline * 4; + bit9addr = getaddr_9bitword(fontbase); + bitnum = bit9addr & 7; + bit9addr >>= 3; + bit9addr += 0x20000; /* real: C0000h */ + + fontbase &= 0x1ffff; font = epoch->vram[fontbase + 2]; /* w9xh21 font */ font <<= 8; - // font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 3]; - fontbase >>= 3; - fontbase += 0x20000; /* real: C0000h */ - font |= epoch->vram[fontbase] << (8 + 7 - bitnum); + font |= (epoch->vram[bit9addr] << (7 - bitnum)) & 0x80; // if(chr!=0x20) epoch_log("faddr: %x, scline: %x, chr: %x, font: %x ", fontbase + chr * 0x80 + epoch->scanline * 4, epoch->scanline, chr, font); } // if(chr!=0x20) epoch_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", epoch->memaddr, epoch->scanline, chr, font); @@ -1287,31 +1304,27 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ - toaddr = addr; - if (addr & 2) - toaddr--; - if (addr & 0x20000) - toaddr += 2; - toaddr &= 0x1ffff; - - //addr >>= 1; + toaddr = getaddr_9bitword(addr); + bitnum = toaddr & 7; epoch_vram_write(toaddr, val & 0xff, epoch); - // epoch_log("%x %x ", toaddr, val); + // epoch_log("%x %x\n", toaddr, val); /* get 9th bit */ - bitnum = toaddr & 0x7; toaddr >>= 3; toaddr += 0x20000; /* real: C0000h */ val >>= 15; + // epoch_log("%x %x ", toaddr, val); val <<= bitnum; - val |= epoch_vram_read(toaddr, epoch) & ~(1 << bitnum);/* mask to update one bit */ + // epoch_log("%x ", val); + val |= (epoch_vram_read(toaddr, epoch) & (~(1 << bitnum)));/* mask to update one bit */ epoch_vram_write(toaddr, val, epoch); + // epoch_log("%x %x\n", toaddr, val); // epoch_log("%x %x\n", addr, val); } else {/* is graphic mode */ epoch_vram_write(addr, val & 0xff, epoch); epoch_vram_write(addr + 1, val >> 8, epoch); } - // epoch_log("%x %x\n", addr, addr + 1); + // epoch_log("%x %x\n", addr, val); } // static uint8_t @@ -1382,15 +1395,10 @@ epoch_vram_readw(uint32_t addr, void *priv) /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ - toaddr = addr; /* 1101 */ - if (addr & 2) - toaddr--; - if (addr & 0x20000) - toaddr += 2; - toaddr &= 0x1ffff; + toaddr = getaddr_9bitword(addr); + bitnum = toaddr & 7; ret = epoch_vram_read(toaddr, epoch); /* get 9th bit */ - bitnum = toaddr & 0x7; toaddr >>= 3; toaddr += 0x20000; /* real: C0000h */ ret |= (epoch_vram_read(toaddr, epoch) << (8 + 7 - bitnum)) & 0x8000; @@ -2148,11 +2156,11 @@ epoch_nvr_reset(nvr_t *nvr) } static void -epoch_nvr_init(epoch_t *epoch, int size) +epoch_nvr_init(epoch_t *epoch) { nvr_t* nvr = &epoch->nvr; /* This is machine specific. */ - nvr->size = size; + nvr->size = 17; nvr->irq = -1; /* Set up any local handlers here. */ nvr->reset = epoch_nvr_reset; @@ -2315,6 +2323,8 @@ epoch_init(UNUSED(const device_t *info)) changeframecount = 3; epoch->vram = calloc(1, 256* 1024); + // for(int i=0;i<256*1024;i++) /* for debug */ + // epoch->vram[i] = 0xff; epoch->cram = calloc(1, 4 * 1024); // epoch->fontcard.rom = calloc(1, EPOCH_FONTROM_SIZE); // epoch_video_load_font("roms/machines/ibm5550/GEN1FONT.BIN", epoch); @@ -2347,7 +2357,7 @@ epoch_init(UNUSED(const device_t *info)) timer_add(&epoch->timer, epoch_poll, epoch, 1); - epoch_nvr_init(epoch, 17); + epoch_nvr_init(epoch); epoch->font24 = device_get_config_int("model"); From 87500155883a3c3c6e9ada358371a65faefdbf95 Mon Sep 17 00:00:00 2001 From: WNT50 <173389620+WNT50@users.noreply.github.com> Date: Fri, 20 Feb 2026 13:16:08 +0800 Subject: [PATCH 41/66] IBM PS/1 XTA controller fixes --- src/disk/hdc_xta_ps1.c | 43 ++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/disk/hdc_xta_ps1.c b/src/disk/hdc_xta_ps1.c index 38f49fa67..c37bf3186 100644 --- a/src/disk/hdc_xta_ps1.c +++ b/src/disk/hdc_xta_ps1.c @@ -381,6 +381,7 @@ typedef struct hdc_t { pc_timer_t timer; int8_t state; /* controller state */ int8_t reset; /* reset state counter */ + int8_t ready; /* ready state counter */ /* Data transfer. */ int16_t buf_idx; /* buffer index and pointer */ @@ -723,6 +724,15 @@ hdc_callback(void *priv) uint8_t cmd = ccb->cmd & 0x0f; #endif + /* If we are returning from a RESET, handle this first. */ + if (dev->reset) { + ps1_hdc_log("XTA reset.\n"); + dev->status &= ~ASR_BUSY; + dev->reset = 0; + do_finish(dev); + return; + } + /* Clear the SSB error bits. */ dev->ssb.track_0 = 0; dev->ssb.cylinder_err = 0; @@ -754,6 +764,12 @@ hdc_callback(void *priv) return; } + if (!(dev->ready | no_data)) { + /* Delay a bit, transfer not ready. */ + timer_advance_u64(&dev->timer, HDC_TIME); + return; + } + switch (dev->state) { case STATE_IDLE: /* Seek to cylinder if requested. */ @@ -944,6 +960,12 @@ do_send: return; } + if (!(dev->ready | no_data)) { + /* Delay a bit, transfer not ready. */ + timer_advance_u64(&dev->timer, HDC_TIME); + return; + } + switch (dev->state) { case STATE_IDLE: /* Seek to cylinder if requested. */ @@ -1228,24 +1250,21 @@ hdc_write(uint16_t port, uint8_t val, void *priv) if (val & ACR_INT_EN) set_intr(dev, 0); /* clear IRQ */ - if (dev->reset != 0) { - if (++dev->reset == 3) { - dev->reset = 0; - - set_intr(dev, 1); - } - break; + if (val & ACR_RESET) { + dev->reset = 1; + dev->status |= ASR_BUSY; + /* Schedule command execution. */ + timer_set_delay_u64(&dev->timer, HDC_TIME); } - if (val & ACR_RESET) - dev->reset = 1; break; case 4: /* ATTN */ dev->status &= ~ASR_INT_REQ; - if (val & ATT_DATA) { - /* Dunno. Start PIO/DMA now? */ - } + if (val & ATT_DATA) + dev->ready = 1; + else + dev->ready = 0; if (val & ATT_SSB) { if (dev->attn & ATT_CCB) { From 99a0a1ef04b4208251100a90bce4f5753e9e54d1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 20 Feb 2026 15:03:51 +0600 Subject: [PATCH 42/66] MPU-401: Don't clear queues on reset Backported from DOSBox SVN revision r4492 --- src/sound/snd_mpu401.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 87c191cec..b1ff6ab8b 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -316,7 +316,6 @@ MPU401_Reset(mpu_t *mpu) mpu->ch_toref[i] = 4; /* Dummy reftable. */ } - MPU401_ClrQueue(mpu); mpu->state.data_onoff = -1; mpu->state.req_mask = 0; From c03a4e91c945fe1745d958e7d44e6074c276644a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 20 Feb 2026 23:36:08 +0900 Subject: [PATCH 43/66] IBM 5550: Add cursor blinking Added cursor blinking controlled by CRTC (HD46505). --- src/machine/m_xt_ibm5550.c | 20 +++++++++++++++++--- src/video/vid_ps55da2.c | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 2edb547a4..ccc55578b 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -862,7 +862,7 @@ epoch_render_text(epoch_t *epoch) } /* Drawing text cursor */ drawcursor = ((epoch->memaddr == epoch->cursoraddr) && epoch->cursorvisible && epoch->cursoron); - if (drawcursor && epoch->scanline >= epoch->crtc[LC_CURSOR_ROW_START] && epoch->scanline <= epoch->crtc[LC_CURSOR_ROW_END]) { + if (drawcursor) { // int cursorwidth = (epoch->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); int cursorwidth = epoch->char_width; int cursorcolor = 2; /* Choose color 2 if mode 8 */ @@ -1140,11 +1140,25 @@ epoch_poll(void *priv) // if (epoch->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ // { // epoch->cursoron = (epoch->blink | 1) & epoch->blinkconf; - epoch->cursoron = 1; + // epoch->cursoron = 1; // } else { // epoch->cursoron = 0; // } - if (!(epoch->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ + switch (epoch->crtc[LC_CURSOR_ROW_START] & 0x60) { + case 0x20: + epoch->cursoron = 0; + break; + case 0x60: + epoch->cursoron = epoch->blink & 0x10; + break; + case 0x40: + epoch->cursoron = epoch->blink & 0x08; + break; + default: + epoch->cursoron = 1; + break; + } + if (!(epoch->blink & (0x08 - 2))) /* force redrawing for cursor and blink attribute */ epoch->fullchange = changeframecount; } epoch->blink++; diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a1d7fe25f..9dffcdf97 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2055,7 +2055,7 @@ da2_render_text(da2_t *da2) } /* Drawing text cursor */ drawcursor = ((da2->memaddr == da2->cursoraddr) && da2->cursorvisible && da2->cursoron); - if (drawcursor && da2->scanline >= da2->crtc[LC_CURSOR_ROW_START] && da2->scanline <= da2->crtc[LC_CURSOR_ROW_END]) { + if (drawcursor) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ fg = (colormode) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); From 894e4bb0cf08456d3221b47b67744dfce04c7ed9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:25:07 +0900 Subject: [PATCH 44/66] IBM 5550: Set pixel clock for Font 16 --- src/machine/m_xt_ibm5550.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index ccc55578b..aefbf0193 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -73,7 +73,8 @@ #define EPOCH_MASK_CRAM 0xfff /* 0xFFF */ #define EPOCH_MASK_VRAM 0x3ffff /* 0xFFFFF */ // #define EPOCH_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ -#define EPOCH_PIXELCLOCK 40000000.0 /* 40 MHz interlaced */ +#define EPOCH_PIXELCLOCK24 40000000.0 /* 40 MHz interlaced */ +#define EPOCH_PIXELCLOCK16 20000000.0 /* 20 MHz interlaced (not confirmed) */ #define EPOCH_CONFIG_MONO16 0 /* Model 5551-Axx (Font 16, monochrome) */ #define EPOCH_CONFIG_MONO24 1 /* Model 5551-Bxx (Font 24, monochrome) */ @@ -241,6 +242,7 @@ typedef struct epoch_t { int scrollcache; int char_width; int font24; + double pixelclock; int firstline, lastline; int firstline_draw, lastline_draw; @@ -1088,7 +1090,7 @@ epoch_poll(void *priv) video_wait_for_buffer(); } - if((epoch->displine ^ !epoch->oddeven) & 1) + if ((epoch->displine ^ !epoch->oddeven) & 1) epoch->render(epoch); if (epoch->lastline < epoch->displine) @@ -1199,8 +1201,8 @@ epoch_poll(void *priv) epoch->vslines = 0; - epoch->memaddr - = epoch->memaddr_backup = epoch->memaddr_latch << 1; + epoch->memaddr + = epoch->memaddr_backup = epoch->memaddr_latch << 1; epoch->cursoraddr = ((epoch->crtc[LC_CURSOR_LOC_HIGH] << 8) | epoch->crtc[LC_CURSOR_LOC_LOWJ]) + epoch->ca_adj; epoch->cursoraddr <<= 1; @@ -1431,7 +1433,7 @@ epoch_cram_write(uint32_t addr, uint8_t val, void *priv) // if ((addr & ~0xfff) != 0xE0000) return; addr &= EPOCH_MASK_CRAM; epoch->cram[addr] = val; - epoch->fullchange = changeframecount;; + epoch->fullchange = changeframecount; // epoch_log("cw %04X:%04X %04X %02X\n", cs >> 4, cpu_state.pc, addr, val); } static void @@ -2328,6 +2330,8 @@ static void * epoch_init(UNUSED(const device_t *info)) { epoch_t *epoch = calloc(1, sizeof(epoch_t)); + epoch->font24 = device_get_config_int("model"); + video_inform(VIDEO_FLAG_TYPE_NONE, &timing_epoch_vid); video_update_timing(); @@ -2335,6 +2339,10 @@ epoch_init(UNUSED(const device_t *info)) epoch->dispofftime = 1000ull << 32; // epoch->changedvram = calloc(1, (EPOCH_MASK_VRAMPLANE + 1) >> 9); /* XX000h */ changeframecount = 3; + if (epoch->font24) + epoch->pixelclock = EPOCH_PIXELCLOCK24; + else + epoch->pixelclock = EPOCH_PIXELCLOCK16; epoch->vram = calloc(1, 256* 1024); // for(int i=0;i<256*1024;i++) /* for debug */ @@ -2343,7 +2351,7 @@ epoch_init(UNUSED(const device_t *info)) // epoch->fontcard.rom = calloc(1, EPOCH_FONTROM_SIZE); // epoch_video_load_font("roms/machines/ibm5550/GEN1FONT.BIN", epoch); - epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); + epoch->epochconst = (uint64_t) ((cpuclock / epoch->pixelclock) * (double) (1ull << 32)); mem_mapping_add(&epoch->cmap, 0xE0000, 0x1000, epoch_cram_readb, epoch_cram_readw, NULL, epoch_cram_writeb, epoch_cram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); @@ -2373,8 +2381,6 @@ epoch_init(UNUSED(const device_t *info)) epoch_nvr_init(epoch); - epoch->font24 = device_get_config_int("model"); - return epoch; } @@ -2441,7 +2447,7 @@ static void epoch_speed_changed(void *priv) { epoch_t *epoch = (epoch_t *) priv; - epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); + epoch->epochconst = (uint64_t) ((cpuclock / epoch->pixelclock) * (double) (1ull << 32)); epoch_recalctimings(epoch); } From 3a199fb8cb83d4540d985e677d0431208f398ec8 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:26:54 +0900 Subject: [PATCH 45/66] PS55DA2: Change to interlaced screen update --- src/video/vid_ps55da2.c | 62 ++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 9dffcdf97..0bd5035b0 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -64,7 +64,7 @@ #define DA2_MASK_GAIJIRAM 0x3ffff /* 0x3FFFF */ #define DA2_MASK_VRAM 0xfffff /* 0xFFFFF */ #define DA2_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ -#define DA2_PIXELCLOCK 29000000.0 /* 58 MHz interlaced */ +#define DA2_PIXELCLOCK 58000000.0 /* 58 MHz interlaced */ #define DA2_BLT_MEMSIZE 0x10 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) @@ -368,6 +368,7 @@ typedef struct da2_t { int firstline, lastline; int firstline_draw, lastline_draw; int displine; + int oddeven; /* Attribute Buffer E0000-E0FFFh (4 KB) */ uint8_t *cram; @@ -441,6 +442,9 @@ typedef struct da2_t { int old_pos2; } da2_t; +static video_timings_t timing_da2_mca = +{ .type = VIDEO_MCA, .write_b = 4, .write_w = 4, .write_l = 10, .read_b = 4, .read_w = 4, .read_l = 10 }; + static void da2_recalctimings(da2_t *da2); static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p); static void da2_bitblt_exec(void *p); @@ -515,7 +519,7 @@ da2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s uint32_t writepx[8]; destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = changeframecount; + da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = 3; destaddr <<= 3; /* read destination data with big endian order */ for (uint8_t i = 0; i < 8; i++) @@ -1245,7 +1249,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) case 0x3C9: /* Data */ // da2_iolog("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); da2->dac_status = 0; - da2->fullchange = changeframecount; + da2->fullchange = 3; switch (da2->dac_pos) { case 0: da2->dac_r = val; @@ -1283,7 +1287,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ da2_reset_ioctl(da2); else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) { /* Mode register */ - da2->fullchange = changeframecount; + da2->fullchange = 3; da2_recalctimings(da2); da2_updatevidselector(da2); } @@ -1372,7 +1376,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) case LC_START_V_DISPLAY_ENAB: case LC_VIEWPORT_SELECT: case LC_VIEWPORT_PRIORITY: - da2->fullchange = changeframecount; + da2->fullchange = 3; da2_recalctimings(da2); break; default: @@ -1391,13 +1395,13 @@ da2_out(uint16_t addr, uint16_t val, void *priv) // da2_iolog("set attraddr: %X\n", da2->attraddr); } else { if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) - da2->fullchange = changeframecount; + da2->fullchange = 3; if (da2->attrc[da2->attraddr & 0x3f] != val) da2_iolog("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); da2->attrc[da2->attraddr & 0x3f] = val; // da2_iolog("set attrc %x: %x\n", da2->attraddr & 31, val); if (da2->attraddr < 16) - da2->fullchange = changeframecount; + da2->fullchange = 3; if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { // if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); @@ -1411,7 +1415,7 @@ da2_out(uint16_t addr, uint16_t val, void *priv) switch (da2->attraddr) { case LV_COLOR_PLANE_ENAB: if ((val & 0xff) != da2->plane_mask) - da2->fullchange = changeframecount; + da2->fullchange = 3; da2->plane_mask = val & 0xff; break; case LV_CURSOR_CONTROL: @@ -2743,7 +2747,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *priv) //} #endif cycles -= video_timing_write_b; - da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */ + da2->changedvram[addr >> 9] = 3;/* 0x1FFFF -> 0x1F */ addr <<= 3; for (uint8_t i = 0; i < 8; i++) @@ -2804,7 +2808,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *priv) } else { /* mode 3h text */ cycles -= video_timing_write_b; da2_vram_w(addr, val, da2); - da2->fullchange = 2; + da2->fullchange = 3; } } static uint16_t @@ -2843,7 +2847,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *priv) // da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); // da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); - da2->changedvram[addr >> 9] = changeframecount; + da2->changedvram[addr >> 9] = 3; addr <<= 3; for (uint8_t i = 0; i < 8; i++) @@ -2942,7 +2946,7 @@ da2_code_write(uint32_t addr, uint8_t val, void *priv) // if ((addr & ~0xfff) != 0xE0000) return; addr &= DA2_MASK_CRAM; da2->cram[addr] = val; - da2->fullchange = 2; + da2->fullchange = 3; } static void da2_code_writeb(uint32_t addr, uint8_t val, void *priv) @@ -2987,7 +2991,7 @@ da2_code_readw(uint32_t addr, void *priv) } static void -da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) +da2_doblit(int wx, int wy, da2_t *da2) { if (wx != xsize || wy != ysize) { xsize = wx; @@ -3026,14 +3030,14 @@ da2_poll(void *priv) video_wait_for_buffer(); } - if (!da2->override) + if (!da2->override && ((da2->displine ^ !da2->oddeven) & 1)) da2->render(da2); if (da2->lastline < da2->displine) da2->lastline = da2->displine; } - - // da2_log("%03i %06X %06X\n", da2->displine, da2->memaddr,da2->vram_display_mask); + // if(da2->fullchange) + // pclog("%03i %05X %d %d\n", da2->displine, da2->memaddr, ((da2->displine ^ !da2->oddeven) & 1), da2->fullchange); da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { // da2_log("Vsync off at line %i\n",displine); @@ -3085,14 +3089,13 @@ da2_poll(void *priv) // if (da2->crtc[10] & 0x20) da2->cursoron = 0; // else da2->cursoron = da2->blink & 16; if (da2->ioctl[LS_MODE] & 1) { /* in text mode */ - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ - { + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01) {/* cursor blinking */ da2->cursoron = (da2->blink | 1) & da2->blinkconf; } else { da2->cursoron = 0; } - if (!(da2->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ - da2->fullchange = 2; + if (!(da2->blink & (0x08 - 1))) /* force redrawing for cursor and blink attribute */ + da2->fullchange = 3; } da2->blink++; @@ -3103,6 +3106,7 @@ da2_poll(void *priv) // memset(changedvram,0,2048); del if (da2->fullchange) { da2->fullchange--; + // pclog("fc %d %d\n",da2->fullchange,da2->oddeven); } } if (da2->vc == da2->vsyncstart) { @@ -3112,10 +3116,15 @@ da2_poll(void *priv) da2->cgastat |= 8; x = da2->hdisp; + if (!da2->oddeven) + da2->lastline++; + if (da2->oddeven) + da2->firstline--; + wx = x; wy = da2->lastline - da2->firstline; - da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); + da2_doblit(wx, wy, da2); da2->firstline = 2000; da2->lastline = 0; @@ -3123,7 +3132,8 @@ da2_poll(void *priv) da2->firstline_draw = 2000; da2->lastline_draw = 0; - changeframecount = 2; + da2->oddeven ^= 1; + da2->vslines = 0; da2->memaddr @@ -3137,7 +3147,7 @@ da2_poll(void *priv) // da2_log("VC vtotal\n"); // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); da2->vc = 0; - da2->scanline = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->scanline = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; da2->displine = 0; da2->scrollcache = da2->attrc[LV_PANNING] & 7; @@ -3229,7 +3239,8 @@ da2_reset(void *priv) da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ - da2->memaddr_latch = 0; + da2->memaddr_latch = 0; + da2->oddeven = 0; da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ @@ -3278,6 +3289,7 @@ da2_init(UNUSED(const device_t *info)) mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (double) (1ull << 32)); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_da2_mca); memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT @@ -3432,7 +3444,7 @@ static void da2_force_redraw(void *priv) { da2_t *da2 = (da2_t *) priv; - da2->fullchange = changeframecount; + da2->fullchange = 3; } static const device_config_t da2_configuration[] = { From dad8edd32e89094d85a8ca7533dcae0aa222b72f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:40:26 +0900 Subject: [PATCH 46/66] cleanup (m_xt_ibm5550.c) --- src/machine/m_xt_ibm5550.c | 169 ++++--------------------------------- 1 file changed, 17 insertions(+), 152 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index aefbf0193..00f203f1a 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -18,7 +18,7 @@ * These first-gen models have 1-3 DSQD diskette drives. * You need select "Type: 5.25" 720k" in the Settings dialog - Floppy & CD-ROM drives. * - * Currently, this module only support the model B configuration without hard disk. + * Currently, this module supports model A and B configurations without hard disk. * * Authors: Akamaki. * @@ -133,12 +133,12 @@ // #define LV_OUTPUT 0x3E // #define LV_COMPATIBILITY 0x3F -#define TIMER_CTR_0 0 //DMA -#define TIMER_CTR_1 1 //8253 timer -#define TIMER_CTR_2 2 //Speaker +#define TIMER_CTR_0 0 /* DMA */ +#define TIMER_CTR_1 1 /* PIT */ +#define TIMER_CTR_2 2 /* Speaker */ -#define EPOCH_IRQ3_BIT (1 << 3) //Keyboard -#define EPOCH_IRQ6_BIT (1 << 6) //Timer +#define EPOCH_IRQ3_BIT (1 << 3) /* Keyboard */ +#define EPOCH_IRQ6_BIT (1 << 6) /* PIT */ enum epoch_nvr_ADDR { epoch_nvr_SECOND1, @@ -161,7 +161,7 @@ enum epoch_nvr_ADDR { }; #ifndef RELEASE_BUILD -#define ENABLE_EPOCH_LOG 1 +//#define ENABLE_EPOCH_LOG 1 #endif #ifdef ENABLE_EPOCH_LOG @@ -381,7 +381,7 @@ epoch_out(uint16_t addr, uint16_t val, void *priv) case LC_MAXIMUM_SCAN_LINE: case LC_START_ADDRESS_HIGH: case LC_START_ADDRESS_LOW: - epoch->fullchange = changeframecount; + epoch->fullchange = 3; epoch_recalctimings(epoch); break; default: @@ -648,6 +648,7 @@ epoch_inw(uint16_t addr, void *priv) return temp; } +/* Return a memory address for 9-bit word access */ static uint32_t getaddr_9bitword(int32_t addr) { @@ -1139,13 +1140,6 @@ epoch_poll(void *priv) if (epoch->vc == epoch->dispend) { epoch->dispon = 0; if (!(epoch->crtmode & 0x02)) { /* in text mode */ - // if (epoch->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ - // { - // epoch->cursoron = (epoch->blink | 1) & epoch->blinkconf; - // epoch->cursoron = 1; - // } else { - // epoch->cursoron = 0; - // } switch (epoch->crtc[LC_CURSOR_ROW_START] & 0x60) { case 0x20: epoch->cursoron = 0; @@ -1161,7 +1155,7 @@ epoch_poll(void *priv) break; } if (!(epoch->blink & (0x08 - 2))) /* force redrawing for cursor and blink attribute */ - epoch->fullchange = changeframecount; + epoch->fullchange = 3; } epoch->blink++; @@ -1227,112 +1221,44 @@ static void epoch_vram_write(uint32_t addr, uint8_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~0xfff) != 0xE0000) return; // epoch_log("epoch_vw: %x %x\n", addr, val); addr &= EPOCH_MASK_VRAM; epoch->vram[addr] = val; - epoch->fullchange = changeframecount; - // if(val == 0x66) - // epoch_log("66 %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI,ES,DI); + epoch->fullchange = 3; } static uint8_t epoch_vram_read(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) - // return epoch_INVALIDACCESS8; addr &= EPOCH_MASK_VRAM; return epoch->vram[addr]; } -// static void -// epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) -// { -// epoch_t *epoch = (epoch_t *) priv; -// // epoch_log("%04X:%04X epoch_vwb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, val); -// cycles -= video_timing_write_b; -// // return; -// // epoch_vram_write(addr, val, epoch); -// } static void epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // uint8_t convert[8] = {0, 2, 8, 8, 1, 3, 8, 8};/* only even chars */ - //uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even chars */ - // uint8_t convert[8] = {0, 1, 2, 3, 4, 5, 6, 7};/* all but alt */ - // uint8_t convert[8] = {0, 1, 2, 3, 8, 8, 8, 8};/* even alt */ - // uint8_t convert[8] = {8, 8, 8, 8, 0, 1, 2, 3};/* even alt */ - // uint8_t convert[8] = {0, 4, 1, 5, 2, 6, 3, 7};/* all but pos+-1 */ - // uint8_t convert[8] = {8, 8, 4, 6, 8, 8, 5, 7};/* only odd (0) */ - // uint8_t convert[8] = {8, 8, 0, 2, 8, 8, 1, 3};/* only even */ - // uint8_t convert[8] = {4, 6, 8, 8, 5, 7, 8, 8};/* only odd (0) */ - // uint8_t convert[8] = {8, 4, 6, 8, 8, 5, 7, 8};/* none */ // epoch_log("%04X:%04X epoch_vww: %x, val %x DS %x SI %x ES %x DI %x %x\n", cs >> 4, cpu_state.pc, addr, val,DS,SI,ES,DI, epoch->crtc[LC_INTERLACE_AND_SKEW]); // epoch_log("%04X:%04X epoch_vww: %x, val %x cm %x\n", cs >> 4, cpu_state.pc, addr, val, epoch->crtmode); cycles -= video_timing_write_w; addr -= 0xA0000; - // addr &= 0xfffffffe; - // if (0) { if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { uint32_t toaddr, bitnum; - // if (addr < 0xd0000) { - // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // addr += 0xA0000 + 84 * index; - // epoch_log("%x %x\n", addr, index); - // } else if (addr >= 0xD8000) { - // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // if (addr & 2) return; - // addr >>= 1; - // addr += 0xC0000 + 42 * index; - // epoch_log("%x %x\n", addr, index); - // } else - // return; - - // if (addr < 0xd0000) { - // addr -= 0xA0000; - // if (addr & 2) - // return; - // addr >>= 1; - // addr += 0xA0000; - // } else if (addr >= 0xD8000) { - // addr -= 0xD8000; - // if (addr & 2) - // return; - // addr >>= 1; - // addr += 0xD8000; - // } else - // return; - - // addr >>= 1; - // if(addr & 0x02) - // addr--; - // addr ^= 0x06; - //addr &= 0xffffd;/* 1101 */ - // addr >>= 1; - - // if (convert[(addr + 0) & 7] > 7) - // return; - // epoch_vram_write((addr & 0xffff8) + convert[(addr + 0) & 7], val & 0xff, epoch); - // epoch_vram_write((addr & 0xffff8) + convert[(addr + 1) & 7], val >> 8, epoch); /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ - toaddr = getaddr_9bitword(addr); bitnum = toaddr & 7; epoch_vram_write(toaddr, val & 0xff, epoch); - // epoch_log("%x %x\n", toaddr, val); + /* get 9th bit */ toaddr >>= 3; toaddr += 0x20000; /* real: C0000h */ val >>= 15; - // epoch_log("%x %x ", toaddr, val); val <<= bitnum; - // epoch_log("%x ", val); - val |= (epoch_vram_read(toaddr, epoch) & (~(1 << bitnum)));/* mask to update one bit */ + + /* mask to update one bit */ + val |= (epoch_vram_read(toaddr, epoch) & (~(1 << bitnum))); epoch_vram_write(toaddr, val, epoch); // epoch_log("%x %x\n", toaddr, val); // epoch_log("%x %x\n", addr, val); @@ -1343,72 +1269,17 @@ epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) // epoch_log("%x %x\n", addr, val); } -// static uint8_t -// epoch_vram_readb(uint32_t addr, void *priv) -// { -// epoch_t *epoch = (epoch_t *) priv; -// cycles -= video_timing_read_b; -// // return 0xff; -// // epoch_log("%04X:%04X epoch_vrb: %x, val %x\n", cs >> 4, cpu_state.pc, addr, epoch_vram_read(addr, epoch)); -// // return epoch_vram_read(addr, epoch); -// } - static uint16_t epoch_vram_readw(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // uint8_t convert[8] = {0, 2, 4, 6, 1, 3, 5, 7};/* all but pos+-1 */ - // uint8_t convert[8] = {0, 4, 8, 8, 8, 8, 8, 8};/* all but pos+-1 */ cycles -= video_timing_read_w; addr -= 0xA0000; // epoch_log("%04X:%04X epoch_vrw: %x cm %x\n", cs >> 4, cpu_state.pc, addr, epoch->crtmode); - // addr &= 0xfffffffe; - //read 0->0,1 2->2,3 4->4,5 6->6,7 - //read 0->0,2 2->1,3 4->4,6 6->5,7 - // if (0) { if (!(epoch->crtmode & 0x02) && !(epoch->font24)) { uint16_t ret; uint32_t bitnum; uint32_t toaddr; - // if (addr < 0xd0000) { - // int index = (addr - 0xA0000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // addr += 0xA0000 + 84 * index; - // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); - // } else if (addr >= 0xD8000) { - // int index = (addr - 0xD8000) >> 7; /* 128 bytes per char */ - // addr &= 0x007f; - // if (addr & 2) return EPOCH_INVALIDACCESS16; - // addr >>= 1; - // addr += 0xC0000 + 42 * index; - // epoch_log("%x %x %x\n", addr, index, epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8)); - // } else - // return EPOCH_INVALIDACCESS16; - - // if (addr < 0xd0000) { - // addr -= 0xA0000; - // if (addr & 2) - // return EPOCH_INVALIDACCESS16; - // addr >>= 1; - // addr += 0xA0000; - // } else if (addr >= 0xD8000) { - // addr -= 0xD8000; - // if (addr & 2) - // return EPOCH_INVALIDACCESS16; - // addr >>= 1; - // addr += 0xD8000; - // } else - // return EPOCH_INVALIDACCESS16; - - // if(addr & 0x02) - // addr--; - // // addr ^= 0x06; - // addr >>= 1; - - // if (convert[(addr + 0) & 7] > 7) - // return 0; - // return epoch_vram_read((addr & 0xffff8) + convert[addr & 7], epoch) | (epoch_vram_read((addr & 0xffff8) + convert[(addr + 1) & 7], epoch) << 8); - /* rw one word with 9 bits */ /* virtual: 20000h (0010b, 0011b) -> real: 00001h (0000b, 0001b) */ toaddr = getaddr_9bitword(addr); @@ -1430,10 +1301,9 @@ static void epoch_cram_write(uint32_t addr, uint8_t val, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~0xfff) != 0xE0000) return; addr &= EPOCH_MASK_CRAM; epoch->cram[addr] = val; - epoch->fullchange = changeframecount; + epoch->fullchange = 3; // epoch_log("cw %04X:%04X %04X %02X\n", cs >> 4, cpu_state.pc, addr, val); } static void @@ -1458,8 +1328,6 @@ static uint8_t epoch_cram_read(uint32_t addr, void *priv) { epoch_t *epoch = (epoch_t *) priv; - // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) - // return epoch_INVALIDACCESS8; addr &= EPOCH_MASK_CRAM; return epoch->cram[addr]; } @@ -1495,7 +1363,6 @@ epoch_parity_readb(uint32_t addr, void *priv) return EPOCH_INVALIDACCESS8; } } - // return EPOCH_INVALIDACCESS8; return mem_read_ram(addr, priv); } @@ -1533,8 +1400,6 @@ epoch_parity_writeb(uint32_t addr, uint8_t val, void *priv) return; } } - // if (val == 0xcb) - // epoch_log("CB %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI, ES, DI); mem_write_ram(addr, val, priv); } static void @@ -2338,7 +2203,7 @@ epoch_init(UNUSED(const device_t *info)) epoch->dispontime = 1000ull << 32; epoch->dispofftime = 1000ull << 32; // epoch->changedvram = calloc(1, (EPOCH_MASK_VRAMPLANE + 1) >> 9); /* XX000h */ - changeframecount = 3; + if (epoch->font24) epoch->pixelclock = EPOCH_PIXELCLOCK24; else From 3fd344d957e16a19cf2c968f3230104c6cfa42e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sat, 21 Feb 2026 04:24:20 +0100 Subject: [PATCH 47/66] MPU-401: The IRQ must still be cleared on reset. --- src/sound/snd_mpu401.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index b1ff6ab8b..2562f16cc 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -316,6 +316,9 @@ MPU401_Reset(mpu_t *mpu) mpu->ch_toref[i] = 4; /* Dummy reftable. */ } + mpu->state.irq_pending = 0; + MPU401_UpdateIRQ(mpu, 0); + mpu->state.data_onoff = -1; mpu->state.req_mask = 0; From 74824bbac4f0455621f4be0cbb7113390875115d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Sun, 22 Feb 2026 01:34:07 +0100 Subject: [PATCH 48/66] Voodoo 64-bit recompiler: Fix shift in FOG_Z per report by skiretic. --- src/include/86box/vid_voodoo_codegen_x86-64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/vid_voodoo_codegen_x86-64.h b/src/include/86box/vid_voodoo_codegen_x86-64.h index b7028c7d7..a9701860c 100644 --- a/src/include/86box/vid_voodoo_codegen_x86-64.h +++ b/src/include/86box/vid_voodoo_codegen_x86-64.h @@ -2327,7 +2327,7 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addlong(offsetof(voodoo_state_t, z)); addbyte(0xc1); /*SHR EAX, 12*/ addbyte(0xe8); - addbyte(12); + addbyte(20); addbyte(0x25); /*AND EAX, 0xff*/ addlong(0xff); #if 0 From f23e88df4d6e9bb50fa34fddcd5b1209a6aa3f84 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 22 Feb 2026 01:44:51 -0500 Subject: [PATCH 49/66] Initial corrections to PAS16 DSP info --- src/include/86box/snd_sb_dsp.h | 1 + src/sound/snd_pas16.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/include/86box/snd_sb_dsp.h b/src/include/86box/snd_sb_dsp.h index 200912c42..b73508211 100644 --- a/src/include/86box/snd_sb_dsp.h +++ b/src/include/86box/snd_sb_dsp.h @@ -11,6 +11,7 @@ #define SB_SUBTYPE_CLONE_AZTPR16_0X09 3 /* Aztech Sound Galaxy Pro 16 Extra */ #define SB_SUBTYPE_ESS_ES688 4 /* ESS Technology ES688 */ #define SB_SUBTYPE_ESS_ES1688 5 /* ESS Technology ES1688 */ +#define SB_SUBTYPE_MVD201 6 /* Mediavision MVD201, found on the thunderboard and PAS16 */ /* ESS-related */ #define IS_ESS(dsp) ((dsp)->sb_subtype >= SB_SUBTYPE_ESS_ES688) /* Check for future ESS cards here */ diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 9b82d580d..d3addf41a 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -2327,7 +2327,7 @@ pas16_init(const device_t *info) pas16->has_scsi = (!pas16->type) || (pas16->type == 0x0f); fm_driver_get(FM_YMF262, &pas16->opl); sb_dsp_set_real_opl(&pas16->dsp, 1); - sb_dsp_init(&pas16->dsp, SB_DSP_201, SB_SUBTYPE_DEFAULT, pas16); + sb_dsp_init(&pas16->dsp, SB_DSP_200, SB_SUBTYPE_MVD201, pas16); pas16->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&pas16->dsp, pas16->mpu); From 97afe701a835c553b98b2747947b8cecc9ebe722 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 22 Feb 2026 03:57:31 -0500 Subject: [PATCH 50/66] Some cleanups to SB DSP, add two known missing DSP revisions --- src/include/86box/snd_sb.h | 6 ++++-- src/sound/snd_ad1816.c | 2 +- src/sound/snd_azt2316a.c | 2 +- src/sound/snd_cmi8x38.c | 2 +- src/sound/snd_optimc.c | 2 +- src/sound/snd_sb.c | 12 ++++++------ src/sound/snd_sb_dsp.c | 36 +++++++++++++++++++----------------- src/sound/snd_ymf701.c | 2 +- src/sound/snd_ymf71x.c | 2 +- 9 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 51822f210..394b1b249 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -28,12 +28,14 @@ enum { SADLIB = 1, /* No DSP */ - SB_DSP_105, /* DSP v1.05, Original CT1320 (Also known as CT1310) */ + SB_DSP_103, /* DSP v1.03, "killer card" prototype (Also known as CT1310) */ + SB_DSP_105, /* DSP v1.05, Original CT1320 */ SB_DSP_200, /* DSP v2.00 */ SB_DSP_201, /* DSP v2.01 - needed for high-speed DMA, Seen on CT1350B with CT1336 */ SB_DSP_202, /* DSP v2.02 - Seen on CT1350B with CT1336A */ SBPRO_DSP_300, /* DSP v3.00 */ - SBPRO2_DSP_302, /* DSP v3.02 + OPL3 */ + SBPRO_DSP_301, /* DSP v3.01 */ + SBPRO_DSP_302, /* DSP v3.02 */ SB16_DSP_404, /* DSP v4.05 + OPL3 */ SB16_DSP_405, /* DSP v4.05 + OPL3 */ SB16_DSP_406, /* DSP v4.06 + OPL3 */ diff --git a/src/sound/snd_ad1816.c b/src/sound/snd_ad1816.c index 4e929794d..d47f70a04 100644 --- a/src/sound/snd_ad1816.c +++ b/src/sound/snd_ad1816.c @@ -819,7 +819,7 @@ ad1816_init(const device_t *info) ad1816->sb->opl_enabled = 1; sb_dsp_set_real_opl(&ad1816->sb->dsp, FM_YMF262); - sb_dsp_init(&ad1816->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ad1816); + sb_dsp_init(&ad1816->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, ad1816); sb_dsp_setaddr(&ad1816->sb->dsp, ad1816->cur_sb_addr); sb_dsp_setirq(&ad1816->sb->dsp, ad1816->cur_irq); sb_dsp_setirq(&ad1816->sb->dsp, ad1816->cur_dma); diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index 08fca0f87..b7f981d5c 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -1835,7 +1835,7 @@ azt_init(const device_t *info) fm_driver_get(FM_YMF262, &azt2316a->sb->opl); sb_dsp_set_real_opl(&azt2316a->sb->dsp, 1); - sb_dsp_init(&azt2316a->sb->dsp, SBPRO2_DSP_302, azt2316a->type, azt2316a); + sb_dsp_init(&azt2316a->sb->dsp, SBPRO_DSP_302, azt2316a->type, azt2316a); sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c index d4490ac23..826f44bb0 100644 --- a/src/sound/snd_cmi8x38.c +++ b/src/sound/snd_cmi8x38.c @@ -877,7 +877,7 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) dev->sb->dsp.sbleftright_default = !!(val & 0x02); /* Enable or disable SB16 mode. */ - dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2_DSP_302 : SB16_DSP_405; + dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO_DSP_302 : SB16_DSP_405; break; case 0x22: diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index 5ea5d773c..0bad013ff 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -1095,7 +1095,7 @@ optimc_init(const device_t *info) optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262; sb_dsp_set_real_opl(&optimc->sb->dsp, optimc->fm_type != FM_YMF278B); - sb_dsp_init(&optimc->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, optimc); + sb_dsp_init(&optimc->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, optimc); sb_dsp_setaddr(&optimc->sb->dsp, optimc->cur_addr); sb_dsp_setirq(&optimc->sb->dsp, optimc->cur_irq); sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index c2193869d..9a9a9978a 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -3170,7 +3170,7 @@ sb_pro_v2_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3226,7 +3226,7 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); sb->mixer_enabled = 1; @@ -3258,7 +3258,7 @@ sb_pro_compat_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); sb->mixer_enabled = 1; @@ -3938,7 +3938,7 @@ ess_x688_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setaddr(&ess->dsp, addr); sb_dsp_setirq(&ess->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma")); @@ -4050,7 +4050,7 @@ ess_x688_pnp_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); @@ -4136,7 +4136,7 @@ ess_x688_mca_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 8adb46c5d..275c90576 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -85,20 +85,22 @@ char sb202_copyright[] = "COPYRIGHT(C) CREATIVE TECHNOLOGY PTE. LTD. (1991) char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; uint16_t sb_dsp_versions[] = { 0, /* Pad */ - 0, /* SADLIB - No DSP */ + 0, /* SADLIB - No DSP */ + 0x103, /* SB_DSP_103 - SB "killer card" prototype, DSP v1.03 */ 0x105, /* SB_DSP_105 - SB1/1.5, DSP v1.05 */ 0x200, /* SB_DSP_200 - SB1.5/2, DSP v2.00 */ 0x201, /* SB_DSP_201 - SB1.5/2, DSP v2.01 - needed for high-speed DMA */ 0x202, /* SB_DSP_202 - SB2, DSP v2.02 */ - 0x300, /* SB_PRO_DSP_300 - SB Pro, DSP v3.00 */ - 0x302, /* SBPRO2_DSP_302 - SB Pro 2, DSP v3.02 + OPL3 */ - 0x404, /* SB16_DSP_404 - DSP v4.04 + OPL3 */ - 0x405, /* SB16_405 - DSP v4.05 + OPL3 */ - 0x406, /* SB16_406 - DSP v4.06 + OPL3 */ - 0x40b, /* SB16_411 - DSP v4.11 + OPL3 */ - 0x40c, /* SBAWE32 - DSP v4.12 + OPL3 */ - 0x40d, /* SBAWE32PNP - DSP v4.13 + OPL3 */ - 0x410 /* SBAWE64 - DSP v4.16 + OPL3 */ + 0x300, /* SBPRO_DSP_300 - SB Pro, DSP v3.00 */ + 0x301, /* SBPRO_DSP_301 - SB Pro/Pro 2, DSP v3.01 */ + 0x302, /* SBPRO_DSP_302 - SB Pro/Pro 2, DSP v3.02 */ + 0x404, /* SB16_DSP_404 - DSP v4.04 + OPL3 */ + 0x405, /* SB16_DSP_405 - DSP v4.05 + OPL3 */ + 0x406, /* SB16_DSP_406 - DSP v4.06 + OPL3 */ + 0x40b, /* SB16_DSP_411 - DSP v4.11 + OPL3 */ + 0x40c, /* SBAWE32_DSP_412 - DSP v4.12 + OPL3 */ + 0x40d, /* SBAWE32_DSP_413 - DSP v4.13 + OPL3 */ + 0x410 /* SBAWE64_DSP_416 - DSP v4.16 + OPL3 */ }; /*These tables were 'borrowed' from DOSBox*/ @@ -1614,7 +1616,7 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0xA0: /* Set input mode to mono */ case 0xA8: /* Set input mode to stereo */ - if ((dsp->sb_type < SBPRO_DSP_300) || (dsp->sb_type > SBPRO2_DSP_302)) + if ((dsp->sb_type < SBPRO_DSP_300) || (dsp->sb_type > SBPRO_DSP_302)) break; /* TODO: Implement. 3.xx-only command. */ break; @@ -1859,12 +1861,12 @@ sb_exec_command(sb_dsp_t *dsp) * 059h Fetches the samples and then immediately plays them back. SB??? * 078h Auto-init DMA ADPCM SB2??? * 07Ah 2.6-bit ADPCM SB??? - * 0E3h DSP Copyright SBPro2??? (SBPRO2_DSP_302) - * 0F0h Sine Generator SB (SB_DSP_105, DSP20x) - * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 (DSP20x, SBPRO2_DSP_302) - * 0F2h IRQ Request, 8-bit SB (SB_DSP_105, DSP20x) + * 0E3h DSP Copyright SBPro2??? (SBPRO_DSP_302) + * 0F0h Sine Generator SB (SB_DSP_105, SB_DSP_20x) + * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 (SB_DSP_20x, SBPRO_DSP_302) + * 0F2h IRQ Request, 8-bit SB (SB_DSP_105, SB_DSP_20x) * 0F3h IRQ Request, 16-bit SB16 - * 0F4h Perform ROM checksum SB (SB_DSP_105, DSP20x) + * 0F4h Perform ROM checksum SB (SB_DSP_105, SB_DSP_20x) * 0FBh DSP Status SB16 * 0FCh DSP Auxiliary Status SB16 * 0FDh DSP Command Status SB16 @@ -2236,7 +2238,7 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) a set frequency command is sent. */ recalc_sb16_filter(0, 3200 * 2); } - if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2_DSP_302)) { + if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO_DSP_302)) { /* OPL3 or dual OPL2 is stereo. */ if (dsp->sb_has_real_opl) recalc_opl_filter(FREQ_49716 * 2); diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index c6b1467c8..c599eed9e 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -419,7 +419,7 @@ ymf701_init(const device_t *info) ymf701->sb->opl_enabled = 1; sb_dsp_set_real_opl(&ymf701->sb->dsp, 1); - sb_dsp_init(&ymf701->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ymf701); + sb_dsp_init(&ymf701->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, ymf701); sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_sb_addr); sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_sb_irq); sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_sb_dma); diff --git a/src/sound/snd_ymf71x.c b/src/sound/snd_ymf71x.c index 70ccf6872..4886e69b8 100644 --- a/src/sound/snd_ymf71x.c +++ b/src/sound/snd_ymf71x.c @@ -712,7 +712,7 @@ ymf71x_init(const device_t *info) ymf71x->sb->opl_enabled = 1; sb_dsp_set_real_opl(&ymf71x->sb->dsp, 1); - sb_dsp_init(&ymf71x->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ymf71x); + sb_dsp_init(&ymf71x->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, ymf71x); sb_ct1345_mixer_reset(ymf71x->sb); ymf71x->sb->opl_mixer = ymf71x; From 2bb0ad3165f9f60edd0123a67f5d0c9bb1ebe80c Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 22 Feb 2026 03:59:17 -0500 Subject: [PATCH 51/66] Correct ESS x688 DSP revisions --- src/sound/snd_sb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 9a9a9978a..de9b71f9b 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -3938,7 +3938,7 @@ ess_x688_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO_DSP_301, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setaddr(&ess->dsp, addr); sb_dsp_setirq(&ess->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma")); @@ -4050,7 +4050,7 @@ ess_x688_pnp_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO_DSP_301, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); @@ -4136,7 +4136,7 @@ ess_x688_mca_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO_DSP_301, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); From 597adb5897aa713d63d65f090c3c0c28e9ba0d37 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Sun, 22 Feb 2026 15:56:07 +0600 Subject: [PATCH 52/66] Add functionality to emulate QLogic ISP SCSI HBA devices Tested with Windows 2000 and NetBSD 10.1. Target Mode is not implemented, because I had no OS using it. --- src/include/86box/pci.h | 37 + src/include/86box/scsi_qlogic.h | 19 + src/scsi/CMakeLists.txt | 1 + src/scsi/scsi.c | 6 + src/scsi/scsi_ql1xxx.c | 4581 +++++++++++++++++++++++++++++++ 5 files changed, 4644 insertions(+) create mode 100644 src/include/86box/scsi_qlogic.h create mode 100644 src/scsi/scsi_ql1xxx.c diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index f5f5aee04..d07dff7eb 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -31,6 +31,43 @@ #define PCI_REG_LATENCY_TIMER 0x0d #define PCI_REG_HEADER_TYPE 0x0e #define PCI_REG_BIST 0x0f +#define PCI_REG_BAR0_BYTE0 0x10 +#define PCI_REG_BAR0_BYTE1 0x11 +#define PCI_REG_BAR0_BYTE2 0x12 +#define PCI_REG_BAR0_BYTE3 0x13 +#define PCI_REG_BAR1_BYTE0 0x14 +#define PCI_REG_BAR1_BYTE1 0x15 +#define PCI_REG_BAR1_BYTE2 0x16 +#define PCI_REG_BAR1_BYTE3 0x17 +#define PCI_REG_BAR2_BYTE0 0x18 +#define PCI_REG_BAR2_BYTE1 0x19 +#define PCI_REG_BAR2_BYTE2 0x1a +#define PCI_REG_BAR2_BYTE3 0x1b +#define PCI_REG_BAR3_BYTE0 0x1c +#define PCI_REG_BAR3_BYTE1 0x1d +#define PCI_REG_BAR3_BYTE2 0x1e +#define PCI_REG_BAR3_BYTE3 0x1e +#define PCI_REG_BAR4_BYTE0 0x20 +#define PCI_REG_BAR4_BYTE1 0x21 +#define PCI_REG_BAR4_BYTE2 0x22 +#define PCI_REG_BAR4_BYTE3 0x23 +#define PCI_REG_BAR5_BYTE0 0x24 +#define PCI_REG_BAR5_BYTE1 0x25 +#define PCI_REG_BAR5_BYTE2 0x26 +#define PCI_REG_BAR5_BYTE3 0x27 +#define PCI_REG_SUBVEN_ID_L 0x2c +#define PCI_REG_SUBVEN_ID_H 0x2d +#define PCI_REG_SUBSYS_ID_L 0x2e +#define PCI_REG_SUBSYS_ID_H 0x2f +#define PCI_REG_ROM_BAR_BYTE0 0x30 +#define PCI_REG_ROM_BAR_BYTE1 0x31 +#define PCI_REG_ROM_BAR_BYTE2 0x32 +#define PCI_REG_ROM_BAR_BYTE3 0x33 +#define PCI_REG_CAPS_PTR 0x34 +#define PCI_REG_INT_LINE 0x3c +#define PCI_REG_INT_PIN 0x3d +#define PCI_REG_MIN_GRANT 0x3e +#define PCI_REG_MAX_LAT 0x3f #define PCI_COMMAND_L_IO 0x01 #define PCI_COMMAND_L_MEM 0x02 diff --git a/src/include/86box/scsi_qlogic.h b/src/include/86box/scsi_qlogic.h new file mode 100644 index 000000000..f3c0a695e --- /dev/null +++ b/src/include/86box/scsi_qlogic.h @@ -0,0 +1,19 @@ +/* + * 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. + * + * Emulation of QLogic QLA1x40/QLA1x80/QLA1x160 SCSI HBA. + * + * Authors: Dmitry Borisov, + * + * Copyright 2026 Dmitry Borisov + */ +#pragma once + +extern const device_t qla1040b_device; +extern const device_t qla1080_device; +extern const device_t qla1240_device; +extern const device_t qla1280_device; +extern const device_t qla12160a_device; diff --git a/src/scsi/CMakeLists.txt b/src/scsi/CMakeLists.txt index c710f758d..63bf9c225 100644 --- a/src/scsi/CMakeLists.txt +++ b/src/scsi/CMakeLists.txt @@ -28,5 +28,6 @@ add_library(scsi OBJECT scsi_t128.c scsi_ncr53c8xx.c scsi_pcscsi.c + scsi_ql1xxx.c scsi_spock.c ) diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index 36e1d0638..89ea9fc29 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -38,6 +38,7 @@ #include <86box/scsi_ncr5380.h> #include <86box/scsi_ncr53c8xx.h> #include <86box/scsi_pcscsi.h> +#include <86box/scsi_qlogic.h> #include <86box/scsi_spock.h> int scsi_card_current[SCSI_CARD_MAX] = { 0, 0, 0, 0 }; @@ -91,6 +92,11 @@ static SCSI_CARD scsi_cards[] = { { &ncr53c860_pci_device, }, { &ncr53c875_pci_device, }, { &dc390_pci_device, }, + { &qla1040b_device, }, + { &qla1080_device, }, + { &qla1240_device, }, + { &qla1280_device, }, + { &qla12160a_device, }, { NULL, }, // clang-format on }; diff --git a/src/scsi/scsi_ql1xxx.c b/src/scsi/scsi_ql1xxx.c new file mode 100644 index 000000000..def034163 --- /dev/null +++ b/src/scsi/scsi_ql1xxx.c @@ -0,0 +1,4581 @@ +/* + * 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. + * + * QLogic QLA1x40/QLA1x80/QLA1x160 SCSI HBA emulation. + * + * Register values are derived from the Matthew Jacob's + * multiplatform driver for ISP chipsets. + * + * Authors: Dmitry Borisov, + * + * Copyright 2026 Dmitry Borisov + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/dma.h> +#include <86box/rom.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/pci.h> +#include <86box/scsi.h> +#include <86box/scsi_device.h> +#include <86box/scsi_qlogic.h> +#include <86box/nmc93cxx.h> +#include <86box/fifo8.h> +#include <86box/plat_unused.h> +#include <86box/plat_fallthrough.h> + +#include "cpu.h" + +#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0]) + +/* + * Device configuration + */ +#define QL_CFG_BIOS_ENABLE "bios" +#define QL_CFG_BIOS_REVISION "bios_rev" + +/* + * Device info->local definitions + */ +#define QL_DEV_CHIP_TYPE_MASK 0x000000FF +#define QL_DEV_CHIP_REV_MASK 0x00000F00 +#define QL_DEV_FLASH_TYPE_MASK 0x0000F000 +#define QL_DEV_CHIP_REV_SHIFT 8 +#define QL_DEV_FLASH_TYPE_SHIFT 12 + +#define QL_ISP1040 0x00000000 +#define QL_ISP1080 0x00000001 +#define QL_ISP1240 0x00000002 +#define QL_ISP1280 0x00000003 +#define QL_ISP12160 0x00000004 +#define QL_REV_ISP1080 0x00000100 +#define QL_REV_ISP1020 0x00000000 +#define QL_REV_ISP1020A 0x00000100 +#define QL_REV_ISP1040 0x00000200 +#define QL_REV_ISP1040A 0x00000300 +#define QL_REV_ISP1040B 0x00000400 +#define QL_REV_ISP1040C 0x00000500 +#define QL_FLASH_AM29F010 0x00000000 +#define QL_FLASH_AM29LV010B 0x00000100 + +/* ISP firmware version extracted from the BIOS */ +#define ISP_FW_VER(Major, Minor, Micro) (((Major) << 16) | ((Minor) << 8) | (Micro)) + +/* Address of the IOCB handler in firmware for the 1040 ISP chips */ +#define QL_IOCB_FW_BASE 0x0700 + +/* Maximum SCSI devices supported by the chip */ +#define QL_MAX_TID 16 + +#define QL_PCI_PM_BASE 0x44 +#define QL_PCI_IO_BAR_SIZE 0x100 +#define QL_PCI_MMIO_BAR_SIZE 0x1000 +#define QL_PCI_ROM_BAR_64K_SIZE 0x10000 +#define QL_PCI_ROM_BAR_128K_SIZE 0x20000 + +#define QL_IO_DECODE_MASK (QL_PCI_IO_BAR_SIZE - 1) + +/* The hardware register layout consists of a set of 2-byte aligned registers */ +#define REG_TO_IDX(x) ((x) / 2) +#define IDX_TO_REG(x) ((x) * 2) + +/* + * Flash command definitions + */ +#define FLASH_CMD_CHIP_ERASE_CONFIRM 0x10 +#define FLASH_CMD_BLOCK_ERASE_CONFIRM 0x30 +#define FLASH_CMD_SETUP_ERASE 0x80 +#define FLASH_CMD_AUTO_SELECT 0x90 +#define FLASH_CMD_PROGRAM 0xA0 +#define FLASH_CMD_READ_ARRAY 0xF0 + +/* + * Flash status register definitions + */ +#define FLASH_STATUS_ERASE_TIMEOUT_EXPIRED 0x08 // DQ3 +#define FLASH_STATUS_ERROR 0x20 // DQ5 +#define FLASH_STATUS_TOGGLE 0x40 // DQ6 +#define FLASH_STATUS_DATA_POLLING 0x80 // DQ7 + +/* + * Flash block brotection status definitions + */ +#define FLASH_BLOCK_STATUS_NOT_PROTECTED 0x00 +#define FLASH_BLOCK_STATUS_PROTECTED 0x01 + +/* All boards use Am29F010 or Am29LV010B, which are 128KB in size */ +#define AM29_FLASH_SIZE 0x20000 +#define AM29_MAX_BLOCKS 8 + +#define AM29_MANUFACTURER_ID 0x01 // AMD +#define AM29F010_MODEL_ID 0x20 +#define AM29LV010B_MODEL_ID 0x6E + +#define AM29_BLOCK_ERASE_ACCEPT_TIMEOUT_US 50.0 // 50 us + +/* A0-A1 */ +#define AM29_AUTOSEL_ADDR_MASK 0x3 + +/* Read the manufacturer ID. A0 = 0, A1 = 0 */ +#define AM29_AUTOSEL_ADDR_MANUFACTURER_ID 0x0 + +/* Read the model ID. A0 = 1, A1 = 0 */ +#define AM29_AUTOSEL_ADDR_MODEL_ID 0x1 + +/* + * Hardware registers + */ +#define QL_REG_ID_LOW REG_TO_IDX(0x00) +#define QL_REG_ID_HIGH REG_TO_IDX(0x02) +#define QL_REG_CFG0 REG_TO_IDX(0x04) +#define QL_REG_CFG1 REG_TO_IDX(0x06) +#define QL_REG_INT_CTRL REG_TO_IDX(0x08) +#define QL_REG_INT_STATUS REG_TO_IDX(0x0A) +#define QL_REG_SEMAPHORE REG_TO_IDX(0x0C) +#define QL_REG_NVRAM REG_TO_IDX(0x0E) +#define QL_REG_FLASH_BIOS_DATA REG_TO_IDX(0x10) +#define QL_REG_FLASH_BIOS_ADDRESS REG_TO_IDX(0x12) +#define QL_REG_MAILBOX0 REG_TO_IDX(0x70) +#define QL_REG_MAILBOX1 REG_TO_IDX(0x72) +#define QL_REG_MAILBOX2 REG_TO_IDX(0x74) +#define QL_REG_MAILBOX3 REG_TO_IDX(0x76) +#define QL_REG_MAILBOX4 REG_TO_IDX(0x78) +#define QL_REG_MAILBOX5 REG_TO_IDX(0x7A) +#define QL_REG_MAILBOX6 REG_TO_IDX(0x7C) +#define QL_REG_MAILBOX7 REG_TO_IDX(0x7E) + +/* RISC bank registers (at offset 0x80) */ +#define QL_REG_RISC_PSR REG_TO_IDX(0x20) +#define QL_REG_RISC_PCR REG_TO_IDX(0x24) +#define QL_REG_RISC_PC REG_TO_IDX(0x2C) +#define QL_REG_RISC_MTR REG_TO_IDX(0x2E) +#define QL_REG_HOST_CMD REG_TO_IDX(0x40) +#define QL_REG_GPIO_DATA REG_TO_IDX(0x4C) +#define QL_REG_GPIO_ENABLE REG_TO_IDX(0x4E) + +/* SXP bank registers (at offset 0x80) */ +#define QL_REG_SXP_PINS_DIFF REG_TO_IDX(0x76) + +/* DMA bank registers (at offset 0x20 for the 1040, for other chips at offset 0x80) */ +#define QL_REG_CDMA_CFG REG_TO_IDX(0x00) +#define QL_REG_CDMA_CTRL REG_TO_IDX(0x02) +#define QL_REG_CDMA_STATUS REG_TO_IDX(0x04) +#define QL_REG_CDMA_FIFO_STATUS REG_TO_IDX(0x06) +#define QL_REG_CDMA_COUNT REG_TO_IDX(0x08) +#define QL_REG_CDMA_ADDR0 REG_TO_IDX(0x0C) +#define QL_REG_CDMA_ADDR1 REG_TO_IDX(0x0E) +#define QL_REG_CDMA_ADDR2 REG_TO_IDX(0x10) +#define QL_REG_CDMA_ADDR3 REG_TO_IDX(0x12) +#define QL_REG_DDMA_CFG REG_TO_IDX(0x20) +#define QL_REG_DDMA_CTRL REG_TO_IDX(0x22) +#define QL_REG_DDMA_STATUS REG_TO_IDX(0x24) +#define QL_REG_DDMA_FIFO_STATUS REG_TO_IDX(0x26) +#define QL_REG_DDMA_XFER_COUNT_LOW REG_TO_IDX(0x28) +#define QL_REG_DDMA_XFER_COUNT_HIGH REG_TO_IDX(0x2A) +#define QL_REG_DDMA_ADDR0 REG_TO_IDX(0x2C) +#define QL_REG_DDMA_ADDR1 REG_TO_IDX(0x2E) +#define QL_REG_DDMA_ADDR2 REG_TO_IDX(0x30) +#define QL_REG_DDMA_ADDR3 REG_TO_IDX(0x32) +#define QL_REG_DDMA_DATA_PORT REG_TO_IDX(0x42) + +/* QL_REG_SXP_PINS_DIFF */ +#define SXP_PINS_SE_MODE 0x0400 +#define SXP_PINS_HVD_MODE 0x0800 +#define SXP_PINS_LVD_MODE 0x1000 + +/* QL_REG_CFG0 */ +#define BIU_CONF0_HW_MASK 0x000F /* Hardware revision mask */ + +#define BIU_CONF0_REV_1020 0x0000 +#define BIU_CONF0_REV_1020A 0x0001 +#define BIU_CONF0_REV_1040 0x0002 +#define BIU_CONF0_REV_1040A 0x0003 +#define BIU_CONF0_REV_1040B 0x0004 +#define BIU_CONF0_REV_1040C 0x0005 + +#define BIU_CONF0_REV_1080 0x0001 + +/* QL_REG_CFG1 */ +#define BIU_BURST_ENABLE 0x0004 +#define BIU_PCI_CONF1_SXP 0x0008 /* SXP bank select (1040 only) */ +#define BIU_PCI_CONF1_FIFO_16 0x0010 +#define BIU_PCI_CONF1_FIFO_32 0x0020 +#define BIU_PCI_CONF1_FIFO_64 0x0030 +#define BIU_PCI_CONF1_FIFO_128 0x0040 + +#define BIU_PCI1080_CONF1_SXP0 0x0100 /* SXP bank #1 select */ +#define BIU_PCI1080_CONF1_SXP1 0x0200 /* SXP bank #2 select */ +#define BIU_PCI1080_CONF1_DMA 0x0300 /* DMA bank select */ +#define BIU_PCI1080_REG_BANK_MASK 0x0700 /* Bank mask */ + +/* QL_REG_INT_CTRL */ +#define QL_IFACE_SOFT_RESET 0x0001 +#define QL_IFACE_FLASH_ENABLE 0x0100 + +/* QL_REG_INT_STATUS and QL_REG_INT_CTRL */ +#define QL_INTR_REQ 0x0002 +#define QL_RISC_INTR_REQ 0x0004 + +/* QL_REG_SEMAPHORE */ +#define QL_SEMAPHORE_LOCK 0x0001 +#define QL_SEMAPHORE_STATUS 0x0002 + +/* QL_REG_NVRAM */ +#define QL_EEPROM_SK 0x0001 +#define QL_EEPROM_CS 0x0002 +#define QL_EEPROM_DI 0x0004 +#define QL_EEPROM_DO 0x0008 + +/* QL_REG_HOST_CMD read */ +#define QL_HC_FLAG_RISC_EXT 0x0010 +#define QL_HC_FLAG_RISC_PAUSE 0x0020 +#define QL_HC_FLAG_RISC_RESET 0x0040 +#define QL_HC_FLAG_HOST_INTR 0x0080 + +/* QL_REG_HOST_CMD write */ +#define QL_HC_RESET_RISC 0x1000 +#define QL_HC_PAUSE_RISC 0x2000 +#define QL_HC_RELEASE_RISC 0x3000 +#define QL_HC_SET_HOST_INTR 0x5000 +#define QL_HC_CLEAR_HOST_INTR 0x6000 +#define QL_HC_CLEAR_RISC_INTR 0x7000 +#define QL_HC_DISABLE_BIOS 0x9000 + +/* + * All IOCB Queue entries are this size + */ +#define QENTRY_LEN 64 + +/* + * Mailbox commands + */ +#define QL_CMD_NOP 0x0000 +#define QL_CMD_LOAD_RAM 0x0001 +#define QL_CMD_EXEC_FIRMWARE 0x0002 +#define QL_CMD_DUMP_RAM 0x0003 +#define QL_CMD_WRITE_RAM_WORD 0x0004 +#define QL_CMD_READ_RAM_WORD 0x0005 +#define QL_CMD_REGISTER_TEST 0x0006 +#define QL_CMD_VERIFY_CHECKSUM 0x0007 +#define QL_CMD_ABOUT_FIRMWARE 0x0008 +#define QL_CMD_LOAD_RAM_A64 0x0009 +#define QL_CMD_DUMP_RAM_A64 0x000A +#define QL_CMD_INIT_REQ_QUEUE 0x0010 +#define QL_CMD_INIT_RSP_QUEUE 0x0011 +#define QL_CMD_EXECUTE_IOCB 0x0012 +#define QL_CMD_ABORT_COMMAND 0x0015 +#define QL_CMD_ABORT_DEVICE 0x0016 +#define QL_CMD_ABORT_TARGET 0x0017 +#define QL_CMD_BUS_RESET 0x0018 +#define QL_CMD_START_QUEUE 0x001A +#define QL_CMD_GET_FIRMWARE_STATUS 0x001F +#define QL_CMD_GET_RETRY_COUNT 0x0022 +#define QL_CMD_GET_ACT_NEG_STATE 0x0025 +#define QL_CMD_GET_TARGET_PARAMETERS 0x0028 +#define QL_CMD_SET_INITIATOR_ID 0x0030 +#define QL_CMD_SET_SELECTION_TIMEOUT 0x0031 +#define QL_CMD_SET_RETRY_COUNT 0x0032 +#define QL_CMD_SET_TAG_AGE_LIMIT 0x0033 +#define QL_CMD_SET_CLOCK_RATE 0x0034 +#define QL_CMD_SET_ACTIVE_NEGATION 0x0035 +#define QL_CMD_SET_ASYNC_DATA_SETUP 0x0036 +#define QL_CMD_SET_PCI_CONTROL 0x0037 +#define QL_CMD_SET_TARGET_PARAMETERS 0x0038 +#define QL_CMD_SET_DEVICE_QUEUE 0x0039 +#define QL_CMD_RETURN_BIOS_BLOCK_ADDR 0x0040 +#define QL_CMD_WRITE_FOUR_RAM_WORDS 0x0041 +#define QL_CMD_EXEC_BIOS_IOCB 0x0042 +#define QL_CMD_SET_SYSTEM_PARAMETER 0x0045 +#define QL_CMD_SET_FIRMWARE_FEATURES 0x004A +#define QL_CMD_INIT_REQ_QUEUE_A64 0x0052 +#define QL_CMD_INIT_RSP_QUEUE_A64 0x0053 +#define QL_CMD_EXECUTE_IOCB_A64 0x0054 +#define QL_CMD_GET_TRANSFER_MODE 0x0059 +#define QL_CMD_SET_DATA_OVERRUN_RECOVERY 0x005A + +/* + * Mailbox command complete status codes + */ +#define QL_MBOX_STATUS_COMPLETE 0x4000 +#define QL_MBOX_STATUS_INVALID 0x4001 +#define QL_MBOX_STATUS_HOST_IFACE_ERROR 0x4002 +#define QL_MBOX_STATUS_TEST_FAILED 0x4003 +#define QL_MBOX_STATUS_CMD_ERROR 0x4005 +#define QL_MBOX_STATUS_CMD_PARAM_ERROR 0x4006 +#define QL_MBOX_STATUS_PENDING 0xFFFF // Invalid, for internal use only + +/* + * Mailbox asynchronous event status codes + */ +#define QL_ASYNC_STATUS_BUS_RESET 0x8001 +#define QL_ASYNC_STATUS_SYSTEM_ERROR 0x8002 +#define QL_ASYNC_STATUS_REQ_XFER_ERROR 0x8003 +#define QL_ASYNC_STATUS_RSP_XFER_ERROR 0x8004 +#define QL_ASYNC_STATUS_SCSI_CMD_COMPLETE 0x8020 + +/* + * Mailbox I/O interface registers + */ +#define QL_MBOX_STATUS 0 +#define QL_MBOX_HNDL_LOW 1 +#define QL_MBOX_HNDL_HIGH 2 +#define QL_MBOX_RQST 4 +#define QL_MBOX_RESP 5 +#define QL_MBOX_REGS_MAX 8 + +/* + * Request and response ring helpers + */ +#define QL_RQST_CONS(dev) ((dev)->reg_mbox_out[QL_MBOX_RQST]) // consumer (HW) +#define QL_RQST_PROD(dev) ((dev)->reg_mbox_in[QL_MBOX_RQST]) // producer (SW) +#define QL_RESP_CONS(dev) ((dev)->reg_mbox_in[QL_MBOX_RESP]) // consumer (SW) +#define QL_RESP_PROD(dev) ((dev)->reg_mbox_out[QL_MBOX_RESP]) // producer (HW) + +/* + * Firmware features flags (QL_CMD_SET_FIRMWARE_FEATURES) + */ +#define FW_FEATURE_FAST_POST 0x1 +#define FW_FEATURE_LVD_NOTIFY 0x2 +#define FW_FEATURE_RIO_32BIT 0x4 +#define FW_FEATURE_RIO_16BIT 0x8 + +/* + * Request header flags definitions + */ +#define RQSFLAG_CONTINUATION 0x01 +#define RQSFLAG_FULL 0x02 +#define RQSFLAG_BADHEADER 0x04 +#define RQSFLAG_BADPACKET 0x08 +#define RQSFLAG_BADCOUNT 0x10 +#define RQSFLAG_BADORDER 0x20 +#define RQSFLAG_MASK 0x3F + +/* + * Request header entry_type definitions + */ +#define RQSTYPE_REQUEST 0x01 +#define RQSTYPE_DATASEG 0x02 +#define RQSTYPE_RESPONSE 0x03 +#define RQSTYPE_MARKER 0x04 +#define RQSTYPE_CMDONLY 0x05 +#define RQSTYPE_ATIO 0x06 // Target Mode +#define RQSTYPE_CTIO 0x07 // Target Mode +#define RQSTYPE_REQUEST_A64 0x09 +#define RQSTYPE_A64_CONT 0x0A +#define RQSTYPE_ENABLE_LUN 0x0B // Target Mode +#define RQSTYPE_MODIFY_LUN 0x0C // Target Mode +#define RQSTYPE_NOTIFY 0x0D // Target Mode +#define RQSTYPE_NOTIFY_ACK 0x0E // Target Mode +#define RQSTYPE_CTIO_A64 0x0F // Target Mode + +/* + * Request flags values + */ +#define REQFLAG_NODISCON 0x0001 +#define REQFLAG_HTAG 0x0002 +#define REQFLAG_OTAG 0x0004 +#define REQFLAG_STAG 0x0008 +#define REQFLAG_TARGET_RTN 0x0010 + +#define REQFLAG_NODATA 0x0000 +#define REQFLAG_DATA_IN 0x0020 +#define REQFLAG_DATA_OUT 0x0040 +#define REQFLAG_DATA_BIDIRECTIONAL 0x0060 + +#define REQFLAG_DISARQ 0x0100 +#define REQFLAG_FRC_ASYNC 0x0200 +#define REQFLAG_FRC_SYNC 0x0400 +#define REQFLAG_FRC_WIDE 0x0800 +#define REQFLAG_NOPARITY 0x1000 +#define REQFLAG_STOPQ 0x2000 +#define REQFLAG_XTRASNS 0x4000 +#define REQFLAG_PRIORITY 0x8000 + +/* + * Request completion status cdes + */ +#define RQCS_COMPLETE 0x0000 +#define RQCS_INCOMPLETE 0x0001 +#define RQCS_DMA_ERROR 0x0002 +#define RQCS_TRANSPORT_ERROR 0x0003 +#define RQCS_RESET_OCCURRED 0x0004 +#define RQCS_ABORTED 0x0005 +#define RQCS_TIMEOUT 0x0006 +#define RQCS_DATA_OVERRUN 0x0007 +#define RQCS_COMMAND_OVERRUN 0x0008 +#define RQCS_STATUS_OVERRUN 0x0009 +#define RQCS_BAD_MESSAGE 0x000A +#define RQCS_NO_MESSAGE_OUT 0x000B +#define RQCS_EXT_ID_FAILED 0x000C +#define RQCS_IDE_MSG_FAILED 0x000D +#define RQCS_ABORT_MSG_FAILED 0x000E +#define RQCS_REJECT_MSG_FAILED 0x000F +#define RQCS_NOP_MSG_FAILED 0x0010 +#define RQCS_PARITY_ERROR_MSG_FAILED 0x0011 +#define RQCS_DEVICE_RESET_MSG_FAILED 0x0012 +#define RQCS_ID_MSG_FAILED 0x0013 +#define RQCS_UNEXP_BUS_FREE 0x0014 +#define RQCS_DATA_UNDERRUN 0x0015 +#define RQCS_XACT_ERR1 0x0018 +#define RQCS_XACT_ERR2 0x0019 +#define RQCS_XACT_ERR3 0x001A +#define RQCS_BAD_ENTRY 0x001B +#define RQCS_PHASE_SKIPPED 0x001D +#define RQCS_ARQS_FAILED 0x001E +#define RQCS_WIDE_FAILED 0x001F +#define RQCS_QUEUE_FULL 0x001C +#define RQCS_SYNCXFER_FAILED 0x0020 +#define RQCS_LVD_BUSERR 0x0021 + +/* + * Request State Flags + */ +#define RQSF_GOT_BUS 0x0100 +#define RQSF_GOT_TARGET 0x0200 +#define RQSF_SENT_CDB 0x0400 +#define RQSF_XFRD_DATA 0x0800 +#define RQSF_GOT_STATUS 0x1000 +#define RQSF_GOT_SENSE 0x2000 +#define RQSF_XFER_COMPLETE 0x4000 + +/* + * Request Status Flags + */ +#define RQSTF_DISCONNECT 0x0001 +#define RQSTF_SYNCHRONOUS 0x0002 +#define RQSTF_PARITY_ERROR 0x0004 +#define RQSTF_BUS_RESET 0x0008 +#define RQSTF_DEVICE_RESET 0x0010 +#define RQSTF_ABORTED 0x0020 +#define RQSTF_TIMEOUT 0x0040 +#define RQSTF_NEGOTIATION 0x0080 + +/* + * Device Flags (QL_CMD_SET_TARGET_PARAMETERS, QL_CMD_GET_TARGET_PARAMETERS) + */ +#define DPARM_PPR 0x0020 +#define DPARM_ASYNC 0x0040 +#define DPARM_NARROW 0x0080 +#define DPARM_RENEG 0x0100 +#define DPARM_QFRZ 0x0200 +#define DPARM_ARQ 0x0400 +#define DPARM_TQING 0x0800 +#define DPARM_SYNC 0x1000 +#define DPARM_WIDE 0x2000 +#define DPARM_PARITY 0x4000 +#define DPARM_DISC 0x8000 + +/* + * Generic mailbox command completion time. + * On QLA1080 real hardware the loading of firmware image (15675 words) + * via PIO takes approximately 1878 ms. + */ +#define QL_MBOX_GENERIC_TIME_US 110 // 110 us + +/* + * Command completion time when the SCSI device does not exists, + * measured on QLA1080 real hardware. + */ +#define QL_CMD_SELECTION_TIMEOUT_TIME_US 370000 // 370 ms + +#define SXP_FLAG_ENGINE_ACTIVE 0x00000001 +#define SXP_FLAG_PICK_UP_MBOX 0x00000002 +#define SXP_FLAG_FAST_POSTING 0x00000004 +#define SXP_FLAG_MBOX_IOCB 0x00000008 +#define SXP_FLAG_BIOS_IOCB 0x00000010 +#define SXP_FLAG_WRITE_RESP_IOCB 0x00000020 +#define SXP_FLAG_INC_RESP_RING 0x00000040 +#define SXP_FLAG_ABORTED_CMD 0x00000080 + +#define QL_BIT(b) (1 << (b)) + +#define ql_dma_write(address, buffer, size) dma_bm_write(address, (uint8_t *)(buffer), size, 4); +#define ql_dma_write8(address, buffer) dma_bm_write(address, (uint8_t *)(buffer), 1, 4); +#define ql_dma_write16(address, buffer) dma_bm_write(address, (uint8_t *)(buffer), 2, 4); +#define ql_dma_write32(address, buffer) dma_bm_write(address, (uint8_t *)(buffer), 4, 4); + +#define ql_dma_read(address, buffer, size) dma_bm_read(address, (uint8_t *)(buffer), size, 4); +#define ql_dma_read8(address, buffer) dma_bm_read(address, (uint8_t *)(buffer), 1, 4); +#define ql_dma_read16(address, buffer) dma_bm_read(address, (uint8_t *)(buffer), 2, 4); +#define ql_dma_read32(address, buffer) dma_bm_read(address, (uint8_t *)(buffer), 4, 4); + +typedef enum FlashMode { + M_READ_ARRAY, + M_AUTO_SELECT, + M_PROGRAM, + M_BLOCK_ERASE, + M_CHIP_ERASE, + M_MAX, +} FlashMode; + +typedef enum FlashBusCycleState { + CYCLE_INVALID, + CYCLE_CHECK_55, + CYCLE_CHECK_AA, + CYCLE_CHECK_FIRST_CMD, + CYCLE_CHECK_SECOND_CMD, + CYCLE_ENTER_PROGRAM, +} FlashBusCycleState; + +typedef struct flash_block_t { + /* Block index */ + uint32_t number; + /* Starting address */ + uint32_t start_addr; + /* Ending address */ + uint32_t end_addr; + /* Block protection status */ + uint8_t protection_status; +} flash_block_t; + +typedef struct flash_t { + /* Data access cycles */ + int access_cycles; + /* BIOS image (memory array data) */ + uint8_t *array_data; + /* Operation mode */ + FlashMode mode; + /* Command bus cycle */ + uint8_t bus_cycle; + /* Command decoder state */ + uint8_t cmd_cycle; + /* Write operation status register */ + uint8_t status_reg; + /* Manufacturer ID */ + uint8_t manufacturer_id; + /* Model ID */ + uint8_t model_id; + /* Block select address mask for erase operations */ + uint32_t block_select_addr_mask; + /* Address mask for command decode */ + uint32_t cmd_cycle_addr_mask; + /* Physical address of the AAAA coded cycle */ + uint32_t addr_AAAA_phys; + /* Physical address of the 5555 coded cycle */ + uint32_t addr_5555_phys; + /* Bitmap of pending blocks for erase operation */ + uint32_t blocks_to_erase_bitmap; + /* Byte programming time */ + double program_time_us; + /* Block erase time */ + double block_erase_time_us; + /* Chip erase time */ + double chip_erase_time_us; + /* Erase timer */ + pc_timer_t erase_accept_timeout_timer; + /* Command completion timer */ + pc_timer_t cmd_complete_timer; + /* Blocks (sectors) */ + flash_block_t block[AM29_MAX_BLOCKS]; + /* Name of BIOS image file */ + char filename[1024]; +} flash_t; + +typedef struct isp_hdr_t { + uint8_t entry_type; + uint8_t entry_count; + uint8_t seqno; + uint8_t flags; +} isp_hdr_t; + +typedef struct isp_data_seg_t { + uint32_t address; + uint32_t length; +} isp_data_seg_t; + +/* RQSTYPE_RESPONSE HW structure */ +typedef struct isp_req_status_t { + isp_hdr_t hdr; + uint32_t handle; + uint16_t scsi_status; + uint16_t comp_status; + uint16_t state_flags; + uint16_t status_flags; + uint16_t time; + uint16_t sense_length; + uint32_t residual_length; + uint8_t response[8]; + uint8_t sense_data[32]; +} isp_req_status_t; + +typedef enum SxpState { + SXP_STATE_IDLE, + SXP_STATE_BAD_PACKET, + SXP_STATE_SELECT_DEVICE, + SXP_STATE_SELECTION_TIMEOUT, + SXP_STATE_SEND_CDB, + SXP_STATE_COMPLETE_COMMAND, + SXP_STATE_SCHEDULE_MBOX_INTERRUPT, + SXP_STATE_ACQUIRE_MBOX_SEMAPHORE, + SXP_STATE_SCHEDULE_RISC_INTERRUPT, + SXP_STATE_SET_RISC_INTERRUPT, + SXP_STATE_SCHEDULE_TIMER_SILENCE, + SXP_STATE_MBOX_WAIT_TIMER, + SXP_STATE_WAIT_TIMER, +} SxpState; + +/* Common structure for request entries (RQSTYPE_REQUEST, RQSTYPE_REQUEST_A64, RQSTYPE_MARKER) */ +typedef struct ql_sxp_req_t { + isp_hdr_t hdr; + uint32_t handle; + uint8_t lun; + uint8_t bus_target; + uint16_t cdb_length; + uint16_t flags; + uint16_t reserved; + uint16_t timeout; + uint16_t seg_count; + uint8_t cdb[12]; +} ql_sxp_req_t; + +typedef struct ql_fw_target_params { + uint16_t flags; + uint16_t sync_period; +} ql_fw_target_params; + +typedef struct ql_t { + /* Hardware registers */ + uint16_t reg_cdma_cfg; + uint16_t reg_cdma_ctrl; + uint16_t reg_ddma_cfg; + uint16_t reg_ddma_ctrl; + uint16_t reg_risc_psr; + uint16_t reg_risc_pcr; + uint16_t reg_risc_pc; + uint16_t reg_risc_mtr; + uint16_t reg_id_low; + uint16_t reg_id_high; + uint16_t reg_cfg0; + uint16_t reg_cfg1; + uint16_t reg_scsi_diff_pins; + uint16_t reg_gpio_data; + uint16_t reg_gpio_enable; + uint16_t reg_flash_bios_addr; + uint16_t reg_nvram; + uint16_t reg_host_cmd_flags; + uint16_t reg_intr_ctrl; + uint16_t reg_intr_status; + uint16_t reg_semaphore; + uint16_t reg_mbox_in[QL_MBOX_REGS_MAX]; + uint16_t reg_mbox_out[QL_MBOX_REGS_MAX]; + /* SCSI executive processor state */ + SxpState sxp_state; + /* SXP flags */ + uint32_t sxp_flags; + /* Physical address of the request ring */ + uint32_t rqst_ring_base; + /* Request ring size */ + uint16_t rqst_ring_size; + /* Response ring size */ + uint16_t resp_ring_size; + /* Physical address of the response ring */ + uint32_t resp_ring_base; + /* Physical address of the current request IOCB */ + uint32_t pkt_address; + /* Current request IOCB */ + ql_sxp_req_t pkt; + /* Current response IOCB */ + isp_req_status_t pkt_resp; + /* Holds the request queue indexes to abort */ + Fifo8 abort_iocbs_fifo; + /* Current Path ID */ + uint8_t curr_path_id; + /* Current Target ID */ + uint8_t curr_target_id; + /* Number of SCSI buses on this HBA */ + uint8_t max_bus_count; + /* SCSI bus emulation internal index */ + uint8_t scsi_bus; + /* ISP chip type */ + uint8_t isp_type; + /* ISP chip revision */ + uint8_t isp_rev; + /* IRQ emulation internal context */ + uint8_t irq_state; + /* PCI slot emulation internal context */ + uint8_t pci_slot; + /* Bit map of mailbox registers to return to the host */ + uint32_t mbox_out_mask; + /* Pending mailbox response */ + uint16_t mbox_data[QL_MBOX_REGS_MAX]; + /* Transfer speed in bytes per second */ + double xfer_rate_bps; + /* Command timer period in microsecounds */ + double timer_period; + /* Command timer */ + pc_timer_t cmd_timer; + /* Firmware device parameters */ + ql_fw_target_params fw_tid_params[2][QL_MAX_TID]; + /* Firmware retry count and delay settings */ + uint16_t fw_retry_params[4]; + /* Firmware version */ + uint32_t fw_version; + /* Size of the SCSI payload data */ + uint32_t scsi_data_size; + /* Current offset in the SCSI payload data */ + uint32_t scsi_data_offset; + /* Temporary buffer to hold payload data of the SCSI command */ + uint8_t *scsi_data_buffer; + /* PCI MMIO BAR mapping */ + mem_mapping_t mmio_bar_mapping; + /* PCI ROM BAR mapping */ + mem_mapping_t rom_bar_mapping; + /* PCI configuration space */ + uint8_t pci_cfg[256]; + /* Size of the area to map the expansion ROM */ + uint32_t pci_rom_area_size; + /* Writable bits of the ROM BAR */ + uint32_t rom_bar_mask; + /* Supports PCI capabilities */ + bool has_pci_caps; + /* NVRAM device */ + nmc93cxx_eeprom_t *eeprom_device; + /* Flash BIOS device */ + flash_t flash_device; + /* RISC CPU memory */ + uint16_t cpu_mem[0x10000]; +} ql_t; + +extern double cpuclock; + +static bool +ql_sxp_fetch_request(ql_sxp_req_t* pkt, uint32_t address); + +#ifdef ENABLE_QL_LOG +int ql_do_log = ENABLE_QL_LOG; + +static bool ql_fw_load_in_progress = false; +static bool ql_nvram_read_in_progress = false; + +static void +ql_log(const char *fmt, ...) +{ + va_list ap; + + if (ql_fw_load_in_progress || ql_nvram_read_in_progress) { + return; + } + + if (ql_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} + +static void +ql_debug_check_for_nvram_access(uint32_t addr) +{ + /* Suppress log messages during NVRAM access */ + if (!ql_nvram_read_in_progress) { + if (addr == QL_REG_NVRAM) { + ql_log("QL: Disable NVRAM log\n"); + ql_nvram_read_in_progress = true; + } + } else { + if (addr != QL_REG_NVRAM) { + ql_nvram_read_in_progress = false; + ql_log("QL: Enable NVRAM log\n"); + } + } +} + +#define MAKE_CASE(x) case x: return #x; +static char * +ql_debug_cmd_to_name(uint16_t opcode) +{ + switch (opcode) { + MAKE_CASE(QL_CMD_NOP ); + MAKE_CASE(QL_CMD_LOAD_RAM ); + MAKE_CASE(QL_CMD_EXEC_FIRMWARE ); + MAKE_CASE(QL_CMD_DUMP_RAM ); + MAKE_CASE(QL_CMD_WRITE_RAM_WORD ); + MAKE_CASE(QL_CMD_READ_RAM_WORD ); + MAKE_CASE(QL_CMD_REGISTER_TEST ); + MAKE_CASE(QL_CMD_VERIFY_CHECKSUM ); + MAKE_CASE(QL_CMD_ABOUT_FIRMWARE ); + MAKE_CASE(QL_CMD_LOAD_RAM_A64 ); + MAKE_CASE(QL_CMD_DUMP_RAM_A64 ); + MAKE_CASE(QL_CMD_INIT_REQ_QUEUE ); + MAKE_CASE(QL_CMD_INIT_RSP_QUEUE ); + MAKE_CASE(QL_CMD_EXECUTE_IOCB ); + MAKE_CASE(QL_CMD_ABORT_COMMAND ); + MAKE_CASE(QL_CMD_ABORT_DEVICE ); + MAKE_CASE(QL_CMD_ABORT_TARGET ); + MAKE_CASE(QL_CMD_BUS_RESET ); + MAKE_CASE(QL_CMD_START_QUEUE ); + MAKE_CASE(QL_CMD_GET_FIRMWARE_STATUS ); + MAKE_CASE(QL_CMD_GET_RETRY_COUNT ); + MAKE_CASE(QL_CMD_GET_ACT_NEG_STATE ); + MAKE_CASE(QL_CMD_GET_TARGET_PARAMETERS ); + MAKE_CASE(QL_CMD_SET_INITIATOR_ID ); + MAKE_CASE(QL_CMD_SET_SELECTION_TIMEOUT ); + MAKE_CASE(QL_CMD_SET_RETRY_COUNT ); + MAKE_CASE(QL_CMD_SET_TAG_AGE_LIMIT ); + MAKE_CASE(QL_CMD_SET_CLOCK_RATE ); + MAKE_CASE(QL_CMD_SET_ACTIVE_NEGATION ); + MAKE_CASE(QL_CMD_SET_ASYNC_DATA_SETUP ); + MAKE_CASE(QL_CMD_SET_PCI_CONTROL ); + MAKE_CASE(QL_CMD_SET_TARGET_PARAMETERS ); + MAKE_CASE(QL_CMD_SET_DEVICE_QUEUE ); + MAKE_CASE(QL_CMD_RETURN_BIOS_BLOCK_ADDR ); + MAKE_CASE(QL_CMD_WRITE_FOUR_RAM_WORDS ); + MAKE_CASE(QL_CMD_EXEC_BIOS_IOCB ); + MAKE_CASE(QL_CMD_SET_SYSTEM_PARAMETER ); + MAKE_CASE(QL_CMD_SET_FIRMWARE_FEATURES ); + MAKE_CASE(QL_CMD_INIT_REQ_QUEUE_A64 ); + MAKE_CASE(QL_CMD_INIT_RSP_QUEUE_A64 ); + MAKE_CASE(QL_CMD_EXECUTE_IOCB_A64 ); + MAKE_CASE(QL_CMD_GET_TRANSFER_MODE ); + MAKE_CASE(QL_CMD_SET_DATA_OVERRUN_RECOVERY); + default: + return ""; + } +} + +static char * +debug_sxp_state_to_name(SxpState state) +{ + switch (state) { + MAKE_CASE(SXP_STATE_IDLE); + MAKE_CASE(SXP_STATE_BAD_PACKET); + MAKE_CASE(SXP_STATE_SELECT_DEVICE); + MAKE_CASE(SXP_STATE_SELECTION_TIMEOUT); + MAKE_CASE(SXP_STATE_SEND_CDB); + MAKE_CASE(SXP_STATE_COMPLETE_COMMAND); + MAKE_CASE(SXP_STATE_SCHEDULE_MBOX_INTERRUPT); + MAKE_CASE(SXP_STATE_SCHEDULE_RISC_INTERRUPT); + MAKE_CASE(SXP_STATE_SET_RISC_INTERRUPT); + MAKE_CASE(SXP_STATE_ACQUIRE_MBOX_SEMAPHORE); + MAKE_CASE(SXP_STATE_SCHEDULE_TIMER_SILENCE); + MAKE_CASE(SXP_STATE_WAIT_TIMER); + MAKE_CASE(SXP_STATE_MBOX_WAIT_TIMER); + default: + return ""; + } +} +#undef MAKE_CASE +#else +# define ql_log(fmt, ...) +#endif + +static flash_block_t* +am29_address_to_block(flash_t *dev, uint32_t addr) +{ + for (uint32_t i = 0; i < AM29_MAX_BLOCKS; i++) { + flash_block_t *block = &dev->block[i]; + + if ((addr >= block->start_addr) && (addr <= block->end_addr)) + return block; + } + + /* Should not happen */ + assert(false); + return NULL; +} + +static void +am29_reset_cmd_sequence(flash_t *dev) +{ + dev->bus_cycle = 0; + dev->cmd_cycle = 0; +} + +static void +am29_set_mode(flash_t *dev, FlashMode mode) +{ + if (mode != dev->mode) { + ql_log("FLASH: Set mode %u\n", mode); + } + dev->mode = mode; + + am29_reset_cmd_sequence(dev); +} + +static void +am29_process_reset_or_complete_cmd(flash_t *dev) +{ + am29_set_mode(dev, M_READ_ARRAY); + + dev->status_reg = 0; + dev->blocks_to_erase_bitmap = 0; + + /* Terminate the block erase timeout */ + timer_stop(&dev->erase_accept_timeout_timer); +} + +static void +am29_reset(flash_t *dev) +{ + am29_process_reset_or_complete_cmd(dev); +} + +static void +am29_cmd_complete_timer_callback(void *priv) +{ + flash_t *dev = priv; + + ql_log("FLASH: Command completed with status %02X\n", dev->status_reg); + + /* The memory will return to the Read Mode, unless an error has occurred */ + if (dev->status_reg & FLASH_STATUS_ERROR) { + return; + } + am29_process_reset_or_complete_cmd(dev); +} + +static void +am29_erase_blocks(flash_t *dev) +{ + for (uint32_t i = 0; i < AM29_MAX_BLOCKS; i++) { + flash_block_t *block = &dev->block[i]; + void *block_start; + size_t block_length; + + if (!(dev->blocks_to_erase_bitmap & (1 << i))) { + continue; + } + + /* Protected block: The data remains unchanged, no error is given */ + if (block->protection_status == FLASH_BLOCK_STATUS_PROTECTED) { + continue; + } + + ql_log("FLASH: Erase block #%lu %lX-%lX\n", block->number, block->start_addr, block->end_addr); + + block_start = &dev->array_data[block->start_addr]; + block_length = (block->end_addr - block->start_addr) + 1; + + memset(block_start, 0xFF, block_length); + } +} + +static void +am29_erase_begin_timer_callback(void *priv) +{ + flash_t *dev = priv; + + ql_log("FLASH: Begin erase operation\n"); + + /* Finally, erase the blocks (fill with 0xFF) */ + am29_erase_blocks(dev); + + if (dev->mode == M_CHIP_ERASE) { + timer_on_auto(&dev->cmd_complete_timer, dev->chip_erase_time_us); + } else { + dev->status_reg |= FLASH_STATUS_ERASE_TIMEOUT_EXPIRED; + + timer_on_auto(&dev->cmd_complete_timer, dev->block_erase_time_us); + } +} + +static uint8_t +am29_status_register_read(flash_t *dev) +{ + switch (dev->mode) { + case M_PROGRAM: + case M_BLOCK_ERASE: + case M_CHIP_ERASE: { + dev->status_reg ^= FLASH_STATUS_TOGGLE; + break; + } + + default: + break; + } + + return dev->status_reg; +} + +static void +am29_accept_cmd(flash_t *dev, uint32_t addr, uint8_t val) +{ + flash_block_t *block; + + /* Single cycle command (write to any address inside the device) */ + if ((val == FLASH_CMD_READ_ARRAY) && (dev->mode != M_PROGRAM)) { + am29_process_reset_or_complete_cmd(dev); + return; + } + + switch (dev->mode) { + case M_PROGRAM: { + block = am29_address_to_block(dev, addr); + + /* Write to a protected block: The data remains unchanged, no error is given */ + if (block->protection_status == FLASH_BLOCK_STATUS_PROTECTED) { + ql_log("FLASH: Program failure - the block #lu is protected\n", block->number); + goto ProgramDone; + } + + /* The program command cannot change a bit set at '0' back to '1' */ + if (~dev->array_data[addr] & val) { + ql_log("FLASH: Program error - the address %lX " + "was not previously erased %04X <> %04X\n", + addr, + dev->array_data[addr], + val); + + dev->status_reg |= FLASH_STATUS_ERROR; + goto ProgramDone; + } + + /* Data# polling */ + if (!(val & FLASH_STATUS_DATA_POLLING)) { + dev->status_reg |= FLASH_STATUS_DATA_POLLING; + } + + /* Finally, program the value */ + ql_log("FLASH: Program %08lX to %04X\n", addr, val); + dev->array_data[addr] = val; + +ProgramDone: + timer_on_auto(&dev->cmd_complete_timer, dev->program_time_us); + break; + } + + case M_BLOCK_ERASE: { + /* We shouldn't get here if the operation has already started */ + assert(!(dev->status_reg & FLASH_STATUS_ERASE_TIMEOUT_EXPIRED)); + + addr &= dev->block_select_addr_mask; + block = am29_address_to_block(dev, addr); + + ql_log("FLASH: Queued block #%lu %lX-%lX for erase\n", + block->number, + block->start_addr, + block->end_addr); + + /* Add block to the list */ + dev->blocks_to_erase_bitmap |= 1 << block->number; + + /* Wait for a next block to erase (restart the timeout period) */ + timer_stop(&dev->erase_accept_timeout_timer); + timer_on_auto(&dev->erase_accept_timeout_timer, AM29_BLOCK_ERASE_ACCEPT_TIMEOUT_US); + break; + } + + case M_CHIP_ERASE: { + /* Add all blocks to the list */ + dev->blocks_to_erase_bitmap = 0xFFFFFFFF; + + /* Immediately start the erase operation */ + am29_erase_begin_timer_callback(dev); + break; + } + + default: + break; + } +} + +static void +am29_interpret_cmd_sequence(flash_t *dev, uint32_t addr, uint8_t val) +{ + // clang-format off + static const uint8_t cmd_seq_next_state[6][2] = { + // Phase 0 Phase 1 + { CYCLE_CHECK_AA, CYCLE_INVALID }, // Cycle 1 + { CYCLE_CHECK_55, CYCLE_INVALID }, // Cycle 2 + { CYCLE_CHECK_FIRST_CMD, CYCLE_INVALID }, // Cycle 3 + { CYCLE_CHECK_AA, CYCLE_ENTER_PROGRAM }, // Cycle 4 + { CYCLE_CHECK_55, CYCLE_INVALID }, // Cycle 5 + { CYCLE_CHECK_SECOND_CMD, CYCLE_INVALID }, // Cycle 6 + }; + // clang-format on + + addr &= dev->cmd_cycle_addr_mask; + + switch (cmd_seq_next_state[dev->bus_cycle][dev->cmd_cycle]) { + case CYCLE_CHECK_AA: { + if ((val == 0xAA) && (addr == dev->addr_5555_phys)) { + dev->bus_cycle++; + return; + } + break; + } + + case CYCLE_CHECK_55: { + if ((val == 0x55) && (addr == dev->addr_AAAA_phys)) { + dev->bus_cycle++; + return; + } + break; + } + + case CYCLE_CHECK_FIRST_CMD: { + if (addr != dev->addr_5555_phys) { + break; + } + + switch (val) { + case FLASH_CMD_AUTO_SELECT: + am29_set_mode(dev, M_AUTO_SELECT); + return; + + case FLASH_CMD_PROGRAM: + dev->bus_cycle++; + dev->cmd_cycle++; + return; + + case FLASH_CMD_SETUP_ERASE: + dev->bus_cycle++; + return; + + default: + break; + } + break; + } + + case CYCLE_ENTER_PROGRAM: { + am29_set_mode(dev, M_PROGRAM); + return; + } + + case CYCLE_CHECK_SECOND_CMD: { + switch (val) { + case FLASH_CMD_BLOCK_ERASE_CONFIRM: { + am29_set_mode(dev, M_BLOCK_ERASE); + return; + } + + case FLASH_CMD_CHIP_ERASE_CONFIRM: { + if (addr == dev->addr_5555_phys) { + am29_set_mode(dev, M_CHIP_ERASE); + return; + } + break; + } + + default: + break; + } + break; + } + + default: + break; + } + + am29_reset_cmd_sequence(dev); +} + +static void +am29_mmio_write8(uint32_t addr, uint8_t val, flash_t *dev) +{ + cycles -= dev->access_cycles; + + addr &= (AM29_FLASH_SIZE - 1); + + ql_log("FLASH: [%08lX] <-- %02X\n", addr, val); + + switch (dev->mode) { + /* Ignore all commands while the chip is being programmed or erased */ + case M_CHIP_ERASE: + case M_PROGRAM: { + /* A Read/Reset command can be issued to reset the error condition */ + if ((dev->status_reg & FLASH_STATUS_ERROR) && (val == FLASH_CMD_READ_ARRAY)) + break; + return; + } + + /* Ignore all commands during the Block Erase except the Read/Reset command */ + case M_BLOCK_ERASE: { + /* The command has not started yet, we keep accepting blocks to the erase list */ + if (!(dev->status_reg & FLASH_STATUS_ERASE_TIMEOUT_EXPIRED)) + break; + + if (val == FLASH_CMD_READ_ARRAY) + break; + return; + } + + default: + break; + } + + /* Receive the command sequence */ + if ((dev->mode == M_READ_ARRAY) || (dev->mode == M_AUTO_SELECT)) { + am29_interpret_cmd_sequence(dev, addr, val); + } + + /* Begin the operation */ + am29_accept_cmd(dev, addr, val); +} + +static uint8_t +am29_mmio_read8(uint32_t addr, flash_t *dev) +{ + uint8_t ret; + + cycles -= dev->access_cycles; + + addr &= (AM29_FLASH_SIZE - 1); + + switch (dev->mode) { + case M_READ_ARRAY: { + /* Read array data */ + ret = dev->array_data[addr]; + break; + } + + case M_AUTO_SELECT: { + switch (addr & AM29_AUTOSEL_ADDR_MASK) { + case AM29_AUTOSEL_ADDR_MANUFACTURER_ID: + ret = dev->manufacturer_id; + break; + + case AM29_AUTOSEL_ADDR_MODEL_ID: + ret = dev->model_id; + break; + + default: { + flash_block_t *block = am29_address_to_block(dev, addr); + + /* Read the block protection status */ + ret = block->protection_status; + break; + } + } + break; + } + + default: { + /* Return the status register during Program and Erase operations */ + ret = am29_status_register_read(dev); + break; + } + } + + if (dev->mode != M_READ_ARRAY) { + ql_log("FLASH: [%08lX] --> %02X\n", addr, ret); + } + return ret; +} + +static uint8_t +ql_rom_bar_mmio_read8(uint32_t addr, void* priv) +{ + ql_t *dev = priv; + + return am29_mmio_read8(addr, &dev->flash_device); +} + +static void +ql_update_irq(ql_t *dev) +{ + uint16_t isr = dev->reg_intr_status & dev->reg_intr_ctrl; + + /* NOTE: Unmasking QL_INTR_REQ does nothing on QLA1080 real hardware */ + isr &= QL_RISC_INTR_REQ; + + if (isr != 0) + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + else + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); +} + +static void +ql_reset_asic(ql_t *dev) +{ + ql_log("QL: Reset ASIC\n"); + + dev->reg_id_low = 0x1077; + dev->reg_id_high = 0x1240; + dev->reg_cfg0 = dev->isp_rev; + dev->reg_cfg1 = BIU_BURST_ENABLE | BIU_PCI_CONF1_FIFO_128; + dev->reg_intr_ctrl = 0; + dev->reg_intr_status = 0; + dev->reg_semaphore = 0; + dev->reg_nvram = 0; + dev->reg_flash_bios_addr = 0; + dev->reg_mbox_out[0] = 0; + dev->reg_mbox_out[1] = 0x4953; // 'IS' + dev->reg_mbox_out[2] = 0x5020; // 'P ' + dev->reg_mbox_out[3] = 0x2020; // ' ' + dev->reg_mbox_out[4] = 1; + dev->reg_mbox_out[5] = 7; + dev->reg_mbox_out[6] = 0; + dev->reg_mbox_out[7] = 1; + dev->reg_host_cmd_flags = 0; + dev->reg_gpio_data = 0x000F; + dev->reg_gpio_enable = 0; + dev->reg_scsi_diff_pins = SXP_PINS_SE_MODE; + dev->reg_cdma_cfg = 0x0001; + dev->reg_cdma_ctrl = 0; + dev->reg_ddma_cfg = 0x0008; + dev->reg_ddma_ctrl = 0; + dev->reg_risc_psr = 0x2000; + dev->reg_risc_pcr = 0; + dev->reg_risc_pc = 0; + dev->reg_risc_mtr = 0x0001; + + memset(dev->cpu_mem, 0, sizeof(dev->cpu_mem)); + /* FastUtil BIOS checks area 0xFF03-0xFFF3 if the word at 0xFF03 is invalid */ + dev->cpu_mem[0xFF03] = 0xFBFF; + + timer_stop(&dev->cmd_timer); + dev->rqst_ring_base = 0; + dev->resp_ring_base = 0; + dev->sxp_flags = 0; + dev->sxp_state = SXP_STATE_IDLE; + + ql_update_irq(dev); +} + + +static bool +ql_sxp_abort_commands(ql_t *dev, uint8_t path_id, uint8_t target_id, uint8_t lun, uint32_t handle, bool is_handle_valid) +{ + bool success = false; + uint16_t cons; + + if (!(dev->sxp_flags & SXP_FLAG_ENGINE_ACTIVE)) { + return false; + } + + /* Iterate over the request IOCBs looking for a match */ + for (cons = QL_RQST_CONS(dev); cons != QL_RQST_PROD(dev); cons = (cons + 1) % dev->rqst_ring_size) { + uint32_t pkt_address = dev->rqst_ring_base + cons * QENTRY_LEN; + ql_sxp_req_t pkt; + uint8_t curr_path_id, curr_target_id; + + if (!ql_sxp_fetch_request(&pkt, pkt_address)) { + continue; + } + + curr_path_id = (pkt.bus_target & 0x80) >> 7; + curr_target_id = pkt.bus_target & ~0x80; + + /* Exact match? */ + if ((curr_path_id != path_id) || (curr_target_id != target_id)) { + continue; + } + if ((lun != 0xFF) && (pkt.lun != lun)) { + continue; + } + if (is_handle_valid && (pkt.handle != handle)) { + continue; + } + + /* Save the queue index, it will be checked before the next command is processed */ + fifo8_push(&dev->abort_iocbs_fifo, cons & 0xFF); + fifo8_push(&dev->abort_iocbs_fifo, (cons >> 8) & 0xFF); + + success = true; + } + + return success; +} + +static void +ql_sxp_initialize_queues(ql_t *dev) +{ + if ((dev->rqst_ring_base != 0) && (dev->resp_ring_base != 0)) { + /* Each queue index consists of 2 bytes (size of the mailbox register) */ + uint32_t fifo_size = dev->rqst_ring_size * sizeof(uint16_t); + + fifo8_destroy(&dev->abort_iocbs_fifo); + fifo8_create(&dev->abort_iocbs_fifo, fifo_size); + + dev->sxp_flags |= SXP_FLAG_ENGINE_ACTIVE; + } else { + dev->sxp_flags &= ~SXP_FLAG_ENGINE_ACTIVE; + } +} + +static uint16_t +ql_handle_cmd_nop(ql_t *dev) +{ + /* Nothing to do */ + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_write_ram_word(ql_t *dev) +{ +#ifdef ENABLE_QL_LOG + /* Suppress log messages during loading of firmware */ + if (!ql_fw_load_in_progress) { + if (dev->reg_mbox_in[1] == 0x1003) { + ql_log("QL: Disable log before FW load\n"); + ql_fw_load_in_progress = true; + } + } else { + if ((dev->reg_mbox_in[1] - 0x1000) == (dev->cpu_mem[0x1003] - 2)) { + ql_fw_load_in_progress = false; + ql_log("QL: Enable log after FW load\n"); + } + } +#endif + + dev->cpu_mem[dev->reg_mbox_in[1]] = dev->reg_mbox_in[2]; + + dev->mbox_out_mask |= QL_BIT(2); + dev->mbox_data[2] = dev->reg_mbox_in[2]; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_write_four_ram_words(ql_t *dev) +{ + uint16_t address = dev->reg_mbox_in[1]; + + if (dev->isp_type != QL_ISP1040) { + return QL_MBOX_STATUS_INVALID; + } + + if (address >= (ARRAY_SIZE(dev->cpu_mem) - 4)) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + dev->cpu_mem[address + 0] = dev->reg_mbox_in[2]; + dev->cpu_mem[address + 1] = dev->reg_mbox_in[3]; + dev->cpu_mem[address + 2] = dev->reg_mbox_in[4]; + dev->cpu_mem[address + 3] = dev->reg_mbox_in[5]; + + if (address == (QL_IOCB_FW_BASE + 4)) { + /* Save the SCSI device address for later use */ + dev->cpu_mem[QL_IOCB_FW_BASE + 48] = dev->cpu_mem[address]; + + /* Return some status data */ + dev->cpu_mem[address] = 0x0300; + } + + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_read_ram_word(ql_t *dev) +{ + dev->mbox_out_mask |= QL_BIT(2) | QL_BIT(3); + dev->mbox_data[2] = dev->cpu_mem[dev->reg_mbox_in[1]]; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_load_ram_block(ql_t *dev, UNUSED(bool is_64bit_addr)) +{ + uint32_t offset = dev->reg_mbox_in[1]; + uint32_t block_size_words = dev->reg_mbox_in[4]; + uint8_t *dest_address = (uint8_t *)&dev->cpu_mem[offset]; + uint32_t src_address = ((uint32_t)dev->reg_mbox_in[2] << 16) | dev->reg_mbox_in[3]; + + if ((offset + block_size_words) > ARRAY_SIZE(dev->cpu_mem)) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + ql_dma_read(src_address, dest_address, block_size_words * sizeof(uint16_t)); + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_dump_ram_block(ql_t *dev, UNUSED(bool is_64bit_addr)) +{ + uint32_t offset = dev->reg_mbox_in[1]; + uint32_t block_size_words = dev->reg_mbox_in[4]; + uint8_t *src_address = (uint8_t *)&dev->cpu_mem[offset]; + uint32_t dest_address = ((uint32_t)dev->reg_mbox_in[2] << 16) | dev->reg_mbox_in[3]; + + if ((offset + block_size_words) > ARRAY_SIZE(dev->cpu_mem)) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + ql_dma_write(dest_address, src_address, block_size_words * sizeof(uint16_t)); + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_register_test(ql_t *dev) +{ + for (uint32_t i = 1; i < ARRAY_SIZE(dev->reg_mbox_in); i++) { + dev->mbox_out_mask |= QL_BIT(i); + dev->mbox_data[i] = dev->reg_mbox_in[i]; + } + + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_verify_checksum(ql_t *dev) +{ + uint32_t start_addr = dev->reg_mbox_in[1]; + uint16_t fw_size_words; + uint32_t end_addr; + uint16_t crc; + + if (start_addr >= (ARRAY_SIZE(dev->cpu_mem) - 3)) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + fw_size_words = dev->cpu_mem[start_addr + 3]; + + end_addr = start_addr + fw_size_words; + if (end_addr > ARRAY_SIZE(dev->cpu_mem)) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + crc = 0; + for (uint32_t i = start_addr; i < end_addr; i++) { + crc += dev->cpu_mem[i]; + } + dev->mbox_out_mask |= QL_BIT(1); + dev->mbox_data[1] = crc; + + if (crc != 0) { + ql_log("QL: Firmware crc 0x%X\n", crc); + return QL_MBOX_STATUS_TEST_FAILED; + } + + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_exec_firmware(ql_t *dev) +{ + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3) | QL_BIT(4) | QL_BIT(5); + dev->mbox_data[1] = 0x4953; // 'IS' + dev->mbox_data[2] = 0x5020; // 'P ' + dev->mbox_data[3] = 0x2020; // ' ' + dev->mbox_data[4] = 8; + dev->mbox_data[5] = 0x04FE; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_about_firmware(ql_t *dev) +{ + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = (dev->fw_version >> 16) & 0xFF; // Major revision + dev->mbox_data[2] = (dev->fw_version >> 8) & 0xFF; // Minor revision + dev->mbox_data[3] = (dev->fw_version >> 0) & 0xFF; // Micro revision + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_init_request_queue(ql_t *dev, UNUSED(bool is_64bit_addr)) +{ + uint32_t address = ((uint32_t)dev->reg_mbox_in[2] << 16) | dev->reg_mbox_in[3]; + uint16_t queue_length = dev->reg_mbox_in[1]; + + ql_log("QL: REQ queue address 0x%X, length %u\n", address, queue_length); + + if ((address == 0) || (queue_length == 0)) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + dev->rqst_ring_base = address; + dev->rqst_ring_size = queue_length; + ql_sxp_initialize_queues(dev); + + dev->mbox_out_mask |= 1 << QL_MBOX_RQST; + dev->mbox_data[QL_MBOX_RQST] = dev->reg_mbox_in[QL_MBOX_RQST]; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_init_response_queue(ql_t *dev, UNUSED(bool is_64bit_addr)) +{ + uint32_t address = ((uint32_t)dev->reg_mbox_in[2] << 16) | dev->reg_mbox_in[3]; + uint16_t queue_length = dev->reg_mbox_in[1]; + + ql_log("QL: RSP queue address 0x%X, length %u\n", address, queue_length); + + if ((address == 0) || (queue_length == 0)) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + dev->resp_ring_base = address; + dev->resp_ring_size = queue_length; + ql_sxp_initialize_queues(dev); + + dev->mbox_out_mask |= 1 << QL_MBOX_RESP; + dev->mbox_data[QL_MBOX_RESP] = dev->reg_mbox_in[QL_MBOX_RESP]; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_abort_command(ql_t *dev) +{ + uint8_t path_id = dev->reg_mbox_in[1] >> 15; + uint8_t target_id = (dev->reg_mbox_in[1] >> 8) & ~0x80; + uint8_t lun = dev->reg_mbox_in[1] & 0xFF; + uint32_t handle; + bool success; + + ql_log("QL: [%u:%u] Abort command\n", path_id, target_id); + + if (path_id >= dev->max_bus_count) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + if (target_id >= QL_MAX_TID) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + /* Abort an active command on the device (PATH:TID:LUN) that match the handle */ + handle = dev->reg_mbox_in[QL_MBOX_HNDL_LOW]; + handle |= (uint32_t)dev->reg_mbox_in[QL_MBOX_HNDL_HIGH] << 16; + success = ql_sxp_abort_commands(dev, path_id, target_id, lun, handle, true); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = dev->reg_mbox_in[3]; + + if (!success) { + return QL_MBOX_STATUS_CMD_ERROR; + } + + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_abort_device(ql_t *dev) +{ + uint8_t path_id = dev->reg_mbox_in[1] >> 15; + uint8_t target_id = (dev->reg_mbox_in[1] >> 8) & ~0x80; + uint8_t lun = dev->reg_mbox_in[1] & 0xFF; + + ql_log("QL: [%u:%u:%u] Abort device\n", path_id, target_id, lun); + + if (path_id >= dev->max_bus_count) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + if (target_id >= QL_MAX_TID) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + /* Abort all active commands on the device (PATH:TID:LUN) */ + (void) ql_sxp_abort_commands(dev, path_id, target_id, lun, 0, false); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = dev->reg_mbox_in[3]; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_abort_target(ql_t *dev) +{ + uint8_t path_id = dev->reg_mbox_in[1] >> 15; + uint8_t target_id = (dev->reg_mbox_in[1] >> 8) & ~0x80; + + ql_log("QL: [%u:%u] Abort target\n", path_id, target_id); + + if (path_id >= dev->max_bus_count) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + if (target_id >= QL_MAX_TID) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + /* Abort all active commands on the target (PATH:TID) */ + (void) ql_sxp_abort_commands(dev, path_id, target_id, 0xFF, 0, false); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = dev->reg_mbox_in[3]; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_bus_reset(ql_t *dev) +{ + uint8_t path_id; + + if (dev->isp_type == QL_ISP1040) { + path_id = 0; + } else { + path_id = dev->reg_mbox_in[2]; + } + + ql_log("QL: Reset bus %u, delay %u\n", path_id, dev->reg_mbox_in[1]); + + if (path_id >= dev->max_bus_count) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + /* 86Box supports one SCSI bus per controller for now */ + if (path_id == 0) { + for (uint32_t i = 0; i < MIN(QL_MAX_TID, SCSI_ID_MAX); i++) { + scsi_device_reset(&scsi_devices[dev->scsi_bus][i]); + } + } + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_get_firmware_status(ql_t *dev) +{ + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = 0; + dev->mbox_data[2] = 527; // Max queue depth + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_initialor_id(ql_t *dev) +{ + ql_log("QL: Initialor ID 0x%X\n", dev->reg_mbox_in[1]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_selection_timeout(ql_t *dev) +{ + ql_log("QL: Selection timeout #1 %u\n", dev->reg_mbox_in[1]); + ql_log("QL: Selection timeout #2 %u\n", dev->reg_mbox_in[2]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_retry_count(ql_t *dev) +{ + ql_log("QL: Retry count #1 %u\n", dev->reg_mbox_in[1]); + ql_log("QL: Retry count #2 %u\n", dev->reg_mbox_in[2]); + ql_log("QL: Retry delay #1 %u\n", dev->reg_mbox_in[6]); + ql_log("QL: Retry delay #2 %u\n", dev->reg_mbox_in[7]); + + dev->fw_retry_params[0] = dev->reg_mbox_in[1]; + dev->fw_retry_params[1] = dev->reg_mbox_in[2]; + dev->fw_retry_params[2] = dev->reg_mbox_in[6]; + dev->fw_retry_params[3] = dev->reg_mbox_in[7]; + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = 8; + dev->mbox_data[2] = 5; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_get_retry_count(ql_t *dev) +{ + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->fw_retry_params[0]; + dev->mbox_data[2] = dev->fw_retry_params[1]; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_get_act_neg_state(ql_t *dev) +{ + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = 0; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_tag_age_limit(ql_t *dev) +{ + ql_log("QL: Tag age limit #1 %u\n", dev->reg_mbox_in[1]); + ql_log("QL: Tag age limit #2 %u\n", dev->reg_mbox_in[2]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_clock_rate(ql_t *dev) +{ + ql_log("QL: Clock rate %u\n", dev->reg_mbox_in[1]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_active_negation(ql_t *dev) +{ + ql_log("QL: Acq active negation 0x%X\n", dev->reg_mbox_in[1]); + ql_log("QL: Data line active negation 0x%X\n", dev->reg_mbox_in[2]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_async_data_setup(ql_t *dev) +{ + ql_log("QL: Async data setup %u %u\n", dev->reg_mbox_in[1], dev->reg_mbox_in[2]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_pci_control(ql_t *dev) +{ + ql_log("QL: PCI control %x %x\n", dev->reg_mbox_in[1], dev->reg_mbox_in[2]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_target_parameters(ql_t *dev) +{ + uint8_t path_id = dev->reg_mbox_in[1] >> 15; + uint8_t target_id = (dev->reg_mbox_in[1] >> 8) & ~0x80; + + ql_log("QL: [%u:%u] Set params 0x%X 0x%X\n", path_id, target_id, dev->reg_mbox_in[2], dev->reg_mbox_in[3]); + + if (path_id >= dev->max_bus_count) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + if (target_id >= QL_MAX_TID) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + dev->fw_tid_params[path_id][target_id].flags = dev->reg_mbox_in[2]; + dev->fw_tid_params[path_id][target_id].sync_period = dev->reg_mbox_in[3]; + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = dev->reg_mbox_in[3]; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_get_target_parameters(ql_t *dev) +{ + uint8_t path_id = dev->reg_mbox_in[1] >> 15; + uint8_t target_id = (dev->reg_mbox_in[1] >> 8) & ~0x80; + + ql_log("QL: [%u:%u] Return params\n", path_id, target_id); + + if (path_id >= dev->max_bus_count) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + if (target_id >= QL_MAX_TID) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3) | QL_BIT(6); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->fw_tid_params[path_id][target_id].flags; + dev->mbox_data[3] = dev->fw_tid_params[path_id][target_id].sync_period; + dev->mbox_data[6] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_device_queue(ql_t *dev) +{ + ql_log("QL: Queue params 0x%X %u %u\n", dev->reg_mbox_in[1], dev->reg_mbox_in[2], dev->reg_mbox_in[3]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = dev->reg_mbox_in[2]; + dev->mbox_data[3] = 0x0064; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_return_bios_block_addr(ql_t *dev) +{ + if (dev->isp_type != QL_ISP1040) { + return QL_MBOX_STATUS_INVALID; + } + + dev->mbox_out_mask |= QL_BIT(1); + dev->mbox_data[1] = QL_IOCB_FW_BASE; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_system_parameter(ql_t *dev) +{ + ql_log("QL: System parameter 0x%X\n", dev->reg_mbox_in[1]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = 2; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_firmware_features(ql_t *dev) +{ + ql_log("QL: FW features 0x%X\n", dev->reg_mbox_in[1]); + + if (dev->reg_mbox_in[1] & FW_FEATURE_FAST_POST) { + dev->sxp_flags |= SXP_FLAG_FAST_POSTING; + } else { + dev->sxp_flags &= ~SXP_FLAG_FAST_POSTING; + } + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = 0; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_get_transfer_mode(ql_t *dev) +{ + uint8_t path_id = dev->reg_mbox_in[1] >> 15; + uint8_t target_id = (dev->reg_mbox_in[1] >> 8) & ~0x80; + + ql_log("QL: [%u:%u] Return xfer mode\n", path_id, target_id); + + if (path_id >= dev->max_bus_count) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + if (target_id >= QL_MAX_TID) { + return QL_MBOX_STATUS_CMD_PARAM_ERROR; + } + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3) | QL_BIT(6); + dev->mbox_data[1] = dev->reg_mbox_in[1]; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0x000C; + dev->mbox_data[6] = 0xFD10; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_cmd_set_data_overrun_recovery(ql_t *dev) +{ + ql_log("QL: Data overrun recovery 0x%X\n", dev->reg_mbox_in[1]); + + dev->mbox_out_mask |= QL_BIT(1) | QL_BIT(2) | QL_BIT(3); + dev->mbox_data[1] = 0; + dev->mbox_data[2] = 0; + dev->mbox_data[3] = 0; + return QL_MBOX_STATUS_COMPLETE; +} + +static uint16_t +ql_handle_exec_bios_iocb(ql_t *dev) +{ + if (dev->isp_type != QL_ISP1040) { + return QL_MBOX_STATUS_INVALID; + } + + dev->sxp_flags |= SXP_FLAG_BIOS_IOCB; + return QL_MBOX_STATUS_PENDING; +} + +static uint16_t +ql_handle_exec_mbox_iocb(ql_t *dev, bool is_64bit_addr) +{ + if (is_64bit_addr && (dev->reg_mbox_in[1] != QENTRY_LEN)) { + return QL_MBOX_STATUS_CMD_ERROR; + } + + dev->sxp_flags |= SXP_FLAG_MBOX_IOCB; + return QL_MBOX_STATUS_PENDING; +} + +static uint16_t +ql_process_mailbox(ql_t *dev) +{ + uint16_t status; + + ql_log("QL: Command %02X %s\n", dev->reg_mbox_in[0], ql_debug_cmd_to_name(dev->reg_mbox_in[0])); + + switch (dev->reg_mbox_in[0]) { + case QL_CMD_NOP: + status = ql_handle_cmd_nop(dev); + break; + case QL_CMD_LOAD_RAM: + status = ql_handle_cmd_load_ram_block(dev, false); + break; + case QL_CMD_EXEC_FIRMWARE: + status = ql_handle_cmd_exec_firmware(dev); + break; + case QL_CMD_DUMP_RAM: + status = ql_handle_cmd_dump_ram_block(dev, false); + break; + case QL_CMD_WRITE_RAM_WORD: + status = ql_handle_cmd_write_ram_word(dev); + break; + case QL_CMD_READ_RAM_WORD: + status = ql_handle_cmd_read_ram_word(dev); + break; + case QL_CMD_REGISTER_TEST: + status = ql_handle_cmd_register_test(dev); + break; + case QL_CMD_VERIFY_CHECKSUM: + status = ql_handle_cmd_verify_checksum(dev); + break; + case QL_CMD_ABOUT_FIRMWARE: + status = ql_handle_cmd_about_firmware(dev); + break; + case QL_CMD_LOAD_RAM_A64: + status = ql_handle_cmd_load_ram_block(dev, true); + break; + case QL_CMD_DUMP_RAM_A64: + status = ql_handle_cmd_dump_ram_block(dev, true); + break; + case QL_CMD_INIT_REQ_QUEUE: + status = ql_handle_cmd_init_request_queue(dev, false); + break; + case QL_CMD_INIT_RSP_QUEUE: + status = ql_handle_cmd_init_response_queue(dev, false); + break; + case QL_CMD_EXECUTE_IOCB: + status = ql_handle_exec_mbox_iocb(dev, false); + break; + case QL_CMD_ABORT_COMMAND: + status = ql_handle_cmd_abort_command(dev); + break; + case QL_CMD_ABORT_DEVICE: + status = ql_handle_cmd_abort_device(dev); + break; + case QL_CMD_ABORT_TARGET: + status = ql_handle_cmd_abort_target(dev); + break; + case QL_CMD_BUS_RESET: + status = ql_handle_cmd_bus_reset(dev); + break; + case QL_CMD_START_QUEUE: + status = ql_handle_cmd_nop(dev); + break; + case QL_CMD_GET_RETRY_COUNT: + status = ql_handle_cmd_get_retry_count(dev); + break; + case QL_CMD_GET_ACT_NEG_STATE: + status = ql_handle_cmd_get_act_neg_state(dev); + break; + case QL_CMD_GET_TARGET_PARAMETERS: + status = ql_handle_cmd_get_target_parameters(dev); + break; + case QL_CMD_GET_FIRMWARE_STATUS: + status = ql_handle_cmd_get_firmware_status(dev); + break; + case QL_CMD_SET_INITIATOR_ID: + status = ql_handle_cmd_set_initialor_id(dev); + break; + case QL_CMD_SET_SELECTION_TIMEOUT: + status = ql_handle_cmd_set_selection_timeout(dev); + break; + case QL_CMD_SET_RETRY_COUNT: + status = ql_handle_cmd_set_retry_count(dev); + break; + case QL_CMD_SET_TAG_AGE_LIMIT: + status = ql_handle_cmd_set_tag_age_limit(dev); + break; + case QL_CMD_SET_CLOCK_RATE: + status = ql_handle_cmd_set_clock_rate(dev); + break; + case QL_CMD_SET_ACTIVE_NEGATION: + status = ql_handle_cmd_set_active_negation(dev); + break; + case QL_CMD_SET_ASYNC_DATA_SETUP: + status = ql_handle_cmd_set_async_data_setup(dev); + break; + case QL_CMD_SET_PCI_CONTROL: + status = ql_handle_cmd_set_pci_control(dev); + break; + case QL_CMD_SET_TARGET_PARAMETERS: + status = ql_handle_cmd_set_target_parameters(dev); + break; + case QL_CMD_SET_DEVICE_QUEUE: + status = ql_handle_cmd_set_device_queue(dev); + break; + case QL_CMD_RETURN_BIOS_BLOCK_ADDR: + status = ql_handle_cmd_return_bios_block_addr(dev); + break; + case QL_CMD_WRITE_FOUR_RAM_WORDS: + status = ql_handle_cmd_write_four_ram_words(dev); + break; + case QL_CMD_EXEC_BIOS_IOCB: + status = ql_handle_exec_bios_iocb(dev); + break; + case QL_CMD_SET_SYSTEM_PARAMETER: + status = ql_handle_cmd_set_system_parameter(dev); + break; + case QL_CMD_SET_FIRMWARE_FEATURES: + status = ql_handle_cmd_set_firmware_features(dev); + break; + case QL_CMD_INIT_REQ_QUEUE_A64: + status = ql_handle_cmd_init_request_queue(dev, true); + break; + case QL_CMD_INIT_RSP_QUEUE_A64: + status = ql_handle_cmd_init_response_queue(dev, true); + break; + case QL_CMD_EXECUTE_IOCB_A64: + status = ql_handle_exec_mbox_iocb(dev, true); + break; + case QL_CMD_GET_TRANSFER_MODE: + status = ql_handle_cmd_get_transfer_mode(dev); + break; + case QL_CMD_SET_DATA_OVERRUN_RECOVERY: + status = ql_handle_cmd_set_data_overrun_recovery(dev); + break; + + default: + ql_log("Unhandled or invalid command %02X\n", dev->reg_mbox_in[0]); + status = QL_MBOX_STATUS_INVALID; + break; + } + + return status; +} + +/* RQSTYPE_REQUEST */ +static void +ql_pkt_get_sgl_req(uint32_t address, uint32_t idx, isp_data_seg_t *data_seg) +{ + uint32_t offset = address + 32 + idx * 8; + + ql_dma_read32(offset + 0, &data_seg->address); + ql_dma_read32(offset + 4, &data_seg->length); +} + +/* RQSTYPE_REQUEST_A64 */ +static void +ql_pkt_get_sgl_req64(uint32_t address, uint32_t idx, isp_data_seg_t *data_seg) +{ + uint32_t offset = address + 36 + idx * 12; + + /* The high part of the address is ignored for 86Box */ + ql_dma_read32(offset + 0, &data_seg->address); + ql_dma_read32(offset + 8, &data_seg->length); +} + +/* RQSTYPE_DATASEG */ +static void +ql_pkt_get_sgl_cont(uint32_t address, uint32_t idx, isp_data_seg_t *data_seg) +{ + uint32_t offset = address + 8 + idx * 8; + + ql_dma_read32(offset + 0, &data_seg->address); + ql_dma_read32(offset + 4, &data_seg->length); +} + +/* RQSTYPE_A64_CONT */ +static void +ql_pkt_get_sgl_cont64(uint32_t address, uint32_t idx, isp_data_seg_t *data_seg) +{ + uint32_t offset = address + 4 + idx * 12; + + /* The high part of the address is ignored for 86Box */ + ql_dma_read32(offset + 0, &data_seg->address); + ql_dma_read32(offset + 8, &data_seg->length); +} + +static void +ql_pkt_get_entry_type(uint32_t address, uint8_t *entry_type) +{ + ql_dma_read8(address + 0, entry_type); +} + +static void +ql_pkt_put_header(uint32_t address, isp_hdr_t *hdr) +{ + ql_dma_write8(address + 0, &hdr->entry_type); + ql_dma_write8(address + 1, &hdr->entry_count); + ql_dma_write8(address + 2, &hdr->seqno); + ql_dma_write8(address + 3, &hdr->flags); +} + +static void +ql_pkt_put_request_status(uint32_t address, isp_req_status_t *resp) +{ + ql_pkt_put_header(address, &resp->hdr); + + ql_dma_write32(address + 4, &resp->handle); + ql_dma_write16(address + 8, &resp->scsi_status); + ql_dma_write16(address + 10, &resp->comp_status); + ql_dma_write16(address + 12, &resp->state_flags); + ql_dma_write16(address + 14, &resp->status_flags); + ql_dma_write16(address + 16, &resp->time); + ql_dma_write16(address + 18, &resp->sense_length); + ql_dma_write32(address + 20, &resp->residual_length); + ql_dma_write(address + 24, &resp->response[0], ARRAY_SIZE(resp->response)); + ql_dma_write(address + 32, &resp->sense_data[0], ARRAY_SIZE(resp->sense_data)); + + ql_log("QL: RESP HDR type 0x%X cnt %u seq %u fl 0x%X\n", + resp->hdr.entry_type, + resp->hdr.entry_count, + resp->hdr.seqno, + resp->hdr.flags); + ql_log("QL: RESP h 0x%X scsi 0x%X comp 0x%X state 0x%X statfl 0x%X time %u sens %u resid %u\n", + resp->handle, + resp->scsi_status, + resp->comp_status, + resp->state_flags, + resp->status_flags, + resp->time, + resp->sense_length, + resp->residual_length); +} + +static bool +ql_sxp_fetch_request(ql_sxp_req_t* pkt, uint32_t address) +{ + /* Fetch the header */ + ql_dma_read8(address + 0, &pkt->hdr.entry_type); + ql_dma_read8(address + 1, &pkt->hdr.entry_count); + ql_dma_read8(address + 2, &pkt->hdr.seqno); + ql_dma_read8(address + 3, &pkt->hdr.flags); + + switch (pkt->hdr.entry_type) { + case RQSTYPE_REQUEST: + case RQSTYPE_REQUEST_A64: { + ql_dma_read32(address + 4, &pkt->handle); + ql_dma_read8(address + 8, &pkt->lun); + ql_dma_read8(address + 9, &pkt->bus_target); + ql_dma_read16(address + 10, &pkt->cdb_length); + ql_dma_read16(address + 12, &pkt->flags); + ql_dma_read16(address + 14, &pkt->reserved); + ql_dma_read16(address + 16, &pkt->timeout); + ql_dma_read16(address + 18, &pkt->seg_count); + ql_dma_read(address + 20, &pkt->cdb[0], ARRAY_SIZE(pkt->cdb)); + return true; + } + + case RQSTYPE_MARKER: { + ql_dma_read32(address + 4, &pkt->handle); + ql_dma_read8(address + 8, &pkt->lun); + ql_dma_read8(address + 9, &pkt->bus_target); + pkt->timeout = 0; + return true; + } + + default: + break; + } + + ql_log("QL: Unknown/invalid request type %u\n", pkt->hdr.entry_type); + return false; +} + +static void +ql_sxp_begin_response_entry(ql_sxp_req_t *pkt, isp_req_status_t *resp) +{ + memset(resp, 0, sizeof(*resp)); + resp->hdr.entry_type = RQSTYPE_RESPONSE; + resp->hdr.entry_count = pkt->hdr.entry_count; + resp->hdr.seqno = pkt->hdr.seqno; + resp->hdr.flags = pkt->hdr.flags; + resp->handle = pkt->handle; + resp->time = pkt->timeout; +} + +static double +ql_sxp_handle_state_send_cdb_bios(ql_t *dev, scsi_device_t *sd) +{ + ql_sxp_req_t *pkt = &dev->pkt; + isp_req_status_t *resp = &dev->pkt_resp; + double media_period = 10.0; + uint64_t bytes_xfered = 0; + + if (dev->scsi_data_buffer) { + free(dev->scsi_data_buffer); + dev->scsi_data_buffer = NULL; + } + + if ((sd->phase != SCSI_PHASE_STATUS) && (sd->buffer_length > 0)) { + uint32_t dev_buffer_length = sd->buffer_length; + uint8_t *dev_buffer = sd->sc->temp_buffer; + uint32_t host_buffer_size; + double p; + + p = scsi_device_get_callback(sd); + if (p <= 0.0) + bytes_xfered += sd->buffer_length; + else + media_period = p; + + host_buffer_size = dev->cpu_mem[QL_IOCB_FW_BASE + 2]; + host_buffer_size |= (uint32_t)dev->cpu_mem[QL_IOCB_FW_BASE + 3] << 16; + + if (dev->cpu_mem[QL_IOCB_FW_BASE + 12] == 3) { + /* PIO */ + dev->scsi_data_offset = 0; + dev->scsi_data_size = dev_buffer_length; + dev->scsi_data_buffer = malloc(dev_buffer_length); + memcpy(dev->scsi_data_buffer, dev_buffer, dev_buffer_length); + } else { + uint32_t address, block_size; + + address = dev->cpu_mem[QL_IOCB_FW_BASE + 0]; + address |= (uint32_t)dev->cpu_mem[QL_IOCB_FW_BASE + 1] << 16; + + block_size = MIN(host_buffer_size, dev_buffer_length); + + /* DMA */ + if (sd->phase == SCSI_PHASE_DATA_IN) { + ql_log("QL: DMA to 0x%lx %lu bytes\n", address, block_size); + ql_dma_write(address, dev_buffer, block_size); + } else if (sd->phase == SCSI_PHASE_DATA_OUT) { + ql_log("QL: DMA from 0x%lx %lu bytes\n", address, block_size); + ql_dma_read(address, dev_buffer, block_size); + } + } + scsi_device_command_phase1(sd); + + if (dev_buffer_length < host_buffer_size) { + /* + * Data underrun + * + * NOTE: It seems that there is no way to return residual_length to the software. + * It has been observed that the BIOS does a retry in PIO mode + * when a DMA underrun error occurs. + */ + resp->comp_status = RQCS_DATA_UNDERRUN; + } else if (dev_buffer_length > host_buffer_size) { + /* Data overrun */ + resp->comp_status = RQCS_DATA_OVERRUN; + } else { + /* Normal completion */ + resp->comp_status = RQCS_COMPLETE; + } + resp->scsi_status = sd->status; + } else { + resp->scsi_status = sd->status; + resp->comp_status = RQCS_COMPLETE; + } + + return media_period + (1000000.0 / dev->xfer_rate_bps) * (double)bytes_xfered; +} + +static double +ql_sxp_handle_state_send_cdb_sgl(ql_t *dev, scsi_device_t *sd) +{ + ql_sxp_req_t *pkt = &dev->pkt; + isp_req_status_t *resp = &dev->pkt_resp; + double media_period = 10.0; + uint64_t bytes_xfered = QENTRY_LEN; + + /* Read/write command */ + if ((sd->phase != SCSI_PHASE_STATUS) && (sd->buffer_length > 0)) { + uint32_t dev_buffer_length = sd->buffer_length; + uint8_t *dev_buffer = sd->sc->temp_buffer; + uint8_t entry_type = pkt->hdr.entry_type; + uint32_t pkt_address = dev->pkt_address; + uint16_t pkt_entry_idx = QL_RQST_CONS(dev); + uint32_t host_buffer_size = 0; + uint32_t bytes_moved = 0; + uint32_t max_seg_count; + double p; + + p = scsi_device_get_callback(sd); + if (p <= 0.0) + bytes_xfered += sd->buffer_length; + else + media_period = p; + + if (entry_type == RQSTYPE_REQUEST) { + max_seg_count = 4; + } else { + assert(entry_type == RQSTYPE_REQUEST_A64); + max_seg_count = 2; + } + + /* Process the S/G list */ + for (uint32_t i = 0, seg_idx = 0; i < pkt->seg_count; i++, seg_idx++) { + isp_data_seg_t data_seg; + uint32_t block_size; + + /* Fetch a continuation segment entry */ + if (seg_idx == max_seg_count) { + seg_idx = 0; + + pkt_entry_idx = (pkt_entry_idx + 1) % dev->rqst_ring_size; + pkt_address = dev->rqst_ring_base + pkt_entry_idx * QENTRY_LEN; + + ql_pkt_get_entry_type(pkt_address, &entry_type); + if (entry_type == RQSTYPE_DATASEG) { + max_seg_count = 7; + } else if (entry_type == RQSTYPE_A64_CONT) { + max_seg_count = 5; + } else { + /* Bad entry in the request ring */ + ql_log("QL: Expected continuation segment but got %u\n", entry_type); + break; + } + } + + /* Read the S/G fragment */ + switch (entry_type) { + case RQSTYPE_REQUEST: + ql_pkt_get_sgl_req(pkt_address, seg_idx, &data_seg); + break; + case RQSTYPE_REQUEST_A64: + ql_pkt_get_sgl_req64(pkt_address, seg_idx, &data_seg); + break; + case RQSTYPE_DATASEG: + ql_pkt_get_sgl_cont(pkt_address, seg_idx, &data_seg); + break; + case RQSTYPE_A64_CONT: + ql_pkt_get_sgl_cont64(pkt_address, seg_idx, &data_seg); + break; + + default: + /* Should not happen */ + assert(false); + break; + } + host_buffer_size += data_seg.length; + block_size = MIN(data_seg.length, dev_buffer_length - bytes_moved); + bytes_xfered += sizeof(data_seg); + + if (sd->phase == SCSI_PHASE_DATA_IN) { + ql_log("QL: DMA to 0x%lx %lu bytes\n", data_seg.address, block_size); + ql_dma_write(data_seg.address, &dev_buffer[bytes_moved], block_size); + } else if (sd->phase == SCSI_PHASE_DATA_OUT) { + ql_log("QL: DMA from 0x%lx %lu bytes\n", data_seg.address, block_size); + ql_dma_read(data_seg.address, &dev_buffer[bytes_moved], block_size); + } + bytes_moved += block_size; + } + scsi_device_command_phase1(sd); + + if (dev_buffer_length < host_buffer_size) { + /* Data underrun */ + resp->residual_length = host_buffer_size - dev_buffer_length; + resp->comp_status = RQCS_DATA_UNDERRUN; + } else if (dev_buffer_length > host_buffer_size) { + /* Data overrun */ + resp->comp_status = RQCS_DATA_OVERRUN; + } else { + /* Normal completion */ + resp->comp_status = RQCS_COMPLETE; + } + resp->scsi_status = sd->status; + resp->state_flags |= RQSF_GOT_STATUS | RQSF_XFER_COMPLETE; + } else { + resp->scsi_status = sd->status; + resp->comp_status = RQCS_COMPLETE; + resp->state_flags |= RQSF_GOT_STATUS; + } + + /* Auto request sense */ + if ((resp->scsi_status == SCSI_STATUS_CHECK_CONDITION) && !(pkt->flags & REQFLAG_DISARQ)) { + if (dev->fw_tid_params[dev->curr_path_id][dev->curr_target_id].flags & DPARM_ARQ) { + scsi_device_request_sense(sd, resp->sense_data, sizeof(resp->sense_data)); + + resp->state_flags |= RQSF_GOT_SENSE; + resp->sense_length = sizeof(resp->sense_data); + + bytes_xfered += resp->sense_length; + } + } + + return media_period + (1000000.0 / dev->xfer_rate_bps) * (double)bytes_xfered; +} + +static bool +ql_sxp_state_machine(ql_t *dev) +{ + switch (dev->sxp_state) { + case SXP_STATE_IDLE: { + ql_sxp_req_t *pkt = &dev->pkt; + + /* Do we have to pick mailbox registers up? */ + if (dev->sxp_flags & SXP_FLAG_PICK_UP_MBOX) { + dev->sxp_flags &= ~SXP_FLAG_PICK_UP_MBOX; + + dev->mbox_out_mask = 1 << QL_MBOX_STATUS; + dev->mbox_data[QL_MBOX_STATUS] = ql_process_mailbox(dev); + + /* Check for mailbox commands that do not need to go through the command processor */ + if (dev->mbox_data[QL_MBOX_STATUS] != QL_MBOX_STATUS_PENDING) { + dev->timer_period = QL_MBOX_GENERIC_TIME_US; + dev->sxp_state = SXP_STATE_SCHEDULE_MBOX_INTERRUPT; + break; + } + + assert(dev->sxp_flags & (SXP_FLAG_BIOS_IOCB | SXP_FLAG_MBOX_IOCB)); + + if (dev->sxp_flags & SXP_FLAG_BIOS_IOCB) { + uint8_t lun = dev->cpu_mem[QL_IOCB_FW_BASE + 48] & 0x0F; + uint8_t target_id = (dev->cpu_mem[QL_IOCB_FW_BASE + 48] & 0xF0) >> 4 ; + uint8_t *cdb_bytes = (uint8_t *)&dev->cpu_mem[QL_IOCB_FW_BASE + 5]; + + /* Translate the BIOS IOCB request into a common structure for easier processing */ + memset(pkt, 0, sizeof(*pkt)); + pkt->hdr.entry_type = RQSTYPE_REQUEST; + pkt->hdr.entry_count = 1; + pkt->lun = lun; + pkt->bus_target = target_id; + pkt->cdb_length = ARRAY_SIZE(pkt->cdb); + memcpy(pkt->cdb, cdb_bytes, ARRAY_SIZE(pkt->cdb)); + + dev->sxp_state = SXP_STATE_SELECT_DEVICE; + break; + } + } + + if (dev->sxp_flags & SXP_FLAG_MBOX_IOCB) { + dev->pkt_address = ((uint32_t)dev->reg_mbox_in[2] << 16) | dev->reg_mbox_in[3]; + } else { + /* Skip processing command queues if they are not initialized */ + if (!(dev->sxp_flags & SXP_FLAG_ENGINE_ACTIVE)) { + return false; + } + + /* No available entries the request queue, try again later */ + if (QL_RQST_CONS(dev) == QL_RQST_PROD(dev)) { + return false; + } + + /* No room in the response queue, try again later */ + if (((QL_RESP_PROD(dev) + 1) % dev->resp_ring_size) == QL_RESP_CONS(dev)) { + return false; + } + + /* Check is this entry has been aborted */ + if (!fifo8_is_empty(&dev->abort_iocbs_fifo)) { + const uint8_t* idx_buf; + uint16_t rqst_idx; + + idx_buf = fifo8_peek_bufptr(&dev->abort_iocbs_fifo, sizeof(rqst_idx), NULL); + rqst_idx = ((uint16_t)idx_buf[1] << 8) | idx_buf[0]; + + if (rqst_idx == QL_RQST_CONS(dev)) { + fifo8_drop(&dev->abort_iocbs_fifo, sizeof(rqst_idx)); + + dev->sxp_flags |= SXP_FLAG_ABORTED_CMD; + + dev->timer_period = QL_MBOX_GENERIC_TIME_US; + dev->sxp_state = SXP_STATE_COMPLETE_COMMAND; + break; + } + } + + dev->pkt_address = dev->rqst_ring_base + QL_RQST_CONS(dev) * QENTRY_LEN; + } + + if (!ql_sxp_fetch_request(pkt, dev->pkt_address)) { + /* Skip this packet */ + pkt->hdr.entry_count = 1; + + dev->sxp_state = SXP_STATE_BAD_PACKET; + break; + } + + dev->sxp_state = SXP_STATE_SELECT_DEVICE; + break; + } + case SXP_STATE_SELECT_DEVICE: { + ql_sxp_req_t *pkt = &dev->pkt; + + ql_log("QL: RQST HDR type 0x%X cnt %u seq %u fl 0x%X\n", + pkt->hdr.entry_type, + pkt->hdr.entry_count, + pkt->hdr.seqno, + pkt->hdr.flags); + ql_log("QL: RQST h 0x%X lun %u bus_tid 0x%X cdb_len %u fl 0x%X time %u seq_cnt %u\n", + pkt->handle, + pkt->lun, + pkt->bus_target, + pkt->cdb_length, + pkt->flags, + pkt->timeout, + pkt->seg_count); + + /* Extract the SCSI address */ + dev->curr_path_id = (pkt->bus_target & 0x80) >> 7; + dev->curr_target_id = pkt->bus_target & ~0x80; + + if (dev->curr_path_id >= dev->max_bus_count) { + dev->sxp_state = SXP_STATE_SELECTION_TIMEOUT; + break; + } + + /* 86Box supports one SCSI bus per controller for now */ + if (dev->curr_path_id != 0) { + dev->sxp_state = SXP_STATE_SELECTION_TIMEOUT; + break; + } + + if (dev->curr_target_id >= MIN(QL_MAX_TID, SCSI_ID_MAX)) { + dev->sxp_state = SXP_STATE_SELECTION_TIMEOUT; + break; + } + + if (!scsi_device_present(&scsi_devices[dev->scsi_bus][dev->curr_target_id])) { + dev->sxp_state = SXP_STATE_SELECTION_TIMEOUT; + break; + } + + ql_log("QL: Selected target %u:%u\n", dev->curr_path_id, dev->curr_target_id); + dev->sxp_state = SXP_STATE_SEND_CDB; + break; + } + case SXP_STATE_SEND_CDB: { + scsi_device_t *sd = &scsi_devices[dev->scsi_bus][dev->curr_target_id]; + ql_sxp_req_t *pkt = &dev->pkt; + isp_req_status_t *resp = &dev->pkt_resp; + + ql_sxp_begin_response_entry(pkt, resp); + resp->state_flags = RQSF_GOT_BUS | RQSF_GOT_TARGET | RQSF_SENT_CDB; + + if (pkt->hdr.entry_type == RQSTYPE_MARKER) { + resp->scsi_status = SCSI_STATUS_OK; + resp->comp_status = RQCS_COMMAND_OVERRUN; + resp->status_flags = RQSTF_ABORTED; + + dev->timer_period = QL_MBOX_GENERIC_TIME_US; + dev->sxp_state = SXP_STATE_COMPLETE_COMMAND; + break; + } + + scsi_device_identify(sd, pkt->lun); + + for (uint32_t i = 0; i < ARRAY_SIZE(pkt->cdb); i++) { + ql_log("QL: SCSI CDB[%2lu]=%02X\n", i, pkt->cdb[i]); + } + + sd->buffer_length = -1; + scsi_device_command_phase0(sd, pkt->cdb); + + if (dev->sxp_flags & SXP_FLAG_BIOS_IOCB) { + dev->timer_period = ql_sxp_handle_state_send_cdb_bios(dev, sd); + } else { + dev->timer_period = ql_sxp_handle_state_send_cdb_sgl(dev, sd); + } + scsi_device_identify(sd, SCSI_LUN_USE_CDB); + + dev->sxp_state = SXP_STATE_COMPLETE_COMMAND; + break; + } + case SXP_STATE_SELECTION_TIMEOUT: { + isp_req_status_t *resp = &dev->pkt_resp; + + ql_sxp_begin_response_entry(&dev->pkt, resp); + resp->scsi_status = SCSI_STATUS_OK; + resp->comp_status = RQCS_INCOMPLETE; + resp->state_flags = RQSF_GOT_BUS; + resp->status_flags = RQSTF_TIMEOUT; + + dev->timer_period = QL_CMD_SELECTION_TIMEOUT_TIME_US; + dev->sxp_state = SXP_STATE_COMPLETE_COMMAND; + break; + } + case SXP_STATE_BAD_PACKET: { + isp_req_status_t *resp = &dev->pkt_resp; + + memset(resp, 0, sizeof(*resp)); + resp->hdr.entry_type = 0; + resp->hdr.flags = RQSFLAG_BADHEADER; + resp->comp_status = RQCS_INCOMPLETE; + + dev->timer_period = QL_MBOX_GENERIC_TIME_US; + dev->sxp_state = SXP_STATE_COMPLETE_COMMAND; + break; + } + case SXP_STATE_COMPLETE_COMMAND: { + isp_req_status_t *resp = &dev->pkt_resp; + ql_sxp_req_t *pkt = &dev->pkt; + + /* There are three possible ways of sending SCSI commands to ISP */ + if (dev->sxp_flags & SXP_FLAG_BIOS_IOCB) { + dev->mbox_out_mask = (1 << QL_MBOX_STATUS) | QL_BIT(1) | QL_BIT(2); + dev->mbox_data[QL_MBOX_STATUS] = QL_MBOX_STATUS_COMPLETE; + dev->mbox_data[1] = resp->comp_status; + dev->mbox_data[2] = resp->scsi_status; + + /* Return the internal queue index */ + dev->cpu_mem[QL_IOCB_FW_BASE + 13] = 0; + + dev->sxp_state = SXP_STATE_SCHEDULE_MBOX_INTERRUPT; + } else if (dev->sxp_flags & SXP_FLAG_MBOX_IOCB) { + dev->mbox_out_mask = (1 << QL_MBOX_STATUS); + dev->mbox_data[QL_MBOX_STATUS] = QL_MBOX_STATUS_COMPLETE; + + /* Mailbox IOCB commands always write a response queue entry */ + dev->sxp_flags |= SXP_FLAG_WRITE_RESP_IOCB; + dev->sxp_state = SXP_STATE_SCHEDULE_MBOX_INTERRUPT; + } else { + uint16_t num_consumed = MAX(pkt->hdr.entry_count, 1); + QL_RQST_CONS(dev) = (QL_RQST_CONS(dev) + num_consumed) % dev->rqst_ring_size; + + if ((dev->sxp_flags & SXP_FLAG_ABORTED_CMD) || (pkt->hdr.entry_type == RQSTYPE_MARKER)) { + /* + * Marker entries never raise an interrupt, even if the SCSI device does not exist. + * Aborted commands also never raise an interrupt. + */ + dev->sxp_state = SXP_STATE_SCHEDULE_TIMER_SILENCE; + } else if ((dev->sxp_flags & SXP_FLAG_FAST_POSTING) && + (resp->scsi_status == SCSI_STATUS_OK) && + (resp->comp_status == RQCS_COMPLETE)) { + /* Fast posting avoids having to deal with response queue for successful commands */ + dev->mbox_out_mask = (1 << QL_MBOX_STATUS) | (1 << QL_MBOX_HNDL_LOW) | 1 << (QL_MBOX_HNDL_HIGH); + dev->mbox_data[QL_MBOX_STATUS] = QL_ASYNC_STATUS_SCSI_CMD_COMPLETE; + dev->mbox_data[QL_MBOX_HNDL_LOW] = pkt->handle & 0xFFFF; + dev->mbox_data[QL_MBOX_HNDL_HIGH] = (pkt->handle >> 16) & 0xFFFF; + + dev->sxp_state = SXP_STATE_SCHEDULE_MBOX_INTERRUPT; + } else { + /* Normal command completion, write a response queue entry */ + dev->pkt_address = dev->resp_ring_base + QL_RESP_PROD(dev) * QENTRY_LEN; + dev->sxp_flags |= SXP_FLAG_WRITE_RESP_IOCB | SXP_FLAG_INC_RESP_RING; + dev->sxp_state = SXP_STATE_SCHEDULE_RISC_INTERRUPT; + } + } + break; + } + case SXP_STATE_SCHEDULE_RISC_INTERRUPT: { + dev->sxp_state = SXP_STATE_SET_RISC_INTERRUPT; + timer_on_auto(&dev->cmd_timer, dev->timer_period); + return false; + } + case SXP_STATE_SCHEDULE_MBOX_INTERRUPT: { + dev->sxp_state = SXP_STATE_MBOX_WAIT_TIMER; + timer_on_auto(&dev->cmd_timer, dev->timer_period); + return false; + } + case SXP_STATE_MBOX_WAIT_TIMER: { + dev->sxp_state = SXP_STATE_ACQUIRE_MBOX_SEMAPHORE; + break; + } + case SXP_STATE_ACQUIRE_MBOX_SEMAPHORE: { + /* Wait for the mailbox semaphore to be released */ + if (dev->reg_semaphore & QL_SEMAPHORE_LOCK) { + return false; + } + + /* Return mailbox registers to the host */ + for (uint32_t i = 0; i < ARRAY_SIZE(dev->reg_mbox_out); i++) { + if (dev->mbox_out_mask & (1 << i)) { + dev->reg_mbox_out[i] = dev->mbox_data[i]; + } + } + dev->reg_semaphore = QL_SEMAPHORE_LOCK; + fallthrough; + } + case SXP_STATE_SET_RISC_INTERRUPT: { + if (dev->sxp_flags & SXP_FLAG_WRITE_RESP_IOCB) { + ql_pkt_put_request_status(dev->pkt_address, &dev->pkt_resp); + + if (dev->sxp_flags & SXP_FLAG_INC_RESP_RING) { + QL_RESP_PROD(dev) = (QL_RESP_PROD(dev) + 1) % dev->resp_ring_size; + } + } + dev->sxp_flags &= ~(SXP_FLAG_WRITE_RESP_IOCB | SXP_FLAG_INC_RESP_RING + | SXP_FLAG_BIOS_IOCB | SXP_FLAG_MBOX_IOCB | SXP_FLAG_ABORTED_CMD); + + dev->reg_intr_status |= QL_INTR_REQ | QL_RISC_INTR_REQ; + ql_update_irq(dev); + + dev->sxp_state = SXP_STATE_IDLE; + break; + } + case SXP_STATE_SCHEDULE_TIMER_SILENCE: { + dev->sxp_state = SXP_STATE_WAIT_TIMER; + timer_on_auto(&dev->cmd_timer, dev->timer_period); + return false; + } + case SXP_STATE_WAIT_TIMER: { + dev->sxp_state = SXP_STATE_IDLE; + break; + } + + default: { + /* Should not happen */ + assert(false); + break; + } + } + + return true; +} + +static void +ql_sxp_run_state_machine(ql_t *dev) +{ + ql_log("QL: Enter with %s\n", debug_sxp_state_to_name(dev->sxp_state)); + + while (true) { + SxpState old_state = dev->sxp_state; + + if (!ql_sxp_state_machine(dev)) { + break; + } + + if (dev->sxp_state != old_state) { + ql_log("QL: State %s --> %s\n", debug_sxp_state_to_name(old_state), debug_sxp_state_to_name(dev->sxp_state)); + } + } + + ql_log("QL: Exit with %s\n", debug_sxp_state_to_name(dev->sxp_state)); +} + +static void +ql_sxp_kick_engine(ql_t *dev) +{ + if (dev->sxp_state == SXP_STATE_IDLE) { + ql_log("QL: SCSI kick\n"); + ql_sxp_run_state_machine(dev); + } +} + +static void +ql_sxp_timer_callback(void *priv) +{ + ql_t *dev = priv; + + ql_log("QL: Timer called\n"); + + assert(dev->sxp_state != SXP_STATE_IDLE); + + ql_sxp_run_state_machine(dev); +} + +static void +ql_sxp_write_semaphore(ql_t *dev, uint16_t val) +{ + if (val == 0) { + val = QL_SEMAPHORE_STATUS; + } else { + val &= QL_SEMAPHORE_STATUS | QL_SEMAPHORE_LOCK; + } + dev->reg_semaphore = val; + + if (dev->sxp_state == SXP_STATE_ACQUIRE_MBOX_SEMAPHORE) { + ql_sxp_run_state_machine(dev); + } +} + +static void +ql_sxp_write_mailbox(ql_t *dev, uint32_t idx, uint16_t val) +{ + dev->reg_mbox_in[idx] = val; + + /* Kick the command processor */ + if ((idx == QL_MBOX_RQST) || (idx == QL_MBOX_RESP)) { + ql_sxp_kick_engine(dev); + } +} + +static void +ql_write_host_command(ql_t *dev, uint16_t val) +{ + switch (val) { + case QL_HC_RESET_RISC: + dev->reg_host_cmd_flags = QL_HC_FLAG_RISC_RESET; + break; + case QL_HC_PAUSE_RISC: + dev->reg_host_cmd_flags |= QL_HC_FLAG_RISC_PAUSE; + break; + case QL_HC_RELEASE_RISC: + dev->reg_host_cmd_flags &= ~(QL_HC_FLAG_RISC_PAUSE | QL_HC_FLAG_RISC_RESET); + break; + case QL_HC_SET_HOST_INTR: + dev->reg_host_cmd_flags |= QL_HC_FLAG_HOST_INTR; + dev->sxp_flags |= SXP_FLAG_PICK_UP_MBOX; + ql_sxp_kick_engine(dev); + break; + case QL_HC_CLEAR_HOST_INTR: + /* This command does nothing */ + break; + case QL_HC_CLEAR_RISC_INTR: + dev->reg_host_cmd_flags &= ~QL_HC_FLAG_HOST_INTR; + dev->reg_intr_status = 0; + ql_update_irq(dev); + break; + case QL_HC_DISABLE_BIOS: + dev->reg_host_cmd_flags = 0; + break; + + default: { + ql_log("QL: Unknown host command %04X\n", val); + break; + } + } +} + +static void +ql_write_interface_control(ql_t *dev, uint16_t val) +{ + if (val & QL_IFACE_SOFT_RESET) { + ql_reset_asic(dev); + return; + } + + dev->reg_intr_ctrl = val & 0x01FF; + ql_update_irq(dev); +} + +static uint32_t +ql_get_flash_bios_addr(ql_t *dev) +{ + uint32_t address = dev->reg_flash_bios_addr; + + /* Select between two consecutive flash memory banks of 64KB each */ + if (dev->reg_nvram & QL_EEPROM_CS) { + address |= 0x10000; + } + return address; +} + +static uint16_t +ql_read_flash_bios_data(ql_t *dev) +{ + uint8_t byte; + + if (!(dev->reg_intr_ctrl & QL_IFACE_FLASH_ENABLE)) { + return 0xFFFF; + } + + byte = am29_mmio_read8(ql_get_flash_bios_addr(dev), &dev->flash_device); + return (byte << 8) | byte; +} + +static void +ql_write_flash_bios_data(ql_t *dev, uint16_t value) +{ + if (!(dev->reg_intr_ctrl & QL_IFACE_FLASH_ENABLE)) { + return; + } + + am29_mmio_write8(ql_get_flash_bios_addr(dev), (uint8_t)value, &dev->flash_device); +} + +static void +ql_write_bank_sxp(ql_t *dev, uint32_t addr, uint32_t bus_number, uint16_t val) +{ + if (bus_number >= dev->max_bus_count) { + return; + } + + ql_log("QL: [W16] Unhandled SPX bank write %lX <-- %X\n", IDX_TO_REG(addr), val); +} + +static void +ql_write_bank_dma(ql_t *dev, uint32_t addr, uint16_t val) +{ + switch (addr) { + case QL_REG_CDMA_CFG: + dev->reg_cdma_cfg = val; + break; + case QL_REG_CDMA_CTRL: + dev->reg_cdma_ctrl = val; + break; + case QL_REG_DDMA_CFG: + dev->reg_ddma_cfg = val; + break; + case QL_REG_DDMA_CTRL: + dev->reg_ddma_ctrl = val; + break; + + default: + ql_log("QL: [W16] Unhandled DMA bank write %lX <-- %X\n", IDX_TO_REG(addr), val); + break; + } +} + +static uint16_t +ql_write_bank_risc(ql_t *dev, uint32_t addr, uint16_t val) +{ + switch (addr) { + case QL_REG_RISC_PSR: + dev->reg_risc_psr = val; + break; + case QL_REG_RISC_PCR: + dev->reg_risc_pcr = val; + break; + case QL_REG_RISC_MTR: + dev->reg_risc_mtr = val; + break; + case QL_REG_HOST_CMD: + ql_write_host_command(dev, val); + break; + case QL_REG_GPIO_DATA: + dev->reg_gpio_data = val; + break; + case QL_REG_GPIO_ENABLE: + dev->reg_gpio_enable = val; + break; + + default: + ql_log("QL: [W16] Unhandled RISC bank write %lX <-- %X\n", IDX_TO_REG(addr), val); + break; + } +} + +static void +ql_mmio_write16(uint32_t addr, uint16_t val, void* priv) +{ + ql_t *dev = priv; + + /* The hw does not handle unaligned access */ + if (addr & 0x1) { + return; + } + + addr &= QL_IO_DECODE_MASK; + addr = REG_TO_IDX(addr); + +#ifdef ENABLE_QL_LOG + ql_debug_check_for_nvram_access(addr); +#endif + + ql_log("QL: [W16] [%02lX] <-- %4X\n", IDX_TO_REG(addr), val); + + switch (addr) { + case QL_REG_CFG1: + dev->reg_cfg1 = val & 0x03FF; + break; + case QL_REG_INT_CTRL: + ql_write_interface_control(dev, val); + break; + case QL_REG_SEMAPHORE: + ql_sxp_write_semaphore(dev, val); + break; + case QL_REG_NVRAM: + dev->reg_nvram = val & (QL_EEPROM_SK | QL_EEPROM_CS | QL_EEPROM_DI); + nmc93cxx_eeprom_write(dev->eeprom_device, + !!(val & QL_EEPROM_CS), + !!(val & QL_EEPROM_SK), + !!(val & QL_EEPROM_DI)); + break; + case QL_REG_FLASH_BIOS_DATA: + ql_write_flash_bios_data(dev, val); + break; + case QL_REG_FLASH_BIOS_ADDRESS: + dev->reg_flash_bios_addr = val; + break; + case QL_REG_MAILBOX0: + case QL_REG_MAILBOX1: + case QL_REG_MAILBOX2: + case QL_REG_MAILBOX3: + case QL_REG_MAILBOX4: + case QL_REG_MAILBOX5: + case QL_REG_MAILBOX6: + case QL_REG_MAILBOX7: + ql_sxp_write_mailbox(dev, addr - QL_REG_MAILBOX0, val); + break; + + default: { + if (dev->isp_type == QL_ISP1040) { + if (addr >= REG_TO_IDX(0x20) && addr < REG_TO_IDX(0x80)) { + /* DMA bank */ + addr -= REG_TO_IDX(0x20); + ql_write_bank_dma(dev, addr, val); + break; + } else if (addr >= REG_TO_IDX(0x80) && addr < REG_TO_IDX(0xFF)) { + /* RISC or SXP bank */ + addr -= REG_TO_IDX(0x80); + if (dev->reg_cfg1 & BIU_PCI_CONF1_SXP) { + ql_write_bank_sxp(dev, addr, 0, val); + } else { + ql_write_bank_risc(dev, addr, val); + } + break; + } + } else { + if (addr >= REG_TO_IDX(0x80) && addr < REG_TO_IDX(0xFF)) { + addr -= REG_TO_IDX(0x80); + + switch (dev->reg_cfg1 & BIU_PCI1080_REG_BANK_MASK) { + case BIU_PCI1080_CONF1_SXP0: + ql_write_bank_sxp(dev, addr, 0, val); + break; + case BIU_PCI1080_CONF1_SXP1: + ql_write_bank_sxp(dev, addr, 1, val); + break; + case BIU_PCI1080_CONF1_DMA: + ql_write_bank_dma(dev, addr, val); + break; + default: + ql_write_bank_risc(dev, addr, val); + break; + } + break; + } + } + + ql_log("QL: [W16] Unhandled write %lX <-- %X\n", IDX_TO_REG(addr), val); + break; + } + } +} + +static uint16_t +ql_read_bank_sxp(ql_t *dev, uint32_t addr, uint32_t bus_number) +{ + uint16_t ret; + + if (bus_number >= dev->max_bus_count) { + return 0; + } + + switch (addr) { + case QL_REG_SXP_PINS_DIFF: + ret = dev->reg_scsi_diff_pins; + break; + + default: + ql_log("QL: [R16] Unhandled SXP bank read %lX\n", IDX_TO_REG(addr)); + ret = 0; + break; + } + + return ret; +} + +static uint16_t +ql_read_bank_dma(ql_t *dev, uint32_t addr) +{ + uint16_t ret; + + switch (addr) { + case QL_REG_CDMA_CFG: + ret = dev->reg_cdma_cfg; + break; + case QL_REG_CDMA_CTRL: + ret = dev->reg_cdma_ctrl; + break; + case QL_REG_DDMA_CFG: + ret = dev->reg_ddma_cfg; + break; + case QL_REG_DDMA_CTRL: + ret = dev->reg_ddma_ctrl; + break; + + case QL_REG_DDMA_DATA_PORT: { + if (!dev->scsi_data_buffer) { + ret = 0; + break; + } + + /* Return a word via PIO interface */ + ret = 0; + for (uint32_t i = 0; i < sizeof(uint16_t); i++) { + uint8_t byte = dev->scsi_data_buffer[dev->scsi_data_offset++]; + + ql_log("QL: Return byte 0x%02X at offset %lu\n", byte, dev->scsi_data_offset - 1); + + ret |= (uint16_t)byte << (i * 8); + + /* Last byte, destroy the buffer */ + if (dev->scsi_data_offset >= dev->scsi_data_size) { + ql_log("QL: All data has been transmitted\n"); + + free(dev->scsi_data_buffer); + dev->scsi_data_buffer = NULL; + break; + } + } + break; + } + + default: + ql_log("QL: [R16] Unhandled DMA bank read %lX\n", IDX_TO_REG(addr)); + ret = 0; + break; + } + + return ret; +} + +static uint16_t +ql_read_bank_risc(ql_t *dev, uint32_t addr) +{ + uint16_t ret; + + switch (addr) { + case QL_REG_RISC_PSR: + ret = dev->reg_risc_psr; + break; + case QL_REG_RISC_PCR: + ret = dev->reg_risc_pcr; + break; + case QL_REG_RISC_PC: + ret = dev->reg_risc_pc; + break; + case QL_REG_RISC_MTR: + ret = dev->reg_risc_mtr; + break; + case QL_REG_HOST_CMD: + ret = dev->reg_host_cmd_flags; + break; + case QL_REG_GPIO_DATA: + ret = dev->reg_gpio_data; + break; + case QL_REG_GPIO_ENABLE: + ret = dev->reg_gpio_enable; + break; + + default: + ql_log("QL: [R16] Unhandled RISC bank read %lX\n", IDX_TO_REG(addr)); + ret = 0; + break; + } + + return ret; +} + +static uint16_t +ql_mmio_read16(uint32_t addr, void* priv) +{ + ql_t *dev = priv; + uint16_t ret; + + /* The hw does not handle unaligned access */ + if (addr & 0x1) { + return 0xFFFF; + } + + addr &= QL_IO_DECODE_MASK; + addr = REG_TO_IDX(addr); + + switch (addr) { + case QL_REG_ID_LOW: + ret = dev->reg_id_low; + break; + case QL_REG_ID_HIGH: + ret = dev->reg_id_high; + break; + case QL_REG_CFG0: + ret = dev->reg_cfg0; + break; + case QL_REG_CFG1: + ret = dev->reg_cfg1; + break; + case QL_REG_INT_CTRL: + ret = dev->reg_intr_ctrl; + break; + case QL_REG_INT_STATUS: + ret = dev->reg_intr_status; + break; + case QL_REG_SEMAPHORE: + ret = dev->reg_semaphore; + break; + case QL_REG_NVRAM: + ret = dev->reg_nvram; + if (nmc93cxx_eeprom_read(dev->eeprom_device)) { + ret |= QL_EEPROM_DO; + } + break; + case QL_REG_FLASH_BIOS_DATA: + ret = ql_read_flash_bios_data(dev); + break; + case QL_REG_FLASH_BIOS_ADDRESS: + ret = dev->reg_flash_bios_addr; + break; + case QL_REG_MAILBOX0: + case QL_REG_MAILBOX1: + case QL_REG_MAILBOX2: + case QL_REG_MAILBOX3: + case QL_REG_MAILBOX4: + case QL_REG_MAILBOX5: + case QL_REG_MAILBOX6: + case QL_REG_MAILBOX7: + ret = dev->reg_mbox_out[addr - QL_REG_MAILBOX0]; + break; + + default: { + uint32_t bank_addr; + + if (dev->isp_type == QL_ISP1040) { + if (addr >= REG_TO_IDX(0x20) && addr < REG_TO_IDX(0x80)) { + /* DMA bank */ + bank_addr = addr - REG_TO_IDX(0x20); + ret = ql_read_bank_dma(dev, bank_addr); + break; + } else if (addr >= REG_TO_IDX(0x80) && addr < REG_TO_IDX(0xFF)) { + /* RISC or SXP bank */ + bank_addr = addr - REG_TO_IDX(0x80); + if (dev->reg_cfg1 & BIU_PCI_CONF1_SXP) { + ret = ql_read_bank_sxp(dev, bank_addr, 0); + } else { + ret = ql_read_bank_risc(dev, bank_addr); + } + break; + } + } else { + if (addr >= REG_TO_IDX(0x80) && addr < REG_TO_IDX(0xFF)) { + bank_addr = addr - REG_TO_IDX(0x80); + + switch (dev->reg_cfg1 & BIU_PCI1080_REG_BANK_MASK) { + case BIU_PCI1080_CONF1_SXP0: + ret = ql_read_bank_sxp(dev, bank_addr, 0); + break; + case BIU_PCI1080_CONF1_SXP1: + ret = ql_read_bank_sxp(dev, bank_addr, 1); + break; + case BIU_PCI1080_CONF1_DMA: + ret = ql_read_bank_dma(dev, bank_addr); + break; + default: + ret = ql_read_bank_risc(dev, bank_addr); + break; + } + break; + } + } + + ql_log("QL: [R16] Unhandled read %lX\n", IDX_TO_REG(addr)); + ret = 0; + break; + } + } + +#ifdef ENABLE_QL_LOG + ql_debug_check_for_nvram_access(addr); +#endif + + ql_log("QL: [R16] [%02lX] --> %4X\n", IDX_TO_REG(addr), ret); + return ret; +} + +static uint8_t +ql_mmio_read8(uint32_t addr, void* priv) +{ + /* The hw only supports 16-bit R/W access */ + return 0xFF; +} + +static uint32_t +ql_mmio_read32(uint32_t addr, void* priv) +{ + /* The hw only supports 16-bit R/W access */ + return 0xFFFFFFFF; +} + +static void +ql_mmio_write8(uint32_t addr, uint8_t val, void* priv) +{ + /* The hw only supports 16-bit R/W access */ +} + +static void +ql_mmio_write32(uint32_t addr, uint32_t val, void* priv) +{ + /* The hw only supports 16-bit R/W access */ +} + +static void +ql_ioport_write32(uint16_t addr, uint32_t val, void *priv) +{ + ql_mmio_write32(addr, val, priv); +} + +static void +ql_ioport_write16(uint16_t addr, uint16_t val, void *priv) +{ + ql_mmio_write16(addr, val, priv); +} + +static void +ql_ioport_write8(uint16_t addr, uint8_t val, void *priv) +{ + ql_mmio_write8(addr, val, priv); +} + +static uint16_t +ql_ioport_read16(uint16_t addr, void* priv) +{ + return ql_mmio_read16(addr, priv); +} + +static uint32_t +ql_ioport_read32(uint16_t addr, void* priv) +{ + return ql_mmio_read32(addr, priv); +} + +static uint8_t +ql_ioport_read8(uint16_t addr, void* priv) +{ + return ql_mmio_read8(addr, priv); +} + +static void +ql_pci_remap_rom_mapping(ql_t *dev, bool do_enable) +{ + uint32_t rom_addr; + + if (do_enable) { + rom_addr = dev->pci_cfg[PCI_REG_ROM_BAR_BYTE0]; + rom_addr |= dev->pci_cfg[PCI_REG_ROM_BAR_BYTE1] << 8; + rom_addr |= dev->pci_cfg[PCI_REG_ROM_BAR_BYTE2] << 16; + rom_addr |= dev->pci_cfg[PCI_REG_ROM_BAR_BYTE3] << 24; + rom_addr &= ~0x01; + + ql_log("QL: ROM Base %08lX\n", rom_addr); + mem_mapping_set_addr(&dev->rom_bar_mapping, rom_addr, dev->pci_rom_area_size); + } else { + mem_mapping_disable(&dev->rom_bar_mapping); + } +} + +static void +ql_pci_remap_mmio_mapping(ql_t *dev, bool do_enable) +{ + uint32_t mmio_base; + + if (do_enable) { + mmio_base = dev->pci_cfg[PCI_REG_BAR1_BYTE0]; + mmio_base |= dev->pci_cfg[PCI_REG_BAR1_BYTE1] << 8; + mmio_base |= dev->pci_cfg[PCI_REG_BAR1_BYTE2] << 16; + mmio_base |= dev->pci_cfg[PCI_REG_BAR1_BYTE3] << 24; + mmio_base &= ~0x0F; + + ql_log("QL: MMIO I/O Base %08lX\n", mmio_base); + mem_mapping_set_addr(&dev->mmio_bar_mapping, mmio_base, QL_PCI_MMIO_BAR_SIZE); + } else { + mem_mapping_disable(&dev->mmio_bar_mapping); + } +} + +static void +ql_pci_remap_ioport_mapping(ql_t *dev, bool do_enable) +{ + uint32_t ioport_base; + + ioport_base = dev->pci_cfg[PCI_REG_BAR0_BYTE0]; + ioport_base |= dev->pci_cfg[PCI_REG_BAR0_BYTE1] << 8; + ioport_base |= dev->pci_cfg[PCI_REG_BAR0_BYTE2] << 16; + ioport_base |= dev->pci_cfg[PCI_REG_BAR0_BYTE3] << 24; + ioport_base &= ~0x03; + + if (do_enable) { + ql_log("QL: I/O Base %08lX\n", ioport_base); + io_sethandler(ioport_base, + QL_PCI_IO_BAR_SIZE, + ql_ioport_read8, + ql_ioport_read16, + ql_ioport_read32, + ql_ioport_write8, + ql_ioport_write16, + ql_ioport_write32, + dev); + } else { + io_removehandler(ioport_base, + QL_PCI_IO_BAR_SIZE, + ql_ioport_read8, + ql_ioport_read16, + ql_ioport_read32, + ql_ioport_write8, + ql_ioport_write16, + ql_ioport_write32, + dev); + } +} + +static void +ql_pci_write(UNUSED(int func), int addr, UNUSED(int len), uint8_t val, void *priv) +{ + ql_t *dev = priv; + uint8_t write_bits_mask; + + ql_log("QL: PCI [%2X] <-- %X\n", addr, val); + + assert(addr < 256); + + switch (addr) { + case PCI_REG_COMMAND_L: + write_bits_mask = 0x57; + break; + case PCI_REG_COMMAND_H: + write_bits_mask = 0x01; + break; + + case PCI_REG_CACHELINE_SIZE: + write_bits_mask = 0xFF; + break; + + case PCI_REG_LATENCY_TIMER: + write_bits_mask = 0xF8; + break; + + /* BAR[0] length 0x100 */ + case PCI_REG_BAR0_BYTE0: + write_bits_mask = 0; + break; + case PCI_REG_BAR0_BYTE1: + case PCI_REG_BAR0_BYTE2: + case PCI_REG_BAR0_BYTE3: + write_bits_mask = 0xFF; + break; + + /* BAR[1] length 0x1000 */ + case PCI_REG_BAR1_BYTE0: + write_bits_mask = 0; + break; + case PCI_REG_BAR1_BYTE1: + write_bits_mask = 0xF0; + break; + case PCI_REG_BAR1_BYTE2: + write_bits_mask = 0xFF; + break; + case PCI_REG_BAR1_BYTE3: + write_bits_mask = 0xFF; + break; + + /* ROM BAR */ + case PCI_REG_ROM_BAR_BYTE0: + write_bits_mask = (uint8_t)(dev->rom_bar_mask >> 0); + break; + case PCI_REG_ROM_BAR_BYTE1: + write_bits_mask = (uint8_t)(dev->rom_bar_mask >> 8); + break; + case PCI_REG_ROM_BAR_BYTE2: + write_bits_mask = (uint8_t)(dev->rom_bar_mask >> 16); + break; + case PCI_REG_ROM_BAR_BYTE3: + write_bits_mask = (uint8_t)(dev->rom_bar_mask >> 24); + break; + + case PCI_REG_INT_LINE: + write_bits_mask = 0xFF; + break; + + case 0x40: + write_bits_mask = 0xFF; + break; + case 0x41: + write_bits_mask = 0x03; + break; + + /* PMCSR */ + case QL_PCI_PM_BASE + 4: + write_bits_mask = dev->has_pci_caps ? 0x03 : 0; + break; + case QL_PCI_PM_BASE + 5: + write_bits_mask = dev->has_pci_caps ? 0x1E : 0; + break; + + default: + write_bits_mask = 0; + break; + } + + val &= write_bits_mask; + + /* Disable old BAR mapping and handle command change */ + switch (addr) { + case PCI_REG_COMMAND_L: + if ((val ^ dev->pci_cfg[addr]) & PCI_COMMAND_IO) { + ql_pci_remap_ioport_mapping(dev, !!(val & PCI_COMMAND_IO)); + } + if ((val ^ dev->pci_cfg[addr]) & PCI_COMMAND_MEM) { + ql_pci_remap_mmio_mapping(dev, !!(val & PCI_COMMAND_MEM)); + + if ((val & PCI_COMMAND_MEM) && (dev->pci_cfg[PCI_REG_ROM_BAR_BYTE0] & 0x01)) { + ql_pci_remap_rom_mapping(dev, true); + } else { + ql_pci_remap_rom_mapping(dev, false); + } + } + break; + + case PCI_REG_BAR0_BYTE0: + case PCI_REG_BAR0_BYTE1: + case PCI_REG_BAR0_BYTE2: + case PCI_REG_BAR0_BYTE3: + ql_pci_remap_ioport_mapping(dev, false); + break; + + case PCI_REG_BAR1_BYTE0: + case PCI_REG_BAR1_BYTE1: + case PCI_REG_BAR1_BYTE2: + case PCI_REG_BAR1_BYTE3: + ql_pci_remap_mmio_mapping(dev, false); + break; + + case PCI_REG_ROM_BAR_BYTE0: + case PCI_REG_ROM_BAR_BYTE1: + case PCI_REG_ROM_BAR_BYTE2: + case PCI_REG_ROM_BAR_BYTE3: + ql_pci_remap_rom_mapping(dev, false); + break; + + default: + break; + } + + /* Update PCI register value */ + val |= dev->pci_cfg[addr] & ~write_bits_mask; + dev->pci_cfg[addr] = val; + + /* Enable new BAR mapping */ + switch (addr) { + case PCI_REG_BAR0_BYTE0: + case PCI_REG_BAR0_BYTE1: + case PCI_REG_BAR0_BYTE2: + case PCI_REG_BAR0_BYTE3: + if (dev->pci_cfg[PCI_REG_COMMAND_L] & PCI_COMMAND_IO) { + ql_pci_remap_ioport_mapping(dev, true); + } + break; + + case PCI_REG_BAR1_BYTE0: + case PCI_REG_BAR1_BYTE1: + case PCI_REG_BAR1_BYTE2: + case PCI_REG_BAR1_BYTE3: + if (dev->pci_cfg[PCI_REG_COMMAND_L] & PCI_COMMAND_MEM) { + ql_pci_remap_mmio_mapping(dev, true); + } + break; + + case PCI_REG_ROM_BAR_BYTE0: + case PCI_REG_ROM_BAR_BYTE1: + case PCI_REG_ROM_BAR_BYTE2: + case PCI_REG_ROM_BAR_BYTE3: + if (dev->pci_cfg[PCI_REG_COMMAND_L] & PCI_COMMAND_MEM) { + if (dev->pci_cfg[PCI_REG_ROM_BAR_BYTE0] & 0x01) { + ql_pci_remap_rom_mapping(dev, true); + } + } + break; + + default: + break; + } +} + +static uint8_t +ql_pci_read(UNUSED(int func), int addr, UNUSED(int len), void *priv) +{ + ql_t *dev = priv; + uint8_t ret; + + assert(addr < 256); + + ret = dev->pci_cfg[addr]; + + ql_log("QL: PCI [%2X] --> %X\n", addr, ret); + return ret; +} + +static void ql_init_scsi(ql_t *dev) { + switch (dev->isp_type) { + case QL_ISP1040: + /* Ultra SCSI, 40 MB/s */ + dev->xfer_rate_bps = 40 * 1000000.0; + dev->max_bus_count = 1; + break; + case QL_ISP1080: + /* Ultra2 SCSI, 80 MB/s */ + dev->xfer_rate_bps = 80 * 1000000.0; + dev->max_bus_count = 1; + break; + case QL_ISP1240: + /* Ultra SCSI, 40 MB/s */ + dev->xfer_rate_bps = 40 * 1000000.0; + dev->max_bus_count = 2; + break; + case QL_ISP1280: + /* Ultra2 SCSI, 80 MB/s */ + dev->xfer_rate_bps = 80 * 1000000.0; + dev->max_bus_count = 2; + break; + case QL_ISP12160: + /* Ultra3 SCSI, 160 MB/s */ + dev->xfer_rate_bps = 160 * 1000000.0; + dev->max_bus_count = 2; + break; + + default: + /* Should not happen */ + assert(false); + break; + } + + /* 86Box supports one SCSI bus per controller for now */ + dev->scsi_bus = scsi_get_bus(); + + scsi_bus_set_speed(dev->scsi_bus, dev->xfer_rate_bps); + + timer_add(&dev->cmd_timer, ql_sxp_timer_callback, dev, 0); +} + +static uint8_t +ql_get_eeprom_checksum(const uint8_t* buffer, size_t size) +{ + size_t i; + uint8_t crc = 0; + + for (i = 0; i < size - 1; i++) { + crc += buffer[i]; + } + + return -crc; +} + +static void +ql_create_eeprom_image_1040(uint8_t* nvr) +{ + /* ID header */ + nvr[0x00] = 'I'; + nvr[0x01] = 'S'; + nvr[0x02] = 'P'; + nvr[0x03] = ' '; + /* NVRAM version */ + nvr[0x04] = 7; + + /* ISP config */ + nvr[0x05] = 0x7A; + + /* Bus reset delay */ + nvr[0x06] = 5; + /* Bus retry count */ + nvr[0x07] = 0; + /* Bus retry delay */ + nvr[0x08] = 0; + + /* Bus config */ + nvr[0x09] = 0xF9; + /* Tag age limit */ + nvr[0x0A] = 8; + /* Bus flags */ + nvr[0x0B] = 0x0B; + /* Bus selection timeout */ + nvr[0x0C] = 250; + nvr[0x0D] = 0; + /* Bus max queue depth */ + nvr[0x0E] = 0x00; + nvr[0x0F] = 0x01; + + /* Board type */ + nvr[0x10] = 0x17; + + /* System Vendor */ + nvr[0x14] = 0x77; + nvr[0x15] = 0x10; + /* System ID */ + nvr[0x12] = 0x01; + nvr[0x13] = 0x00; + + /* ISP paramrter */ + nvr[0x16] = 0x03; + nvr[0x17] = 0x00; + + /* FW features */ + nvr[0x18] = 0x01; + + /* Target settings */ + for (uint32_t target_id = 0; target_id < QL_MAX_TID; target_id++) { + const uint32_t tid_offset = 28 + target_id * 6; + + /* Config */ + nvr[tid_offset + 0] = 0xFD; + /* Execution throttle */ + nvr[tid_offset + 1] = 16; + /* Sync period */ + nvr[tid_offset + 2] = 12; + /* Flags */ + nvr[tid_offset + 3] = 0x18; + } + + /* System ID offset in words */ + nvr[0x7E] = 0x09; +} + +static void +ql_create_eeprom_image_1080(ql_t *dev, uint8_t* nvr) +{ + /* ID header */ + nvr[0x00] = 'I'; + nvr[0x01] = 'S'; + nvr[0x02] = 'P'; + nvr[0x03] = ' '; + /* NVRAM version */ + nvr[0x04] = 1; + + /* ISP config */ + nvr[0x10] = 0x44; + /* Bus termination */ + nvr[0x11] = 0x0C; + /* FW features */ + nvr[0x14] = 0x21; + + /* Bus settings */ + for (uint32_t path_id = 0; path_id < dev->max_bus_count; path_id++) { + const uint32_t bus_offset = path_id * 112; + + /* Bus config 1 */ + nvr[bus_offset + 0x18] = 0x67; + /* Bus reset delay */ + nvr[bus_offset + 0x19] = 5; + /* Bus retry count */ + nvr[bus_offset + 0x1A] = 0; + /* Bus retry delay */ + nvr[bus_offset + 0x1B] = 0; + /* Bus config 2 */ + nvr[bus_offset + 0x1C] = 0x39; + /* Bus selection timeout */ + nvr[bus_offset + 0x1E] = 250; + nvr[bus_offset + 0x1F] = 0; + /* Bus max queue depth */ + nvr[bus_offset + 0x20] = 0x00; + nvr[bus_offset + 0x21] = 0x01; + + /* Target settings */ + for (uint32_t target_id = 0; target_id < QL_MAX_TID; target_id++) { + const uint32_t tid_offset = bus_offset + 40 + target_id * 6; + + /* Config */ + nvr[tid_offset + 0] = 0xFD; + /* Execution throttle */ + nvr[tid_offset + 1] = 16; + /* Sync period */ + nvr[tid_offset + 2] = 10; + /* Flags */ + if (dev->isp_type == QL_ISP12160) { + nvr[tid_offset + 3] = 0x30; + } else { + nvr[tid_offset + 3] = 0x18; + } + } + } + + /* System Vendor */ + nvr[0xFA] = 0x77; + nvr[0xFB] = 0x10; + + /* System ID */ + switch (dev->isp_type) { + case QL_ISP1280: + nvr[0xFC] = 0x06; + nvr[0xFD] = 0x00; + break; + case QL_ISP12160: + nvr[0xFC] = 0x07; + nvr[0xFD] = 0x00; + break; + + default: + nvr[0xFC] = 0x01; + nvr[0xFD] = 0x00; + break; + } + + /* System Vendor offset in words */ + if (dev->isp_type != QL_ISP1080) { + nvr[0xFE] = 0xFA; + } +} + +static void +ql_register_eeprom_device(const device_t *info, ql_t *dev) +{ + int inst = device_get_instance(); + nmc93cxx_eeprom_params_t params; + char filename[1024] = { 0 }; + nmc93cxx_eeprom_type nvram_type; + size_t nvram_size; + + if (dev->isp_type == QL_ISP1040) { + nvram_type = NMC_93C46_x16_64; + nvram_size = 2 * 64; + } else { + nvram_type = NMC_93C56_x16_128; + nvram_size = 2 * 128; + } + + uint8_t* nvr = calloc(1, nvram_size); + + if (dev->isp_type == QL_ISP1040) { + ql_create_eeprom_image_1040(nvr); + } else { + ql_create_eeprom_image_1080(dev, nvr); + } + + /* Checksum */ + nvr[nvram_size - 1] = ql_get_eeprom_checksum(nvr, nvram_size); + + snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, inst); + params.type = nvram_type; + params.default_content = nvr; + params.filename = filename; + dev->eeprom_device = device_add_inst_params(&nmc93cxx_device, inst, ¶ms); + + free(nvr); +} + +static void +am29_create_flash_image(const device_t *info, flash_t *dev) +{ + FILE *fp; + size_t bytes_written; + const char *bios_path; + + dev->array_data = calloc(1, AM29_FLASH_SIZE); + + snprintf(dev->filename, + sizeof(dev->filename), + "am29f400_option_rom_%s_%d.bin", + info->internal_name, + device_get_instance()); + + /* Load the flash image, if it is already present in the system */ + fp = nvr_fopen(dev->filename, "rb"); + if (fp) { + bytes_written = fread(dev->array_data, 1, AM29_FLASH_SIZE, fp); + } else { + bios_path = device_get_bios_file(info, device_get_config_bios(QL_CFG_BIOS_REVISION), 0); + + /* Clone the ROM data to create a new image */ + fp = rom_fopen(bios_path, "rb"); + if (fp) { + bytes_written = fread(dev->array_data, 1, AM29_FLASH_SIZE, fp); + } else { + bytes_written = 0; + ql_log("Unable to load the AM29 Flash ROM file\n"); + } + } + if (fp) + fclose(fp); + + /* Fill the rest with 0xFF (make the memory content erased) */ + if (bytes_written < AM29_FLASH_SIZE) { + ql_log("Less than %lu bytes read from the AM29 Flash ROM file\n", (uint32_t)bytes_written); + + memset(dev->array_data + bytes_written, 0xFF, AM29_FLASH_SIZE - bytes_written); + } +} + +static void +am29_update_flash_image(flash_t *dev) +{ + FILE *fp = nvr_fopen(dev->filename, "wb"); + + /* Replace the original flash image with new version */ + if (fp) { + fwrite(dev->array_data, AM29_FLASH_SIZE, 1, fp); + fclose(fp); + } + + free(dev->array_data); +} + +static void +am29_init(const device_t *info, flash_t *dev) +{ + uint32_t flash_type = (info->local & QL_DEV_FLASH_TYPE_MASK) >> QL_DEV_FLASH_TYPE_SHIFT; + double access_time_us; + + dev->manufacturer_id = AM29_MANUFACTURER_ID; + dev->block_select_addr_mask = 0x1C000; // A14-A16 + + if (flash_type == QL_FLASH_AM29F010) { + dev->model_id = AM29F010_MODEL_ID; + dev->cmd_cycle_addr_mask = 0x1FFFF; // A0-A16 + dev->addr_5555_phys = 0x5555; + dev->addr_AAAA_phys = 0x2AAA; + dev->program_time_us = 14.0; + dev->block_erase_time_us = 200000.0; // 0.2 sec + dev->chip_erase_time_us = 1000000.0; // 1 sec + access_time_us = 0.045; + } else { + dev->model_id = AM29LV010B_MODEL_ID; + dev->cmd_cycle_addr_mask = 0x7FF; // A0-A10 + dev->addr_5555_phys = 0x555; + dev->addr_AAAA_phys = 0x2AA; + dev->program_time_us = 9.0; + dev->block_erase_time_us = 200000.0; // 0.2 sec + dev->chip_erase_time_us = 1000000.0; // 1 sec + access_time_us = 0.070; + } + dev->access_cycles = (cpuclock / (1000000.0 / access_time_us)); + + dev->block[0].start_addr = 0x00000; + dev->block[0].end_addr = 0x03FFF; + + dev->block[1].start_addr = 0x04000; + dev->block[1].end_addr = 0x07FFF; + + dev->block[2].start_addr = 0x08000; + dev->block[2].end_addr = 0x0BFFF; + + dev->block[3].start_addr = 0x0C000; + dev->block[3].end_addr = 0x0FFFF; + + dev->block[4].start_addr = 0x10000; + dev->block[4].end_addr = 0x13FFF; + + dev->block[5].start_addr = 0x14000; + dev->block[5].end_addr = 0x17FFF; + + dev->block[6].start_addr = 0x18000; + dev->block[6].end_addr = 0x1BFFF; + + dev->block[7].start_addr = 0x1C000; + dev->block[7].end_addr = 0x1FFFF; + + am29_create_flash_image(info, dev); + am29_set_mode(dev, M_READ_ARRAY); + + timer_add(&dev->erase_accept_timeout_timer, am29_erase_begin_timer_callback, dev, 0); + timer_add(&dev->cmd_complete_timer, am29_cmd_complete_timer_callback, dev, 0); + + /* Assign block numbers */ + for (uint32_t i = 0; i < AM29_MAX_BLOCKS; i++) { + flash_block_t *block = &dev->block[i]; + + /* We maintain a bitmap of blocks to erase */ + assert(i < 32); + assert(sizeof(dev->blocks_to_erase_bitmap) == sizeof(uint32_t)); + + block->number = i; + } +} + +static void +ql_init_pci_config(ql_t *dev) +{ + const uint8_t *eeprom_data = (const uint8_t *)nmc93cxx_eeprom_data(dev->eeprom_device); + + memset(dev->pci_cfg, 0, sizeof(dev->pci_cfg)); + + dev->pci_cfg[PCI_REG_STATUS_L] = PCI_STATUS_L_FAST_B2B | PCI_STATUS_L_CAPAB; + dev->pci_cfg[PCI_REG_STATUS_H] = PCI_DEVSEL_MEDIUM; + + /* QLA1xxx */ + switch (dev->isp_type) { + case QL_ISP1040: + dev->pci_cfg[PCI_REG_DEVICE_ID_L] = 0x20; + dev->pci_cfg[PCI_REG_DEVICE_ID_H] = 0x10; + dev->pci_cfg[PCI_REG_REVISION] = 0x05; + break; + case QL_ISP1080: + dev->pci_cfg[PCI_REG_DEVICE_ID_L] = 0x80; + dev->pci_cfg[PCI_REG_DEVICE_ID_H] = 0x10; + dev->pci_cfg[PCI_REG_REVISION] = 0x01; + break; + case QL_ISP1240: + dev->pci_cfg[PCI_REG_DEVICE_ID_L] = 0x40; + dev->pci_cfg[PCI_REG_DEVICE_ID_H] = 0x12; + dev->pci_cfg[PCI_REG_REVISION] = 0x01; + break; + case QL_ISP1280: + dev->pci_cfg[PCI_REG_DEVICE_ID_L] = 0x80; + dev->pci_cfg[PCI_REG_DEVICE_ID_H] = 0x12; + dev->pci_cfg[PCI_REG_REVISION] = 0x01; + break; + case QL_ISP12160: + dev->pci_cfg[PCI_REG_DEVICE_ID_L] = 0x16; + dev->pci_cfg[PCI_REG_DEVICE_ID_H] = 0x12; + dev->pci_cfg[PCI_REG_REVISION] = 0x06; + dev->pci_cfg[PCI_REG_STATUS_L] |= PCI_STATUS_L_66MHZ; + break; + + default: + /* Should not happen */ + assert(false); + break; + } + + /* Actual system ID comes from NVRAM. The ISP1040 system ID words are in swapped order */ + if (dev->isp_type == QL_ISP1040) { + dev->pci_cfg[PCI_REG_SUBVEN_ID_L] = eeprom_data[0x14]; + dev->pci_cfg[PCI_REG_SUBVEN_ID_H] = eeprom_data[0x15]; + dev->pci_cfg[PCI_REG_SUBSYS_ID_L] = eeprom_data[0x12]; + dev->pci_cfg[PCI_REG_SUBSYS_ID_H] = eeprom_data[0x13]; + } else { + dev->pci_cfg[PCI_REG_SUBVEN_ID_L] = eeprom_data[0xFA]; + dev->pci_cfg[PCI_REG_SUBVEN_ID_H] = eeprom_data[0xFB]; + dev->pci_cfg[PCI_REG_SUBSYS_ID_L] = eeprom_data[0xFC]; + dev->pci_cfg[PCI_REG_SUBSYS_ID_H] = eeprom_data[0xFD]; + } + + /* QLogic */ + dev->pci_cfg[PCI_REG_VENDOR_ID_L] = 0x77; + dev->pci_cfg[PCI_REG_VENDOR_ID_H] = 0x10; + + /* SCSI Controller */ + dev->pci_cfg[PCI_REG_CLASS] = 0x01; + + dev->pci_cfg[PCI_REG_CACHELINE_SIZE] = 64; + dev->pci_cfg[PCI_REG_LATENCY_TIMER] = 248; + dev->pci_cfg[PCI_REG_INT_PIN] = PCI_INTA; + + /* BAR[0] I/O ports */ + dev->pci_cfg[PCI_REG_BAR0_BYTE0] = 0x01; + + /* BAR[1] Memory */ + dev->pci_cfg[PCI_REG_BAR1_BYTE0] = 0; + + dev->pci_cfg[0x40] = 0x44; + + if (dev->has_pci_caps) { + dev->pci_cfg[PCI_REG_STATUS_L] |= PCI_STATUS_L_CAPAB; + + dev->pci_cfg[PCI_REG_CAPS_PTR] = QL_PCI_PM_BASE; + + /* Power management capabilities */ + dev->pci_cfg[QL_PCI_PM_BASE + 0] = 0x01; // POWER MANAGEMENT + dev->pci_cfg[QL_PCI_PM_BASE + 1] = 0x00; // Last entry + /* PMC */ + dev->pci_cfg[QL_PCI_PM_BASE + 2] = 0x01; // Version 1.0 + dev->pci_cfg[QL_PCI_PM_BASE + 3] = 0x00; + /* PMCSR */ + dev->pci_cfg[QL_PCI_PM_BASE + 4] = 0x00; + dev->pci_cfg[QL_PCI_PM_BASE + 5] = 0x00; + /* PMCSR_BSE */ + dev->pci_cfg[QL_PCI_PM_BASE + 6] = 0x00; + /* Data */ + dev->pci_cfg[QL_PCI_PM_BASE + 7] = 0x00; + } + + /* This area for some reason holds the VenID/DevID pair */ + for (uint32_t reg = 0x4C; reg < sizeof(dev->pci_cfg); reg += 4) { + dev->pci_cfg[reg + 0] = dev->pci_cfg[PCI_REG_VENDOR_ID_L]; + dev->pci_cfg[reg + 1] = dev->pci_cfg[PCI_REG_VENDOR_ID_H]; + dev->pci_cfg[reg + 2] = dev->pci_cfg[PCI_REG_DEVICE_ID_L]; + dev->pci_cfg[reg + 3] = dev->pci_cfg[PCI_REG_DEVICE_ID_H]; + } +} + +static void +ql_reset(void *priv) +{ + ql_t *dev = priv; + + /* Clear all BAR memory mappings and I/O handlers */ + ql_pci_remap_ioport_mapping(dev, false); + ql_pci_remap_mmio_mapping(dev, false); + ql_pci_remap_rom_mapping(dev, false); + + /* Reset PCI configuration registers */ + ql_init_pci_config(dev); + + ql_reset_asic(dev); + am29_reset(&dev->flash_device); +} + +static void * +ql_init(const device_t *info) +{ + ql_t *dev = calloc(1, sizeof(ql_t)); + + dev->isp_type = info->local & QL_DEV_CHIP_TYPE_MASK; + dev->isp_rev = (info->local & QL_DEV_CHIP_REV_MASK) >> QL_DEV_CHIP_REV_SHIFT; + + dev->fw_version = device_get_bios_local(device_context_get_device(), device_get_config_bios(QL_CFG_BIOS_REVISION)); + dev->has_pci_caps = (dev->isp_type != QL_ISP1040); + + /* + * Determine size of the area to map the expansion ROM. + * NOTE: On most ISP chips this area is smaller than the FLASH size. + * The QLogic boot code reads the required data directly from the FLASH at run-time. + */ + if (dev->isp_type == QL_ISP12160) { + dev->pci_rom_area_size = QL_PCI_ROM_BAR_128K_SIZE; + } else { + dev->pci_rom_area_size = QL_PCI_ROM_BAR_64K_SIZE; + } + + /* Determine writable bits of the ROM BAR */ + if (!device_get_config_int(QL_CFG_BIOS_ENABLE)) { + dev->rom_bar_mask = 0; + } else { + uint32_t length = dev->pci_rom_area_size; + uint32_t ln2size = 0; + + while (length != 1) { + ln2size++; + length >>= 1; + } + + dev->rom_bar_mask = ~((1 << ln2size) - 1); + dev->rom_bar_mask |= 1; // Expansion ROM enable bit + } + + ql_init_scsi(dev); + am29_init(info, &dev->flash_device); + ql_register_eeprom_device(info, dev); + ql_init_pci_config(dev); + ql_reset_asic(dev); + + mem_mapping_add(&dev->rom_bar_mapping, + 0, + 0, + ql_rom_bar_mmio_read8, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + MEM_MAPPING_EXTERNAL, + dev); + mem_mapping_disable(&dev->rom_bar_mapping); + + mem_mapping_add(&dev->mmio_bar_mapping, + 0, + 0, + ql_mmio_read8, + ql_mmio_read16, + ql_mmio_read32, + ql_mmio_write8, + ql_mmio_write16, + ql_mmio_write32, + NULL, + MEM_MAPPING_EXTERNAL, + dev); + mem_mapping_disable(&dev->mmio_bar_mapping); + + pci_add_card(PCI_CARD_NORMAL, ql_pci_read, ql_pci_write, dev, &dev->pci_slot); + return dev; +} + +static void +ql_close(void *priv) +{ + ql_t *dev = priv; + + am29_update_flash_image(&dev->flash_device); + + fifo8_destroy(&dev->abort_iocbs_fifo); + + if (dev->scsi_data_buffer) { + free(dev->scsi_data_buffer); + } + free(dev); +} + +// clang-format off +static const device_config_t qla1040b_config[] = { + { + .name = QL_CFG_BIOS_REVISION, + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "v6_26", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Version 6.20", + .internal_name = "v6_20", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(4, 53, 0), + .size = 0x10000, + .files = { "roms/scsi/qlogic/qla1040_v6_20.bin", "" } + }, + { + .name = "Version 6.26", + .internal_name = "v6_26", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(4, 55, 0), + .size = 0x10000, + .files = { "roms/scsi/qlogic/qla1040_v6_26.bin", "" } + }, + { .files_no = 0 } + }, + }, + { + .name = QL_CFG_BIOS_ENABLE, + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t qla1080_config[] = { + { + .name = QL_CFG_BIOS_REVISION, + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "v1_19", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Version 1.11", + .internal_name = "v1_11", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(2, 13, 0), + .size = 0x10000, + .files = { "roms/scsi/qlogic/qla1080_v1_11.bin", "" } + }, + { + .name = "Version 1.16", + .internal_name = "v1_16", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(8, 3, 0), + .size = 0x20000, + .files = { "roms/scsi/qlogic/qla1080_v1_16.bin", "" } + }, + { + .name = "Version 1.19", + .internal_name = "v1_19", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(8, 9, 0), + .size = 0x20000, + .files = { "roms/scsi/qlogic/qla1080_v1_19.bin", "" } + }, + { .files_no = 0 } + }, + }, + { + .name = QL_CFG_BIOS_ENABLE, + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t qla1240_config[] = { + { + .name = QL_CFG_BIOS_REVISION, + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "v1_26", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Version 1.26", + .internal_name = "v1_26", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(2, 13, 0), + .size = 0x10000, + .files = { "roms/scsi/qlogic/qla1240_v1_26.bin", "" } + }, + { .files_no = 0 } + }, + }, + { + .name = QL_CFG_BIOS_ENABLE, + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t qla1280_config[] = { + { + .name = QL_CFG_BIOS_REVISION, + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "v1_30", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Version 1.30", + .internal_name = "v1_30", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(8, 15, 0), + .size = 0x20000, + .files = { "roms/scsi/qlogic/qla1280_v1_30.bin", "" } + }, + { .files_no = 0 } + }, + }, + { + .name = QL_CFG_BIOS_ENABLE, + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t qla12160a_config[] = { + { + .name = QL_CFG_BIOS_REVISION, + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "v1_37", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .bios = { + { + .name = "Version 1.34", + .internal_name = "v1_34", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(10, 4, 0), + .size = 0x20000, + .files = { "roms/scsi/qlogic/qla12160_v1_34.bin", "" } + }, + { + .name = "Version 1.37", + .internal_name = "v1_37", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = ISP_FW_VER(10, 4, 0), + .size = 0x20000, + .files = { "roms/scsi/qlogic/qla12160_v1_37.bin", "" } + }, + { .files_no = 0 } + }, + }, + { + .name = QL_CFG_BIOS_ENABLE, + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +const device_t qla1040b_device = { + .name = "QLogic QLA1040B", + .internal_name = "qla1040b", + .flags = DEVICE_PCI, + .local = QL_ISP1040 | QL_REV_ISP1040B | QL_FLASH_AM29F010, + .init = ql_init, + .close = ql_close, + .reset = ql_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = qla1040b_config, +}; + +const device_t qla1080_device = { + .name = "QLogic QLA1080", + .internal_name = "qla1080", + .flags = DEVICE_PCI, + .local = QL_ISP1080 | QL_REV_ISP1080 | QL_FLASH_AM29F010, + .init = ql_init, + .close = ql_close, + .reset = ql_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = qla1080_config, +}; + +const device_t qla1240_device = { + .name = "QLogic QLA1240", + .internal_name = "qla1240", + .flags = DEVICE_PCI, + .local = QL_ISP1240 | QL_REV_ISP1080 | QL_FLASH_AM29LV010B, + .init = ql_init, + .close = ql_close, + .reset = ql_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = qla1240_config, +}; + +const device_t qla1280_device = { + .name = "QLogic QLA1280", + .internal_name = "qla1280", + .flags = DEVICE_PCI, + .local = QL_ISP1280 | QL_REV_ISP1080 | QL_FLASH_AM29LV010B, + .init = ql_init, + .close = ql_close, + .reset = ql_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = qla1280_config, +}; + +const device_t qla12160a_device = { + .name = "QLogic QLA12160A", + .internal_name = "qla12160a", + .flags = DEVICE_PCI, + .local = QL_ISP12160 | QL_REV_ISP1080 | QL_FLASH_AM29LV010B, + .init = ql_init, + .close = ql_close, + .reset = ql_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = qla12160a_config, +}; From 658425b33e4d391ab07f4477b7134069eca4cda7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 23 Feb 2026 01:58:58 +0900 Subject: [PATCH 53/66] IBM 5550: Add machine config for test mode * Added a machine config for the RNA test mode. * Changed the keyboard reset sequence to work on the RNA test correctly. * Reduced screen updates for text cursor. --- src/include/86box/machine.h | 2 +- src/machine/m_xt_ibm5550.c | 179 ++++++++++++++++++++++-------------- src/machine/machine_table.c | 4 +- 3 files changed, 111 insertions(+), 74 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 8a631f40a..f1a660f7d 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -1522,7 +1522,7 @@ extern int machine_xt_compaq_deskpro_init(const machine_t *); /* m_xt_ibm5550.c */ #ifdef EMU_DEVICE_H -extern const device_t ibm5550_vid_device; +extern const device_t ibm5550_device; #endif extern int machine_xt_ibm5550_init(const machine_t *); diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index 00f203f1a..c9940ba7e 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -161,12 +161,12 @@ enum epoch_nvr_ADDR { }; #ifndef RELEASE_BUILD -//#define ENABLE_EPOCH_LOG 1 +// #define ENABLE_EPOCH_LOG 1 #endif #ifdef ENABLE_EPOCH_LOG -#define ENABLE_EPOCH_DEBUGIO 1 -// #define ENABLE_EPOCH_DEBUGKBD 1 +// #define ENABLE_EPOCH_DEBUGIO 1 +#define ENABLE_EPOCH_DEBUGKBD 1 int epoch_do_log = ENABLE_EPOCH_LOG; static void @@ -279,6 +279,8 @@ typedef struct epoch_t { nvr_t nvr; int nvrctrl; int nvrdata; + + int testmode; } epoch_t; @@ -1154,7 +1156,7 @@ epoch_poll(void *priv) epoch->cursoron = 1; break; } - if (!(epoch->blink & (0x08 - 2))) /* force redrawing for cursor and blink attribute */ + if (!(epoch->blink & (0x08 - 1))) /* force redrawing for cursor and blink attribute */ epoch->fullchange = 3; } epoch->blink++; @@ -1429,15 +1431,21 @@ epoch_misc_in(uint16_t port, void *priv) /* I/O A0h R: xxxx xxx1: Memory or parity error? +xxxx xx1x: Test switch (physical switch on the rear panel) +x1xx xxxx: Sense DREQ? (only used in diag test) 0xxx xxxx: Coprocessor installed? */ case 0xA0: - if(!epoch->parityenabled) - ret &= 0xfe; - else - ret = epoch->parityerror & 1; + ret = 0; + if (epoch->parityenabled) + ret |= epoch->parityerror & 1; if (fpu_type == FPU_NONE) ret |= 0x80; + for (int i = 0; i < 2; i++) + if (dma_get_drq(i)) + ret |= 0x40; + if (epoch->testmode) + ret |= 0x02; break; case 0xA1: /* High address where memory error occured */ ret = epoch->parityerroraddr; @@ -1549,15 +1557,16 @@ x1xx xxxx: Enable parity update (Disable this -> Write data -> Enable this -> Re typedef struct epochkbd_t { int want_irq; int blocked; + uint8_t irq_state; uint8_t pa; uint8_t pb; uint8_t clk_hold; uint8_t key_waiting; - uint8_t kbd_reset_step; - uint8_t mouse_reset_step; + int8_t kbd_readdata_step; int mouse_enabled; int mouse_queue_num; + int kbc_resetstep; uint8_t mouse_queue[4]; pc_timer_t send_delay_timer; @@ -1572,22 +1581,33 @@ kbd_epoch_poll(void *priv) { epochkbd_t *kbd = (epochkbd_t *) priv; - timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC); + timer_advance_u64(&kbd->send_delay_timer, 250 * TIMER_USEC); if (kbd->pb & 0x04) /* controller is sending something to keyboard */ return; + if (kbd->kbd_readdata_step < 16) + kbd->kbd_readdata_step++; + if (!(kbd->pb & 0x08)) /* keyboard interrupt is disabled */ return; - if (kbd->want_irq) { - kbd->want_irq = 0; - kbd->pa = kbd->key_waiting; - kbd->blocked = 1; - picint(EPOCH_IRQ3_BIT); - epoch_kbdlog("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n"); + if (kbd->want_irq && kbd->kbd_readdata_step >= 16) { + if (kbd->blocked) { + kbd->want_irq = 0; + kbd->irq_state = 1; + picint(EPOCH_IRQ3_BIT); + epoch_kbdlog("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n"); + } else { + kbd->pa = kbd->key_waiting; + kbd->kbd_readdata_step = -4; + kbd->blocked = 1; + } } + if (kbd->irq_state && (kbd->pb & 0x01)) /* Trigger interrupt repeatedly (for RNA test) */ + picint(EPOCH_IRQ3_BIT); + if (!kbd->blocked) { if (kbd->mouse_queue_num > 0) { kbd->mouse_queue_num--; @@ -1641,6 +1661,21 @@ kbd_adddata_ex(uint16_t val) kbd_epoch_adddata_process(val, kbd_epoch_adddata); } +static void +kbd_epoch_softreset(void *priv) +{ + epochkbd_t *kbd = (epochkbd_t *) priv; + key_queue_start = key_queue_end = 0; + kbd->kbd_readdata_step = 16; + kbd->want_irq = 0; + kbd->blocked = 0; + kbd->clk_hold = 0; + kbd->mouse_queue_num = 0; + kbd->blocked = 0; + kbd->irq_state = 0; + kbd->pa = 0; + picintc(EPOCH_IRQ3_BIT); +} /* I/O 61h W: xxxx xxx1: ? (used by kbd interrupt in DOS) @@ -1672,20 +1707,26 @@ kbd_write(uint16_t port, uint8_t val, void *priv) new_clock = !(val & 0x04); /* Trigger kbd reset after the clk line is reset to a high level */ if (kbd->clk_hold && new_clock) { - key_queue_start = key_queue_end = 0; - kbd->want_irq = 0; - kbd->blocked = 0; - kbd->kbd_reset_step = 0; - kbd->clk_hold = 0; - kbd->mouse_enabled = 0; - kbd->mouse_queue_num = 0; + kbd->mouse_enabled = 0; + kbd_epoch_softreset(kbd); epoch_kbdlog("epochkbd: Starting keyboard reset sequence.\n"); + /* IBM 5556 keyboards send three bytes of identification code in the reset sequence. + DOS K3.44 supports following IDs: + A5xx1x: ? (standard layout) + A6xx1x: AIUEO RPQ Keyboard + B1xx1x, B2xx1x: Type 3, 4 Keyboard (1972 JIS layout) + B5xx1x: ? (standard layout) + */ + kbd_epoch_adddata(0xA5); + kbd_epoch_adddata(0x00); + kbd_epoch_adddata(0x10); } } else if ((val & 0x18) == 0x18) { new_clock = !(val & 0x04); if (kbd->clk_hold && new_clock) { - kbd->mouse_reset_step = 0; + kbd_epoch_softreset(kbd); epoch_kbdlog("epochkbd: Starting mouse reset sequence.\n"); + kbd_epoch_adddata(0x00); } } @@ -1706,8 +1747,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv) /* clear buffer */ kbd->pa = 0; kbd->blocked = 0; - /* IRQ will be cleared by the software */ - // picintc(EPOCH_IRQ3_BIT); + kbd->irq_state = 0; + picintc(EPOCH_IRQ3_BIT); } break; @@ -1736,35 +1777,29 @@ kbd_read(uint16_t port, void *priv) case 0x61: /* Keyboard Control Register (aka Port B) */ ret = kbd->pb & 0xf0; /* reset sense bit */ ret |= 0x0c; /* reset sense bit */ - if (kbd->kbd_reset_step < 18) { + if (kbd->kbd_readdata_step < 16) { ret &= 0xf3; - if (!!(kbd->kbd_reset_step & 1)) - ret |= 0x04; - switch (kbd->kbd_reset_step >> 1) { /* AAh (0 1010 1010) in serial data */ - case 0: - case 2: - case 4: - case 6: - case 8: - ret |= 0x08; + switch (kbd->kbd_readdata_step) { + case -4: + ret |= 0x0c; /* start bit */ + break; + case -3: + ret |= 0x0c; /* start bit */ + break; + case -2: + ret |= 0x08; /* start bit */ + break; + case -1: + ret |= 0x0c; /* start bit */ break; default: - ret |= 0x00; + if (!!(kbd->kbd_readdata_step & 1)) + ret |= 0x04; + if ((kbd->key_waiting >> (kbd->kbd_readdata_step >> 1)) & 1) + ret |= 0x08; break; } - epoch_kbdlog(" reset step: %d %x %x", kbd->kbd_reset_step, ret & 0x08, ret & 0x04); - epoch_kbdlog(" Clk: %x %x\n", kbd->blocked, kbd->clk_hold); - kbd->kbd_reset_step++; - /* Specific 5556 keyboards send three bytes of identification code, - but this simply sends AAh that can pass the IPL and DOS K3.4 init. */ - if (kbd->kbd_reset_step == 18) - kbd_epoch_adddata(0xaa); - } else if (kbd->mouse_reset_step < 20) { - ret &= 0xf3; - if (!!(kbd->mouse_reset_step & 1)) - ret |= 0x04; - epoch_kbdlog(" reset step: %d %x %x\n", kbd->mouse_reset_step, ret & 0x08, ret & 0x04); - kbd->mouse_reset_step++; + epoch_kbdlog(" rdata step: %d %x %x\n", kbd->kbd_readdata_step, ret & 0x08, ret & 0x04); } /* Bit 1: Timer 2 (Speaker) out state */ @@ -1777,7 +1812,8 @@ kbd_read(uint16_t port, void *priv) default: break; } - epoch_kbdlog("%04X:%04X epochkbd: Port %02X in : %02X pb: %02x CX: %04x\n", cs >> 4, cpu_state.pc, port, ret, kbd->pb, CX); + // if (port != 0x61) + epoch_kbdlog("%04X:%04X epochkbd: Port %02X in : %02X pb: %02x CX: %04x\n", cs >> 4, cpu_state.pc, port, ret, kbd->pb, CX); return ret; } @@ -1786,21 +1822,11 @@ kbd_reset(void *priv) { epochkbd_t *kbd = (epochkbd_t *) priv; - kbd->want_irq = 0; - kbd->blocked = 0; - kbd->pa = 0x00; - kbd->pb = 0x00; - kbd->kbd_reset_step = 0xff; - kbd->mouse_reset_step = 0xff; - - keyboard_scan = 1; - - key_queue_start = 0; - key_queue_end = 0; + kbd_epoch_softreset(kbd); + kbd->pb = 0x00; + keyboard_scan = 1; kbd->mouse_enabled = 0; - kbd->mouse_queue_num = 0; - kbd_epoch_adddata(0xaa); } static void * @@ -1843,7 +1869,7 @@ kbd_close(void *priv) } static const device_t kbc_epoch_device = { - .name = "IBM 5550 Keyboard Controller", + .name = "IBM 5556 Keyboard and Mouse", .internal_name = "kbc_epoch", .flags = 0, .local = 0, @@ -2196,6 +2222,7 @@ epoch_init(UNUSED(const device_t *info)) { epoch_t *epoch = calloc(1, sizeof(epoch_t)); epoch->font24 = device_get_config_int("model"); + epoch->testmode = device_get_config_int("testmode"); video_inform(VIDEO_FLAG_TYPE_NONE, &timing_epoch_vid); video_update_timing(); @@ -2233,7 +2260,7 @@ epoch_init(UNUSED(const device_t *info)) io_sethandler(0x44, 0x0001, epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); - io_sethandler(0xA0, 0x0006, + io_sethandler(0xA0, 0x0008, epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); io_sethandler(0x310, 0x0008, epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); @@ -2342,13 +2369,20 @@ static const device_config_t epoch_config[] = { { .description = "" } } }, + { + .name = "testmode", + .description = "Test mode", + .type = CONFIG_BINARY, + .default_int = 0, + .selection = { { 0 } } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; -const device_t ibm5550_vid_device = { - .name = "IBM 5550 Video Adapter", - .internal_name = "ibm5550vid", +const device_t ibm5550_device = { + .name = "IBM 5551 System Unit", + .internal_name = "ibm5550", .flags = DEVICE_ISA, .local = 0, .init = epoch_init, @@ -2418,7 +2452,7 @@ machine_xt_ibm5550_init(const machine_t *model) pit_ibm5550_init(); nmi_mask = 0; - device_add(&ibm5550_vid_device); + device_add(&ibm5550_device); device_add(&lpt_port_device); serial_t *uart = device_add(&ns8250_device); @@ -2428,6 +2462,9 @@ machine_xt_ibm5550_init(const machine_t *model) /* Tell mouse driver about our internal mouse. */ mouse_reset(); mouse_set_buttons(2); + /* I don't know the actual polling speed, but + a higher value may cause a conflict with the mouse driver */ + mouse_set_sample_rate(30.0); mouse_set_poll(epoch_mouse_poll, kbc); } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 2e76f5a24..26e4dcda6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2724,11 +2724,11 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibm5550_device, .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &ibm5550_vid_device, + .vid_device = NULL, .snd_device = NULL, .net_device = NULL }, From f0a3c3707362de3fb911d29371df0189875fea11 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 22 Feb 2026 18:45:40 +0100 Subject: [PATCH 54/66] 8514/A: Correct interlaced refresh rates And when the accel command is bitblt (6), the patterns and'ed to 3 are from the destination x register. --- src/include/86box/vid_8514a.h | 2 + src/video/vid_8514a.c | 220 +++++++++++++++++++++++----------- src/video/vid_ati_mach8.c | 8 +- 3 files changed, 156 insertions(+), 74 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index d0cd25547..f0c9fdf24 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -65,6 +65,7 @@ typedef union { typedef struct ibm8514_t { rom_t bios_rom; + rom_t bios_rom2; uint8_t *rom1; uint8_t *rom2; hwcursor8514_t hwcursor; @@ -187,6 +188,7 @@ typedef struct ibm8514_t { uint32_t dst_ge_offset; uint16_t src_pitch; uint16_t dst_pitch; + uint16_t read_pixel; int64_t cur_x_24bpp; int64_t cur_y_24bpp; int64_t dest_x_24bpp; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index d44d9e9d8..e152e98a5 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -1121,83 +1121,159 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (pixcntl == 1) { mix_dat = 0; - if (and3 == 3) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x08; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x10; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x20; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x01; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x02; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x04; - } - if (and3 == 2) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x04; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x08; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x10; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x20; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x01; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x02; - } - if (and3 == 1) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x02; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x04; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x08; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x10; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x20; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x01; - } - if (and3 == 0) { - if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x01; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x02; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x04; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x08; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x10; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x20; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x10) - mix_dat |= 0x80; + if (cmd == 6) { + if (and3_blt == 3) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x04; + } + if (and3_blt == 2) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x02; + } + if (and3_blt == 1) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x01; + } + if (and3_blt == 0) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x01; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x80; + } + } else { + if (and3 == 3) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x04; + } + if (and3 == 2) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x02; + } + if (and3 == 1) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x01; + } + if (and3 == 0) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x01; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x80; + } } } old_mix_dat = mix_dat; - ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); + if (!(dev->accel.cmd & 0x01)) + ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index ab38e26f6..58a54fb48 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -3021,8 +3021,10 @@ ati8514_recalctimings(svga_t *svga) if (dev->ven_clock & 0x40) svga->clock_8514 *= 2.0; - if (dev->interlace) + if (dev->interlace) { dev->dispend >>= 1; + svga->clock_8514 /= 2.0; + } mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, @@ -3183,8 +3185,10 @@ mach_recalctimings(svga_t *svga) mach_log("8514/A modes=%d, clocksel=%02x, clkselmode=%02x, divide reg ibm=%02x, divide reg vga=%02x, vgainterlace=%x, interlace=%x, htotal=%02x.\n", _8514_modes, mach->accel.clock_sel & 0xfe, mach->accel.clock_sel_mode & 0xfe, mach->accel.clock_sel & 0x40, mach->regs[0xb8] & 0x40, svga->interlace, dev->interlace, dev->htotal); - if (dev->interlace) + if (dev->interlace) { dev->dispend >>= 1; + svga->clock_8514 /= 2.0; + } if (ATI_MACH32) { switch ((mach->shadow_set >> 8) & 0x03) { From 81ba889f9e03d91a91778fd8db31ad6e423c1af7 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 22 Feb 2026 21:05:39 +0100 Subject: [PATCH 55/66] Sort out the IRQ/INT enabling/disabling stuff of the 5380/53c80 chip. Allowing proper operation of the IRQ in the 53c400 and, at the same time, recognizing the RTASPI10.SYS driver of the Rancho RT1000B. Code based on the 53c400 manual and MAME. TODO: Verify the Trantor T128 scheme. --- src/include/86box/scsi_ncr5380.h | 1 + src/scsi/scsi_ncr5380.c | 22 ++++--- src/scsi/scsi_ncr53c400.c | 103 +++++++++++++++++++------------ src/scsi/scsi_t128.c | 10 ++- 4 files changed, 86 insertions(+), 50 deletions(-) diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 6453340ae..151a9873c 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -84,6 +84,7 @@ typedef struct ncr_t { int (*dma_send_ext)(void *priv, void *ext_priv); int (*dma_initiator_receive_ext)(void *priv, void *ext_priv); void (*timer)(void *ext_priv, double period); + int (*irq_ena)(void *priv, void *ext_priv, int state); scsi_bus_t scsibus; } ncr_t; diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 102e637c4..2a29b070d 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -62,13 +62,9 @@ void ncr5380_irq(ncr_t *ncr, int set_irq) { if (set_irq) { - ncr->irq_state = 1; - ncr->isr |= STATUS_INT; if (ncr->irq != -1) picint(1 << ncr->irq); } else { - ncr->irq_state = 0; - ncr->isr &= ~STATUS_INT; if (ncr->irq != 1) picintc(1 << ncr->irq); } @@ -104,7 +100,12 @@ ncr5380_reset(ncr_t *ncr) scsi_bus->data = 0; scsi_bus->command_issued = 0; - ncr5380_irq(ncr, 0); + if (ncr->irq_ena) + ncr->irq_ena(ncr, ncr->priv, 0); + else + ncr5380_irq(ncr, 0); + + ncr->isr &= ~STATUS_INT; } uint32_t @@ -164,7 +165,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) if ((val & 0x80) && !(ncr->icr & 0x80)) { ncr5380_log("Resetting the 5380\n"); ncr5380_reset(ncr); - ncr5380_irq(ncr, 1); + ncr->isr |= STATUS_INT; } ncr->icr = val; ncr5380_log("ICR WaitData=%d, ClearReq=%d.\n", scsi_bus->wait_data, scsi_bus->clear_req); @@ -301,7 +302,7 @@ ncr5380_read(uint16_t port, ncr_t *ncr) if (bus & BUS_MSG) bus_state |= TCR_MSG; if ((ncr->tcr & 7) != bus_state) { - ncr5380_irq(ncr, 1); + ncr->isr |= STATUS_INT; ncr5380_log("IRQ issued\n"); } } @@ -321,7 +322,12 @@ ncr5380_read(uint16_t port, ncr_t *ncr) case 7: /* reset Parity/Interrupt */ ncr->isr &= ~(STATUS_BUSY_ERROR | 0x20); - ncr5380_irq(ncr, 0); + if (ncr->irq_ena) + ncr->irq_ena(ncr, ncr->priv, 0); + else + ncr5380_irq(ncr, 0); + + ncr->isr &= ~STATUS_INT; ncr5380_log("Reset Interrupt\n"); break; diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index 31a2de8b3..c8520d082 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -72,6 +72,7 @@ typedef struct ncr53c400_t { int8_t type; uint8_t block_count; uint8_t status_ctrl; + uint8_t irq_config; int block_count_loaded; @@ -103,6 +104,23 @@ ncr53c400_log(const char *fmt, ...) # define ncr53c400_log(fmt, ...) #endif +static int +ncr53c400_irq_enable(void *priv, void *ext_priv, int state) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv; + ncr_t *ncr = (ncr_t *) priv; + + if (ncr->irq_state != state) { + ncr->irq_state = state; + ncr400->status_ctrl &= ~0x01; + ncr400->status_ctrl |= (state << 0); + ncr53c400_log("Status Control bit 4=%02x.\n", ncr400->status_ctrl); + if (ncr400->status_ctrl & 0x10) + ncr5380_irq(ncr, state); + } + return 1; +} + static void ncr53c400_timer_on_auto(void *ext_priv, double period) { @@ -263,7 +281,8 @@ ncr53c400_read(uint32_t addr, void *priv) ncr->isr |= STATUS_END_OF_DMA; if (ncr->mode & MODE_ENA_EOP_INT) { ncr53c400_log("NCR read irq\n"); - ncr5380_irq(ncr, 1); + ncr53c400_irq_enable(ncr, ncr400, 1); + ncr->isr |= STATUS_INT; } } else if (!timer_is_enabled(&ncr400->timer)) { ncr53c400_log("Timer re-enabled.\n"); @@ -277,15 +296,16 @@ ncr53c400_read(uint32_t addr, void *priv) case 0x3980: switch (addr) { case 0x3980: /* status */ + if (ncr400->reset) { + ncr400->reset = 0; + ncr53c400_irq_enable(ncr, ncr400, 1); + } + ret = ncr400->status_ctrl; ncr53c400_log("NCR status ctrl read=%02x.\n", ncr400->status_ctrl & STATUS_BUFFER_NOT_READY); if (!ncr400->busy) ret |= STATUS_5380_ACCESSIBLE; - if (ncr400->reset) { - ncr400->reset = 0; - ret |= 0x01; - } ncr53c400_log("NCR 53c400 status=%02x.\n", ret); break; @@ -295,10 +315,7 @@ ncr53c400_read(uint32_t addr, void *priv) break; case 0x3982: /* switch register read */ - if (ncr->irq != -1) { - ret = 0xf8; - ret += ncr->irq; - } + ret = ((ncr400->irq_config >> 5) & 7) | 0xf8; ncr53c400_log("Switches read=%02x.\n", ret); break; @@ -519,7 +536,8 @@ ncr53c400_callback(void *priv) ncr->isr |= STATUS_END_OF_DMA; if (ncr->mode & MODE_ENA_EOP_INT) { ncr53c400_log("NCR 53c400 write irq\n"); - ncr5380_irq(ncr, 1); + ncr53c400_irq_enable(ncr, ncr400, 1); + ncr->isr |= STATUS_INT; } } break; @@ -573,7 +591,8 @@ ncr53c400_callback(void *priv) ncr->isr |= STATUS_END_OF_DMA; if (ncr->mode & MODE_ENA_EOP_INT) { ncr53c400_log("NCR read irq\n"); - ncr5380_irq(ncr, 1); + ncr53c400_irq_enable(ncr, ncr400, 1); + ncr->isr |= STATUS_INT; } } else timer_on_auto(&ncr400->timer, 1.0); @@ -675,7 +694,8 @@ ncr53c400_init(const device_t *info) switch (ncr400->type) { case ROM_LCS6821N: /* Longshine LCS6821N */ ncr400->rom_addr = device_get_config_hex20("bios_addr"); - ncr->irq = device_get_config_int("irq"); + ncr400->irq_config = device_get_config_hex16("irq"); + ncr->irq = (ncr400->irq_config >> 5) & 7; rom_init(&ncr400->bios_rom, LCS6821N_ROM, ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -689,7 +709,8 @@ ncr53c400_init(const device_t *info) case ROM_LS2000: /* Corel LS2000 */ ncr400->rom_addr = device_get_config_hex20("bios_addr"); - ncr->irq = device_get_config_int("irq"); + ncr400->irq_config = device_get_config_hex16("irq"); + ncr->irq = (ncr400->irq_config >> 5) & 7; rom_init(&ncr400->bios_rom, COREL_LS2000_ROM, ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -702,7 +723,9 @@ ncr53c400_init(const device_t *info) case ROM_RT1000B: /* Rancho RT1000B/MC */ ncr400->rom_addr = device_get_config_hex20("bios_addr"); - ncr->irq = device_get_config_int("irq"); + ncr400->irq_config = device_get_config_hex16("irq"); + ncr->irq = (ncr400->irq_config >> 5) & 7; + if (info->flags & DEVICE_MCA) { rom_init(&ncr400->bios_rom, RT1000B_820R_ROM, 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -729,7 +752,8 @@ ncr53c400_init(const device_t *info) case ROM_T130B: /* Trantor T130B */ ncr400->rom_addr = device_get_config_hex20("bios_addr"); ncr400->base = device_get_config_hex16("base"); - ncr->irq = device_get_config_int("irq"); + ncr400->irq_config = device_get_config_hex16("irq"); + ncr->irq = (ncr400->irq_config >> 5) & 7; if (ncr400->rom_addr > 0x00000) { rom_init(&ncr400->bios_rom, T130B_ROM, @@ -754,6 +778,7 @@ ncr53c400_init(const device_t *info) ncr->dma_send_ext = NULL; ncr->dma_initiator_receive_ext = NULL; ncr->timer = ncr53c400_timer_on_auto; + ncr->irq_ena = ncr53c400_irq_enable; scsi_bus->bus_device = ncr->bus; scsi_bus->timer = ncr->timer; scsi_bus->priv = ncr->priv; @@ -839,16 +864,16 @@ static const device_config_t ncr53c400_mmio_config[] = { { .name = "irq", .description = "IRQ", - .type = CONFIG_SELECTION, + .type = CONFIG_HEX16, .default_string = NULL, - .default_int = 5, + .default_int = 0xa0, .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 3", .value = 0x60 }, + { .description = "IRQ 4", .value = 0x80 }, + { .description = "IRQ 5", .value = 0xa0 }, + { .description = "IRQ 7", .value = 0xe0 }, { .description = "" } }, .bios = { { 0 } } @@ -910,16 +935,16 @@ static const device_config_t rt1000b_config[] = { { .name = "irq", .description = "IRQ", - .type = CONFIG_SELECTION, + .type = CONFIG_HEX16, .default_string = NULL, - .default_int = 5, + .default_int = 0xa0, .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 3", .value = 0x60 }, + { .description = "IRQ 4", .value = 0x80 }, + { .description = "IRQ 5", .value = 0xa0 }, + { .description = "IRQ 7", .value = 0xe0 }, { .description = "" } }, .bios = { { 0 } } @@ -931,16 +956,16 @@ static const device_config_t rt1000b_mc_config[] = { { .name = "irq", .description = "IRQ", - .type = CONFIG_SELECTION, + .type = CONFIG_HEX16, .default_string = NULL, - .default_int = 5, + .default_int = 0xa0, .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 3", .value = 0x60 }, + { .description = "IRQ 4", .value = 0x80 }, + { .description = "IRQ 5", .value = 0xa0 }, + { .description = "IRQ 7", .value = 0xe0 }, { .description = "" } }, .bios = { { 0 } } @@ -987,16 +1012,16 @@ static const device_config_t t130b_config[] = { { .name = "irq", .description = "IRQ", - .type = CONFIG_SELECTION, + .type = CONFIG_HEX16, .default_string = NULL, - .default_int = 5, + .default_int = 0xa0, .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "None", .value = -1 }, - { .description = "IRQ 3", .value = 3 }, - { .description = "IRQ 5", .value = 5 }, - { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 3", .value = 0x60 }, + { .description = "IRQ 4", .value = 0x80 }, + { .description = "IRQ 5", .value = 0xa0 }, + { .description = "IRQ 7", .value = 0xe0 }, { .description = "" } }, .bios = { { 0 } } diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 5b893dd70..2c2451cc7 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -27,7 +27,6 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> -#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/pic.h> @@ -41,6 +40,7 @@ #include <86box/scsi_device.h> #include <86box/scsi_ncr5380.h> #include <86box/scsi_t128.h> +#include "cpu.h" #define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin" @@ -75,7 +75,7 @@ t128_write(uint32_t addr, uint8_t val, void *priv) if ((addr >= 0x1800) && (addr < 0x1880)) t128->ext_ram[addr & 0x7f] = val; else if ((addr >= 0x1c00) && (addr < 0x1c20)) { - t128_log("T128 ctrl write=%02x, mode=%02x.\n", val, ncr->mode & MODE_DMA); + t128_log("T128 ctrl write=%02x, mode=%02x.\n", val & 0x10, ncr->mode & MODE_DMA); t128->ctrl = val; } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ncr5380_write((addr - 0x1d00) >> 5, val, ncr); @@ -141,6 +141,7 @@ t128_read(uint32_t addr, void *priv) if (ncr->mode & MODE_ENA_EOP_INT) { t128_log("T128 read irq\n"); ncr5380_irq(ncr, 1); + ncr->isr |= STATUS_INT; } scsi_bus->bus_out |= BUS_CD; scsi_bus->tx_mode = PIO_TX_BUS; @@ -298,6 +299,7 @@ t128_callback(void *priv) if (ncr->mode & MODE_ENA_EOP_INT) { t128_log("T128 write irq\n"); ncr5380_irq(ncr, 1); + ncr->isr |= STATUS_INT; } scsi_bus->tx_mode = PIO_TX_BUS; timer_stop(&t128->timer); @@ -497,6 +499,7 @@ t128_init(const device_t *info) ncr->dma_send_ext = t128_dma_send_ext; ncr->dma_initiator_receive_ext = t128_dma_initiator_receive_ext; ncr->timer = t128_timer_on_auto; + ncr->irq_ena = NULL; scsi_bus->bus_device = ncr->bus; scsi_bus->timer = ncr->timer; scsi_bus->priv = ncr->priv; @@ -566,12 +569,13 @@ static const device_config_t t128_config[] = { .description = "IRQ", .type = CONFIG_SELECTION, .default_string = NULL, - .default_int = 5, + .default_int = -1, .file_filter = NULL, .spinner = { 0 }, .selection = { { .description = "None", .value = -1 }, { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 7", .value = 7 }, { .description = "IRQ 10", .value = 10 }, From 5896c1c43b9386950d829bfdc10ba90e6c7383ad Mon Sep 17 00:00:00 2001 From: Nacho Glinsek Date: Sun, 22 Feb 2026 20:22:12 -0300 Subject: [PATCH 56/66] Added support to use CD/DVD drives on Linux --- src/qt/CMakeLists.txt | 3 +- src/qt/qt_mediamenu.cpp | 11 +- src/unix/CMakeLists.txt | 6 +- src/unix/linux_cdrom_ioctl.c | 875 +++++++++++++++++++++++++++++++++++ 4 files changed, 892 insertions(+), 3 deletions(-) create mode 100644 src/unix/linux_cdrom_ioctl.c diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index b7d39109e..3a651b480 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -348,8 +348,9 @@ endif() if(WIN32) target_sources(plat PRIVATE win_cdrom_ioctl.c) +elseif(UNIX AND NOT APPLE) + target_sources(plat PRIVATE ../unix/linux_cdrom_ioctl.c) else() -# Replace with proper *nix and mac handler files once they are done. target_sources(plat PRIVATE dummy_cdrom_ioctl.c) endif() diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index c9250f44c..cdff36469 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -20,6 +20,7 @@ #include "qt_machinestatus.hpp" #include +#include #include #include #include @@ -176,7 +177,15 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addAction(QIcon(":/settings/qt/icons/cdrom_host.ico"), tr("&Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false); } menu->addSeparator(); -#endif // Q_OS_WINDOWS +#elif defined(Q_OS_LINUX) + /* Enumerate Linux CD/DVD drives (/dev/sr0 .. /dev/sr15). */ + for (int sr = 0; sr < 16; sr++) { + QString devPath = QString("/dev/sr%1").arg(sr); + if (QFile::exists(devPath)) + menu->addAction(QIcon(":/settings/qt/icons/cdrom_host.ico"), tr("&Host CD/DVD Drive (%1)").arg(devPath), [this, i, devPath] { cdromMount(i, 2, devPath); })->setCheckable(false); + } + menu->addSeparator(); +#endif cdromEjectPos = menu->children().count(); menu->addAction(tr("E&ject"), [this, i]() { cdromEject(i); })->setCheckable(false); cdromMenus[i] = menu; diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index 1c79b42d2..5ec72bf97 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -47,8 +47,12 @@ add_library(ui OBJECT unix_sdl.c unix_osd.c unix_cdrom.c - dummy_cdrom_ioctl.c ) +if(APPLE) + target_sources(ui PRIVATE dummy_cdrom_ioctl.c) +else() + target_sources(ui PRIVATE linux_cdrom_ioctl.c) +endif() target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64) target_link_libraries(ui ${CMAKE_DL_LIBS}) diff --git a/src/unix/linux_cdrom_ioctl.c b/src/unix/linux_cdrom_ioctl.c new file mode 100644 index 000000000..fdd1c09e8 --- /dev/null +++ b/src/unix/linux_cdrom_ioctl.c @@ -0,0 +1,875 @@ +/* + * 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. + * + * Linux CD-ROM support via IOCTL (SG_IO). + * + * Authors: Miran Grca, + * TheCollector1995, + * + * Copyright 2023 TheCollector1995. + * Copyright 2023 Miran Grca. + * Copyright 2025 86Box contributors. + */ +#include +#ifdef ENABLE_IOCTL_LOG +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/cdrom.h> +#include <86box/log.h> +#include <86box/plat_cdrom_ioctl.h> +#include <86box/scsi_device.h> + +typedef struct ioctl_t { + cdrom_t *dev; + void *log; + int fd; + int is_dvd; + int has_audio; + int blocks_num; + uint8_t cur_rti[65536]; + char path[256]; + pthread_t poll_tid; + int poll_active; +} ioctl_t; + +static int ioctl_read_dvd_structure(const void *local, uint8_t layer, uint8_t format, + uint8_t *buffer, uint32_t *info); +static int ioctl_is_empty(const void *local); + +/* + * Wrapper for the system ioctl() call to avoid naming collisions + * with the local 'ioctl' variable of type ioctl_t*. + */ +static inline int +sys_ioctl(int fd, unsigned long request, void *arg) +{ + return ioctl(fd, request, arg); +} + +#ifdef ENABLE_IOCTL_LOG +int ioctl_do_log = ENABLE_IOCTL_LOG; + +void +ioctl_log(void *priv, const char *fmt, ...) +{ + if (ioctl_do_log) { + va_list ap; + va_start(ap, fmt); + log_out(priv, fmt, ap); + va_end(ap); + } +} +#else +# define ioctl_log(priv, fmt, ...) +#endif + +/* Internal functions. */ +static void +ioctl_close_handle(const ioctl_t *ioctl) +{ + if (ioctl->fd >= 0) + close(ioctl->fd); +} + +static int +ioctl_open_handle(ioctl_t *ioctl) +{ + ioctl_log(ioctl->log, "ioctl->path = \"%s\"\n", ioctl->path); + ioctl->fd = open(ioctl->path, O_RDONLY | O_NONBLOCK); + + ioctl_log(ioctl->log, "fd=%d, errno=%d\n", ioctl->fd, errno); + + return (ioctl->fd >= 0); +} + +/* + * Execute a SCSI command via the Linux SG_IO interface. + * Returns 1 on success, 0 on failure. + * sense_buf should be at least 64 bytes, sense_len receives actual sense length. + */ +static int +sg_io_cmd(int fd, const uint8_t *cdb, int cdb_len, + uint8_t *data_buf, int data_len, int direction, + uint8_t *sense_buf, int *sense_len) +{ + sg_io_hdr_t io_hdr; + + memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = cdb_len; + io_hdr.mx_sb_len = 64; + io_hdr.dxfer_direction = direction; + io_hdr.dxfer_len = data_len; + io_hdr.dxferp = data_buf; + io_hdr.cmdp = (unsigned char *) cdb; + io_hdr.sbp = sense_buf; + io_hdr.timeout = 6000; /* 6 seconds, matching Windows */ + + if (ioctl(fd, SG_IO, &io_hdr) < 0) + return 0; + + if (sense_len != NULL) + *sense_len = io_hdr.sb_len_wr; + + /* Check for SCSI errors. */ + if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { + if (io_hdr.sb_len_wr > 0) { + if (sense_len != NULL) + *sense_len = io_hdr.sb_len_wr; + return 0; + } + return 0; + } + + return 1; +} + +static int +ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf, int32_t *tracks_num) +{ + struct cdrom_tochdr tochdr; + struct cdrom_tocentry tocentry; + int status; + + *tracks_num = 0; + memset(toc_buf, 0x00, 65536); + + status = sys_ioctl(ioctl->fd, CDROMREADTOCHDR, &tochdr); + if (status < 0) + return 0; + + ioctl_log(ioctl->log, "TOC: first=%d, last=%d\n", + tochdr.cdth_trk0, tochdr.cdth_trk1); + + /* + * Build a cooked TOC buffer in the same format as the Windows + * CDROM_TOC structure: + * [0..1] = length (big-endian) + * [2] = first track + * [3] = last track + * [4..] = 8-byte track descriptors + * + * Each track descriptor: + * [0] = reserved + * [1] = Adr/Control + * [2] = track number + * [3] = reserved + * [4..7] = MSF address (0, M, S, F) + */ + toc_buf[2] = tochdr.cdth_trk0; + toc_buf[3] = tochdr.cdth_trk1; + + int count = 0; + for (int i = tochdr.cdth_trk0; i <= tochdr.cdth_trk1; i++) { + memset(&tocentry, 0, sizeof(tocentry)); + tocentry.cdte_track = i; + tocentry.cdte_format = CDROM_MSF; + + if (sys_ioctl(ioctl->fd, CDROMREADTOCENTRY, &tocentry) < 0) + continue; + + uint8_t *t = &toc_buf[4 + count * 8]; + t[0] = 0; + t[1] = ((tocentry.cdte_adr & 0xf) << 4) | (tocentry.cdte_ctrl & 0xf); + t[2] = i; + t[3] = 0; + t[4] = 0; + t[5] = tocentry.cdte_addr.msf.minute; + t[6] = tocentry.cdte_addr.msf.second; + t[7] = tocentry.cdte_addr.msf.frame; + count++; + } + + /* Lead-out (track 0xAA). */ + memset(&tocentry, 0, sizeof(tocentry)); + tocentry.cdte_track = CDROM_LEADOUT; + tocentry.cdte_format = CDROM_MSF; + + if (sys_ioctl(ioctl->fd, CDROMREADTOCENTRY, &tocentry) >= 0) { + uint8_t *t = &toc_buf[4 + count * 8]; + t[0] = 0; + t[1] = ((tocentry.cdte_adr & 0xf) << 4) | (tocentry.cdte_ctrl & 0xf); + t[2] = 0xAA; + t[3] = 0; + t[4] = 0; + t[5] = tocentry.cdte_addr.msf.minute; + t[6] = tocentry.cdte_addr.msf.second; + t[7] = tocentry.cdte_addr.msf.frame; + count++; + } + + /* Set the length field (big-endian). */ + int length = 2 + count * 8; + toc_buf[0] = (length >> 8) & 0xff; + toc_buf[1] = length & 0xff; + *tracks_num = count; + + ioctl_log(ioctl->log, "%i tracks\n", *tracks_num); + + return 1; +} + +static void +ioctl_read_raw_toc(ioctl_t *ioctl) +{ + raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; + uint8_t *buffer = (uint8_t *) calloc(1, 2052); + int status = 0; + + ioctl->is_dvd = (ioctl_read_dvd_structure(ioctl, 0, 0, buffer, NULL) > 0); + free(buffer); + + ioctl->has_audio = 0; + ioctl->blocks_num = 0; + memset(ioctl->cur_rti, 0x00, 65536); + + if (!ioctl->is_dvd) { + /* Try SG_IO with READ TOC command, Format=2 (full/raw TOC). */ + uint8_t cdb[12]; + uint8_t sense[64]; + uint8_t *raw_buf = (uint8_t *) calloc(1, 65536); + int sense_len = 0; + + memset(cdb, 0, sizeof(cdb)); + cdb[0] = 0x43; /* READ TOC */ + cdb[1] = 0x02; /* MSF */ + cdb[2] = 0x02; /* Format = Full TOC (raw) */ + cdb[6] = 0x01; /* Session = 1 */ + cdb[7] = 0xff; /* Allocation length high */ + cdb[8] = 0xff; /* Allocation length low */ + + memset(sense, 0, sizeof(sense)); + status = sg_io_cmd(ioctl->fd, cdb, 10, raw_buf, 65535, + SG_DXFER_FROM_DEV, sense, &sense_len); + + if (status && sense_len == 0) { + int length = ((raw_buf[0] << 8) | raw_buf[1]) - 2; + ioctl->blocks_num = length / 11; + if (ioctl->blocks_num > 0) + memcpy(ioctl->cur_rti, &raw_buf[4], ioctl->blocks_num * 11); + } else { + status = 0; + } + + free(raw_buf); + } + + if (status == 0) { + /* + * Raw TOC read failed (or this is a DVD). Fall back to the + * cooked TOC, and construct raw_track_info_t entries from it, + * mirroring the Windows fallback path. + */ + uint8_t cur_toc[65536] = { 0 }; + int32_t tracks_num = 0; + + status = ioctl_read_normal_toc(ioctl, cur_toc, &tracks_num); + + if ((status > 0) && (tracks_num >= 1)) { + /* Last real entry (the lead-out). */ + const uint8_t *ct = &cur_toc[4 + (tracks_num - 1) * 8]; + + rti[0].adr_ctl = ct[1]; + rti[0].point = 0xa0; + rti[0].pm = cur_toc[2]; /* FirstTrack */ + + rti[1].adr_ctl = rti[0].adr_ctl; + rti[1].point = 0xa1; + rti[1].pm = cur_toc[3]; /* LastTrack */ + + rti[2].adr_ctl = rti[0].adr_ctl; + rti[2].point = 0xa2; + rti[2].pm = ct[5]; /* M */ + rti[2].ps = ct[6]; /* S */ + rti[2].pf = ct[7]; /* F */ + + ioctl->blocks_num = 3; + + for (int i = 0; i < (tracks_num - 1); i++) { + raw_track_info_t *crt = &(rti[ioctl->blocks_num]); + + ct = &cur_toc[4 + i * 8]; + + crt->adr_ctl = ct[1]; + crt->point = ct[2]; + crt->pm = ct[5]; + crt->ps = ct[6]; + crt->pf = ct[7]; + + ioctl->blocks_num++; + } + } else if (status > 0) + /* Announce that we've had a failure. */ + status = 0; + } + + if (ioctl->blocks_num) for (int i = 0; i < ioctl->blocks_num; i++) { + const raw_track_info_t *crt = &(rti[i]); + + if ((crt->point >= 1) && (crt->point <= 99) && !(crt->adr_ctl & 0x04)) { + ioctl->has_audio = 1; + break; + } + } + +#ifdef ENABLE_IOCTL_LOG + ioctl_log(ioctl->log, "%i blocks\n", ioctl->blocks_num); + + for (int i = 0; i < ioctl->blocks_num; i++) { + uint8_t *t = (uint8_t *) &rti[i]; + ioctl_log(ioctl->log, "Block %03i: %02X %02X %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X\n", + i, t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], + t[9], t[10]); + } +#endif +} + +static int +ioctl_get_track(const ioctl_t *ioctl, const uint32_t sector) +{ + raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; + int track = -1; + + for (int i = (ioctl->blocks_num - 1); i >= 0; i--) { + const raw_track_info_t *ct = &(rti[i]); + const uint32_t start = (ct->pm * 60 * 75) + (ct->ps * 75) + ct->pf - 150; + + ioctl_log(ioctl->log, "ioctl_get_track(): ct: %02X, %08X\n", + ct->point, start); + + if ((ct->point >= 1) && (ct->point <= 99) && (sector >= start)) { + track = i; + ioctl_log(ioctl->log, "ioctl_get_track(): found track: %i\n", i); + break; + } + } + + return track; +} + +static int +ioctl_is_track_audio(const ioctl_t *ioctl, const uint32_t pos) +{ + const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; + int ret = 0; + + if (ioctl->has_audio && !ioctl->is_dvd) { + const int track = ioctl_get_track(ioctl, pos); + const int control = rti[track].adr_ctl; + + ret = !(control & 0x04); + + ioctl_log(ioctl->log, "ioctl_is_track_audio(%08X, %02X): %i\n", pos, track, ret); + } + + return ret; +} + +/* Shared functions (cdrom_ops_t interface). */ +static int +ioctl_get_track_info(const void *local, const uint32_t track, + int end, track_info_t *ti) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; + int ret = 1; + int trk = -1; + int next = -1; + + if ((track >= 1) && (track < 99)) + for (int i = 0; i < ioctl->blocks_num; i++) + if (rti[i].point == track) { + trk = i; + break; + } + + if ((track >= 1) && (track < 98)) + for (int i = 0; i < ioctl->blocks_num; i++) + if ((rti[i].point == (track + 1)) && (rti[i].session == rti[trk].session)) { + next = i; + break; + } + + if ((track >= 1) && (track < 99) && (trk != -1) && (next == -1)) + for (int i = 0; i < ioctl->blocks_num; i++) + if ((rti[i].point == 0xa2) && (rti[i].session == rti[trk].session)) { + next = i; + break; + } + + if ((track == 0xaa) || (trk == -1)) { + ioctl_log(ioctl->log, "ioctl_get_track_info(%02i)\n", track); + ret = 0; + } else { + if (end) { + if (next != -1) { + ti->m = rti[next].pm; + ti->s = rti[next].ps; + ti->f = rti[next].pf; + } + } else { + ti->m = rti[trk].pm; + ti->s = rti[trk].ps; + ti->f = rti[trk].pf; + } + + ti->number = rti[trk].point; + ti->attr = rti[trk].adr_ctl; + + ioctl_log(ioctl->log, "ioctl_get_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n", + track, ti->m, ti->s, ti->f, ti->number, ti->attr); + } + + return ret; +} + +static void +ioctl_get_raw_track_info(const void *local, int *num, uint8_t *rti) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + + *num = ioctl->blocks_num; + memcpy(rti, ioctl->cur_rti, ioctl->blocks_num * 11); +} + +static int +ioctl_is_track_pre(const void *local, const uint32_t sector) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; + int ret = 0; + + if (ioctl->has_audio && !ioctl->is_dvd) { + const int track = ioctl_get_track(ioctl, sector); + const int control = rti[track].adr_ctl; + + ret = control & 0x01; + + ioctl_log(ioctl->log, "ioctl_is_track_pre(%08X, %02X): %i\n", sector, track, ret); + } + + return ret; +} + +static int +ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + const raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; + const int sc_offs = (sector == 0xffffffff) ? 0 : 2352; + int len = (sector == 0xffffffff) ? 16 : 2368; + int m = 0; + int s = 0; + int f = 0; + uint32_t lba = sector; + int ret; + int data_len = 0; + + if (ioctl->is_dvd) { + int track; + + data_len = 0; + ret = 0; + + if (lba == 0xffffffff) { + lba = ioctl->dev->seek_pos; + track = ioctl_get_track(ioctl, lba); + + if (track != -1) { + data_len = len; + ret = 1; + } + } else { + len = COOKED_SECTOR_SIZE; + track = ioctl_get_track(ioctl, lba); + + if (track != -1) { + ssize_t nread = pread(ioctl->fd, &(buffer[16]), + COOKED_SECTOR_SIZE, + (off_t) lba * COOKED_SECTOR_SIZE); + if (nread > 0) { + data_len = (int) nread; + ret = 1; + } + } + } + + if (ret && (data_len >= len) && (track != -1)) { + const raw_track_info_t *ct = &(rti[track]); + const uint32_t start = (ct->pm * 60 * 75) + (ct->ps * 75) + ct->pf; + + m = s = f = 0; + + /* Construct sector header and sub-header. */ + if (sector != 0xffffffff) { + /* Sync bytes. */ + buffer[0] = 0x00; + memset(&(buffer[1]), 0xff, 10); + buffer[11] = 0x00; + + /* Sector header. */ + FRAMES_TO_MSF(lba + 150, &m, &s, &f); + buffer[12] = bin2bcd(m); + buffer[13] = bin2bcd(s); + buffer[14] = bin2bcd(f); + + /* Mode 1 data. */ + buffer[15] = 0x01; + } + + /* Construct Q. */ + buffer[sc_offs + 0] = (ct->adr_ctl >> 4) | ((ct->adr_ctl & 0xf) << 4); + buffer[sc_offs + 1] = bin2bcd(ct->point); + buffer[sc_offs + 2] = 1; + FRAMES_TO_MSF((int32_t) (lba + 150 - start), &m, &s, &f); + buffer[sc_offs + 3] = bin2bcd(m); + buffer[sc_offs + 4] = bin2bcd(s); + buffer[sc_offs + 5] = bin2bcd(f); + FRAMES_TO_MSF(lba + 150, &m, &s, &f); + buffer[sc_offs + 7] = bin2bcd(m); + buffer[sc_offs + 8] = bin2bcd(s); + buffer[sc_offs + 9] = bin2bcd(f); + } + } else { + /* CD: use SG_IO with READ CD (0xBE). */ + uint8_t cdb[12]; + uint8_t sense[64]; + int sense_len = 0; + + memset(cdb, 0, sizeof(cdb)); + cdb[0] = 0xbe; /* READ CD */ + cdb[1] = 0x00; + cdb[2] = (sector >> 24) & 0xff; + cdb[3] = (sector >> 16) & 0xff; + cdb[4] = (sector >> 8) & 0xff; + cdb[5] = sector & 0xff; /* Starting LBA */ + cdb[6] = 0x00; + cdb[7] = 0x00; + cdb[8] = 0x01; /* Transfer Length = 1 */ + /* If sector is FFFFFFFF, only return the subchannel. */ + cdb[9] = (sector == 0xffffffff) ? 0x00 : 0xf8; + cdb[10] = 0x02; + cdb[11] = 0x00; + +#ifdef ENABLE_IOCTL_LOG + ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X\n", + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], + cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); +#endif + + memset(sense, 0, sizeof(sense)); + ret = sg_io_cmd(ioctl->fd, cdb, 12, buffer, len, + SG_DXFER_FROM_DEV, sense, &sense_len); + + ioctl_log(ioctl->log, "ioctl_read_sector: ret = %d, sense_len = %d\n", + ret, sense_len); + + if (sense_len >= 16) { + if ((sense[2] == 0x03) && (sense[12] == 0x11)) + /* Treat this as an error to correctly indicate CIRC error to the guest. */ + ret = 0; + ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n", + sense[0], sense[1], sense[2], sense[3], + sense[4], sense[5], sense[6], sense[7]); + ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n", + sense[8], sense[9], sense[10], sense[11], + sense[12], sense[13], sense[14], sense[15]); + } + + ret = ret ? 1 : -1; + data_len = len; /* sg_io_cmd handles this internally */ + } + + ioctl_log(ioctl->log, "ioctl_read_sector: final ret = %i\n", ret); + + /* Construct raw subchannel data from Q only. */ + if ((ret > 0) && !ioctl->is_dvd) + for (int i = 11; i >= 0; i--) + for (int j = 7; j >= 0; j--) + buffer[2352 + (i * 8) + j] = ((buffer[sc_offs + i] >> (7 - j)) & 0x01) << 6; + + return ret; +} + +static uint8_t +ioctl_get_track_type(const void *local, const uint32_t sector) +{ + ioctl_t *ioctl = (ioctl_t *) local; + int track = ioctl_get_track(ioctl, sector); + raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; + const raw_track_info_t *trk = &(rti[track]); + uint8_t ret = 0x00; + + if (ioctl_is_track_audio(ioctl, sector)) + ret = CD_TRACK_AUDIO; + else if (track != -1) for (int i = 0; i < ioctl->blocks_num; i++) { + const raw_track_info_t *ct = &(rti[i]); + const raw_track_info_t *nt = &(rti[i + 1]); + + if (ct->point == 0xa0) { + uint8_t first = ct->pm; + uint8_t last = nt->pm; + + if ((trk->point >= first) && (trk->point <= last)) { + ret = ct->ps; + break; + } + } + } + + return ret; +} + +static uint32_t +ioctl_get_last_block(const void *local) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; + uint32_t lb = 0; + + for (int i = (ioctl->blocks_num - 1); i >= 0; i--) + if (rti[i].point == 0xa2) { + lb = MSFtoLBA(rti[i].pm, rti[i].ps, rti[i].pf) - 151; + break; + } + + ioctl_log(ioctl->log, "LBCapacity=%d\n", lb); + + return lb; +} + +static int +ioctl_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t format, + uint8_t *buffer, uint32_t *info) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + const int len = 2052; + uint8_t cdb[12]; + uint8_t sense[64]; + int sense_len = 0; + + memset(cdb, 0, sizeof(cdb)); + cdb[0] = 0xad; /* READ DVD STRUCTURE */ + cdb[6] = layer; /* Layer Number */ + cdb[7] = format; /* Format */ + cdb[8] = 0x08; /* Allocation Length high */ + cdb[9] = 0x04; /* Allocation Length low */ + +#ifdef ENABLE_IOCTL_LOG + ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X\n", + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], + cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); +#endif + + memset(sense, 0, sizeof(sense)); + int ret = sg_io_cmd(ioctl->fd, cdb, 12, buffer, len, + SG_DXFER_FROM_DEV, sense, &sense_len); + + ioctl_log(ioctl->log, "ioctl_read_dvd_structure(): ret = %d, sense_len = %d\n", + ret, sense_len); + + if (sense_len >= 16) { + /* Return sense to the host as is. */ + ret = -((sense[2] << 16) | (sense[12] << 8) | sense[13]); + if (info != NULL) + *info = *(uint32_t *) &(sense[3]); + ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n", + sense[0], sense[1], sense[2], sense[3], + sense[4], sense[5], sense[6], sense[7]); + ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n", + sense[8], sense[9], sense[10], sense[11], + sense[12], sense[13], sense[14], sense[15]); + } else + ret = ret ? 1 : 0; + + return ret; +} + +static int +ioctl_is_dvd(const void *local) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + + return ioctl->is_dvd; +} + +static int +ioctl_has_audio(const void *local) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + + return ioctl->has_audio; +} + +static int +ioctl_is_empty(const void *local) +{ + const ioctl_t *ioctl = (const ioctl_t *) local; + uint8_t cdb[12]; + uint8_t sense[64]; + int sense_len = 0; + + /* TEST UNIT READY */ + memset(cdb, 0, sizeof(cdb)); + cdb[0] = 0x00; + +#ifdef ENABLE_IOCTL_LOG + ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X\n", + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], + cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); +#endif + + memset(sense, 0, sizeof(sense)); + int ret = sg_io_cmd(ioctl->fd, cdb, 6, NULL, 0, + SG_DXFER_NONE, sense, &sense_len); + + ioctl_log(ioctl->log, "ioctl_is_empty(): ret = %d, sense_len = %d\n", + ret, sense_len); + + if (sense_len >= 16) { + /* Check for NOT READY + MEDIUM NOT PRESENT. */ + ret = ((sense[2] == SENSE_NOT_READY) && (sense[12] == ASC_MEDIUM_NOT_PRESENT)); + ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n", + sense[0], sense[1], sense[2], sense[3], + sense[4], sense[5], sense[6], sense[7]); + ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n", + sense[8], sense[9], sense[10], sense[11], + sense[12], sense[13], sense[14], sense[15]); + } else if (!ret) + ret = 1; /* SG_IO itself failed, assume empty */ + else + ret = 0; /* No sense data and command succeeded = media present */ + + return ret; +} + +/* Disc change polling thread. */ +static void * +ioctl_poll_thread(void *arg) +{ + ioctl_t *ioctl = (ioctl_t *) arg; + int was_empty = ioctl_is_empty(ioctl); + + while (ioctl->poll_active) { + sleep(2); /* Poll every 2 seconds. */ + if (!ioctl->poll_active) + break; + + int now_empty = ioctl_is_empty(ioctl); + if (now_empty != was_empty) { + if (now_empty) + cdrom_set_empty(ioctl->dev); + else + cdrom_update_status(ioctl->dev); + was_empty = now_empty; + } + } + + return NULL; +} + +static void +ioctl_close(void *local) +{ + ioctl_t *ioctl = (ioctl_t *) local; + + /* Stop the polling thread. */ + if (ioctl->poll_active) { + ioctl->poll_active = 0; + pthread_join(ioctl->poll_tid, NULL); + } + + ioctl_close_handle(ioctl); + ioctl->fd = -1; + + ioctl_log(ioctl->log, "Log closed\n"); + + log_close(ioctl->log); + ioctl->log = NULL; + + free(ioctl); +} + +static void +ioctl_load(const void *local) +{ + ioctl_t *ioctl = (ioctl_t *) local; + + if ((ioctl->fd >= 0) || ioctl_open_handle(ioctl)) { + /* Try to close the tray. */ + (void) sys_ioctl(ioctl->fd, CDROMCLOSETRAY, NULL); + + ioctl_read_raw_toc(ioctl); + } +} + +static const cdrom_ops_t ioctl_ops = { + ioctl_get_track_info, + ioctl_get_raw_track_info, + ioctl_is_track_pre, + ioctl_read_sector, + ioctl_get_track_type, + ioctl_get_last_block, + ioctl_read_dvd_structure, + ioctl_is_dvd, + ioctl_has_audio, + ioctl_is_empty, + ioctl_close, + ioctl_load +}; + +/* Public functions. */ +void * +ioctl_open(cdrom_t *dev, const char *drv) +{ + ioctl_t *ioctl = (ioctl_t *) calloc(1, sizeof(ioctl_t)); + + if (ioctl != NULL) { + char n[1024] = { 0 }; + + sprintf(n, "CD-ROM %i IOCtl", dev->id + 1); + ioctl->log = log_open(n); + + memset(ioctl->path, 0x00, sizeof(ioctl->path)); + ioctl->fd = -1; + + /* drv is "ioctl:///dev/sr0", extract the path part. */ + snprintf(ioctl->path, sizeof(ioctl->path), "%s", &(drv[8])); + ioctl_log(ioctl->log, "Path is %s\n", ioctl->path); + + ioctl->dev = dev; + dev->ops = &ioctl_ops; + + ioctl_load(ioctl); + + /* Start the disc change polling thread. */ + ioctl->poll_active = 1; + if (pthread_create(&ioctl->poll_tid, NULL, ioctl_poll_thread, ioctl) != 0) + ioctl->poll_active = 0; + } + + return ioctl; +} From 5bbfbdcee6ff0cf650434dcca40b143772da1c34 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 23 Feb 2026 08:05:09 +0600 Subject: [PATCH 57/66] ql1xxx: Minor code enhancements - Fix typos - Fix incorrect usage of ARRAY_SIZE - ql_write_bank_risc should not return a value - Reorder reg_cfg1 for better cache locality --- src/scsi/scsi_ql1xxx.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/scsi/scsi_ql1xxx.c b/src/scsi/scsi_ql1xxx.c index def034163..a01318210 100644 --- a/src/scsi/scsi_ql1xxx.c +++ b/src/scsi/scsi_ql1xxx.c @@ -8,7 +8,7 @@ * * QLogic QLA1x40/QLA1x80/QLA1x160 SCSI HBA emulation. * - * Register values are derived from the Matthew Jacob's + * Register definitions are derived from the Matthew Jacob's * multiplatform driver for ISP chipsets. * * Authors: Dmitry Borisov, @@ -664,12 +664,12 @@ typedef struct ql_t { uint16_t reg_id_low; uint16_t reg_id_high; uint16_t reg_cfg0; - uint16_t reg_cfg1; uint16_t reg_scsi_diff_pins; uint16_t reg_gpio_data; uint16_t reg_gpio_enable; uint16_t reg_flash_bios_addr; uint16_t reg_nvram; + uint16_t reg_cfg1; uint16_t reg_host_cmd_flags; uint16_t reg_intr_ctrl; uint16_t reg_intr_status; @@ -1342,7 +1342,6 @@ ql_reset_asic(ql_t *dev) ql_update_irq(dev); } - static bool ql_sxp_abort_commands(ql_t *dev, uint8_t path_id, uint8_t target_id, uint8_t lun, uint32_t handle, bool is_handle_valid) { @@ -2172,7 +2171,7 @@ ql_process_mailbox(ql_t *dev) break; default: - ql_log("Unhandled or invalid command %02X\n", dev->reg_mbox_in[0]); + ql_log("Unhandled or invalid command %04X\n", dev->reg_mbox_in[0]); status = QL_MBOX_STATUS_INVALID; break; } @@ -2250,8 +2249,8 @@ ql_pkt_put_request_status(uint32_t address, isp_req_status_t *resp) ql_dma_write16(address + 16, &resp->time); ql_dma_write16(address + 18, &resp->sense_length); ql_dma_write32(address + 20, &resp->residual_length); - ql_dma_write(address + 24, &resp->response[0], ARRAY_SIZE(resp->response)); - ql_dma_write(address + 32, &resp->sense_data[0], ARRAY_SIZE(resp->sense_data)); + ql_dma_write(address + 24, &resp->response[0], sizeof(resp->response)); + ql_dma_write(address + 32, &resp->sense_data[0], sizeof(resp->sense_data)); ql_log("QL: RESP HDR type 0x%X cnt %u seq %u fl 0x%X\n", resp->hdr.entry_type, @@ -2289,7 +2288,7 @@ ql_sxp_fetch_request(ql_sxp_req_t* pkt, uint32_t address) ql_dma_read16(address + 14, &pkt->reserved); ql_dma_read16(address + 16, &pkt->timeout); ql_dma_read16(address + 18, &pkt->seg_count); - ql_dma_read(address + 20, &pkt->cdb[0], ARRAY_SIZE(pkt->cdb)); + ql_dma_read(address + 20, &pkt->cdb[0], sizeof(pkt->cdb)); return true; } @@ -2559,8 +2558,8 @@ ql_sxp_state_machine(ql_t *dev) pkt->hdr.entry_count = 1; pkt->lun = lun; pkt->bus_target = target_id; - pkt->cdb_length = ARRAY_SIZE(pkt->cdb); - memcpy(pkt->cdb, cdb_bytes, ARRAY_SIZE(pkt->cdb)); + pkt->cdb_length = sizeof(pkt->cdb); + memcpy(pkt->cdb, cdb_bytes, sizeof(pkt->cdb)); dev->sxp_state = SXP_STATE_SELECT_DEVICE; break; @@ -2575,7 +2574,7 @@ ql_sxp_state_machine(ql_t *dev) return false; } - /* No available entries the request queue, try again later */ + /* No available entries in the request queue, try again later */ if (QL_RQST_CONS(dev) == QL_RQST_PROD(dev)) { return false; } @@ -2684,7 +2683,7 @@ ql_sxp_state_machine(ql_t *dev) scsi_device_identify(sd, pkt->lun); - for (uint32_t i = 0; i < ARRAY_SIZE(pkt->cdb); i++) { + for (uint32_t i = 0; i < sizeof(pkt->cdb); i++) { ql_log("QL: SCSI CDB[%2lu]=%02X\n", i, pkt->cdb[i]); } @@ -3027,7 +3026,7 @@ ql_write_bank_dma(ql_t *dev, uint32_t addr, uint16_t val) } } -static uint16_t +static void ql_write_bank_risc(ql_t *dev, uint32_t addr, uint16_t val) { switch (addr) { From eb3b07a485f41b4694efca07739c0f02847b9a01 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 14 Jun 2024 23:18:57 -0400 Subject: [PATCH 58/66] MediaVision ThunderBoard --- src/include/86box/snd_sb.h | 2 +- src/include/86box/snd_sb_dsp.h | 10 ++- src/include/86box/sound.h | 3 + src/sound/snd_sb.c | 143 +++++++++++++++++++++++++++++++-- src/sound/snd_sb_dsp.c | 12 +++ src/sound/sound.c | 1 + 6 files changed, 162 insertions(+), 9 deletions(-) diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 394b1b249..a5783d010 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -15,7 +15,7 @@ * * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. - * Copyright 2024-2025 Jasmine Iwanek. + * Copyright 2024-2026 Jasmine Iwanek. */ #ifndef SOUND_SND_SB_H #define SOUND_SND_SB_H diff --git a/src/include/86box/snd_sb_dsp.h b/src/include/86box/snd_sb_dsp.h index b73508211..6e4df0eb1 100644 --- a/src/include/86box/snd_sb_dsp.h +++ b/src/include/86box/snd_sb_dsp.h @@ -9,9 +9,9 @@ #define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /* Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone */ #define SB_SUBTYPE_CLONE_AZTPR16_0X09 3 /* Aztech Sound Galaxy Pro 16 Extra */ -#define SB_SUBTYPE_ESS_ES688 4 /* ESS Technology ES688 */ -#define SB_SUBTYPE_ESS_ES1688 5 /* ESS Technology ES1688 */ -#define SB_SUBTYPE_MVD201 6 /* Mediavision MVD201, found on the thunderboard and PAS16 */ +#define SB_SUBTYPE_MVD201 4 /* Mediavision MVD201, found on the thunderboard and PAS16 */ +#define SB_SUBTYPE_ESS_ES688 5 /* ESS Technology ES688 */ +#define SB_SUBTYPE_ESS_ES1688 6 /* ESS Technology ES1688 */ /* ESS-related */ #define IS_ESS(dsp) ((dsp)->sb_subtype >= SB_SUBTYPE_ESS_ES688) /* Check for future ESS cards here */ @@ -21,6 +21,9 @@ #define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZTPR16_0X09) /* check for future AZT cards here */ #define AZTECH_EEPROM_SIZE 36 +/* MediaVision related */ +#define IS_MV201(dsp) ((dsp)->sb_subtype >= SB_SUBTYPE_MVD201) + typedef struct sb_dsp_t { int sb_type; int sb_subtype; /* which clone */ @@ -103,6 +106,7 @@ typedef struct sb_dsp_t { int sbreset; uint8_t sbreaddat; uint8_t sb_command; + uint8_t sb_last_command; uint8_t sb_test; int sb_timei; int sb_timeo; diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index d83d00a24..b69785353 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -228,6 +228,9 @@ extern const device_t entertainer_device; /* Mindscape Music Board */ extern const device_t mmb_device; +/* MediaVision ThunderBoard */ +extern const device_t thunderboard_device; + /* OPTi 82c93x */ extern const device_t acermagic_s20_device; extern const device_t mirosound_pcm10_device; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index de9b71f9b..20f8b5694 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -15,7 +15,7 @@ * * Copyright 2008-2020 Sarah Walker. * Copyright 2016-2020 Miran Grca. - * Copyright 2024-2025 Jasmine Iwanek. + * Copyright 2024-2026 Jasmine Iwanek. */ #include #include @@ -45,9 +45,10 @@ #include <86box/plat_unused.h> #include <86box/snd_azt2316a.h> -#define SB_1 0 -#define SB_15 1 -#define SB_2 2 +#define SB_1 0 +#define SB_15 1 +#define SB_2 2 +#define THUNDERBOARD 3 #define SB_16_PNP_NOIDE 0 #define SB_16_PNP_IDE 1 @@ -2959,6 +2960,10 @@ sb_init(UNUSED(const device_t *info)) sb->cms_enabled = device_get_config_int("cms"); mixer_addr = device_get_config_int("mixaddr"); break; + case THUNDERBOARD: + model = SB_DSP_200; + sb->cms_enabled = 0; + break; } sb->opl_enabled = device_get_config_int("opl"); @@ -3006,7 +3011,7 @@ sb_init(UNUSED(const device_t *info)) &sb->cms); } - if (mixer_addr > 0x000) { + if (mixer_addr > 0x0000) { sb->mixer_enabled = 1; io_sethandler(mixer_addr + 4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, @@ -3026,6 +3031,58 @@ sb_init(UNUSED(const device_t *info)) return sb; } +void * +thunderboard_init(UNUSED(const device_t *info)) +{ + /* ThunderBoard port mappings, 210h to 260h in 10h steps + 2x6, 2xA, 2xC, 2xE -> DSP chip */ + sb_t *sb = calloc(1, sizeof(sb_t)); + const uint16_t addr = device_get_config_hex16("base"); + + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + fm_driver_get(FM_YM3812, &sb->opl); + + sb_dsp_set_real_opl(&sb->dsp, 0); + sb_dsp_init(&sb->dsp, SB_DSP_200, SB_SUBTYPE_MVD201, sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, addr); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, 1); + + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + if (sb->opl_enabled) { + io_sethandler(addr, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + } + + + sb->cms_enabled = 0; + sb->mixer_enabled = 0; + sound_add_handler(sb_get_buffer_sb2, sb); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sb2, sb); + sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); + + return sb; +} + void * sb_mcv_init(UNUSED(const device_t *info)) { @@ -4288,6 +4345,68 @@ static const device_config_t sb_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t thunderboard_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = NULL, + .default_int = 0x220, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "0x210", .value = 0x210 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x250", .value = 0x250 }, + { .description = "0x260", .value = 0x260 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 7, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + static const device_config_t sb15_config[] = { { .name = "base", @@ -5576,6 +5695,20 @@ static const device_config_t ess_1688_pnp_config[] = { }; // clang-format on +const device_t thunderboard_device = { + .name = "MediaVision ThunderBoard", + .internal_name = "thunderboard", + .flags = DEVICE_ISA, + .local = THUNDERBOARD, + .init = thunderboard_init, + .close = sb_close, + .reset = NULL, + .available = NULL, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = thunderboard_config +}; + const device_t sb_1_device = { .name = "Sound Blaster v1.0", .internal_name = "sb", diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 275c90576..c0ff417b3 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -1732,6 +1732,18 @@ sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, ~dsp->sb_data[0]); break; case 0xE1: /* Get DSP version */ + if (IS_MV201(dsp)) { + if (dsp->sb_last_command == 0xE1) { + sb_add_data(dsp, 0x01); + sb_add_data(dsp, 0x30); + dsp->sb_last_command = 0x00; + } else { + sb_add_data(dsp, 0x02); + sb_add_data(dsp, 0x00); + dsp->sb_last_command = 0xE1; + } + break; + } if (IS_ESS(dsp)) { /* 0x03 0x01 (Sound Blaster Pro compatibility) confirmed by both the diff --git a/src/sound/sound.c b/src/sound/sound.c index c7aefc746..af2f958a9 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -126,6 +126,7 @@ static const SOUND_CARD sound_cards[] = { #ifdef USE_LIBSERIALPORT /*The following devices required LIBSERIALPORT*/ { &opl2board_device }, #endif + { &thunderboard_device }, { &pasplus_device }, { &sb_1_device }, { &sb_15_device }, From c51b944f0f6bea15bd9d5478161770b8c7fb0e95 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:42:09 +0900 Subject: [PATCH 59/66] IBM 5550: Fix hang-up in software reset Remove unnecessary kbc interrupt repeatedly --- src/machine/m_xt_ibm5550.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c index c9940ba7e..582645235 100644 --- a/src/machine/m_xt_ibm5550.c +++ b/src/machine/m_xt_ibm5550.c @@ -1605,9 +1605,6 @@ kbd_epoch_poll(void *priv) } } - if (kbd->irq_state && (kbd->pb & 0x01)) /* Trigger interrupt repeatedly (for RNA test) */ - picint(EPOCH_IRQ3_BIT); - if (!kbd->blocked) { if (kbd->mouse_queue_num > 0) { kbd->mouse_queue_num--; @@ -1716,6 +1713,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) A6xx1x: AIUEO RPQ Keyboard B1xx1x, B2xx1x: Type 3, 4 Keyboard (1972 JIS layout) B5xx1x: ? (standard layout) + AA----: XT keyboard? (The IPL supports it, but the Japanese DOS doesn't) */ kbd_epoch_adddata(0xA5); kbd_epoch_adddata(0x00); From bfa791dbc801fd5579a0e472a62484f00d2b964b Mon Sep 17 00:00:00 2001 From: flama12333 <143599905+flama12333@users.noreply.github.com> Date: Tue, 24 Feb 2026 16:32:18 -0500 Subject: [PATCH 60/66] Change ibm cga to correct has v6355d-f which is emulated idk what origin of bios dump and which model is? since there are two different board. https://www.reddit.com/r/retrocomputing/comments/1i3k7p4/zenith_supersport_zwl18402_ram_failure/ https://retrocomputingforum.com/t/zenith-data-systems-80c88-laptop-from-circa-1985/1454 --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c7585f5ba..081a84ee3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2167,7 +2167,7 @@ const machine_t machines[] = { .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &cga_device, + .vid_device = &v6355d_device, .snd_device = NULL, .net_device = NULL }, From 71ff5a7ed521d340c6df19105cc08ef7dc5103ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 25 Feb 2026 14:32:30 +0100 Subject: [PATCH 61/66] Configuration: Add ../../ that's relative to the parent of the parent of the VM path and no longer relativize anything that's in the root directory. --- src/config.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index edd713755..4c1394ff3 100644 --- a/src/config.c +++ b/src/config.c @@ -1016,12 +1016,19 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp) int ret = 0; char *slash = NULL; char *above = NULL; + char *above2 = NULL; char *use = NULL; if ((slash = memrmem(usr_path + strlen(usr_path) - 2, usr_path, "/")) != NULL) { slash++; above = (char *) calloc(1, slash - usr_path + 1); memcpy(above, usr_path, slash - usr_path); + + if ((slash = memrmem(above + strlen(above) - 2, above, "/")) != NULL) { + slash++; + above2 = (char *) calloc(1, slash - above + 1); + memcpy(above2, above, slash - above); + } } if (strstr(p, "wp://") == p) { @@ -1051,6 +1058,13 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp) else snprintf(dest, MAX_IMAGE_PATH_LEN, "%s%s%s%s", prefix, exe_path, path_get_slash(exe_path), p + strlen("/")); + } else if (memcmp(p, "../../", strlen("../../")) == 0) { + use = (above2 == NULL) ? usr_path : above2; + if ((strlen(prefix) + strlen(use) + strlen(path_get_slash(use)) + strlen(p + strlen("../"))) > + (MAX_IMAGE_PATH_LEN - 11)) + ret = 1; + else + snprintf(dest, MAX_IMAGE_PATH_LEN, "%s%s%s%s", prefix, use, path_get_slash(use), p + strlen("../")); } else if (memcmp(p, "../", strlen("../")) == 0) { use = (above == NULL) ? usr_path : above; if ((strlen(prefix) + strlen(use) + strlen(path_get_slash(use)) + strlen(p + strlen("../"))) > @@ -3146,11 +3160,25 @@ save_image_file(char *cat, char *var, char *src) char *prefix = ""; char *slash = NULL; char *above = NULL; + char *above2 = NULL; + char *above3 = NULL; if ((slash = memrmem(usr_path + strlen(usr_path) - 2, usr_path, "/")) != NULL) { slash++; above = (char *) calloc(1, slash - usr_path + 1); memcpy(above, usr_path, slash - usr_path); + + if ((slash = memrmem(above + strlen(above) - 2, above, "/")) != NULL) { + slash++; + above2 = (char *) calloc(1, slash - above + 1); + memcpy(above2, above, slash - above); + + if ((slash = memrmem(above2 + strlen(above2) - 2, above2, "/")) != NULL) { + slash++; + above3 = (char *) calloc(1, slash - above2 + 1); + memcpy(above3, above2, slash - above2); + } + } } path_normalize(src); @@ -3164,7 +3192,11 @@ save_image_file(char *cat, char *var, char *src) sprintf(temp, "%s", src); else if (!strnicmp(src, usr_path, strlen(usr_path))) sprintf(temp, "%s%s", prefix, &src[strlen(usr_path)]); - else if ((above != NULL) && !strnicmp(src, above, strlen(above))) + /* Do not relativize to root. */ + else if ((above2 != NULL) && (above3 != NULL) && !strnicmp(src, above, strlen(above2))) + sprintf(temp, "../../%s%s", prefix, &src[strlen(above2)]); + /* Do not relativize to root. */ + else if ((above != NULL) && (above2 != NULL) && !strnicmp(src, above, strlen(above))) sprintf(temp, "../%s%s", prefix, &src[strlen(above)]); else if (!strnicmp(src, exe_path, strlen(exe_path))) sprintf(temp, "/%s%s", prefix, &src[strlen(exe_path)]); From 2b05e0054c6b26dbcf9fcb734b08080adede833b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 25 Feb 2026 19:40:38 +0100 Subject: [PATCH 62/66] Configuration: Fix the previous commit. --- src/config.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index 4c1394ff3..e1dacb32b 100644 --- a/src/config.c +++ b/src/config.c @@ -1060,7 +1060,7 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp) p + strlen("/")); } else if (memcmp(p, "../../", strlen("../../")) == 0) { use = (above2 == NULL) ? usr_path : above2; - if ((strlen(prefix) + strlen(use) + strlen(path_get_slash(use)) + strlen(p + strlen("../"))) > + if ((strlen(prefix) + strlen(use) + strlen(path_get_slash(use)) + strlen(p + strlen("../../"))) > (MAX_IMAGE_PATH_LEN - 11)) ret = 1; else @@ -1086,6 +1086,9 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp) path_normalize(dest); + if (above2 != NULL) + free(above2); + if (above != NULL) free(above); @@ -3193,7 +3196,7 @@ save_image_file(char *cat, char *var, char *src) else if (!strnicmp(src, usr_path, strlen(usr_path))) sprintf(temp, "%s%s", prefix, &src[strlen(usr_path)]); /* Do not relativize to root. */ - else if ((above2 != NULL) && (above3 != NULL) && !strnicmp(src, above, strlen(above2))) + else if ((above2 != NULL) && (above3 != NULL) && !strnicmp(src, above2, strlen(above2))) sprintf(temp, "../../%s%s", prefix, &src[strlen(above2)]); /* Do not relativize to root. */ else if ((above != NULL) && (above2 != NULL) && !strnicmp(src, above, strlen(above))) @@ -3205,6 +3208,12 @@ save_image_file(char *cat, char *var, char *src) ini_section_set_string(cat, var, temp); + if (above3 != NULL) + free(above3); + + if (above2 != NULL) + free(above2); + if (above != NULL) free(above); } From 35ab05a0fca3a910baaf9e0c94b706d56f8aea4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 25 Feb 2026 19:51:19 +0100 Subject: [PATCH 63/66] And fix it again. --- src/config.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/config.c b/src/config.c index e1dacb32b..ce8ed3671 100644 --- a/src/config.c +++ b/src/config.c @@ -1032,18 +1032,21 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp) } if (strstr(p, "wp://") == p) { - p += 5; - prefix = "wp://"; - if (ui_wp != NULL) - *ui_wp = 1; + p += 5; + prefix = "wp://"; + if (ui_wp != NULL) + *ui_wp = 1; } else if ((ui_wp != NULL) && *ui_wp) - prefix = "wp://"; + prefix = "wp://"; if (strstr(p, "ioctl://") == p) { - if (strlen(p) > (MAX_IMAGE_PATH_LEN - 11)) - ret = 1; - else - snprintf(dest, MAX_IMAGE_PATH_LEN, "%s", p); + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 11)) + ret = 1; + else + snprintf(dest, MAX_IMAGE_PATH_LEN, "%s", p); + + if (above2 != NULL) + free(above2); if (above != NULL) free(above); @@ -1064,7 +1067,7 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp) (MAX_IMAGE_PATH_LEN - 11)) ret = 1; else - snprintf(dest, MAX_IMAGE_PATH_LEN, "%s%s%s%s", prefix, use, path_get_slash(use), p + strlen("../")); + snprintf(dest, MAX_IMAGE_PATH_LEN, "%s%s%s%s", prefix, use, path_get_slash(use), p + strlen("../../")); } else if (memcmp(p, "../", strlen("../")) == 0) { use = (above == NULL) ? usr_path : above; if ((strlen(prefix) + strlen(use) + strlen(path_get_slash(use)) + strlen(p + strlen("../"))) > From 843f1c81c8b3422d9944b3e6f78e9092f6e9508e Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Wed, 25 Feb 2026 19:57:03 -0600 Subject: [PATCH 64/66] VLSI 59x: Implement DRAM rows, fixes RAM size detection on AST Bravo MS P/90 --- src/chipset/vl82c59x.c | 103 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/src/chipset/vl82c59x.c b/src/chipset/vl82c59x.c index 30cc63065..d75556e76 100644 --- a/src/chipset/vl82c59x.c +++ b/src/chipset/vl82c59x.c @@ -12,7 +12,7 @@ * win2kgamer * * Copyright 2020-2025 Miran Grca. - * Copyright 2025 win2kgamer + * Copyright 2025-2026 win2kgamer */ #ifdef ENABLE_VL82C59X_LOG #include @@ -80,6 +80,9 @@ typedef struct vl82c59x_t { port_92_t *port_92; nvr_t *nvr; + uint32_t banks[4]; + uint8_t bankcfg[4]; + void * log; /* New logging system */ } vl82c59x_t; @@ -207,6 +210,52 @@ vl82c59x_set_pm_io(void *priv) } +void +vl82c59x_recalc_banks(vl82c59x_t *dev) +{ + uint32_t sizes[8] = { 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144 }; + uint8_t shifts[4] = { 0, 4, 0, 4 }; + uint8_t regs[4] = { 0x58, 0x58, 0x59, 0x59 }; + uint32_t total = 0; + + for (uint8_t i = 0; i < 4; i++) { + uint8_t shift = shifts[i]; + uint8_t reg = regs[i]; + uint8_t cfg = (dev->pci_conf[reg] >> shift) & 0x03; /* Module types */ + uint8_t dbl = ((dev->pci_conf[reg] >> shift) & 0x08) ? 1 : 0; /* Single/double sided */ + uint8_t conf = (cfg << 1) | (dbl & 0x01); + uint32_t size = sizes[conf]; + + vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i, cfg = %02X, dbl = %i, conf = %02X, size = %i, RAMCTL0 = %02X\n", i, cfg, dbl, conf, size, dev->pci_conf[0x5c]); + vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i size = %i\n", i, dev->banks[i]); + + /* Handle case where the BIOS programs RAMCFGx for dual-sided/ranked memory when single-sided memory is installed */ + if (((dev->bankcfg[i] & 0x08) == 0x00) && dbl == 1) { + size = sizes[conf - 1]; + vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i mismatch, bankcfg = %02X, reg = %02X\n", dev->bankcfg[i], dev->pci_conf[reg]); + } + + if (!(dev->pci_conf[0x5c] & (1 << i))) + size = 0; + + total += MIN(dev->banks[i], size); + vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i, total = %i\n", i, total); + } + + if (total > 1024) { + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (total - 1024) << 10); + } else { + if (total >= 1024) + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + else + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_high_mapping); + } + + flushmmucache(); +} + static void vl82c59x_write(int func, int addr, UNUSED(int len), uint8_t val, void *priv) { @@ -231,12 +280,21 @@ vl82c59x_write(int func, int addr, UNUSED(int len), uint8_t val, void *priv) case 0x58: /* RAMCFG0 */ case 0x59: /* RAMCFG1 */ dev->pci_conf[addr] = val; + vl82c59x_log(dev->log, "VL82c59x: RAMCFGx write, RAMCFG0 = %02X, RAMCFG1 = %02X\n", dev->pci_conf[0x58], dev->pci_conf[0x59]); + if (machines[machine].init == machine_at_bravoms586_init) + vl82c59x_recalc_banks(dev); break; case 0x5a: /* Wildcat EDO RAM control */ if (dev->type == 0x01) dev->pci_conf[addr] = val; break; - case 0x5c ... 0x5e: /* RAMCTL0-RAMCTL2 */ + case 0x5c: /* RAMCTL0 */ + vl82c59x_log(dev->log, "VL82c59x: RAMCTL0 write\n"); + dev->pci_conf[addr] = val; + if (machines[machine].init == machine_at_bravoms586_init) + vl82c59x_recalc_banks(dev); + break; + case 0x5d ... 0x5e: /* RAMCTL1-RAMCTL2 */ case 0x5f ... 0x60: case 0x62: /* Apricot XEN-PC Ruby/Jade BIOS requires bit 2 to be set or */ @@ -483,6 +541,47 @@ vl82c59x_reset(void *priv) cpu_cache_int_enabled = 1; cpu_cache_ext_enabled = 1; cpu_update_waitstates(); + + /* Init DRAM bank registers */ + uint32_t sizes[8] = { 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144 }; + uint8_t reg_vals[8] = { 0x00, 0x08, 0x01, 0x09, 0x02, 0x0a, 0x03, 0x0b }; + uint32_t ms = mem_size; + + dev->pci_conf[0x58] = 0x00; /* RAMCFG0 */ + dev->pci_conf[0x59] = 0x00; /* RAMCFG1 */ + dev->pci_conf[0x5c] = 0x00; /* RAMCTL0 */ + + + if (ms > 0) for (uint8_t i = 0; i < 4; i++ ) { + for (uint8_t j = 0; j < 8; j++ ) { + if (ms >= sizes[j] ) { + dev->banks[i] = sizes[j]; + dev->bankcfg[i] = reg_vals[j]; + dev->pci_conf[0x5c] |= (1 << i); + } else + break; + } + + ms -= dev->banks[i]; + + if ((ms == 0 || dev->banks[i] == 0)) + break; + } + + for (uint8_t i = 0; i < 4; i++ ) { + if (dev->banks[0] != 0) + dev->pci_conf[0x58] = (dev->bankcfg[0] & 0x0f); + if (dev->banks[1] != 0) + dev->pci_conf[0x58] |= ((dev->bankcfg[1] & 0x0f) << 4); + if (dev->banks[2] != 0) + dev->pci_conf[0x59] = (dev->bankcfg[2] & 0x0f); + if (dev->banks[3] != 0) + dev->pci_conf[0x59] |= ((dev->bankcfg[3] & 0x0f) << 4); + } + + vl82c59x_log(dev->log, "VL82c59x: DRAM bank init, RAMCFG0 = %02X, RAMCFG1 = %02X, RAMCTL0 = %02X\n", dev->pci_conf[0x58], dev->pci_conf[0x59], dev->pci_conf[0x5c]); + vl82c59x_log(dev->log, "VL82c59x: DRAM bank vals: %i, %i, %i, %i\n", dev->banks[0], dev->banks[1], dev->banks[2], dev->banks[3]); + } static void From 34c0bfc15ecab1d432447f0d90b886b203113550 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 26 Feb 2026 11:47:03 +0100 Subject: [PATCH 65/66] AT NVR clean-ups and manually applied the pull requests by Toggo9 and Kotochi. --- src/chipset/ali1543.c | 2 +- src/chipset/intel_piix.c | 6 +- src/chipset/opti602.c | 2 +- src/chipset/opti895.c | 13 +- src/chipset/sis_5513_p2i.c | 2 +- src/chipset/sis_85c496.c | 4 +- src/chipset/sis_85c50x.c | 2 +- src/chipset/via_pipc.c | 2 +- src/chipset/vl82c59x.c | 2 +- src/chipset/wd76c10.c | 2 +- src/include/86box/machine.h | 28 +- src/include/86box/nvr.h | 91 +- src/machine/m_amstrad.c | 11 - src/machine/m_at_286.c | 32 +- src/machine/m_at_386dx.c | 2 +- src/machine/m_at_386sx.c | 37 +- src/machine/m_at_486_misc.c | 12 +- src/machine/m_at_common.c | 24 +- src/machine/m_at_misc.c | 2 +- src/machine/m_at_slot1.c | 58 +- src/machine/m_at_slot1_2.c | 2 +- src/machine/m_at_slot1_socket370.c | 6 +- src/machine/m_at_slot2.c | 4 +- src/machine/m_at_socket1.c | 8 +- src/machine/m_at_socket2.c | 9 +- src/machine/m_at_socket3.c | 15 +- src/machine/m_at_socket370.c | 28 +- src/machine/m_at_socket3_pci.c | 36 +- src/machine/m_at_socket4.c | 12 +- src/machine/m_at_socket4_5.c | 2 +- src/machine/m_at_socket5.c | 259 ++- src/machine/m_at_socket7.c | 83 +- src/machine/m_at_socket7_3v.c | 284 ++-- src/machine/m_at_socket8.c | 10 +- src/machine/m_at_sockets7.c | 24 +- src/machine/m_elt.c | 2 +- src/machine/m_ps1.c | 2 - src/machine/m_ps2_isa.c | 2 - src/machine/m_ps2_mca.c | 1 - src/machine/m_xt.c | 4 - src/machine/m_xt_xi8088.c | 1 - src/machine/machine.c | 3 + src/machine/machine_table.c | 2556 ++++++++++++++++++++++------ src/nvr_at.c | 503 +----- src/scsi/scsi_ql1xxx.c | 1 - src/sio/sio_f82c606.c | 2 +- src/sio/sio_fdc37c93x.c | 2 +- src/sio/sio_pc87306.c | 2 +- src/sio/sio_vl82c113.c | 9 +- src/sio/sio_w83977.c | 2 +- 50 files changed, 2726 insertions(+), 1482 deletions(-) diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 3d5ddf603..3ede62298 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -1614,7 +1614,7 @@ ali1543_init(const device_t *info) /* ACPI */ dev->acpi = device_add(&acpi_ali_device); - dev->nvr = device_add(&piix4_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_PIIX4); /* DMA */ dma_alias_set(); diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 9f7814869..d7db43e0a 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1581,11 +1581,11 @@ piix_init(const device_t *info) if (dev->type > 3) { if (info->local & PIIX4_NVR_AMI_1995J) - dev->nvr = device_add(&piix4_ami_1995j_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_PIIX4_AMI_1995J); else if (info->local & PIIX4_NVR_AMI_1995) - dev->nvr = device_add(&piix4_ami_1995_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_PIIX4_AMI_1995); else - dev->nvr = device_add(&piix4_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_PIIX4); dev->smbus = device_add(&piix4_smbus_device); dev->acpi = device_add(&acpi_intel_device); diff --git a/src/chipset/opti602.c b/src/chipset/opti602.c index 7082408c7..7520497d7 100644 --- a/src/chipset/opti602.c +++ b/src/chipset/opti602.c @@ -203,7 +203,7 @@ opti602_init(UNUSED(const device_t *info)) io_sethandler(0x0022, 0x0001, opti602_read, NULL, NULL, opti602_write, NULL, NULL, dev); io_sethandler(0x0024, 0x0001, opti602_read, NULL, NULL, opti602_write, NULL, NULL, dev); - dev->nvr = device_add(&at_mb_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_MB); opti602_reset(dev); diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index 6edd7c855..7be1d0bd1 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -44,6 +44,7 @@ typedef struct opti895_t { static uint8_t masks[0x10] = { 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xe3, 0xff, 0xe3, 0xff, 0x00, 0xff, 0xff, 0xff }; +#define ENABLE_OPTI895_LOG 1 #ifdef ENABLE_OPTI895_LOG int opti895_do_log = ENABLE_OPTI895_LOG; @@ -159,6 +160,8 @@ opti895_write(uint16_t addr, uint8_t val, void *priv) ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { if (dev->idx > 0x2f) dev->regs[dev->idx] = val; + else if (dev->idx == 0x28) + dev->regs[dev->idx] = (val & masks[dev->idx - 0x20]) | 0x18; else dev->regs[dev->idx] = val & masks[dev->idx - 0x20]; opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val); @@ -247,7 +250,11 @@ opti895_read(uint16_t addr, void *priv) if (((dev->idx >= 0x20) && (dev->idx <= 0x2f) && (dev->idx != 0x2c)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { ret = dev->regs[dev->idx]; - if (dev->idx == 0xe0) + if (dev->idx == 0x21) + ret |= 0x1c; + else if (dev->idx == 0x28) + ret |= 0x18; + else if (dev->idx == 0xe0) ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green; } break; @@ -291,7 +298,7 @@ opti895_init(const device_t *info) dev->regs[0x01] = 0xc0; - dev->regs[0x22] = 0xc4; + dev->regs[0x22] = 0xe4; dev->regs[0x25] = 0x7c; dev->regs[0x26] = 0x10; dev->regs[0x27] = 0xde; @@ -304,7 +311,7 @@ opti895_init(const device_t *info) dev->regs[0xe8] = 0x08; dev->regs[0xe9] = 0x08; dev->regs[0xeb] = 0xff; - dev->regs[0xef] = 0x40; + dev->regs[0xef] = 0x41; opti895_recalc(dev); diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index ac160f337..50b5c8362 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -1238,7 +1238,7 @@ sis_5513_pci_to_isa_init(UNUSED(const device_t *info)) dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; /* NVR */ - dev->nvr = device_add(&at_mb_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_MB); switch (dev->rev) { case 0x00: diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index a04f01633..2f0db10dc 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -673,9 +673,9 @@ static void ide_sec_disable(); if (info->local) - dev->nvr = device_add(&ami_1994_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AMI_1994); else - dev->nvr = device_add(&at_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT); dma_high_page_init(); diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 5eb3b518d..79f35f3fe 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -667,7 +667,7 @@ sis_85c50x_init(UNUSED(const device_t *info)) dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; /* NVR */ - dev->nvr = device_add(&at_mb_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_MB); device_add(&ide_pci_2ch_device); } diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index a5883791e..e36a91970 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -1722,7 +1722,7 @@ pipc_init(const device_t *info) else if (dev->local >= VIA_PIPC_596A) dev->smbus = device_add(&piix4_smbus_device); - dev->nvr = device_add(&via_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_VIA); if (dev->local >= VIA_PIPC_596A) { dev->acpi = device_add(&acpi_via_596b_device); diff --git a/src/chipset/vl82c59x.c b/src/chipset/vl82c59x.c index d75556e76..b0e92b3ef 100644 --- a/src/chipset/vl82c59x.c +++ b/src/chipset/vl82c59x.c @@ -622,7 +622,7 @@ vl82c59x_init(UNUSED(const device_t *info)) dev->port_92 = device_add(&port_92_device); /* NVR */ - dev->nvr = device_add(&at_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT); dev->smram[0] = smram_add(); dev->smram[1] = smram_add(); diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index b70785b37..be18f8d96 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -1393,7 +1393,7 @@ wd76c10_init(UNUSED(const device_t *info)) dev->mem_pages[i] = i - 0x20; device_add(&port_92_inv_device); - dev->nvr = device_add(&amstrad_megapc_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_ZERO_DEFAULT); dev->uart[0] = device_add_inst(&ns16450_device, 1); dev->uart[1] = device_add_inst(&ns16450_device, 2); dev->lpt = device_add_inst(&lpt_port_device, 1); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f1a660f7d..6daa66738 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -245,6 +245,7 @@ enum { MACHINE_CHIPSET_INTEL_430VX, MACHINE_CHIPSET_INTEL_430TX, MACHINE_CHIPSET_INTEL_450KX, + MACHINE_CHIPSET_INTEL_450GX, MACHINE_CHIPSET_INTEL_440FX, MACHINE_CHIPSET_INTEL_440EX, MACHINE_CHIPSET_INTEL_440LX, @@ -353,6 +354,18 @@ typedef struct _machine_ { void *kbc_device; #endif /* EMU_DEVICE_H */ uintptr_t kbc_params; +#ifdef EMU_DEVICE_H + const device_t *nvr_device; +#else + void *nvr_device; +#endif /* EMU_DEVICE_H */ + uintptr_t nvr_params; +#ifdef EMU_DEVICE_H + const device_t *sio_device; +#else + void *sio_device; +#endif /* EMU_DEVICE_H */ + uintptr_t sio_params; /* Bits 23-16: XOR mask, bits 15-8: OR mask, bits 7-0: AND mask. */ uint32_t kbc_p1; uint32_t gpio; @@ -361,7 +374,6 @@ typedef struct _machine_ { const device_t *device; const device_t *kbd_device; const device_t *fdc_device; - const device_t *sio_device; const device_t *vid_device; const device_t *snd_device; const device_t *net_device; @@ -369,7 +381,6 @@ typedef struct _machine_ { void *device; void *kbd_device; void *fdc_device; - void *sio_device; void *vid_device; void *snd_device; void *net_device; @@ -394,9 +405,10 @@ extern int machine_get_machine_from_internal_name(const char *s); extern void machine_init(void); #ifdef EMU_DEVICE_H extern const device_t *machine_get_kbc_device(int m); +extern const device_t *machine_get_nvr_device(int m); +extern const device_t *machine_get_sio_device(int m); extern const device_t *machine_get_device(int m); extern const device_t *machine_get_fdc_device(int m); -extern const device_t *machine_get_sio_device(int m); extern const device_t *machine_get_vid_device(int m); extern const device_t *machine_get_snd_device(int m); extern const device_t *machine_get_net_device(int m); @@ -528,6 +540,7 @@ extern int machine_at_px286_init(const machine_t *); extern int machine_at_ataripc4_init(const machine_t *); extern int machine_at_neat_ami_init(const machine_t *); extern int machine_at_3302_init(const machine_t *); +extern int machine_at_n8810m30_init(const machine_t *); /* SCAMP */ extern int machine_at_pc7286_init(const machine_t *); @@ -579,6 +592,7 @@ extern int machine_at_shuttle386sx_init(const machine_t *); /* NEAT */ extern int machine_at_cmdsl386sx16_init(const machine_t *); extern int machine_at_neat_init(const machine_t *); +extern int machine_at_p3345_init(const machine_t *); /* NEATsx */ extern int machine_at_if386sx_init(const machine_t *); @@ -659,12 +673,10 @@ extern const device_t opti495_ami_device; extern int machine_at_opti495_ami_init(const machine_t *); /* m_at_common.c */ -extern void machine_at_common_init_ex(const machine_t *, int type); extern void machine_at_common_init(const machine_t *); extern void machine_at_init(const machine_t *); extern void machine_at_ps2_init(const machine_t *); extern void machine_at_common_ide_init(const machine_t *); -extern void machine_at_ibm_common_ide_init(const machine_t *); extern void machine_at_ide_init(const machine_t *); extern void machine_at_ps2_ide_init(const machine_t *); @@ -965,12 +977,12 @@ extern int machine_at_hot539_init(const machine_t *); /* VLSI SuperCore */ extern int machine_at_bravoms586_init(const machine_t *); -extern int machine_at_g586vpmc_init(const machine_t *); extern int machine_at_m54si_init(const machine_t *); extern int machine_at_pb600_init(const machine_t *); /* VLSI Wildcat */ extern int machine_at_globalyst620_init(const machine_t *); +extern int machine_at_g586vpmc_init(const machine_t *); /* m_at_socket7_3v.c */ /* i430FX */ @@ -986,6 +998,7 @@ extern const device_t vectra52_device; extern int machine_at_vectra52_init(const machine_t *); extern int machine_at_vectra500mt_init(const machine_t *); extern int machine_at_vectra54_init(const machine_t *); +extern int machine_at_atlantis_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t thor_device; #endif @@ -994,7 +1007,6 @@ extern uint32_t machine_at_monaco_gpio_handler(uint8_t write, uint32_t va extern int machine_at_monaco_init(const machine_t *); extern uint32_t machine_at_endeavor_gpio_handler(uint8_t write, uint32_t val); extern int machine_at_endeavor_init(const machine_t *); -extern int machine_at_atlantis_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t monaco_device; #endif @@ -1177,6 +1189,8 @@ extern int machine_at_5sg100_init(const machine_t *); /* m_at_socket8.c */ /* i450KX */ extern int machine_at_ap61_init(const machine_t *); + +/* i450GX */ #ifdef EMU_DEVICE_H extern const device_t ficpo6000_device; #endif diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 9d6d78923..7add5cb39 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -57,6 +57,76 @@ #define TIME_SYNC_ENABLED 1 #define TIME_SYNC_UTC 2 +/* Century register for the AT, etc. */ +#define RTC_CENTURY_AT 0x32 +/* Century register for the PS/1 and the PS/2. */ +#define RTC_CENTURY_PS 0x37 +/* Century register for the Epson Equity LT. */ +#define RTC_CENTURY_ELT 0x1a +/* century register for VIA VT82C586B. */ +#define RTC_CENTURY_VIA 0x7f +/* No century register. */ +#define RTC_CENTURY_NONE 0xff + +#define FLAG_ZERO_DEFAULT 0x0001 +#define FLAG_NO_NMI 0x0002 +#define FLAG_MULTI_ADDRESS 0x0004 +#define FLAG_MULTI_BANK 0x0008 +#define FLAG_PIIX4 0x0010 +#define FLAG_FIXED_SIZE 0x0020 +#define FLAG_MARTIN_HACK 0x0040 +#define FLAG_AMI_1992_HACK 0x0080 +#define FLAG_AMI_1994_HACK 0x0100 +#define FLAG_P6RP4_HACK 0x0200 +#define FLAG_AMI_1995_HACK 0x0400 +#define FLAG_AMI_1999_HACK 0x0800 +#define FLAG_AMI_1999J_HACK 0x1000 +#define FLAG_SPITFIRE_HACK 0x2000 +#define FLAG_BX6_HACK 0x4000 + +#define NVR_CENTURY_AT (RTC_CENTURY_AT << 16) +#define NVR_CENTURY_PS (RTC_CENTURY_PS << 16) +#define NVR_CENTURY_VIA (RTC_CENTURY_VIA << 16) +#define NVR_CENTURY_ELT (RTC_CENTURY_ELT << 16) +#define NVR_CENTURY_NONE (0xff << 16) + +#define NVR_ADDR_STANDARD (0x0070ULL << 24) +#define NVR_ADDR_ELT (0x11b4ULL << 24) +#define NVR_ADDR_CONFIG (0xfffeULL << 24) +#define NVR_ADDR_NONE (0xffffULL << 24) + +#define NVR_IRQ_STANDARD (0x0008ULL << 40) +#define NVR_IRQ_AMSTRAD (0x0001ULL << 40) +#define NVR_IRQ_CONFIG (0xfffeULL << 40) +#define NVR_IRQ_NONE (0xffffULL << 40) + +#define NVR_AT_STANDARD NVR_IRQ_STANDARD | NVR_ADDR_STANDARD +#define NVR_AT_STANDARD_MA NVR_AT_STANDARD | FLAG_MULTI_ADDRESS +#define NVR_AT_STANDARD_ZERO NVR_AT_STANDARD | FLAG_ZERO_DEFAULT + +#define NVR_AT_OLD (NVR_AT_STANDARD | NVR_CENTURY_NONE) +#define NVR_AT (NVR_AT_STANDARD | NVR_CENTURY_AT) +#define NVR_AT_ZERO_DEFAULT (NVR_AT_STANDARD_ZERO | NVR_CENTURY_AT) +#define NVR_AT_MA (NVR_AT | FLAG_MULTI_ADDRESS) +#define NVR_AT_MA_ZERO (NVR_AT_ZERO_DEFAULT | FLAG_MULTI_ADDRESS) +#define NVR_AT_MB (NVR_AT_ZERO_DEFAULT | FLAG_MULTI_BANK) +#define NVR_PS (NVR_AT_STANDARD_ZERO | NVR_CENTURY_PS) +#define NVR_PS_NO_NMI (NVR_PS | FLAG_NO_NMI) +#define NVR_AMSTRAD (NVR_IRQ_AMSTRAD | NVR_ADDR_STANDARD | NVR_CENTURY_AT) +#define NVR_AMSTRAD_NO_NMI (NVR_AMSTRAD | FLAG_NO_NMI) +#define NVR_PIIX4 (NVR_AT_MA_ZERO | FLAG_PIIX4) +#define NVR_AMI_1992 (NVR_AT_ZERO_DEFAULT | FLAG_AMI_1992_HACK) +#define NVR_AMI_1994 (NVR_AT_ZERO_DEFAULT | FLAG_AMI_1994_HACK) +#define NVR_AMI_1995 (NVR_AT_ZERO_DEFAULT | FLAG_AMI_1995_HACK) +#define NVR_P6RP4 (NVR_AT_MA_ZERO | FLAG_P6RP4_HACK) +#define NVR_PIIX4_AMI_1995 (NVR_PIIX4 | FLAG_AMI_1999_HACK) +#define NVR_PIIX4_AMI_1995J (NVR_PIIX4 | FLAG_AMI_1999J_HACK) +#define NVR_VIA (NVR_AT_STANDARD_MA | NVR_CENTURY_VIA) +#define NVR_MARTIN (NVR_AT_MB | FLAG_MARTIN_HACK) +#define NVR_ELT (NVR_IRQ_NONE | NVR_ADDR_ELT | NVR_CENTURY_ELT) +#define NVR_RTC8088 (NVR_IRQ_CONFIG | NVR_ADDR_CONFIG | \ + NVR_CENTURY_ALT | FLAG_NO_NMI | FLAG_FIXED_SIZE) + #ifdef _TIMER_H_ /* Define a generic RTC/NVRAM device. */ typedef struct _nvr_ { @@ -80,26 +150,9 @@ typedef struct _nvr_ { } nvr_t; extern int nvr_dosave; + #ifdef EMU_DEVICE_H -extern const device_t at_nvr_old_device; -extern const device_t at_nvr_device; -extern const device_t at_mb_nvr_device; -extern const device_t ps_nvr_device; -extern const device_t amstrad_nvr_device; -extern const device_t amstrad_megapc_nvr_device; -extern const device_t ibmat_nvr_device; -extern const device_t piix4_nvr_device; -extern const device_t ps_no_nmi_nvr_device; -extern const device_t amstrad_no_nmi_nvr_device; -extern const device_t ami_1992_nvr_device; -extern const device_t ami_1994_nvr_device; -extern const device_t ami_1995_nvr_device; -extern const device_t via_nvr_device; -extern const device_t piix4_ami_1995_nvr_device; -extern const device_t piix4_ami_1995j_nvr_device; -extern const device_t p6rp4_nvr_device; -extern const device_t martin_nvr_device; -extern const device_t elt_nvr_device; +extern const device_t nvr_at_device; #endif extern void rtc_tick(void); diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 8e4a16c60..b443f3756 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2971,17 +2971,6 @@ machine_amstrad_init(const machine_t *model, int type) ams->type = type; amstrad_latch = 0x80000000; - switch (type) { - case AMS_PC200: - case AMS_PPC512: - device_add(&amstrad_no_nmi_nvr_device); - break; - - default: - device_add(&amstrad_nvr_device); - break; - } - machine_common_init(model); nmi_init(); diff --git a/src/machine/m_at_286.c b/src/machine/m_at_286.c index ad36e3245..82edfe51a 100644 --- a/src/machine/m_at_286.c +++ b/src/machine/m_at_286.c @@ -140,7 +140,7 @@ const device_t ibmat_device = { static void machine_at_ibm_common_init(const machine_t *model) { - machine_at_common_init_ex(model, 1); + machine_at_common_init(model); device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); @@ -510,8 +510,7 @@ machine_at_m290_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 6); - device_add(&amstrad_megapc_nvr_device); + machine_at_common_init(model); device_add(&olivetti_eva_device); device_add(&port_6x_olivetti_device); @@ -630,7 +629,7 @@ machine_at_siemens_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 1); + machine_at_common_init(model); device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); @@ -923,6 +922,29 @@ machine_at_3302_init(const machine_t *model) return ret; } +int +machine_at_n8810m30_init(const machine_t *model) /* Onboard SCSI not yet emulated */ +{ + int ret; + + ret = bios_load_linear("roms/machines/n8810m30/at286bios_53889.00.0.17jr.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&neat_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + + return ret; +} + /* SCAMP */ int machine_at_pc7286_init(const machine_t *model) @@ -935,7 +957,7 @@ machine_at_pc7286_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); diff --git a/src/machine/m_at_386dx.c b/src/machine/m_at_386dx.c index 3a90f801d..f8d3476fa 100644 --- a/src/machine/m_at_386dx.c +++ b/src/machine/m_at_386dx.c @@ -272,7 +272,7 @@ machine_at_spc6000a_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 1); + machine_at_common_init(model); device_add(&cs8230_device); diff --git a/src/machine/m_at_386sx.c b/src/machine/m_at_386sx.c index d996a14bc..e9a24a61a 100644 --- a/src/machine/m_at_386sx.c +++ b/src/machine/m_at_386sx.c @@ -409,8 +409,7 @@ machine_at_adi386sx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); /* NVR that is initialized to all 0x00's. */ + machine_at_common_init(model); device_add(&intel_82335_device); device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); @@ -494,6 +493,31 @@ machine_at_neat_init(const machine_t *model) return ret; } +int +machine_at_p3345_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/p3345/BIOS_EVEN.BIN", + "roms/machines/p3345/BIOS_ODD.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + + device_add(&neat_device); + device_add(&ide_isa_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + /* NEATsx */ int machine_at_if386sx_init(const machine_t *model) @@ -507,8 +531,7 @@ machine_at_if386sx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); /* NVR that is initialized to all 0x00's. */ + machine_at_common_init(model); device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); @@ -588,7 +611,7 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5402_onboard_commodore_device); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&ide_isa_device); @@ -700,7 +723,7 @@ machine_at_dells333sl_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&ide_isa_device); @@ -774,7 +797,7 @@ machine_at_wd76c10_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); diff --git a/src/machine/m_at_486_misc.c b/src/machine/m_at_486_misc.c index 6c492ada5..0d009c1ca 100644 --- a/src/machine/m_at_486_misc.c +++ b/src/machine/m_at_486_misc.c @@ -60,7 +60,7 @@ machine_at_itoxstar_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -90,7 +90,7 @@ machine_at_arb1423c_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -117,7 +117,7 @@ machine_at_arb1479_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -144,7 +144,7 @@ machine_at_iach488_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -169,7 +169,7 @@ machine_at_pcm9340_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -198,7 +198,7 @@ machine_at_pcm5330_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_common.c b/src/machine/m_at_common.c index 383c8dba5..bd122a6ce 100644 --- a/src/machine/m_at_common.c +++ b/src/machine/m_at_common.c @@ -61,7 +61,7 @@ #include <86box/machine.h> void -machine_at_common_init_ex(const machine_t *model, int type) +machine_at_common_init(const machine_t *model) { machine_common_init(model); @@ -70,24 +70,12 @@ machine_at_common_init_ex(const machine_t *model, int type) pic2_init(); dma16_init(); - if (!(type & 4)) + if (model->init != machine_at_m290_init) device_add(&port_6x_device); - type &= 3; - - if (type == 1) - device_add(&ibmat_nvr_device); - else if (type == 0) - device_add(&at_nvr_device); standalone_gameport_type = &gameport_device; } -void -machine_at_common_init(const machine_t *model) -{ - machine_at_common_init_ex(model, 0); -} - void machine_at_init(const machine_t *model) { @@ -112,14 +100,6 @@ machine_at_common_ide_init(const machine_t *model) device_add(&ide_isa_device); } -void -machine_at_ibm_common_ide_init(const machine_t *model) -{ - machine_at_common_init_ex(model, 1); - - device_add(&ide_isa_device); -} - void machine_at_ide_init(const machine_t *model) { diff --git a/src/machine/m_at_misc.c b/src/machine/m_at_misc.c index eb93688a7..f34c5b157 100644 --- a/src/machine/m_at_misc.c +++ b/src/machine/m_at_misc.c @@ -47,7 +47,7 @@ machine_at_vpc2007_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); is_vpc = 1; pci_init(PCI_CONFIG_TYPE_1); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index a40fac2dd..013d6a828 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -50,7 +50,7 @@ machine_at_m729_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -83,7 +83,7 @@ machine_at_acerv62x_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -220,7 +220,7 @@ machine_at_lx6_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -251,7 +251,7 @@ machine_at_optiplexgxa_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); @@ -442,7 +442,7 @@ machine_at_ms6117_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -479,7 +479,7 @@ machine_at_ma30d_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -516,7 +516,7 @@ machine_at_brio83xx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); // Actual settings! @@ -610,7 +610,7 @@ machine_at_como_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -643,7 +643,7 @@ machine_at_p6i440e2_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -676,7 +676,7 @@ machine_at_bf6_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -792,7 +792,7 @@ machine_at_bx6_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -823,7 +823,7 @@ machine_at_p2bls_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -862,7 +862,7 @@ machine_at_p3bf_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -962,7 +962,7 @@ machine_at_ax6bc_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1059,7 +1059,7 @@ machine_at_ga686_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1178,7 +1178,7 @@ machine_at_ms6119_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1273,7 +1273,7 @@ machine_at_ms6147_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1363,7 +1363,7 @@ machine_at_p6sba_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1453,7 +1453,7 @@ machine_at_s1846_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1556,7 +1556,7 @@ machine_at_vei8_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1580,7 +1580,7 @@ machine_at_vei8_init(const machine_t *model) static void machine_at_ms6168_common_init(const machine_t *model) { - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1651,7 +1651,7 @@ machine_at_atc6310bxii_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1683,7 +1683,7 @@ machine_at_ficka6130_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1715,7 +1715,7 @@ machine_at_p3v133_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1825,7 +1825,7 @@ machine_at_ms6199va_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1866,7 +1866,7 @@ machine_at_p3v4x_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1901,7 +1901,7 @@ machine_at_gt694va_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1944,7 +1944,7 @@ machine_at_p6f99_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1979,7 +1979,7 @@ machine_at_m747_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_slot1_2.c b/src/machine/m_at_slot1_2.c index 2c8151abe..9ee1e5dc6 100644 --- a/src/machine/m_at_slot1_2.c +++ b/src/machine/m_at_slot1_2.c @@ -51,7 +51,7 @@ machine_at_fw6400gx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_slot1_socket370.c b/src/machine/m_at_slot1_socket370.c index a9006c5e7..ff3baf220 100644 --- a/src/machine/m_at_slot1_socket370.c +++ b/src/machine/m_at_slot1_socket370.c @@ -114,7 +114,7 @@ machine_at_prosignias31x_bx_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -154,7 +154,7 @@ machine_at_s1857_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -193,7 +193,7 @@ machine_at_p6bat_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_slot2.c b/src/machine/m_at_slot2.c index 20b5f05f7..ae1bf49ca 100644 --- a/src/machine/m_at_slot2.c +++ b/src/machine/m_at_slot2.c @@ -50,7 +50,7 @@ machine_at_6gxu_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -85,7 +85,7 @@ machine_at_s2dge_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_socket1.c b/src/machine/m_at_socket1.c index 7bb69d368..dddc16a9e 100644 --- a/src/machine/m_at_socket1.c +++ b/src/machine/m_at_socket1.c @@ -304,7 +304,7 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&vl82c480_device); @@ -342,7 +342,7 @@ machine_at_d824_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&vl82c480_device); @@ -379,7 +379,7 @@ machine_at_pcs44c_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&vl82c486_device); device_add(&tulip_jumper_device); @@ -437,7 +437,7 @@ machine_at_tuliptc38_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&vl82c486_device); device_add(&tulip_jumper_device); diff --git a/src/machine/m_at_socket2.c b/src/machine/m_at_socket2.c index 5b871d298..ba44aa557 100644 --- a/src/machine/m_at_socket2.c +++ b/src/machine/m_at_socket2.c @@ -61,7 +61,7 @@ machine_at_pb410a_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_ibm_common_ide_init(model); + machine_at_common_ide_init(model); device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); @@ -199,8 +199,7 @@ machine_at_g486ip_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&ami_1992_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -380,7 +379,7 @@ machine_at_monsoon_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&vl82c480_device); device_add(&vl82c113_device); @@ -408,7 +407,7 @@ machine_at_martin_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&vl82c480_device); device_add(&vl82c113_device); diff --git a/src/machine/m_at_socket3.c b/src/machine/m_at_socket3.c index 7c8c801f6..ac6b979d6 100644 --- a/src/machine/m_at_socket3.c +++ b/src/machine/m_at_socket3.c @@ -105,15 +105,14 @@ machine_at_ap4100aa_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); - device_add(&ami_1994_nvr_device); device_add(&ali1429g_device); device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); device_add(&ide_vlb_device); - device_add_params(&um866x_device, (void *) UM8663BF); + device_add_params(&um866x_device, (void *) (uintptr_t) UM8663BF); return ret; } @@ -265,11 +264,8 @@ machine_at_403tg_init(const machine_t *model) fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); ret = bios_load_linear(fn, 0x000f0000, 65536, 0); - if (nvr_hack) { - machine_at_common_init_ex(model, 2); - device_add(&ami_1994_nvr_device); - } else - machine_at_common_init(model); + machine_at_common_init(model); + device_add_params(&nvr_at_device, (void *) (uintptr_t) (nvr_hack ? (NVR_AMI_1994) : (NVR_AT))); device_add(&opti895_device); @@ -482,8 +478,7 @@ machine_at_tg486g_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); + machine_at_common_init(model); device_add(&sis_85c471_device); device_add(&ide_isa_device); device_add_params(&fdc37c6xx_device, (void *) (FDC37C651 | FDC37C6XX_IDE_PRI)); diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 6602f2aed..a77b9b992 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -50,7 +50,7 @@ machine_at_s370slm_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -85,7 +85,7 @@ machine_at_awo671r_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -120,7 +120,7 @@ machine_at_ambx133_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -156,7 +156,7 @@ machine_at_cubx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -194,7 +194,7 @@ machine_at_63a1_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -227,7 +227,7 @@ machine_at_7sbb_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -256,7 +256,7 @@ machine_at_atc7020bxii_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -288,7 +288,7 @@ machine_at_m773_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -329,7 +329,7 @@ machine_at_apas3_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -361,7 +361,7 @@ machine_at_p6bap_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -397,7 +397,7 @@ machine_at_6via90ap_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -435,7 +435,7 @@ machine_at_cuv4xls_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -565,7 +565,7 @@ machine_at_ms6318_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -602,7 +602,7 @@ machine_at_cairo5_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_socket3_pci.c b/src/machine/m_at_socket3_pci.c index a8b0f8eea..fecf77c41 100644 --- a/src/machine/m_at_socket3_pci.c +++ b/src/machine/m_at_socket3_pci.c @@ -350,7 +350,7 @@ machine_at_pc330_6573_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&ide_vlb_2ch_device); pci_init(PCI_CONFIG_TYPE_1); @@ -458,7 +458,7 @@ machine_at_pb450_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); device_add(&ide_vlb_2ch_device); pci_init(PCI_CONFIG_TYPE_1); @@ -582,8 +582,7 @@ machine_at_ninja_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -707,9 +706,8 @@ machine_at_alfredo_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); - device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); @@ -881,8 +879,7 @@ machine_at_pci400cb_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&ami_1994_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -929,7 +926,7 @@ machine_at_acerp3_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_device); @@ -963,7 +960,7 @@ machine_at_486sp3c_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_device); @@ -991,7 +988,7 @@ machine_at_ls486e_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_ls486e_device); @@ -1018,7 +1015,7 @@ machine_at_m4li_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_device); @@ -1045,7 +1042,7 @@ machine_at_ms4144_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_ls486e_device); @@ -1073,7 +1070,7 @@ machine_at_r418_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_device); @@ -1100,7 +1097,7 @@ machine_at_4saw2_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_device); @@ -1129,7 +1126,7 @@ machine_at_4dps_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_sis_85c496_common_init(model); device_add(&sis_85c496_device); @@ -1471,11 +1468,8 @@ machine_at_hot433a_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); - if (is_award) - device_add(&amstrad_megapc_nvr_device); - else - device_add(&ami_1994_nvr_device); + machine_at_common_init(model); + device_add_params(&nvr_at_device, (void *) (uintptr_t) (is_award ? (NVR_AT_ZERO_DEFAULT) : (NVR_AMI_1994))); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 991ff9cab..4dc5a89fc 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -254,9 +254,8 @@ machine_at_opti560l_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); - device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); @@ -434,9 +433,8 @@ machine_at_batman_init(const machine_t *model) } device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); - device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); @@ -466,9 +464,8 @@ machine_at_batman_init(const machine_t *model) void machine_at_premiere_common_init(const machine_t *model, int pci_switch) { - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); - device_add(&amstrad_megapc_nvr_device); device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2 | pci_switch); @@ -669,8 +666,7 @@ machine_at_excaliburpci2_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&ami_1994_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index 573f8bb71..2a2365ec7 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -83,7 +83,7 @@ machine_at_celebris5xx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index adfdfbacd..a25ce383a 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -371,8 +371,7 @@ machine_at_apollo_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&ami_1995_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -402,8 +401,7 @@ machine_at_optiplexgxl_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); @@ -428,6 +426,91 @@ machine_at_optiplexgxl_init(const machine_t *model) return ret; } +static const device_config_t pt2000_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "pt2000", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "Award Modular BIOS v4.50GP - Revision T1.01", + .internal_name = "pt2000", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 131072, + .files = { "roms/machines/ficpt2000/PT2000_v1.01.BIN", "" } + }, + { + .name = "Award Modular BIOS v4.51PG - Revision 3.072C806", + .internal_name = "pt2000_451pg", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 131072, + .files = { "roms/machines/ficpt2000/3072c806.bin", "" } + }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t pt2000_device = { + .name = "FIC PT-2000", + .internal_name = "pt2000_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pt2000_config +}; + +int +machine_at_pt2000_init(const machine_t *model) +{ + int ret = 0; + const char *fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add(&i430fx_device); + device_add(&piix_device); + device_add_params(&pc873xx_device, (void *) (PC87332 | PCX730X_398)); + device_add(&intel_flash_bxt_device); + + return ret; +} + static void machine_at_morrison32_gpio_init(void) { @@ -476,7 +559,7 @@ machine_at_morrison32_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_morrison32_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -571,7 +654,7 @@ machine_at_pc330_65x6_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_morrison64_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -625,91 +708,6 @@ machine_at_zappa_gpio_init(void) machine_set_gpio_default(gpio); } -static const device_config_t pt2000_config[] = { - // clang-format off - { - .name = "bios", - .description = "BIOS Version", - .type = CONFIG_BIOS, - .default_string = "pt2000", - .default_int = 0, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { { 0 } }, - .bios = { - { - .name = "Award Modular BIOS v4.50GP - Revision T1.01", - .internal_name = "pt2000", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 131072, - .files = { "roms/machines/ficpt2000/PT2000_v1.01.BIN", "" } - }, - { - .name = "Award Modular BIOS v4.51PG - Revision 3.072C806", - .internal_name = "pt2000_451pg", - .bios_type = BIOS_NORMAL, - .files_no = 1, - .local = 0, - .size = 131072, - .files = { "roms/machines/ficpt2000/3072c806.bin", "" } - }, - { .files_no = 0 } - }, - }, - { .name = "", .description = "", .type = CONFIG_END } - // clang-format on -}; - -const device_t pt2000_device = { - .name = "FIC PT-2000", - .internal_name = "pt2000_device", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - .available = NULL, - .speed_changed = NULL, - .force_redraw = NULL, - .config = pt2000_config -}; - -int -machine_at_pt2000_init(const machine_t *model) -{ - int ret = 0; - const char *fn; - - /* No ROMs available */ - if (!device_available(model->device)) - return ret; - - device_context(model->device); - fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); - ret = bios_load_linear(fn, 0x000e0000, 131072, 0); - device_context_restore(); - - machine_at_common_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - - device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); - device_add(&i430fx_device); - device_add(&piix_device); - device_add_params(&pc873xx_device, (void *) (PC87332 | PCX730X_398)); - device_add(&intel_flash_bxt_device); - - return ret; -} - static const device_config_t zappa_config[] = { // clang-format off { @@ -778,7 +776,7 @@ machine_at_zappa_init(const machine_t *model) ret = bios_load_linear_combined(fn, fn2, 0x20000, 128); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_zappa_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -894,8 +892,7 @@ machine_at_hawk_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&ami_1994_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1088,8 +1085,7 @@ machine_at_ms5109_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&ami_1994_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1121,8 +1117,7 @@ machine_at_torino_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&ami_1994_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1189,7 +1184,7 @@ machine_at_bravoms586_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1216,36 +1211,6 @@ machine_at_bravoms586_init(const machine_t *model) return ret; } -int -machine_at_g586vpmc_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/g586vpmc/Vpm_c3.bin", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x02, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x08, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_IDE, 0, 0, 0, 0); - - device_add(&vl82c59x_device); - device_add(&sst_flash_29ee010_device); - device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); - device_add_params(&pc873xx_device, (void *) (PC87332 | PCX730X_398)); - device_add(&ide_cmd646_device); - return ret; -} - int machine_at_m54si_init(const machine_t *model) { @@ -1257,7 +1222,7 @@ machine_at_m54si_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1288,7 +1253,7 @@ machine_at_pb600_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1324,7 +1289,7 @@ machine_at_globalyst620_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1346,3 +1311,33 @@ machine_at_globalyst620_init(const machine_t *model) return ret; } + +int +machine_at_g586vpmc_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/g586vpmc/Vpm_c3.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x08, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_IDE, 0, 0, 0, 0); + + device_add(&vl82c59x_wildcat_device); + device_add(&sst_flash_29ee010_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add_params(&pc873xx_device, (void *) (PC87332 | PCX730X_398)); + device_add(&ide_cmd646_device); + return ret; +} diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 24b0b9e84..d90a4e113 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -55,7 +55,7 @@ machine_at_acerm3a_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -190,7 +190,7 @@ machine_at_rubyusb_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_rubyusb_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -326,7 +326,7 @@ machine_at_cu430hx_init(const machine_t *model) ret = bios_load_linear_combined2(fn[0], fn[1], fn[2], fn[3], fn[4], 0x3a000, 128); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_cu430hx_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -452,7 +452,7 @@ machine_at_tc430hx_init(const machine_t *model) ret = bios_load_linear_combined2(fn[0], fn[1], fn[2], fn[3], fn[4], 0x3a000, 128); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_tc430hx_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -544,7 +544,7 @@ machine_at_m7shi_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); @@ -573,8 +573,7 @@ machine_at_epc2102_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add_params(&at_nvr_device, (void *) 0x20); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -613,7 +612,7 @@ machine_at_pcv90_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_ag430hx_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -647,7 +646,7 @@ machine_at_p55t2s_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -801,7 +800,7 @@ machine_at_presario2240_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -831,7 +830,7 @@ machine_at_presario4500_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -865,7 +864,7 @@ machine_at_dellhannibalp_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -980,7 +979,7 @@ machine_at_p55va_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1013,7 +1012,7 @@ machine_at_gw2kte_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1046,7 +1045,7 @@ machine_at_brio80xx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); @@ -1168,7 +1167,7 @@ machine_at_pb680_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_nv430vx_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -1201,7 +1200,7 @@ machine_at_pb810_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1293,7 +1292,7 @@ machine_at_nupro592_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1333,7 +1332,7 @@ machine_at_tx97_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1383,7 +1382,7 @@ machine_at_optiplexgn_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); @@ -1421,7 +1420,7 @@ machine_at_tomahawk_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1463,7 +1462,7 @@ machine_at_ym430tx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1495,7 +1494,7 @@ machine_at_tx97xv_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); @@ -1648,7 +1647,7 @@ machine_at_ms5156_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1684,7 +1683,7 @@ machine_at_ma23c_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1775,7 +1774,7 @@ machine_at_an430tx_init(const machine_t *model) ret = bios_load_linear_combined2(fn[0], fn[1], fn[2], fn[3], fn[4], 0x3a000, 160); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1814,7 +1813,7 @@ machine_at_mb540n_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1845,7 +1844,7 @@ machine_at_56a5_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1877,7 +1876,7 @@ machine_at_p5mms98_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1910,7 +1909,7 @@ machine_at_richmond_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1944,7 +1943,7 @@ machine_at_ficva502_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1975,7 +1974,7 @@ machine_at_ficpa2012_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2006,7 +2005,7 @@ machine_at_via809ds_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2038,7 +2037,7 @@ machine_at_cb52xsi_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2121,7 +2120,7 @@ machine_at_ms5146_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2204,7 +2203,7 @@ machine_at_r534f_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2233,7 +2232,7 @@ machine_at_sp97xv_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2262,7 +2261,7 @@ machine_at_sq578_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2290,7 +2289,7 @@ machine_at_ms5172_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2374,7 +2373,7 @@ machine_at_m5ata_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); @@ -2403,7 +2402,7 @@ machine_at_ms5164_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -2436,7 +2435,7 @@ machine_at_m560_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index a1ea76940..41bb1406c 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -204,7 +204,7 @@ machine_at_holly_init(const machine_t *model) /* HP Pavilion Holly, 7070/7090/51 if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_holly_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -228,6 +228,38 @@ machine_at_holly_init(const machine_t *model) /* HP Pavilion Holly, 7070/7090/51 return ret; } +int +machine_at_vectra500mt_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/vectra500mt/GJ0718.FUL", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add_params(&fdc37c93x_device, (void *) (FDC37XXX2 | FDC37C93X_NORMAL)); + device_add(&sst_flash_29ee010_device); + + return ret; +} + static void machine_at_vectra52_gpio_init(void) { @@ -308,7 +340,7 @@ const device_t vectra52_device = { int machine_at_vectra52_init(const machine_t *model) { - int ret = 0; + int ret = 0; const char *fn; /* No ROMs available */ @@ -320,8 +352,8 @@ machine_at_vectra52_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); - machine_at_vectra52_gpio_init(); + machine_at_common_init(model); + machine_at_vectra52_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -335,40 +367,9 @@ machine_at_vectra52_init(const machine_t *model) device_add_params(&pc87306_device, (void *) PCX730X_PHOENIX_42); device_add(&intel_flash_bxt_device); - if (gfxcard[0] == VID_INTERNAL) - device_add(machine_get_vid_device(machine)); - - return ret; -} -int -machine_at_vectra500mt_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/vectra500mt/GJ0718.FUL", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_VIDEO, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); - if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); - device_add(&i430fx_device); - device_add(&piix_device); - device_add_params(&fdc37c93x_device, (void *) (FDC37XXX2 | FDC37C93X_NORMAL)); - device_add(&sst_flash_29ee010_device); - return ret; } @@ -383,7 +384,7 @@ machine_at_vectra54_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -404,6 +405,80 @@ machine_at_vectra54_init(const machine_t *model) return ret; } +static void +machine_at_atlantis_gpio_init(void) +{ + uint32_t gpio = 0xffffe0cf; + + /* Register 0x0079: */ + /* Bit 7: 0 = Clear password, 1 = Keep password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ + /* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */ + /* Bit 0: 0 = 2x multiplier, 1 = 1.5x multiplier (Switch 6). */ + /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ + if (cpu_busspeed <= 50000000) + gpio |= 0xffff0000; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0xffff0800; + else if (cpu_busspeed > 60000000) + gpio |= 0xffff1000; + + if (sound_card_current[0] == SOUND_INTERNAL) + gpio |= 0xffff0400; + + if (cpu_dmulti <= 1.5) + gpio |= 0xffff0100; + else + gpio |= 0xffff0000; + + machine_set_gpio_default(gpio); +} + +int +machine_at_atlantis_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/atlantis/1007CL0_.BIO", + "roms/machines/atlantis/1007CL0_.BI1", + 0x20000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + machine_at_atlantis_gpio_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + if (sound_card_current[0] == SOUND_INTERNAL) + machine_snd = device_add(machine_get_snd_device(machine)); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add_params(&pc87306_device, (void *) PCX730X_AMI); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + static const device_config_t thor_config[] = { // clang-format off { @@ -535,7 +610,7 @@ machine_at_thor_init(const machine_t *model) } device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_thor_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -648,58 +723,6 @@ machine_at_endeavor_gpio_handler(uint8_t write, uint32_t val) return ret; } -static void -machine_at_monaco_gpio_init(void) -{ - uint32_t gpio = 0xffffe0cf; - - /* Register 0x0079: */ - /* Bit 7: 0 = Clear password, 1 = Keep password. */ - /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ - /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ - /* Bit 4: External CPU clock (Switch 8). */ - /* Bit 3: External CPU clock (Switch 7). */ - /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ - /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ - /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ - /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ - /* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */ - /* Bit 0: 0 = 2x multiplier, 1 = 1.5x multiplier (Switch 6). */ - /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ - if (cpu_busspeed <= 50000000) - gpio |= 0xffff0000; - else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - gpio |= 0xffff0800; - else if (cpu_busspeed > 60000000) - gpio |= 0xffff1000; - - if (sound_card_current[0] == SOUND_INTERNAL) - gpio |= 0xffff0400; - - if (cpu_dmulti <= 1.5) - gpio |= 0xffff0100; - else - gpio |= 0xffff0000; - - machine_set_gpio_default(gpio); -} - -uint32_t -machine_at_monaco_gpio_handler(uint8_t write, uint32_t val) -{ - uint32_t ret = machine_get_gpio_default(); - - if (write) { - ret &= ((val & 0xffffffcf) | 0xffff0000); - ret |= (val & 0x00000030); - - machine_set_gpio(ret); - } else - ret = machine_get_gpio(); - - return ret; -} - int machine_at_endeavor_init(const machine_t *model) { @@ -712,7 +735,7 @@ machine_at_endeavor_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_endeavor_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -739,45 +762,7 @@ machine_at_endeavor_init(const machine_t *model) } /* The Monaco and Atlantis share the same GPIO config */ -#define machine_at_atlantis_gpio_init machine_at_monaco_gpio_init - -int -machine_at_atlantis_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear_combined("roms/machines/atlantis/1007CL0_.BIO", - "roms/machines/atlantis/1007CL0_.BI1", - 0x20000, 128); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - machine_at_atlantis_gpio_init(); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); - - if (gfxcard[0] == VID_INTERNAL) - device_add(machine_get_vid_device(machine)); - - if (sound_card_current[0] == SOUND_INTERNAL) - machine_snd = device_add(machine_get_snd_device(machine)); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add_params(&pc87306_device, (void *) PCX730X_AMI); - device_add(&intel_flash_bxt_ami_device); - - return ret; -} +#define machine_at_monaco_gpio_init machine_at_atlantis_gpio_init static const device_config_t monaco_config[] = { // clang-format off @@ -830,6 +815,22 @@ const device_t monaco_device = { .config = monaco_config }; +uint32_t +machine_at_monaco_gpio_handler(uint8_t write, uint32_t val) +{ + uint32_t ret = machine_get_gpio_default(); + + if (write) { + ret &= ((val & 0xffffffcf) | 0xffff0000); + ret |= (val & 0x00000030); + + machine_set_gpio(ret); + } else + ret = machine_get_gpio(); + + return ret; +} + int machine_at_monaco_init(const machine_t *model) { @@ -847,7 +848,7 @@ machine_at_monaco_init(const machine_t *model) ret = bios_load_linear_combined(fn, fn2, 0x20000, 128); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_monaco_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -999,7 +1000,7 @@ machine_at_pb640_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); machine_at_pb640_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); @@ -1148,7 +1149,7 @@ machine_at_acerv35n_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1313,8 +1314,7 @@ machine_at_d943_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); - device_add(&amstrad_megapc_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1356,7 +1356,7 @@ machine_at_gw2kma_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1456,7 +1456,7 @@ machine_at_5sbm2_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1485,7 +1485,7 @@ machine_at_amis727_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1578,7 +1578,7 @@ machine_at_ap5s_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1607,7 +1607,7 @@ machine_at_fm562_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); @@ -1638,7 +1638,7 @@ machine_at_pc140_6260_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); @@ -1724,7 +1724,7 @@ machine_at_ms5124_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1754,7 +1754,7 @@ machine_at_zeoswildcat_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 11fbcd694..b79a057af 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -72,6 +72,7 @@ machine_at_ap61_init(const machine_t *model) return ret; } +/* i450GX */ int machine_at_p6rp4_init(const machine_t *model) { @@ -83,8 +84,7 @@ machine_at_p6rp4_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); - device_add(&p6rp4_nvr_device); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x19, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -173,7 +173,7 @@ machine_at_ficpo6000_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x19, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -207,7 +207,7 @@ machine_at_acerv60n_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -496,7 +496,7 @@ machine_at_m6mi_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 725874a07..a87b889e7 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -50,7 +50,7 @@ machine_at_p5a_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -86,7 +86,7 @@ machine_at_m579_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -118,7 +118,7 @@ machine_at_gwlucas_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -156,7 +156,7 @@ machine_at_5aa_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -243,7 +243,7 @@ machine_at_g5x_init(const machine_t *model) ret = bios_load_linear(fn, 0x000e0000, 131072, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -278,7 +278,7 @@ machine_at_ax59pro_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -364,7 +364,7 @@ machine_at_delhi3_init(const machine_t *model) ret = bios_load_linear(fn, 0x000c0000, 262144, 0); device_context_restore(); - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -395,7 +395,7 @@ machine_at_mvp3_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -425,7 +425,7 @@ machine_at_ficva503a_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -461,7 +461,7 @@ machine_at_5emapro_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -496,7 +496,7 @@ machine_at_k6bv3p_a_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 5); @@ -528,7 +528,7 @@ machine_at_5sg100_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init_ex(model, 2); + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c index 1f440bad2..c0d0b9945 100644 --- a/src/machine/m_elt.c +++ b/src/machine/m_elt.c @@ -191,7 +191,7 @@ machine_elt_init(const machine_t *model) * indicate the correct display type */ device_add(&kbc_xt_device); - device_add(&elt_nvr_device); + device_add_params(model->nvr_device, (void *) model->nvr_params); io_sethandler(0x11b8, 1, sysstat_in, NULL, NULL, sysstat_out, NULL, NULL, cga); diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index b37abdaa8..895713cb1 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -444,8 +444,6 @@ ps1_setup(int model) device_add(&ps1snd_device); } - - device_add(&ps_nvr_device); } static void diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index ec3a53894..248a141d5 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -229,8 +229,6 @@ ps2_isa_setup(int model, int cpu_type) mem_remap_top(384); - device_add(&ps_nvr_device); - device_add(&fdc_ps2_device); /* Enable the builtin HDC. */ diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index f02dd265a..b0d13adaa 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1636,7 +1636,6 @@ machine_ps2_common_init(const machine_t *model) dma16_init(); ps2_dma_init(); - device_add(&ps_no_nmi_nvr_device); pic2_init(); int pit_type = ((pit_mode == -1 && is486) || pit_mode == 1) ? PIT_8254_FAST : PIT_8254; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 3e1c78a03..c3904d7ec 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -2082,8 +2082,6 @@ machine_xt_tuliptc8_init(const machine_t *model) nmi_init(); standalone_gameport_type = &gameport_200_device; - device_add(&amstrad_megapc_nvr_device); - return ret; } @@ -2134,8 +2132,6 @@ machine_xt_pc5086_init(const machine_t *model) device_add(&kbc_xt_device); - device_add(&amstrad_megapc_nvr_device); /* NVR that is initialized to all 0x00's. */ - return ret; } diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index 729cf48d5..3c270bba8 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -207,7 +207,6 @@ machine_xt_xi8088_init(const machine_t *model) device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); device_add(&port_6x_xi8088_device); nmi_init(); - device_add(&ibmat_nvr_device); pic2_init(); standalone_gameport_type = &gameport_200_device; device_add(&sst_flash_39sf010_device); diff --git a/src/machine/machine.c b/src/machine/machine.c index 2db543cf2..e11e9f901 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -117,6 +117,9 @@ machine_init_ex(int m) cpu_fast_off_reset(); pci_flags = 0x00000000; + + if (machines[m].nvr_device) + device_add_params(machines[m].nvr_device, (void *) (uintptr_t) machines[m].nvr_params); } is_pcjr = 0; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 276653ffe..2b8a41f83 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -30,6 +30,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/keyboard.h> +#include <86box/nvr.h> #include <86box/sio.h> #include <86box/sound.h> #include <86box/video.h> @@ -225,13 +226,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ibmpc_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -268,13 +272,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc82_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ibmpc82_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -311,13 +318,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, /* TODO: No specific kbd_device yet */ .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = &fdc_pcjr_device, - .sio_device = NULL, .vid_device = &pcjr_device, .snd_device = NULL, .net_device = NULL @@ -354,13 +364,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ibmxt_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -397,13 +410,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt86_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ibmxt86_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -440,13 +456,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -483,13 +502,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -526,13 +548,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -569,13 +594,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -612,13 +640,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc82_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -655,13 +686,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_compaq_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_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 @@ -698,13 +732,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &dtk_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -741,13 +778,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc82_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -784,13 +824,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -827,13 +870,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -870,13 +916,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = &fdc_xt_device, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -913,13 +962,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = &fdc_xt_device, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -956,13 +1008,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = &fdc_xt_device, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -999,13 +1054,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &jukopc_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1042,13 +1100,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1085,13 +1146,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1128,13 +1192,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc82_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pc500_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1171,13 +1238,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pc500plus_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1214,13 +1284,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc82_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pc700_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1257,13 +1330,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1300,13 +1376,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_olivetti_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &m19_vid_device, .snd_device = NULL, .net_device = NULL @@ -1343,13 +1422,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1386,13 +1468,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1429,13 +1514,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1472,13 +1560,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pravetz_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1515,13 +1606,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1558,13 +1652,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1601,13 +1698,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = &fdc_xt_device, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1644,13 +1744,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_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 @@ -1687,13 +1790,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1730,13 +1836,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_tandy_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &tandy_1000_video_device, .snd_device = NULL, .net_device = NULL @@ -1773,13 +1882,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_tandy_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &tandy_1000hx_video_device, .snd_device = NULL, .net_device = NULL @@ -1816,13 +1928,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &to16_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1859,13 +1974,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_t1x00_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &t1000_video_device, .snd_device = NULL, .net_device = NULL @@ -1902,13 +2020,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &vendex_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = &fdc_xt_device, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1945,13 +2066,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &laserxt_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -1988,13 +2112,16 @@ const machine_t machines[] = { .jumpered_ecp_dma = 0, .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00400cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &xi8088_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2031,13 +2158,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2074,13 +2204,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_zenith_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2117,13 +2250,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_zenith_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2160,13 +2296,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_zenith_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &v6355d_device, .snd_device = NULL, .net_device = NULL @@ -2203,13 +2342,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_pc_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2246,13 +2388,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2289,13 +2434,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2334,13 +2482,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMSTRAD, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &vid_1512_device, .snd_device = NULL, .net_device = NULL @@ -2377,13 +2528,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMSTRAD, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &vid_1640_device, .snd_device = NULL, .net_device = NULL @@ -2420,13 +2574,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMSTRAD, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &vid_pc2086_device, .snd_device = NULL, .net_device = NULL @@ -2463,13 +2620,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMSTRAD, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &vid_pc3086_device, .snd_device = NULL, .net_device = NULL @@ -2506,13 +2666,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &f82c710_pc5086_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2549,13 +2712,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMSTRAD_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &vid_200_device, .snd_device = NULL, .net_device = NULL @@ -2592,13 +2758,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMSTRAD_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &vid_ppc512_device, .snd_device = NULL, .net_device = NULL @@ -2635,13 +2804,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_compaq_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2678,13 +2850,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_ELT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, /* Discrete onboard video card? */ .snd_device = NULL, .net_device = NULL @@ -2721,13 +2896,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ibm5550_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2763,13 +2941,16 @@ const machine_t machines[] = { .jumpered_ecp_dma = 0, .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2806,13 +2987,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &ogc_m24_device, .snd_device = NULL, .net_device = NULL @@ -2850,13 +3034,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_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 @@ -2893,13 +3080,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xtclone_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -2936,13 +3126,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL /* TODO: No specific kbd_device yet */, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &tandy_1000sl_video_device, .snd_device = NULL, .net_device = NULL @@ -2979,13 +3172,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_t1x00_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &t1200_video_device, .snd_device = NULL, .net_device = NULL @@ -3022,13 +3218,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &v86p_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3065,13 +3264,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_xt_lxt3_device, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &lxt3_device, .kbd_device = &keyboard_pc_xt_device, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3111,13 +3313,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ibmat_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3155,13 +3360,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ps1_2011_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3199,13 +3407,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ps2_m30_286_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3243,13 +3454,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ibmxt286_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3288,13 +3502,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3332,13 +3549,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3376,13 +3596,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &compaq_plasma_device, .snd_device = NULL, .net_device = NULL @@ -3419,13 +3642,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3463,13 +3689,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pc900_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3507,13 +3736,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3551,13 +3783,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_NCR, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004df, .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 @@ -3595,13 +3830,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_OLIVETTI, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3640,13 +3878,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3684,13 +3925,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3728,13 +3972,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_QUADTEL, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3772,13 +4019,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3817,13 +4067,16 @@ const machine_t machines[] = { .kbc_device = &kbc_at_device, /* The version number is a guess - we have no probe of this machine's controller. */ .kbc_params = KBC_VEN_PHOENIX | 0x00010500, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3861,13 +4114,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_SIEMENS, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -3905,13 +4161,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_TOSHIBA, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x0000bfff, .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 @@ -3949,12 +4208,15 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00003800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -3993,13 +4255,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4037,12 +4302,15 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AWARD | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -4081,13 +4349,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4126,13 +4397,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4170,13 +4444,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_CHIPS | 0x0000a600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4214,13 +4491,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_QUADTEL, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4258,13 +4538,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004200, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4303,12 +4586,15 @@ const machine_t machines[] = { .kbc_device = &kbc_at_device, /* The version number is a guess - we have no probe of this machine's controller. */ .kbc_params = KBC_VEN_PHOENIX | 0x00010500, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -4346,13 +4632,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_CHIPS | 0x0000a600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4390,13 +4679,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4434,17 +4726,68 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_NCR, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004df, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = ¶dise_pvga1a_ncr3302_device, .snd_device = NULL, .net_device = NULL }, + /* Has unknown keyboard controller. */ + { + .name = "[NEAT] Nixdorf 8810 M30", + .internal_name = "n8810m30", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_n8810m30_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_AT, + /* Has SCSI chip WD33C93AJM, which is not yet emulated. */ + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .jumpered_ecp_dma = 0, + .default_jumpered_ecp_dma = -1, + .kbc_device = &kbc_at_device, + .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, + .kbc_p1 = 0x000004f0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the VLSI 82C113 with on-chip KBC. */ { .name = "[SCAMP] Amstrad PC7286", @@ -4478,13 +4821,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5401_onboard_device, .snd_device = NULL, .net_device = NULL @@ -4522,13 +4868,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &f82c710_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -4566,13 +4915,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_CHIPS | 0x0000a600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &f82c710_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -4612,13 +4964,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -4656,13 +5011,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4700,13 +5058,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -4743,13 +5104,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5401_onboard_device, .snd_device = NULL, .net_device = NULL @@ -4787,13 +5151,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -4832,13 +5199,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -4876,13 +5246,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -4920,13 +5293,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &ati28800k_spc4620p_device, .snd_device = NULL, .net_device = NULL @@ -4964,13 +5340,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00003800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5009,13 +5388,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM | KBC_FLAG_IS_TYPE2, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ps2_model_50_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -5053,13 +5435,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM | KBC_FLAG_IS_TYPE2, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -5100,12 +5485,15 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -5143,13 +5531,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_NCR, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004df, .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 @@ -5187,13 +5578,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_QUADTEL, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5232,13 +5626,16 @@ const machine_t machines[] = { .kbc_device = &kbc_at_device, /* The version number is a guess - we have no probe of this machine's controller. */ .kbc_params = KBC_VEN_PHOENIX | 0x00010500, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pbl300sx_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &oti037_pbl300sx_device, .snd_device = NULL, .net_device = NULL @@ -5277,13 +5674,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5321,13 +5721,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -5365,13 +5768,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00003800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &c325ax_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -5409,13 +5815,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &tvga8900d_device, /* Onboard variant not yet emulated */ .snd_device = NULL, .net_device = NULL @@ -5454,13 +5863,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ACER, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x004008f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &oti077_acer100t_device, .snd_device = NULL, .net_device = NULL @@ -5500,13 +5912,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &oti067_ama932j_device, .snd_device = NULL, .net_device = NULL @@ -5544,13 +5959,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5402_onboard_device, .snd_device = NULL, .net_device = NULL @@ -5588,13 +6006,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00010500, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5631,13 +6052,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004400, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5677,13 +6101,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -5721,6 +6148,56 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, + .kbc_p1 = 0x000004f0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[NEAT] Philips P3345", + .internal_name = "p3345", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_p3345_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_AT, + .flags = MACHINE_IDE, + .ram = { + .min = 2048, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .jumpered_ecp_dma = 0, + .default_jumpered_ecp_dma = -1, + .kbc_device = &kbc_at_device, + .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, @@ -5732,7 +6209,8 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - { .name = "[NEATsx] OKI if386AX30L", + { + .name = "[NEATsx] OKI if386AX30L", .internal_name = "if386sx", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_NEAT_SX, @@ -5764,13 +6242,16 @@ const machine_t machines[] = { .kbc_device = &kbc_at_device, /* The version number is a guess - we have no probe of this machine's controller. */ .kbc_params = KBC_VEN_PHOENIX | 0x00010500, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &if386jega_device, .snd_device = NULL, .net_device = NULL @@ -5808,13 +6289,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00003800, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5852,13 +6336,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5898,13 +6385,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, /* The keyboard controller is part of the VL82c113. */ .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5402_onboard_commodore_device, .snd_device = NULL, .net_device = NULL @@ -5944,13 +6434,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004400, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -5989,13 +6482,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00002020, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &dells333sl_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5420_onboard_device, .snd_device = NULL, .net_device = NULL @@ -6034,13 +6530,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, /* Possibly. */ .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &ati28800k_spc6033p_device, .snd_device = NULL, .net_device = NULL @@ -6079,13 +6578,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, /* Possibly. */ .kbc_params = KBC_VEN_AMI | 0x00004600, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6123,13 +6625,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_QUADTEL, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = ¶dise_wd90c11_megapc_device, .snd_device = NULL, .net_device = NULL @@ -6169,13 +6674,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -6211,12 +6719,15 @@ const machine_t machines[] = { .nvrmask = 63, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -6256,13 +6767,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -6300,13 +6814,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -6347,13 +6864,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6393,13 +6913,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_COMPAQ, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000000f4, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &deskpro386_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -6437,13 +6960,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_COMPAQ, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000000f4, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &compaq_plasma_device, .snd_device = NULL, .net_device = NULL @@ -6481,13 +7007,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6525,13 +7054,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6570,13 +7102,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6614,6 +7149,10 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, /* TODO: Lance LT38C41. */ .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, @@ -6655,13 +7194,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00003800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6699,13 +7241,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AWARD | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6744,13 +7289,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6788,13 +7336,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | KBC_FLAG_IS_CLONE | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &dataexpert386wb_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -6834,13 +7385,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6878,13 +7432,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AWARD | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6922,13 +7479,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -6968,13 +7528,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -7012,13 +7575,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -7058,13 +7624,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7102,13 +7671,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_SIEMENS, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7147,13 +7719,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004d00, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &opti495_ami_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -7191,13 +7766,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -7235,13 +7813,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -7279,13 +7860,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -7326,13 +7910,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7370,13 +7957,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7414,13 +8004,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7459,13 +8052,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7503,13 +8099,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7548,13 +8147,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7592,13 +8194,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7636,13 +8241,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5424_onboard_device, .snd_device = NULL, .net_device = NULL @@ -7680,13 +8288,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7728,13 +8339,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -7772,13 +8386,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, /* The keyboard controller is part of the VL82c113. */ .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ .vid_device = &gd5426_onboard_isa_device, .snd_device = NULL, .net_device = NULL @@ -7816,13 +8433,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5428_onboard_device, .snd_device = NULL, .net_device = NULL @@ -7860,13 +8480,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &oti077_pcs44c_device, .snd_device = NULL, .net_device = NULL @@ -7904,13 +8527,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &sensationaud_device, .net_device = NULL @@ -7948,13 +8574,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ + /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ .vid_device = &gd5426_onboard_device, .snd_device = NULL, .net_device = NULL @@ -7992,13 +8622,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AWARD | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8036,13 +8669,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8080,13 +8716,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_IBM, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_PS_NO_NMI, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -8127,13 +8766,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900 /* Guess. */, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &ht216_32_pb410a_device, .snd_device = NULL, .net_device = NULL @@ -8171,13 +8813,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ACER, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x004008f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5428_onboard_device, .snd_device = NULL, .net_device = NULL @@ -8215,13 +8860,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8260,13 +8908,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8304,13 +8955,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -8348,13 +9002,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMI_1992, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8392,13 +9049,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5428_vlb_onboard_device, .snd_device = NULL, .net_device = NULL @@ -8436,13 +9096,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8480,13 +9143,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_86c805_onboard_vlb_device, .snd_device = NULL, .net_device = NULL @@ -8524,13 +9190,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00002420, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5428_onboard_vlb_device, .snd_device = NULL, .net_device = NULL @@ -8569,13 +9238,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &et4000w32_onboard_device, .snd_device = NULL, .net_device = NULL @@ -8613,13 +9285,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000ce0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5428_onboard_vlb_device, .snd_device = NULL, .net_device = NULL @@ -8657,13 +9332,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8701,13 +9379,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5428_vlb_onboard_tandy_device, .snd_device = NULL, .net_device = NULL @@ -8748,13 +9429,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | KBC_FLAG_IS_CLONE | KBC_FLAG_IS_ASIC | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -8792,13 +9476,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -8837,13 +9524,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMI_1994, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -8881,13 +9571,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8925,13 +9618,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -8969,13 +9665,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9013,13 +9712,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + /* TODO: Per-BIOS NVR parameters. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &j403tg_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -9058,13 +9761,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ACER, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x004008f0, .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 @@ -9104,13 +9810,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9148,13 +9857,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | KBC_FLAG_IS_CLONE | KBC_FLAG_IS_ASIC | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9192,13 +9904,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9236,13 +9951,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9280,13 +9998,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 4, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio32_onboard_vlb_device, .snd_device = NULL, .net_device = NULL @@ -9324,13 +10045,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | KBC_FLAG_IS_CLONE | KBC_FLAG_IS_ASIC | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9368,13 +10092,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | KBC_FLAG_IS_CLONE | KBC_FLAG_IS_ASIC | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9412,13 +10139,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9456,13 +10186,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI_TRIGEM | 0x00005a00, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9504,13 +10237,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9548,13 +10284,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI_TRIGEM | 0x00005a00, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9592,13 +10331,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &tgui9440_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -9637,13 +10379,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ALI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9681,13 +10426,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00014000, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9729,13 +10477,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00005500, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9773,13 +10524,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00014000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9821,13 +10575,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ALI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -9865,13 +10622,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9909,13 +10669,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9953,13 +10716,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -9997,13 +10763,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 4, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10041,13 +10810,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005200, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10085,13 +10857,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10132,13 +10907,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10176,13 +10954,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000ce0, .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 @@ -10221,13 +11002,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10266,13 +11050,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &sb486pv_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5436_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -10310,13 +11097,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005000, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10354,13 +11144,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pc330_6573_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5430_onboard_vlb_device, .snd_device = NULL, .net_device = NULL @@ -10398,13 +11191,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pb450_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5428_vlb_onboard_device, .snd_device = NULL, .net_device = NULL @@ -10442,13 +11238,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ACER | 0x00004200, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x004008f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5434_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -10486,13 +11285,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10530,13 +11332,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10574,13 +11379,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10618,13 +11426,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -10663,13 +11474,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10708,13 +11522,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10753,13 +11570,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10797,13 +11617,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, /* UMC UM8886 on-chip KBC. */ .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -10842,13 +11665,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10887,13 +11713,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5430_onboard_pci_device, .snd_device = &ess_1688_device, /* Onboard variant not yet emulated */ .net_device = NULL @@ -10931,13 +11760,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -10975,13 +11807,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI_TRIGEM | 0x00005a00, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &tgui9440_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -11020,13 +11855,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI_TRIGEM | 0x00005a00, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5430_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -11065,13 +11903,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, /* UMC UM8886 on-chip KBC. */ .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -11109,13 +11950,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, /* UMC UM8886 on-chip KBC. */ .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11153,13 +11997,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + /* TODO: Per-BIOS NVR parameters. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &hot433a_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -11197,13 +12045,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11241,13 +12092,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11289,13 +12143,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11334,13 +12191,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11379,13 +12239,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11424,13 +12287,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11469,13 +12335,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11514,13 +12383,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11561,13 +12433,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ACER | 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x004008f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &v12p_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -11609,13 +12484,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11653,13 +12531,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &p5mp3_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -11697,13 +12578,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11741,13 +12625,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -11785,13 +12672,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &mach32_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -11829,13 +12719,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00001030, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &batman_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -11873,13 +12766,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11917,13 +12813,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -11961,13 +12860,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5434_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -12009,13 +12911,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005000, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -12055,13 +12960,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -12099,13 +13007,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -12145,13 +13056,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005200, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMI_1994, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -12189,13 +13103,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -12233,13 +13150,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -12280,13 +13200,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -12325,13 +13248,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_vision864_pci_device, /* Onboard variant not yet emulated */ .snd_device = NULL, .net_device = NULL @@ -12372,13 +13298,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -12416,13 +13345,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -12460,13 +13392,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00001030, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &plato_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -12504,13 +13439,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &d842_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -12548,13 +13486,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005200, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -12594,13 +13535,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_ACER | 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x004008f0, .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 @@ -12638,13 +13582,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMI_1995, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -12682,13 +13629,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, .snd_device = &sb_vibra16s_onboard_device, .net_device = NULL /* not yet emulated */ @@ -12726,13 +13676,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &pt2000_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -12772,13 +13725,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the Super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio32_onboard_pci_device, .snd_device = &cs4232_onboard_device, .net_device = NULL @@ -12815,13 +13772,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the Super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, - .kbd_device = NULL, + .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -12861,13 +13822,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the Super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &zappa_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -12908,13 +13873,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &powermatev_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &opti_82c930_device, .net_device = NULL @@ -12952,13 +13920,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI_TRIGEM | KBC_FLAG_IS_GREEN | 0x00005a00, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMI_1994, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -12998,13 +13969,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004d00, /* Guess */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -13042,13 +14016,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -13088,13 +14065,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005000, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -13134,13 +14114,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -13178,13 +14161,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -13222,13 +14208,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -13266,13 +14255,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMI_1994, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -13310,13 +14302,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI_TRIGEM | KBC_FLAG_IS_GREEN | 0x00005a00, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AMI_1994, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &tgui9660_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -13356,13 +14351,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -13403,61 +14401,21 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess */ + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5434_onboard_pci_device, .snd_device = NULL, .net_device = NULL }, - /* Has a VIA KBC chip */ - { - .name = "[VLSI SuperCore] DFI G586VPM (rev. C)", - .internal_name = "g586vpmc", - .type = MACHINE_TYPE_SOCKET5, - .chipset = MACHINE_CHIPSET_VLSI_SUPERCORE, - .init = machine_at_g586vpmc_init, - .p1_handler = machine_generic_p1_handler, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, - .min_bus = 50000000, - .max_bus = 66666667, - .min_voltage = 3520, - .max_voltage = 3520, - .min_multi = 1.5, - .max_multi = 2.0 - }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, - .ram = { - .min = 4096, - .max = 262144, - .step = 4096 - }, - .nvrmask = 127, - .jumpered_ecp_dma = MACHINE_DMA_1 | MACHINE_DMA_3, - .default_jumpered_ecp_dma = 1, - .kbc_device = &kbc_at_device, - .kbc_params = KBC_VEN_VIA | 0x00424600, /* Guess */ - .kbc_p1 = 0x00000cf0, - .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 - }, /* KBC firmware is unknown. No commands outside of the base PS/2 */ /* KBC command set are used. */ { @@ -13492,13 +14450,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 4, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess */ + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -13536,13 +14498,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess */ + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5430_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -13582,17 +14548,69 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess */ + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64_onboard_pci_device, .snd_device = NULL, .net_device = NULL }, + /* Has a VIA KBC chip */ + { + .name = "[VLSI Wildcat] DFI G586VPM (rev. C)", + .internal_name = "g586vpmc", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_VLSI_WILDCAT, + .init = machine_at_g586vpmc_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 4096, + .max = 262144, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_1 | MACHINE_DMA_3, + .default_jumpered_ecp_dma = 1, + .kbc_device = &kbc_at_device, + .kbc_params = KBC_VEN_VIA | 0x00424600, /* Guess */ + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 7 (Single Voltage) machines */ /* 430FX */ @@ -13630,13 +14648,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &p54tp4xe_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -13674,13 +14695,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -13720,13 +14744,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, .snd_device = &cs4232_onboard_device, .net_device = NULL @@ -13763,13 +14791,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -13806,13 +14838,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &vectra52_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5436_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -13851,13 +14887,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -13897,13 +14937,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &mach64ct_device_onboard, .snd_device = &cs4232_onboard_device, .net_device = NULL @@ -13943,13 +14987,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &thor_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, .snd_device = &cs4232_onboard_device, .net_device = NULL @@ -13989,13 +15037,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64_onboard_pci_device, .snd_device = &sb_vibra16s_onboard_device, .net_device = NULL @@ -14035,13 +15087,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &monaco_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &mach64ct_device_onboard, .snd_device = &cs4232_onboard_device, .net_device = NULL @@ -14079,13 +15135,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms5119_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -14124,13 +15183,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5440_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -14168,13 +15231,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -14212,13 +15278,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &fmb_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -14260,13 +15329,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -14304,13 +15377,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -14348,13 +15424,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -14392,13 +15471,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &d943_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5436_onboard_pci_device, .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL @@ -14439,13 +15521,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* NVR is on the super I/O chip. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL @@ -14485,13 +15571,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &c5sbm2_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -14531,13 +15621,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005200, + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -14575,13 +15669,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ap5s_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -14619,13 +15717,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cs4232_onboard_device, .net_device = NULL @@ -14663,13 +15765,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, /* Guess. */ + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &gd5436_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -14707,13 +15813,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms5124_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -14754,13 +15864,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = 0x00000000, + /* NVR is on the chipset. */ + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000004f0, .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 @@ -14801,13 +15915,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &m5ata_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -14845,13 +15962,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -14889,13 +16009,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -14936,13 +16059,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -14980,13 +16106,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -15024,13 +16153,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -15071,13 +16203,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_virge_325_onboard_pci_device, .snd_device = &ymf701_device, .net_device = NULL @@ -15116,13 +16251,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &cu430hx_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL @@ -15163,13 +16301,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &tc430hx_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_virge_375_onboard_pci_device, .snd_device = &ymf701_device, .net_device = NULL @@ -15208,13 +16349,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &m7shi_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -15252,13 +16396,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00005200, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT_ZERO_DEFAULT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -15300,13 +16447,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &ymf701_device, .net_device = NULL @@ -15345,13 +16495,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -15391,13 +16544,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -15435,13 +16591,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -15480,13 +16639,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, /* Guess. */ .kbc_params = KBC_VEN_AMI | 0x00004800, /* Guess. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -15524,13 +16686,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -15569,13 +16734,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_trio64v2_dx_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -15614,13 +16782,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_trio64v2_dx_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -15660,13 +16831,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -15704,13 +16878,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &p5vxb_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -15749,13 +16926,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -15795,13 +16975,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL @@ -15840,13 +17023,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -15884,13 +17070,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &lgibmx52_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -15931,13 +17120,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -15976,13 +17168,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cs4237b_device, .net_device = NULL @@ -16021,13 +17216,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16066,13 +17264,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16112,13 +17313,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &chips_69000_onboard_device, .snd_device = NULL, .net_device = NULL @@ -16156,13 +17360,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16209,13 +17416,18 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* TODO: PC87307 NVR. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, + /* Stop-gap measure until the Trio64V2/GX is emulated, as both use the same VBIOS. */ .vid_device = &s3_trio64v2_dx_onboard_pci_device, .snd_device = &sb_vibra16xv_onboard_device, @@ -16254,13 +17466,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* TODO: PC87307 NVR. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_trio64v2_dx_onboard_pci_device, .snd_device = &cs4236b_onboard_device, .net_device = &pcnet_am79c973_onboard_device @@ -16299,13 +17515,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004600, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &mach64vt3_onboard_device, .snd_device = NULL, .net_device = NULL @@ -16344,13 +17563,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &an430tx_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &ymf715_onboard_device, .net_device = NULL @@ -16389,13 +17611,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16440,13 +17665,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16485,13 +17713,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms5156_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -16530,13 +17761,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -16575,13 +17809,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16619,13 +17856,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16663,13 +17903,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16707,13 +17950,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16753,13 +17999,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16797,13 +18046,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms5146_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -16841,13 +18093,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &r534f_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -16887,13 +18142,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16931,13 +18189,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -16977,13 +18238,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17024,13 +18288,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17071,13 +18338,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17116,13 +18386,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17163,13 +18436,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17207,13 +18483,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &es1373_onboard_device, .net_device = NULL @@ -17251,13 +18530,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17295,13 +18577,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &g5x_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -17340,13 +18625,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17386,13 +18674,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17433,13 +18724,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17478,13 +18772,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17523,13 +18820,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17568,13 +18868,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17613,13 +18916,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17657,13 +18963,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &delhi3_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cs4235_onboard_device, .net_device = NULL @@ -17704,23 +19013,27 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 3, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000008f0, .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 }, + /* 450GX */ /* This has an AMIKey-2, which is type 'H'. */ { - .name = "[i450KX] ASUS P/I-P6RP4", + .name = "[i450GX] ASUS P/I-P6RP4", .internal_name = "p6rp4", .type = MACHINE_TYPE_SOCKET8, - .chipset = MACHINE_CHIPSET_INTEL_450KX, + .chipset = MACHINE_CHIPSET_INTEL_450GX, .init = machine_at_p6rp4_init, .p1_handler = machine_generic_p1_handler, .gpio_handler = NULL, @@ -17748,23 +19061,26 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_P6RP4, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 }, /* This has a PC87306 with unknown keyboard controller firmware (Phoenix?). */ { - .name = "[i450KX] FIC PO-6000", + .name = "[i450GX] FIC PO-6000", .internal_name = "ficpo6000", .type = MACHINE_TYPE_SOCKET8, - .chipset = MACHINE_CHIPSET_INTEL_450KX, + .chipset = MACHINE_CHIPSET_INTEL_450GX, .init = machine_at_ficpo6000_init, .p1_handler = machine_generic_p1_handler, .gpio_handler = NULL, @@ -17792,13 +19108,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = 1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ficpo6000_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -17839,13 +19158,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17883,13 +19205,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17927,13 +19252,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -17971,13 +19299,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18017,13 +19348,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* TODO: Implement the PC87307 NVR. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_virge_325_onboard_pci_device, .snd_device = &cs4236b_onboard_device, .net_device = NULL @@ -18063,13 +19398,17 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + /* TODO: Implement the PC87307 NVR. */ + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &vs440fx_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cs4236_onboard_device, .net_device = NULL @@ -18107,13 +19446,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18152,13 +19494,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18196,13 +19541,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_VIA | 0x00424600, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18243,13 +19591,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18290,13 +19641,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18334,13 +19688,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18378,13 +19735,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_HOLTEK | 0x00004800, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18425,13 +19785,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &lx6_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -18470,13 +19833,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, /* not yet emulated */ .snd_device = &cs4236b_device, .net_device = NULL /* not yet emulated */ @@ -18515,13 +19881,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = &nvr_at_device, + .nvr_params = NVR_AT, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18560,13 +19929,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms6117_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -18605,13 +19977,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x0000044f0, .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 @@ -18655,13 +20030,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &s3_trio64v2_dx_onboard_pci_device, .snd_device = NULL, .net_device = NULL @@ -18701,13 +20079,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18747,13 +20128,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &como_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, /* Onboard video not yet emulated: ATi Rage IIc AGP */ .snd_device = &cs4235_onboard_device, .net_device = NULL @@ -18794,13 +20178,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18839,13 +20226,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &bx6_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -18884,13 +20274,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ax6bc_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -18929,13 +20322,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -18974,13 +20370,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -19019,13 +20418,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ga686_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -19063,13 +20465,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms6119_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -19107,13 +20512,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms6147_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &es1371_onboard_device, .net_device = NULL @@ -19152,13 +20560,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &p6sba_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -19197,13 +20608,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &s1846_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &es1371_onboard_device, .net_device = NULL @@ -19244,13 +20658,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &vei8_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = NULL, .net_device = NULL @@ -19289,13 +20706,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &voodoo_3_2000_agp_onboard_8m_device, .snd_device = &es1373_onboard_device, .net_device = NULL @@ -19334,13 +20754,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &voodoo_3_2000_agp_onboard_8m_device, .snd_device = &es1373_onboard_device, .net_device = NULL @@ -19380,13 +20803,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &es1373_onboard_device, .net_device = NULL @@ -19424,13 +20850,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -19471,13 +20900,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -19518,13 +20950,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -19565,13 +21000,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -19610,13 +21048,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms6199va_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &es1373_onboard_device, .net_device = NULL @@ -19657,13 +21098,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -19702,13 +21146,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = &kbc_at_device, .kbc_params = KBC_VEN_AMI | 0x00004800, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &es1373_onboard_device, .net_device = NULL @@ -19750,13 +21197,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x000044f0, .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 @@ -19797,13 +21247,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &prosignias31x_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cmi8738_onboard_device, .net_device = NULL @@ -19842,13 +21295,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &es1373_onboard_device, .net_device = NULL @@ -19888,13 +21344,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cmi8738_onboard_device, .net_device = NULL @@ -19936,13 +21395,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -19981,13 +21443,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20029,13 +21494,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20077,13 +21545,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = &chips_69000_onboard_device, .snd_device = NULL, .net_device = NULL @@ -20122,13 +21593,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20167,13 +21641,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20214,13 +21691,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20261,13 +21741,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20308,13 +21791,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20353,13 +21839,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cmi8738_onboard_device, .net_device = NULL @@ -20400,13 +21889,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20445,13 +21937,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cmi8738_onboard_device, .net_device = NULL @@ -20490,13 +21985,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20535,13 +22033,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = NULL, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &cmi8738_onboard_device, .net_device = NULL @@ -20580,13 +22081,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, .device = &ms6318_device, .kbd_device = NULL, .fdc_device = NULL, - .sio_device = NULL, .vid_device = NULL, .snd_device = &ct5880_onboard_device, .net_device = NULL @@ -20625,13 +22129,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20672,13 +22179,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000cf0, .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 @@ -20716,13 +22226,16 @@ const machine_t machines[] = { .default_jumpered_ecp_dma = -1, .kbc_device = NULL, .kbc_params = 0x00000000, + .nvr_device = NULL, + .nvr_params = 0x00000000, + .sio_device = NULL, + .sio_params = 0x00000000, .kbc_p1 = 0x00000000, .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 @@ -20934,6 +22447,24 @@ machine_get_kbc_device(int m) return (NULL); } +const device_t * +machine_get_nvr_device(int m) +{ + if (machines[m].nvr_device) + return (machines[m].nvr_device); + + return (NULL); +} + +const device_t * +machine_get_sio_device(int m) +{ + if (machines[m].sio_device) + return (machines[m].sio_device); + + return (NULL); +} + const device_t * machine_get_device(int m) { @@ -20952,15 +22483,6 @@ machine_get_fdc_device(int m) return (NULL); } -const device_t * -machine_get_sio_device(int m) -{ - if (machines[m].sio_device) - return (machines[m].sio_device); - - return (NULL); -} - const device_t * machine_get_vid_device(int m) { @@ -21179,3 +22701,5 @@ machine_get_nvr_name(void) { return machine_get_nvr_name_ex(machine); } + + diff --git a/src/nvr_at.c b/src/nvr_at.c index 11b5ffc45..5a2e6bd87 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -238,67 +238,59 @@ #include <86box/nvr.h> /* RTC registers and bit definitions. */ -#define RTC_SECONDS 0 -#define RTC_ALSECONDS 1 -#define AL_DONTCARE 0xc0 /* Alarm time is not set */ -#define RTC_MINUTES 2 -#define RTC_ALMINUTES 3 -#define RTC_HOURS 4 -#define RTC_AMPM 0x80 /* PM flag if 12h format in use */ -#define RTC_ALHOURS 5 -#define RTC_DOW 6 -#define RTC_DOM 7 -#define RTC_MONTH 8 -#define RTC_YEAR 9 -#define RTC_REGA 10 -#define REGA_UIP 0x80 -#define REGA_DV2 0x40 -#define REGA_DV1 0x20 -#define REGA_DV0 0x10 -#define REGA_DV 0x70 -#define REGA_RS3 0x08 -#define REGA_RS2 0x04 -#define REGA_RS1 0x02 -#define REGA_RS0 0x01 -#define REGA_RS 0x0f -#define RTC_REGB 11 -#define REGB_SET 0x80 -#define REGB_PIE 0x40 -#define REGB_AIE 0x20 -#define REGB_UIE 0x10 -#define REGB_SQWE 0x08 -#define REGB_DM 0x04 -#define REGB_2412 0x02 -#define REGB_DSE 0x01 -#define RTC_REGC 12 -#define REGC_IRQF 0x80 -#define REGC_PF 0x40 -#define REGC_AF 0x20 -#define REGC_UF 0x10 -#define RTC_REGD 13 -#define REGD_VRT 0x80 -#define RTC_CENTURY_AT 0x32 /* century register for AT etc */ -#define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */ -#define RTC_CENTURY_ELT 0x1A /* century register for Epson Equity LT */ -#define RTC_ALDAY 0x7D /* VIA VT82C586B - alarm day */ -#define RTC_ALMONTH 0x7E /* VIA VT82C586B - alarm month */ -#define RTC_CENTURY_VIA 0x7F /* century register for VIA VT82C586B */ +#define RTC_SECONDS 0 +#define RTC_ALSECONDS 1 +/* Alarm time is not set. */ +#define AL_DONTCARE 0xc0 +#define RTC_MINUTES 2 +#define RTC_ALMINUTES 3 +#define RTC_HOURS 4 +/* PM flag if 12h format in use. */ +#define RTC_AMPM 0x80 +#define RTC_ALHOURS 5 +#define RTC_DOW 6 +#define RTC_DOM 7 +#define RTC_MONTH 8 +#define RTC_YEAR 9 +#define RTC_REGA 10 +#define REGA_UIP 0x80 +#define REGA_DV2 0x40 +#define REGA_DV1 0x20 +#define REGA_DV0 0x10 +#define REGA_DV 0x70 +#define REGA_RS3 0x08 +#define REGA_RS2 0x04 +#define REGA_RS1 0x02 +#define REGA_RS0 0x01 +#define REGA_RS 0x0f +#define RTC_REGB 11 +#define REGB_SET 0x80 +#define REGB_PIE 0x40 +#define REGB_AIE 0x20 +#define REGB_UIE 0x10 +#define REGB_SQWE 0x08 +#define REGB_DM 0x04 +#define REGB_2412 0x02 +#define REGB_DSE 0x01 +#define RTC_REGC 12 +#define REGC_IRQF 0x80 +#define REGC_PF 0x40 +#define REGC_AF 0x20 +#define REGC_UF 0x10 +#define RTC_REGD 13 +#define REGD_VRT 0x80 +/* VIA VT82C586B - alarm day. */ +#define RTC_ALDAY 0x7d +/* VIA VT82C586B - alarm month. */ +#define RTC_ALMONTH 0x7e -#define RTC_ALDAY_SIS 0x7E /* Day of Month Alarm for SiS */ -#define RTC_ALMONT_SIS 0x7F /* Month Alarm for SiS */ +/* Day of Month Alarm for SiS. */ +#define RTC_ALDAY_SIS 0x7e +/* Month Alarm for SiS. */ +#define RTC_ALMONTH_SIS 0x7f -#define RTC_REGS 14 /* number of registers */ - -#define FLAG_NO_NMI 0x001 -#define FLAG_AMI_1992_HACK 0x002 -#define FLAG_AMI_1994_HACK 0x004 -#define FLAG_AMI_1995_HACK 0x008 -#define FLAG_AMI_1999_HACK 0x010 -#define FLAG_AMI_1999J_HACK 0x020 -#define FLAG_P6RP4_HACK 0x040 -#define FLAG_PIIX4 0x080 -#define FLAG_MULTI_BANK 0x100 -#define FLAG_MARTIN_HACK 0x200 +/* Number of registers. */ +#define RTC_REGS 14 typedef struct local_t { int8_t stat; @@ -319,6 +311,7 @@ typedef struct local_t { int16_t state; uint16_t flags; + uint16_t default_addr; uint16_t addr[8]; @@ -482,7 +475,7 @@ timer_update(void *priv) /* Check for any alarms we need to handle. */ if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && check_alarm(nvr, RTC_HOURS) && check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH) /* && - check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS) */) { + check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH_SIS) */) { nvr->regs[RTC_REGC] |= REGC_AF; timer_update_irq(nvr); } @@ -1148,108 +1141,34 @@ nvr_at_init(const device_t *info) local = (local_t *) malloc(sizeof(local_t)); memset(local, 0x00, sizeof(local_t)); - nvr->data = local; + + nvr->data = local; /* This is machine specific. */ - nvr->size = machines[machine].nvrmask + 1; - local->lock = (uint8_t *) malloc(nvr->size); + nvr->size = (info->local & FLAG_FIXED_SIZE) ? 128 : + (machines[machine].nvrmask + 1); + local->lock = (uint8_t *) malloc(nvr->size); memset(local->lock, 0x00, nvr->size); - local->def = 0xff /*0x00*/; - local->flags = 0x00; - switch (info->local & 0x0f) { - case 0: /* standard AT, no century register */ - if (info->local == 32) { - local->flags |= FLAG_P6RP4_HACK; - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - } else { - nvr->irq = 8; - local->cent = 0xff; - } - break; - case 1: /* standard AT */ - case 5: /* AMI WinBIOS 1994 */ - case 6: /* AMI BIOS 1995 */ - if ((info->local & 0x1f) == 0x11) { - local->flags |= FLAG_PIIX4; - local->def = 0x00; - } else { - local->def = 0x00; - if ((info->local & 0x1f) == 0x15) - local->flags |= FLAG_AMI_1994_HACK; - else if ((info->local & 0x1f) == 0x16) - local->flags |= FLAG_AMI_1995_HACK; - else - local->def = 0xff; - } - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - break; + local->flags = info->local & 0xffff; + local->cent = (info->local >> 16) & 0xff; + local->default_addr = (info->local >> 24) & 0xffff; + local->def = (local->flags & FLAG_ZERO_DEFAULT) ? 0x00 : 0xff; + nvr->irq = (info->local >> 40) & 0xff; - case 2: /* PS/1 or PS/2 */ - nvr->irq = 8; - local->cent = RTC_CENTURY_PS; - local->def = 0x00; - if (info->local & 0x10) - local->flags |= FLAG_NO_NMI; - break; + if (nvr->irq == 0xff) + nvr->irq = -1; + else if (nvr->irq == 0xfe) + nvr->irq = device_get_config_int("irq"); - case 3: /* Amstrad PC's */ - nvr->irq = 1; - local->cent = RTC_CENTURY_AT; - local->def = 0xff; - if (info->local & 0x10) - local->flags |= FLAG_NO_NMI; - break; + if (local->default_addr == 0xfffe) + local->default_addr = device_get_config_hex16("base"); - case 4: /* IBM AT */ - if (info->local & 0x10) { - local->def = 0x00; - local->flags |= FLAG_AMI_1992_HACK; - } else if ((info->local == 36) || (info->local == 68)) { - local->def = 0x00; - if (info->local == 68) - local->flags |= FLAG_MARTIN_HACK; - } else - local->def = 0xff; - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - break; + if (nvr->is_new && (machines[machine].init == machine_at_spitfire_init)) + local->flags |= FLAG_SPITFIRE_HACK; - case 7: /* VIA VT82C586B */ - nvr->irq = 8; - local->cent = RTC_CENTURY_VIA; - break; - case 8: /* Epson Equity LT */ - nvr->irq = -1; - local->cent = RTC_CENTURY_ELT; - break; - case 9: /* Intel PIIX4 + AMI 1999 hack */ - local->flags |= (FLAG_PIIX4 | FLAG_AMI_1999_HACK); - local->def = 0x00; - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - break; - case 0x0a: /* Intel PIIX4 + AMI 1999J hack */ - local->flags |= (FLAG_PIIX4 | FLAG_AMI_1999J_HACK); - local->def = 0x00; - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - break; - - default: - break; - } - - if (info->local & 0x20) - local->def = 0x00; - - if (machines[machine].init == machine_at_monsoon_init) - local->def = 0xff; - - if (info->local & 0x40) - local->flags |= FLAG_MULTI_BANK; + if (nvr->is_new && (machines[machine].init == machine_at_bx6_init)) + local->flags |= FLAG_BX6_HACK; local->read_addr = 1; @@ -1276,27 +1195,21 @@ nvr_at_init(const device_t *info) timer_load_count(nvr); /* Set up the I/O handler for this device. */ - if (info->local == 8) { - io_sethandler(0x11b4, 2, + io_sethandler(local->default_addr, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + + if (local->flags & FLAG_MULTI_ADDRESS) + io_sethandler(local->default_addr + 2, 2, nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); - } else { - io_sethandler(0x0070, 2, - nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); - } - if (((info->local & 0x1f) == 0x11) || ((info->local & 0x1f) == 0x17) || - ((info->local & 0x1f) == 0x18)) { - io_sethandler(0x0072, 2, - nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); - } nvr_at_inited = 1; } /* This is a hack but it is required for the machine to boot properly, no idea why. */ - if (nvr->is_new && (machines[machine].init == machine_at_spitfire_init)) + if (nvr->is_new && (local->flags & FLAG_SPITFIRE_HACK)) nvr->regs[0x33] = nvr->regs[0x34] = 0xff; - if (nvr->is_new && (machines[machine].init == machine_at_bx6_init)) + if (nvr->is_new && (local->flags & FLAG_BX6_HACK)) nvr->regs[0x39] = 0x09; return nvr; @@ -1328,8 +1241,8 @@ nvr_at_close(void *priv) nvr_at_inited = 0; } -const device_t at_nvr_old_device = { - .name = "PC/AT NVRAM (No century)", +const device_t nvr_at_device = { + .name = "PC/AT NVRAM", .internal_name = "at_nvr_old", .flags = DEVICE_ISA16, .local = 0, @@ -1341,255 +1254,3 @@ const device_t at_nvr_old_device = { .force_redraw = NULL, .config = NULL }; - -const device_t at_nvr_device = { - .name = "PC/AT NVRAM", - .internal_name = "at_nvr", - .flags = DEVICE_ISA16, - .local = 1, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t at_mb_nvr_device = { - .name = "PC/AT NVRAM", - .internal_name = "at_nvr", - .flags = DEVICE_ISA16, - .local = 0x40 | 0x20 | 1, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ps_nvr_device = { - .name = "PS/1 or PS/2 NVRAM", - .internal_name = "ps_nvr", - .flags = DEVICE_ISA16, - .local = 2, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t amstrad_nvr_device = { - .name = "Amstrad NVRAM", - .internal_name = "amstrad_nvr", - .flags = DEVICE_ISA16, - .local = 3, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ibmat_nvr_device = { - .name = "IBM AT NVRAM", - .internal_name = "ibmat_nvr", - .flags = DEVICE_ISA16, - .local = 4, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t piix4_nvr_device = { - .name = "Intel PIIX4 PC/AT NVRAM", - .internal_name = "piix4_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 1, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ps_no_nmi_nvr_device = { - .name = "PS/1 or PS/2 NVRAM (No NMI)", - .internal_name = "ps1_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 2, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t amstrad_no_nmi_nvr_device = { - .name = "Amstrad NVRAM (No NMI)", - .internal_name = "amstrad_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 3, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ami_1992_nvr_device = { - .name = "AMI Color 1992 PC/AT NVRAM", - .internal_name = "ami_1992_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 4, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ami_1994_nvr_device = { - .name = "AMI WinBIOS 1994 PC/AT NVRAM", - .internal_name = "ami_1994_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 5, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ami_1995_nvr_device = { - .name = "AMI WinBIOS 1995 PC/AT NVRAM", - .internal_name = "ami_1995_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 6, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t via_nvr_device = { - .name = "VIA PC/AT NVRAM", - .internal_name = "via_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 7, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t piix4_ami_1995_nvr_device = { - .name = "Intel PIIX4 AMI WinBIOS 1995 PC/AT NVRAM", - .internal_name = "piix4_ami_1995_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 9, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t piix4_ami_1995j_nvr_device = { - .name = "Intel PIIX4 AMI WinBIOS 1995J PC/AT NVRAM", - .internal_name = "piix4_ami_1995j_nvr", - .flags = DEVICE_ISA16, - .local = 0x10 | 10, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t p6rp4_nvr_device = { - .name = "ASUS P/I-P6RP4 PC/AT NVRAM", - .internal_name = "p6rp4_nvr", - .flags = DEVICE_ISA16, - .local = 32, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t amstrad_megapc_nvr_device = { - .name = "Amstrad MegaPC NVRAM", - .internal_name = "amstrad_megapc_nvr", - .flags = DEVICE_ISA16, - .local = 36, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t martin_nvr_device = { - .name = "Zeos Martin NVRAM", - .internal_name = "martin_nvr", - .flags = DEVICE_ISA16, - .local = 68, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t elt_nvr_device = { - .name = "Epson Equity LT NVRAM", - .internal_name = "elt_nvr", - .flags = DEVICE_ISA, - .local = 8, - .init = nvr_at_init, - .close = nvr_at_close, - .reset = nvr_at_reset, - .available = NULL, - .speed_changed = nvr_at_speed_changed, - .force_redraw = NULL, - .config = NULL -}; diff --git a/src/scsi/scsi_ql1xxx.c b/src/scsi/scsi_ql1xxx.c index a01318210..496e3adea 100644 --- a/src/scsi/scsi_ql1xxx.c +++ b/src/scsi/scsi_ql1xxx.c @@ -2323,7 +2323,6 @@ ql_sxp_begin_response_entry(ql_sxp_req_t *pkt, isp_req_status_t *resp) static double ql_sxp_handle_state_send_cdb_bios(ql_t *dev, scsi_device_t *sd) { - ql_sxp_req_t *pkt = &dev->pkt; isp_req_status_t *resp = &dev->pkt_resp; double media_period = 10.0; uint64_t bytes_xfered = 0; diff --git a/src/sio/sio_f82c606.c b/src/sio/sio_f82c606.c index 1e6eacccc..816abaf15 100644 --- a/src/sio/sio_f82c606.c +++ b/src/sio/sio_f82c606.c @@ -298,7 +298,7 @@ f82c606_init(const device_t *info) { upc_t *dev = (upc_t *) calloc(1, sizeof(upc_t)); - dev->nvr = device_add(&at_nvr_old_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_OLD); dev->gameport = gameport_add(&gameport_sio_device); dev->uart[0] = device_add_inst(&ns16450_device, 1); diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 42ab2c7a7..d6788960a 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -1892,7 +1892,7 @@ fdc37c93x_init(const device_t *info) dev->port_370 = !!(info->local & FDC37XXXX_370); if (dev->has_nvr) { - dev->nvr = device_add(&amstrad_megapc_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_ZERO_DEFAULT); nvr_bank_set(0, 0, dev->nvr); nvr_bank_set(1, 0xff, dev->nvr); diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index 7fdf6d2d6..059d36027 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -486,7 +486,7 @@ pc87306_init(UNUSED(const device_t *info)) dev->lpt = device_add_inst(&lpt_port_device, 1); lpt_set_cnfga_readout(dev->lpt, 0x10); - dev->nvr = device_add(&at_mb_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_MB); switch (dev->kbc_type) { case PCX730X_AMI: diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c index fb3df1409..78b0a675b 100644 --- a/src/sio/sio_vl82c113.c +++ b/src/sio/sio_vl82c113.c @@ -135,11 +135,12 @@ vl82c113_init(UNUSED(const device_t *info)) vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t)); if (machines[machine].init == machine_at_martin_init) - dev->nvr = device_add(&martin_nvr_device); - else if (machines[machine].init == machine_at_sensation1_init || machines[machine].init == machine_at_sensation2_init) - dev->nvr = device_add(&at_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_MARTIN); + else if ((machines[machine].init == machine_at_monsoon_init) || (machines[machine].init == machine_at_sensation1_init) || + (machines[machine].init == machine_at_sensation2_init)) + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT); else - dev->nvr = device_add(&amstrad_megapc_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_ZERO_DEFAULT); dev->nvr_enabled = 1; dev->nvr_base = 0x0070; diff --git a/src/sio/sio_w83977.c b/src/sio/sio_w83977.c index 07fda5d4e..60b42a9ce 100644 --- a/src/sio/sio_w83977.c +++ b/src/sio/sio_w83977.c @@ -1287,7 +1287,7 @@ w83977_init(const device_t *info) dev->has_nvr = !(info->local & W83977_NO_NVR); if (dev->has_nvr && (dev->id != 1)) { - dev->nvr = device_add(&amstrad_megapc_nvr_device); + dev->nvr = device_add_params(&nvr_at_device, (void *) (uintptr_t) NVR_AT_ZERO_DEFAULT); nvr_bank_set(0, 0, dev->nvr); } From a2a4a3490b098a69121b3d552e4fc425241b8be8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 26 Feb 2026 12:41:32 +0100 Subject: [PATCH 66/66] Revised icons and logo and used the old unused SuperDisk icon for the generic removable disk drive. --- src/qt/icons/86Box-gray.ico | Bin 151938 -> 402694 bytes src/qt/icons/86Box-green.ico | Bin 152054 -> 402694 bytes src/qt/icons/86Box-red.ico | Bin 154898 -> 402694 bytes src/qt/icons/86Box-yellow.ico | Bin 136502 -> 402694 bytes src/qt/icons/active.ico | Bin 9622 -> 9622 bytes src/qt/icons/cartridge.ico | Bin 9622 -> 9622 bytes src/qt/icons/cartridge_image.ico | Bin 9622 -> 9622 bytes src/qt/icons/cassette.ico | Bin 9622 -> 9622 bytes src/qt/icons/cassette_image.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom_disabled.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom_folder.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom_host.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom_image.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom_mute.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom_nomedia.ico | Bin 9622 -> 9622 bytes src/qt/icons/cdrom_unmute.ico | Bin 9622 -> 9622 bytes src/qt/icons/floppy_35.ico | Bin 9622 -> 9622 bytes src/qt/icons/floppy_35_image.ico | Bin 9622 -> 9622 bytes src/qt/icons/floppy_525.ico | Bin 9622 -> 9622 bytes src/qt/icons/floppy_525_image.ico | Bin 9622 -> 9622 bytes src/qt/icons/floppy_and_cdrom_drives.ico | Bin 9622 -> 9622 bytes src/qt/icons/floppy_disabled.ico | Bin 9622 -> 9622 bytes src/qt/icons/mo.ico | Bin 9622 -> 9622 bytes src/qt/icons/mo_disabled.ico | Bin 9622 -> 9622 bytes src/qt/icons/other_removable_devices.ico | Bin 9622 -> 9622 bytes src/qt/icons/ports.ico | Bin 9622 -> 9622 bytes src/qt/icons/rdisk.ico | Bin 9622 -> 9622 bytes src/qt/icons/rdisk_disabled.ico | Bin 9622 -> 9622 bytes src/qt/icons/rdisk_image.ico | Bin 9622 -> 9622 bytes src/qt/icons/superdisk.ico | Bin 9622 -> 0 bytes src/qt/icons/superdisk_disabled.ico | Bin 9622 -> 0 bytes src/qt/icons/superdisk_image.ico | Bin 9622 -> 0 bytes src/qt/icons/zip.ico | Bin 0 -> 9622 bytes src/qt/icons/zip_image.ico | Bin 0 -> 9622 bytes src/qt/qt_machinestatus.cpp | 18 +++++++++++++ src/qt/qt_mediamenu.cpp | 3 ++- src/qt/qt_settingsotherremovable.cpp | 32 ++++++++++++++++++----- src/qt/qt_settingsotherremovable.hpp | 4 ++- src/qt_resources.qrc | 5 ++-- 40 files changed, 51 insertions(+), 11 deletions(-) delete mode 100644 src/qt/icons/superdisk.ico delete mode 100644 src/qt/icons/superdisk_disabled.ico delete mode 100644 src/qt/icons/superdisk_image.ico create mode 100644 src/qt/icons/zip.ico create mode 100644 src/qt/icons/zip_image.ico diff --git a/src/qt/icons/86Box-gray.ico b/src/qt/icons/86Box-gray.ico index 68f278334a1a7b1a9573b1168928e9c858fd1192..52fe1c49b5f931616834172f05ab0b9c562b9a92 100644 GIT binary patch literal 402694 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 z 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 XzK+)-@pU{za2U diff --git a/src/qt/icons/86Box-red.ico b/src/qt/icons/86Box-red.ico index 36fbd2c9964a5d5bd616b1956d5c09a3f0857daf..645621bfc836490feb9f71cb2aa220bd9542ecf0 100644 GIT binary patch literal 402694 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 literal 154898 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

{8;I}Zr)Ic$W@^4j|V*n+WR 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 literal 136502 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 diff --git a/src/qt/icons/cartridge_image.ico b/src/qt/icons/cartridge_image.ico index 4f01aa1a9f5585a35ee600b869cb596529ef4be9..f537903f33ded20a2f3c96b7e1846307efbab11c 100644 GIT binary patch literal 9622 zcmeHLyKdV+5In<1j39+wxNv8cDf0(*mG1~t1o;c8Oqow`ks?)Um--ZaL7*~45N1Z= z1gGUKxqKNmpaaIsJKoOhu8wy!Q#wl*>H0dsF4C8als=}EZf*|!r#C76#Mtfaq5t)5 zN}u1Qv{)SaKj8NZbKk=UmtZ)I!=wlJ^=K95cEP1vuh-RPvvE;#xB6F3Bkzp zHBW!JTvozR|L>2F6@AC}i(_c~%&(+h*Ic!yJ!;CGx+Q<|>fVuK-I2eiukn&E$LP=8 zX;njOJzwiD4vaVQ^f;u?7!=14fAP@v^{0=87ca;EoK;nh9r{~~bBtXASHS8R+-I=e z?Dre)S8U&~NA+yVGiqDu`I~dCL;#}B-?y}u_Y2wlq24RzQ|!fO*QC1ddimP*H@1G{ z)1Id1xfG8bYl}~OveviM@8V;eoHJFv$U&RKG}kj9-nq;A^y;uPZ+B zd0ZsV`MT<-`;DNo0r63j*R*ZOT#J`EpXK2_I2G$uB*S3N$7@0H4&~!o&LQ40eB@wU zB&U(b5A()izWS6S>Zwk_fw<0}AX70)uBTLwJ0@Cuzi06Mom;az$_)9>HchNM_~ zuK7LyadR^dpl+QOV8HS{5mhmEBMuD-f623<9|+mX*HwtN22jF z7tWol{^V!t;^+PPd9}8&|K#-<+m@C^M~#U7f#W1zLc$HttGCs{a>5pIktl?PL=c=t={l>?J7VJ_w-^Or>c~`(4a1X2i Le52qu3m^XgT2RO} literal 9622 zcmeHLF>V_%5L`n>gdl}nxNv8cDf0ul$~yuTL4f=qjZ~&g%8 z_CHs$`k#I}X;AC`{kL;Ot-sg5mH+bRxKsK~%r*A3?b3{Wxm+gw88_u_J2p>^zqav> zgFp0VzmmSJ)c7xNeLJ>|k@b!I1st3QROj_#GU$6B?FVgz|Hog>5q>;{{`WCx_aW}- z{qxl|hLwdDFA)^lD1 zy+dx+#Pf?g9Pe=`8|d@_Av(#SM!HC zH1*r-9~r;KyvTOUu3O{sA7CdFyiZv$MY|br4J?3F5_}Jv12=%ahpqYHa+s3KO(pf! zJ>igYu{sAGJdmmLZ5fc6iW1iHE=lJaZNP-ly=v>Hx(yHaP8Sjfj-A&flat+Wz>)3 zqGzVh871S5J9pCe-~IG`!^aab>9ei&1I1rCOYD&IU!tpRpM!qiT$}zM@2iey_ZJ@> aITRj@`gKdz$FpWTyRq9_gWlVR8?(1&c6ZmezdbYi3fujC-~RaA?EMR~{l0I1 zf!_~cU&9AgF!XjPdw}1SmM7%3M9ez)EfvOu?WW4ns59@oxLjV)p`KEp;tA#cm2;zoQCTXD@-ZQz?j&IPjGp^Z-XYMekDWDV^bHBi?%5 z_=R0VM}EdygO?mNZ)vTUHFcXG1kt)&U6Xq&|MU#R@21XnqjLZgaL`7-tnfQ*4|#y- zJFMeBF1NDH!1c|*!F7(5FM+w-8Qvk^L&7luQ|?*T-90$CdxdfR9y_Q2`Rz1 YKidrazcavlF_w=1GFY*YFUC;&Cx=IZqW}N^ literal 9622 zcmeHLyKWRg5FASu5+cBX17}=F$R{}BJBSdUu^}O!K}1aGF9HdlkHgqns(Po|y>oM~ zy|s0~wl&u?J>69`v*X#bQ#whf>Fg}Q&(ep}l-{P4&d3Yb6YFD*uWcBmhIMtRQ5hKI};4Jvzg z7iN4;_m6V*d+G6vLyTSyFq9L|O4(BsA`McDqbq?TGb*hyvRXb;>h>*k9??$u~^Hv)dh~2Tk7*#;-cADwK=vnt~_wM zUi5{rua{1FTgZVQzFvS@Kdfo+m{^k?v;*<6Ht7}4^UIwZ^GoA<3tyqr8#KMQ-r>9S zWJkFJ4|f>vj`7-fzvH!gf;thWQM2wh8|S-_eZ@?qPt_F|w{W z24ZhM;>S7G>|=Is25jTppuglAGB(bH%DhfuL=$F=)%vx(nttQsnlc};SSuZTZ?myh zedah;S<7*Hz!Q$)W)81Ko-j-Ns3F!0PkMbEIfH)F!nx3T`W0{Td57=m7Z&4e_;LM; z)qEw->r#j1I+Qzt_x*q-+c$6-?-P#(!9o%HSi zEPkgk>uSdDVKcN#G<^?i_>arUrX4uG9oXrtL-yEtk9UXf@?PM2kVoU%;(L%Wjg_PE zMlU?QPcbg@Z66Vrk6bY~#q>mn^Dnpi5N#!vpNBQ;cU^ooXfo4)nq6##qrl?4 z^JL5zBZs)%hnn~|33ah4##(9h+Pn^p<2-egHOwO(y=tO9af!R+kGb2h#2;&@$9bha ztY5lnzFbQUYvcN{A3a=-@#8fdZ)?(8!7?1prw+?BuH#UAfG>55+t(8KdvgQ0_N_N< zf#3J|3Am4P{n(3r_i$*wo$m%a9`>JS@F~roKSY%0^vTBLo^0BI|9A&#zw-_MWiX-< Iug1gJALo_rE&u=k diff --git a/src/qt/icons/cassette_image.ico b/src/qt/icons/cassette_image.ico index fa635805067fcfb7e327fd980f710ed9405d4e61..77fef6cb79549b088612837039e3ea4bc6f12883 100644 GIT binary patch literal 9622 zcmeHMv2xTf5Zw$JZWxM7ks{q)Ny#5vD!zk?;V+_+D#K?`QB&qa_y%eU2J_xpYu3KC zEc-5m$#^rHl_l%F)k<2)iO7Xq%GH&??&ag9$U70azHXnty%hP1x|^H!`O_`!^#(+-KI`#?x8GZ%lgQ zPne@X=k&jC?vn7g%a}1I(P#){w>q`*pkG>iQ z_(99}BJFssko()X$E;$LBNAX}`;?9PK5^Zzi>8S*pFrC`e^^}c;%El(3)jM;_!ai%QoLc_ zV-8^5DR@!-DdFYyJB*X&MW2&AZV8WbV8ZvhwQKRiexcY{X>0I$SOj%=ItDyzJS*^y zuri+Y@31G%0^)>N4$sGJs;sEY<1W2GxJQ;~6&2T~Kd)-a*`I2BAD5|ekfVz{^nZ@5_~mFl)A)?;pOe?m zM6NvtzMebG0X%QqchJT03X%WcOS#oK8826hM#dQMmo=EGyh7q z2H#>n*Q!7Ctt9ZX^Lt6TguS*sX#^VK$A4K9+NGx(Ja3^p=%LeuJK0cp58Fd;p>_{T z{KMsW1l+oIPqB+V;htsgTB_OillX`6u6?G@EB{2^o0u8S|591wzplS^{~hf=%Sl!C ztov`lz2@Bfyu0a|2);A4ZSaloDEyA2$BFp#p7Gve^V>HHd840y!EfJVk*($DdwH)% zwmoHBeEnFB*VkEj4!@mKJa?QwEjND~zuO1Kqdu@++BvuT&RqUc?jb*TD4kDSlPB^Q zxdVQVHR9KLwn68NKa4qfO)x&jyNflRb=C+q-kl?2PU8ML2ihj@;>~gWb33Z^REB(t#hB> zIk(w#{qOMmg=gQx2TdS!<1p?Dej}vCv%9ni*ECJL-ENEOu?PLzf)F?HS3g+tm!#+4 z;2kqM#-BWf**;>8^-p6R5faa*+IA71_2xXQRRBHC#SAL(YQ^?|*Nyk2ev|W;S<~EG=HRi8sJ4}pb_qPI zxyK~%-1saweHQK{c2bghu)ouB|V*B7O+MG5RcSXI#y=y4u3chQx@VkX0 zwEFnWp*CY!@yi){ru?WTS=%*&%#lQdGZw@V-ax0acti+w;qUuY=E-fwsYq|AIE|5c931$GCUW zQ=ZjQ;W=yry@Ki-*6#p-qT16mwoWZ@1Mq!_G|h19P3)pZvXT7B}XjcjK|a-!!IAz z&BxMl^D2H=&3E}Q1{=dWkdrDLJu_q#r+l7pr~KfdC?=~3JLn&OLuP2hkmt8ti*tw7d)3&$Q)+mA-0rP^ zWMOijSemyb+A!|I{c3&&f*AIq;U(9`nt_*@f%YDMXc(al{xE?z$>}l1PoNjj QOXxM!_G{XP{{WGZ{}B`&FaQ7m diff --git a/src/qt/icons/cdrom.ico b/src/qt/icons/cdrom.ico index 0b28c73fe92181362285a084c8fc47ea3d4c2fa1..2fe824b6c064f7c10990f7d96a8d869d81b3844d 100644 GIT binary patch delta 361 zcmZ9Hze>YU7{$}nCO1vfo7=QnlX`QNDz%^vE`s78a1aW0bZ}^$g^DjAT}4FXln(j` zLMsHs$vO%JySNu$z~~di+fp1H&TxkBe7|42(ylzVH0)X)x>_k2MUm2Mj)FaF3A!%O zcT?!cN;uXXsPi*erW_S2a3k#7P{TEK@jwfpu$ps?$jMo}?b^o0&MOi6mMv z2WJZc_b$b%o5N9h17X_7w&&o)D@#&eQqSQ^5{J@e$4_BErzJKY_n}QtBSnN>9;dcI z&*M{L{U6SyM-e@q!6z?c%^+B31$3E@hCeI2gFD%)qA&svhU`PlDN3Yl{fiR3W#8>z D(}jCt delta 307 zcmZvWu}T9$07P>MUhX(9yDJ+L_b#~@RIFl=!X{uNHUaJY11tYQ>(o!u_z8j$4iprk zm_`tiLK_={b~b8f=eaf(VlnV$ikazm``yz+*U5Nx4Fh+D^OE4DI!|W#Q)=#=22re8 zj}4E-Wd_9oExE*{OgPKe$fTsA65hNj<3!u0$ZxZ`5Hs{crb;sjJ(6&S>q5Z0AEYOK z&j~+7mitw@5zH3YGLol6^JUkMj9}FvtG-8D#cUgoiK*ZU#erI5M^(A-RXSA<`EnGLUHk zH;OAyCb+U3Tx$#bN;-~Ym*`+A1foEYLeRO6rQV0%5lGri44XSh!jLw%m>Rdz##vD2 zKX+yNeNyHhMSp!u!Ps;#;xR^ssJ#n5#GLQpt4gRdqWb+CM;8O;e@DlB5&|9fBPN2_3pfAzKC){R<)pF4q1436xhl^$(aq zg@9v6=^&ld(W$H8qJu-Ow>mwCa}MwOOa_y|!<&Y0iDIdxSeTkLLf7)pb98)2I*w}$ zlmxhO7^bx+4E4tNR7IsQ%&389R!1B%1geRn(8hxFQAq^3LhwlIxOROEWrDOF2{y}I zzm@FIkQYDqJo`EkEc@n$B5nrel;VsYh}pxo#V(3|_P>NUe7#R-6&OVY> z2RkH!&D!EGLLfTsoYvp|oOBVeJ%w`)*F8iUMo9gY&n}XV@ZD;b@9wL-K9hNNwZ@C8 Z5X}C0S$l|gu+{Q~4nY8?Oo diff --git a/src/qt/icons/cdrom_folder.ico b/src/qt/icons/cdrom_folder.ico index be8386b87e518ee3c3cc3b0d95a14082dc362399..3472428ece472a9fa73b8a5adf213ce6975a597f 100644 GIT binary patch literal 9622 zcmeHNJB}PT6y#zBYYhihpg`G9=+J-;u!;;H!;#=ysGT`2b&cC!Jz zaJ!0p#d&0t{h3+VflcA*v73BV#Xozb5U#?j@a9c`--VxFh44cN;qBY>{N<|PHm~<$sI8)o*L#X$4fW4 zO+U+8Ms0<$=NZFTl7IOzV>~@Q75xz7(wr#A%i?3KG_YRH#j;L(j-?7|04`J3N1j$Z z)kF>8wD=guSZ0u7c`w$*lRFw?oJEYecww04SYPoej@s8Hw#C~*6uFKN`{-xE%hu+-*7KZa z8H`+uco>J-{f_15;w@k|^=ba8y&gmPPTMDVwk9wg+k2z%ym#0Ip2I@*b$AYoeO%*l ztwpT0c&O*cD&wioh$BqvKS-F}%T-?JBc5Spzc8OCdoJqRzFq9|8ISWEb+p%0huUUw z{kbcBh|#{8_gV3JPcFvv)|TOAEVW%R^s1vW`W_w%;yCa;VZCV3z(2rY;yb47=dcVf z;hgZKS2!7qxJ!5iX40nf$KyrLHCV)BvcB@#GG4-=w(Ut{;QdMz@;~DsI#zbT^By*s z1^5td$9Qh>?1Bx~$@Z_u@qn}Jc$dyCT%p7FFr8aJ;V%83O7Gu~;S!tcEUaDbZI@Wo z*5d&F@pw%8jrM5Fk=e7A^~~bF%eMED$M?8CFJ9rQ49}bK6-(dCJDx7S)>f@wxO3Pl z>**&p>O|||Q=_tJT?C0OqjzLX3gbzGrqfrIjxXN9uZ& zWxBKHJMwq>i0_NGORF%w7d|+29%dfnsPz@t(&90F9_7NNkJxI@DK?E0>#EHAIsN1^ zj*Lwf`&NzPPM(OI)?dM~gl+g98$F-#BNnxq={fpS`+SeI^HC#_OKjl@pFY1^qusL^ zhx*2#vUbmbu>RTMG3z`zU_Lc)&%^dy#*@ca&%VxzymbDBi_|mP?ClZH2iP7qm;n;n zuVB}(yKF=FggT#47k4n+$sTbhd&XUizaQ*iA7HwN4gBHq|FpdaF1gFi#ja7ZVn3hT z>*va5?}5_h_j;XswZ~-6XM0`7XaCNgscRFzFvzvUr}7Rr^=#&^dG##s_0{=?j*I!l z;l1)|f9<6M{%n4=x96q7d!IK=i~QPG{rvNs!Zf^m4{Oy?U3#-wesTjRT93cQBQ4@< z)v>ZJzvrfg9)F8thA*!{)7a#%x###jmthv`(w9rC^AmpKM%bzEneVmVSM;B zUhGrFtBvAnd9`0L&d2X2mJ?@T9!$82a{+(;W)nZPLqpHF>;=wt9al zx6_chUE8Uk%l}f`PJ`APd6f$O#Hl?&kuUH4y7&1PU{bsABLaV1z~q}6ewzqK7=D)s q2iP7qI79Xdb`4A6yW|Ne+v9hOLwJq<55a$Hy2bAucjNfWIQ|V8t7TOH delta 1269 zcmYjRU1%d!6rP_nGn2{uC6ml_W|BpfSZlu24z$hEZh|&lsQ?Zm|z&&YQYevF((@6vjQ%P zN;Ame9m-?Ika0p%ur2y{k@wIi`*U9bFIjj^Dj+whVAhS`iwPO`q$IwUCLZ|iNNIe} zOAumtlw(D#OqH;o6j6_vkRy*b*F;nzI=;)#VAB*A2TU$F7@a}TBbha^lX(hiR>DV)g;Uul(a4JUNlJ;7 z99`?+K59`1%Q*>C3A&15<1>{Cg6to46Mf$v$q{=`N{@*mEyFMVEXursvk4Wu6DEF3 z7^u_YGI4%w!X;b5HOUX_yw8oHH1#OCL_C|E9!aBNF-GYmReTbAjC_|vZC(n?Z@}=R z4?9GU`tArd>O(LOz|&YDXhYOS8g`iqt*Hb(W+NC-?H>xAJ7$%|mR##Bq$4bDSR$6J z{7{`0*M>}JCrtcKiUp2_WhaIE<4K&io+jRPl1s#@6Gufk8rSV7aF3Y0>-soHn$+z) zw#Q3oXd0k6l04>F{i8h+5zBy*9ZlJTi;KuGAZqn{@X!}C7<2Ywa1 gR0%&PQk~U_uXwlx7xRTjq?7bRoh2N{TH&F80NQQIU;qFB diff --git a/src/qt/icons/cdrom_host.ico b/src/qt/icons/cdrom_host.ico index 5065f347a5a8099644ed619ed19da23e3beae68c..d8167f663d3ac84d4cc156716636b0c55af2d263 100644 GIT binary patch delta 1409 zcmY+EO=uit7{}k)+46^hfEEmCt)ac>#idlKdTBiLpoL~V zc&U&j{Goz@R=s&JYbi)6nr`vpsUm_xigt@o4;C5(G0-IA^Uk)l9e7~oeV=)rXa2wc zyl3{G+5h!sadEDQ&7ud>dm8gX2?r$$pXoc%m0~mm8Q(}_Jf$m@@SJQY8C@)6*pzng z<#|EDY17p^9a^R9;xs<=AE)I|VT|%R9sFcf(Uu)tGs{@ETpSM~dNy!bR&j?Kt^^tm z2UQ4B3`1j=VZmUYBo^oh>E&a(9>yjgmk8Od>nvAVj#w|ldB(xUiJVIN;7m|-HrJ3@w@Qo|*)xj1JK zXAeI|9w2k3E#j+^&>B7wEu08~ocnm-AXI2S;A`9qL-s$?1d8p+Ls@a26#XZxVw_Yb z8>k#Bw-grK7$@x#UQ}b)v5GMA3S_JEW);6i4h|Q5oTG`BzK#9l&Ft|HL5x+?W0 z5uJSbA_>M@wzuuc|EVoez28prJ|X~bWNTAd)+f9j!puZ+ijc$48I zgyq3#pNBxX0=>iNT}H0ykZXAKN! z1L-ju&B6<*Noe1pkwP45y!Bw~Um9;?M608nx1ryrw*A6V^K3X6W@paM%+BA=&d%)4?rfT*v?gXRj1;vHudLXg7z!2}(s&{MT-dA% zDiq9mtCFz15D_u)%A0^~si>gXRquMySc>+_&Ej=2qS6M`9KSQ!rVhNEIsfN;?{mJ@ zP_}Ps*Egzd^8Sk1pF6G9tl}m6wFrlhrXsTrdii^`~1JhO! z*CQ82D}+!(+;oaqR`R&1gjg>+n9~e=Y7MJG2*wyLM*-{_$EKqh)FfEDEtnAaP6@D3 zHE~z7aZ1a>c5HjlC&X7zN?|q*R2ohnI$DtK^nD!Syf-F?qvz!Db)|qGYX(YXq!WF z@eJ)h>;+iNC+Ouz2WvW=?J`wWe8Uqgj7(6FINsBJ7(-K?7RU6EgQhpyX=$g#J3{QT zCGiiN7CS6S)n~TolG+0?D)*F7DK$-65^Y7K>Sl%LYeMWKc;0xH%zK8+GjXfzceZE~ zKdoJ`4D^B!Yo>;ma|g-KBHj*7^gI>sn;d_c58-OLie5Ry8^K{Za)`|`&G9%sD?B*x zw&2MCNuTZumkR+dxMezpzzwH_x>K+iqa*GMu2sQGwM_0u*rH(kNnpKhHL#(X_`4cn zCBEOb=$Oxj!6{Q;Oz;#iPM~aaGri+) zPK+1aFb&NzCq5Gc^W|IdXiXpaL4QD++oi*E-z$>{5n#6%{9E^BAVWZ;1 zY(+BB)N?qIOztnbpf?8C*tA)KUtF)#YGA9laZdD?$oPb~(TJODsvV|?KB-GVmue40 z(HR(_P$`v7)uy>^VyR0kN%e`R9pY(MyK>wABa3s z;fth%B&XshE5H&#B$81asSrG5?E$5lwy#s<E&~5s2(1+DLdF4;~5`UscgoFXpWDID%T|fdmmXpf=}Wj&^!mn8a7^w zBT6cV0LnQtHJdIH|Ib_lYqb!&1&&F_!qe0*oGR9e9J{qCI(`8cGX}mT=I=P8gZIH9 zO_l(x*L}>zI!?L;T&ur?v$27XvpQB>>D`NTe4XkR*-ja#&dIlkp8sAL+Vt)=>1t=9sCc_xE)#m diff --git a/src/qt/icons/cdrom_image.ico b/src/qt/icons/cdrom_image.ico index 84fc233e20e4b686d45a949d5767d76358d7df77..b11b023f3876da8ba533a5ba8d84b7a1227e93d7 100644 GIT binary patch delta 1026 zcma)*ziSg=7{}k-CArHbxw|w;n>6>cX{EM_O$VVAZBS53O1p_pEr^57VB;TPO$QMa zl=6iR3RTBej6#=!P=kX)$Bu$+CZ{5GtF`3yxg?ZQ93*^r@1E!K1&dtz#}RJkw-0Kg%K28bqC_c3`wJR^$SENGs>e$9a`@ z?@^aHZ)lt!7I7y$O=ic)>;Rc9pd9F5u0+Uau5Bq&_>b#hGCtaQ-ld(&_~i4ZG?zy|Pqj&1q^5YGxE)jV#vn4AwNuGq~h)TkUepMaI-% z=^;GTZK}!Gj>Yl7QAwT*+lt_$qu_qT#ZZ?<^)5V*rB07n*TYoq#@nnGCOwn`aS~Dl zN4D7s3Hu>MqE@SY!<~TL7st<#gCFiF{aOG)aeur3i^P? z9%~!>i5&@B83mKZP1t4%BL+od+=8a}kY1Tipy66NPm1&8ERID%#)_z;WXk#V!Q ds-#gg!W*~U-(r$Z#>SXLXoO7^8AD~@++T3WX!-yE delta 1043 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 diff --git a/src/qt/icons/cdrom_nomedia.ico b/src/qt/icons/cdrom_nomedia.ico index ca3c58920b6ee508bf766e1c514d928a0d7c3a5e..8b7e29f760dfe8e0b1c9734b6b512acfb874fca1 100644 GIT binary patch delta 947 zcmZ9L&ubGw6vy{Ry1$a{k93p9W}DsArfM{%wIC>^L0a2lFCvH{gzo|%p ze-jnSMyGuVbs>obNykfV7+X>=OhLkdR0{kAO_O*ir{s_t7jme`7n!>*$oQ#STBAW; zYU@*&bIRn-%N$3#Mg!N(EEZ)4%Z`k4p&Pdg@qAHD;kBjVg_y#=TgIYgW75(S(IQJ7 zVCh>zGEX_9+?0!j!gk(BHm8=EtSWZmep(V~L##L%9HmRxF)bXbS={KVpsJlk%NfQ~ zEd$XWK`mior~f?WsUIvQt{&IIaL)+CZMt4VjE&>NkS7x#$32^$#F&ohk88~b$&)@f|PJ3@NELvja?~+dHvi8&$46UTTvo~hL8HtKb~fi zv20%$y~gD@WTWZX_(Ux0j)OHL2SZ`}6k^&F`3y6MmY0nfGfmyJ@!n$^6JOjc@}eF1 z3Zc&7j+n-Vl11I~h@XrB!@^t7#F$7a-2OIG9kf`YkR$Vt9yW{vJ=n=;at3ZIJ@XGS= zmEOZO6=F^WMxW=2VM(l5=^Jb~r*N;Bfve^MKNle$RWn#tlM$dAo$^`w0z(^DZvulw Tz4@-VB4*gf8TrpR_@#lrJ^Wl+ delta 987 zcmaiz%}*0i6vd~VLg%CHo0$%!bjr+>mdZz=s3gXSup>kw>`0UZU9dBu^&im2g&P*8 zISGl0gq0f?NJ64039>~O4Qz=*T)0AuE7{0+-#|gxILS%o-gn=;bAR{E!uZ1YN?$W> zwvA#W*52fKf*|0b+lQI3gyVpLB#WVkWx&EJW|)Mza0C;n2)?mS?8Q}VFdb?zf~?d9 zr#*=p3uDLXLrLqvR?xswJdK)`mpq|T;esxA!0Cu$EvRErl<-bZpeC892UXEq8^dKc z(M+ZEAS&lk*Hyf7HOv{;{cQtQ2rC&CzvMXH$eFX;ft-LHRv;-^6qPRA%NEF=gn7k; z8XByYC5(hLe9HA=E~E_~Ii9y4_PkBe^D2Q82?B55^8$1_S0iq$^IE>=$XT6Lw*mxh z3MFd&t!1JX$W_axA5PmuC6yHaB`IMh9l>%ehBUj1CCkEwmBdrleM*tmtO&jsl1L8l zlc3aDnkcI1Y1h>gc0NP=(A&@}6=7>pgDlc9=OVt_RzCqxVp@vfb0C7>S^|?47j+YR z+Mxf=`43nsZnz4*Yx%!&&3GSVluKb(i=d<@@r-oMb+PN1aAXU1#=r|%!E##?U)^pL z#VGC@F>GW^vae&_$k6~ytY<8Wqga>SYB_}0!6p>4{k%imiu11dY#2rro$g2sFO@5l zdxGa;s#<1zMia-JHO*#UcY45Ba15M?4V0F85tmUtsE`Z?O8Z>9Csx~98I6&QoL|_;h4{EQ6#pui&8rGpS(xTwW(xyFlsA%e~VCnizQWPBcn3*@RDNVe5 zS=4N*S*cC6_>y;6w~}_%WmpO&@zm8NI*so2jK$ETp1{0n;kMd>?`j)vn4R#w!o2^w*pv0VQrPo~^ul~iH3ZS~M2ebw)t=Au!X!o3D^iq% zu(v0qX%jALBY2^W5q}X;z)G|i3tKzby0=O z!DaqsB=ODd!~(hJu^Gn$l0h@u`7JrL=+m*9cCb^|T`|dlPsJ;f;houyDSsLtGYaY> zeR!zZn24N3DUc{^N1lu4_DO_Y5}-t67s*pq!Y4`gtS1z+o>-~|A9E~E0^~`EqM(o< zinmL)+ZU+7E^Xc`tXtbPSWX1U)nj@Jqb!Ir8$<_F@s?f2l%BwRQpJSqN7+^IS+1|- zdVNf5;j8$1`-OMs0}EZGR9RCGOqx_2{@@Frc@E1tUTJZ zdVJs`xJfZ{e4N(kt637`T-OsO#dU<;SfVJ8F%rG`gh zBg(prdD}p%k-{md6Z4XSyHW@Gq$X&A7#^A_6se!6&EuEk;8yK9^aP9m9Z@OO-r>6) z#tc^AK>vZp`@oUE3{!#RU`B`?yv~qn$?OaEs2kUR@hMRMoU1a;jR`#Q9I-JJ;Lpl zjPrJwC^sIO6Y!eXX)cXfO+lNU#31RceGFeRiapz{g_ji580jV!8H`8z zJ(I+0&Xw)RQ+{BdT-qatwzvtlOip-m$pudwIl}!sBARo3i4^OJqrCxgjbr;DzG9QLG4hVI$^q^~!k1s`D$h-O{T( zjl!7p|I6Vjd4G47?EjIuTs<&Ox%&+Ttz|kG@%{!3Sth=z#@|Ag&1J&? diff --git a/src/qt/icons/floppy_35.ico b/src/qt/icons/floppy_35.ico index 9f4412fcc069f5f23388e78a3cee2d9d18a8bd94..724aa0d29bd0145bea161937539007d35d84843a 100644 GIT binary patch literal 9622 zcmeHMJB}1V4E0DWq!j@hY_Qo*NXQX3;v8rKgv1Rt>X49Q5FwF4))5Ec09>K)>z+63 zu4z}hKWHYXkt|oa{Hb!;E~`gmCpU6;CyMv-=|<$eh}_@z^PjIozANqFp`U-b75VsD zWWVp{-&F3e^1f9W9jb<&u1KC#&iN&!F9G@WEGY+1*BBpY>Ccapet+%&^TXkA2GH5@ z9C^V9+L(OPGzkEHVCb7G&oj)Gr%mpG82jw@YR);ffBInxd*@G6zk>a?ZBqoWw^933 zwz=-eM{I-V()M|8#HaY>`KGXQe#Xiaw&&M9jOHNYt%M=l?2_ijGJq`VjFy|O-k@IL z_f>0D;kTsD|MJ)>=Cf^yf`0a zJxu=t(;pb~KIl`fEy1q7sT|GMamP;HM(bA2=jqE$hv#*FeH?`ymN8zr|CkrV%#S>- zqH{0)ynLOaTYb96#qW}>3&;GGRvuF$Z?rb7hembb-O?6X-YM|i`k=jZ;g`QbTg++h z>|N4@u>Ra%oI?l4xElg!_FXKEp@VXaH+#>}W$9eYV}&{_-Fri+gZrP-Z}(XB_r1CG z1N=j<^rimC{a8JvG2^d`lPm_k`(>=G!LWBR{n@h;o(B9At?eEked_uryjh3wcm_|u zx34I@?%(k{$<_bGZy1Ol)&=6h`$9i1#S{K7)yl|P9{+lV&H60ltOe+9Wv6}D%lo0E z(_6B3+^BB!VS9xq1@>VLK3w|0&Frg*s4nhi;GfJ_QC(+zR?pZN`y`$BZ!y+NJzQxG zx~;B3E@&)6H|^(ZlmpLL>~bA=Z2heNK<=1t!H`>OKR;Ks-+vRgeyIL8{|g}YHjY2U zAi?^brb@ld__9>p6xqJAcbpB}1K9|ql zLCL;%gw=H8gOdHZ=Zf;z^AEpOx&6oLi*^*$`#<%BHU9nnH=56L`D*_6?+#+G6n{?k vt|x2$vu`WepL?%S{^i@7cq!-RkFo27?Ry8nyiohnrx- literal 9622 zcmeHLJ&qMI4EAVONQiLp0De-P{oOJNj@<^p=QjZx8Q3o)LZHxx2f=`{(CG?_Ut@ zc8B+`O!tRzUoj02nZse8J9=O`rv;wx0s8rgg2FhCp#~HmGBFOnzlZSaW2kP73pz`W z@qWLr0?3N#m&ynIe=onr2f*>{H?4^+3*)5yL4#QE!0=4bV-B*tSbmH%#>vsAVi-JI z>4k=6f#0d?kL5Hs&^Y=@%uMU8 zW1O@2ya^94=cne4>=Zva%M(sbUeR;!?bq@vD$ zoCgN2!$$nLOt%y1QmpHa>a(tUdLx&7O<(l)x+GyAvlJ^h!?TN$za?OON#N`%|~A8U-9{g?XLqqjcJ z$uGIFdwui&=Km=Ma`ETI@6!3|_=k>bHxv8NBe#F6=c&er=c4b|wdHHgsC=!Cn|zL=&Hl5qq;axV{6B^GgANLf f@y}%be+JkHV0pHVl}Fr*V1A7FJ#d*eucEcQ6k3H;L;7l5I38Ri3sGaXEB468@1JA*b~p0e-rh!Hsr)Dht|jucfpP-tzxbx=K;OlF$_sM(88;Tb z1IJjbyv!L-Udxgokyi$DTn>}gzkjv7=(e@w22xwQg+a?J^~odUIIbq2vzL7({j`JJ zE#O#Nex1aqF`ykRo}ljxI8QOGV&p!9?PlC>xL>h+z#i3EBsQ&ek)AQLIrQ2fdXQ5~ zKIS0FXud%m{~4dyo77AE&CS0#7UMe1M=b5t@gtw!SJ-aZ8#QB%PuA8_f3?+2i5*^}!@g3ize?{IY)KJYrk#0lV5yK7Eb~Kj&EO>}$3E zvH0o3zT+b?ksQ?c`F>unwnn!(hj~vhXyIobIB%4$kvq$8lGeiSaa(?lvuNSZ*)0wv z^V8VQW(z;K82fC|{ML5yn>tDWaT9;W{Bl?2&OnE1_UC+(KF&4DAIg66_V9~ct#z;c zr5xtoweU+0=;u<9!z(fH$NxiY&^G`fi!=0}11sR##eh2+?_q1;29SH$zz>)EDbT&0 zUrV1CTf&^S&ZXSA+4i0EmlwGImi8R=`}=B3Qkegxi+o)(43HgFSX$BUxMa zsbBVXeLrKLzU$lPee2ivXgQmxLqqJ7zJ1Mq`dZV^TpaaJclgJOzpRIUp`W=HJzjmt z`6qMDt7%h9;W&v~rbbtK&-V1${vQ2eC(j*aqgFG5b;tKZX|)6cOr^yn|?&gpkt zPP%*a=VHDMJ|67;SMy!`NeprtHQl@TPwp0IUvtk({4d2w)(Ux{k0=(a-w9=V_xzn@ zss560E$@#0-;H@+8vpi0J0o|@f6JOGjp@xl7YAc?2ox9I{4)N;hlT<+_z*Dw7+%8} U#+(By;2O9G#<}3t1OAEh2X~QZt^fc4 literal 9622 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 W3!A;j(_bRb|J)N~=u5|TCw~E#Gm{1Y diff --git a/src/qt/icons/floppy_525_image.ico b/src/qt/icons/floppy_525_image.ico index ae3a4d8a4c8bc219dce35b829bc3178adf8ed852..dad67ed6cdc4d276785561bc0e76a2ec58bc7913 100644 GIT binary patch literal 9622 zcmeHMJ8~N_428y?D4rB@;X<8Mrc9Ymt};GGs!VPnm8m>AMk?1SbqJrsb&5DCZ~6Kv;5#_do#TuGd5px}@uCV!fn~mqhP~=;o&He|}y-~V()^x+lJ za@qI4u-y~Sea$v}$q4;8E4pR7f);r0m?Ysgn@!kmw@DeWUHgz|z-?$RSfb%mfd8qc z`S0#R&;ncZOY9#XL%6^1MX+k^1?Lp@L(C;k&;)7(Xy_B)63!aycT0FbY zq&CiY@$A@q{EP7$>P_lS^uf6zwF2$c3t}b>^JJshbE*_?z-odAEchdP4L(}`WDU@m z?+Mo8;n_1|tZ%Wbf7-X4>(>5_;o-g)FMSVlQ+SBOF{1PPgBAfoS+e4JTGpn&3V3eu zD>S`fk>}QXewVIjQir8FiwdzGt2cX}f#FM51Aa*Z7XzR16G4l_N8%OJbZq>+{e?WW zz)w9l!TmSm%Q=@wWpvo)7cof1=TE>#eun*Ob$32^{^!(>fNQBtOSZ^p7wX;XVM~@<7I_cb;KOB`#(Z7v z9;2&0K|V|NgPlA0eiXmEL7bcL<;e16k%kF;5_~)Fj;FfuK zCv45{y=Tg^LNvIan_oY(&iwyx{B;esI{&b*#_C_{PxSAsfB2irk9qpsGS}SQe-D=R z#WZ+31O6%DmptLQqx=!5z4!1KFUENCjvI!h{3&i=<>a5IRr7n?&%qyyIe4Yztl#FK zB>v2^7dznsOASA2wT0wz+x6G3 z+1eonxjyLlw^%zcYWeLtYWubPu*=y~-W*_*@*@YQkevM&zVXKfNB9H61>=m%oTl`a WW-JSq75@`xJ@60bz(mf2J^d4V1pU`GI)!}j2*irU5b20r=ow68#^Waj82_9`XllkojU|j-@7}y zv`*4VcbC)!jsPKvA|H7qB{>mU$V$%71>;V>tVBMF$i+po{`p$u2V~oAv;O)<x8|MrRo|~iu08e0jGGvo6EkJ6HldNhTKQ4%SUfG9vn*IE zSM7YYbZ)fiXX$C0^h@Cu8wF-e=>f}32^{CIX*G_-uaySO=I;( zy$8p{Pg~-q;y6Wo#-zE`_*JHP(J>W2_d?7@^W`C#)#1J+SK*I;!y-%c*k7*9+{#7P z(Ay+=aki=df3SnY8?gQktN4%0X^7`xEDw%^HRbsq%5ChU{OA7e^7R<=?7w@TmK1~a zA4+rnJN>8qm_1IJe|tyf&ZqXDdf)V&u;c81+VjV{m(*a+|8)5;$-SP>f02Ls);A*8 zKlR$THZ<07Ip5!6sCy~#ukRG!9TU$1>m~fhd^3pW_Mh^d>z{WobO+Txlymx3%K3i1 z`(abZQBwcbM%{JB68{5Z*wo9KYU$%wLds%}w;7i%c PHEiy{dIyBZ590m+GThIg diff --git a/src/qt/icons/floppy_and_cdrom_drives.ico b/src/qt/icons/floppy_and_cdrom_drives.ico index eb0ab95edd9f013ceec3b1252cf4a89417a3be5c..1ddc61dc5b2bdf385f3565660272b36e4d077752 100644 GIT binary patch literal 9622 zcmeHMyN(@25bf1ktPp`6IB@0-3HgI{g!l}!0Yc&rNIYbOdFUSyy<5svc~)M$DDb!C`)8$mT}pZR((m7WR?2U9 z_Ue`2|NMC=-+fWa?XBPcinzbg_DjUz5(xeruDn6qj#3em?KFsKs)bhP0+iEm5XZt; zncouu<=r>JS=SQW9>Y&Bid~5po@)->)X!r5;5B$Hmd|L&%O5}Xrap_y?v+2`4)OJ` z-)sHz2g6c)<6+DgFPz{X<6A6MGFNO5V-ddjA)XqhXv<9VkMS1ASi1@g*HqYl@iU(0 z91%OjH;j$=hlhtsGmOxj`CBex^N@BL5pK-KxRB!BV1>WyN#K!2qP@NCL#*g3$dbp zz!Zo3=%>f?bH;Ric#yGJ9~#HG($)vtj5@_LVg(;DyLHg^0LQYv2$NXKKd*(6{T80u zXOFhF?_du#T-M2=F9-DnujPqxTX@2v-_nP=#rOrLw6O_`X_Vibe9@k0(ku*(Z@XW?W1Y&3*=u9Hu$m97Eq$F% z+z)Pm`ChM?~Os$_AS;W`$b&olF$8}(2rB> zvEEDM&L&OS*Pm+rRNmH)<*t4xuj>RWcp0r5>u7hdx3JpTg!dWWTR1|OuV8v_eT%d7 zg#|n34E>3;2Hap z`P*K%#=&PSS-Y@PKQewl{~|ArVNi>HsBWR%csbv|j-q*O?d zVbdr4eEzn$z#ciQZXQF&poVkb>q);jgnfU1Z@B8O=~VlyKl+gO9mcHbZyeD6X!xTR zY6SiSuQ8+Ftv}&gegj{5k?-)8Cwb`E%n$H2H!MHo3l787IO7@1YF-C?y^q*-fgP*K zaL6MwbpPl$oPYH_D*UFKt3m5O@aDR})^qaWI{Mh*OFw6c-&^^o z<70j>YS1n$(;2u8oA(>|S%2$88VhIk&k@`19hdm6bn_375tQi`;}~% zwZ3~8f7bPQYRC)D(Imt9ai{%@=YX^~T_ofPH#MyC^ZBJ3Hn^3CgWRU;0u90K9H-}A z+B$!39>@(7w|s|bwXRF!KGt{l=V(yg4`~REc};YD(AV8B`87Y5Uf9GKHK@+<=2$%+ zd3E3OFZS7(tKAy6z6~1e8L-BE+Ty7}d}}_%>D;Jy0?)&CCKkq;=QCim*!X{gFpg>n z{`@^du@kUqt&}@ik2p7yS7tczF0=d*%M4t+(pX3feQSe@xHhl4Bm7y5 z_%o(6JGbSg4Alv(342UZvT zHu4qzV`uZMLGw}E^auF|?$!Qhu#IcYhqL%sxYziP^CX57 literal 9622 zcmc&(yKY=J5Tzg^Mv%fTT)4B!l=%a>3i27Lg2d|cXtY_*KT6-G7*q2z7fvY7UwQH{9lrE2l~P*HoM)lpUM2-Gk8sxbri(q?_W~B_&Md%)yhOZ zi_6N2pKv?<{PtC*D>1)MFpwpP!$Xv3z}! zCyv=3`m~3(a~_^SpBQIn=XnKvmf1#Zx1Zgcl<(#I{xIiv2Sp~BL)t2+PZab?=o@8v zlrz^EEH}2^aJ^#s4Qtd5llctYKEECuV@Kh{@dQNwgAX(Q)wsZ6B9^3-XFR@R_MR2o zWz2vjOy*1l4G+Syx@xO1qwUQ*B46j6hy_n}TkbY$-D1wQtG*xP?d@bNS;w_RcEuc+ zWgb5*@2_K6U+P9omKA@sMJzs}op$lP;4|08-acVk`{uIrAucf`vIF&;|6FHneNlbj zHQ(GeR9iATdn~lDUh8Il{lwNy$mw5`D_IOZp@n96)%{7%YPb5EN4m1m7Zp9i}Pti!W+1$f*q zrfF%csmu0|TfOS$F|2X4n6SMU^nLczY(MV^)i&WNCm;H+*XtnY zPd?eQh>v|a?0dcawG6C2?T3%`5BSyo-VT;;YyXRR-!^*#hsD?NciOKwDUb0V*sr-! z`JBUI!nk|v$yvuh*xt8{FXHd^tM3*zW{3SzFG_Hz;VAs6&L6XXK8Lh(4j$+ob-e0R zD9bi$>+xy-i~bG@zx{6)KJg4&xnm=K!G7$YoTJ9$_tOPzVMQMzhmQ~8xAFHlw=Cg1 zF2}v5IsPZv)*|`3+J}VM||&3oDn|vma_gY z<6CS(j8&E%$BQ_?A11bupL+rQq^uYh2(cvcNo~}V?hqK2`OPY4T=YMryEuCt;@ouz zI}Ti`&+^@KwX-kfE~G!J@eFrt=ddI2Jcj5THu1ydr%7(#mffF*ji`u!mH2|;8CI0P zF!mqS5ONz2xn_|Wg&ifWy~x2&xqZ5Vn>GyjS$|s_7Pu9Io!n;EEo^Y^!ZF7@a*z1c z-sIPf1GypMR^DJ*Yq3k?-nTd9>)4>U@3O&djPFFl2m6|G%dfdH&V@~k-UhW5yjfrM zJ+I2nuRE-A-4#~8zcv04v$Mh4fh9fOhwI&5{l(em(9=1;>~ZC+iEcF+K1#!!_`qlq z_A!3D+RFy$(r@lZh66qRR>8Z>X0tJ=ytJVg=P!MWUi}_{IN1BXD+b`VZydJYmh(&F z3;A~GkNoF32r<~#|M-1GcZu?wNxAPV@$((CHuzBPM&)-Fof{f{`OxRle?PzN&jbB_xN#c>+#DNEJ?B+v-t+R{8P_`HkX_Cxm-{bc)oK|JIXuW@0Y=00opJ>8LQ4=s0G?m;*8e?NZQmtn*I$N%yCujeoRj)Hk-{`+q# z*N(sIacqdou^LRdrm8uAT*1#d;Fy+cUa-#QpZJMW_#3XJ0{hZl<~j%S*~ZuBp13p* z85?`%`v75o;kfThbWMHc4?z0y=U;qGc!Q4$m-a#803Q+#CVoCxPHdAL;`uJ*9^?_^ N7}CV6EffAQ{|6$pFV6q~ diff --git a/src/qt/icons/floppy_disabled.ico b/src/qt/icons/floppy_disabled.ico index 439996c81512381d3ab4e3d610ec5f056a725b3e..ca190eaab7e291147918a223d1eec48ed9f6f3ac 100644 GIT binary patch literal 9622 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 literal 9622 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 F{{aa5N+JLN diff --git a/src/qt/icons/other_removable_devices.ico b/src/qt/icons/other_removable_devices.ico index ed5db133c625430c747c550c3528a2b4c1e956c6..d26fb79188cfe310480e849a8a79892442fbae34 100644 GIT binary patch literal 9622 zcmd5=F>W0<5Tzi)Mv%fTT)2~(04Z|=xym^L6@~#H!ds>ia*QBF0Cy>M2%RHv>B0!} z9+!`Q$Q^RIUviKIM#Ik~-+MFU4he;D5uSxtuLAsac>gSfpF;?*U$4LadLF``=zH^K z{r&5AA-wxOgzM||_wShZH^%;mIcNf5?S~6*F>msT7&l`ZxETJ3)><6rU4@a}KYWhy z?jhma-rhzTv7&jGv4``QWr?zc>CZ2*R{U9m)toSLf6_xul_7p{a2(s#*k|Tbe478j zc!_1^qkVsWANj}^Y`iP{ocrlhcfRH(FKzAoyF2KDIsBX_j4nUtQiFrB$zSHKV&^=@ zA)^kO@+F`9IhRkBJMk+Y(jqMQbyod%%{y{$H4uwNtVEN(hk9a0oU1i&uVU zJ_Qy1XpY(&@#y$+5#wh}lPwuSK0#tkxP-loak*N(+N?7uH>uvRUh(-2HR`|v$tkx- zybB+HzV~jqv zlds~{_&uNT0I=PA)T20v!*{U!~t$b%@U+1x1jxQf$T@>8uFe$;i?&YNxL{gAMT z*BbYNjhDFmJu=IE+Ha>is2bqu$9SC|o=<&NkJYbwGJ)@5^LU=dXKftlCr*!}%BQEF z*ovj)$oUbz%c1;aZ0w&??upI(SPqP9HCg+Id?4#tZr9^1FMuQ?d$8zsNag!atfy8*xD zTNU&*crj@Ir5tz~CirJH^!QzFozIi}Ga9D(b@$*}9N^#6aEPDWT#tkNBMnph%DeUg z_){%y_aJ_gt7rCGC~dp{G2h*L}V_*F|L^046^@%J>a z{|pU#+*ku%sMft^xw-zH4KyTud~Z#8lE*u(JGuF6_^F5amrt$F{)& zxbfrii&LJw+K=jMHE4|1Y2`k~PfTzB30pDuG}!l({LD_31Iw>`D|UR literal 9622 zcmchcJ&qhV5QTfOf(^rg6ev)(n;1~&8(5Lg;mEM0J7~w514-~P3&-3ethn<$$g#_#?dTN1Fk zIBs|MVH{gha0^ZoquMjp%I)oK700yxWUuz*GrYle4Z{pa1U#=}SM1@Ht+e-*=hf!! zZnAy*cE&HiWm|QyCjs(deEoWF|JpF|r6uLrf z8I=alM)5P&WMRJr1Dqm?Rc+}e|NU|NbUBV6FDBXTVa8Z@Xd5%w_}$fBbI#atjl57Z`!v7Yb&PXF}SSNjOXXx3TF245T5+XT5)GQCZ%FF;%)gSY=0K= z?D+zNvJ&qaX7;c8_UhF%FU+SnH7E4-B(0f)cp865mo+oPBj)U1Uc(0iM=bGW9mg0) ziNo=&QP(E@-o_7|2eP$3y<4(wjTMLEh5hIID&rSyhGlHEXB;-Zi+=$7EDrM1z!zrL z@?E+WL(LCoP6r?RjIFk?eN3FQlB0@W&Z?IG!VqTG_4%3j?xTUXwD+yyuiOjdpLF)W zwok!l{WIrVM0=&!)cu45J^!Q4G4(vZ;4{bg8RG<#_7;i!86RvoGCu8MSN5d#=0eZ> zYT=Wo75sR=$aT+kj637Aw^}g-|1)N6ckq|@8ul^w8gP?DyjDGqH$E?Q|KfkVm%w4d z-K2XziQ~=Q0Fgy;4&{d&1zE+{xI@^?EBMi$V!MhT#~%+<1^6LyAR=IocAn`_h zf)A_QhNt^M*0cB089sFRjhm8rW4r0YG6z~4P2J=V+(-Km_>FLOzOqJVeemSY8g6ta{upT2-MZQjn7LQn`!I?z>`; zw)r@UzhD_LbF^A2KmHTHIFtTT{5a>laIc8IF=$__y=Jo-czHPT4r;wdr48e6l1fAUD)-tLC);mh1qK}ySb^$-=CR%L*4Cd zUHa76AN%_dUzZ=!=d*ATtIr27j*t&s_NmV#d%mn&5B^urFC^QY z$@B7kSvCU7?dt;ic7I>#horGRhU4+Ev=CzSIYRbp0-9GCV+LFSIZ!NtIgr&@LvB!J z`aLbn-2^b?ff9M{GuUpb{f7G$(`W2ahe$*A9p68$*Qem)y98V9YsGh_p)4OAPH{^% zXojoxj&j`MR2?O>lKiF)d0Y;^E`?LNHFu;Lo6TqHSWVM zX9`~oXDXjK{drTF?I)P@T$^OP%h*%f;se`2M#QB(Uno{oT!GCt**G9;9)g9VK>KM?!^=#meqYrM$v*tD zLERXz|38p;R$2iWz$4WMpg=)qt{is)Iqm@p+y|_I4X_1xPf#Tu%G9aqh=w(k_KD}P z8E^;a9G3Iq@&waUo};>k%f0aw>@&u|*R=hmYjBb6=Q*h3Ki9!2JclFsP^~|$1;+=i z%aDv*VeQ>$llBDP2bM#9z>N;&amv*_4!TlByrWhmd{QX_B%}In)Q)4}Bjr)w%Y^ z^r30Iq588A^*eKF^DuNhLO<$z%wH3lhcWCA@nJ0c@nma@h3XJH`Dj zOwGgiu(-9iAN^hF|G$*qSwnmnI{u;d`Si%q^*!3uK8AhyK(0QZ{yCjz;K(z;>w*=K z0lbI!1n@562k;XpaIKKz-XXUoFb6W+NnGJh;u3cfQ`|{R@w$*hYTCG OHmR_KtUA=q?%zK^(=kH; literal 9622 zcmeHLO=wj|6rS97`)o03TquMHHR8g$P~5qa1R-fxLXm=tKvRfq@ehTFiZL(QNH;<- z5J?vP1i?s2S1z)sCLnh2u8S_D?yb8>Ni#j)y!j^QjrZPn^Gv$Rz{#02=li~MX71$X z5@Xs-YIf~1;(N?bsWAh_nBBYU@nY4OUuCVUs~-RSnK3`?G^VGg9?uK!tzf?tj!Z?N zzAn!62`?VUjvY%zM@RR{x@GR>&70}?__$qOUbgVa_4oH{wyjhud-w0(pFDi{umTKm z)QI_do!H^w;q=j?M~-i0pbl|<&b6=(F0tp&pHEMnI^}w$Cis}g=Ji4jvGkwby?fWy z_jy+bTs;tLKCy#?gXxnePr_Mg4EVYSox`~zK700TA)h_O^~oO@8A<2o=X2`=r=OwJ zG|(dd#*G{4bv8PX;{$yZa0QZXL z8$9<8Pkf9!bm)+)edWrPKY@vj`=>^nhaT22h}E8Wy~a6m-Om`Yx7KwO7^>Mf9$pPw_a=Uo{`s$d*9%F zg)u4bsI1Z5-OWC6cBZ4FgR$Ea&ereE<$<|y;Q}#kjT(YW78Vu~;A0MWSj*Cr-?`6` zyL9Q&s=zEX#N!>%CU@QG;qZ|Y<6syG(F#6 zWo&FL;eAFQvW>#~lGmTV&+h)s&d$2$f%9ml_u#>UhUZI;)JdwGn6_5U2zI>TXOiVaE_V6*jR;#s%ZWzAr5F39EMjCeJ&uJY{{~ggW z=c48A_K5iJZ{J@3hJ=PTPxyLlES2vX#{ri*zjSsz+gzwum_+1pntz!fzRPK>?NlM*30v*Ob(Z4 z8!)>Nro|;~RQ{ZalE2_0-&P^Yp>fJwcaR zx(3%YR&!g?M~^UFb1U>wW3&5*UTo^j4Qp~g8$F*`d%OSjcS_dTw0b`AGvi&%su5#> z(a-n5fddWiAD<(}d9Cj*zWiVMj z>9u$c4E1Fm-v3z78ZkePvpCe(-zDrV_E~(r7ULQ78N?p>J9qAMEG{jjQ!_I=iO=(z z4~&kp=7Pa@Tids{ZY8zF#l-k?GtzW})wL`zU!6RO?;*#_(#%`?W^S(je4v$OLhPTO z4$m-4XXV6?_RWa_`{sq1`Q83y1~z1`P1P=&L|MhYGk=S9+O>(A`wr`o!hK@=4jacm zE;lwZ&t1;UT?O7b#3GxCEm$w?1e!&<%+qJpDasWVmn66tdAi6o+kcTpnfl;=Z2dfq zGW9d|&wiSDC%>8dhgMnRnGw&p*`9Si?wv88d7cN3^~hnY^_$JX&C){Myn$TI(Q&hy zI_9!}2|j4)`p9e3InB`;WorZ1tbW=3Z&iK0cg+9q z{m1orUhrFe{y5V-+pfQT{@eF&{hhfL@1MNiJ*;o$?;o_ho`L5(4t3(eo;*JM%|Pte z@LJ!<;Cn21)`uSJ(d(QP2^=*qU7J0}p0$eV0~7NQ`#wtb06h1@nz4^-#CaXJTHiIH zerV02xuS&WM)x1@ugsaSr!1~NgHq>Dkmj&{*igYl?^SD1w^a|VGS;eoQ=Y$%{)27A|O{{xn6&t?Ds diff --git a/src/qt/icons/rdisk.ico b/src/qt/icons/rdisk.ico index eeeaa50eef808e3b753ad3b82a5f5a22c78138b3..ac5cc5fb0cc368975b78f36f399ac34bb9d9acdc 100644 GIT binary patch literal 9622 zcmeHMIdT+15bTXr5J6xdLxw!9iOCNn3tLaXB6!A_m^=du8+m$$UcncZ%IV4N+)`gN zJFFmJB3ji)Rc2Oo&mk#_vl#0dLYy}f?kuiw?QMQZ3-|Y7zqEl9vHN}4KRm>SG5Y?BbH{!fuNn~h z^z?MpBHpo9jc5K*k7wsN)d+qXPyMjOpayb#pH@6s=f+cm)Xd6ay)AuM=Q9`k#=d|461#?{SbQe7 zFwcdT)5hmKa#fvr4omtlpD^S5>p15jd*A2qFvt25BWIzJe$+VO*;0BhMP0|5a(I}7 zueK4$emsWT{Sa;}hqouT8^gIB-&^(x9o}2xd+VcpOINP3ezv}rJy2=BYxO6cC%@OY zzp&h6^q~_Ru$Wif8q?b+w&E!Ml+VaROe1by$v2)=#Zi3v!N!~-w13a&IFYCOfH=VD z!A}^q-aLGtLk*dAr*7Jsevhv;VLx#`*UtD-eN;oj$@TKsz4-LgGpBv($k|qXaxrt} z{uO+jzf!B!tEWEj(eDSGHyxMGK6qRB9-Hs8UXGW(QXWPJAQ}l4EW9(zrzOn;j($GeS%DEG_Re$)=7x(L&#@Lc=-T$SywdVixm*0Q68slE>ZMk?qH>dva)!#31ZrOC6 z{n~SfI(qp%xBt$E4)UsPY4{uXTe+harTkHgS`B*ge@Xrx?pFS_8np7qI$Jzf&wpR8 z@iVrx2Q_}I@jij|XI{s;|GX!Cd``n!{H#IL5o?6L>Yu~!wQH`uea{aqUc;2XxgP&N e2lLu`IlZ4^uLr}?GxEay|>ul}3O zCRh`u^_NB9jg|G)I`$Rc!*vL|bN*JRA#6^LCNeE1{birw?I!LwvR_I1#(Pv}%HzX+ zSnk9eeeoT!4D2cwePUU^xy{oYt#PBj&LQhxst>t?SThfOm2Y$GljbYJTo(7!HEi=d z_mpdxBVJ&P68V|wQjuZ7vmn_|x4)tF5@nNvI# zO{ViN`N;YkjUV>uDVM&7Fzos&)lsj+lXp%1VE@3qFPEFf4|uxQdwCoyiCbe#@yWh0 z7{g^e!Nuf#PcJTPLm%Zl@fmgC^JYi)VN18sHgp}th%TB<`isAuTYQD4cWioYec-$F z%#^qG2z*O<-xjFzU1aTihSLC-$y?o>y73vyu_&pkP`K=mD_$?Ys`BNHQ{Imw++>&+BVz_=`4ZHKx_MKC&&Hp(( z>odhK?U|+a9=?n>^f%{VJ~y$w>-!o$-c7u+=#=;Cs`a?^!!K=ljzs-@8t-abI`LYwhAM9Jz`ex$hX$-4a;?4OkzzR&rV9U^0lMUl=%s`{*Dz&x7 zP}JvGHHpS*F_C1U3=g%6ZXD{aI3@Glu*!MZg|AW5X>6Yf+_)WdPe0SrQ?$COdZq8@TKS$sGY}-1@GULTL0b@vzXKPNm9-9HlD9*C~@{D+?%(fO9>RBXe) NLQtcXlJK_7{sX*KkJbPH diff --git a/src/qt/icons/rdisk_disabled.ico b/src/qt/icons/rdisk_disabled.ico index eb2dd9d1bbb1411bfb07264dc26dc4017bbf89eb..e26bf03f8d43a9c9062fbb8ac22f77273b9df1e6 100644 GIT binary patch literal 9622 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 diff --git a/src/qt/icons/rdisk_image.ico b/src/qt/icons/rdisk_image.ico index 82fd868fdf5026584ecdf6a601ad377ddefa294a..b19fea250559213747dc086b7f36d44878995c16 100644 GIT binary patch literal 9622 zcmeHMF>(|!5R?lSE{ebo95}lR3HgB?5&H>56uggk?Y7-#nkzk-;6V(DI~&vUY* zm2`UtuCl6z(Mp=`(P(zGKAbyor|#myL9gBCQ|CT7=Pob(^N-igeaG0# zom;Q{^EcT2#M*bTK^F*q9Ln9muAz-sJ11GVVHn2EW|NhGU9=xFjkpWj3va9Gf38{n z+gmrLq{V(5J;wdL+fugJlb^QK4-XHMwAeG2vX=uX`w;VOjCgqDr2n)R2FFtNj2j#0 zXv-Gc6N{3wx3;l8u`mW(Z_l-{(8f0L%jbX}Fdp|NY-`It$E~gGwVqn%i{;yW3nyhS z4C#`+eBj!YkW(DuwEFkSI9eI->|%L^u`|f|t_-VjWSv2|nd%Me728+TsK#bI&-%+dg>KKVq?7?t>Td zXL`qo$F>ii>Zoez9G>_i{iLqe;;BZ9S9#00+4GQ}953xxcw8ea>Kq<%=kQ{z5*~f# z`jS|`)KB@xG0X$YOB@f)3&ZLdkI(Wchgpkfu|jO7d?c>r?Zp$OwDw)X(LPgJ zK58xPQtgjhjj;?Eb4j_z_#FhE#&;Q>2i#}8x9|z=-a~Y6eZ;qPN1Jj2cCEUKiZQeI zRZTzmQjO1dy|$761wS9HLVOgr9nJG?X(@cYJ1M;{J~8nYZNKeR_obJ@x4zqWEQKF( zcITdMx%=f)9Df@h#l(+!i>3S*HgyX=`L*{*<1v2^i(}4z%`+~BYrSspBKmMP} z24e%nCFKm`=a3cTIwN{B39bkL!4m|HxLK6qbrcgA^2d#-(s{JFg|2J!xRHmMlw zv;Tj|U*fj=kK+)>pm+bYli1%Plz)#t__NU3CHRSD^Vo8x`iy~HZ+#%vT<&XLd$2mi smm0G+wlC~CJ^sQE4F%cYhll|JoH;qensdksat*nIFa{YpnSST^3(t*JLI3~& literal 9622 zcmeHNJ8s-C6r^DzMv%fTT)6W#0aE4$c9nCa3UUjpOcmr9L5kEVbqF6|PY}4=Vi9JB z;v=58Bt=SE=K~X%rKIJX89x5xg^f8eXXf(Kpx&5|XU4oU##~(u_di}3^BvEwuZR0j zFOB)|%9zb&xc`c{pJ@9AF}MW7@En!7LtI0#Xgh^0UDtKC@B1t~cQM{(3VDwdFT9ri zb0wv3Uw^Y2E%7ey;n7-!+W4T!Sb9LAzoz&omK>>gpYxC-4qosMZR)b*^yPbUGnOTe z*KHh``VihBa`+7KpC1nLPn{S#me-?ra^!&iv3W5*ngfoT&%C!{Jlpy4_w7V4^eYul zKS9Uq$9DhPAlUjJqBA=Rq#Y<{FF<)|>=1dm+Ip3To%wKIu@yT3sHRk;iKF1+@BG(YESK;&P zk^P*@7rZGh=3^~Ba{Vv<{F;!p!Fs&!V&1X8wfWPzAs5SNJY-BN=dk>c6 z>i&M!oU#w8{ec=O$a_n*f9A$((OU`O9fj>{^P~7ve&w0V3;QSi&hVq%cn&S&Ctb3* zaVEEdc+J(iZIToZZHGVp6@Hmhy92gB@6n+q%n0YWzsQ2`Y`wX4?_nG0+yU|)*71kS zbxLu5K%(aR*-n^uuK&64{ub%${ix-do}cv(_tTca;P}ri&-tG<|76a(`ib%%H1&SU z>tpN3df_bcXVNkCowh#zvGi-SnTuoS7qt`bJ!`K2qBiDRe9o-h|ExaWIZ*zH zzS538tl9r$-+j(q=Y9XRhgyBM^Ji_Uc1KQ5U-VKQTJ&|i@)M4`oIb}q=b=@fTq$ju zDCy@swCI<#YxGkdTJ&@MmI0XRKlNh|E&5EcXr<~}eeHqzwMc2|XGwjYHC+EKQ0J37 zFA)o!V&CZ_s~_{V-v8_R(V6G|<}N*p^RuM?9CyX%$5F;JS&x1bVC;(eQ*)jE=ISTs zVATHw`lPQarL{Jt&+p^-Dp53YKRWP-haB(!CD?0`pL3-myz0Gd_vl#0dLYy}f?kuiw?QMQZ3-|Y7zqEl9vHN}4KRm>SG5Y?BbH{!fuNn~h z^z?MpBHpo9jc5K*k7wsN)d+qXPyMjOpayb#pH@6s=f+cm)Xd6ay)AuM=Q9`k#=d|461#?{SbQe7 zFwcdT)5hmKa#fvr4omtlpD^S5>p15jd*A2qFvt25BWIzJe$+VO*;0BhMP0|5a(I}7 zueK4$emsWT{Sa;}hqouT8^gIB-&^(x9o}2xd+VcpOINP3ezv}rJy2=BYxO6cC%@OY zzp&h6^q~_Ru$Wif8q?b+w&E!Ml+VaROe1by$v2)=#Zi3v!N!~-w13a&IFYCOfH=VD z!A}^q-aLGtLk*dAr*7Jsevhv;VLx#`*UtD-eN;oj$@TKsz4-LgGpBv($k|qXaxrt} z{uO+jzf!B!tEWEj(eDSGHyxMGK6qRB9-Hs8UXGW(QXWPJAQ}l4EW9(zrzOn;j($GeS%DEG_Re$)=7x(L&#@Lc=-T$SywdVixm*0Q68slE>ZMk?qH>dva)!#31ZrOC6 z{n~SfI(qp%xBt$E4)UsPY4{uXTe+harTkHgS`B*ge@Xrx?pFS_8np7qI$Jzf&wpR8 z@iVrx2Q_}I@jij|XI{s;|GX!Cd``n!{H#IL5o?6L>Yu~!wQH`uea{aqUc;2XxgP&N e2lLu`IlZ4^x(K}yEG#7XxQ zyuwh`wcmDk?Q~D?c|r0>i?^%XJ^J2!bP|Yn@tehhMzA(_&$X2@}=2-eHy|a zvi9ng*>67&;msEzY`12=m%M)@_G`(JOJT5efp8^xjbq;XTByGKj49(d#+((Dm^nL* zhn)NS`+{SZL&*)5-*SmFJ96w}LV%0h$H&LWA)c6T>+@`Jk$-<3+laBAqtqvkK1zLR zg9H7NgIujC9Q4Tr>7hi;u@eogh!}D~VnEixmOe2xgtMhz%VoW#Pfs8@U`rq0@4H>x zQ;=M6NuOMhT##J+dH<||%CCMoBC-yLuKP7?kX(>?Wd6YQsVJP`;d-8@ah`|EJ#O}> z>yxYx4ZNFYea^_^CO&WUd8NlYc}6vkVkQ#TveoC$1NDjh3J<@%9GCZoJzB=`z=hxT z1zzLydxh=MKcDbhf6AHe6Xr$l#PX~$q(1GqtjT6j)<+MX6YjFU5G;P4!Mr}WKsZXI zK3$Fdg~Vn3>L!;ybkq8B&-4qbR+=Amfwi7ZTXV~k_*Q+yctq13=w*_xr%lqn2d0+k5 zfq%#MmV82oZ{*~?^^<%{H;#DUi2o_5Ir&-0JasXJ*{XtG|uXJV%Z zezg*xX(YS;yMlWeef_0I&Y$$t`;k7Dx%2vMMrAy+xA`y&VnEi>sL#kWY|rV-xU~{J z;D8(S8pMIe_Yt+Hy@mr$kN9ht>Q+upxf%}|)%v~GskV*=ol|qy;^A%0e~n|!-%~$( zS;Lw}PyNL34%K?JUu-mM8m;<0H+HW^7GJ%8s1qay8+=OrEdHo|eB@$- ztb?_ESen1*zy_%wtZ8KNC)W=*2$!Fc`fEO7@z;HSu|vo?Zn1+UE3_34>>cYPu_2@WUVUHlH)iq4gse20zths*jAf5YNFCn{Hdsyh67 z9gj25cds`J`qOGbPsO?BKJYf{otSCz&diZ|(*3J7@H<5t?9>bvH!6+j+Zhe_4?dgA z(JXXsd#=+_IrVTF1z+;(9HPET9{RUFj`zg!Qk=I-?YxetQ}Fv5)@JRsmhGCR&ckY; zH?P0ce;FHs{|5B7?;pR@ihJSKs?Sm8vfQuVi(3E0r8#*0p8nTr@cl2xTMb^HKAAbl zI$X@OhW#}hW)XjHt^R!t)Uu5E9-yK3UViF2zM%Tm{bvr#TI{PwtHE;6N~r64XifBX zO8>Rlm+RKADV6^+3wk?$|7jj*m6)EZJ^fRs%`9>E+T_=;r+;#(w-?E)Av~@9ujQU= z{gnRCr3uf+)_?CkM;v|D@Ra_E<^LSIZ+hRz5s`JUw+79Jd#z5mi3gurLzXX3WPK*4 zXM?W=ZIE1$b&sCM+dchzPBg(<|Kxd1>@2_9KQVA&d&KW?ZLY2U(SQ@%<68f<8sL%q z|EzyBn7PMR|2`HjkG_9wpYLsWB>t#>eB@x)5Ka8pubT?FkIeD(=S{3`@=?X+^>sY<95%6;r2`UyTl}a Kml!?(@BRge4M<)9 diff --git a/src/qt/icons/superdisk_image.ico b/src/qt/icons/superdisk_image.ico deleted file mode 100644 index b8c854fd2346860c41e95d4d51b864ce76a4e774..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeHLF>c&25M0AXj39+wxNvt@rpyoQDz%@GD#$OaGG(5TDs|l5Gwv0sQy5@&M9tlL zkEBRRcSZmcSg%BJXO_bisk6wLT*&pcs9(#s3z5$va&r^!f4>v?rG2-z@&5aJk*^;_ z*6VoxQ{(>V*pC{cmx>Vk)yciaHMF2($1DribzRtOHd!06i}4}TfV*%!@pc~h=bGhz zc#x2?miQ1N#?zDRC|lyek68HacH3J^JhWsy6G+7mn(s8i;(-(SBc2%OOT|MsG(1Br znvVw-EEjKMeLS$VPh(>|#(G1HZRBUp1O9-qpBu4lEUwXSV;Rr!@LXRVzMD63Qt`x~ zFU2zlj7=Fh$w5x*pU*8pt8I2)uo(7wCfUgmaU_Y3PXY<24%*7klyMHH^ zz~jEhy>D)Q$HZG=J#2opc+}kZgMFX4HTu<@BdvJgweKnF&ek*V(1&p~X0dSX@hp}; zR?NLwUW~(YVAy8yEY>iOK35&T+xv+*1&^5Y&|(Y^xq{2*=C!jqay(*vdzMwO*6F>B z+MSMhRMTvY;f%w%rJvC9NsZ^$7yXu=*c5-aPPNz7RM5iP*eT;O#GVP8XQaS*VpPpO=2G- zrl0w!!`HyaJU9nvw1ocDhMxFP=@|H&19)=y=x1FdJmgR6&pFVS@L2_@8^hOQFNL4O z9>d3b4J+mEu%XwBma0!`zyBsk@1NkMCcshPD*U*n$UEj<${(1_XAVAd^`13Qn|~^I zYJmA5N9x9XwVBr%sFDmn#Y({e8h0R#7uc=j;K>J547~}3;+NC diff --git a/src/qt/icons/zip.ico b/src/qt/icons/zip.ico new file mode 100644 index 0000000000000000000000000000000000000000..0a8a243cd116726ecc7856956b3b4f8233594b25 GIT binary patch literal 9622 zcmdT~J8o4m5S=Iy5u!+n6zTFBBuaLWRICG~KV8Lf_Ad?$|C<9QV%=a<6|lEjb)LN9vgC>koV9zCQT+{r$a5 z#m~byM9sDAx7)2t#oM*m2Oq>gQwt8Sd&DneEjnk9^_4`hEqm_ky3V0k+V@rBhdGw* zfZ1rD!>H|_@QWUJWlae`??In~=nv}`ThSWB^M}~M7A4I=vC|qDsqejY|1-tN=1#&r z!r<{JUuD0cG1l8_vr%2x+4aN``#89r|Od4ux`@-)Q7nueLnX4pm}6`sxILHzeO}>4v+iseWO@9`u6p@DtH!_a0q6a7v_Eh z{|1|apL6g^e$K_qVOn^+=J=aS)+_5aF=ao(UH}Wl=ctS!2U;+b`GE0Y;m0J*3Kk#- zykxHLXMZCtc^vv-9^8u5U?cM@I^dXC8n}x4?3XsH)(6~Vy(PnrZrzq{*yoF8!F&j8 zAv^ly4t#$-@!f@ci=WW+mPPKZ_xzSF6vS&y(Nyuib6i@ua&bg|uz$`sofAB+?=q_n z`{9g-t^Pic+Ta}dy%ULZ2JsC-Y~!QeyjBXH~RK~m7Y@p-_K>9+_?3|EA^T0 zzrVcdigy;dCq?U(p!={5M5_^=lLTp!ltpX0;Y{8N262LBWvj>X^V!!h|= zd^k3L)d%Z-3+FGNfyFlvuv~^h{1|w^rA2rwUErSNgN0q|Yv4Yb4->eL z;R9nvxh@} e=@=WbBRb#nAD9kAH;+WOPsD#P!aqFhFWeucK`CVb literal 0 HcmV?d00001 diff --git a/src/qt/icons/zip_image.ico b/src/qt/icons/zip_image.ico new file mode 100644 index 0000000000000000000000000000000000000000..daa8c7d8d6a51835082f1e8b80bc5eb03eb7631a GIT binary patch literal 9622 zcmeHMF^&{55cCPe3K84|7m)2GNQC@giFgOP0P%|(G9tt?5CJjaJc0+@3lQN22vg;8 zd3${JjAwQagg8sR?V0JW>TY{&@2qnt?x8z7bI=#=?L+5YIp@yLhwHD8ocn@%PoECg z?;kt&=81C`7sK@@_i~PU+@czTMfOC0y=_zad=_hH9U;Hr!=2PNVZboB*Ab;!6KBVN& zy0P&YFhU#o1Iyav@$;GWB|ynvcC^i9VBLS#{1r#a4Y38fy=&^_7~z_Ap~RZjdaP4w=fO{Lr=^)+K`+ny=M%r_o!EzJU8?IMuAF)O)Y^rUm zo`mO^bNpHaKxr=4K#AAV$oG%oDc+G@ldpegjY)4Bp&t&4MOqa7zZ9w9b^ z$C#{GzgoYF$M37j{os7<_aFT!JX>eeccXlX7uV(5+N_+JqZ)aE8QKUBxyp`uDn8j+ zECQDBtgT|mwfKgp_MbI8*^|E}dz5i6Va9xkC1G6bhsN5%2HvS&W2E6K;l=qPEa`+5 zpU>eDHOCCsW-f-kq#?E;!r?PvFpgXzwzY5VCtMR>tM4zj^|^Go=Zdn!{VNFeE9_+* z_Ag4m@%|cn*v)R(w{V1ZFCf~tUgIpiqH)aEND~$3tma3nj`1|(50kjpF)gxz>n;CP6ibvIlAyNHjqpSEoB2^WKz^VR*ta{#V){PBNVdfe+Et|%Ma zKZR@|JJ?+X>2V&TT;oi3gR|JL?QjmeK!z_NI)`<9ae15u{xE+J(W@ij_g3GpH9E$A z5I?`yYZ~Ld=Wkp4Y6HaaU)%2MU!8xNm$Ui~>OVSXbA659k)l2(e^|@y-WT^!dlt|8 ze}bPJQ*x~NU(0`r`_A)^W03E&y8a{ll`{(8+x!>&=C_J{$2s?&b8cSd>u+uT(T+{p z_FL;uyNPuqY%f#%;+9qnOZe%-Mhp{A+S=y$#Vt*&rTjH+2GPPVZs{fbQ`}4V#VtJ6 zVXiUGQq5EG7vxV~#jqrQQdquH|JE2_{}W$HE3Xz^;>+*d;*aZZiCgzrd-g*s?4RJ6 z&0BF4`5R*x{jS!Uy+1#QVpgw-;aJ=XZYqZGEdJh1edQ~?B5!d^S7Q)IO&@`K6hn=t zav#3U^G!TcI@OppuW(wMDXc@ESsvRz6qo+~1}_>Wq{oYh4g%9T*}&!$vW4s*R~_Ix b{82>dL38ak{s-P)+~EDiPrSeI@4WvFq*GKt literal 0 HcmV?d00001 diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index e6f6c824e..668ebaf62 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -106,7 +106,9 @@ struct Pixmaps { PixmapSetEmptyActive floppy_525; PixmapSetEmptyActive floppy_35; PixmapSetEmptyActive cdrom; + PixmapSetEmptyActive rdisk_disabled; PixmapSetEmptyActive rdisk; + PixmapSetEmptyActive zip; PixmapSetEmptyActive mo; PixmapSetActive hd; PixmapSetEmptyActive net; @@ -327,7 +329,15 @@ struct MachineStatus::States { pixmaps.floppy_525.load(QIcon(":/settings/qt/icons/floppy_525.ico")); pixmaps.floppy_35.load(QIcon(":/settings/qt/icons/floppy_35.ico")); pixmaps.cdrom.load(QIcon(":/settings/qt/icons/cdrom.ico")); + pixmaps.rdisk_disabled.normal = QIcon(":/settings/qt/icons/rdisk_disabled.ico").pixmap(pixmap_size); + pixmaps.rdisk_disabled.active = pixmaps.rdisk_disabled.normal; + pixmaps.rdisk_disabled.read_write_active = pixmaps.rdisk_disabled.normal; + pixmaps.rdisk_disabled.empty = pixmaps.rdisk_disabled.normal; + pixmaps.rdisk_disabled.empty_active = pixmaps.rdisk_disabled.normal; + pixmaps.rdisk_disabled.empty_write_active = pixmaps.rdisk_disabled.normal; + pixmaps.rdisk_disabled.empty_read_write_active = pixmaps.rdisk_disabled.normal; pixmaps.rdisk.load(QIcon(":/settings/qt/icons/rdisk.ico")); + pixmaps.zip.load(QIcon(":/settings/qt/icons/zip.ico")); pixmaps.mo.load(QIcon(":/settings/qt/icons/mo.ico")); pixmaps.hd.load(QIcon(":/settings/qt/icons/hard_disk.ico")); pixmaps.net.load(QIcon(":/settings/qt/icons/network.ico")); @@ -758,6 +768,14 @@ MachineStatus::refresh(QStatusBar *sbar) }); iterateRDisk([this, sbar](int i) { + int t = rdisk_drives[i].type; + if (rdisk_drives[i].bus_type == RDISK_BUS_DISABLED) { + d->rdisk[i].pixmaps = &d->pixmaps.rdisk_disabled; + } else if ((t == RDISK_TYPE_ZIP_100) || (t == RDISK_TYPE_ZIP_250)) { + d->fdd[i].pixmaps = &d->pixmaps.zip; + } else { + d->fdd[i].pixmaps = &d->pixmaps.rdisk; + } d->rdisk[i].label = std::make_unique(); d->rdisk[i].setEmpty(QString(rdisk_drives[i].image_path).isEmpty()); if (QString(rdisk_drives[i].image_path).isEmpty()) diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index cdff36469..feb732c2e 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -195,7 +195,8 @@ MediaMenu::refresh(QMenu *parentMenu) rdiskMenus.clear(); MachineStatus::iterateRDisk([this, parentMenu](int i) { auto *menu = parentMenu->addMenu(""); - QIcon img_icon = QIcon(":/settings/qt/icons/rdisk_image.ico"); + int t = rdisk_drives[i].type; + QIcon img_icon = ((t == RDISK_TYPE_ZIP_100) || (t == RDISK_TYPE_ZIP_250)) ? QIcon(":/settings/qt/icons/zip_image.ico") : QIcon(":/settings/qt/icons/rdisk_image.ico"); menu->addAction(getIconWithIndicator(img_icon, pixmap_size, QIcon::Normal, New), tr("&New image…"), [this, i]() { rdiskNewImage(i); }); menu->addSeparator(); menu->addAction(getIconWithIndicator(img_icon, pixmap_size, QIcon::Normal, Browse), tr("&Existing image…"), [this, i]() { rdiskSelectImage(i, false); }); diff --git a/src/qt/qt_settingsotherremovable.cpp b/src/qt/qt_settingsotherremovable.cpp index 567eaa3e2..e00e3686f 100644 --- a/src/qt/qt_settingsotherremovable.cpp +++ b/src/qt/qt_settingsotherremovable.cpp @@ -67,7 +67,7 @@ SettingsOtherRemovable::setMOBus(QAbstractItemModel *model, const QModelIndex &i } void -SettingsOtherRemovable::setRDiskBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t channel) +SettingsOtherRemovable::setRDiskBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint32_t type, uint8_t channel) { QIcon icon; switch (bus) { @@ -76,7 +76,7 @@ SettingsOtherRemovable::setRDiskBus(QAbstractItemModel *model, const QModelIndex break; case RDISK_BUS_ATAPI: case RDISK_BUS_SCSI: - icon = rdisk_icon; + icon = ((type == RDISK_TYPE_ZIP_100) || (type == RDISK_TYPE_ZIP_250)) ? zip_icon : rdisk_icon; break; default: @@ -101,15 +101,30 @@ setMOType(QAbstractItemModel *model, const QModelIndex &idx, uint32_t type) model->setData(i, type, Qt::UserRole); } -static void -setRDiskType(QAbstractItemModel *model, const QModelIndex &idx, uint32_t type) +void +SettingsOtherRemovable::setRDiskType(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint32_t type) { + QIcon icon; + switch (bus) { + case RDISK_BUS_DISABLED: + icon = rdisk_disabled_icon; + break; + case RDISK_BUS_ATAPI: + case RDISK_BUS_SCSI: + icon = ((type == RDISK_TYPE_ZIP_100) || (type == RDISK_TYPE_ZIP_250)) ? zip_icon : rdisk_icon; + break; + + default: + break; + } + auto i = idx.siblingAtColumn(1); if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() == RDISK_BUS_DISABLED) model->setData(i, QCoreApplication::translate("", "None")); else model->setData(i, rdiskDriveTypeName(type)); model->setData(i, type, Qt::UserRole); + model->setData(i, icon, Qt::DecorationRole); } SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) @@ -147,6 +162,7 @@ SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) rdisk_disabled_icon = QIcon(":/settings/qt/icons/rdisk_disabled.ico"); rdisk_icon = QIcon(":/settings/qt/icons/rdisk.ico"); + zip_icon = QIcon(":/settings/qt/icons/zip.ico"); Harddrives::populateRemovableBuses(ui->comboBoxRDiskBus->model()); if ((ui->comboBoxRDiskBus->model()->rowCount() - 3) > 0) @@ -163,8 +179,8 @@ SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) model->insertRows(0, RDISK_NUM); for (int i = 0; i < RDISK_NUM; i++) { auto idx = model->index(i, 0); - setRDiskBus(model, idx, rdisk_drives[i].bus_type, rdisk_drives[i].res); - setRDiskType(model, idx.siblingAtColumn(1), rdisk_drives[i].type); + setRDiskBus(model, idx, rdisk_drives[i].bus_type, rdisk_drives[i].type, rdisk_drives[i].res); + setRDiskType(model, idx.siblingAtColumn(1), rdisk_drives[i].bus_type, rdisk_drives[i].type); Harddrives::busTrackClass->device_track(1, DEV_MO, rdisk_drives[i].bus_type, rdisk_drives[i].bus_type == RDISK_BUS_ATAPI ? rdisk_drives[i].ide_channel : rdisk_drives[i].scsi_device_id); } ui->tableViewRDisk->resizeColumnsToContents(); @@ -317,9 +333,11 @@ SettingsOtherRemovable::on_comboBoxRDiskBus_activated(int) setRDiskBus(ui->tableViewRDisk->model(), ui->tableViewRDisk->selectionModel()->currentIndex(), ui->comboBoxRDiskBus->currentData().toUInt(), + ui->comboBoxRDiskType->currentData().toUInt(), ui->comboBoxRDiskChannel->currentData().toUInt()); setRDiskType(ui->tableViewRDisk->model(), ui->tableViewRDisk->selectionModel()->currentIndex(), + ui->comboBoxRDiskBus->currentData().toUInt(), ui->comboBoxRDiskType->currentData().toUInt()); ui->tableViewRDisk->resizeColumnsToContents(); ui->tableViewRDisk->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); @@ -367,6 +385,7 @@ SettingsOtherRemovable::on_comboBoxRDiskChannel_activated(int) setRDiskBus(ui->tableViewRDisk->model(), ui->tableViewRDisk->selectionModel()->currentIndex(), ui->comboBoxRDiskBus->currentData().toUInt(), + ui->comboBoxRDiskType->currentData().toUInt(), ui->comboBoxRDiskChannel->currentData().toUInt()); Harddrives::busTrackClass->device_track(1, DEV_RDISK, ui->tableViewRDisk->model()->data(i, Qt::UserRole).toInt(), ui->tableViewRDisk->model()->data(i, Qt::UserRole + 1).toInt()); @@ -388,6 +407,7 @@ SettingsOtherRemovable::on_comboBoxRDiskType_activated(int) { setRDiskType(ui->tableViewRDisk->model(), ui->tableViewRDisk->selectionModel()->currentIndex(), + ui->comboBoxRDiskBus->currentData().toUInt(), ui->comboBoxRDiskType->currentData().toUInt()); ui->tableViewRDisk->resizeColumnsToContents(); ui->tableViewRDisk->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); diff --git a/src/qt/qt_settingsotherremovable.hpp b/src/qt/qt_settingsotherremovable.hpp index 794939589..a06bd9a37 100644 --- a/src/qt/qt_settingsotherremovable.hpp +++ b/src/qt/qt_settingsotherremovable.hpp @@ -40,7 +40,8 @@ private: Ui::SettingsOtherRemovable *ui; void setMOBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t channel); - void setRDiskBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t channel); + void setRDiskBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint32_t type, uint8_t channel); + void setRDiskType(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint32_t type); void enableCurrentlySelectedChannel_MO(); void enableCurrentlySelectedChannel_RDisk(); @@ -48,6 +49,7 @@ private: QIcon mo_icon; QIcon rdisk_disabled_icon; QIcon rdisk_icon; + QIcon zip_icon; }; #endif // QT_SETTINGSOTHERREMOVABLE_HPP diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 4b069cb3f..a356260c3 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -36,9 +36,8 @@ qt/icons/rewind.ico qt/icons/sound.ico qt/icons/storage_controllers.ico - qt/icons/superdisk.ico - qt/icons/superdisk_image.ico - qt/icons/superdisk_disabled.ico + qt/icons/zip.ico + qt/icons/zip_image.ico qt/icons/active.ico qt/icons/browse.ico qt/icons/eject.ico