From c577aa85f2966f03e5c63678c312d4d83d17261c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 16 Feb 2022 01:09:11 +0600 Subject: [PATCH 001/133] qt: Add fullscreen status icons support and option --- src/config.c | 6 +++++ src/include/86box/plat.h | 5 ++-- src/qt/qt_hardwarerenderer.cpp | 22 ++++++++++++++-- src/qt/qt_hardwarerenderer.hpp | 1 + src/qt/qt_mainwindow.cpp | 14 ++++++++--- src/qt/qt_mainwindow.hpp | 4 ++- src/qt/qt_mainwindow.ui | 9 +++++++ src/qt/qt_renderercommon.cpp | 46 ++++++++++++++++++++++++++++++++++ src/qt/qt_renderercommon.hpp | 1 + src/qt/qt_softwarerenderer.cpp | 4 ++- src/unix/unix.c | 3 ++- src/win/win_ui.c | 1 + 12 files changed, 106 insertions(+), 10 deletions(-) diff --git a/src/config.c b/src/config.c index 5f3503ea9..b110d6984 100644 --- a/src/config.c +++ b/src/config.c @@ -521,6 +521,7 @@ load_general(void) rctrl_is_lalt = config_get_int(cat, "rctrl_is_lalt", 0); update_icons = config_get_int(cat, "update_icons", 1); + status_icons_fullscreen = !!config_get_int(cat, "status_icons_fullscreen", 0); window_remember = config_get_int(cat, "window_remember", 0); if (window_remember || (vid_resize & 2)) { @@ -2294,6 +2295,11 @@ save_general(void) else config_delete_var(cat, "enable_discord"); + if (status_icons_fullscreen) + config_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen); + else + config_delete_var(cat, "status_icons_fullscreen"); + if (video_framerate != -1) config_set_int(cat, "video_gl_framerate", video_framerate); else diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index c60e6d922..d00bc1b87 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -75,7 +75,7 @@ extern "C" { /* Global variables residing in the platform module. */ extern int dopause, /* system is paused */ - mouse_capture; /* mouse is captured in app */ + mouse_capture; /* mouse is captured in app */ extern atomic_flag_t doresize; /* screen resize requested */ extern volatile int is_quit; /* system exit requested */ @@ -88,9 +88,10 @@ extern int infocus; extern char emu_version[200]; /* version ID string */ extern int rctrl_is_lalt; extern int update_icons; +extern int status_icons_fullscreen; extern int unscaled_size_x, /* current unscaled size X */ - unscaled_size_y; /* current unscaled size Y */ + unscaled_size_y; /* current unscaled size Y */ extern int kbd_req_capture, hide_status_bar, hide_tool_bar; diff --git a/src/qt/qt_hardwarerenderer.cpp b/src/qt/qt_hardwarerenderer.cpp index 1a89b93be..e4d2b4900 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -86,6 +86,7 @@ void HardwareRenderer::initializeGL() "void main(void)\n" "{\n" " gl_FragColor = texture2D(texture, texc.st).bgra;\n" + " gl_FragColor.a = 1.0;\n" "}\n"; QString fsrccore = "uniform sampler2D texture;\n" @@ -94,6 +95,7 @@ void HardwareRenderer::initializeGL() "void main(void)\n" "{\n" " FragColor = texture2D(texture, texc.st).bgra;\n" + " FragColor.a = 1.0;\n" "}\n"; if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) { @@ -135,6 +137,22 @@ void HardwareRenderer::initializeGL() glClearColor(0, 0, 0, 1); } +void HardwareRenderer::paintOverGL() +{ + // Context switching is needed to make use of QPainter to draw status bar icons in fullscreen. + // Especially since it seems to be impossible to use QPainter on externally-created OpenGL contexts. + if (video_fullscreen && status_icons_fullscreen) + { + m_context->makeCurrent(nullptr); + makeCurrent(); + QPainter painter(this); + drawStatusBarIcons(&painter); + painter.end(); + doneCurrent(); + m_context->makeCurrent(this); + } +} + void HardwareRenderer::paintGL() { m_context->makeCurrent(this); glClear(GL_COLOR_BUFFER_BIT); @@ -200,7 +218,7 @@ void HardwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) { void HardwareRenderer::resizeEvent(QResizeEvent *event) { onResize(width(), height()); - + QOpenGLWindow::resizeEvent(event); } @@ -214,7 +232,7 @@ bool HardwareRenderer::event(QEvent *event) std::vector> HardwareRenderer::getBuffers() { std::vector> buffers; - + buffers.push_back(std::make_tuple(imagebufs[0].get(), &buf_usage[0])); buffers.push_back(std::make_tuple(imagebufs[1].get(), &buf_usage[1])); diff --git a/src/qt/qt_hardwarerenderer.hpp b/src/qt/qt_hardwarerenderer.hpp index af4f05464..9720a8c2e 100644 --- a/src/qt/qt_hardwarerenderer.hpp +++ b/src/qt/qt_hardwarerenderer.hpp @@ -47,6 +47,7 @@ public: void resizeGL(int w, int h) override; void initializeGL() override; void paintGL() override; + void paintOverGL() override; std::vector> getBuffers() override; HardwareRenderer(QWidget* parent = nullptr, RenderType rtype = RenderType::OpenGL) : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent->windowHandle()), QOpenGLFunctions() diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 6a54bf200..8cb107192 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -132,7 +132,7 @@ MainWindow::MainWindow(QWidget *parent) : return; } if (!hide_tool_bar) -#ifdef _WIN32 +#ifdef _WIN32 toolbar_label->setText(title); #else { @@ -187,12 +187,12 @@ MainWindow::MainWindow(QWidget *parent) : connect(this, &MainWindow::resizeContents, this, [this](int w, int h) { if (!QApplication::platformName().contains("eglfs") && vid_resize == 0) { w = qRound(w / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)); - + int modifiedHeight = qRound(h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)) + menuBar()->height() + (statusBar()->height() * !hide_status_bar) + (ui->toolBar->height() * !hide_tool_bar); - + ui->stackedWidget->resize(w, h); setFixedSize(w, modifiedHeight); } @@ -225,6 +225,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->actionHide_tool_bar->setChecked(hide_tool_bar); ui->actionUpdate_status_bar_icons->setChecked(update_icons); ui->actionEnable_Discord_integration->setChecked(enable_discord); + ui->actionShow_status_icons_in_fullscreen->setChecked(status_icons_fullscreen); #if defined Q_OS_WINDOWS || defined Q_OS_MACOS /* Make the option visible only if ANGLE is loaded. */ @@ -1614,3 +1615,10 @@ void MainWindow::changeEvent(QEvent* event) #endif QWidget::changeEvent(event); } + +void MainWindow::on_actionShow_status_icons_in_fullscreen_triggered() +{ + status_icons_fullscreen = !status_icons_fullscreen; + ui->actionShow_status_icons_in_fullscreen->setChecked(status_icons_fullscreen); +} + diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 3d5a6a02a..90f7ddcff 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -110,6 +110,8 @@ private slots: void on_actionEnable_Discord_integration_triggered(bool checked); + void on_actionShow_status_icons_in_fullscreen_triggered(); + protected: void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; @@ -124,7 +126,7 @@ private: Ui::MainWindow *ui; std::unique_ptr status; std::shared_ptr mm; - + /* If main window should send keyboard input */ bool send_keyboard_input = true; bool shownonce = false; diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index 6a35279c2..edc692a85 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -149,6 +149,7 @@ + @@ -697,6 +698,14 @@ false + + + true + + + Show status icons in fullscreen + + diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 0974c1f78..e8300dfa0 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -17,17 +17,25 @@ #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" +#include "qt_machinestatus.hpp" +#include "ui_qt_mainwindow.h" #include #include #include #include +#include +#include +#include #include extern "C" { #include <86box/86box.h> +#include <86box/plat.h> #include <86box/video.h> + +int status_icons_fullscreen = 0; } RendererCommon::RendererCommon() = default; @@ -101,6 +109,44 @@ void RendererCommon::onResize(int width, int height) { } } +void RendererCommon::drawStatusBarIcons(QPainter* painter) +{ + uint32_t x = 0; + auto prevcompositionMode = painter->compositionMode(); + painter->setCompositionMode(QPainter::CompositionMode::CompositionMode_SourceOver); + for (int i = 0; i < main_window->ui->statusbar->children().count(); i++) + { + QLabel* label = qobject_cast(main_window->ui->statusbar->children()[i]); + if (label) + { + auto pixmap = label->pixmap(Qt::ReturnByValue); + if (!pixmap.isNull()) + { + painter->setBrush(QColor(0, 0, 0, 255)); + painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, pixmap.width(), pixmap.height() + 4, QColor(0, 0, 0, 127)); + painter->drawPixmap(x, painter->device()->height() - pixmap.height(), pixmap); + x += pixmap.width(); + if (i <= main_window->ui->statusbar->children().count() - 3) + { + painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, main_window->ui->statusbar->layout()->spacing(), pixmap.height() + 4, QColor(0, 0, 0, 127)); + x += main_window->ui->statusbar->layout()->spacing(); + } + else painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, pixmap.height() + 4, QColor(0, 0, 0, 127)); + } + } + } + if (main_window->status->getMessage().isEmpty() == false) + { + auto curStatusMsg = main_window->status->getMessage(); + auto textSize = painter->fontMetrics().size(Qt::TextSingleLine, curStatusMsg); + painter->setPen(QColor(0, 0, 0, 127)); + painter->fillRect(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), textSize.width(), textSize.height(), QColor(0, 0, 0, 127)); + painter->setPen(QColor(255, 255, 255, 255)); + painter->drawText(QRectF(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), textSize.width(), textSize.height()), Qt::TextSingleLine, curStatusMsg); + } + painter->setCompositionMode(prevcompositionMode); +} + bool RendererCommon::eventDelegate(QEvent *event, bool& result) { switch (event->type()) diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index f55f3ee03..fe4d278c7 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -20,6 +20,7 @@ public: virtual std::vector> getBuffers() = 0; protected: bool eventDelegate(QEvent* event, bool& result); + void drawStatusBarIcons(QPainter* painter); QRect source, destination; QWidget* parentWidget{nullptr}; diff --git a/src/qt/qt_softwarerenderer.cpp b/src/qt/qt_softwarerenderer.cpp index 13d727e83..2d260eca3 100644 --- a/src/qt/qt_softwarerenderer.cpp +++ b/src/qt/qt_softwarerenderer.cpp @@ -24,6 +24,7 @@ extern "C" { #include <86box/86box.h> +#include <86box/plat.h> #include <86box/video.h> } @@ -53,7 +54,7 @@ void SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) { cur_image = buf_idx; buf_usage[(buf_idx + 1) % 2].clear(); - + source.setRect(x, y, w, h), update(); } @@ -83,6 +84,7 @@ void SoftwareRenderer::onPaint(QPaintDevice* device) { #endif painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.drawImage(destination, *images[cur_image], source); + if (video_fullscreen && status_icons_fullscreen) drawStatusBarIcons(&painter); } std::vector> SoftwareRenderer::getBuffers() diff --git a/src/unix/unix.c b/src/unix/unix.c index a93609e2e..11f00b786 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -48,6 +48,7 @@ extern wchar_t sdl_win_title[512]; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; joystick_t joystick_state[MAX_JOYSTICKS]; int joysticks_present; +int status_icons_fullscreen = 0; /* unused. */ SDL_mutex *blitmtx; SDL_threadID eventthread; static int exit_event = 0; @@ -1272,4 +1273,4 @@ void endblit() void ui_sb_mt32lcd(char* str) { -} \ No newline at end of file +} diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 6f0301d09..3e027021d 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -67,6 +67,7 @@ int fixed_size_x = 0, fixed_size_y = 0; int kbd_req_capture = 0; int hide_status_bar = 0; int hide_tool_bar = 0; +int status_icons_fullscreen = 0; /* unused. */ int dpi = 96; extern char openfilestring[512]; From 611486cb71b72e23e83d2076b2ed5bfdc651142d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 16 Feb 2022 14:37:09 +0600 Subject: [PATCH 002/133] qt: Fix compilation with Qt 5 --- src/qt/qt_renderercommon.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index e8300dfa0..3ced773d4 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -119,7 +119,11 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) QLabel* label = qobject_cast(main_window->ui->statusbar->children()[i]); if (label) { - auto pixmap = label->pixmap(Qt::ReturnByValue); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QPixmap pixmap = label->pixmap(); +#else + const QPixmap pixmap = *label->pixmap(); +#endif if (!pixmap.isNull()) { painter->setBrush(QColor(0, 0, 0, 255)); From ab4c68402dfcce87ca82580098c36a706d23ec68 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 16 Feb 2022 14:57:22 +0600 Subject: [PATCH 003/133] qt: Fix crash on fullscreen with status icons enabled --- src/qt/qt_renderercommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 3ced773d4..82856d206 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -122,7 +122,7 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const QPixmap pixmap = label->pixmap(); #else - const QPixmap pixmap = *label->pixmap(); + const QPixmap pixmap = label->pixmap() ? *label->pixmap() : QPixmap(); #endif if (!pixmap.isNull()) { From ed9b67c4335d4c3a6dfbca8acc9e564617f4148c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 16 Feb 2022 15:56:37 +0600 Subject: [PATCH 004/133] qt: Improve appearance of text and status icons in fullscreen --- src/qt/qt_renderercommon.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 82856d206..d08fe9a26 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -18,7 +18,6 @@ #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" #include "qt_machinestatus.hpp" -#include "ui_qt_mainwindow.h" #include #include @@ -114,9 +113,9 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) uint32_t x = 0; auto prevcompositionMode = painter->compositionMode(); painter->setCompositionMode(QPainter::CompositionMode::CompositionMode_SourceOver); - for (int i = 0; i < main_window->ui->statusbar->children().count(); i++) + for (int i = 0; i < main_window->statusBar()->children().count(); i++) { - QLabel* label = qobject_cast(main_window->ui->statusbar->children()[i]); + QLabel* label = qobject_cast(main_window->statusBar()->children()[i]); if (label) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -127,13 +126,13 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) if (!pixmap.isNull()) { painter->setBrush(QColor(0, 0, 0, 255)); - painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, pixmap.width(), pixmap.height() + 4, QColor(0, 0, 0, 127)); - painter->drawPixmap(x, painter->device()->height() - pixmap.height(), pixmap); + painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, pixmap.width(), pixmap.height() + 5, QColor(0, 0, 0, 127)); + painter->drawPixmap(x + main_window->statusBar()->layout()->spacing() / 2, painter->device()->height() - pixmap.height() - 3, pixmap); x += pixmap.width(); - if (i <= main_window->ui->statusbar->children().count() - 3) + if (i <= main_window->statusBar()->children().count() - 3) { - painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, main_window->ui->statusbar->layout()->spacing(), pixmap.height() + 4, QColor(0, 0, 0, 127)); - x += main_window->ui->statusbar->layout()->spacing(); + painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, main_window->statusBar()->layout()->spacing(), pixmap.height() + 5, QColor(0, 0, 0, 127)); + x += main_window->statusBar()->layout()->spacing(); } else painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, pixmap.height() + 4, QColor(0, 0, 0, 127)); } @@ -142,11 +141,11 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) if (main_window->status->getMessage().isEmpty() == false) { auto curStatusMsg = main_window->status->getMessage(); - auto textSize = painter->fontMetrics().size(Qt::TextSingleLine, curStatusMsg); + auto textSize = painter->fontMetrics().size(Qt::TextSingleLine, QChar(' ') + curStatusMsg + QChar(' ')); painter->setPen(QColor(0, 0, 0, 127)); painter->fillRect(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), textSize.width(), textSize.height(), QColor(0, 0, 0, 127)); painter->setPen(QColor(255, 255, 255, 255)); - painter->drawText(QRectF(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), textSize.width(), textSize.height()), Qt::TextSingleLine, curStatusMsg); + painter->drawText(QRectF(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), textSize.width(), textSize.height()), Qt::TextSingleLine, QChar(' ') + curStatusMsg + QChar(' ')); } painter->setCompositionMode(prevcompositionMode); } From 9e0ca23060baacf8fa82fec7f16aa28ab42fc801 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 16 Feb 2022 16:10:54 +0600 Subject: [PATCH 005/133] qt: Construct colors from floating point values --- src/qt/qt_renderercommon.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index d08fe9a26..82fa78628 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -125,16 +125,17 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) #endif if (!pixmap.isNull()) { - painter->setBrush(QColor(0, 0, 0, 255)); - painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, pixmap.width(), pixmap.height() + 5, QColor(0, 0, 0, 127)); + painter->setBrush(QColor::fromRgbF(0, 0, 0, 1.)); + painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, pixmap.width(), pixmap.height() + 5, QColor::fromRgbF(0, 0, 0, .5)); painter->drawPixmap(x + main_window->statusBar()->layout()->spacing() / 2, painter->device()->height() - pixmap.height() - 3, pixmap); x += pixmap.width(); if (i <= main_window->statusBar()->children().count() - 3) { - painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, main_window->statusBar()->layout()->spacing(), pixmap.height() + 5, QColor(0, 0, 0, 127)); + painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, main_window->statusBar()->layout()->spacing(), pixmap.height() + 5, QColor::fromRgbF(0, 0, 0, .5)); x += main_window->statusBar()->layout()->spacing(); } - else painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, pixmap.height() + 4, QColor(0, 0, 0, 127)); + else painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, pixmap.height() + 4, QColor::fromRgbF(0, 0, 0, .5)); + pixheight = qMax((unsigned int)pixheight, (unsigned int)pixmap.height()); } } } From d25a16eedbe5bae33abd3b4f4efa14e8ba429a49 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 16 Feb 2022 16:19:55 +0600 Subject: [PATCH 006/133] qt: Fix compile error --- src/qt/qt_renderercommon.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 82fa78628..c76067add 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -135,7 +135,6 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) x += main_window->statusBar()->layout()->spacing(); } else painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, pixmap.height() + 4, QColor::fromRgbF(0, 0, 0, .5)); - pixheight = qMax((unsigned int)pixheight, (unsigned int)pixmap.height()); } } } From 4cefc6908e2c3d9c51c7bc7a7a36d996b2228b09 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 27 Nov 2022 16:11:46 +0600 Subject: [PATCH 007/133] Add OPL4-ML daughterboard emulation --- src/include/86box/midi.h | 1 + src/include/86box/opl4_defines.h | 101 +++ src/include/86box/snd_opl.h | 1 + src/sound/CMakeLists.txt | 2 +- src/sound/midi.c | 1 + src/sound/midi_opl4.c | 703 ++++++++++++++++++++ src/sound/midi_opl4_yrw801.c | 1042 ++++++++++++++++++++++++++++++ src/sound/snd_opl_nuked.c | 1 + src/sound/snd_opl_ymfm.cpp | 8 + src/sound/yrw801.h | 45 ++ 10 files changed, 1904 insertions(+), 1 deletion(-) create mode 100644 src/include/86box/opl4_defines.h create mode 100644 src/sound/midi_opl4.c create mode 100644 src/sound/midi_opl4_yrw801.c create mode 100644 src/sound/yrw801.h diff --git a/src/include/86box/midi.h b/src/include/86box/midi.h index e2b8c2626..9f3a81581 100644 --- a/src/include/86box/midi.h +++ b/src/include/86box/midi.h @@ -92,6 +92,7 @@ extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #ifdef EMU_DEVICE_H extern const device_t rtmidi_output_device; extern const device_t rtmidi_input_device; +extern const device_t opl4_midi_device; # ifdef USE_FLUIDSYNTH extern const device_t fluidsynth_device; # endif diff --git a/src/include/86box/opl4_defines.h b/src/include/86box/opl4_defines.h new file mode 100644 index 000000000..248b1f729 --- /dev/null +++ b/src/include/86box/opl4_defines.h @@ -0,0 +1,101 @@ +/* + * RoboPlay for MSX + * Copyright (C) 2020 by RoboSoft Inc. + * + * opl4_defines.h + * + */ + +#ifndef __OPL4_DEFINES_H +#define __OPL4_DEFINES_H + +/* + * Register numbers + */ + +#define OPL4_REG_TEST0 0x00 +#define OPL4_REG_TEST1 0x01 + +#define OPL4_REG_MEMORY_CONFIGURATION 0x02 +#define OPL4_MODE_BIT 0x01 +#define OPL4_MTYPE_BIT 0x02 +#define OPL4_TONE_HEADER_MASK 0x1C +#define OPL4_DEVICE_ID_MASK 0xE0 + +#define OPL4_REG_MEMORY_ADDRESS_HIGH 0x03 +#define OPL4_REG_MEMORY_ADDRESS_MID 0x04 +#define OPL4_REG_MEMORY_ADDRESS_LOW 0x05 +#define OPL4_REG_MEMORY_DATA 0x06 + +/* + * Offsets to the register banks for voices. To get the + * register number just add the voice number to the bank offset. + * + * Wave Table Number low bits (0x08 to 0x1F) + */ +#define OPL4_REG_TONE_NUMBER 0x08 + +/* Wave Table Number high bit, F-Number low bits (0x20 to 0x37) */ +#define OPL4_REG_F_NUMBER 0x20 +#define OPL4_TONE_NUMBER_BIT8 0x01 +#define OPL4_F_NUMBER_LOW_MASK 0xFE + +/* F-Number high bits, Octave, Pseudo-Reverb (0x38 to 0x4F) */ +#define OPL4_REG_OCTAVE 0x38 +#define OPL4_F_NUMBER_HIGH_MASK 0x07 +#define OPL4_BLOCK_MASK 0xF0 +#define OPL4_PSEUDO_REVERB_BIT 0x08 + +/* Total Level, Level Direct (0x50 to 0x67) */ +#define OPL4_REG_LEVEL 0x50 +#define OPL4_TOTAL_LEVEL_MASK 0xFE +#define OPL4_LEVEL_DIRECT_BIT 0x01 + +/* Key On, Damp, LFO RST, CH, Panpot (0x68 to 0x7F) */ +#define OPL4_REG_MISC 0x68 +#define OPL4_KEY_ON_BIT 0x80 +#define OPL4_DAMP_BIT 0x40 +#define OPL4_LFO_RESET_BIT 0x20 +#define OPL4_OUTPUT_CHANNEL_BIT 0x10 +#define OPL4_PAN_POT_MASK 0x0F + +/* LFO, VIB (0x80 to 0x97) */ +#define OPL4_REG_LFO_VIBRATO 0x80 +#define OPL4_LFO_FREQUENCY_MASK 0x38 +#define OPL4_VIBRATO_DEPTH_MASK 0x07 +#define OPL4_CHORUS_SEND_MASK 0xC0 + +/* Attack / Decay 1 rate (0x98 to 0xAF) */ +#define OPL4_REG_ATTACK_DECAY1 0x98 +#define OPL4_ATTACK_RATE_MASK 0xF0 +#define OPL4_DECAY1_RATE_MASK 0x0F + +/* Decay level / 2 rate (0xB0 to 0xC7) */ +#define OPL4_REG_LEVEL_DECAY2 0xB0 +#define OPL4_DECAY_LEVEL_MASK 0xF0 +#define OPL4_DECAY2_RATE_MASK 0x0F + +/* Release rate / Rate correction (0xC8 to 0xDF) */ +#define OPL4_REG_RELEASE_CORRECTION 0xC8 +#define OPL4_RELEASE_RATE_MASK 0x0F +#define OPL4_RATE_INTERPOLATION_MASK 0xF0 + +/* AM (0xE0 to 0xF7) */ +#define OPL4_REG_TREMOLO 0xE0 +#define OPL4_TREMOLO_DEPTH_MASK 0x07 +#define OPL4_REVERB_SEND_MASK 0xE0 + +/* Mixer */ +#define OPL4_REG_MIX_CONTROL_FM 0xF8 +#define OPL4_REG_MIX_CONTROL_PCM 0xF9 +#define OPL4_MIX_LEFT_MASK 0x07 +#define OPL4_MIX_RIGHT_MASK 0x38 + +#define OPL4_REG_ATC 0xFA +#define OPL4_ATC_BIT 0x01 + +/* Bits in the OPL4 Status register */ +#define OPL4_STATUS_BUSY 0x01 +#define OPL4_STATUS_LOAD 0x02 + +#endif /* __OPL4_DEFINES_H */ diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index 5caccf8fc..3b84a837b 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -38,6 +38,7 @@ typedef struct { void (*reset_buffer)(void *priv); void (*set_do_cycles)(void *priv, int8_t do_cycles); void *priv; + void (*generate)(void *priv, int32_t *data, uint32_t num_samples); /* daughterboard only. */ } fm_drv_t; extern uint8_t fm_driver_get(int chip_id, fm_drv_t *drv); diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 66672d547..7024bc5fc 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_re snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c - snd_optimc.c) + snd_optimc.c midi_opl4.c midi_opl4_yrw801.c) if(OPENAL) if(VCPKG_TOOLCHAIN) diff --git a/src/sound/midi.c b/src/sound/midi.c index 93fa62891..c58342648 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -100,6 +100,7 @@ static const MIDI_OUT_DEVICE devices[] = { #ifdef USE_RTMIDI { &rtmidi_output_device }, #endif + { &opl4_midi_device }, { NULL } // clang-format on }; diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c new file mode 100644 index 000000000..f816cff49 --- /dev/null +++ b/src/sound/midi_opl4.c @@ -0,0 +1,703 @@ +// Based off ROBOPLAY's OPL4 MID player code, with some fixes and modifications to make it work well. + +#include +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/midi.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/rom.h> +#include <86box/sound.h> +#include <86box/ui.h> +#include <86box/snd_opl.h> +#include <86box/opl4_defines.h> + +#include "yrw801.h" + +#define NR_OF_MIDI_CHANNELS 16 +#define NR_OF_WAVE_CHANNELS 24 + +#define DRUM_CHANNEL 9 + +typedef struct +{ + uint8_t instrument; + uint8_t panpot; + uint8_t vibrato; + bool drum_channel; +} MIDI_CHANNEL_DATA; + +typedef struct +{ + bool is_active; + uint64_t activated; + + uint8_t number; + MIDI_CHANNEL_DATA *midi_channel; + uint8_t note; + uint8_t velocity; + const YRW801_WAVE_DATA *wave_data; + uint8_t level_direct; + uint8_t reg_f_number; + uint8_t reg_misc; + uint8_t reg_lfo_vibrato; +} VOICE_DATA; + +static const int16_t g_wave_pitch_map[0x600] = { + 0x000, 0x000, 0x001, 0x001, 0x002, 0x002, 0x003, 0x003, + 0x004, 0x004, 0x005, 0x005, 0x006, 0x006, 0x006, 0x007, + 0x007, 0x008, 0x008, 0x009, 0x009, 0x00a, 0x00a, 0x00b, + 0x00b, 0x00c, 0x00c, 0x00d, 0x00d, 0x00d, 0x00e, 0x00e, + 0x00f, 0x00f, 0x010, 0x010, 0x011, 0x011, 0x012, 0x012, + 0x013, 0x013, 0x014, 0x014, 0x015, 0x015, 0x015, 0x016, + 0x016, 0x017, 0x017, 0x018, 0x018, 0x019, 0x019, 0x01a, + 0x01a, 0x01b, 0x01b, 0x01c, 0x01c, 0x01d, 0x01d, 0x01e, + 0x01e, 0x01e, 0x01f, 0x01f, 0x020, 0x020, 0x021, 0x021, + 0x022, 0x022, 0x023, 0x023, 0x024, 0x024, 0x025, 0x025, + 0x026, 0x026, 0x027, 0x027, 0x028, 0x028, 0x029, 0x029, + 0x029, 0x02a, 0x02a, 0x02b, 0x02b, 0x02c, 0x02c, 0x02d, + 0x02d, 0x02e, 0x02e, 0x02f, 0x02f, 0x030, 0x030, 0x031, + 0x031, 0x032, 0x032, 0x033, 0x033, 0x034, 0x034, 0x035, + 0x035, 0x036, 0x036, 0x037, 0x037, 0x038, 0x038, 0x038, + 0x039, 0x039, 0x03a, 0x03a, 0x03b, 0x03b, 0x03c, 0x03c, + 0x03d, 0x03d, 0x03e, 0x03e, 0x03f, 0x03f, 0x040, 0x040, + 0x041, 0x041, 0x042, 0x042, 0x043, 0x043, 0x044, 0x044, + 0x045, 0x045, 0x046, 0x046, 0x047, 0x047, 0x048, 0x048, + 0x049, 0x049, 0x04a, 0x04a, 0x04b, 0x04b, 0x04c, 0x04c, + 0x04d, 0x04d, 0x04e, 0x04e, 0x04f, 0x04f, 0x050, 0x050, + 0x051, 0x051, 0x052, 0x052, 0x053, 0x053, 0x054, 0x054, + 0x055, 0x055, 0x056, 0x056, 0x057, 0x057, 0x058, 0x058, + 0x059, 0x059, 0x05a, 0x05a, 0x05b, 0x05b, 0x05c, 0x05c, + 0x05d, 0x05d, 0x05e, 0x05e, 0x05f, 0x05f, 0x060, 0x060, + 0x061, 0x061, 0x062, 0x062, 0x063, 0x063, 0x064, 0x064, + 0x065, 0x065, 0x066, 0x066, 0x067, 0x067, 0x068, 0x068, + 0x069, 0x069, 0x06a, 0x06a, 0x06b, 0x06b, 0x06c, 0x06c, + 0x06d, 0x06d, 0x06e, 0x06e, 0x06f, 0x06f, 0x070, 0x071, + 0x071, 0x072, 0x072, 0x073, 0x073, 0x074, 0x074, 0x075, + 0x075, 0x076, 0x076, 0x077, 0x077, 0x078, 0x078, 0x079, + 0x079, 0x07a, 0x07a, 0x07b, 0x07b, 0x07c, 0x07c, 0x07d, + 0x07d, 0x07e, 0x07e, 0x07f, 0x07f, 0x080, 0x081, 0x081, + 0x082, 0x082, 0x083, 0x083, 0x084, 0x084, 0x085, 0x085, + 0x086, 0x086, 0x087, 0x087, 0x088, 0x088, 0x089, 0x089, + 0x08a, 0x08a, 0x08b, 0x08b, 0x08c, 0x08d, 0x08d, 0x08e, + 0x08e, 0x08f, 0x08f, 0x090, 0x090, 0x091, 0x091, 0x092, + 0x092, 0x093, 0x093, 0x094, 0x094, 0x095, 0x096, 0x096, + 0x097, 0x097, 0x098, 0x098, 0x099, 0x099, 0x09a, 0x09a, + 0x09b, 0x09b, 0x09c, 0x09c, 0x09d, 0x09d, 0x09e, 0x09f, + 0x09f, 0x0a0, 0x0a0, 0x0a1, 0x0a1, 0x0a2, 0x0a2, 0x0a3, + 0x0a3, 0x0a4, 0x0a4, 0x0a5, 0x0a6, 0x0a6, 0x0a7, 0x0a7, + 0x0a8, 0x0a8, 0x0a9, 0x0a9, 0x0aa, 0x0aa, 0x0ab, 0x0ab, + 0x0ac, 0x0ad, 0x0ad, 0x0ae, 0x0ae, 0x0af, 0x0af, 0x0b0, + 0x0b0, 0x0b1, 0x0b1, 0x0b2, 0x0b2, 0x0b3, 0x0b4, 0x0b4, + 0x0b5, 0x0b5, 0x0b6, 0x0b6, 0x0b7, 0x0b7, 0x0b8, 0x0b8, + 0x0b9, 0x0ba, 0x0ba, 0x0bb, 0x0bb, 0x0bc, 0x0bc, 0x0bd, + 0x0bd, 0x0be, 0x0be, 0x0bf, 0x0c0, 0x0c0, 0x0c1, 0x0c1, + 0x0c2, 0x0c2, 0x0c3, 0x0c3, 0x0c4, 0x0c4, 0x0c5, 0x0c6, + 0x0c6, 0x0c7, 0x0c7, 0x0c8, 0x0c8, 0x0c9, 0x0c9, 0x0ca, + 0x0cb, 0x0cb, 0x0cc, 0x0cc, 0x0cd, 0x0cd, 0x0ce, 0x0ce, + 0x0cf, 0x0d0, 0x0d0, 0x0d1, 0x0d1, 0x0d2, 0x0d2, 0x0d3, + 0x0d3, 0x0d4, 0x0d5, 0x0d5, 0x0d6, 0x0d6, 0x0d7, 0x0d7, + 0x0d8, 0x0d8, 0x0d9, 0x0da, 0x0da, 0x0db, 0x0db, 0x0dc, + 0x0dc, 0x0dd, 0x0de, 0x0de, 0x0df, 0x0df, 0x0e0, 0x0e0, + 0x0e1, 0x0e1, 0x0e2, 0x0e3, 0x0e3, 0x0e4, 0x0e4, 0x0e5, + 0x0e5, 0x0e6, 0x0e7, 0x0e7, 0x0e8, 0x0e8, 0x0e9, 0x0e9, + 0x0ea, 0x0eb, 0x0eb, 0x0ec, 0x0ec, 0x0ed, 0x0ed, 0x0ee, + 0x0ef, 0x0ef, 0x0f0, 0x0f0, 0x0f1, 0x0f1, 0x0f2, 0x0f3, + 0x0f3, 0x0f4, 0x0f4, 0x0f5, 0x0f5, 0x0f6, 0x0f7, 0x0f7, + 0x0f8, 0x0f8, 0x0f9, 0x0f9, 0x0fa, 0x0fb, 0x0fb, 0x0fc, + 0x0fc, 0x0fd, 0x0fd, 0x0fe, 0x0ff, 0x0ff, 0x100, 0x100, + 0x101, 0x101, 0x102, 0x103, 0x103, 0x104, 0x104, 0x105, + 0x106, 0x106, 0x107, 0x107, 0x108, 0x108, 0x109, 0x10a, + 0x10a, 0x10b, 0x10b, 0x10c, 0x10c, 0x10d, 0x10e, 0x10e, + 0x10f, 0x10f, 0x110, 0x111, 0x111, 0x112, 0x112, 0x113, + 0x114, 0x114, 0x115, 0x115, 0x116, 0x116, 0x117, 0x118, + 0x118, 0x119, 0x119, 0x11a, 0x11b, 0x11b, 0x11c, 0x11c, + 0x11d, 0x11e, 0x11e, 0x11f, 0x11f, 0x120, 0x120, 0x121, + 0x122, 0x122, 0x123, 0x123, 0x124, 0x125, 0x125, 0x126, + 0x126, 0x127, 0x128, 0x128, 0x129, 0x129, 0x12a, 0x12b, + 0x12b, 0x12c, 0x12c, 0x12d, 0x12e, 0x12e, 0x12f, 0x12f, + 0x130, 0x131, 0x131, 0x132, 0x132, 0x133, 0x134, 0x134, + 0x135, 0x135, 0x136, 0x137, 0x137, 0x138, 0x138, 0x139, + 0x13a, 0x13a, 0x13b, 0x13b, 0x13c, 0x13d, 0x13d, 0x13e, + 0x13e, 0x13f, 0x140, 0x140, 0x141, 0x141, 0x142, 0x143, + 0x143, 0x144, 0x144, 0x145, 0x146, 0x146, 0x147, 0x148, + 0x148, 0x149, 0x149, 0x14a, 0x14b, 0x14b, 0x14c, 0x14c, + 0x14d, 0x14e, 0x14e, 0x14f, 0x14f, 0x150, 0x151, 0x151, + 0x152, 0x153, 0x153, 0x154, 0x154, 0x155, 0x156, 0x156, + 0x157, 0x157, 0x158, 0x159, 0x159, 0x15a, 0x15b, 0x15b, + 0x15c, 0x15c, 0x15d, 0x15e, 0x15e, 0x15f, 0x160, 0x160, + 0x161, 0x161, 0x162, 0x163, 0x163, 0x164, 0x165, 0x165, + 0x166, 0x166, 0x167, 0x168, 0x168, 0x169, 0x16a, 0x16a, + 0x16b, 0x16b, 0x16c, 0x16d, 0x16d, 0x16e, 0x16f, 0x16f, + 0x170, 0x170, 0x171, 0x172, 0x172, 0x173, 0x174, 0x174, + 0x175, 0x175, 0x176, 0x177, 0x177, 0x178, 0x179, 0x179, + 0x17a, 0x17a, 0x17b, 0x17c, 0x17c, 0x17d, 0x17e, 0x17e, + 0x17f, 0x180, 0x180, 0x181, 0x181, 0x182, 0x183, 0x183, + 0x184, 0x185, 0x185, 0x186, 0x187, 0x187, 0x188, 0x188, + 0x189, 0x18a, 0x18a, 0x18b, 0x18c, 0x18c, 0x18d, 0x18e, + 0x18e, 0x18f, 0x190, 0x190, 0x191, 0x191, 0x192, 0x193, + 0x193, 0x194, 0x195, 0x195, 0x196, 0x197, 0x197, 0x198, + 0x199, 0x199, 0x19a, 0x19a, 0x19b, 0x19c, 0x19c, 0x19d, + 0x19e, 0x19e, 0x19f, 0x1a0, 0x1a0, 0x1a1, 0x1a2, 0x1a2, + 0x1a3, 0x1a4, 0x1a4, 0x1a5, 0x1a6, 0x1a6, 0x1a7, 0x1a8, + 0x1a8, 0x1a9, 0x1a9, 0x1aa, 0x1ab, 0x1ab, 0x1ac, 0x1ad, + 0x1ad, 0x1ae, 0x1af, 0x1af, 0x1b0, 0x1b1, 0x1b1, 0x1b2, + 0x1b3, 0x1b3, 0x1b4, 0x1b5, 0x1b5, 0x1b6, 0x1b7, 0x1b7, + 0x1b8, 0x1b9, 0x1b9, 0x1ba, 0x1bb, 0x1bb, 0x1bc, 0x1bd, + 0x1bd, 0x1be, 0x1bf, 0x1bf, 0x1c0, 0x1c1, 0x1c1, 0x1c2, + 0x1c3, 0x1c3, 0x1c4, 0x1c5, 0x1c5, 0x1c6, 0x1c7, 0x1c7, + 0x1c8, 0x1c9, 0x1c9, 0x1ca, 0x1cb, 0x1cb, 0x1cc, 0x1cd, + 0x1cd, 0x1ce, 0x1cf, 0x1cf, 0x1d0, 0x1d1, 0x1d1, 0x1d2, + 0x1d3, 0x1d3, 0x1d4, 0x1d5, 0x1d5, 0x1d6, 0x1d7, 0x1d7, + 0x1d8, 0x1d9, 0x1d9, 0x1da, 0x1db, 0x1db, 0x1dc, 0x1dd, + 0x1dd, 0x1de, 0x1df, 0x1df, 0x1e0, 0x1e1, 0x1e1, 0x1e2, + 0x1e3, 0x1e4, 0x1e4, 0x1e5, 0x1e6, 0x1e6, 0x1e7, 0x1e8, + 0x1e8, 0x1e9, 0x1ea, 0x1ea, 0x1eb, 0x1ec, 0x1ec, 0x1ed, + 0x1ee, 0x1ee, 0x1ef, 0x1f0, 0x1f0, 0x1f1, 0x1f2, 0x1f3, + 0x1f3, 0x1f4, 0x1f5, 0x1f5, 0x1f6, 0x1f7, 0x1f7, 0x1f8, + 0x1f9, 0x1f9, 0x1fa, 0x1fb, 0x1fb, 0x1fc, 0x1fd, 0x1fe, + 0x1fe, 0x1ff, 0x200, 0x200, 0x201, 0x202, 0x202, 0x203, + 0x204, 0x205, 0x205, 0x206, 0x207, 0x207, 0x208, 0x209, + 0x209, 0x20a, 0x20b, 0x20b, 0x20c, 0x20d, 0x20e, 0x20e, + 0x20f, 0x210, 0x210, 0x211, 0x212, 0x212, 0x213, 0x214, + 0x215, 0x215, 0x216, 0x217, 0x217, 0x218, 0x219, 0x21a, + 0x21a, 0x21b, 0x21c, 0x21c, 0x21d, 0x21e, 0x21e, 0x21f, + 0x220, 0x221, 0x221, 0x222, 0x223, 0x223, 0x224, 0x225, + 0x226, 0x226, 0x227, 0x228, 0x228, 0x229, 0x22a, 0x22b, + 0x22b, 0x22c, 0x22d, 0x22d, 0x22e, 0x22f, 0x230, 0x230, + 0x231, 0x232, 0x232, 0x233, 0x234, 0x235, 0x235, 0x236, + 0x237, 0x237, 0x238, 0x239, 0x23a, 0x23a, 0x23b, 0x23c, + 0x23c, 0x23d, 0x23e, 0x23f, 0x23f, 0x240, 0x241, 0x241, + 0x242, 0x243, 0x244, 0x244, 0x245, 0x246, 0x247, 0x247, + 0x248, 0x249, 0x249, 0x24a, 0x24b, 0x24c, 0x24c, 0x24d, + 0x24e, 0x24f, 0x24f, 0x250, 0x251, 0x251, 0x252, 0x253, + 0x254, 0x254, 0x255, 0x256, 0x257, 0x257, 0x258, 0x259, + 0x259, 0x25a, 0x25b, 0x25c, 0x25c, 0x25d, 0x25e, 0x25f, + 0x25f, 0x260, 0x261, 0x262, 0x262, 0x263, 0x264, 0x265, + 0x265, 0x266, 0x267, 0x267, 0x268, 0x269, 0x26a, 0x26a, + 0x26b, 0x26c, 0x26d, 0x26d, 0x26e, 0x26f, 0x270, 0x270, + 0x271, 0x272, 0x273, 0x273, 0x274, 0x275, 0x276, 0x276, + 0x277, 0x278, 0x279, 0x279, 0x27a, 0x27b, 0x27c, 0x27c, + 0x27d, 0x27e, 0x27f, 0x27f, 0x280, 0x281, 0x282, 0x282, + 0x283, 0x284, 0x285, 0x285, 0x286, 0x287, 0x288, 0x288, + 0x289, 0x28a, 0x28b, 0x28b, 0x28c, 0x28d, 0x28e, 0x28e, + 0x28f, 0x290, 0x291, 0x291, 0x292, 0x293, 0x294, 0x294, + 0x295, 0x296, 0x297, 0x298, 0x298, 0x299, 0x29a, 0x29b, + 0x29b, 0x29c, 0x29d, 0x29e, 0x29e, 0x29f, 0x2a0, 0x2a1, + 0x2a1, 0x2a2, 0x2a3, 0x2a4, 0x2a5, 0x2a5, 0x2a6, 0x2a7, + 0x2a8, 0x2a8, 0x2a9, 0x2aa, 0x2ab, 0x2ab, 0x2ac, 0x2ad, + 0x2ae, 0x2af, 0x2af, 0x2b0, 0x2b1, 0x2b2, 0x2b2, 0x2b3, + 0x2b4, 0x2b5, 0x2b5, 0x2b6, 0x2b7, 0x2b8, 0x2b9, 0x2b9, + 0x2ba, 0x2bb, 0x2bc, 0x2bc, 0x2bd, 0x2be, 0x2bf, 0x2c0, + 0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c4, 0x2c5, 0x2c6, + 0x2c7, 0x2c7, 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cb, 0x2cc, + 0x2cd, 0x2ce, 0x2ce, 0x2cf, 0x2d0, 0x2d1, 0x2d2, 0x2d2, + 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2d6, 0x2d7, 0x2d8, 0x2d9, + 0x2da, 0x2da, 0x2db, 0x2dc, 0x2dd, 0x2dd, 0x2de, 0x2df, + 0x2e0, 0x2e1, 0x2e1, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e5, + 0x2e6, 0x2e7, 0x2e8, 0x2e9, 0x2e9, 0x2ea, 0x2eb, 0x2ec, + 0x2ed, 0x2ed, 0x2ee, 0x2ef, 0x2f0, 0x2f1, 0x2f1, 0x2f2, + 0x2f3, 0x2f4, 0x2f5, 0x2f5, 0x2f6, 0x2f7, 0x2f8, 0x2f9, + 0x2f9, 0x2fa, 0x2fb, 0x2fc, 0x2fd, 0x2fd, 0x2fe, 0x2ff, + 0x300, 0x301, 0x302, 0x302, 0x303, 0x304, 0x305, 0x306, + 0x306, 0x307, 0x308, 0x309, 0x30a, 0x30a, 0x30b, 0x30c, + 0x30d, 0x30e, 0x30f, 0x30f, 0x310, 0x311, 0x312, 0x313, + 0x313, 0x314, 0x315, 0x316, 0x317, 0x318, 0x318, 0x319, + 0x31a, 0x31b, 0x31c, 0x31c, 0x31d, 0x31e, 0x31f, 0x320, + 0x321, 0x321, 0x322, 0x323, 0x324, 0x325, 0x326, 0x326, + 0x327, 0x328, 0x329, 0x32a, 0x32a, 0x32b, 0x32c, 0x32d, + 0x32e, 0x32f, 0x32f, 0x330, 0x331, 0x332, 0x333, 0x334, + 0x334, 0x335, 0x336, 0x337, 0x338, 0x339, 0x339, 0x33a, + 0x33b, 0x33c, 0x33d, 0x33e, 0x33e, 0x33f, 0x340, 0x341, + 0x342, 0x343, 0x343, 0x344, 0x345, 0x346, 0x347, 0x348, + 0x349, 0x349, 0x34a, 0x34b, 0x34c, 0x34d, 0x34e, 0x34e, + 0x34f, 0x350, 0x351, 0x352, 0x353, 0x353, 0x354, 0x355, + 0x356, 0x357, 0x358, 0x359, 0x359, 0x35a, 0x35b, 0x35c, + 0x35d, 0x35e, 0x35f, 0x35f, 0x360, 0x361, 0x362, 0x363, + 0x364, 0x364, 0x365, 0x366, 0x367, 0x368, 0x369, 0x36a, + 0x36a, 0x36b, 0x36c, 0x36d, 0x36e, 0x36f, 0x370, 0x370, + 0x371, 0x372, 0x373, 0x374, 0x375, 0x376, 0x377, 0x377, + 0x378, 0x379, 0x37a, 0x37b, 0x37c, 0x37d, 0x37d, 0x37e, + 0x37f, 0x380, 0x381, 0x382, 0x383, 0x383, 0x384, 0x385, + 0x386, 0x387, 0x388, 0x389, 0x38a, 0x38a, 0x38b, 0x38c, + 0x38d, 0x38e, 0x38f, 0x390, 0x391, 0x391, 0x392, 0x393, + 0x394, 0x395, 0x396, 0x397, 0x398, 0x398, 0x399, 0x39a, + 0x39b, 0x39c, 0x39d, 0x39e, 0x39f, 0x39f, 0x3a0, 0x3a1, + 0x3a2, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a7, 0x3a8, + 0x3a9, 0x3aa, 0x3ab, 0x3ac, 0x3ad, 0x3ae, 0x3ae, 0x3af, + 0x3b0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b6, + 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, + 0x3bf, 0x3bf, 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4, 0x3c5, + 0x3c6, 0x3c7, 0x3c7, 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cc, + 0x3cd, 0x3ce, 0x3cf, 0x3d0, 0x3d1, 0x3d1, 0x3d2, 0x3d3, + 0x3d4, 0x3d5, 0x3d6, 0x3d7, 0x3d8, 0x3d9, 0x3da, 0x3da, + 0x3db, 0x3dc, 0x3dd, 0x3de, 0x3df, 0x3e0, 0x3e1, 0x3e2, + 0x3e3, 0x3e4, 0x3e4, 0x3e5, 0x3e6, 0x3e7, 0x3e8, 0x3e9, + 0x3ea, 0x3eb, 0x3ec, 0x3ed, 0x3ee, 0x3ef, 0x3ef, 0x3f0, + 0x3f1, 0x3f2, 0x3f3, 0x3f4, 0x3f5, 0x3f6, 0x3f7, 0x3f8, + 0x3f9, 0x3fa, 0x3fa, 0x3fb, 0x3fc, 0x3fd, 0x3fe, 0x3ff +}; + +/* + * Attenuation according to GM recommendations, in -0.375 dB units. + * table[v] = 40 * log(v / 127) / -0.375 + */ +static const uint8_t g_volume_table[128] = { + 255, 224, 192, 173, 160, 150, 141, 134, + 128, 122, 117, 113, 109, 105, 102, 99, + 96, 93, 90, 88, 85, 83, 81, 79, + 77, 75, 73, 71, 70, 68, 67, 65, + 64, 62, 61, 59, 58, 57, 56, 54, + 53, 52, 51, 50, 49, 48, 47, 46, + 45, 44, 43, 42, 41, 40, 39, 39, + 38, 37, 36, 35, 34, 34, 33, 32, + 31, 31, 30, 29, 29, 28, 27, 27, + 26, 25, 25, 24, 24, 23, 22, 22, + 21, 21, 20, 19, 19, 18, 18, 17, + 17, 16, 16, 15, 15, 14, 14, 13, + 13, 12, 12, 11, 11, 10, 10, 9, + 9, 9, 8, 8, 7, 7, 6, 6, + 6, 5, 5, 4, 4, 4, 3, 3, + 2, 2, 2, 1, 1, 0, 0, 0 +}; + +typedef struct opl4_midi { + fm_drv_t opl4; + MIDI_CHANNEL_DATA midi_channel_data[16]; + VOICE_DATA voice_data[24]; + int16_t buffer[SOUNDBUFLEN * 2]; + float buffer_float[SOUNDBUFLEN * 2]; + uint32_t midi_pos; + bool on; + atomic_bool gen_in_progress; + thread_t *thread; + event_t *wait_event; +} opl4_midi_t; + +static opl4_midi_t *opl4_midi_cur; + +static void +opl4_write_wave_register(const uint8_t reg, const uint8_t value, opl4_midi_t *opl4_midi) +{ + opl4_midi->opl4.write(0x380, reg, opl4_midi->opl4.priv); + opl4_midi->opl4.write(0x381, value, opl4_midi->opl4.priv); +} + +VOICE_DATA * +get_voice(const YRW801_WAVE_DATA *wave_data, opl4_midi_t *opl4_midi) +{ + VOICE_DATA *free_voice = &opl4_midi->voice_data[0]; + VOICE_DATA *oldest_voice = &opl4_midi->voice_data[0]; + for (uint8_t voice = 0; voice < 24; voice++) { + if (opl4_midi_cur->voice_data[voice].is_active) { + if (opl4_midi_cur->voice_data[voice].activated < oldest_voice->activated) + oldest_voice = &opl4_midi_cur->voice_data[voice]; + } else { + if (opl4_midi_cur->voice_data[voice].wave_data == wave_data) { + free_voice = &opl4_midi_cur->voice_data[voice]; + break; + } + + if (opl4_midi_cur->voice_data[voice].activated < free_voice->activated) + free_voice = &opl4_midi_cur->voice_data[voice]; + } + } + + /* If no free voice found, deactivate the 'oldest' */ + if (free_voice->is_active) { + free_voice = oldest_voice; + free_voice->is_active = 0; + free_voice->activated = 0; + + free_voice->reg_misc &= ~OPL4_KEY_ON_BIT; + opl4_write_wave_register(OPL4_REG_MISC + free_voice->number, free_voice->reg_misc, opl4_midi); + } + + return free_voice; +} + +static void +update_pan(VOICE_DATA *voice, opl4_midi_t *opl4_midi) +{ + int8_t pan = voice->wave_data->panpot; + + if (!voice->midi_channel->drum_channel) + pan += voice->midi_channel->panpot; + if (pan < -7) + pan = -7; + else if (pan > 7) + pan = 7; + + voice->reg_misc = (voice->reg_misc & ~OPL4_PAN_POT_MASK) | (pan & OPL4_PAN_POT_MASK); + opl4_write_wave_register(OPL4_REG_MISC + voice->number, voice->reg_misc, opl4_midi); +} + +void +update_pitch(VOICE_DATA *voice, uint16_t pitch_bend, opl4_midi_t *opl4_midi) +{ + int32_t pitch = voice->midi_channel->drum_channel ? 0 : (voice->note - 60) * 128; + pitch = pitch * (int) voice->wave_data->key_scaling / 100; + pitch = pitch + 7680; + pitch += voice->wave_data->pitch_offset; + pitch += pitch_bend * 256 / 0x2000; + if (pitch < 0) + pitch = 0; + else if (pitch > 0x5FFF) + pitch = 0x5FFF; + + int8_t octave = pitch / 0x600 - 8; + uint16_t fnumber = g_wave_pitch_map[pitch % 0x600]; + + opl4_write_wave_register(OPL4_REG_OCTAVE + voice->number, (octave << 4) | ((fnumber >> 7) & 0x07), opl4_midi); + voice->reg_f_number = (voice->reg_f_number & OPL4_TONE_NUMBER_BIT8) | ((fnumber << 1) & OPL4_F_NUMBER_LOW_MASK); + opl4_write_wave_register(OPL4_REG_F_NUMBER + voice->number, voice->reg_f_number, opl4_midi); +} + +void +update_volume(VOICE_DATA *voice, opl4_midi_t *opl4_midi) +{ + int16_t att = voice->wave_data->tone_attenuate; + + att += g_volume_table[voice->velocity]; + att = 0x7F - (0x7F - att) * (voice->wave_data->volume_factor) / 0xFE; + att -= 16; + if (att < 0) + att = 0; + else if (att > 0x7E) + att = 0x7E; + + opl4_write_wave_register(OPL4_REG_LEVEL + voice->number, (att << 1) | voice->level_direct, opl4_midi); + voice->level_direct = 0; +} + +void +note_off(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_midi_t *opl4_midi) +{ + /* Velocity not used */ + (void) velocity; + + while (opl4_midi->gen_in_progress) { } + for (uint8_t i = 0; i < 24; i++) { + VOICE_DATA *voice = &opl4_midi->voice_data[i]; + if (voice->is_active && voice->midi_channel == midi_channel && voice->note == note) { + voice->is_active = false; + voice->activated = 0; + + voice->reg_misc &= ~OPL4_KEY_ON_BIT; + opl4_write_wave_register(OPL4_REG_MISC + voice->number, voice->reg_misc, opl4_midi); + } + } +} + +void +update_vibrato_depth(VOICE_DATA *voice, opl4_midi_t *opl4_midi) +{ + uint16_t depth; + + depth = (7 - voice->wave_data->vibrato) * (voice->midi_channel->vibrato & 0x7F); + depth = (depth >> 7) + voice->wave_data->vibrato; + voice->reg_lfo_vibrato &= ~OPL4_VIBRATO_DEPTH_MASK; + voice->reg_lfo_vibrato |= depth & OPL4_VIBRATO_DEPTH_MASK; + opl4_write_wave_register(OPL4_REG_LFO_VIBRATO + voice->number, voice->reg_lfo_vibrato, opl4_midi); +} + +void +note_on(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_midi_t *opl4_midi) +{ + const YRW801_REGION_DATA_PTR *region_ptr = &snd_yrw801_regions[0]; + const YRW801_WAVE_DATA *wave_data[2]; + VOICE_DATA *voice[2]; + uint8_t i = 0, voices = 0; + uint32_t j = 0; + static uint64_t activation_num = 0; + + while (opl4_midi->gen_in_progress) { } + + if (midi_channel->drum_channel) + wave_data[voices++] = ®ion_ptr[0x80].regions[note - 0x1A].wave_data; + else { + /* Determine the number of voices and voice parameters */ + const YRW801_REGION_DATA *region = region_ptr[midi_channel->instrument & 0x7F].regions; + + while (i < region_ptr[midi_channel->instrument & 0x7F].count) { + if (note >= region[i].key_min && note <= region[i].key_max) { + wave_data[voices] = ®ion[i].wave_data; + if (++voices >= 2) + break; + } + i++; + } + } + + /* Allocate and initialize needed voices */ + for (i = 0; i < voices; i++) { + voice[i] = get_voice(wave_data[i], opl4_midi); + voice[i]->is_active = true; + voice[i]->activated = activation_num++; + + voice[i]->midi_channel = midi_channel; + voice[i]->note = note; + voice[i]->velocity = velocity & 0x7F; + } + + for (i = 0; i < voices; i++) { + voice[i]->reg_f_number = (wave_data[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8; + opl4_write_wave_register(OPL4_REG_F_NUMBER + voice[i]->number, voice[i]->reg_f_number, opl4_midi); + + bool new_wave = (voice[i]->wave_data != wave_data[i]); + /* Set tone number (triggers header loading) */ + if (new_wave) { + opl4_write_wave_register(OPL4_REG_TONE_NUMBER + voice[i]->number, wave_data[i]->tone & 0xFF, opl4_midi); + voice[i]->wave_data = wave_data[i]; + } + + voice[i]->reg_misc = OPL4_LFO_RESET_BIT; + update_pan(voice[i], opl4_midi); + update_pitch(voice[i], 0, opl4_midi); + voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT; + update_volume(voice[i], opl4_midi); + if (new_wave) { + /* Set remaining parameters */ + opl4_write_wave_register(OPL4_REG_ATTACK_DECAY1 + voice[i]->number, voice[i]->wave_data->reg_attack_decay1, opl4_midi); + opl4_write_wave_register(OPL4_REG_LEVEL_DECAY2 + voice[i]->number, voice[i]->wave_data->reg_level_decay2, opl4_midi); + opl4_write_wave_register(OPL4_REG_RELEASE_CORRECTION + voice[i]->number, voice[i]->wave_data->reg_release_correction, opl4_midi); + opl4_write_wave_register(OPL4_REG_TREMOLO + voice[i]->number, voice[i]->wave_data->reg_tremolo, opl4_midi); + + voice[i]->reg_lfo_vibrato = voice[i]->wave_data->reg_lfo_vibrato; + + if (!midi_channel->drum_channel) + update_vibrato_depth(voice[i], opl4_midi); + } + } + + /* Finally, switch on all voices */ + for (i = 0; i < voices; i++) { + voice[i]->reg_misc = (voice[i]->reg_misc & 0x1F) | OPL4_KEY_ON_BIT; + opl4_write_wave_register(OPL4_REG_MISC + voice[i]->number, voice[i]->reg_misc, opl4_midi); + } +} + +void +control_change(uint8_t midi_channel, uint8_t id, uint8_t value, opl4_midi_t *opl4_midi) +{ + int i = 0; + switch (id) { + case 10: + /* Change stereo panning */ + if (midi_channel != DRUM_CHANNEL) { + opl4_midi->midi_channel_data[midi_channel].panpot = (value - 0x40) >> 3; + for (i = 0; i < NR_OF_WAVE_CHANNELS; i++) { + if (opl4_midi->voice_data[i].is_active && opl4_midi->voice_data[i].midi_channel == &opl4_midi->midi_channel_data[midi_channel]) { + update_pan(&opl4_midi->voice_data[i], opl4_midi); + } + } + } + break; + } +} + +void +pitch_wheel(uint8_t midi_channel, uint16_t value, opl4_midi_t *opl4_midi) +{ + int i = 0; + + for (i = 0; i < 24; i++) { + if (opl4_midi->voice_data[i].is_active && opl4_midi->voice_data[i].midi_channel == &opl4_midi->midi_channel_data[midi_channel]) { + update_pitch(&opl4_midi->voice_data[i], value, opl4_midi); + } + } +} + +void +channel_pressure(uint8_t midi_channel, uint8_t pressure) +{ + (void) midi_channel; + (void) pressure; +} + +void +key_pressure(uint8_t midi_channel, uint8_t note, uint8_t pressure) +{ + (void) midi_channel; + (void) note; + (void) pressure; +} + +void +program_change(uint8_t midi_channel, uint8_t program, opl4_midi_t *opl4_midi) +{ + opl4_midi->midi_channel_data[midi_channel].instrument = program; +} + +#define RENDER_RATE (48000 / 100) +static void +opl4_midi_thread(void *arg) +{ + opl4_midi_t *opl4_midi = opl4_midi_cur; + uint32_t i = 0; + uint32_t buf_size = RENDER_RATE * 2; + + int32_t buffer[RENDER_RATE * 2]; + + extern void givealbuffer_midi(void *buf, uint32_t size); + while (opl4_midi->on) { + thread_wait_event(opl4_midi->wait_event, -1); + thread_reset_event(opl4_midi->wait_event); + if (!opl4_midi->on) + break; + atomic_store(&opl4_midi->gen_in_progress, true); + opl4_midi->opl4.generate(opl4_midi->opl4.priv, buffer, RENDER_RATE); + atomic_store(&opl4_midi->gen_in_progress, false); + if (sound_is_float) { + for (i = 0; i < (buf_size / 2); i++) { + opl4_midi->buffer_float[i * 2] = buffer[i * 2] / 32768.0; + opl4_midi->buffer_float[(i * 2) + 1] = buffer[(i * 2) + 1] / 32768.0; + } + givealbuffer_midi(opl4_midi->buffer_float, buf_size); + } else { + for (i = 0; i < (buf_size / 2); i++) { + opl4_midi->buffer[i * 2] = buffer[i * 2] & 0xFFFF; /* Outputs are clamped beforehand. */ + opl4_midi->buffer[(i * 2) + 1] = buffer[(i * 2) + 1] & 0xFFFF; /* Outputs are clamped beforehand. */ + } + givealbuffer_midi(opl4_midi->buffer, buf_size); + } + } +} + +static void +opl4_midi_poll(void) +{ + opl4_midi_t *opl4_midi = opl4_midi_cur; + opl4_midi->midi_pos++; + if (opl4_midi->midi_pos == RENDER_RATE) { + opl4_midi->midi_pos = 0; + thread_set_event(opl4_midi->wait_event); + } +} + +void +opl4_midi_msg(uint8_t *val) +{ + opl4_midi_t *opl4_midi = opl4_midi_cur; + + uint32_t msg = *(uint32_t *) (val); + uint8_t data_byte_1 = msg & 0xFF; + uint8_t data_byte_2 = (msg >> 8) & 0xFF; + uint8_t data_byte_3 = (msg >> 16) & 0xFF; + + uint8_t midi_channel = data_byte_1 & 0x0F; + uint8_t midi_command = data_byte_1 >> 4; + + switch (midi_command) { + case 0x8: // Note OFF + note_off(data_byte_2 & 0x7F, data_byte_3, &opl4_midi->midi_channel_data[midi_channel], opl4_midi); + break; + case 0x9: // Note ON + note_on(data_byte_2 & 0x7F, data_byte_3, &opl4_midi->midi_channel_data[midi_channel], opl4_midi); + break; + case 0xA: // Key after-touch + break; + case 0xB: // Control change + control_change(midi_channel, data_byte_2, data_byte_3, opl4_midi); + break; + case 0xC: // Program change + program_change(midi_channel, data_byte_2 & 0x7F, opl4_midi); + break; + case 0xD: // Channel after-touch + break; + case 0xE: // Pitch wheel + pitch_wheel(midi_channel, ((data_byte_3 <<= 7) | data_byte_2), opl4_midi); + break; + } +} + +void +opl4_midi_sysex(uint8_t *data, unsigned int len) +{ +} + +void * +opl4_init(const device_t *info) +{ + midi_device_t *dev; + extern void al_set_midi(int freq, int buf_size); + + dev = malloc(sizeof(midi_device_t)); + memset(dev, 0, sizeof(midi_device_t)); + + dev->play_msg = opl4_midi_msg; + dev->play_sysex = opl4_midi_sysex; + dev->poll = opl4_midi_poll; + + al_set_midi(48000, 4800); + + opl4_midi_cur = calloc(1, sizeof(opl4_midi_t)); + + fm_driver_get(FM_YMF278B, &opl4_midi_cur->opl4); + + opl4_midi_cur->opl4.write(0x38A, 0x05, opl4_midi_cur->opl4.priv); + opl4_midi_cur->opl4.write(0x389, 0x3, opl4_midi_cur->opl4.priv); + midi_out_init(dev); + + opl4_midi_cur->on = true; + opl4_midi_cur->midi_channel_data[9].drum_channel = true; + atomic_init(&opl4_midi_cur->gen_in_progress, 0); + + for (uint8_t voice = 0; voice < NR_OF_WAVE_CHANNELS; voice++) { + opl4_midi_cur->voice_data[voice].number = voice; + opl4_midi_cur->voice_data[voice].is_active = false; + opl4_midi_cur->voice_data[voice].activated = 0; + opl4_midi_cur->voice_data[voice].midi_channel = NULL; + opl4_midi_cur->voice_data[voice].note = 0; + opl4_midi_cur->voice_data[voice].velocity = 0; + opl4_midi_cur->voice_data[voice].wave_data = NULL; + opl4_midi_cur->voice_data[voice].level_direct = 0; + opl4_midi_cur->voice_data[voice].reg_f_number = 0; + opl4_midi_cur->voice_data[voice].reg_misc = 0; + opl4_midi_cur->voice_data[voice].reg_lfo_vibrato = 0; + } + opl4_midi_cur->wait_event = thread_create_event(); + opl4_midi_cur->thread = thread_create(opl4_midi_thread, NULL); + return dev; +} + +void +opl4_close(void *p) +{ + if (!p) + return; + + opl4_midi_cur->on = false; + thread_set_event(opl4_midi_cur->wait_event); + thread_wait(opl4_midi_cur->thread); + free(opl4_midi_cur); + opl4_midi_cur = NULL; +} + +static int +opl4_midi_available(void) +{ + return rom_present("roms/sound/yamaha/yrw801.rom"); +} + +const device_t opl4_midi_device = { + .name = "OPL4-ML Daughterboard", + .internal_name = "opl4-ml", + .flags = 0, + .local = 0, + .init = opl4_init, + .close = opl4_close, + .reset = NULL, + { .available = opl4_midi_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sound/midi_opl4_yrw801.c b/src/sound/midi_opl4_yrw801.c new file mode 100644 index 000000000..96822b9af --- /dev/null +++ b/src/sound/midi_opl4_yrw801.c @@ -0,0 +1,1042 @@ +/* Table taken from linux/sound/drivers/opl4/yrw801.c */ +/* Macros from Linux source code as well */ + +#include "yrw801.h" + +static const YRW801_REGION_DATA regions_00[] = { + /* Acoustic Grand Piano */ + { 0x14, 0x27, { 0x12c, 7474, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6816, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5899, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5290, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4260, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3625, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3116, 100, 0, 0, 0x04, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2081, 100, 0, 0, 0x03, 0xc8, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1444, 100, 0, 0, 0x07, 0xc8, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1915, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_01[] = { + /* Bright Acoustic Piano */ + { 0x14, 0x2d, { 0x12c, 7474, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12d, 6816, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12e, 5899, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x12f, 5290, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x130, 4260, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x131, 3625, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x132, 3116, 100, 0, 0, 0x04, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x53, 0x58, { 0x133, 2081, 100, 0, 0, 0x07, 0xc8, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x59, 0x5e, { 0x134, 1444, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x5f, 0x6d, { 0x135, 1915, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_02[] = { + /* Electric Grand Piano */ + { 0x14, 0x2d, { 0x12c, 7476, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x13, 0x07, 0x0 } }, + { 0x2e, 0x33, { 0x12d, 6818, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x34, 0x39, { 0x12e, 5901, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x3a, 0x3f, { 0x12f, 5292, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x40, 0x45, { 0x130, 4262, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x46, 0x4b, { 0x131, 3627, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x4c, 0x52, { 0x132, 3118, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x53, 0x58, { 0x133, 2083, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x17, 0x0 } }, + { 0x59, 0x5e, { 0x134, 1446, 100, 1, 0, 0x00, 0xae, 0x20, 0xf3, 0x14, 0x17, 0x0 } }, + { 0x5f, 0x6d, { 0x135, 1917, 100, 1, 0, 0x00, 0xae, 0x20, 0xf4, 0x15, 0x07, 0x0 } }, + { 0x00, 0x7f, { 0x06c, 6375, 100, -1, 0, 0x00, 0xc2, 0x28, 0xf4, 0x23, 0x18, 0x0 }} +}; +static const YRW801_REGION_DATA regions_03[] = { + /* Honky-Tonk Piano */ + { 0x14, 0x27, { 0x12c, 7474, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6816, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5899, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5290, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4260, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3625, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3116, 100, 0, 0, 0x04, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2081, 100, 0, 0, 0x03, 0xb4, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1444, 100, 0, 0, 0x07, 0xb4, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1915, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf4, 0x15, 0x08, 0x0 }}, + { 0x14, 0x27, { 0x12c, 7486, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6803, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5912, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5275, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4274, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3611, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3129, 100, 0, 0, 0x04, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2074, 100, 0, 0, 0x07, 0xb4, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1457, 100, 0, 0, 0x01, 0xb4, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1903, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_04[] = { + /* Electric Piano 1 */ + { 0x15, 0x6c, { 0x00b, 6570, 100, 0, 0, 0x00, 0x28, 0x38, 0xf0, 0x00, 0x0c, 0x0 }}, + { 0x00, 0x7f, { 0x06c, 6375, 100, 0, 2, 0x00, 0xb0, 0x22, 0xf4, 0x23, 0x19, 0x0 }} +}; +static const YRW801_REGION_DATA regions_05[] = { + /* Electric Piano 2 */ + { 0x14, 0x27, { 0x12c, 7476, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6818, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5901, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5292, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4262, 100, 0, 3, 0x0a, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3627, 100, 0, 3, 0x0a, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3118, 100, 0, 3, 0x04, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2083, 100, 0, 3, 0x03, 0xa2, 0x1b, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1446, 100, 0, 3, 0x07, 0xa2, 0x1b, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1917, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf4, 0x15, 0x08, 0x0 }}, + { 0x14, 0x2d, { 0x12c, 7472, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12d, 6814, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12e, 5897, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x12f, 5288, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x130, 4258, 100, 0, 0, 0x0a, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x131, 3623, 100, 0, 0, 0x0a, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x132, 3114, 100, 0, 0, 0x04, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x53, 0x58, { 0x133, 2079, 100, 0, 0, 0x07, 0xa2, 0x18, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x59, 0x5e, { 0x134, 1442, 100, 0, 0, 0x0a, 0xa2, 0x18, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x5f, 0x6d, { 0x135, 1913, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_06[] = { + /* Harpsichord */ + { 0x15, 0x39, { 0x080, 5158, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x24, 0x19, 0x0 }}, + { 0x3a, 0x3f, { 0x081, 4408, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x09, 0x0 }}, + { 0x40, 0x45, { 0x082, 3622, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x09, 0x0 }}, + { 0x46, 0x4d, { 0x083, 2843, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x19, 0x0 }}, + { 0x4e, 0x6c, { 0x084, 1307, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x29, 0x0 }} +}; +static const YRW801_REGION_DATA regions_07[] = { + /* Clavinet */ + { 0x15, 0x51, { 0x027, 5009, 100, 0, 0, 0x00, 0xd2, 0x28, 0xf5, 0x13, 0x2b, 0x0 }}, + { 0x52, 0x6c, { 0x028, 3495, 100, 0, 0, 0x00, 0xd2, 0x28, 0xf5, 0x13, 0x3b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_08[] = { + /* Celesta */ + { 0x15, 0x6c, { 0x02b, 3267, 100, 0, 0, 0x00, 0xdc, 0x20, 0xf4, 0x15, 0x07, 0x3 }} +}; +static const YRW801_REGION_DATA regions_09[] = { + /* Glockenspiel */ + { 0x15, 0x78, { 0x0f3, 285, 100, 0, 0, 0x00, 0xc2, 0x28, 0xf6, 0x25, 0x25, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0a[] = { + /* Music Box */ + { 0x15, 0x6c, { 0x0f3, 3362, 100, 0, 0, 0x00, 0xb6, 0x20, 0xa6, 0x25, 0x25, 0x0 }}, + { 0x15, 0x6c, { 0x101, 4773, 100, 0, 0, 0x00, 0xaa, 0x20, 0xd4, 0x14, 0x16, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0b[] = { + /* Vibraphone */ + { 0x15, 0x6c, { 0x101, 4778, 100, 0, 0, 0x00, 0xc0, 0x28, 0xf4, 0x14, 0x16, 0x4 }} +}; +static const YRW801_REGION_DATA regions_0c[] = { + /* Marimba */ + { 0x15, 0x3f, { 0x0f4, 4778, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x47, 0x08, 0x0 }}, + { 0x40, 0x4c, { 0x0f5, 3217, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x47, 0x08, 0x0 }}, + { 0x4d, 0x5a, { 0x0f5, 3217, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x48, 0x08, 0x0 }}, + { 0x5b, 0x7f, { 0x0f5, 3218, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x48, 0x18, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0d[] = { + /* Xylophone */ + { 0x00, 0x7f, { 0x136, 1729, 100, 0, 0, 0x00, 0xd2, 0x38, 0xf0, 0x06, 0x36, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0e[] = { + /* Tubular Bell */ + { 0x01, 0x7f, { 0x0ff, 3999, 100, 0, 1, 0x00, 0x90, 0x21, 0xf4, 0xa3, 0x25, 0x1 }} +}; +static const YRW801_REGION_DATA regions_0f[] = { + /* Dulcimer */ + { 0x00, 0x7f, { 0x03f, 4236, 100, 0, 1, 0x00, 0xbc, 0x29, 0xf5, 0x16, 0x07, 0x0 }}, + { 0x00, 0x7f, { 0x040, 4236, 100, 0, 2, 0x0e, 0x94, 0x2a, 0xf5, 0x16, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_10[] = { + /* Drawbar Organ */ + { 0x01, 0x7f, { 0x08e, 4394, 100, 0, 2, 0x14, 0xc2, 0x3a, 0xf0, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_11[] = { + /* Percussive Organ */ + { 0x15, 0x3b, { 0x08c, 6062, 100, 0, 3, 0x00, 0xbe, 0x3b, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3c, 0x6c, { 0x08d, 2984, 100, 0, 3, 0x00, 0xbe, 0x3b, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_12[] = { + /* Rock Organ */ + { 0x15, 0x30, { 0x128, 6574, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x31, 0x3c, { 0x129, 5040, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x3d, 0x48, { 0x12a, 3498, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x49, 0x54, { 0x12b, 1957, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x55, 0x6c, { 0x127, 423, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 } } +}; +static const YRW801_REGION_DATA regions_13[] = { + /* Church Organ */ + { 0x15, 0x29, { 0x087, 7466, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x2a, 0x30, { 0x088, 6456, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x31, 0x38, { 0x089, 5428, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x39, 0x41, { 0x08a, 4408, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x42, 0x6c, { 0x08b, 3406, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_14[] = { + /* Reed Organ */ + { 0x00, 0x53, { 0x0ac, 5570, 100, 0, 0, 0x06, 0xc0, 0x38, 0xf0, 0x00, 0x09, 0x1 }}, + { 0x54, 0x7f, { 0x0ad, 2497, 100, 0, 0, 0x00, 0xc0, 0x38, 0xf0, 0x00, 0x09, 0x1 }} +}; +static const YRW801_REGION_DATA regions_15[] = { + /* Accordion */ + { 0x15, 0x4c, { 0x006, 4261, 100, 0, 2, 0x00, 0xa4, 0x22, 0x90, 0x00, 0x09, 0x0 }}, + { 0x4d, 0x6c, { 0x007, 1530, 100, 0, 2, 0x00, 0xa4, 0x22, 0x90, 0x00, 0x09, 0x0 }}, + { 0x15, 0x6c, { 0x070, 4391, 100, 0, 3, 0x00, 0x8a, 0x23, 0xa0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_16[] = { + /* Harmonica */ + { 0x15, 0x6c, { 0x070, 4408, 100, 0, 0, 0x00, 0xae, 0x30, 0xa0, 0x00, 0x09, 0x2 }} +}; +static const YRW801_REGION_DATA regions_17[] = { + /* Tango Accordion */ + { 0x00, 0x53, { 0x0ac, 5573, 100, 0, 0, 0x00, 0xae, 0x38, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x54, 0x7f, { 0x0ad, 2500, 100, 0, 0, 0x00, 0xae, 0x38, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x15, 0x6c, { 0x041, 8479, 100, 0, 2, 0x00, 0x6a, 0x3a, 0x75, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_18[] = { + /* Nylon Guitar */ + { 0x15, 0x2f, { 0x0b3, 6964, 100, 0, 0, 0x05, 0xca, 0x28, 0xf5, 0x34, 0x09, 0x0 }}, + { 0x30, 0x36, { 0x0b7, 5567, 100, 0, 0, 0x0c, 0xca, 0x28, 0xf5, 0x34, 0x09, 0x0 }}, + { 0x37, 0x3c, { 0x0b5, 4653, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }}, + { 0x3d, 0x43, { 0x0b4, 3892, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x35, 0x09, 0x0 }}, + { 0x44, 0x60, { 0x0b6, 2723, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x35, 0x19, 0x0 }} +}; +static const YRW801_REGION_DATA regions_19[] = { + /* Steel Guitar */ + { 0x15, 0x31, { 0x00c, 6937, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x04, 0x19, 0x0 }}, + { 0x32, 0x38, { 0x00d, 5410, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x05, 0x09, 0x0 }}, + { 0x39, 0x47, { 0x00e, 4379, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf5, 0x94, 0x09, 0x0 }}, + { 0x48, 0x6c, { 0x00f, 2843, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf6, 0x95, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1a[] = { + /* Jazz Guitar */ + { 0x15, 0x31, { 0x05a, 6832, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }}, + { 0x32, 0x3f, { 0x05b, 4897, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }}, + { 0x40, 0x6c, { 0x05c, 3218, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1b[] = { + /* Clean Guitar */ + { 0x15, 0x2c, { 0x061, 7053, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x54, 0x0a, 0x0 }}, + { 0x2d, 0x31, { 0x060, 6434, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x54, 0x0a, 0x0 }}, + { 0x32, 0x38, { 0x063, 5764, 100, 0, 1, 0x00, 0xbe, 0x29, 0xf5, 0x55, 0x0a, 0x0 }}, + { 0x39, 0x3f, { 0x062, 4627, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x0a, 0x0 }}, + { 0x40, 0x44, { 0x065, 3963, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x1a, 0x0 }}, + { 0x45, 0x4b, { 0x064, 3313, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x1a, 0x0 }}, + { 0x4c, 0x54, { 0x066, 2462, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x2a, 0x0 }}, + { 0x55, 0x6c, { 0x067, 1307, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf6, 0x56, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1c[] = { + /* Muted Guitar */ + { 0x01, 0x7f, { 0x068, 4408, 100, 0, 0, 0x00, 0xcc, 0x28, 0xf6, 0x15, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1d[] = { + /* Overdriven Guitar */ + { 0x00, 0x40, { 0x0a5, 6589, 100, 0, 1, 0x00, 0xc0, 0x29, 0xf2, 0x11, 0x09, 0x0 }}, + { 0x41, 0x7f, { 0x0a6, 5428, 100, 0, 1, 0x00, 0xc0, 0x29, 0xf2, 0x11, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1e[] = { + /* Distortion Guitar */ + { 0x15, 0x2a, { 0x051, 6928, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x2b, 0x2e, { 0x052, 6433, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x2f, 0x32, { 0x053, 5944, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x33, 0x36, { 0x054, 5391, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x37, 0x3a, { 0x055, 4897, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x3b, 0x3e, { 0x056, 4408, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x3f, 0x42, { 0x057, 3892, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x43, 0x46, { 0x058, 3361, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x47, 0x6c, { 0x059, 2784, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1f[] = { + /* Guitar Harmonics */ + { 0x15, 0x44, { 0x05e, 5499, 100, 0, 0, 0x00, 0xce, 0x28, 0xf4, 0x24, 0x09, 0x0 }}, + { 0x45, 0x49, { 0x05d, 4850, 100, 0, 0, 0x00, 0xe2, 0x28, 0xf4, 0x24, 0x09, 0x0 }}, + { 0x4a, 0x6c, { 0x05f, 4259, 100, 0, 0, 0x00, 0xce, 0x28, 0xf4, 0x24, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_20[] = { + /* Acoustic Bass */ + { 0x15, 0x30, { 0x004, 8053, 100, 0, 0, 0x00, 0xe2, 0x18, 0xf5, 0x15, 0x09, 0x0 }}, + { 0x31, 0x6c, { 0x005, 4754, 100, 0, 0, 0x00, 0xe2, 0x18, 0xf5, 0x15, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_21[] = { + /* Fingered Bass */ + { 0x01, 0x20, { 0x04a, 8762, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }}, + { 0x21, 0x25, { 0x04b, 8114, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }}, + { 0x26, 0x2a, { 0x04c, 7475, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }}, + { 0x2b, 0x7f, { 0x04d, 6841, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_22[] = { + /* Picked Bass */ + { 0x15, 0x23, { 0x04f, 7954, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf3, 0x90, 0x0a, 0x0 }}, + { 0x24, 0x2a, { 0x050, 7318, 100, 0, 0, 0x05, 0xcc, 0x18, 0xf3, 0x90, 0x1a, 0x0 }}, + { 0x2b, 0x2f, { 0x06b, 6654, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf3, 0x90, 0x2a, 0x0 }}, + { 0x30, 0x47, { 0x069, 6031, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf5, 0xb0, 0x0a, 0x0 }}, + { 0x48, 0x6c, { 0x06a, 5393, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf5, 0xb0, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_23[] = { + /* Fretless Bass */ + { 0x01, 0x7f, { 0x04e, 5297, 100, 0, 0, 0x00, 0xd2, 0x10, 0xf3, 0x63, 0x19, 0x0 }} +}; +static const YRW801_REGION_DATA regions_24[] = { + /* Slap Bass 1 */ + { 0x15, 0x6c, { 0x0a3, 7606, 100, 0, 1, 0x00, 0xde, 0x19, 0xf5, 0x32, 0x1a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_25[] = { + /* Slap Bass 2 */ + { 0x01, 0x7f, { 0x0a2, 6694, 100, 0, 0, 0x00, 0xda, 0x20, 0xb0, 0x02, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_26[] = { + /* Synth Bass 1 */ + { 0x15, 0x6c, { 0x0be, 7466, 100, 0, 1, 0x00, 0xb8, 0x39, 0xf4, 0x14, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_27[] = { + /* Synth Bass 2 */ + { 0x00, 0x7f, { 0x117, 8103, 100, 0, 1, 0x00, 0xca, 0x39, 0xf3, 0x50, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_28[] = { + /* Violin */ + { 0x15, 0x3a, { 0x105, 5158, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x3b, 0x3f, { 0x102, 4754, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x40, 0x41, { 0x106, 4132, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x42, 0x44, { 0x107, 4033, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x45, 0x47, { 0x108, 3580, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x48, 0x4a, { 0x10a, 2957, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4b, 0x4c, { 0x10b, 2724, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4d, 0x4e, { 0x10c, 2530, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4f, 0x51, { 0x10d, 2166, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x52, 0x6c, { 0x109, 1825, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_29[] = { + /* Viola */ + { 0x15, 0x32, { 0x103, 5780, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x33, 0x35, { 0x104, 5534, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x36, 0x38, { 0x105, 5158, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x39, 0x3d, { 0x102, 4754, 100, 0, 3, 0x00, 0xca, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x3e, 0x3f, { 0x106, 4132, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x40, 0x42, { 0x107, 4033, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x43, 0x45, { 0x108, 3580, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x46, 0x48, { 0x10a, 2957, 100, 0, 3, 0x00, 0xca, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x49, 0x4a, { 0x10b, 2724, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x4b, 0x4c, { 0x10c, 2530, 100, 0, 3, 0x00, 0xca, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x4d, 0x4f, { 0x10d, 2166, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x50, 0x6c, { 0x109, 1825, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2a[] = { + /* Cello */ + { 0x15, 0x2d, { 0x112, 6545, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x08, 0x0 }}, + { 0x2e, 0x37, { 0x113, 5764, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x08, 0x0 }}, + { 0x38, 0x3e, { 0x115, 4378, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x18, 0x0 }}, + { 0x3f, 0x44, { 0x116, 3998, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x18, 0x0 }}, + { 0x45, 0x6c, { 0x114, 3218, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x18, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2b[] = { + /* Contrabass */ + { 0x15, 0x29, { 0x110, 7713, 100, 0, 1, 0x00, 0xc2, 0x19, 0x90, 0x00, 0x09, 0x0 }}, + { 0x2a, 0x6c, { 0x111, 6162, 100, 0, 1, 0x00, 0xc2, 0x19, 0x90, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2c[] = { + /* Tremolo Strings */ + { 0x15, 0x3b, { 0x0b0, 4810, 100, 0, 0, 0x0a, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x3c, 0x41, { 0x035, 4035, 100, 0, 0, 0x05, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x42, 0x47, { 0x033, 3129, 100, 0, 0, 0x05, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x48, 0x52, { 0x034, 2625, 100, 0, 0, 0x05, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x53, 0x6c, { 0x0af, 936, 100, 0, 0, 0x00, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 } } +}; +static const YRW801_REGION_DATA regions_2d[] = { + /* Pizzicato Strings */ + { 0x15, 0x32, { 0x0b8, 6186, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x33, 0x3b, { 0x0b9, 5031, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x3c, 0x42, { 0x0bb, 4146, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x43, 0x48, { 0x0ba, 3245, 100, 0, 0, 0x00, 0xc2, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x49, 0x6c, { 0x0bc, 2352, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2e[] = { + /* Harp */ + { 0x15, 0x46, { 0x07e, 3740, 100, 0, 1, 0x00, 0xd2, 0x29, 0xf5, 0x25, 0x07, 0x0 }}, + { 0x47, 0x6c, { 0x07f, 2319, 100, 0, 1, 0x00, 0xd2, 0x29, 0xf5, 0x25, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2f[] = { + /* Timpani */ + { 0x15, 0x6c, { 0x100, 6570, 100, 0, 0, 0x00, 0xf8, 0x28, 0xf0, 0x05, 0x16, 0x0 }} +}; +static const YRW801_REGION_DATA regions_30[] = { + /* Strings */ + { 0x15, 0x3b, { 0x13c, 4806, 100, 0, 0, 0x00, 0xc8, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x3c, 0x41, { 0x13e, 4035, 100, 0, 0, 0x00, 0xc8, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x42, 0x47, { 0x13d, 3122, 100, 0, 0, 0x00, 0xc8, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x48, 0x52, { 0x13f, 2629, 100, 0, 0, 0x00, 0xbe, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x53, 0x6c, { 0x140, 950, 100, 0, 0, 0x00, 0xbe, 0x20, 0x80, 0x00, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_31[] = { + /* Slow Strings */ + { 0x15, 0x3b, { 0x0b0, 4810, 100, 0, 1, 0x0a, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x3c, 0x41, { 0x035, 4035, 100, 0, 1, 0x05, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x42, 0x47, { 0x033, 3129, 100, 0, 1, 0x05, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x48, 0x52, { 0x034, 2625, 100, 0, 1, 0x05, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x53, 0x6c, { 0x0af, 936, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_32[] = { + /* Synth Strings 1 */ + { 0x05, 0x71, { 0x002, 6045, 100, -2, 0, 0x00, 0xa6, 0x20, 0x93, 0x22, 0x06, 0x0 }}, + { 0x15, 0x6c, { 0x0ae, 3261, 100, 2, 0, 0x00, 0xc6, 0x20, 0x70, 0x01, 0x06, 0x0 } } +}; +static const YRW801_REGION_DATA regions_33[] = { + /* Synth Strings 2 */ + { 0x15, 0x6c, { 0x002, 4513, 100, 5, 1, 0x00, 0xb4, 0x19, 0x70, 0x00, 0x06, 0x0 } }, + { 0x15, 0x6c, { 0x002, 4501, 100, -5, 1, 0x00, 0xb4, 0x19, 0x70, 0x00, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_34[] = { + /* Choir Aahs */ + { 0x15, 0x3a, { 0x018, 5010, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }}, + { 0x3b, 0x40, { 0x019, 4370, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }}, + { 0x41, 0x47, { 0x01a, 3478, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }}, + { 0x48, 0x6c, { 0x01b, 2197, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_35[] = { + /* Voice Oohs */ + { 0x15, 0x6c, { 0x029, 3596, 100, 0, 0, 0x00, 0xe6, 0x20, 0xf7, 0x20, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_36[] = { + /* Synth Voice */ + { 0x15, 0x6c, { 0x02a, 3482, 100, 0, 1, 0x00, 0xc2, 0x19, 0x85, 0x21, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_37[] = { + /* Orchestra Hit */ + { 0x15, 0x6c, { 0x049, 4394, 100, 0, 0, 0x00, 0xfe, 0x30, 0x80, 0x05, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_38[] = { + /* Trumpet */ + { 0x15, 0x3c, { 0x0f6, 4706, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x3d, 0x43, { 0x0f8, 3894, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x44, 0x48, { 0x0f7, 3118, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x49, 0x4e, { 0x0fa, 2322, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x4f, 0x55, { 0x0f9, 1634, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x56, 0x6c, { 0x0fb, 786, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 } } +}; +static const YRW801_REGION_DATA regions_39[] = { + /* Trombone */ + { 0x15, 0x3a, { 0x0f0, 5053, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3b, 0x3f, { 0x0f1, 4290, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x40, 0x6c, { 0x0f2, 3580, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3a[] = { + /* Tuba */ + { 0x15, 0x2d, { 0x085, 7096, 100, 0, 1, 0x00, 0xde, 0x21, 0xf5, 0x10, 0x09, 0x0 }}, + { 0x2e, 0x6c, { 0x086, 6014, 100, 0, 1, 0x00, 0xde, 0x21, 0xf5, 0x10, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3b[] = { + /* Muted Trumpet */ + { 0x15, 0x45, { 0x0b1, 4135, 100, 0, 0, 0x00, 0xcc, 0x28, 0xf3, 0x10, 0x0a, 0x1 }}, + { 0x46, 0x6c, { 0x0b2, 2599, 100, 0, 0, 0x00, 0xcc, 0x28, 0x83, 0x10, 0x0a, 0x1 }} +}; +static const YRW801_REGION_DATA regions_3c[] = { + /* French Horns */ + { 0x15, 0x49, { 0x07c, 3624, 100, 0, 2, 0x00, 0xd0, 0x1a, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x4a, 0x6c, { 0x07d, 2664, 100, 0, 2, 0x00, 0xd0, 0x1a, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3d[] = { + /* Brass Section */ + { 0x15, 0x42, { 0x0fc, 4375, 100, 0, 0, 0x00, 0xd6, 0x28, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x43, 0x6c, { 0x0fd, 2854, 100, 0, 0, 0x00, 0xd6, 0x28, 0xf0, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3e[] = { + /* Synth Brass 1 */ + { 0x01, 0x27, { 0x0d3, 9094, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x0da, 8335, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x0d4, 7558, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x0db, 6785, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x0d5, 6042, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x0dc, 5257, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x0d6, 4493, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x4c, 0x51, { 0x0dd, 3741, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x52, 0x57, { 0x0d7, 3012, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x58, 0x5d, { 0x0de, 2167, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x5e, 0x63, { 0x0d8, 1421, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x64, 0x7f, { 0x0d9, -115, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x01, 0x27, { 0x118, 9103, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x28, 0x2d, { 0x119, 8340, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x2e, 0x33, { 0x11a, 7565, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x34, 0x39, { 0x11b, 6804, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x3a, 0x3f, { 0x11c, 6042, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x40, 0x45, { 0x11d, 5277, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x46, 0x4b, { 0x11e, 4520, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x4c, 0x51, { 0x11f, 3741, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x52, 0x57, { 0x120, 3012, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x58, 0x5d, { 0x121, 2166, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x5e, 0x64, { 0x122, 1421, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x65, 0x7f, { 0x123, -115, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } } +}; +static const YRW801_REGION_DATA regions_3f[] = { + /* Synth Brass 2 */ + { 0x01, 0x27, { 0x118, 9113, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x28, 0x2d, { 0x119, 8350, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x2e, 0x33, { 0x11a, 7575, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x34, 0x39, { 0x11b, 6814, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x3a, 0x3f, { 0x11c, 6052, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x40, 0x45, { 0x11d, 5287, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x46, 0x4b, { 0x11e, 4530, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x4c, 0x51, { 0x11f, 3751, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x52, 0x57, { 0x120, 3022, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x58, 0x5d, { 0x121, 2176, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x5e, 0x64, { 0x122, 1431, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x65, 0x7f, { 0x123, -105, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x00, 0x7f, { 0x124, 4034, 100, -3, 2, 0x00, 0xea, 0x22, 0x85, 0x23, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_40[] = { + /* Soprano Sax */ + { 0x15, 0x3f, { 0x0e3, 4228, 100, 0, 1, 0x00, 0xc8, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x0e4, 3495, 100, 0, 1, 0x00, 0xc8, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x0e5, 2660, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x0e6, 2002, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x52, 0x59, { 0x0e7, 1186, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x59, 0x6c, { 0x0e8, 1730, 100, 0, 1, 0x00, 0xc8, 0x21, 0xf5, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_41[] = { + /* Alto Sax */ + { 0x15, 0x32, { 0x092, 6204, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x33, 0x35, { 0x096, 5812, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x36, 0x3a, { 0x099, 5318, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x3b, 0x3b, { 0x08f, 5076, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x3c, 0x3e, { 0x093, 4706, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x3f, 0x41, { 0x097, 4321, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x42, 0x44, { 0x09a, 3893, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x45, 0x47, { 0x090, 3497, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x48, 0x4a, { 0x094, 3119, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x4b, 0x4d, { 0x098, 2726, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x4e, 0x50, { 0x09b, 2393, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x51, 0x53, { 0x091, 2088, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x54, 0x6c, { 0x095, 1732, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_42[] = { + /* Tenor Sax */ + { 0x24, 0x30, { 0x0e9, 6301, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x31, 0x34, { 0x0ea, 5781, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x35, 0x3a, { 0x0eb, 5053, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x3b, 0x41, { 0x0ed, 4165, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x42, 0x47, { 0x0ec, 3218, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x48, 0x51, { 0x0ee, 2462, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x52, 0x6c, { 0x0ef, 1421, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_43[] = { + /* Baritone Sax */ + { 0x15, 0x2d, { 0x0df, 6714, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x2e, 0x34, { 0x0e1, 5552, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x35, 0x39, { 0x0e2, 5178, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x3a, 0x6c, { 0x0e0, 4437, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_44[] = { + /* Oboe */ + { 0x15, 0x3c, { 0x042, 4493, 100, 0, 1, 0x00, 0xe6, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x3d, 0x43, { 0x044, 3702, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x44, 0x49, { 0x043, 2956, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x4a, 0x4f, { 0x046, 2166, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x50, 0x55, { 0x045, 1420, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x56, 0x6c, { 0x047, 630, 100, 0, 1, 0x00, 0xe6, 0x39, 0xf4, 0x10, 0x0a, 0x0 } } +}; +static const YRW801_REGION_DATA regions_45[] = { + /* English Horn */ + { 0x15, 0x38, { 0x03c, 5098, 100, 0, 1, 0x00, 0xc4, 0x31, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x39, 0x3e, { 0x03b, 4291, 100, 0, 1, 0x00, 0xc4, 0x31, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3f, 0x6c, { 0x03d, 3540, 100, 0, 1, 0x00, 0xc4, 0x31, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_46[] = { + /* Bassoon */ + { 0x15, 0x22, { 0x038, 7833, 100, 0, 1, 0x00, 0xc6, 0x31, 0xf0, 0x00, 0x0b, 0x0 }}, + { 0x23, 0x2e, { 0x03a, 7070, 100, 0, 1, 0x00, 0xc6, 0x31, 0xf0, 0x00, 0x0b, 0x0 }}, + { 0x2f, 0x6c, { 0x039, 6302, 100, 0, 1, 0x00, 0xc6, 0x31, 0xf0, 0x00, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_47[] = { + /* Clarinet */ + { 0x15, 0x3b, { 0x09e, 5900, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x3c, 0x41, { 0x0a0, 5158, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x42, 0x4a, { 0x09f, 4260, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x4b, 0x6c, { 0x0a1, 2957, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_48[] = { + /* Piccolo */ + { 0x15, 0x40, { 0x071, 4803, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x41, 0x4d, { 0x072, 3314, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x4e, 0x53, { 0x073, 1731, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x54, 0x5f, { 0x074, 2085, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x60, 0x6c, { 0x075, 1421, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }} +}; +static const YRW801_REGION_DATA regions_49[] = { + /* Flute */ + { 0x15, 0x40, { 0x071, 4803, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x41, 0x4d, { 0x072, 3314, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x4e, 0x6c, { 0x073, 1731, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }} +}; +static const YRW801_REGION_DATA regions_4a[] = { + /* Recorder */ + { 0x15, 0x6f, { 0x0bd, 4897, 100, 0, 0, 0x00, 0xec, 0x30, 0x70, 0x00, 0x09, 0x1 }} +}; +static const YRW801_REGION_DATA regions_4b[] = { + /* Pan Flute */ + { 0x15, 0x6c, { 0x077, 2359, 100, 0, 0, 0x00, 0xde, 0x38, 0xf0, 0x00, 0x09, 0x3 }} +}; +static const YRW801_REGION_DATA regions_4c[] = { + /* Bottle Blow */ + { 0x15, 0x6c, { 0x077, 2359, 100, 0, 0, 0x00, 0xc8, 0x38, 0xf0, 0x00, 0x09, 0x1 }}, + { 0x01, 0x7f, { 0x125, 7372, 100, 0, 0, 0x1e, 0x80, 0x00, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_4d[] = { + /* Shakuhachi */ + { 0x00, 0x7f, { 0x0ab, 4548, 100, 0, 0, 0x00, 0xd6, 0x30, 0xf0, 0x00, 0x0a, 0x3 }}, + { 0x15, 0x6c, { 0x076, 3716, 100, 0, 0, 0x00, 0xa2, 0x28, 0x70, 0x00, 0x09, 0x2 }} +}; +static const YRW801_REGION_DATA regions_4e[] = { + /* Whistle */ + { 0x00, 0x7f, { 0x0aa, 1731, 100, 0, 4, 0x00, 0xd2, 0x2c, 0x70, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_4f[] = { + /* Ocarina */ + { 0x00, 0x7f, { 0x0aa, 1731, 100, 0, 1, 0x00, 0xce, 0x29, 0x90, 0x00, 0x0a, 0x1 }} +}; +static const YRW801_REGION_DATA regions_50[] = { + /* Square Lead */ + { 0x01, 0x2a, { 0x0cc, 9853, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x2b, 0x36, { 0x0cd, 6785, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x37, 0x42, { 0x0ca, 5248, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x43, 0x4e, { 0x0cf, 3713, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x4f, 0x5a, { 0x0ce, 2176, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x5b, 0x7f, { 0x0cb, 640, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x01, 0x2a, { 0x0cc, 9844, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x2b, 0x36, { 0x0cd, 6776, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x37, 0x42, { 0x0ca, 5239, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x43, 0x4e, { 0x0cf, 3704, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x4f, 0x5a, { 0x0ce, 2167, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x5b, 0x7f, { 0x0cb, 631, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 } } +}; +static const YRW801_REGION_DATA regions_51[] = { + /* Sawtooth Lead */ + { 0x01, 0x27, { 0x118, 9108, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8345, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7570, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6809, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6047, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5282, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4525, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3746, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x52, 0x57, { 0x120, 3017, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2171, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1426, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x67, 0x7f, { 0x123, -110, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x01, 0x27, { 0x118, 9098, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8335, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7560, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6799, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6037, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5272, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4515, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3736, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x52, 0x57, { 0x120, 3007, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2161, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1416, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x67, 0x7f, { 0x123, -120, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_52[] = { + /* Calliope Lead */ + { 0x00, 0x7f, { 0x0aa, 1731, 100, 0, 0, 0x00, 0xc2, 0x28, 0x90, 0x00, 0x0a, 0x2 }}, + { 0x15, 0x6c, { 0x076, 3716, 100, 0, 0, 0x00, 0xb6, 0x28, 0xb0, 0x00, 0x09, 0x2 }} +}; +static const YRW801_REGION_DATA regions_53[] = { + /* Chiffer Lead */ + { 0x00, 0x7f, { 0x13a, 3665, 100, 0, 2, 0x00, 0xcc, 0x2a, 0xf0, 0x10, 0x09, 0x1 }}, + { 0x01, 0x7f, { 0x0fe, 3660, 100, 0, 0, 0x00, 0xbe, 0x28, 0xf3, 0x10, 0x17, 0x0 }} +}; +static const YRW801_REGION_DATA regions_54[] = { + /* Charang Lead */ + { 0x00, 0x40, { 0x0a5, 6594, 100, 0, 3, 0x00, 0xba, 0x33, 0xf2, 0x11, 0x09, 0x0 }}, + { 0x41, 0x7f, { 0x0a6, 5433, 100, 0, 3, 0x00, 0xba, 0x33, 0xf2, 0x11, 0x09, 0x0 }}, + { 0x01, 0x27, { 0x118, 9098, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8335, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7560, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6799, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6037, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5272, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4515, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3736, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x52, 0x57, { 0x120, 3007, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2161, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1416, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x67, 0x7f, { 0x123, -120, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }} +}; +static const YRW801_REGION_DATA regions_55[] = { + /* Voice Lead */ + { 0x00, 0x7f, { 0x0aa, 1739, 100, 0, 6, 0x00, 0x8c, 0x2e, 0x90, 0x00, 0x0a, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3474, 100, 0, 1, 0x00, 0xd8, 0x29, 0xf0, 0x05, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_56[] = { + /* 5ths Lead */ + { 0x01, 0x27, { 0x118, 8468, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x119, 7705, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 6930, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6169, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 5407, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x11d, 4642, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 3885, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3106, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x52, 0x57, { 0x120, 2377, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x58, 0x5d, { 0x121, 1531, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x5e, 0x64, { 0x122, 786, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 } }, + { 0x65, 0x7f, { 0x123, -750, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x05, 0x71, { 0x002, 4503, 100, 0, 1, 0x00, 0xb8, 0x31, 0xb3, 0x20, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_57[] = { + /* Bass & Lead */ + { 0x00, 0x7f, { 0x117, 8109, 100, 0, 1, 0x00, 0xbc, 0x29, 0xf3, 0x50, 0x08, 0x0 }}, + { 0x01, 0x27, { 0x118, 9097, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8334, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7559, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6798, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6036, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5271, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4514, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3735, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x52, 0x57, { 0x120, 3006, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2160, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1415, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x67, 0x7f, { 0x123, -121, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_58[] = { + /* New Age Pad */ + { 0x15, 0x6c, { 0x002, 4501, 100, 0, 4, 0x00, 0xa4, 0x24, 0x80, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x0f3, 4253, 100, 0, 3, 0x00, 0x8c, 0x23, 0xa2, 0x14, 0x06, 0x1 }} +}; +static const YRW801_REGION_DATA regions_59[] = { + /* Warm Pad */ + { 0x15, 0x6c, { 0x04e, 5306, 100, 2, 2, 0x00, 0x92, 0x2a, 0x34, 0x23, 0x05, 0x2 } }, + { 0x15, 0x6c, { 0x029, 3575, 100, -2, 2, 0x00, 0xbe, 0x22, 0x31, 0x23, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5a[] = { + /* Polysynth Pad */ + { 0x01, 0x27, { 0x118, 9111, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x28, 0x2d, { 0x119, 8348, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x2e, 0x33, { 0x11a, 7573, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x34, 0x39, { 0x11b, 6812, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x3a, 0x3f, { 0x11c, 6050, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x40, 0x45, { 0x11d, 5285, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x46, 0x4b, { 0x11e, 4528, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x4c, 0x51, { 0x11f, 3749, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x52, 0x57, { 0x120, 3020, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x58, 0x5d, { 0x121, 2174, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x5e, 0x66, { 0x122, 1429, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x67, 0x7f, { 0x123, -107, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x00, 0x7f, { 0x124, 4024, 100, 0, 2, 0x00, 0xae, 0x22, 0xe5, 0x20, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5b[] = { + /* Choir Pad */ + { 0x15, 0x3a, { 0x018, 5010, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x3b, 0x40, { 0x019, 4370, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x41, 0x47, { 0x01a, 3478, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x48, 0x6c, { 0x01b, 2197, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3482, 100, 0, 4, 0x00, 0x98, 0x24, 0x65, 0x21, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5c[] = { + /* Bowed Pad */ + { 0x15, 0x6c, { 0x101, 4790, 100, -1, 1, 0x00, 0xbe, 0x19, 0x44, 0x14, 0x16, 0x0 }}, + { 0x00, 0x7f, { 0x0aa, 1720, 100, 1, 1, 0x00, 0x94, 0x19, 0x40, 0x00, 0x06, 0x0 } } +}; +static const YRW801_REGION_DATA regions_5d[] = { + /* Metallic Pad */ + { 0x15, 0x31, { 0x00c, 6943, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x32, 0x38, { 0x00d, 5416, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x39, 0x47, { 0x00e, 4385, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x48, 0x6c, { 0x00f, 2849, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x00, 0x7f, { 0x03f, 4224, 100, 0, 1, 0x00, 0x9c, 0x31, 0x65, 0x16, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5e[] = { + /* Halo Pad */ + { 0x00, 0x7f, { 0x124, 4038, 100, 0, 2, 0x00, 0xa6, 0x1a, 0x85, 0x23, 0x08, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3471, 100, 0, 3, 0x00, 0xc0, 0x1b, 0xc0, 0x05, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5f[] = { + /* Sweep Pad */ + { 0x01, 0x27, { 0x0d3, 9100, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x28, 0x2d, { 0x0da, 8341, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x2e, 0x33, { 0x0d4, 7564, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x34, 0x39, { 0x0db, 6791, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x3a, 0x3f, { 0x0d5, 6048, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x40, 0x45, { 0x0dc, 5263, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x46, 0x4b, { 0x0d6, 4499, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x4c, 0x51, { 0x0dd, 3747, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x52, 0x57, { 0x0d7, 3018, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x58, 0x5d, { 0x0de, 2173, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x5e, 0x63, { 0x0d8, 1427, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x64, 0x7f, { 0x0d9, -109, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x01, 0x27, { 0x0d3, 9088, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x28, 0x2d, { 0x0da, 8329, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x2e, 0x33, { 0x0d4, 7552, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x34, 0x39, { 0x0db, 6779, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x3a, 0x3f, { 0x0d5, 6036, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x40, 0x45, { 0x0dc, 5251, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x46, 0x4b, { 0x0d6, 4487, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x4c, 0x51, { 0x0dd, 3735, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x52, 0x57, { 0x0d7, 3006, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x58, 0x5d, { 0x0de, 2161, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x5e, 0x63, { 0x0d8, 1415, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x64, 0x7f, { 0x0d9, -121, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_60[] = { + /* Ice Rain */ + { 0x01, 0x7f, { 0x04e, 9345, 100, 0, 2, 0x00, 0xcc, 0x22, 0xa3, 0x63, 0x17, 0x0 }}, + { 0x00, 0x7f, { 0x143, 5586, 20, 0, 2, 0x00, 0x6e, 0x2a, 0xf0, 0x05, 0x05, 0x0 } } +}; +static const YRW801_REGION_DATA regions_61[] = { + /* Soundtrack */ + { 0x15, 0x6c, { 0x002, 4501, 100, 0, 2, 0x00, 0xb6, 0x2a, 0x60, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x0f3, 1160, 100, 0, 5, 0x00, 0xa8, 0x2d, 0x52, 0x14, 0x06, 0x2 }} +}; +static const YRW801_REGION_DATA regions_62[] = { + /* Crystal */ + { 0x15, 0x6c, { 0x0f3, 1826, 100, 0, 3, 0x00, 0xb8, 0x33, 0xf6, 0x25, 0x25, 0x0 }}, + { 0x15, 0x2c, { 0x06d, 7454, 100, 0, 3, 0x00, 0xac, 0x3b, 0x85, 0x24, 0x06, 0x0 }}, + { 0x2d, 0x36, { 0x06e, 5925, 100, 0, 3, 0x00, 0xac, 0x3b, 0x85, 0x24, 0x06, 0x0 }}, + { 0x37, 0x6c, { 0x06f, 4403, 100, 0, 3, 0x09, 0xac, 0x3b, 0x85, 0x24, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_63[] = { + /* Atmosphere */ + { 0x05, 0x71, { 0x002, 4509, 100, 0, 2, 0x00, 0xc8, 0x32, 0x73, 0x22, 0x06, 0x1 }}, + { 0x15, 0x2f, { 0x0b3, 6964, 100, 0, 2, 0x05, 0xc2, 0x32, 0xf5, 0x34, 0x07, 0x2 }}, + { 0x30, 0x36, { 0x0b7, 5567, 100, 0, 2, 0x0c, 0xc2, 0x32, 0xf5, 0x34, 0x07, 0x2 }}, + { 0x37, 0x3c, { 0x0b5, 4653, 100, 0, 2, 0x00, 0xc2, 0x32, 0xf6, 0x34, 0x07, 0x2 }}, + { 0x3d, 0x43, { 0x0b4, 3892, 100, 0, 2, 0x00, 0xc2, 0x32, 0xf6, 0x35, 0x07, 0x2 }}, + { 0x44, 0x60, { 0x0b6, 2723, 100, 0, 2, 0x00, 0xc2, 0x32, 0xf6, 0x35, 0x17, 0x2 }} +}; +static const YRW801_REGION_DATA regions_64[] = { + /* Brightness */ + { 0x00, 0x7f, { 0x137, 5285, 100, 0, 2, 0x00, 0xbe, 0x2a, 0xa5, 0x18, 0x08, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3481, 100, 0, 1, 0x00, 0xc8, 0x29, 0x80, 0x05, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_65[] = { + /* Goblins */ + { 0x15, 0x6c, { 0x002, 4501, 100, -1, 2, 0x00, 0xca, 0x2a, 0x40, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x009, 9679, 20, 1, 4, 0x00, 0x3c, 0x0c, 0x22, 0x11, 0x06, 0x0 } } +}; +static const YRW801_REGION_DATA regions_66[] = { + /* Echoes */ + { 0x15, 0x6c, { 0x02a, 3487, 100, 0, 3, 0x00, 0xae, 0x2b, 0xf5, 0x21, 0x06, 0x0 }}, + { 0x00, 0x7f, { 0x124, 4027, 100, 0, 3, 0x00, 0xae, 0x2b, 0x85, 0x23, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_67[] = { + /* Sci-Fi */ + { 0x15, 0x31, { 0x00c, 6940, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x32, 0x38, { 0x00d, 5413, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x39, 0x47, { 0x00e, 4382, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x48, 0x6c, { 0x00f, 2846, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x15, 0x6c, { 0x002, 4498, 100, 0, 2, 0x00, 0xd4, 0x22, 0x80, 0x01, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_68[] = { + /* Sitar */ + { 0x00, 0x7f, { 0x10f, 4408, 100, 0, 2, 0x00, 0xc4, 0x32, 0xf4, 0x15, 0x16, 0x1 }} +}; +static const YRW801_REGION_DATA regions_69[] = { + /* Banjo */ + { 0x15, 0x34, { 0x013, 5685, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x35, 0x38, { 0x014, 5009, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x39, 0x3c, { 0x012, 4520, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x3d, 0x44, { 0x015, 3622, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x45, 0x4c, { 0x017, 2661, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x4d, 0x6d, { 0x016, 1632, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6a[] = { + /* Shamisen */ + { 0x15, 0x6c, { 0x10e, 3273, 100, 0, 0, 0x00, 0xc0, 0x28, 0xf7, 0x76, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6b[] = { + /* Koto */ + { 0x00, 0x7f, { 0x0a9, 4033, 100, 0, 0, 0x00, 0xc6, 0x20, 0xf0, 0x06, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6c[] = { + /* Kalimba */ + { 0x00, 0x7f, { 0x137, 3749, 100, 0, 0, 0x00, 0xce, 0x38, 0xf5, 0x18, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6d[] = { + /* Bagpipe */ + { 0x15, 0x39, { 0x0a4, 7683, 100, 0, 4, 0x00, 0xc0, 0x1c, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x15, 0x39, { 0x0a7, 7680, 100, 0, 1, 0x00, 0xaa, 0x19, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3a, 0x6c, { 0x0a8, 3697, 100, 0, 1, 0x00, 0xaa, 0x19, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6e[] = { + /* Fiddle */ + { 0x15, 0x3a, { 0x105, 5158, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x3b, 0x3f, { 0x102, 4754, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x40, 0x41, { 0x106, 4132, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x42, 0x44, { 0x107, 4033, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x45, 0x47, { 0x108, 3580, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x48, 0x4a, { 0x10a, 2957, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4b, 0x4c, { 0x10b, 2724, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4d, 0x4e, { 0x10c, 2530, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4f, 0x51, { 0x10d, 2166, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x52, 0x6c, { 0x109, 1825, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6f[] = { + /* Shanai */ + { 0x15, 0x6c, { 0x041, 6946, 100, 0, 1, 0x00, 0xc4, 0x31, 0x95, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_70[] = { + /* Tinkle Bell */ + { 0x15, 0x73, { 0x0f3, 1821, 100, 0, 3, 0x00, 0xc8, 0x3b, 0xd6, 0x25, 0x25, 0x0 }}, + { 0x00, 0x7f, { 0x137, 5669, 100, 0, 3, 0x00, 0x66, 0x3b, 0xf5, 0x18, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_71[] = { + /* Agogo */ + { 0x15, 0x74, { 0x00b, 2474, 100, 0, 0, 0x00, 0xd2, 0x38, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_72[] = { + /* Steel Drums */ + { 0x01, 0x7f, { 0x0fe, 3670, 100, 0, 0, 0x00, 0xca, 0x38, 0xf3, 0x06, 0x17, 0x1 }}, + { 0x15, 0x6c, { 0x100, 9602, 100, 0, 0, 0x00, 0x54, 0x38, 0xb0, 0x05, 0x16, 0x1 }} +}; +static const YRW801_REGION_DATA regions_73[] = { + /* Woodblock */ + { 0x15, 0x6c, { 0x02c, 2963, 50, 0, 0, 0x07, 0xd4, 0x00, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_74[] = { + /* Taiko Drum */ + { 0x13, 0x6c, { 0x03e, 1194, 50, 0, 0, 0x00, 0xaa, 0x38, 0xf0, 0x04, 0x04, 0x0 }} +}; +static const YRW801_REGION_DATA regions_75[] = { + /* Melodic Tom */ + { 0x15, 0x6c, { 0x0c7, 6418, 50, 0, 0, 0x00, 0xe4, 0x38, 0xf0, 0x05, 0x01, 0x0 }} +}; +static const YRW801_REGION_DATA regions_76[] = { + /* Synth Drum */ + { 0x15, 0x6c, { 0x026, 3898, 50, 0, 0, 0x00, 0xd0, 0x38, 0xf0, 0x04, 0x04, 0x0 }} +}; +static const YRW801_REGION_DATA regions_77[] = { + /* Reverse Cymbal */ + { 0x15, 0x6c, { 0x031, 4138, 50, 0, 0, 0x00, 0xfe, 0x38, 0x3a, 0xf0, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_78[] = { + /* Guitar Fret Noise */ + { 0x15, 0x6c, { 0x138, 5266, 100, 0, 0, 0x00, 0xa0, 0x38, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_79[] = { + /* Breath Noise */ + { 0x01, 0x7f, { 0x125, 4269, 100, 0, 0, 0x1e, 0xd0, 0x38, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_7a[] = { + /* Seashore */ + { 0x15, 0x6c, { 0x008, 2965, 20, -2, 0, 0x00, 0xfe, 0x00, 0x20, 0x03, 0x04, 0x0 }}, + { 0x01, 0x7f, { 0x037, 4394, 20, 2, 0, 0x14, 0xfe, 0x00, 0x20, 0x04, 0x05, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7b[] = { + /* Bird Tweet */ + { 0x15, 0x6c, { 0x009, 8078, 5, -4, 7, 0x00, 0xc2, 0x0f, 0x22, 0x12, 0x07, 0x0 }}, + { 0x15, 0x6c, { 0x009, 3583, 5, 4, 5, 0x00, 0xae, 0x15, 0x72, 0x12, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7c[] = { + /* Telephone Ring */ + { 0x15, 0x6c, { 0x003, 3602, 10, 0, 0, 0x00, 0xce, 0x00, 0xf0, 0x00, 0x0f, 0x0 }} +}; +static const YRW801_REGION_DATA regions_7d[] = { + /* Helicopter */ + { 0x0c, 0x7f, { 0x001, 2965, 10, -2, 0, 0x00, 0xe0, 0x08, 0x30, 0x01, 0x07, 0x0 }}, + { 0x01, 0x7f, { 0x037, 4394, 10, 2, 0, 0x44, 0x76, 0x00, 0x30, 0x01, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7e[] = { + /* Applause */ + { 0x15, 0x6c, { 0x036, 8273, 20, -6, 7, 0x00, 0xc4, 0x0f, 0x70, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x036, 8115, 5, 6, 7, 0x00, 0xc6, 0x07, 0x70, 0x01, 0x05, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7f[] = { + /* Gun Shot */ + { 0x15, 0x6c, { 0x139, 2858, 20, 0, 0, 0x00, 0xbe, 0x38, 0xf0, 0x03, 0x00, 0x0 }} +}; +static const YRW801_REGION_DATA regions_drums[] = { + { 0x18, 0x18, { 0x0cb, 6397, 100, 3, 0, 0x00, 0xf4, 0x38, 0xc9, 0x1c, 0x0c, 0x0 } }, + { 0x19, 0x19, { 0x0c4, 3714, 100, 0, 0, 0x00, 0xe0, 0x00, 0x97, 0x19, 0x09, 0x0 } }, + { 0x1a, 0x1a, { 0x0c4, 3519, 100, 0, 0, 0x00, 0xea, 0x00, 0x61, 0x01, 0x07, 0x0 } }, + { 0x1b, 0x1b, { 0x0c4, 3586, 100, 0, 0, 0x00, 0xea, 0x00, 0xf7, 0x19, 0x09, 0x0 } }, + { 0x1c, 0x1c, { 0x0c4, 3586, 100, 0, 0, 0x00, 0xea, 0x00, 0x81, 0x01, 0x07, 0x0 } }, + { 0x1e, 0x1e, { 0x0c3, 4783, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x1f, 0x1f, { 0x0d1, 4042, 100, 0, 0, 0x00, 0xd6, 0x00, 0xf0, 0x05, 0x05, 0x0 } }, + { 0x20, 0x20, { 0x0d2, 5943, 100, 0, 0, 0x00, 0xcc, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x21, 0x21, { 0x011, 3842, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x16, 0x06, 0x0 } }, + { 0x23, 0x23, { 0x011, 4098, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x16, 0x06, 0x0 } }, + { 0x24, 0x24, { 0x011, 4370, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x06, 0x0 } }, + { 0x25, 0x25, { 0x0d2, 4404, 100, 0, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x06, 0x0 } }, + { 0x26, 0x26, { 0x0d1, 4298, 100, 0, 0, 0x00, 0xd6, 0x00, 0xf0, 0x05, 0x05, 0x0 } }, + { 0x27, 0x27, { 0x00a, 4403, 100, -1, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x28, 0x28, { 0x0d1, 4554, 100, 0, 0, 0x00, 0xdc, 0x00, 0xf0, 0x07, 0x07, 0x0 } }, + { 0x29, 0x29, { 0x0c8, 4242, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf6, 0x16, 0x06, 0x0 }}, + { 0x2a, 0x2a, { 0x079, 6160, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf5, 0x19, 0x09, 0x0 } }, + { 0x2b, 0x2b, { 0x0c8, 4626, 100, -3, 0, 0x00, 0xd6, 0x00, 0xf6, 0x16, 0x06, 0x0 }}, + { 0x2c, 0x2c, { 0x07b, 6039, 100, 2, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x2d, 0x2d, { 0x0c8, 5394, 100, -2, 0, 0x00, 0xd6, 0x00, 0xf6, 0x16, 0x06, 0x0 }}, + { 0x2e, 0x2e, { 0x07a, 5690, 100, 2, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x05, 0x0 } }, + { 0x2f, 0x2f, { 0x0c7, 5185, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf6, 0x17, 0x07, 0x0 } }, + { 0x30, 0x30, { 0x0c7, 5650, 100, 3, 0, 0x00, 0xe0, 0x00, 0xf6, 0x17, 0x07, 0x0 } }, + { 0x31, 0x31, { 0x031, 4395, 100, 2, 0, 0x00, 0xea, 0x00, 0xf0, 0x05, 0x05, 0x0 } }, + { 0x32, 0x32, { 0x0c7, 6162, 100, 4, 0, 0x00, 0xe0, 0x00, 0xf6, 0x17, 0x07, 0x0 } }, + { 0x33, 0x33, { 0x02e, 4391, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x05, 0x05, 0x0 }}, + { 0x34, 0x34, { 0x07a, 3009, 100, -2, 0, 0x00, 0xea, 0x00, 0xf2, 0x15, 0x05, 0x0 }}, + { 0x35, 0x35, { 0x021, 4522, 100, -3, 0, 0x00, 0xd6, 0x00, 0xf0, 0x05, 0x05, 0x0 }}, + { 0x36, 0x36, { 0x025, 5163, 100, 1, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x37, 0x37, { 0x031, 5287, 100, -1, 0, 0x00, 0xea, 0x00, 0xf5, 0x16, 0x06, 0x0 }}, + { 0x38, 0x38, { 0x01d, 4395, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x39, 0x39, { 0x031, 4647, 100, -2, 0, 0x00, 0xea, 0x00, 0xf4, 0x16, 0x06, 0x0 }}, + { 0x3a, 0x3a, { 0x09d, 4426, 100, -4, 0, 0x00, 0xe0, 0x00, 0xf4, 0x17, 0x07, 0x0 }}, + { 0x3b, 0x3b, { 0x02e, 4659, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x06, 0x06, 0x0 }}, + { 0x3c, 0x3c, { 0x01c, 4769, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x3d, 0x3d, { 0x01c, 4611, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x3e, 0x3e, { 0x01e, 4402, 100, -3, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3f, 0x3f, { 0x01f, 4387, 100, -3, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x40, 0x40, { 0x01f, 3983, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x41, 0x41, { 0x09c, 4526, 100, 2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x42, 0x42, { 0x09c, 4016, 100, 2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x43, 0x43, { 0x00b, 4739, 100, -4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x44, 0x44, { 0x00b, 4179, 100, -4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x45, 0x45, { 0x02f, 4787, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x46, 0x46, { 0x030, 4665, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x47, 0x47, { 0x144, 4519, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x0b, 0x0 } }, + { 0x48, 0x48, { 0x144, 4111, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x0b, 0x0 } }, + { 0x49, 0x49, { 0x024, 6408, 100, 3, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4a, 0x4a, { 0x024, 4144, 100, 3, 0, 0x00, 0xcc, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4b, 0x4b, { 0x020, 4001, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4c, 0x4c, { 0x02c, 4402, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4d, 0x4d, { 0x02c, 3612, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4e, 0x4e, { 0x022, 4129, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x4f, 0x4f, { 0x023, 4147, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x50, 0x50, { 0x032, 4412, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x08, 0x09, 0x0 }}, + { 0x51, 0x51, { 0x032, 4385, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x52, 0x52, { 0x02f, 5935, 100, -1, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }} +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#define REGION(num) \ + { \ + ARRAY_SIZE(regions##num), regions##num \ + } +const YRW801_REGION_DATA_PTR snd_yrw801_regions[0x81] = { + REGION(_00), REGION(_01), REGION(_02), REGION(_03), + REGION(_04), REGION(_05), REGION(_06), REGION(_07), + REGION(_08), REGION(_09), REGION(_0a), REGION(_0b), + REGION(_0c), REGION(_0d), REGION(_0e), REGION(_0f), + REGION(_10), REGION(_11), REGION(_12), REGION(_13), + REGION(_14), REGION(_15), REGION(_16), REGION(_17), + REGION(_18), REGION(_19), REGION(_1a), REGION(_1b), + REGION(_1c), REGION(_1d), REGION(_1e), REGION(_1f), + REGION(_20), REGION(_21), REGION(_22), REGION(_23), + REGION(_24), REGION(_25), REGION(_26), REGION(_27), + REGION(_28), REGION(_29), REGION(_2a), REGION(_2b), + REGION(_2c), REGION(_2d), REGION(_2e), REGION(_2f), + REGION(_30), REGION(_31), REGION(_32), REGION(_33), + REGION(_34), REGION(_35), REGION(_36), REGION(_37), + REGION(_38), REGION(_39), REGION(_3a), REGION(_3b), + REGION(_3c), REGION(_3d), REGION(_3e), REGION(_3f), + REGION(_40), REGION(_41), REGION(_42), REGION(_43), + REGION(_44), REGION(_45), REGION(_46), REGION(_47), + REGION(_48), REGION(_49), REGION(_4a), REGION(_4b), + REGION(_4c), REGION(_4d), REGION(_4e), REGION(_4f), + REGION(_50), REGION(_51), REGION(_52), REGION(_53), + REGION(_54), REGION(_55), REGION(_56), REGION(_57), + REGION(_58), REGION(_59), REGION(_5a), REGION(_5b), + REGION(_5c), REGION(_5d), REGION(_5e), REGION(_5f), + REGION(_60), REGION(_61), REGION(_62), REGION(_63), + REGION(_64), REGION(_65), REGION(_66), REGION(_67), + REGION(_68), REGION(_69), REGION(_6a), REGION(_6b), + REGION(_6c), REGION(_6d), REGION(_6e), REGION(_6f), + REGION(_70), REGION(_71), REGION(_72), REGION(_73), + REGION(_74), REGION(_75), REGION(_76), REGION(_77), + REGION(_78), REGION(_79), REGION(_7a), REGION(_7b), + REGION(_7c), REGION(_7d), REGION(_7e), REGION(_7f), + REGION(_drums) +}; \ No newline at end of file diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 3c0d22131..ee761e627 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -1622,4 +1622,5 @@ const fm_drv_t nuked_opl_drv = { &nuked_drv_reset_buffer, &nuked_drv_set_do_cycles, NULL, + NULL, }; \ No newline at end of file diff --git a/src/sound/snd_opl_ymfm.cpp b/src/sound/snd_opl_ymfm.cpp index bb52f3c55..b2466dcb5 100644 --- a/src/sound/snd_opl_ymfm.cpp +++ b/src/sound/snd_opl_ymfm.cpp @@ -368,6 +368,13 @@ ymfm_drv_set_do_cycles(void *priv, int8_t do_cycles) drv->set_do_cycles(do_cycles); } +static void +ymfm_drv_generate(void *priv, int32_t *data, uint32_t num_samples) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + drv->generate_resampled(data, num_samples); +} + const device_t ym3812_ymfm_device = { .name = "Yamaha YM3812 OPL2 (YMFM)", .internal_name = "ym3812_ymfm", @@ -431,5 +438,6 @@ const fm_drv_t ymfm_drv { &ymfm_drv_reset_buffer, &ymfm_drv_set_do_cycles, NULL, + ymfm_drv_generate, }; } diff --git a/src/sound/yrw801.h b/src/sound/yrw801.h new file mode 100644 index 000000000..0df3c0343 --- /dev/null +++ b/src/sound/yrw801.h @@ -0,0 +1,45 @@ +/* + * RoboPlay for MSX + * Copyright (C) 2022 by RoboSoft Inc. + * + * yrw801.h + */ + +/* Cacodemon345: Added pointer structs from Linux */ + +#pragma once + +#include + +typedef struct +{ + uint16_t tone; + int16_t pitch_offset; + uint8_t key_scaling; + int8_t panpot; + uint8_t vibrato; + uint8_t tone_attenuate; + uint8_t volume_factor; + uint8_t reg_lfo_vibrato; + uint8_t reg_attack_decay1; + uint8_t reg_level_decay2; + uint8_t reg_release_correction; + uint8_t reg_tremolo; +} YRW801_WAVE_DATA; + +typedef struct +{ + uint8_t key_min; + uint8_t key_max; + + YRW801_WAVE_DATA wave_data; +} YRW801_REGION_DATA; + +typedef struct +{ + int count; + + const YRW801_REGION_DATA* regions; +} YRW801_REGION_DATA_PTR; + +extern const YRW801_REGION_DATA_PTR snd_yrw801_regions[0x81]; \ No newline at end of file From 9df45dba0f8aaef9b3e52148f86bb59ed34ae8b4 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 27 Nov 2022 21:24:17 +0600 Subject: [PATCH 008/133] Fix OPL4 audio crackling --- src/sound/midi_opl4.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index f816cff49..b75ac23b5 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -269,12 +269,15 @@ static const uint8_t g_volume_table[128] = { 2, 2, 2, 1, 1, 0, 0, 0 }; +#define BUFFER_SEGMENTS 10 +#define RENDER_RATE (48000 / 100) + typedef struct opl4_midi { fm_drv_t opl4; MIDI_CHANNEL_DATA midi_channel_data[16]; VOICE_DATA voice_data[24]; - int16_t buffer[SOUNDBUFLEN * 2]; - float buffer_float[SOUNDBUFLEN * 2]; + int16_t buffer[(48000 / 100) * 2 * BUFFER_SEGMENTS]; + float buffer_float[(48000 / 100) * 2 * BUFFER_SEGMENTS]; uint32_t midi_pos; bool on; atomic_bool gen_in_progress; @@ -537,13 +540,14 @@ program_change(uint8_t midi_channel, uint8_t program, opl4_midi_t *opl4_midi) opl4_midi->midi_channel_data[midi_channel].instrument = program; } -#define RENDER_RATE (48000 / 100) static void opl4_midi_thread(void *arg) { opl4_midi_t *opl4_midi = opl4_midi_cur; uint32_t i = 0; uint32_t buf_size = RENDER_RATE * 2; + uint32_t buf_size_segments = buf_size * BUFFER_SEGMENTS; + uint32_t buf_pos = 0; int32_t buffer[RENDER_RATE * 2]; @@ -558,16 +562,24 @@ opl4_midi_thread(void *arg) atomic_store(&opl4_midi->gen_in_progress, false); if (sound_is_float) { for (i = 0; i < (buf_size / 2); i++) { - opl4_midi->buffer_float[i * 2] = buffer[i * 2] / 32768.0; - opl4_midi->buffer_float[(i * 2) + 1] = buffer[(i * 2) + 1] / 32768.0; + opl4_midi->buffer_float[(i + buf_pos) * 2] = buffer[i * 2] / 32768.0; + opl4_midi->buffer_float[((i + buf_pos) * 2) + 1] = buffer[(i * 2) + 1] / 32768.0; + } + buf_pos += buf_size / 2; + if (buf_pos >= (buf_size_segments / 2)) { + givealbuffer_midi(opl4_midi->buffer_float, buf_size_segments); + buf_pos = 0; } - givealbuffer_midi(opl4_midi->buffer_float, buf_size); } else { for (i = 0; i < (buf_size / 2); i++) { - opl4_midi->buffer[i * 2] = buffer[i * 2] & 0xFFFF; /* Outputs are clamped beforehand. */ - opl4_midi->buffer[(i * 2) + 1] = buffer[(i * 2) + 1] & 0xFFFF; /* Outputs are clamped beforehand. */ + opl4_midi->buffer[(i + buf_pos) * 2] = buffer[i * 2] & 0xFFFF; /* Outputs are clamped beforehand. */ + opl4_midi->buffer[((i + buf_pos) * 2) + 1] = buffer[(i * 2) + 1] & 0xFFFF; /* Outputs are clamped beforehand. */ + } + buf_pos += buf_size / 2; + if (buf_pos >= (buf_size_segments / 2)) { + givealbuffer_midi(opl4_midi->buffer, buf_size_segments); + buf_pos = 0; } - givealbuffer_midi(opl4_midi->buffer, buf_size); } } } From ca6ebbec72e4790185e34172c9a81f3963a36138 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 27 Nov 2022 21:35:08 +0600 Subject: [PATCH 009/133] OPL4 activation timestamp now comes from platform timestamp --- src/sound/midi_opl4.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index b75ac23b5..5a4480835 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -270,7 +270,7 @@ static const uint8_t g_volume_table[128] = { }; #define BUFFER_SEGMENTS 10 -#define RENDER_RATE (48000 / 100) +#define RENDER_RATE (48000 / 100) typedef struct opl4_midi { fm_drv_t opl4; @@ -419,8 +419,7 @@ note_on(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_mi const YRW801_WAVE_DATA *wave_data[2]; VOICE_DATA *voice[2]; uint8_t i = 0, voices = 0; - uint32_t j = 0; - static uint64_t activation_num = 0; + uint32_t j = 0; while (opl4_midi->gen_in_progress) { } @@ -444,7 +443,7 @@ note_on(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_mi for (i = 0; i < voices; i++) { voice[i] = get_voice(wave_data[i], opl4_midi); voice[i]->is_active = true; - voice[i]->activated = activation_num++; + voice[i]->activated = plat_get_ticks(); voice[i]->midi_channel = midi_channel; voice[i]->note = note; @@ -543,11 +542,11 @@ program_change(uint8_t midi_channel, uint8_t program, opl4_midi_t *opl4_midi) static void opl4_midi_thread(void *arg) { - opl4_midi_t *opl4_midi = opl4_midi_cur; - uint32_t i = 0; - uint32_t buf_size = RENDER_RATE * 2; + opl4_midi_t *opl4_midi = opl4_midi_cur; + uint32_t i = 0; + uint32_t buf_size = RENDER_RATE * 2; uint32_t buf_size_segments = buf_size * BUFFER_SEGMENTS; - uint32_t buf_pos = 0; + uint32_t buf_pos = 0; int32_t buffer[RENDER_RATE * 2]; From facdbfaef6aabfe0d6bfc154ca3079e351b3df5e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 27 Nov 2022 16:11:46 +0600 Subject: [PATCH 010/133] Add OPL4-ML daughterboard emulation --- src/include/86box/midi.h | 1 + src/include/86box/opl4_defines.h | 101 +++ src/include/86box/snd_opl.h | 1 + src/sound/CMakeLists.txt | 2 +- src/sound/midi.c | 1 + src/sound/midi_opl4.c | 703 ++++++++++++++++++++ src/sound/midi_opl4_yrw801.c | 1042 ++++++++++++++++++++++++++++++ src/sound/snd_opl_nuked.c | 1 + src/sound/snd_opl_ymfm.cpp | 8 + src/sound/yrw801.h | 45 ++ 10 files changed, 1904 insertions(+), 1 deletion(-) create mode 100644 src/include/86box/opl4_defines.h create mode 100644 src/sound/midi_opl4.c create mode 100644 src/sound/midi_opl4_yrw801.c create mode 100644 src/sound/yrw801.h diff --git a/src/include/86box/midi.h b/src/include/86box/midi.h index e2b8c2626..9f3a81581 100644 --- a/src/include/86box/midi.h +++ b/src/include/86box/midi.h @@ -92,6 +92,7 @@ extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #ifdef EMU_DEVICE_H extern const device_t rtmidi_output_device; extern const device_t rtmidi_input_device; +extern const device_t opl4_midi_device; # ifdef USE_FLUIDSYNTH extern const device_t fluidsynth_device; # endif diff --git a/src/include/86box/opl4_defines.h b/src/include/86box/opl4_defines.h new file mode 100644 index 000000000..248b1f729 --- /dev/null +++ b/src/include/86box/opl4_defines.h @@ -0,0 +1,101 @@ +/* + * RoboPlay for MSX + * Copyright (C) 2020 by RoboSoft Inc. + * + * opl4_defines.h + * + */ + +#ifndef __OPL4_DEFINES_H +#define __OPL4_DEFINES_H + +/* + * Register numbers + */ + +#define OPL4_REG_TEST0 0x00 +#define OPL4_REG_TEST1 0x01 + +#define OPL4_REG_MEMORY_CONFIGURATION 0x02 +#define OPL4_MODE_BIT 0x01 +#define OPL4_MTYPE_BIT 0x02 +#define OPL4_TONE_HEADER_MASK 0x1C +#define OPL4_DEVICE_ID_MASK 0xE0 + +#define OPL4_REG_MEMORY_ADDRESS_HIGH 0x03 +#define OPL4_REG_MEMORY_ADDRESS_MID 0x04 +#define OPL4_REG_MEMORY_ADDRESS_LOW 0x05 +#define OPL4_REG_MEMORY_DATA 0x06 + +/* + * Offsets to the register banks for voices. To get the + * register number just add the voice number to the bank offset. + * + * Wave Table Number low bits (0x08 to 0x1F) + */ +#define OPL4_REG_TONE_NUMBER 0x08 + +/* Wave Table Number high bit, F-Number low bits (0x20 to 0x37) */ +#define OPL4_REG_F_NUMBER 0x20 +#define OPL4_TONE_NUMBER_BIT8 0x01 +#define OPL4_F_NUMBER_LOW_MASK 0xFE + +/* F-Number high bits, Octave, Pseudo-Reverb (0x38 to 0x4F) */ +#define OPL4_REG_OCTAVE 0x38 +#define OPL4_F_NUMBER_HIGH_MASK 0x07 +#define OPL4_BLOCK_MASK 0xF0 +#define OPL4_PSEUDO_REVERB_BIT 0x08 + +/* Total Level, Level Direct (0x50 to 0x67) */ +#define OPL4_REG_LEVEL 0x50 +#define OPL4_TOTAL_LEVEL_MASK 0xFE +#define OPL4_LEVEL_DIRECT_BIT 0x01 + +/* Key On, Damp, LFO RST, CH, Panpot (0x68 to 0x7F) */ +#define OPL4_REG_MISC 0x68 +#define OPL4_KEY_ON_BIT 0x80 +#define OPL4_DAMP_BIT 0x40 +#define OPL4_LFO_RESET_BIT 0x20 +#define OPL4_OUTPUT_CHANNEL_BIT 0x10 +#define OPL4_PAN_POT_MASK 0x0F + +/* LFO, VIB (0x80 to 0x97) */ +#define OPL4_REG_LFO_VIBRATO 0x80 +#define OPL4_LFO_FREQUENCY_MASK 0x38 +#define OPL4_VIBRATO_DEPTH_MASK 0x07 +#define OPL4_CHORUS_SEND_MASK 0xC0 + +/* Attack / Decay 1 rate (0x98 to 0xAF) */ +#define OPL4_REG_ATTACK_DECAY1 0x98 +#define OPL4_ATTACK_RATE_MASK 0xF0 +#define OPL4_DECAY1_RATE_MASK 0x0F + +/* Decay level / 2 rate (0xB0 to 0xC7) */ +#define OPL4_REG_LEVEL_DECAY2 0xB0 +#define OPL4_DECAY_LEVEL_MASK 0xF0 +#define OPL4_DECAY2_RATE_MASK 0x0F + +/* Release rate / Rate correction (0xC8 to 0xDF) */ +#define OPL4_REG_RELEASE_CORRECTION 0xC8 +#define OPL4_RELEASE_RATE_MASK 0x0F +#define OPL4_RATE_INTERPOLATION_MASK 0xF0 + +/* AM (0xE0 to 0xF7) */ +#define OPL4_REG_TREMOLO 0xE0 +#define OPL4_TREMOLO_DEPTH_MASK 0x07 +#define OPL4_REVERB_SEND_MASK 0xE0 + +/* Mixer */ +#define OPL4_REG_MIX_CONTROL_FM 0xF8 +#define OPL4_REG_MIX_CONTROL_PCM 0xF9 +#define OPL4_MIX_LEFT_MASK 0x07 +#define OPL4_MIX_RIGHT_MASK 0x38 + +#define OPL4_REG_ATC 0xFA +#define OPL4_ATC_BIT 0x01 + +/* Bits in the OPL4 Status register */ +#define OPL4_STATUS_BUSY 0x01 +#define OPL4_STATUS_LOAD 0x02 + +#endif /* __OPL4_DEFINES_H */ diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index 5caccf8fc..3b84a837b 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -38,6 +38,7 @@ typedef struct { void (*reset_buffer)(void *priv); void (*set_do_cycles)(void *priv, int8_t do_cycles); void *priv; + void (*generate)(void *priv, int32_t *data, uint32_t num_samples); /* daughterboard only. */ } fm_drv_t; extern uint8_t fm_driver_get(int chip_id, fm_drv_t *drv); diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 66672d547..7024bc5fc 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_re snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c - snd_optimc.c) + snd_optimc.c midi_opl4.c midi_opl4_yrw801.c) if(OPENAL) if(VCPKG_TOOLCHAIN) diff --git a/src/sound/midi.c b/src/sound/midi.c index 93fa62891..c58342648 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -100,6 +100,7 @@ static const MIDI_OUT_DEVICE devices[] = { #ifdef USE_RTMIDI { &rtmidi_output_device }, #endif + { &opl4_midi_device }, { NULL } // clang-format on }; diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c new file mode 100644 index 000000000..f816cff49 --- /dev/null +++ b/src/sound/midi_opl4.c @@ -0,0 +1,703 @@ +// Based off ROBOPLAY's OPL4 MID player code, with some fixes and modifications to make it work well. + +#include +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/midi.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/rom.h> +#include <86box/sound.h> +#include <86box/ui.h> +#include <86box/snd_opl.h> +#include <86box/opl4_defines.h> + +#include "yrw801.h" + +#define NR_OF_MIDI_CHANNELS 16 +#define NR_OF_WAVE_CHANNELS 24 + +#define DRUM_CHANNEL 9 + +typedef struct +{ + uint8_t instrument; + uint8_t panpot; + uint8_t vibrato; + bool drum_channel; +} MIDI_CHANNEL_DATA; + +typedef struct +{ + bool is_active; + uint64_t activated; + + uint8_t number; + MIDI_CHANNEL_DATA *midi_channel; + uint8_t note; + uint8_t velocity; + const YRW801_WAVE_DATA *wave_data; + uint8_t level_direct; + uint8_t reg_f_number; + uint8_t reg_misc; + uint8_t reg_lfo_vibrato; +} VOICE_DATA; + +static const int16_t g_wave_pitch_map[0x600] = { + 0x000, 0x000, 0x001, 0x001, 0x002, 0x002, 0x003, 0x003, + 0x004, 0x004, 0x005, 0x005, 0x006, 0x006, 0x006, 0x007, + 0x007, 0x008, 0x008, 0x009, 0x009, 0x00a, 0x00a, 0x00b, + 0x00b, 0x00c, 0x00c, 0x00d, 0x00d, 0x00d, 0x00e, 0x00e, + 0x00f, 0x00f, 0x010, 0x010, 0x011, 0x011, 0x012, 0x012, + 0x013, 0x013, 0x014, 0x014, 0x015, 0x015, 0x015, 0x016, + 0x016, 0x017, 0x017, 0x018, 0x018, 0x019, 0x019, 0x01a, + 0x01a, 0x01b, 0x01b, 0x01c, 0x01c, 0x01d, 0x01d, 0x01e, + 0x01e, 0x01e, 0x01f, 0x01f, 0x020, 0x020, 0x021, 0x021, + 0x022, 0x022, 0x023, 0x023, 0x024, 0x024, 0x025, 0x025, + 0x026, 0x026, 0x027, 0x027, 0x028, 0x028, 0x029, 0x029, + 0x029, 0x02a, 0x02a, 0x02b, 0x02b, 0x02c, 0x02c, 0x02d, + 0x02d, 0x02e, 0x02e, 0x02f, 0x02f, 0x030, 0x030, 0x031, + 0x031, 0x032, 0x032, 0x033, 0x033, 0x034, 0x034, 0x035, + 0x035, 0x036, 0x036, 0x037, 0x037, 0x038, 0x038, 0x038, + 0x039, 0x039, 0x03a, 0x03a, 0x03b, 0x03b, 0x03c, 0x03c, + 0x03d, 0x03d, 0x03e, 0x03e, 0x03f, 0x03f, 0x040, 0x040, + 0x041, 0x041, 0x042, 0x042, 0x043, 0x043, 0x044, 0x044, + 0x045, 0x045, 0x046, 0x046, 0x047, 0x047, 0x048, 0x048, + 0x049, 0x049, 0x04a, 0x04a, 0x04b, 0x04b, 0x04c, 0x04c, + 0x04d, 0x04d, 0x04e, 0x04e, 0x04f, 0x04f, 0x050, 0x050, + 0x051, 0x051, 0x052, 0x052, 0x053, 0x053, 0x054, 0x054, + 0x055, 0x055, 0x056, 0x056, 0x057, 0x057, 0x058, 0x058, + 0x059, 0x059, 0x05a, 0x05a, 0x05b, 0x05b, 0x05c, 0x05c, + 0x05d, 0x05d, 0x05e, 0x05e, 0x05f, 0x05f, 0x060, 0x060, + 0x061, 0x061, 0x062, 0x062, 0x063, 0x063, 0x064, 0x064, + 0x065, 0x065, 0x066, 0x066, 0x067, 0x067, 0x068, 0x068, + 0x069, 0x069, 0x06a, 0x06a, 0x06b, 0x06b, 0x06c, 0x06c, + 0x06d, 0x06d, 0x06e, 0x06e, 0x06f, 0x06f, 0x070, 0x071, + 0x071, 0x072, 0x072, 0x073, 0x073, 0x074, 0x074, 0x075, + 0x075, 0x076, 0x076, 0x077, 0x077, 0x078, 0x078, 0x079, + 0x079, 0x07a, 0x07a, 0x07b, 0x07b, 0x07c, 0x07c, 0x07d, + 0x07d, 0x07e, 0x07e, 0x07f, 0x07f, 0x080, 0x081, 0x081, + 0x082, 0x082, 0x083, 0x083, 0x084, 0x084, 0x085, 0x085, + 0x086, 0x086, 0x087, 0x087, 0x088, 0x088, 0x089, 0x089, + 0x08a, 0x08a, 0x08b, 0x08b, 0x08c, 0x08d, 0x08d, 0x08e, + 0x08e, 0x08f, 0x08f, 0x090, 0x090, 0x091, 0x091, 0x092, + 0x092, 0x093, 0x093, 0x094, 0x094, 0x095, 0x096, 0x096, + 0x097, 0x097, 0x098, 0x098, 0x099, 0x099, 0x09a, 0x09a, + 0x09b, 0x09b, 0x09c, 0x09c, 0x09d, 0x09d, 0x09e, 0x09f, + 0x09f, 0x0a0, 0x0a0, 0x0a1, 0x0a1, 0x0a2, 0x0a2, 0x0a3, + 0x0a3, 0x0a4, 0x0a4, 0x0a5, 0x0a6, 0x0a6, 0x0a7, 0x0a7, + 0x0a8, 0x0a8, 0x0a9, 0x0a9, 0x0aa, 0x0aa, 0x0ab, 0x0ab, + 0x0ac, 0x0ad, 0x0ad, 0x0ae, 0x0ae, 0x0af, 0x0af, 0x0b0, + 0x0b0, 0x0b1, 0x0b1, 0x0b2, 0x0b2, 0x0b3, 0x0b4, 0x0b4, + 0x0b5, 0x0b5, 0x0b6, 0x0b6, 0x0b7, 0x0b7, 0x0b8, 0x0b8, + 0x0b9, 0x0ba, 0x0ba, 0x0bb, 0x0bb, 0x0bc, 0x0bc, 0x0bd, + 0x0bd, 0x0be, 0x0be, 0x0bf, 0x0c0, 0x0c0, 0x0c1, 0x0c1, + 0x0c2, 0x0c2, 0x0c3, 0x0c3, 0x0c4, 0x0c4, 0x0c5, 0x0c6, + 0x0c6, 0x0c7, 0x0c7, 0x0c8, 0x0c8, 0x0c9, 0x0c9, 0x0ca, + 0x0cb, 0x0cb, 0x0cc, 0x0cc, 0x0cd, 0x0cd, 0x0ce, 0x0ce, + 0x0cf, 0x0d0, 0x0d0, 0x0d1, 0x0d1, 0x0d2, 0x0d2, 0x0d3, + 0x0d3, 0x0d4, 0x0d5, 0x0d5, 0x0d6, 0x0d6, 0x0d7, 0x0d7, + 0x0d8, 0x0d8, 0x0d9, 0x0da, 0x0da, 0x0db, 0x0db, 0x0dc, + 0x0dc, 0x0dd, 0x0de, 0x0de, 0x0df, 0x0df, 0x0e0, 0x0e0, + 0x0e1, 0x0e1, 0x0e2, 0x0e3, 0x0e3, 0x0e4, 0x0e4, 0x0e5, + 0x0e5, 0x0e6, 0x0e7, 0x0e7, 0x0e8, 0x0e8, 0x0e9, 0x0e9, + 0x0ea, 0x0eb, 0x0eb, 0x0ec, 0x0ec, 0x0ed, 0x0ed, 0x0ee, + 0x0ef, 0x0ef, 0x0f0, 0x0f0, 0x0f1, 0x0f1, 0x0f2, 0x0f3, + 0x0f3, 0x0f4, 0x0f4, 0x0f5, 0x0f5, 0x0f6, 0x0f7, 0x0f7, + 0x0f8, 0x0f8, 0x0f9, 0x0f9, 0x0fa, 0x0fb, 0x0fb, 0x0fc, + 0x0fc, 0x0fd, 0x0fd, 0x0fe, 0x0ff, 0x0ff, 0x100, 0x100, + 0x101, 0x101, 0x102, 0x103, 0x103, 0x104, 0x104, 0x105, + 0x106, 0x106, 0x107, 0x107, 0x108, 0x108, 0x109, 0x10a, + 0x10a, 0x10b, 0x10b, 0x10c, 0x10c, 0x10d, 0x10e, 0x10e, + 0x10f, 0x10f, 0x110, 0x111, 0x111, 0x112, 0x112, 0x113, + 0x114, 0x114, 0x115, 0x115, 0x116, 0x116, 0x117, 0x118, + 0x118, 0x119, 0x119, 0x11a, 0x11b, 0x11b, 0x11c, 0x11c, + 0x11d, 0x11e, 0x11e, 0x11f, 0x11f, 0x120, 0x120, 0x121, + 0x122, 0x122, 0x123, 0x123, 0x124, 0x125, 0x125, 0x126, + 0x126, 0x127, 0x128, 0x128, 0x129, 0x129, 0x12a, 0x12b, + 0x12b, 0x12c, 0x12c, 0x12d, 0x12e, 0x12e, 0x12f, 0x12f, + 0x130, 0x131, 0x131, 0x132, 0x132, 0x133, 0x134, 0x134, + 0x135, 0x135, 0x136, 0x137, 0x137, 0x138, 0x138, 0x139, + 0x13a, 0x13a, 0x13b, 0x13b, 0x13c, 0x13d, 0x13d, 0x13e, + 0x13e, 0x13f, 0x140, 0x140, 0x141, 0x141, 0x142, 0x143, + 0x143, 0x144, 0x144, 0x145, 0x146, 0x146, 0x147, 0x148, + 0x148, 0x149, 0x149, 0x14a, 0x14b, 0x14b, 0x14c, 0x14c, + 0x14d, 0x14e, 0x14e, 0x14f, 0x14f, 0x150, 0x151, 0x151, + 0x152, 0x153, 0x153, 0x154, 0x154, 0x155, 0x156, 0x156, + 0x157, 0x157, 0x158, 0x159, 0x159, 0x15a, 0x15b, 0x15b, + 0x15c, 0x15c, 0x15d, 0x15e, 0x15e, 0x15f, 0x160, 0x160, + 0x161, 0x161, 0x162, 0x163, 0x163, 0x164, 0x165, 0x165, + 0x166, 0x166, 0x167, 0x168, 0x168, 0x169, 0x16a, 0x16a, + 0x16b, 0x16b, 0x16c, 0x16d, 0x16d, 0x16e, 0x16f, 0x16f, + 0x170, 0x170, 0x171, 0x172, 0x172, 0x173, 0x174, 0x174, + 0x175, 0x175, 0x176, 0x177, 0x177, 0x178, 0x179, 0x179, + 0x17a, 0x17a, 0x17b, 0x17c, 0x17c, 0x17d, 0x17e, 0x17e, + 0x17f, 0x180, 0x180, 0x181, 0x181, 0x182, 0x183, 0x183, + 0x184, 0x185, 0x185, 0x186, 0x187, 0x187, 0x188, 0x188, + 0x189, 0x18a, 0x18a, 0x18b, 0x18c, 0x18c, 0x18d, 0x18e, + 0x18e, 0x18f, 0x190, 0x190, 0x191, 0x191, 0x192, 0x193, + 0x193, 0x194, 0x195, 0x195, 0x196, 0x197, 0x197, 0x198, + 0x199, 0x199, 0x19a, 0x19a, 0x19b, 0x19c, 0x19c, 0x19d, + 0x19e, 0x19e, 0x19f, 0x1a0, 0x1a0, 0x1a1, 0x1a2, 0x1a2, + 0x1a3, 0x1a4, 0x1a4, 0x1a5, 0x1a6, 0x1a6, 0x1a7, 0x1a8, + 0x1a8, 0x1a9, 0x1a9, 0x1aa, 0x1ab, 0x1ab, 0x1ac, 0x1ad, + 0x1ad, 0x1ae, 0x1af, 0x1af, 0x1b0, 0x1b1, 0x1b1, 0x1b2, + 0x1b3, 0x1b3, 0x1b4, 0x1b5, 0x1b5, 0x1b6, 0x1b7, 0x1b7, + 0x1b8, 0x1b9, 0x1b9, 0x1ba, 0x1bb, 0x1bb, 0x1bc, 0x1bd, + 0x1bd, 0x1be, 0x1bf, 0x1bf, 0x1c0, 0x1c1, 0x1c1, 0x1c2, + 0x1c3, 0x1c3, 0x1c4, 0x1c5, 0x1c5, 0x1c6, 0x1c7, 0x1c7, + 0x1c8, 0x1c9, 0x1c9, 0x1ca, 0x1cb, 0x1cb, 0x1cc, 0x1cd, + 0x1cd, 0x1ce, 0x1cf, 0x1cf, 0x1d0, 0x1d1, 0x1d1, 0x1d2, + 0x1d3, 0x1d3, 0x1d4, 0x1d5, 0x1d5, 0x1d6, 0x1d7, 0x1d7, + 0x1d8, 0x1d9, 0x1d9, 0x1da, 0x1db, 0x1db, 0x1dc, 0x1dd, + 0x1dd, 0x1de, 0x1df, 0x1df, 0x1e0, 0x1e1, 0x1e1, 0x1e2, + 0x1e3, 0x1e4, 0x1e4, 0x1e5, 0x1e6, 0x1e6, 0x1e7, 0x1e8, + 0x1e8, 0x1e9, 0x1ea, 0x1ea, 0x1eb, 0x1ec, 0x1ec, 0x1ed, + 0x1ee, 0x1ee, 0x1ef, 0x1f0, 0x1f0, 0x1f1, 0x1f2, 0x1f3, + 0x1f3, 0x1f4, 0x1f5, 0x1f5, 0x1f6, 0x1f7, 0x1f7, 0x1f8, + 0x1f9, 0x1f9, 0x1fa, 0x1fb, 0x1fb, 0x1fc, 0x1fd, 0x1fe, + 0x1fe, 0x1ff, 0x200, 0x200, 0x201, 0x202, 0x202, 0x203, + 0x204, 0x205, 0x205, 0x206, 0x207, 0x207, 0x208, 0x209, + 0x209, 0x20a, 0x20b, 0x20b, 0x20c, 0x20d, 0x20e, 0x20e, + 0x20f, 0x210, 0x210, 0x211, 0x212, 0x212, 0x213, 0x214, + 0x215, 0x215, 0x216, 0x217, 0x217, 0x218, 0x219, 0x21a, + 0x21a, 0x21b, 0x21c, 0x21c, 0x21d, 0x21e, 0x21e, 0x21f, + 0x220, 0x221, 0x221, 0x222, 0x223, 0x223, 0x224, 0x225, + 0x226, 0x226, 0x227, 0x228, 0x228, 0x229, 0x22a, 0x22b, + 0x22b, 0x22c, 0x22d, 0x22d, 0x22e, 0x22f, 0x230, 0x230, + 0x231, 0x232, 0x232, 0x233, 0x234, 0x235, 0x235, 0x236, + 0x237, 0x237, 0x238, 0x239, 0x23a, 0x23a, 0x23b, 0x23c, + 0x23c, 0x23d, 0x23e, 0x23f, 0x23f, 0x240, 0x241, 0x241, + 0x242, 0x243, 0x244, 0x244, 0x245, 0x246, 0x247, 0x247, + 0x248, 0x249, 0x249, 0x24a, 0x24b, 0x24c, 0x24c, 0x24d, + 0x24e, 0x24f, 0x24f, 0x250, 0x251, 0x251, 0x252, 0x253, + 0x254, 0x254, 0x255, 0x256, 0x257, 0x257, 0x258, 0x259, + 0x259, 0x25a, 0x25b, 0x25c, 0x25c, 0x25d, 0x25e, 0x25f, + 0x25f, 0x260, 0x261, 0x262, 0x262, 0x263, 0x264, 0x265, + 0x265, 0x266, 0x267, 0x267, 0x268, 0x269, 0x26a, 0x26a, + 0x26b, 0x26c, 0x26d, 0x26d, 0x26e, 0x26f, 0x270, 0x270, + 0x271, 0x272, 0x273, 0x273, 0x274, 0x275, 0x276, 0x276, + 0x277, 0x278, 0x279, 0x279, 0x27a, 0x27b, 0x27c, 0x27c, + 0x27d, 0x27e, 0x27f, 0x27f, 0x280, 0x281, 0x282, 0x282, + 0x283, 0x284, 0x285, 0x285, 0x286, 0x287, 0x288, 0x288, + 0x289, 0x28a, 0x28b, 0x28b, 0x28c, 0x28d, 0x28e, 0x28e, + 0x28f, 0x290, 0x291, 0x291, 0x292, 0x293, 0x294, 0x294, + 0x295, 0x296, 0x297, 0x298, 0x298, 0x299, 0x29a, 0x29b, + 0x29b, 0x29c, 0x29d, 0x29e, 0x29e, 0x29f, 0x2a0, 0x2a1, + 0x2a1, 0x2a2, 0x2a3, 0x2a4, 0x2a5, 0x2a5, 0x2a6, 0x2a7, + 0x2a8, 0x2a8, 0x2a9, 0x2aa, 0x2ab, 0x2ab, 0x2ac, 0x2ad, + 0x2ae, 0x2af, 0x2af, 0x2b0, 0x2b1, 0x2b2, 0x2b2, 0x2b3, + 0x2b4, 0x2b5, 0x2b5, 0x2b6, 0x2b7, 0x2b8, 0x2b9, 0x2b9, + 0x2ba, 0x2bb, 0x2bc, 0x2bc, 0x2bd, 0x2be, 0x2bf, 0x2c0, + 0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c4, 0x2c5, 0x2c6, + 0x2c7, 0x2c7, 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cb, 0x2cc, + 0x2cd, 0x2ce, 0x2ce, 0x2cf, 0x2d0, 0x2d1, 0x2d2, 0x2d2, + 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2d6, 0x2d7, 0x2d8, 0x2d9, + 0x2da, 0x2da, 0x2db, 0x2dc, 0x2dd, 0x2dd, 0x2de, 0x2df, + 0x2e0, 0x2e1, 0x2e1, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e5, + 0x2e6, 0x2e7, 0x2e8, 0x2e9, 0x2e9, 0x2ea, 0x2eb, 0x2ec, + 0x2ed, 0x2ed, 0x2ee, 0x2ef, 0x2f0, 0x2f1, 0x2f1, 0x2f2, + 0x2f3, 0x2f4, 0x2f5, 0x2f5, 0x2f6, 0x2f7, 0x2f8, 0x2f9, + 0x2f9, 0x2fa, 0x2fb, 0x2fc, 0x2fd, 0x2fd, 0x2fe, 0x2ff, + 0x300, 0x301, 0x302, 0x302, 0x303, 0x304, 0x305, 0x306, + 0x306, 0x307, 0x308, 0x309, 0x30a, 0x30a, 0x30b, 0x30c, + 0x30d, 0x30e, 0x30f, 0x30f, 0x310, 0x311, 0x312, 0x313, + 0x313, 0x314, 0x315, 0x316, 0x317, 0x318, 0x318, 0x319, + 0x31a, 0x31b, 0x31c, 0x31c, 0x31d, 0x31e, 0x31f, 0x320, + 0x321, 0x321, 0x322, 0x323, 0x324, 0x325, 0x326, 0x326, + 0x327, 0x328, 0x329, 0x32a, 0x32a, 0x32b, 0x32c, 0x32d, + 0x32e, 0x32f, 0x32f, 0x330, 0x331, 0x332, 0x333, 0x334, + 0x334, 0x335, 0x336, 0x337, 0x338, 0x339, 0x339, 0x33a, + 0x33b, 0x33c, 0x33d, 0x33e, 0x33e, 0x33f, 0x340, 0x341, + 0x342, 0x343, 0x343, 0x344, 0x345, 0x346, 0x347, 0x348, + 0x349, 0x349, 0x34a, 0x34b, 0x34c, 0x34d, 0x34e, 0x34e, + 0x34f, 0x350, 0x351, 0x352, 0x353, 0x353, 0x354, 0x355, + 0x356, 0x357, 0x358, 0x359, 0x359, 0x35a, 0x35b, 0x35c, + 0x35d, 0x35e, 0x35f, 0x35f, 0x360, 0x361, 0x362, 0x363, + 0x364, 0x364, 0x365, 0x366, 0x367, 0x368, 0x369, 0x36a, + 0x36a, 0x36b, 0x36c, 0x36d, 0x36e, 0x36f, 0x370, 0x370, + 0x371, 0x372, 0x373, 0x374, 0x375, 0x376, 0x377, 0x377, + 0x378, 0x379, 0x37a, 0x37b, 0x37c, 0x37d, 0x37d, 0x37e, + 0x37f, 0x380, 0x381, 0x382, 0x383, 0x383, 0x384, 0x385, + 0x386, 0x387, 0x388, 0x389, 0x38a, 0x38a, 0x38b, 0x38c, + 0x38d, 0x38e, 0x38f, 0x390, 0x391, 0x391, 0x392, 0x393, + 0x394, 0x395, 0x396, 0x397, 0x398, 0x398, 0x399, 0x39a, + 0x39b, 0x39c, 0x39d, 0x39e, 0x39f, 0x39f, 0x3a0, 0x3a1, + 0x3a2, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a7, 0x3a8, + 0x3a9, 0x3aa, 0x3ab, 0x3ac, 0x3ad, 0x3ae, 0x3ae, 0x3af, + 0x3b0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b6, + 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, + 0x3bf, 0x3bf, 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4, 0x3c5, + 0x3c6, 0x3c7, 0x3c7, 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cc, + 0x3cd, 0x3ce, 0x3cf, 0x3d0, 0x3d1, 0x3d1, 0x3d2, 0x3d3, + 0x3d4, 0x3d5, 0x3d6, 0x3d7, 0x3d8, 0x3d9, 0x3da, 0x3da, + 0x3db, 0x3dc, 0x3dd, 0x3de, 0x3df, 0x3e0, 0x3e1, 0x3e2, + 0x3e3, 0x3e4, 0x3e4, 0x3e5, 0x3e6, 0x3e7, 0x3e8, 0x3e9, + 0x3ea, 0x3eb, 0x3ec, 0x3ed, 0x3ee, 0x3ef, 0x3ef, 0x3f0, + 0x3f1, 0x3f2, 0x3f3, 0x3f4, 0x3f5, 0x3f6, 0x3f7, 0x3f8, + 0x3f9, 0x3fa, 0x3fa, 0x3fb, 0x3fc, 0x3fd, 0x3fe, 0x3ff +}; + +/* + * Attenuation according to GM recommendations, in -0.375 dB units. + * table[v] = 40 * log(v / 127) / -0.375 + */ +static const uint8_t g_volume_table[128] = { + 255, 224, 192, 173, 160, 150, 141, 134, + 128, 122, 117, 113, 109, 105, 102, 99, + 96, 93, 90, 88, 85, 83, 81, 79, + 77, 75, 73, 71, 70, 68, 67, 65, + 64, 62, 61, 59, 58, 57, 56, 54, + 53, 52, 51, 50, 49, 48, 47, 46, + 45, 44, 43, 42, 41, 40, 39, 39, + 38, 37, 36, 35, 34, 34, 33, 32, + 31, 31, 30, 29, 29, 28, 27, 27, + 26, 25, 25, 24, 24, 23, 22, 22, + 21, 21, 20, 19, 19, 18, 18, 17, + 17, 16, 16, 15, 15, 14, 14, 13, + 13, 12, 12, 11, 11, 10, 10, 9, + 9, 9, 8, 8, 7, 7, 6, 6, + 6, 5, 5, 4, 4, 4, 3, 3, + 2, 2, 2, 1, 1, 0, 0, 0 +}; + +typedef struct opl4_midi { + fm_drv_t opl4; + MIDI_CHANNEL_DATA midi_channel_data[16]; + VOICE_DATA voice_data[24]; + int16_t buffer[SOUNDBUFLEN * 2]; + float buffer_float[SOUNDBUFLEN * 2]; + uint32_t midi_pos; + bool on; + atomic_bool gen_in_progress; + thread_t *thread; + event_t *wait_event; +} opl4_midi_t; + +static opl4_midi_t *opl4_midi_cur; + +static void +opl4_write_wave_register(const uint8_t reg, const uint8_t value, opl4_midi_t *opl4_midi) +{ + opl4_midi->opl4.write(0x380, reg, opl4_midi->opl4.priv); + opl4_midi->opl4.write(0x381, value, opl4_midi->opl4.priv); +} + +VOICE_DATA * +get_voice(const YRW801_WAVE_DATA *wave_data, opl4_midi_t *opl4_midi) +{ + VOICE_DATA *free_voice = &opl4_midi->voice_data[0]; + VOICE_DATA *oldest_voice = &opl4_midi->voice_data[0]; + for (uint8_t voice = 0; voice < 24; voice++) { + if (opl4_midi_cur->voice_data[voice].is_active) { + if (opl4_midi_cur->voice_data[voice].activated < oldest_voice->activated) + oldest_voice = &opl4_midi_cur->voice_data[voice]; + } else { + if (opl4_midi_cur->voice_data[voice].wave_data == wave_data) { + free_voice = &opl4_midi_cur->voice_data[voice]; + break; + } + + if (opl4_midi_cur->voice_data[voice].activated < free_voice->activated) + free_voice = &opl4_midi_cur->voice_data[voice]; + } + } + + /* If no free voice found, deactivate the 'oldest' */ + if (free_voice->is_active) { + free_voice = oldest_voice; + free_voice->is_active = 0; + free_voice->activated = 0; + + free_voice->reg_misc &= ~OPL4_KEY_ON_BIT; + opl4_write_wave_register(OPL4_REG_MISC + free_voice->number, free_voice->reg_misc, opl4_midi); + } + + return free_voice; +} + +static void +update_pan(VOICE_DATA *voice, opl4_midi_t *opl4_midi) +{ + int8_t pan = voice->wave_data->panpot; + + if (!voice->midi_channel->drum_channel) + pan += voice->midi_channel->panpot; + if (pan < -7) + pan = -7; + else if (pan > 7) + pan = 7; + + voice->reg_misc = (voice->reg_misc & ~OPL4_PAN_POT_MASK) | (pan & OPL4_PAN_POT_MASK); + opl4_write_wave_register(OPL4_REG_MISC + voice->number, voice->reg_misc, opl4_midi); +} + +void +update_pitch(VOICE_DATA *voice, uint16_t pitch_bend, opl4_midi_t *opl4_midi) +{ + int32_t pitch = voice->midi_channel->drum_channel ? 0 : (voice->note - 60) * 128; + pitch = pitch * (int) voice->wave_data->key_scaling / 100; + pitch = pitch + 7680; + pitch += voice->wave_data->pitch_offset; + pitch += pitch_bend * 256 / 0x2000; + if (pitch < 0) + pitch = 0; + else if (pitch > 0x5FFF) + pitch = 0x5FFF; + + int8_t octave = pitch / 0x600 - 8; + uint16_t fnumber = g_wave_pitch_map[pitch % 0x600]; + + opl4_write_wave_register(OPL4_REG_OCTAVE + voice->number, (octave << 4) | ((fnumber >> 7) & 0x07), opl4_midi); + voice->reg_f_number = (voice->reg_f_number & OPL4_TONE_NUMBER_BIT8) | ((fnumber << 1) & OPL4_F_NUMBER_LOW_MASK); + opl4_write_wave_register(OPL4_REG_F_NUMBER + voice->number, voice->reg_f_number, opl4_midi); +} + +void +update_volume(VOICE_DATA *voice, opl4_midi_t *opl4_midi) +{ + int16_t att = voice->wave_data->tone_attenuate; + + att += g_volume_table[voice->velocity]; + att = 0x7F - (0x7F - att) * (voice->wave_data->volume_factor) / 0xFE; + att -= 16; + if (att < 0) + att = 0; + else if (att > 0x7E) + att = 0x7E; + + opl4_write_wave_register(OPL4_REG_LEVEL + voice->number, (att << 1) | voice->level_direct, opl4_midi); + voice->level_direct = 0; +} + +void +note_off(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_midi_t *opl4_midi) +{ + /* Velocity not used */ + (void) velocity; + + while (opl4_midi->gen_in_progress) { } + for (uint8_t i = 0; i < 24; i++) { + VOICE_DATA *voice = &opl4_midi->voice_data[i]; + if (voice->is_active && voice->midi_channel == midi_channel && voice->note == note) { + voice->is_active = false; + voice->activated = 0; + + voice->reg_misc &= ~OPL4_KEY_ON_BIT; + opl4_write_wave_register(OPL4_REG_MISC + voice->number, voice->reg_misc, opl4_midi); + } + } +} + +void +update_vibrato_depth(VOICE_DATA *voice, opl4_midi_t *opl4_midi) +{ + uint16_t depth; + + depth = (7 - voice->wave_data->vibrato) * (voice->midi_channel->vibrato & 0x7F); + depth = (depth >> 7) + voice->wave_data->vibrato; + voice->reg_lfo_vibrato &= ~OPL4_VIBRATO_DEPTH_MASK; + voice->reg_lfo_vibrato |= depth & OPL4_VIBRATO_DEPTH_MASK; + opl4_write_wave_register(OPL4_REG_LFO_VIBRATO + voice->number, voice->reg_lfo_vibrato, opl4_midi); +} + +void +note_on(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_midi_t *opl4_midi) +{ + const YRW801_REGION_DATA_PTR *region_ptr = &snd_yrw801_regions[0]; + const YRW801_WAVE_DATA *wave_data[2]; + VOICE_DATA *voice[2]; + uint8_t i = 0, voices = 0; + uint32_t j = 0; + static uint64_t activation_num = 0; + + while (opl4_midi->gen_in_progress) { } + + if (midi_channel->drum_channel) + wave_data[voices++] = ®ion_ptr[0x80].regions[note - 0x1A].wave_data; + else { + /* Determine the number of voices and voice parameters */ + const YRW801_REGION_DATA *region = region_ptr[midi_channel->instrument & 0x7F].regions; + + while (i < region_ptr[midi_channel->instrument & 0x7F].count) { + if (note >= region[i].key_min && note <= region[i].key_max) { + wave_data[voices] = ®ion[i].wave_data; + if (++voices >= 2) + break; + } + i++; + } + } + + /* Allocate and initialize needed voices */ + for (i = 0; i < voices; i++) { + voice[i] = get_voice(wave_data[i], opl4_midi); + voice[i]->is_active = true; + voice[i]->activated = activation_num++; + + voice[i]->midi_channel = midi_channel; + voice[i]->note = note; + voice[i]->velocity = velocity & 0x7F; + } + + for (i = 0; i < voices; i++) { + voice[i]->reg_f_number = (wave_data[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8; + opl4_write_wave_register(OPL4_REG_F_NUMBER + voice[i]->number, voice[i]->reg_f_number, opl4_midi); + + bool new_wave = (voice[i]->wave_data != wave_data[i]); + /* Set tone number (triggers header loading) */ + if (new_wave) { + opl4_write_wave_register(OPL4_REG_TONE_NUMBER + voice[i]->number, wave_data[i]->tone & 0xFF, opl4_midi); + voice[i]->wave_data = wave_data[i]; + } + + voice[i]->reg_misc = OPL4_LFO_RESET_BIT; + update_pan(voice[i], opl4_midi); + update_pitch(voice[i], 0, opl4_midi); + voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT; + update_volume(voice[i], opl4_midi); + if (new_wave) { + /* Set remaining parameters */ + opl4_write_wave_register(OPL4_REG_ATTACK_DECAY1 + voice[i]->number, voice[i]->wave_data->reg_attack_decay1, opl4_midi); + opl4_write_wave_register(OPL4_REG_LEVEL_DECAY2 + voice[i]->number, voice[i]->wave_data->reg_level_decay2, opl4_midi); + opl4_write_wave_register(OPL4_REG_RELEASE_CORRECTION + voice[i]->number, voice[i]->wave_data->reg_release_correction, opl4_midi); + opl4_write_wave_register(OPL4_REG_TREMOLO + voice[i]->number, voice[i]->wave_data->reg_tremolo, opl4_midi); + + voice[i]->reg_lfo_vibrato = voice[i]->wave_data->reg_lfo_vibrato; + + if (!midi_channel->drum_channel) + update_vibrato_depth(voice[i], opl4_midi); + } + } + + /* Finally, switch on all voices */ + for (i = 0; i < voices; i++) { + voice[i]->reg_misc = (voice[i]->reg_misc & 0x1F) | OPL4_KEY_ON_BIT; + opl4_write_wave_register(OPL4_REG_MISC + voice[i]->number, voice[i]->reg_misc, opl4_midi); + } +} + +void +control_change(uint8_t midi_channel, uint8_t id, uint8_t value, opl4_midi_t *opl4_midi) +{ + int i = 0; + switch (id) { + case 10: + /* Change stereo panning */ + if (midi_channel != DRUM_CHANNEL) { + opl4_midi->midi_channel_data[midi_channel].panpot = (value - 0x40) >> 3; + for (i = 0; i < NR_OF_WAVE_CHANNELS; i++) { + if (opl4_midi->voice_data[i].is_active && opl4_midi->voice_data[i].midi_channel == &opl4_midi->midi_channel_data[midi_channel]) { + update_pan(&opl4_midi->voice_data[i], opl4_midi); + } + } + } + break; + } +} + +void +pitch_wheel(uint8_t midi_channel, uint16_t value, opl4_midi_t *opl4_midi) +{ + int i = 0; + + for (i = 0; i < 24; i++) { + if (opl4_midi->voice_data[i].is_active && opl4_midi->voice_data[i].midi_channel == &opl4_midi->midi_channel_data[midi_channel]) { + update_pitch(&opl4_midi->voice_data[i], value, opl4_midi); + } + } +} + +void +channel_pressure(uint8_t midi_channel, uint8_t pressure) +{ + (void) midi_channel; + (void) pressure; +} + +void +key_pressure(uint8_t midi_channel, uint8_t note, uint8_t pressure) +{ + (void) midi_channel; + (void) note; + (void) pressure; +} + +void +program_change(uint8_t midi_channel, uint8_t program, opl4_midi_t *opl4_midi) +{ + opl4_midi->midi_channel_data[midi_channel].instrument = program; +} + +#define RENDER_RATE (48000 / 100) +static void +opl4_midi_thread(void *arg) +{ + opl4_midi_t *opl4_midi = opl4_midi_cur; + uint32_t i = 0; + uint32_t buf_size = RENDER_RATE * 2; + + int32_t buffer[RENDER_RATE * 2]; + + extern void givealbuffer_midi(void *buf, uint32_t size); + while (opl4_midi->on) { + thread_wait_event(opl4_midi->wait_event, -1); + thread_reset_event(opl4_midi->wait_event); + if (!opl4_midi->on) + break; + atomic_store(&opl4_midi->gen_in_progress, true); + opl4_midi->opl4.generate(opl4_midi->opl4.priv, buffer, RENDER_RATE); + atomic_store(&opl4_midi->gen_in_progress, false); + if (sound_is_float) { + for (i = 0; i < (buf_size / 2); i++) { + opl4_midi->buffer_float[i * 2] = buffer[i * 2] / 32768.0; + opl4_midi->buffer_float[(i * 2) + 1] = buffer[(i * 2) + 1] / 32768.0; + } + givealbuffer_midi(opl4_midi->buffer_float, buf_size); + } else { + for (i = 0; i < (buf_size / 2); i++) { + opl4_midi->buffer[i * 2] = buffer[i * 2] & 0xFFFF; /* Outputs are clamped beforehand. */ + opl4_midi->buffer[(i * 2) + 1] = buffer[(i * 2) + 1] & 0xFFFF; /* Outputs are clamped beforehand. */ + } + givealbuffer_midi(opl4_midi->buffer, buf_size); + } + } +} + +static void +opl4_midi_poll(void) +{ + opl4_midi_t *opl4_midi = opl4_midi_cur; + opl4_midi->midi_pos++; + if (opl4_midi->midi_pos == RENDER_RATE) { + opl4_midi->midi_pos = 0; + thread_set_event(opl4_midi->wait_event); + } +} + +void +opl4_midi_msg(uint8_t *val) +{ + opl4_midi_t *opl4_midi = opl4_midi_cur; + + uint32_t msg = *(uint32_t *) (val); + uint8_t data_byte_1 = msg & 0xFF; + uint8_t data_byte_2 = (msg >> 8) & 0xFF; + uint8_t data_byte_3 = (msg >> 16) & 0xFF; + + uint8_t midi_channel = data_byte_1 & 0x0F; + uint8_t midi_command = data_byte_1 >> 4; + + switch (midi_command) { + case 0x8: // Note OFF + note_off(data_byte_2 & 0x7F, data_byte_3, &opl4_midi->midi_channel_data[midi_channel], opl4_midi); + break; + case 0x9: // Note ON + note_on(data_byte_2 & 0x7F, data_byte_3, &opl4_midi->midi_channel_data[midi_channel], opl4_midi); + break; + case 0xA: // Key after-touch + break; + case 0xB: // Control change + control_change(midi_channel, data_byte_2, data_byte_3, opl4_midi); + break; + case 0xC: // Program change + program_change(midi_channel, data_byte_2 & 0x7F, opl4_midi); + break; + case 0xD: // Channel after-touch + break; + case 0xE: // Pitch wheel + pitch_wheel(midi_channel, ((data_byte_3 <<= 7) | data_byte_2), opl4_midi); + break; + } +} + +void +opl4_midi_sysex(uint8_t *data, unsigned int len) +{ +} + +void * +opl4_init(const device_t *info) +{ + midi_device_t *dev; + extern void al_set_midi(int freq, int buf_size); + + dev = malloc(sizeof(midi_device_t)); + memset(dev, 0, sizeof(midi_device_t)); + + dev->play_msg = opl4_midi_msg; + dev->play_sysex = opl4_midi_sysex; + dev->poll = opl4_midi_poll; + + al_set_midi(48000, 4800); + + opl4_midi_cur = calloc(1, sizeof(opl4_midi_t)); + + fm_driver_get(FM_YMF278B, &opl4_midi_cur->opl4); + + opl4_midi_cur->opl4.write(0x38A, 0x05, opl4_midi_cur->opl4.priv); + opl4_midi_cur->opl4.write(0x389, 0x3, opl4_midi_cur->opl4.priv); + midi_out_init(dev); + + opl4_midi_cur->on = true; + opl4_midi_cur->midi_channel_data[9].drum_channel = true; + atomic_init(&opl4_midi_cur->gen_in_progress, 0); + + for (uint8_t voice = 0; voice < NR_OF_WAVE_CHANNELS; voice++) { + opl4_midi_cur->voice_data[voice].number = voice; + opl4_midi_cur->voice_data[voice].is_active = false; + opl4_midi_cur->voice_data[voice].activated = 0; + opl4_midi_cur->voice_data[voice].midi_channel = NULL; + opl4_midi_cur->voice_data[voice].note = 0; + opl4_midi_cur->voice_data[voice].velocity = 0; + opl4_midi_cur->voice_data[voice].wave_data = NULL; + opl4_midi_cur->voice_data[voice].level_direct = 0; + opl4_midi_cur->voice_data[voice].reg_f_number = 0; + opl4_midi_cur->voice_data[voice].reg_misc = 0; + opl4_midi_cur->voice_data[voice].reg_lfo_vibrato = 0; + } + opl4_midi_cur->wait_event = thread_create_event(); + opl4_midi_cur->thread = thread_create(opl4_midi_thread, NULL); + return dev; +} + +void +opl4_close(void *p) +{ + if (!p) + return; + + opl4_midi_cur->on = false; + thread_set_event(opl4_midi_cur->wait_event); + thread_wait(opl4_midi_cur->thread); + free(opl4_midi_cur); + opl4_midi_cur = NULL; +} + +static int +opl4_midi_available(void) +{ + return rom_present("roms/sound/yamaha/yrw801.rom"); +} + +const device_t opl4_midi_device = { + .name = "OPL4-ML Daughterboard", + .internal_name = "opl4-ml", + .flags = 0, + .local = 0, + .init = opl4_init, + .close = opl4_close, + .reset = NULL, + { .available = opl4_midi_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sound/midi_opl4_yrw801.c b/src/sound/midi_opl4_yrw801.c new file mode 100644 index 000000000..96822b9af --- /dev/null +++ b/src/sound/midi_opl4_yrw801.c @@ -0,0 +1,1042 @@ +/* Table taken from linux/sound/drivers/opl4/yrw801.c */ +/* Macros from Linux source code as well */ + +#include "yrw801.h" + +static const YRW801_REGION_DATA regions_00[] = { + /* Acoustic Grand Piano */ + { 0x14, 0x27, { 0x12c, 7474, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6816, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5899, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5290, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4260, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3625, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3116, 100, 0, 0, 0x04, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2081, 100, 0, 0, 0x03, 0xc8, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1444, 100, 0, 0, 0x07, 0xc8, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1915, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_01[] = { + /* Bright Acoustic Piano */ + { 0x14, 0x2d, { 0x12c, 7474, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12d, 6816, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12e, 5899, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x12f, 5290, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x130, 4260, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x131, 3625, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x132, 3116, 100, 0, 0, 0x04, 0xc8, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x53, 0x58, { 0x133, 2081, 100, 0, 0, 0x07, 0xc8, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x59, 0x5e, { 0x134, 1444, 100, 0, 0, 0x0a, 0xc8, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x5f, 0x6d, { 0x135, 1915, 100, 0, 0, 0x00, 0xc8, 0x20, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_02[] = { + /* Electric Grand Piano */ + { 0x14, 0x2d, { 0x12c, 7476, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x13, 0x07, 0x0 } }, + { 0x2e, 0x33, { 0x12d, 6818, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x34, 0x39, { 0x12e, 5901, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x3a, 0x3f, { 0x12f, 5292, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x40, 0x45, { 0x130, 4262, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x46, 0x4b, { 0x131, 3627, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x4c, 0x52, { 0x132, 3118, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x07, 0x0 } }, + { 0x53, 0x58, { 0x133, 2083, 100, 1, 0, 0x00, 0xae, 0x20, 0xf2, 0x14, 0x17, 0x0 } }, + { 0x59, 0x5e, { 0x134, 1446, 100, 1, 0, 0x00, 0xae, 0x20, 0xf3, 0x14, 0x17, 0x0 } }, + { 0x5f, 0x6d, { 0x135, 1917, 100, 1, 0, 0x00, 0xae, 0x20, 0xf4, 0x15, 0x07, 0x0 } }, + { 0x00, 0x7f, { 0x06c, 6375, 100, -1, 0, 0x00, 0xc2, 0x28, 0xf4, 0x23, 0x18, 0x0 }} +}; +static const YRW801_REGION_DATA regions_03[] = { + /* Honky-Tonk Piano */ + { 0x14, 0x27, { 0x12c, 7474, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6816, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5899, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5290, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4260, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3625, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3116, 100, 0, 0, 0x04, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2081, 100, 0, 0, 0x03, 0xb4, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1444, 100, 0, 0, 0x07, 0xb4, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1915, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf4, 0x15, 0x08, 0x0 }}, + { 0x14, 0x27, { 0x12c, 7486, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6803, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5912, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5275, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4274, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3611, 100, 0, 0, 0x0a, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3129, 100, 0, 0, 0x04, 0xb4, 0x20, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2074, 100, 0, 0, 0x07, 0xb4, 0x20, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1457, 100, 0, 0, 0x01, 0xb4, 0x20, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1903, 100, 0, 0, 0x00, 0xb4, 0x20, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_04[] = { + /* Electric Piano 1 */ + { 0x15, 0x6c, { 0x00b, 6570, 100, 0, 0, 0x00, 0x28, 0x38, 0xf0, 0x00, 0x0c, 0x0 }}, + { 0x00, 0x7f, { 0x06c, 6375, 100, 0, 2, 0x00, 0xb0, 0x22, 0xf4, 0x23, 0x19, 0x0 }} +}; +static const YRW801_REGION_DATA regions_05[] = { + /* Electric Piano 2 */ + { 0x14, 0x27, { 0x12c, 7476, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x12d, 6818, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12e, 5901, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12f, 5292, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x130, 4262, 100, 0, 3, 0x0a, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x131, 3627, 100, 0, 3, 0x0a, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x132, 3118, 100, 0, 3, 0x04, 0xa2, 0x1b, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x133, 2083, 100, 0, 3, 0x03, 0xa2, 0x1b, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x53, 0x58, { 0x134, 1446, 100, 0, 3, 0x07, 0xa2, 0x1b, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x59, 0x6d, { 0x135, 1917, 100, 0, 3, 0x00, 0xa2, 0x1b, 0xf4, 0x15, 0x08, 0x0 }}, + { 0x14, 0x2d, { 0x12c, 7472, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x13, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x12d, 6814, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x12e, 5897, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x12f, 5288, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x130, 4258, 100, 0, 0, 0x0a, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x131, 3623, 100, 0, 0, 0x0a, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x4c, 0x52, { 0x132, 3114, 100, 0, 0, 0x04, 0xa2, 0x18, 0xf2, 0x14, 0x08, 0x0 }}, + { 0x53, 0x58, { 0x133, 2079, 100, 0, 0, 0x07, 0xa2, 0x18, 0xf2, 0x14, 0x18, 0x0 }}, + { 0x59, 0x5e, { 0x134, 1442, 100, 0, 0, 0x0a, 0xa2, 0x18, 0xf3, 0x14, 0x18, 0x0 }}, + { 0x5f, 0x6d, { 0x135, 1913, 100, 0, 0, 0x00, 0xa2, 0x18, 0xf4, 0x15, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_06[] = { + /* Harpsichord */ + { 0x15, 0x39, { 0x080, 5158, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x24, 0x19, 0x0 }}, + { 0x3a, 0x3f, { 0x081, 4408, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x09, 0x0 }}, + { 0x40, 0x45, { 0x082, 3622, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x09, 0x0 }}, + { 0x46, 0x4d, { 0x083, 2843, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x19, 0x0 }}, + { 0x4e, 0x6c, { 0x084, 1307, 100, 0, 0, 0x00, 0xb2, 0x20, 0xf5, 0x25, 0x29, 0x0 }} +}; +static const YRW801_REGION_DATA regions_07[] = { + /* Clavinet */ + { 0x15, 0x51, { 0x027, 5009, 100, 0, 0, 0x00, 0xd2, 0x28, 0xf5, 0x13, 0x2b, 0x0 }}, + { 0x52, 0x6c, { 0x028, 3495, 100, 0, 0, 0x00, 0xd2, 0x28, 0xf5, 0x13, 0x3b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_08[] = { + /* Celesta */ + { 0x15, 0x6c, { 0x02b, 3267, 100, 0, 0, 0x00, 0xdc, 0x20, 0xf4, 0x15, 0x07, 0x3 }} +}; +static const YRW801_REGION_DATA regions_09[] = { + /* Glockenspiel */ + { 0x15, 0x78, { 0x0f3, 285, 100, 0, 0, 0x00, 0xc2, 0x28, 0xf6, 0x25, 0x25, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0a[] = { + /* Music Box */ + { 0x15, 0x6c, { 0x0f3, 3362, 100, 0, 0, 0x00, 0xb6, 0x20, 0xa6, 0x25, 0x25, 0x0 }}, + { 0x15, 0x6c, { 0x101, 4773, 100, 0, 0, 0x00, 0xaa, 0x20, 0xd4, 0x14, 0x16, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0b[] = { + /* Vibraphone */ + { 0x15, 0x6c, { 0x101, 4778, 100, 0, 0, 0x00, 0xc0, 0x28, 0xf4, 0x14, 0x16, 0x4 }} +}; +static const YRW801_REGION_DATA regions_0c[] = { + /* Marimba */ + { 0x15, 0x3f, { 0x0f4, 4778, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x47, 0x08, 0x0 }}, + { 0x40, 0x4c, { 0x0f5, 3217, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x47, 0x08, 0x0 }}, + { 0x4d, 0x5a, { 0x0f5, 3217, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x48, 0x08, 0x0 }}, + { 0x5b, 0x7f, { 0x0f5, 3218, 100, 0, 0, 0x00, 0xc4, 0x38, 0xf7, 0x48, 0x18, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0d[] = { + /* Xylophone */ + { 0x00, 0x7f, { 0x136, 1729, 100, 0, 0, 0x00, 0xd2, 0x38, 0xf0, 0x06, 0x36, 0x0 }} +}; +static const YRW801_REGION_DATA regions_0e[] = { + /* Tubular Bell */ + { 0x01, 0x7f, { 0x0ff, 3999, 100, 0, 1, 0x00, 0x90, 0x21, 0xf4, 0xa3, 0x25, 0x1 }} +}; +static const YRW801_REGION_DATA regions_0f[] = { + /* Dulcimer */ + { 0x00, 0x7f, { 0x03f, 4236, 100, 0, 1, 0x00, 0xbc, 0x29, 0xf5, 0x16, 0x07, 0x0 }}, + { 0x00, 0x7f, { 0x040, 4236, 100, 0, 2, 0x0e, 0x94, 0x2a, 0xf5, 0x16, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_10[] = { + /* Drawbar Organ */ + { 0x01, 0x7f, { 0x08e, 4394, 100, 0, 2, 0x14, 0xc2, 0x3a, 0xf0, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_11[] = { + /* Percussive Organ */ + { 0x15, 0x3b, { 0x08c, 6062, 100, 0, 3, 0x00, 0xbe, 0x3b, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3c, 0x6c, { 0x08d, 2984, 100, 0, 3, 0x00, 0xbe, 0x3b, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_12[] = { + /* Rock Organ */ + { 0x15, 0x30, { 0x128, 6574, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x31, 0x3c, { 0x129, 5040, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x3d, 0x48, { 0x12a, 3498, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x49, 0x54, { 0x12b, 1957, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x55, 0x6c, { 0x127, 423, 100, 0, 1, 0x00, 0xcc, 0x39, 0xf0, 0x00, 0x0a, 0x0 } } +}; +static const YRW801_REGION_DATA regions_13[] = { + /* Church Organ */ + { 0x15, 0x29, { 0x087, 7466, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x2a, 0x30, { 0x088, 6456, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x31, 0x38, { 0x089, 5428, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x39, 0x41, { 0x08a, 4408, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x42, 0x6c, { 0x08b, 3406, 100, 0, 1, 0x00, 0xc4, 0x11, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_14[] = { + /* Reed Organ */ + { 0x00, 0x53, { 0x0ac, 5570, 100, 0, 0, 0x06, 0xc0, 0x38, 0xf0, 0x00, 0x09, 0x1 }}, + { 0x54, 0x7f, { 0x0ad, 2497, 100, 0, 0, 0x00, 0xc0, 0x38, 0xf0, 0x00, 0x09, 0x1 }} +}; +static const YRW801_REGION_DATA regions_15[] = { + /* Accordion */ + { 0x15, 0x4c, { 0x006, 4261, 100, 0, 2, 0x00, 0xa4, 0x22, 0x90, 0x00, 0x09, 0x0 }}, + { 0x4d, 0x6c, { 0x007, 1530, 100, 0, 2, 0x00, 0xa4, 0x22, 0x90, 0x00, 0x09, 0x0 }}, + { 0x15, 0x6c, { 0x070, 4391, 100, 0, 3, 0x00, 0x8a, 0x23, 0xa0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_16[] = { + /* Harmonica */ + { 0x15, 0x6c, { 0x070, 4408, 100, 0, 0, 0x00, 0xae, 0x30, 0xa0, 0x00, 0x09, 0x2 }} +}; +static const YRW801_REGION_DATA regions_17[] = { + /* Tango Accordion */ + { 0x00, 0x53, { 0x0ac, 5573, 100, 0, 0, 0x00, 0xae, 0x38, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x54, 0x7f, { 0x0ad, 2500, 100, 0, 0, 0x00, 0xae, 0x38, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x15, 0x6c, { 0x041, 8479, 100, 0, 2, 0x00, 0x6a, 0x3a, 0x75, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_18[] = { + /* Nylon Guitar */ + { 0x15, 0x2f, { 0x0b3, 6964, 100, 0, 0, 0x05, 0xca, 0x28, 0xf5, 0x34, 0x09, 0x0 }}, + { 0x30, 0x36, { 0x0b7, 5567, 100, 0, 0, 0x0c, 0xca, 0x28, 0xf5, 0x34, 0x09, 0x0 }}, + { 0x37, 0x3c, { 0x0b5, 4653, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }}, + { 0x3d, 0x43, { 0x0b4, 3892, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x35, 0x09, 0x0 }}, + { 0x44, 0x60, { 0x0b6, 2723, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x35, 0x19, 0x0 }} +}; +static const YRW801_REGION_DATA regions_19[] = { + /* Steel Guitar */ + { 0x15, 0x31, { 0x00c, 6937, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x04, 0x19, 0x0 }}, + { 0x32, 0x38, { 0x00d, 5410, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x05, 0x09, 0x0 }}, + { 0x39, 0x47, { 0x00e, 4379, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf5, 0x94, 0x09, 0x0 }}, + { 0x48, 0x6c, { 0x00f, 2843, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf6, 0x95, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1a[] = { + /* Jazz Guitar */ + { 0x15, 0x31, { 0x05a, 6832, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }}, + { 0x32, 0x3f, { 0x05b, 4897, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }}, + { 0x40, 0x6c, { 0x05c, 3218, 100, 0, 0, 0x00, 0xca, 0x28, 0xf6, 0x34, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1b[] = { + /* Clean Guitar */ + { 0x15, 0x2c, { 0x061, 7053, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x54, 0x0a, 0x0 }}, + { 0x2d, 0x31, { 0x060, 6434, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x54, 0x0a, 0x0 }}, + { 0x32, 0x38, { 0x063, 5764, 100, 0, 1, 0x00, 0xbe, 0x29, 0xf5, 0x55, 0x0a, 0x0 }}, + { 0x39, 0x3f, { 0x062, 4627, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x0a, 0x0 }}, + { 0x40, 0x44, { 0x065, 3963, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x1a, 0x0 }}, + { 0x45, 0x4b, { 0x064, 3313, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x1a, 0x0 }}, + { 0x4c, 0x54, { 0x066, 2462, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf5, 0x55, 0x2a, 0x0 }}, + { 0x55, 0x6c, { 0x067, 1307, 100, 0, 1, 0x00, 0xb4, 0x29, 0xf6, 0x56, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1c[] = { + /* Muted Guitar */ + { 0x01, 0x7f, { 0x068, 4408, 100, 0, 0, 0x00, 0xcc, 0x28, 0xf6, 0x15, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1d[] = { + /* Overdriven Guitar */ + { 0x00, 0x40, { 0x0a5, 6589, 100, 0, 1, 0x00, 0xc0, 0x29, 0xf2, 0x11, 0x09, 0x0 }}, + { 0x41, 0x7f, { 0x0a6, 5428, 100, 0, 1, 0x00, 0xc0, 0x29, 0xf2, 0x11, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1e[] = { + /* Distortion Guitar */ + { 0x15, 0x2a, { 0x051, 6928, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x2b, 0x2e, { 0x052, 6433, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x2f, 0x32, { 0x053, 5944, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x33, 0x36, { 0x054, 5391, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x37, 0x3a, { 0x055, 4897, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x3b, 0x3e, { 0x056, 4408, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x3f, 0x42, { 0x057, 3892, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x43, 0x46, { 0x058, 3361, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }}, + { 0x47, 0x6c, { 0x059, 2784, 100, 0, 1, 0x00, 0xbc, 0x21, 0xa2, 0x12, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_1f[] = { + /* Guitar Harmonics */ + { 0x15, 0x44, { 0x05e, 5499, 100, 0, 0, 0x00, 0xce, 0x28, 0xf4, 0x24, 0x09, 0x0 }}, + { 0x45, 0x49, { 0x05d, 4850, 100, 0, 0, 0x00, 0xe2, 0x28, 0xf4, 0x24, 0x09, 0x0 }}, + { 0x4a, 0x6c, { 0x05f, 4259, 100, 0, 0, 0x00, 0xce, 0x28, 0xf4, 0x24, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_20[] = { + /* Acoustic Bass */ + { 0x15, 0x30, { 0x004, 8053, 100, 0, 0, 0x00, 0xe2, 0x18, 0xf5, 0x15, 0x09, 0x0 }}, + { 0x31, 0x6c, { 0x005, 4754, 100, 0, 0, 0x00, 0xe2, 0x18, 0xf5, 0x15, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_21[] = { + /* Fingered Bass */ + { 0x01, 0x20, { 0x04a, 8762, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }}, + { 0x21, 0x25, { 0x04b, 8114, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }}, + { 0x26, 0x2a, { 0x04c, 7475, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }}, + { 0x2b, 0x7f, { 0x04d, 6841, 100, 0, 0, 0x00, 0xde, 0x18, 0xf6, 0x14, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_22[] = { + /* Picked Bass */ + { 0x15, 0x23, { 0x04f, 7954, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf3, 0x90, 0x0a, 0x0 }}, + { 0x24, 0x2a, { 0x050, 7318, 100, 0, 0, 0x05, 0xcc, 0x18, 0xf3, 0x90, 0x1a, 0x0 }}, + { 0x2b, 0x2f, { 0x06b, 6654, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf3, 0x90, 0x2a, 0x0 }}, + { 0x30, 0x47, { 0x069, 6031, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf5, 0xb0, 0x0a, 0x0 }}, + { 0x48, 0x6c, { 0x06a, 5393, 100, 0, 0, 0x00, 0xcc, 0x18, 0xf5, 0xb0, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_23[] = { + /* Fretless Bass */ + { 0x01, 0x7f, { 0x04e, 5297, 100, 0, 0, 0x00, 0xd2, 0x10, 0xf3, 0x63, 0x19, 0x0 }} +}; +static const YRW801_REGION_DATA regions_24[] = { + /* Slap Bass 1 */ + { 0x15, 0x6c, { 0x0a3, 7606, 100, 0, 1, 0x00, 0xde, 0x19, 0xf5, 0x32, 0x1a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_25[] = { + /* Slap Bass 2 */ + { 0x01, 0x7f, { 0x0a2, 6694, 100, 0, 0, 0x00, 0xda, 0x20, 0xb0, 0x02, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_26[] = { + /* Synth Bass 1 */ + { 0x15, 0x6c, { 0x0be, 7466, 100, 0, 1, 0x00, 0xb8, 0x39, 0xf4, 0x14, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_27[] = { + /* Synth Bass 2 */ + { 0x00, 0x7f, { 0x117, 8103, 100, 0, 1, 0x00, 0xca, 0x39, 0xf3, 0x50, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_28[] = { + /* Violin */ + { 0x15, 0x3a, { 0x105, 5158, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x3b, 0x3f, { 0x102, 4754, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x40, 0x41, { 0x106, 4132, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x42, 0x44, { 0x107, 4033, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x45, 0x47, { 0x108, 3580, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x48, 0x4a, { 0x10a, 2957, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4b, 0x4c, { 0x10b, 2724, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4d, 0x4e, { 0x10c, 2530, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4f, 0x51, { 0x10d, 2166, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x52, 0x6c, { 0x109, 1825, 100, 0, 3, 0x00, 0xcc, 0x3b, 0xf3, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_29[] = { + /* Viola */ + { 0x15, 0x32, { 0x103, 5780, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x33, 0x35, { 0x104, 5534, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x36, 0x38, { 0x105, 5158, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x39, 0x3d, { 0x102, 4754, 100, 0, 3, 0x00, 0xca, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x3e, 0x3f, { 0x106, 4132, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x40, 0x42, { 0x107, 4033, 100, 0, 3, 0x00, 0xc4, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x43, 0x45, { 0x108, 3580, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x46, 0x48, { 0x10a, 2957, 100, 0, 3, 0x00, 0xca, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x49, 0x4a, { 0x10b, 2724, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x4b, 0x4c, { 0x10c, 2530, 100, 0, 3, 0x00, 0xca, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x4d, 0x4f, { 0x10d, 2166, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }}, + { 0x50, 0x6c, { 0x109, 1825, 100, 0, 3, 0x00, 0xd0, 0x3b, 0xa3, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2a[] = { + /* Cello */ + { 0x15, 0x2d, { 0x112, 6545, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x08, 0x0 }}, + { 0x2e, 0x37, { 0x113, 5764, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x08, 0x0 }}, + { 0x38, 0x3e, { 0x115, 4378, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x18, 0x0 }}, + { 0x3f, 0x44, { 0x116, 3998, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x18, 0x0 }}, + { 0x45, 0x6c, { 0x114, 3218, 100, 0, 3, 0x00, 0xc0, 0x33, 0xa0, 0x00, 0x18, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2b[] = { + /* Contrabass */ + { 0x15, 0x29, { 0x110, 7713, 100, 0, 1, 0x00, 0xc2, 0x19, 0x90, 0x00, 0x09, 0x0 }}, + { 0x2a, 0x6c, { 0x111, 6162, 100, 0, 1, 0x00, 0xc2, 0x19, 0x90, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2c[] = { + /* Tremolo Strings */ + { 0x15, 0x3b, { 0x0b0, 4810, 100, 0, 0, 0x0a, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x3c, 0x41, { 0x035, 4035, 100, 0, 0, 0x05, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x42, 0x47, { 0x033, 3129, 100, 0, 0, 0x05, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x48, 0x52, { 0x034, 2625, 100, 0, 0, 0x05, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 }}, + { 0x53, 0x6c, { 0x0af, 936, 100, 0, 0, 0x00, 0xde, 0x38, 0xf0, 0x00, 0x07, 0x6 } } +}; +static const YRW801_REGION_DATA regions_2d[] = { + /* Pizzicato Strings */ + { 0x15, 0x32, { 0x0b8, 6186, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x33, 0x3b, { 0x0b9, 5031, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x3c, 0x42, { 0x0bb, 4146, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x43, 0x48, { 0x0ba, 3245, 100, 0, 0, 0x00, 0xc2, 0x28, 0xf0, 0x00, 0x05, 0x0 }}, + { 0x49, 0x6c, { 0x0bc, 2352, 100, 0, 0, 0x00, 0xbc, 0x28, 0xf0, 0x00, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2e[] = { + /* Harp */ + { 0x15, 0x46, { 0x07e, 3740, 100, 0, 1, 0x00, 0xd2, 0x29, 0xf5, 0x25, 0x07, 0x0 }}, + { 0x47, 0x6c, { 0x07f, 2319, 100, 0, 1, 0x00, 0xd2, 0x29, 0xf5, 0x25, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_2f[] = { + /* Timpani */ + { 0x15, 0x6c, { 0x100, 6570, 100, 0, 0, 0x00, 0xf8, 0x28, 0xf0, 0x05, 0x16, 0x0 }} +}; +static const YRW801_REGION_DATA regions_30[] = { + /* Strings */ + { 0x15, 0x3b, { 0x13c, 4806, 100, 0, 0, 0x00, 0xc8, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x3c, 0x41, { 0x13e, 4035, 100, 0, 0, 0x00, 0xc8, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x42, 0x47, { 0x13d, 3122, 100, 0, 0, 0x00, 0xc8, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x48, 0x52, { 0x13f, 2629, 100, 0, 0, 0x00, 0xbe, 0x20, 0x80, 0x00, 0x07, 0x0 }}, + { 0x53, 0x6c, { 0x140, 950, 100, 0, 0, 0x00, 0xbe, 0x20, 0x80, 0x00, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_31[] = { + /* Slow Strings */ + { 0x15, 0x3b, { 0x0b0, 4810, 100, 0, 1, 0x0a, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x3c, 0x41, { 0x035, 4035, 100, 0, 1, 0x05, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x42, 0x47, { 0x033, 3129, 100, 0, 1, 0x05, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x48, 0x52, { 0x034, 2625, 100, 0, 1, 0x05, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 }}, + { 0x53, 0x6c, { 0x0af, 936, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf0, 0x00, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_32[] = { + /* Synth Strings 1 */ + { 0x05, 0x71, { 0x002, 6045, 100, -2, 0, 0x00, 0xa6, 0x20, 0x93, 0x22, 0x06, 0x0 }}, + { 0x15, 0x6c, { 0x0ae, 3261, 100, 2, 0, 0x00, 0xc6, 0x20, 0x70, 0x01, 0x06, 0x0 } } +}; +static const YRW801_REGION_DATA regions_33[] = { + /* Synth Strings 2 */ + { 0x15, 0x6c, { 0x002, 4513, 100, 5, 1, 0x00, 0xb4, 0x19, 0x70, 0x00, 0x06, 0x0 } }, + { 0x15, 0x6c, { 0x002, 4501, 100, -5, 1, 0x00, 0xb4, 0x19, 0x70, 0x00, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_34[] = { + /* Choir Aahs */ + { 0x15, 0x3a, { 0x018, 5010, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }}, + { 0x3b, 0x40, { 0x019, 4370, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }}, + { 0x41, 0x47, { 0x01a, 3478, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }}, + { 0x48, 0x6c, { 0x01b, 2197, 100, 0, 2, 0x00, 0xc2, 0x1a, 0x70, 0x00, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_35[] = { + /* Voice Oohs */ + { 0x15, 0x6c, { 0x029, 3596, 100, 0, 0, 0x00, 0xe6, 0x20, 0xf7, 0x20, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_36[] = { + /* Synth Voice */ + { 0x15, 0x6c, { 0x02a, 3482, 100, 0, 1, 0x00, 0xc2, 0x19, 0x85, 0x21, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_37[] = { + /* Orchestra Hit */ + { 0x15, 0x6c, { 0x049, 4394, 100, 0, 0, 0x00, 0xfe, 0x30, 0x80, 0x05, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_38[] = { + /* Trumpet */ + { 0x15, 0x3c, { 0x0f6, 4706, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x3d, 0x43, { 0x0f8, 3894, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x44, 0x48, { 0x0f7, 3118, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x49, 0x4e, { 0x0fa, 2322, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x4f, 0x55, { 0x0f9, 1634, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x56, 0x6c, { 0x0fb, 786, 100, 0, 2, 0x00, 0xd6, 0x32, 0xf3, 0x20, 0x0a, 0x0 } } +}; +static const YRW801_REGION_DATA regions_39[] = { + /* Trombone */ + { 0x15, 0x3a, { 0x0f0, 5053, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3b, 0x3f, { 0x0f1, 4290, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x40, 0x6c, { 0x0f2, 3580, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3a[] = { + /* Tuba */ + { 0x15, 0x2d, { 0x085, 7096, 100, 0, 1, 0x00, 0xde, 0x21, 0xf5, 0x10, 0x09, 0x0 }}, + { 0x2e, 0x6c, { 0x086, 6014, 100, 0, 1, 0x00, 0xde, 0x21, 0xf5, 0x10, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3b[] = { + /* Muted Trumpet */ + { 0x15, 0x45, { 0x0b1, 4135, 100, 0, 0, 0x00, 0xcc, 0x28, 0xf3, 0x10, 0x0a, 0x1 }}, + { 0x46, 0x6c, { 0x0b2, 2599, 100, 0, 0, 0x00, 0xcc, 0x28, 0x83, 0x10, 0x0a, 0x1 }} +}; +static const YRW801_REGION_DATA regions_3c[] = { + /* French Horns */ + { 0x15, 0x49, { 0x07c, 3624, 100, 0, 2, 0x00, 0xd0, 0x1a, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x4a, 0x6c, { 0x07d, 2664, 100, 0, 2, 0x00, 0xd0, 0x1a, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3d[] = { + /* Brass Section */ + { 0x15, 0x42, { 0x0fc, 4375, 100, 0, 0, 0x00, 0xd6, 0x28, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x43, 0x6c, { 0x0fd, 2854, 100, 0, 0, 0x00, 0xd6, 0x28, 0xf0, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_3e[] = { + /* Synth Brass 1 */ + { 0x01, 0x27, { 0x0d3, 9094, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x0da, 8335, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x0d4, 7558, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x0db, 6785, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x0d5, 6042, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x0dc, 5257, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x0d6, 4493, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x4c, 0x51, { 0x0dd, 3741, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x52, 0x57, { 0x0d7, 3012, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x58, 0x5d, { 0x0de, 2167, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x5e, 0x63, { 0x0d8, 1421, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x64, 0x7f, { 0x0d9, -115, 100, -1, 0, 0x00, 0xbe, 0x18, 0xa5, 0x11, 0x08, 0x0 }}, + { 0x01, 0x27, { 0x118, 9103, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x28, 0x2d, { 0x119, 8340, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x2e, 0x33, { 0x11a, 7565, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x34, 0x39, { 0x11b, 6804, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x3a, 0x3f, { 0x11c, 6042, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x40, 0x45, { 0x11d, 5277, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x46, 0x4b, { 0x11e, 4520, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x4c, 0x51, { 0x11f, 3741, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x52, 0x57, { 0x120, 3012, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x58, 0x5d, { 0x121, 2166, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x5e, 0x64, { 0x122, 1421, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } }, + { 0x65, 0x7f, { 0x123, -115, 100, 1, 1, 0x00, 0xbe, 0x19, 0x85, 0x23, 0x08, 0x0 } } +}; +static const YRW801_REGION_DATA regions_3f[] = { + /* Synth Brass 2 */ + { 0x01, 0x27, { 0x118, 9113, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x28, 0x2d, { 0x119, 8350, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x2e, 0x33, { 0x11a, 7575, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x34, 0x39, { 0x11b, 6814, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x3a, 0x3f, { 0x11c, 6052, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x40, 0x45, { 0x11d, 5287, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x46, 0x4b, { 0x11e, 4530, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x4c, 0x51, { 0x11f, 3751, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x52, 0x57, { 0x120, 3022, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x58, 0x5d, { 0x121, 2176, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x5e, 0x64, { 0x122, 1431, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x65, 0x7f, { 0x123, -105, 100, 3, 6, 0x00, 0xae, 0x26, 0x85, 0x23, 0x08, 0x0 } }, + { 0x00, 0x7f, { 0x124, 4034, 100, -3, 2, 0x00, 0xea, 0x22, 0x85, 0x23, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_40[] = { + /* Soprano Sax */ + { 0x15, 0x3f, { 0x0e3, 4228, 100, 0, 1, 0x00, 0xc8, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x0e4, 3495, 100, 0, 1, 0x00, 0xc8, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x0e5, 2660, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x0e6, 2002, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x52, 0x59, { 0x0e7, 1186, 100, 0, 1, 0x00, 0xd6, 0x21, 0xf5, 0x20, 0x0a, 0x0 }}, + { 0x59, 0x6c, { 0x0e8, 1730, 100, 0, 1, 0x00, 0xc8, 0x21, 0xf5, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_41[] = { + /* Alto Sax */ + { 0x15, 0x32, { 0x092, 6204, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x33, 0x35, { 0x096, 5812, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x36, 0x3a, { 0x099, 5318, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x3b, 0x3b, { 0x08f, 5076, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x3c, 0x3e, { 0x093, 4706, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x3f, 0x41, { 0x097, 4321, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x42, 0x44, { 0x09a, 3893, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x45, 0x47, { 0x090, 3497, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x48, 0x4a, { 0x094, 3119, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x4b, 0x4d, { 0x098, 2726, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x4e, 0x50, { 0x09b, 2393, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x51, 0x53, { 0x091, 2088, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }}, + { 0x54, 0x6c, { 0x095, 1732, 100, 0, 1, 0x00, 0xbe, 0x19, 0xf5, 0x20, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_42[] = { + /* Tenor Sax */ + { 0x24, 0x30, { 0x0e9, 6301, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x31, 0x34, { 0x0ea, 5781, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x35, 0x3a, { 0x0eb, 5053, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x3b, 0x41, { 0x0ed, 4165, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x42, 0x47, { 0x0ec, 3218, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x48, 0x51, { 0x0ee, 2462, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }}, + { 0x52, 0x6c, { 0x0ef, 1421, 100, 0, 1, 0x00, 0xbc, 0x19, 0xf4, 0x10, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_43[] = { + /* Baritone Sax */ + { 0x15, 0x2d, { 0x0df, 6714, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x2e, 0x34, { 0x0e1, 5552, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x35, 0x39, { 0x0e2, 5178, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }}, + { 0x3a, 0x6c, { 0x0e0, 4437, 100, 0, 1, 0x00, 0xce, 0x19, 0xf0, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_44[] = { + /* Oboe */ + { 0x15, 0x3c, { 0x042, 4493, 100, 0, 1, 0x00, 0xe6, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x3d, 0x43, { 0x044, 3702, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x44, 0x49, { 0x043, 2956, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x4a, 0x4f, { 0x046, 2166, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x50, 0x55, { 0x045, 1420, 100, 0, 1, 0x00, 0xdc, 0x39, 0xf4, 0x10, 0x0a, 0x0 }}, + { 0x56, 0x6c, { 0x047, 630, 100, 0, 1, 0x00, 0xe6, 0x39, 0xf4, 0x10, 0x0a, 0x0 } } +}; +static const YRW801_REGION_DATA regions_45[] = { + /* English Horn */ + { 0x15, 0x38, { 0x03c, 5098, 100, 0, 1, 0x00, 0xc4, 0x31, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x39, 0x3e, { 0x03b, 4291, 100, 0, 1, 0x00, 0xc4, 0x31, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3f, 0x6c, { 0x03d, 3540, 100, 0, 1, 0x00, 0xc4, 0x31, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_46[] = { + /* Bassoon */ + { 0x15, 0x22, { 0x038, 7833, 100, 0, 1, 0x00, 0xc6, 0x31, 0xf0, 0x00, 0x0b, 0x0 }}, + { 0x23, 0x2e, { 0x03a, 7070, 100, 0, 1, 0x00, 0xc6, 0x31, 0xf0, 0x00, 0x0b, 0x0 }}, + { 0x2f, 0x6c, { 0x039, 6302, 100, 0, 1, 0x00, 0xc6, 0x31, 0xf0, 0x00, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_47[] = { + /* Clarinet */ + { 0x15, 0x3b, { 0x09e, 5900, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x3c, 0x41, { 0x0a0, 5158, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x42, 0x4a, { 0x09f, 4260, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }}, + { 0x4b, 0x6c, { 0x0a1, 2957, 100, 0, 1, 0x00, 0xc8, 0x29, 0xf3, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_48[] = { + /* Piccolo */ + { 0x15, 0x40, { 0x071, 4803, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x41, 0x4d, { 0x072, 3314, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x4e, 0x53, { 0x073, 1731, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x54, 0x5f, { 0x074, 2085, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x60, 0x6c, { 0x075, 1421, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }} +}; +static const YRW801_REGION_DATA regions_49[] = { + /* Flute */ + { 0x15, 0x40, { 0x071, 4803, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x41, 0x4d, { 0x072, 3314, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf0, 0x00, 0x0a, 0x2 }}, + { 0x4e, 0x6c, { 0x073, 1731, 100, 0, 0, 0x00, 0xe6, 0x38, 0xf0, 0x00, 0x0a, 0x2 }} +}; +static const YRW801_REGION_DATA regions_4a[] = { + /* Recorder */ + { 0x15, 0x6f, { 0x0bd, 4897, 100, 0, 0, 0x00, 0xec, 0x30, 0x70, 0x00, 0x09, 0x1 }} +}; +static const YRW801_REGION_DATA regions_4b[] = { + /* Pan Flute */ + { 0x15, 0x6c, { 0x077, 2359, 100, 0, 0, 0x00, 0xde, 0x38, 0xf0, 0x00, 0x09, 0x3 }} +}; +static const YRW801_REGION_DATA regions_4c[] = { + /* Bottle Blow */ + { 0x15, 0x6c, { 0x077, 2359, 100, 0, 0, 0x00, 0xc8, 0x38, 0xf0, 0x00, 0x09, 0x1 }}, + { 0x01, 0x7f, { 0x125, 7372, 100, 0, 0, 0x1e, 0x80, 0x00, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_4d[] = { + /* Shakuhachi */ + { 0x00, 0x7f, { 0x0ab, 4548, 100, 0, 0, 0x00, 0xd6, 0x30, 0xf0, 0x00, 0x0a, 0x3 }}, + { 0x15, 0x6c, { 0x076, 3716, 100, 0, 0, 0x00, 0xa2, 0x28, 0x70, 0x00, 0x09, 0x2 }} +}; +static const YRW801_REGION_DATA regions_4e[] = { + /* Whistle */ + { 0x00, 0x7f, { 0x0aa, 1731, 100, 0, 4, 0x00, 0xd2, 0x2c, 0x70, 0x00, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_4f[] = { + /* Ocarina */ + { 0x00, 0x7f, { 0x0aa, 1731, 100, 0, 1, 0x00, 0xce, 0x29, 0x90, 0x00, 0x0a, 0x1 }} +}; +static const YRW801_REGION_DATA regions_50[] = { + /* Square Lead */ + { 0x01, 0x2a, { 0x0cc, 9853, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x2b, 0x36, { 0x0cd, 6785, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x37, 0x42, { 0x0ca, 5248, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x43, 0x4e, { 0x0cf, 3713, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x4f, 0x5a, { 0x0ce, 2176, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x5b, 0x7f, { 0x0cb, 640, 100, 3, 0, 0x00, 0xac, 0x38, 0xc6, 0x21, 0x09, 0x0 } }, + { 0x01, 0x2a, { 0x0cc, 9844, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x2b, 0x36, { 0x0cd, 6776, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x37, 0x42, { 0x0ca, 5239, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x43, 0x4e, { 0x0cf, 3704, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x4f, 0x5a, { 0x0ce, 2167, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 }}, + { 0x5b, 0x7f, { 0x0cb, 631, 100, -3, 0, 0x00, 0xac, 0x08, 0xc6, 0x21, 0x09, 0x0 } } +}; +static const YRW801_REGION_DATA regions_51[] = { + /* Sawtooth Lead */ + { 0x01, 0x27, { 0x118, 9108, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8345, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7570, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6809, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6047, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5282, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4525, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3746, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x52, 0x57, { 0x120, 3017, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2171, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1426, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x67, 0x7f, { 0x123, -110, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x01, 0x27, { 0x118, 9098, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8335, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7560, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6799, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6037, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5272, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4515, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3736, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x52, 0x57, { 0x120, 3007, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2161, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1416, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }}, + { 0x67, 0x7f, { 0x123, -120, 100, 0, 0, 0x00, 0xc8, 0x30, 0xf2, 0x22, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_52[] = { + /* Calliope Lead */ + { 0x00, 0x7f, { 0x0aa, 1731, 100, 0, 0, 0x00, 0xc2, 0x28, 0x90, 0x00, 0x0a, 0x2 }}, + { 0x15, 0x6c, { 0x076, 3716, 100, 0, 0, 0x00, 0xb6, 0x28, 0xb0, 0x00, 0x09, 0x2 }} +}; +static const YRW801_REGION_DATA regions_53[] = { + /* Chiffer Lead */ + { 0x00, 0x7f, { 0x13a, 3665, 100, 0, 2, 0x00, 0xcc, 0x2a, 0xf0, 0x10, 0x09, 0x1 }}, + { 0x01, 0x7f, { 0x0fe, 3660, 100, 0, 0, 0x00, 0xbe, 0x28, 0xf3, 0x10, 0x17, 0x0 }} +}; +static const YRW801_REGION_DATA regions_54[] = { + /* Charang Lead */ + { 0x00, 0x40, { 0x0a5, 6594, 100, 0, 3, 0x00, 0xba, 0x33, 0xf2, 0x11, 0x09, 0x0 }}, + { 0x41, 0x7f, { 0x0a6, 5433, 100, 0, 3, 0x00, 0xba, 0x33, 0xf2, 0x11, 0x09, 0x0 }}, + { 0x01, 0x27, { 0x118, 9098, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8335, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7560, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6799, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6037, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5272, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4515, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3736, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x52, 0x57, { 0x120, 3007, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2161, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1416, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }}, + { 0x67, 0x7f, { 0x123, -120, 100, 0, 2, 0x00, 0xa4, 0x2a, 0xf2, 0x22, 0x0e, 0x0 }} +}; +static const YRW801_REGION_DATA regions_55[] = { + /* Voice Lead */ + { 0x00, 0x7f, { 0x0aa, 1739, 100, 0, 6, 0x00, 0x8c, 0x2e, 0x90, 0x00, 0x0a, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3474, 100, 0, 1, 0x00, 0xd8, 0x29, 0xf0, 0x05, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_56[] = { + /* 5ths Lead */ + { 0x01, 0x27, { 0x118, 8468, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x28, 0x2d, { 0x119, 7705, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 6930, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6169, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 5407, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x40, 0x45, { 0x11d, 4642, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 3885, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3106, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x52, 0x57, { 0x120, 2377, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x58, 0x5d, { 0x121, 1531, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x5e, 0x64, { 0x122, 786, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 } }, + { 0x65, 0x7f, { 0x123, -750, 100, 0, 2, 0x00, 0xd0, 0x32, 0xf5, 0x20, 0x08, 0x0 }}, + { 0x05, 0x71, { 0x002, 4503, 100, 0, 1, 0x00, 0xb8, 0x31, 0xb3, 0x20, 0x0b, 0x0 }} +}; +static const YRW801_REGION_DATA regions_57[] = { + /* Bass & Lead */ + { 0x00, 0x7f, { 0x117, 8109, 100, 0, 1, 0x00, 0xbc, 0x29, 0xf3, 0x50, 0x08, 0x0 }}, + { 0x01, 0x27, { 0x118, 9097, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x28, 0x2d, { 0x119, 8334, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x2e, 0x33, { 0x11a, 7559, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x34, 0x39, { 0x11b, 6798, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x3a, 0x3f, { 0x11c, 6036, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x40, 0x45, { 0x11d, 5271, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x46, 0x4b, { 0x11e, 4514, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x4c, 0x51, { 0x11f, 3735, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x52, 0x57, { 0x120, 3006, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x58, 0x5d, { 0x121, 2160, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x5e, 0x66, { 0x122, 1415, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }}, + { 0x67, 0x7f, { 0x123, -121, 100, 0, 2, 0x00, 0xbc, 0x2a, 0xf2, 0x20, 0x0a, 0x0 }} +}; +static const YRW801_REGION_DATA regions_58[] = { + /* New Age Pad */ + { 0x15, 0x6c, { 0x002, 4501, 100, 0, 4, 0x00, 0xa4, 0x24, 0x80, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x0f3, 4253, 100, 0, 3, 0x00, 0x8c, 0x23, 0xa2, 0x14, 0x06, 0x1 }} +}; +static const YRW801_REGION_DATA regions_59[] = { + /* Warm Pad */ + { 0x15, 0x6c, { 0x04e, 5306, 100, 2, 2, 0x00, 0x92, 0x2a, 0x34, 0x23, 0x05, 0x2 } }, + { 0x15, 0x6c, { 0x029, 3575, 100, -2, 2, 0x00, 0xbe, 0x22, 0x31, 0x23, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5a[] = { + /* Polysynth Pad */ + { 0x01, 0x27, { 0x118, 9111, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x28, 0x2d, { 0x119, 8348, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x2e, 0x33, { 0x11a, 7573, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x34, 0x39, { 0x11b, 6812, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x3a, 0x3f, { 0x11c, 6050, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x40, 0x45, { 0x11d, 5285, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x46, 0x4b, { 0x11e, 4528, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x4c, 0x51, { 0x11f, 3749, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x52, 0x57, { 0x120, 3020, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x58, 0x5d, { 0x121, 2174, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x5e, 0x66, { 0x122, 1429, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x67, 0x7f, { 0x123, -107, 100, 0, 3, 0x00, 0xae, 0x23, 0xf2, 0x20, 0x07, 0x1 }}, + { 0x00, 0x7f, { 0x124, 4024, 100, 0, 2, 0x00, 0xae, 0x22, 0xe5, 0x20, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5b[] = { + /* Choir Pad */ + { 0x15, 0x3a, { 0x018, 5010, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x3b, 0x40, { 0x019, 4370, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x41, 0x47, { 0x01a, 3478, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x48, 0x6c, { 0x01b, 2197, 100, 0, 5, 0x00, 0xb0, 0x25, 0x70, 0x00, 0x06, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3482, 100, 0, 4, 0x00, 0x98, 0x24, 0x65, 0x21, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5c[] = { + /* Bowed Pad */ + { 0x15, 0x6c, { 0x101, 4790, 100, -1, 1, 0x00, 0xbe, 0x19, 0x44, 0x14, 0x16, 0x0 }}, + { 0x00, 0x7f, { 0x0aa, 1720, 100, 1, 1, 0x00, 0x94, 0x19, 0x40, 0x00, 0x06, 0x0 } } +}; +static const YRW801_REGION_DATA regions_5d[] = { + /* Metallic Pad */ + { 0x15, 0x31, { 0x00c, 6943, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x32, 0x38, { 0x00d, 5416, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x39, 0x47, { 0x00e, 4385, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x48, 0x6c, { 0x00f, 2849, 100, 0, 2, 0x00, 0xa0, 0x0a, 0x60, 0x03, 0x06, 0x0 }}, + { 0x00, 0x7f, { 0x03f, 4224, 100, 0, 1, 0x00, 0x9c, 0x31, 0x65, 0x16, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5e[] = { + /* Halo Pad */ + { 0x00, 0x7f, { 0x124, 4038, 100, 0, 2, 0x00, 0xa6, 0x1a, 0x85, 0x23, 0x08, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3471, 100, 0, 3, 0x00, 0xc0, 0x1b, 0xc0, 0x05, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_5f[] = { + /* Sweep Pad */ + { 0x01, 0x27, { 0x0d3, 9100, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x28, 0x2d, { 0x0da, 8341, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x2e, 0x33, { 0x0d4, 7564, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x34, 0x39, { 0x0db, 6791, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x3a, 0x3f, { 0x0d5, 6048, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x40, 0x45, { 0x0dc, 5263, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x46, 0x4b, { 0x0d6, 4499, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x4c, 0x51, { 0x0dd, 3747, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x52, 0x57, { 0x0d7, 3018, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x58, 0x5d, { 0x0de, 2173, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x5e, 0x63, { 0x0d8, 1427, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x64, 0x7f, { 0x0d9, -109, 100, 0, 1, 0x00, 0xce, 0x19, 0x13, 0x11, 0x06, 0x0 }}, + { 0x01, 0x27, { 0x0d3, 9088, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x28, 0x2d, { 0x0da, 8329, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x2e, 0x33, { 0x0d4, 7552, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x34, 0x39, { 0x0db, 6779, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x3a, 0x3f, { 0x0d5, 6036, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x40, 0x45, { 0x0dc, 5251, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x46, 0x4b, { 0x0d6, 4487, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x4c, 0x51, { 0x0dd, 3735, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x52, 0x57, { 0x0d7, 3006, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x58, 0x5d, { 0x0de, 2161, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x5e, 0x63, { 0x0d8, 1415, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }}, + { 0x64, 0x7f, { 0x0d9, -121, 100, 0, 0, 0x00, 0xce, 0x18, 0x13, 0x11, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_60[] = { + /* Ice Rain */ + { 0x01, 0x7f, { 0x04e, 9345, 100, 0, 2, 0x00, 0xcc, 0x22, 0xa3, 0x63, 0x17, 0x0 }}, + { 0x00, 0x7f, { 0x143, 5586, 20, 0, 2, 0x00, 0x6e, 0x2a, 0xf0, 0x05, 0x05, 0x0 } } +}; +static const YRW801_REGION_DATA regions_61[] = { + /* Soundtrack */ + { 0x15, 0x6c, { 0x002, 4501, 100, 0, 2, 0x00, 0xb6, 0x2a, 0x60, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x0f3, 1160, 100, 0, 5, 0x00, 0xa8, 0x2d, 0x52, 0x14, 0x06, 0x2 }} +}; +static const YRW801_REGION_DATA regions_62[] = { + /* Crystal */ + { 0x15, 0x6c, { 0x0f3, 1826, 100, 0, 3, 0x00, 0xb8, 0x33, 0xf6, 0x25, 0x25, 0x0 }}, + { 0x15, 0x2c, { 0x06d, 7454, 100, 0, 3, 0x00, 0xac, 0x3b, 0x85, 0x24, 0x06, 0x0 }}, + { 0x2d, 0x36, { 0x06e, 5925, 100, 0, 3, 0x00, 0xac, 0x3b, 0x85, 0x24, 0x06, 0x0 }}, + { 0x37, 0x6c, { 0x06f, 4403, 100, 0, 3, 0x09, 0xac, 0x3b, 0x85, 0x24, 0x06, 0x0 }} +}; +static const YRW801_REGION_DATA regions_63[] = { + /* Atmosphere */ + { 0x05, 0x71, { 0x002, 4509, 100, 0, 2, 0x00, 0xc8, 0x32, 0x73, 0x22, 0x06, 0x1 }}, + { 0x15, 0x2f, { 0x0b3, 6964, 100, 0, 2, 0x05, 0xc2, 0x32, 0xf5, 0x34, 0x07, 0x2 }}, + { 0x30, 0x36, { 0x0b7, 5567, 100, 0, 2, 0x0c, 0xc2, 0x32, 0xf5, 0x34, 0x07, 0x2 }}, + { 0x37, 0x3c, { 0x0b5, 4653, 100, 0, 2, 0x00, 0xc2, 0x32, 0xf6, 0x34, 0x07, 0x2 }}, + { 0x3d, 0x43, { 0x0b4, 3892, 100, 0, 2, 0x00, 0xc2, 0x32, 0xf6, 0x35, 0x07, 0x2 }}, + { 0x44, 0x60, { 0x0b6, 2723, 100, 0, 2, 0x00, 0xc2, 0x32, 0xf6, 0x35, 0x17, 0x2 }} +}; +static const YRW801_REGION_DATA regions_64[] = { + /* Brightness */ + { 0x00, 0x7f, { 0x137, 5285, 100, 0, 2, 0x00, 0xbe, 0x2a, 0xa5, 0x18, 0x08, 0x0 }}, + { 0x15, 0x6c, { 0x02a, 3481, 100, 0, 1, 0x00, 0xc8, 0x29, 0x80, 0x05, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_65[] = { + /* Goblins */ + { 0x15, 0x6c, { 0x002, 4501, 100, -1, 2, 0x00, 0xca, 0x2a, 0x40, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x009, 9679, 20, 1, 4, 0x00, 0x3c, 0x0c, 0x22, 0x11, 0x06, 0x0 } } +}; +static const YRW801_REGION_DATA regions_66[] = { + /* Echoes */ + { 0x15, 0x6c, { 0x02a, 3487, 100, 0, 3, 0x00, 0xae, 0x2b, 0xf5, 0x21, 0x06, 0x0 }}, + { 0x00, 0x7f, { 0x124, 4027, 100, 0, 3, 0x00, 0xae, 0x2b, 0x85, 0x23, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_67[] = { + /* Sci-Fi */ + { 0x15, 0x31, { 0x00c, 6940, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x32, 0x38, { 0x00d, 5413, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x39, 0x47, { 0x00e, 4382, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x48, 0x6c, { 0x00f, 2846, 100, 0, 3, 0x00, 0xc8, 0x2b, 0x90, 0x05, 0x06, 0x3 }}, + { 0x15, 0x6c, { 0x002, 4498, 100, 0, 2, 0x00, 0xd4, 0x22, 0x80, 0x01, 0x05, 0x0 }} +}; +static const YRW801_REGION_DATA regions_68[] = { + /* Sitar */ + { 0x00, 0x7f, { 0x10f, 4408, 100, 0, 2, 0x00, 0xc4, 0x32, 0xf4, 0x15, 0x16, 0x1 }} +}; +static const YRW801_REGION_DATA regions_69[] = { + /* Banjo */ + { 0x15, 0x34, { 0x013, 5685, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x35, 0x38, { 0x014, 5009, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x39, 0x3c, { 0x012, 4520, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x3d, 0x44, { 0x015, 3622, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x45, 0x4c, { 0x017, 2661, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }}, + { 0x4d, 0x6d, { 0x016, 1632, 100, 0, 0, 0x00, 0xdc, 0x38, 0xf6, 0x15, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6a[] = { + /* Shamisen */ + { 0x15, 0x6c, { 0x10e, 3273, 100, 0, 0, 0x00, 0xc0, 0x28, 0xf7, 0x76, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6b[] = { + /* Koto */ + { 0x00, 0x7f, { 0x0a9, 4033, 100, 0, 0, 0x00, 0xc6, 0x20, 0xf0, 0x06, 0x07, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6c[] = { + /* Kalimba */ + { 0x00, 0x7f, { 0x137, 3749, 100, 0, 0, 0x00, 0xce, 0x38, 0xf5, 0x18, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6d[] = { + /* Bagpipe */ + { 0x15, 0x39, { 0x0a4, 7683, 100, 0, 4, 0x00, 0xc0, 0x1c, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x15, 0x39, { 0x0a7, 7680, 100, 0, 1, 0x00, 0xaa, 0x19, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3a, 0x6c, { 0x0a8, 3697, 100, 0, 1, 0x00, 0xaa, 0x19, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6e[] = { + /* Fiddle */ + { 0x15, 0x3a, { 0x105, 5158, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x3b, 0x3f, { 0x102, 4754, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x40, 0x41, { 0x106, 4132, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x42, 0x44, { 0x107, 4033, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x45, 0x47, { 0x108, 3580, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x48, 0x4a, { 0x10a, 2957, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4b, 0x4c, { 0x10b, 2724, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4d, 0x4e, { 0x10c, 2530, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x4f, 0x51, { 0x10d, 2166, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }}, + { 0x52, 0x6c, { 0x109, 1825, 100, 0, 1, 0x00, 0xca, 0x31, 0xf3, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_6f[] = { + /* Shanai */ + { 0x15, 0x6c, { 0x041, 6946, 100, 0, 1, 0x00, 0xc4, 0x31, 0x95, 0x20, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_70[] = { + /* Tinkle Bell */ + { 0x15, 0x73, { 0x0f3, 1821, 100, 0, 3, 0x00, 0xc8, 0x3b, 0xd6, 0x25, 0x25, 0x0 }}, + { 0x00, 0x7f, { 0x137, 5669, 100, 0, 3, 0x00, 0x66, 0x3b, 0xf5, 0x18, 0x08, 0x0 }} +}; +static const YRW801_REGION_DATA regions_71[] = { + /* Agogo */ + { 0x15, 0x74, { 0x00b, 2474, 100, 0, 0, 0x00, 0xd2, 0x38, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_72[] = { + /* Steel Drums */ + { 0x01, 0x7f, { 0x0fe, 3670, 100, 0, 0, 0x00, 0xca, 0x38, 0xf3, 0x06, 0x17, 0x1 }}, + { 0x15, 0x6c, { 0x100, 9602, 100, 0, 0, 0x00, 0x54, 0x38, 0xb0, 0x05, 0x16, 0x1 }} +}; +static const YRW801_REGION_DATA regions_73[] = { + /* Woodblock */ + { 0x15, 0x6c, { 0x02c, 2963, 50, 0, 0, 0x07, 0xd4, 0x00, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_74[] = { + /* Taiko Drum */ + { 0x13, 0x6c, { 0x03e, 1194, 50, 0, 0, 0x00, 0xaa, 0x38, 0xf0, 0x04, 0x04, 0x0 }} +}; +static const YRW801_REGION_DATA regions_75[] = { + /* Melodic Tom */ + { 0x15, 0x6c, { 0x0c7, 6418, 50, 0, 0, 0x00, 0xe4, 0x38, 0xf0, 0x05, 0x01, 0x0 }} +}; +static const YRW801_REGION_DATA regions_76[] = { + /* Synth Drum */ + { 0x15, 0x6c, { 0x026, 3898, 50, 0, 0, 0x00, 0xd0, 0x38, 0xf0, 0x04, 0x04, 0x0 }} +}; +static const YRW801_REGION_DATA regions_77[] = { + /* Reverse Cymbal */ + { 0x15, 0x6c, { 0x031, 4138, 50, 0, 0, 0x00, 0xfe, 0x38, 0x3a, 0xf0, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_78[] = { + /* Guitar Fret Noise */ + { 0x15, 0x6c, { 0x138, 5266, 100, 0, 0, 0x00, 0xa0, 0x38, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_79[] = { + /* Breath Noise */ + { 0x01, 0x7f, { 0x125, 4269, 100, 0, 0, 0x1e, 0xd0, 0x38, 0xf0, 0x00, 0x09, 0x0 }} +}; +static const YRW801_REGION_DATA regions_7a[] = { + /* Seashore */ + { 0x15, 0x6c, { 0x008, 2965, 20, -2, 0, 0x00, 0xfe, 0x00, 0x20, 0x03, 0x04, 0x0 }}, + { 0x01, 0x7f, { 0x037, 4394, 20, 2, 0, 0x14, 0xfe, 0x00, 0x20, 0x04, 0x05, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7b[] = { + /* Bird Tweet */ + { 0x15, 0x6c, { 0x009, 8078, 5, -4, 7, 0x00, 0xc2, 0x0f, 0x22, 0x12, 0x07, 0x0 }}, + { 0x15, 0x6c, { 0x009, 3583, 5, 4, 5, 0x00, 0xae, 0x15, 0x72, 0x12, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7c[] = { + /* Telephone Ring */ + { 0x15, 0x6c, { 0x003, 3602, 10, 0, 0, 0x00, 0xce, 0x00, 0xf0, 0x00, 0x0f, 0x0 }} +}; +static const YRW801_REGION_DATA regions_7d[] = { + /* Helicopter */ + { 0x0c, 0x7f, { 0x001, 2965, 10, -2, 0, 0x00, 0xe0, 0x08, 0x30, 0x01, 0x07, 0x0 }}, + { 0x01, 0x7f, { 0x037, 4394, 10, 2, 0, 0x44, 0x76, 0x00, 0x30, 0x01, 0x07, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7e[] = { + /* Applause */ + { 0x15, 0x6c, { 0x036, 8273, 20, -6, 7, 0x00, 0xc4, 0x0f, 0x70, 0x01, 0x05, 0x0 }}, + { 0x15, 0x6c, { 0x036, 8115, 5, 6, 7, 0x00, 0xc6, 0x07, 0x70, 0x01, 0x05, 0x0 } } +}; +static const YRW801_REGION_DATA regions_7f[] = { + /* Gun Shot */ + { 0x15, 0x6c, { 0x139, 2858, 20, 0, 0, 0x00, 0xbe, 0x38, 0xf0, 0x03, 0x00, 0x0 }} +}; +static const YRW801_REGION_DATA regions_drums[] = { + { 0x18, 0x18, { 0x0cb, 6397, 100, 3, 0, 0x00, 0xf4, 0x38, 0xc9, 0x1c, 0x0c, 0x0 } }, + { 0x19, 0x19, { 0x0c4, 3714, 100, 0, 0, 0x00, 0xe0, 0x00, 0x97, 0x19, 0x09, 0x0 } }, + { 0x1a, 0x1a, { 0x0c4, 3519, 100, 0, 0, 0x00, 0xea, 0x00, 0x61, 0x01, 0x07, 0x0 } }, + { 0x1b, 0x1b, { 0x0c4, 3586, 100, 0, 0, 0x00, 0xea, 0x00, 0xf7, 0x19, 0x09, 0x0 } }, + { 0x1c, 0x1c, { 0x0c4, 3586, 100, 0, 0, 0x00, 0xea, 0x00, 0x81, 0x01, 0x07, 0x0 } }, + { 0x1e, 0x1e, { 0x0c3, 4783, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x1f, 0x1f, { 0x0d1, 4042, 100, 0, 0, 0x00, 0xd6, 0x00, 0xf0, 0x05, 0x05, 0x0 } }, + { 0x20, 0x20, { 0x0d2, 5943, 100, 0, 0, 0x00, 0xcc, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x21, 0x21, { 0x011, 3842, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x16, 0x06, 0x0 } }, + { 0x23, 0x23, { 0x011, 4098, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x16, 0x06, 0x0 } }, + { 0x24, 0x24, { 0x011, 4370, 100, 0, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x06, 0x0 } }, + { 0x25, 0x25, { 0x0d2, 4404, 100, 0, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x06, 0x0 } }, + { 0x26, 0x26, { 0x0d1, 4298, 100, 0, 0, 0x00, 0xd6, 0x00, 0xf0, 0x05, 0x05, 0x0 } }, + { 0x27, 0x27, { 0x00a, 4403, 100, -1, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x28, 0x28, { 0x0d1, 4554, 100, 0, 0, 0x00, 0xdc, 0x00, 0xf0, 0x07, 0x07, 0x0 } }, + { 0x29, 0x29, { 0x0c8, 4242, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf6, 0x16, 0x06, 0x0 }}, + { 0x2a, 0x2a, { 0x079, 6160, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf5, 0x19, 0x09, 0x0 } }, + { 0x2b, 0x2b, { 0x0c8, 4626, 100, -3, 0, 0x00, 0xd6, 0x00, 0xf6, 0x16, 0x06, 0x0 }}, + { 0x2c, 0x2c, { 0x07b, 6039, 100, 2, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x2d, 0x2d, { 0x0c8, 5394, 100, -2, 0, 0x00, 0xd6, 0x00, 0xf6, 0x16, 0x06, 0x0 }}, + { 0x2e, 0x2e, { 0x07a, 5690, 100, 2, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x05, 0x0 } }, + { 0x2f, 0x2f, { 0x0c7, 5185, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf6, 0x17, 0x07, 0x0 } }, + { 0x30, 0x30, { 0x0c7, 5650, 100, 3, 0, 0x00, 0xe0, 0x00, 0xf6, 0x17, 0x07, 0x0 } }, + { 0x31, 0x31, { 0x031, 4395, 100, 2, 0, 0x00, 0xea, 0x00, 0xf0, 0x05, 0x05, 0x0 } }, + { 0x32, 0x32, { 0x0c7, 6162, 100, 4, 0, 0x00, 0xe0, 0x00, 0xf6, 0x17, 0x07, 0x0 } }, + { 0x33, 0x33, { 0x02e, 4391, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x05, 0x05, 0x0 }}, + { 0x34, 0x34, { 0x07a, 3009, 100, -2, 0, 0x00, 0xea, 0x00, 0xf2, 0x15, 0x05, 0x0 }}, + { 0x35, 0x35, { 0x021, 4522, 100, -3, 0, 0x00, 0xd6, 0x00, 0xf0, 0x05, 0x05, 0x0 }}, + { 0x36, 0x36, { 0x025, 5163, 100, 1, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x37, 0x37, { 0x031, 5287, 100, -1, 0, 0x00, 0xea, 0x00, 0xf5, 0x16, 0x06, 0x0 }}, + { 0x38, 0x38, { 0x01d, 4395, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x39, 0x39, { 0x031, 4647, 100, -2, 0, 0x00, 0xea, 0x00, 0xf4, 0x16, 0x06, 0x0 }}, + { 0x3a, 0x3a, { 0x09d, 4426, 100, -4, 0, 0x00, 0xe0, 0x00, 0xf4, 0x17, 0x07, 0x0 }}, + { 0x3b, 0x3b, { 0x02e, 4659, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x06, 0x06, 0x0 }}, + { 0x3c, 0x3c, { 0x01c, 4769, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x3d, 0x3d, { 0x01c, 4611, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x3e, 0x3e, { 0x01e, 4402, 100, -3, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x3f, 0x3f, { 0x01f, 4387, 100, -3, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x40, 0x40, { 0x01f, 3983, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x41, 0x41, { 0x09c, 4526, 100, 2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x42, 0x42, { 0x09c, 4016, 100, 2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x43, 0x43, { 0x00b, 4739, 100, -4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x44, 0x44, { 0x00b, 4179, 100, -4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x45, 0x45, { 0x02f, 4787, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x46, 0x46, { 0x030, 4665, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x47, 0x47, { 0x144, 4519, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x0b, 0x0 } }, + { 0x48, 0x48, { 0x144, 4111, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x0b, 0x0 } }, + { 0x49, 0x49, { 0x024, 6408, 100, 3, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4a, 0x4a, { 0x024, 4144, 100, 3, 0, 0x00, 0xcc, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4b, 0x4b, { 0x020, 4001, 100, 2, 0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4c, 0x4c, { 0x02c, 4402, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4d, 0x4d, { 0x02c, 3612, 100, 4, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 } }, + { 0x4e, 0x4e, { 0x022, 4129, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x4f, 0x4f, { 0x023, 4147, 100, -2, 0, 0x00, 0xea, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x50, 0x50, { 0x032, 4412, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x08, 0x09, 0x0 }}, + { 0x51, 0x51, { 0x032, 4385, 100, -4, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }}, + { 0x52, 0x52, { 0x02f, 5935, 100, -1, 0, 0x00, 0xd6, 0x00, 0xf0, 0x00, 0x09, 0x0 }} +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#define REGION(num) \ + { \ + ARRAY_SIZE(regions##num), regions##num \ + } +const YRW801_REGION_DATA_PTR snd_yrw801_regions[0x81] = { + REGION(_00), REGION(_01), REGION(_02), REGION(_03), + REGION(_04), REGION(_05), REGION(_06), REGION(_07), + REGION(_08), REGION(_09), REGION(_0a), REGION(_0b), + REGION(_0c), REGION(_0d), REGION(_0e), REGION(_0f), + REGION(_10), REGION(_11), REGION(_12), REGION(_13), + REGION(_14), REGION(_15), REGION(_16), REGION(_17), + REGION(_18), REGION(_19), REGION(_1a), REGION(_1b), + REGION(_1c), REGION(_1d), REGION(_1e), REGION(_1f), + REGION(_20), REGION(_21), REGION(_22), REGION(_23), + REGION(_24), REGION(_25), REGION(_26), REGION(_27), + REGION(_28), REGION(_29), REGION(_2a), REGION(_2b), + REGION(_2c), REGION(_2d), REGION(_2e), REGION(_2f), + REGION(_30), REGION(_31), REGION(_32), REGION(_33), + REGION(_34), REGION(_35), REGION(_36), REGION(_37), + REGION(_38), REGION(_39), REGION(_3a), REGION(_3b), + REGION(_3c), REGION(_3d), REGION(_3e), REGION(_3f), + REGION(_40), REGION(_41), REGION(_42), REGION(_43), + REGION(_44), REGION(_45), REGION(_46), REGION(_47), + REGION(_48), REGION(_49), REGION(_4a), REGION(_4b), + REGION(_4c), REGION(_4d), REGION(_4e), REGION(_4f), + REGION(_50), REGION(_51), REGION(_52), REGION(_53), + REGION(_54), REGION(_55), REGION(_56), REGION(_57), + REGION(_58), REGION(_59), REGION(_5a), REGION(_5b), + REGION(_5c), REGION(_5d), REGION(_5e), REGION(_5f), + REGION(_60), REGION(_61), REGION(_62), REGION(_63), + REGION(_64), REGION(_65), REGION(_66), REGION(_67), + REGION(_68), REGION(_69), REGION(_6a), REGION(_6b), + REGION(_6c), REGION(_6d), REGION(_6e), REGION(_6f), + REGION(_70), REGION(_71), REGION(_72), REGION(_73), + REGION(_74), REGION(_75), REGION(_76), REGION(_77), + REGION(_78), REGION(_79), REGION(_7a), REGION(_7b), + REGION(_7c), REGION(_7d), REGION(_7e), REGION(_7f), + REGION(_drums) +}; \ No newline at end of file diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 3c0d22131..ee761e627 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -1622,4 +1622,5 @@ const fm_drv_t nuked_opl_drv = { &nuked_drv_reset_buffer, &nuked_drv_set_do_cycles, NULL, + NULL, }; \ No newline at end of file diff --git a/src/sound/snd_opl_ymfm.cpp b/src/sound/snd_opl_ymfm.cpp index bb52f3c55..b2466dcb5 100644 --- a/src/sound/snd_opl_ymfm.cpp +++ b/src/sound/snd_opl_ymfm.cpp @@ -368,6 +368,13 @@ ymfm_drv_set_do_cycles(void *priv, int8_t do_cycles) drv->set_do_cycles(do_cycles); } +static void +ymfm_drv_generate(void *priv, int32_t *data, uint32_t num_samples) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + drv->generate_resampled(data, num_samples); +} + const device_t ym3812_ymfm_device = { .name = "Yamaha YM3812 OPL2 (YMFM)", .internal_name = "ym3812_ymfm", @@ -431,5 +438,6 @@ const fm_drv_t ymfm_drv { &ymfm_drv_reset_buffer, &ymfm_drv_set_do_cycles, NULL, + ymfm_drv_generate, }; } diff --git a/src/sound/yrw801.h b/src/sound/yrw801.h new file mode 100644 index 000000000..0df3c0343 --- /dev/null +++ b/src/sound/yrw801.h @@ -0,0 +1,45 @@ +/* + * RoboPlay for MSX + * Copyright (C) 2022 by RoboSoft Inc. + * + * yrw801.h + */ + +/* Cacodemon345: Added pointer structs from Linux */ + +#pragma once + +#include + +typedef struct +{ + uint16_t tone; + int16_t pitch_offset; + uint8_t key_scaling; + int8_t panpot; + uint8_t vibrato; + uint8_t tone_attenuate; + uint8_t volume_factor; + uint8_t reg_lfo_vibrato; + uint8_t reg_attack_decay1; + uint8_t reg_level_decay2; + uint8_t reg_release_correction; + uint8_t reg_tremolo; +} YRW801_WAVE_DATA; + +typedef struct +{ + uint8_t key_min; + uint8_t key_max; + + YRW801_WAVE_DATA wave_data; +} YRW801_REGION_DATA; + +typedef struct +{ + int count; + + const YRW801_REGION_DATA* regions; +} YRW801_REGION_DATA_PTR; + +extern const YRW801_REGION_DATA_PTR snd_yrw801_regions[0x81]; \ No newline at end of file From 4445f1f108d2fa26498ab8a9212dacb584866347 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 27 Nov 2022 21:24:17 +0600 Subject: [PATCH 011/133] Fix OPL4 audio crackling --- src/sound/midi_opl4.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index f816cff49..b75ac23b5 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -269,12 +269,15 @@ static const uint8_t g_volume_table[128] = { 2, 2, 2, 1, 1, 0, 0, 0 }; +#define BUFFER_SEGMENTS 10 +#define RENDER_RATE (48000 / 100) + typedef struct opl4_midi { fm_drv_t opl4; MIDI_CHANNEL_DATA midi_channel_data[16]; VOICE_DATA voice_data[24]; - int16_t buffer[SOUNDBUFLEN * 2]; - float buffer_float[SOUNDBUFLEN * 2]; + int16_t buffer[(48000 / 100) * 2 * BUFFER_SEGMENTS]; + float buffer_float[(48000 / 100) * 2 * BUFFER_SEGMENTS]; uint32_t midi_pos; bool on; atomic_bool gen_in_progress; @@ -537,13 +540,14 @@ program_change(uint8_t midi_channel, uint8_t program, opl4_midi_t *opl4_midi) opl4_midi->midi_channel_data[midi_channel].instrument = program; } -#define RENDER_RATE (48000 / 100) static void opl4_midi_thread(void *arg) { opl4_midi_t *opl4_midi = opl4_midi_cur; uint32_t i = 0; uint32_t buf_size = RENDER_RATE * 2; + uint32_t buf_size_segments = buf_size * BUFFER_SEGMENTS; + uint32_t buf_pos = 0; int32_t buffer[RENDER_RATE * 2]; @@ -558,16 +562,24 @@ opl4_midi_thread(void *arg) atomic_store(&opl4_midi->gen_in_progress, false); if (sound_is_float) { for (i = 0; i < (buf_size / 2); i++) { - opl4_midi->buffer_float[i * 2] = buffer[i * 2] / 32768.0; - opl4_midi->buffer_float[(i * 2) + 1] = buffer[(i * 2) + 1] / 32768.0; + opl4_midi->buffer_float[(i + buf_pos) * 2] = buffer[i * 2] / 32768.0; + opl4_midi->buffer_float[((i + buf_pos) * 2) + 1] = buffer[(i * 2) + 1] / 32768.0; + } + buf_pos += buf_size / 2; + if (buf_pos >= (buf_size_segments / 2)) { + givealbuffer_midi(opl4_midi->buffer_float, buf_size_segments); + buf_pos = 0; } - givealbuffer_midi(opl4_midi->buffer_float, buf_size); } else { for (i = 0; i < (buf_size / 2); i++) { - opl4_midi->buffer[i * 2] = buffer[i * 2] & 0xFFFF; /* Outputs are clamped beforehand. */ - opl4_midi->buffer[(i * 2) + 1] = buffer[(i * 2) + 1] & 0xFFFF; /* Outputs are clamped beforehand. */ + opl4_midi->buffer[(i + buf_pos) * 2] = buffer[i * 2] & 0xFFFF; /* Outputs are clamped beforehand. */ + opl4_midi->buffer[((i + buf_pos) * 2) + 1] = buffer[(i * 2) + 1] & 0xFFFF; /* Outputs are clamped beforehand. */ + } + buf_pos += buf_size / 2; + if (buf_pos >= (buf_size_segments / 2)) { + givealbuffer_midi(opl4_midi->buffer, buf_size_segments); + buf_pos = 0; } - givealbuffer_midi(opl4_midi->buffer, buf_size); } } } From 767d486aee07a28cdf422d42557ca5bd3d945cda Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 27 Nov 2022 21:35:08 +0600 Subject: [PATCH 012/133] OPL4 activation timestamp now comes from platform timestamp --- src/sound/midi_opl4.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index b75ac23b5..5a4480835 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -270,7 +270,7 @@ static const uint8_t g_volume_table[128] = { }; #define BUFFER_SEGMENTS 10 -#define RENDER_RATE (48000 / 100) +#define RENDER_RATE (48000 / 100) typedef struct opl4_midi { fm_drv_t opl4; @@ -419,8 +419,7 @@ note_on(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_mi const YRW801_WAVE_DATA *wave_data[2]; VOICE_DATA *voice[2]; uint8_t i = 0, voices = 0; - uint32_t j = 0; - static uint64_t activation_num = 0; + uint32_t j = 0; while (opl4_midi->gen_in_progress) { } @@ -444,7 +443,7 @@ note_on(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_mi for (i = 0; i < voices; i++) { voice[i] = get_voice(wave_data[i], opl4_midi); voice[i]->is_active = true; - voice[i]->activated = activation_num++; + voice[i]->activated = plat_get_ticks(); voice[i]->midi_channel = midi_channel; voice[i]->note = note; @@ -543,11 +542,11 @@ program_change(uint8_t midi_channel, uint8_t program, opl4_midi_t *opl4_midi) static void opl4_midi_thread(void *arg) { - opl4_midi_t *opl4_midi = opl4_midi_cur; - uint32_t i = 0; - uint32_t buf_size = RENDER_RATE * 2; + opl4_midi_t *opl4_midi = opl4_midi_cur; + uint32_t i = 0; + uint32_t buf_size = RENDER_RATE * 2; uint32_t buf_size_segments = buf_size * BUFFER_SEGMENTS; - uint32_t buf_pos = 0; + uint32_t buf_pos = 0; int32_t buffer[RENDER_RATE * 2]; From 83f256bed9f2da4cf34149d052e9b94360e92c60 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 29 Nov 2022 12:08:01 +0600 Subject: [PATCH 013/133] Attempt minimizing polyphony problems --- src/sound/midi_opl4.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index 5a4480835..25984e832 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -314,7 +314,23 @@ get_voice(const YRW801_WAVE_DATA *wave_data, opl4_midi_t *opl4_midi) } } - /* If no free voice found, deactivate the 'oldest' */ + /* If no free voice is found, look for one with the same instrument */ + if (free_voice->is_active) { + for (uint8_t voice = 0; voice < 24; voice++) { + if (opl4_midi_cur->voice_data[voice].is_active + && opl4_midi_cur->voice_data[voice].wave_data == wave_data) { + free_voice = &opl4_midi_cur->voice_data[voice]; + free_voice->is_active = 0; + free_voice->activated = 0; + + free_voice->reg_misc &= ~OPL4_KEY_ON_BIT; + opl4_write_wave_register(OPL4_REG_MISC + free_voice->number, free_voice->reg_misc, opl4_midi); + return free_voice; + } + } + } + + /* If still no free voice found, deactivate the 'oldest' */ if (free_voice->is_active) { free_voice = oldest_voice; free_voice->is_active = 0; From 7ac1867222e779bbdb29591478bfdf86d16e9b4f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 30 Nov 2022 00:20:03 +0600 Subject: [PATCH 014/133] Make free voice behaviour more aggressive --- src/sound/midi_opl4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index 25984e832..ba641701c 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -309,8 +309,10 @@ get_voice(const YRW801_WAVE_DATA *wave_data, opl4_midi_t *opl4_midi) break; } - if (opl4_midi_cur->voice_data[voice].activated < free_voice->activated) + if (opl4_midi_cur->voice_data[voice].activated < free_voice->activated) { free_voice = &opl4_midi_cur->voice_data[voice]; + break; + } } } From 659143408efc4684c15eb742dfb96744996d375e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Jul 2023 16:24:35 +0600 Subject: [PATCH 015/133] Port DECchip 21143 "Tulip" emulation from QEMU --- src/include/86box/net_eeprom_nmc93cxx.h | 20 + src/include/86box/net_tulip.h | 1 + src/network/CMakeLists.txt | 3 +- src/network/net_eeprom_nmc93cxx.c | 273 +++++ src/network/net_tulip.c | 1264 +++++++++++++++++++++++ src/network/network.c | 2 + 6 files changed, 1562 insertions(+), 1 deletion(-) create mode 100644 src/include/86box/net_eeprom_nmc93cxx.h create mode 100644 src/include/86box/net_tulip.h create mode 100644 src/network/net_eeprom_nmc93cxx.c create mode 100644 src/network/net_tulip.c diff --git a/src/include/86box/net_eeprom_nmc93cxx.h b/src/include/86box/net_eeprom_nmc93cxx.h new file mode 100644 index 000000000..7f503ed4f --- /dev/null +++ b/src/include/86box/net_eeprom_nmc93cxx.h @@ -0,0 +1,20 @@ +struct nmc93cxx_eeprom_t; +typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t; + +typedef struct nmc93cxx_eeprom_params_t +{ + uint16_t nwords; + char* filename; + uint16_t* default_content; +} nmc93cxx_eeprom_params_t; + +/* Read from the EEPROM. */ +uint16_t nmc93cxx_eeprom_read(nmc93cxx_eeprom_t *eeprom); + +/* Write to the EEPROM. */ +void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi); + +/* Get EEPROM data array. */ +uint16_t *nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom); + +extern const device_t nmc93cxx_device; \ No newline at end of file diff --git a/src/include/86box/net_tulip.h b/src/include/86box/net_tulip.h new file mode 100644 index 000000000..492d5a40f --- /dev/null +++ b/src/include/86box/net_tulip.h @@ -0,0 +1 @@ +extern const device_t dec_tulip_device; \ No newline at end of file diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index ce1bba325..6b6340334 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -14,7 +14,8 @@ # set(net_sources) list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c - net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c) + net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c + net_eeprom_nmc93cxx.c net_tulip.c) find_package(PkgConfig REQUIRED) pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c new file mode 100644 index 000000000..66f9a6fdb --- /dev/null +++ b/src/network/net_eeprom_nmc93cxx.c @@ -0,0 +1,273 @@ +/* + * 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. + * + * Emulation of National Semiconductors NMC93Cxx EEPROMs. + * + * + * Authors: Cacodemon345 + * + * Copyright 2023 Cacodemon345 + */ + +/* Ported over from QEMU */ + + +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/net_eeprom_nmc93cxx.h> + +struct nmc93cxx_eeprom_t { + uint8_t tick; + uint8_t address; + uint8_t command; + uint8_t writable; + + uint8_t eecs; + uint8_t eesk; + uint8_t eedo; + + uint8_t addrbits; + uint16_t size; + uint16_t data; + char filename[1024]; + uint16_t contents[]; +}; + +typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t; + +#define logout pclog + +static const char *opstring[] = { + "extended", "write", "read", "erase" +}; + +static void * +nmc93cxx_eeprom_init_params(const device_t *info, void* params) +{ + uint16_t nwords = 64; + uint8_t addrbits = 6; + uint8_t filldefault = 1; + nmc93cxx_eeprom_params_t* params_details = (nmc93cxx_eeprom_params_t*)params; + nmc93cxx_eeprom_t* eeprom = NULL; + if (!params) + return NULL; + + nwords = params_details->nwords; + + switch (nwords) { + case 16: + case 64: + addrbits = 6; + break; + case 128: + case 256: + addrbits = 8; + break; + default: + nwords = 64; + addrbits = 6; + break; + } + eeprom = calloc(1, sizeof(nmc93cxx_eeprom_t) + ((nwords + 1) * 2)); + if (!eeprom) + return NULL; + eeprom->size = nwords; + eeprom->addrbits = addrbits; + /* Output DO is tristate, read results in 1. */ + eeprom->eedo = 1; + + if (params_details->filename) + { + FILE* file = nvr_fopen(params_details->filename, "rb"); + strncpy(eeprom->filename, params_details->filename, 1024); + if (file) { + filldefault = !fread(eeprom->contents, sizeof(uint16_t), nwords, file); + fclose(file); + } + } + + if (filldefault) + { + memcpy(eeprom->contents, params_details->default_content, nwords * sizeof(uint16_t)); + } + + return eeprom; +} + +void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi) +{ + uint8_t tick = eeprom->tick; + uint8_t eedo = eeprom->eedo; + uint16_t address = eeprom->address; + uint8_t command = eeprom->command; + + logout("CS=%u SK=%u DI=%u DO=%u, tick = %u\n", + eecs, eesk, eedi, eedo, tick); + + if (!eeprom->eecs && eecs) { + /* Start chip select cycle. */ + logout("Cycle start, waiting for 1st start bit (0)\n"); + tick = 0; + command = 0x0; + address = 0x0; + } else if (eeprom->eecs && !eecs) { + /* End chip select cycle. This triggers write / erase. */ + if (eeprom->writable) { + uint8_t subcommand = address >> (eeprom->addrbits - 2); + if (command == 0 && subcommand == 2) { + /* Erase all. */ + for (address = 0; address < eeprom->size; address++) { + eeprom->contents[address] = 0xffff; + } + } else if (command == 3) { + /* Erase word. */ + eeprom->contents[address] = 0xffff; + } else if (tick >= 2 + 2 + eeprom->addrbits + 16) { + if (command == 1) { + /* Write word. */ + eeprom->contents[address] &= eeprom->data; + } else if (command == 0 && subcommand == 1) { + /* Write all. */ + for (address = 0; address < eeprom->size; address++) { + eeprom->contents[address] &= eeprom->data; + } + } + } + } + /* Output DO is tristate, read results in 1. */ + eedo = 1; + } else if (eecs && !eeprom->eesk && eesk) { + /* Raising edge of clock shifts data in. */ + if (tick == 0) { + /* Wait for 1st start bit. */ + if (eedi == 0) { + logout("Got correct 1st start bit, waiting for 2nd start bit (1)\n"); + tick++; + } else { + logout("wrong 1st start bit (is 1, should be 0)\n"); + tick = 2; + //~ assert(!"wrong start bit"); + } + } else if (tick == 1) { + /* Wait for 2nd start bit. */ + if (eedi != 0) { + logout("Got correct 2nd start bit, getting command + address\n"); + tick++; + } else { + logout("1st start bit is longer than needed\n"); + } + } else if (tick < 2 + 2) { + /* Got 2 start bits, transfer 2 opcode bits. */ + tick++; + command <<= 1; + if (eedi) { + command += 1; + } + } else if (tick < 2 + 2 + eeprom->addrbits) { + /* Got 2 start bits and 2 opcode bits, transfer all address bits. */ + tick++; + address = ((address << 1) | eedi); + if (tick == 2 + 2 + eeprom->addrbits) { + logout("%s command, address = 0x%02x (value 0x%04x)\n", + opstring[command], address, eeprom->contents[address]); + if (command == 2) { + eedo = 0; + } + address = address % eeprom->size; + if (command == 0) { + /* Command code in upper 2 bits of address. */ + switch (address >> (eeprom->addrbits - 2)) { + case 0: + logout("write disable command\n"); + eeprom->writable = 0; + break; + case 1: + logout("write all command\n"); + break; + case 2: + logout("erase all command\n"); + break; + case 3: + logout("write enable command\n"); + eeprom->writable = 1; + break; + } + } else { + /* Read, write or erase word. */ + eeprom->data = eeprom->contents[address]; + } + } + } else if (tick < 2 + 2 + eeprom->addrbits + 16) { + /* Transfer 16 data bits. */ + tick++; + if (command == 2) { + /* Read word. */ + eedo = ((eeprom->data & 0x8000) != 0); + } + eeprom->data <<= 1; + eeprom->data += eedi; + } else { + logout("additional unneeded tick, not processed\n"); + } + } + /* Save status of EEPROM. */ + eeprom->tick = tick; + eeprom->eecs = eecs; + eeprom->eesk = eesk; + eeprom->eedo = eedo; + eeprom->address = address; + eeprom->command = command; +} + +uint16_t nmc93cxx_eeprom_read(nmc93cxx_eeprom_t *eeprom) +{ + /* Return status of pin DO (0 or 1). */ + return eeprom->eedo; +} + + +static void +nmc93cxx_eeprom_close(void *priv) +{ + nmc93cxx_eeprom_t* eeprom = (nmc93cxx_eeprom_t*)priv; + FILE* file = nvr_fopen(eeprom->filename, "wb"); + if (file) + { + fwrite(eeprom->contents, 2, eeprom->size, file); + } + fclose(file); + free(priv); +} + +uint16_t *nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom) +{ + /* Get EEPROM data array. */ + return &eeprom->contents[0]; +} + +const device_t nmc93cxx_device = { + .name = "National Semiconductor NMC93Cxx", + .internal_name = "nmc93cxx", + .flags = DEVICE_EXTPARAMS, + .local = 0, + .init_ext = nmc93cxx_eeprom_init_params, + .close = nmc93cxx_eeprom_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c new file mode 100644 index 000000000..0d9f352c6 --- /dev/null +++ b/src/network/net_tulip.c @@ -0,0 +1,1264 @@ +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/pci.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/dma.h> +#include <86box/device.h> +#include <86box/thread.h> +#include <86box/network.h> +#include <86box/net_eeprom_nmc93cxx.h> +#include <86box/net_tulip.h> +#include <86box/bswap.h> + +#define CSR(_x) ((_x) << 3) + +#define BIT(x) (1 << x) + +#define CSR0_SWR BIT(0) +#define CSR0_BAR BIT(1) +#define CSR0_DSL_SHIFT 2 +#define CSR0_DSL_MASK 0x1f +#define CSR0_BLE BIT(7) +#define CSR0_PBL_SHIFT 8 +#define CSR0_PBL_MASK 0x3f +#define CSR0_CAC_SHIFT 14 +#define CSR0_CAC_MASK 0x3 +#define CSR0_DAS 0x10000 +#define CSR0_TAP_SHIFT 17 +#define CSR0_TAP_MASK 0x7 +#define CSR0_DBO 0x100000 +#define CSR1_TPD 0x01 +#define CSR0_RLE BIT(23) +#define CSR0_WIE BIT(24) + +#define CSR2_RPD 0x01 + +#define CSR5_TI BIT(0) +#define CSR5_TPS BIT(1) +#define CSR5_TU BIT(2) +#define CSR5_TJT BIT(3) +#define CSR5_LNP_ANC BIT(4) +#define CSR5_UNF BIT(5) +#define CSR5_RI BIT(6) +#define CSR5_RU BIT(7) +#define CSR5_RPS BIT(8) +#define CSR5_RWT BIT(9) +#define CSR5_ETI BIT(10) +#define CSR5_GTE BIT(11) +#define CSR5_LNF BIT(12) +#define CSR5_FBE BIT(13) +#define CSR5_ERI BIT(14) +#define CSR5_AIS BIT(15) +#define CSR5_NIS BIT(16) +#define CSR5_RS_SHIFT 17 +#define CSR5_RS_MASK 7 +#define CSR5_TS_SHIFT 20 +#define CSR5_TS_MASK 7 + +#define CSR5_TS_STOPPED 0 +#define CSR5_TS_RUNNING_FETCH 1 +#define CSR5_TS_RUNNING_WAIT_EOT 2 +#define CSR5_TS_RUNNING_READ_BUF 3 +#define CSR5_TS_RUNNING_SETUP 5 +#define CSR5_TS_SUSPENDED 6 +#define CSR5_TS_RUNNING_CLOSE 7 + +#define CSR5_RS_STOPPED 0 +#define CSR5_RS_RUNNING_FETCH 1 +#define CSR5_RS_RUNNING_CHECK_EOR 2 +#define CSR5_RS_RUNNING_WAIT_RECEIVE 3 +#define CSR5_RS_SUSPENDED 4 +#define CSR5_RS_RUNNING_CLOSE 5 +#define CSR5_RS_RUNNING_FLUSH 6 +#define CSR5_RS_RUNNING_QUEUE 7 + +#define CSR5_EB_SHIFT 23 +#define CSR5_EB_MASK 7 + +#define CSR5_GPI BIT(26) +#define CSR5_LC BIT(27) + +#define CSR6_HP BIT(0) +#define CSR6_SR BIT(1) +#define CSR6_HO BIT(2) +#define CSR6_PB BIT(3) +#define CSR6_IF BIT(4) +#define CSR6_SB BIT(5) +#define CSR6_PR BIT(6) +#define CSR6_PM BIT(7) +#define CSR6_FKD BIT(8) +#define CSR6_FD BIT(9) + +#define CSR6_OM_SHIFT 10 +#define CSR6_OM_MASK 3 +#define CSR6_OM_NORMAL 0 +#define CSR6_OM_INT_LOOPBACK 1 +#define CSR6_OM_EXT_LOOPBACK 2 + +#define CSR6_FC BIT(12) +#define CSR6_ST BIT(13) + + +#define CSR6_TR_SHIFT 14 +#define CSR6_TR_MASK 3 +#define CSR6_TR_72 0 +#define CSR6_TR_96 1 +#define CSR6_TR_128 2 +#define CSR6_TR_160 3 + +#define CSR6_CA BIT(17) +#define CSR6_RA BIT(30) +#define CSR6_SC BIT(31) + +#define CSR7_TIM BIT(0) +#define CSR7_TSM BIT(1) +#define CSR7_TUM BIT(2) +#define CSR7_TJM BIT(3) +#define CSR7_LPM BIT(4) +#define CSR7_UNM BIT(5) +#define CSR7_RIM BIT(6) +#define CSR7_RUM BIT(7) +#define CSR7_RSM BIT(8) +#define CSR7_RWM BIT(9) +#define CSR7_TMM BIT(11) +#define CSR7_LFM BIT(12) +#define CSR7_SEM BIT(13) +#define CSR7_ERM BIT(14) +#define CSR7_AIM BIT(15) +#define CSR7_NIM BIT(16) + +#define CSR8_MISSED_FRAME_OVL BIT(16) +#define CSR8_MISSED_FRAME_CNT_MASK 0xffff + +#define CSR9_DATA_MASK 0xff +#define CSR9_SR_CS BIT(0) +#define CSR9_SR_SK BIT(1) +#define CSR9_SR_DI BIT(2) +#define CSR9_SR_DO BIT(3) +#define CSR9_REG BIT(10) +#define CSR9_SR BIT(11) +#define CSR9_BR BIT(12) +#define CSR9_WR BIT(13) +#define CSR9_RD BIT(14) +#define CSR9_MOD BIT(15) +#define CSR9_MDC BIT(16) +#define CSR9_MDO BIT(17) +#define CSR9_MII BIT(18) +#define CSR9_MDI BIT(19) + +#define CSR11_CON BIT(16) +#define CSR11_TIMER_MASK 0xffff + +#define CSR12_MRA BIT(0) +#define CSR12_LS100 BIT(1) +#define CSR12_LS10 BIT(2) +#define CSR12_APS BIT(3) +#define CSR12_ARA BIT(8) +#define CSR12_TRA BIT(9) +#define CSR12_NSN BIT(10) +#define CSR12_TRF BIT(11) +#define CSR12_ANS_SHIFT 12 +#define CSR12_ANS_MASK 7 +#define CSR12_LPN BIT(15) +#define CSR12_LPC_SHIFT 16 +#define CSR12_LPC_MASK 0xffff + +#define CSR13_SRL BIT(0) +#define CSR13_CAC BIT(2) +#define CSR13_AUI BIT(3) +#define CSR13_SDM_SHIFT 4 +#define CSR13_SDM_MASK 0xfff + +#define CSR14_ECEN BIT(0) +#define CSR14_LBK BIT(1) +#define CSR14_DREN BIT(2) +#define CSR14_LSE BIT(3) +#define CSR14_CPEN_SHIFT 4 +#define CSR14_CPEN_MASK 3 +#define CSR14_MBO BIT(6) +#define CSR14_ANE BIT(7) +#define CSR14_RSQ BIT(8) +#define CSR14_CSQ BIT(9) +#define CSR14_CLD BIT(10) +#define CSR14_SQE BIT(11) +#define CSR14_LTE BIT(12) +#define CSR14_APE BIT(13) +#define CSR14_SPP BIT(14) +#define CSR14_TAS BIT(15) + +#define CSR15_JBD BIT(0) +#define CSR15_HUJ BIT(1) +#define CSR15_JCK BIT(2) +#define CSR15_ABM BIT(3) +#define CSR15_RWD BIT(4) +#define CSR15_RWR BIT(5) +#define CSR15_LE1 BIT(6) +#define CSR15_LV1 BIT(7) +#define CSR15_TSCK BIT(8) +#define CSR15_FUSQ BIT(9) +#define CSR15_FLF BIT(10) +#define CSR15_LSD BIT(11) +#define CSR15_DPST BIT(12) +#define CSR15_FRL BIT(13) +#define CSR15_LE2 BIT(14) +#define CSR15_LV2 BIT(15) + +#define RDES0_OF BIT(0) +#define RDES0_CE BIT(1) +#define RDES0_DB BIT(2) +#define RDES0_RJ BIT(4) +#define RDES0_FT BIT(5) +#define RDES0_CS BIT(6) +#define RDES0_TL BIT(7) +#define RDES0_LS BIT(8) +#define RDES0_FS BIT(9) +#define RDES0_MF BIT(10) +#define RDES0_RF BIT(11) +#define RDES0_DT_SHIFT 12 +#define RDES0_DT_MASK 3 +#define RDES0_DE BIT(14) +#define RDES0_ES BIT(15) +#define RDES0_FL_SHIFT 16 +#define RDES0_FL_MASK 0x3fff +#define RDES0_FF BIT(30) +#define RDES0_OWN BIT(31) + +#define RDES1_BUF1_SIZE_SHIFT 0 +#define RDES1_BUF1_SIZE_MASK 0x7ff + +#define RDES1_BUF2_SIZE_SHIFT 11 +#define RDES1_BUF2_SIZE_MASK 0x7ff +#define RDES1_RCH BIT(24) +#define RDES1_RER BIT(25) + +#define TDES0_DE BIT(0) +#define TDES0_UF BIT(1) +#define TDES0_LF BIT(2) +#define TDES0_CC_SHIFT 3 +#define TDES0_CC_MASK 0xf +#define TDES0_HF BIT(7) +#define TDES0_EC BIT(8) +#define TDES0_LC BIT(9) +#define TDES0_NC BIT(10) +#define TDES0_LO BIT(11) +#define TDES0_TO BIT(14) +#define TDES0_ES BIT(15) +#define TDES0_OWN BIT(31) + +#define TDES1_BUF1_SIZE_SHIFT 0 +#define TDES1_BUF1_SIZE_MASK 0x7ff + +#define TDES1_BUF2_SIZE_SHIFT 11 +#define TDES1_BUF2_SIZE_MASK 0x7ff + +#define TDES1_FT0 BIT(22) +#define TDES1_DPD BIT(23) +#define TDES1_TCH BIT(24) +#define TDES1_TER BIT(25) +#define TDES1_AC BIT(26) +#define TDES1_SET BIT(27) +#define TDES1_FT1 BIT(28) +#define TDES1_FS BIT(29) +#define TDES1_LS BIT(30) +#define TDES1_IC BIT(31) + +#define ETH_ALEN 6 + +struct tulip_descriptor { + uint32_t status; + uint32_t control; + uint32_t buf_addr1; + uint32_t buf_addr2; +}; + +struct TULIPState { + uint8_t dev; + uint16_t subsys_id, subsys_ven_id; + mem_mapping_t memory; + netcard_t *nic; + nmc93cxx_eeprom_t *eeprom; + uint32_t csr[16]; + uint8_t pci_conf[256]; + uint16_t mii_regs[32]; + + /* state for MII */ + uint32_t old_csr9; + uint32_t mii_word; + uint32_t mii_bitcnt; + + uint32_t current_rx_desc; + uint32_t current_tx_desc; + + uint8_t rx_frame[2048]; + uint8_t tx_frame[2048]; + uint16_t tx_frame_len; + uint16_t rx_frame_len; + uint16_t rx_frame_size; + + uint32_t rx_status; + uint8_t filter[16][6]; +}; + +typedef struct TULIPState TULIPState; + +static void tulip_desc_read(TULIPState *s, uint32_t p, + struct tulip_descriptor *desc) +{ + desc->status = mem_readl_phys(p); + desc->control = mem_readl_phys(p + 4); + desc->buf_addr1 = mem_readl_phys(p + 8); + desc->buf_addr2 = mem_readl_phys(p + 12); + + if (s->csr[0] & CSR0_DBO) { + bswap32s(&desc->status); + bswap32s(&desc->control); + bswap32s(&desc->buf_addr1); + bswap32s(&desc->buf_addr2); + } +} + +static void tulip_desc_write(TULIPState *s, uint32_t p, + struct tulip_descriptor *desc) +{ + if (s->csr[0] & CSR0_DBO) { + mem_writel_phys(p, bswap32(desc->status)); + mem_writel_phys(p + 4, bswap32(desc->control)); + mem_writel_phys(p + 8, bswap32(desc->buf_addr1)); + mem_writel_phys(p + 12, bswap32(desc->buf_addr2)); + } else { + mem_writel_phys(p, desc->status); + mem_writel_phys(p + 4, desc->control); + mem_writel_phys(p + 8, desc->buf_addr1); + mem_writel_phys(p + 12, desc->buf_addr2); + } +} + +static void tulip_update_int(TULIPState *s) +{ + uint32_t ie = s->csr[5] & s->csr[7]; + bool assert = false; + + s->csr[5] &= ~(CSR5_AIS | CSR5_NIS); + + if (ie & (CSR5_TI | CSR5_TU | CSR5_RI | CSR5_GTE | CSR5_ERI)) { + s->csr[5] |= CSR5_NIS; + } + + if (ie & (CSR5_LC | CSR5_GPI | CSR5_FBE | CSR5_LNF | CSR5_ETI | CSR5_RWT | + CSR5_RPS | CSR5_RU | CSR5_UNF | CSR5_LNP_ANC | CSR5_TJT | + CSR5_TPS)) { + s->csr[5] |= CSR5_AIS; + } + + assert = s->csr[5] & s->csr[7] & (CSR5_AIS | CSR5_NIS); + if (!assert) + pci_clear_irq(s->dev, PCI_INTA); + else + pci_set_irq(s->dev, PCI_INTA); +} + +static bool tulip_rx_stopped(TULIPState *s) +{ + return ((s->csr[5] >> CSR5_RS_SHIFT) & CSR5_RS_MASK) == CSR5_RS_STOPPED; +} + +static void tulip_next_rx_descriptor(TULIPState *s, + struct tulip_descriptor *desc) +{ + if (desc->control & RDES1_RER) { + s->current_rx_desc = s->csr[3]; + } else if (desc->control & RDES1_RCH) { + s->current_rx_desc = desc->buf_addr2; + } else { + s->current_rx_desc += sizeof(struct tulip_descriptor) + + (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); + } + s->current_rx_desc &= ~3ULL; +} + +static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) +{ + int len1 = (desc->control >> RDES1_BUF1_SIZE_SHIFT) & RDES1_BUF1_SIZE_MASK; + int len2 = (desc->control >> RDES1_BUF2_SIZE_SHIFT) & RDES1_BUF2_SIZE_MASK; + int len; + + if (s->rx_frame_len && len1) { + if (s->rx_frame_len > len1) { + len = len1; + } else { + len = s->rx_frame_len; + } + + dma_bm_write(desc->buf_addr1, s->rx_frame + + (s->rx_frame_size - s->rx_frame_len), len, 1); + s->rx_frame_len -= len; + } + + if (s->rx_frame_len && len2) { + if (s->rx_frame_len > len2) { + len = len2; + } else { + len = s->rx_frame_len; + } + + dma_bm_write(desc->buf_addr2, s->rx_frame + + (s->rx_frame_size - s->rx_frame_len), len, 1); + s->rx_frame_len -= len; + } +} + +static bool tulip_filter_address(TULIPState *s, const uint8_t *addr) +{ + static const char broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + bool ret = false; + int i; + + for (i = 0; i < 16 && ret == false; i++) { + if (!memcmp(&s->filter[i], addr, ETH_ALEN)) { + ret = true; + } + } + + if (!memcmp(addr, broadcast, ETH_ALEN)) { + return true; + } + + if (s->csr[6] & (CSR6_PR | CSR6_RA)) { + /* Promiscuous mode enabled */ + s->rx_status |= RDES0_FF; + return true; + } + + if ((s->csr[6] & CSR6_PM) && (addr[0] & 1)) { + /* Pass all Multicast enabled */ + s->rx_status |= RDES0_MF; + return true; + } + + if (s->csr[6] & CSR6_IF) { + ret ^= true; + } + return ret; +} + +static int tulip_receive(void* p, uint8_t *buf, int size) +{ + struct tulip_descriptor desc; + TULIPState *s = (TULIPState*)p; + + if (size < 14 || size > sizeof(s->rx_frame) - 4 + || s->rx_frame_len || tulip_rx_stopped(s)) { + return 0; + } + + if (!tulip_filter_address(s, buf)) { + return 1; + } + + do { + tulip_desc_read(s, s->current_rx_desc, &desc); + + if (!(desc.status & RDES0_OWN)) { + s->csr[5] |= CSR5_RU; + tulip_update_int(s); + return s->rx_frame_size - s->rx_frame_len; + } + desc.status = 0; + + if (!s->rx_frame_len) { + s->rx_frame_size = size + 4; + s->rx_status = RDES0_LS | + ((s->rx_frame_size & RDES0_FL_MASK) << RDES0_FL_SHIFT); + desc.status |= RDES0_FS; + memcpy(s->rx_frame, buf, size); + s->rx_frame_len = s->rx_frame_size; + } + + tulip_copy_rx_bytes(s, &desc); + + if (!s->rx_frame_len) { + desc.status |= s->rx_status; + s->csr[5] |= CSR5_RI; + tulip_update_int(s); + } + tulip_desc_write(s, s->current_rx_desc, &desc); + tulip_next_rx_descriptor(s, &desc); + } while (s->rx_frame_len); + return 1; +} + +static const char *tulip_reg_name(const uint32_t addr) +{ + switch (addr) { + case CSR(0): + return "CSR0"; + + case CSR(1): + return "CSR1"; + + case CSR(2): + return "CSR2"; + + case CSR(3): + return "CSR3"; + + case CSR(4): + return "CSR4"; + + case CSR(5): + return "CSR5"; + + case CSR(6): + return "CSR6"; + + case CSR(7): + return "CSR7"; + + case CSR(8): + return "CSR8"; + + case CSR(9): + return "CSR9"; + + case CSR(10): + return "CSR10"; + + case CSR(11): + return "CSR11"; + + case CSR(12): + return "CSR12"; + + case CSR(13): + return "CSR13"; + + case CSR(14): + return "CSR14"; + + case CSR(15): + return "CSR15"; + + default: + break; + } + return ""; +} + +static const char *tulip_rx_state_name(int state) +{ + switch (state) { + case CSR5_RS_STOPPED: + return "STOPPED"; + + case CSR5_RS_RUNNING_FETCH: + return "RUNNING/FETCH"; + + case CSR5_RS_RUNNING_CHECK_EOR: + return "RUNNING/CHECK EOR"; + + case CSR5_RS_RUNNING_WAIT_RECEIVE: + return "WAIT RECEIVE"; + + case CSR5_RS_SUSPENDED: + return "SUSPENDED"; + + case CSR5_RS_RUNNING_CLOSE: + return "RUNNING/CLOSE"; + + case CSR5_RS_RUNNING_FLUSH: + return "RUNNING/FLUSH"; + + case CSR5_RS_RUNNING_QUEUE: + return "RUNNING/QUEUE"; + + default: + break; + } + return ""; +} + +static const char *tulip_tx_state_name(int state) +{ + switch (state) { + case CSR5_TS_STOPPED: + return "STOPPED"; + + case CSR5_TS_RUNNING_FETCH: + return "RUNNING/FETCH"; + + case CSR5_TS_RUNNING_WAIT_EOT: + return "RUNNING/WAIT EOT"; + + case CSR5_TS_RUNNING_READ_BUF: + return "RUNNING/READ BUF"; + + case CSR5_TS_RUNNING_SETUP: + return "RUNNING/SETUP"; + + case CSR5_TS_SUSPENDED: + return "SUSPENDED"; + + case CSR5_TS_RUNNING_CLOSE: + return "RUNNING/CLOSE"; + + default: + break; + } + return ""; +} + +static void tulip_update_rs(TULIPState *s, int state) +{ + s->csr[5] &= ~(CSR5_RS_MASK << CSR5_RS_SHIFT); + s->csr[5] |= (state & CSR5_RS_MASK) << CSR5_RS_SHIFT; +} + +static const uint16_t tulip_mdi_default[] = { + /* MDI Registers 0 - 6, 7 */ + 0x3100, 0xf02c, 0x7810, 0x0000, 0x0501, 0x4181, 0x0000, 0x0000, + /* MDI Registers 8 - 15 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* MDI Registers 16 - 31 */ + 0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +/* Readonly mask for MDI (PHY) registers */ +static const uint16_t tulip_mdi_mask[] = { + 0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +static uint16_t tulip_mii_read(TULIPState *s, int phy, int reg) +{ + uint16_t ret = 0; + if (phy == 1) { + ret = s->mii_regs[reg]; + } + return ret; +} + +static void tulip_mii_write(TULIPState *s, int phy, int reg, uint16_t data) +{ + if (phy != 1) { + return; + } + + s->mii_regs[reg] &= ~tulip_mdi_mask[reg]; + s->mii_regs[reg] |= (data & tulip_mdi_mask[reg]); +} + +static void tulip_mii(TULIPState *s) +{ + uint32_t changed = s->old_csr9 ^ s->csr[9]; + uint16_t data; + int op, phy, reg; + + if (!(changed & CSR9_MDC)) { + return; + } + + if (!(s->csr[9] & CSR9_MDC)) { + return; + } + + s->mii_bitcnt++; + s->mii_word <<= 1; + + if (s->csr[9] & CSR9_MDO && (s->mii_bitcnt < 16 || + !(s->csr[9] & CSR9_MII))) { + /* write op or address bits */ + s->mii_word |= 1; + } + + if (s->mii_bitcnt >= 16 && (s->csr[9] & CSR9_MII)) { + if (s->mii_word & 0x8000) { + s->csr[9] |= CSR9_MDI; + } else { + s->csr[9] &= ~CSR9_MDI; + } + } + + if (s->mii_word == 0xffffffff) { + s->mii_bitcnt = 0; + } else if (s->mii_bitcnt == 16) { + op = (s->mii_word >> 12) & 0x0f; + phy = (s->mii_word >> 7) & 0x1f; + reg = (s->mii_word >> 2) & 0x1f; + + if (op == 6) { + s->mii_word = tulip_mii_read(s, phy, reg); + } + } else if (s->mii_bitcnt == 32) { + op = (s->mii_word >> 28) & 0x0f; + phy = (s->mii_word >> 23) & 0x1f; + reg = (s->mii_word >> 18) & 0x1f; + data = s->mii_word & 0xffff; + + if (op == 5) { + tulip_mii_write(s, phy, reg, data); + } + } +} + +static uint32_t tulip_csr9_read(TULIPState *s) +{ + if (s->csr[9] & CSR9_SR) { + if (nmc93cxx_eeprom_read(s->eeprom)) { + s->csr[9] |= CSR9_SR_DO; + } else { + s->csr[9] &= ~CSR9_SR_DO; + } + } + + tulip_mii(s); + return s->csr[9]; +} + +static void tulip_update_ts(TULIPState *s, int state) +{ + s->csr[5] &= ~(CSR5_TS_MASK << CSR5_TS_SHIFT); + s->csr[5] |= (state & CSR5_TS_MASK) << CSR5_TS_SHIFT; +} + +static uint32_t tulip_read(uint32_t addr, void *opaque) +{ + TULIPState *s = opaque; + uint32_t data = 0; + addr &= 127; + + switch (addr) { + case CSR(9): + data = tulip_csr9_read(s); + break; + + case CSR(12): + /* Fake autocompletion complete until we have PHY emulation */ + data = 5 << CSR12_ANS_SHIFT; + break; + + default: + if (addr & 7) { + } else { + data = s->csr[addr >> 3]; + } + break; + } + return data; +} + +static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc) +{ + if (s->tx_frame_len) { + if ((s->csr[6] >> CSR6_OM_SHIFT) & CSR6_OM_MASK) { + /* Internal or external Loopback */ + tulip_receive(s, s->tx_frame, s->tx_frame_len); + } else if (s->tx_frame_len <= sizeof(s->tx_frame)) { + network_tx(s->nic, s->tx_frame, s->tx_frame_len); + } + } + + if (desc->control & TDES1_IC) { + s->csr[5] |= CSR5_TI; + tulip_update_int(s); + } +} + +static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) +{ + int len1 = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; + int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK; + + if (s->tx_frame_len + len1 > sizeof(s->tx_frame)) { + return -1; + } + if (len1) { + dma_bm_read(desc->buf_addr1, + s->tx_frame + s->tx_frame_len, len1, 1); + s->tx_frame_len += len1; + } + + if (s->tx_frame_len + len2 > sizeof(s->tx_frame)) { + return -1; + } + if (len2) { + dma_bm_read(desc->buf_addr2, + s->tx_frame + s->tx_frame_len, len2, 1); + s->tx_frame_len += len2; + } + desc->status = (len1 + len2) ? 0 : 0x7fffffff; + + return 0; +} + +static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n) +{ + int offset = n * 12; + + s->filter[n][0] = buf[offset]; + s->filter[n][1] = buf[offset + 1]; + + s->filter[n][2] = buf[offset + 4]; + s->filter[n][3] = buf[offset + 5]; + + s->filter[n][4] = buf[offset + 8]; + s->filter[n][5] = buf[offset + 9]; +} + +static void tulip_setup_frame(TULIPState *s, + struct tulip_descriptor *desc) +{ + uint8_t buf[4096]; + int len = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; + int i; + + if (len == 192) { + dma_bm_read(desc->buf_addr1, buf, len, 1); + for (i = 0; i < 16; i++) { + tulip_setup_filter_addr(s, buf, i); + } + } + + desc->status = 0x7fffffff; + + if (desc->control & TDES1_IC) { + s->csr[5] |= CSR5_TI; + tulip_update_int(s); + } +} + +static void tulip_next_tx_descriptor(TULIPState *s, + struct tulip_descriptor *desc) +{ + if (desc->control & TDES1_TER) { + s->current_tx_desc = s->csr[4]; + } else if (desc->control & TDES1_TCH) { + s->current_tx_desc = desc->buf_addr2; + } else { + s->current_tx_desc += sizeof(struct tulip_descriptor) + + (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); + } + s->current_tx_desc &= ~3ULL; +} + +static uint32_t tulip_ts(TULIPState *s) +{ + return (s->csr[5] >> CSR5_TS_SHIFT) & CSR5_TS_MASK; +} + +static void tulip_xmit_list_update(TULIPState *s) +{ +#define TULIP_DESC_MAX 128 + uint8_t i = 0; + struct tulip_descriptor desc; + + if (tulip_ts(s) != CSR5_TS_SUSPENDED) { + return; + } + + for (i = 0; i < TULIP_DESC_MAX; i++) { + tulip_desc_read(s, s->current_tx_desc, &desc); + + if (!(desc.status & TDES0_OWN)) { + tulip_update_ts(s, CSR5_TS_SUSPENDED); + s->csr[5] |= CSR5_TU; + tulip_update_int(s); + return; + } + + if (desc.control & TDES1_SET) { + tulip_setup_frame(s, &desc); + } else { + if (desc.control & TDES1_FS) { + s->tx_frame_len = 0; + } + + if (!tulip_copy_tx_buffers(s, &desc)) { + if (desc.control & TDES1_LS) { + tulip_tx(s, &desc); + } + } + } + tulip_desc_write(s, s->current_tx_desc, &desc); + tulip_next_tx_descriptor(s, &desc); + } +} + +static void tulip_csr9_write(TULIPState *s, uint32_t old_val, + uint32_t new_val) +{ + if (new_val & CSR9_SR) { + nmc93cxx_eeprom_write(s->eeprom, + !!(new_val & CSR9_SR_CS), + !!(new_val & CSR9_SR_SK), + !!(new_val & CSR9_SR_DI)); + } +} + +static void tulip_reset(void* priv) +{ + TULIPState *s = (TULIPState*)priv; + uint16_t* eeprom_data = nmc93cxx_eeprom_data(s->eeprom); + s->csr[0] = 0xfe000000; + s->csr[1] = 0xffffffff; + s->csr[2] = 0xffffffff; + s->csr[5] = 0xf0000000; + s->csr[6] = 0x32000040; + s->csr[7] = 0xf3fe0000; + s->csr[8] = 0xe0000000; + s->csr[9] = 0xfff483ff; + s->csr[11] = 0xfffe0000; + s->csr[12] = 0x000000c6; + s->csr[13] = 0xffff0000; + s->csr[14] = 0xffffffff; + s->csr[15] = 0x8ff00000; + s->subsys_id = eeprom_data[1]; + s->subsys_ven_id = eeprom_data[0]; +} + +static void tulip_write(uint32_t addr, uint32_t data, void *opaque) +{ + TULIPState *s = opaque; + addr &= 127; + + switch (addr) { + case CSR(0): + s->csr[0] = data; + if (data & CSR0_SWR) { + tulip_reset(s); + tulip_update_int(s); + } + break; + + case CSR(1): + tulip_xmit_list_update(s); + break; + + case CSR(2): + break; + + case CSR(3): + s->csr[3] = data & ~3ULL; + s->current_rx_desc = s->csr[3]; + break; + + case CSR(4): + s->csr[4] = data & ~3ULL; + s->current_tx_desc = s->csr[4]; + tulip_xmit_list_update(s); + break; + + case CSR(5): + /* Status register, write clears bit */ + s->csr[5] &= ~(data & (CSR5_TI | CSR5_TPS | CSR5_TU | CSR5_TJT | + CSR5_LNP_ANC | CSR5_UNF | CSR5_RI | CSR5_RU | + CSR5_RPS | CSR5_RWT | CSR5_ETI | CSR5_GTE | + CSR5_LNF | CSR5_FBE | CSR5_ERI | CSR5_AIS | + CSR5_NIS | CSR5_GPI | CSR5_LC)); + tulip_update_int(s); + break; + + case CSR(6): + s->csr[6] = data; + if (s->csr[6] & CSR6_SR) { + tulip_update_rs(s, CSR5_RS_RUNNING_WAIT_RECEIVE); + } else { + tulip_update_rs(s, CSR5_RS_STOPPED); + } + + if (s->csr[6] & CSR6_ST) { + tulip_update_ts(s, CSR5_TS_SUSPENDED); + tulip_xmit_list_update(s); + } else { + tulip_update_ts(s, CSR5_TS_STOPPED); + } + break; + + case CSR(7): + s->csr[7] = data; + tulip_update_int(s); + break; + + case CSR(8): + s->csr[9] = data; + break; + + case CSR(9): + tulip_csr9_write(s, s->csr[9], data); + /* don't clear MII read data */ + s->csr[9] &= CSR9_MDI; + s->csr[9] |= (data & ~CSR9_MDI); + tulip_mii(s); + s->old_csr9 = s->csr[9]; + break; + + case CSR(10): + s->csr[10] = data; + break; + + case CSR(11): + s->csr[11] = data; + break; + + case CSR(12): + /* SIA Status register, some bits are cleared by writing 1 */ + s->csr[12] &= ~(data & (CSR12_MRA | CSR12_TRA | CSR12_ARA)); + break; + + case CSR(13): + s->csr[13] = data; + break; + + case CSR(14): + s->csr[14] = data; + break; + + case CSR(15): + s->csr[15] = data; + break; + + default: + pclog("%s: write to CSR at unknown address " + "0x%u\n", __func__, addr); + break; + } +} + +static void tulip_write_io(uint16_t addr, uint32_t data, void *opaque) +{ + return tulip_write(addr, data, opaque); +} + +static uint32_t tulip_read_io(uint16_t addr, void *opaque) +{ + return tulip_read(addr, opaque); +} + +static void tulip_idblock_crc(uint16_t *srom) +{ + int word; + int bit; + unsigned char bitval, crc; + const int len = 9; + crc = -1; + + for (word = 0; word < len; word++) { + for (bit = 15; bit >= 0; bit--) { + if ((word == (len - 1)) && (bit == 7)) { + /* + * Insert the correct CRC result into input data stream + * in place. + */ + srom[len - 1] = (srom[len - 1] & 0xff00) | (unsigned short)crc; + break; + } + bitval = ((srom[word] >> bit) & 1) ^ ((crc >> 7) & 1); + crc = crc << 1; + if (bitval == 1) { + crc ^= 6; + crc |= 0x01; + } + } + } +} + +static uint16_t tulip_srom_crc(uint8_t *eeprom, size_t len) +{ + unsigned long crc = 0xffffffff; + unsigned long flippedcrc = 0; + unsigned char currentbyte; + unsigned int msb, bit, i; + + for (i = 0; i < len; i++) { + currentbyte = eeprom[i]; + for (bit = 0; bit < 8; bit++) { + msb = (crc >> 31) & 1; + crc <<= 1; + if (msb ^ (currentbyte & 1)) { + crc ^= 0x04c11db6; + crc |= 0x00000001; + } + currentbyte >>= 1; + } + } + + for (i = 0; i < 32; i++) { + flippedcrc <<= 1; + bit = crc & 1; + crc >>= 1; + flippedcrc += bit; + } + return (flippedcrc ^ 0xffffffff) & 0xffff; +} + +static const uint8_t eeprom_default[128] = { + 0xf0, 0x11, 0x35, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x08, 0x04, 0x01, 0x00, 0x80, 0x48, 0xb3, + 0x0e, 0xa7, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, + 0x01, 0x8d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x78, + 0xe0, 0x01, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x6b, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x48, 0xb3, 0x0e, 0xa7, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static void tulip_fill_eeprom(TULIPState *s) +{ + uint16_t *eeprom = nmc93cxx_eeprom_data(s->eeprom); + memcpy(eeprom, eeprom_default, 128); + + tulip_idblock_crc(eeprom); + eeprom[63] = (tulip_srom_crc((uint8_t *)eeprom, 126)); +} + +static uint8_t tulip_pci_read(int func, int addr, void* p) +{ + TULIPState* s = (TULIPState*)p; + + switch(addr) { + default: + return s->pci_conf[addr & 0xFF]; + case 0x00: + return 0x11; + case 0x01: + return 0x10; + case 0x02: + return 0x19; + case 0x03: + return 0x00; + case 0x07: + return 0x02; + case 0x06: + return 0x80; + case 0x5: + return s->pci_conf[addr & 0xFF] & 1; + case 0x8: + return 0x30; + case 0x9: + return 0x0; + case 0xA: + return 0x0; + case 0xB: + return 0x2; + case 0x10: + return (s->pci_conf[addr & 0xFF] & 0x80) | 1; + case 0x14: + return s->pci_conf[addr & 0xFF] & 0x80; + case 0x2C: + return s->subsys_ven_id & 0xFF; + case 0x2D: + return s->subsys_ven_id >> 8; + case 0x2E: + return s->subsys_id & 0xFF; + case 0x2F: + return s->subsys_id >> 8; + case 0x3D: + return PCI_INTA; + } +} + +static void tulip_pci_write(int func, int addr, uint8_t val, void* p) +{ + TULIPState* s = (TULIPState*)p; + + switch (addr) + { + case 0x4: + mem_mapping_disable(&s->memory); + io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + s->pci_conf[addr & 0xFF] = val; + if (val & PCI_COMMAND_IO) + io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + if ((val & PCI_COMMAND_MEM) && s->memory.size) + mem_mapping_enable(&s->memory); + break; + case 0x5: + s->pci_conf[addr & 0xFF] = val & 1; + break; + case 0x10: + case 0x11: + io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + s->pci_conf[addr & 0xFF] = val; + if (s->pci_conf[0x4] & PCI_COMMAND_IO) + io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + s->pci_conf[addr & 0xFF] = val; + if (s->pci_conf[0x4] & PCI_COMMAND_MEM) + mem_mapping_set_addr(&s->memory, (s->pci_conf[0x14] & 0x80) | (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24), 128); + break; + case 0x3C: + s->pci_conf[addr & 0xFF] = val; + break; + } +} + +static void * +nic_init(const device_t *info) +{ + uint8_t eeprom_default_local[128]; + nmc93cxx_eeprom_params_t params; + TULIPState *s = calloc(1, sizeof(TULIPState)); + char filename[1024] = { 0 }; + + if (!s) + return NULL; + memcpy(eeprom_default_local, eeprom_default, sizeof(eeprom_default)); + tulip_idblock_crc((uint16_t*)eeprom_default_local); + (((uint16_t*)eeprom_default_local))[63] = (tulip_srom_crc((uint8_t *)eeprom_default_local, 126)); + + params.nwords = 64; + params.default_content = (uint16_t*)eeprom_default_local; + params.filename = filename; + snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, device_get_instance()); + s->eeprom = device_add_parameters(&nmc93cxx_device, ¶ms); + if (!s->eeprom) { + free(s); + return NULL; + } + memcpy(s->mii_regs, tulip_mdi_default, sizeof(tulip_mdi_default)); + s->nic = network_attach(s, (uint8_t*)&nmc93cxx_eeprom_data(s->eeprom)[10], tulip_receive, NULL); + s->dev = pci_add_card(PCI_ADD_NETWORK, tulip_pci_read, tulip_pci_write, s); + tulip_reset(s); + return s; +} + +static void +nic_close(void* priv) +{ + free(priv); +} + +const device_t dec_tulip_device = { + .name = "Compu-Shack FASTLine-II UTP 10/100", + .internal_name = "dec_21143_tulip", + .flags = DEVICE_PCI, + .local = 0, + .init = nic_init, + .close = nic_close, + .reset = tulip_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; \ No newline at end of file diff --git a/src/network/network.c b/src/network/network.c index eec85fcb0..06b70bf51 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -73,6 +73,7 @@ #include <86box/net_pcnet.h> #include <86box/net_plip.h> #include <86box/net_wd8003.h> +#include <86box/net_tulip.h> #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN @@ -116,6 +117,7 @@ static const device_t *net_cards[] = { &pcnet_am79c970a_device, &rtl8029as_device, &pcnet_am79c960_vlb_device, + &dec_tulip_device, NULL }; From 868a0b7f5fe41cf5f32910807cbb0fd8941903a3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Jul 2023 21:03:38 +0600 Subject: [PATCH 016/133] net_tulip.c: Code style changes (part 1) --- src/network/net_tulip.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 0d9f352c6..f9f56ec2e 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -747,10 +747,8 @@ static uint32_t tulip_read(uint32_t addr, void *opaque) break; default: - if (addr & 7) { - } else { + if (!(addr & 7)) data = s->csr[addr >> 3]; - } break; } return data; From 7abc05274da52a9efdf22821f0e14d64a9f9cfd2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Jul 2023 21:04:05 +0600 Subject: [PATCH 017/133] Format changes (part 2) --- src/network/net_tulip.c | 1284 ++++++++++++++++++++++----------------- 1 file changed, 737 insertions(+), 547 deletions(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index f9f56ec2e..6e042a028 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -17,259 +17,258 @@ #include <86box/net_tulip.h> #include <86box/bswap.h> -#define CSR(_x) ((_x) << 3) +#define CSR(_x) ((_x) << 3) -#define BIT(x) (1 << x) +#define BIT(x) (1 << x) -#define CSR0_SWR BIT(0) -#define CSR0_BAR BIT(1) -#define CSR0_DSL_SHIFT 2 -#define CSR0_DSL_MASK 0x1f -#define CSR0_BLE BIT(7) -#define CSR0_PBL_SHIFT 8 -#define CSR0_PBL_MASK 0x3f -#define CSR0_CAC_SHIFT 14 -#define CSR0_CAC_MASK 0x3 -#define CSR0_DAS 0x10000 -#define CSR0_TAP_SHIFT 17 -#define CSR0_TAP_MASK 0x7 -#define CSR0_DBO 0x100000 -#define CSR1_TPD 0x01 -#define CSR0_RLE BIT(23) -#define CSR0_WIE BIT(24) +#define CSR0_SWR BIT(0) +#define CSR0_BAR BIT(1) +#define CSR0_DSL_SHIFT 2 +#define CSR0_DSL_MASK 0x1f +#define CSR0_BLE BIT(7) +#define CSR0_PBL_SHIFT 8 +#define CSR0_PBL_MASK 0x3f +#define CSR0_CAC_SHIFT 14 +#define CSR0_CAC_MASK 0x3 +#define CSR0_DAS 0x10000 +#define CSR0_TAP_SHIFT 17 +#define CSR0_TAP_MASK 0x7 +#define CSR0_DBO 0x100000 +#define CSR1_TPD 0x01 +#define CSR0_RLE BIT(23) +#define CSR0_WIE BIT(24) -#define CSR2_RPD 0x01 +#define CSR2_RPD 0x01 -#define CSR5_TI BIT(0) -#define CSR5_TPS BIT(1) -#define CSR5_TU BIT(2) -#define CSR5_TJT BIT(3) -#define CSR5_LNP_ANC BIT(4) -#define CSR5_UNF BIT(5) -#define CSR5_RI BIT(6) -#define CSR5_RU BIT(7) -#define CSR5_RPS BIT(8) -#define CSR5_RWT BIT(9) -#define CSR5_ETI BIT(10) -#define CSR5_GTE BIT(11) -#define CSR5_LNF BIT(12) -#define CSR5_FBE BIT(13) -#define CSR5_ERI BIT(14) -#define CSR5_AIS BIT(15) -#define CSR5_NIS BIT(16) -#define CSR5_RS_SHIFT 17 -#define CSR5_RS_MASK 7 -#define CSR5_TS_SHIFT 20 -#define CSR5_TS_MASK 7 +#define CSR5_TI BIT(0) +#define CSR5_TPS BIT(1) +#define CSR5_TU BIT(2) +#define CSR5_TJT BIT(3) +#define CSR5_LNP_ANC BIT(4) +#define CSR5_UNF BIT(5) +#define CSR5_RI BIT(6) +#define CSR5_RU BIT(7) +#define CSR5_RPS BIT(8) +#define CSR5_RWT BIT(9) +#define CSR5_ETI BIT(10) +#define CSR5_GTE BIT(11) +#define CSR5_LNF BIT(12) +#define CSR5_FBE BIT(13) +#define CSR5_ERI BIT(14) +#define CSR5_AIS BIT(15) +#define CSR5_NIS BIT(16) +#define CSR5_RS_SHIFT 17 +#define CSR5_RS_MASK 7 +#define CSR5_TS_SHIFT 20 +#define CSR5_TS_MASK 7 -#define CSR5_TS_STOPPED 0 -#define CSR5_TS_RUNNING_FETCH 1 -#define CSR5_TS_RUNNING_WAIT_EOT 2 -#define CSR5_TS_RUNNING_READ_BUF 3 -#define CSR5_TS_RUNNING_SETUP 5 -#define CSR5_TS_SUSPENDED 6 -#define CSR5_TS_RUNNING_CLOSE 7 +#define CSR5_TS_STOPPED 0 +#define CSR5_TS_RUNNING_FETCH 1 +#define CSR5_TS_RUNNING_WAIT_EOT 2 +#define CSR5_TS_RUNNING_READ_BUF 3 +#define CSR5_TS_RUNNING_SETUP 5 +#define CSR5_TS_SUSPENDED 6 +#define CSR5_TS_RUNNING_CLOSE 7 -#define CSR5_RS_STOPPED 0 -#define CSR5_RS_RUNNING_FETCH 1 -#define CSR5_RS_RUNNING_CHECK_EOR 2 -#define CSR5_RS_RUNNING_WAIT_RECEIVE 3 -#define CSR5_RS_SUSPENDED 4 -#define CSR5_RS_RUNNING_CLOSE 5 -#define CSR5_RS_RUNNING_FLUSH 6 -#define CSR5_RS_RUNNING_QUEUE 7 +#define CSR5_RS_STOPPED 0 +#define CSR5_RS_RUNNING_FETCH 1 +#define CSR5_RS_RUNNING_CHECK_EOR 2 +#define CSR5_RS_RUNNING_WAIT_RECEIVE 3 +#define CSR5_RS_SUSPENDED 4 +#define CSR5_RS_RUNNING_CLOSE 5 +#define CSR5_RS_RUNNING_FLUSH 6 +#define CSR5_RS_RUNNING_QUEUE 7 -#define CSR5_EB_SHIFT 23 -#define CSR5_EB_MASK 7 +#define CSR5_EB_SHIFT 23 +#define CSR5_EB_MASK 7 -#define CSR5_GPI BIT(26) -#define CSR5_LC BIT(27) +#define CSR5_GPI BIT(26) +#define CSR5_LC BIT(27) -#define CSR6_HP BIT(0) -#define CSR6_SR BIT(1) -#define CSR6_HO BIT(2) -#define CSR6_PB BIT(3) -#define CSR6_IF BIT(4) -#define CSR6_SB BIT(5) -#define CSR6_PR BIT(6) -#define CSR6_PM BIT(7) -#define CSR6_FKD BIT(8) -#define CSR6_FD BIT(9) +#define CSR6_HP BIT(0) +#define CSR6_SR BIT(1) +#define CSR6_HO BIT(2) +#define CSR6_PB BIT(3) +#define CSR6_IF BIT(4) +#define CSR6_SB BIT(5) +#define CSR6_PR BIT(6) +#define CSR6_PM BIT(7) +#define CSR6_FKD BIT(8) +#define CSR6_FD BIT(9) -#define CSR6_OM_SHIFT 10 -#define CSR6_OM_MASK 3 -#define CSR6_OM_NORMAL 0 -#define CSR6_OM_INT_LOOPBACK 1 -#define CSR6_OM_EXT_LOOPBACK 2 +#define CSR6_OM_SHIFT 10 +#define CSR6_OM_MASK 3 +#define CSR6_OM_NORMAL 0 +#define CSR6_OM_INT_LOOPBACK 1 +#define CSR6_OM_EXT_LOOPBACK 2 -#define CSR6_FC BIT(12) -#define CSR6_ST BIT(13) +#define CSR6_FC BIT(12) +#define CSR6_ST BIT(13) +#define CSR6_TR_SHIFT 14 +#define CSR6_TR_MASK 3 +#define CSR6_TR_72 0 +#define CSR6_TR_96 1 +#define CSR6_TR_128 2 +#define CSR6_TR_160 3 -#define CSR6_TR_SHIFT 14 -#define CSR6_TR_MASK 3 -#define CSR6_TR_72 0 -#define CSR6_TR_96 1 -#define CSR6_TR_128 2 -#define CSR6_TR_160 3 +#define CSR6_CA BIT(17) +#define CSR6_RA BIT(30) +#define CSR6_SC BIT(31) -#define CSR6_CA BIT(17) -#define CSR6_RA BIT(30) -#define CSR6_SC BIT(31) +#define CSR7_TIM BIT(0) +#define CSR7_TSM BIT(1) +#define CSR7_TUM BIT(2) +#define CSR7_TJM BIT(3) +#define CSR7_LPM BIT(4) +#define CSR7_UNM BIT(5) +#define CSR7_RIM BIT(6) +#define CSR7_RUM BIT(7) +#define CSR7_RSM BIT(8) +#define CSR7_RWM BIT(9) +#define CSR7_TMM BIT(11) +#define CSR7_LFM BIT(12) +#define CSR7_SEM BIT(13) +#define CSR7_ERM BIT(14) +#define CSR7_AIM BIT(15) +#define CSR7_NIM BIT(16) -#define CSR7_TIM BIT(0) -#define CSR7_TSM BIT(1) -#define CSR7_TUM BIT(2) -#define CSR7_TJM BIT(3) -#define CSR7_LPM BIT(4) -#define CSR7_UNM BIT(5) -#define CSR7_RIM BIT(6) -#define CSR7_RUM BIT(7) -#define CSR7_RSM BIT(8) -#define CSR7_RWM BIT(9) -#define CSR7_TMM BIT(11) -#define CSR7_LFM BIT(12) -#define CSR7_SEM BIT(13) -#define CSR7_ERM BIT(14) -#define CSR7_AIM BIT(15) -#define CSR7_NIM BIT(16) +#define CSR8_MISSED_FRAME_OVL BIT(16) +#define CSR8_MISSED_FRAME_CNT_MASK 0xffff -#define CSR8_MISSED_FRAME_OVL BIT(16) -#define CSR8_MISSED_FRAME_CNT_MASK 0xffff +#define CSR9_DATA_MASK 0xff +#define CSR9_SR_CS BIT(0) +#define CSR9_SR_SK BIT(1) +#define CSR9_SR_DI BIT(2) +#define CSR9_SR_DO BIT(3) +#define CSR9_REG BIT(10) +#define CSR9_SR BIT(11) +#define CSR9_BR BIT(12) +#define CSR9_WR BIT(13) +#define CSR9_RD BIT(14) +#define CSR9_MOD BIT(15) +#define CSR9_MDC BIT(16) +#define CSR9_MDO BIT(17) +#define CSR9_MII BIT(18) +#define CSR9_MDI BIT(19) -#define CSR9_DATA_MASK 0xff -#define CSR9_SR_CS BIT(0) -#define CSR9_SR_SK BIT(1) -#define CSR9_SR_DI BIT(2) -#define CSR9_SR_DO BIT(3) -#define CSR9_REG BIT(10) -#define CSR9_SR BIT(11) -#define CSR9_BR BIT(12) -#define CSR9_WR BIT(13) -#define CSR9_RD BIT(14) -#define CSR9_MOD BIT(15) -#define CSR9_MDC BIT(16) -#define CSR9_MDO BIT(17) -#define CSR9_MII BIT(18) -#define CSR9_MDI BIT(19) +#define CSR11_CON BIT(16) +#define CSR11_TIMER_MASK 0xffff -#define CSR11_CON BIT(16) -#define CSR11_TIMER_MASK 0xffff +#define CSR12_MRA BIT(0) +#define CSR12_LS100 BIT(1) +#define CSR12_LS10 BIT(2) +#define CSR12_APS BIT(3) +#define CSR12_ARA BIT(8) +#define CSR12_TRA BIT(9) +#define CSR12_NSN BIT(10) +#define CSR12_TRF BIT(11) +#define CSR12_ANS_SHIFT 12 +#define CSR12_ANS_MASK 7 +#define CSR12_LPN BIT(15) +#define CSR12_LPC_SHIFT 16 +#define CSR12_LPC_MASK 0xffff -#define CSR12_MRA BIT(0) -#define CSR12_LS100 BIT(1) -#define CSR12_LS10 BIT(2) -#define CSR12_APS BIT(3) -#define CSR12_ARA BIT(8) -#define CSR12_TRA BIT(9) -#define CSR12_NSN BIT(10) -#define CSR12_TRF BIT(11) -#define CSR12_ANS_SHIFT 12 -#define CSR12_ANS_MASK 7 -#define CSR12_LPN BIT(15) -#define CSR12_LPC_SHIFT 16 -#define CSR12_LPC_MASK 0xffff +#define CSR13_SRL BIT(0) +#define CSR13_CAC BIT(2) +#define CSR13_AUI BIT(3) +#define CSR13_SDM_SHIFT 4 +#define CSR13_SDM_MASK 0xfff -#define CSR13_SRL BIT(0) -#define CSR13_CAC BIT(2) -#define CSR13_AUI BIT(3) -#define CSR13_SDM_SHIFT 4 -#define CSR13_SDM_MASK 0xfff +#define CSR14_ECEN BIT(0) +#define CSR14_LBK BIT(1) +#define CSR14_DREN BIT(2) +#define CSR14_LSE BIT(3) +#define CSR14_CPEN_SHIFT 4 +#define CSR14_CPEN_MASK 3 +#define CSR14_MBO BIT(6) +#define CSR14_ANE BIT(7) +#define CSR14_RSQ BIT(8) +#define CSR14_CSQ BIT(9) +#define CSR14_CLD BIT(10) +#define CSR14_SQE BIT(11) +#define CSR14_LTE BIT(12) +#define CSR14_APE BIT(13) +#define CSR14_SPP BIT(14) +#define CSR14_TAS BIT(15) -#define CSR14_ECEN BIT(0) -#define CSR14_LBK BIT(1) -#define CSR14_DREN BIT(2) -#define CSR14_LSE BIT(3) -#define CSR14_CPEN_SHIFT 4 -#define CSR14_CPEN_MASK 3 -#define CSR14_MBO BIT(6) -#define CSR14_ANE BIT(7) -#define CSR14_RSQ BIT(8) -#define CSR14_CSQ BIT(9) -#define CSR14_CLD BIT(10) -#define CSR14_SQE BIT(11) -#define CSR14_LTE BIT(12) -#define CSR14_APE BIT(13) -#define CSR14_SPP BIT(14) -#define CSR14_TAS BIT(15) +#define CSR15_JBD BIT(0) +#define CSR15_HUJ BIT(1) +#define CSR15_JCK BIT(2) +#define CSR15_ABM BIT(3) +#define CSR15_RWD BIT(4) +#define CSR15_RWR BIT(5) +#define CSR15_LE1 BIT(6) +#define CSR15_LV1 BIT(7) +#define CSR15_TSCK BIT(8) +#define CSR15_FUSQ BIT(9) +#define CSR15_FLF BIT(10) +#define CSR15_LSD BIT(11) +#define CSR15_DPST BIT(12) +#define CSR15_FRL BIT(13) +#define CSR15_LE2 BIT(14) +#define CSR15_LV2 BIT(15) -#define CSR15_JBD BIT(0) -#define CSR15_HUJ BIT(1) -#define CSR15_JCK BIT(2) -#define CSR15_ABM BIT(3) -#define CSR15_RWD BIT(4) -#define CSR15_RWR BIT(5) -#define CSR15_LE1 BIT(6) -#define CSR15_LV1 BIT(7) -#define CSR15_TSCK BIT(8) -#define CSR15_FUSQ BIT(9) -#define CSR15_FLF BIT(10) -#define CSR15_LSD BIT(11) -#define CSR15_DPST BIT(12) -#define CSR15_FRL BIT(13) -#define CSR15_LE2 BIT(14) -#define CSR15_LV2 BIT(15) +#define RDES0_OF BIT(0) +#define RDES0_CE BIT(1) +#define RDES0_DB BIT(2) +#define RDES0_RJ BIT(4) +#define RDES0_FT BIT(5) +#define RDES0_CS BIT(6) +#define RDES0_TL BIT(7) +#define RDES0_LS BIT(8) +#define RDES0_FS BIT(9) +#define RDES0_MF BIT(10) +#define RDES0_RF BIT(11) +#define RDES0_DT_SHIFT 12 +#define RDES0_DT_MASK 3 +#define RDES0_DE BIT(14) +#define RDES0_ES BIT(15) +#define RDES0_FL_SHIFT 16 +#define RDES0_FL_MASK 0x3fff +#define RDES0_FF BIT(30) +#define RDES0_OWN BIT(31) -#define RDES0_OF BIT(0) -#define RDES0_CE BIT(1) -#define RDES0_DB BIT(2) -#define RDES0_RJ BIT(4) -#define RDES0_FT BIT(5) -#define RDES0_CS BIT(6) -#define RDES0_TL BIT(7) -#define RDES0_LS BIT(8) -#define RDES0_FS BIT(9) -#define RDES0_MF BIT(10) -#define RDES0_RF BIT(11) -#define RDES0_DT_SHIFT 12 -#define RDES0_DT_MASK 3 -#define RDES0_DE BIT(14) -#define RDES0_ES BIT(15) -#define RDES0_FL_SHIFT 16 -#define RDES0_FL_MASK 0x3fff -#define RDES0_FF BIT(30) -#define RDES0_OWN BIT(31) +#define RDES1_BUF1_SIZE_SHIFT 0 +#define RDES1_BUF1_SIZE_MASK 0x7ff -#define RDES1_BUF1_SIZE_SHIFT 0 -#define RDES1_BUF1_SIZE_MASK 0x7ff +#define RDES1_BUF2_SIZE_SHIFT 11 +#define RDES1_BUF2_SIZE_MASK 0x7ff +#define RDES1_RCH BIT(24) +#define RDES1_RER BIT(25) -#define RDES1_BUF2_SIZE_SHIFT 11 -#define RDES1_BUF2_SIZE_MASK 0x7ff -#define RDES1_RCH BIT(24) -#define RDES1_RER BIT(25) +#define TDES0_DE BIT(0) +#define TDES0_UF BIT(1) +#define TDES0_LF BIT(2) +#define TDES0_CC_SHIFT 3 +#define TDES0_CC_MASK 0xf +#define TDES0_HF BIT(7) +#define TDES0_EC BIT(8) +#define TDES0_LC BIT(9) +#define TDES0_NC BIT(10) +#define TDES0_LO BIT(11) +#define TDES0_TO BIT(14) +#define TDES0_ES BIT(15) +#define TDES0_OWN BIT(31) -#define TDES0_DE BIT(0) -#define TDES0_UF BIT(1) -#define TDES0_LF BIT(2) -#define TDES0_CC_SHIFT 3 -#define TDES0_CC_MASK 0xf -#define TDES0_HF BIT(7) -#define TDES0_EC BIT(8) -#define TDES0_LC BIT(9) -#define TDES0_NC BIT(10) -#define TDES0_LO BIT(11) -#define TDES0_TO BIT(14) -#define TDES0_ES BIT(15) -#define TDES0_OWN BIT(31) +#define TDES1_BUF1_SIZE_SHIFT 0 +#define TDES1_BUF1_SIZE_MASK 0x7ff -#define TDES1_BUF1_SIZE_SHIFT 0 -#define TDES1_BUF1_SIZE_MASK 0x7ff +#define TDES1_BUF2_SIZE_SHIFT 11 +#define TDES1_BUF2_SIZE_MASK 0x7ff -#define TDES1_BUF2_SIZE_SHIFT 11 -#define TDES1_BUF2_SIZE_MASK 0x7ff +#define TDES1_FT0 BIT(22) +#define TDES1_DPD BIT(23) +#define TDES1_TCH BIT(24) +#define TDES1_TER BIT(25) +#define TDES1_AC BIT(26) +#define TDES1_SET BIT(27) +#define TDES1_FT1 BIT(28) +#define TDES1_FS BIT(29) +#define TDES1_LS BIT(30) +#define TDES1_IC BIT(31) -#define TDES1_FT0 BIT(22) -#define TDES1_DPD BIT(23) -#define TDES1_TCH BIT(24) -#define TDES1_TER BIT(25) -#define TDES1_AC BIT(26) -#define TDES1_SET BIT(27) -#define TDES1_FT1 BIT(28) -#define TDES1_FS BIT(29) -#define TDES1_LS BIT(30) -#define TDES1_IC BIT(31) - -#define ETH_ALEN 6 +#define ETH_ALEN 6 struct tulip_descriptor { uint32_t status; @@ -279,14 +278,14 @@ struct tulip_descriptor { }; struct TULIPState { - uint8_t dev; - uint16_t subsys_id, subsys_ven_id; - mem_mapping_t memory; - netcard_t *nic; + uint8_t dev; + uint16_t subsys_id, subsys_ven_id; + mem_mapping_t memory; + netcard_t *nic; nmc93cxx_eeprom_t *eeprom; - uint32_t csr[16]; - uint8_t pci_conf[256]; - uint16_t mii_regs[32]; + uint32_t csr[16]; + uint8_t pci_conf[256]; + uint16_t mii_regs[32]; /* state for MII */ uint32_t old_csr9; @@ -296,23 +295,24 @@ struct TULIPState { uint32_t current_rx_desc; uint32_t current_tx_desc; - uint8_t rx_frame[2048]; - uint8_t tx_frame[2048]; + uint8_t rx_frame[2048]; + uint8_t tx_frame[2048]; uint16_t tx_frame_len; uint16_t rx_frame_len; uint16_t rx_frame_size; uint32_t rx_status; - uint8_t filter[16][6]; + uint8_t filter[16][6]; }; typedef struct TULIPState TULIPState; -static void tulip_desc_read(TULIPState *s, uint32_t p, - struct tulip_descriptor *desc) +static void +tulip_desc_read(TULIPState *s, uint32_t p, + struct tulip_descriptor *desc) { - desc->status = mem_readl_phys(p); - desc->control = mem_readl_phys(p + 4); + desc->status = mem_readl_phys(p); + desc->control = mem_readl_phys(p + 4); desc->buf_addr1 = mem_readl_phys(p + 8); desc->buf_addr2 = mem_readl_phys(p + 12); @@ -324,8 +324,9 @@ static void tulip_desc_read(TULIPState *s, uint32_t p, } } -static void tulip_desc_write(TULIPState *s, uint32_t p, - struct tulip_descriptor *desc) +static void +tulip_desc_write(TULIPState *s, uint32_t p, + struct tulip_descriptor *desc) { if (s->csr[0] & CSR0_DBO) { mem_writel_phys(p, bswap32(desc->status)); @@ -340,10 +341,11 @@ static void tulip_desc_write(TULIPState *s, uint32_t p, } } -static void tulip_update_int(TULIPState *s) +static void +tulip_update_int(TULIPState *s) { - uint32_t ie = s->csr[5] & s->csr[7]; - bool assert = false; + uint32_t ie = s->csr[5] & s->csr[7]; + bool assert = false; s->csr[5] &= ~(CSR5_AIS | CSR5_NIS); @@ -351,9 +353,7 @@ static void tulip_update_int(TULIPState *s) s->csr[5] |= CSR5_NIS; } - if (ie & (CSR5_LC | CSR5_GPI | CSR5_FBE | CSR5_LNF | CSR5_ETI | CSR5_RWT | - CSR5_RPS | CSR5_RU | CSR5_UNF | CSR5_LNP_ANC | CSR5_TJT | - CSR5_TPS)) { + if (ie & (CSR5_LC | CSR5_GPI | CSR5_FBE | CSR5_LNF | CSR5_ETI | CSR5_RWT | CSR5_RPS | CSR5_RU | CSR5_UNF | CSR5_LNP_ANC | CSR5_TJT | CSR5_TPS)) { s->csr[5] |= CSR5_AIS; } @@ -364,26 +364,28 @@ static void tulip_update_int(TULIPState *s) pci_set_irq(s->dev, PCI_INTA); } -static bool tulip_rx_stopped(TULIPState *s) +static bool +tulip_rx_stopped(TULIPState *s) { return ((s->csr[5] >> CSR5_RS_SHIFT) & CSR5_RS_MASK) == CSR5_RS_STOPPED; } -static void tulip_next_rx_descriptor(TULIPState *s, - struct tulip_descriptor *desc) +static void +tulip_next_rx_descriptor(TULIPState *s, + struct tulip_descriptor *desc) { if (desc->control & RDES1_RER) { s->current_rx_desc = s->csr[3]; } else if (desc->control & RDES1_RCH) { s->current_rx_desc = desc->buf_addr2; } else { - s->current_rx_desc += sizeof(struct tulip_descriptor) + - (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); + s->current_rx_desc += sizeof(struct tulip_descriptor) + (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); } s->current_rx_desc &= ~3ULL; } -static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) +static void +tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) { int len1 = (desc->control >> RDES1_BUF1_SIZE_SHIFT) & RDES1_BUF1_SIZE_MASK; int len2 = (desc->control >> RDES1_BUF2_SIZE_SHIFT) & RDES1_BUF2_SIZE_MASK; @@ -396,8 +398,7 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) len = s->rx_frame_len; } - dma_bm_write(desc->buf_addr1, s->rx_frame + - (s->rx_frame_size - s->rx_frame_len), len, 1); + dma_bm_write(desc->buf_addr1, s->rx_frame + (s->rx_frame_size - s->rx_frame_len), len, 1); s->rx_frame_len -= len; } @@ -408,17 +409,17 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) len = s->rx_frame_len; } - dma_bm_write(desc->buf_addr2, s->rx_frame + - (s->rx_frame_size - s->rx_frame_len), len, 1); + dma_bm_write(desc->buf_addr2, s->rx_frame + (s->rx_frame_size - s->rx_frame_len), len, 1); s->rx_frame_len -= len; } } -static bool tulip_filter_address(TULIPState *s, const uint8_t *addr) +static bool +tulip_filter_address(TULIPState *s, const uint8_t *addr) { static const char broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - bool ret = false; - int i; + bool ret = false; + int i; for (i = 0; i < 16 && ret == false; i++) { if (!memcmp(&s->filter[i], addr, ETH_ALEN)) { @@ -448,10 +449,11 @@ static bool tulip_filter_address(TULIPState *s, const uint8_t *addr) return ret; } -static int tulip_receive(void* p, uint8_t *buf, int size) +static int +tulip_receive(void *p, uint8_t *buf, int size) { struct tulip_descriptor desc; - TULIPState *s = (TULIPState*)p; + TULIPState *s = (TULIPState *) p; if (size < 14 || size > sizeof(s->rx_frame) - 4 || s->rx_frame_len || tulip_rx_stopped(s)) { @@ -474,8 +476,7 @@ static int tulip_receive(void* p, uint8_t *buf, int size) if (!s->rx_frame_len) { s->rx_frame_size = size + 4; - s->rx_status = RDES0_LS | - ((s->rx_frame_size & RDES0_FL_MASK) << RDES0_FL_SHIFT); + s->rx_status = RDES0_LS | ((s->rx_frame_size & RDES0_FL_MASK) << RDES0_FL_SHIFT); desc.status |= RDES0_FS; memcpy(s->rx_frame, buf, size); s->rx_frame_len = s->rx_frame_size; @@ -494,127 +495,131 @@ static int tulip_receive(void* p, uint8_t *buf, int size) return 1; } -static const char *tulip_reg_name(const uint32_t addr) +static const char * +tulip_reg_name(const uint32_t addr) { switch (addr) { - case CSR(0): - return "CSR0"; + case CSR(0): + return "CSR0"; - case CSR(1): - return "CSR1"; + case CSR(1): + return "CSR1"; - case CSR(2): - return "CSR2"; + case CSR(2): + return "CSR2"; - case CSR(3): - return "CSR3"; + case CSR(3): + return "CSR3"; - case CSR(4): - return "CSR4"; + case CSR(4): + return "CSR4"; - case CSR(5): - return "CSR5"; + case CSR(5): + return "CSR5"; - case CSR(6): - return "CSR6"; + case CSR(6): + return "CSR6"; - case CSR(7): - return "CSR7"; + case CSR(7): + return "CSR7"; - case CSR(8): - return "CSR8"; + case CSR(8): + return "CSR8"; - case CSR(9): - return "CSR9"; + case CSR(9): + return "CSR9"; - case CSR(10): - return "CSR10"; + case CSR(10): + return "CSR10"; - case CSR(11): - return "CSR11"; + case CSR(11): + return "CSR11"; - case CSR(12): - return "CSR12"; + case CSR(12): + return "CSR12"; - case CSR(13): - return "CSR13"; + case CSR(13): + return "CSR13"; - case CSR(14): - return "CSR14"; + case CSR(14): + return "CSR14"; - case CSR(15): - return "CSR15"; + case CSR(15): + return "CSR15"; - default: - break; + default: + break; } return ""; } -static const char *tulip_rx_state_name(int state) +static const char * +tulip_rx_state_name(int state) { switch (state) { - case CSR5_RS_STOPPED: - return "STOPPED"; + case CSR5_RS_STOPPED: + return "STOPPED"; - case CSR5_RS_RUNNING_FETCH: - return "RUNNING/FETCH"; + case CSR5_RS_RUNNING_FETCH: + return "RUNNING/FETCH"; - case CSR5_RS_RUNNING_CHECK_EOR: - return "RUNNING/CHECK EOR"; + case CSR5_RS_RUNNING_CHECK_EOR: + return "RUNNING/CHECK EOR"; - case CSR5_RS_RUNNING_WAIT_RECEIVE: - return "WAIT RECEIVE"; + case CSR5_RS_RUNNING_WAIT_RECEIVE: + return "WAIT RECEIVE"; - case CSR5_RS_SUSPENDED: - return "SUSPENDED"; + case CSR5_RS_SUSPENDED: + return "SUSPENDED"; - case CSR5_RS_RUNNING_CLOSE: - return "RUNNING/CLOSE"; + case CSR5_RS_RUNNING_CLOSE: + return "RUNNING/CLOSE"; - case CSR5_RS_RUNNING_FLUSH: - return "RUNNING/FLUSH"; + case CSR5_RS_RUNNING_FLUSH: + return "RUNNING/FLUSH"; - case CSR5_RS_RUNNING_QUEUE: - return "RUNNING/QUEUE"; + case CSR5_RS_RUNNING_QUEUE: + return "RUNNING/QUEUE"; - default: - break; + default: + break; } return ""; } -static const char *tulip_tx_state_name(int state) +static const char * +tulip_tx_state_name(int state) { switch (state) { - case CSR5_TS_STOPPED: - return "STOPPED"; + case CSR5_TS_STOPPED: + return "STOPPED"; - case CSR5_TS_RUNNING_FETCH: - return "RUNNING/FETCH"; + case CSR5_TS_RUNNING_FETCH: + return "RUNNING/FETCH"; - case CSR5_TS_RUNNING_WAIT_EOT: - return "RUNNING/WAIT EOT"; + case CSR5_TS_RUNNING_WAIT_EOT: + return "RUNNING/WAIT EOT"; - case CSR5_TS_RUNNING_READ_BUF: - return "RUNNING/READ BUF"; + case CSR5_TS_RUNNING_READ_BUF: + return "RUNNING/READ BUF"; - case CSR5_TS_RUNNING_SETUP: - return "RUNNING/SETUP"; + case CSR5_TS_RUNNING_SETUP: + return "RUNNING/SETUP"; - case CSR5_TS_SUSPENDED: - return "SUSPENDED"; + case CSR5_TS_SUSPENDED: + return "SUSPENDED"; - case CSR5_TS_RUNNING_CLOSE: - return "RUNNING/CLOSE"; + case CSR5_TS_RUNNING_CLOSE: + return "RUNNING/CLOSE"; - default: - break; + default: + break; } return ""; } -static void tulip_update_rs(TULIPState *s, int state) +static void +tulip_update_rs(TULIPState *s, int state) { s->csr[5] &= ~(CSR5_RS_MASK << CSR5_RS_SHIFT); s->csr[5] |= (state & CSR5_RS_MASK) << CSR5_RS_SHIFT; @@ -622,23 +627,80 @@ static void tulip_update_rs(TULIPState *s, int state) static const uint16_t tulip_mdi_default[] = { /* MDI Registers 0 - 6, 7 */ - 0x3100, 0xf02c, 0x7810, 0x0000, 0x0501, 0x4181, 0x0000, 0x0000, + 0x3100, + 0xf02c, + 0x7810, + 0x0000, + 0x0501, + 0x4181, + 0x0000, + 0x0000, /* MDI Registers 8 - 15 */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, /* MDI Registers 16 - 31 */ - 0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0003, + 0x0000, + 0x0001, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, }; /* Readonly mask for MDI (PHY) registers */ static const uint16_t tulip_mdi_mask[] = { - 0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, + 0xffff, + 0xffff, + 0xffff, + 0xc01f, + 0xffff, + 0xffff, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0fff, + 0x0000, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, }; -static uint16_t tulip_mii_read(TULIPState *s, int phy, int reg) +static uint16_t +tulip_mii_read(TULIPState *s, int phy, int reg) { uint16_t ret = 0; if (phy == 1) { @@ -647,7 +709,8 @@ static uint16_t tulip_mii_read(TULIPState *s, int phy, int reg) return ret; } -static void tulip_mii_write(TULIPState *s, int phy, int reg, uint16_t data) +static void +tulip_mii_write(TULIPState *s, int phy, int reg, uint16_t data) { if (phy != 1) { return; @@ -657,11 +720,12 @@ static void tulip_mii_write(TULIPState *s, int phy, int reg, uint16_t data) s->mii_regs[reg] |= (data & tulip_mdi_mask[reg]); } -static void tulip_mii(TULIPState *s) +static void +tulip_mii(TULIPState *s) { uint32_t changed = s->old_csr9 ^ s->csr[9]; uint16_t data; - int op, phy, reg; + int op, phy, reg; if (!(changed & CSR9_MDC)) { return; @@ -674,8 +738,7 @@ static void tulip_mii(TULIPState *s) s->mii_bitcnt++; s->mii_word <<= 1; - if (s->csr[9] & CSR9_MDO && (s->mii_bitcnt < 16 || - !(s->csr[9] & CSR9_MII))) { + if (s->csr[9] & CSR9_MDO && (s->mii_bitcnt < 16 || !(s->csr[9] & CSR9_MII))) { /* write op or address bits */ s->mii_word |= 1; } @@ -691,7 +754,7 @@ static void tulip_mii(TULIPState *s) if (s->mii_word == 0xffffffff) { s->mii_bitcnt = 0; } else if (s->mii_bitcnt == 16) { - op = (s->mii_word >> 12) & 0x0f; + op = (s->mii_word >> 12) & 0x0f; phy = (s->mii_word >> 7) & 0x1f; reg = (s->mii_word >> 2) & 0x1f; @@ -699,10 +762,10 @@ static void tulip_mii(TULIPState *s) s->mii_word = tulip_mii_read(s, phy, reg); } } else if (s->mii_bitcnt == 32) { - op = (s->mii_word >> 28) & 0x0f; - phy = (s->mii_word >> 23) & 0x1f; - reg = (s->mii_word >> 18) & 0x1f; - data = s->mii_word & 0xffff; + op = (s->mii_word >> 28) & 0x0f; + phy = (s->mii_word >> 23) & 0x1f; + reg = (s->mii_word >> 18) & 0x1f; + data = s->mii_word & 0xffff; if (op == 5) { tulip_mii_write(s, phy, reg, data); @@ -710,7 +773,8 @@ static void tulip_mii(TULIPState *s) } } -static uint32_t tulip_csr9_read(TULIPState *s) +static uint32_t +tulip_csr9_read(TULIPState *s) { if (s->csr[9] & CSR9_SR) { if (nmc93cxx_eeprom_read(s->eeprom)) { @@ -724,37 +788,40 @@ static uint32_t tulip_csr9_read(TULIPState *s) return s->csr[9]; } -static void tulip_update_ts(TULIPState *s, int state) +static void +tulip_update_ts(TULIPState *s, int state) { - s->csr[5] &= ~(CSR5_TS_MASK << CSR5_TS_SHIFT); - s->csr[5] |= (state & CSR5_TS_MASK) << CSR5_TS_SHIFT; + s->csr[5] &= ~(CSR5_TS_MASK << CSR5_TS_SHIFT); + s->csr[5] |= (state & CSR5_TS_MASK) << CSR5_TS_SHIFT; } -static uint32_t tulip_read(uint32_t addr, void *opaque) +static uint32_t +tulip_read(uint32_t addr, void *opaque) { - TULIPState *s = opaque; - uint32_t data = 0; + TULIPState *s = opaque; + uint32_t data = 0; addr &= 127; switch (addr) { - case CSR(9): - data = tulip_csr9_read(s); - break; + case CSR(9): + data = tulip_csr9_read(s); + break; - case CSR(12): - /* Fake autocompletion complete until we have PHY emulation */ - data = 5 << CSR12_ANS_SHIFT; - break; + case CSR(12): + /* Fake autocompletion complete until we have PHY emulation */ + data = 5 << CSR12_ANS_SHIFT; + break; - default: - if (!(addr & 7)) - data = s->csr[addr >> 3]; - break; + default: + if (!(addr & 7)) + data = s->csr[addr >> 3]; + break; } return data; } -static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc) +static void +tulip_tx(TULIPState *s, struct tulip_descriptor *desc) { if (s->tx_frame_len) { if ((s->csr[6] >> CSR6_OM_SHIFT) & CSR6_OM_MASK) { @@ -771,7 +838,8 @@ static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc) } } -static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) +static int +tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) { int len1 = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK; @@ -781,7 +849,7 @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) } if (len1) { dma_bm_read(desc->buf_addr1, - s->tx_frame + s->tx_frame_len, len1, 1); + s->tx_frame + s->tx_frame_len, len1, 1); s->tx_frame_len += len1; } @@ -790,7 +858,7 @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) } if (len2) { dma_bm_read(desc->buf_addr2, - s->tx_frame + s->tx_frame_len, len2, 1); + s->tx_frame + s->tx_frame_len, len2, 1); s->tx_frame_len += len2; } desc->status = (len1 + len2) ? 0 : 0x7fffffff; @@ -798,7 +866,8 @@ static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) return 0; } -static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n) +static void +tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n) { int offset = n * 12; @@ -812,12 +881,13 @@ static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n) s->filter[n][5] = buf[offset + 9]; } -static void tulip_setup_frame(TULIPState *s, - struct tulip_descriptor *desc) +static void +tulip_setup_frame(TULIPState *s, + struct tulip_descriptor *desc) { uint8_t buf[4096]; - int len = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; - int i; + int len = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; + int i; if (len == 192) { dma_bm_read(desc->buf_addr1, buf, len, 1); @@ -834,29 +904,31 @@ static void tulip_setup_frame(TULIPState *s, } } -static void tulip_next_tx_descriptor(TULIPState *s, - struct tulip_descriptor *desc) +static void +tulip_next_tx_descriptor(TULIPState *s, + struct tulip_descriptor *desc) { if (desc->control & TDES1_TER) { s->current_tx_desc = s->csr[4]; } else if (desc->control & TDES1_TCH) { s->current_tx_desc = desc->buf_addr2; } else { - s->current_tx_desc += sizeof(struct tulip_descriptor) + - (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); + s->current_tx_desc += sizeof(struct tulip_descriptor) + (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); } s->current_tx_desc &= ~3ULL; } -static uint32_t tulip_ts(TULIPState *s) +static uint32_t +tulip_ts(TULIPState *s) { return (s->csr[5] >> CSR5_TS_SHIFT) & CSR5_TS_MASK; } -static void tulip_xmit_list_update(TULIPState *s) +static void +tulip_xmit_list_update(TULIPState *s) { #define TULIP_DESC_MAX 128 - uint8_t i = 0; + uint8_t i = 0; struct tulip_descriptor desc; if (tulip_ts(s) != CSR5_TS_SUSPENDED) { @@ -891,163 +963,166 @@ static void tulip_xmit_list_update(TULIPState *s) } } -static void tulip_csr9_write(TULIPState *s, uint32_t old_val, - uint32_t new_val) +static void +tulip_csr9_write(TULIPState *s, uint32_t old_val, + uint32_t new_val) { if (new_val & CSR9_SR) { nmc93cxx_eeprom_write(s->eeprom, - !!(new_val & CSR9_SR_CS), - !!(new_val & CSR9_SR_SK), - !!(new_val & CSR9_SR_DI)); + !!(new_val & CSR9_SR_CS), + !!(new_val & CSR9_SR_SK), + !!(new_val & CSR9_SR_DI)); } } -static void tulip_reset(void* priv) +static void +tulip_reset(void *priv) { - TULIPState *s = (TULIPState*)priv; - uint16_t* eeprom_data = nmc93cxx_eeprom_data(s->eeprom); - s->csr[0] = 0xfe000000; - s->csr[1] = 0xffffffff; - s->csr[2] = 0xffffffff; - s->csr[5] = 0xf0000000; - s->csr[6] = 0x32000040; - s->csr[7] = 0xf3fe0000; - s->csr[8] = 0xe0000000; - s->csr[9] = 0xfff483ff; - s->csr[11] = 0xfffe0000; - s->csr[12] = 0x000000c6; - s->csr[13] = 0xffff0000; - s->csr[14] = 0xffffffff; - s->csr[15] = 0x8ff00000; - s->subsys_id = eeprom_data[1]; - s->subsys_ven_id = eeprom_data[0]; + TULIPState *s = (TULIPState *) priv; + uint16_t *eeprom_data = nmc93cxx_eeprom_data(s->eeprom); + s->csr[0] = 0xfe000000; + s->csr[1] = 0xffffffff; + s->csr[2] = 0xffffffff; + s->csr[5] = 0xf0000000; + s->csr[6] = 0x32000040; + s->csr[7] = 0xf3fe0000; + s->csr[8] = 0xe0000000; + s->csr[9] = 0xfff483ff; + s->csr[11] = 0xfffe0000; + s->csr[12] = 0x000000c6; + s->csr[13] = 0xffff0000; + s->csr[14] = 0xffffffff; + s->csr[15] = 0x8ff00000; + s->subsys_id = eeprom_data[1]; + s->subsys_ven_id = eeprom_data[0]; } -static void tulip_write(uint32_t addr, uint32_t data, void *opaque) +static void +tulip_write(uint32_t addr, uint32_t data, void *opaque) { TULIPState *s = opaque; addr &= 127; switch (addr) { - case CSR(0): - s->csr[0] = data; - if (data & CSR0_SWR) { - tulip_reset(s); - tulip_update_int(s); - } - break; + case CSR(0): + s->csr[0] = data; + if (data & CSR0_SWR) { + tulip_reset(s); + tulip_update_int(s); + } + break; - case CSR(1): - tulip_xmit_list_update(s); - break; - - case CSR(2): - break; - - case CSR(3): - s->csr[3] = data & ~3ULL; - s->current_rx_desc = s->csr[3]; - break; - - case CSR(4): - s->csr[4] = data & ~3ULL; - s->current_tx_desc = s->csr[4]; - tulip_xmit_list_update(s); - break; - - case CSR(5): - /* Status register, write clears bit */ - s->csr[5] &= ~(data & (CSR5_TI | CSR5_TPS | CSR5_TU | CSR5_TJT | - CSR5_LNP_ANC | CSR5_UNF | CSR5_RI | CSR5_RU | - CSR5_RPS | CSR5_RWT | CSR5_ETI | CSR5_GTE | - CSR5_LNF | CSR5_FBE | CSR5_ERI | CSR5_AIS | - CSR5_NIS | CSR5_GPI | CSR5_LC)); - tulip_update_int(s); - break; - - case CSR(6): - s->csr[6] = data; - if (s->csr[6] & CSR6_SR) { - tulip_update_rs(s, CSR5_RS_RUNNING_WAIT_RECEIVE); - } else { - tulip_update_rs(s, CSR5_RS_STOPPED); - } - - if (s->csr[6] & CSR6_ST) { - tulip_update_ts(s, CSR5_TS_SUSPENDED); + case CSR(1): tulip_xmit_list_update(s); - } else { - tulip_update_ts(s, CSR5_TS_STOPPED); - } - break; + break; - case CSR(7): - s->csr[7] = data; - tulip_update_int(s); - break; + case CSR(2): + break; - case CSR(8): - s->csr[9] = data; - break; + case CSR(3): + s->csr[3] = data & ~3ULL; + s->current_rx_desc = s->csr[3]; + break; - case CSR(9): - tulip_csr9_write(s, s->csr[9], data); - /* don't clear MII read data */ - s->csr[9] &= CSR9_MDI; - s->csr[9] |= (data & ~CSR9_MDI); - tulip_mii(s); - s->old_csr9 = s->csr[9]; - break; + case CSR(4): + s->csr[4] = data & ~3ULL; + s->current_tx_desc = s->csr[4]; + tulip_xmit_list_update(s); + break; - case CSR(10): - s->csr[10] = data; - break; + case CSR(5): + /* Status register, write clears bit */ + s->csr[5] &= ~(data & (CSR5_TI | CSR5_TPS | CSR5_TU | CSR5_TJT | CSR5_LNP_ANC | CSR5_UNF | CSR5_RI | CSR5_RU | CSR5_RPS | CSR5_RWT | CSR5_ETI | CSR5_GTE | CSR5_LNF | CSR5_FBE | CSR5_ERI | CSR5_AIS | CSR5_NIS | CSR5_GPI | CSR5_LC)); + tulip_update_int(s); + break; - case CSR(11): - s->csr[11] = data; - break; + case CSR(6): + s->csr[6] = data; + if (s->csr[6] & CSR6_SR) { + tulip_update_rs(s, CSR5_RS_RUNNING_WAIT_RECEIVE); + } else { + tulip_update_rs(s, CSR5_RS_STOPPED); + } - case CSR(12): - /* SIA Status register, some bits are cleared by writing 1 */ - s->csr[12] &= ~(data & (CSR12_MRA | CSR12_TRA | CSR12_ARA)); - break; + if (s->csr[6] & CSR6_ST) { + tulip_update_ts(s, CSR5_TS_SUSPENDED); + tulip_xmit_list_update(s); + } else { + tulip_update_ts(s, CSR5_TS_STOPPED); + } + break; - case CSR(13): - s->csr[13] = data; - break; + case CSR(7): + s->csr[7] = data; + tulip_update_int(s); + break; - case CSR(14): - s->csr[14] = data; - break; + case CSR(8): + s->csr[9] = data; + break; - case CSR(15): - s->csr[15] = data; - break; + case CSR(9): + tulip_csr9_write(s, s->csr[9], data); + /* don't clear MII read data */ + s->csr[9] &= CSR9_MDI; + s->csr[9] |= (data & ~CSR9_MDI); + tulip_mii(s); + s->old_csr9 = s->csr[9]; + break; - default: - pclog("%s: write to CSR at unknown address " - "0x%u\n", __func__, addr); - break; + case CSR(10): + s->csr[10] = data; + break; + + case CSR(11): + s->csr[11] = data; + break; + + case CSR(12): + /* SIA Status register, some bits are cleared by writing 1 */ + s->csr[12] &= ~(data & (CSR12_MRA | CSR12_TRA | CSR12_ARA)); + break; + + case CSR(13): + s->csr[13] = data; + break; + + case CSR(14): + s->csr[14] = data; + break; + + case CSR(15): + s->csr[15] = data; + break; + + default: + pclog("%s: write to CSR at unknown address " + "0x%u\n", + __func__, addr); + break; } } -static void tulip_write_io(uint16_t addr, uint32_t data, void *opaque) +static void +tulip_write_io(uint16_t addr, uint32_t data, void *opaque) { return tulip_write(addr, data, opaque); } -static uint32_t tulip_read_io(uint16_t addr, void *opaque) +static uint32_t +tulip_read_io(uint16_t addr, void *opaque) { return tulip_read(addr, opaque); } -static void tulip_idblock_crc(uint16_t *srom) +static void +tulip_idblock_crc(uint16_t *srom) { - int word; - int bit; + int word; + int bit; unsigned char bitval, crc; - const int len = 9; - crc = -1; + const int len = 9; + crc = -1; for (word = 0; word < len; word++) { for (bit = 15; bit >= 0; bit--) { @@ -1056,11 +1131,11 @@ static void tulip_idblock_crc(uint16_t *srom) * Insert the correct CRC result into input data stream * in place. */ - srom[len - 1] = (srom[len - 1] & 0xff00) | (unsigned short)crc; + srom[len - 1] = (srom[len - 1] & 0xff00) | (unsigned short) crc; break; } bitval = ((srom[word] >> bit) & 1) ^ ((crc >> 7) & 1); - crc = crc << 1; + crc = crc << 1; if (bitval == 1) { crc ^= 6; crc |= 0x01; @@ -1069,12 +1144,13 @@ static void tulip_idblock_crc(uint16_t *srom) } } -static uint16_t tulip_srom_crc(uint8_t *eeprom, size_t len) +static uint16_t +tulip_srom_crc(uint8_t *eeprom, size_t len) { - unsigned long crc = 0xffffffff; + unsigned long crc = 0xffffffff; unsigned long flippedcrc = 0; unsigned char currentbyte; - unsigned int msb, bit, i; + unsigned int msb, bit, i; for (i = 0; i < len; i++) { currentbyte = eeprom[i]; @@ -1099,38 +1175,152 @@ static uint16_t tulip_srom_crc(uint8_t *eeprom, size_t len) } static const uint8_t eeprom_default[128] = { - 0xf0, 0x11, 0x35, 0x42, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x56, 0x08, 0x04, 0x01, 0x00, 0x80, 0x48, 0xb3, - 0x0e, 0xa7, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, - 0x01, 0x8d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x78, - 0xe0, 0x01, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x6b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x48, 0xb3, 0x0e, 0xa7, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, + 0x11, + 0x35, + 0x42, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x56, + 0x08, + 0x04, + 0x01, + 0x00, + 0x80, + 0x48, + 0xb3, + 0x0e, + 0xa7, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x08, + 0x01, + 0x8d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x78, + 0xe0, + 0x01, + 0x00, + 0x50, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe8, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x48, + 0xb3, + 0x0e, + 0xa7, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, }; -static void tulip_fill_eeprom(TULIPState *s) +static void +tulip_fill_eeprom(TULIPState *s) { uint16_t *eeprom = nmc93cxx_eeprom_data(s->eeprom); memcpy(eeprom, eeprom_default, 128); tulip_idblock_crc(eeprom); - eeprom[63] = (tulip_srom_crc((uint8_t *)eeprom, 126)); + eeprom[63] = (tulip_srom_crc((uint8_t *) eeprom, 126)); } -static uint8_t tulip_pci_read(int func, int addr, void* p) +static uint8_t +tulip_pci_read(int func, int addr, void *p) { - TULIPState* s = (TULIPState*)p; + TULIPState *s = (TULIPState *) p; - switch(addr) { + switch (addr) { default: return s->pci_conf[addr & 0xFF]; case 0x00: @@ -1172,12 +1362,12 @@ static uint8_t tulip_pci_read(int func, int addr, void* p) } } -static void tulip_pci_write(int func, int addr, uint8_t val, void* p) +static void +tulip_pci_write(int func, int addr, uint8_t val, void *p) { - TULIPState* s = (TULIPState*)p; + TULIPState *s = (TULIPState *) p; - switch (addr) - { + switch (addr) { case 0x4: mem_mapping_disable(&s->memory); io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); @@ -1214,20 +1404,20 @@ static void tulip_pci_write(int func, int addr, uint8_t val, void* p) static void * nic_init(const device_t *info) { - uint8_t eeprom_default_local[128]; + uint8_t eeprom_default_local[128]; nmc93cxx_eeprom_params_t params; - TULIPState *s = calloc(1, sizeof(TULIPState)); - char filename[1024] = { 0 }; + TULIPState *s = calloc(1, sizeof(TULIPState)); + char filename[1024] = { 0 }; if (!s) return NULL; memcpy(eeprom_default_local, eeprom_default, sizeof(eeprom_default)); - tulip_idblock_crc((uint16_t*)eeprom_default_local); - (((uint16_t*)eeprom_default_local))[63] = (tulip_srom_crc((uint8_t *)eeprom_default_local, 126)); - - params.nwords = 64; - params.default_content = (uint16_t*)eeprom_default_local; - params.filename = filename; + tulip_idblock_crc((uint16_t *) eeprom_default_local); + (((uint16_t *) eeprom_default_local))[63] = (tulip_srom_crc((uint8_t *) eeprom_default_local, 126)); + + params.nwords = 64; + params.default_content = (uint16_t *) eeprom_default_local; + params.filename = filename; snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, device_get_instance()); s->eeprom = device_add_parameters(&nmc93cxx_device, ¶ms); if (!s->eeprom) { @@ -1235,14 +1425,14 @@ nic_init(const device_t *info) return NULL; } memcpy(s->mii_regs, tulip_mdi_default, sizeof(tulip_mdi_default)); - s->nic = network_attach(s, (uint8_t*)&nmc93cxx_eeprom_data(s->eeprom)[10], tulip_receive, NULL); + s->nic = network_attach(s, (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[10], tulip_receive, NULL); s->dev = pci_add_card(PCI_ADD_NETWORK, tulip_pci_read, tulip_pci_write, s); tulip_reset(s); return s; } static void -nic_close(void* priv) +nic_close(void *priv) { free(priv); } From 42e53cb180b8264b0cb14c02ad063eeb2a51a7dd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Jul 2023 21:06:09 +0600 Subject: [PATCH 018/133] net_tulip.c: Change name of adapter for clarity --- src/network/net_tulip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 6e042a028..b7a5956b3 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -1438,7 +1438,7 @@ nic_close(void *priv) } const device_t dec_tulip_device = { - .name = "Compu-Shack FASTLine-II UTP 10/100", + .name = "Compu-Shack FASTLine-II UTP 10/100 (DECchip 21143 \"Tulip\")", .internal_name = "dec_21143_tulip", .flags = DEVICE_PCI, .local = 0, From 4e038fa5fa24ff56f456f1fa469d7127097f294c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Jul 2023 21:15:36 +0600 Subject: [PATCH 019/133] MII status changes --- src/network/net_tulip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index b7a5956b3..8c73c4fc2 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -646,7 +646,7 @@ static const uint16_t tulip_mdi_default[] = { 0x0000, /* MDI Registers 16 - 31 */ 0x0003, - 0x0000, + 0x0600, 0x0001, 0x0000, 0x0000, From 96d2de125f0116da71864c2df4857b18672362ea Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Jul 2023 17:32:57 +0200 Subject: [PATCH 020/133] Update version to 4.1. --- CMakeLists.txt | 2 +- debian/changelog | 4 ++-- src/include_make/86box/version.h | 6 +++--- src/unix/assets/86Box.spec | 4 ++-- src/unix/assets/net.86box.86Box.metainfo.xml | 2 +- vcpkg.json | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8af57ca9a..866933e32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 4.0 + VERSION 4.1 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) diff --git a/debian/changelog b/debian/changelog index 1bca318dd..c9ba78f12 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -86box (4.0) UNRELEASED; urgency=medium +86box (4.1) UNRELEASED; urgency=medium * Bump release. - -- Jasmine Iwanek Tue, 28 Feb 2023 00:02:16 -0500 + -- Jasmine Iwanek Sat, 29 Jul 2023 17:32:30 +0200 diff --git a/src/include_make/86box/version.h b/src/include_make/86box/version.h index 96e81ce5f..9a175be24 100644 --- a/src/include_make/86box/version.h +++ b/src/include_make/86box/version.h @@ -22,11 +22,11 @@ #define EMU_NAME "86Box" #define EMU_NAME_W LSTR(EMU_NAME) -#define EMU_VERSION "4.0" +#define EMU_VERSION "4.1" #define EMU_VERSION_W LSTR(EMU_VERSION) #define EMU_VERSION_EX "3.50" /* frozen due to IDE re-detection behavior on Windows */ #define EMU_VERSION_MAJ 4 -#define EMU_VERSION_MIN 0 +#define EMU_VERSION_MIN 1 #define EMU_VERSION_PATCH 0 #define EMU_BUILD_NUM 0 @@ -42,7 +42,7 @@ #define EMU_ROMS_URL "https://github.com/86Box/roms/releases/latest" #define EMU_ROMS_URL_W LSTR(EMU_ROMS_URL) #ifdef RELEASE_BUILD -# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v4.0/" +# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v4.1/" #else # define EMU_DOCS_URL "https://86box.readthedocs.io" #endif diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index ede0d5bb6..aabed20b2 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -15,7 +15,7 @@ %global romver 3.11 Name: 86Box -Version: 4.0 +Version: 4.1 Release: 1%{?dist} Summary: Classic PC emulator License: GPLv2+ @@ -118,5 +118,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Tue Feb 28 2023 Robert de Rooy 4.0-1 +* Sat Jul 29 2023 Robert de Rooy 4.1-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index 59671d0f9..d17c10986 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -10,7 +10,7 @@ net.86box.86Box.desktop - + diff --git a/vcpkg.json b/vcpkg.json index f9cf6783c..6342a076a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "86box", - "version-string": "4.0", + "version-string": "4.1", "homepage": "https://86box.net/", "documentation": "https://86box.readthedocs.io/", "license": "GPL-2.0-or-later", From 5671b0b6794adacb795009847f322d2af198d3eb Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Jul 2023 22:35:57 +0600 Subject: [PATCH 021/133] net_tulip.c: Copyright header --- src/network/net_tulip.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 8c73c4fc2..c599a69db 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -1,3 +1,20 @@ +/* + * 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. + * + * Emulation of DECchip "Tulip" 21143 NIC. + * + * + * Authors: Cacodemon345 + * + * Copyright 2023 Cacodemon345 + */ + +/* Ported over from QEMU */ #include #include #include @@ -1449,4 +1466,4 @@ const device_t dec_tulip_device = { .speed_changed = NULL, .force_redraw = NULL, .config = NULL -}; \ No newline at end of file +}; From 2d3d99aec09f3fd4a035399f02054abed6cd50f5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 31 Jul 2023 01:43:47 +0600 Subject: [PATCH 022/133] net_eeprom_nmc93cxx.c: Proper logging --- src/network/net_eeprom_nmc93cxx.c | 42 +++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index 66f9a6fdb..d31b7f8cd 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -48,7 +48,23 @@ struct nmc93cxx_eeprom_t { typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t; -#define logout pclog +#ifdef ENABLE_NMC93CXX_EEPROM_LOG +int nmc93cxx_eeprom_do_log = ENABLE_NMC93CXX_EEPROM_LOG; + +static void +nmc93cxx_eeprom_log(int lvl, const char *fmt, ...) +{ + va_list ap; + + if (nmc93cxx_eeprom_do_log >= lvl) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define nmc93cxx_eeprom_log(lvl, fmt, ...) +#endif static const char *opstring[] = { "extended", "write", "read", "erase" @@ -114,12 +130,12 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee uint16_t address = eeprom->address; uint8_t command = eeprom->command; - logout("CS=%u SK=%u DI=%u DO=%u, tick = %u\n", + nmc93cxx_eeprom_log(1, "CS=%u SK=%u DI=%u DO=%u, tick = %u\n", eecs, eesk, eedi, eedo, tick); if (!eeprom->eecs && eecs) { /* Start chip select cycle. */ - logout("Cycle start, waiting for 1st start bit (0)\n"); + nmc93cxx_eeprom_log(1, "Cycle start, waiting for 1st start bit (0)\n"); tick = 0; command = 0x0; address = 0x0; @@ -154,20 +170,20 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee if (tick == 0) { /* Wait for 1st start bit. */ if (eedi == 0) { - logout("Got correct 1st start bit, waiting for 2nd start bit (1)\n"); + nmc93cxx_eeprom_log(1, "Got correct 1st start bit, waiting for 2nd start bit (1)\n"); tick++; } else { - logout("wrong 1st start bit (is 1, should be 0)\n"); + nmc93cxx_eeprom_log(1, "wrong 1st start bit (is 1, should be 0)\n"); tick = 2; //~ assert(!"wrong start bit"); } } else if (tick == 1) { /* Wait for 2nd start bit. */ if (eedi != 0) { - logout("Got correct 2nd start bit, getting command + address\n"); + nmc93cxx_eeprom_log(1, "Got correct 2nd start bit, getting command + address\n"); tick++; } else { - logout("1st start bit is longer than needed\n"); + nmc93cxx_eeprom_log(1, "1st start bit is longer than needed\n"); } } else if (tick < 2 + 2) { /* Got 2 start bits, transfer 2 opcode bits. */ @@ -181,7 +197,7 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee tick++; address = ((address << 1) | eedi); if (tick == 2 + 2 + eeprom->addrbits) { - logout("%s command, address = 0x%02x (value 0x%04x)\n", + nmc93cxx_eeprom_log(1, "%s command, address = 0x%02x (value 0x%04x)\n", opstring[command], address, eeprom->contents[address]); if (command == 2) { eedo = 0; @@ -191,17 +207,17 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee /* Command code in upper 2 bits of address. */ switch (address >> (eeprom->addrbits - 2)) { case 0: - logout("write disable command\n"); + nmc93cxx_eeprom_log(1, "write disable command\n"); eeprom->writable = 0; break; case 1: - logout("write all command\n"); + nmc93cxx_eeprom_log(1, "write all command\n"); break; case 2: - logout("erase all command\n"); + nmc93cxx_eeprom_log(1, "erase all command\n"); break; case 3: - logout("write enable command\n"); + nmc93cxx_eeprom_log(1, "write enable command\n"); eeprom->writable = 1; break; } @@ -220,7 +236,7 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee eeprom->data <<= 1; eeprom->data += eedi; } else { - logout("additional unneeded tick, not processed\n"); + nmc93cxx_eeprom_log(1, "additional unneeded tick, not processed\n"); } } /* Save status of EEPROM. */ From f3233c4eb53a93571b57604f72719eaf071d9ab0 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 31 Jul 2023 02:04:53 +0600 Subject: [PATCH 023/133] Port Realtek RTL8139C emulation from QEMU --- src/include/86box/net_rtl8139.h | 1 + src/network/CMakeLists.txt | 2 +- src/network/net_rtl8139.c | 3337 +++++++++++++++++++++++++++++++ src/network/network.c | 2 + 4 files changed, 3341 insertions(+), 1 deletion(-) create mode 100644 src/include/86box/net_rtl8139.h create mode 100644 src/network/net_rtl8139.c diff --git a/src/include/86box/net_rtl8139.h b/src/include/86box/net_rtl8139.h new file mode 100644 index 000000000..420b07b4f --- /dev/null +++ b/src/include/86box/net_rtl8139.h @@ -0,0 +1 @@ +extern const device_t rtl8139c_device; \ No newline at end of file diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 6b6340334..0920fcf26 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -15,7 +15,7 @@ set(net_sources) list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c - net_eeprom_nmc93cxx.c net_tulip.c) + net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c) find_package(PkgConfig REQUIRED) pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c new file mode 100644 index 000000000..144af7845 --- /dev/null +++ b/src/network/net_rtl8139.c @@ -0,0 +1,3337 @@ +/* + * 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. + * + * Emulation of Realtek RTL8139C NIC. + * + * + * Authors: Cacodemon345 + * + * Copyright 2023 Cacodemon345 + */ + +/* Ported over from QEMU */ +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/pci.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/dma.h> +#include <86box/device.h> +#include <86box/thread.h> +#include <86box/network.h> +#include <86box/bswap.h> +#include <86box/nvr.h> +#include <86box/net_rtl8139.h> + +#define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ + +#define SET_MASKED(input, mask, curr) \ + ( ( (input) & ~(mask) ) | ( (curr) & (mask) ) ) + +/* arg % size for size which is a power of 2 */ +#define MOD2(input, size) \ + ( ( input ) & ( size - 1 ) ) + +#define ETHER_TYPE_LEN 2 + +#define VLAN_TCI_LEN 2 +#define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) + +#if defined (DEBUG_RTL8139) +# define DPRINTF(fmt, ...) \ + do { pclog("RTL8139: " fmt, ## __VA_ARGS__); } while (0) +#else +static inline __attribute__ ((format (printf, 1, 2))) int DPRINTF(const char *fmt, ...) +{ + return 0; +} +#endif + +struct RTL8139State; +typedef struct RTL8139State RTL8139State; + +/* Symbolic offsets to registers. */ +enum RTL8139_registers { + MAC0 = 0, /* Ethernet hardware address. */ + MAR0 = 8, /* Multicast filter. */ + TxStatus0 = 0x10,/* Transmit status (Four 32bit registers). C mode only */ + /* Dump Tally Conter control register(64bit). C+ mode only */ + TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ + RxBuf = 0x30, + ChipCmd = 0x37, + RxBufPtr = 0x38, + RxBufAddr = 0x3A, + IntrMask = 0x3C, + IntrStatus = 0x3E, + TxConfig = 0x40, + RxConfig = 0x44, + Timer = 0x48, /* A general-purpose counter. */ + RxMissed = 0x4C, /* 24 bits valid, write clears. */ + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + FlashReg = 0x54, + MediaStatus = 0x58, + Config3 = 0x59, + Config4 = 0x5A, /* absent on RTL-8139A */ + HltClk = 0x5B, + MultiIntr = 0x5C, + PCIRevisionID = 0x5E, + TxSummary = 0x60, /* TSAD register. Transmit Status of All Descriptors*/ + BasicModeCtrl = 0x62, + BasicModeStatus = 0x64, + NWayAdvert = 0x66, + NWayLPAR = 0x68, + NWayExpansion = 0x6A, + /* Undocumented registers, but required for proper operation. */ + FIFOTMS = 0x70, /* FIFO Control and test. */ + CSCR = 0x74, /* Chip Status and Configuration Register. */ + PARA78 = 0x78, + PARA7c = 0x7c, /* Magic transceiver parameter register. */ + Config5 = 0xD8, /* absent on RTL-8139A */ + /* C+ mode */ + TxPoll = 0xD9, /* Tell chip to check Tx descriptors for work */ + RxMaxSize = 0xDA, /* Max size of an Rx packet (8169 only) */ + CpCmd = 0xE0, /* C+ Command register (C+ mode only) */ + IntrMitigate = 0xE2, /* rx/tx interrupt mitigation control */ + RxRingAddrLO = 0xE4, /* 64-bit start addr of Rx ring */ + RxRingAddrHI = 0xE8, /* 64-bit start addr of Rx ring */ + TxThresh = 0xEC, /* Early Tx threshold */ +}; + +enum ClearBitMasks { + MultiIntrClear = 0xF000, + ChipCmdClear = 0xE2, + Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), +}; + +enum ChipCmdBits { + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, + RxBufEmpty = 0x01, +}; + +/* C+ mode */ +enum CplusCmdBits { + CPlusRxVLAN = 0x0040, /* enable receive VLAN detagging */ + CPlusRxChkSum = 0x0020, /* enable receive checksum offloading */ + CPlusRxEnb = 0x0002, + CPlusTxEnb = 0x0001, +}; + +/* Interrupt register bits, using my own meaningful names. */ +enum IntrStatusBits { + PCIErr = 0x8000, + PCSTimeout = 0x4000, + RxFIFOOver = 0x40, + RxUnderrun = 0x20, /* Packet Underrun / Link Change */ + RxOverflow = 0x10, + TxErr = 0x08, + TxOK = 0x04, + RxErr = 0x02, + RxOK = 0x01, + + RxAckBits = RxFIFOOver | RxOverflow | RxOK, +}; + +enum TxStatusBits { + TxHostOwns = 0x2000, + TxUnderrun = 0x4000, + TxStatOK = 0x8000, + TxOutOfWindow = 0x20000000, + TxAborted = 0x40000000, + TxCarrierLost = 0x80000000, +}; +enum RxStatusBits { + RxMulticast = 0x8000, + RxPhysical = 0x4000, + RxBroadcast = 0x2000, + RxBadSymbol = 0x0020, + RxRunt = 0x0010, + RxTooLong = 0x0008, + RxCRCErr = 0x0004, + RxBadAlign = 0x0002, + RxStatusOK = 0x0001, +}; + +/* Bits in RxConfig. */ +enum rx_mode_bits { + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0x08, + AcceptMulticast = 0x04, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, +}; + +/* Bits in TxConfig. */ +enum tx_config_bits { + + /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ + TxIFGShift = 24, + TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ + TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ + TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ + TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ + + TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ + TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ + TxClearAbt = (1 << 0), /* Clear abort (WO) */ + TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ + TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ + + TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ +}; + + +/* Transmit Status of All Descriptors (TSAD) Register */ +enum TSAD_bits { + TSAD_TOK3 = 1<<15, // TOK bit of Descriptor 3 + TSAD_TOK2 = 1<<14, // TOK bit of Descriptor 2 + TSAD_TOK1 = 1<<13, // TOK bit of Descriptor 1 + TSAD_TOK0 = 1<<12, // TOK bit of Descriptor 0 + TSAD_TUN3 = 1<<11, // TUN bit of Descriptor 3 + TSAD_TUN2 = 1<<10, // TUN bit of Descriptor 2 + TSAD_TUN1 = 1<<9, // TUN bit of Descriptor 1 + TSAD_TUN0 = 1<<8, // TUN bit of Descriptor 0 + TSAD_TABT3 = 1<<07, // TABT bit of Descriptor 3 + TSAD_TABT2 = 1<<06, // TABT bit of Descriptor 2 + TSAD_TABT1 = 1<<05, // TABT bit of Descriptor 1 + TSAD_TABT0 = 1<<04, // TABT bit of Descriptor 0 + TSAD_OWN3 = 1<<03, // OWN bit of Descriptor 3 + TSAD_OWN2 = 1<<02, // OWN bit of Descriptor 2 + TSAD_OWN1 = 1<<01, // OWN bit of Descriptor 1 + TSAD_OWN0 = 1<<00, // OWN bit of Descriptor 0 +}; + + +/* Bits in Config1 */ +enum Config1Bits { + Cfg1_PM_Enable = 0x01, + Cfg1_VPD_Enable = 0x02, + Cfg1_PIO = 0x04, + Cfg1_MMIO = 0x08, + LWAKE = 0x10, /* not on 8139, 8139A */ + Cfg1_Driver_Load = 0x20, + Cfg1_LED0 = 0x40, + Cfg1_LED1 = 0x80, + SLEEP = (1 << 1), /* only on 8139, 8139A */ + PWRDN = (1 << 0), /* only on 8139, 8139A */ +}; + +/* Bits in Config3 */ +enum Config3Bits { + Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */ + Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */ + Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */ + Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */ + Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */ + Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */ + Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */ + Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */ +}; + +/* Bits in Config4 */ +enum Config4Bits { + LWPTN = (1 << 2), /* not on 8139, 8139A */ +}; + +/* Bits in Config5 */ +enum Config5Bits { + Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */ + Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */ + Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */ + Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */ + Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */ + Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */ + Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */ +}; + +enum RxConfigBits { + /* rx fifo threshold */ + RxCfgFIFOShift = 13, + RxCfgFIFONone = (7 << RxCfgFIFOShift), + + /* Max DMA burst */ + RxCfgDMAShift = 8, + RxCfgDMAUnlimited = (7 << RxCfgDMAShift), + + /* rx ring buffer length */ + RxCfgRcv8K = 0, + RxCfgRcv16K = (1 << 11), + RxCfgRcv32K = (1 << 12), + RxCfgRcv64K = (1 << 11) | (1 << 12), + + /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */ + RxNoWrap = (1 << 7), +}; + +/* Twister tuning parameters from RealTek. + Completely undocumented, but required to tune bad links on some boards. */ +/* +enum CSCRBits { + CSCR_LinkOKBit = 0x0400, + CSCR_LinkChangeBit = 0x0800, + CSCR_LinkStatusBits = 0x0f000, + CSCR_LinkDownOffCmd = 0x003c0, + CSCR_LinkDownCmd = 0x0f3c0, +*/ +enum CSCRBits { + CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ + CSCR_LD = 1<<9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ + CSCR_HEART_BIT = 1<<8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/ + CSCR_JBEN = 1<<7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/ + CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/ + CSCR_F_Connect = 1<<5, /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/ + CSCR_Con_status = 1<<3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/ + CSCR_Con_status_En = 1<<2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/ + CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/ +}; + +enum Cfg9346Bits { + Cfg9346_Normal = 0x00, + Cfg9346_Autoload = 0x40, + Cfg9346_Programming = 0x80, + Cfg9346_ConfigWrite = 0xC0, +}; + +typedef enum { + CH_8139 = 0, + CH_8139_K, + CH_8139A, + CH_8139A_G, + CH_8139B, + CH_8130, + CH_8139C, + CH_8100, + CH_8100B_8139D, + CH_8101, +} chip_t; + +enum chip_flags { + HasHltClk = (1 << 0), + HasLWake = (1 << 1), +}; + +#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ + (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) +#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) + +#define RTL8139_PCI_REVID_8139 0x10 +#define RTL8139_PCI_REVID_8139CPLUS 0x20 + +#define RTL8139_PCI_REVID RTL8139_PCI_REVID_8139CPLUS + +/* Size is 64 * 16bit words */ +#define EEPROM_9346_ADDR_BITS 6 +#define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS) +#define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1) + +enum Chip9346Operation +{ + Chip9346_op_mask = 0xc0, /* 10 zzzzzz */ + Chip9346_op_read = 0x80, /* 10 AAAAAA */ + Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */ + Chip9346_op_ext_mask = 0xf0, /* 11 zzzzzz */ + Chip9346_op_write_enable = 0x30, /* 00 11zzzz */ + Chip9346_op_write_all = 0x10, /* 00 01zzzz */ + Chip9346_op_write_disable = 0x00, /* 00 00zzzz */ +}; + +enum Chip9346Mode +{ + Chip9346_none = 0, + Chip9346_enter_command_mode, + Chip9346_read_command, + Chip9346_data_read, /* from output register */ + Chip9346_data_write, /* to input register, then to contents at specified address */ + Chip9346_data_write_all, /* to input register, then filling contents */ +}; + +typedef struct EEprom9346 +{ + uint16_t contents[EEPROM_9346_SIZE]; + int mode; + uint32_t tick; + uint8_t address; + uint16_t input; + uint16_t output; + + uint8_t eecs; + uint8_t eesk; + uint8_t eedi; + uint8_t eedo; +} EEprom9346; + +#pragma pack(push, 1) +typedef struct RTL8139TallyCounters +{ + /* Tally counters */ + uint64_t TxOk; + uint64_t RxOk; + uint64_t TxERR; + uint32_t RxERR; + uint16_t MissPkt; + uint16_t FAE; + uint32_t Tx1Col; + uint32_t TxMCol; + uint64_t RxOkPhy; + uint64_t RxOkBrd; + uint32_t RxOkMul; + uint16_t TxAbt; + uint16_t TxUndrn; +} RTL8139TallyCounters; +#pragma pack(pop) + +/* Clears all tally counters */ +static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters); + +struct RTL8139State { + /*< private >*/ + uint8_t dev; + uint8_t inst; + /*< public >*/ + + uint8_t phys[8]; /* mac address */ + uint8_t mult[8]; /* multicast mask array */ + uint8_t pci_conf[256]; + + uint32_t TxStatus[4]; /* TxStatus0 in C mode*/ /* also DTCCR[0] and DTCCR[1] in C+ mode */ + uint32_t TxAddr[4]; /* TxAddr0 */ + uint32_t RxBuf; /* Receive buffer */ + uint32_t RxBufferSize;/* internal variable, receive ring buffer size in C mode */ + uint32_t RxBufPtr; + uint32_t RxBufAddr; + + uint16_t IntrStatus; + uint16_t IntrMask; + + uint32_t TxConfig; + uint32_t RxConfig; + uint32_t RxMissed; + + uint16_t CSCR; + + uint8_t Cfg9346; + uint8_t Config0; + uint8_t Config1; + uint8_t Config3; + uint8_t Config4; + uint8_t Config5; + + uint8_t clock_enabled; + uint8_t bChipCmdState; + + uint16_t MultiIntr; + + uint16_t BasicModeCtrl; + uint16_t BasicModeStatus; + uint16_t NWayAdvert; + uint16_t NWayLPAR; + uint16_t NWayExpansion; + + uint16_t CpCmd; + uint8_t TxThresh; + + netcard_t *nic; + + /* C ring mode */ + uint32_t currTxDesc; + + /* C+ mode */ + uint32_t cplus_enabled; + + uint32_t currCPlusRxDesc; + uint32_t currCPlusTxDesc; + + uint32_t RxRingAddrLO; + uint32_t RxRingAddrHI; + + EEprom9346 eeprom; + + uint32_t TCTR; + uint32_t TimerInt; + int64_t TCTR_base; + + /* Tally counters */ + RTL8139TallyCounters tally_counters; + + /* Non-persistent data */ + uint8_t *cplus_txbuffer; + int cplus_txbuffer_len; + int cplus_txbuffer_offset; + + /* PCI interrupt timer */ + pc_timer_t timer; + + mem_mapping_t bar_mem; + + /* Support migration to/from old versions */ + int rtl8139_mmio_io_addr_dummy; +}; + +/* Writes tally counters to memory via DMA */ +static void RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr); + +static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) +{ + DPRINTF("eeprom command 0x%02x\n", command); + + switch (command & Chip9346_op_mask) + { + case Chip9346_op_read: + { + eeprom->address = command & EEPROM_9346_ADDR_MASK; + eeprom->output = eeprom->contents[eeprom->address]; + eeprom->eedo = 0; + eeprom->tick = 0; + eeprom->mode = Chip9346_data_read; + DPRINTF("eeprom read from address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); + } + break; + + case Chip9346_op_write: + { + eeprom->address = command & EEPROM_9346_ADDR_MASK; + eeprom->input = 0; + eeprom->tick = 0; + eeprom->mode = Chip9346_none; /* Chip9346_data_write */ + DPRINTF("eeprom begin write to address 0x%02x\n", + eeprom->address); + } + break; + default: + eeprom->mode = Chip9346_none; + switch (command & Chip9346_op_ext_mask) + { + case Chip9346_op_write_enable: + DPRINTF("eeprom write enabled\n"); + break; + case Chip9346_op_write_all: + DPRINTF("eeprom begin write all\n"); + break; + case Chip9346_op_write_disable: + DPRINTF("eeprom write disabled\n"); + break; + } + break; + } +} + +static void prom9346_shift_clock(EEprom9346 *eeprom) +{ + int bit = eeprom->eedi?1:0; + + ++ eeprom->tick; + + DPRINTF("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, + eeprom->eedo); + + switch (eeprom->mode) + { + case Chip9346_enter_command_mode: + if (bit) + { + eeprom->mode = Chip9346_read_command; + eeprom->tick = 0; + eeprom->input = 0; + DPRINTF("eeprom: +++ synchronized, begin command read\n"); + } + break; + + case Chip9346_read_command: + eeprom->input = (eeprom->input << 1) | (bit & 1); + if (eeprom->tick == 8) + { + prom9346_decode_command(eeprom, eeprom->input & 0xff); + } + break; + + case Chip9346_data_read: + eeprom->eedo = (eeprom->output & 0x8000)?1:0; + eeprom->output <<= 1; + if (eeprom->tick == 16) + { +#if 1 + // the FreeBSD drivers (rl and re) don't explicitly toggle + // CS between reads (or does setting Cfg9346 to 0 count too?), + // so we need to enter wait-for-command state here + eeprom->mode = Chip9346_enter_command_mode; + eeprom->input = 0; + eeprom->tick = 0; + + DPRINTF("eeprom: +++ end of read, awaiting next command\n"); +#else + // original behaviour + ++eeprom->address; + eeprom->address &= EEPROM_9346_ADDR_MASK; + eeprom->output = eeprom->contents[eeprom->address]; + eeprom->tick = 0; + + DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); +#endif + } + break; + + case Chip9346_data_write: + eeprom->input = (eeprom->input << 1) | (bit & 1); + if (eeprom->tick == 16) + { + DPRINTF("eeprom write to address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->input); + + eeprom->contents[eeprom->address] = eeprom->input; + eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ + eeprom->tick = 0; + eeprom->input = 0; + } + break; + + case Chip9346_data_write_all: + eeprom->input = (eeprom->input << 1) | (bit & 1); + if (eeprom->tick == 16) + { + int i; + for (i = 0; i < EEPROM_9346_SIZE; i++) + { + eeprom->contents[i] = eeprom->input; + } + DPRINTF("eeprom filled with data=0x%04x\n", eeprom->input); + + eeprom->mode = Chip9346_enter_command_mode; + eeprom->tick = 0; + eeprom->input = 0; + } + break; + + default: + break; + } +} + +static int prom9346_get_wire(RTL8139State *s) +{ + EEprom9346 *eeprom = &s->eeprom; + if (!eeprom->eecs) + return 0; + + return eeprom->eedo; +} + +/* FIXME: This should be merged into/replaced by eeprom93xx.c. */ +static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) +{ + EEprom9346 *eeprom = &s->eeprom; + uint8_t old_eecs = eeprom->eecs; + uint8_t old_eesk = eeprom->eesk; + + eeprom->eecs = eecs; + eeprom->eesk = eesk; + eeprom->eedi = eedi; + + DPRINTF("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, + eeprom->eesk, eeprom->eedi, eeprom->eedo); + + if (!old_eecs && eecs) + { + /* Synchronize start */ + eeprom->tick = 0; + eeprom->input = 0; + eeprom->output = 0; + eeprom->mode = Chip9346_enter_command_mode; + + DPRINTF("=== eeprom: begin access, enter command mode\n"); + } + + if (!eecs) + { + DPRINTF("=== eeprom: end access\n"); + return; + } + + if (!old_eesk && eesk) + { + /* SK front rules */ + prom9346_shift_clock(eeprom); + } +} + +static void rtl8139_update_irq(RTL8139State *s) +{ + uint8_t d = s->dev; + int isr; + isr = (s->IntrStatus & s->IntrMask) & 0xffff; + + DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus, + s->IntrMask); + + if (isr != 0) + pci_set_irq(d, PCI_INTA); + else + pci_clear_irq(d, PCI_INTA); +} + +static int rtl8139_RxWrap(RTL8139State *s) +{ + /* wrapping enabled; assume 1.5k more buffer space if size < 65536 */ + return (s->RxConfig & (1 << 7)); +} + +static int rtl8139_receiver_enabled(RTL8139State *s) +{ + return s->bChipCmdState & CmdRxEnb; +} + +static int rtl8139_transmitter_enabled(RTL8139State *s) +{ + return s->bChipCmdState & CmdTxEnb; +} + +static int rtl8139_cp_receiver_enabled(RTL8139State *s) +{ + return s->CpCmd & CPlusRxEnb; +} + +static int rtl8139_cp_transmitter_enabled(RTL8139State *s) +{ + return s->CpCmd & CPlusTxEnb; +} + +static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) +{ + if (s->RxBufAddr + size > s->RxBufferSize) + { + int wrapped = MOD2(s->RxBufAddr + size, s->RxBufferSize); + + /* write packet data */ + if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s))) + { + DPRINTF(">>> rx packet wrapped in buffer at %d\n", size - wrapped); + + if (size > wrapped) + { + dma_bm_write(s->RxBuf + s->RxBufAddr, + buf, size-wrapped, 1); + } + + /* reset buffer pointer */ + s->RxBufAddr = 0; + + dma_bm_write(s->RxBuf + s->RxBufAddr, + buf + (size-wrapped), wrapped, 1); + + s->RxBufAddr = wrapped; + + return; + } + } + + /* non-wrapping path or overwrapping enabled */ + dma_bm_write(s->RxBuf + s->RxBufAddr, buf, size, 1); + + s->RxBufAddr += size; +} + +static __inline uint32_t rtl8139_addr64(uint32_t low, uint32_t high) +{ + (void)high; + return low; +} + +/* Workaround for buggy guest driver such as linux who allocates rx + * rings after the receiver were enabled. */ +static bool rtl8139_cp_rx_valid(RTL8139State *s) +{ + return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0); +} + +static bool rtl8139_can_receive(RTL8139State *s) +{ + int avail; + + /* Receive (drop) packets if card is disabled. */ + if (!s->clock_enabled) { + return true; + } + if (!rtl8139_receiver_enabled(s)) { + return true; + } + + if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) { + /* ??? Flow control not implemented in c+ mode. + This is a hack to work around slirp deficiencies anyway. */ + return true; + } + + avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, + s->RxBufferSize); + return avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow); +} + +/* From FreeBSD */ +/* XXX: optimize */ +static uint32_t net_crc32(const uint8_t *p, int len) +{ + uint32_t crc; + int carry, i, j; + uint8_t b; + + crc = 0xffffffff; + for (i = 0; i < len; i++) { + b = *p++; + for (j = 0; j < 8; j++) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) { + crc = ((crc ^ 0x04c11db6) | carry); + } + } + } + + return crc; +} + +uint32_t net_crc32_le(const uint8_t *p, int len) +{ + uint32_t crc; + int carry, i, j; + uint8_t b; + + crc = 0xffffffff; + for (i = 0; i < len; i++) { + b = *p++; + for (j = 0; j < 8; j++) { + carry = (crc & 0x1) ^ (b & 0x01); + crc >>= 1; + b >>= 1; + if (carry) { + crc ^= 0xedb88320; + } + } + } + + return crc; +} + + +#define ETH_ALEN 6 +static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) +{ + RTL8139State *s = (RTL8139State*)p; + /* size is the length of the buffer passed to the driver */ + size_t size = size_; + const uint8_t *dot1q_buf = NULL; + + uint32_t packet_header = 0; + uint8_t buf1[60 + VLAN_HLEN]; + + static const uint8_t broadcast_macaddr[6] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + DPRINTF(">>> received len=%zu\n", size); + + if (!rtl8139_can_receive(s)) + return 0; + + /* test if board clock is stopped */ + if (!s->clock_enabled) + { + DPRINTF("stopped ==========================\n"); + return -1; + } + + /* first check if receiver is enabled */ + + if (!rtl8139_receiver_enabled(s)) + { + DPRINTF("receiver disabled ================\n"); + return -1; + } + + /* XXX: check this */ + if (s->RxConfig & AcceptAllPhys) { + /* promiscuous: receive all */ + DPRINTF(">>> packet received in promiscuous mode\n"); + + } else { + if (!memcmp(buf, broadcast_macaddr, 6)) { + /* broadcast address */ + if (!(s->RxConfig & AcceptBroadcast)) + { + DPRINTF(">>> broadcast packet rejected\n"); + + /* update tally counter */ + ++s->tally_counters.RxERR; + + return size; + } + + packet_header |= RxBroadcast; + + DPRINTF(">>> broadcast packet received\n"); + + /* update tally counter */ + ++s->tally_counters.RxOkBrd; + + } else if (buf[0] & 0x01) { + /* multicast */ + if (!(s->RxConfig & AcceptMulticast)) + { + DPRINTF(">>> multicast packet rejected\n"); + + /* update tally counter */ + ++s->tally_counters.RxERR; + + return size; + } + + int mcast_idx = net_crc32(buf, ETH_ALEN) >> 26; + + if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) + { + DPRINTF(">>> multicast address mismatch\n"); + + /* update tally counter */ + ++s->tally_counters.RxERR; + + return size; + } + + packet_header |= RxMulticast; + + DPRINTF(">>> multicast packet received\n"); + + /* update tally counter */ + ++s->tally_counters.RxOkMul; + + } else if (s->phys[0] == buf[0] && + s->phys[1] == buf[1] && + s->phys[2] == buf[2] && + s->phys[3] == buf[3] && + s->phys[4] == buf[4] && + s->phys[5] == buf[5]) { + /* match */ + if (!(s->RxConfig & AcceptMyPhys)) + { + DPRINTF(">>> rejecting physical address matching packet\n"); + + /* update tally counter */ + ++s->tally_counters.RxERR; + + return size; + } + + packet_header |= RxPhysical; + + DPRINTF(">>> physical address matching packet received\n"); + + /* update tally counter */ + ++s->tally_counters.RxOkPhy; + + } else { + + DPRINTF(">>> unknown packet\n"); + + /* update tally counter */ + ++s->tally_counters.RxERR; + + return size; + } + } + + if (size < 60 + VLAN_HLEN) { + memcpy(buf1, buf, size); + memset(buf1 + size, 0, 60 + VLAN_HLEN - size); + buf = buf1; + if (size < 60) { + size = 60; + } + } + + if (rtl8139_cp_receiver_enabled(s)) + { + if (!rtl8139_cp_rx_valid(s)) { + return size; + } + + DPRINTF("in C+ Rx mode ================\n"); + + /* begin C+ receiver mode */ + +/* w0 ownership flag */ +#define CP_RX_OWN (1<<31) +/* w0 end of ring flag */ +#define CP_RX_EOR (1<<30) +/* w0 bits 0...12 : buffer size */ +#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1) +/* w1 tag available flag */ +#define CP_RX_TAVA (1<<16) +/* w1 bits 0...15 : VLAN tag */ +#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1) +/* w2 low 32bit of Rx buffer ptr */ +/* w3 high 32bit of Rx buffer ptr */ + + int descriptor = s->currCPlusRxDesc; + uint32_t cplus_rx_ring_desc; + + cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); + cplus_rx_ring_desc += 16 * descriptor; + + DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at " + "%08x %08x = ""0x%8X""\n", descriptor, s->RxRingAddrHI, + s->RxRingAddrLO, cplus_rx_ring_desc); + + uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; + + dma_bm_read(cplus_rx_ring_desc, (uint8_t*)&val, 4, 4); + rxdw0 = (val); + dma_bm_read(cplus_rx_ring_desc+4, (uint8_t*)&val, 4, 4); + rxdw1 = (val); + dma_bm_read(cplus_rx_ring_desc+8, (uint8_t*)&val, 4, 4); + rxbufLO = (val); + dma_bm_read(cplus_rx_ring_desc+12, (uint8_t*)&val, 4, 4); + rxbufHI = (val); + + DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", + descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI); + + if (!(rxdw0 & CP_RX_OWN)) + { + DPRINTF("C+ Rx mode : descriptor %d is owned by host\n", + descriptor); + + s->IntrStatus |= RxOverflow; + ++s->RxMissed; + + /* update tally counter */ + ++s->tally_counters.RxERR; + ++s->tally_counters.MissPkt; + + rtl8139_update_irq(s); + return size_; + } + + uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK; + + /* write VLAN info to descriptor variables. */ + if (s->CpCmd & CPlusRxVLAN && + bswap16(*((uint16_t*)&buf[ETH_ALEN * 2])) == 0x8100) { + dot1q_buf = &buf[ETH_ALEN * 2]; + size -= VLAN_HLEN; + /* if too small buffer, use the tailroom added duing expansion */ + if (size < 60) { + size = 60; + } + + rxdw1 &= ~CP_RX_VLAN_TAG_MASK; + /* BE + ~le_to_cpu()~ + cpu_to_le() = BE */ + rxdw1 |= CP_RX_TAVA | *((uint16_t*)(&dot1q_buf[ETHER_TYPE_LEN])); + + DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n", + bswap16(*((uint16_t*)&dot1q_buf[ETHER_TYPE_LEN]))); + } else { + /* reset VLAN tag flag */ + rxdw1 &= ~CP_RX_TAVA; + } + + /* TODO: scatter the packet over available receive ring descriptors space */ + + if (size+4 > rx_space) + { + DPRINTF("C+ Rx mode : descriptor %d size %d received %zu + 4\n", + descriptor, rx_space, size); + + s->IntrStatus |= RxOverflow; + ++s->RxMissed; + + /* update tally counter */ + ++s->tally_counters.RxERR; + ++s->tally_counters.MissPkt; + + rtl8139_update_irq(s); + return size_; + } + + uint32_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); + + /* receive/copy to target memory */ + if (dot1q_buf) { + dma_bm_write(rx_addr, buf, 2 * ETH_ALEN, 1); + dma_bm_write(rx_addr + 2 * ETH_ALEN, + buf + 2 * ETH_ALEN + VLAN_HLEN, + size - 2 * ETH_ALEN, 1); + } else { + dma_bm_write(rx_addr, buf, size, 1); + } + + if (s->CpCmd & CPlusRxChkSum) + { + /* do some packet checksumming */ + } + + /* write checksum */ + val = (net_crc32_le(buf, size_)); + dma_bm_write(rx_addr+size, (uint8_t *)&val, 4, 4); + +/* first segment of received packet flag */ +#define CP_RX_STATUS_FS (1<<29) +/* last segment of received packet flag */ +#define CP_RX_STATUS_LS (1<<28) +/* multicast packet flag */ +#define CP_RX_STATUS_MAR (1<<26) +/* physical-matching packet flag */ +#define CP_RX_STATUS_PAM (1<<25) +/* broadcast packet flag */ +#define CP_RX_STATUS_BAR (1<<24) +/* runt packet flag */ +#define CP_RX_STATUS_RUNT (1<<19) +/* crc error flag */ +#define CP_RX_STATUS_CRC (1<<18) +/* IP checksum error flag */ +#define CP_RX_STATUS_IPF (1<<15) +/* UDP checksum error flag */ +#define CP_RX_STATUS_UDPF (1<<14) +/* TCP checksum error flag */ +#define CP_RX_STATUS_TCPF (1<<13) + + /* transfer ownership to target */ + rxdw0 &= ~CP_RX_OWN; + + /* set first segment bit */ + rxdw0 |= CP_RX_STATUS_FS; + + /* set last segment bit */ + rxdw0 |= CP_RX_STATUS_LS; + + /* set received packet type flags */ + if (packet_header & RxBroadcast) + rxdw0 |= CP_RX_STATUS_BAR; + if (packet_header & RxMulticast) + rxdw0 |= CP_RX_STATUS_MAR; + if (packet_header & RxPhysical) + rxdw0 |= CP_RX_STATUS_PAM; + + /* set received size */ + rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK; + rxdw0 |= (size+4); + + /* update ring data */ + val = (rxdw0); + dma_bm_write(cplus_rx_ring_desc, (uint8_t *)&val, 4, 4); + val = (rxdw1); + dma_bm_write(cplus_rx_ring_desc+4, (uint8_t *)&val, 4, 4); + + /* update tally counter */ + ++s->tally_counters.RxOk; + + /* seek to next Rx descriptor */ + if (rxdw0 & CP_RX_EOR) + { + s->currCPlusRxDesc = 0; + } + else + { + ++s->currCPlusRxDesc; + } + + DPRINTF("done C+ Rx mode ----------------\n"); + + } + else + { + DPRINTF("in ring Rx mode ================\n"); + + /* begin ring receiver mode */ + int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); + + /* if receiver buffer is empty then avail == 0 */ + +#define RX_ALIGN(x) (((x) + 3) & ~0x3) + + if (avail != 0 && RX_ALIGN(size + 8) >= avail) + { + DPRINTF("rx overflow: rx buffer length %d head 0x%04x " + "read 0x%04x === available 0x%04x need 0x%04zx\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); + + s->IntrStatus |= RxOverflow; + ++s->RxMissed; + rtl8139_update_irq(s); + return 0; + } + + packet_header |= RxStatusOK; + + packet_header |= (((size+4) << 16) & 0xffff0000); + + /* write header */ + uint32_t val = (packet_header); + + rtl8139_write_buffer(s, (uint8_t *)&val, 4); + + rtl8139_write_buffer(s, buf, size); + + /* write checksum */ + val = (net_crc32_le(buf, size)); + rtl8139_write_buffer(s, (uint8_t *)&val, 4); + + /* correct buffer write pointer */ + s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize); + + /* now we can signal we have received something */ + + DPRINTF("received: rx buffer length %d head 0x%04x read 0x%04x\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); + } + + s->IntrStatus |= RxOK; + + { + rtl8139_update_irq(s); + } + + return size_; +} + +static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize) +{ + s->RxBufferSize = bufferSize; + s->RxBufPtr = 0; + s->RxBufAddr = 0; +} + +static void rtl8139_reset_phy(RTL8139State *s) +{ + s->BasicModeStatus = 0x7809; + s->BasicModeStatus |= 0x0020; /* autonegotiation completed */ + /* preserve link state */ + s->BasicModeStatus |= (net_cards_conf[s->nic->card_num].link_state & NET_LINK_DOWN) ? 0 : 0x04; + + s->NWayAdvert = 0x05e1; /* all modes, full duplex */ + s->NWayLPAR = 0x05e1; /* all modes, full duplex */ + s->NWayExpansion = 0x0001; /* autonegotiation supported */ + + s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD; +} + + +static void rtl8139_reset(void* p) +{ + int i; + RTL8139State *s = (RTL8139State*)p; + + /* reset interrupt mask */ + s->IntrStatus = 0; + s->IntrMask = 0; + + rtl8139_update_irq(s); + + /* mark all status registers as owned by host */ + for (i = 0; i < 4; ++i) + { + s->TxStatus[i] = TxHostOwns; + } + + s->currTxDesc = 0; + s->currCPlusRxDesc = 0; + s->currCPlusTxDesc = 0; + + s->RxRingAddrLO = 0; + s->RxRingAddrHI = 0; + + s->RxBuf = 0; + + rtl8139_reset_rxring(s, 8192); + + /* ACK the reset */ + s->TxConfig = 0; + +#if 0 +// s->TxConfig |= HW_REVID(1, 0, 0, 0, 0, 0, 0); // RTL-8139 HasHltClk + s->clock_enabled = 0; +#else + s->TxConfig |= HW_REVID(1, 1, 1, 0, 1, 1, 0); // RTL-8139C+ HasLWake + s->clock_enabled = 1; +#endif + + s->bChipCmdState = CmdReset; /* RxBufEmpty bit is calculated on read from ChipCmd */; + + /* set initial state data */ + s->Config0 = 0x0; /* No boot ROM */ + s->Config1 = 0xC; /* IO mapped and MEM mapped registers available */ + s->Config3 = 0x1; /* fast back-to-back compatible */ + s->Config5 = 0x0; + + s->CpCmd = 0x0; /* reset C+ mode */ + s->cplus_enabled = 0; + +// s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation +// s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex + s->BasicModeCtrl = 0x1000; // autonegotiation + + rtl8139_reset_phy(s); + + /* also reset timer and disable timer interrupt */ + s->TCTR = 0; + s->TimerInt = 0; + s->TCTR_base = 0; + //rtl8139_set_next_tctr_time(s); + + /* reset tally counters */ + RTL8139TallyCounters_clear(&s->tally_counters); +} + +static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters) +{ + counters->TxOk = 0; + counters->RxOk = 0; + counters->TxERR = 0; + counters->RxERR = 0; + counters->MissPkt = 0; + counters->FAE = 0; + counters->Tx1Col = 0; + counters->TxMCol = 0; + counters->RxOkPhy = 0; + counters->RxOkBrd = 0; + counters->RxOkMul = 0; + counters->TxAbt = 0; + counters->TxUndrn = 0; +} + +static void RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr) +{ + RTL8139TallyCounters *tally_counters = &s->tally_counters; + + dma_bm_write(tc_addr, (uint8_t*)tally_counters, sizeof(RTL8139TallyCounters), 1); +} + +static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val) +{ + val &= 0xff; + + DPRINTF("ChipCmd write val=0x%08x\n", val); + + if (val & CmdReset) + { + DPRINTF("ChipCmd reset\n"); + rtl8139_reset(s); + } + if (val & CmdRxEnb) + { + DPRINTF("ChipCmd enable receiver\n"); + + s->currCPlusRxDesc = 0; + } + if (val & CmdTxEnb) + { + DPRINTF("ChipCmd enable transmitter\n"); + + s->currCPlusTxDesc = 0; + } + + /* mask unwritable bits */ + val = SET_MASKED(val, 0xe3, s->bChipCmdState); + + /* Deassert reset pin before next read */ + val &= ~CmdReset; + + s->bChipCmdState = val; +} + +static int rtl8139_RxBufferEmpty(RTL8139State *s) +{ + int unread = MOD2(s->RxBufferSize + s->RxBufAddr - s->RxBufPtr, s->RxBufferSize); + + if (unread != 0) + { + DPRINTF("receiver buffer data available 0x%04x\n", unread); + return 0; + } + + DPRINTF("receiver buffer is empty\n"); + + return 1; +} + +static uint32_t rtl8139_ChipCmd_read(RTL8139State *s) +{ + uint32_t ret = s->bChipCmdState; + + if (rtl8139_RxBufferEmpty(s)) + ret |= RxBufEmpty; + + DPRINTF("ChipCmd read val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val) +{ + val &= 0xffff; + + DPRINTF("C+ command register write(w) val=0x%04x\n", val); + + s->cplus_enabled = 1; + + /* mask unwritable bits */ + val = SET_MASKED(val, 0xff84, s->CpCmd); + + s->CpCmd = val; +} + +static uint32_t rtl8139_CpCmd_read(RTL8139State *s) +{ + uint32_t ret = s->CpCmd; + + DPRINTF("C+ command register read(w) val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val) +{ + DPRINTF("C+ IntrMitigate register write(w) val=0x%04x\n", val); +} + +static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s) +{ + uint32_t ret = 0; + + DPRINTF("C+ IntrMitigate register read(w) val=0x%04x\n", ret); + + return ret; +} + +static int rtl8139_config_writable(RTL8139State *s) +{ + if ((s->Cfg9346 & Chip9346_op_mask) == Cfg9346_ConfigWrite) + { + return 1; + } + + DPRINTF("Configuration registers are write-protected\n"); + + return 0; +} + +static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) +{ + val &= 0xffff; + + DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val); + + /* mask unwritable bits */ + uint32_t mask = 0xccff; + + if (1 || !rtl8139_config_writable(s)) + { + /* Speed setting and autonegotiation enable bits are read-only */ + mask |= 0x3000; + /* Duplex mode setting is read-only */ + mask |= 0x0100; + } + + if (val & 0x8000) { + /* Reset PHY */ + rtl8139_reset_phy(s); + } + + val = SET_MASKED(val, mask, s->BasicModeCtrl); + + s->BasicModeCtrl = val; +} + +static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s) +{ + uint32_t ret = s->BasicModeCtrl; + + DPRINTF("BasicModeCtrl register read(w) val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val) +{ + val &= 0xffff; + + DPRINTF("BasicModeStatus register write(w) val=0x%04x\n", val); + + /* mask unwritable bits */ + val = SET_MASKED(val, 0xff3f, s->BasicModeStatus); + + s->BasicModeStatus = val; +} + +static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s) +{ + uint32_t ret = s->BasicModeStatus; + + DPRINTF("BasicModeStatus register read(w) val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) +{ + val &= 0xff; + + DPRINTF("Cfg9346 write val=0x%02x\n", val); + + /* mask unwritable bits */ + val = SET_MASKED(val, 0x31, s->Cfg9346); + + uint32_t opmode = val & 0xc0; + uint32_t eeprom_val = val & 0xf; + + if (opmode == 0x80) { + /* eeprom access */ + int eecs = (eeprom_val & 0x08)?1:0; + int eesk = (eeprom_val & 0x04)?1:0; + int eedi = (eeprom_val & 0x02)?1:0; + prom9346_set_wire(s, eecs, eesk, eedi); + } else if (opmode == 0x40) { + /* Reset. */ + val = 0; + rtl8139_reset(s); + } + + s->Cfg9346 = val; +} + +static uint32_t rtl8139_Cfg9346_read(RTL8139State *s) +{ + uint32_t ret = s->Cfg9346; + + uint32_t opmode = ret & 0xc0; + + if (opmode == 0x80) + { + /* eeprom access */ + int eedo = prom9346_get_wire(s); + if (eedo) + { + ret |= 0x01; + } + else + { + ret &= ~0x01; + } + } + + DPRINTF("Cfg9346 read val=0x%02x\n", ret); + + return ret; +} + +static void rtl8139_Config0_write(RTL8139State *s, uint32_t val) +{ + val &= 0xff; + + DPRINTF("Config0 write val=0x%02x\n", val); + + if (!rtl8139_config_writable(s)) { + return; + } + + /* mask unwritable bits */ + val = SET_MASKED(val, 0xf8, s->Config0); + + s->Config0 = val; +} + +static uint32_t rtl8139_Config0_read(RTL8139State *s) +{ + uint32_t ret = s->Config0; + + DPRINTF("Config0 read val=0x%02x\n", ret); + + return ret; +} + +static void rtl8139_Config1_write(RTL8139State *s, uint32_t val) +{ + val &= 0xff; + + DPRINTF("Config1 write val=0x%02x\n", val); + + if (!rtl8139_config_writable(s)) { + return; + } + + /* mask unwritable bits */ + val = SET_MASKED(val, 0xC, s->Config1); + + s->Config1 = val; +} + +static uint32_t rtl8139_Config1_read(RTL8139State *s) +{ + uint32_t ret = s->Config1; + + DPRINTF("Config1 read val=0x%02x\n", ret); + + return ret; +} + +static void rtl8139_Config3_write(RTL8139State *s, uint32_t val) +{ + val &= 0xff; + + DPRINTF("Config3 write val=0x%02x\n", val); + + if (!rtl8139_config_writable(s)) { + return; + } + + /* mask unwritable bits */ + val = SET_MASKED(val, 0x8F, s->Config3); + + s->Config3 = val; +} + +static uint32_t rtl8139_Config3_read(RTL8139State *s) +{ + uint32_t ret = s->Config3; + + DPRINTF("Config3 read val=0x%02x\n", ret); + + return ret; +} + +static void rtl8139_Config4_write(RTL8139State *s, uint32_t val) +{ + val &= 0xff; + + DPRINTF("Config4 write val=0x%02x\n", val); + + if (!rtl8139_config_writable(s)) { + return; + } + + /* mask unwritable bits */ + val = SET_MASKED(val, 0x0a, s->Config4); + + s->Config4 = val; +} + +static uint32_t rtl8139_Config4_read(RTL8139State *s) +{ + uint32_t ret = s->Config4; + + DPRINTF("Config4 read val=0x%02x\n", ret); + + return ret; +} + +static void rtl8139_Config5_write(RTL8139State *s, uint32_t val) +{ + val &= 0xff; + + DPRINTF("Config5 write val=0x%02x\n", val); + + /* mask unwritable bits */ + val = SET_MASKED(val, 0x80, s->Config5); + + s->Config5 = val; +} + +static uint32_t rtl8139_Config5_read(RTL8139State *s) +{ + uint32_t ret = s->Config5; + + DPRINTF("Config5 read val=0x%02x\n", ret); + + return ret; +} + +static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) +{ + if (!rtl8139_transmitter_enabled(s)) + { + DPRINTF("transmitter disabled; no TxConfig write val=0x%08x\n", val); + return; + } + + DPRINTF("TxConfig write val=0x%08x\n", val); + + val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig); + + s->TxConfig = val; +} + +static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val) +{ + DPRINTF("RTL8139C TxConfig via write(b) val=0x%02x\n", val); + + uint32_t tc = s->TxConfig; + tc &= 0xFFFFFF00; + tc |= (val & 0x000000FF); + rtl8139_TxConfig_write(s, tc); +} + +static uint32_t rtl8139_TxConfig_read(RTL8139State *s) +{ + uint32_t ret = s->TxConfig; + + DPRINTF("TxConfig read val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) +{ + DPRINTF("RxConfig write val=0x%08x\n", val); + + /* mask unwritable bits */ + val = SET_MASKED(val, 0xf0fc0040, s->RxConfig); + + s->RxConfig = val; + + /* reset buffer size and read/write pointers */ + rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3)); + + DPRINTF("RxConfig write reset buffer size to %d\n", s->RxBufferSize); +} + +static uint32_t rtl8139_RxConfig_read(RTL8139State *s) +{ + uint32_t ret = s->RxConfig; + + DPRINTF("RxConfig read val=0x%08x\n", ret); + + return ret; +} + +void +rtl8139_network_rx_put(netcard_t *card, uint8_t *bufp, int len) +{ + (void)network_rx_put(card, bufp, len); +} + +static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, + int do_interrupt, const uint8_t *dot1q_buf) +{ + void (*network_func)(netcard_t *, uint8_t *, int) = (TxLoopBack == (s->TxConfig & TxLoopBack)) ? rtl8139_network_rx_put : network_tx; + if (!size) + { + DPRINTF("+++ empty ethernet frame\n"); + return; + } + + if (dot1q_buf && size >= ETH_ALEN * 2) { + network_func(s->nic, buf, ETH_ALEN * 2); + network_func(s->nic, (uint8_t*)dot1q_buf, VLAN_HLEN ); + network_func(s->nic, buf + ETH_ALEN * 2, size - ETH_ALEN * 2); + return; + } + + network_func(s->nic, buf, size); + return; +} + +static int rtl8139_transmit_one(RTL8139State *s, int descriptor) +{ + int txsize = s->TxStatus[descriptor] & 0x1fff; + uint8_t txbuffer[0x2000]; + + if (!rtl8139_transmitter_enabled(s)) + { + DPRINTF("+++ cannot transmit from descriptor %d: transmitter " + "disabled\n", descriptor); + return 0; + } + + if (s->TxStatus[descriptor] & TxHostOwns) + { + DPRINTF("+++ cannot transmit from descriptor %d: owned by host " + "(%08x)\n", descriptor, s->TxStatus[descriptor]); + return 0; + } + + DPRINTF("+++ transmitting from descriptor %d\n", descriptor); + + DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n", + txsize, s->TxAddr[descriptor]); + + dma_bm_read(s->TxAddr[descriptor], txbuffer, txsize, 1); + + /* Mark descriptor as transferred */ + s->TxStatus[descriptor] |= TxHostOwns; + s->TxStatus[descriptor] |= TxStatOK; + + rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL); + + DPRINTF("+++ transmitted %d bytes from descriptor %d\n", txsize, + descriptor); + + /* update interrupt */ + s->IntrStatus |= TxOK; + rtl8139_update_irq(s); + + return 1; +} + +#define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off))) + +/* produces ones' complement sum of data */ +static uint16_t ones_complement_sum(uint8_t *data, size_t len) +{ + uint32_t result = 0; + + for (; len > 1; data+=2, len-=2) + { + result += *(uint16_t*)data; + } + + /* add the remainder byte */ + if (len) + { + uint8_t odd[2] = {*data, 0}; + result += *(uint16_t*)odd; + } + + while (result>>16) + result = (result & 0xffff) + (result >> 16); + + return result; +} + +static uint16_t ip_checksum(void *data, size_t len) +{ + return ~ones_complement_sum((uint8_t*)data, len); +} + +/* TODO: Replace these with equivalents in 86Box if applicable. */ +struct ip_header { + uint8_t ip_ver_len; /* version and header length */ + uint8_t ip_tos; /* type of service */ + uint16_t ip_len; /* total length */ + uint16_t ip_id; /* identification */ + uint16_t ip_off; /* fragment offset field */ + uint8_t ip_ttl; /* time to live */ + uint8_t ip_p; /* protocol */ + uint16_t ip_sum; /* checksum */ + uint32_t ip_src, ip_dst; /* source and destination address */ +}; + +typedef struct tcp_header { + uint16_t th_sport; /* source port */ + uint16_t th_dport; /* destination port */ + uint32_t th_seq; /* sequence number */ + uint32_t th_ack; /* acknowledgment number */ + uint16_t th_offset_flags; /* data offset, reserved 6 bits, */ + /* TCP protocol flags */ + uint16_t th_win; /* window */ + uint16_t th_sum; /* checksum */ + uint16_t th_urp; /* urgent pointer */ +} tcp_header; + +typedef struct ip_pseudo_header { + uint32_t ip_src; + uint32_t ip_dst; + uint8_t zeros; + uint8_t ip_proto; + uint16_t ip_payload; +} ip_pseudo_header; + +typedef struct udp_header { + uint16_t uh_sport; /* source port */ + uint16_t uh_dport; /* destination port */ + uint16_t uh_ulen; /* udp length */ + uint16_t uh_sum; /* udp checksum */ +} udp_header; + +#define ETH_HLEN 14 +#define ETH_P_IP (0x0800) +#define IP_PROTO_TCP (6) +#define IP_PROTO_UDP (17) +#define IP_HEADER_VERSION_4 (4) +#define TH_PUSH 0x08 +#define TH_FIN 0x01 + +#define IP_HDR_GET_LEN(p) \ + ((*(uint8_t*)((p + __builtin_offsetof(struct ip_header, ip_ver_len))) & 0x0F) << 2) + +#define IP_HEADER_VERSION(ip) \ + (((ip)->ip_ver_len >> 4) & 0xf) + +#define TCP_HEADER_DATA_OFFSET(tcp) \ + (((be16_to_cpu((tcp)->th_offset_flags) >> 12) & 0xf) << 2) + + +static int rtl8139_cplus_transmit_one(RTL8139State *s) +{ + if (!rtl8139_transmitter_enabled(s)) + { + DPRINTF("+++ C+ mode: transmitter disabled\n"); + return 0; + } + + if (!rtl8139_cp_transmitter_enabled(s)) + { + DPRINTF("+++ C+ mode: C+ transmitter disabled\n"); + return 0 ; + } + int descriptor = s->currCPlusTxDesc; + + uint32_t cplus_tx_ring_desc = rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]); + + /* Normal priority ring */ + cplus_tx_ring_desc += 16 * descriptor; + + DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at " + "%08x %08x = 0x%08X\n", descriptor, s->TxAddr[1], + s->TxAddr[0], cplus_tx_ring_desc); + + uint32_t val, txdw0,txdw1,txbufLO,txbufHI; + + dma_bm_read(cplus_tx_ring_desc, (uint8_t *)&val, 4, 4); + txdw0 = le32_to_cpu(val); + dma_bm_read(cplus_tx_ring_desc+4, (uint8_t *)&val, 4, 4); + txdw1 = le32_to_cpu(val); + dma_bm_read(cplus_tx_ring_desc+8, (uint8_t *)&val, 4, 4); + txbufLO = le32_to_cpu(val); + dma_bm_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4, 4); + txbufHI = le32_to_cpu(val); + + DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor, + txdw0, txdw1, txbufLO, txbufHI); + +/* w0 ownership flag */ +#define CP_TX_OWN (1<<31) +/* w0 end of ring flag */ +#define CP_TX_EOR (1<<30) +/* first segment of received packet flag */ +#define CP_TX_FS (1<<29) +/* last segment of received packet flag */ +#define CP_TX_LS (1<<28) +/* large send packet flag */ +#define CP_TX_LGSEN (1<<27) +/* large send MSS mask, bits 16...26 */ +#define CP_TC_LGSEN_MSS_SHIFT 16 +#define CP_TC_LGSEN_MSS_MASK ((1 << 11) - 1) + +/* IP checksum offload flag */ +#define CP_TX_IPCS (1<<18) +/* UDP checksum offload flag */ +#define CP_TX_UDPCS (1<<17) +/* TCP checksum offload flag */ +#define CP_TX_TCPCS (1<<16) + +/* w0 bits 0...15 : buffer size */ +#define CP_TX_BUFFER_SIZE (1<<16) +#define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1) +/* w1 add tag flag */ +#define CP_TX_TAGC (1<<17) +/* w1 bits 0...15 : VLAN tag (big endian) */ +#define CP_TX_VLAN_TAG_MASK ((1<<16) - 1) +/* w2 low 32bit of Rx buffer ptr */ +/* w3 high 32bit of Rx buffer ptr */ + +/* set after transmission */ +/* FIFO underrun flag */ +#define CP_TX_STATUS_UNF (1<<25) +/* transmit error summary flag, valid if set any of three below */ +#define CP_TX_STATUS_TES (1<<23) +/* out-of-window collision flag */ +#define CP_TX_STATUS_OWC (1<<22) +/* link failure flag */ +#define CP_TX_STATUS_LNKF (1<<21) +/* excessive collisions flag */ +#define CP_TX_STATUS_EXC (1<<20) + + if (!(txdw0 & CP_TX_OWN)) + { + DPRINTF("C+ Tx mode : descriptor %d is owned by host\n", descriptor); + return 0 ; + } + + DPRINTF("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor); + + if (txdw0 & CP_TX_FS) + { + DPRINTF("+++ C+ Tx mode : descriptor %d is first segment " + "descriptor\n", descriptor); + + /* reset internal buffer offset */ + s->cplus_txbuffer_offset = 0; + } + + int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK; + uint32_t tx_addr = rtl8139_addr64(txbufLO, txbufHI); + + /* make sure we have enough space to assemble the packet */ + if (!s->cplus_txbuffer) + { + s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE; + s->cplus_txbuffer = calloc(s->cplus_txbuffer_len, 1); + s->cplus_txbuffer_offset = 0; + + DPRINTF("+++ C+ mode transmission buffer allocated space %d\n", + s->cplus_txbuffer_len); + } + + if (s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) + { + /* The spec didn't tell the maximum size, stick to CP_TX_BUFFER_SIZE */ + txsize = s->cplus_txbuffer_len - s->cplus_txbuffer_offset; + DPRINTF("+++ C+ mode transmission buffer overrun, truncated descriptor" + "length to %d\n", txsize); + } + + /* append more data to the packet */ + + DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at " + "%08X"" to offset %d\n", txsize, tx_addr, + s->cplus_txbuffer_offset); + + dma_bm_read(tx_addr, + s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize, 1); + s->cplus_txbuffer_offset += txsize; + + /* seek to next Rx descriptor */ + if (txdw0 & CP_TX_EOR) + { + s->currCPlusTxDesc = 0; + } + else + { + ++s->currCPlusTxDesc; + if (s->currCPlusTxDesc >= 64) + s->currCPlusTxDesc = 0; + } + + /* Build the Tx Status Descriptor */ + uint32_t tx_status = txdw0; + + /* transfer ownership to target */ + tx_status &= ~CP_TX_OWN; + + /* reset error indicator bits */ + tx_status &= ~CP_TX_STATUS_UNF; + tx_status &= ~CP_TX_STATUS_TES; + tx_status &= ~CP_TX_STATUS_OWC; + tx_status &= ~CP_TX_STATUS_LNKF; + tx_status &= ~CP_TX_STATUS_EXC; + + /* update ring data */ + val = cpu_to_le32(tx_status); + dma_bm_write(cplus_tx_ring_desc, (uint8_t *)&val, 4, 4); + + /* Now decide if descriptor being processed is holding the last segment of packet */ + if (txdw0 & CP_TX_LS) + { + uint8_t dot1q_buffer_space[VLAN_HLEN]; + uint16_t *dot1q_buffer; + + DPRINTF("+++ C+ Tx mode : descriptor %d is last segment descriptor\n", + descriptor); + + /* can transfer fully assembled packet */ + + uint8_t *saved_buffer = s->cplus_txbuffer; + int saved_size = s->cplus_txbuffer_offset; + int saved_buffer_len = s->cplus_txbuffer_len; + + /* create vlan tag */ + if (txdw1 & CP_TX_TAGC) { + /* the vlan tag is in BE byte order in the descriptor + * BE + le_to_cpu() + ~swap()~ = cpu */ + DPRINTF("+++ C+ Tx mode : inserting vlan tag with ""tci: %u\n", + bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)); + + dot1q_buffer = (uint16_t *) dot1q_buffer_space; + dot1q_buffer[0] = cpu_to_be16(0x8100); + /* BE + le_to_cpu() + ~cpu_to_le()~ = BE */ + dot1q_buffer[1] = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK); + } else { + dot1q_buffer = NULL; + } + + /* reset the card space to protect from recursive call */ + s->cplus_txbuffer = NULL; + s->cplus_txbuffer_offset = 0; + s->cplus_txbuffer_len = 0; + + if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN)) + { + DPRINTF("+++ C+ mode offloaded task checksum\n"); + + /* Large enough for Ethernet and IP headers? */ + if (saved_size < ETH_HLEN + sizeof(struct ip_header)) { + goto skip_offload; + } + + /* ip packet header */ + struct ip_header *ip = NULL; + int hlen = 0; + uint8_t ip_protocol = 0; + uint16_t ip_data_len = 0; + + uint8_t *eth_payload_data = NULL; + size_t eth_payload_len = 0; + + int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); + if (proto != ETH_P_IP) + { + goto skip_offload; + } + + DPRINTF("+++ C+ mode has IP packet\n"); + + /* Note on memory alignment: eth_payload_data is 16-bit aligned + * since saved_buffer is allocated with g_malloc() and ETH_HLEN is + * even. 32-bit accesses must use ldl/stl wrappers to avoid + * unaligned accesses. + */ + eth_payload_data = saved_buffer + ETH_HLEN; + eth_payload_len = saved_size - ETH_HLEN; + + ip = (struct ip_header*)eth_payload_data; + + if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { + DPRINTF("+++ C+ mode packet has bad IP version %d " + "expected %d\n", IP_HEADER_VERSION(ip), + IP_HEADER_VERSION_4); + goto skip_offload; + } + + hlen = IP_HDR_GET_LEN(ip); + if (hlen < sizeof(struct ip_header) || hlen > eth_payload_len) { + goto skip_offload; + } + + ip_protocol = ip->ip_p; + + ip_data_len = be16_to_cpu(ip->ip_len); + if (ip_data_len < hlen || ip_data_len > eth_payload_len) { + goto skip_offload; + } + ip_data_len -= hlen; + + if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & CP_TX_IPCS)) + { + DPRINTF("+++ C+ mode need IP checksum\n"); + + ip->ip_sum = 0; + ip->ip_sum = ip_checksum(ip, hlen); + DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", + hlen, ip->ip_sum); + } + + if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) + { + /* Large enough for the TCP header? */ + if (ip_data_len < sizeof(tcp_header)) { + goto skip_offload; + } + + int large_send_mss = (txdw0 >> CP_TC_LGSEN_MSS_SHIFT) & + CP_TC_LGSEN_MSS_MASK; + if (large_send_mss == 0) { + goto skip_offload; + } + + DPRINTF("+++ C+ mode offloaded task TSO IP data %d " + "frame data %d specified MSS=%d\n", + ip_data_len, saved_size - ETH_HLEN, large_send_mss); + + int tcp_send_offset = 0; + + /* maximum IP header length is 60 bytes */ + uint8_t saved_ip_header[60]; + + /* save IP header template; data area is used in tcp checksum calculation */ + memcpy(saved_ip_header, eth_payload_data, hlen); + + /* a placeholder for checksum calculation routine in tcp case */ + uint8_t *data_to_checksum = eth_payload_data + hlen - 12; + // size_t data_to_checksum_len = eth_payload_len - hlen + 12; + + /* pointer to TCP header */ + tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); + + int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); + + /* Invalid TCP data offset? */ + if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) { + goto skip_offload; + } + + int tcp_data_len = ip_data_len - tcp_hlen; + + DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " + "data len %d\n", ip_data_len, tcp_hlen, tcp_data_len); + + /* note the cycle below overwrites IP header data, + but restores it from saved_ip_header before sending packet */ + + int is_last_frame = 0; + + for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += large_send_mss) + { + uint16_t chunk_size = large_send_mss; + + /* check if this is the last frame */ + if (tcp_send_offset + large_send_mss >= tcp_data_len) + { + is_last_frame = 1; + chunk_size = tcp_data_len - tcp_send_offset; + } + + //DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", + // ldl_be_p(&p_tcp_hdr->th_seq)); + + /* add 4 TCP pseudoheader fields */ + /* copy IP source and destination fields */ + memcpy(data_to_checksum, saved_ip_header + 12, 8); + + DPRINTF("+++ C+ mode TSO calculating TCP checksum for " + "packet with %d bytes data\n", tcp_hlen + + chunk_size); + + if (tcp_send_offset) + { + memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); + } + +#define TCP_FLAGS_ONLY(flags) ((flags) & 0x3f) +#define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off))) + /* keep PUSH and FIN flags only for the last frame */ + if (!is_last_frame) + { + TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TH_PUSH | TH_FIN); + } + + /* recalculate TCP checksum */ + ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; + p_tcpip_hdr->zeros = 0; + p_tcpip_hdr->ip_proto = IP_PROTO_TCP; + p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); + + p_tcp_hdr->th_sum = 0; + + int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); + DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", + tcp_checksum); + + p_tcp_hdr->th_sum = tcp_checksum; + + /* restore IP header */ + memcpy(eth_payload_data, saved_ip_header, hlen); + + /* set IP data length and recalculate IP checksum */ + ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size); + + /* increment IP id for subsequent frames */ + ip->ip_id = cpu_to_be16(tcp_send_offset/large_send_mss + be16_to_cpu(ip->ip_id)); + + ip->ip_sum = 0; + ip->ip_sum = ip_checksum(eth_payload_data, hlen); + DPRINTF("+++ C+ mode TSO IP header len=%d " + "checksum=%04x\n", hlen, ip->ip_sum); + + int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; + DPRINTF("+++ C+ mode TSO transferring packet size " + "%d\n", tso_send_size); + rtl8139_transfer_frame(s, saved_buffer, tso_send_size, + 0, (uint8_t *) dot1q_buffer); + + /* add transferred count to TCP sequence number */ + //stl_be_p(&p_tcp_hdr->th_seq, + // chunk_size + ldl_be_p(&p_tcp_hdr->th_seq)); + p_tcp_hdr->th_seq = bswap32(chunk_size + bswap32(p_tcp_hdr->th_seq)); + } + + /* Stop sending this frame */ + saved_size = 0; + } + else if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))) + { + DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); + + /* maximum IP header length is 60 bytes */ + uint8_t saved_ip_header[60]; + memcpy(saved_ip_header, eth_payload_data, hlen); + + uint8_t *data_to_checksum = eth_payload_data + hlen - 12; + // size_t data_to_checksum_len = eth_payload_len - hlen + 12; + + /* add 4 TCP pseudoheader fields */ + /* copy IP source and destination fields */ + memcpy(data_to_checksum, saved_ip_header + 12, 8); + + if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) + { + DPRINTF("+++ C+ mode calculating TCP checksum for " + "packet with %d bytes data\n", ip_data_len); + + ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; + p_tcpip_hdr->zeros = 0; + p_tcpip_hdr->ip_proto = IP_PROTO_TCP; + p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); + + tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12); + + p_tcp_hdr->th_sum = 0; + + int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); + DPRINTF("+++ C+ mode TCP checksum %04x\n", + tcp_checksum); + + p_tcp_hdr->th_sum = tcp_checksum; + } + else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) + { + DPRINTF("+++ C+ mode calculating UDP checksum for " + "packet with %d bytes data\n", ip_data_len); + + ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; + p_udpip_hdr->zeros = 0; + p_udpip_hdr->ip_proto = IP_PROTO_UDP; + p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); + + udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12); + + p_udp_hdr->uh_sum = 0; + + int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); + DPRINTF("+++ C+ mode UDP checksum %04x\n", + udp_checksum); + + p_udp_hdr->uh_sum = udp_checksum; + } + + /* restore IP header */ + memcpy(eth_payload_data, saved_ip_header, hlen); + } + } + +skip_offload: + /* update tally counter */ + ++s->tally_counters.TxOk; + + DPRINTF("+++ C+ mode transmitting %d bytes packet\n", saved_size); + + rtl8139_transfer_frame(s, saved_buffer, saved_size, 1, + (uint8_t *) dot1q_buffer); + + /* restore card space if there was no recursion and reset offset */ + if (!s->cplus_txbuffer) + { + s->cplus_txbuffer = saved_buffer; + s->cplus_txbuffer_len = saved_buffer_len; + s->cplus_txbuffer_offset = 0; + } + else + { + free(saved_buffer); + } + } + else + { + DPRINTF("+++ C+ mode transmission continue to next descriptor\n"); + } + + return 1; +} + +static void rtl8139_cplus_transmit(RTL8139State *s) +{ + int txcount = 0; + + while (txcount < 64 && rtl8139_cplus_transmit_one(s)) + { + ++txcount; + } + + /* Mark transfer completed */ + if (!txcount) + { + DPRINTF("C+ mode : transmitter queue stalled, current TxDesc = %d\n", + s->currCPlusTxDesc); + } + else + { + /* update interrupt status */ + s->IntrStatus |= TxOK; + rtl8139_update_irq(s); + } +} + +static void rtl8139_transmit(RTL8139State *s) +{ + int descriptor = s->currTxDesc, txcount = 0; + + /*while*/ + if (rtl8139_transmit_one(s, descriptor)) + { + ++s->currTxDesc; + s->currTxDesc %= 4; + ++txcount; + } + + /* Mark transfer completed */ + if (!txcount) + { + DPRINTF("transmitter queue stalled, current TxDesc = %d\n", + s->currTxDesc); + } +} + + +static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) +{ + + int descriptor = txRegOffset/4; + + /* handle C+ transmit mode register configuration */ + + if (s->cplus_enabled) + { + DPRINTF("RTL8139C+ DTCCR write offset=0x%x val=0x%08x " + "descriptor=%d\n", txRegOffset, val, descriptor); + + /* handle Dump Tally Counters command */ + s->TxStatus[descriptor] = val; + + if (descriptor == 0 && (val & 0x8)) + { + uint32_t tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]); + + /* dump tally counters to specified memory location */ + RTL8139TallyCounters_dma_write(s, tc_addr); + + /* mark dump completed */ + s->TxStatus[0] &= ~0x8; + } + + return; + } + + DPRINTF("TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", + txRegOffset, val, descriptor); + + /* mask only reserved bits */ + val &= ~0xff00c000; /* these bits are reset on write */ + val = SET_MASKED(val, 0x00c00000, s->TxStatus[descriptor]); + + s->TxStatus[descriptor] = val; + + /* attempt to start transmission */ + rtl8139_transmit(s); +} + +static uint32_t rtl8139_TxStatus_TxAddr_read(RTL8139State *s, uint32_t regs[], + uint32_t base, uint8_t addr, + int size) +{ + uint32_t reg = (addr - base) / 4; + uint32_t offset = addr & 0x3; + uint32_t ret = 0; + + if (addr & (size - 1)) { + DPRINTF("not implemented read for TxStatus/TxAddr " + "addr=0x%x size=0x%x\n", addr, size); + return ret; + } + + switch (size) { + case 1: /* fall through */ + case 2: /* fall through */ + case 4: + ret = (regs[reg] >> offset * 8) & (((uint64_t)1 << (size * 8)) - 1); + DPRINTF("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n", + reg, addr, size, ret); + break; + default: + DPRINTF("unsupported size 0x%x of TxStatus/TxAddr reading\n", size); + break; + } + + return ret; +} + +static uint16_t rtl8139_TSAD_read(RTL8139State *s) +{ + uint16_t ret = 0; + + /* Simulate TSAD, it is read only anyway */ + + ret = ((s->TxStatus[3] & TxStatOK )?TSAD_TOK3:0) + |((s->TxStatus[2] & TxStatOK )?TSAD_TOK2:0) + |((s->TxStatus[1] & TxStatOK )?TSAD_TOK1:0) + |((s->TxStatus[0] & TxStatOK )?TSAD_TOK0:0) + + |((s->TxStatus[3] & TxUnderrun)?TSAD_TUN3:0) + |((s->TxStatus[2] & TxUnderrun)?TSAD_TUN2:0) + |((s->TxStatus[1] & TxUnderrun)?TSAD_TUN1:0) + |((s->TxStatus[0] & TxUnderrun)?TSAD_TUN0:0) + + |((s->TxStatus[3] & TxAborted )?TSAD_TABT3:0) + |((s->TxStatus[2] & TxAborted )?TSAD_TABT2:0) + |((s->TxStatus[1] & TxAborted )?TSAD_TABT1:0) + |((s->TxStatus[0] & TxAborted )?TSAD_TABT0:0) + + |((s->TxStatus[3] & TxHostOwns )?TSAD_OWN3:0) + |((s->TxStatus[2] & TxHostOwns )?TSAD_OWN2:0) + |((s->TxStatus[1] & TxHostOwns )?TSAD_OWN1:0) + |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ; + + + DPRINTF("TSAD read val=0x%04x\n", ret); + + return ret; +} + +static uint16_t rtl8139_CSCR_read(RTL8139State *s) +{ + uint16_t ret = s->CSCR; + + DPRINTF("CSCR read val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val) +{ + DPRINTF("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val); + + s->TxAddr[txAddrOffset/4] = val; +} + +static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) +{ + uint32_t ret = s->TxAddr[txAddrOffset/4]; + + DPRINTF("TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret); + + return ret; +} + +static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) +{ + DPRINTF("RxBufPtr write val=0x%04x\n", val); + + /* this value is off by 16 */ + s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize); + + DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); +} + +static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s) +{ + /* this value is off by 16 */ + uint32_t ret = s->RxBufPtr - 0x10; + + DPRINTF("RxBufPtr read val=0x%04x\n", ret); + + return ret; +} + +static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s) +{ + /* this value is NOT off by 16 */ + uint32_t ret = s->RxBufAddr; + + DPRINTF("RxBufAddr read val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val) +{ + DPRINTF("RxBuf write val=0x%08x\n", val); + + s->RxBuf = val; + + /* may need to reset rxring here */ +} + +static uint32_t rtl8139_RxBuf_read(RTL8139State *s) +{ + uint32_t ret = s->RxBuf; + + DPRINTF("RxBuf read val=0x%08x\n", ret); + + return ret; +} + +static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) +{ + DPRINTF("IntrMask write(w) val=0x%04x\n", val); + + /* mask unwritable bits */ + val = SET_MASKED(val, 0x1e00, s->IntrMask); + + s->IntrMask = val; + + rtl8139_update_irq(s); + +} + +static uint32_t rtl8139_IntrMask_read(RTL8139State *s) +{ + uint32_t ret = s->IntrMask; + + DPRINTF("IntrMask read(w) val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) +{ + DPRINTF("IntrStatus write(w) val=0x%04x\n", val); + +#if 0 + + /* writing to ISR has no effect */ + + return; + +#else + uint16_t newStatus = s->IntrStatus & ~val; + + /* mask unwritable bits */ + newStatus = SET_MASKED(newStatus, 0x1e00, s->IntrStatus); + + /* writing 1 to interrupt status register bit clears it */ + s->IntrStatus = 0; + rtl8139_update_irq(s); + + s->IntrStatus = newStatus; + rtl8139_update_irq(s); + +#endif +} + +static uint32_t rtl8139_IntrStatus_read(RTL8139State *s) +{ + uint32_t ret = s->IntrStatus; + + DPRINTF("IntrStatus read(w) val=0x%04x\n", ret); + +#if 0 + + /* reading ISR clears all interrupts */ + s->IntrStatus = 0; + + rtl8139_update_irq(s); + +#endif + + return ret; +} + +static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val) +{ + DPRINTF("MultiIntr write(w) val=0x%04x\n", val); + + /* mask unwritable bits */ + val = SET_MASKED(val, 0xf000, s->MultiIntr); + + s->MultiIntr = val; +} + +static uint32_t rtl8139_MultiIntr_read(RTL8139State *s) +{ + uint32_t ret = s->MultiIntr; + + DPRINTF("MultiIntr read(w) val=0x%04x\n", ret); + + return ret; +} + +static void rtl8139_io_writeb(uint32_t addr, uint8_t val, void *opaque) +{ + RTL8139State *s = opaque; + + addr &= 0xFF; + switch (addr) + { + case MAC0 ... MAC0+4: + s->phys[addr - MAC0] = val; + break; + case MAC0+5: + s->phys[addr - MAC0] = val; + break; + case MAC0+6 ... MAC0+7: + /* reserved */ + break; + case MAR0 ... MAR0+7: + s->mult[addr - MAR0] = val; + break; + case ChipCmd: + rtl8139_ChipCmd_write(s, val); + break; + case Cfg9346: + rtl8139_Cfg9346_write(s, val); + break; + case TxConfig: /* windows driver sometimes writes using byte-lenth call */ + rtl8139_TxConfig_writeb(s, val); + break; + case Config0: + rtl8139_Config0_write(s, val); + break; + case Config1: + rtl8139_Config1_write(s, val); + break; + case Config3: + rtl8139_Config3_write(s, val); + break; + case Config4: + rtl8139_Config4_write(s, val); + break; + case Config5: + rtl8139_Config5_write(s, val); + break; + case MediaStatus: + /* ignore */ + DPRINTF("not implemented write(b) to MediaStatus val=0x%02x\n", + val); + break; + + case HltClk: + DPRINTF("HltClk write val=0x%08x\n", val); + if (val == 'R') + { + s->clock_enabled = 1; + } + else if (val == 'H') + { + s->clock_enabled = 0; + } + break; + + case TxThresh: + DPRINTF("C+ TxThresh write(b) val=0x%02x\n", val); + s->TxThresh = val; + break; + + case TxPoll: + DPRINTF("C+ TxPoll write(b) val=0x%02x\n", val); + if (val & (1 << 7)) + { + DPRINTF("C+ TxPoll high priority transmission (not " + "implemented)\n"); + //rtl8139_cplus_transmit(s); + } + if (val & (1 << 6)) + { + DPRINTF("C+ TxPoll normal priority transmission\n"); + rtl8139_cplus_transmit(s); + } + + break; + + default: + DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr, + val); + break; + } +} + +static void rtl8139_io_writew(uint32_t addr, uint16_t val, void *opaque) +{ + RTL8139State *s = opaque; + + addr &= 0xFF; + switch (addr) + { + case IntrMask: + rtl8139_IntrMask_write(s, val); + break; + + case IntrStatus: + rtl8139_IntrStatus_write(s, val); + break; + + case MultiIntr: + rtl8139_MultiIntr_write(s, val); + break; + + case RxBufPtr: + rtl8139_RxBufPtr_write(s, val); + break; + + case BasicModeCtrl: + rtl8139_BasicModeCtrl_write(s, val); + break; + case BasicModeStatus: + rtl8139_BasicModeStatus_write(s, val); + break; + case NWayAdvert: + DPRINTF("NWayAdvert write(w) val=0x%04x\n", val); + s->NWayAdvert = val; + break; + case NWayLPAR: + DPRINTF("forbidden NWayLPAR write(w) val=0x%04x\n", val); + break; + case NWayExpansion: + DPRINTF("NWayExpansion write(w) val=0x%04x\n", val); + s->NWayExpansion = val; + break; + + case CpCmd: + rtl8139_CpCmd_write(s, val); + break; + + case IntrMitigate: + rtl8139_IntrMitigate_write(s, val); + break; + + default: + DPRINTF("ioport write(w) addr=0x%x val=0x%04x via write(b)\n", + addr, val); + + rtl8139_io_writeb(addr, val & 0xff, opaque); + rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, opaque); + break; + } +} + +/* TODO: Implement timer. */ + +static void rtl8139_io_writel(uint32_t addr, uint32_t val, void *opaque) +{ + RTL8139State *s = opaque; + + addr &= 0xFF; + switch (addr) + { + case RxMissed: + DPRINTF("RxMissed clearing on write\n"); + s->RxMissed = 0; + break; + + case TxConfig: + rtl8139_TxConfig_write(s, val); + break; + + case RxConfig: + rtl8139_RxConfig_write(s, val); + break; + + case TxStatus0 ... TxStatus0+4*4-1: + rtl8139_TxStatus_write(s, addr-TxStatus0, val); + break; + + case TxAddr0 ... TxAddr0+4*4-1: + rtl8139_TxAddr_write(s, addr-TxAddr0, val); + break; + + case RxBuf: + rtl8139_RxBuf_write(s, val); + break; + + case RxRingAddrLO: + DPRINTF("C+ RxRing low bits write val=0x%08x\n", val); + s->RxRingAddrLO = val; + break; + + case RxRingAddrHI: + DPRINTF("C+ RxRing high bits write val=0x%08x\n", val); + s->RxRingAddrHI = val; + break; + + case Timer: + DPRINTF("TCTR Timer reset on write\n"); + s->TCTR = 0; + //s->TCTR_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + //rtl8139_set_next_tctr_time(s); + break; + + case FlashReg: + DPRINTF("FlashReg TimerInt write val=0x%08x\n", val); + if (s->TimerInt != val) { + s->TimerInt = val; + } + break; + + default: + DPRINTF("ioport write(l) addr=0x%x val=0x%08x via write(b)\n", + addr, val); + rtl8139_io_writeb(addr, val & 0xff, opaque); + rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, opaque); + rtl8139_io_writeb(addr + 2, (val >> 16) & 0xff, opaque); + rtl8139_io_writeb(addr + 3, (val >> 24) & 0xff, opaque); + break; + } +} + + +static uint8_t rtl8139_io_readb(uint32_t addr, void *opaque) +{ + RTL8139State *s = opaque; + uint8_t ret; + + addr &= 0xFF; + switch (addr) + { + case MAC0 ... MAC0+5: + ret = s->phys[addr - MAC0]; + break; + case MAC0+6 ... MAC0+7: + ret = 0; + break; + case MAR0 ... MAR0+7: + ret = s->mult[addr - MAR0]; + break; + case TxStatus0 ... TxStatus0+4*4-1: + ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0, + addr, 1); + break; + case ChipCmd: + ret = rtl8139_ChipCmd_read(s); + break; + case Cfg9346: + ret = rtl8139_Cfg9346_read(s); + break; + case Config0: + ret = rtl8139_Config0_read(s); + break; + case Config1: + ret = rtl8139_Config1_read(s); + break; + case Config3: + ret = rtl8139_Config3_read(s); + break; + case Config4: + ret = rtl8139_Config4_read(s); + break; + case Config5: + ret = rtl8139_Config5_read(s); + break; + + case MediaStatus: + /* The LinkDown bit of MediaStatus is inverse with link status */ + ret = 0xd0 | (~s->BasicModeStatus & 0x04); + DPRINTF("MediaStatus read 0x%x\n", ret); + break; + + case HltClk: + ret = s->clock_enabled; + DPRINTF("HltClk read 0x%x\n", ret); + break; + + case PCIRevisionID: + ret = RTL8139_PCI_REVID; + DPRINTF("PCI Revision ID read 0x%x\n", ret); + break; + + case TxThresh: + ret = s->TxThresh; + DPRINTF("C+ TxThresh read(b) val=0x%02x\n", ret); + break; + + case 0x43: /* Part of TxConfig register. Windows driver tries to read it */ + ret = s->TxConfig >> 24; + DPRINTF("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret); + break; + + default: + DPRINTF("not implemented read(b) addr=0x%x\n", addr); + ret = 0; + break; + } + + return ret; +} + +static uint16_t rtl8139_io_readw(uint32_t addr, void *opaque) +{ + RTL8139State *s = opaque; + uint16_t ret; + + addr &= 0xFF; + switch (addr) + { + case TxAddr0 ... TxAddr0+4*4-1: + ret = rtl8139_TxStatus_TxAddr_read(s, s->TxAddr, TxAddr0, addr, 2); + break; + case IntrMask: + ret = rtl8139_IntrMask_read(s); + break; + + case IntrStatus: + ret = rtl8139_IntrStatus_read(s); + break; + + case MultiIntr: + ret = rtl8139_MultiIntr_read(s); + break; + + case RxBufPtr: + ret = rtl8139_RxBufPtr_read(s); + break; + + case RxBufAddr: + ret = rtl8139_RxBufAddr_read(s); + break; + + case BasicModeCtrl: + ret = rtl8139_BasicModeCtrl_read(s); + break; + case BasicModeStatus: + ret = rtl8139_BasicModeStatus_read(s); + break; + case NWayAdvert: + ret = s->NWayAdvert; + DPRINTF("NWayAdvert read(w) val=0x%04x\n", ret); + break; + case NWayLPAR: + ret = s->NWayLPAR; + DPRINTF("NWayLPAR read(w) val=0x%04x\n", ret); + break; + case NWayExpansion: + ret = s->NWayExpansion; + DPRINTF("NWayExpansion read(w) val=0x%04x\n", ret); + break; + + case CpCmd: + ret = rtl8139_CpCmd_read(s); + break; + + case IntrMitigate: + ret = rtl8139_IntrMitigate_read(s); + break; + + case TxSummary: + ret = rtl8139_TSAD_read(s); + break; + + case CSCR: + ret = rtl8139_CSCR_read(s); + break; + + default: + DPRINTF("ioport read(w) addr=0x%x via read(b)\n", addr); + + ret = rtl8139_io_readb(addr, opaque); + ret |= rtl8139_io_readb(addr + 1, opaque) << 8; + + DPRINTF("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret); + break; + } + + return ret; +} + +static uint32_t rtl8139_io_readl(uint32_t addr, void *opaque) +{ + RTL8139State *s = opaque; + uint32_t ret; + + addr &= 0xFF; + switch (addr) + { + case RxMissed: + ret = s->RxMissed; + + DPRINTF("RxMissed read val=0x%08x\n", ret); + break; + + case TxConfig: + ret = rtl8139_TxConfig_read(s); + break; + + case RxConfig: + ret = rtl8139_RxConfig_read(s); + break; + + case TxStatus0 ... TxStatus0+4*4-1: + ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0, + addr, 4); + break; + + case TxAddr0 ... TxAddr0+4*4-1: + ret = rtl8139_TxAddr_read(s, addr-TxAddr0); + break; + + case RxBuf: + ret = rtl8139_RxBuf_read(s); + break; + + case RxRingAddrLO: + ret = s->RxRingAddrLO; + DPRINTF("C+ RxRing low bits read val=0x%08x\n", ret); + break; + + case RxRingAddrHI: + ret = s->RxRingAddrHI; + DPRINTF("C+ RxRing high bits read val=0x%08x\n", ret); + break; + + case Timer: + //ret = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->TCTR_base) / + // PCI_PERIOD; + ret = s->TCTR; + DPRINTF("TCTR Timer read val=0x%08x\n", ret); + break; + + case FlashReg: + ret = s->TimerInt; + DPRINTF("FlashReg TimerInt read val=0x%08x\n", ret); + break; + + default: + DPRINTF("ioport read(l) addr=0x%x via read(b)\n", addr); + + ret = rtl8139_io_readb(addr, opaque); + ret |= rtl8139_io_readb(addr + 1, opaque) << 8; + ret |= rtl8139_io_readb(addr + 2, opaque) << 16; + ret |= rtl8139_io_readb(addr + 3, opaque) << 24; + + DPRINTF("read(l) addr=0x%x val=%08x\n", addr, ret); + break; + } + + return ret; +} + +static uint32_t rtl8139_io_readl_ioport(uint16_t addr, void *opaque) +{ + return rtl8139_io_readl(addr, opaque); +} + +static uint16_t rtl8139_io_readw_ioport(uint16_t addr, void *opaque) +{ + return rtl8139_io_readw(addr, opaque); +} + +static uint8_t rtl8139_io_readb_ioport(uint16_t addr, void *opaque) +{ + return rtl8139_io_readb(addr, opaque); +} + +static void rtl8139_io_writel_ioport(uint16_t addr, uint32_t val, void *opaque) +{ + return rtl8139_io_writel(addr, val, opaque); +} + +static void rtl8139_io_writew_ioport(uint16_t addr, uint16_t val, void *opaque) +{ + return rtl8139_io_writew(addr, val, opaque); +} + +static void rtl8139_io_writeb_ioport(uint16_t addr, uint8_t val, void *opaque) +{ + return rtl8139_io_writeb(addr, val, opaque); +} + +static int rtl8139_set_link_status(void* priv, uint32_t link_state) +{ + RTL8139State *s = (RTL8139State*)priv; + + if ((link_state & NET_LINK_DOWN)) { + s->BasicModeStatus &= ~0x04; + } else { + s->BasicModeStatus |= 0x04; + } + + s->IntrStatus |= RxUnderrun; + rtl8139_update_irq(s); + return 0; +} + +static void rtl8139_timer(void *opaque) +{ + RTL8139State *s = opaque; + + timer_on_auto(&s->timer, 1. / 33.); + + if (!s->clock_enabled) + { + DPRINTF(">>> timer: clock is not running\n"); + return; + } + + s->TCTR++; + + if (s->TCTR >= s->TimerInt && s->TimerInt != 0){ + s->IntrStatus |= PCSTimeout; + rtl8139_update_irq(s); + } +} + +static uint8_t +rtl8139_pci_read(int func, int addr, void *p) +{ + RTL8139State *s = (RTL8139State *) p; + + switch (addr) { + default: + return s->pci_conf[addr & 0xFF]; + case 0x00: + return 0xEC; + case 0x01: + return 0x10; + case 0x02: + return 0x39; + case 0x03: + return 0x81; + case 0x07: + return 0x02; + case 0x06: + return 0x80; + case 0x5: + return s->pci_conf[addr & 0xFF] & 1; + case 0x8: + return 0x20; + case 0x9: + return 0x0; + case 0xA: + return 0x0; + case 0xB: + return 0x2; + case 0x10: + return 1; + case 0x14: + return 0; + case 0x2C: + return 0xEC; + case 0x2D: + return 0x10; + case 0x2E: + return 0x39; + case 0x2F: + return 0x81; + case 0x3D: + return PCI_INTA; + case 0x34: + return 0xDC; + } +} + +static void +rtl8139_pci_write(int func, int addr, uint8_t val, void *p) +{ + RTL8139State *s = (RTL8139State *) p; + + switch (addr) { + case 0x4: + mem_mapping_disable(&s->bar_mem); + io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + s->pci_conf[addr & 0xFF] = val; + if (val & PCI_COMMAND_IO) + io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + if ((val & PCI_COMMAND_MEM) && s->bar_mem.size) + mem_mapping_enable(&s->bar_mem); + break; + case 0x5: + s->pci_conf[addr & 0xFF] = val & 1; + break; + case 0xc: + s->pci_conf[addr & 0xFF] = val; + break; + case 0x10: + case 0x11: + io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + s->pci_conf[addr & 0xFF] = val; + if (s->pci_conf[0x4] & PCI_COMMAND_IO) + io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + s->pci_conf[addr & 0xFF] = val; + if (s->pci_conf[0x4] & PCI_COMMAND_MEM) + mem_mapping_set_addr(&s->bar_mem, (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24), 256); + break; + case 0x3C: + s->pci_conf[addr & 0xFF] = val; + break; + } +} + +static void * +nic_init(const device_t *info) +{ + RTL8139State *s = calloc(1, sizeof(RTL8139State)); + FILE* f = NULL; + char eeprom_filename[1024] = { 0 }; + mem_mapping_add(&s->bar_mem, 0, 0, rtl8139_io_readb, rtl8139_io_readw, rtl8139_io_readl, rtl8139_io_writeb, rtl8139_io_writew, rtl8139_io_writel, NULL, MEM_MAPPING_EXTERNAL, s); + s->dev = pci_add_card(PCI_ADD_NETWORK, rtl8139_pci_read, rtl8139_pci_write, s); + s->inst = device_get_instance(); + + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_%d.nvr", s->inst); + + f = nvr_fopen(eeprom_filename, "rb"); + if (f) + { + fread(s->eeprom.contents, 2, 64, f); + fclose(f); + f = NULL; + } else { + /* prepare eeprom */ + s->eeprom.contents[0] = 0x8129; + + /* PCI vendor and device ID should be mirrored here */ + s->eeprom.contents[1] = 0x10EC; + s->eeprom.contents[2] = 0x8139; + + /* XXX: Get proper MAC addresses from real EEPROM dumps. OID taken from net_ne2000.c */ + s->eeprom.contents[7] = 0xe000; + s->eeprom.contents[8] = 0x124c; + s->eeprom.contents[9] = 0x1413; + } + + s->nic = network_attach(s, (uint8_t*)&s->eeprom.contents[7], rtl8139_do_receive, rtl8139_set_link_status); + timer_add(&s->timer, rtl8139_timer, s, 0); + timer_on_auto(&s->timer, 1. / 33.); + + s->cplus_txbuffer = NULL; + s->cplus_txbuffer_len = 0; + s->cplus_txbuffer_offset = 0; + + return s; +} + +static void +nic_close(void *priv) +{ + RTL8139State *s = (RTL8139State*)priv; + FILE* f = NULL; + char eeprom_filename[1024] = { 0 }; + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_%d.nvr", s->inst); + f = nvr_fopen(eeprom_filename, "wb"); + if (f) + { + fwrite(s->eeprom.contents, 2, 64, f); + fclose(f); + f = NULL; + } + free(priv); +} + +const device_t rtl8139c_device = { + .name = "Realtek RTL8139C", + .internal_name = "rtl8139c", + .flags = DEVICE_PCI, + .local = 0, + .init = nic_init, + .close = nic_close, + .reset = rtl8139_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/network/network.c b/src/network/network.c index 06b70bf51..ac27b9067 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -74,6 +74,7 @@ #include <86box/net_plip.h> #include <86box/net_wd8003.h> #include <86box/net_tulip.h> +#include <86box/net_rtl8139.h> #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN @@ -118,6 +119,7 @@ static const device_t *net_cards[] = { &rtl8029as_device, &pcnet_am79c960_vlb_device, &dec_tulip_device, + &rtl8139c_device, NULL }; From 5685583d335609a523d9669b673afe439dc98d1f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 31 Jul 2023 02:37:49 +0600 Subject: [PATCH 024/133] RTL8139: Fix potential interrupt storm --- src/network/net_rtl8139.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 144af7845..24ac2f72a 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -3165,7 +3165,7 @@ static void rtl8139_timer(void *opaque) s->TCTR++; - if (s->TCTR >= s->TimerInt && s->TimerInt != 0){ + if (s->TCTR == s->TimerInt && s->TimerInt != 0){ s->IntrStatus |= PCSTimeout; rtl8139_update_irq(s); } From abdb34aed6633014c66e908ed53cac7f9465b018 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 31 Jul 2023 16:40:41 +0600 Subject: [PATCH 025/133] net_rtl8139: This is a RTL8139C+ NIC --- src/include/86box/net_rtl8139.h | 2 +- src/network/net_rtl8139.c | 8 ++++---- src/network/network.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/include/86box/net_rtl8139.h b/src/include/86box/net_rtl8139.h index 420b07b4f..fec851b06 100644 --- a/src/include/86box/net_rtl8139.h +++ b/src/include/86box/net_rtl8139.h @@ -1 +1 @@ -extern const device_t rtl8139c_device; \ No newline at end of file +extern const device_t rtl8139c_plus_device; \ No newline at end of file diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 24ac2f72a..4b4f320b9 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Emulation of Realtek RTL8139C NIC. + * Emulation of Realtek RTL8139C+ NIC. * * * Authors: Cacodemon345 @@ -3322,9 +3322,9 @@ nic_close(void *priv) free(priv); } -const device_t rtl8139c_device = { - .name = "Realtek RTL8139C", - .internal_name = "rtl8139c", +const device_t rtl8139c_plus_device = { + .name = "Realtek RTL8139C+", + .internal_name = "rtl8139c+", .flags = DEVICE_PCI, .local = 0, .init = nic_init, diff --git a/src/network/network.c b/src/network/network.c index ac27b9067..71cffe176 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -119,7 +119,7 @@ static const device_t *net_cards[] = { &rtl8029as_device, &pcnet_am79c960_vlb_device, &dec_tulip_device, - &rtl8139c_device, + &rtl8139c_plus_device, NULL }; From 76a589012f6bb083ddd6171823cb27363a9fc7aa Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 31 Jul 2023 17:19:45 +0600 Subject: [PATCH 026/133] net_rtl8139.c: Also change name of EEPROM file on-disk --- src/network/net_rtl8139.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 4b4f320b9..02187582f 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -3272,7 +3272,7 @@ nic_init(const device_t *info) s->dev = pci_add_card(PCI_ADD_NETWORK, rtl8139_pci_read, rtl8139_pci_write, s); s->inst = device_get_instance(); - snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_%d.nvr", s->inst); + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); f = nvr_fopen(eeprom_filename, "rb"); if (f) @@ -3311,7 +3311,7 @@ nic_close(void *priv) RTL8139State *s = (RTL8139State*)priv; FILE* f = NULL; char eeprom_filename[1024] = { 0 }; - snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_%d.nvr", s->inst); + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); f = nvr_fopen(eeprom_filename, "wb"); if (f) { From dbf798f63db144563b3acf8af6377bb6b7c5ff6b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 31 Jul 2023 17:45:20 -0400 Subject: [PATCH 027/133] Fix makefile.mingw building --- src/win/Makefile.mingw | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index a947dfb62..3b158a0d2 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -686,7 +686,10 @@ NETOBJ := network.o \ net_3c503.o net_ne2000.o \ net_pcnet.o net_wd8003.o \ net_plip.o net_event.o \ - net_null.o + net_null.o \ + net_eeprom_nmc93cxx.c \ + net_tulip.c \ + net_rtl8139.c PRINTOBJ := png.o prt_cpmap.o \ prt_escp.o prt_text.o prt_ps.o From 3522b3ba5dcc7cf1d73f9128f03201f999ed9dc4 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 3 Aug 2023 00:26:15 +0600 Subject: [PATCH 028/133] Add DECchip 24110 NIC emulation --- src/include/86box/net_tulip.h | 3 +- src/network/net_tulip.c | 152 +++++++++++++++++++++++++++++++++- src/network/network.c | 1 + 3 files changed, 153 insertions(+), 3 deletions(-) diff --git a/src/include/86box/net_tulip.h b/src/include/86box/net_tulip.h index 492d5a40f..681b89c97 100644 --- a/src/include/86box/net_tulip.h +++ b/src/include/86box/net_tulip.h @@ -1 +1,2 @@ -extern const device_t dec_tulip_device; \ No newline at end of file +extern const device_t dec_tulip_device; +extern const device_t dec_tulip_21140_device; \ No newline at end of file diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index c599a69db..f9aa662d1 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -296,6 +296,7 @@ struct tulip_descriptor { struct TULIPState { uint8_t dev; + const device_t* device_info; uint16_t subsys_id, subsys_ven_id; mem_mapping_t memory; netcard_t *nic; @@ -1322,6 +1323,137 @@ static const uint8_t eeprom_default[128] = { 0x00, }; +static const uint8_t eeprom_default_24110[128] = { + 0x46, + 0x26, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x56, + 0x08, + 0x04, + 0x01, + 0x00, /* TODO: Change the MAC Address to the correct one. */ + 0x80, + 0x48, + 0xc3, + 0x3e, + 0xa7, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x08, + 0xff, + 0x01, + 0x8d, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x78, + 0xe0, + 0x01, + 0x00, + 0x50, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe8, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x48, + 0xb3, + 0x0e, + 0xa7, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +}; + static void tulip_fill_eeprom(TULIPState *s) { @@ -1345,7 +1477,7 @@ tulip_pci_read(int func, int addr, void *p) case 0x01: return 0x10; case 0x02: - return 0x19; + return s->device_info->local ? 0x09 : 0x19; case 0x03: return 0x00; case 0x07: @@ -1428,7 +1560,9 @@ nic_init(const device_t *info) if (!s) return NULL; - memcpy(eeprom_default_local, eeprom_default, sizeof(eeprom_default)); + + s->device_info = info; + memcpy(eeprom_default_local, s->device_info->local ? eeprom_default_24110 : eeprom_default, sizeof(eeprom_default)); tulip_idblock_crc((uint16_t *) eeprom_default_local); (((uint16_t *) eeprom_default_local))[63] = (tulip_srom_crc((uint8_t *) eeprom_default_local, 126)); @@ -1467,3 +1601,17 @@ const device_t dec_tulip_device = { .force_redraw = NULL, .config = NULL }; + +const device_t dec_tulip_21140_device = { + .name = "Kingston KNE100TX (DECchip 21140 \"Tulip FasterNet\")", + .internal_name = "dec_21140_tulip", + .flags = DEVICE_PCI, + .local = 1, + .init = nic_init, + .close = nic_close, + .reset = tulip_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/network/network.c b/src/network/network.c index 71cffe176..7778e5ed3 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -120,6 +120,7 @@ static const device_t *net_cards[] = { &pcnet_am79c960_vlb_device, &dec_tulip_device, &rtl8139c_plus_device, + &dec_tulip_21140_device, NULL }; From f1548b3fe6d13eece1272e08b998fffc4c8752cd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 4 Aug 2023 00:03:04 +0600 Subject: [PATCH 029/133] net_tulip: Return TX suspended status --- src/network/net_tulip.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index f9aa662d1..cddcb59d1 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -1067,6 +1067,7 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque) tulip_xmit_list_update(s); } else { tulip_update_ts(s, CSR5_TS_STOPPED); + s->csr[5] |= CSR5_TPS; } break; From 76faa5ef758ddef9e35397964e629d67cb477733 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 4 Aug 2023 00:03:22 +0600 Subject: [PATCH 030/133] net_tulip.c: Add memory mapping --- src/network/net_tulip.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index cddcb59d1..e1f04aaa2 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -1579,6 +1579,7 @@ nic_init(const device_t *info) memcpy(s->mii_regs, tulip_mdi_default, sizeof(tulip_mdi_default)); s->nic = network_attach(s, (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[10], tulip_receive, NULL); s->dev = pci_add_card(PCI_ADD_NETWORK, tulip_pci_read, tulip_pci_write, s); + mem_mapping_add(&s->memory, 0, 0, NULL, NULL, tulip_read, NULL, NULL, tulip_write, NULL, MEM_MAPPING_EXTERNAL, s); tulip_reset(s); return s; } From 57decf2e72810fafb514c2f1793868874b5c69b0 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 4 Aug 2023 15:04:58 +0600 Subject: [PATCH 031/133] net_tulip: L80225 transceiver emulation --- src/network/CMakeLists.txt | 2 +- src/network/net_l80225.c | 42 ++++++++++++++++++++++++++++++++++++++ src/network/net_tulip.c | 13 ++++++++---- 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 src/network/net_l80225.c diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 0920fcf26..b0ba913d5 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -15,7 +15,7 @@ set(net_sources) list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c - net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c) + net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c net_l80225.c) find_package(PkgConfig REQUIRED) pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) diff --git a/src/network/net_l80225.c b/src/network/net_l80225.c new file mode 100644 index 000000000..40764aa67 --- /dev/null +++ b/src/network/net_l80225.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/pci.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/dma.h> +#include <86box/device.h> +#include <86box/thread.h> +#include <86box/network.h> + +uint16_t +l80225_mii_readw(uint16_t* regs, uint16_t addr) +{ + switch (addr) + { + case 0x1: + return 0x782D; + case 0x2: + return 0b10110; + case 0x3: + return 0xF830; + case 0x5: + return 0x41E1; + case 0x18: + return 0xC0; + default: + return regs[addr]; + } + return 0; +} + +void +l80225_mii_writew(uint16_t* regs, uint16_t addr, uint16_t val) +{ + regs[addr] = val; +} \ No newline at end of file diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index e1f04aaa2..421b05d3d 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -660,7 +660,7 @@ static const uint16_t tulip_mdi_default[] = { 0x0000, 0x0000, 0x0000, - 0x0000, + 0x3800, 0x0000, /* MDI Registers 16 - 31 */ 0x0003, @@ -683,6 +683,7 @@ static const uint16_t tulip_mdi_default[] = { /* Readonly mask for MDI (PHY) registers */ static const uint16_t tulip_mdi_mask[] = { + /* MDI Registers 0 - 6, 7 */ 0x0000, 0xffff, 0xffff, @@ -691,6 +692,7 @@ static const uint16_t tulip_mdi_mask[] = { 0xffff, 0xffff, 0x0000, + /* MDI Registers 8 - 15 */ 0x0000, 0x0000, 0x0000, @@ -699,6 +701,7 @@ static const uint16_t tulip_mdi_mask[] = { 0x0000, 0x0000, 0x0000, + /* MDI Registers 16 - 31 */ 0x0fff, 0x0000, 0xffff, @@ -717,12 +720,15 @@ static const uint16_t tulip_mdi_mask[] = { 0x0000, }; +extern uint16_t l80225_mii_readw(uint16_t* regs, uint16_t addr); +extern void l80225_mii_writew(uint16_t* regs, uint16_t addr, uint16_t val); + static uint16_t tulip_mii_read(TULIPState *s, int phy, int reg) { uint16_t ret = 0; if (phy == 1) { - ret = s->mii_regs[reg]; + ret = l80225_mii_readw(s->mii_regs, reg); } return ret; } @@ -734,8 +740,7 @@ tulip_mii_write(TULIPState *s, int phy, int reg, uint16_t data) return; } - s->mii_regs[reg] &= ~tulip_mdi_mask[reg]; - s->mii_regs[reg] |= (data & tulip_mdi_mask[reg]); + return l80225_mii_writew(s->mii_regs, reg, data); } static void From 3616a5b604c8c7472882f3ff1aecf7f323c15da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Fri, 4 Aug 2023 21:45:37 +0200 Subject: [PATCH 032/133] The RTL8193 PCI Latency Timer register is now writable. --- src/network/net_rtl8139.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 02187582f..80f6b2287 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -444,7 +444,9 @@ struct RTL8139State { uint16_t NWayExpansion; uint16_t CpCmd; + uint8_t TxThresh; + uint8_t pci_latency; netcard_t *nic; @@ -3191,32 +3193,34 @@ rtl8139_pci_read(int func, int addr, void *p) return 0x02; case 0x06: return 0x80; - case 0x5: + case 0x05: return s->pci_conf[addr & 0xFF] & 1; - case 0x8: + case 0x08: return 0x20; - case 0x9: + case 0x09: return 0x0; - case 0xA: + case 0x0a: return 0x0; - case 0xB: + case 0x0b: return 0x2; + case 0x0d: + return s->pci_latency; case 0x10: return 1; case 0x14: return 0; - case 0x2C: + case 0x2c: return 0xEC; - case 0x2D: + case 0x2d: return 0x10; - case 0x2E: + case 0x2e: return 0x39; - case 0x2F: + case 0x2f: return 0x81; - case 0x3D: - return PCI_INTA; case 0x34: - return 0xDC; + return 0xdc; + case 0x3d: + return PCI_INTA; } } @@ -3226,7 +3230,7 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *p) RTL8139State *s = (RTL8139State *) p; switch (addr) { - case 0x4: + case 0x04: mem_mapping_disable(&s->bar_mem); io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); s->pci_conf[addr & 0xFF] = val; @@ -3235,12 +3239,15 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *p) if ((val & PCI_COMMAND_MEM) && s->bar_mem.size) mem_mapping_enable(&s->bar_mem); break; - case 0x5: + case 0x05: s->pci_conf[addr & 0xFF] = val & 1; break; - case 0xc: + case 0x0c: s->pci_conf[addr & 0xFF] = val; break; + case 0x0d: + s->pci_latency = val; + break; case 0x10: case 0x11: io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); @@ -3256,7 +3263,7 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *p) if (s->pci_conf[0x4] & PCI_COMMAND_MEM) mem_mapping_set_addr(&s->bar_mem, (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24), 256); break; - case 0x3C: + case 0x3c: s->pci_conf[addr & 0xFF] = val; break; } From 83571bb3440ba3ce9b65b27fa22650ada77e00d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Fri, 4 Aug 2023 21:50:25 +0200 Subject: [PATCH 033/133] Update net_rtl8139.c Make the RTL8139 timer use the actual PCI bus speed. --- src/network/net_rtl8139.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 80f6b2287..25e30d24f 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -33,6 +33,7 @@ #include <86box/network.h> #include <86box/bswap.h> #include <86box/nvr.h> +#include <86box/cpu.h> #include <86box/net_rtl8139.h> #define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ @@ -3157,7 +3158,7 @@ static void rtl8139_timer(void *opaque) { RTL8139State *s = opaque; - timer_on_auto(&s->timer, 1. / 33.); + timer_on_auto(&s->timer, 1000000.0 / ((double) cpu_pci_speed)); if (!s->clock_enabled) { @@ -3303,7 +3304,7 @@ nic_init(const device_t *info) s->nic = network_attach(s, (uint8_t*)&s->eeprom.contents[7], rtl8139_do_receive, rtl8139_set_link_status); timer_add(&s->timer, rtl8139_timer, s, 0); - timer_on_auto(&s->timer, 1. / 33.); + timer_on_auto(&s->timer, 1000000.0 / cpu_pci_speed); s->cplus_txbuffer = NULL; s->cplus_txbuffer_len = 0; From 93c03b5df9ab5776ed80c2377b091ae9c44ceef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Fri, 4 Aug 2023 21:56:35 +0200 Subject: [PATCH 034/133] Update net_rtl8139.c Proper copyrights for the RTL8139. --- src/network/net_rtl8139.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 25e30d24f..39e29791f 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -8,13 +8,20 @@ * * Emulation of Realtek RTL8139C+ NIC. * + * Authors: Igor Kovalenko, + * Mark Malakanov, + * Jurgen Lock, + * Frediano Ziglio, + * Benjamin Poirier. + * Cacodemon345, * - * Authors: Cacodemon345 - * - * Copyright 2023 Cacodemon345 + * Copyright 2006-2023 Igor Kovalenko. + * Copyright 2006-2023 Mark Malakanov. + * Copyright 2006-2023 Jurgen Lock. + * Copyright 2010-2023 Frediano Ziglio. + * Copyright 2011-2023 Benjamin Poirier. + * Copyright 2023 Cacodemon345. */ - -/* Ported over from QEMU */ #include #include #include From bae1915e222494c5fc4b53eda5fc94e47c35b536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Fri, 4 Aug 2023 21:58:16 +0200 Subject: [PATCH 035/133] Proper copyrights for the Tulip code as well. --- src/network/net_tulip.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index c599a69db..956f142e6 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -8,13 +8,12 @@ * * Emulation of DECchip "Tulip" 21143 NIC. * + * Authors: Sven Schnelle, + * Cacodemon345, * - * Authors: Cacodemon345 - * - * Copyright 2023 Cacodemon345 + * Copyright 2019-2023 Sven Schnelle. + * Copyright 2023 Cacodemon345. */ - -/* Ported over from QEMU */ #include #include #include From 45a4a0a58b49b739f35e8764f0f4579ffdcb13b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Fri, 4 Aug 2023 21:58:36 +0200 Subject: [PATCH 036/133] Update net_tulip.c A copyright fix. --- src/network/net_tulip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 956f142e6..70655a1cd 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -8,7 +8,7 @@ * * Emulation of DECchip "Tulip" 21143 NIC. * - * Authors: Sven Schnelle, + * Authors: Sven Schnelle, * Cacodemon345, * * Copyright 2019-2023 Sven Schnelle. From 2f485f830bd632c66c05749eef137e18af67c2bf Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 7 Aug 2023 03:22:22 +0200 Subject: [PATCH 037/133] Updated Cacodemon's two new Network adapters to the new PCI API. --- src/network/net_rtl8139.c | 12 +++++++----- src/network/net_tulip.c | 9 +++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 39e29791f..c436615a3 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -409,8 +409,10 @@ static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters); struct RTL8139State { /*< private >*/ - uint8_t dev; + uint8_t pci_slot; uint8_t inst; + uint8_t irq_state; + uint8_t pad; /*< public >*/ uint8_t phys[8]; /* mac address */ @@ -683,7 +685,7 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) static void rtl8139_update_irq(RTL8139State *s) { - uint8_t d = s->dev; + uint8_t d = s->pci_slot; int isr; isr = (s->IntrStatus & s->IntrMask) & 0xffff; @@ -691,9 +693,9 @@ static void rtl8139_update_irq(RTL8139State *s) s->IntrMask); if (isr != 0) - pci_set_irq(d, PCI_INTA); + pci_set_irq(d, PCI_INTA, &s->irq_state); else - pci_clear_irq(d, PCI_INTA); + pci_clear_irq(d, PCI_INTA, &s->irq_state); } static int rtl8139_RxWrap(RTL8139State *s) @@ -3284,7 +3286,7 @@ nic_init(const device_t *info) FILE* f = NULL; char eeprom_filename[1024] = { 0 }; mem_mapping_add(&s->bar_mem, 0, 0, rtl8139_io_readb, rtl8139_io_readw, rtl8139_io_readl, rtl8139_io_writeb, rtl8139_io_writew, rtl8139_io_writel, NULL, MEM_MAPPING_EXTERNAL, s); - s->dev = pci_add_card(PCI_ADD_NETWORK, rtl8139_pci_read, rtl8139_pci_write, s); + pci_add_card(PCI_ADD_NETWORK, rtl8139_pci_read, rtl8139_pci_write, s, &s->pci_slot); s->inst = device_get_instance(); snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 9f243db7f..2437b2b1a 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -294,7 +294,8 @@ struct tulip_descriptor { }; struct TULIPState { - uint8_t dev; + uint8_t pci_slot; + uint8_t irq_state; const device_t* device_info; uint16_t subsys_id, subsys_ven_id; mem_mapping_t memory; @@ -376,9 +377,9 @@ tulip_update_int(TULIPState *s) assert = s->csr[5] & s->csr[7] & (CSR5_AIS | CSR5_NIS); if (!assert) - pci_clear_irq(s->dev, PCI_INTA); + pci_clear_irq(s->pci_slot, PCI_INTA, &s->irq_state); else - pci_set_irq(s->dev, PCI_INTA); + pci_set_irq(s->pci_slot, PCI_INTA, &s->irq_state); } static bool @@ -1582,7 +1583,7 @@ nic_init(const device_t *info) } memcpy(s->mii_regs, tulip_mdi_default, sizeof(tulip_mdi_default)); s->nic = network_attach(s, (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[10], tulip_receive, NULL); - s->dev = pci_add_card(PCI_ADD_NETWORK, tulip_pci_read, tulip_pci_write, s); + pci_add_card(PCI_ADD_NETWORK, tulip_pci_read, tulip_pci_write, s, &s->pci_slot); mem_mapping_add(&s->memory, 0, 0, NULL, NULL, tulip_read, NULL, NULL, tulip_write, NULL, MEM_MAPPING_EXTERNAL, s); tulip_reset(s); return s; From d79ad02e91b3ce7def8e1992339c1b9c3c34d24e Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 6 Aug 2023 17:26:41 -0400 Subject: [PATCH 038/133] Fix compilation error in net_rtl8139.c --- src/network/net_rtl8139.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index c436615a3..f34452c3e 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -40,7 +40,7 @@ #include <86box/network.h> #include <86box/bswap.h> #include <86box/nvr.h> -#include <86box/cpu.h> +#include "cpu.h" #include <86box/net_rtl8139.h> #define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ From 69bbee137fa069f3d124e7b8ccf6e4a0219553d1 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 6 Aug 2023 18:22:38 -0400 Subject: [PATCH 039/133] Sonarlint the new network cards --- src/include/86box/net_eeprom_nmc93cxx.h | 11 +- src/include/86box/net_rtl8139.h | 2 +- src/include/86box/net_tulip.h | 2 +- src/network/net_eeprom_nmc93cxx.c | 50 +- src/network/net_l80225.c | 5 +- src/network/net_rtl8139.c | 789 ++++++++++++------------ src/network/net_tulip.c | 93 +-- 7 files changed, 487 insertions(+), 465 deletions(-) diff --git a/src/include/86box/net_eeprom_nmc93cxx.h b/src/include/86box/net_eeprom_nmc93cxx.h index 7f503ed4f..f5260d1ed 100644 --- a/src/include/86box/net_eeprom_nmc93cxx.h +++ b/src/include/86box/net_eeprom_nmc93cxx.h @@ -1,11 +1,10 @@ struct nmc93cxx_eeprom_t; typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t; -typedef struct nmc93cxx_eeprom_params_t -{ - uint16_t nwords; - char* filename; - uint16_t* default_content; +typedef struct nmc93cxx_eeprom_params_t { + uint16_t nwords; + char *filename; + uint16_t *default_content; } nmc93cxx_eeprom_params_t; /* Read from the EEPROM. */ @@ -17,4 +16,4 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee /* Get EEPROM data array. */ uint16_t *nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom); -extern const device_t nmc93cxx_device; \ No newline at end of file +extern const device_t nmc93cxx_device; diff --git a/src/include/86box/net_rtl8139.h b/src/include/86box/net_rtl8139.h index fec851b06..f44d0facb 100644 --- a/src/include/86box/net_rtl8139.h +++ b/src/include/86box/net_rtl8139.h @@ -1 +1 @@ -extern const device_t rtl8139c_plus_device; \ No newline at end of file +extern const device_t rtl8139c_plus_device; diff --git a/src/include/86box/net_tulip.h b/src/include/86box/net_tulip.h index 681b89c97..3e02b66e4 100644 --- a/src/include/86box/net_tulip.h +++ b/src/include/86box/net_tulip.h @@ -1,2 +1,2 @@ extern const device_t dec_tulip_device; -extern const device_t dec_tulip_21140_device; \ No newline at end of file +extern const device_t dec_tulip_21140_device; diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index d31b7f8cd..22d2bdd08 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -16,7 +16,6 @@ /* Ported over from QEMU */ - #include #include #include @@ -28,6 +27,7 @@ #include <86box/timer.h> #include <86box/nvr.h> #include <86box/net_eeprom_nmc93cxx.h> +#include <86box/plat_unused.h> struct nmc93cxx_eeprom_t { uint8_t tick; @@ -71,12 +71,12 @@ static const char *opstring[] = { }; static void * -nmc93cxx_eeprom_init_params(const device_t *info, void* params) +nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void* params) { uint16_t nwords = 64; uint8_t addrbits = 6; uint8_t filldefault = 1; - nmc93cxx_eeprom_params_t* params_details = (nmc93cxx_eeprom_params_t*)params; + nmc93cxx_eeprom_params_t *params_details = (nmc93cxx_eeprom_params_t*) params; nmc93cxx_eeprom_t* eeprom = NULL; if (!params) return NULL; @@ -175,7 +175,9 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee } else { nmc93cxx_eeprom_log(1, "wrong 1st start bit (is 1, should be 0)\n"); tick = 2; - //~ assert(!"wrong start bit"); +#if 0 + ~ assert(!"wrong start bit"); +#endif } } else if (tick == 1) { /* Wait for 2nd start bit. */ @@ -206,20 +208,23 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee if (command == 0) { /* Command code in upper 2 bits of address. */ switch (address >> (eeprom->addrbits - 2)) { - case 0: - nmc93cxx_eeprom_log(1, "write disable command\n"); - eeprom->writable = 0; - break; - case 1: - nmc93cxx_eeprom_log(1, "write all command\n"); - break; - case 2: - nmc93cxx_eeprom_log(1, "erase all command\n"); - break; - case 3: - nmc93cxx_eeprom_log(1, "write enable command\n"); - eeprom->writable = 1; - break; + case 0: + nmc93cxx_eeprom_log(1, "write disable command\n"); + eeprom->writable = 0; + break; + case 1: + nmc93cxx_eeprom_log(1, "write all command\n"); + break; + case 2: + nmc93cxx_eeprom_log(1, "erase all command\n"); + break; + case 3: + nmc93cxx_eeprom_log(1, "write enable command\n"); + eeprom->writable = 1; + break; + + default: + break; } } else { /* Read, write or erase word. */ @@ -259,12 +264,11 @@ static void nmc93cxx_eeprom_close(void *priv) { nmc93cxx_eeprom_t* eeprom = (nmc93cxx_eeprom_t*)priv; - FILE* file = nvr_fopen(eeprom->filename, "wb"); - if (file) - { - fwrite(eeprom->contents, 2, eeprom->size, file); + FILE* fp = nvr_fopen(eeprom->filename, "wb"); + if (fp) { + fwrite(eeprom->contents, 2, eeprom->size, fp); + fclose(fp); } - fclose(file); free(priv); } diff --git a/src/network/net_l80225.c b/src/network/net_l80225.c index 40764aa67..801adaa8b 100644 --- a/src/network/net_l80225.c +++ b/src/network/net_l80225.c @@ -17,8 +17,7 @@ uint16_t l80225_mii_readw(uint16_t* regs, uint16_t addr) { - switch (addr) - { + switch (addr) { case 0x1: return 0x782D; case 0x2: @@ -39,4 +38,4 @@ void l80225_mii_writew(uint16_t* regs, uint16_t addr, uint16_t val) { regs[addr] = val; -} \ No newline at end of file +} diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index f34452c3e..9173e69a0 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -42,6 +42,7 @@ #include <86box/nvr.h> #include "cpu.h" #include <86box/net_rtl8139.h> +#include <86box/plat_unused.h> #define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ @@ -61,7 +62,7 @@ # define DPRINTF(fmt, ...) \ do { pclog("RTL8139: " fmt, ## __VA_ARGS__); } while (0) #else -static inline __attribute__ ((format (printf, 1, 2))) int DPRINTF(const char *fmt, ...) +static inline __attribute__ ((format (printf, 1, 2))) int DPRINTF(UNUSED(const char *fmt), ...) { return 0; } @@ -289,14 +290,14 @@ enum RxConfigBits { /* Twister tuning parameters from RealTek. Completely undocumented, but required to tune bad links on some boards. */ -/* +#if 0 enum CSCRBits { CSCR_LinkOKBit = 0x0400, CSCR_LinkChangeBit = 0x0800, CSCR_LinkStatusBits = 0x0f000, CSCR_LinkDownOffCmd = 0x003c0, CSCR_LinkDownCmd = 0x0f3c0, -*/ +#endif enum CSCRBits { CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ CSCR_LD = 1<<9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ @@ -348,8 +349,7 @@ enum chip_flags { #define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS) #define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1) -enum Chip9346Operation -{ +enum Chip9346Operation { Chip9346_op_mask = 0xc0, /* 10 zzzzzz */ Chip9346_op_read = 0x80, /* 10 AAAAAA */ Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */ @@ -359,8 +359,7 @@ enum Chip9346Operation Chip9346_op_write_disable = 0x00, /* 00 00zzzz */ }; -enum Chip9346Mode -{ +enum Chip9346Mode { Chip9346_none = 0, Chip9346_enter_command_mode, Chip9346_read_command, @@ -369,8 +368,7 @@ enum Chip9346Mode Chip9346_data_write_all, /* to input register, then filling contents */ }; -typedef struct EEprom9346 -{ +typedef struct EEprom9346 { uint16_t contents[EEPROM_9346_SIZE]; int mode; uint32_t tick; @@ -385,8 +383,7 @@ typedef struct EEprom9346 } EEprom9346; #pragma pack(push, 1) -typedef struct RTL8139TallyCounters -{ +typedef struct RTL8139TallyCounters { /* Tally counters */ uint64_t TxOk; uint64_t RxOk; @@ -420,9 +417,9 @@ struct RTL8139State { uint8_t pci_conf[256]; uint32_t TxStatus[4]; /* TxStatus0 in C mode*/ /* also DTCCR[0] and DTCCR[1] in C+ mode */ - uint32_t TxAddr[4]; /* TxAddr0 */ - uint32_t RxBuf; /* Receive buffer */ - uint32_t RxBufferSize;/* internal variable, receive ring buffer size in C mode */ + uint32_t TxAddr[4]; /* TxAddr0 */ + uint32_t RxBuf; /* Receive buffer */ + uint32_t RxBufferSize; /* internal variable, receive ring buffer size in C mode */ uint32_t RxBufPtr; uint32_t RxBufAddr; @@ -498,7 +495,8 @@ struct RTL8139State { /* Writes tally counters to memory via DMA */ static void RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr); -static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) +static void +prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) { DPRINTF("eeprom command 0x%02x\n", command); @@ -539,12 +537,16 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) case Chip9346_op_write_disable: DPRINTF("eeprom write disabled\n"); break; + + default: + break; } break; } } -static void prom9346_shift_clock(EEprom9346 *eeprom) +static void +prom9346_shift_clock(EEprom9346 *eeprom) { int bit = eeprom->eedi?1:0; @@ -556,8 +558,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) switch (eeprom->mode) { case Chip9346_enter_command_mode: - if (bit) - { + if (bit) { eeprom->mode = Chip9346_read_command; eeprom->tick = 0; eeprom->input = 0; @@ -567,8 +568,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) case Chip9346_read_command: eeprom->input = (eeprom->input << 1) | (bit & 1); - if (eeprom->tick == 8) - { + if (eeprom->tick == 8) { prom9346_decode_command(eeprom, eeprom->input & 0xff); } break; @@ -576,25 +576,24 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) case Chip9346_data_read: eeprom->eedo = (eeprom->output & 0x8000)?1:0; eeprom->output <<= 1; - if (eeprom->tick == 16) - { + if (eeprom->tick == 16) { #if 1 - // the FreeBSD drivers (rl and re) don't explicitly toggle - // CS between reads (or does setting Cfg9346 to 0 count too?), - // so we need to enter wait-for-command state here - eeprom->mode = Chip9346_enter_command_mode; - eeprom->input = 0; - eeprom->tick = 0; + // the FreeBSD drivers (rl and re) don't explicitly toggle + // CS between reads (or does setting Cfg9346 to 0 count too?), + // so we need to enter wait-for-command state here + eeprom->mode = Chip9346_enter_command_mode; + eeprom->input = 0; + eeprom->tick = 0; - DPRINTF("eeprom: +++ end of read, awaiting next command\n"); + DPRINTF("eeprom: +++ end of read, awaiting next command\n"); #else - // original behaviour - ++eeprom->address; - eeprom->address &= EEPROM_9346_ADDR_MASK; - eeprom->output = eeprom->contents[eeprom->address]; - eeprom->tick = 0; + // original behaviour + ++eeprom->address; + eeprom->address &= EEPROM_9346_ADDR_MASK; + eeprom->output = eeprom->contents[eeprom->address]; + eeprom->tick = 0; - DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n", + DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n", eeprom->address, eeprom->output); #endif } @@ -602,8 +601,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) case Chip9346_data_write: eeprom->input = (eeprom->input << 1) | (bit & 1); - if (eeprom->tick == 16) - { + if (eeprom->tick == 16) { DPRINTF("eeprom write to address 0x%02x data=0x%04x\n", eeprom->address, eeprom->input); @@ -616,11 +614,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) case Chip9346_data_write_all: eeprom->input = (eeprom->input << 1) | (bit & 1); - if (eeprom->tick == 16) - { - int i; - for (i = 0; i < EEPROM_9346_SIZE; i++) - { + if (eeprom->tick == 16) { + for (int i = 0; i < EEPROM_9346_SIZE; i++) { eeprom->contents[i] = eeprom->input; } DPRINTF("eeprom filled with data=0x%04x\n", eeprom->input); @@ -636,9 +631,10 @@ static void prom9346_shift_clock(EEprom9346 *eeprom) } } -static int prom9346_get_wire(RTL8139State *s) +static int +prom9346_get_wire(RTL8139State *s) { - EEprom9346 *eeprom = &s->eeprom; + const EEprom9346 *eeprom = &s->eeprom; if (!eeprom->eecs) return 0; @@ -646,7 +642,8 @@ static int prom9346_get_wire(RTL8139State *s) } /* FIXME: This should be merged into/replaced by eeprom93xx.c. */ -static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) +static void +prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) { EEprom9346 *eeprom = &s->eeprom; uint8_t old_eecs = eeprom->eecs; @@ -659,8 +656,7 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) DPRINTF("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo); - if (!old_eecs && eecs) - { + if (!old_eecs && eecs) { /* Synchronize start */ eeprom->tick = 0; eeprom->input = 0; @@ -670,20 +666,19 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) DPRINTF("=== eeprom: begin access, enter command mode\n"); } - if (!eecs) - { + if (!eecs) { DPRINTF("=== eeprom: end access\n"); return; } - if (!old_eesk && eesk) - { + if (!old_eesk && eesk) { /* SK front rules */ prom9346_shift_clock(eeprom); } } -static void rtl8139_update_irq(RTL8139State *s) +static void +rtl8139_update_irq(RTL8139State *s) { uint8_t d = s->pci_slot; int isr; @@ -698,45 +693,48 @@ static void rtl8139_update_irq(RTL8139State *s) pci_clear_irq(d, PCI_INTA, &s->irq_state); } -static int rtl8139_RxWrap(RTL8139State *s) +static int +rtl8139_RxWrap(RTL8139State *s) { /* wrapping enabled; assume 1.5k more buffer space if size < 65536 */ return (s->RxConfig & (1 << 7)); } -static int rtl8139_receiver_enabled(RTL8139State *s) +static int +rtl8139_receiver_enabled(RTL8139State *s) { return s->bChipCmdState & CmdRxEnb; } -static int rtl8139_transmitter_enabled(RTL8139State *s) +static int +rtl8139_transmitter_enabled(RTL8139State *s) { return s->bChipCmdState & CmdTxEnb; } -static int rtl8139_cp_receiver_enabled(RTL8139State *s) +static int +rtl8139_cp_receiver_enabled(RTL8139State *s) { return s->CpCmd & CPlusRxEnb; } -static int rtl8139_cp_transmitter_enabled(RTL8139State *s) +static int +rtl8139_cp_transmitter_enabled(RTL8139State *s) { return s->CpCmd & CPlusTxEnb; } -static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) +static void +rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) { - if (s->RxBufAddr + size > s->RxBufferSize) - { + if (s->RxBufAddr + size > s->RxBufferSize) { int wrapped = MOD2(s->RxBufAddr + size, s->RxBufferSize); /* write packet data */ - if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s))) - { + if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s))) { DPRINTF(">>> rx packet wrapped in buffer at %d\n", size - wrapped); - if (size > wrapped) - { + if (size > wrapped) { dma_bm_write(s->RxBuf + s->RxBufAddr, buf, size-wrapped, 1); } @@ -759,20 +757,22 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) s->RxBufAddr += size; } -static __inline uint32_t rtl8139_addr64(uint32_t low, uint32_t high) +static __inline uint32_t +rtl8139_addr64(uint32_t low, UNUSED(uint32_t high)) { - (void)high; return low; } /* Workaround for buggy guest driver such as linux who allocates rx * rings after the receiver were enabled. */ -static bool rtl8139_cp_rx_valid(RTL8139State *s) +static bool +rtl8139_cp_rx_valid(RTL8139State *s) { return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0); } -static bool rtl8139_can_receive(RTL8139State *s) +static bool +rtl8139_can_receive(RTL8139State *s) { int avail; @@ -797,16 +797,17 @@ static bool rtl8139_can_receive(RTL8139State *s) /* From FreeBSD */ /* XXX: optimize */ -static uint32_t net_crc32(const uint8_t *p, int len) +static uint32_t +net_crc32(const uint8_t *p, int len) { uint32_t crc; - int carry, i, j; - uint8_t b; + int carry; + uint8_t b; crc = 0xffffffff; - for (i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { b = *p++; - for (j = 0; j < 8; j++) { + for (uint8_t j = 0; j < 8; j++) { carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); crc <<= 1; b >>= 1; @@ -819,16 +820,17 @@ static uint32_t net_crc32(const uint8_t *p, int len) return crc; } -uint32_t net_crc32_le(const uint8_t *p, int len) +uint32_t +net_crc32_le(const uint8_t *p, int len) { uint32_t crc; - int carry, i, j; - uint8_t b; + int carry; + uint8_t b; crc = 0xffffffff; - for (i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { b = *p++; - for (j = 0; j < 8; j++) { + for (uint8_t j = 0; j < 8; j++) { carry = (crc & 0x1) ^ (b & 0x01); crc >>= 1; b >>= 1; @@ -843,9 +845,10 @@ uint32_t net_crc32_le(const uint8_t *p, int len) #define ETH_ALEN 6 -static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) +static int +rtl8139_do_receive(void *priv, uint8_t *buf, int size_) { - RTL8139State *s = (RTL8139State*)p; + RTL8139State *s = (RTL8139State*) priv; /* size is the length of the buffer passed to the driver */ size_t size = size_; const uint8_t *dot1q_buf = NULL; @@ -862,16 +865,14 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) return 0; /* test if board clock is stopped */ - if (!s->clock_enabled) - { + if (!s->clock_enabled) { DPRINTF("stopped ==========================\n"); return -1; } /* first check if receiver is enabled */ - if (!rtl8139_receiver_enabled(s)) - { + if (!rtl8139_receiver_enabled(s)) { DPRINTF("receiver disabled ================\n"); return -1; } @@ -903,8 +904,7 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) } else if (buf[0] & 0x01) { /* multicast */ - if (!(s->RxConfig & AcceptMulticast)) - { + if (!(s->RxConfig & AcceptMulticast)) { DPRINTF(">>> multicast packet rejected\n"); /* update tally counter */ @@ -915,8 +915,7 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) int mcast_idx = net_crc32(buf, ETH_ALEN) >> 26; - if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) - { + if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) { DPRINTF(">>> multicast address mismatch\n"); /* update tally counter */ @@ -932,15 +931,9 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) /* update tally counter */ ++s->tally_counters.RxOkMul; - } else if (s->phys[0] == buf[0] && - s->phys[1] == buf[1] && - s->phys[2] == buf[2] && - s->phys[3] == buf[3] && - s->phys[4] == buf[4] && - s->phys[5] == buf[5]) { + } else if (s->phys[0] == buf[0] && s->phys[1] == buf[1] && s->phys[2] == buf[2] && s->phys[3] == buf[3] && s->phys[4] == buf[4] && s->phys[5] == buf[5]) { /* match */ - if (!(s->RxConfig & AcceptMyPhys)) - { + if (!(s->RxConfig & AcceptMyPhys)) { DPRINTF(">>> rejecting physical address matching packet\n"); /* update tally counter */ @@ -1009,22 +1002,25 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) "%08x %08x = ""0x%8X""\n", descriptor, s->RxRingAddrHI, s->RxRingAddrLO, cplus_rx_ring_desc); - uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; + uint32_t val; + uint32_t rxdw0; + uint32_t rxdw1; + uint32_t rxbufLO; + uint32_t rxbufHI; dma_bm_read(cplus_rx_ring_desc, (uint8_t*)&val, 4, 4); - rxdw0 = (val); + rxdw0 = val; dma_bm_read(cplus_rx_ring_desc+4, (uint8_t*)&val, 4, 4); - rxdw1 = (val); + rxdw1 = val; dma_bm_read(cplus_rx_ring_desc+8, (uint8_t*)&val, 4, 4); - rxbufLO = (val); + rxbufLO = val; dma_bm_read(cplus_rx_ring_desc+12, (uint8_t*)&val, 4, 4); - rxbufHI = (val); + rxbufHI = val; DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI); - if (!(rxdw0 & CP_RX_OWN)) - { + if (!(rxdw0 & CP_RX_OWN)) { DPRINTF("C+ Rx mode : descriptor %d is owned by host\n", descriptor); @@ -1064,8 +1060,7 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) /* TODO: scatter the packet over available receive ring descriptors space */ - if (size+4 > rx_space) - { + if (size+4 > rx_space) { DPRINTF("C+ Rx mode : descriptor %d size %d received %zu + 4\n", descriptor, rx_space, size); @@ -1092,8 +1087,7 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) dma_bm_write(rx_addr, buf, size, 1); } - if (s->CpCmd & CPlusRxChkSum) - { + if (s->CpCmd & CPlusRxChkSum) { /* do some packet checksumming */ } @@ -1144,29 +1138,24 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) rxdw0 |= (size+4); /* update ring data */ - val = (rxdw0); + val = rxdw0; dma_bm_write(cplus_rx_ring_desc, (uint8_t *)&val, 4, 4); - val = (rxdw1); + val = rxdw1; dma_bm_write(cplus_rx_ring_desc+4, (uint8_t *)&val, 4, 4); /* update tally counter */ ++s->tally_counters.RxOk; /* seek to next Rx descriptor */ - if (rxdw0 & CP_RX_EOR) - { + if (rxdw0 & CP_RX_EOR) { s->currCPlusRxDesc = 0; - } - else - { + } else { ++s->currCPlusRxDesc; } DPRINTF("done C+ Rx mode ----------------\n"); - } - else - { + } else { DPRINTF("in ring Rx mode ================\n"); /* begin ring receiver mode */ @@ -1176,8 +1165,7 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) #define RX_ALIGN(x) (((x) + 3) & ~0x3) - if (avail != 0 && RX_ALIGN(size + 8) >= avail) - { + if (avail != 0 && RX_ALIGN(size + 8) >= avail) { DPRINTF("rx overflow: rx buffer length %d head 0x%04x " "read 0x%04x === available 0x%04x need 0x%04zx\n", s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); @@ -1193,7 +1181,7 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) packet_header |= (((size+4) << 16) & 0xffff0000); /* write header */ - uint32_t val = (packet_header); + uint32_t val = packet_header; rtl8139_write_buffer(s, (uint8_t *)&val, 4); @@ -1221,14 +1209,16 @@ static int rtl8139_do_receive(void* p, uint8_t *buf, int size_) return size_; } -static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize) +static void +rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize) { s->RxBufferSize = bufferSize; s->RxBufPtr = 0; s->RxBufAddr = 0; } -static void rtl8139_reset_phy(RTL8139State *s) +static void +rtl8139_reset_phy(RTL8139State *s) { s->BasicModeStatus = 0x7809; s->BasicModeStatus |= 0x0020; /* autonegotiation completed */ @@ -1243,10 +1233,10 @@ static void rtl8139_reset_phy(RTL8139State *s) } -static void rtl8139_reset(void* p) +static void +rtl8139_reset(void* priv) { - int i; - RTL8139State *s = (RTL8139State*)p; + RTL8139State *s = (RTL8139State*) priv; /* reset interrupt mask */ s->IntrStatus = 0; @@ -1255,8 +1245,7 @@ static void rtl8139_reset(void* p) rtl8139_update_irq(s); /* mark all status registers as owned by host */ - for (i = 0; i < 4; ++i) - { + for (uint8_t i = 0; i < 4; ++i) { s->TxStatus[i] = TxHostOwns; } @@ -1282,7 +1271,7 @@ static void rtl8139_reset(void* p) s->clock_enabled = 1; #endif - s->bChipCmdState = CmdReset; /* RxBufEmpty bit is calculated on read from ChipCmd */; + s->bChipCmdState = CmdReset; /* RxBufEmpty bit is calculated on read from ChipCmd */ /* set initial state data */ s->Config0 = 0x0; /* No boot ROM */ @@ -1293,8 +1282,10 @@ static void rtl8139_reset(void* p) s->CpCmd = 0x0; /* reset C+ mode */ s->cplus_enabled = 0; -// s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation -// s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex +#if 0 + s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation + s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex +#endif s->BasicModeCtrl = 0x1000; // autonegotiation rtl8139_reset_phy(s); @@ -1303,13 +1294,16 @@ static void rtl8139_reset(void* p) s->TCTR = 0; s->TimerInt = 0; s->TCTR_base = 0; - //rtl8139_set_next_tctr_time(s); +#if 0 + rtl8139_set_next_tctr_time(s); +#endif /* reset tally counters */ RTL8139TallyCounters_clear(&s->tally_counters); } -static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters) +static void +RTL8139TallyCounters_clear(RTL8139TallyCounters* counters) { counters->TxOk = 0; counters->RxOk = 0; @@ -1326,32 +1320,31 @@ static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters) counters->TxUndrn = 0; } -static void RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr) +static void +RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr) { RTL8139TallyCounters *tally_counters = &s->tally_counters; dma_bm_write(tc_addr, (uint8_t*)tally_counters, sizeof(RTL8139TallyCounters), 1); } -static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val) +static void +rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val) { val &= 0xff; DPRINTF("ChipCmd write val=0x%08x\n", val); - if (val & CmdReset) - { + if (val & CmdReset) { DPRINTF("ChipCmd reset\n"); rtl8139_reset(s); } - if (val & CmdRxEnb) - { + if (val & CmdRxEnb) { DPRINTF("ChipCmd enable receiver\n"); s->currCPlusRxDesc = 0; } - if (val & CmdTxEnb) - { + if (val & CmdTxEnb) { DPRINTF("ChipCmd enable transmitter\n"); s->currCPlusTxDesc = 0; @@ -1366,12 +1359,12 @@ static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val) s->bChipCmdState = val; } -static int rtl8139_RxBufferEmpty(RTL8139State *s) +static int +rtl8139_RxBufferEmpty(RTL8139State *s) { int unread = MOD2(s->RxBufferSize + s->RxBufAddr - s->RxBufPtr, s->RxBufferSize); - if (unread != 0) - { + if (unread != 0) { DPRINTF("receiver buffer data available 0x%04x\n", unread); return 0; } @@ -1381,7 +1374,8 @@ static int rtl8139_RxBufferEmpty(RTL8139State *s) return 1; } -static uint32_t rtl8139_ChipCmd_read(RTL8139State *s) +static uint32_t +rtl8139_ChipCmd_read(RTL8139State *s) { uint32_t ret = s->bChipCmdState; @@ -1393,7 +1387,8 @@ static uint32_t rtl8139_ChipCmd_read(RTL8139State *s) return ret; } -static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val) +static void +rtl8139_CpCmd_write(RTL8139State *s, uint32_t val) { val &= 0xffff; @@ -1407,7 +1402,8 @@ static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val) s->CpCmd = val; } -static uint32_t rtl8139_CpCmd_read(RTL8139State *s) +static uint32_t +rtl8139_CpCmd_read(RTL8139State *s) { uint32_t ret = s->CpCmd; @@ -1416,12 +1412,14 @@ static uint32_t rtl8139_CpCmd_read(RTL8139State *s) return ret; } -static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val) +static void +rtl8139_IntrMitigate_write(UNUSED(RTL8139State *s), uint32_t val) { DPRINTF("C+ IntrMitigate register write(w) val=0x%04x\n", val); } -static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s) +static uint32_t +rtl8139_IntrMitigate_read(UNUSED(RTL8139State *s)) { uint32_t ret = 0; @@ -1430,10 +1428,10 @@ static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s) return ret; } -static int rtl8139_config_writable(RTL8139State *s) +static int +rtl8139_config_writable(RTL8139State *s) { - if ((s->Cfg9346 & Chip9346_op_mask) == Cfg9346_ConfigWrite) - { + if ((s->Cfg9346 & Chip9346_op_mask) == Cfg9346_ConfigWrite) { return 1; } @@ -1442,7 +1440,8 @@ static int rtl8139_config_writable(RTL8139State *s) return 0; } -static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) +static void +rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) { val &= 0xffff; @@ -1451,8 +1450,7 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) /* mask unwritable bits */ uint32_t mask = 0xccff; - if (1 || !rtl8139_config_writable(s)) - { + if (1 || !rtl8139_config_writable(s)) { /* Speed setting and autonegotiation enable bits are read-only */ mask |= 0x3000; /* Duplex mode setting is read-only */ @@ -1469,7 +1467,8 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) s->BasicModeCtrl = val; } -static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s) +static uint32_t +rtl8139_BasicModeCtrl_read(RTL8139State *s) { uint32_t ret = s->BasicModeCtrl; @@ -1478,7 +1477,8 @@ static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s) return ret; } -static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val) +static void +rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val) { val &= 0xffff; @@ -1490,7 +1490,8 @@ static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val) s->BasicModeStatus = val; } -static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s) +static uint32_t +rtl8139_BasicModeStatus_read(RTL8139State *s) { uint32_t ret = s->BasicModeStatus; @@ -1499,7 +1500,8 @@ static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s) return ret; } -static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) +static void +rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) { val &= 0xff; @@ -1526,22 +1528,19 @@ static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) s->Cfg9346 = val; } -static uint32_t rtl8139_Cfg9346_read(RTL8139State *s) +static uint32_t +rtl8139_Cfg9346_read(RTL8139State *s) { uint32_t ret = s->Cfg9346; uint32_t opmode = ret & 0xc0; - if (opmode == 0x80) - { + if (opmode == 0x80) { /* eeprom access */ int eedo = prom9346_get_wire(s); - if (eedo) - { + if (eedo) { ret |= 0x01; - } - else - { + } else { ret &= ~0x01; } } @@ -1551,7 +1550,8 @@ static uint32_t rtl8139_Cfg9346_read(RTL8139State *s) return ret; } -static void rtl8139_Config0_write(RTL8139State *s, uint32_t val) +static void +rtl8139_Config0_write(RTL8139State *s, uint32_t val) { val &= 0xff; @@ -1567,7 +1567,8 @@ static void rtl8139_Config0_write(RTL8139State *s, uint32_t val) s->Config0 = val; } -static uint32_t rtl8139_Config0_read(RTL8139State *s) +static uint32_t +rtl8139_Config0_read(RTL8139State *s) { uint32_t ret = s->Config0; @@ -1576,7 +1577,8 @@ static uint32_t rtl8139_Config0_read(RTL8139State *s) return ret; } -static void rtl8139_Config1_write(RTL8139State *s, uint32_t val) +static void +rtl8139_Config1_write(RTL8139State *s, uint32_t val) { val &= 0xff; @@ -1592,7 +1594,8 @@ static void rtl8139_Config1_write(RTL8139State *s, uint32_t val) s->Config1 = val; } -static uint32_t rtl8139_Config1_read(RTL8139State *s) +static uint32_t +rtl8139_Config1_read(RTL8139State *s) { uint32_t ret = s->Config1; @@ -1601,7 +1604,8 @@ static uint32_t rtl8139_Config1_read(RTL8139State *s) return ret; } -static void rtl8139_Config3_write(RTL8139State *s, uint32_t val) +static void +rtl8139_Config3_write(RTL8139State *s, uint32_t val) { val &= 0xff; @@ -1617,7 +1621,8 @@ static void rtl8139_Config3_write(RTL8139State *s, uint32_t val) s->Config3 = val; } -static uint32_t rtl8139_Config3_read(RTL8139State *s) +static uint32_t +rtl8139_Config3_read(RTL8139State *s) { uint32_t ret = s->Config3; @@ -1626,7 +1631,8 @@ static uint32_t rtl8139_Config3_read(RTL8139State *s) return ret; } -static void rtl8139_Config4_write(RTL8139State *s, uint32_t val) +static void +rtl8139_Config4_write(RTL8139State *s, uint32_t val) { val &= 0xff; @@ -1642,7 +1648,8 @@ static void rtl8139_Config4_write(RTL8139State *s, uint32_t val) s->Config4 = val; } -static uint32_t rtl8139_Config4_read(RTL8139State *s) +static uint32_t +rtl8139_Config4_read(RTL8139State *s) { uint32_t ret = s->Config4; @@ -1651,7 +1658,8 @@ static uint32_t rtl8139_Config4_read(RTL8139State *s) return ret; } -static void rtl8139_Config5_write(RTL8139State *s, uint32_t val) +static void +rtl8139_Config5_write(RTL8139State *s, uint32_t val) { val &= 0xff; @@ -1663,7 +1671,8 @@ static void rtl8139_Config5_write(RTL8139State *s, uint32_t val) s->Config5 = val; } -static uint32_t rtl8139_Config5_read(RTL8139State *s) +static uint32_t +rtl8139_Config5_read(RTL8139State *s) { uint32_t ret = s->Config5; @@ -1672,10 +1681,10 @@ static uint32_t rtl8139_Config5_read(RTL8139State *s) return ret; } -static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) +static void +rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) { - if (!rtl8139_transmitter_enabled(s)) - { + if (!rtl8139_transmitter_enabled(s)) { DPRINTF("transmitter disabled; no TxConfig write val=0x%08x\n", val); return; } @@ -1687,17 +1696,20 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) s->TxConfig = val; } -static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val) +static void +rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val) { DPRINTF("RTL8139C TxConfig via write(b) val=0x%02x\n", val); uint32_t tc = s->TxConfig; + tc &= 0xFFFFFF00; tc |= (val & 0x000000FF); rtl8139_TxConfig_write(s, tc); } -static uint32_t rtl8139_TxConfig_read(RTL8139State *s) +static uint32_t +rtl8139_TxConfig_read(RTL8139State *s) { uint32_t ret = s->TxConfig; @@ -1706,7 +1718,8 @@ static uint32_t rtl8139_TxConfig_read(RTL8139State *s) return ret; } -static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) +static void +rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) { DPRINTF("RxConfig write val=0x%08x\n", val); @@ -1721,7 +1734,8 @@ static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) DPRINTF("RxConfig write reset buffer size to %d\n", s->RxBufferSize); } -static uint32_t rtl8139_RxConfig_read(RTL8139State *s) +static uint32_t +rtl8139_RxConfig_read(RTL8139State *s) { uint32_t ret = s->RxConfig; @@ -1736,8 +1750,9 @@ rtl8139_network_rx_put(netcard_t *card, uint8_t *bufp, int len) (void)network_rx_put(card, bufp, len); } -static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, - int do_interrupt, const uint8_t *dot1q_buf) +static void +rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, + UNUSED(int do_interrupt), const uint8_t *dot1q_buf) { void (*network_func)(netcard_t *, uint8_t *, int) = (TxLoopBack == (s->TxConfig & TxLoopBack)) ? rtl8139_network_rx_put : network_tx; if (!size) @@ -1757,20 +1772,19 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, return; } -static int rtl8139_transmit_one(RTL8139State *s, int descriptor) +static int +rtl8139_transmit_one(RTL8139State *s, int descriptor) { int txsize = s->TxStatus[descriptor] & 0x1fff; uint8_t txbuffer[0x2000]; - if (!rtl8139_transmitter_enabled(s)) - { + if (!rtl8139_transmitter_enabled(s)) { DPRINTF("+++ cannot transmit from descriptor %d: transmitter " "disabled\n", descriptor); return 0; } - if (s->TxStatus[descriptor] & TxHostOwns) - { + if (s->TxStatus[descriptor] & TxHostOwns) { DPRINTF("+++ cannot transmit from descriptor %d: owned by host " "(%08x)\n", descriptor, s->TxStatus[descriptor]); return 0; @@ -1802,18 +1816,17 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor) #define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off))) /* produces ones' complement sum of data */ -static uint16_t ones_complement_sum(uint8_t *data, size_t len) +static uint16_t +ones_complement_sum(uint8_t *data, size_t len) { uint32_t result = 0; - for (; len > 1; data+=2, len-=2) - { + for (; len > 1; data+=2, len-=2) { result += *(uint16_t*)data; } /* add the remainder byte */ - if (len) - { + if (len) { uint8_t odd[2] = {*data, 0}; result += *(uint16_t*)odd; } @@ -1824,7 +1837,8 @@ static uint16_t ones_complement_sum(uint8_t *data, size_t len) return result; } -static uint16_t ip_checksum(void *data, size_t len) +static uint16_t +ip_checksum(void *data, size_t len) { return ~ones_complement_sum((uint8_t*)data, len); } @@ -1887,16 +1901,15 @@ typedef struct udp_header { (((be16_to_cpu((tcp)->th_offset_flags) >> 12) & 0xf) << 2) -static int rtl8139_cplus_transmit_one(RTL8139State *s) +static int +rtl8139_cplus_transmit_one(RTL8139State *s) { - if (!rtl8139_transmitter_enabled(s)) - { + if (!rtl8139_transmitter_enabled(s)) { DPRINTF("+++ C+ mode: transmitter disabled\n"); return 0; } - if (!rtl8139_cp_transmitter_enabled(s)) - { + if (!rtl8139_cp_transmitter_enabled(s)) { DPRINTF("+++ C+ mode: C+ transmitter disabled\n"); return 0 ; } @@ -1911,7 +1924,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) "%08x %08x = 0x%08X\n", descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc); - uint32_t val, txdw0,txdw1,txbufLO,txbufHI; + uint32_t val; + uint32_t txdw0; + uint32_t txdw1; + uint32_t txbufLO; + uint32_t txbufHI; dma_bm_read(cplus_tx_ring_desc, (uint8_t *)&val, 4, 4); txdw0 = le32_to_cpu(val); @@ -1968,16 +1985,14 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* excessive collisions flag */ #define CP_TX_STATUS_EXC (1<<20) - if (!(txdw0 & CP_TX_OWN)) - { + if (!(txdw0 & CP_TX_OWN)) { DPRINTF("C+ Tx mode : descriptor %d is owned by host\n", descriptor); return 0 ; } DPRINTF("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor); - if (txdw0 & CP_TX_FS) - { + if (txdw0 & CP_TX_FS) { DPRINTF("+++ C+ Tx mode : descriptor %d is first segment " "descriptor\n", descriptor); @@ -1989,8 +2004,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) uint32_t tx_addr = rtl8139_addr64(txbufLO, txbufHI); /* make sure we have enough space to assemble the packet */ - if (!s->cplus_txbuffer) - { + if (!s->cplus_txbuffer) { s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE; s->cplus_txbuffer = calloc(s->cplus_txbuffer_len, 1); s->cplus_txbuffer_offset = 0; @@ -1999,8 +2013,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) s->cplus_txbuffer_len); } - if (s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) - { + if (s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) { /* The spec didn't tell the maximum size, stick to CP_TX_BUFFER_SIZE */ txsize = s->cplus_txbuffer_len - s->cplus_txbuffer_offset; DPRINTF("+++ C+ mode transmission buffer overrun, truncated descriptor" @@ -2018,12 +2031,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) s->cplus_txbuffer_offset += txsize; /* seek to next Rx descriptor */ - if (txdw0 & CP_TX_EOR) - { + if (txdw0 & CP_TX_EOR) { s->currCPlusTxDesc = 0; - } - else - { + } else { ++s->currCPlusTxDesc; if (s->currCPlusTxDesc >= 64) s->currCPlusTxDesc = 0; @@ -2047,8 +2057,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) dma_bm_write(cplus_tx_ring_desc, (uint8_t *)&val, 4, 4); /* Now decide if descriptor being processed is holding the last segment of packet */ - if (txdw0 & CP_TX_LS) - { + if (txdw0 & CP_TX_LS) { uint8_t dot1q_buffer_space[VLAN_HLEN]; uint16_t *dot1q_buffer; @@ -2081,8 +2090,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) s->cplus_txbuffer_offset = 0; s->cplus_txbuffer_len = 0; - if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN)) - { + if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN)) { DPRINTF("+++ C+ mode offloaded task checksum\n"); /* Large enough for Ethernet and IP headers? */ @@ -2100,8 +2108,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) size_t eth_payload_len = 0; int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); - if (proto != ETH_P_IP) - { + if (proto != ETH_P_IP) { goto skip_offload; } @@ -2137,8 +2144,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) } ip_data_len -= hlen; - if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & CP_TX_IPCS)) - { + if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & CP_TX_IPCS)) { DPRINTF("+++ C+ mode need IP checksum\n"); ip->ip_sum = 0; @@ -2147,8 +2153,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) hlen, ip->ip_sum); } - if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) - { + if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) { /* Large enough for the TCP header? */ if (ip_data_len < sizeof(tcp_header)) { goto skip_offload; @@ -2164,8 +2169,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) "frame data %d specified MSS=%d\n", ip_data_len, saved_size - ETH_HLEN, large_send_mss); - int tcp_send_offset = 0; - /* maximum IP header length is 60 bytes */ uint8_t saved_ip_header[60]; @@ -2174,7 +2177,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* a placeholder for checksum calculation routine in tcp case */ uint8_t *data_to_checksum = eth_payload_data + hlen - 12; - // size_t data_to_checksum_len = eth_payload_len - hlen + 12; +#if 0 + size_t data_to_checksum_len = eth_payload_len - hlen + 12; +#endif /* pointer to TCP header */ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); @@ -2196,13 +2201,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) int is_last_frame = 0; - for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += large_send_mss) - { + for (int tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += large_send_mss) { uint16_t chunk_size = large_send_mss; /* check if this is the last frame */ - if (tcp_send_offset + large_send_mss >= tcp_data_len) - { + if (tcp_send_offset + large_send_mss >= tcp_data_len) { is_last_frame = 1; chunk_size = tcp_data_len - tcp_send_offset; } @@ -2218,16 +2221,14 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) "packet with %d bytes data\n", tcp_hlen + chunk_size); - if (tcp_send_offset) - { + if (tcp_send_offset) { memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); } #define TCP_FLAGS_ONLY(flags) ((flags) & 0x3f) #define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off))) /* keep PUSH and FIN flags only for the last frame */ - if (!is_last_frame) - { + if (!is_last_frame) { TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TH_PUSH | TH_FIN); } @@ -2266,16 +2267,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) 0, (uint8_t *) dot1q_buffer); /* add transferred count to TCP sequence number */ - //stl_be_p(&p_tcp_hdr->th_seq, - // chunk_size + ldl_be_p(&p_tcp_hdr->th_seq)); +#if 0 + stl_be_p(&p_tcp_hdr->th_seq, + chunk_size + ldl_be_p(&p_tcp_hdr->th_seq)); +#endif p_tcp_hdr->th_seq = bswap32(chunk_size + bswap32(p_tcp_hdr->th_seq)); } /* Stop sending this frame */ saved_size = 0; - } - else if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))) - { + } else if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))) { DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); /* maximum IP header length is 60 bytes */ @@ -2283,14 +2284,15 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) memcpy(saved_ip_header, eth_payload_data, hlen); uint8_t *data_to_checksum = eth_payload_data + hlen - 12; - // size_t data_to_checksum_len = eth_payload_len - hlen + 12; +#if 0 + size_t data_to_checksum_len = eth_payload_len - hlen + 12; +#endif /* add 4 TCP pseudoheader fields */ /* copy IP source and destination fields */ memcpy(data_to_checksum, saved_ip_header + 12, 8); - if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) - { + if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) { DPRINTF("+++ C+ mode calculating TCP checksum for " "packet with %d bytes data\n", ip_data_len); @@ -2308,9 +2310,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) tcp_checksum); p_tcp_hdr->th_sum = tcp_checksum; - } - else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) - { + } else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) { DPRINTF("+++ C+ mode calculating UDP checksum for " "packet with %d bytes data\n", ip_data_len); @@ -2345,86 +2345,76 @@ skip_offload: (uint8_t *) dot1q_buffer); /* restore card space if there was no recursion and reset offset */ - if (!s->cplus_txbuffer) - { + if (!s->cplus_txbuffer) { s->cplus_txbuffer = saved_buffer; s->cplus_txbuffer_len = saved_buffer_len; s->cplus_txbuffer_offset = 0; - } - else - { + } else { free(saved_buffer); } - } - else - { + } else { DPRINTF("+++ C+ mode transmission continue to next descriptor\n"); } return 1; } -static void rtl8139_cplus_transmit(RTL8139State *s) +static void +rtl8139_cplus_transmit(RTL8139State *s) { int txcount = 0; - while (txcount < 64 && rtl8139_cplus_transmit_one(s)) - { + while (txcount < 64 && rtl8139_cplus_transmit_one(s)) { ++txcount; } /* Mark transfer completed */ - if (!txcount) - { + if (!txcount) { DPRINTF("C+ mode : transmitter queue stalled, current TxDesc = %d\n", s->currCPlusTxDesc); - } - else - { + } else { /* update interrupt status */ s->IntrStatus |= TxOK; rtl8139_update_irq(s); } } -static void rtl8139_transmit(RTL8139State *s) +static void +rtl8139_transmit(RTL8139State *s) { - int descriptor = s->currTxDesc, txcount = 0; + int descriptor = s->currTxDesc; + int txcount = 0; /*while*/ - if (rtl8139_transmit_one(s, descriptor)) - { + if (rtl8139_transmit_one(s, descriptor)) { ++s->currTxDesc; s->currTxDesc %= 4; ++txcount; } /* Mark transfer completed */ - if (!txcount) - { + if (!txcount) { DPRINTF("transmitter queue stalled, current TxDesc = %d\n", s->currTxDesc); } } -static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) +static void +rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) { - int descriptor = txRegOffset/4; /* handle C+ transmit mode register configuration */ - if (s->cplus_enabled) - { + if (s->cplus_enabled) { DPRINTF("RTL8139C+ DTCCR write offset=0x%x val=0x%08x " "descriptor=%d\n", txRegOffset, val, descriptor); /* handle Dump Tally Counters command */ s->TxStatus[descriptor] = val; - if (descriptor == 0 && (val & 0x8)) - { + if (descriptor == 0 && (val & 0x8)) { uint32_t tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]); /* dump tally counters to specified memory location */ @@ -2450,9 +2440,10 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32 rtl8139_transmit(s); } -static uint32_t rtl8139_TxStatus_TxAddr_read(RTL8139State *s, uint32_t regs[], - uint32_t base, uint8_t addr, - int size) +static uint32_t +rtl8139_TxStatus_TxAddr_read(UNUSED(RTL8139State *s), uint32_t regs[], + uint32_t base, uint8_t addr, + int size) { uint32_t reg = (addr - base) / 4; uint32_t offset = addr & 0x3; @@ -2465,22 +2456,24 @@ static uint32_t rtl8139_TxStatus_TxAddr_read(RTL8139State *s, uint32_t regs[], } switch (size) { - case 1: /* fall through */ - case 2: /* fall through */ - case 4: - ret = (regs[reg] >> offset * 8) & (((uint64_t)1 << (size * 8)) - 1); - DPRINTF("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n", - reg, addr, size, ret); - break; - default: - DPRINTF("unsupported size 0x%x of TxStatus/TxAddr reading\n", size); - break; + case 1: /* fall through */ + case 2: /* fall through */ + case 4: + ret = (regs[reg] >> offset * 8) & (((uint64_t)1 << (size * 8)) - 1); + DPRINTF("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n", + reg, addr, size, ret); + break; + + default: + DPRINTF("unsupported size 0x%x of TxStatus/TxAddr reading\n", size); + break; } return ret; } -static uint16_t rtl8139_TSAD_read(RTL8139State *s) +static uint16_t +rtl8139_TSAD_read(RTL8139State *s) { uint16_t ret = 0; @@ -2512,7 +2505,8 @@ static uint16_t rtl8139_TSAD_read(RTL8139State *s) return ret; } -static uint16_t rtl8139_CSCR_read(RTL8139State *s) +static uint16_t +rtl8139_CSCR_read(RTL8139State *s) { uint16_t ret = s->CSCR; @@ -2521,14 +2515,16 @@ static uint16_t rtl8139_CSCR_read(RTL8139State *s) return ret; } -static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val) +static void +rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val) { DPRINTF("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val); s->TxAddr[txAddrOffset/4] = val; } -static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) +static uint32_t +rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) { uint32_t ret = s->TxAddr[txAddrOffset/4]; @@ -2537,7 +2533,8 @@ static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) return ret; } -static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) +static void +rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) { DPRINTF("RxBufPtr write val=0x%04x\n", val); @@ -2548,7 +2545,8 @@ static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } -static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s) +static uint32_t +rtl8139_RxBufPtr_read(RTL8139State *s) { /* this value is off by 16 */ uint32_t ret = s->RxBufPtr - 0x10; @@ -2558,7 +2556,8 @@ static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s) return ret; } -static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s) +static uint32_t +rtl8139_RxBufAddr_read(RTL8139State *s) { /* this value is NOT off by 16 */ uint32_t ret = s->RxBufAddr; @@ -2568,7 +2567,8 @@ static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s) return ret; } -static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val) +static void +rtl8139_RxBuf_write(RTL8139State *s, uint32_t val) { DPRINTF("RxBuf write val=0x%08x\n", val); @@ -2577,7 +2577,8 @@ static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val) /* may need to reset rxring here */ } -static uint32_t rtl8139_RxBuf_read(RTL8139State *s) +static uint32_t +rtl8139_RxBuf_read(RTL8139State *s) { uint32_t ret = s->RxBuf; @@ -2586,7 +2587,8 @@ static uint32_t rtl8139_RxBuf_read(RTL8139State *s) return ret; } -static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) +static void +rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) { DPRINTF("IntrMask write(w) val=0x%04x\n", val); @@ -2599,7 +2601,8 @@ static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) } -static uint32_t rtl8139_IntrMask_read(RTL8139State *s) +static uint32_t +rtl8139_IntrMask_read(RTL8139State *s) { uint32_t ret = s->IntrMask; @@ -2608,7 +2611,8 @@ static uint32_t rtl8139_IntrMask_read(RTL8139State *s) return ret; } -static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) +static void +rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) { DPRINTF("IntrStatus write(w) val=0x%04x\n", val); @@ -2634,7 +2638,8 @@ static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) #endif } -static uint32_t rtl8139_IntrStatus_read(RTL8139State *s) +static uint32_t +rtl8139_IntrStatus_read(RTL8139State *s) { uint32_t ret = s->IntrStatus; @@ -2652,7 +2657,8 @@ static uint32_t rtl8139_IntrStatus_read(RTL8139State *s) return ret; } -static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val) +static void +rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val) { DPRINTF("MultiIntr write(w) val=0x%04x\n", val); @@ -2662,7 +2668,8 @@ static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val) s->MultiIntr = val; } -static uint32_t rtl8139_MultiIntr_read(RTL8139State *s) +static uint32_t +rtl8139_MultiIntr_read(RTL8139State *s) { uint32_t ret = s->MultiIntr; @@ -2671,13 +2678,13 @@ static uint32_t rtl8139_MultiIntr_read(RTL8139State *s) return ret; } -static void rtl8139_io_writeb(uint32_t addr, uint8_t val, void *opaque) +static void +rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) { - RTL8139State *s = opaque; + RTL8139State *s = priv; addr &= 0xFF; - switch (addr) - { + switch (addr) { case MAC0 ... MAC0+4: s->phys[addr - MAC0] = val; break; @@ -2722,12 +2729,9 @@ static void rtl8139_io_writeb(uint32_t addr, uint8_t val, void *opaque) case HltClk: DPRINTF("HltClk write val=0x%08x\n", val); - if (val == 'R') - { + if (val == 'R') { s->clock_enabled = 1; - } - else if (val == 'H') - { + } else if (val == 'H') { s->clock_enabled = 0; } break; @@ -2739,14 +2743,14 @@ static void rtl8139_io_writeb(uint32_t addr, uint8_t val, void *opaque) case TxPoll: DPRINTF("C+ TxPoll write(b) val=0x%02x\n", val); - if (val & (1 << 7)) - { + if (val & (1 << 7)) { DPRINTF("C+ TxPoll high priority transmission (not " "implemented)\n"); +#if 0 //rtl8139_cplus_transmit(s); +#endif } - if (val & (1 << 6)) - { + if (val & (1 << 6)) { DPRINTF("C+ TxPoll normal priority transmission\n"); rtl8139_cplus_transmit(s); } @@ -2760,9 +2764,10 @@ static void rtl8139_io_writeb(uint32_t addr, uint8_t val, void *opaque) } } -static void rtl8139_io_writew(uint32_t addr, uint16_t val, void *opaque) +static void +rtl8139_io_writew(uint32_t addr, uint16_t val, void *priv) { - RTL8139State *s = opaque; + RTL8139State *s = priv; addr &= 0xFF; switch (addr) @@ -2813,17 +2818,18 @@ static void rtl8139_io_writew(uint32_t addr, uint16_t val, void *opaque) DPRINTF("ioport write(w) addr=0x%x val=0x%04x via write(b)\n", addr, val); - rtl8139_io_writeb(addr, val & 0xff, opaque); - rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, opaque); + rtl8139_io_writeb(addr, val & 0xff, priv); + rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, priv); break; } } /* TODO: Implement timer. */ -static void rtl8139_io_writel(uint32_t addr, uint32_t val, void *opaque) +static void +rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) { - RTL8139State *s = opaque; + RTL8139State *s = priv; addr &= 0xFF; switch (addr) @@ -2866,8 +2872,10 @@ static void rtl8139_io_writel(uint32_t addr, uint32_t val, void *opaque) case Timer: DPRINTF("TCTR Timer reset on write\n"); s->TCTR = 0; - //s->TCTR_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - //rtl8139_set_next_tctr_time(s); +#if 0 + s->TCTR_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + rtl8139_set_next_tctr_time(s); +#endif break; case FlashReg: @@ -2880,23 +2888,23 @@ static void rtl8139_io_writel(uint32_t addr, uint32_t val, void *opaque) default: DPRINTF("ioport write(l) addr=0x%x val=0x%08x via write(b)\n", addr, val); - rtl8139_io_writeb(addr, val & 0xff, opaque); - rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, opaque); - rtl8139_io_writeb(addr + 2, (val >> 16) & 0xff, opaque); - rtl8139_io_writeb(addr + 3, (val >> 24) & 0xff, opaque); + rtl8139_io_writeb(addr, val & 0xff, priv); + rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, priv); + rtl8139_io_writeb(addr + 2, (val >> 16) & 0xff, priv); + rtl8139_io_writeb(addr + 3, (val >> 24) & 0xff, priv); break; } } -static uint8_t rtl8139_io_readb(uint32_t addr, void *opaque) +static uint8_t +rtl8139_io_readb(uint32_t addr, void *priv) { - RTL8139State *s = opaque; + RTL8139State *s = priv; uint8_t ret; addr &= 0xFF; - switch (addr) - { + switch (addr) { case MAC0 ... MAC0+5: ret = s->phys[addr - MAC0]; break; @@ -2967,14 +2975,14 @@ static uint8_t rtl8139_io_readb(uint32_t addr, void *opaque) return ret; } -static uint16_t rtl8139_io_readw(uint32_t addr, void *opaque) +static uint16_t +rtl8139_io_readw(uint32_t addr, void *priv) { - RTL8139State *s = opaque; + RTL8139State *s = priv; uint16_t ret; addr &= 0xFF; - switch (addr) - { + switch (addr) { case TxAddr0 ... TxAddr0+4*4-1: ret = rtl8139_TxStatus_TxAddr_read(s, s->TxAddr, TxAddr0, addr, 2); break; @@ -3036,8 +3044,8 @@ static uint16_t rtl8139_io_readw(uint32_t addr, void *opaque) default: DPRINTF("ioport read(w) addr=0x%x via read(b)\n", addr); - ret = rtl8139_io_readb(addr, opaque); - ret |= rtl8139_io_readb(addr + 1, opaque) << 8; + ret = rtl8139_io_readb(addr, priv); + ret |= rtl8139_io_readb(addr + 1, priv) << 8; DPRINTF("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret); break; @@ -3046,14 +3054,14 @@ static uint16_t rtl8139_io_readw(uint32_t addr, void *opaque) return ret; } -static uint32_t rtl8139_io_readl(uint32_t addr, void *opaque) +static uint32_t +rtl8139_io_readl(uint32_t addr, void *priv) { - RTL8139State *s = opaque; + RTL8139State *s = priv; uint32_t ret; addr &= 0xFF; - switch (addr) - { + switch (addr) { case RxMissed: ret = s->RxMissed; @@ -3092,8 +3100,10 @@ static uint32_t rtl8139_io_readl(uint32_t addr, void *opaque) break; case Timer: - //ret = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->TCTR_base) / - // PCI_PERIOD; +#if 0 + ret = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->TCTR_base) / + PCI_PERIOD; +#endif ret = s->TCTR; DPRINTF("TCTR Timer read val=0x%08x\n", ret); break; @@ -3106,10 +3116,10 @@ static uint32_t rtl8139_io_readl(uint32_t addr, void *opaque) default: DPRINTF("ioport read(l) addr=0x%x via read(b)\n", addr); - ret = rtl8139_io_readb(addr, opaque); - ret |= rtl8139_io_readb(addr + 1, opaque) << 8; - ret |= rtl8139_io_readb(addr + 2, opaque) << 16; - ret |= rtl8139_io_readb(addr + 3, opaque) << 24; + ret = rtl8139_io_readb(addr, priv); + ret |= rtl8139_io_readb(addr + 1, priv) << 8; + ret |= rtl8139_io_readb(addr + 2, priv) << 16; + ret |= rtl8139_io_readb(addr + 3, priv) << 24; DPRINTF("read(l) addr=0x%x val=%08x\n", addr, ret); break; @@ -3118,41 +3128,48 @@ static uint32_t rtl8139_io_readl(uint32_t addr, void *opaque) return ret; } -static uint32_t rtl8139_io_readl_ioport(uint16_t addr, void *opaque) +static uint32_t +rtl8139_io_readl_ioport(uint16_t addr, void *priv) { - return rtl8139_io_readl(addr, opaque); + return rtl8139_io_readl(addr, priv); } -static uint16_t rtl8139_io_readw_ioport(uint16_t addr, void *opaque) +static uint16_t +rtl8139_io_readw_ioport(uint16_t addr, void *priv) { - return rtl8139_io_readw(addr, opaque); + return rtl8139_io_readw(addr, priv); } -static uint8_t rtl8139_io_readb_ioport(uint16_t addr, void *opaque) +static uint8_t +rtl8139_io_readb_ioport(uint16_t addr, void *priv) { - return rtl8139_io_readb(addr, opaque); + return rtl8139_io_readb(addr, priv); } -static void rtl8139_io_writel_ioport(uint16_t addr, uint32_t val, void *opaque) +static void +rtl8139_io_writel_ioport(uint16_t addr, uint32_t val, void *priv) { - return rtl8139_io_writel(addr, val, opaque); + return rtl8139_io_writel(addr, val, priv); } -static void rtl8139_io_writew_ioport(uint16_t addr, uint16_t val, void *opaque) +static void +rtl8139_io_writew_ioport(uint16_t addr, uint16_t val, void *priv) { - return rtl8139_io_writew(addr, val, opaque); + return rtl8139_io_writew(addr, val, priv); } -static void rtl8139_io_writeb_ioport(uint16_t addr, uint8_t val, void *opaque) +static void +rtl8139_io_writeb_ioport(uint16_t addr, uint8_t val, void *priv) { - return rtl8139_io_writeb(addr, val, opaque); + return rtl8139_io_writeb(addr, val, priv); } -static int rtl8139_set_link_status(void* priv, uint32_t link_state) +static int +rtl8139_set_link_status(void* priv, uint32_t link_state) { RTL8139State *s = (RTL8139State*)priv; - if ((link_state & NET_LINK_DOWN)) { + if (link_state & NET_LINK_DOWN) { s->BasicModeStatus &= ~0x04; } else { s->BasicModeStatus |= 0x04; @@ -3163,9 +3180,10 @@ static int rtl8139_set_link_status(void* priv, uint32_t link_state) return 0; } -static void rtl8139_timer(void *opaque) +static void +rtl8139_timer(void *priv) { - RTL8139State *s = opaque; + RTL8139State *s = priv; timer_on_auto(&s->timer, 1000000.0 / ((double) cpu_pci_speed)); @@ -3184,9 +3202,9 @@ static void rtl8139_timer(void *opaque) } static uint8_t -rtl8139_pci_read(int func, int addr, void *p) +rtl8139_pci_read(UNUSED(int func), int addr, void *priv) { - RTL8139State *s = (RTL8139State *) p; + const RTL8139State *s = (RTL8139State *) priv; switch (addr) { default: @@ -3235,17 +3253,17 @@ rtl8139_pci_read(int func, int addr, void *p) } static void -rtl8139_pci_write(int func, int addr, uint8_t val, void *p) +rtl8139_pci_write(int func, int addr, uint8_t val, void *priv) { - RTL8139State *s = (RTL8139State *) p; + RTL8139State *s = (RTL8139State *) priv; switch (addr) { case 0x04: mem_mapping_disable(&s->bar_mem); - io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); s->pci_conf[addr & 0xFF] = val; if (val & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); if ((val & PCI_COMMAND_MEM) && s->bar_mem.size) mem_mapping_enable(&s->bar_mem); break; @@ -3260,10 +3278,10 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *p) break; case 0x10: case 0x11: - io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); s->pci_conf[addr & 0xFF] = val; if (s->pci_conf[0x4] & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, p); + io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); break; case 0x14: case 0x15: @@ -3283,7 +3301,7 @@ static void * nic_init(const device_t *info) { RTL8139State *s = calloc(1, sizeof(RTL8139State)); - FILE* f = NULL; + FILE* fp = NULL; char eeprom_filename[1024] = { 0 }; mem_mapping_add(&s->bar_mem, 0, 0, rtl8139_io_readb, rtl8139_io_readw, rtl8139_io_readl, rtl8139_io_writeb, rtl8139_io_writew, rtl8139_io_writel, NULL, MEM_MAPPING_EXTERNAL, s); pci_add_card(PCI_ADD_NETWORK, rtl8139_pci_read, rtl8139_pci_write, s, &s->pci_slot); @@ -3291,12 +3309,12 @@ nic_init(const device_t *info) snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); - f = nvr_fopen(eeprom_filename, "rb"); - if (f) + fp = nvr_fopen(eeprom_filename, "rb"); + if (fp) { - fread(s->eeprom.contents, 2, 64, f); - fclose(f); - f = NULL; + fread(s->eeprom.contents, 2, 64, fp); + fclose(fp); + fp = NULL; } else { /* prepare eeprom */ s->eeprom.contents[0] = 0x8129; @@ -3325,16 +3343,17 @@ nic_init(const device_t *info) static void nic_close(void *priv) { - RTL8139State *s = (RTL8139State*)priv; - FILE* f = NULL; + const RTL8139State *s = (RTL8139State*) priv; + FILE* fp = NULL; char eeprom_filename[1024] = { 0 }; + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); - f = nvr_fopen(eeprom_filename, "wb"); - if (f) + fp = nvr_fopen(eeprom_filename, "wb"); + if (fp) { - fwrite(s->eeprom.contents, 2, 64, f); - fclose(f); - f = NULL; + fwrite(s->eeprom.contents, 2, 64, fp); + fclose(fp); + fp = NULL; } free(priv); } diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 2437b2b1a..680f1e939 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -32,6 +32,7 @@ #include <86box/net_eeprom_nmc93cxx.h> #include <86box/net_tulip.h> #include <86box/bswap.h> +#include <86box/plat_unused.h> #define CSR(_x) ((_x) << 3) @@ -296,8 +297,9 @@ struct tulip_descriptor { struct TULIPState { uint8_t pci_slot; uint8_t irq_state; - const device_t* device_info; - uint16_t subsys_id, subsys_ven_id; + const device_t *device_info; + uint16_t subsys_id; + uint16_t subsys_ven_id; mem_mapping_t memory; netcard_t *nic; nmc93cxx_eeprom_t *eeprom; @@ -437,9 +439,8 @@ tulip_filter_address(TULIPState *s, const uint8_t *addr) { static const char broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; bool ret = false; - int i; - for (i = 0; i < 16 && ret == false; i++) { + for (uint8_t i = 0; i < 16 && ret == false; i++) { if (!memcmp(&s->filter[i], addr, ETH_ALEN)) { ret = true; } @@ -468,10 +469,10 @@ tulip_filter_address(TULIPState *s, const uint8_t *addr) } static int -tulip_receive(void *p, uint8_t *buf, int size) +tulip_receive(void *priv, uint8_t *buf, int size) { struct tulip_descriptor desc; - TULIPState *s = (TULIPState *) p; + TULIPState *s = (TULIPState *) priv; if (size < 14 || size > sizeof(s->rx_frame) - 4 || s->rx_frame_len || tulip_rx_stopped(s)) { @@ -748,7 +749,9 @@ tulip_mii(TULIPState *s) { uint32_t changed = s->old_csr9 ^ s->csr[9]; uint16_t data; - int op, phy, reg; + int op; + int phy; + int reg; if (!(changed & CSR9_MDC)) { return; @@ -910,11 +913,10 @@ tulip_setup_frame(TULIPState *s, { uint8_t buf[4096]; int len = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; - int i; if (len == 192) { dma_bm_read(desc->buf_addr1, buf, len, 1); - for (i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { tulip_setup_filter_addr(s, buf, i); } } @@ -951,14 +953,13 @@ static void tulip_xmit_list_update(TULIPState *s) { #define TULIP_DESC_MAX 128 - uint8_t i = 0; struct tulip_descriptor desc; if (tulip_ts(s) != CSR5_TS_SUSPENDED) { return; } - for (i = 0; i < TULIP_DESC_MAX; i++) { + for (uint8_t i = 0; i < TULIP_DESC_MAX; i++) { tulip_desc_read(s, s->current_tx_desc, &desc); if (!(desc.status & TDES0_OWN)) { @@ -987,7 +988,7 @@ tulip_xmit_list_update(TULIPState *s) } static void -tulip_csr9_write(TULIPState *s, uint32_t old_val, +tulip_csr9_write(TULIPState *s, UNUSED(uint32_t old_val), uint32_t new_val) { if (new_val & CSR9_SR) { @@ -1001,23 +1002,23 @@ tulip_csr9_write(TULIPState *s, uint32_t old_val, static void tulip_reset(void *priv) { - TULIPState *s = (TULIPState *) priv; - uint16_t *eeprom_data = nmc93cxx_eeprom_data(s->eeprom); - s->csr[0] = 0xfe000000; - s->csr[1] = 0xffffffff; - s->csr[2] = 0xffffffff; - s->csr[5] = 0xf0000000; - s->csr[6] = 0x32000040; - s->csr[7] = 0xf3fe0000; - s->csr[8] = 0xe0000000; - s->csr[9] = 0xfff483ff; - s->csr[11] = 0xfffe0000; - s->csr[12] = 0x000000c6; - s->csr[13] = 0xffff0000; - s->csr[14] = 0xffffffff; - s->csr[15] = 0x8ff00000; - s->subsys_id = eeprom_data[1]; - s->subsys_ven_id = eeprom_data[0]; + TULIPState *s = (TULIPState *) priv; + const uint16_t *eeprom_data = nmc93cxx_eeprom_data(s->eeprom); + s->csr[0] = 0xfe000000; + s->csr[1] = 0xffffffff; + s->csr[2] = 0xffffffff; + s->csr[5] = 0xf0000000; + s->csr[6] = 0x32000040; + s->csr[7] = 0xf3fe0000; + s->csr[8] = 0xe0000000; + s->csr[9] = 0xfff483ff; + s->csr[11] = 0xfffe0000; + s->csr[12] = 0x000000c6; + s->csr[13] = 0xffff0000; + s->csr[14] = 0xffffffff; + s->csr[15] = 0x8ff00000; + s->subsys_id = eeprom_data[1]; + s->subsys_ven_id = eeprom_data[0]; } static void @@ -1142,14 +1143,13 @@ tulip_read_io(uint16_t addr, void *opaque) static void tulip_idblock_crc(uint16_t *srom) { - int word; - int bit; - unsigned char bitval, crc; + unsigned char bitval; + unsigned char crc; const int len = 9; crc = -1; - for (word = 0; word < len; word++) { - for (bit = 15; bit >= 0; bit--) { + for (int word = 0; word < len; word++) { + for (int8_t bit = 15; bit >= 0; bit--) { if ((word == (len - 1)) && (bit == 7)) { /* * Insert the correct CRC result into input data stream @@ -1174,9 +1174,10 @@ tulip_srom_crc(uint8_t *eeprom, size_t len) unsigned long crc = 0xffffffff; unsigned long flippedcrc = 0; unsigned char currentbyte; - unsigned int msb, bit, i; + unsigned int msb; + unsigned int bit; - for (i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { currentbyte = eeprom[i]; for (bit = 0; bit < 8; bit++) { msb = (crc >> 31) & 1; @@ -1189,7 +1190,7 @@ tulip_srom_crc(uint8_t *eeprom, size_t len) } } - for (i = 0; i < 32; i++) { + for (uint8_t i = 0; i < 32; i++) { flippedcrc <<= 1; bit = crc & 1; crc >>= 1; @@ -1471,9 +1472,9 @@ tulip_fill_eeprom(TULIPState *s) } static uint8_t -tulip_pci_read(int func, int addr, void *p) +tulip_pci_read(UNUSED(int func), int addr, void *priv) { - TULIPState *s = (TULIPState *) p; + const TULIPState *s = (TULIPState *) priv; switch (addr) { default: @@ -1518,17 +1519,17 @@ tulip_pci_read(int func, int addr, void *p) } static void -tulip_pci_write(int func, int addr, uint8_t val, void *p) +tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - TULIPState *s = (TULIPState *) p; + TULIPState *s = (TULIPState *) priv; switch (addr) { case 0x4: mem_mapping_disable(&s->memory); - io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); s->pci_conf[addr & 0xFF] = val; if (val & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); if ((val & PCI_COMMAND_MEM) && s->memory.size) mem_mapping_enable(&s->memory); break; @@ -1537,10 +1538,10 @@ tulip_pci_write(int func, int addr, uint8_t val, void *p) break; case 0x10: case 0x11: - io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); s->pci_conf[addr & 0xFF] = val; if (s->pci_conf[0x4] & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, p); + io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); break; case 0x14: case 0x15: @@ -1570,7 +1571,7 @@ nic_init(const device_t *info) s->device_info = info; memcpy(eeprom_default_local, s->device_info->local ? eeprom_default_24110 : eeprom_default, sizeof(eeprom_default)); tulip_idblock_crc((uint16_t *) eeprom_default_local); - (((uint16_t *) eeprom_default_local))[63] = (tulip_srom_crc((uint8_t *) eeprom_default_local, 126)); + ((uint16_t *) eeprom_default_local)[63] = (tulip_srom_crc((uint8_t *) eeprom_default_local, 126)); params.nwords = 64; params.default_content = (uint16_t *) eeprom_default_local; From 70d4fc1b9a3feafceb4a63efecca615f5c2c231a Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 6 Aug 2023 18:28:04 -0400 Subject: [PATCH 040/133] clang-format the new network cards --- src/network/net_eeprom_nmc93cxx.c | 98 +-- src/network/net_l80225.c | 4 +- src/network/net_rtl8139.c | 1080 +++++++++++++++-------------- src/network/net_tulip.c | 24 +- 4 files changed, 616 insertions(+), 590 deletions(-) diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index 22d2bdd08..d51cc94e7 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -30,10 +30,10 @@ #include <86box/plat_unused.h> struct nmc93cxx_eeprom_t { - uint8_t tick; - uint8_t address; - uint8_t command; - uint8_t writable; + uint8_t tick; + uint8_t address; + uint8_t command; + uint8_t writable; uint8_t eecs; uint8_t eesk; @@ -42,7 +42,7 @@ struct nmc93cxx_eeprom_t { uint8_t addrbits; uint16_t size; uint16_t data; - char filename[1024]; + char filename[1024]; uint16_t contents[]; }; @@ -67,76 +67,75 @@ nmc93cxx_eeprom_log(int lvl, const char *fmt, ...) #endif static const char *opstring[] = { - "extended", "write", "read", "erase" + "extended", "write", "read", "erase" }; static void * -nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void* params) +nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void *params) { - uint16_t nwords = 64; - uint8_t addrbits = 6; - uint8_t filldefault = 1; - nmc93cxx_eeprom_params_t *params_details = (nmc93cxx_eeprom_params_t*) params; - nmc93cxx_eeprom_t* eeprom = NULL; + uint16_t nwords = 64; + uint8_t addrbits = 6; + uint8_t filldefault = 1; + nmc93cxx_eeprom_params_t *params_details = (nmc93cxx_eeprom_params_t *) params; + nmc93cxx_eeprom_t *eeprom = NULL; if (!params) return NULL; nwords = params_details->nwords; switch (nwords) { - case 16: - case 64: - addrbits = 6; - break; - case 128: - case 256: - addrbits = 8; - break; - default: - nwords = 64; - addrbits = 6; - break; + case 16: + case 64: + addrbits = 6; + break; + case 128: + case 256: + addrbits = 8; + break; + default: + nwords = 64; + addrbits = 6; + break; } eeprom = calloc(1, sizeof(nmc93cxx_eeprom_t) + ((nwords + 1) * 2)); if (!eeprom) return NULL; - eeprom->size = nwords; + eeprom->size = nwords; eeprom->addrbits = addrbits; /* Output DO is tristate, read results in 1. */ eeprom->eedo = 1; - if (params_details->filename) - { - FILE* file = nvr_fopen(params_details->filename, "rb"); + if (params_details->filename) { + FILE *fp = nvr_fopen(params_details->filename, "rb"); strncpy(eeprom->filename, params_details->filename, 1024); - if (file) { - filldefault = !fread(eeprom->contents, sizeof(uint16_t), nwords, file); - fclose(file); + if (fp) { + filldefault = !fread(eeprom->contents, sizeof(uint16_t), nwords, fp); + fclose(fp); } } - if (filldefault) - { + if (filldefault) { memcpy(eeprom->contents, params_details->default_content, nwords * sizeof(uint16_t)); } return eeprom; } -void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi) +void +nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi) { - uint8_t tick = eeprom->tick; - uint8_t eedo = eeprom->eedo; + uint8_t tick = eeprom->tick; + uint8_t eedo = eeprom->eedo; uint16_t address = eeprom->address; - uint8_t command = eeprom->command; + uint8_t command = eeprom->command; nmc93cxx_eeprom_log(1, "CS=%u SK=%u DI=%u DO=%u, tick = %u\n", - eecs, eesk, eedi, eedo, tick); + eecs, eesk, eedi, eedo, tick); if (!eeprom->eecs && eecs) { /* Start chip select cycle. */ nmc93cxx_eeprom_log(1, "Cycle start, waiting for 1st start bit (0)\n"); - tick = 0; + tick = 0; command = 0x0; address = 0x0; } else if (eeprom->eecs && !eecs) { @@ -200,7 +199,7 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee address = ((address << 1) | eedi); if (tick == 2 + 2 + eeprom->addrbits) { nmc93cxx_eeprom_log(1, "%s command, address = 0x%02x (value 0x%04x)\n", - opstring[command], address, eeprom->contents[address]); + opstring[command], address, eeprom->contents[address]); if (command == 2) { eedo = 0; } @@ -245,26 +244,26 @@ void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int ee } } /* Save status of EEPROM. */ - eeprom->tick = tick; - eeprom->eecs = eecs; - eeprom->eesk = eesk; - eeprom->eedo = eedo; + eeprom->tick = tick; + eeprom->eecs = eecs; + eeprom->eesk = eesk; + eeprom->eedo = eedo; eeprom->address = address; eeprom->command = command; } -uint16_t nmc93cxx_eeprom_read(nmc93cxx_eeprom_t *eeprom) +uint16_t +nmc93cxx_eeprom_read(nmc93cxx_eeprom_t *eeprom) { /* Return status of pin DO (0 or 1). */ return eeprom->eedo; } - static void nmc93cxx_eeprom_close(void *priv) { - nmc93cxx_eeprom_t* eeprom = (nmc93cxx_eeprom_t*)priv; - FILE* fp = nvr_fopen(eeprom->filename, "wb"); + nmc93cxx_eeprom_t *eeprom = (nmc93cxx_eeprom_t *) priv; + FILE *fp = nvr_fopen(eeprom->filename, "wb"); if (fp) { fwrite(eeprom->contents, 2, eeprom->size, fp); fclose(fp); @@ -272,7 +271,8 @@ nmc93cxx_eeprom_close(void *priv) free(priv); } -uint16_t *nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom) +uint16_t * +nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom) { /* Get EEPROM data array. */ return &eeprom->contents[0]; diff --git a/src/network/net_l80225.c b/src/network/net_l80225.c index 801adaa8b..6493edec6 100644 --- a/src/network/net_l80225.c +++ b/src/network/net_l80225.c @@ -15,7 +15,7 @@ #include <86box/network.h> uint16_t -l80225_mii_readw(uint16_t* regs, uint16_t addr) +l80225_mii_readw(uint16_t *regs, uint16_t addr) { switch (addr) { case 0x1: @@ -35,7 +35,7 @@ l80225_mii_readw(uint16_t* regs, uint16_t addr) } void -l80225_mii_writew(uint16_t* regs, uint16_t addr, uint16_t val) +l80225_mii_writew(uint16_t *regs, uint16_t addr, uint16_t val) { regs[addr] = val; } diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 9173e69a0..c184bdafa 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -44,25 +44,28 @@ #include <86box/net_rtl8139.h> #include <86box/plat_unused.h> -#define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ +#define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ #define SET_MASKED(input, mask, curr) \ - ( ( (input) & ~(mask) ) | ( (curr) & (mask) ) ) + (((input) & ~(mask)) | ((curr) & (mask))) /* arg % size for size which is a power of 2 */ #define MOD2(input, size) \ - ( ( input ) & ( size - 1 ) ) + ((input) & (size - 1)) #define ETHER_TYPE_LEN 2 -#define VLAN_TCI_LEN 2 -#define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) +#define VLAN_TCI_LEN 2 +#define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) -#if defined (DEBUG_RTL8139) -# define DPRINTF(fmt, ...) \ - do { pclog("RTL8139: " fmt, ## __VA_ARGS__); } while (0) +#if defined(DEBUG_RTL8139) +# define DPRINTF(fmt, ...) \ + do { \ + pclog("RTL8139: " fmt, ##__VA_ARGS__); \ + } while (0) #else -static inline __attribute__ ((format (printf, 1, 2))) int DPRINTF(UNUSED(const char *fmt), ...) +static inline __attribute__((format(printf, 1, 2))) int +DPRINTF(UNUSED(const char *fmt), ...) { return 0; } @@ -73,63 +76,63 @@ typedef struct RTL8139State RTL8139State; /* Symbolic offsets to registers. */ enum RTL8139_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxStatus0 = 0x10,/* Transmit status (Four 32bit registers). C mode only */ - /* Dump Tally Conter control register(64bit). C+ mode only */ - TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ - RxBuf = 0x30, - ChipCmd = 0x37, - RxBufPtr = 0x38, - RxBufAddr = 0x3A, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - Timer = 0x48, /* A general-purpose counter. */ - RxMissed = 0x4C, /* 24 bits valid, write clears. */ - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - FlashReg = 0x54, - MediaStatus = 0x58, - Config3 = 0x59, - Config4 = 0x5A, /* absent on RTL-8139A */ - HltClk = 0x5B, - MultiIntr = 0x5C, - PCIRevisionID = 0x5E, - TxSummary = 0x60, /* TSAD register. Transmit Status of All Descriptors*/ - BasicModeCtrl = 0x62, + MAC0 = 0, /* Ethernet hardware address. */ + MAR0 = 8, /* Multicast filter. */ + TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). C mode only */ + /* Dump Tally Conter control register(64bit). C+ mode only */ + TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ + RxBuf = 0x30, + ChipCmd = 0x37, + RxBufPtr = 0x38, + RxBufAddr = 0x3A, + IntrMask = 0x3C, + IntrStatus = 0x3E, + TxConfig = 0x40, + RxConfig = 0x44, + Timer = 0x48, /* A general-purpose counter. */ + RxMissed = 0x4C, /* 24 bits valid, write clears. */ + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + FlashReg = 0x54, + MediaStatus = 0x58, + Config3 = 0x59, + Config4 = 0x5A, /* absent on RTL-8139A */ + HltClk = 0x5B, + MultiIntr = 0x5C, + PCIRevisionID = 0x5E, + TxSummary = 0x60, /* TSAD register. Transmit Status of All Descriptors*/ + BasicModeCtrl = 0x62, BasicModeStatus = 0x64, - NWayAdvert = 0x66, - NWayLPAR = 0x68, - NWayExpansion = 0x6A, + NWayAdvert = 0x66, + NWayLPAR = 0x68, + NWayExpansion = 0x6A, /* Undocumented registers, but required for proper operation. */ - FIFOTMS = 0x70, /* FIFO Control and test. */ - CSCR = 0x74, /* Chip Status and Configuration Register. */ - PARA78 = 0x78, - PARA7c = 0x7c, /* Magic transceiver parameter register. */ - Config5 = 0xD8, /* absent on RTL-8139A */ + FIFOTMS = 0x70, /* FIFO Control and test. */ + CSCR = 0x74, /* Chip Status and Configuration Register. */ + PARA78 = 0x78, + PARA7c = 0x7c, /* Magic transceiver parameter register. */ + Config5 = 0xD8, /* absent on RTL-8139A */ /* C+ mode */ - TxPoll = 0xD9, /* Tell chip to check Tx descriptors for work */ + TxPoll = 0xD9, /* Tell chip to check Tx descriptors for work */ RxMaxSize = 0xDA, /* Max size of an Rx packet (8169 only) */ CpCmd = 0xE0, /* C+ Command register (C+ mode only) */ - IntrMitigate = 0xE2, /* rx/tx interrupt mitigation control */ - RxRingAddrLO = 0xE4, /* 64-bit start addr of Rx ring */ - RxRingAddrHI = 0xE8, /* 64-bit start addr of Rx ring */ - TxThresh = 0xEC, /* Early Tx threshold */ + IntrMitigate = 0xE2, /* rx/tx interrupt mitigation control */ + RxRingAddrLO = 0xE4, /* 64-bit start addr of Rx ring */ + RxRingAddrHI = 0xE8, /* 64-bit start addr of Rx ring */ + TxThresh = 0xEC, /* Early Tx threshold */ }; enum ClearBitMasks { MultiIntrClear = 0xF000, - ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), + ChipCmdClear = 0xE2, + Config1Clear = (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2) | (1 << 1), }; enum ChipCmdBits { - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, RxBufEmpty = 0x01, }; @@ -143,102 +146,100 @@ enum CplusCmdBits { /* Interrupt register bits, using my own meaningful names. */ enum IntrStatusBits { - PCIErr = 0x8000, + PCIErr = 0x8000, PCSTimeout = 0x4000, RxFIFOOver = 0x40, RxUnderrun = 0x20, /* Packet Underrun / Link Change */ RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, + TxErr = 0x08, + TxOK = 0x04, + RxErr = 0x02, + RxOK = 0x01, RxAckBits = RxFIFOOver | RxOverflow | RxOK, }; enum TxStatusBits { - TxHostOwns = 0x2000, - TxUnderrun = 0x4000, - TxStatOK = 0x8000, + TxHostOwns = 0x2000, + TxUnderrun = 0x4000, + TxStatOK = 0x8000, TxOutOfWindow = 0x20000000, - TxAborted = 0x40000000, + TxAborted = 0x40000000, TxCarrierLost = 0x80000000, }; enum RxStatusBits { RxMulticast = 0x8000, - RxPhysical = 0x4000, + RxPhysical = 0x4000, RxBroadcast = 0x2000, RxBadSymbol = 0x0020, - RxRunt = 0x0010, - RxTooLong = 0x0008, - RxCRCErr = 0x0004, - RxBadAlign = 0x0002, - RxStatusOK = 0x0001, + RxRunt = 0x0010, + RxTooLong = 0x0008, + RxCRCErr = 0x0004, + RxBadAlign = 0x0002, + RxStatusOK = 0x0001, }; /* Bits in RxConfig. */ enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, + AcceptErr = 0x20, + AcceptRunt = 0x10, AcceptBroadcast = 0x08, AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, }; /* Bits in TxConfig. */ enum tx_config_bits { - /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ - TxIFGShift = 24, - TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ - TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ - TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ - TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ + /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ + TxIFGShift = 24, + TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ + TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ + TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ + TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ - TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ - TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ - TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ - TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ + TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ + TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ + TxClearAbt = (1 << 0), /* Clear abort (WO) */ + TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */ + TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */ TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ }; - /* Transmit Status of All Descriptors (TSAD) Register */ enum TSAD_bits { - TSAD_TOK3 = 1<<15, // TOK bit of Descriptor 3 - TSAD_TOK2 = 1<<14, // TOK bit of Descriptor 2 - TSAD_TOK1 = 1<<13, // TOK bit of Descriptor 1 - TSAD_TOK0 = 1<<12, // TOK bit of Descriptor 0 - TSAD_TUN3 = 1<<11, // TUN bit of Descriptor 3 - TSAD_TUN2 = 1<<10, // TUN bit of Descriptor 2 - TSAD_TUN1 = 1<<9, // TUN bit of Descriptor 1 - TSAD_TUN0 = 1<<8, // TUN bit of Descriptor 0 - TSAD_TABT3 = 1<<07, // TABT bit of Descriptor 3 - TSAD_TABT2 = 1<<06, // TABT bit of Descriptor 2 - TSAD_TABT1 = 1<<05, // TABT bit of Descriptor 1 - TSAD_TABT0 = 1<<04, // TABT bit of Descriptor 0 - TSAD_OWN3 = 1<<03, // OWN bit of Descriptor 3 - TSAD_OWN2 = 1<<02, // OWN bit of Descriptor 2 - TSAD_OWN1 = 1<<01, // OWN bit of Descriptor 1 - TSAD_OWN0 = 1<<00, // OWN bit of Descriptor 0 + TSAD_TOK3 = 1 << 15, // TOK bit of Descriptor 3 + TSAD_TOK2 = 1 << 14, // TOK bit of Descriptor 2 + TSAD_TOK1 = 1 << 13, // TOK bit of Descriptor 1 + TSAD_TOK0 = 1 << 12, // TOK bit of Descriptor 0 + TSAD_TUN3 = 1 << 11, // TUN bit of Descriptor 3 + TSAD_TUN2 = 1 << 10, // TUN bit of Descriptor 2 + TSAD_TUN1 = 1 << 9, // TUN bit of Descriptor 1 + TSAD_TUN0 = 1 << 8, // TUN bit of Descriptor 0 + TSAD_TABT3 = 1 << 07, // TABT bit of Descriptor 3 + TSAD_TABT2 = 1 << 06, // TABT bit of Descriptor 2 + TSAD_TABT1 = 1 << 05, // TABT bit of Descriptor 1 + TSAD_TABT0 = 1 << 04, // TABT bit of Descriptor 0 + TSAD_OWN3 = 1 << 03, // OWN bit of Descriptor 3 + TSAD_OWN2 = 1 << 02, // OWN bit of Descriptor 2 + TSAD_OWN1 = 1 << 01, // OWN bit of Descriptor 1 + TSAD_OWN0 = 1 << 00, // OWN bit of Descriptor 0 }; - /* Bits in Config1 */ enum Config1Bits { - Cfg1_PM_Enable = 0x01, - Cfg1_VPD_Enable = 0x02, - Cfg1_PIO = 0x04, - Cfg1_MMIO = 0x08, - LWAKE = 0x10, /* not on 8139, 8139A */ + Cfg1_PM_Enable = 0x01, + Cfg1_VPD_Enable = 0x02, + Cfg1_PIO = 0x04, + Cfg1_MMIO = 0x08, + LWAKE = 0x10, /* not on 8139, 8139A */ Cfg1_Driver_Load = 0x20, - Cfg1_LED0 = 0x40, - Cfg1_LED1 = 0x80, - SLEEP = (1 << 1), /* only on 8139, 8139A */ - PWRDN = (1 << 0), /* only on 8139, 8139A */ + Cfg1_LED0 = 0x40, + Cfg1_LED1 = 0x80, + SLEEP = (1 << 1), /* only on 8139, 8139A */ + PWRDN = (1 << 0), /* only on 8139, 8139A */ }; /* Bits in Config3 */ @@ -255,7 +256,7 @@ enum Config3Bits { /* Bits in Config4 */ enum Config4Bits { - LWPTN = (1 << 2), /* not on 8139, 8139A */ + LWPTN = (1 << 2), /* not on 8139, 8139A */ }; /* Bits in Config5 */ @@ -272,14 +273,14 @@ enum Config5Bits { enum RxConfigBits { /* rx fifo threshold */ RxCfgFIFOShift = 13, - RxCfgFIFONone = (7 << RxCfgFIFOShift), + RxCfgFIFONone = (7 << RxCfgFIFOShift), /* Max DMA burst */ - RxCfgDMAShift = 8, + RxCfgDMAShift = 8, RxCfgDMAUnlimited = (7 << RxCfgDMAShift), /* rx ring buffer length */ - RxCfgRcv8K = 0, + RxCfgRcv8K = 0, RxCfgRcv16K = (1 << 11), RxCfgRcv32K = (1 << 12), RxCfgRcv64K = (1 << 11) | (1 << 12), @@ -299,20 +300,20 @@ enum CSCRBits { CSCR_LinkDownCmd = 0x0f3c0, #endif enum CSCRBits { - CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ - CSCR_LD = 1<<9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ - CSCR_HEART_BIT = 1<<8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/ - CSCR_JBEN = 1<<7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/ - CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/ - CSCR_F_Connect = 1<<5, /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/ - CSCR_Con_status = 1<<3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/ - CSCR_Con_status_En = 1<<2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/ - CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/ + CSCR_Testfun = 1 << 15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ + CSCR_LD = 1 << 9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ + CSCR_HEART_BIT = 1 << 8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/ + CSCR_JBEN = 1 << 7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/ + CSCR_F_LINK_100 = 1 << 6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/ + CSCR_F_Connect = 1 << 5, /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/ + CSCR_Con_status = 1 << 3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/ + CSCR_Con_status_En = 1 << 2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/ + CSCR_PASS_SCR = 1 << 0, /* Bypass Scramble, def 0*/ }; enum Cfg9346Bits { - Cfg9346_Normal = 0x00, - Cfg9346_Autoload = 0x40, + Cfg9346_Normal = 0x00, + Cfg9346_Autoload = 0x40, Cfg9346_Programming = 0x80, Cfg9346_ConfigWrite = 0xC0, }; @@ -332,12 +333,12 @@ typedef enum { enum chip_flags { HasHltClk = (1 << 0), - HasLWake = (1 << 1), + HasLWake = (1 << 1), }; #define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ - (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) -#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) + (b30 << 30 | b29 << 29 | b28 << 28 | b27 << 27 | b26 << 26 | b23 << 23 | b22 << 22) +#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) #define RTL8139_PCI_REVID_8139 0x10 #define RTL8139_PCI_REVID_8139CPLUS 0x20 @@ -346,16 +347,16 @@ enum chip_flags { /* Size is 64 * 16bit words */ #define EEPROM_9346_ADDR_BITS 6 -#define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS) +#define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS) #define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1) enum Chip9346Operation { - Chip9346_op_mask = 0xc0, /* 10 zzzzzz */ - Chip9346_op_read = 0x80, /* 10 AAAAAA */ - Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */ - Chip9346_op_ext_mask = 0xf0, /* 11 zzzzzz */ - Chip9346_op_write_enable = 0x30, /* 00 11zzzz */ - Chip9346_op_write_all = 0x10, /* 00 01zzzz */ + Chip9346_op_mask = 0xc0, /* 10 zzzzzz */ + Chip9346_op_read = 0x80, /* 10 AAAAAA */ + Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */ + Chip9346_op_ext_mask = 0xf0, /* 11 zzzzzz */ + Chip9346_op_write_enable = 0x30, /* 00 11zzzz */ + Chip9346_op_write_all = 0x10, /* 00 01zzzz */ Chip9346_op_write_disable = 0x00, /* 00 00zzzz */ }; @@ -385,24 +386,24 @@ typedef struct EEprom9346 { #pragma pack(push, 1) typedef struct RTL8139TallyCounters { /* Tally counters */ - uint64_t TxOk; - uint64_t RxOk; - uint64_t TxERR; - uint32_t RxERR; - uint16_t MissPkt; - uint16_t FAE; - uint32_t Tx1Col; - uint32_t TxMCol; - uint64_t RxOkPhy; - uint64_t RxOkBrd; - uint32_t RxOkMul; - uint16_t TxAbt; - uint16_t TxUndrn; + uint64_t TxOk; + uint64_t RxOk; + uint64_t TxERR; + uint32_t RxERR; + uint16_t MissPkt; + uint16_t FAE; + uint32_t Tx1Col; + uint32_t TxMCol; + uint64_t RxOkPhy; + uint64_t RxOkBrd; + uint32_t RxOkMul; + uint16_t TxAbt; + uint16_t TxUndrn; } RTL8139TallyCounters; #pragma pack(pop) /* Clears all tally counters */ -static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters); +static void RTL8139TallyCounters_clear(RTL8139TallyCounters *counters); struct RTL8139State { /*< private >*/ @@ -432,15 +433,15 @@ struct RTL8139State { uint16_t CSCR; - uint8_t Cfg9346; - uint8_t Config0; - uint8_t Config1; - uint8_t Config3; - uint8_t Config4; - uint8_t Config5; + uint8_t Cfg9346; + uint8_t Config0; + uint8_t Config1; + uint8_t Config3; + uint8_t Config4; + uint8_t Config5; - uint8_t clock_enabled; - uint8_t bChipCmdState; + uint8_t clock_enabled; + uint8_t bChipCmdState; uint16_t MultiIntr; @@ -452,36 +453,36 @@ struct RTL8139State { uint16_t CpCmd; - uint8_t TxThresh; - uint8_t pci_latency; + uint8_t TxThresh; + uint8_t pci_latency; netcard_t *nic; /* C ring mode */ - uint32_t currTxDesc; + uint32_t currTxDesc; /* C+ mode */ - uint32_t cplus_enabled; + uint32_t cplus_enabled; - uint32_t currCPlusRxDesc; - uint32_t currCPlusTxDesc; + uint32_t currCPlusRxDesc; + uint32_t currCPlusTxDesc; - uint32_t RxRingAddrLO; - uint32_t RxRingAddrHI; + uint32_t RxRingAddrLO; + uint32_t RxRingAddrHI; EEprom9346 eeprom; - uint32_t TCTR; - uint32_t TimerInt; - int64_t TCTR_base; + uint32_t TCTR; + uint32_t TimerInt; + int64_t TCTR_base; /* Tally counters */ RTL8139TallyCounters tally_counters; /* Non-persistent data */ - uint8_t *cplus_txbuffer; - int cplus_txbuffer_len; - int cplus_txbuffer_offset; + uint8_t *cplus_txbuffer; + int cplus_txbuffer_len; + int cplus_txbuffer_offset; /* PCI interrupt timer */ pc_timer_t timer; @@ -500,34 +501,32 @@ prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) { DPRINTF("eeprom command 0x%02x\n", command); - switch (command & Chip9346_op_mask) - { + switch (command & Chip9346_op_mask) { case Chip9346_op_read: - { - eeprom->address = command & EEPROM_9346_ADDR_MASK; - eeprom->output = eeprom->contents[eeprom->address]; - eeprom->eedo = 0; - eeprom->tick = 0; - eeprom->mode = Chip9346_data_read; - DPRINTF("eeprom read from address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output); - } - break; + { + eeprom->address = command & EEPROM_9346_ADDR_MASK; + eeprom->output = eeprom->contents[eeprom->address]; + eeprom->eedo = 0; + eeprom->tick = 0; + eeprom->mode = Chip9346_data_read; + DPRINTF("eeprom read from address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); + } + break; case Chip9346_op_write: - { - eeprom->address = command & EEPROM_9346_ADDR_MASK; - eeprom->input = 0; - eeprom->tick = 0; - eeprom->mode = Chip9346_none; /* Chip9346_data_write */ - DPRINTF("eeprom begin write to address 0x%02x\n", - eeprom->address); - } - break; + { + eeprom->address = command & EEPROM_9346_ADDR_MASK; + eeprom->input = 0; + eeprom->tick = 0; + eeprom->mode = Chip9346_none; /* Chip9346_data_write */ + DPRINTF("eeprom begin write to address 0x%02x\n", + eeprom->address); + } + break; default: eeprom->mode = Chip9346_none; - switch (command & Chip9346_op_ext_mask) - { + switch (command & Chip9346_op_ext_mask) { case Chip9346_op_write_enable: DPRINTF("eeprom write enabled\n"); break; @@ -548,19 +547,18 @@ prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) static void prom9346_shift_clock(EEprom9346 *eeprom) { - int bit = eeprom->eedi?1:0; + int bit = eeprom->eedi ? 1 : 0; - ++ eeprom->tick; + ++eeprom->tick; DPRINTF("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, - eeprom->eedo); + eeprom->eedo); - switch (eeprom->mode) - { + switch (eeprom->mode) { case Chip9346_enter_command_mode: if (bit) { - eeprom->mode = Chip9346_read_command; - eeprom->tick = 0; + eeprom->mode = Chip9346_read_command; + eeprom->tick = 0; eeprom->input = 0; DPRINTF("eeprom: +++ synchronized, begin command read\n"); } @@ -574,27 +572,27 @@ prom9346_shift_clock(EEprom9346 *eeprom) break; case Chip9346_data_read: - eeprom->eedo = (eeprom->output & 0x8000)?1:0; + eeprom->eedo = (eeprom->output & 0x8000) ? 1 : 0; eeprom->output <<= 1; if (eeprom->tick == 16) { #if 1 - // the FreeBSD drivers (rl and re) don't explicitly toggle - // CS between reads (or does setting Cfg9346 to 0 count too?), - // so we need to enter wait-for-command state here - eeprom->mode = Chip9346_enter_command_mode; - eeprom->input = 0; - eeprom->tick = 0; + // the FreeBSD drivers (rl and re) don't explicitly toggle + // CS between reads (or does setting Cfg9346 to 0 count too?), + // so we need to enter wait-for-command state here + eeprom->mode = Chip9346_enter_command_mode; + eeprom->input = 0; + eeprom->tick = 0; - DPRINTF("eeprom: +++ end of read, awaiting next command\n"); + DPRINTF("eeprom: +++ end of read, awaiting next command\n"); #else - // original behaviour - ++eeprom->address; - eeprom->address &= EEPROM_9346_ADDR_MASK; - eeprom->output = eeprom->contents[eeprom->address]; - eeprom->tick = 0; + // original behaviour + ++eeprom->address; + eeprom->address &= EEPROM_9346_ADDR_MASK; + eeprom->output = eeprom->contents[eeprom->address]; + eeprom->tick = 0; - DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output); + DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); #endif } break; @@ -603,12 +601,12 @@ prom9346_shift_clock(EEprom9346 *eeprom) eeprom->input = (eeprom->input << 1) | (bit & 1); if (eeprom->tick == 16) { DPRINTF("eeprom write to address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->input); + eeprom->address, eeprom->input); eeprom->contents[eeprom->address] = eeprom->input; - eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ - eeprom->tick = 0; - eeprom->input = 0; + eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ + eeprom->tick = 0; + eeprom->input = 0; } break; @@ -620,8 +618,8 @@ prom9346_shift_clock(EEprom9346 *eeprom) } DPRINTF("eeprom filled with data=0x%04x\n", eeprom->input); - eeprom->mode = Chip9346_enter_command_mode; - eeprom->tick = 0; + eeprom->mode = Chip9346_enter_command_mode; + eeprom->tick = 0; eeprom->input = 0; } break; @@ -645,23 +643,23 @@ prom9346_get_wire(RTL8139State *s) static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) { - EEprom9346 *eeprom = &s->eeprom; - uint8_t old_eecs = eeprom->eecs; - uint8_t old_eesk = eeprom->eesk; + EEprom9346 *eeprom = &s->eeprom; + uint8_t old_eecs = eeprom->eecs; + uint8_t old_eesk = eeprom->eesk; eeprom->eecs = eecs; eeprom->eesk = eesk; eeprom->eedi = eedi; DPRINTF("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, - eeprom->eesk, eeprom->eedi, eeprom->eedo); + eeprom->eesk, eeprom->eedi, eeprom->eedo); if (!old_eecs && eecs) { /* Synchronize start */ - eeprom->tick = 0; - eeprom->input = 0; + eeprom->tick = 0; + eeprom->input = 0; eeprom->output = 0; - eeprom->mode = Chip9346_enter_command_mode; + eeprom->mode = Chip9346_enter_command_mode; DPRINTF("=== eeprom: begin access, enter command mode\n"); } @@ -681,11 +679,12 @@ static void rtl8139_update_irq(RTL8139State *s) { uint8_t d = s->pci_slot; - int isr; + int isr; + isr = (s->IntrStatus & s->IntrMask) & 0xffff; DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus, - s->IntrMask); + s->IntrMask); if (isr != 0) pci_set_irq(d, PCI_INTA, &s->irq_state); @@ -736,14 +735,14 @@ rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) if (size > wrapped) { dma_bm_write(s->RxBuf + s->RxBufAddr, - buf, size-wrapped, 1); + buf, size - wrapped, 1); } /* reset buffer pointer */ s->RxBufAddr = 0; dma_bm_write(s->RxBuf + s->RxBufAddr, - buf + (size-wrapped), wrapped, 1); + buf + (size - wrapped), wrapped, 1); s->RxBufAddr = wrapped; @@ -843,21 +842,19 @@ net_crc32_le(const uint8_t *p, int len) return crc; } - #define ETH_ALEN 6 static int rtl8139_do_receive(void *priv, uint8_t *buf, int size_) { - RTL8139State *s = (RTL8139State*) priv; + RTL8139State *s = (RTL8139State *) priv; /* size is the length of the buffer passed to the driver */ - size_t size = size_; + size_t size = size_; const uint8_t *dot1q_buf = NULL; uint32_t packet_header = 0; - uint8_t buf1[60 + VLAN_HLEN]; + uint8_t buf1[60 + VLAN_HLEN]; - static const uint8_t broadcast_macaddr[6] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; DPRINTF(">>> received len=%zu\n", size); @@ -883,10 +880,9 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) DPRINTF(">>> packet received in promiscuous mode\n"); } else { - if (!memcmp(buf, broadcast_macaddr, 6)) { + if (!memcmp(buf, broadcast_macaddr, 6)) { /* broadcast address */ - if (!(s->RxConfig & AcceptBroadcast)) - { + if (!(s->RxConfig & AcceptBroadcast)) { DPRINTF(">>> broadcast packet rejected\n"); /* update tally counter */ @@ -969,8 +965,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) } } - if (rtl8139_cp_receiver_enabled(s)) - { + if (rtl8139_cp_receiver_enabled(s)) { if (!rtl8139_cp_rx_valid(s)) { return size; } @@ -980,27 +975,30 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* begin C+ receiver mode */ /* w0 ownership flag */ -#define CP_RX_OWN (1<<31) +#define CP_RX_OWN (1 << 31) /* w0 end of ring flag */ -#define CP_RX_EOR (1<<30) +#define CP_RX_EOR (1 << 30) /* w0 bits 0...12 : buffer size */ -#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1) +#define CP_RX_BUFFER_SIZE_MASK ((1 << 13) - 1) /* w1 tag available flag */ -#define CP_RX_TAVA (1<<16) +#define CP_RX_TAVA (1 << 16) /* w1 bits 0...15 : VLAN tag */ -#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1) -/* w2 low 32bit of Rx buffer ptr */ -/* w3 high 32bit of Rx buffer ptr */ +#define CP_RX_VLAN_TAG_MASK ((1 << 16) - 1) + /* w2 low 32bit of Rx buffer ptr */ + /* w3 high 32bit of Rx buffer ptr */ - int descriptor = s->currCPlusRxDesc; + int descriptor = s->currCPlusRxDesc; uint32_t cplus_rx_ring_desc; cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); cplus_rx_ring_desc += 16 * descriptor; DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at " - "%08x %08x = ""0x%8X""\n", descriptor, s->RxRingAddrHI, - s->RxRingAddrLO, cplus_rx_ring_desc); + "%08x %08x = " + "0x%8X" + "\n", + descriptor, s->RxRingAddrHI, + s->RxRingAddrLO, cplus_rx_ring_desc); uint32_t val; uint32_t rxdw0; @@ -1008,21 +1006,21 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) uint32_t rxbufLO; uint32_t rxbufHI; - dma_bm_read(cplus_rx_ring_desc, (uint8_t*)&val, 4, 4); + dma_bm_read(cplus_rx_ring_desc, (uint8_t *) &val, 4, 4); rxdw0 = val; - dma_bm_read(cplus_rx_ring_desc+4, (uint8_t*)&val, 4, 4); + dma_bm_read(cplus_rx_ring_desc + 4, (uint8_t *) &val, 4, 4); rxdw1 = val; - dma_bm_read(cplus_rx_ring_desc+8, (uint8_t*)&val, 4, 4); + dma_bm_read(cplus_rx_ring_desc + 8, (uint8_t *) &val, 4, 4); rxbufLO = val; - dma_bm_read(cplus_rx_ring_desc+12, (uint8_t*)&val, 4, 4); + dma_bm_read(cplus_rx_ring_desc + 12, (uint8_t *) &val, 4, 4); rxbufHI = val; DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", - descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI); + descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI); if (!(rxdw0 & CP_RX_OWN)) { DPRINTF("C+ Rx mode : descriptor %d is owned by host\n", - descriptor); + descriptor); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1038,8 +1036,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK; /* write VLAN info to descriptor variables. */ - if (s->CpCmd & CPlusRxVLAN && - bswap16(*((uint16_t*)&buf[ETH_ALEN * 2])) == 0x8100) { + if (s->CpCmd & CPlusRxVLAN && bswap16(*((uint16_t *) &buf[ETH_ALEN * 2])) == 0x8100) { dot1q_buf = &buf[ETH_ALEN * 2]; size -= VLAN_HLEN; /* if too small buffer, use the tailroom added duing expansion */ @@ -1049,10 +1046,11 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) rxdw1 &= ~CP_RX_VLAN_TAG_MASK; /* BE + ~le_to_cpu()~ + cpu_to_le() = BE */ - rxdw1 |= CP_RX_TAVA | *((uint16_t*)(&dot1q_buf[ETHER_TYPE_LEN])); + rxdw1 |= CP_RX_TAVA | *((uint16_t *) (&dot1q_buf[ETHER_TYPE_LEN])); - DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n", - bswap16(*((uint16_t*)&dot1q_buf[ETHER_TYPE_LEN]))); + DPRINTF("C+ Rx mode : extracted vlan tag with tci: " + "%u\n", + bswap16(*((uint16_t *) &dot1q_buf[ETHER_TYPE_LEN]))); } else { /* reset VLAN tag flag */ rxdw1 &= ~CP_RX_TAVA; @@ -1060,9 +1058,9 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* TODO: scatter the packet over available receive ring descriptors space */ - if (size+4 > rx_space) { + if (size + 4 > rx_space) { DPRINTF("C+ Rx mode : descriptor %d size %d received %zu + 4\n", - descriptor, rx_space, size); + descriptor, rx_space, size); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1081,8 +1079,8 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) if (dot1q_buf) { dma_bm_write(rx_addr, buf, 2 * ETH_ALEN, 1); dma_bm_write(rx_addr + 2 * ETH_ALEN, - buf + 2 * ETH_ALEN + VLAN_HLEN, - size - 2 * ETH_ALEN, 1); + buf + 2 * ETH_ALEN + VLAN_HLEN, + size - 2 * ETH_ALEN, 1); } else { dma_bm_write(rx_addr, buf, size, 1); } @@ -1093,28 +1091,28 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* write checksum */ val = (net_crc32_le(buf, size_)); - dma_bm_write(rx_addr+size, (uint8_t *)&val, 4, 4); + dma_bm_write(rx_addr + size, (uint8_t *) &val, 4, 4); /* first segment of received packet flag */ -#define CP_RX_STATUS_FS (1<<29) +#define CP_RX_STATUS_FS (1 << 29) /* last segment of received packet flag */ -#define CP_RX_STATUS_LS (1<<28) +#define CP_RX_STATUS_LS (1 << 28) /* multicast packet flag */ -#define CP_RX_STATUS_MAR (1<<26) +#define CP_RX_STATUS_MAR (1 << 26) /* physical-matching packet flag */ -#define CP_RX_STATUS_PAM (1<<25) +#define CP_RX_STATUS_PAM (1 << 25) /* broadcast packet flag */ -#define CP_RX_STATUS_BAR (1<<24) +#define CP_RX_STATUS_BAR (1 << 24) /* runt packet flag */ -#define CP_RX_STATUS_RUNT (1<<19) +#define CP_RX_STATUS_RUNT (1 << 19) /* crc error flag */ -#define CP_RX_STATUS_CRC (1<<18) +#define CP_RX_STATUS_CRC (1 << 18) /* IP checksum error flag */ -#define CP_RX_STATUS_IPF (1<<15) +#define CP_RX_STATUS_IPF (1 << 15) /* UDP checksum error flag */ -#define CP_RX_STATUS_UDPF (1<<14) +#define CP_RX_STATUS_UDPF (1 << 14) /* TCP checksum error flag */ -#define CP_RX_STATUS_TCPF (1<<13) +#define CP_RX_STATUS_TCPF (1 << 13) /* transfer ownership to target */ rxdw0 &= ~CP_RX_OWN; @@ -1135,13 +1133,13 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* set received size */ rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK; - rxdw0 |= (size+4); + rxdw0 |= (size + 4); /* update ring data */ val = rxdw0; - dma_bm_write(cplus_rx_ring_desc, (uint8_t *)&val, 4, 4); + dma_bm_write(cplus_rx_ring_desc, (uint8_t *) &val, 4, 4); val = rxdw1; - dma_bm_write(cplus_rx_ring_desc+4, (uint8_t *)&val, 4, 4); + dma_bm_write(cplus_rx_ring_desc + 4, (uint8_t *) &val, 4, 4); /* update tally counter */ ++s->tally_counters.RxOk; @@ -1167,8 +1165,8 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) if (avail != 0 && RX_ALIGN(size + 8) >= avail) { DPRINTF("rx overflow: rx buffer length %d head 0x%04x " - "read 0x%04x === available 0x%04x need 0x%04zx\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); + "read 0x%04x === available 0x%04x need 0x%04zx\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1178,18 +1176,18 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) packet_header |= RxStatusOK; - packet_header |= (((size+4) << 16) & 0xffff0000); + packet_header |= (((size + 4) << 16) & 0xffff0000); /* write header */ uint32_t val = packet_header; - rtl8139_write_buffer(s, (uint8_t *)&val, 4); + rtl8139_write_buffer(s, (uint8_t *) &val, 4); rtl8139_write_buffer(s, buf, size); /* write checksum */ val = (net_crc32_le(buf, size)); - rtl8139_write_buffer(s, (uint8_t *)&val, 4); + rtl8139_write_buffer(s, (uint8_t *) &val, 4); /* correct buffer write pointer */ s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize); @@ -1197,7 +1195,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* now we can signal we have received something */ DPRINTF("received: rx buffer length %d head 0x%04x read 0x%04x\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } s->IntrStatus |= RxOK; @@ -1213,14 +1211,14 @@ static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize) { s->RxBufferSize = bufferSize; - s->RxBufPtr = 0; - s->RxBufAddr = 0; + s->RxBufPtr = 0; + s->RxBufAddr = 0; } static void rtl8139_reset_phy(RTL8139State *s) { - s->BasicModeStatus = 0x7809; + s->BasicModeStatus = 0x7809; s->BasicModeStatus |= 0x0020; /* autonegotiation completed */ /* preserve link state */ s->BasicModeStatus |= (net_cards_conf[s->nic->card_num].link_state & NET_LINK_DOWN) ? 0 : 0x04; @@ -1232,15 +1230,14 @@ rtl8139_reset_phy(RTL8139State *s) s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD; } - static void -rtl8139_reset(void* priv) +rtl8139_reset(void *priv) { - RTL8139State *s = (RTL8139State*) priv; + RTL8139State *s = (RTL8139State *) priv; /* reset interrupt mask */ s->IntrStatus = 0; - s->IntrMask = 0; + s->IntrMask = 0; rtl8139_update_irq(s); @@ -1249,7 +1246,7 @@ rtl8139_reset(void* priv) s->TxStatus[i] = TxHostOwns; } - s->currTxDesc = 0; + s->currTxDesc = 0; s->currCPlusRxDesc = 0; s->currCPlusTxDesc = 0; @@ -1279,7 +1276,7 @@ rtl8139_reset(void* priv) s->Config3 = 0x1; /* fast back-to-back compatible */ s->Config5 = 0x0; - s->CpCmd = 0x0; /* reset C+ mode */ + s->CpCmd = 0x0; /* reset C+ mode */ s->cplus_enabled = 0; #if 0 @@ -1291,8 +1288,8 @@ rtl8139_reset(void* priv) rtl8139_reset_phy(s); /* also reset timer and disable timer interrupt */ - s->TCTR = 0; - s->TimerInt = 0; + s->TCTR = 0; + s->TimerInt = 0; s->TCTR_base = 0; #if 0 rtl8139_set_next_tctr_time(s); @@ -1303,20 +1300,20 @@ rtl8139_reset(void* priv) } static void -RTL8139TallyCounters_clear(RTL8139TallyCounters* counters) +RTL8139TallyCounters_clear(RTL8139TallyCounters *counters) { - counters->TxOk = 0; - counters->RxOk = 0; - counters->TxERR = 0; - counters->RxERR = 0; + counters->TxOk = 0; + counters->RxOk = 0; + counters->TxERR = 0; + counters->RxERR = 0; counters->MissPkt = 0; - counters->FAE = 0; - counters->Tx1Col = 0; - counters->TxMCol = 0; + counters->FAE = 0; + counters->Tx1Col = 0; + counters->TxMCol = 0; counters->RxOkPhy = 0; counters->RxOkBrd = 0; counters->RxOkMul = 0; - counters->TxAbt = 0; + counters->TxAbt = 0; counters->TxUndrn = 0; } @@ -1325,7 +1322,7 @@ RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr) { RTL8139TallyCounters *tally_counters = &s->tally_counters; - dma_bm_write(tc_addr, (uint8_t*)tally_counters, sizeof(RTL8139TallyCounters), 1); + dma_bm_write(tc_addr, (uint8_t *) tally_counters, sizeof(RTL8139TallyCounters), 1); } static void @@ -1510,14 +1507,14 @@ rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) /* mask unwritable bits */ val = SET_MASKED(val, 0x31, s->Cfg9346); - uint32_t opmode = val & 0xc0; + uint32_t opmode = val & 0xc0; uint32_t eeprom_val = val & 0xf; if (opmode == 0x80) { /* eeprom access */ - int eecs = (eeprom_val & 0x08)?1:0; - int eesk = (eeprom_val & 0x04)?1:0; - int eedi = (eeprom_val & 0x02)?1:0; + int eecs = (eeprom_val & 0x08) ? 1 : 0; + int eesk = (eeprom_val & 0x04) ? 1 : 0; + int eedi = (eeprom_val & 0x02) ? 1 : 0; prom9346_set_wire(s, eecs, eesk, eedi); } else if (opmode == 0x40) { /* Reset. */ @@ -1539,7 +1536,7 @@ rtl8139_Cfg9346_read(RTL8139State *s) /* eeprom access */ int eedo = prom9346_get_wire(s); if (eedo) { - ret |= 0x01; + ret |= 0x01; } else { ret &= ~0x01; } @@ -1747,23 +1744,22 @@ rtl8139_RxConfig_read(RTL8139State *s) void rtl8139_network_rx_put(netcard_t *card, uint8_t *bufp, int len) { - (void)network_rx_put(card, bufp, len); + (void) network_rx_put(card, bufp, len); } static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, - UNUSED(int do_interrupt), const uint8_t *dot1q_buf) + UNUSED(int do_interrupt), const uint8_t *dot1q_buf) { void (*network_func)(netcard_t *, uint8_t *, int) = (TxLoopBack == (s->TxConfig & TxLoopBack)) ? rtl8139_network_rx_put : network_tx; - if (!size) - { + if (!size) { DPRINTF("+++ empty ethernet frame\n"); return; } if (dot1q_buf && size >= ETH_ALEN * 2) { network_func(s->nic, buf, ETH_ALEN * 2); - network_func(s->nic, (uint8_t*)dot1q_buf, VLAN_HLEN ); + network_func(s->nic, (uint8_t *) dot1q_buf, VLAN_HLEN); network_func(s->nic, buf + ETH_ALEN * 2, size - ETH_ALEN * 2); return; } @@ -1775,25 +1771,27 @@ rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, static int rtl8139_transmit_one(RTL8139State *s, int descriptor) { - int txsize = s->TxStatus[descriptor] & 0x1fff; + int txsize = s->TxStatus[descriptor] & 0x1fff; uint8_t txbuffer[0x2000]; if (!rtl8139_transmitter_enabled(s)) { DPRINTF("+++ cannot transmit from descriptor %d: transmitter " - "disabled\n", descriptor); + "disabled\n", + descriptor); return 0; } if (s->TxStatus[descriptor] & TxHostOwns) { DPRINTF("+++ cannot transmit from descriptor %d: owned by host " - "(%08x)\n", descriptor, s->TxStatus[descriptor]); + "(%08x)\n", + descriptor, s->TxStatus[descriptor]); return 0; } DPRINTF("+++ transmitting from descriptor %d\n", descriptor); DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n", - txsize, s->TxAddr[descriptor]); + txsize, s->TxAddr[descriptor]); dma_bm_read(s->TxAddr[descriptor], txbuffer, txsize, 1); @@ -1804,7 +1802,7 @@ rtl8139_transmit_one(RTL8139State *s, int descriptor) rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL); DPRINTF("+++ transmitted %d bytes from descriptor %d\n", txsize, - descriptor); + descriptor); /* update interrupt */ s->IntrStatus |= TxOK; @@ -1821,17 +1819,17 @@ ones_complement_sum(uint8_t *data, size_t len) { uint32_t result = 0; - for (; len > 1; data+=2, len-=2) { - result += *(uint16_t*)data; + for (; len > 1; data += 2, len -= 2) { + result += *(uint16_t *) data; } /* add the remainder byte */ if (len) { - uint8_t odd[2] = {*data, 0}; - result += *(uint16_t*)odd; + uint8_t odd[2] = { *data, 0 }; + result += *(uint16_t *) odd; } - while (result>>16) + while (result >> 16) result = (result & 0xffff) + (result >> 16); return result; @@ -1840,7 +1838,7 @@ ones_complement_sum(uint8_t *data, size_t len) static uint16_t ip_checksum(void *data, size_t len) { - return ~ones_complement_sum((uint8_t*)data, len); + return ~ones_complement_sum((uint8_t *) data, len); } /* TODO: Replace these with equivalents in 86Box if applicable. */ @@ -1857,15 +1855,15 @@ struct ip_header { }; typedef struct tcp_header { - uint16_t th_sport; /* source port */ - uint16_t th_dport; /* destination port */ - uint32_t th_seq; /* sequence number */ - uint32_t th_ack; /* acknowledgment number */ - uint16_t th_offset_flags; /* data offset, reserved 6 bits, */ - /* TCP protocol flags */ - uint16_t th_win; /* window */ - uint16_t th_sum; /* checksum */ - uint16_t th_urp; /* urgent pointer */ + uint16_t th_sport; /* source port */ + uint16_t th_dport; /* destination port */ + uint32_t th_seq; /* sequence number */ + uint32_t th_ack; /* acknowledgment number */ + uint16_t th_offset_flags; /* data offset, reserved 6 bits, */ + /* TCP protocol flags */ + uint16_t th_win; /* window */ + uint16_t th_sum; /* checksum */ + uint16_t th_urp; /* urgent pointer */ } tcp_header; typedef struct ip_pseudo_header { @@ -1883,24 +1881,23 @@ typedef struct udp_header { uint16_t uh_sum; /* udp checksum */ } udp_header; -#define ETH_HLEN 14 -#define ETH_P_IP (0x0800) -#define IP_PROTO_TCP (6) -#define IP_PROTO_UDP (17) +#define ETH_HLEN 14 +#define ETH_P_IP (0x0800) +#define IP_PROTO_TCP (6) +#define IP_PROTO_UDP (17) #define IP_HEADER_VERSION_4 (4) -#define TH_PUSH 0x08 -#define TH_FIN 0x01 +#define TH_PUSH 0x08 +#define TH_FIN 0x01 -#define IP_HDR_GET_LEN(p) \ - ((*(uint8_t*)((p + __builtin_offsetof(struct ip_header, ip_ver_len))) & 0x0F) << 2) +#define IP_HDR_GET_LEN(p) \ + ((*(uint8_t *) ((p + __builtin_offsetof(struct ip_header, ip_ver_len))) & 0x0F) << 2) -#define IP_HEADER_VERSION(ip) \ +#define IP_HEADER_VERSION(ip) \ (((ip)->ip_ver_len >> 4) & 0xf) #define TCP_HEADER_DATA_OFFSET(tcp) \ (((be16_to_cpu((tcp)->th_offset_flags) >> 12) & 0xf) << 2) - static int rtl8139_cplus_transmit_one(RTL8139State *s) { @@ -1911,7 +1908,7 @@ rtl8139_cplus_transmit_one(RTL8139State *s) if (!rtl8139_cp_transmitter_enabled(s)) { DPRINTF("+++ C+ mode: C+ transmitter disabled\n"); - return 0 ; + return 0; } int descriptor = s->currCPlusTxDesc; @@ -1921,8 +1918,9 @@ rtl8139_cplus_transmit_one(RTL8139State *s) cplus_tx_ring_desc += 16 * descriptor; DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at " - "%08x %08x = 0x%08X\n", descriptor, s->TxAddr[1], - s->TxAddr[0], cplus_tx_ring_desc); + "%08x %08x = 0x%08X\n", + descriptor, s->TxAddr[1], + s->TxAddr[0], cplus_tx_ring_desc); uint32_t val; uint32_t txdw0; @@ -1930,104 +1928,108 @@ rtl8139_cplus_transmit_one(RTL8139State *s) uint32_t txbufLO; uint32_t txbufHI; - dma_bm_read(cplus_tx_ring_desc, (uint8_t *)&val, 4, 4); + dma_bm_read(cplus_tx_ring_desc, (uint8_t *) &val, 4, 4); txdw0 = le32_to_cpu(val); - dma_bm_read(cplus_tx_ring_desc+4, (uint8_t *)&val, 4, 4); + dma_bm_read(cplus_tx_ring_desc + 4, (uint8_t *) &val, 4, 4); txdw1 = le32_to_cpu(val); - dma_bm_read(cplus_tx_ring_desc+8, (uint8_t *)&val, 4, 4); + dma_bm_read(cplus_tx_ring_desc + 8, (uint8_t *) &val, 4, 4); txbufLO = le32_to_cpu(val); - dma_bm_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4, 4); + dma_bm_read(cplus_tx_ring_desc + 12, (uint8_t *) &val, 4, 4); txbufHI = le32_to_cpu(val); DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor, - txdw0, txdw1, txbufLO, txbufHI); + txdw0, txdw1, txbufLO, txbufHI); /* w0 ownership flag */ -#define CP_TX_OWN (1<<31) +#define CP_TX_OWN (1 << 31) /* w0 end of ring flag */ -#define CP_TX_EOR (1<<30) +#define CP_TX_EOR (1 << 30) /* first segment of received packet flag */ -#define CP_TX_FS (1<<29) +#define CP_TX_FS (1 << 29) /* last segment of received packet flag */ -#define CP_TX_LS (1<<28) +#define CP_TX_LS (1 << 28) /* large send packet flag */ -#define CP_TX_LGSEN (1<<27) +#define CP_TX_LGSEN (1 << 27) /* large send MSS mask, bits 16...26 */ #define CP_TC_LGSEN_MSS_SHIFT 16 -#define CP_TC_LGSEN_MSS_MASK ((1 << 11) - 1) +#define CP_TC_LGSEN_MSS_MASK ((1 << 11) - 1) /* IP checksum offload flag */ -#define CP_TX_IPCS (1<<18) +#define CP_TX_IPCS (1 << 18) /* UDP checksum offload flag */ -#define CP_TX_UDPCS (1<<17) +#define CP_TX_UDPCS (1 << 17) /* TCP checksum offload flag */ -#define CP_TX_TCPCS (1<<16) +#define CP_TX_TCPCS (1 << 16) /* w0 bits 0...15 : buffer size */ -#define CP_TX_BUFFER_SIZE (1<<16) +#define CP_TX_BUFFER_SIZE (1 << 16) #define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1) /* w1 add tag flag */ -#define CP_TX_TAGC (1<<17) +#define CP_TX_TAGC (1 << 17) /* w1 bits 0...15 : VLAN tag (big endian) */ -#define CP_TX_VLAN_TAG_MASK ((1<<16) - 1) +#define CP_TX_VLAN_TAG_MASK ((1 << 16) - 1) /* w2 low 32bit of Rx buffer ptr */ /* w3 high 32bit of Rx buffer ptr */ /* set after transmission */ /* FIFO underrun flag */ -#define CP_TX_STATUS_UNF (1<<25) +#define CP_TX_STATUS_UNF (1 << 25) /* transmit error summary flag, valid if set any of three below */ -#define CP_TX_STATUS_TES (1<<23) +#define CP_TX_STATUS_TES (1 << 23) /* out-of-window collision flag */ -#define CP_TX_STATUS_OWC (1<<22) +#define CP_TX_STATUS_OWC (1 << 22) /* link failure flag */ -#define CP_TX_STATUS_LNKF (1<<21) +#define CP_TX_STATUS_LNKF (1 << 21) /* excessive collisions flag */ -#define CP_TX_STATUS_EXC (1<<20) +#define CP_TX_STATUS_EXC (1 << 20) if (!(txdw0 & CP_TX_OWN)) { DPRINTF("C+ Tx mode : descriptor %d is owned by host\n", descriptor); - return 0 ; + return 0; } DPRINTF("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor); if (txdw0 & CP_TX_FS) { DPRINTF("+++ C+ Tx mode : descriptor %d is first segment " - "descriptor\n", descriptor); + "descriptor\n", + descriptor); /* reset internal buffer offset */ s->cplus_txbuffer_offset = 0; } - int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK; + int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK; uint32_t tx_addr = rtl8139_addr64(txbufLO, txbufHI); /* make sure we have enough space to assemble the packet */ if (!s->cplus_txbuffer) { - s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE; - s->cplus_txbuffer = calloc(s->cplus_txbuffer_len, 1); + s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE; + s->cplus_txbuffer = calloc(s->cplus_txbuffer_len, 1); s->cplus_txbuffer_offset = 0; DPRINTF("+++ C+ mode transmission buffer allocated space %d\n", - s->cplus_txbuffer_len); + s->cplus_txbuffer_len); } if (s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) { /* The spec didn't tell the maximum size, stick to CP_TX_BUFFER_SIZE */ txsize = s->cplus_txbuffer_len - s->cplus_txbuffer_offset; DPRINTF("+++ C+ mode transmission buffer overrun, truncated descriptor" - "length to %d\n", txsize); + "length to %d\n", + txsize); } /* append more data to the packet */ DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at " - "%08X"" to offset %d\n", txsize, tx_addr, + "%08X" + " to offset %d\n", + txsize, tx_addr, s->cplus_txbuffer_offset); dma_bm_read(tx_addr, - s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize, 1); + s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize, 1); s->cplus_txbuffer_offset += txsize; /* seek to next Rx descriptor */ @@ -2054,30 +2056,31 @@ rtl8139_cplus_transmit_one(RTL8139State *s) /* update ring data */ val = cpu_to_le32(tx_status); - dma_bm_write(cplus_tx_ring_desc, (uint8_t *)&val, 4, 4); + dma_bm_write(cplus_tx_ring_desc, (uint8_t *) &val, 4, 4); /* Now decide if descriptor being processed is holding the last segment of packet */ if (txdw0 & CP_TX_LS) { - uint8_t dot1q_buffer_space[VLAN_HLEN]; + uint8_t dot1q_buffer_space[VLAN_HLEN]; uint16_t *dot1q_buffer; DPRINTF("+++ C+ Tx mode : descriptor %d is last segment descriptor\n", - descriptor); + descriptor); /* can transfer fully assembled packet */ - uint8_t *saved_buffer = s->cplus_txbuffer; - int saved_size = s->cplus_txbuffer_offset; + uint8_t *saved_buffer = s->cplus_txbuffer; + int saved_size = s->cplus_txbuffer_offset; int saved_buffer_len = s->cplus_txbuffer_len; /* create vlan tag */ if (txdw1 & CP_TX_TAGC) { /* the vlan tag is in BE byte order in the descriptor * BE + le_to_cpu() + ~swap()~ = cpu */ - DPRINTF("+++ C+ Tx mode : inserting vlan tag with ""tci: %u\n", - bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)); + DPRINTF("+++ C+ Tx mode : inserting vlan tag with " + "tci: %u\n", + bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)); - dot1q_buffer = (uint16_t *) dot1q_buffer_space; + dot1q_buffer = (uint16_t *) dot1q_buffer_space; dot1q_buffer[0] = cpu_to_be16(0x8100); /* BE + le_to_cpu() + ~cpu_to_le()~ = BE */ dot1q_buffer[1] = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK); @@ -2086,9 +2089,9 @@ rtl8139_cplus_transmit_one(RTL8139State *s) } /* reset the card space to protect from recursive call */ - s->cplus_txbuffer = NULL; + s->cplus_txbuffer = NULL; s->cplus_txbuffer_offset = 0; - s->cplus_txbuffer_len = 0; + s->cplus_txbuffer_len = 0; if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN)) { DPRINTF("+++ C+ mode offloaded task checksum\n"); @@ -2099,15 +2102,15 @@ rtl8139_cplus_transmit_one(RTL8139State *s) } /* ip packet header */ - struct ip_header *ip = NULL; - int hlen = 0; - uint8_t ip_protocol = 0; - uint16_t ip_data_len = 0; + struct ip_header *ip = NULL; + int hlen = 0; + uint8_t ip_protocol = 0; + uint16_t ip_data_len = 0; uint8_t *eth_payload_data = NULL; size_t eth_payload_len = 0; - int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); + int proto = be16_to_cpu(*(uint16_t *) (saved_buffer + 12)); if (proto != ETH_P_IP) { goto skip_offload; } @@ -2120,14 +2123,15 @@ rtl8139_cplus_transmit_one(RTL8139State *s) * unaligned accesses. */ eth_payload_data = saved_buffer + ETH_HLEN; - eth_payload_len = saved_size - ETH_HLEN; + eth_payload_len = saved_size - ETH_HLEN; - ip = (struct ip_header*)eth_payload_data; + ip = (struct ip_header *) eth_payload_data; if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { DPRINTF("+++ C+ mode packet has bad IP version %d " - "expected %d\n", IP_HEADER_VERSION(ip), - IP_HEADER_VERSION_4); + "expected %d\n", + IP_HEADER_VERSION(ip), + IP_HEADER_VERSION_4); goto skip_offload; } @@ -2150,7 +2154,7 @@ rtl8139_cplus_transmit_one(RTL8139State *s) ip->ip_sum = 0; ip->ip_sum = ip_checksum(ip, hlen); DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", - hlen, ip->ip_sum); + hlen, ip->ip_sum); } if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) { @@ -2159,15 +2163,14 @@ rtl8139_cplus_transmit_one(RTL8139State *s) goto skip_offload; } - int large_send_mss = (txdw0 >> CP_TC_LGSEN_MSS_SHIFT) & - CP_TC_LGSEN_MSS_MASK; + int large_send_mss = (txdw0 >> CP_TC_LGSEN_MSS_SHIFT) & CP_TC_LGSEN_MSS_MASK; if (large_send_mss == 0) { goto skip_offload; } DPRINTF("+++ C+ mode offloaded task TSO IP data %d " - "frame data %d specified MSS=%d\n", - ip_data_len, saved_size - ETH_HLEN, large_send_mss); + "frame data %d specified MSS=%d\n", + ip_data_len, saved_size - ETH_HLEN, large_send_mss); /* maximum IP header length is 60 bytes */ uint8_t saved_ip_header[60]; @@ -2176,13 +2179,13 @@ rtl8139_cplus_transmit_one(RTL8139State *s) memcpy(saved_ip_header, eth_payload_data, hlen); /* a placeholder for checksum calculation routine in tcp case */ - uint8_t *data_to_checksum = eth_payload_data + hlen - 12; + uint8_t *data_to_checksum = eth_payload_data + hlen - 12; #if 0 size_t data_to_checksum_len = eth_payload_len - hlen + 12; #endif /* pointer to TCP header */ - tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); + tcp_header *p_tcp_hdr = (tcp_header *) (eth_payload_data + hlen); int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); @@ -2194,7 +2197,8 @@ rtl8139_cplus_transmit_one(RTL8139State *s) int tcp_data_len = ip_data_len - tcp_hlen; DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " - "data len %d\n", ip_data_len, tcp_hlen, tcp_data_len); + "data len %d\n", + ip_data_len, tcp_hlen, tcp_data_len); /* note the cycle below overwrites IP header data, but restores it from saved_ip_header before sending packet */ @@ -2207,25 +2211,25 @@ rtl8139_cplus_transmit_one(RTL8139State *s) /* check if this is the last frame */ if (tcp_send_offset + large_send_mss >= tcp_data_len) { is_last_frame = 1; - chunk_size = tcp_data_len - tcp_send_offset; + chunk_size = tcp_data_len - tcp_send_offset; } - //DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", - // ldl_be_p(&p_tcp_hdr->th_seq)); + // DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", + // ldl_be_p(&p_tcp_hdr->th_seq)); /* add 4 TCP pseudoheader fields */ /* copy IP source and destination fields */ memcpy(data_to_checksum, saved_ip_header + 12, 8); DPRINTF("+++ C+ mode TSO calculating TCP checksum for " - "packet with %d bytes data\n", tcp_hlen + - chunk_size); + "packet with %d bytes data\n", + tcp_hlen + chunk_size); if (tcp_send_offset) { - memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); + memcpy((uint8_t *) p_tcp_hdr + tcp_hlen, (uint8_t *) p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); } -#define TCP_FLAGS_ONLY(flags) ((flags) & 0x3f) +#define TCP_FLAGS_ONLY(flags) ((flags) &0x3f) #define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off))) /* keep PUSH and FIN flags only for the last frame */ if (!is_last_frame) { @@ -2233,16 +2237,16 @@ rtl8139_cplus_transmit_one(RTL8139State *s) } /* recalculate TCP checksum */ - ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; - p_tcpip_hdr->zeros = 0; - p_tcpip_hdr->ip_proto = IP_PROTO_TCP; - p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); + ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *) data_to_checksum; + p_tcpip_hdr->zeros = 0; + p_tcpip_hdr->ip_proto = IP_PROTO_TCP; + p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); p_tcp_hdr->th_sum = 0; int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", - tcp_checksum); + tcp_checksum); p_tcp_hdr->th_sum = tcp_checksum; @@ -2253,18 +2257,20 @@ rtl8139_cplus_transmit_one(RTL8139State *s) ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size); /* increment IP id for subsequent frames */ - ip->ip_id = cpu_to_be16(tcp_send_offset/large_send_mss + be16_to_cpu(ip->ip_id)); + ip->ip_id = cpu_to_be16(tcp_send_offset / large_send_mss + be16_to_cpu(ip->ip_id)); ip->ip_sum = 0; ip->ip_sum = ip_checksum(eth_payload_data, hlen); DPRINTF("+++ C+ mode TSO IP header len=%d " - "checksum=%04x\n", hlen, ip->ip_sum); + "checksum=%04x\n", + hlen, ip->ip_sum); int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; DPRINTF("+++ C+ mode TSO transferring packet size " - "%d\n", tso_send_size); + "%d\n", + tso_send_size); rtl8139_transfer_frame(s, saved_buffer, tso_send_size, - 0, (uint8_t *) dot1q_buffer); + 0, (uint8_t *) dot1q_buffer); /* add transferred count to TCP sequence number */ #if 0 @@ -2276,14 +2282,14 @@ rtl8139_cplus_transmit_one(RTL8139State *s) /* Stop sending this frame */ saved_size = 0; - } else if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))) { + } else if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & (CP_TX_TCPCS | CP_TX_UDPCS))) { DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); /* maximum IP header length is 60 bytes */ uint8_t saved_ip_header[60]; memcpy(saved_ip_header, eth_payload_data, hlen); - uint8_t *data_to_checksum = eth_payload_data + hlen - 12; + uint8_t *data_to_checksum = eth_payload_data + hlen - 12; #if 0 size_t data_to_checksum_len = eth_payload_len - hlen + 12; #endif @@ -2294,38 +2300,40 @@ rtl8139_cplus_transmit_one(RTL8139State *s) if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) { DPRINTF("+++ C+ mode calculating TCP checksum for " - "packet with %d bytes data\n", ip_data_len); + "packet with %d bytes data\n", + ip_data_len); - ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; - p_tcpip_hdr->zeros = 0; - p_tcpip_hdr->ip_proto = IP_PROTO_TCP; - p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); + ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *) data_to_checksum; + p_tcpip_hdr->zeros = 0; + p_tcpip_hdr->ip_proto = IP_PROTO_TCP; + p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); - tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12); + tcp_header *p_tcp_hdr = (tcp_header *) (data_to_checksum + 12); p_tcp_hdr->th_sum = 0; int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); DPRINTF("+++ C+ mode TCP checksum %04x\n", - tcp_checksum); + tcp_checksum); p_tcp_hdr->th_sum = tcp_checksum; } else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) { DPRINTF("+++ C+ mode calculating UDP checksum for " - "packet with %d bytes data\n", ip_data_len); + "packet with %d bytes data\n", + ip_data_len); - ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; - p_udpip_hdr->zeros = 0; - p_udpip_hdr->ip_proto = IP_PROTO_UDP; - p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); + ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *) data_to_checksum; + p_udpip_hdr->zeros = 0; + p_udpip_hdr->ip_proto = IP_PROTO_UDP; + p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); - udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12); + udp_header *p_udp_hdr = (udp_header *) (data_to_checksum + 12); p_udp_hdr->uh_sum = 0; int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); DPRINTF("+++ C+ mode UDP checksum %04x\n", - udp_checksum); + udp_checksum); p_udp_hdr->uh_sum = udp_checksum; } @@ -2342,7 +2350,7 @@ skip_offload: DPRINTF("+++ C+ mode transmitting %d bytes packet\n", saved_size); rtl8139_transfer_frame(s, saved_buffer, saved_size, 1, - (uint8_t *) dot1q_buffer); + (uint8_t *) dot1q_buffer); /* restore card space if there was no recursion and reset offset */ if (!s->cplus_txbuffer) { @@ -2371,7 +2379,7 @@ rtl8139_cplus_transmit(RTL8139State *s) /* Mark transfer completed */ if (!txcount) { DPRINTF("C+ mode : transmitter queue stalled, current TxDesc = %d\n", - s->currCPlusTxDesc); + s->currCPlusTxDesc); } else { /* update interrupt status */ s->IntrStatus |= TxOK; @@ -2383,7 +2391,7 @@ static void rtl8139_transmit(RTL8139State *s) { int descriptor = s->currTxDesc; - int txcount = 0; + int txcount = 0; /*while*/ if (rtl8139_transmit_one(s, descriptor)) { @@ -2395,21 +2403,21 @@ rtl8139_transmit(RTL8139State *s) /* Mark transfer completed */ if (!txcount) { DPRINTF("transmitter queue stalled, current TxDesc = %d\n", - s->currTxDesc); + s->currTxDesc); } } - static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) { - int descriptor = txRegOffset/4; + int descriptor = txRegOffset / 4; /* handle C+ transmit mode register configuration */ if (s->cplus_enabled) { DPRINTF("RTL8139C+ DTCCR write offset=0x%x val=0x%08x " - "descriptor=%d\n", txRegOffset, val, descriptor); + "descriptor=%d\n", + txRegOffset, val, descriptor); /* handle Dump Tally Counters command */ s->TxStatus[descriptor] = val; @@ -2428,7 +2436,7 @@ rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) } DPRINTF("TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", - txRegOffset, val, descriptor); + txRegOffset, val, descriptor); /* mask only reserved bits */ val &= ~0xff00c000; /* these bits are reset on write */ @@ -2442,16 +2450,17 @@ rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) static uint32_t rtl8139_TxStatus_TxAddr_read(UNUSED(RTL8139State *s), uint32_t regs[], - uint32_t base, uint8_t addr, - int size) + uint32_t base, uint8_t addr, + int size) { - uint32_t reg = (addr - base) / 4; + uint32_t reg = (addr - base) / 4; uint32_t offset = addr & 0x3; - uint32_t ret = 0; + uint32_t ret = 0; if (addr & (size - 1)) { DPRINTF("not implemented read for TxStatus/TxAddr " - "addr=0x%x size=0x%x\n", addr, size); + "addr=0x%x size=0x%x\n", + addr, size); return ret; } @@ -2459,7 +2468,7 @@ rtl8139_TxStatus_TxAddr_read(UNUSED(RTL8139State *s), uint32_t regs[], case 1: /* fall through */ case 2: /* fall through */ case 4: - ret = (regs[reg] >> offset * 8) & (((uint64_t)1 << (size * 8)) - 1); + ret = (regs[reg] >> offset * 8) & (((uint64_t) 1 << (size * 8)) - 1); DPRINTF("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n", reg, addr, size, ret); break; @@ -2479,26 +2488,25 @@ rtl8139_TSAD_read(RTL8139State *s) /* Simulate TSAD, it is read only anyway */ - ret = ((s->TxStatus[3] & TxStatOK )?TSAD_TOK3:0) - |((s->TxStatus[2] & TxStatOK )?TSAD_TOK2:0) - |((s->TxStatus[1] & TxStatOK )?TSAD_TOK1:0) - |((s->TxStatus[0] & TxStatOK )?TSAD_TOK0:0) + ret = ((s->TxStatus[3] & TxStatOK) ? TSAD_TOK3 : 0) + | ((s->TxStatus[2] & TxStatOK) ? TSAD_TOK2 : 0) + | ((s->TxStatus[1] & TxStatOK) ? TSAD_TOK1 : 0) + | ((s->TxStatus[0] & TxStatOK) ? TSAD_TOK0 : 0) - |((s->TxStatus[3] & TxUnderrun)?TSAD_TUN3:0) - |((s->TxStatus[2] & TxUnderrun)?TSAD_TUN2:0) - |((s->TxStatus[1] & TxUnderrun)?TSAD_TUN1:0) - |((s->TxStatus[0] & TxUnderrun)?TSAD_TUN0:0) + | ((s->TxStatus[3] & TxUnderrun) ? TSAD_TUN3 : 0) + | ((s->TxStatus[2] & TxUnderrun) ? TSAD_TUN2 : 0) + | ((s->TxStatus[1] & TxUnderrun) ? TSAD_TUN1 : 0) + | ((s->TxStatus[0] & TxUnderrun) ? TSAD_TUN0 : 0) - |((s->TxStatus[3] & TxAborted )?TSAD_TABT3:0) - |((s->TxStatus[2] & TxAborted )?TSAD_TABT2:0) - |((s->TxStatus[1] & TxAborted )?TSAD_TABT1:0) - |((s->TxStatus[0] & TxAborted )?TSAD_TABT0:0) - - |((s->TxStatus[3] & TxHostOwns )?TSAD_OWN3:0) - |((s->TxStatus[2] & TxHostOwns )?TSAD_OWN2:0) - |((s->TxStatus[1] & TxHostOwns )?TSAD_OWN1:0) - |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ; + | ((s->TxStatus[3] & TxAborted) ? TSAD_TABT3 : 0) + | ((s->TxStatus[2] & TxAborted) ? TSAD_TABT2 : 0) + | ((s->TxStatus[1] & TxAborted) ? TSAD_TABT1 : 0) + | ((s->TxStatus[0] & TxAborted) ? TSAD_TABT0 : 0) + | ((s->TxStatus[3] & TxHostOwns) ? TSAD_OWN3 : 0) + | ((s->TxStatus[2] & TxHostOwns) ? TSAD_OWN2 : 0) + | ((s->TxStatus[1] & TxHostOwns) ? TSAD_OWN1 : 0) + | ((s->TxStatus[0] & TxHostOwns) ? TSAD_OWN0 : 0); DPRINTF("TSAD read val=0x%04x\n", ret); @@ -2520,13 +2528,13 @@ rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val) { DPRINTF("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val); - s->TxAddr[txAddrOffset/4] = val; + s->TxAddr[txAddrOffset / 4] = val; } static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) { - uint32_t ret = s->TxAddr[txAddrOffset/4]; + uint32_t ret = s->TxAddr[txAddrOffset / 4]; DPRINTF("TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret); @@ -2542,7 +2550,7 @@ rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize); DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } static uint32_t @@ -2598,7 +2606,6 @@ rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) s->IntrMask = val; rtl8139_update_irq(s); - } static uint32_t @@ -2685,16 +2692,16 @@ rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) addr &= 0xFF; switch (addr) { - case MAC0 ... MAC0+4: + case MAC0 ... MAC0 + 4: s->phys[addr - MAC0] = val; break; - case MAC0+5: + case MAC0 + 5: s->phys[addr - MAC0] = val; break; - case MAC0+6 ... MAC0+7: + case MAC0 + 6 ... MAC0 + 7: /* reserved */ break; - case MAR0 ... MAR0+7: + case MAR0 ... MAR0 + 7: s->mult[addr - MAR0] = val; break; case ChipCmd: @@ -2724,7 +2731,7 @@ rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) case MediaStatus: /* ignore */ DPRINTF("not implemented write(b) to MediaStatus val=0x%02x\n", - val); + val); break; case HltClk: @@ -2745,7 +2752,7 @@ rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) DPRINTF("C+ TxPoll write(b) val=0x%02x\n", val); if (val & (1 << 7)) { DPRINTF("C+ TxPoll high priority transmission (not " - "implemented)\n"); + "implemented)\n"); #if 0 //rtl8139_cplus_transmit(s); #endif @@ -2759,7 +2766,7 @@ rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) default: DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr, - val); + val); break; } } @@ -2770,8 +2777,7 @@ rtl8139_io_writew(uint32_t addr, uint16_t val, void *priv) RTL8139State *s = priv; addr &= 0xFF; - switch (addr) - { + switch (addr) { case IntrMask: rtl8139_IntrMask_write(s, val); break; @@ -2816,7 +2822,7 @@ rtl8139_io_writew(uint32_t addr, uint16_t val, void *priv) default: DPRINTF("ioport write(w) addr=0x%x val=0x%04x via write(b)\n", - addr, val); + addr, val); rtl8139_io_writeb(addr, val & 0xff, priv); rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, priv); @@ -2832,8 +2838,7 @@ rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) RTL8139State *s = priv; addr &= 0xFF; - switch (addr) - { + switch (addr) { case RxMissed: DPRINTF("RxMissed clearing on write\n"); s->RxMissed = 0; @@ -2847,12 +2852,12 @@ rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) rtl8139_RxConfig_write(s, val); break; - case TxStatus0 ... TxStatus0+4*4-1: - rtl8139_TxStatus_write(s, addr-TxStatus0, val); + case TxStatus0 ... TxStatus0 + 4 * 4 - 1: + rtl8139_TxStatus_write(s, addr - TxStatus0, val); break; - case TxAddr0 ... TxAddr0+4*4-1: - rtl8139_TxAddr_write(s, addr-TxAddr0, val); + case TxAddr0 ... TxAddr0 + 4 * 4 - 1: + rtl8139_TxAddr_write(s, addr - TxAddr0, val); break; case RxBuf: @@ -2887,7 +2892,7 @@ rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) default: DPRINTF("ioport write(l) addr=0x%x val=0x%08x via write(b)\n", - addr, val); + addr, val); rtl8139_io_writeb(addr, val & 0xff, priv); rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, priv); rtl8139_io_writeb(addr + 2, (val >> 16) & 0xff, priv); @@ -2896,25 +2901,24 @@ rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) } } - static uint8_t rtl8139_io_readb(uint32_t addr, void *priv) { RTL8139State *s = priv; - uint8_t ret; + uint8_t ret; addr &= 0xFF; switch (addr) { - case MAC0 ... MAC0+5: + case MAC0 ... MAC0 + 5: ret = s->phys[addr - MAC0]; break; - case MAC0+6 ... MAC0+7: + case MAC0 + 6 ... MAC0 + 7: ret = 0; break; - case MAR0 ... MAR0+7: + case MAR0 ... MAR0 + 7: ret = s->mult[addr - MAR0]; break; - case TxStatus0 ... TxStatus0+4*4-1: + case TxStatus0 ... TxStatus0 + 4 * 4 - 1: ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0, addr, 1); break; @@ -2979,11 +2983,11 @@ static uint16_t rtl8139_io_readw(uint32_t addr, void *priv) { RTL8139State *s = priv; - uint16_t ret; + uint16_t ret; addr &= 0xFF; switch (addr) { - case TxAddr0 ... TxAddr0+4*4-1: + case TxAddr0 ... TxAddr0 + 4 * 4 - 1: ret = rtl8139_TxStatus_TxAddr_read(s, s->TxAddr, TxAddr0, addr, 2); break; case IntrMask: @@ -3044,7 +3048,7 @@ rtl8139_io_readw(uint32_t addr, void *priv) default: DPRINTF("ioport read(w) addr=0x%x via read(b)\n", addr); - ret = rtl8139_io_readb(addr, priv); + ret = rtl8139_io_readb(addr, priv); ret |= rtl8139_io_readb(addr + 1, priv) << 8; DPRINTF("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret); @@ -3058,7 +3062,7 @@ static uint32_t rtl8139_io_readl(uint32_t addr, void *priv) { RTL8139State *s = priv; - uint32_t ret; + uint32_t ret; addr &= 0xFF; switch (addr) { @@ -3076,13 +3080,13 @@ rtl8139_io_readl(uint32_t addr, void *priv) ret = rtl8139_RxConfig_read(s); break; - case TxStatus0 ... TxStatus0+4*4-1: + case TxStatus0 ... TxStatus0 + 4 * 4 - 1: ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0, addr, 4); break; - case TxAddr0 ... TxAddr0+4*4-1: - ret = rtl8139_TxAddr_read(s, addr-TxAddr0); + case TxAddr0 ... TxAddr0 + 4 * 4 - 1: + ret = rtl8139_TxAddr_read(s, addr - TxAddr0); break; case RxBuf: @@ -3116,7 +3120,7 @@ rtl8139_io_readl(uint32_t addr, void *priv) default: DPRINTF("ioport read(l) addr=0x%x via read(b)\n", addr); - ret = rtl8139_io_readb(addr, priv); + ret = rtl8139_io_readb(addr, priv); ret |= rtl8139_io_readb(addr + 1, priv) << 8; ret |= rtl8139_io_readb(addr + 2, priv) << 16; ret |= rtl8139_io_readb(addr + 3, priv) << 24; @@ -3165,9 +3169,9 @@ rtl8139_io_writeb_ioport(uint16_t addr, uint8_t val, void *priv) } static int -rtl8139_set_link_status(void* priv, uint32_t link_state) +rtl8139_set_link_status(void *priv, uint32_t link_state) { - RTL8139State *s = (RTL8139State*)priv; + RTL8139State *s = (RTL8139State *) priv; if (link_state & NET_LINK_DOWN) { s->BasicModeStatus &= ~0x04; @@ -3187,15 +3191,14 @@ rtl8139_timer(void *priv) timer_on_auto(&s->timer, 1000000.0 / ((double) cpu_pci_speed)); - if (!s->clock_enabled) - { + if (!s->clock_enabled) { DPRINTF(">>> timer: clock is not running\n"); return; } s->TCTR++; - if (s->TCTR == s->TimerInt && s->TimerInt != 0){ + if (s->TCTR == s->TimerInt && s->TimerInt != 0) { s->IntrStatus |= PCSTimeout; rtl8139_update_irq(s); } @@ -3260,10 +3263,16 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *priv) switch (addr) { case 0x04: mem_mapping_disable(&s->bar_mem); - io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); + io_removehandler((s->pci_conf[0x11] << 8), 256, + rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, + rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, + priv); s->pci_conf[addr & 0xFF] = val; if (val & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); + io_sethandler((s->pci_conf[0x11] << 8), 256, + rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, + rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, + priv); if ((val & PCI_COMMAND_MEM) && s->bar_mem.size) mem_mapping_enable(&s->bar_mem); break; @@ -3278,10 +3287,16 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *priv) break; case 0x10: case 0x11: - io_removehandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); + io_removehandler((s->pci_conf[0x11] << 8), 256, + rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, + rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, + priv); s->pci_conf[addr & 0xFF] = val; if (s->pci_conf[0x4] & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); + io_sethandler((s->pci_conf[0x11] << 8), 256, + rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, + rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, + priv); break; case 0x14: case 0x15: @@ -3300,18 +3315,18 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *priv) static void * nic_init(const device_t *info) { - RTL8139State *s = calloc(1, sizeof(RTL8139State)); - FILE* fp = NULL; - char eeprom_filename[1024] = { 0 }; + RTL8139State *s = calloc(1, sizeof(RTL8139State)); + FILE *fp = NULL; + char eeprom_filename[1024] = { 0 }; + mem_mapping_add(&s->bar_mem, 0, 0, rtl8139_io_readb, rtl8139_io_readw, rtl8139_io_readl, rtl8139_io_writeb, rtl8139_io_writew, rtl8139_io_writel, NULL, MEM_MAPPING_EXTERNAL, s); pci_add_card(PCI_ADD_NETWORK, rtl8139_pci_read, rtl8139_pci_write, s, &s->pci_slot); s->inst = device_get_instance(); - + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); fp = nvr_fopen(eeprom_filename, "rb"); - if (fp) - { + if (fp) { fread(s->eeprom.contents, 2, 64, fp); fclose(fp); fp = NULL; @@ -3329,12 +3344,12 @@ nic_init(const device_t *info) s->eeprom.contents[9] = 0x1413; } - s->nic = network_attach(s, (uint8_t*)&s->eeprom.contents[7], rtl8139_do_receive, rtl8139_set_link_status); + s->nic = network_attach(s, (uint8_t *) &s->eeprom.contents[7], rtl8139_do_receive, rtl8139_set_link_status); timer_add(&s->timer, rtl8139_timer, s, 0); timer_on_auto(&s->timer, 1000000.0 / cpu_pci_speed); - s->cplus_txbuffer = NULL; - s->cplus_txbuffer_len = 0; + s->cplus_txbuffer = NULL; + s->cplus_txbuffer_len = 0; s->cplus_txbuffer_offset = 0; return s; @@ -3343,14 +3358,13 @@ nic_init(const device_t *info) static void nic_close(void *priv) { - const RTL8139State *s = (RTL8139State*) priv; - FILE* fp = NULL; - char eeprom_filename[1024] = { 0 }; + const RTL8139State *s = (RTL8139State *) priv; + FILE *fp = NULL; + char eeprom_filename[1024] = { 0 }; snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); fp = nvr_fopen(eeprom_filename, "wb"); - if (fp) - { + if (fp) { fwrite(s->eeprom.contents, 2, 64, fp); fclose(fp); fp = NULL; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 680f1e939..0f5724608 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -989,7 +989,7 @@ tulip_xmit_list_update(TULIPState *s) static void tulip_csr9_write(TULIPState *s, UNUSED(uint32_t old_val), - uint32_t new_val) + uint32_t new_val) { if (new_val & CSR9_SR) { nmc93cxx_eeprom_write(s->eeprom, @@ -1002,7 +1002,7 @@ tulip_csr9_write(TULIPState *s, UNUSED(uint32_t old_val), static void tulip_reset(void *priv) { - TULIPState *s = (TULIPState *) priv; + TULIPState *s = (TULIPState *) priv; const uint16_t *eeprom_data = nmc93cxx_eeprom_data(s->eeprom); s->csr[0] = 0xfe000000; s->csr[1] = 0xffffffff; @@ -1526,10 +1526,16 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) switch (addr) { case 0x4: mem_mapping_disable(&s->memory); - io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); + io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, + NULL, NULL, tulip_read_io, + NULL, NULL, tulip_write_io, + priv); s->pci_conf[addr & 0xFF] = val; if (val & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); + io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, + NULL, NULL, tulip_read_io, + NULL, NULL, tulip_write_io, + priv); if ((val & PCI_COMMAND_MEM) && s->memory.size) mem_mapping_enable(&s->memory); break; @@ -1538,10 +1544,16 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x10: case 0x11: - io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); + io_removehandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, + NULL, NULL, tulip_read_io, + NULL, NULL, tulip_write_io, + priv); s->pci_conf[addr & 0xFF] = val; if (s->pci_conf[0x4] & PCI_COMMAND_IO) - io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, NULL, NULL, tulip_read_io, NULL, NULL, tulip_write_io, priv); + io_sethandler((s->pci_conf[0x10] & 0x80) | (s->pci_conf[0x11] << 8), 128, + NULL, NULL, tulip_read_io, + NULL, NULL, tulip_write_io, + priv); break; case 0x14: case 0x15: From f2bebbf7c92436f0e3c7bd6043824a336ba09991 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 6 Aug 2023 19:39:33 -0400 Subject: [PATCH 041/133] Fix typos in win32 makefile --- src/win/Makefile.mingw | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 3b158a0d2..0235ca61d 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -687,9 +687,10 @@ NETOBJ := network.o \ net_pcnet.o net_wd8003.o \ net_plip.o net_event.o \ net_null.o \ - net_eeprom_nmc93cxx.c \ - net_tulip.c \ - net_rtl8139.c + net_eeprom_nmc93cxx.o \ + net_tulip.o \ + net_rtl8139.o \ + net_l80225.o PRINTOBJ := png.o prt_cpmap.o \ prt_escp.o prt_text.o prt_ps.o From edf5c2bb5d23cad2e798df5ecebf4399661fc24d Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Fri, 11 Aug 2023 20:42:01 +0200 Subject: [PATCH 042/133] Add Dell OEM version of Intel Premiere PCI/II (part 1) --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 7e17c270f..a2f824619 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -572,6 +572,7 @@ extern int machine_at_p5sp4_init(const machine_t *); /* m_at_socket5.c */ extern int machine_at_plato_init(const machine_t *); +extern int machine_at_dellplato_init(const machine_t *); extern int machine_at_ambradp90_init(const machine_t *); extern int machine_at_430nx_init(const machine_t *); From cced8a66c96b0c593ad824c2ce7b9dcb75fc64d4 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Fri, 11 Aug 2023 20:44:33 +0200 Subject: [PATCH 043/133] Add Dell OEM Version of Intel Premiere PCI/II (part 2) --- src/machine/m_at_socket5.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 9a45e71bf..acaff764e 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -61,6 +61,25 @@ machine_at_plato_init(const machine_t *model) return ret; } +int +machine_at_dellplato_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/dellplato/1016AX1J.bio", + "roms/machines/dellplato/1016AX1J.bi1", + 0x1d000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_premiere_common_init(model, PCI_CAN_SWITCH_TYPE); + + device_add(&i430nx_device); + + return ret; +} + int machine_at_ambradp90_init(const machine_t *model) { From 3bf6478b71b4f87c6076c02b5ae7938f900fedf5 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Fri, 11 Aug 2023 20:47:01 +0200 Subject: [PATCH 044/133] Add Dell OEM version of Intel Premiere PCI/II (part 3) --- src/machine/machine_table.c | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d16713e6c..f19e7c9ef 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8094,6 +8094,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Same as Intel Premiere PCI/II, but with a Dell OEM BIOS */ + { + .name = "[i430NX] Dell Dimension XPS Pxxx", + .internal_name = "dellplato", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_dellplato_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .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 = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0, + .gpio = 0, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the Phoenix MultiKey KBC firmware. This is basically an Intel Premiere/PCI II with a fancier POST screen. */ { From 7395a3341489f5a15c2ad7eaa42e0d2eabae2456 Mon Sep 17 00:00:00 2001 From: rue <99608219+luennix@users.noreply.github.com> Date: Fri, 18 Aug 2023 20:45:02 +0300 Subject: [PATCH 045/133] Add Micronics Thunderbolt to m_at_socket7.c --- src/machine/m_at_socket7.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 1fee61b88..b665b90e0 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -1085,3 +1085,33 @@ machine_at_ms5164_init(const machine_t *model) return ret; } + +int +machine_at_thunderbolt_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/thunderbolt/tbolt-01.rom", + 0x000c0000, 262144, 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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 1, 2, 3); /* PIIX4 */ + pci_register_slot(0x11, PCI_CARD_NORMAL, 0, 1, 2, 3); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 0, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 0, 1, 2); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c935_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} From 7f21bbf0da3808e8f33ba7855e79e11692bd9897 Mon Sep 17 00:00:00 2001 From: rue <99608219+luennix@users.noreply.github.com> Date: Fri, 18 Aug 2023 20:46:37 +0300 Subject: [PATCH 046/133] Add Micronics Thunderbolt to machine_table.c --- src/machine/machine_table.c | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 899284318..2018015e0 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -10334,6 +10334,45 @@ const machine_t machines[] = { .vid_device = NULL, .snd_device = NULL, .net_device = NULL + }, + /* PhoenixBIOS 4.0 Rel 6.0 for 430TX, most likely has AMI KBC of some sort. Also has onboard Yamaha YMF701 which can't be emulated yet. */ + { + .name = "[i430TX] Micronics Thunderbolt", + .internal_name = "thunderbolt", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_thunderbolt_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0, + .gpio = 0, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL }, /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. */ { From 194101bb980c2fd3320205611c55678782defce5 Mon Sep 17 00:00:00 2001 From: rue <99608219+luennix@users.noreply.github.com> Date: Fri, 18 Aug 2023 20:47:36 +0300 Subject: [PATCH 047/133] Add Micronics Thunderbolt to machine.h --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 1f9ed480f..af44e3744 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -658,6 +658,7 @@ extern int machine_at_tx97_init(const machine_t *); extern int machine_at_an430tx_init(const machine_t *); #endif extern int machine_at_ym430tx_init(const machine_t *); +extern int machine_at_thunderbolt_init(const machine_t *); extern int machine_at_mb540n_init(const machine_t *); extern int machine_at_56a5_init(const machine_t *); extern int machine_at_p5mms98_init(const machine_t *); From a24c97a3505c6fac58a51129ac702e0ab47ae3a1 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Sat, 9 Sep 2023 11:10:05 +0100 Subject: [PATCH 048/133] Add Gateway 2000 Venus (Part 1) --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 5cc83ef1c..8456867bf 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -687,6 +687,7 @@ extern int machine_at_aurora_init(const machine_t *); extern int machine_at_686nx_init(const machine_t *); extern int machine_at_acerv60n_init(const machine_t *); extern int machine_at_vs440fx_init(const machine_t *); +extern int machine_at_GW2KVenus_init(const machine_t *); extern int machine_at_ap440fx_init(const machine_t *); extern int machine_at_mb600n_init(const machine_t *); extern int machine_at_8600ttc_init(const machine_t *); From 6148dbcb7acaf0571bd1dd72fb221cde67e81d62 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Sat, 9 Sep 2023 11:12:31 +0100 Subject: [PATCH 049/133] Add Gateway 2000 Venus (Part 2) --- src/machine/m_at_socket8.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index c8e507335..2ec32802c 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -195,6 +195,40 @@ machine_at_vs440fx_init(const machine_t *model) return ret; } +int +machine_at_GW2KVenus_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined2("roms/machines/GW2KVenus/1011CS1T.BIO", + "roms/machines/GW2KVenus/1011CS1T.BI1", + "roms/machines/GW2KVenus/1011CS1T.BI2", + "roms/machines/GW2KVenus/1011CS1T.BI3", + "roms/machines/GW2KVenus/1011CS1T.RCV", + 0x3a000, 128); + + 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(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i440fx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&pc87307_device); + + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + int machine_at_ap440fx_init(const machine_t *model) { From bbed19ce4cf1ab305ec69eefa4da7297aadf52d9 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Sat, 9 Sep 2023 11:16:53 +0100 Subject: [PATCH 050/133] Add Gateway 2000 Venus (Part 3) --- src/machine/machine_table.c | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5ce4b0795..c7f8ce18d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11300,6 +11300,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* It's a Intel VS440FX with a Gateway 2000 OEM BIOS */ + { + .name = "[i440FX] Gateway 2000 Venus", + .internal_name = "GW2KVenus", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_GW2KVenus_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 3.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0, + .gpio = 0, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { .name = "[i440FX] Micronics M6Mi", From df65ec21036d57ae94cf6f7ec988157f3fed8652 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 21 Sep 2023 20:46:11 +0200 Subject: [PATCH 051/133] Resolve conflict. --- src/include/86box/snd_opl.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index eacd09e2c..0d89589c4 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -38,11 +38,7 @@ typedef struct fm_drv_t { void (*reset_buffer)(void *priv); void (*set_do_cycles)(void *priv, int8_t do_cycles); void *priv; -<<<<<<< HEAD - void (*generate)(void *priv, int32_t *data, uint32_t num_samples); /* daughterboard only. */ -======= void (*generate)(void *priv, int32_t *data, uint32_t num_samples); /* daughterboard only. */ ->>>>>>> 2b4f7733811f8b79197d2b44a0ff7ba2553d68c9 } fm_drv_t; extern uint8_t fm_driver_get(int chip_id, fm_drv_t *drv); From 04fc564903eaadebf6d68c8c28a9da2b4f9d9737 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 8 Oct 2023 14:45:01 -0400 Subject: [PATCH 052/133] Update new machines --- src/machine/machine_table.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8f6c5cdd5..06905de8d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8300,10 +8300,10 @@ const machine_t machines[] = { .type = MACHINE_TYPE_SOCKET5, .chipset = MACHINE_CHIPSET_INTEL_430NX, .init = machine_at_dellplato_init, - .pad = 0, - .pad0 = 0, - .pad1 = MACHINE_AVAILABLE, - .pad2 = 0, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, @@ -10638,10 +10638,10 @@ const machine_t machines[] = { .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430TX, .init = machine_at_thunderbolt_init, - .pad = 0, - .pad0 = 0, - .pad1 = MACHINE_AVAILABLE, - .pad2 = 0, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2), @@ -11666,10 +11666,10 @@ const machine_t machines[] = { .type = MACHINE_TYPE_SOCKET8, .chipset = MACHINE_CHIPSET_INTEL_440FX, .init = machine_at_GW2KVenus_init, - .pad = 0, - .pad0 = 0, - .pad1 = MACHINE_AVAILABLE, - .pad2 = 0, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, .cpu = { .package = CPU_PKG_SOCKET8, .block = CPU_BLOCK_NONE, From 29e1f9e2bb97cf0bba8c9a8f5a146456553a0a3d Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 12 Oct 2023 00:27:24 +0200 Subject: [PATCH 053/133] Fixed src/unix/assets/86Box.spec. --- src/unix/assets/86Box.spec | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index 65f545dc1..d70d31ad9 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -121,9 +121,5 @@ popd %{_datadir}/%{name}/roms %changelog -<<<<<<< HEAD -* Sat Aug 26 2023 Robert de Rooy 4.1-1 -======= -* Thu Oct 12 2023 Robert de Rooy 4.0.1-1 ->>>>>>> origin/master +* Thu Oct 12 2023 Robert de Rooy 4.1-1 - Bump release From e441b3a4fc8ef95ae8e72d29ba1c1f7d1e773169 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 12 Oct 2023 00:28:51 +0200 Subject: [PATCH 054/133] ROM version. --- src/unix/assets/86Box.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index ed81acb23..a024e4288 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -12,7 +12,7 @@ # After a successful build, you can install the RPMs as follows: # sudo dnf install RPMS/$(uname -m)/86Box-3* RPMS/noarch/86Box-roms* -%global romver 4.0.1 +%global romver 4.1 Name: 86Box Version: 4.1 From 53bb97ab9a939942ed36abb12012e758bca7321b Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 23 Oct 2023 15:48:18 -0300 Subject: [PATCH 055/133] isapnp: Rework to allow for external access to device registers --- src/device/isapnp.c | 280 ++++++++++++++++--------------------- src/include/86box/isapnp.h | 28 ++-- 2 files changed, 139 insertions(+), 169 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 26301b622..7b9d570bb 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -29,29 +29,21 @@ #include <86box/plat_unused.h> #define CHECK_CURRENT_LD() \ - if (!dev->current_ld) { \ + if (!ld) { \ isapnp_log("ISAPnP: No logical device selected\n"); \ - break; \ + goto vendor_defined; \ } -#define CHECK_CURRENT_CARD() \ - if (1) { \ - card = dev->first_card; \ - while (card) { \ - if (card->enable && (card->state == PNP_STATE_CONFIG)) \ - break; \ - card = card->next; \ - } \ - if (!card) { \ - isapnp_log("ISAPnP: No card in CONFIG state\n"); \ - break; \ - } \ +#define CHECK_CURRENT_CARD() \ + if (!card) { \ + isapnp_log("ISAPnP: No card in CONFIG state\n"); \ + break; \ } -static const uint8_t pnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, - 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, - 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, - 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 }; +const uint8_t isapnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, + 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, + 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, + 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 }; static const device_t isapnp_device; #ifdef ENABLE_ISAPNP_LOG @@ -95,6 +87,7 @@ typedef struct _isapnp_card_ { uint8_t enable; uint8_t state; uint8_t csn; + uint8_t ld; uint8_t id_checksum; uint8_t serial_read; uint8_t serial_read_pair; @@ -265,15 +258,13 @@ isapnp_read_rangecheck(UNUSED(uint16_t addr), void *priv) } static uint8_t -isapnp_read_data(UNUSED(uint16_t addr), void *priv) +isapnp_read_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uint8_t reg) { - isapnp_t *dev = (isapnp_t *) priv; - uint8_t ret = 0xff; - uint8_t bit; - uint8_t next_shift; - isapnp_card_t *card; + uint8_t ret = 0xff; + uint8_t bit; + uint8_t next_shift; - switch (dev->reg) { + switch (reg) { case 0x01: /* Serial Isolation */ card = dev->first_card; while (card) { @@ -342,78 +333,52 @@ isapnp_read_data(UNUSED(uint16_t addr), void *priv) ret = 0x00; CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Query LDN for CSN %02X device %02X\n", dev->current_ld_card->csn, dev->current_ld->number); - ret = dev->current_ld->number; + isapnp_log("ISAPnP: Query LDN for CSN %02X device %02X\n", card->csn, ld->number); + ret = ld->number; break; - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: + case 0x20 ... 0x2f: + case 0x38 ... 0x3f: + case 0xa9 ... 0xff: +vendor_defined: CHECK_CURRENT_CARD(); - isapnp_log("ISAPnP: Read vendor-defined register %02X from CSN %02X\n", dev->reg, card->csn); + isapnp_log("ISAPnP: Read vendor-defined register %02X from CSN %02X device %02X\n", reg, card->csn, ld ? ld->number : -1); if (card->read_vendor_reg) - ret = card->read_vendor_reg(0, dev->reg, card->priv); - break; - - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Read vendor-defined register %02X from CSN %02X device %02X\n", dev->reg, dev->current_ld_card->csn, dev->current_ld->number); - if (dev->current_ld_card->read_vendor_reg) - ret = dev->current_ld_card->read_vendor_reg(dev->current_ld->number, dev->reg, dev->current_ld_card->priv); + ret = card->read_vendor_reg(ld ? ld->number : -1, reg, card->priv); break; default: - if (dev->reg >= 0x30) { + if (reg >= 0x30) { CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Read register %02X from CSN %02X device %02X\n", dev->reg, dev->current_ld_card->csn, dev->current_ld->number); - ret = dev->current_ld->regs[dev->reg]; + isapnp_log("ISAPnP: Read register %02X from CSN %02X device %02X\n", reg, card->csn, ld->number); + ret = ld->regs[reg]; } break; } - isapnp_log("ISAPnP: read_data(%02X) = %02X\n", dev->reg, ret); + isapnp_log("ISAPnP: read_common(%02X) = %02X\n", reg, ret); return ret; } +static uint8_t +isapnp_read_data(UNUSED(uint16_t addr), void *priv) +{ + isapnp_t *dev = (isapnp_t *) priv; + isapnp_card_t *card = dev->first_card; + while (card) { + if (card->enable && (card->state == PNP_STATE_CONFIG)) + break; + card = card->next; + } + + isapnp_log("ISAPnP: read_data() => "); + return isapnp_read_common(dev, card, dev->current_ld, dev->reg); +} + static void isapnp_set_read_data(uint16_t addr, isapnp_t *dev) { @@ -445,7 +410,7 @@ isapnp_write_addr(UNUSED(uint16_t addr), uint8_t val, void *priv) if (card->state == PNP_STATE_WAIT_FOR_KEY) { /* checking only the first card should be fine */ /* Check written value against LFSR key. */ - if (val == pnp_init_key[dev->key_pos]) { + if (val == isapnp_init_key[dev->key_pos]) { dev->key_pos++; if (!dev->key_pos) { isapnp_log("ISAPnP: Key unlocked, putting cards to SLEEP\n"); @@ -462,17 +427,14 @@ isapnp_write_addr(UNUSED(uint16_t addr), uint8_t val, void *priv) } static void -isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) +isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uint8_t reg, uint8_t val) { - isapnp_t *dev = (isapnp_t *) priv; - isapnp_card_t *card; - isapnp_device_t *ld; - uint16_t io_addr; - uint16_t reset_cards = 0; + uint16_t io_addr; + uint16_t reset_cards = 0; - isapnp_log("ISAPnP: write_data(%02X)\n", val); + isapnp_log("ISAPnP: write_common(%02X, %02X)\n", reg, val); - switch (dev->reg) { + switch (reg) { case 0x00: /* Set RD_DATA Port */ isapnp_set_read_data((val << 2) | 3, dev); isapnp_log("ISAPnP: Read data port set to %04X\n", dev->read_data_addr); @@ -526,7 +488,7 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) while (card) { if (card->csn == val) { card->rom_pos = 0; - card->id_checksum = pnp_init_key[0]; + card->id_checksum = isapnp_init_key[0]; if (card->state == PNP_STATE_SLEEP) card->state = (val == 0) ? PNP_STATE_ISOLATION : PNP_STATE_CONFIG; } else { @@ -551,6 +513,7 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) case 0x07: /* Logical Device Number */ CHECK_CURRENT_CARD(); + card->ld = val; ld = card->first_ld; while (ld) { if (ld->number == val) { @@ -570,10 +533,10 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) case 0x30: /* Activate */ CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: %sctivate CSN %02X device %02X\n", (val & 0x01) ? "A" : "Dea", dev->current_ld_card->csn, dev->current_ld->number); + isapnp_log("ISAPnP: %sctivate CSN %02X device %02X\n", (val & 0x01) ? "A" : "Dea", card->csn, ld->number); - dev->current_ld->regs[dev->reg] = val & 0x01; - isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); + ld->regs[reg] = val & 0x01; + isapnp_device_config_changed(card, ld); break; @@ -581,80 +544,39 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) CHECK_CURRENT_LD(); for (uint8_t i = 0; i < 8; i++) { - if (!dev->current_ld->io_len[i]) + if (!ld->io_len[i]) continue; - io_addr = (dev->current_ld->regs[0x60 + (2 * i)] << 8) | dev->current_ld->regs[0x61 + (2 * i)]; - if (dev->current_ld->regs[dev->reg] & 0x02) - io_removehandler(io_addr, dev->current_ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, dev->current_ld); + io_addr = (ld->regs[0x60 + (2 * i)] << 8) | ld->regs[0x61 + (2 * i)]; + if (ld->regs[reg] & 0x02) + io_removehandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld); if (val & 0x02) - io_sethandler(io_addr, dev->current_ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, dev->current_ld); + io_sethandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld); } - dev->current_ld->regs[dev->reg] = val & 0x03; - isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); + ld->regs[reg] = val & 0x03; + isapnp_device_config_changed(card, ld); break; - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: + case 0x20 ... 0x2f: + case 0x38 ... 0x3f: + case 0xa9 ... 0xff: +vendor_defined: CHECK_CURRENT_CARD(); - isapnp_log("ISAPnP: Write %02X to vendor-defined register %02X on CSN %02X\n", val, dev->reg, card->csn); + isapnp_log("ISAPnP: Write %02X to vendor-defined register %02X on CSN %02X device %02X\n", val, reg, card->csn, ld ? ld->number : -1); if (card->write_vendor_reg) - card->write_vendor_reg(0, dev->reg, val, card->priv); - break; - - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Write %02X to vendor-defined register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number); - if (dev->current_ld_card->write_vendor_reg) - dev->current_ld_card->write_vendor_reg(dev->current_ld->number, dev->reg, val, dev->current_ld_card->priv); + card->write_vendor_reg(ld ? ld->number : -1, reg, val, card->priv); break; default: - if (dev->reg >= 0x40) { + if (reg >= 0x40) { CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number); + isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, reg, card->csn, ld->number); - switch (dev->reg) { + switch (reg) { case 0x42: case 0x4a: case 0x52: @@ -664,7 +586,7 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) case 0x94: case 0xa4: /* Read-only memory range length / upper limit bit. */ - val = (val & 0xfe) | (dev->current_ld->regs[dev->reg] & 0x01); + val = (val & 0xfe) | (ld->regs[reg] & 0x01); break; case 0x60: @@ -676,21 +598,21 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) case 0x6c: case 0x6e: /* Discard upper address bits if this I/O range can only decode 10-bit. */ - if (!(dev->current_ld->io_16bit & (1 << ((dev->reg >> 1) & 0x07)))) + if (!(ld->io_16bit & (1 << ((reg >> 1) & 0x07)))) val &= 0x03; break; case 0x71: case 0x73: /* Limit IRQ types to supported ones. */ - if ((val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0c : 0xc0))) /* level, not supported = force edge */ + if ((val & 0x01) && !(ld->irq_types & ((reg == 0x71) ? 0x0c : 0xc0))) /* level, not supported = force edge */ val &= ~0x01; - else if (!(val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x03 : 0x30))) /* edge, not supported = force level */ + else if (!(val & 0x01) && !(ld->irq_types & ((reg == 0x71) ? 0x03 : 0x30))) /* edge, not supported = force level */ val |= 0x01; - if ((val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x05 : 0x50))) /* high, not supported = force low */ + if ((val & 0x02) && !(ld->irq_types & ((reg == 0x71) ? 0x05 : 0x50))) /* high, not supported = force low */ val &= ~0x02; - else if (!(val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0a : 0xa0))) /* low, not supported = force high */ + else if (!(val & 0x02) && !(ld->irq_types & ((reg == 0x71) ? 0x0a : 0xa0))) /* low, not supported = force high */ val |= 0x02; break; @@ -699,13 +621,31 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) break; } - dev->current_ld->regs[dev->reg] = val; - isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); + ld->regs[reg] = val; + isapnp_device_config_changed(card, ld); } break; } } +static void +isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) +{ + isapnp_t *dev = (isapnp_t *) priv; + isapnp_card_t *card = NULL; + if (!card) { + card = dev->first_card; + while (card) { + if (card->enable && (card->state == PNP_STATE_CONFIG)) + break; + card = card->next; + } + } + + isapnp_log("ISAPnP: write_data(%02X) => ", val); + isapnp_write_common(dev, card, dev->current_ld, dev->reg, val); +} + static void * isapnp_init(UNUSED(const device_t *info)) { @@ -869,7 +809,7 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) } #ifdef ENABLE_ISAPNP_LOG - isapnp_log(" bytes, %swritable, %sread cacheable, %s, %sshadowable, %sexpansion ROM\n", + isapnp_log(" bytes, %swritable, %sread cacheable, %s, %s, %sshadowable, %sexpansion ROM\n", (card->rom[i + 3] & 0x01) ? "not " : "", (card->rom[i + 3] & 0x02) ? "not " : "", (card->rom[i + 3] & 0x04) ? "upper limit" : "range length", @@ -1135,6 +1075,32 @@ isapnp_set_csn(void *priv, uint8_t csn) card->csn_changed(card->csn, card->priv); } +uint8_t +isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg) +{ + isapnp_card_t *card = (isapnp_card_t *) priv; + isapnp_device_t *ld = card->first_ld; + while (ld) { + if (ld->number == ldn) + break; + ld = ld->next; + } + return isapnp_read_common(device_get_priv(&isapnp_device), card, ld, reg); +} + +void +isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val) +{ + isapnp_card_t *card = (isapnp_card_t *) priv; + isapnp_device_t *ld = card->first_ld; + while (ld) { + if (ld->number == ldn) + break; + ld = ld->next; + } + isapnp_write_common(device_get_priv(&isapnp_device), card, ld, reg, val); +} + void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config) { diff --git a/src/include/86box/isapnp.h b/src/include/86box/isapnp.h index 71c1bb29a..5e48b7c18 100644 --- a/src/include/86box/isapnp.h +++ b/src/include/86box/isapnp.h @@ -54,17 +54,21 @@ typedef struct isapnp_device_config_t { } dma[2]; } isapnp_device_config_t; -void *isapnp_add_card(uint8_t *rom, uint16_t rom_size, - void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv), - void (*csn_changed)(uint8_t csn, void *priv), - uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv), - void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv), - void *priv); -void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size); -void isapnp_enable_card(void *priv, uint8_t enable); -void isapnp_set_csn(void *priv, uint8_t csn); -void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config); -void isapnp_reset_card(void *priv); -void isapnp_reset_device(void *priv, uint8_t ld); +extern const uint8_t isapnp_init_key[32]; + +void *isapnp_add_card(uint8_t *rom, uint16_t rom_size, + void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv), + void (*csn_changed)(uint8_t csn, void *priv), + uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv), + void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv), + void *priv); +void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size); +void isapnp_enable_card(void *priv, uint8_t enable); +void isapnp_set_csn(void *priv, uint8_t csn); +uint8_t isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg); +void isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val); +void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config); +void isapnp_reset_card(void *priv); +void isapnp_reset_device(void *priv, uint8_t ld); #endif /*EMU_ISAPNP_H*/ From 3d65f69949d2063b49d6469d0f34797ca3dda1a2 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 23 Oct 2023 15:50:19 -0300 Subject: [PATCH 056/133] Rewrite IT8661F and add IT8671F --- src/include/86box/sio.h | 1 + src/sio/CMakeLists.txt | 2 +- src/sio/sio_it8661f.c | 353 ---------------- src/sio/sio_it86x1f.c | 862 ++++++++++++++++++++++++++++++++++++++++ src/win/Makefile.mingw | 2 +- 5 files changed, 865 insertions(+), 355 deletions(-) delete mode 100644 src/sio/sio_it8661f.c create mode 100644 src/sio/sio_it86x1f.c diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 2736a4eb5..b51f466e4 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -42,6 +42,7 @@ extern const device_t fdc37c935_device; extern const device_t fdc37m60x_device; extern const device_t fdc37m60x_370_device; extern const device_t it8661f_device; +extern const device_t it8671f_device; extern const device_t i82091aa_device; extern const device_t i82091aa_398_device; extern const device_t i82091aa_ide_pri_device; diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 15411d3e6..3140a7181 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -15,7 +15,7 @@ add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c sio_fdc37c6xx.c sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c - sio_it8661f.c + sio_it86x1f.c sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87310.c sio_pc87311.c sio_pc87332.c sio_prime3b.c sio_prime3c.c sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c diff --git a/src/sio/sio_it8661f.c b/src/sio/sio_it8661f.c deleted file mode 100644 index 5367ffedf..000000000 --- a/src/sio/sio_it8661f.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * 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. - * - * Implementation of the ITE IT8661F chipset. - * - * Note: This Super I/O is partially incomplete and intended only for having the intended machine to function - * - * Authors: Tiseno100 - * - * Copyright 2021 Tiseno100 - * - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/lpt.h> -#include <86box/serial.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/fdd_common.h> -#include <86box/sio.h> -#include <86box/plat_unused.h> - -#define LDN dev->regs[7] - -typedef struct it8661f_t { - fdc_t *fdc_controller; - serial_t *uart[2]; - - uint8_t index; - uint8_t regs[256]; - uint8_t device_regs[6][256]; - int unlocked; - int enumerator; -} it8661f_t; - -static uint8_t mb_pnp_key[32] = { 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 }; - -static void it8661f_reset(void *priv); - -#ifdef ENABLE_IT8661_LOG -int it8661_do_log = ENABLE_IT8661_LOG; - -void -it8661_log(const char *fmt, ...) -{ - va_list ap; - - if (it8661_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define it8661_log(fmt, ...) -#endif - -static void -it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev) -{ - fdc_remove(dev->fdc_controller); - - if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) { - switch (addr) { - case 0x30: - dev->device_regs[0][addr] = val & 1; - break; - - case 0x31: - dev->device_regs[0][addr] = val & 3; - if (val & 1) - dev->device_regs[0][addr] |= 0x55; - break; - - case 0x60: - case 0x61: - dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); - break; - - case 0x70: - dev->device_regs[0][addr] = val & 0x0f; - break; - - case 0x74: - dev->device_regs[0][addr] = val & 7; - break; - - case 0xf0: - dev->device_regs[0][addr] = val & 0x0f; - break; - - default: - break; - } - - fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61])); - fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f); - fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7); - - if (dev->device_regs[0][0xf0] & 1) - fdc_writeprotect(dev->fdc_controller); - - it8661_log("ITE 8661-FDC: BASE %04x IRQ %02x\n", (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]), - dev->device_regs[0][0x70] & 0x0f); - } -} - -static void -it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev) -{ - serial_remove(dev->uart[uart]); - - if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) { - switch (addr) { - case 0x30: - dev->device_regs[1 + uart][addr] = val & 1; - break; - - case 0x60: - case 0x61: - dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); - break; - - case 0x70: - dev->device_regs[1 + uart][addr] = val & 0x0f; - break; - - case 0x74: - dev->device_regs[1 + uart][addr] = val & 7; - break; - - case 0xf0: - dev->device_regs[1 + uart][addr] = val & 3; - break; - - default: - break; - } - - serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f); - - it8661_log("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1), - (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), - dev->device_regs[1 + uart][0x70] & 0x0f); - } -} - -void -it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev) -{ - lpt1_remove(); - - if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) { - switch (addr) { - case 0x30: - dev->device_regs[3][addr] = val & 1; - break; - - case 0x60: - case 0x61: - dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); - break; - - case 0x70: - dev->device_regs[3][addr] = val & 0x0f; - break; - - case 0x74: - dev->device_regs[3][addr] = val & 7; - break; - - case 0xf0: - dev->device_regs[3][addr] = val & 3; - break; - - default: - break; - } - - lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61])); - lpt1_irq(dev->device_regs[3][0x70] & 0x0f); - - it8661_log("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]), - dev->device_regs[3][0x70] & 0x0f); - } -} - -void -it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev) -{ - switch (LDN) { - case 0: - it8661_fdc(addr, val, dev); - break; - case 1: - case 2: - it8661_serial((LDN & 2) - 1, addr, val, dev); - break; - case 3: - it8661_lpt(addr, val, dev); - break; - - default: - break; - } -} - -static void -it8661f_write(uint16_t addr, uint8_t val, void *priv) -{ - it8661f_t *dev = (it8661f_t *) priv; - - switch (addr) { - case FDC_SECONDARY_ADDR: - if (!dev->unlocked) { - (val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0); - if (dev->enumerator == 31) { - dev->unlocked = 1; - it8661_log("ITE8661F: Unlocked!\n"); - } - } else - dev->index = val; - break; - - case 0x371: - if (dev->unlocked) { - switch (dev->index) { - case 0x02: - dev->regs[dev->index] = val; - if (val & 1) - it8661f_reset(dev); - if (val & 2) - dev->unlocked = 0; - break; - case 0x07: - dev->regs[dev->index] = val; - break; - case 0x22: - dev->regs[dev->index] = val & 0x30; - break; - case 0x23: - dev->regs[dev->index] = val & 0x1f; - break; - default: - it8661_ldn(dev->index, val, dev); - break; - } - } - break; - - default: - break; - } - - return; -} - -static uint8_t -it8661f_read(uint16_t addr, void *priv) -{ - const it8661f_t *dev = (it8661f_t *) priv; - - it8661_log("IT8661F:\n", addr, dev->regs[dev->index]); - return (addr == 0xa79) ? dev->regs[dev->index] : 0xff; -} - -static void -it8661f_reset(void *priv) -{ - it8661f_t *dev = (it8661f_t *) priv; - dev->regs[0x20] = 0x86; - dev->regs[0x21] = 0x61; - - dev->device_regs[0][0x60] = 3; - dev->device_regs[0][0x61] = 0xf0; - dev->device_regs[0][0x70] = 6; - dev->device_regs[0][0x71] = 2; - dev->device_regs[0][0x74] = 2; - - dev->device_regs[1][0x60] = 3; - dev->device_regs[1][0x61] = 0xf8; - dev->device_regs[1][0x70] = 4; - dev->device_regs[1][0x71] = 2; - - dev->device_regs[2][0x60] = 2; - dev->device_regs[2][0x61] = 0xf8; - dev->device_regs[2][0x70] = 3; - dev->device_regs[2][0x71] = 2; - - dev->device_regs[3][0x60] = 3; - dev->device_regs[3][0x61] = 0x78; - dev->device_regs[3][0x70] = 7; - dev->device_regs[3][0x71] = 2; - dev->device_regs[3][0x74] = 3; - dev->device_regs[3][0xf0] = 3; -} - -static void -it8661f_close(void *priv) -{ - it8661f_t *dev = (it8661f_t *) priv; - - free(dev); -} - -static void * -it8661f_init(UNUSED(const device_t *info)) -{ - it8661f_t *dev = (it8661f_t *) malloc(sizeof(it8661f_t)); - memset(dev, 0, sizeof(it8661f_t)); - - dev->fdc_controller = device_add(&fdc_at_smc_device); - fdc_reset(dev->fdc_controller); - - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); - - io_sethandler(FDC_SECONDARY_ADDR, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev); - - dev->enumerator = 0; - dev->unlocked = 0; - - it8661f_reset(dev); - return dev; -} - -const device_t it8661f_device = { - .name = "ITE IT8661F", - .internal_name = "it8661f", - .flags = 0, - .local = 0, - .init = it8661f_init, - .close = it8661f_close, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c new file mode 100644 index 000000000..91dcc756b --- /dev/null +++ b/src/sio/sio_it86x1f.c @@ -0,0 +1,862 @@ +/* + * 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. + * + * Emulation of the ITE IT86x1F Super I/O chips. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/pci.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/gameport.h> +#include <86box/sio.h> +#include <86box/isapnp.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> + +enum { + ITE_IT8661F = 0x8661, + ITE_IT8671F = 0x8681 +}; + +#define CHIP_ID *((uint16_t *) &dev->global_regs[0]) + +static void it8671f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); +static void it8661f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); + +static const struct { + uint16_t chip_id; + uint16_t unlock_id; + uint8_t gpio_ldn; + /* Fake ROMs to delegate all the logical device register handling over to the ISAPnP subsystem. + The actual ROMs/IDs used by real chips when those are set to ISAPnP mode remain to be seen. */ + uint8_t *pnp_rom; + + const isapnp_device_config_t *pnp_defaults; + + void (*pnp_config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv); +} it86x1f_models[] = { + { + .chip_id = ITE_IT8661F, + .unlock_id = 0x8661, + .gpio_ldn = 0x05, + .pnp_rom = (uint8_t[]) { + 0x26, 0x85, 0x86, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, /* ITE8661, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + + 0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */ + 0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + + 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ + 0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + + 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ + 0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + + 0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */ + 0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x100-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ + + 0x15, 0x41, 0xd0, 0x05, 0x10, 0x01, /* logical device PNP0510, can participate in boot */ + 0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */ + 0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + }, + .pnp_defaults = (const isapnp_device_config_t[]) { + { + .activate = 0, + .io = { { .base = FDC_PRIMARY_ADDR }, }, + .irq = { { .irq = FDC_PRIMARY_IRQ }, }, + .dma = { { .dma = FDC_PRIMARY_DMA }, } + }, { + .activate = 0, + .io = { { .base = COM1_ADDR }, }, + .irq = { { .irq = COM1_IRQ }, } + }, { + .activate = 0, + .io = { { .base = COM2_ADDR }, }, + .irq = { { .irq = COM2_IRQ }, } + }, { + .activate = 0, + .io = { { .base = LPT1_ADDR }, { .base = 0x778 }, }, + .irq = { { .irq = LPT1_IRQ }, }, + .dma = { { .dma = 3 }, } + }, { + .activate = 0, + .io = { { .base = COM4_ADDR }, { .base = 0x300 }, }, + .irq = { { .irq = 10 }, { .irq = 11 }, }, + .dma = { { .dma = 1 }, { .dma = 0 }, } + }, { + .activate = -1 + } + }, + .pnp_config_changed = it8661f_pnp_config_changed + }, { + .chip_id = ITE_IT8671F, + .unlock_id = 0x8680, + .gpio_ldn = 0x07, + .pnp_rom = (uint8_t[]) { + 0x26, 0x85, 0x86, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, /* ITE8671, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + + 0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */ + 0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + + 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ + 0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + + 0x15, 0x41, 0xd0, 0x05, 0x10, 0x01, /* logical device PNP0510, can participate in boot */ + 0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */ + 0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + + 0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */ + 0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x100-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ + + 0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (dummy to create APC gap in LDNs) */ + + 0x15, 0x41, 0xd0, 0x03, 0x03, 0x01, /* logical device PNP0303, can participate in boot */ + 0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */ + 0x47, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x01, 0x01, /* I/O 0x0-0xFFF, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x01, 0x01, /* I/O 0x0-0xFFF, decodes 16-bit, 1-byte alignment, 1 address */ + + 0x15, 0x41, 0xd0, 0x0f, 0x13, 0x01, /* logical device PNP0F13, can participate in boot */ + 0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + }, + .pnp_defaults = (const isapnp_device_config_t[]) { + { + .activate = 0, + .io = { { .base = FDC_PRIMARY_ADDR }, }, + .irq = { { .irq = FDC_PRIMARY_IRQ }, }, + .dma = { { .dma = FDC_PRIMARY_DMA }, } + }, { + .activate = 0, + .io = { { .base = COM1_ADDR }, }, + .irq = { { .irq = COM1_IRQ }, } + }, { + .activate = 0, + .io = { { .base = COM2_ADDR }, { .base = 0x300 }, }, + .irq = { { .irq = COM2_IRQ }, { .irq = 10 }, }, + .dma = { { .dma = 0 }, { .dma = 1 }, } + }, { + .activate = 0, + .io = { { .base = LPT1_ADDR }, { .base = 0x778 }, }, + .irq = { { .irq = LPT1_IRQ }, }, + .dma = { { .dma = 3 }, } + }, { + .activate = 0 + }, { + .activate = 1, + .io = { { .base = 0x60 }, { .base = 0x64 }, }, + .irq = { { .irq = 1 }, } + }, { + .activate = 0, + .irq = { { .irq = 12 }, } + }, { + .activate = -1 + } + }, + .pnp_config_changed = it8671f_pnp_config_changed + } +}; + +#ifdef ENABLE_IT86X1F_LOG +int it86x1f_do_log = ENABLE_IT86X1F_LOG; + +static void +it86x1f_log(const char *fmt, ...) +{ + va_list ap; + + if (it86x1f_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define it86x1f_log(fmt, ...) +#endif + +typedef struct it86x1f_t { + uint8_t instance; + uint8_t locked; + uint8_t cur_ldn; + uint8_t cur_reg; + void *pnp_card; + uint8_t global_regs[16]; /* [0x20:0x2f] */ + uint8_t ldn_regs[8][16]; /* [0xf0:0xff] */ + uint8_t gpio_regs[36]; /* [0x60:0x7f] then [0xe0:0xe3] */ + uint8_t gpio_ldn; + + uint16_t unlock_id; + uint16_t addr_port; + uint16_t data_port; + uint8_t unlock_val; + uint8_t unlock_pos : 2; + uint8_t key_pos : 5; + + fdc_t *fdc; + serial_t *uart[2]; + void *gameport; +} it86x1f_t; + +static void it86x1f_remap(it86x1f_t *dev, uint16_t addr_port, uint16_t data_port); + +static void +it8661f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + if (ld > 5) { + it86x1f_log("IT86x1F: Unknown logical device %d\n", ld); + return; + } + + it86x1f_t *dev = (it86x1f_t *) priv; + + switch (ld) { + case 0: + fdc_remove(dev->fdc); + + if (config->activate) { + it86x1f_log("IT86x1F: FDC enabled at port %04X IRQ %d DMA %d\n", config->io[0].base, config->irq[0].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma); + + if (config->io[0].base != ISAPNP_IO_DISABLED) + fdc_set_base(dev->fdc, config->io[0].base); + + fdc_set_irq(dev->fdc, config->irq[0].irq); + fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma); + } else { + it86x1f_log("IT86x1F: FDC disabled\n"); + } + + break; + + case 1: + case 2: + serial_remove(dev->uart[ld - 1]); + + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { + it86x1f_log("IT86x1F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq); + serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq); + } else { + it86x1f_log("IT86x1F: UART %d disabled\n", ld - 1); + } + + break; + + case 3: + lpt1_remove(); + + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { + it86x1f_log("IT86x1F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq); + lpt1_init(config->io[0].base); + } else { + it86x1f_log("IT86x1F: LPT disabled\n"); + } + + break; + + case 4: + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { + it86x1f_log("IT86x1F: IR enabled at ports %04X %04X IRQs %d %d DMAs %d %d\n", config->io[0].base, config->io[1].base, config->irq[0].irq, config->irq[1].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma, (config->dma[1].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[1].dma); + } else { + it86x1f_log("IT86x1F: IR disabled\n"); + } + break; + + default: + break; + } +} + +static void +it8671f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + + switch (ld) { + case 2: + it8661f_pnp_config_changed(4, config, dev); /* just for logging, should change if IR UART is implemented */ + fallthrough; + + case 0 ... 1: + case 3: + it8661f_pnp_config_changed(ld, config, dev); + break; + + case 5: + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED) && (config->io[1].base != ISAPNP_IO_DISABLED)) { + it86x1f_log("IT86x1F: KBC enabled at ports %04X %04X IRQ %d\n", config->io[0].base, config->io[1].base, config->irq[0].irq); + } else { + it86x1f_log("IT86x1F: KBC disabled\n"); + } + break; + + case 6: + if (config->activate) { + it86x1f_log("IT86x1F: KBC mouse enabled at IRQ %d\n", config->irq[0].irq); + } else { + it86x1f_log("IT86x1F: KBC mouse disabled\n"); + } + break; + + default: + break; + } +} + +static uint8_t +it86x1f_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + uint8_t ret = 0xff; + + switch (reg) { + case 0x20 ... 0x2f: + ret = dev->global_regs[reg & 0x0f]; + break; + + case 0x60 ... 0x7f: + if (ld != dev->gpio_ldn) + break; + + ret = dev->gpio_regs[reg & 0x1f]; + break; + + case 0xe0 ... 0xe3: + if (ld != dev->gpio_ldn) + break; + + ret = dev->gpio_regs[0x20 | (reg & 0x03)]; + break; + + case 0xf0 ... 0xff: + if (ld > dev->gpio_ldn) + break; + + ret = dev->ldn_regs[ld][reg & 0x0f]; + break; + + default: + break; + } + + it86x1f_log("IT86x1F: read_vendor_reg(%X, %02X) = %02X\n", ld, reg, ret); + + return ret; +} + +static void +it86x1f_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + + it86x1f_log("IT86x1F: write_vendor_reg(%X, %02X, %02X)\n", ld, reg, val); + + switch (reg) { + case 0x22: + if (CHIP_ID == ITE_IT8661F) { + dev->global_regs[reg & 0x0f] = (val & 0x30) | (dev->global_regs[reg & 0x0f] & ~0x30); + uint8_t mcc = (val & 0x30) >> 4; + if (mcc != dev->instance) { + it86x1f_log("IT86x1F: Instance %d unmapping as ID %d was written\n", dev->instance, mcc); + it86x1f_remap(dev, 0, 0); + } + } + break; + + case 0x23: + val &= (1 << dev->gpio_ldn) - 1; + dev->global_regs[reg & 0x0f] = val; + if (val) + pclog("IT86x1F: Warning: ISAPnP mode enabled.\n"); + break; + + case 0x24: + dev->global_regs[reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x03 : 0x5f); + break; + + case 0x25: + val &= (CHIP_ID == ITE_IT8661F) ? 0x1f : 0xf0; + fallthrough; + + case 0x26: + if (ld == dev->gpio_ldn) + dev->global_regs[reg & 0x0f] = val; + break; + + case 0x2e ... 0x2f: + if ((CHIP_ID == ITE_IT8671F) && (ld == 0xf4)) + dev->global_regs[reg & 0x0f] = val; + break; + + case 0x60 ... 0x7f: + if (ld != dev->gpio_ldn) + break; + + dev->gpio_regs[reg & 0x1f] = val; + break; + + case 0xe0 ... 0xe3: + if (ld != dev->gpio_ldn) + break; + + dev->gpio_regs[0x20 | (reg & 0x0f)] = val; + break; + + case 0xf0 ... 0xff: + /* Translate GPIO LDN to 7 for the switch block. */ + uint8_t effective_ldn; + if (ld == dev->gpio_ldn) + effective_ldn = 7; + else if (ld == 7) + effective_ldn = 8; /* dummy */ + else + effective_ldn = ld; + + switch ((effective_ldn << 8) | reg) { + case 0x0f0: + dev->ldn_regs[ld][reg & 0x0f] = val & 0x0f; + fdc_set_swwp(dev->fdc, !!(val & 0x01)); + fdc_set_swap(dev->fdc, !!(val & 0x04)); + break; + + case 0x1f0: + dev->ldn_regs[ld][reg & 0x0f] = val & 0x03; + break; + + case 0x2f0: + dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x03 : 0xf3); + break; + + case 0x2f1: + if (CHIP_ID == ITE_IT8671F) + dev->ldn_regs[ld][reg & 0x0f] = val & 0xb7; + break; + + case 0x3f0: + dev->ldn_regs[ld][reg & 0x0f] = val & 0x07; + break; + + case 0x4f0: + if (CHIP_ID == ITE_IT8661F) + val &= 0x3f; + dev->ldn_regs[ld][reg & 0x0f] = val; + break; + + case 0x4f1: + if (CHIP_ID == ITE_IT8671F) + dev->ldn_regs[ld][reg & 0x0f] = val & 0x7f; + break; + + case 0x4f2: + case 0x4f6: + if (CHIP_ID == ITE_IT8671F) + dev->ldn_regs[ld][reg & 0x0f] = val; + break; + + case 0x4f7: + if (CHIP_ID == ITE_IT8671F) + dev->ldn_regs[ld][reg & 0x0f] = val & 0x7f; + break; + + case 0x4f8: + if (CHIP_ID == ITE_IT8671F) + dev->ldn_regs[ld][reg & 0x0f] = val & 0x07; + break; + + case 0x5f0: + dev->ldn_regs[ld][reg & 0x0f] = val & 0x1f; + break; + + case 0x6f0: + if (CHIP_ID == ITE_IT8671F) + dev->ldn_regs[ld][reg & 0x0f] = val & 0x03; + break; + + case 0x760: + case 0x762: + case 0x764: + case 0x766: + dev->gpio_regs[reg & 0x1f] = val & 0x0f; + break; + + case 0x772: + if (CHIP_ID != ITE_IT8671F) + break; + fallthrough; + + case 0x761: + case 0x763: + case 0x765: + case 0x767: + case 0x770: + dev->gpio_regs[reg & 0x1f] = val; + + case 0x771: + if (CHIP_ID == ITE_IT8671F) + dev->gpio_regs[reg & 0x1f] = val & 0xde; + break; + + case 0x7e0: + if (CHIP_ID == ITE_IT8671F) + dev->gpio_regs[0x20 | (reg & 0x03)] = val & 0xef; + break; + + case 0x7e1: + if (CHIP_ID == ITE_IT8671F) + dev->gpio_regs[0x20 | (reg & 0x03)] = val & 0x7f; + break; + + case 0x7e3: + if ((CHIP_ID == ITE_IT8671F) && (val & 0x80)) + *((uint16_t *) &dev->gpio_regs[0x22]) = 0x0000; + break; + + case 0x7fb: + if (CHIP_ID == ITE_IT8671F) + val &= 0x7f; + fallthrough; + + case 0x7f0 ... 0x7f5: + dev->ldn_regs[ld][reg & 0x0f] = val; + break; + + case 0x7f6: + dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x3f : 0xcf); + break; + + case 0x7f7: + dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x9f : 0xdf); + break; + + case 0x7f8 ... 0x7fa: + dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x1f : 0x0f); + break; + + case 0x7fc: + if (CHIP_ID == ITE_IT8661F) + dev->ldn_regs[ld][reg & 0x0f] = val; + break; + + case 0x7ff: + if (CHIP_ID == ITE_IT8671F) + dev->ldn_regs[ld][reg & 0x0f] = val & 0x2f; + break; + + default: + break; + } + break; + + default: + break; + } +} + +static void +it86x1f_write_addr(uint16_t port, uint8_t val, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + + it86x1f_log("IT86x1F: write_addr(%04X, %02X)\n", port, val); + + if (dev->locked) { + if (val == isapnp_init_key[dev->key_pos]) { + if (++dev->key_pos == 0) { + it86x1f_log("IT86x1F: Unlocked\n"); + dev->locked = 0; + } + } else { + dev->key_pos = 0; + } + } else { + dev->cur_reg = val; + } +} + +static void +it86x1f_write_data(uint16_t port, uint8_t val, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + + it86x1f_log("IT86x1F: write_data(%04X, %02X)\n", port, val); + + if (dev->locked) + return; + + switch (dev->cur_reg) { + case 0x00 ... 0x01: + case 0x03 ... 0x06: + case 0x31: + case 0x71: + case 0x73: + break; /* ISAPnP-only */ + + case 0x07: + dev->cur_ldn = val; + break; + + case 0x02: + if (val & 0x02) { + it86x1f_log("IT86x1F: Locked => "); + dev->locked = 1; + it86x1f_remap(dev, 0, 0); + } + fallthrough; + + default: + isapnp_write_reg(dev->pnp_card, dev->cur_ldn, dev->cur_reg, val); + break; + } +} + +static uint8_t +it86x1f_read_addr(uint16_t port, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + uint8_t ret = dev->locked ? 0xff : dev->cur_reg; + + it86x1f_log("IT86x1F: read_addr(%04X) = %02X\n", port, ret); + + return ret; +} + +static uint8_t +it86x1f_read_data(uint16_t port, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + uint8_t ret = 0xff; + + switch (dev->cur_reg) { + case 0x00 ... 0x01: + case 0x03 ... 0x06: + case 0x31: + case 0x71: + case 0x73: + break; /* ISAPnP-only */ + + case 0x07: + ret = dev->cur_ldn; + break; + + default: + ret = isapnp_read_reg(dev->pnp_card, dev->cur_ldn, dev->cur_reg); + break; + } + + it86x1f_log("IT86x1F: read_data(%04X) = %02X\n", port, ret); + + return ret; +} + +static void +it86x1f_remap(it86x1f_t *dev, uint16_t addr_port, uint16_t data_port) +{ + if (dev->addr_port) + io_removehandler(dev->addr_port, 1, it86x1f_read_addr, NULL, NULL, it86x1f_write_addr, NULL, NULL, dev); + if (dev->data_port) + io_removehandler(dev->data_port, 1, it86x1f_read_data, NULL, NULL, it86x1f_write_data, NULL, NULL, dev); + + it86x1f_log("IT86x1F: remap(%04X, %04X)\n", addr_port, data_port); + dev->addr_port = addr_port; + dev->data_port = data_port; + + if (dev->addr_port) + io_sethandler(dev->addr_port, 1, it86x1f_read_addr, NULL, NULL, it86x1f_write_addr, NULL, NULL, dev); + if (dev->data_port) + io_sethandler(dev->data_port, 1, it86x1f_read_data, NULL, NULL, it86x1f_write_data, NULL, NULL, dev); +} + +static void +it86x1f_write_unlock(UNUSED(uint16_t port), uint8_t val, void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + + it86x1f_log("IT86x1F: write_unlock(%04X, %02X)\n", port, val); + + if (!dev->locked) + dev->unlock_pos = 0; + + switch (dev->unlock_pos++) { + case 0: + if (val != (dev->unlock_id >> 8)) + dev->unlock_pos = 0; + break; + + case 1: + if (val != (dev->unlock_id & 0xff)) + dev->unlock_pos = 0; + break; + + case 2: + if ((val != 0x55) && (val != 0xaa)) + dev->unlock_pos = 0; + else + dev->unlock_val = val; + break; + + case 3: + switch ((dev->unlock_val << 8) | val) { + case 0x5555: + it86x1f_remap(dev, 0x3f0, 0x3f1); + break; + + case 0x55aa: + it86x1f_remap(dev, 0x3bd, 0x3bf); + break; + + case 0xaa55: + it86x1f_remap(dev, 0x370, 0x371); + break; + + default: + it86x1f_remap(dev, 0, 0); + break; + } + dev->unlock_pos = 0; + break; + } +} + +void +it86x1f_reset(it86x1f_t *dev) +{ + it86x1f_log("IT86x1F: reset()\n"); + + fdc_reset(dev->fdc); + + serial_remove(dev->uart[0]); + + serial_remove(dev->uart[1]); + + lpt1_remove(); + + isapnp_enable_card(dev->pnp_card, ISAPNP_CARD_DISABLE); + + dev->locked = 1; + + isapnp_reset_card(dev->pnp_card); +} + +static void +it86x1f_close(void *priv) +{ + it86x1f_t *dev = (it86x1f_t *) priv; + + it86x1f_log("IT86x1F: close()\n"); + + free(dev); +} + +static void * +it86x1f_init(UNUSED(const device_t *info)) +{ + it86x1f_t *dev = (it86x1f_t *) malloc(sizeof(it86x1f_t)); + memset(dev, 0, sizeof(it86x1f_t)); + + uint8_t i; + for (i = 0; i < (sizeof(it86x1f_models) / sizeof(it86x1f_models[0])); i++) { + if (it86x1f_models[i].chip_id == info->local) + break; + } + if (i >= (sizeof(it86x1f_models) / sizeof(it86x1f_models[0]))) { + fatal("IT86x1F: Unknown type %04X selected\n", info->local); + return NULL; + } + it86x1f_log("IT86x1F: init(%04X)\n", info->local); + + /* Let the resource data parser figure out the ROM size. */ + dev->pnp_card = isapnp_add_card(it86x1f_models[i].pnp_rom, -1, it86x1f_models[i].pnp_config_changed, NULL, it86x1f_pnp_read_vendor_reg, it86x1f_pnp_write_vendor_reg, dev); + for (uint8_t j = 0; it86x1f_models[i].pnp_defaults[j].activate != (uint8_t) -1; j++) + isapnp_set_device_defaults(dev->pnp_card, j, &it86x1f_models[i].pnp_defaults[j]); + + dev->fdc = device_add(&fdc_at_smc_device); + + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + dev->gameport = gameport_add(&gameport_sio_device); + + dev->instance = device_get_instance(); + dev->gpio_ldn = it86x1f_models[i].gpio_ldn; + CHIP_ID = it86x1f_models[i].chip_id; + dev->unlock_id = it86x1f_models[i].unlock_id; + io_sethandler(0x279, 1, NULL, NULL, NULL, it86x1f_write_unlock, NULL, NULL, dev); + + it86x1f_reset(dev); + + return dev; +} + +const device_t it8661f_device = { + .name = "ITE IT8661F Super I/O", + .internal_name = "it8661f", + .flags = 0, + .local = ITE_IT8661F, + .init = it86x1f_init, + .close = it86x1f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t it8671f_device = { + .name = "ITE IT8671F Super I/O", + .internal_name = "it8671f", + .flags = 0, + .local = ITE_IT8671F, + .init = it86x1f_init, + .close = it86x1f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index e22e5c289..eea036f7b 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -633,7 +633,7 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm SIOOBJ := sio_acc3221.o sio_ali5123.o \ sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \ sio_fdc37c67x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ - sio_it8661f.o \ + sio_it86x1f.o \ sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \ sio_prime3b.o sio_prime3c.o \ sio_w83787f.o \ From d505fcd310535c93f32aaf884e31051b8db052a1 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 23 Oct 2023 18:34:34 -0300 Subject: [PATCH 057/133] Add Genesys Logic GL520SM hardware monitor --- src/device/hwm_gl518sm.c | 57 +++++++++++++++++++++++++++++++++++++--- src/include/86box/hwm.h | 2 ++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c index 01f917b32..855c61762 100644 --- a/src/device/hwm_gl518sm.c +++ b/src/device/hwm_gl518sm.c @@ -36,6 +36,8 @@ #define GL518SM_VOLTAGE_TO_REG(v) ((uint8_t) round((v) / 19.0)) #define GL518SM_VDD_TO_REG(v) ((uint8_t) (((v) *4) / 95.0)) +#define GL520SM 0x100 + typedef struct gl518sm_t { uint32_t local; hwm_values_t *values; @@ -128,7 +130,7 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg) switch (reg) { case 0x04: /* temperature */ - ret = (dev->values->temperatures[0] + 119) & 0xff; + ret = (dev->values->temperatures[0] + ((dev->local & GL520SM) ? 130 : 119)) & 0xff; break; case 0x07: /* fan speeds */ @@ -140,6 +142,10 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg) ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[2]); break; + case 0x0e: /* temperature 2 */ + ret = (dev->local & GL520SM) ? ((dev->values->temperatures[1] + 130) & 0xff) : dev->regs[reg]; + break; + case 0x13: /* VIN2 */ ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[1]); break; @@ -217,6 +223,11 @@ gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val) gl518sm_reset(dev); break; + case 0x0e: + if (dev->local & GL520SM) + return 0; + break; + case 0x0f: dev->regs[reg] = val & 0xf8; break; @@ -238,8 +249,14 @@ gl518sm_reset(gl518sm_t *dev) { memset(dev->regs, 0, sizeof(dev->regs)); - dev->regs[0x00] = 0x80; - dev->regs[0x01] = 0x80; /* revision 0x80 can read all voltages */ + if (dev->local & GL520SM) { + dev->regs[0x00] = 0x20; + dev->regs[0x01] = 0x00; + dev->regs[0x03] = 0x04; + } else { + dev->regs[0x00] = 0x80; + dev->regs[0x01] = 0x80; /* revision 0x80 can read all voltages */ + } dev->regs[0x05] = 0xc7; dev->regs[0x06] = 0xc2; dev->regs[0x08] = 0x6464; @@ -279,7 +296,8 @@ gl518sm_init(const device_t *info) }, { /* temperatures */ - 30 /* usually CPU */ + 30, /* usually CPU */ + 30 /* GL520SM only: usually System */ }, { /* voltages */ @@ -327,3 +345,34 @@ const device_t gl518sm_2d_device = { .force_redraw = NULL, .config = NULL }; + +/* GL520SM on SMBus address 2Ch */ +const device_t gl520sm_2c_device = { + .name = "Genesys Logic GL520SM Hardware Monitor", + .internal_name = "gl520sm_2c", + .flags = DEVICE_ISA, + .local = GL520SM | 0x2c, + .init = gl518sm_init, + .close = gl518sm_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + + +/* GL520SM on SMBus address 2Dh */ +const device_t gl520sm_2d_device = { + .name = "Genesys Logic GL520SM Hardware Monitor", + .internal_name = "gl520sm_2d", + .flags = DEVICE_ISA, + .local = GL520SM | 0x2d, + .init = gl518sm_init, + .close = gl518sm_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/hwm.h b/src/include/86box/hwm.h index b1b1d8c25..4ad5e6917 100644 --- a/src/include/86box/hwm.h +++ b/src/include/86box/hwm.h @@ -68,6 +68,8 @@ extern const device_t w83782d_device; extern const device_t gl518sm_2c_device; extern const device_t gl518sm_2d_device; +extern const device_t gl520sm_2c_device; +extern const device_t gl520sm_2d_device; extern const device_t via_vt82c686_hwm_device; From 79eb95981b81c001df8ec107f3916bebaae42524 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 23 Oct 2023 18:41:35 -0300 Subject: [PATCH 058/133] Add PC Chips M773 machine --- src/acpi.c | 5 ++++- src/include/86box/machine.h | 1 + src/machine/m_at_socket370.c | 41 +++++++++++++++++++++++++++++++++-- src/machine/machine_table.c | 42 +++++++++++++++++++++++++++++++++++- 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index fd38bae29..723ffcd9c 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -1619,7 +1619,10 @@ acpi_reset(void *priv) acpi_t *dev = (acpi_t *) priv; memset(&dev->regs, 0x00, sizeof(acpi_regs_t)); - dev->regs.gpireg[0] = 0xff; + /* PC Chips M773: + - Bit 3: 80-conductor cable on unknown IDE channel (active low) + - Bit 1: 80-conductor cable on unknown IDE channel (active low) */ + dev->regs.gpireg[0] = !strcmp(machine_get_internal_name(), "m773") ? 0xf5 : 0xff; dev->regs.gpireg[1] = 0xff; /* A-Trend ATC7020BXII: - Bit 3: 80-conductor cable on secondary IDE channel (active low) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index bc0443011..e3df11190 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -755,6 +755,7 @@ extern int machine_at_s370slm_init(const machine_t *); extern int machine_at_cubx_init(const machine_t *); extern int machine_at_atc7020bxii_init(const machine_t *); +extern int machine_at_m773_init(const machine_t *); extern int machine_at_ambx133_init(const machine_t *); extern int machine_at_awo671r_init(const machine_t *); extern int machine_at_63a1_init(const machine_t *); diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index db6013ae1..4e2284f80 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -173,9 +173,8 @@ machine_at_p6bat_init(const machine_t *model) device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); - if (sound_card_current[0] == SOUND_INTERNAL) { + if (sound_card_current[0] == SOUND_INTERNAL) device_add(&cmi8738_onboard_device); - } return ret; } @@ -248,6 +247,44 @@ machine_at_atc7020bxii_init(const machine_t *model) return ret; } +int +machine_at_m773_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m773/010504s.rom", + 0x000c0000, 262144, 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(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_SOUND, 4, 3, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&slc90e66_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&it8671f_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 256); + device_add(&gl520sm_2d_device); /* fans: CPU, Chassis; temperature: System */ + hwm_values.voltages[0] = 3300; /* Vcore and 3.3V are swapped */ + hwm_values.voltages[2] = hwm_get_vcore(); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&cmi8738_onboard_device); + + return ret; +} + int machine_at_ambx133_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f52df1d07..5d2754722 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -163,7 +163,6 @@ const machine_filter_t machine_chipsets[] = { }; /* Machines to add before machine freeze: - - PCChips M773 (440BX + SMSC with AMI BIOS); - TMC Mycomp PCI54ST; - Zeos Quadtel 486. @@ -13163,6 +13162,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has an ITE IT8671F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { + .name = "[SMSC VictoryBX-66] PC Chips M773", + .internal_name = "m773", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, + .init = machine_at_m773_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &cmi8738_onboard_device, + .net_device = NULL + }, /* VIA Apollo Pro */ /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA From 1891e110c1df5116ed13bbe6c0e93cc2222686ce Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 23 Oct 2023 19:33:24 -0300 Subject: [PATCH 059/133] Genesys Logic hardware monitor fixes --- src/device/hwm_gl518sm.c | 12 ++++++------ src/machine/m_at_socket370.c | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c index 855c61762..6ba1083d9 100644 --- a/src/device/hwm_gl518sm.c +++ b/src/device/hwm_gl518sm.c @@ -31,8 +31,8 @@ #define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) -/* Formulas and factors derived from Linux's gl518sm.c driver. */ -#define GL518SM_RPM_TO_REG(r, d) ((r) ? CLAMP((480000 + (r) * (d) / 2) / (r) * (d), 1, 255) : 0) +/* Formulas and factors derived from Linux's gl518sm.c and gl520sm.c drivers. */ +#define GL518SM_RPM_TO_REG(r, d) ((r) ? (480000 / (CLAMP((r), (480000 >> (d)) / 255, (480000 >> (d))) << (d))) : 0) #define GL518SM_VOLTAGE_TO_REG(v) ((uint8_t) round((v) / 19.0)) #define GL518SM_VDD_TO_REG(v) ((uint8_t) (((v) *4) / 95.0)) @@ -134,8 +134,8 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg) break; case 0x07: /* fan speeds */ - ret = GL518SM_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x0f] >> 6) & 0x3)) << 8; - ret |= GL518SM_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x0f] >> 4) & 0x3)); + ret = GL518SM_RPM_TO_REG(dev->values->fans[0], (dev->regs[0x0f] >> 6) & 0x3) << 8; + ret |= GL518SM_RPM_TO_REG(dev->values->fans[1], (dev->regs[0x0f] >> 4) & 0x3); break; case 0x0d: /* VIN3 */ @@ -256,9 +256,9 @@ gl518sm_reset(gl518sm_t *dev) } else { dev->regs[0x00] = 0x80; dev->regs[0x01] = 0x80; /* revision 0x80 can read all voltages */ + dev->regs[0x05] = 0xc7; + dev->regs[0x06] = 0xc2; } - dev->regs[0x05] = 0xc7; - dev->regs[0x06] = 0xc2; dev->regs[0x08] = 0x6464; dev->regs[0x09] = 0xdac5; dev->regs[0x0a] = 0xdac5; diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 4e2284f80..2b2615422 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -275,8 +275,10 @@ machine_at_m773_init(const machine_t *model) device_add(&it8671f_device); device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x3, 256); - device_add(&gl520sm_2d_device); /* fans: CPU, Chassis; temperature: System */ - hwm_values.voltages[0] = 3300; /* Vcore and 3.3V are swapped */ + device_add(&gl520sm_2d_device); /* fans: CPU, Chassis; temperature: System */ + hwm_values.temperatures[0] += 2; /* System offset */ + hwm_values.temperatures[1] += 2; /* CPU offset */ + hwm_values.voltages[0] = 3300; /* Vcore and 3.3V are swapped */ hwm_values.voltages[2] = hwm_get_vcore(); if (sound_card_current[0] == SOUND_INTERNAL) From 1e156b96b1e7a4903ea089dcb246cf9bbdb49038 Mon Sep 17 00:00:00 2001 From: linear cannon Date: Sun, 12 Feb 2023 14:55:49 -0500 Subject: [PATCH 060/133] add machine Hyundai Super 286C --- src/cpu/cpu_table.c | 1 + src/include/86box/machine.h | 1 + src/machine/m_at_286_386sx.c | 23 +++++++++++++++++++++ src/machine/machine_table.c | 40 ++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 194089f72..6c406f166 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -1946,6 +1946,7 @@ const cpu_legacy_machine_t cpu_legacy_table[] = { { "award286", cputables_286 }, { "gw286ct", cputables_286 }, { "gdc212m", cputables_286 }, + { "super286c", cputables_286 }, { "super286tr", cputables_286 }, { "spc4200p", cputables_286 }, { "spc4216p", cputables_286 }, diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 61f4d0ee9..997f709cd 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -446,6 +446,7 @@ extern int machine_at_quadt386sx_init(const machine_t *); extern int machine_at_award286_init(const machine_t *); extern int machine_at_gdc212m_init(const machine_t *); extern int machine_at_gw286ct_init(const machine_t *); +extern int machine_at_super286c_init(const machine_t *); extern int machine_at_super286tr_init(const machine_t *); extern int machine_at_spc4200p_init(const machine_t *); extern int machine_at_spc4216p_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index c7b1acb0c..9a2f7d8bf 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -348,6 +348,29 @@ machine_at_gw286ct_init(const machine_t *model) return ret; } +int +machine_at_super286c_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/super286c/hyundai_award286.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_init(model); + + device_add(&neat_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&keyboard_at_ami_device); + + return ret; +} + int machine_at_super286tr_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8277a8415..51458fe62 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3239,6 +3239,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* has an Award-branded KBC controller */ + { + .name = "[NEAT] Hyundai Super-286C", + .internal_name = "super286c", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_super286c_init, + .p1_handler = NULL, + .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, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 512, + .max = 1024, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ { .name = "[NEAT] NCR 3302", From 18bd861c556697fdd49cdb17267a08ba0e7497f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=99=E6=B2=99=E5=AE=AE=E7=B4=97=E5=A4=9C?= <117635969+kzmidze@users.noreply.github.com> Date: Thu, 2 Nov 2023 14:06:32 +0800 Subject: [PATCH 061/133] Update languages --- src/qt/languages/zh-CN.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index fe099265b..3d045b74e 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -653,7 +653,7 @@ msgid "ZIP images" msgstr "ZIP 映像" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box 找不到任何可用的 ROM 映像。\n\n请下载ROM 包并将其解压到 \"roms\" 文件夹中。" +msgstr "86Box 找不到任何可用的 ROM 映像。\n\n请下载 ROM 包并将其解压到 \"roms\" 文件夹中。" msgid "(empty)" msgstr "(空)" From 4b9b664571358cde4ac713e03cc91fa90a10ecf2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Nov 2023 05:52:26 +0100 Subject: [PATCH 062/133] ACPI now correctly only does the power on resume event on power on, not software-initiated hard resets, fixes #3794. --- src/acpi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 544145553..0fe25d79f 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -1653,9 +1653,6 @@ acpi_reset(void *priv) dev->regs.gpi_val |= 0x00000004; } - /* Power on always generates a resume event. */ - dev->regs.pmsts |= 0x8100; - acpi_rtc_status = 0; acpi_update_irq(dev); @@ -1762,6 +1759,9 @@ acpi_init(const device_t *info) acpi_reset(dev); + /* Power on always generates a resume event. */ + dev->regs.pmsts |= 0x8100; + acpi_enabled = 1; return dev; } From 2a5a8f74317c1100ef20b542ceea8fd384126ab6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Nov 2023 05:54:30 +0100 Subject: [PATCH 063/133] Assorted IDE fixes and the PCI IDE bus master now also resets ATAPI hard disks. --- src/chipset/intel_piix.c | 2 -- src/disk/hdc_ide.c | 54 +++++++++++++++++------------------ src/disk/hdc_ide_sff8038i.c | 33 +++++++++------------ src/include/86box/hdc_ide.h | 6 ++-- src/include/86box/scsi_disk.h | 2 ++ src/scsi/scsi_disk.c | 3 +- 6 files changed, 48 insertions(+), 52 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index e5b90d861..2094eefcf 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1172,8 +1172,6 @@ piix_read(int func, int addr, void *priv) if ((func <= dev->max_func) || ((func == 1) && (dev->max_func == 0))) { fregs = (uint8_t *) dev->regs[func]; ret = fregs[addr]; - if ((func == 2) && (addr == 0xff)) - ret |= 0xef; piix_log("PIIX function %i read: %02X from %02X\n", func, ret, addr); } diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 2dffeeec3..049ebd259 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -336,7 +336,7 @@ ide_atapi_get_period(uint8_t channel) } static void -ide_irq_update(ide_board_t *dev) +ide_irq_update(ide_board_t *dev, int log) { ide_t *ide; uint8_t set; @@ -344,7 +344,10 @@ ide_irq_update(ide_board_t *dev) if (dev == NULL) return; - ide_log("IDE %i: IRQ update (%i)\n", dev->cur_dev >> 1, dev->irq); +#ifdef ENABLE_IDE_LOG + if (log) + ide_log("IDE %i: IRQ update (%i)\n", dev->cur_dev >> 1, dev->irq); +#endif ide = ide_drives[dev->cur_dev]; set = !(ide_boards[ide->board]->devctl & 2) && ide->irqstat; @@ -356,32 +359,22 @@ ide_irq_update(ide_board_t *dev) } void -ide_irq_raise(ide_t *ide) +ide_irq(ide_t *ide, int set, int log) { if (!ide_boards[ide->board]) return; - ide_log("IDE %i: IRQ raise\n", ide->channel); +#ifdef IDE_MORE_SPECIFIC_LOGS + ide_log("IDE %i: IRQ %s\n", set ? "raise" : "lower"); +#endif - ide->irqstat = 1; - ide->service = 1; + ide->irqstat = set; + + if (set) + ide->service = 1; if (ide->selected) - ide_irq_update(ide_boards[ide->board]); -} - -void -ide_irq_lower(ide_t *ide) -{ - if (!ide_boards[ide->board]) - return; - - ide_log("IDE %i: IRQ lower\n", ide->channel); - - ide->irqstat = 0; - - if (ide->selected) - ide_irq_update(ide_boards[ide->board]); + ide_irq_update(ide_boards[ide->board], log); } /** @@ -1214,7 +1207,9 @@ ide_writew(uint16_t addr, uint16_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv); +#endif addr &= 0x7; @@ -1246,7 +1241,9 @@ ide_writel(uint16_t addr, uint32_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv); +#endif addr &= 0x7; @@ -1361,7 +1358,7 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) old = dev->devctl; dev->devctl = val; if (!(val & 0x02) && (old & 0x02)) - ide_irq_update(ide_boards[ide->board]); + ide_irq_update(ide_boards[ide->board], 1); } static void @@ -1429,7 +1426,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) #ifdef WRITE_PARAM_TO_BOTH_DEVICES ide_other->tf->cylprecomp = val; #endif - return; + break; case 0x2: /* Sector count */ ide->tf->secount = val; @@ -1439,6 +1436,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case 0x3: /* Sector */ ide->sector = val; ide->lba_addr = (ide->lba_addr & 0xfffff00) | val; + ide_other->sector = val; ide_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val; break; @@ -1482,7 +1480,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide_set_board_callback(ide->board, 0.0); reset = 1; } else - ide_irq_update(ide_boards[ide->board]); + ide_irq_update(ide_boards[ide->board], 1); } if (!reset) { @@ -1911,7 +1909,7 @@ ide_readb(uint16_t addr, void *priv) /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is DF (drive fault). */ case 0x7: /* Status */ - ide_irq_lower(ide); + ide_irq(ide, 0, 0); ret = ide_status(ide, ide_drives[ch ^ 1], ch); break; @@ -1969,7 +1967,9 @@ ide_readw(uint16_t addr, void *priv) break; } +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret); +#endif return ret; } @@ -2002,7 +2002,9 @@ ide_readl(uint16_t addr, void *priv) break; } +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret); +#endif return ret; } @@ -2012,9 +2014,7 @@ ide_board_callback(void *priv) ide_board_t *dev = (ide_board_t *) priv; ide_t *ide; -#ifdef ENABLE_IDE_LOG ide_log("ide_board_callback(%i)\n", dev->cur_dev >> 1); -#endif for (uint8_t i = 0; i < 2; i++) { ide = dev->ide[i]; diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 40cca95a9..3f43f80e6 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -27,7 +27,9 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/cdrom.h> +#include <86box/hdd.h> #include <86box/scsi_device.h> +#include <86box/scsi_disk.h> #include <86box/scsi_cdrom.h> #include <86box/dma.h> #include <86box/io.h> @@ -389,7 +391,6 @@ sff_bus_master_set_irq(uint8_t status, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; uint8_t irq = !!(status & 0x04); - int irq_shift = 0; if (!(dev->status & 0x04) || (status & 0x04)) dev->status = (dev->status & ~0x04) | status; @@ -410,16 +411,12 @@ sff_bus_master_set_irq(uint8_t status, void *priv) else pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); break; - case IRQ_MODE_MIRQ_0: - case IRQ_MODE_MIRQ_1: - /* MIRQ 0 or 1. */ - case IRQ_MODE_MIRQ_2: - case IRQ_MODE_MIRQ_3: - /* MIRQ 2 or 3. */ + case IRQ_MODE_MIRQ_0 ... IRQ_MODE_MIRQ_3: + /* MIRQ 0, 1, 2, or 3. */ if (irq) - pci_set_mirq((dev->irq_mode & 3) + irq_shift, 0, &dev->irq_state); + pci_set_mirq(dev->irq_mode & 3, 0, &dev->irq_state); else - pci_clear_mirq((dev->irq_mode & 3) + irq_shift, 0, &dev->irq_state); + pci_clear_mirq(dev->irq_mode & 3, 0, &dev->irq_state); break; /* TODO: Redo this as a MIRQ. */ case IRQ_MODE_PCI_IRQ_LINE: @@ -477,6 +474,10 @@ sff_reset(void *priv) sff_log("SFF8038i: Reset\n"); #endif + for (uint8_t i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_ATAPI) && (hdd[i].ide_channel < 4) && hdd[i].priv) + scsi_disk_reset((scsi_common_t *) hdd[i].priv); + } for (uint8_t i = 0; i < CDROM_NUM; i++) { if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && cdrom[i].priv) scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); @@ -522,21 +523,15 @@ sff_set_irq_mode(sff8038i_t *dev, int irq_mode) default: case IRQ_MODE_LEGACY: /* Legacy IRQ mode. */ - sff_log("[%08X] Setting IRQ mode to legacy IRQ %i\n", dev, 14 + channel); + sff_log("[%08X] Setting IRQ mode to legacy IRQ %i\n", dev, dev->irq_line); break; case IRQ_MODE_PCI_IRQ_PIN: /* Native PCI IRQ mode with interrupt pin. */ sff_log("[%08X] Setting IRQ mode to native PCI INT%c\n", dev, 0x40 + dev->irq_pin); break; - case IRQ_MODE_MIRQ_0: - case IRQ_MODE_MIRQ_1: - /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, irq_mode & 1); - break; - case IRQ_MODE_MIRQ_2: - case IRQ_MODE_MIRQ_3: - /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, (irq_mode & 1) + 1); + case IRQ_MODE_MIRQ_0 ... IRQ_MODE_MIRQ_3: + /* MIRQ 0, 1, 2, or 3. */ + sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, dev->irq_mode & 3); break; case IRQ_MODE_PCI_IRQ_LINE: /* Native PCI IRQ mode with specified interrupt line. */ diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index b1bff13b3..71ed9e448 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -179,8 +179,7 @@ extern int ide_qua_enabled; #ifdef SCSI_DEVICE_H extern ide_t *ide_get_drive(int ch); -extern void ide_irq_raise(ide_t *ide); -extern void ide_irq_lower(ide_t *ide); +extern void ide_irq(ide_t *ide, int set, int log); extern void ide_allocate_buffer(ide_t *dev); extern void ide_atapi_attach(ide_t *dev); #endif @@ -224,6 +223,9 @@ extern uint8_t ide_read_ali_75(void); extern uint8_t ide_read_ali_76(void); /* Legacy #define's. */ +#define ide_irq_raise(ide) ide_irq(ide, 1, 1) +#define ide_irq_lower(ide) ide_irq(ide, 0, 1) + #define ide_set_base(board, port) ide_set_base_addr(board, 0, port) #define ide_set_side(board, port) ide_set_base_addr(board, 1, port) diff --git a/src/include/86box/scsi_disk.h b/src/include/86box/scsi_disk.h index a62bc9e20..eb4dc69a4 100644 --- a/src/include/86box/scsi_disk.h +++ b/src/include/86box/scsi_disk.h @@ -68,6 +68,8 @@ typedef struct scsi_disk_t { extern scsi_disk_t *scsi_disk[HDD_NUM]; +extern void scsi_disk_reset(scsi_common_t *sc); + extern void scsi_disk_hard_reset(void); extern void scsi_disk_close(void); diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index ee0c3fc00..93d29a672 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -128,7 +128,6 @@ static void scsi_disk_command_complete(scsi_disk_t *dev); static void scsi_disk_mode_sense_load(scsi_disk_t *dev); static void scsi_disk_init(scsi_disk_t *dev); -static void scsi_disk_reset(scsi_common_t *sc); #ifdef ENABLE_SCSI_DISK_LOG int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; @@ -787,7 +786,7 @@ scsi_disk_rezero(scsi_disk_t *dev) scsi_disk_seek(dev, 0); } -static void +void scsi_disk_reset(scsi_common_t *sc) { scsi_disk_t *dev = (scsi_disk_t *) sc; From 859e74b30124c8c9d2e5c4ee9852d866a635145f Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 21 Oct 2023 17:24:36 -0400 Subject: [PATCH 064/133] Named-initializers for FPU's --- src/cpu/cpu_table.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 194089f72..b5c223231 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -33,39 +33,39 @@ #include <86box/machine.h> FPU fpus_none[] = { - {"None", "none", FPU_NONE}, - { NULL, NULL, 0 } + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; FPU fpus_8088[] = { - {"None", "none", FPU_NONE}, - { "8087", "8087", FPU_8087}, - { NULL, NULL, 0 } + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "8087", .internal_name = "8087", .type = FPU_8087 }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; FPU fpus_80186[] = { - {"None", "none", FPU_NONE }, - { "8087", "8087", FPU_8087 }, - { "80187", "80187", FPU_80187}, - { NULL, NULL, 0 } + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "8087", .internal_name = "8087", .type = FPU_8087 }, + { .name = "80187", .internal_name = "80187", .type = FPU_80187 }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; FPU fpus_80286[] = { - {"None", "none", FPU_NONE }, - { "287", "287", FPU_287 }, - { "287XL", "287xl", FPU_287XL}, - { NULL, NULL, 0 } + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "287", .internal_name = "287", .type = FPU_287 }, + { .name = "287XL", .internal_name = "287xl", .type = FPU_287XL }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; FPU fpus_80386[] = { - {"None", "none", FPU_NONE}, - { "387", "387", FPU_387 }, - { NULL, NULL, 0 } + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "387", .internal_name = "387", .type = FPU_387 }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; FPU fpus_486sx[] = { - {"None", "none", FPU_NONE }, - { "487SX", "487sx", FPU_487SX}, - { NULL, NULL, 0 } + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "487SX", .internal_name = "487sx", .type = FPU_487SX }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; FPU fpus_internal[] = { - {"Internal", "internal", FPU_INTERNAL}, - { NULL, NULL, 0 } + { .name = "Internal", .internal_name = "internal", .type = FPU_INTERNAL }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; const cpu_family_t cpu_families[] = { From f6e6e2cda99c7a6545fb836bc9cd55c2a58b6058 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 21 Oct 2023 18:50:25 -0400 Subject: [PATCH 065/133] Named-initializers for 8088 CPU's --- src/cpu/cpu_table.c | 186 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 174 insertions(+), 12 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index b5c223231..f12bb254a 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -76,14 +76,128 @@ const cpu_family_t cpu_families[] = { .name = "8088", .internal_name = "8088", .cpus = (const CPU[]) { - {"4.77", CPU_8088, fpus_8088, 4772728, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"7.16", CPU_8088, fpus_8088, 7159092, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8", CPU_8088, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, -// {"9.54", CPU_8088, fpus_8088, 9545456, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"10", CPU_8088, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_8088, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_8088, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", 0} + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, +#if 0 + { + .name = "9.54", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, +#endif + { + .name = "10", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_8088_EUROPC, @@ -91,10 +205,58 @@ const cpu_family_t cpu_families[] = { .name = "8088", .internal_name = "8088_europc", .cpus = (const CPU[]) { - {"4.77", CPU_8088, fpus_8088, 4772728, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"7.16", CPU_8088, fpus_8088, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"9.54", CPU_8088, fpus_8088, 9545456, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", 0} + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_8086, From bc4f006e5904f36b08e3a0a222f3d9ea11388177 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 21 Oct 2023 19:42:14 -0400 Subject: [PATCH 066/133] Named-initializers for 8086 CPU's --- src/cpu/cpu_table.c | 110 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 7 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index f12bb254a..e52697ab7 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -264,13 +264,109 @@ const cpu_family_t cpu_families[] = { .name = "8086", .internal_name = "8086", .cpus = (const CPU[]) { - {"7.16", CPU_8086, fpus_8088, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8", CPU_8086, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"9.54", CPU_8086, fpus_8088, 9545456, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"10", CPU_8086, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_8086, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_8086, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, - {"", 0} + { + .name = "7.16", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_188, From eb3d3804aad790c299d65d857328ba2d87050886 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 21 Oct 2023 20:03:05 -0400 Subject: [PATCH 067/133] Named-initializers for 80188 CPU's --- src/cpu/cpu_table.c | 164 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 154 insertions(+), 10 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index e52697ab7..2128f22eb 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -374,16 +374,160 @@ const cpu_family_t cpu_families[] = { .name = "80188", .internal_name = "80188", .cpus = (const CPU[]) { - {"6", CPU_188, fpus_8088, 6000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"7.16", CPU_188, fpus_8088, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8", CPU_188, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"9.54", CPU_188, fpus_8088, 9545456, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"10", CPU_188, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_188, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_188, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, - {"20", CPU_188, fpus_8088, 20000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, - {"25", CPU_188, fpus_8088, 25000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 3}, - {"", 0} + { + .name = "6", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 6000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_8088, From cf6af5128b9b103d2a7f1a406b0d566c842dad81 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Mon, 23 Oct 2023 15:27:23 -0400 Subject: [PATCH 068/133] Named-initializers for NEC V20 CPU's --- src/cpu/cpu_table.c | 92 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 2128f22eb..6556b9380 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -535,12 +535,92 @@ const cpu_family_t cpu_families[] = { .name = "V20", .internal_name = "necv20", .cpus = (const CPU[]) { - {"4.77", CPU_V20, fpus_8088, 4772728, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"7.16", CPU_V20, fpus_8088, 7159092, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"10", CPU_V20, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_V20, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_V20, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, - {"", 0} + { + .name = "4.77", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_186, From ba44d3cbac01162ab1ef11c2dbdb7ca73258f508 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 3 Nov 2023 21:32:57 -0400 Subject: [PATCH 069/133] Named-initializers for 80186 CPU's --- src/cpu/cpu_table.c | 164 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 154 insertions(+), 10 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 6556b9380..52d8edf5a 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -628,16 +628,160 @@ const cpu_family_t cpu_families[] = { .name = "80186", .internal_name = "80186", .cpus = (const CPU[]) { - {"6", CPU_186, fpus_80186, 6000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"7.16", CPU_186, fpus_80186, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8", CPU_186, fpus_80186, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"9.54", CPU_186, fpus_80186, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"10", CPU_186, fpus_80186, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_186, fpus_80186, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_186, fpus_80186, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, - {"20", CPU_186, fpus_80186, 20000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, - {"25", CPU_186, fpus_80186, 25000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, - {"", 0} + { + .name = "6", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 6000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 7159092, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 8000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 9545456, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 10000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 12000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 16000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 20000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 25000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_8086, From 2c7175bb664400deac23b61177452533d464aa2d Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 3 Nov 2023 21:57:19 -0400 Subject: [PATCH 070/133] Named-initializers for NEC V30 CPU's --- src/cpu/cpu_table.c | 92 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 52d8edf5a..be9656b43 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -789,12 +789,92 @@ const cpu_family_t cpu_families[] = { .name = "V30", .internal_name = "necv30", .cpus = (const CPU[]) { - {"5", CPU_V30, fpus_80186, 5000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8", CPU_V30, fpus_80186, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"10", CPU_V30, fpus_80186, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_V30, fpus_80186, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_V30, fpus_80186, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, - {"", 0} + { + .name = "5", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 5000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_286, From 410e6a834739ea340c7b51d47750479979071c25 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 3 Nov 2023 22:20:14 -0400 Subject: [PATCH 071/133] Named-initializers for 80286 CPU's --- src/cpu/cpu_table.c | 128 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index be9656b43..0b37ce2d6 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -882,14 +882,126 @@ const cpu_family_t cpu_families[] = { .name = "80286", .internal_name = "286", .cpus = (const CPU[]) { - {"6", CPU_286, fpus_80286, 6000000, 1, 5000, 0, 0, 0, 0, 2,2,2,2, 1}, - {"8", CPU_286, fpus_80286, 8000000, 1, 5000, 0, 0, 0, 0, 2,2,2,2, 1}, - {"10", CPU_286, fpus_80286, 10000000, 1, 5000, 0, 0, 0, 0, 2,2,2,2, 1}, - {"12", CPU_286, fpus_80286, 12500000, 1, 5000, 0, 0, 0, 0, 3,3,3,3, 2}, - {"16", CPU_286, fpus_80286, 16000000, 1, 5000, 0, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_286, fpus_80286, 20000000, 1, 5000, 0, 0, 0, 0, 4,4,4,4, 3}, - {"25", CPU_286, fpus_80286, 25000000, 1, 5000, 0, 0, 0, 0, 4,4,4,4, 3}, - {"", 0} + { + .name = "6", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 6000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 12500000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "16", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 3 + }, + { .name = "", 0 } } }, { .package = CPU_PKG_386SX, From 507aa202d47210cf5503d6c3a2393517541f8df8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 3 Nov 2023 22:25:50 -0400 Subject: [PATCH 072/133] Fix compile error in opti499.c --- src/chipset/opti499.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c index acac4d87b..f8b878559 100644 --- a/src/chipset/opti499.c +++ b/src/chipset/opti499.c @@ -33,7 +33,7 @@ #include <86box/chipset.h> typedef struct opti499_t { - uint8_t idx, + uint8_t idx; uint8_t regs[256]; uint8_t scratch[2]; } opti499_t; From 058391e1485346f70d982d8e6cb585162aa8d47e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 4 Nov 2023 03:28:42 +0100 Subject: [PATCH 073/133] More IDE clean-ups and properly implemented task file ownership, fixes OS/2 Warp 3.0 booting from IDE hard disks. --- src/disk/hdc_ide.c | 590 ++++++++++++++++++++---------------- src/include/86box/hdc_ide.h | 35 +-- 2 files changed, 346 insertions(+), 279 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 049ebd259..126a9d583 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -82,23 +82,23 @@ #define WIN_SEEK 0x70 #define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */ #define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */ -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */ -#define WIN_READ_MULTIPLE 0xC4 -#define WIN_WRITE_MULTIPLE 0xC5 -#define WIN_SET_MULTIPLE_MODE 0xC6 -#define WIN_READ_DMA 0xC8 -#define WIN_READ_DMA_ALT 0xC9 -#define WIN_WRITE_DMA 0xCA -#define WIN_WRITE_DMA_ALT 0xCB -#define WIN_STANDBYNOW1 0xE0 -#define WIN_IDLENOW1 0xE1 -#define WIN_SETIDLE1 0xE3 -#define WIN_CHECKPOWERMODE1 0xE5 -#define WIN_SLEEP1 0xE6 -#define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */ -#define WIN_SET_FEATURES 0xEF -#define WIN_READ_NATIVE_MAX 0xF8 +#define WIN_PACKETCMD 0xa0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xa1 /* Identify ATAPI device */ +#define WIN_READ_MULTIPLE 0xc4 +#define WIN_WRITE_MULTIPLE 0xc5 +#define WIN_SET_MULTIPLE_MODE 0xc6 +#define WIN_READ_DMA 0xc8 +#define WIN_READ_DMA_ALT 0xc9 +#define WIN_WRITE_DMA 0xcA +#define WIN_WRITE_DMA_ALT 0xcB +#define WIN_STANDBYNOW1 0xe0 +#define WIN_IDLENOW1 0xe1 +#define WIN_SETIDLE1 0xe3 +#define WIN_CHECKPOWERMODE1 0xe5 +#define WIN_SLEEP1 0xe6 +#define WIN_IDENTIFY 0xeC /* Ask drive to identify itself */ +#define WIN_SET_FEATURES 0xeF +#define WIN_READ_NATIVE_MAX 0xf8 #define FEATURE_SET_TRANSFER_MODE 0x03 #define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d @@ -138,50 +138,90 @@ typedef struct ide_board_t { ide_board_t *ide_boards[IDE_BUS_MAX]; static uint8_t ide_ter_pnp_rom[] = { - 0x09, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0001, serial 0, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */ + /* BOX0001, serial 0, dummy checksum (filled in by isapnp_add_card) */ + 0x09, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* PnP version 1.0, vendor version 1.0 */ + 0x0a, 0x10, 0x10, + /* ANSI identifier */ + 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', + 'l', 'l', 'e', 'r', - 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, /* logical device BOX0001 */ - 0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x00, 0x08, /* IRQ 11 */ - 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ - 0x38, /* end dependent functions */ + /* Logical device BOX0001 */ + 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, + /* Compatible device PNP0600 */ + 0x1c, 0x41, 0xd0, 0x06, 0x00, + /* Start dependent functions, preferred */ + 0x31, 0x00, + /* IRQ 11 */ + 0x22, 0x00, 0x08, + /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, + /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, + /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, + /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, + /* End dependent functions */ + 0x38, - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + /* End tag, dummy checksum (filled in by isapnp_add_card) */ + 0x79, 0x00 }; static uint8_t ide_qua_pnp_rom[] = { - 0x09, 0xf8, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, /* BOX0001, serial 1, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */ + /* BOX0001, serial 1, dummy checksum (filled in by isapnp_add_card) */ + 0x09, 0xf8, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + /* PnP version 1.0, vendor version 1.0 */ + 0x0a, 0x10, 0x10, + /* ANSI identifier */ + 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', + 'l', 'l', 'e', 'r', - 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, /* logical device BOX0001 */ - 0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x00, 0x04, /* IRQ 10 */ - 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ - 0x38, /* end dependent functions */ + /* Logical device BOX0001 */ + 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, + /* Compatible device PNP0600 */ + 0x1c, 0x41, 0xd0, 0x06, 0x00, + /* Start dependent functions, preferred */ + 0x31, 0x00, + /* IRQ 10 */ + 0x22, 0x00, 0x04, + /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, + /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, + /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, + /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, + /* End dependent functions */ + 0x38, - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + /* End tag, dummy checksum (filled in by isapnp_add_card) */ + 0x79, 0x00 }; ide_t *ide_drives[IDE_NUM]; @@ -364,8 +404,8 @@ ide_irq(ide_t *ide, int set, int log) if (!ide_boards[ide->board]) return; -#ifdef IDE_MORE_SPECIFIC_LOGS - ide_log("IDE %i: IRQ %s\n", set ? "raise" : "lower"); +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("IDE %i: IRQ %s\n", ide->channel, set ? "raise" : "lower"); #endif ide->irqstat = set; @@ -583,7 +623,7 @@ ide_identify(ide_t *ide) if (ide->type == IDE_ATAPI) ide->identify(ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL)); - else if (ide->type != IDE_NONE) + else if (ide->type == IDE_HDD) ide_hd_identify(ide); else { fatal("IDE IDENTIFY or IDENTIFY PACKET DEVICE on non-attached IDE device\n"); @@ -675,15 +715,15 @@ ide_get_sector(ide_t *ide) uint32_t heads; uint32_t sectors; - if (ide->lba) + if (ide->tf->lba) return (off64_t) ide->lba_addr; else { heads = ide->cfg_hpc; sectors = ide->cfg_spt; - uint8_t sector = ide->sector ? (ide->sector - 1) : 0; + uint8_t sector = ide->tf->sector ? (ide->tf->sector - 1) : 0; - return ((((off64_t) ide->tf->cylinder * heads) + (off64_t) ide->head) * sectors) + + return ((((off64_t) ide->tf->cylinder * heads) + (off64_t) ide->tf->head) * sectors) + (off64_t) sector; } } @@ -694,15 +734,15 @@ ide_get_sector(ide_t *ide) static void ide_next_sector(ide_t *ide) { - if (ide->lba) + if (ide->tf->lba) ide->lba_addr++; else { - ide->sector++; - if ((ide->sector == 0) || (ide->sector == (ide->cfg_spt + 1))) { - ide->sector = 1; - ide->head++; - if ((ide->head == 0) || (ide->head == ide->cfg_hpc)) { - ide->head = 0; + ide->tf->sector++; + if ((ide->tf->sector == 0) || (ide->tf->sector == (ide->cfg_spt + 1))) { + ide->tf->sector = 1; + ide->tf->head++; + if ((ide->tf->head == 0) || (ide->head == ide->cfg_hpc)) { + ide->tf->head = 0; ide->tf->cylinder++; } } @@ -729,13 +769,12 @@ loadhd(ide_t *ide, int d, UNUSED(const char *fn)) void ide_set_signature(ide_t *ide) { - uint16_t ide_signatures[3] = { /* 0xffff */ 0x7f7f, 0x0000, 0xeb14 }; + uint16_t ide_signatures[4] = { 0x7f7f, 0x0000, 0xeb14, 0x7f7f }; - ide->sector = 1; - ide->head = 0; - - ide->tf->secount = 1; - ide->tf->cylinder = ide_signatures[ide->type]; + ide->tf->sector = 1; + ide->tf->head = 0; + ide->tf->secount = 1; + ide->tf->cylinder = ide_signatures[ide->type & ~IDE_SHADOW]; if (ide->type == IDE_HDD) ide->drive = 0; @@ -839,16 +878,16 @@ ide_set_sector(ide_t *ide, int64_t sector_num) { unsigned int cyl; unsigned int r; - if (ide->lba) { - ide->head = (sector_num >> 24) & 0xff; + if (ide->tf->lba) { + ide->tf->head = (sector_num >> 24) & 0xff; ide->tf->cylinder = (sector_num >> 8) & 0xffff; - ide->sector = sector_num & 0xff; + ide->tf->sector = sector_num & 0xff; } else { cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); ide->tf->cylinder = cyl & 0xffff; - ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f) & 0xff; - ide->sector = ((r % hdd[ide->hdd_num].spt) + 1) & 0xff; + ide->tf->head = ((r / hdd[ide->hdd_num].spt) & 0x0f) & 0xff; + ide->tf->sector = ((r % hdd[ide->hdd_num].spt) + 1) & 0xff; } } @@ -954,14 +993,20 @@ ide_atapi_callback(ide_t *ide) "Complete" }; char *phase; - if (ide->sc->packet_status <= PHASE_COMPLETE) - phase = phases[ide->sc->packet_status]; - else if (ide->sc->packet_status == PHASE_ERROR) - phase = "Error"; - else if (ide->sc->packet_status == PHASE_NONE) - phase = "None"; - else - phase = "Unknown"; + switch (ide->sc->packet_status) { + default: + phase = "Unknown"; + break; + case PHASE_IDLE ... PHASE_COMPLETE: + phase = phases[ide->sc->packet_status]; + break; + case PHASE_ERROR: + phase = "Error"; + break; + case PHASE_NONE: + phase = "None"; + break; + } ide_log("Phase: %02X (%s)\n", ide->sc->packet_status, phase); #endif @@ -1162,36 +1207,38 @@ ide_write_data(ide_t *ide, uint16_t val, int length) uint8_t *idebufferb = (uint8_t *) ide->buffer; uint16_t *idebufferw = ide->buffer; - if (ide->command == WIN_PACKETCMD) { - if (ide->type == IDE_ATAPI) - ide_atapi_packet_write(ide, val, length); - else - ide->tf->pos = 0; - } else { - if (length == 2) { - idebufferw[ide->tf->pos >> 1] = val & 0xffff; - ide->tf->pos += 2; + if ((ide->type != IDE_NONE) && !(ide->type & IDE_SHADOW) && ide->buffer) { + if (ide->command == WIN_PACKETCMD) { + if (ide->type == IDE_ATAPI) + ide_atapi_packet_write(ide, val, length); + else + ide->tf->pos = 0; } else { - idebufferb[ide->tf->pos] = val & 0xff; - ide->tf->pos++; - } + if (length == 2) { + idebufferw[ide->tf->pos >> 1] = val & 0xffff; + ide->tf->pos += 2; + } else { + idebufferb[ide->tf->pos] = val & 0xff; + ide->tf->pos++; + } - if (ide->tf->pos >= 512) { - ide->tf->pos = 0; - ide->tf->atastat = BSY_STAT; - double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1); - double xfer_time = ide_get_xfer_time(ide, 512); - double wait_time = seek_time + xfer_time; - if (ide->command == WIN_WRITE_MULTIPLE) { - if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) { - ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay); - ide->pending_delay = 0; - } else { - ide->pending_delay += wait_time; - ide_callback(ide); - } - } else - ide_set_callback(ide, wait_time); + if (ide->tf->pos >= 512) { + ide->tf->pos = 0; + ide->tf->atastat = BSY_STAT; + double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1); + double xfer_time = ide_get_xfer_time(ide, 512); + double wait_time = seek_time + xfer_time; + if (ide->command == WIN_WRITE_MULTIPLE) { + if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) { + ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay); + ide->pending_delay = 0; + } else { + ide->pending_delay += wait_time; + ide_callback(ide); + } + } else + ide_set_callback(ide, wait_time); + } } } } @@ -1207,7 +1254,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; -#ifdef IDE_MORE_SPECIFIC_LOGS +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv); #endif @@ -1241,7 +1288,7 @@ ide_writel(uint16_t addr, uint32_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; -#ifdef IDE_MORE_SPECIFIC_LOGS +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv); #endif @@ -1289,6 +1336,10 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) uint8_t old; ch = dev->cur_dev; + /* ATA/ATAPI specification: On a slave with non-present master, pretend the + master is selected. */ + if (ide_drives[ch]->type & IDE_SHADOW) + ch ^= 1; ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; @@ -1364,16 +1415,16 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) static void ide_reset_registers(ide_t *ide) { - uint16_t ide_signatures[3] = { /* 0xffff */ 0x7f7f, 0x0000, 0xeb14 }; + uint16_t ide_signatures[4] = { 0x7f7f, 0x0000, 0xeb14, 0x7f7f }; ide->tf->atastat = DRDY_STAT | DSC_STAT; ide->tf->error = 1; ide->tf->secount = 1; - ide->tf->cylinder = ide_signatures[ide->type]; + ide->tf->cylinder = ide_signatures[ide->type & ~IDE_SHADOW]; + ide->tf->sector = 1; + ide->tf->head = 0; - ide->sector = 1; - ide->head = 0; - ide->reset = 0; + ide->reset = 0; if (ide->type == IDE_ATAPI) ide->sc->callback = 0.0; @@ -1388,7 +1439,6 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide_t *ide; ide_t *ide_other; int ch; - int absent = 0; int bad = 0; int reset = 0; @@ -1396,65 +1446,74 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; - /* Absent and is master or both are absent. */ - if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) - absent = 1; - /* Absent and is slave and master is present. */ - else if ((ide->type == IDE_NONE) && (ch & 1)) - absent = 2; - ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv); addr &= 0x7; - if ((absent != 1) || ((addr != 0x0) && (addr != 0x7))) switch (addr) { + if ((ide->type != IDE_NONE) || ((addr != 0x0) && (addr != 0x7))) switch (addr) { case 0x0: /* Data */ - if (absent == 0) - ide_write_data(ide, val | (val << 8), 2); + ide_write_data(ide, val | (val << 8), 2); break; /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ case 0x1: /* Features */ - ide->tf->cylprecomp = val; - if (ide->type == IDE_ATAPI) - ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->cylprecomp = val; + if (ide->type == IDE_ATAPI) + ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + } -/* The ATA-3 specification says this register is the parameter for the - command and is unclear as to whether or not it's written to both - devices at once. Writing it to both devices at once breaks CD boot - on the AMI Apollo. */ -#ifdef WRITE_PARAM_TO_BOTH_DEVICES - ide_other->tf->cylprecomp = val; -#endif + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) + ide_other->tf->cylprecomp = val; break; case 0x2: /* Sector count */ - ide->tf->secount = val; - ide_other->tf->secount = val; + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) + ide->tf->secount = val; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) + ide_other->tf->secount = val; break; case 0x3: /* Sector */ - ide->sector = val; - ide->lba_addr = (ide->lba_addr & 0xfffff00) | val; + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->sector = val; + ide->lba_addr = (ide->lba_addr & 0xfffff00) | val; + } - ide_other->sector = val; - ide_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->sector = val; + ide_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val; + } break; case 0x4: /* Cylinder low */ - ide->tf->cylinder = (ide->tf->cylinder & 0xff00) | val; - ide->lba_addr = (ide->lba_addr & 0xfff00ff) | (val << 8); + if (ide->type & IDE_SHADOW) + break; - ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff00) | val; - ide_other->lba_addr = (ide_other->lba_addr & 0xfff00ff) | (val << 8); + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->cylinder = (ide->tf->cylinder & 0xff00) | val; + ide->lba_addr = (ide->lba_addr & 0xfff00ff) | (val << 8); + } + + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff00) | val; + ide_other->lba_addr = (ide_other->lba_addr & 0xfff00ff) | (val << 8); + } break; case 0x5: /* Cylinder high */ - ide->tf->cylinder = (ide->tf->cylinder & 0xff) | (val << 8); - ide->lba_addr = (ide->lba_addr & 0xf00ffff) | (val << 16); + if (ide->type & IDE_SHADOW) + break; - ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff) | (val << 8); - ide_other->lba_addr = (ide_other->lba_addr & 0xf00ffff) | (val << 16); + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->cylinder = (ide->tf->cylinder & 0xff) | (val << 8); + ide->lba_addr = (ide->lba_addr & 0xf00ffff) | (val << 16); + } + + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff) | (val << 8); + ide_other->lba_addr = (ide_other->lba_addr & 0xf00ffff) | (val << 16); + } break; case 0x6: /* Drive/Head */ @@ -1484,16 +1543,27 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) } if (!reset) { - ide->head = ide_other->head = val & 0xF; - ide->lba = ide_other->lba = val & 0x40; + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->head = val & 0xf; + ide->tf->lba = val & 0x40; - ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); - ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); + ide->lba_addr = (ide->lba_addr & 0x0ffffff) | (ide->tf->head << 24); + } + + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->head = val & 0xf; + ide_other->tf->lba = val & 0x40; + + ide_other->lba_addr = (ide_other->lba_addr & 0x0ffffff) | (ide->tf->head << 24); + } } break; case 0x7: /* Command register */ - if (absent != 0) + if (ide->tf->atastat & (BSY_STAT | DRQ_STAT)) + break; + + if ((ide->type == IDE_NONE) || ((ide->type & IDE_SHADOW) && (val != WIN_DRIVE_DIAGNOSTICS))) break; ide_irq_lower(ide); @@ -1719,70 +1789,70 @@ ide_read_data(ide_t *ide, int length) { const uint8_t *idebufferb = (uint8_t *) ide->buffer; const uint16_t *idebufferw = ide->buffer; - int ch = ide->channel; uint16_t ret = 0; + double seek_us; + double xfer_us; - /* Absent and is master or both are absent. */ - if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) { +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ch, + ide->board, ide->type); +#endif + + if ((ide->type == IDE_NONE) || (ide->type & IDE_SHADOW) || !ide->buffer) { if (length == 2) ret = 0xff7f; else ret = 0x7f; - /* Absent and is slave and master is present. */ - } else if ((ide->type != IDE_NONE) || !(ch & 1)) { - if (!ide->buffer) { - if (length == 2) - ret = 0xffff; - else - ret = 0xff; - } else if (ide->command == WIN_PACKETCMD) { - if (ide->type == IDE_ATAPI) - ret = ide_atapi_packet_read(ide, length); - else { - ide_log("Drive not ATAPI (position: %i)\n", ide->tf->pos); - ide->tf->pos = 0; - } + } else if (ide->command == WIN_PACKETCMD) { + if (ide->type == IDE_ATAPI) + ret = ide_atapi_packet_read(ide, length); + else { + ide_log("Drive not ATAPI (position: %i)\n", ide->tf->pos); + ide->tf->pos = 0; + } + } else { + if (length == 2) { + ret = idebufferw[ide->tf->pos >> 1]; + ide->tf->pos += 2; } else { - if (length == 2) { - ret = idebufferw[ide->tf->pos >> 1]; - ide->tf->pos += 2; - } else { - ret = idebufferb[ide->tf->pos]; - ide->tf->pos++; - } + ret = idebufferb[ide->tf->pos]; + ide->tf->pos++; + } - if (ide->tf->pos >= 512) { - ide->tf->pos = 0; - ide->tf->atastat = DRDY_STAT | DSC_STAT; - if (ide->type == IDE_ATAPI) - ide->sc->packet_status = PHASE_IDLE; + if (ide->tf->pos >= 512) { + ide->tf->pos = 0; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + if (ide->type == IDE_ATAPI) + ide->sc->packet_status = PHASE_IDLE; - if ((ide->command == WIN_READ) || (ide->command == WIN_READ_NORETRY) || - (ide->command == WIN_READ_MULTIPLE)) { - ide->tf->secount--; + if ((ide->command == WIN_READ) || + (ide->command == WIN_READ_NORETRY) || + (ide->command == WIN_READ_MULTIPLE)) { + ide->tf->secount--; - if (ide->tf->secount) { - ide_next_sector(ide); - ide->tf->atastat = BSY_STAT | READY_STAT | DSC_STAT; - if (ide->command == WIN_READ_MULTIPLE) { - if (!ide->blockcount) { - uint32_t sec_count = ide->tf->secount ? ide->tf->secount : 256; - if (sec_count > ide->blocksize) - sec_count = ide->blocksize; - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], - ide_get_sector(ide), sec_count); - double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); - ide_set_callback(ide, seek_time + xfer_time); - } else - ide_callback(ide); - } else { - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), 1); - double xfer_time = ide_get_xfer_time(ide, 512); - ide_set_callback(ide, seek_time + xfer_time); - } - } else - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } + if (ide->tf->secount) { + ide_next_sector(ide); + ide->tf->atastat = BSY_STAT | READY_STAT | DSC_STAT; + if (ide->command == WIN_READ_MULTIPLE) { + if (!ide->blockcount) { + uint32_t cnt = ide->tf->secount ? + ide->tf->secount : 256; + if (cnt > ide->blocksize) + cnt = ide->blocksize; + seek_us = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), cnt); + xfer_us = ide_get_xfer_time(ide, 512 * cnt); + ide_set_callback(ide, seek_us + xfer_us); + } else + ide_callback(ide); + } else { + seek_us = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), 1); + xfer_us = ide_get_xfer_time(ide, 512); + ide_set_callback(ide, seek_us + xfer_us); + } + } else + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } } } @@ -1796,11 +1866,11 @@ ide_status(ide_t *ide, ide_t *ide_other, int ch) uint8_t ret; /* Absent and is master or both are absent. */ - if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) { + if (ide->type == IDE_NONE) { /* Bit 7 pulled down, all other bits pulled up, per the spec. */ ret = 0x7f; /* Absent and is slave and master is present. */ - } else if ((ide->type == IDE_NONE) && (ch & 1)) { + } else if (ide->type & IDE_SHADOW) { /* On real hardware, a slave with a present master always returns a status of 0x00. Confirmed by the ATA-3 and ATA-4 specifications. */ @@ -1819,21 +1889,11 @@ ide_readb(uint16_t addr, void *priv) { const ide_board_t *dev = (ide_board_t *) priv; int ch; - int absent = 0; ide_t *ide; - ide_t *ide_other; uint8_t ret = 0xff; ch = dev->cur_dev; ide = ide_drives[ch]; - ide_other = ide_drives[ch ^ 1]; - - /* Absent and is master or both are absent. */ - if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) - absent = 1; - /* Absent and is slave and master is present. */ - else if ((ide->type == IDE_NONE) && (ch & 1)) - absent = 2; switch (addr & 0x7) { case 0x0: /* Data */ @@ -1844,7 +1904,7 @@ ide_readb(uint16_t addr, void *priv) Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), and Bit 0 = ILI (illegal length indication). */ case 0x1: /* Error */ - if (absent == 1) + if (ide->type == IDE_NONE) ret = 0x7f; else ret = ide->tf->error; @@ -1864,46 +1924,46 @@ ide_readb(uint16_t addr, void *priv) 0 1 0 Data from host 1 0 1 Status. */ case 0x2: /* Sector count */ - if (absent == 1) + if (ide->type == IDE_NONE) ret = 0x7f; - else if (absent == 2) - ret = ide_other->tf->secount; else ret = ide->tf->secount; break; case 0x3: /* Sector */ - if (absent == 1) + if (ide->type == IDE_NONE) ret = 0x7f; - else if (absent == 2) - ret = (uint8_t) ide_other->sector; else - ret = (uint8_t) ide->sector; + ret = (uint8_t) ide->tf->sector; break; case 0x4: /* Cylinder low */ - if (absent == 1) + if (ide->type == IDE_NONE) ret = 0x7f; - else if (absent == 2) - ret = ide_other->tf->cylinder & 0xff; else ret = ide->tf->cylinder & 0xff; +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("Cylinder low @ board %i, channel %i: ide->type = %i, " + "ret = %02X\n", ide->board, ide->channel, ide->type, ret); +#endif break; case 0x5: /* Cylinder high */ - if (absent == 1) + if (ide->type == IDE_NONE) ret = 0x7f; - else if (absent == 2) - ret = ide_other->tf->cylinder >> 8; else ret = ide->tf->cylinder >> 8; +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + pclog("Cylinder high @ board %i, channel %i: ide->type = %i, " + "ret = %02X\n", ide->board, ide->channel, ide->type, ret); +#endif break; case 0x6: /* Drive/Head */ - if (absent == 1) + if (ide->type == IDE_NONE) ret = 0x7f; else - ret = (uint8_t) (ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); + ret = ide->tf->drvsel | ((ch & 1) ? 0xb0 : 0xa0); break; /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is @@ -1967,7 +2027,7 @@ ide_readw(uint16_t addr, void *priv) break; } -#ifdef IDE_MORE_SPECIFIC_LOGS +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret); #endif return ret; @@ -2002,7 +2062,7 @@ ide_readl(uint16_t addr, void *priv) break; } -#ifdef IDE_MORE_SPECIFIC_LOGS +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret); #endif return ret; @@ -2060,13 +2120,13 @@ ide_callback(void *priv) ide_log("ide_callback(%i): %02X\n", ide->channel, ide->command); switch (ide->command) { - case WIN_SEEK ... 0x7F: - chk_chs = !ide->lba; + case WIN_SEEK ... 0x7f: + chk_chs = !ide->tf->lba; if (ide->type == IDE_ATAPI) atapi_error_no_ready(ide); else { - if (chk_chs && ((ide->tf->cylinder >= ide->tracks) || (ide->head >= ide->hpc) || - !ide->sector || (ide->sector > ide->spt))) + if (chk_chs && ((ide->tf->cylinder >= ide->tracks) || (ide->tf->head >= ide->hpc) || + !ide->tf->sector || (ide->tf->sector > ide->spt))) err = IDNF_ERR; else { ide->tf->atastat = DRDY_STAT | DSC_STAT; @@ -2075,7 +2135,7 @@ ide_callback(void *priv) } break; - case WIN_RECAL ... 0x1F: + case WIN_RECAL ... 0x1f: if (ide->type == IDE_ATAPI) atapi_error_no_ready(ide); else { @@ -2091,7 +2151,7 @@ ide_callback(void *priv) ide->tf->error = 1; /*Device passed*/ ide->tf->secount = 1; - ide->sector = 1; + ide->tf->sector = 1; ide_set_signature(ide); @@ -2129,7 +2189,7 @@ ide_callback(void *priv) if (ide->type == IDE_ATAPI) { ide_set_signature(ide); err = ABRT_ERR; - } else if (!ide->lba && (ide->cfg_spt == 0)) + } else if (!ide->tf->lba && (ide->cfg_spt == 0)) err = IDNF_ERR; else { if (ide->do_initial_read) { @@ -2157,7 +2217,7 @@ ide_callback(void *priv) if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) { ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); err = ABRT_ERR; - } else if (!ide->lba && (ide->cfg_spt == 0)) { + } else if (!ide->tf->lba && (ide->cfg_spt == 0)) { ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); err = IDNF_ERR; } else { @@ -2207,7 +2267,7 @@ ide_callback(void *priv) mand error. */ if ((ide->type == IDE_ATAPI) || !ide->blocksize) err = ABRT_ERR; - else if (!ide->lba && (ide->cfg_spt == 0)) + else if (!ide->tf->lba && (ide->cfg_spt == 0)) err = IDNF_ERR; else { if (ide->do_initial_read) { @@ -2235,7 +2295,7 @@ ide_callback(void *priv) case WIN_WRITE_NORETRY: if (ide->type == IDE_ATAPI) err = ABRT_ERR; - else if (!ide->lba && (ide->cfg_spt == 0)) + else if (!ide->tf->lba && (ide->cfg_spt == 0)) err = IDNF_ERR; else { hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); @@ -2258,7 +2318,7 @@ ide_callback(void *priv) if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) { ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); err = ABRT_ERR; - } else if (!ide->lba && (ide->cfg_spt == 0)) { + } else if (!ide->tf->lba && (ide->cfg_spt == 0)) { ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); err = IDNF_ERR; } else { @@ -2307,7 +2367,7 @@ ide_callback(void *priv) mand error. */ if ((ide->type == IDE_ATAPI) || !ide->blocksize) err = ABRT_ERR; - else if (!ide->lba && (ide->cfg_spt == 0)) + else if (!ide->tf->lba && (ide->cfg_spt == 0)) err = IDNF_ERR; else { hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); @@ -2332,7 +2392,7 @@ ide_callback(void *priv) case WIN_VERIFY_ONCE: if (ide->type == IDE_ATAPI) err = ABRT_ERR; - else if (!ide->lba && (ide->cfg_spt == 0)) + else if (!ide->tf->lba && (ide->cfg_spt == 0)) err = IDNF_ERR; else { ide->tf->pos = 0; @@ -2345,7 +2405,7 @@ ide_callback(void *priv) case WIN_FORMAT: if (ide->type == IDE_ATAPI) err = ABRT_ERR; - else if (!ide->lba && (ide->cfg_spt == 0)) + else if (!ide->tf->lba && (ide->cfg_spt == 0)) err = IDNF_ERR; else { hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->tf->secount); @@ -2364,7 +2424,7 @@ ide_callback(void *priv) if (ide->cfg_spt == 0) { /* Only accept after RESET or DIAG. */ ide->cfg_spt = ide->tf->secount; - ide->cfg_hpc = ide->head + 1; + ide->cfg_hpc = ide->tf->head + 1; } ide->command = 0x00; ide->tf->atastat = DRDY_STAT | DSC_STAT; @@ -2863,8 +2923,14 @@ ide_drive_reset(int d) { ide_log("Resetting IDE drive %i...\n", d); + if ((d & 1) && (ide_drives[d]->type == IDE_NONE) && (ide_drives[d ^ 1]->type != IDE_NONE)) { + ide_drives[d]->type = ide_drives[d ^ 1]->type | IDE_SHADOW; + free(ide_drives[d]->tf); + ide_drives[d]->tf = ide_drives[d ^ 1]->tf; + } else + ide_drives[d]->tf->atastat = DRDY_STAT | DSC_STAT; + ide_drives[d]->channel = d; - ide_drives[d]->tf->atastat = DRDY_STAT | DSC_STAT; ide_drives[d]->service = 0; ide_drives[d]->board = d >> 1; ide_drives[d]->selected = !(d & 1); diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 71ed9e448..291dec303 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -36,9 +36,13 @@ #define HDC_QUATERNARY_IRQ 10 enum { - IDE_NONE = 0, - IDE_HDD, - IDE_ATAPI + IDE_NONE = 0, /* Absent master or both. */ + IDE_HDD, /* Hard disk. */ + IDE_ATAPI, /* ATAPI device. */ + IDE_RESERVED, /* Reserved, do not use. */ + IDE_SHADOW, /* Shadow flag, do not assign on is own. */ + IDE_HDD_SHADOW, /* Shadow of a hard disk. */ + IDE_ATAPI_SHADOW /* Shadow of an ATAPI device. */ }; typedef struct ide_tf_s { @@ -59,28 +63,26 @@ typedef struct ide_tf_s { uint8_t status; }; uint8_t error; - uint16_t pad; + uint8_t sector; + union { + uint8_t drvsel; + struct { + uint8_t head :4; + uint8_t pad :2; + uint8_t lba :1; + uint8_t pad0 :1; + }; + }; uint32_t pos; } ide_tf_t; #ifdef _TIMER_H_ typedef struct ide_s { -#ifdef ANCIENT_CODE - /* Task file. */ - uint8_t cylprecomp; - uint8_t secount; - uint16_t cylinder; - uint8_t atastat; - uint8_t error; - uint16_t pad; - uint32_t pos; -#endif - /* The rest. */ uint8_t selected; uint8_t command; uint8_t head; - uint8_t sector; + uint8_t pad; int type; int board; int irqstat; @@ -90,7 +92,6 @@ typedef struct ide_s { int hdd_num; int channel; int sector_pos; - int lba; int reset; int mdma_mode; int do_initial_read; From bb515c3c05eb11e107150c01e711901bda240732 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 4 Nov 2023 04:12:09 +0100 Subject: [PATCH 074/133] Fixed the accidentally broken LBA mode on IDE hard disks. --- src/disk/hdc_ide.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 126a9d583..14ceb6504 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1544,17 +1544,15 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) if (!reset) { if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { - ide->tf->head = val & 0xf; - ide->tf->lba = val & 0x40; - - ide->lba_addr = (ide->lba_addr & 0x0ffffff) | (ide->tf->head << 24); + ide->tf->drvsel = val & 0xef; + ide->lba_addr = (ide->lba_addr & 0x0ffffff) | + (ide->tf->head << 24); } if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { - ide_other->tf->head = val & 0xf; - ide_other->tf->lba = val & 0x40; - - ide_other->lba_addr = (ide_other->lba_addr & 0x0ffffff) | (ide->tf->head << 24); + ide_other->tf->drvsel = val & 0xef; + ide_other->lba_addr = (ide_other->lba_addr & 0x0ffffff) | + (ide->tf->head << 24); } } break; From 06c7567495d6ba1b6af4343fd3051ed8c4a4cba2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 4 Nov 2023 06:41:57 +0100 Subject: [PATCH 075/133] Mouse capture is no longer possible when the emulator is paused, fixes #3799. --- src/qt/qt_rendererstack.cpp | 5 ++++- src/qt/qt_sdl.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 469dc04de..1b1ed45c3 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -144,7 +144,10 @@ int ignoreNextMouseEvent = 1; void RendererStack::mouseReleaseEvent(QMouseEvent *event) { - if (this->geometry().contains(event->pos()) && (event->button() == Qt::LeftButton) && !mouse_capture && (isMouseDown & 1) && (kbd_req_capture || (mouse_get_buttons() != 0)) && (mouse_input_mode == 0)) { + if (!dopause && this->geometry().contains(event->pos()) && + (event->button() == Qt::LeftButton) && !mouse_capture && + (isMouseDown & 1) && (kbd_req_capture || (mouse_get_buttons() != 0)) && + (mouse_input_mode == 0)) { plat_mouse_capture(1); this->setCursor(Qt::BlankCursor); if (!ignoreNextMouseEvent) diff --git a/src/qt/qt_sdl.c b/src/qt/qt_sdl.c index 166ea88fa..15af4d7b6 100644 --- a/src/qt/qt_sdl.c +++ b/src/qt/qt_sdl.c @@ -627,7 +627,7 @@ sdl_main() case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { - if ((event.button.button == SDL_BUTTON_LEFT) + if (!dopause && (event.button.button == SDL_BUTTON_LEFT) && !(mouse_capture || video_fullscreen) && event.button.state == SDL_RELEASED && mouse_inside) { From 73714e8130f5bfb727f8a49fe8ec32e4fd33c792 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sun, 17 Oct 2021 02:38:26 +0500 Subject: [PATCH 076/133] Report correct cache info in CPUID on P6-family CPUs --- src/cpu/cpu.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 1ea8b2dde..1f3e1ce58 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2373,9 +2373,14 @@ cpu_CPUID(void) EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; } else if (EAX == 2) { - EAX = 0x00000001; + EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set fully associative, 32 entries + Instruction TLB: 4 MB pages, fully associative, 2 entries + Data TLB: 4 KB pages, 4-way set associative, 64 entries */ EBX = ECX = 0; - EDX = 0x00000000; + EDX = 0x0C040842; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries + Level 1 instruction cache: 16 KB, 4-way set associative, 32 byte line size + Level 1 data cache: 16 KB, 4-way set associative, 32 byte line size + Level 2 cache: 256 KB, 4-way set associative, 32 byte line size */ } else EAX = EBX = ECX = EDX = 0; break; @@ -2391,9 +2396,14 @@ cpu_CPUID(void) EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; } else if (EAX == 2) { - EAX = 0x00000001; + EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set fully associative, 32 entries + Instruction TLB: 4 MB pages, fully associative, 2 entries + Data TLB: 4 KB pages, 4-way set associative, 64 entries */ EBX = ECX = 0; - EDX = 0x00000000; + EDX = 0x0C040843; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries + Level 1 instruction cache: 16 KB, 4-way set associative, 32 byte line size + Level 1 data cache: 16 KB, 4-way set associative, 32 byte line size + Level 2 cache: 512 KB, 4-way set associative, 32 byte line size */ } else EAX = EBX = ECX = EDX = 0; break; @@ -2409,9 +2419,22 @@ cpu_CPUID(void) EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; } else if (EAX == 2) { - EAX = 0x00000001; + EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set fully associative, 32 entries + Instruction TLB: 4 MB pages, fully associative, 2 entries + Data TLB: 4 KB pages, 4-way set associative, 64 entries */ EBX = ECX = 0; - EDX = 0x00000000; + if (cpu_f->package == CPU_PKG_SLOT2) /* Pentium II Xeon Drake */ + EDX = 0x0C040844; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries + Level 1 instruction cache: 16 KB, 4-way set associative, 32 byte line size + Level 1 data cache: 16 KB, 4-way set associative, 32 byte line size + Level 2 cache: 1 MB, 4-way set associative, 32 byte line size */ + else if (!strncmp(cpu_f->internal_name, "celeron", 7)) { /* Celeron */ + if (CPUID >= 0x660) /* Mendocino */ + EDX = 0x0C040841; /* Level 2 cache: 128 KB, 4-way set associative, 32 byte line size */ + else /* Covington */ + EDX = 0x0C040840; /* No Level 2 cache */ + } else /* Pentium II Deschutes and OverDrive */ + EDX = 0x0C040843; /* Level 2 cache: 512 KB, 4-way set associative, 32 byte line size */ } else EAX = EBX = ECX = EDX = 0; break; From b012ab75f4fa85dba754dbe8d941fc17c97249d2 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 4 Nov 2023 02:50:13 -0400 Subject: [PATCH 077/133] Misc bits from master --- CMakeLists.txt | 2 +- debian/changelog | 2 +- src/unix/assets/86Box.spec | 2 +- src/unix/assets/net.86box.86Box.metainfo.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 866933e32..d9f92add3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,7 +197,7 @@ if(NOT EMU_BUILD_NUM) set(EMU_BUILD_NUM 0) endif() if(NOT EMU_COPYRIGHT_YEAR) - set(EMU_COPYRIGHT_YEAR 2022) + set(EMU_COPYRIGHT_YEAR 2023) endif() add_subdirectory(src) diff --git a/debian/changelog b/debian/changelog index e6571ece3..98ab80043 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,4 +2,4 @@ * Bump release. - -- Jasmine Iwanek Thu, 12 Oct 2023 00:00:31 +0200 + -- Jasmine Iwanek Thu, 16 Oct 2023 20:24:46 +0200 diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index a024e4288..a7e4786be 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -121,5 +121,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Thu Oct 12 2023 Robert de Rooy 4.1-1 +* Mon Oct 16 2023 Robert de Rooy 4.1-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index d17c10986..9e2c5dc88 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -10,7 +10,7 @@ net.86box.86Box.desktop - + From 1ce96a0624badabb3e3a183ecfd540acf127a847 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 4 Nov 2023 02:51:56 -0400 Subject: [PATCH 078/133] Remove unnecessary brace in m_at_socket370.c --- src/machine/m_at_socket370.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index db6013ae1..07432bfd7 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -173,9 +173,8 @@ machine_at_p6bat_init(const machine_t *model) device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); - if (sound_card_current[0] == SOUND_INTERNAL) { + if (sound_card_current[0] == SOUND_INTERNAL) device_add(&cmi8738_onboard_device); - } return ret; } From 1959665149fe50468cb30bef363fc81a556e4c5a Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 4 Nov 2023 03:04:35 -0400 Subject: [PATCH 079/133] And a bit I missed --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 98ab80043..29ec6d3af 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,4 +2,4 @@ * Bump release. - -- Jasmine Iwanek Thu, 16 Oct 2023 20:24:46 +0200 + -- Jasmine Iwanek Mon, 16 Oct 2023 20:24:46 +0200 From 85f358b7f5f9573339618cc4defd0eb7a6372074 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 4 Nov 2023 23:16:08 +0100 Subject: [PATCH 080/133] Removed the recently introduced IDE reset change - fixes CD-ROM detection on Windows 95 on Phoenix BIOS'es. --- src/disk/hdc_ide.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 14ceb6504..7a89c105f 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1336,10 +1336,6 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) uint8_t old; ch = dev->cur_dev; - /* ATA/ATAPI specification: On a slave with non-present master, pretend the - master is selected. */ - if (ide_drives[ch]->type & IDE_SHADOW) - ch ^= 1; ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; From c8f6c0f3c49b99b78bd58ec7e0bd42513327b33a Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Nov 2023 00:53:57 +0100 Subject: [PATCH 081/133] Moved the CPU override warning dialog so it no longer hard freezes the emulator. --- src/qt/qt_main.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 598025795..d025c9168 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -208,6 +208,20 @@ main(int argc, char *argv[]) return 0; } + /* Warn the user about unsupported configs */ + if (cpu_override) { + QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("You are loading an unsupported configuration"), + QObject::tr("CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid."), + QMessageBox::NoButton, main_window); + warningbox.addButton(QObject::tr("Continue"), QMessageBox::AcceptRole); + warningbox.addButton(QObject::tr("Exit"), QMessageBox::RejectRole); + warningbox.exec(); + if (warningbox.result() == QDialog::Accepted) { + confirm_exit_cmdl = 0; /* skip the confirmation prompt without touching the config */ + emit main_window->close(); + } + } + #ifdef DISCORD discord_load(); #endif @@ -279,20 +293,6 @@ main(int argc, char *argv[]) socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET")); } - /* Warn the user about unsupported configs */ - if (cpu_override) { - QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("You are loading an unsupported configuration"), - QObject::tr("CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid."), - QMessageBox::NoButton, main_window); - warningbox.addButton(QObject::tr("Continue"), QMessageBox::AcceptRole); - warningbox.addButton(QObject::tr("Exit"), QMessageBox::RejectRole); - warningbox.exec(); - if (warningbox.result() == QDialog::Accepted) { - confirm_exit_cmdl = 0; /* skip the confirmation prompt without touching the config */ - emit main_window->close(); - } - } - // pc_reset_hard_init(); /* Set the PAUSE mode depending on the renderer. */ From 5ee5b858d3c6d076d2e12897f4515a2b5796340c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Nov 2023 02:10:39 +0100 Subject: [PATCH 082/133] Fixes to the cpu_override warning dialog handling per the suggestions by lemondrops. --- src/qt/qt_main.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index d025c9168..845ff705f 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -212,14 +212,12 @@ main(int argc, char *argv[]) if (cpu_override) { QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("You are loading an unsupported configuration"), QObject::tr("CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid."), - QMessageBox::NoButton, main_window); + QMessageBox::NoButton); warningbox.addButton(QObject::tr("Continue"), QMessageBox::AcceptRole); warningbox.addButton(QObject::tr("Exit"), QMessageBox::RejectRole); warningbox.exec(); - if (warningbox.result() == QDialog::Accepted) { - confirm_exit_cmdl = 0; /* skip the confirmation prompt without touching the config */ - emit main_window->close(); - } + if (warningbox.result() == QDialog::Accepted) + return 0; } #ifdef DISCORD From 33b61668963492118a2255ccb9e6f29f57523358 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sun, 5 Nov 2023 07:08:33 +0500 Subject: [PATCH 083/133] Fix the Pentium Pro L1 cache amount --- src/cpu/cpu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 1f3e1ce58..978ae0165 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2377,9 +2377,9 @@ cpu_CPUID(void) Instruction TLB: 4 MB pages, fully associative, 2 entries Data TLB: 4 KB pages, 4-way set associative, 64 entries */ EBX = ECX = 0; - EDX = 0x0C040842; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries - Level 1 instruction cache: 16 KB, 4-way set associative, 32 byte line size - Level 1 data cache: 16 KB, 4-way set associative, 32 byte line size + EDX = 0x06040A42; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries + Level 1 instruction cache: 8 KB, 4-way set associative, 32-byte line size + Level 1 data cache: 8 KB, 2-way set associative, 32 byte line size Level 2 cache: 256 KB, 4-way set associative, 32 byte line size */ } else EAX = EBX = ECX = EDX = 0; From 8f4fe2f9e205b11f8cc4f723a898b7888fea8321 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sun, 5 Nov 2023 07:20:25 +0500 Subject: [PATCH 084/133] Reorder and reformat comments --- src/cpu/cpu.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 978ae0165..430e11f96 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2373,14 +2373,14 @@ cpu_CPUID(void) EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; } else if (EAX == 2) { - EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set fully associative, 32 entries + EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries Data TLB: 4 KB pages, 4-way set associative, 64 entries */ EBX = ECX = 0; - EDX = 0x06040A42; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries - Level 1 instruction cache: 8 KB, 4-way set associative, 32-byte line size - Level 1 data cache: 8 KB, 2-way set associative, 32 byte line size - Level 2 cache: 256 KB, 4-way set associative, 32 byte line size */ + EDX = 0x06040a42; /* 2nd-level cache: 256 KB, 4-way set associative, 32-byte line size + 1st-level data cache: 8 KB, 2-way set associative, 32-byte line size + Data TLB: 4 MB pages, 4-way set associative, 8 entries + 1st-level instruction cache:8 KB, 4-way set associative, 32-byte line size */ } else EAX = EBX = ECX = EDX = 0; break; @@ -2396,14 +2396,14 @@ cpu_CPUID(void) EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; } else if (EAX == 2) { - EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set fully associative, 32 entries + EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries Data TLB: 4 KB pages, 4-way set associative, 64 entries */ EBX = ECX = 0; - EDX = 0x0C040843; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries - Level 1 instruction cache: 16 KB, 4-way set associative, 32 byte line size - Level 1 data cache: 16 KB, 4-way set associative, 32 byte line size - Level 2 cache: 512 KB, 4-way set associative, 32 byte line size */ + EDX = 0x0c040843; /* 2nd-level cache: 512 KB, 4-way set associative, 32-byte line size + 1st-level data cache: 16 KB, 4-way set associative, 32-byte line size + Data TLB: 4 MB pages, 4-way set associative, 8 entries + 1st-level instruction cache: 16 KB, 4-way set associative, 32-byte line size */ } else EAX = EBX = ECX = EDX = 0; break; @@ -2419,22 +2419,22 @@ cpu_CPUID(void) EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; } else if (EAX == 2) { - EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set fully associative, 32 entries + EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries Data TLB: 4 KB pages, 4-way set associative, 64 entries */ EBX = ECX = 0; if (cpu_f->package == CPU_PKG_SLOT2) /* Pentium II Xeon Drake */ - EDX = 0x0C040844; /* Data TLB: 4 MB pages, 4-way set associative, 8 entries - Level 1 instruction cache: 16 KB, 4-way set associative, 32 byte line size - Level 1 data cache: 16 KB, 4-way set associative, 32 byte line size - Level 2 cache: 1 MB, 4-way set associative, 32 byte line size */ + EDX = 0x0c040844; /* 2nd-level cache: 1 MB, 4-way set associative, 32-byte line size + 1st-level data cache: 16 KB, 4-way set associative, 32-byte line size + Data TLB: 4 MB pages, 4-way set associative, 8 entries + 1st-level instruction cache: 16 KB, 4-way set associative, 32-byte line size */ else if (!strncmp(cpu_f->internal_name, "celeron", 7)) { /* Celeron */ if (CPUID >= 0x660) /* Mendocino */ - EDX = 0x0C040841; /* Level 2 cache: 128 KB, 4-way set associative, 32 byte line size */ + EDX = 0x0c040841; /* 2nd-level cache: 128 KB, 4-way set associative, 32-byte line size */ else /* Covington */ - EDX = 0x0C040840; /* No Level 2 cache */ + EDX = 0x0c040840; /* No 2nd-level cache */ } else /* Pentium II Deschutes and OverDrive */ - EDX = 0x0C040843; /* Level 2 cache: 512 KB, 4-way set associative, 32 byte line size */ + EDX = 0x0c040843; /* 2nd-level cache: 512 KB, 4-way set associative, 32-byte line size */ } else EAX = EBX = ECX = EDX = 0; break; From 70a2ba058183325d215cd5dba84970b2ea75cdc3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Nov 2023 22:31:21 +0100 Subject: [PATCH 085/133] Do not attempt to free the task file of shadowed IDE devices, fixes potential crashes when shutting down the emulator. --- src/disk/hdc_ide.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 7a89c105f..bef5afeb5 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -2651,7 +2651,8 @@ ide_board_close(int board) if (dev->type == IDE_ATAPI) dev->tf->atastat = DRDY_STAT | DSC_STAT; - else if (dev->tf != NULL) { + + if ((dev->type == IDE_HDD) && (dev->tf != NULL)) { free(dev->tf); dev->tf = NULL; } From 33afe6e014725d047e3b6a5698aad799b8013226 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Nov 2023 22:33:19 +0100 Subject: [PATCH 086/133] Improved the fix. --- src/disk/hdc_ide.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index bef5afeb5..2bb83b4ab 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -2651,8 +2651,7 @@ ide_board_close(int board) if (dev->type == IDE_ATAPI) dev->tf->atastat = DRDY_STAT | DSC_STAT; - - if ((dev->type == IDE_HDD) && (dev->tf != NULL)) { + else if (!(dev->type & IDE_SHADOW) && (dev->tf != NULL)) { free(dev->tf); dev->tf = NULL; } From 5399380ac4a55810e93a235b1a519eb11f3b2a13 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 02:06:42 +0100 Subject: [PATCH 087/133] Fixed ACPI power on, again, fixes the HP Vectra VEi 8, again. --- src/acpi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 0fe25d79f..7b070257f 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -46,6 +46,8 @@ int acpi_enabled = 0; static double cpu_to_acpi; +static int acpi_power_on = 0; + #ifdef ENABLE_ACPI_LOG int acpi_do_log = ENABLE_ACPI_LOG; @@ -1653,6 +1655,12 @@ acpi_reset(void *priv) dev->regs.gpi_val |= 0x00000004; } + if (acpi_power_on) { + /* Power on always generates a resume event. */ + dev->regs.pmsts |= 0x8100; + acpi_power_on = 0; + } + acpi_rtc_status = 0; acpi_update_irq(dev); @@ -1759,10 +1767,9 @@ acpi_init(const device_t *info) acpi_reset(dev); - /* Power on always generates a resume event. */ - dev->regs.pmsts |= 0x8100; + acpi_enabled = 1; + acpi_power_on = 1; - acpi_enabled = 1; return dev; } From 9e08c8317b4e2a8f7ea4332828c349312d466635 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 04:14:42 +0100 Subject: [PATCH 088/133] Fixed NVR handling on PC87306 reset, fixes MR BIOS'es. --- src/sio/sio_pc87306.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index f5aa086d0..ab7f8597e 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -439,6 +439,7 @@ pc87306_reset_common(void *priv) fdc_reset(dev->fdc); pc87306_gpio_init(dev); nvr_lock_set(0x00, 256, 0, dev->nvr); + nvr_at_handler(0, 0x0070, dev->nvr); nvr_at_handler(1, 0x0070, dev->nvr); nvr_bank_set(0, 0, dev->nvr); nvr_wp_set(0, 0, dev->nvr); From d5a363e1b643f1b9b627b0dacd19e46c0c576d9f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 05:06:01 +0100 Subject: [PATCH 089/133] Added ISA cycle delays to fast PIT read/write and port 61h read/write, fixes MR BIOS'es on higher CPU speeds. --- src/pit_fast.c | 7 +++++++ src/port_6x.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/pit_fast.c b/src/pit_fast.c index 20633de80..4eb9314f7 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -404,6 +404,8 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); + cycles -= ISA_CYCLES(8); + switch (addr & 3) { case 3: /* control */ t = val >> 6; @@ -470,15 +472,18 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) switch (ctr->wm) { case 1: ctr->l = val; + if (t == 1) pclog("Timer 1 counter set to: %08X\n", ctr->l); pitf_ctr_load(ctr); break; case 2: ctr->l = (val << 8); + if (t == 1) pclog("Timer 1 counter set to: %08X\n", ctr->l); pitf_ctr_load(ctr); break; case 0: ctr->l &= 0xFF; ctr->l |= (val << 8); + if (t == 1) pclog("Timer 1 counter set to: %08X\n", ctr->l); pitf_ctr_load(ctr); ctr->wm = 3; break; @@ -541,6 +546,8 @@ pitf_read(uint16_t addr, void *priv) int t = (addr & 3); ctrf_t *ctr; + cycles -= ISA_CYCLES(8); + switch (addr & 3) { case 3: /* Control. */ /* This is 8254-only, 8253 returns 0x00. */ diff --git a/src/port_6x.c b/src/port_6x.c index 340d6df2b..750b9678c 100644 --- a/src/port_6x.c +++ b/src/port_6x.c @@ -37,6 +37,7 @@ #include <86box/video.h> #include <86box/port_6x.h> #include <86box/plat_unused.h> +#include <86box/random.h> #define PS2_REFRESH_TIME (16 * TIMER_USEC) @@ -52,6 +53,8 @@ port_6x_write(uint16_t port, uint8_t val, void *priv) port &= 3; + cycles -= ISA_CYCLES(8); + if ((port == 3) && (dev->flags & PORT_6X_MIRROR)) port = 1; @@ -80,6 +83,8 @@ port_61_read_simple(UNUSED(uint16_t port), UNUSED(void *priv)) { uint8_t ret = ppi.pb & 0x1f; + cycles -= ISA_CYCLES(8); + if (ppispeakon) ret |= 0x20; @@ -92,6 +97,8 @@ port_61_read(UNUSED(uint16_t port), void *priv) const port_6x_t *dev = (port_6x_t *) priv; uint8_t ret = 0xff; + cycles -= ISA_CYCLES(8); + if (dev->flags & PORT_6X_EXT_REF) { ret = ppi.pb & 0x0f; From d797659c792172553a57eec06a778c35a1530237 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 05:06:42 +0100 Subject: [PATCH 090/133] Removed some excess logging from the fast PIT code. --- src/pit_fast.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pit_fast.c b/src/pit_fast.c index 4eb9314f7..1168cb3c5 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -472,18 +472,15 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) switch (ctr->wm) { case 1: ctr->l = val; - if (t == 1) pclog("Timer 1 counter set to: %08X\n", ctr->l); pitf_ctr_load(ctr); break; case 2: ctr->l = (val << 8); - if (t == 1) pclog("Timer 1 counter set to: %08X\n", ctr->l); pitf_ctr_load(ctr); break; case 0: ctr->l &= 0xFF; ctr->l |= (val << 8); - if (t == 1) pclog("Timer 1 counter set to: %08X\n", ctr->l); pitf_ctr_load(ctr); ctr->wm = 3; break; From 09d2f7517c0d07f41512379635eb00c47527d777 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 06:07:43 +0100 Subject: [PATCH 091/133] Some CPU fixes. --- src/cpu/cpu.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 1ea8b2dde..57017f446 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1816,12 +1816,13 @@ cpu_set_isa_speed(int speed) { if (speed) { cpu_isa_speed = speed; - pc_speed_changed(); } else if (cpu_busspeed >= 8000000) cpu_isa_speed = 8000000; else cpu_isa_speed = cpu_busspeed; + pc_speed_changed(); + cpu_log("cpu_set_isa_speed(%d) = %d\n", speed, cpu_isa_speed); } @@ -2471,6 +2472,28 @@ cpu_ven_reset(void) memset(&msr, 0, sizeof(msr)); switch (cpu_s->cpu_type) { + case CPU_WINCHIP: + case CPU_WINCHIP2: + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + if (cpu_s->cpu_type == CPU_WINCHIP2) + msr.fcr |= (1 << 18) | (1 << 20); + break; + + case CPU_P24T: + case CPU_PENTIUM: + case CPU_PENTIUMMMX: + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + break; + +#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) + case CPU_Cx6x86: + case CPU_Cx6x86L: + case CPU_CxGX1: + case CPU_Cx6x86MX: + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + break; +#endif + case CPU_K6_2P: case CPU_K6_3P: case CPU_K6_3: @@ -2484,12 +2507,19 @@ cpu_ven_reset(void) #endif case CPU_K6: msr.amd_efer = (cpu_s->cpu_type >= CPU_K6_2C) ? 2ULL : 0ULL; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); break; case CPU_PENTIUMPRO: case CPU_PENTIUM2: case CPU_PENTIUM2D: msr.mtrr_cap = 0x00000508ULL; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + break; + + case CPU_CYRIX3S: + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | + (1 << 20) | (1 << 21); break; } } From b0b857a50ed0c1df68351f266d8365c165df2e56 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Mon, 6 Nov 2023 10:22:06 +0500 Subject: [PATCH 092/133] Don't set Centaur/VIA Feature Control Register MSR on CPUs that lack it --- src/cpu/cpu.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 57017f446..b9c4b43a7 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1389,7 +1389,6 @@ cpu_set(void) cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; if (cpu_s->cpu_type == CPU_PENTIUMMMX) cpu_features |= CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_pentium); @@ -1503,7 +1502,6 @@ cpu_set(void) cpu_features |= CPU_FEATURE_MSR | CPU_FEATURE_CR4; if (cpu_s->cpu_type == CPU_Cx6x86MX) cpu_features |= CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); if (cpu_s->cpu_type >= CPU_CxGX1) cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; @@ -1598,7 +1596,6 @@ cpu_set(void) cpu_features |= CPU_FEATURE_3DNOW; if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) cpu_features |= CPU_FEATURE_3DNOWE; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); #if defined(DEV_BRANCH) && defined(USE_AMD_K5) cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE; if (cpu_s->cpu_type >= CPU_K6) { @@ -1701,7 +1698,6 @@ cpu_set(void) cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; if (cpu_s->cpu_type >= CPU_PENTIUM2) cpu_features |= CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PAE | CR4_PCE | CR4_PGE; if (cpu_s->cpu_type == CPU_PENTIUM2D) cpu_CR4_mask |= CR4_OSFXSR; @@ -2479,21 +2475,6 @@ cpu_ven_reset(void) msr.fcr |= (1 << 18) | (1 << 20); break; - case CPU_P24T: - case CPU_PENTIUM: - case CPU_PENTIUMMMX: - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - break; - -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - case CPU_Cx6x86L: - case CPU_CxGX1: - case CPU_Cx6x86MX: - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - break; -#endif - case CPU_K6_2P: case CPU_K6_3P: case CPU_K6_3: @@ -2507,14 +2488,12 @@ cpu_ven_reset(void) #endif case CPU_K6: msr.amd_efer = (cpu_s->cpu_type >= CPU_K6_2C) ? 2ULL : 0ULL; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); break; case CPU_PENTIUMPRO: case CPU_PENTIUM2: case CPU_PENTIUM2D: msr.mtrr_cap = 0x00000508ULL; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); break; case CPU_CYRIX3S: From 8b741d511eb99eb81335d0d2118660c0df81fd90 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Wed, 1 Nov 2023 23:37:50 +0500 Subject: [PATCH 093/133] Add Page Global Enable feature (toggleable by an MSR) to the Cyrix III --- src/cpu/cpu.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b9c4b43a7..4987d96f3 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1745,8 +1745,8 @@ cpu_set(void) timing_misaligned = 2; cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; + msr.fcr = (1 << 7) | (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE | CR4_PGE; cpu_cyrix_alignment = 1; @@ -2433,6 +2433,8 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 7)) + EDX |= CPUID_PGE; break; case 0x80000000: EAX = 0x80000005; @@ -2442,6 +2444,8 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 7)) + EDX |= CPUID_PGE; break; case 0x80000002: /* Processor name string */ EAX = 0x20414956; /* VIA Samuel */ @@ -2497,8 +2501,8 @@ cpu_ven_reset(void) break; case CPU_CYRIX3S: - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | - (1 << 20) | (1 << 21); + msr.fcr = (1 << 7) (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | + (1 << 20) | (1 << 21); break; } } @@ -3098,6 +3102,10 @@ cpu_WRMSR(void) cpu_features |= CPU_FEATURE_CX8; else cpu_features &= ~CPU_FEATURE_CX8; + if (EAX & (1 << 7)) + cpu_CR4_mask |= CR4_PGE; + else + cpu_CR4_mask &= ~CR4_PGE; break; case 0x1108: msr.fcr2 = EAX | ((uint64_t) EDX << 32); From 436d8ceaf7335743869edc34c46d9befa8c110b7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 06:50:26 +0100 Subject: [PATCH 094/133] The Zenith Z-15x machine now have a Tandy/Amstrad-style FDC with changeline support, fixes floppy booting on those machines without XTIDE. --- src/machine/m_xt_zenith.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 0e0f9b9b0..0da091917 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -112,12 +112,8 @@ static const device_t zenith_scratchpad_device = { void machine_zenith_init(const machine_t *model) { - machine_common_init(model); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); - device_add(&zenith_scratchpad_device); pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); @@ -144,6 +140,9 @@ machine_xt_z184_init(const machine_t *model) machine_zenith_init(model); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + lpt1_remove(); /* only one parallel port */ lpt2_remove(); lpt1_init(0x278); @@ -171,6 +170,9 @@ machine_xt_z151_init(const machine_t *model) machine_zenith_init(model); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_tandy_device); + return ret; } @@ -191,6 +193,9 @@ machine_xt_z159_init(const machine_t *model) machine_zenith_init(model); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_tandy_device); + /* parallel port is on the memory board */ lpt1_remove(); /* only one parallel port */ lpt2_remove(); From 7dd13b704c4a4642ad09cc0e9015125be607fadc Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 06:51:44 +0100 Subject: [PATCH 095/133] Fixed a compile-breaking mistake in cpu/cpu.c. --- src/cpu/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 4987d96f3..75ad191f6 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -2501,7 +2501,7 @@ cpu_ven_reset(void) break; case CPU_CYRIX3S: - msr.fcr = (1 << 7) (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | + msr.fcr = (1 << 7) | (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); break; } From 74e2437d9198fa6a1a0256ebe41340d59105f533 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 07:05:15 +0100 Subject: [PATCH 096/133] 808x machines with >= 8 MHz CPU speed now default to fast PIT, fixes #3776. --- src/machine/machine.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/machine/machine.c b/src/machine/machine.c index a21d8115c..c4ace6b4f 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -168,13 +168,15 @@ pit_irq0_timer(int new_out, int old_out) void machine_common_init(UNUSED(const machine_t *model)) { + uint8_t cpu_requires_fast_pit = is486 || (is8086 && (cpu_s->rspeed >= 8000000)); + /* System devices first. */ pic_init(); dma_init(); int pit_type = IS_AT(machine) ? PIT_8254 : PIT_8253; /* Select fast PIT if needed */ - if (((pit_mode == -1) && is486) || (pit_mode == 1)) + if (((pit_mode == -1) && cpu_requires_fast_pit) || (pit_mode == 1)) pit_type += 2; pit_common_init(pit_type, pit_irq0_timer, NULL); From 6d2e5185aea9c07004e1e5afff6f41add8083c9d Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 23:21:58 +0100 Subject: [PATCH 097/133] Reverted back to known-good 808x code from 3.11.4311, fixes PC/XT V20 (the full 808x rewrite based on MartyPC is still coming in 4.1). --- src/cpu/808x.c | 2135 +++++++++++++++++------------------------------- 1 file changed, 771 insertions(+), 1364 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index a24d1f07f..3572f2c9f 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -35,8 +35,6 @@ #include <86box/ppi.h> #include <86box/timer.h> #include <86box/gdbstub.h> -#include <86box/plat_fallthrough.h> -#include <86box/plat_unused.h> /* Is the CPU 8088 or 8086. */ int is8086 = 0; @@ -48,8 +46,7 @@ uint32_t custom_nmi_vector = 0x00000000; static uint8_t pfq[6]; /* Variables to aid with the prefetch queue operation. */ -static int biu_cycles = 0; -static int pfq_pos = 0; +static int biu_cycles = 0, pfq_pos = 0; /* The IP equivalent of the current prefetch queue position. */ static uint16_t pfq_ip; @@ -60,57 +57,18 @@ static x86seg *_opseg[4]; static int noint = 0; static int in_lock = 0; -static int cpu_alu_op; -static int pfq_size; +static int cpu_alu_op, pfq_size; -static uint32_t cpu_src = 0; -static uint32_t cpu_dest = 0; +static uint32_t cpu_src = 0, cpu_dest = 0; static uint32_t cpu_data = 0; static uint16_t last_addr = 0x0000; static uint32_t *ovr_seg = NULL; -static int prefetching = 1; -static int completed = 1; -static int in_rep = 0; -static int repeating = 0; -static int rep_c_flag = 0; -static int oldc; -static int clear_lock = 0; -static int refresh = 0; -static int cycdiff; - -static int access_code = 0; -static int hlda = 0; -static int not_ready = 0; -static int bus_request_type = 0; -static int pic_data = -1; -static int last_was_code = 0; -static uint16_t mem_data = 0; -static uint32_t mem_seg = 0; -static uint16_t mem_addr = 0; -static int schedule_fetch = 1; -static int pasv = 0; - -#define BUS_OUT 1 -#define BUS_HIGH 2 -#define BUS_WIDE 4 -#define BUS_CODE 8 -#define BUS_IO 16 -#define BUS_MEM 32 -#define BUS_PIC 64 -#define BUS_ACCESS_TYPE (BUS_CODE | BUS_IO | BUS_MEM | BUS_PIC) - -#define BUS_CYCLE (biu_cycles & 3) -#define BUS_CYCLE_T1 biu_cycles = 0 -#define BUS_CYCLE_NEXT biu_cycles = (biu_cycles + 1) & 3 - -enum { - BUS_T1 = 0, - BUS_T2, - BUS_T3, - BUS_T4 -}; +static int prefetching = 1, completed = 1; +static int in_rep = 0, repeating = 0, rep_c_flag = 0; +static int oldc, clear_lock = 0; +static int refresh = 0, cycdiff; /* Various things needed for 8087. */ #define OP_TABLE(name) ops_##name @@ -135,6 +93,7 @@ enum { wait(val, 0); \ } +#if 0 # define CLOCK_CYCLES_FPU(val) \ { \ wait(val, 0); \ @@ -153,6 +112,19 @@ enum { } # define CONCURRENCY_CYCLES(c) fpu_cycles = (c) +#else +# define CLOCK_CYCLES(val) \ + { \ + wait(val, 0); \ + } + +# define CLOCK_CYCLES_FPU(val) \ + { \ + wait(val, 0); \ + } + +# define CONCURRENCY_CYCLES(c) +#endif typedef int (*OpFn)(uint32_t fetchdat); @@ -179,7 +151,7 @@ x808x_log(const char *fmt, ...) # define x808x_log(fmt, ...) #endif -static void pfq_add(void); +static void pfq_add(int c, int add); static void set_pzs(int bits); uint16_t @@ -200,344 +172,50 @@ clock_end(void) int diff = cycdiff - cycles; /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ - tsc += ((uint64_t) diff * (xt_cpu_multi >> 32ULL)); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ + tsc += (uint64_t) diff * ((uint64_t) xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) timer_process(); } static void -process_timers(void) +fetch_and_bus(int c, int bus) { - clock_end(); - clock_start(); -} + if (refresh > 0) { + /* Finish the current fetch, if any. */ + cycles -= ((4 - (biu_cycles & 3)) & 3); + pfq_add((4 - (biu_cycles & 3)) & 3, 1); + /* Add 4 memory access cycles. */ + cycles -= 4; + pfq_add(4, 0); -static void -cycles_forward(int c) -{ - cycles -= c; - - if (!is286) - process_timers(); -} - -static void -bus_outb(uint16_t port, uint8_t val) -{ - int old_cycles = cycles; - - cycles--; - outb(port, val); - resub_cycles(old_cycles); -} - -static void -bus_outw(uint16_t port, uint16_t val) -{ - int old_cycles = cycles; - - cycles--; - outw(port, val); - resub_cycles(old_cycles); -} - -static uint8_t -bus_inb(uint16_t port) -{ - int old_cycles = cycles; - uint8_t ret; - - cycles--; - ret = inb(port); - resub_cycles(old_cycles); - - return ret; -} - -static uint16_t -bus_inw(uint16_t port) -{ - int old_cycles = cycles; - uint16_t ret; - - cycles--; - ret = inw(port); - resub_cycles(old_cycles); - - return ret; -} - -static void -bus_do_io(int io_type) -{ - last_was_code = 0; - - x808x_log("(%02X) bus_do_io(%02X): %04X\n", opcode, io_type, cpu_state.eaaddr); - - if (io_type & BUS_OUT) { - if (io_type & BUS_WIDE) - bus_outw((uint16_t) cpu_state.eaaddr, AX); - else if (io_type & BUS_HIGH) - bus_outb(((uint16_t) cpu_state.eaaddr + 1) & 0xffff, AH); - else - bus_outb((uint16_t) cpu_state.eaaddr, AL); - } else { - if (io_type & BUS_WIDE) - AX = bus_inw((uint16_t) cpu_state.eaaddr); - else if (io_type & BUS_HIGH) - AH = bus_inb(((uint16_t) cpu_state.eaaddr + 1) & 0xffff); - else - AL = bus_inb((uint16_t) cpu_state.eaaddr); - } - - process_timers(); -} - -static void -bus_writeb(uint32_t seg, uint32_t addr, uint8_t val) -{ - write_mem_b(seg + addr, val); -} - -static void -bus_writew(uint32_t seg, uint32_t addr, uint16_t val) -{ - write_mem_w(seg + addr, val); -} - -static uint8_t -bus_readb(uint32_t seg, uint32_t addr) -{ - uint8_t ret = read_mem_b(seg + addr); - - return ret; -} - -static uint16_t -bus_readw(uint32_t seg, uint32_t addr) -{ - uint16_t ret = read_mem_w(seg + addr); - - return ret; -} - -static void -bus_do_mem(int io_type) -{ - last_was_code = 0; - - if (io_type & BUS_OUT) { - if (io_type & BUS_WIDE) - bus_writew(mem_seg, (uint32_t) mem_addr, mem_data); - else if (io_type & BUS_HIGH) { - if (is186 && !is_nec) - bus_writeb(mem_seg, ((uint32_t) mem_addr) + 1, mem_data >> 8); - else - bus_writeb(mem_seg, (uint32_t) ((mem_addr + 1) & 0xffff), mem_data >> 8); - } else - bus_writeb(mem_seg, (uint32_t) mem_addr, mem_data & 0xff); - } else { - if (io_type & BUS_WIDE) - mem_data = bus_readw(mem_seg, (uint32_t) mem_addr); - else if (io_type & BUS_HIGH) { - if (is186 && !is_nec) - mem_data = (mem_data & 0x00ff) | (((uint16_t) bus_readb(mem_seg, ((uint32_t) mem_addr) + 1)) << 8); - else - mem_data = (mem_data & 0x00ff) | (((uint16_t) bus_readb(mem_seg, (uint32_t) ((mem_addr + 1) & 0xffff))) << 8); - } else - mem_data = (mem_data & 0xff00) | ((uint16_t) bus_readb(mem_seg, (uint32_t) mem_addr)); - } -} - -static void -run_bus_cycle(int io_type) -{ - int do_bus_access = (io_type != 0) && (!(io_type & BUS_CODE) || schedule_fetch); - - x808x_log("[%04X:%04X] %02X bus access %02X (%i)\n", CS, cpu_state.pc, opcode, io_type, do_bus_access); - - if (do_bus_access) { - if (not_ready > 0) { - x808x_log("[%04X:%04X] %02X TW x%i\n", CS, cpu_state.pc, opcode, not_ready); - cycles_forward(not_ready); - not_ready = 0; - } - - switch (BUS_CYCLE) { - case BUS_T1: - access_code = !!(io_type & BUS_CODE); - break; - case BUS_T2: - switch (io_type & BUS_ACCESS_TYPE) { - case BUS_IO: - if (io_type & BUS_OUT) - bus_do_io(io_type); - break; - case BUS_MEM: - if (io_type & BUS_OUT) - bus_do_mem(io_type); - break; - default: - break; - } - break; - case BUS_T3: - switch (io_type & BUS_ACCESS_TYPE) { - case BUS_CODE: - pfq_add(); - last_was_code = 1; - break; - case BUS_IO: - if (!(io_type & BUS_OUT)) - bus_do_io(io_type); - break; - case BUS_MEM: - if (!(io_type & BUS_OUT)) - bus_do_mem(io_type); - break; - case BUS_PIC: - pic_data = pic_irq_ack(); - last_was_code = 0; - break; - default: - break; - } - break; - default: - break; - } - } -} - -static void -run_dma_cycle(int idle) -{ - if (not_ready > 0) { - /* Subtract one not ready cycle. */ - not_ready--; - } else if (hlda > 0) { - hlda--; - /* DMAWAIT is two cycles in, the actual wait states - are inserted with one cycle of delay. */ - if (hlda == 0) { - /* Deassert READY. */ - not_ready = 6; - } - } else if ((refresh > 0) && (in_lock == 0) && (idle || (BUS_CYCLE >= BUS_T3))) { - /* Refresh pending and it's either non-bus cycle or T3-T4, - raise HLDA. */ - hlda = 2; - /* Decrease the refresh count. */ refresh--; } -} -static void -cycles_idle(int c) -{ - for (int d = 0; d < c; d++) { - x808x_log("[%04X:%04X] %02X TI\n", CS, cpu_state.pc, opcode); - - cycles_forward(1); - run_dma_cycle(1); + pfq_add(c, !bus); + if (bus < 2) { + clock_end(); + clock_start(); } } -static void -pfq_schedule(int on) -{ - schedule_fetch = on && prefetching && (pfq_pos < pfq_size); -} - -static void -cycles_biu(int bus, int init) -{ - /* T1, T2 = Nothing, T3 = Start and schedule, T4 = Nothing */ - pasv = (bus || ((BUS_CYCLE == BUS_T1) && schedule_fetch)) ? 0 : 1; - - x808x_log("cycles_biu(%i, %i): %i, %i, %i, %i\n", bus, init, prefetching, pfq_pos, pfq_size, BUS_CYCLE); - if (bus) { - /* CPU wants non-code bus access. */ - if (init) { - if (schedule_fetch) { - switch (BUS_CYCLE) { - case BUS_T1: - case BUS_T2: - BUS_CYCLE_T1; /* Simply abort the prefetch before actual scheduling, no penalty. */ - break; - case BUS_T3: - case BUS_T4: - cycles_idle(5 - BUS_CYCLE); /* Leftover BIU cycles + 2 idle cycles. */ - BUS_CYCLE_T1; /* Abort the prefetch. */ - break; - - default: - break; - } - - pfq_schedule(0); - access_code = 0; - } - } - - run_bus_cycle(bus_request_type); - } else { - /* CPU wants idle or code bus access. */ - if (schedule_fetch) - run_bus_cycle(BUS_CODE); - } - - if (BUS_CYCLE == BUS_T2) - pfq_schedule(1); - - run_dma_cycle(pasv); - - BUS_CYCLE_NEXT; -} - -static void -cycles_pasv(void) -{ - pfq_schedule(1); - - run_dma_cycle(1); -} - -/* Bus: - 0 CPU cycles without bus access. - 1 CPU cycle T1-T4, bus access. - 2 CPU cycle Tw (wait state). - 3 CPU cycle Ti (idle). - */ static void wait(int c, int bus) { - if (c < 0) - pclog("Negative cycles: %i!\n", c); - - x808x_log("[%04X:%04X] %02X %i cycles (%i)\n", CS, cpu_state.pc, opcode, c, bus); - - for (int d = 0; d < c; d++) { - x808x_log("[%04X:%04X] %02X cycle %i BIU\n", CS, cpu_state.pc, opcode, d); - if (!bus && !schedule_fetch && (BUS_CYCLE == BUS_T1)) - cycles_pasv(); - else - cycles_biu(bus, !d); - x808x_log("[%04X:%04X] %02X cycle %i EU\n", CS, cpu_state.pc, opcode, d); - cycles_forward(1); - } + cycles -= c; + fetch_and_bus(c, bus); } -/* This is for external subtraction of cycles, ie. wait states. */ +/* This is for external subtraction of cycles. */ void sub_cycles(int c) { - if (is286) - cycles -= c; - else { - if (c > 0) - cycles_idle(c); - } + if (c <= 0) + return; + + cycles -= c; + + if (!is286) + fetch_and_bus(c, 2); } void @@ -547,14 +225,9 @@ resub_cycles(int old_cycles) if (old_cycles > cycles) { cyc_diff = old_cycles - cycles; - - for (int i = 0; i < cyc_diff; i++) { - if (not_ready > 0) - not_ready--; - } + cycles = old_cycles; + sub_cycles(cyc_diff); } - - process_timers(); } #undef readmemb @@ -565,55 +238,53 @@ resub_cycles(int old_cycles) static void cpu_io(int bits, int out, uint16_t port) { + int old_cycles = cycles; + if (out) { + wait(4, 1); if (bits == 16) { if (is8086 && !(port & 1)) { - bus_request_type = BUS_IO | BUS_OUT | BUS_WIDE; - wait(4, 1); + old_cycles = cycles; + outw(port, AX); } else { - bus_request_type = BUS_IO | BUS_OUT; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_IO | BUS_OUT | BUS_HIGH; wait(4, 1); + old_cycles = cycles; + outb(port++, AL); + outb(port, AH); } } else { - bus_request_type = BUS_IO | BUS_OUT; - wait(4, 1); + old_cycles = cycles; + outb(port, AL); } } else { + wait(4, 1); if (bits == 16) { if (is8086 && !(port & 1)) { - bus_request_type = BUS_IO | BUS_WIDE; - wait(4, 1); + old_cycles = cycles; + AX = inw(port); } else { - bus_request_type = BUS_IO; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_IO | BUS_HIGH; wait(4, 1); + old_cycles = cycles; + AL = inb(port++); + AH = inb(port); } } else { - bus_request_type = BUS_IO; - wait(4, 1); + old_cycles = cycles; + AL = inb(port); } } - bus_request_type = 0; + resub_cycles(old_cycles); } /* Reads a byte from the memory and advances the BIU. */ static uint8_t -readmemb(uint32_t s, uint16_t a) +readmemb(uint32_t a) { uint8_t ret; - mem_seg = s; - mem_addr = a; - bus_request_type = BUS_MEM; wait(4, 1); - ret = mem_data & 0xff; - bus_request_type = 0; + ret = read_mem_b(a); return ret; } @@ -627,8 +298,6 @@ readmembf(uint32_t a) a = cs + (a & 0xffff); ret = read_mem_b(a); - last_was_code = 1; - return ret; } @@ -638,20 +307,14 @@ readmemw(uint32_t s, uint16_t a) { uint16_t ret; - mem_seg = s; - mem_addr = a; - if (is8086 && !(a & 1)) { - bus_request_type = BUS_MEM | BUS_WIDE; - wait(4, 1); - } else { - bus_request_type = BUS_MEM | BUS_HIGH; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_MEM; + wait(4, 1); + if (is8086 && !(a & 1)) + ret = read_mem_w(s + a); + else { wait(4, 1); + ret = read_mem_b(s + a); + ret |= read_mem_b(s + ((is186 && !is_nec) ? (a + 1) : (a + 1) & 0xffff)) << 8; } - ret = mem_data; - bus_request_type = 0; return ret; } @@ -663,8 +326,6 @@ readmemwf(uint16_t a) ret = read_mem_w(cs + (a & 0xffff)); - last_was_code = 1; - return ret; } @@ -674,7 +335,7 @@ readmem(uint32_t s) if (opcode & 1) return readmemw(s, cpu_state.eaaddr); else - return (uint16_t) readmemb(s, cpu_state.eaaddr); + return (uint16_t) readmemb(s + cpu_state.eaaddr); } static uint32_t @@ -696,8 +357,6 @@ readmemq(uint32_t s, uint16_t a) temp = (uint64_t) (readmeml(s, a + 4)) << 32; temp |= readmeml(s, a); - last_was_code = 0; - return temp; } @@ -707,15 +366,8 @@ writememb(uint32_t s, uint32_t a, uint8_t v) { uint32_t addr = s + a; - // if (CS == DEBUG_SEG) - // fatal("writememb(%08X, %08X, %02X)\n", s, a, v); - - mem_seg = s; - mem_addr = a; - mem_data = v; - bus_request_type = BUS_MEM | BUS_OUT; wait(4, 1); - bus_request_type = 0; + write_mem_b(addr, v); if ((addr >= 0xf0000) && (addr <= 0xfffff)) last_addr = addr & 0xffff; @@ -727,20 +379,15 @@ writememw(uint32_t s, uint32_t a, uint16_t v) { uint32_t addr = s + a; - mem_seg = s; - mem_addr = a; - mem_data = v; - if (is8086 && !(a & 1)) { - bus_request_type = BUS_MEM | BUS_OUT | BUS_WIDE; - wait(4, 1); - } else { - bus_request_type = BUS_MEM | BUS_OUT | BUS_HIGH; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_MEM | BUS_OUT; + wait(4, 1); + if (is8086 && !(a & 1)) + write_mem_w(addr, v); + else { + write_mem_b(addr, v & 0xff); wait(4, 1); + addr = s + ((is186 && !is_nec) ? (a + 1) : ((a + 1) & 0xffff)); + write_mem_b(addr, v >> 8); } - bus_request_type = 0; if ((addr >= 0xf0000) && (addr <= 0xfffff)) last_addr = addr & 0xffff; @@ -773,55 +420,38 @@ static void pfq_write(void) { uint16_t tempw; - /* Byte fetch on odd addres on 8086 to simulate the HL toggle. */ - int fetch_word = is8086 && !(pfq_ip & 1); - if (fetch_word && (pfq_pos < (pfq_size - 1))) { + if (is8086 && (pfq_pos < (pfq_size - 1))) { /* The 8086 fetches 2 bytes at a time, and only if there's at least 2 bytes free in the queue. */ tempw = readmemwf(pfq_ip); *(uint16_t *) &(pfq[pfq_pos]) = tempw; - pfq_ip = (pfq_ip + 2) & 0xffff; + pfq_ip += 2; pfq_pos += 2; - - if (pfq_pos >= (pfq_size - 1)) - pfq_schedule(0); - } else if (!fetch_word && (pfq_pos < pfq_size)) { + } else if (!is8086 && (pfq_pos < pfq_size)) { /* The 8088 fetches 1 byte at a time, and only if there's at least 1 byte free in the queue. */ pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip = (pfq_ip + 1) & 0xffff; + pfq_ip++; pfq_pos++; - - if (pfq_pos >= pfq_size) - pfq_schedule(0); } - - if (pfq_pos >= pfq_size) - pfq_pos = pfq_size; } static uint8_t pfq_read(void) { - uint8_t temp; + uint8_t temp, i; temp = pfq[0]; - for (int i = 0; i < (pfq_size - 1); i++) + for (i = 0; i < (pfq_size - 1); i++) pfq[i] = pfq[i + 1]; pfq_pos--; - if (pfq_pos < 0) - pfq_pos = 0; cpu_state.pc = (cpu_state.pc + 1) & 0xffff; return temp; } /* Fetches a byte from the prefetch queue, or from memory if the queue has - been drained. - - Cycles: 1 If fetching from the queue; - (4 - (biu_cycles & 3)) If fetching from the bus - fetch into the queue; - 1 If fetching from the bus - delay. */ + been drained. */ static uint8_t pfq_fetchb_common(void) { @@ -831,8 +461,7 @@ pfq_fetchb_common(void) /* Reset prefetch queue internal position. */ pfq_ip = cpu_state.pc; /* Fill the queue. */ - while (pfq_pos == 0) - wait(1, 0); + wait(4 - (biu_cycles & 3), 0); } /* Fetch. */ @@ -840,7 +469,6 @@ pfq_fetchb_common(void) return temp; } -/* The timings are above. */ static uint8_t pfq_fetchb(void) { @@ -876,36 +504,26 @@ pfq_fetch(void) /* Adds bytes to the prefetch queue based on the instruction's cycle count. */ static void -pfq_add(void) +pfq_add(int c, int add) { - if (prefetching && (pfq_pos < pfq_size)) - pfq_write(); + int d; + + if ((c <= 0) || (pfq_pos >= pfq_size)) + return; + + for (d = 0; d < c; d++) { + biu_cycles = (biu_cycles + 1) & 0x03; + if (prefetching && add && (biu_cycles == 0x00)) + pfq_write(); + } } /* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */ static void pfq_clear(void) { - pfq_pos = 0; - - BUS_CYCLE_T1; -} - -static void -pfq_do_suspend(void) -{ - while (BUS_CYCLE != BUS_T1) - wait(1, 0); - wait(1, 0); - pfq_schedule(0); - prefetching = 0; -} - -static void -pfq_suspend(void) -{ - pfq_do_suspend(); - pfq_clear(); + pfq_pos = 0; + prefetching = 0; } static void @@ -925,7 +543,7 @@ load_seg(uint16_t seg, x86seg *s) void reset_808x(int hard) { - BUS_CYCLE_T1; + biu_cycles = 0; in_rep = 0; in_lock = 0; completed = 1; @@ -944,7 +562,7 @@ reset_808x(int hard) _opseg[2] = &cpu_state.seg_ss; _opseg[3] = &cpu_state.seg_ds; - pfq_size = is8086 ? 6 : 4; + pfq_size = (is8086) ? 6 : 4; pfq_clear(); } @@ -954,25 +572,11 @@ reset_808x(int hard) cpu_state.flags |= MD_FLAG; rammask = 0xfffff; - pasv = 0; - - cpu_alu_op = 0; + prefetching = 1; + cpu_alu_op = 0; use_custom_nmi_vector = 0x00; custom_nmi_vector = 0x00000000; - - access_code = 0; - hlda = 0; - not_ready = 0; - bus_request_type = 0; - pic_data = -1; - last_was_code = 0; - mem_data = 0; - mem_seg = 0; - mem_addr = 0; - - prefetching = 1; - pfq_schedule(1); } static void @@ -980,7 +584,6 @@ set_ip(uint16_t new_ip) { pfq_ip = cpu_state.pc = new_ip; prefetching = 1; - pfq_schedule(1); } /* Memory refresh read - called by reads and writes on DMA channel 0. */ @@ -1023,11 +626,12 @@ do_mod_rm(void) if (cpu_mod == 3) return; - wait(2, 0); + wait(1, 0); if ((rmdat & 0xc7) == 0x06) { + wait(1, 0); cpu_state.eaaddr = pfq_fetchw(); easeg = ovr_seg ? *ovr_seg : ds; - wait(2, 0); + wait(1, 0); return; } else switch (cpu_rm) { @@ -1039,24 +643,17 @@ do_mod_rm(void) case 2: wait(3, 0); break; - - default: - break; } cpu_state.eaaddr = (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); easeg = ovr_seg ? *ovr_seg : *mod1seg[cpu_rm]; switch (rmdat & 0xc0) { case 0x40: - wait(2, 0); + wait(3, 0); cpu_state.eaaddr += sign_extend(pfq_fetchb()); - wait(1, 0); break; case 0x80: - wait(2, 0); + wait(3, 0); cpu_state.eaaddr += pfq_fetchw(); - wait(1, 0); - break; - default: break; } cpu_state.eaaddr &= 0xffff; @@ -1080,7 +677,7 @@ geteab(void) if (cpu_mod == 3) return (getr8(cpu_rm)); - return readmemb(easeg, cpu_state.eaaddr); + return readmemb(easeg + cpu_state.eaaddr); } /* Reads a word from the effective address. */ @@ -1124,7 +721,7 @@ read_ea(int memory_only, int bits) if (bits == 16) cpu_data = readmemw(easeg, cpu_state.eaaddr); else - cpu_data = readmemb(easeg, cpu_state.eaaddr); + cpu_data = readmemb(easeg + cpu_state.eaaddr); return; } if (!memory_only) { @@ -1142,7 +739,7 @@ read_ea2(int bits) if (bits == 16) cpu_data = readmemw(easeg, cpu_state.eaaddr); else - cpu_data = readmemb(easeg, cpu_state.eaaddr); + cpu_data = readmemb(easeg + cpu_state.eaaddr); } /* Writes a byte to the effective address. */ @@ -1151,10 +748,8 @@ seteab(uint8_t val) { if (cpu_mod == 3) { setr8(cpu_rm, val); - } else { - wait(1, 0); + } else writememb(easeg, cpu_state.eaaddr, val); - } } /* Writes a word to the effective address. */ @@ -1163,10 +758,8 @@ seteaw(uint16_t val) { if (cpu_mod == 3) cpu_state.regs[cpu_rm].w = val; - else { - wait(1, 0); + else writememw(easeg, cpu_state.eaaddr, val); - } } static void @@ -1222,129 +815,206 @@ pop(void) } static void -nearcall(uint16_t new_ip) +access(int num, int bits) { - uint16_t ret_ip = cpu_state.pc & 0xffff; - - wait(1, 0); - set_ip(new_ip); - pfq_clear(); - wait(3, 0); - push(&ret_ip); -} - -static void -farcall2(uint16_t new_cs, uint16_t new_ip) -{ - wait(3, 0); - push(&CS); - load_cs(new_cs); - wait(2, 0); - nearcall(new_ip); + switch (num) { + case 0: + case 61: + case 63: + case 64: + case 67: + case 69: + case 71: + case 72: + default: + break; + case 1: + case 6: + case 7: + case 8: + case 9: + case 17: + case 20: + case 21: + case 24: + case 28: + case 47: + case 48: + case 49: + case 50: + case 51: + case 55: + case 56: + case 62: + case 66: + case 68: + wait(1, 0); + break; + case 3: + case 11: + case 15: + case 22: + case 23: + case 25: + case 26: + case 35: + case 44: + case 45: + case 46: + case 52: + case 53: + case 54: + wait(2, 0); + break; + case 16: + case 18: + case 19: + case 27: + case 32: + case 37: + case 42: + wait(3, 0); + break; + case 10: + case 12: + case 13: + case 14: + case 29: + case 30: + case 33: + case 34: + case 39: + case 41: + case 60: + wait(4, 0); + break; + case 4: + case 70: + wait(5, 0); + break; + case 31: + case 38: + case 40: + wait(6, 0); + break; + case 5: + if (opcode == 0xcc) + wait(7, 0); + else + wait(4, 0); + break; + case 36: + wait(1, 0); + pfq_clear(); + wait(1, 0); + if (cpu_mod != 3) + wait(1, 0); + wait(3, 0); + break; + case 43: + wait(2, 0); + pfq_clear(); + wait(1, 0); + break; + case 57: + if (cpu_mod != 3) + wait(2, 0); + wait(4, 0); + break; + case 58: + if (cpu_mod != 3) + wait(1, 0); + wait(4, 0); + break; + case 59: + wait(2, 0); + pfq_clear(); + if (cpu_mod != 3) + wait(1, 0); + wait(3, 0); + break; + case 65: + wait(1, 0); + pfq_clear(); + wait(2, 0); + if (cpu_mod != 3) + wait(1, 0); + break; + } } /* Calls an interrupt. */ -/* The INTR microcode routine. */ static void -intr_routine(uint16_t intr, int skip_first) +interrupt(uint16_t addr) { - uint16_t vector = intr * 4; - uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); - uint16_t new_cs; - uint16_t new_ip; + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; - if (!skip_first) - wait(1, 0); - wait(2, 0); - - cpu_state.eaaddr = vector & 0xffff; - new_ip = readmemw(0, cpu_state.eaaddr); + addr <<= 2; + cpu_state.eaaddr = addr; + old_cs = CS; + access(5, 16); + new_ip = readmemw(0, cpu_state.eaaddr); wait(1, 0); cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; - new_cs = readmemw(0, cpu_state.eaaddr); - - pfq_do_suspend(); - wait(2, 0); - push(&tempf); - cpu_state.flags &= ~(I_FLAG | T_FLAG); - wait(1, 0); - - farcall2(new_cs, new_ip); -} - -static void -sw_int(uint16_t intr) -{ - uint16_t vector = intr * 4; - uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); - uint16_t new_cs; - uint16_t new_ip; - uint16_t old_ip; - - wait(3, 0); - cpu_state.eaaddr = vector & 0xffff; - new_ip = readmemw(0, cpu_state.eaaddr); - wait(1, 0); - cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; - new_cs = readmemw(0, cpu_state.eaaddr); - pfq_do_suspend(); - wait(2, 0); - push(&tempf); - cpu_state.flags &= ~(I_FLAG | T_FLAG); - - /* FARCALL2 */ - wait(4, 0); - push(&CS); - load_cs(new_cs); - wait(1, 0); - - /* NEARCALL */ - old_ip = cpu_state.pc & 0xffff; - wait(2, 0); - set_ip(new_ip); + access(6, 16); + new_cs = readmemw(0, cpu_state.eaaddr); + prefetching = 0; pfq_clear(); - wait(3, 0); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + push(&tempf); + cpu_state.flags &= ~(I_FLAG | T_FLAG); + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); push(&old_ip); } -static void -int3(void) -{ - wait(4, 0); - intr_routine(3, 0); -} - void interrupt_808x(uint16_t addr) { - intr_routine(addr, 0); + interrupt(addr); } static void custom_nmi(void) { - uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); - uint16_t new_cs; - uint16_t new_ip; - - wait(1, 0); - wait(2, 0); + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; cpu_state.eaaddr = 0x0002; + old_cs = CS; + access(5, 16); (void) readmemw(0, cpu_state.eaaddr); new_ip = custom_nmi_vector & 0xffff; wait(1, 0); cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + access(6, 16); (void) readmemw(0, cpu_state.eaaddr); - new_cs = custom_nmi_vector >> 16; - - pfq_do_suspend(); - wait(2, 0); + new_cs = custom_nmi_vector >> 16; + prefetching = 0; + pfq_clear(); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); - wait(1, 0); - - farcall2(new_cs, new_ip); + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); + push(&old_ip); } static int @@ -1357,18 +1027,6 @@ irq_pending(void) return temp; } -static int -bus_pic_ack(void) -{ - int old_in_lock = in_lock; - - in_lock = 1; - bus_request_type = BUS_PIC; - wait(4, 1); - in_lock = old_in_lock; - return pic_data; -} - static void check_interrupts(void) { @@ -1376,17 +1034,15 @@ check_interrupts(void) if (irq_pending()) { if ((cpu_state.flags & T_FLAG) && !noint) { - wait(2, 0); - intr_routine(1, 0); + interrupt(1); return; } if (nmi && nmi_enable && nmi_mask) { nmi_enable = 0; - wait(2, 0); if (use_custom_nmi_vector) custom_nmi(); else - intr_routine(2, 0); + interrupt(2); #ifndef OLD_NMI_BEHAVIOR nmi = 0; #endif @@ -1396,75 +1052,65 @@ check_interrupts(void) repeating = 0; completed = 1; ovr_seg = NULL; - wait(4, 0); + wait(3, 0); /* ACK to PIC */ - temp = bus_pic_ack(); + temp = pic_irq_ack(); + wait(4, 1); wait(1, 0); /* ACK to PIC */ - temp = bus_pic_ack(); + temp = pic_irq_ack(); + wait(4, 1); wait(1, 0); in_lock = 0; clear_lock = 0; - if (BUS_CYCLE != BUS_T3) - wait(1, 0); - wait(5, 0); + wait(1, 0); /* Here is where temp should be filled, but we cheat. */ + wait(3, 0); opcode = 0x00; - intr_routine(temp, 0); + interrupt(temp); } } } -static void -rep_end(void) -{ - repeating = 0; - in_rep = 0; - completed = 1; -} - static int -rep_start(void) +rep_action(int bits) { - if (!repeating) { - wait(2, 0); + uint16_t t; - if (in_rep != 0) { - if (CX == 0) { - wait(4, 0); - rep_end(); - return 0; - } else - wait(7, 0); - } + if (in_rep == 0) + return 0; + wait(2, 0); + t = CX; + if (irq_pending() && (repeating != 0)) { + access(71, bits); + pfq_clear(); + if (is_nec && (ovr_seg != NULL)) + set_ip(cpu_state.pc - 3); + else + set_ip(cpu_state.pc - 2); + t = 0; } - - completed = 1; - return 1; -} - -static void -rep_interrupt(void) -{ - pfq_do_suspend(); - wait(4, 0); - pfq_clear(); - - if (is_nec && (ovr_seg != NULL)) - set_ip((cpu_state.pc - 3) & 0xffff); - else - set_ip((cpu_state.pc - 2) & 0xffff); - - rep_end(); + if (t == 0) { + wait(1, 0); + completed = 1; + repeating = 0; + return 1; + } + --CX; + completed = 0; + wait(2, 0); + if (!repeating) + wait(2, 0); + return 0; } static uint16_t jump(uint16_t delta) { uint16_t old_ip; - wait(1, 0); - pfq_suspend(); - cycles_idle(1); + access(67, 8); + pfq_clear(); + wait(5, 0); old_ip = cpu_state.pc; set_ip((cpu_state.pc + delta) & 0xffff); return old_ip; @@ -1486,6 +1132,8 @@ jump_near(void) static void jcc(uint8_t opcode, int cond) { + /* int8_t offset; */ + wait(1, 0); cpu_data = pfq_fetchb(); wait(1, 0); @@ -1614,14 +1262,14 @@ alu_op(int bits) case 2: if (cpu_state.flags & C_FLAG) cpu_src++; - fallthrough; + /* Fall through. */ case 0: add(bits); break; case 3: if (cpu_state.flags & C_FLAG) cpu_src++; - fallthrough; + /* Fall through. */ case 5: case 7: sub(bits); @@ -1632,9 +1280,6 @@ alu_op(int bits) case 6: bitwise(bits, (cpu_dest ^ cpu_src)); break; - - default: - break; } } @@ -1655,11 +1300,10 @@ mul(uint16_t a, uint16_t b) { int negate = 0; int bit_count = 8; - int carry; + int carry, i; uint16_t high_bit = 0x80; uint16_t size_mask; - uint16_t c; - uint16_t r; + uint16_t c, r; size_mask = (1 << bit_count) - 1; @@ -1700,7 +1344,7 @@ mul(uint16_t a, uint16_t b) a &= size_mask; carry = (a & 1) != 0; a >>= 1; - for (int i = 0; i < bit_count; ++i) { + for (i = 0; i < bit_count; ++i) { wait(7, 0); if (carry) { cpu_src = c; @@ -1761,7 +1405,7 @@ set_pzs(int bits) } static void -set_co_mul(UNUSED(int bits), int carry) +set_co_mul(int bits, int carry) { set_cf(carry); set_of(carry); @@ -1774,11 +1418,10 @@ set_co_mul(UNUSED(int bits), int carry) static int x86_div(uint16_t l, uint16_t h) { - int bit_count = 8; + int b, bit_count = 8; int negative = 0; int dividend_negative = 0; - int size_mask; - int carry; + int size_mask, carry; uint16_t r; if (opcode & 1) { @@ -1815,14 +1458,14 @@ x86_div(uint16_t l, uint16_t h) if (h >= cpu_src) { if (opcode != 0xd4) wait(1, 0); - intr_routine(0, 0); + interrupt(0); return 0; } if (opcode != 0xd4) wait(1, 0); wait(2, 0); carry = 1; - for (int b = 0; b < bit_count; ++b) { + for (b = 0; b < bit_count; ++b) { r = (l << 1) + (carry ? 1 : 0); carry = top_bit(l, bit_count); l = r; @@ -1851,7 +1494,7 @@ x86_div(uint16_t l, uint16_t h) if (top_bit(l, bit_count)) { if (cpu_mod == 3) wait(1, 0); - intr_routine(0, 0); + interrupt(0); return 0; } wait(7, 0); @@ -1893,21 +1536,10 @@ lods(int bits) if (bits == 16) cpu_data = readmemw((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); else - cpu_data = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + cpu_data = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); SI = string_increment(bits); } -static void -lods_di(int bits) -{ - cpu_state.eaaddr = DI; - if (bits == 16) - cpu_data = readmemw(es, cpu_state.eaaddr); - else - cpu_data = readmemb(es, cpu_state.eaaddr); - DI = string_increment(bits); -} - static void stos(int bits) { @@ -1919,22 +1551,6 @@ stos(int bits) DI = string_increment(bits); } -static void -ins(int bits) -{ - cpu_state.eaaddr = DX; - cpu_io(bits, 0, cpu_state.eaaddr); - stos(bits); -} - -static void -outs(int bits) -{ - lods(bits); - cpu_state.eaaddr = DX; - cpu_io(bits, 1, cpu_state.eaaddr); -} - static void aa(void) { @@ -2028,82 +1644,23 @@ cpu_outw(uint16_t port, uint16_t val) return outw(port, val); } -/* The FARRET microcode routine. */ -static void -farret(int far) -{ - uint8_t far2 = !!(opcode & 0x08); - uint16_t new_cs; - uint16_t new_ip; - - wait(1, 0); - new_ip = pop(); - pfq_do_suspend(); - wait(2, 0); - - if ((!!far) != far2) - fatal("Far call distance mismatch (%i = %i)\n", !!far, far2); - - if (far) { - wait(1, 0); - new_cs = pop(); - - pfq_clear(); - wait(2, 0); - } else { - pfq_clear(); - wait(2, 0); - } - - wait(2, 0); - if (far) - load_cs(new_cs); - set_ip(new_ip); -} - /* Executes instructions up to the specified number of cycles. */ void -execx86(int32_t cycs) +execx86(int cycs) { - uint8_t temp = 0; - uint8_t temp2; - uint8_t old_af; - uint8_t nests; - uint8_t temp_val; - uint8_t temp_al; - uint8_t bit; - uint8_t handled = 0; - uint8_t odd; - uint8_t zero; - uint8_t nibbles_count; - uint8_t destcmp; - uint8_t destbyte; - uint8_t srcbyte; - uint8_t nibble_result; - uint8_t bit_length; + uint8_t temp = 0, temp2, old_af, nests; + uint8_t temp_val, temp_al, bit, handled = 0; + uint8_t odd, zero, nibbles_count, destcmp; + uint8_t destbyte, srcbyte, nibble_result, bit_length; uint8_t bit_offset; int8_t nibble_result_s; - uint16_t addr; - uint16_t tempw; - uint16_t new_cs; - uint16_t new_ip; - uint16_t tempw_int; - uint16_t size; - uint16_t tempbp; - uint16_t lowbound; - uint16_t highbound; - uint16_t regval; - uint16_t orig_sp; - uint16_t wordtopush; - uint16_t immediate; - uint16_t old_flags; - uint16_t tmpa; + uint16_t addr, tempw, new_cs, new_ip; + uint16_t tempw_int, size, tempbp, lowbound; + uint16_t highbound, regval, orig_sp, wordtopush; + uint16_t immediate, old_flags; int bits; - uint32_t i; - uint32_t carry; - uint32_t nibble; - uint32_t srcseg; - uint32_t byteaddr; + uint32_t dest_seg, i, carry, nibble; + uint32_t srcseg, byteaddr; cycles += cycs; @@ -2112,9 +1669,9 @@ execx86(int32_t cycs) if (!repeating) { cpu_state.oldpc = cpu_state.pc; - opcode = pfq_fetchb_common(); - handled = 0; - oldc = cpu_state.flags & C_FLAG; + opcode = pfq_fetchb(); + handled = 0; + oldc = cpu_state.flags & C_FLAG; if (clear_lock) { in_lock = 0; clear_lock = 0; @@ -2123,7 +1680,7 @@ execx86(int32_t cycs) } completed = 1; - x808x_log("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); + // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); if (is186) { switch (opcode) { case 0x60: /*PUSHA/PUSH R*/ @@ -2163,7 +1720,7 @@ execx86(int32_t cycs) regval = get_reg(cpu_reg); if (lowbound > regval || highbound < regval) { cpu_state.pc = cpu_state.oldpc; - intr_routine(5, 0); + interrupt(5); } handled = 1; break; @@ -2219,60 +1776,58 @@ execx86(int32_t cycs) case 0x6c: case 0x6d: /* INM dst, DW/INS dst, DX */ + bits = 8 << (opcode & 1); handled = 1; - bits = 8 << (opcode & 1); - if (rep_start()) { - ins(bits); - wait(3, 0); + if (!repeating) + wait(2, 0); - if (in_rep != 0) { - completed = 0; - repeating = 1; + if (rep_action(bits)) + break; + else if (!repeating) + wait(7, 0); - wait(1, 0); - CX--; - - if (irq_pending()) { - wait(2, 0); - rep_interrupt(); - } else { - wait(2, 0); - - if (CX == 0) - rep_end(); - else - wait(1, 0); - } - } + if (bits == 16) { + writememw(es, DI, cpu_inw(DX)); + DI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + writememb(es, DI, inb(DX)); + DI += (cpu_state.flags & D_FLAG) ? -1 : 1; } + + if (in_rep == 0) + break; + + repeating = 1; + clock_end(); break; case 0x6e: case 0x6f: /* OUTM DW, src/OUTS DX, src */ - handled = 1; - bits = 8 << (opcode & 1); - if (rep_start()) { - wait(1, 0); - outs(bits); - if (in_rep != 0) { - completed = 0; - repeating = 1; + dest_seg = ovr_seg ? *ovr_seg : ds; + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait(2, 0); - wait(1, 0); - if (irq_pending()) { - wait(1, 0); - rep_interrupt(); - } + if (rep_action(bits)) + break; + else if (!repeating) + wait(7, 0); - wait(1, 0); - CX--; - if (CX == 0) - rep_end(); - else - wait(1, 0); - } else - wait(1, 0); + if (bits == 16) { + cpu_outw(DX, readmemw(dest_seg, SI)); + SI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + outb(DX, readmemb(dest_seg + SI)); + SI += (cpu_state.flags & D_FLAG) ? -1 : 1; } + if (in_rep == 0) + break; + + repeating = 1; + clock_end(); break; case 0xc8: /* ENTER/PREPARE */ @@ -2303,6 +1858,7 @@ execx86(int32_t cycs) do_mod_rm(); if (cpu_mod == 3) wait(1, 0); + access(53, bits); cpu_data = get_ea(); cpu_src = pfq_fetchb(); @@ -2376,14 +1932,12 @@ execx86(int32_t cycs) set_af(0); set_pzs(bits); break; - - default: - break; } if ((opcode & 2) != 0) wait(4, 0); --cpu_src; } + access(17, bits); set_ea(cpu_data); handled = 1; break; @@ -2393,9 +1947,6 @@ execx86(int32_t cycs) BP = pop(); handled = 1; break; - - default: - break; } } if (!handled) { @@ -2404,7 +1955,7 @@ execx86(int32_t cycs) case 0x0E: case 0x16: case 0x1E: /* PUSH seg */ - wait(3, 0); + access(29, 16); push(&(_opseg[(opcode >> 3) & 0x03]->seg)); break; case 0x07: @@ -2647,7 +2198,7 @@ execx86(int32_t cycs) } for (i = 0; i < bit_length; i++) { byteaddr = (es) + DI; - writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << bit_offset)) | ((!!(AX & (1 << i))) << bit_offset)); + writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); bit_offset++; if (bit_offset == 8) { DI++; @@ -2678,7 +2229,7 @@ execx86(int32_t cycs) AX = 0; for (i = 0; i < bit_length; i++) { byteaddr = (ds) + SI; - AX |= (!!(readmemb((ds), SI) & (1 << bit_offset))) << i; + AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; bit_offset++; if (bit_offset == 8) { SI++; @@ -2696,20 +2247,23 @@ execx86(int32_t cycs) break; default: - opcode = orig_opcode; - cpu_state.pc = (cpu_state.pc - 1) & 0xffff; + opcode = orig_opcode; + cpu_state.pc--; break; } - } else { - wait(1, 0); - if (opcode == 0x0F) { - load_cs(pop()); - pfq_pos = 0; - } else - load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); - /* All POP segment instructions suppress interrupts for one instruction. */ - noint = 1; - } + } else + handled = 0; + if (handled) + break; + access(22, 16); + if (opcode == 0x0F) { + load_cs(pop()); + pfq_pos = 0; + } else + load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); + wait(1, 0); + /* All POP segment instructions suppress interrupts for one instruction. */ + noint = 1; break; case 0x26: /*ES:*/ @@ -2721,164 +2275,96 @@ execx86(int32_t cycs) completed = 0; break; - case 0x00: /* ADD r/m8, r8; r8, r/m8; al, imm8 */ + case 0x00: + case 0x01: case 0x02: - case 0x04: - case 0x08: /* OR r/m8, r8; r8, r/m8; al, imm8 */ - case 0x0a: - case 0x0c: - case 0x10: /* ADC r/m8, r8; r8, r/m8; al, imm8 */ - case 0x12: - case 0x14: - case 0x18: /* SBB r/m8, r8; r8, r/m8; al, imm8 */ - case 0x1a: - case 0x1c: - case 0x20: /* AND r/m8, r8; r8, r/m8; al, imm8 */ - case 0x22: - case 0x24: - case 0x28: /* SUB r/m8, r8; r8, r/m8; al, imm8 */ - case 0x2a: - case 0x2c: - case 0x30: /* XOR r/m8, r8; r8, r/m8; al, imm8 */ - case 0x32: - case 0x34: - bits = 8; - wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } - cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - if (cpu_mod == 3) - wait(2, 0); - - alu_op(bits); - if (opcode & 0x04) - set_accum(bits, cpu_data); - else { - if (opcode & 2) - set_reg(cpu_reg, cpu_data); - else - set_ea(cpu_data); - } - break; - - case 0x01: /* ADD r/m16, r16; r16, r/m16; ax, imm16 */ case 0x03: - case 0x05: - case 0x09: /* OR r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x08: + case 0x09: + case 0x0a: case 0x0b: - case 0x0d: - case 0x11: /* ADC r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x10: + case 0x11: + case 0x12: case 0x13: - case 0x15: - case 0x19: /* SBB r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x18: + case 0x19: + case 0x1a: case 0x1b: - case 0x1d: - case 0x21: /* AND r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x20: + case 0x21: + case 0x22: case 0x23: - case 0x25: - case 0x29: /* SUB r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x28: + case 0x29: + case 0x2a: case 0x2b: - case 0x2d: - case 0x31: /* XOR r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x30: + case 0x31: + case 0x32: case 0x33: - case 0x35: - bits = 16; - wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } - cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - if (cpu_mod == 3) - wait(2, 0); - - alu_op(bits); - if (opcode & 0x04) - set_accum(bits, cpu_data); - else { - if (opcode & 2) - set_reg(cpu_reg, cpu_data); - else - set_ea(cpu_data); - } - break; - - case 0x38: /* CMP r/m8, r8; r8, r/m8; al, imm8 */ + case 0x38: + case 0x39: case 0x3a: - case 0x3c: - bits = 8; - wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } + case 0x3b: + /* alu rm, r / r, rm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(46, bits); + tempw = get_ea(); cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - + if ((opcode & 2) == 0) { + cpu_dest = tempw; + cpu_src = get_reg(cpu_reg); + } else { + cpu_dest = get_reg(cpu_reg); + cpu_src = tempw; + } + if (cpu_mod != 3) + wait(2, 0); + wait(1, 0); alu_op(bits); + if (cpu_alu_op != 7) { + if ((opcode & 2) == 0) { + access(10, bits); + set_ea(cpu_data); + if (cpu_mod == 3) + wait(1, 0); + } else { + set_reg(cpu_reg, cpu_data); + wait(1, 0); + } + } else + wait(1, 0); break; - case 0x39: /* CMP r/m16, r16; r16, r/m16; ax, imm16 */ - case 0x3b: + case 0x04: + case 0x05: + case 0x0c: + case 0x0d: + case 0x14: + case 0x15: + case 0x1c: + case 0x1d: + case 0x24: + case 0x25: + case 0x2c: + case 0x2d: + case 0x34: + case 0x35: + case 0x3c: case 0x3d: - bits = 16; + /* alu A, imm */ + bits = 8 << (opcode & 1); wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } + cpu_data = pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - alu_op(bits); + if (cpu_alu_op != 7) + set_accum(bits, cpu_data); + wait(1, 0); break; case 0x27: /*DAA*/ @@ -2999,7 +2485,7 @@ execx86(int32_t cycs) case 0x55: case 0x56: case 0x57: - wait(3, 0); + access(30, 16); push(&(cpu_state.regs[opcode & 0x07].w)); break; case 0x58: @@ -3010,8 +2496,9 @@ execx86(int32_t cycs) case 0x5D: case 0x5E: case 0x5F: - wait(1, 0); + access(23, 16); cpu_state.regs[opcode & 0x07].w = pop(); + wait(1, 0); break; case 0x60: /*JO alias*/ @@ -3074,14 +2561,18 @@ execx86(int32_t cycs) /* alu rm, imm */ bits = 8 << (opcode & 1); do_mod_rm(); + access(47, bits); cpu_data = get_ea(); cpu_dest = cpu_data; if (cpu_mod != 3) - wait(1, 0); - wait(1, 0); - if (opcode == 0x81) + wait(3, 0); + if (opcode == 0x81) { + if (cpu_mod == 3) + wait(1, 0); cpu_src = pfq_fetchw(); - else { + } else { + if (cpu_mod == 3) + wait(1, 0); if (opcode == 0x83) cpu_src = sign_extend(pfq_fetchb()); else @@ -3091,8 +2582,7 @@ execx86(int32_t cycs) cpu_alu_op = (rmdat & 0x38) >> 3; alu_op(bits); if (cpu_alu_op != 7) { - if (cpu_mod != 3) - wait(1, 0); + access(11, bits); set_ea(cpu_data); } else { if (cpu_mod != 3) @@ -3105,10 +2595,11 @@ execx86(int32_t cycs) /* TEST rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); + access(48, bits); cpu_data = get_ea(); test(bits, cpu_data, get_reg(cpu_reg)); - if (cpu_mod != 3) - wait(1, 0); + if (cpu_mod == 3) + wait(2, 0); wait(2, 0); break; case 0x86: @@ -3116,12 +2607,12 @@ execx86(int32_t cycs) /* XCHG rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); + access(49, bits); cpu_data = get_ea(); cpu_src = get_reg(cpu_reg); set_reg(cpu_reg, cpu_data); wait(3, 0); - if (cpu_mod != 3) - wait(3, 0); + access(12, bits); set_ea(cpu_src); break; @@ -3131,8 +2622,7 @@ execx86(int32_t cycs) bits = 8 << (opcode & 1); do_mod_rm(); wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); + access(13, bits); set_ea(get_reg(cpu_reg)); break; case 0x8A: @@ -3140,17 +2630,18 @@ execx86(int32_t cycs) /* MOV reg, rm */ bits = 8 << (opcode & 1); do_mod_rm(); + access(50, bits); set_reg(cpu_reg, get_ea()); wait(1, 0); if (cpu_mod != 3) - wait(1, 0); + wait(2, 0); break; case 0x8C: /*MOV w,sreg*/ do_mod_rm(); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); + if (cpu_mod == 3) + wait(1, 0); + access(14, 16); seteaw(_opseg[(rmdat & 0x18) >> 3]->seg); break; @@ -3159,34 +2650,36 @@ execx86(int32_t cycs) cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; wait(1, 0); if (cpu_mod != 3) - wait(1, 0); + wait(2, 0); break; case 0x8E: /*MOV sreg,w*/ do_mod_rm(); + access(51, 16); tempw = geteaw(); - if ((rmdat & 0x18) == 0x08) + if ((rmdat & 0x18) == 0x08) { load_cs(tempw); - else + pfq_pos = 0; + } else load_seg(tempw, _opseg[(rmdat & 0x18) >> 3]); wait(1, 0); if (cpu_mod != 3) - wait(1, 0); + wait(2, 0); if (((rmdat & 0x18) >> 3) == 2) noint = 1; break; case 0x8F: /*POPW*/ do_mod_rm(); - wait(2, 0); - cpu_src = cpu_state.eaaddr; - if (cpu_mod != 3) - wait(1, 0); wait(1, 0); + cpu_src = cpu_state.eaaddr; + access(24, 16); if (cpu_mod != 3) wait(2, 0); cpu_data = pop(); cpu_state.eaaddr = cpu_src; + wait(2, 0); + access(15, 16); seteaw(cpu_data); break; @@ -3224,14 +2717,14 @@ execx86(int32_t cycs) new_ip = pfq_fetchw(); wait(1, 0); new_cs = pfq_fetchw(); - wait(1, 0); - pfq_suspend(); + pfq_clear(); + access(31, 16); push(&(CS)); - wait(4, 0); + access(60, 16); cpu_state.oldpc = cpu_state.pc; load_cs(new_cs); set_ip(new_ip); - wait(1, 0); + access(32, 16); push((uint16_t *) &(cpu_state.oldpc)); break; case 0x9B: /*WAIT*/ @@ -3253,7 +2746,7 @@ execx86(int32_t cycs) #endif break; case 0x9C: /*PUSHF*/ - wait(4, 0); + access(33, 16); if (is_nec) tempw = (cpu_state.flags & 0x8fd7) | 0x7000; else @@ -3261,11 +2754,12 @@ execx86(int32_t cycs) push(&tempw); break; case 0x9D: /*POPF*/ - wait(1, 0); + access(25, 16); if (is_nec) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; + wait(1, 0); break; case 0x9E: /*SAHF*/ wait(1, 0); @@ -3281,49 +2775,58 @@ execx86(int32_t cycs) case 0xA1: /* MOV A, [iw] */ bits = 8 << (opcode & 1); - wait(2, 0); + wait(1, 0); cpu_state.eaaddr = pfq_fetchw(); - set_accum(bits, readmem(ovr_seg ? *ovr_seg : ds)); + access(1, bits); + set_accum(bits, readmem((ovr_seg ? *ovr_seg : ds))); + wait(1, 0); break; case 0xA2: case 0xA3: /* MOV [iw], A */ bits = 8 << (opcode & 1); - wait(2, 0); + wait(1, 0); cpu_state.eaaddr = pfq_fetchw(); + access(7, bits); writemem((ovr_seg ? *ovr_seg : ds), get_accum(bits)); - wait(2, 0); break; case 0xA4: case 0xA5: /* MOVS */ + case 0xAC: + case 0xAD: /* LODS */ bits = 8 << (opcode & 1); - if (rep_start()) { - lods(bits); + if (!repeating) { wait(1, 0); - stos(bits); - wait(1, 0); - - if (in_rep != 0) { - completed = 0; - repeating = 1; - - CX--; - - if (irq_pending()) { - wait(2, 0); - rep_interrupt(); - } else { - wait(2, 0); - - if (CX == 0) - rep_end(); - else - wait(1, 0); - } - } else + if ((opcode & 8) == 0 && in_rep != 0) wait(1, 0); } + if (rep_action(bits)) { + wait(1, 0); + if ((opcode & 8) != 0) + wait(1, 0); + break; + } + if (in_rep != 0 && (opcode & 8) != 0) + wait(1, 0); + access(20, bits); + lods(bits); + if ((opcode & 8) == 0) { + access(27, bits); + stos(bits); + } else { + set_accum(bits, cpu_data); + if (in_rep != 0) + wait(2, 0); + } + if (in_rep == 0) { + wait(3, 0); + if ((opcode & 8) != 0) + wait(1, 0); + break; + } + repeating = 1; + clock_end(); break; case 0xA6: @@ -3331,53 +2834,40 @@ execx86(int32_t cycs) case 0xAE: case 0xAF: /* SCAS */ bits = 8 << (opcode & 1); - if (rep_start()) { - if ((opcode & 8) == 0) { - wait(1, 0); - lods(bits); - tmpa = cpu_data; - } else - tmpa = AX; + if (!repeating) + wait(1, 0); + if (rep_action(bits)) { wait(2, 0); - lods_di(bits); - cpu_src = cpu_data; - cpu_dest = tmpa; - wait(3, 0); - sub(bits); - - if (in_rep) { - uint8_t end = 0; - - completed = 0; - repeating = 1; - - wait(1, 0); - - CX--; - - if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { - completed = 1; - wait(1, 0); - end = 1; - } - - if (!end) { - wait(1, 0); - - if (irq_pending()) { - wait(1, 0); - rep_interrupt(); - } - - wait(1, 0); - if (CX == 0) - rep_end(); - else - wait(1, 0); - } else - wait(1, 0); - } + break; } + if (in_rep != 0) + wait(1, 0); + wait(1, 0); + cpu_dest = get_accum(bits); + if ((opcode & 8) == 0) { + access(21, bits); + lods(bits); + wait(1, 0); + cpu_dest = cpu_data; + } + access(2, bits); + cpu_state.eaaddr = DI; + cpu_data = readmem(es); + DI = string_increment(bits); + cpu_src = cpu_data; + sub(bits); + wait(2, 0); + if (in_rep == 0) { + wait(3, 0); + break; + } + if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { + completed = 1; + wait(4, 0); + break; + } + repeating = 1; + clock_end(); break; case 0xA8: @@ -3393,59 +2883,24 @@ execx86(int32_t cycs) case 0xAA: case 0xAB: /* STOS */ bits = 8 << (opcode & 1); - if (rep_start()) { - cpu_data = AX; + if (!repeating) { wait(1, 0); - stos(bits); - if (in_rep != 0) { - completed = 0; - repeating = 1; - - wait(1, 0); - if (irq_pending()) { - wait(1, 0); - rep_interrupt(); - } - - wait(1, 0); - CX--; - if (CX == 0) - rep_end(); - else - wait(1, 0); - } else + if (in_rep != 0) wait(1, 0); } - break; - - case 0xAC: - case 0xAD: /* LODS */ - bits = 8 << (opcode & 1); - if (rep_start()) { - lods(bits); - set_accum(bits, cpu_data); + if (rep_action(bits)) { + wait(1, 0); + break; + } + cpu_data = AX; + access(28, bits); + stos(bits); + if (in_rep == 0) { wait(3, 0); - - if (in_rep != 0) { - completed = 0; - repeating = 1; - - wait(1, 0); - CX--; - - if (irq_pending()) { - wait(2, 0); - rep_interrupt(); - } else { - wait(2, 0); - - if (CX == 0) - rep_end(); - else - wait(1, 0); - } - } + break; } + repeating = 1; + clock_end(); break; case 0xB0: @@ -3478,53 +2933,42 @@ execx86(int32_t cycs) break; case 0xC0: - case 0xC2: - /* RETN imm16 */ - bits = 8 + (opcode & 0x08); - wait(1, 0); - cpu_src = pfq_fetchw(); - wait(1, 0); - new_ip = pop(); - pfq_do_suspend(); - wait(2, 0); - pfq_clear(); - wait(3, 0); - SP += cpu_src; - set_ip(new_ip); - break; - case 0xC1: + case 0xC2: case 0xC3: - /* RETN */ - bits = 8 + (opcode & 0x08); - wait(1, 0); - cpu_src = pfq_fetchw(); - new_ip = pop(); - pfq_do_suspend(); - wait(1, 0); - pfq_clear(); - wait(2, 0); - set_ip(new_ip); - break; - case 0xC8: - case 0xCA: - /* RETF imm16 */ - bits = 8 + (opcode & 0x08); - wait(1, 0); - cpu_src = pfq_fetchw(); - farret(1); - SP += cpu_src; - wait(1, 0); - break; - case 0xC9: + case 0xCA: case 0xCB: - /* RETF */ + /* RET */ bits = 8 + (opcode & 0x08); - wait(1, 0); - wait(1, 0); - farret(1); + if ((opcode & 9) != 1) + wait(1, 0); + if (!(opcode & 1)) { + cpu_src = pfq_fetchw(); + wait(1, 0); + } + if ((opcode & 9) == 9) + wait(1, 0); + pfq_clear(); + access(26, bits); + new_ip = pop(); + wait(2, 0); + if ((opcode & 8) == 0) + new_cs = CS; + else { + access(42, bits); + new_cs = pop(); + if (opcode & 1) + wait(1, 0); + } + if (!(opcode & 1)) { + SP += cpu_src; + wait(1, 0); + } + load_cs(new_cs); + access(72, bits); + set_ip(new_ip); break; case 0xC4: @@ -3532,12 +2976,13 @@ execx86(int32_t cycs) /* LsS rw, rmd */ do_mod_rm(); bits = 16; + access(52, bits); read_ea(1, bits); cpu_state.regs[cpu_reg].w = cpu_data; - if (cpu_mod != 3) - wait(2, 0); + access(57, bits); read_ea2(bits); load_seg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); + wait(1, 0); break; case 0xC6: @@ -3546,37 +2991,45 @@ execx86(int32_t cycs) bits = 8 << (opcode & 1); do_mod_rm(); wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); cpu_data = pfq_fetch(); - wait((opcode == 0xc6) ? 2 : 1, 0); + if (cpu_mod == 3) + wait(1, 0); + access(16, bits); set_ea(cpu_data); break; case 0xCC: /*INT 3*/ - wait(1, 0); - wait(4, 0); - int3(); + interrupt(3); break; case 0xCD: /*INT*/ wait(1, 0); - temp = pfq_fetchb(); - wait(1, 0); - sw_int(temp); + interrupt(pfq_fetchb()); break; case 0xCE: /*INTO*/ - wait(1, 0); - if (cpu_state.flags & V_FLAG) - sw_int(4); + wait(3, 0); + if (cpu_state.flags & V_FLAG) { + wait(2, 0); + interrupt(4); + } break; case 0xCF: /*IRET*/ - wait(1, 0); - wait(1, 0); - farret(1); + access(43, 8); + new_ip = pop(); + wait(3, 0); + access(44, 8); + new_cs = pop(); + load_cs(new_cs); + access(62, 8); + set_ip(new_ip); + access(45, 8); if (is_nec) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; - wait(1, 0); + wait(5, 0); noint = 1; nmi_enable = 1; break; @@ -3588,9 +3041,10 @@ execx86(int32_t cycs) /* rot rm */ bits = 8 << (opcode & 1); do_mod_rm(); - cpu_data = get_ea(); if (cpu_mod == 3) wait(1, 0); + access(53, bits); + cpu_data = get_ea(); if ((opcode & 2) == 0) { cpu_src = 1; wait((cpu_mod != 3) ? 4 : 0, 0); @@ -3666,14 +3120,12 @@ execx86(int32_t cycs) set_af(0); set_pzs(bits); break; - - default: - break; } if ((opcode & 2) != 0) wait(4, 0); --cpu_src; } + access(17, bits); set_ea(cpu_data); break; @@ -3711,8 +3163,9 @@ execx86(int32_t cycs) break; case 0xD7: /*XLATB*/ cpu_state.eaaddr = (BX + AL) & 0xffff; - wait(4, 0); - AL = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + access(4, 8); + AL = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); + wait(1, 0); break; case 0xD8: @@ -3725,76 +3178,42 @@ execx86(int32_t cycs) case 0xDF: /* esc i, r, rm */ do_mod_rm(); + access(54, 16); tempw = cpu_state.pc; - geteaw(); - wait(1, 0); - if (cpu_mod != 3) - wait(1, 0); - if (hasfpu) { - if (fpu_softfloat) { - switch (opcode) { - case 0xD8: - ops_sf_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xD9: - ops_sf_fpu_8087_d9[rmdat & 0xff](rmdat); - break; - case 0xDA: - ops_sf_fpu_8087_da[rmdat & 0xff](rmdat); - break; - case 0xDB: - ops_sf_fpu_8087_db[rmdat & 0xff](rmdat); - break; - case 0xDC: - ops_sf_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xDD: - ops_sf_fpu_8087_dd[rmdat & 0xff](rmdat); - break; - case 0xDE: - ops_sf_fpu_8087_de[rmdat & 0xff](rmdat); - break; - case 0xDF: - ops_sf_fpu_8087_df[rmdat & 0xff](rmdat); - break; - - default: - break; - } - } else { - switch (opcode) { - case 0xD8: - ops_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xD9: - ops_fpu_8087_d9[rmdat & 0xff](rmdat); - break; - case 0xDA: - ops_fpu_8087_da[rmdat & 0xff](rmdat); - break; - case 0xDB: - ops_fpu_8087_db[rmdat & 0xff](rmdat); - break; - case 0xDC: - ops_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xDD: - ops_fpu_8087_dd[rmdat & 0xff](rmdat); - break; - case 0xDE: - ops_fpu_8087_de[rmdat & 0xff](rmdat); - break; - case 0xDF: - ops_fpu_8087_df[rmdat & 0xff](rmdat); - break; - - default: - break; - } + if (!hasfpu) + geteaw(); + else + switch (opcode) { + case 0xD8: + ops_fpu_8087_d8[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); + break; + case 0xD9: + ops_fpu_8087_d9[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDA: + ops_fpu_8087_da[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDB: + ops_fpu_8087_db[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDC: + ops_fpu_8087_dc[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); + break; + case 0xDD: + ops_fpu_8087_dd[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDE: + ops_fpu_8087_de[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDF: + ops_fpu_8087_df[rmdat & 0xff]((uint32_t) rmdat); + break; } - } cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on the 286+ core, but not here. */ + wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); break; case 0xE0: @@ -3818,9 +3237,6 @@ execx86(int32_t cycs) if (!(cpu_state.flags & Z_FLAG)) oldc = 0; break; - - default: - break; } } else oldc = (CX == 0); @@ -3830,46 +3246,43 @@ execx86(int32_t cycs) case 0xE4: case 0xE5: - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetchb(); - cpu_state.eaaddr = cpu_data; - wait(1, 0); - cpu_io(bits, 0, cpu_state.eaaddr); - break; case 0xE6: case 0xE7: - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetchb(); - cpu_state.eaaddr = cpu_data; - cpu_data = (bits == 16) ? AX : AL; - wait(2, 0); - cpu_io(bits, 1, cpu_state.eaaddr); - break; case 0xEC: case 0xED: - bits = 8 << (opcode & 1); - cpu_data = DX; - cpu_state.eaaddr = cpu_data; - wait(1, 0); - cpu_io(bits, 0, cpu_state.eaaddr); - break; case 0xEE: case 0xEF: bits = 8 << (opcode & 1); - wait(2, 0); - cpu_data = DX; + if ((opcode & 0x0e) != 0x0c) + wait(1, 0); + if ((opcode & 8) == 0) + cpu_data = pfq_fetchb(); + else + cpu_data = DX; cpu_state.eaaddr = cpu_data; - cpu_data = (bits == 16) ? AX : AL; - cpu_io(bits, 1, cpu_state.eaaddr); - wait(1, 0); + if ((opcode & 2) == 0) { + access(3, bits); + if (opcode & 1) + cpu_io(16, 0, cpu_data); + else + cpu_io(8, 0, cpu_data); + wait(1, 0); + } else { + if ((opcode & 8) == 0) + access(8, bits); + else + access(9, bits); + if (opcode & 1) + cpu_io(16, 1, cpu_data); + else + cpu_io(8, 1, cpu_data); + } break; case 0xE8: /*CALL rel 16*/ wait(1, 0); cpu_state.oldpc = jump_near(); - wait(2, 0); + access(34, 8); push((uint16_t *) &(cpu_state.oldpc)); break; case 0xE9: /*JMP rel 16*/ @@ -3879,13 +3292,12 @@ execx86(int32_t cycs) case 0xEA: /*JMP far*/ wait(1, 0); addr = pfq_fetchw(); + wait(1, 0); tempw = pfq_fetchw(); load_cs(tempw); - pfq_do_suspend(); - set_ip(addr); - wait(2, 0); + access(70, 8); pfq_clear(); - wait(1, 0); + set_ip(addr); break; case 0xEB: /*JMP rel*/ wait(1, 0); @@ -3910,23 +3322,18 @@ execx86(int32_t cycs) break; case 0xF4: /*HLT*/ - if (repeating) { + if (!repeating) { wait(1, 0); - wait(1, 0); - wait(1, 0); - if (irq_pending()) { - check_interrupts(); - wait(7, 0); - } else { - repeating = 1; - completed = 0; - } + pfq_clear(); + } + wait(1, 0); + if (irq_pending()) { + wait(cycles & 1, 0); + check_interrupts(); } else { - wait(1, 0); - pfq_do_suspend(); - wait(2, 0); repeating = 1; completed = 0; + clock_end(); } break; case 0xF5: /*CMC*/ @@ -3938,12 +3345,15 @@ execx86(int32_t cycs) case 0xF7: bits = 8 << (opcode & 1); do_mod_rm(); + access(55, bits); cpu_data = get_ea(); switch (rmdat & 0x38) { case 0x00: case 0x08: /* TEST */ wait(2, 0); + if (cpu_mod != 3) + wait(1, 0); cpu_src = pfq_fetch(); wait(1, 0); test(bits, cpu_data, cpu_src); @@ -3960,8 +3370,7 @@ execx86(int32_t cycs) cpu_dest = 0; sub(bits); } - if (cpu_mod != 3) - wait(2, 0); + access(18, bits); set_ea(cpu_data); break; case 0x20: /* MUL */ @@ -3972,19 +3381,19 @@ execx86(int32_t cycs) if (opcode & 1) { AX = cpu_data; DX = cpu_dest; - set_co_mul(bits, DX != ((AX & 0x8000) == 0 || - (rmdat & 0x38) == 0x20 ? 0 : 0xffff)); + set_co_mul(bits, DX != ((AX & 0x8000) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xffff)); cpu_data = DX; } else { AL = (uint8_t) cpu_data; AH = (uint8_t) cpu_dest; - set_co_mul(bits, AH != ((AL & 0x80) == 0 || - (rmdat & 0x38) == 0x20 ? 0 : 0xff)); + set_co_mul(bits, AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff)); if (!is_nec) cpu_data = AH; } set_sf(bits); set_pf(); + if (cpu_mod != 3) + wait(1, 0); /* NOTE: When implementing the V20, care should be taken to not change the zero flag. */ if (is_nec) @@ -3992,13 +3401,12 @@ execx86(int32_t cycs) break; case 0x30: /* DIV */ case 0x38: /* IDIV */ + if (cpu_mod != 3) + wait(1, 0); cpu_src = cpu_data; if (x86_div(AL, AH)) wait(1, 0); break; - - default: - break; } break; @@ -4026,6 +3434,7 @@ execx86(int32_t cycs) /* misc */ bits = 8 << (opcode & 1); do_mod_rm(); + access(56, bits); read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); switch (rmdat & 0x38) { case 0x00: /* INC rm */ @@ -4042,65 +3451,63 @@ execx86(int32_t cycs) do_af(); set_pzs(bits); wait(2, 0); + access(19, bits); set_ea(cpu_data); break; case 0x10: /* CALL rm */ cpu_data_opff_rm(); - wait(2, 0); - pfq_do_suspend(); - wait(4, 0); + access(63, bits); + wait(1, 0); pfq_clear(); + wait(4, 0); + if (cpu_mod != 3) + wait(1, 0); + wait(1, 0); /* Wait. */ cpu_state.oldpc = cpu_state.pc; set_ip(cpu_data); wait(2, 0); + access(35, bits); push((uint16_t *) &(cpu_state.oldpc)); break; case 0x18: /* CALL rmd */ new_ip = cpu_data; - wait(3, 0); + access(58, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; - wait(1, 0); - pfq_do_suspend(); - wait(3, 0); + access(36, bits); push(&(CS)); + access(64, bits); + wait(4, 0); + cpu_state.oldpc = cpu_state.pc; load_cs(new_cs); - wait(3, 0); - pfq_clear(); - wait(3, 0); - push((uint16_t *) &(cpu_state.pc)); set_ip(new_ip); + access(37, bits); + push((uint16_t *) &(cpu_state.oldpc)); break; case 0x20: /* JMP rm */ cpu_data_opff_rm(); - pfq_do_suspend(); - wait(4, 0); - pfq_clear(); + access(65, bits); set_ip(cpu_data); break; case 0x28: /* JMP rmd */ new_ip = cpu_data; - pfq_do_suspend(); - wait(4, 0); - pfq_clear(); + access(59, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; load_cs(new_cs); + access(66, bits); set_ip(new_ip); break; case 0x30: /* PUSH rm */ case 0x38: if (cpu_mod != 3) wait(1, 0); - wait(4, 0); - push((uint16_t *) &cpu_data); - break; - - default: + access(38, bits); + push((uint16_t *) &(cpu_data)); break; } break; From 1caa5b6544a2ee709e2ddcd9573fd272f3196ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Tue, 7 Nov 2023 00:59:33 +0100 Subject: [PATCH 098/133] Fixed the memory granularities of the Olivetti M19, Packard Bell PB8810, and Sanyo SX-16, fixes #3806. --- src/machine/machine_table.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8277a8415..3a9bfa72a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1084,7 +1084,7 @@ const machine_t machines[] = { .ram = { .min = 256, .max = 640, - .step = 256 + .step = 128 }, .nvrmask = 0, .kbc_device = &keyboard_xt_olivetti_device, @@ -1162,7 +1162,7 @@ const machine_t machines[] = { .ram = { .min = 256, .max = 640, - .step = 256 + .step = 128 }, .nvrmask = 0, .kbc_device = &keyboard_xtclone_device, @@ -1318,7 +1318,7 @@ const machine_t machines[] = { .ram = { .min = 256, .max = 640, - .step = 256 + .step = 128 }, .nvrmask = 0, .kbc_device = &keyboard_xtclone_device, From 69f5e9ae4b979fda5c87c7a913682e93a5e6ff75 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 7 Nov 2023 01:42:22 +0100 Subject: [PATCH 099/133] Added a Hyundai XT keyboard controller with the old behavior (the Hyundai XT BIOS'es rely on it), fixes #3771. --- src/device/keyboard_xt.c | 58 +++++++++++++++++++++++------------- src/include/86box/keyboard.h | 1 + src/machine/m_xt.c | 12 ++++++-- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 028c58493..f65a6dffc 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -54,19 +54,22 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -// Keyboard Types -#define KBD_TYPE_PC81 0 -#define KBD_TYPE_PC82 1 -#define KBD_TYPE_XT82 2 -#define KBD_TYPE_XT86 3 -#define KBD_TYPE_COMPAQ 4 -#define KBD_TYPE_TANDY 5 -#define KBD_TYPE_TOSHIBA 6 -#define KBD_TYPE_VTECH 7 -#define KBD_TYPE_OLIVETTI 8 -#define KBD_TYPE_ZENITH 9 -#define KBD_TYPE_PRAVETZ 10 -#define KBD_TYPE_XTCLONE 11 +/* Keyboard Types */ +enum { + KBD_TYPE_PC81 = 0, + KBD_TYPE_PC82, + KBD_TYPE_XT82, + KBD_TYPE_XT86, + KBD_TYPE_COMPAQ, + KBD_TYPE_TANDY, + KBD_TYPE_TOSHIBA, + KBD_TYPE_VTECH, + KBD_TYPE_OLIVETTI, + KBD_TYPE_ZENITH, + KBD_TYPE_PRAVETZ, + KBD_TYPE_HYUNDAI, + KBD_TYPE_XTCLONE +}; typedef struct xtkbd_t { int want_irq; @@ -530,7 +533,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) switch (port) { case 0x61: /* Keyboard Control Register (aka Port B) */ - if (!(val & 0x80)) { + if (!(val & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI)) { new_clock = !!(val & 0x40); if (!kbd->clock && new_clock) { key_queue_start = key_queue_end = 0; @@ -540,7 +543,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) } } kbd->pb = val; - if (!(kbd->pb & 0x80)) + if (!(kbd->pb & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI)) kbd->clock = !!(kbd->pb & 0x40); ppi.pb = val; @@ -603,10 +606,10 @@ kbd_read(uint16_t port, void *priv) (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || - (kbd->type == KBD_TYPE_ZENITH))) { + (kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI))) { if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || - (kbd->type == KBD_TYPE_PRAVETZ)) + (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_HYUNDAI)) ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00); else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)) /* According to Ruud on the PCem forum, this is supposed to @@ -696,7 +699,7 @@ kbd_read(uint16_t port, void *priv) case 0x63: /* Keyboard Configuration Register (aka Port D) */ if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || - (kbd->type == KBD_TYPE_TOSHIBA)) + (kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI)) ret = kbd->pd; break; @@ -762,7 +765,7 @@ kbd_init(const device_t *info) (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) || (kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA) || - (kbd->type == KBD_TYPE_OLIVETTI)) { + (kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI)) { /* DIP switch readout: bit set = OFF, clear = ON. */ if (kbd->type == KBD_TYPE_OLIVETTI) /* Olivetti M19 @@ -781,7 +784,8 @@ kbd_init(const device_t *info) /* Switches 3, 4 - memory size. */ if ((kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || - (kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA)) { + (kbd->type == KBD_TYPE_HYUNDAI) || (kbd->type == KBD_TYPE_COMPAQ) || + (kbd->type == KBD_TYPE_TOSHIBA)) { switch (mem_size) { case 256: kbd->pd |= 0x00; @@ -1076,6 +1080,20 @@ const device_t keyboard_xt_zenith_device = { .config = NULL }; +const device_t keyboard_xt_hyundai_device = { + .name = "Hyundai XT Keyboard", + .internal_name = "keyboard_x_hyundai", + .flags = 0, + .local = KBD_TYPE_HYUNDAI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t keyboard_xtclone_device = { .name = "XT (Clone) Keyboard", .internal_name = "keyboard_xtclone", diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 0a2a038ec..a4b079760 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -226,6 +226,7 @@ extern const device_t keyboard_xt_lxt3_device; # endif /*defined(DEV_BRANCH) && defined(USE_LASERXT) */ extern const device_t keyboard_xt_olivetti_device; extern const device_t keyboard_xt_zenith_device; +extern const device_t keyboard_xt_hyundai_device; extern const device_t keyboard_xtclone_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_siemens_device; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index fe519c65b..a374b58f3 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -493,6 +493,14 @@ machine_xt_vendex_init(const machine_t *model) return ret; } +static void +machine_xt_hyundai_common_init(const machine_t *model) +{ + device_add(&keyboard_xt_hyundai_device); + + machine_xt_common_init(model); +} + int machine_xt_super16t_init(const machine_t *model) { @@ -504,7 +512,7 @@ machine_xt_super16t_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_hyundai_common_init(model); /* On-board FDC cannot be disabled */ device_add(&fdc_xt_device); @@ -523,7 +531,7 @@ machine_xt_super16te_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_hyundai_common_init(model); /* On-board FDC cannot be disabled */ device_add(&fdc_xt_device); From 2cd7fe716d3969a4ca071db6ac24058646a4d5ba Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 7 Nov 2023 06:34:04 +0100 Subject: [PATCH 100/133] The SiS 4xx chipset now no longer allow modifying the RAM amount bits of register 0x00, fixes #2306. --- src/chipset/sis_85c4xx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 97c989b73..cf4ff42d7 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -176,6 +176,8 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) valxor = val ^ dev->regs[rel_reg]; if (rel_reg == 0x19) dev->regs[rel_reg] &= ~val; + else if (rel_reg == 0x00) + dev->regs[rel_reg] = (dev->regs[rel_reg] & 0x1f) | (val & 0xe0); else dev->regs[rel_reg] = val; From fad290df77baee0c6757704f88c9b5a7d340f063 Mon Sep 17 00:00:00 2001 From: "Joakim L. Gilje" Date: Tue, 7 Nov 2023 12:39:42 +0100 Subject: [PATCH 101/133] add cpl_override in pmodeiret() when cpu_state.flags has NT_FLAG --- src/cpu/x86seg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index eaa63f846..709253a20 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -1796,7 +1796,9 @@ pmodeiret(int is32) } if (cpu_state.flags & NT_FLAG) { + cpl_override = 1; seg = readmemw(tr.base, 0); + cpl_override = 0; addr = seg & 0xfff8; if (seg & 0x0004) { x86seg_log("TS LDT %04X %04X IRET\n", seg, gdt.limit); From 465375cd7cdcb2ca6fd03861bc22462d41489093 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 7 Nov 2023 20:09:06 +0100 Subject: [PATCH 102/133] Disabled register FF on non-PNP Sound Blaster 16 and AWE32, fixes the Windows for Workgroups 3.11 AWE32 driver. --- src/sound/snd_sb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index bfd1ca401..14afb2740 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -945,7 +945,7 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) break; case 0xff: - if (sb->dsp.sb_type >= SB16) { + if (sb->dsp.sb_type > SBAWE32) { /* Bit 5: High DMA channel enabled (0 = yes, 1 = no); Bit 2: ????; @@ -1173,7 +1173,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) - Register FF = FF: Volume playback normal. - Register FF = Not FF: Volume playback low unless bit 6 of 82h is set. */ - if (sb->dsp.sb_type >= SB16) + if (sb->dsp.sb_type > SBAWE32) ret = mixer->regs[mixer->index]; break; @@ -2179,6 +2179,7 @@ sb_16_init(UNUSED(const device_t *info)) sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); if (sb->opl_enabled) { @@ -2233,6 +2234,7 @@ sb_16_reply_mca_init(UNUSED(const device_t *info)) sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); sb->mixer_enabled = 1; @@ -2415,6 +2417,7 @@ sb_16_compat_init(const device_t *info) sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); sb->mixer_enabled = 1; @@ -2488,6 +2491,7 @@ sb_awe32_init(UNUSED(const device_t *info)) sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); if (sb->opl_enabled) { From a436c12de3b79e105ef9dd694678b9036040107d Mon Sep 17 00:00:00 2001 From: "Joakim L. Gilje" Date: Tue, 7 Nov 2023 20:45:45 +0100 Subject: [PATCH 103/133] pmodeiret(): move the second cpl_override after read_descriptor() because the flag is reset by the function --- src/cpu/x86seg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 709253a20..96061d3fa 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -1811,8 +1811,8 @@ pmodeiret(int is32) } addr += gdt.base; } - cpl_override = 1; read_descriptor(addr, segdat, segdat32, 1); + cpl_override = 1; op_taskswitch286(seg, segdat, segdat[2] & 0x0800); cpl_override = 0; return; From f938db54d3dfb982c93d73eaeda40aef7644e062 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 7 Nov 2023 21:27:56 -0300 Subject: [PATCH 104/133] snd_sb: Unify SB16 and ViBRA PnP functions --- src/sound/snd_sb.c | 94 +++++----------------------------------------- 1 file changed, 9 insertions(+), 85 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 14afb2740..dbf242e59 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1599,8 +1599,14 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) sb_dsp_setdma8(&sb->dsp, val); val = config->dma[1].dma; - if (val != ISAPNP_DMA_DISABLED) - sb_dsp_setdma16(&sb->dsp, val); + sb_dsp_setdma16_enabled(&sb->dsp, val != ISAPNP_DMA_DISABLED); + sb_dsp_setdma16_translate(&sb->dsp, val < ISAPNP_DMA_DISABLED); + if (val != ISAPNP_DMA_DISABLED) { + if (sb->dsp.sb_16_dma_supported) + sb_dsp_setdma16(&sb->dsp, val); + else + sb_dsp_setdma16_8(&sb->dsp, val); + } } break; @@ -1635,90 +1641,8 @@ sb_vibra16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void * switch (ld) { case 0: /* Audio */ - io_removehandler(addr, 0x0004, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_removehandler(addr + 8, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_removehandler(addr + 4, 0x0002, - sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, - sb); - - addr = sb->opl_pnp_addr; - if (addr) { - sb->opl_pnp_addr = 0; - io_removehandler(addr, 0x0004, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - - sb_dsp_setaddr(&sb->dsp, 0); - sb_dsp_setirq(&sb->dsp, 0); - sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); - sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); - - mpu401_change_addr(sb->mpu, 0); - - if (config->activate) { - addr = config->io[0].base; - if (addr != ISAPNP_IO_DISABLED) { - io_sethandler(addr, 0x0004, - 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(addr + 4, 0x0002, - sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, - sb); - - sb_dsp_setaddr(&sb->dsp, addr); - } - - addr = config->io[1].base; - if (addr != ISAPNP_IO_DISABLED) - mpu401_change_addr(sb->mpu, addr); - - addr = config->io[2].base; - if (addr != ISAPNP_IO_DISABLED) { - sb->opl_pnp_addr = addr; - io_sethandler(addr, 0x0004, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - - val = config->irq[0].irq; - if (val != ISAPNP_IRQ_DISABLED) - sb_dsp_setirq(&sb->dsp, val); - - val = config->dma[0].dma; - if (val != ISAPNP_DMA_DISABLED) - sb_dsp_setdma8(&sb->dsp, val); - - val = config->dma[1].dma; - sb_dsp_setdma16_enabled(&sb->dsp, val != ISAPNP_DMA_DISABLED); - sb_dsp_setdma16_translate(&sb->dsp, val < ISAPNP_DMA_DISABLED); - if (val != ISAPNP_DMA_DISABLED) { - if (sb->dsp.sb_16_dma_supported) - sb_dsp_setdma16(&sb->dsp, val); - else - sb_dsp_setdma16_8(&sb->dsp, val); - } - } - - break; - case 1: /* Game */ - gameport_remap(sb->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + sb_16_pnp_config_changed(ld * 3, config, sb); break; default: From c243af519bc60f5412da67b16b9ea2929ba89e4f Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 7 Nov 2023 22:02:30 -0300 Subject: [PATCH 105/133] sio_um8669f: Implement IDE controller --- src/include/86box/sio.h | 2 ++ src/sio/sio_um8669f.c | 64 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index b51f466e4..6ec9eceb9 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -72,6 +72,8 @@ extern const device_t ps1_m2133_sio; extern const device_t sio_detect_device; #endif extern const device_t um8669f_device; +extern const device_t um8669f_ide_device; +extern const device_t um8669f_ide_sec_device; extern const device_t via_vt82c686_sio_device; extern const device_t w83787f_88h_device; extern const device_t w83787f_device; diff --git a/src/sio/sio_um8669f.c b/src/sio/sio_um8669f.c index 2643e76f7..d6af86c60 100644 --- a/src/sio/sio_um8669f.c +++ b/src/sio/sio_um8669f.c @@ -35,8 +35,10 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/gameport.h> -#include <86box/sio.h> +#include <86box/hdc.h> #include <86box/isapnp.h> +#include <86box/hdc_ide.h> +#include <86box/sio.h> #include <86box/plat_unused.h> /* Real chips don't have a PnP ROM and instead rely on the BIOS going in blind. @@ -63,7 +65,9 @@ static uint8_t um8669f_pnp_rom[] = { 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ - 0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (dummy to create a gap in LDNs) */ + 0x15, 0x41, 0xd0, 0x06, 0x00, 0x01, /* logical device PNP0600, can participate in boot */ + 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ + 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ 0x15, 0x41, 0xd0, 0xb0, 0x2f, 0x01, /* logical device PNPB02F, can participate in boot */ 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ @@ -89,7 +93,9 @@ static const isapnp_device_config_t um8669f_pnp_defaults[] = { .io = { { .base = LPT1_ADDR }, }, .irq = { { .irq = LPT1_IRQ }, } }, { - .activate = 0 + .activate = 0, + .io = { { .base = 0x1f0 }, }, + .irq = { { .irq = 14 }, } }, { .activate = 0, .io = { { .base = 0x200 }, } @@ -123,6 +129,7 @@ typedef struct um8669f_t { fdc_t *fdc; serial_t *uart[2]; + uint8_t ide; void *gameport; } um8669f_t; @@ -179,6 +186,18 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri break; + case 4: + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) + um8669f_log("UM8669F: IDE enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq); + else + um8669f_log("UM8669F: IDE disabled\n"); + + if (dev->ide < IDE_BUS_MAX) { + config->io[1].base = config->io[0].base + 0x206; /* status port apparently fixed */ + ide_pnp_config_changed(0, config, (void *) (int) dev->ide); + } + break; + case 5: if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base); @@ -252,6 +271,9 @@ um8669f_reset(um8669f_t *dev) lpt1_remove(); + if (dev->ide < IDE_BUS_MAX) + ide_remove_handlers(dev->ide); + isapnp_enable_card(dev->pnp_card, ISAPNP_CARD_DISABLE); dev->locked = 1; @@ -270,9 +292,9 @@ um8669f_close(void *priv) } static void * -um8669f_init(UNUSED(const device_t *info)) +um8669f_init(const device_t *info) { - um8669f_log("UM8669F: init()\n"); + um8669f_log("UM8669F: init(%02X)\n", info->local); um8669f_t *dev = (um8669f_t *) malloc(sizeof(um8669f_t)); memset(dev, 0, sizeof(um8669f_t)); @@ -286,6 +308,10 @@ um8669f_init(UNUSED(const device_t *info)) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->ide = info->local; + if (dev->ide < IDE_BUS_MAX) + device_add(&ide_isa_device); + dev->gameport = gameport_add(&gameport_sio_device); io_sethandler(0x0108, 0x0002, @@ -300,6 +326,20 @@ const device_t um8669f_device = { .name = "UMC UM8669F Super I/O", .internal_name = "um8669f", .flags = 0, + .local = 0xff, + .init = um8669f_init, + .close = um8669f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8669f_ide_device = { + .name = "UMC UM8669F Super I/O (With IDE)", + .internal_name = "um8669f_ide", + .flags = 0, .local = 0, .init = um8669f_init, .close = um8669f_close, @@ -309,3 +349,17 @@ const device_t um8669f_device = { .force_redraw = NULL, .config = NULL }; + +const device_t um8669f_ide_sec_device = { + .name = "UMC UM8669F Super I/O (With Secondary IDE)", + .internal_name = "um8669f_ide_sec", + .flags = 0, + .local = 1, + .init = um8669f_init, + .close = um8669f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; From adaba177434b792820c10abb783ede199566ceef Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 7 Nov 2023 22:28:26 -0300 Subject: [PATCH 106/133] sio_um8669f: Improve configuration register system and add definitions --- src/sio/sio_um8669f.c | 48 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/sio/sio_um8669f.c b/src/sio/sio_um8669f.c index d6af86c60..61e9abd97 100644 --- a/src/sio/sio_um8669f.c +++ b/src/sio/sio_um8669f.c @@ -18,6 +18,35 @@ * Copyright 2016-2021 Miran Grca. * Copyright 2021 RichardG. */ + +/* + UMC UM8669F non-PnP register definitions + + C0: + [7] Infrared half duplex + [4:3] LPT mode: + 00 SPP + 01 EPP + 10 ECP + 11 ECP + EPP + + C1: + [7] Enable PnP access + [6:0] Always set regardless of PnP access enabled/disabled + + C2: + [6:5] Potentially pin muxing mode: (names from AMI "IR group" setup option) + 00 Reserved + 01 A (no IDE) + 10 B (no IDE) + 11 C + [4:3] Infrared mode: + 00 Reserved + 01 HPSIR + 10 ASKIR + 11 Disabled +*/ + #include #include #include @@ -122,10 +151,9 @@ um8669f_log(const char *fmt, ...) typedef struct um8669f_t { uint8_t locked; - uint8_t cur_reg_108; + uint8_t cur_reg; void *pnp_card; - - uint8_t regs_108[256]; + uint8_t regs[3]; fdc_t *fdc; serial_t *uart[2]; @@ -228,11 +256,11 @@ um8669f_write(uint16_t port, uint8_t val, void *priv) if (val == 0x55) dev->locked = 1; else - dev->cur_reg_108 = val; - } else { - dev->regs_108[dev->cur_reg_108] = val; + dev->cur_reg = val; + } else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= 0xc2)) { + dev->regs[dev->cur_reg & 3] = val; - if (dev->cur_reg_108 == 0xc1) { + if (dev->cur_reg == 0xc1) { um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis"); isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE); } @@ -248,9 +276,9 @@ um8669f_read(uint16_t port, void *priv) if (!dev->locked) { if (port == 0x108) - ret = dev->cur_reg_108; /* ??? */ - else - ret = dev->regs_108[dev->cur_reg_108]; + ret = dev->cur_reg; /* ??? */ + else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= 0xc2)) + ret = dev->regs[dev->cur_reg & 3]; } um8669f_log("UM8669F: read(%04X) = %02X\n", port, ret); From e6ce96a169d3700dc6d11d3800cc5878ba621bf9 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 7 Nov 2023 22:29:53 -0300 Subject: [PATCH 107/133] snd_sb: Fix small IDE initialization oversight --- src/sound/snd_sb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index dbf242e59..5efb56bd1 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -2230,7 +2230,7 @@ sb_16_pnp_init(UNUSED(const device_t *info)) sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); mpu401_change_addr(sb->mpu, 0); - ide_remove_handlers(2); + ide_remove_handlers(3); sb->gameport_addr = 0; gameport_remap(sb->gameport, 0); @@ -2559,7 +2559,8 @@ sb_awe32_pnp_init(const device_t *info) sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); mpu401_change_addr(sb->mpu, 0); - ide_remove_handlers(2); + if ((info->local != 2) && (info->local != 3) && (info->local != 4)) + ide_remove_handlers(3); emu8k_change_addr(&sb->emu8k, 0); From 1005756e6eb8cc35fe8baaa872b47f3c25f56cf9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Nov 2023 03:48:49 +0100 Subject: [PATCH 108/133] ACPI no longer raises SCI IRQ if the overall SCI enable bit is clear, fixes #3810. --- src/acpi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 7b070257f..d60699f1b 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -124,7 +124,7 @@ acpi_update_irq(acpi_t *dev) if (dev->vendor == VEN_SMC) sci_level |= (dev->regs.pmsts & BM_STS); - if (sci_level) { + if ((dev->regs.pmcntrl & 0x01) && sci_level) { if (dev->irq_mode == 1) pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); else if (dev->irq_mode == 2) @@ -658,6 +658,7 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p acpi_t *dev = (acpi_t *) priv; int shift16; int sus_typ; + uint8_t old; addr &= 0x3f; #ifdef ENABLE_ACPI_LOG @@ -684,6 +685,7 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p case 0x04: case 0x05: /* PMCNTRL - Power Management Control Register (IO) */ + old = dev->regs.pmcntrl & 0xff; if ((addr == 0x05) && (val & 0x20)) { sus_typ = dev->suspend_types[(val >> 2) & 7]; acpi_log("ACPI suspend type %d flags %02X\n", (val >> 2) & 7, sus_typ); @@ -726,6 +728,8 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p } } dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3f07 /* 0x3c07 */; + if ((addr == 0x04) && ((old ^ val) & 0x01)) + acpi_update_irq(dev); break; default: @@ -789,7 +793,7 @@ acpi_reg_write_ali(int size, uint16_t addr, uint8_t val, void *priv) dev->regs.gpcntrl = ((dev->regs.gpcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00000001; break; case 0x30: - /* PM2_CNTRL - Power Management 2 Control Register( */ + /* PM2_CNTRL - Power Management 2 Control Register */ dev->regs.pmcntrl = val & 1; break; default: From 9d61b3a2626bb6994be4b9d4f05d347e395eda0d Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Nov 2023 03:51:40 +0100 Subject: [PATCH 109/133] Fixed two warnings in sound/snd_sb.c. --- src/sound/snd_sb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 5efb56bd1..5f1aeb261 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1636,8 +1636,6 @@ static void sb_vibra16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { sb_t *sb = (sb_t *) priv; - uint16_t addr = sb->dsp.sb_addr; - uint8_t val; switch (ld) { case 0: /* Audio */ From 6c356df9e77e3c91e6ec7904537a64a7029d5b62 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 8 Nov 2023 23:47:16 +0100 Subject: [PATCH 110/133] More and more video changes and fixes (8514/A and compatibles): 1. Made the 8514/A mode switch to VGA and viceversa (including ATI mode) actually usable and eliminating the last bugs related to them. Fixes 8514/A mode in OS/2 1.x/2.x (both IBM and Microsoft). 2. More sanity checks to the 8514/A and XGA pointers. Should fix emulator crashes on hard resets. --- src/include/86box/vid_8514a.h | 4 +- src/video/vid_8514a.c | 20 ++++---- src/video/vid_ati_mach8.c | 95 +++++++++++++++-------------------- src/video/vid_svga.c | 20 ++++---- 4 files changed, 63 insertions(+), 76 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 983e98cd1..da4e9e700 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -41,7 +41,7 @@ typedef struct ibm8514_t { int type; int local; int bpp; - int on; + int on[2]; int accel_bpp; uint32_t vram_size; @@ -64,7 +64,7 @@ typedef struct ibm8514_t { struct { uint16_t subsys_cntl; uint16_t setup_md; - uint8_t advfunc_cntl; + uint16_t advfunc_cntl; uint8_t ext_advfunc_cntl; uint16_t cur_y; uint16_t cur_y_bitres; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index a2cabfb0d..314fee307 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -964,8 +964,8 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) if (!val) break; dev->accel.advfunc_cntl = val & 0x0f; - dev->on = val & 0x01; - vga_on = !dev->on; + dev->on[0] = val & 0x01; + vga_on = !dev->on[0]; ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); svga_recalctimings(svga); break; @@ -1200,17 +1200,16 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (cpu_input) { if ((dev->accel.cmd & 2) || (pixcntl == 2)) { - if ((frgd_mix == 2) || (bkgd_mix == 2)) { + if ((frgd_mix == 2) || (bkgd_mix == 2)) count >>= 3; - } else if (pixcntl == 2) { - if (dev->accel.cmd & 2) { + else if (pixcntl == 2) { + if (dev->accel.cmd & 2) count >>= 1; - } else + else count >>= 3; } - } else { + } else count >>= 3; - } if (dev->bpp) { if ((dev->accel.cmd & 0x200) && (count == 2)) @@ -1299,7 +1298,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat /*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 the NOP command)*/ - ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frgdmix = %02x, bkgdmix = %02x, polygon=%x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_mix, bkgd_mix, dev->accel.multifunc[0x0a] & 6); + if (dev->accel.cmd == 0x53b1 && !cpu_dat) + ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frgdmix = %02x, bkgdmix = %02x, polygon=%x, cpu=%08x, frgdmix=%02x, bkgdmix=%02x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_mix, bkgd_mix, dev->accel.multifunc[0x0a] & 6, cpu_dat, dev->accel.frgd_mix, dev->accel.bkgd_mix); switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -4243,7 +4243,7 @@ ibm8514_recalctimings(svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (dev->on) { + if (dev->on[0]) { dev->h_disp = (dev->hdisp + 1) << 3; dev->pitch = (dev->accel.advfunc_cntl & 4) ? 1024 : 640; dev->h_total = (dev->htotal + 1); diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 8e7174666..90e41d9ba 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -100,8 +100,8 @@ typedef struct mach_t { uint8_t bank_w; uint8_t bank_r; uint16_t shadow_set; - int ext_on; - int ati_mode; + int ext_on[2]; + int ati_mode[2]; struct { uint8_t line_idx; @@ -1140,9 +1140,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mix = 1; break; case 1: - if (mach->accel.mono_pattern_enable) { + if (mach->accel.mono_pattern_enable) mix = mach->accel.mono_pattern[dev->accel.dy & 7][dev->accel.dx & 7]; - } else { + else { if ((dev->accel_bpp == 24) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) mix = 1; else { @@ -1205,18 +1205,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 src_dat = cpu_dat; else { READ(dev->accel.src + (dev->accel.cx), src_dat); - if (mono_src == 3) { + if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; - } } break; case 5: if (mix) { - if (dev->bpp) { + if (dev->bpp) src_dat = mach->accel.color_pattern_word[mach->accel.color_pattern_idx]; - } else { + else src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - } } else src_dat = 0; break; @@ -1318,9 +1316,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx == 3) mach->accel.color_pattern_idx = 0; - } else { + } else mach->accel.color_pattern_idx = (mach->accel.color_pattern_idx + mach->accel.stepx) & mach->accel.patt_len; - } + } else if ((dev->accel_bpp == 24) && (mach->accel.patt_len_reg & 0x4000) && (frgd_sel == 5)) { mach->accel.color_pattern_idx++; if (mach->accel.color_pattern_idx == 3) @@ -1346,9 +1344,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->bpp) dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); - else { + else dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * (dev->pitch)); - } + if ((mono_src == 1) && (dev->accel_bpp == 24) && (frgd_sel == 5)) mach->accel.color_pattern_idx = 0; else @@ -2347,7 +2345,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) mach->bank_r |= ((mach->regs[0xae] & 0x0c) << 2); mach->bank_w |= ((mach->regs[0xae] & 3) << 4); } - if (dev->on) + if (dev->on[0] || dev->on[1]) mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); } else { /* Single bank mode */ mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); @@ -2355,7 +2353,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) mach->bank_w |= ((mach->regs[0xae] & 3) << 4); } mach->bank_r = mach->bank_w; - if (dev->on) + if (dev->on[0] || dev->on[1]) mach_log("Single B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); } svga->read_bank = mach->bank_r << 16; @@ -2590,7 +2588,7 @@ mach_recalctimings(svga_t *svga) if (mach->regs[0xb0] & 0x20) svga->gdcreg[5] |= 0x40; - if (dev->on) { + if (dev->on[0] || dev->on[1]) { mach_log("8514/A ON.\n"); if (dev->local >= 2) { dev->h_disp = (dev->hdisp + 1) << 3; @@ -3686,19 +3684,16 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x4ae8: case 0x4ae9: - if (!(port & 1)) { - if (dev->local < 2) - dev->ext_crt_pitch = 128; + if (dev->local < 2) + dev->ext_crt_pitch = 128; - dev->accel.advfunc_cntl = val & 0x0f; - } else { - dev->on = (dev->accel.advfunc_cntl & 0x01); - vga_on = !dev->on; - mach->ext_on = dev->on; - mach_log("ATI 8514/A: (0x4ae9) val = %04x, ext = %d.\n", dev->accel.advfunc_cntl & 0x01, mach->ext_on); - mach32_updatemapping(mach); - } - mach->ati_mode = 0; + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on[port & 1] = (dev->accel.advfunc_cntl & 0x01); + mach_log("%04x: ON=%d.\n", port, dev->on[port & 1]); + vga_on = !dev->on[port & 1]; + mach->ext_on[port & 1] = dev->on[port & 1]; + mach32_updatemapping(mach); + mach->ati_mode[port & 1] = 0; svga_recalctimings(svga); break; @@ -3806,29 +3801,22 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) break; case 0x42ee: - mach->accel.test2[0] = val; - break; case 0x42ef: - mach->accel.test2[1] = val; + mach->accel.test2[port & 1] = val; break; case 0x46ee: - mach->accel.test3[0] = val; - break; case 0x46ef: - mach->accel.test3[1] = val; + mach->accel.test3[port & 1] = val; break; case 0x4aee: case 0x4aef: WRITE8(port, mach->accel.clock_sel, val); - if (port & 1) { - dev->on = mach->accel.clock_sel & 0x01; - mach->ext_on = dev->on; - vga_on = !dev->on; - mach_log("ATI 8514/A: (0x4aef) val = %04x, ext = %d.\n", mach->accel.clock_sel & 0x01, mach->ext_on); - } - mach->ati_mode = 1; + dev->on[port & 1] = mach->accel.clock_sel & 0x01; + mach->ext_on[port & 1] = dev->on[port & 1]; + vga_on = !dev->on[port & 1]; + mach->ati_mode[port & 1] = 1; svga_recalctimings(svga); break; @@ -3836,16 +3824,14 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x52ef: mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.scratch0, val); - if (port & 1) - mach->ext_on = 1; + mach->ext_on[port & 1] = 1; break; case 0x56ee: case 0x56ef: mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.scratch1, val); - if (port & 1) - mach->ext_on = 1; + mach->ext_on[port & 1] = 1; break; case 0x5aee: @@ -3926,11 +3912,8 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) break; } svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); - if (port & 1) { - mach->ati_mode = 1; - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - mach32_updatemapping(mach); - } + mach->ati_mode[port & 1] = 1; + mach32_updatemapping(mach); } svga_recalctimings(svga); break; @@ -5115,10 +5098,12 @@ mach32_updatemapping(mach_t *mach) mach->ap_size = 4; mem_mapping_disable(&mach->mmio_linear_mapping); } - if (mach->ext_on && (dev->local >= 2) && mach->ati_mode) { + if ((mach->ext_on[0] || mach->ext_on[1]) && (dev->local >= 2) && (mach->ati_mode[0] || mach->ati_mode[1])) { + mach_log("ExtON.\n"); mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); mem_mapping_set_p(&svga->mapping, mach); } else { + mach_log("ExtOFF.\n"); mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_mapping_set_p(&svga->mapping, svga); } @@ -5456,7 +5441,8 @@ mach_mca_reset(void *priv) mem_mapping_disable(&mach->bios_rom.mapping); mem_mapping_disable(&mach->bios_rom2.mapping); mach_log("MCA reset.\n"); - dev->on = 0; + dev->on[0] = 0; + dev->on[1] = 0; vga_on = 1; mach_mca_write(0x102, 0, mach); } @@ -5564,12 +5550,10 @@ mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) case 0x12: mach->linear_base = (mach->linear_base & 0xff000000) | ((val & 0xc0) << 16); - mach->ati_mode = 1; mach32_updatemapping(mach); break; case 0x13: mach->linear_base = (mach->linear_base & 0xc00000) | (val << 24); - mach->ati_mode = 1; mach32_updatemapping(mach); break; @@ -5722,7 +5706,8 @@ mach8_init(const device_t *info) dev->bpp = 0; svga->getclock = ics2494_getclock; - dev->on = 0; + dev->on[0] = 0; + dev->on[1] = 0; dev->ext_pitch = 1024; dev->ext_crt_pitch = 0x80; dev->accel_bpp = 8; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 8ec645016..c48baeb6e 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -212,10 +212,12 @@ svga_out(uint16_t addr, uint8_t val, void *priv) svga_recalctimings(svga); break; case 0x3c3: - if (xga_active) + if (xga_active && xga) xga->on = (val & 0x01) ? 0 : 1; - if (ibm8514_active) - dev->on = (val & 0x01) ? 0 : 1; + if (ibm8514_active && dev) { + dev->on[0] = (val & 0x01) ? 0 : 1; + dev->on[1] = dev->on[0]; + } svga_log("3C3: XGA ON = %d.\n", xga->on); vga_on = val & 0x01; @@ -527,7 +529,7 @@ svga_set_ramdac_type(svga_t *svga, int type) svga->ramdac_type = type; for (int c = 0; c < 256; c++) { - if (ibm8514_active) { + if (ibm8514_active && dev) { if (svga->ramdac_type == RAMDAC_8BIT) dev->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); else @@ -535,7 +537,7 @@ svga_set_ramdac_type(svga_t *svga, int type) (svga->vgapal[c].g & 0x3f) * 4, (svga->vgapal[c].b & 0x3f) * 4); } - if (xga_active) { + if (xga_active && xga) { if (svga->ramdac_type == RAMDAC_8BIT) xga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); else @@ -834,11 +836,11 @@ svga_poll(void *priv) int old_ma; if (!svga->override) { - if (ibm8514_active && dev->on) { + if (ibm8514_active && dev && (dev->on[0] || dev->on[1])) { ibm8514_poll(dev, svga); return; } - if (xga_active && xga->on) { + if (xga_active && xga && xga->on) { if ((xga->disp_cntl_2 & 7) >= 2) { xga_poll(xga, svga); return; @@ -1253,7 +1255,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_write_b; if (!linear) { - if (xga_active) { + if (xga_active && xga) { if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { if (val == 0xa5) { /*Memory size test of XGA*/ xga->test = val; @@ -1474,7 +1476,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_read_b; if (!linear) { - if (xga_active) { + if (xga_active && xga) { if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { if (xga->test == 0xa5) { /*Memory size test of XGA*/ if (addr == 0xa0001) { From 849c3f27f8e32f1e532fef8151cf33766765165b Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 9 Nov 2023 16:51:48 +0100 Subject: [PATCH 111/133] The option to show status icons in full screen now calls config_save() on toggle, fixes #3815. --- src/qt/qt_mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 4b849edd6..a5651eada 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -2033,5 +2033,6 @@ void MainWindow::on_actionShow_status_icons_in_fullscreen_triggered() { status_icons_fullscreen = !status_icons_fullscreen; ui->actionShow_status_icons_in_fullscreen->setChecked(status_icons_fullscreen); + config_save(); } From 45f0ecc87e0a3d622a07ce70129fafaf02feca8b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 9 Nov 2023 23:58:58 +0100 Subject: [PATCH 112/133] Forgot to apply the correction to the ATI 68860 ramdac, should clear the compile warnings. --- src/video/vid_ati68860_ramdac.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index 8b4c4924b..7cdd18019 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -73,16 +73,16 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) switch (addr) { case 0: - svga_out((dev && dev->on) ? 0x2ec : 0x3c8, val, svga); + svga_out((dev && (dev->on[0] || dev->on[1])) ? 0x2ec : 0x3c8, val, svga); break; case 1: - svga_out((dev && dev->on) ? 0x2ed : 0x3c9, val, svga); + svga_out((dev && (dev->on[0] || dev->on[1])) ? 0x2ed : 0x3c9, val, svga); break; case 2: - svga_out((dev && dev->on) ? 0x2ea : 0x3c6, val, svga); + svga_out((dev && (dev->on[0] || dev->on[1])) ? 0x2ea : 0x3c6, val, svga); break; case 3: - svga_out((dev && dev->on) ? 0x2eb : 0x3c7, val, svga); + svga_out((dev && (dev->on[0] || dev->on[1])) ? 0x2eb : 0x3c7, val, svga); break; default: ramdac->regs[addr & 0xf] = val; @@ -178,16 +178,16 @@ ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga) switch (addr) { case 0: - temp = svga_in((dev && dev->on) ? 0x2ec : 0x3c8, svga); + temp = svga_in((dev && (dev->on[0] || dev->on[1])) ? 0x2ec : 0x3c8, svga); break; case 1: - temp = svga_in((dev && dev->on) ? 0x2ed : 0x3c9, svga); + temp = svga_in((dev && (dev->on[0] || dev->on[1])) ? 0x2ed : 0x3c9, svga); break; case 2: - temp = svga_in((dev && dev->on) ? 0x2ea : 0x3c6, svga); + temp = svga_in((dev && (dev->on[0] || dev->on[1])) ? 0x2ea : 0x3c6, svga); break; case 3: - temp = svga_in((dev && dev->on) ? 0x2eb : 0x3c7, svga); + temp = svga_in((dev && (dev->on[0] || dev->on[1])) ? 0x2eb : 0x3c7, svga); break; case 4: case 8: From ad9da9bd4a8ddae053eab54e5348a29ef8f3b070 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Fri, 10 Nov 2023 23:23:18 +0500 Subject: [PATCH 113/133] Fix ATAPI HDDs not being displayed in the status bar --- src/qt/qt_machinestatus.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index bb3002df2..d7b115a64 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -429,11 +429,12 @@ MachineStatus::refresh(QStatusBar *sbar) bool has_xta = machine_has_flags(machine, MACHINE_XTA) > 0; bool has_esdi = machine_has_flags(machine, MACHINE_ESDI) > 0; - int c_mfm = hdd_count(HDD_BUS_MFM); - int c_esdi = hdd_count(HDD_BUS_ESDI); - int c_xta = hdd_count(HDD_BUS_XTA); - int c_ide = hdd_count(HDD_BUS_IDE); - int c_scsi = hdd_count(HDD_BUS_SCSI); + int c_mfm = hdd_count(HDD_BUS_MFM); + int c_esdi = hdd_count(HDD_BUS_ESDI); + int c_xta = hdd_count(HDD_BUS_XTA); + int c_ide = hdd_count(HDD_BUS_IDE); + int c_atapi = hdd_count(HDD_BUS_ATAPI); + int c_scsi = hdd_count(HDD_BUS_SCSI); sbar->removeWidget(d->cassette.label.get()); for (int i = 0; i < 2; ++i) { @@ -597,12 +598,21 @@ MachineStatus::refresh(QStatusBar *sbar) d->hdds[HDD_BUS_XTA].label->setToolTip(tr("Hard disk (%s)").replace("%s", "XTA")); sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get()); } - if ((hasIDE() || hdc_name.left(5) == QStringLiteral("xtide") || hdc_name.left(3) == QStringLiteral("ide")) && c_ide > 0) { - d->hdds[HDD_BUS_IDE].label = std::make_unique(); - d->hdds[HDD_BUS_IDE].setActive(false); - d->hdds[HDD_BUS_IDE].refresh(); - d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%s)").replace("%s", "IDE")); - sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get()); + if (hasIDE() || hdc_name.left(5) == QStringLiteral("xtide") || hdc_name.left(3) == QStringLiteral("ide")) { + if (c_ide > 0) { + d->hdds[HDD_BUS_IDE].label = std::make_unique(); + d->hdds[HDD_BUS_IDE].setActive(false); + d->hdds[HDD_BUS_IDE].refresh(); + d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%s)").replace("%s", "IDE")); + sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get()); + } + if (c_atapi > 0) { + d->hdds[HDD_BUS_ATAPI].label = std::make_unique(); + d->hdds[HDD_BUS_ATAPI].setActive(false); + d->hdds[HDD_BUS_ATAPI].refresh(); + d->hdds[HDD_BUS_ATAPI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "ATAPI")); + sbar->addWidget(d->hdds[HDD_BUS_ATAPI].label.get()); + } } if ((hasSCSI() || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || (scsi_card_current[2] != 0) || (scsi_card_current[3] != 0)) && c_scsi > 0) { d->hdds[HDD_BUS_SCSI].label = std::make_unique(); From 9bcece63fc52a308b8938427df2f3874410f6725 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 10 Nov 2023 17:27:30 -0300 Subject: [PATCH 114/133] Fix some random comments which have been bugging me --- src/cdrom/cdrom.c | 2 +- src/scsi/scsi_cdrom.c | 2 +- src/video/vid_tgui9440.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 22cefb991..40686f14a 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1414,7 +1414,7 @@ cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, in b[3] = ti.attr; cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 2) at %02i:%02i.%02i, track=%d, m=%02i,s=%02i,f=%02i, tno=%02x.\n", dev->id, b[0], b[1], b[2], bcd2bin(track), m, s, f, ti.attr); break; - case 3: /*Undocumented on NEC CD-ROM's, from information based on sr_vendor.c from Android's source code*/ + case 3: /* Undocumented on NEC CD-ROM's, from information based on sr_vendor.c from the Linux kernel */ switch (dev->type) { case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 056c7fdfe..fb52ca898 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1997,7 +1997,7 @@ begin: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_READ_DISC_INFORMATION_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_cdrom_buf_alloc(dev, 22); /*NEC manual claims 4 bytes, but the Android source code (namely sr_vendor.c) actually states otherwise.*/ + scsi_cdrom_buf_alloc(dev, 22); /* NEC manual claims 4 bytes, but the Linux kernel (namely sr_vendor.c) actually states otherwise. */ if (!dev->drv->ops) { scsi_cdrom_not_ready(dev); diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 0b5e99c4c..7bed43ac2 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -1462,7 +1462,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } } - /*See this: https://android.googlesource.com/kernel/tegra/+/android-tegra-flounder-3.10-lollipop-release/drivers/video/tridentfb.c for the pitch*/ + /* See Linux kernel drivers/video/tridentfb.c for the pitch */ tgui->accel.pitch = svga->rowoffset; switch (svga->bpp) { From c8ef85c249880d525103064c2d46bef43073706f Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 10 Nov 2023 22:42:36 +0100 Subject: [PATCH 115/133] Stop the initialization of a ZIP or Magneto-Optical drive if its task file structure pointer is NULL. --- src/disk/mo.c | 3 +++ src/disk/zip.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/disk/mo.c b/src/disk/mo.c index ad781a8ac..dda4222ca 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -2152,6 +2152,9 @@ mo_hard_reset(void) mo_init(dev); + if (dev->tf == NULL) + continue; + if (strlen(mo_drives[c].image_path)) mo_load(dev, mo_drives[c].image_path); diff --git a/src/disk/zip.c b/src/disk/zip.c index c498383e8..69af18e74 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -2391,6 +2391,9 @@ zip_hard_reset(void) zip_init(dev); + if (dev->tf == NULL) + continue; + if (strlen(zip_drives[c].image_path)) zip_load(dev, zip_drives[c].image_path); From f35a042f42d36c327dc7a0759bca9126f2fcc2d5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 10 Nov 2023 22:53:56 +0100 Subject: [PATCH 116/133] Moved the sanity checks to the correct place. --- src/disk/mo.c | 6 +++--- src/disk/zip.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/disk/mo.c b/src/disk/mo.c index dda4222ca..27bf7e5e0 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -2147,14 +2147,14 @@ mo_hard_reset(void) dev = (mo_t *) mo_drives[c].priv; + if (dev->tf == NULL) + continue; + dev->id = c; dev->drv = &mo_drives[c]; mo_init(dev); - if (dev->tf == NULL) - continue; - if (strlen(mo_drives[c].image_path)) mo_load(dev, mo_drives[c].image_path); diff --git a/src/disk/zip.c b/src/disk/zip.c index 69af18e74..887a9c68e 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -2386,14 +2386,14 @@ zip_hard_reset(void) dev = (zip_t *) zip_drives[c].priv; + if (dev->tf == NULL) + continue; + dev->id = c; dev->drv = &zip_drives[c]; zip_init(dev); - if (dev->tf == NULL) - continue; - if (strlen(zip_drives[c].image_path)) zip_load(dev, zip_drives[c].image_path); From 6153c84b8f0a21e7e07a9d07de8bb4e9f62644bf Mon Sep 17 00:00:00 2001 From: maximus105 <58270614+maximus105@users.noreply.github.com> Date: Sat, 11 Nov 2023 14:02:56 +0200 Subject: [PATCH 117/133] Update qt_mainwindow.cpp This commit fixes issue #3485 --- src/qt/qt_mainwindow.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index a5651eada..2fe9d22c2 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -615,6 +615,15 @@ MainWindow::MainWindow(QWidget *parent) if (!vnc_enabled) video_setblit(qt_blit); + if (start_in_fullscreen) { + connect(ui->stackedWidget, &RendererStack::blit, this, [this] () { + if (start_in_fullscreen) { + QTimer::singleShot(100, ui->actionFullscreen, &QAction::trigger); + start_in_fullscreen = 0; + } + }); + } + #ifdef MTR_ENABLED { ui->actionBegin_trace->setVisible(true); @@ -841,10 +850,6 @@ MainWindow::showEvent(QShowEvent *event) QApplication::processEvents(); this->adjustSize(); } - if (start_in_fullscreen) { - start_in_fullscreen = 0; - QTimer::singleShot(0, ui->actionFullscreen, &QAction::trigger); - } } void From 8637066855d00dab6180a01e4ee0fca85c375f26 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Nov 2023 15:42:15 +0100 Subject: [PATCH 118/133] Fixed some newly introduced indentation mess. --- src/qt/qt_mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 2fe9d22c2..a372dbfb8 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -615,7 +615,7 @@ MainWindow::MainWindow(QWidget *parent) if (!vnc_enabled) video_setblit(qt_blit); - if (start_in_fullscreen) { + if (start_in_fullscreen) { connect(ui->stackedWidget, &RendererStack::blit, this, [this] () { if (start_in_fullscreen) { QTimer::singleShot(100, ui->actionFullscreen, &QAction::trigger); From f9d673708a5aa46f5bf5969a9f32feb49bfd7314 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Nov 2023 16:57:55 +0100 Subject: [PATCH 119/133] Fixed warnings in the network code. --- src/network/net_eeprom_nmc93cxx.c | 4 - src/network/net_rtl8139.c | 496 ++++++++++++++---------------- src/network/net_tulip.c | 171 ---------- 3 files changed, 239 insertions(+), 432 deletions(-) diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index d51cc94e7..8842af997 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -66,10 +66,6 @@ nmc93cxx_eeprom_log(int lvl, const char *fmt, ...) # define nmc93cxx_eeprom_log(lvl, fmt, ...) #endif -static const char *opstring[] = { - "extended", "write", "read", "erase" -}; - static void * nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void *params) { diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index c184bdafa..1cac242ad 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -58,17 +58,22 @@ #define VLAN_TCI_LEN 2 #define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) -#if defined(DEBUG_RTL8139) -# define DPRINTF(fmt, ...) \ - do { \ - pclog("RTL8139: " fmt, ##__VA_ARGS__); \ - } while (0) -#else -static inline __attribute__((format(printf, 1, 2))) int -DPRINTF(UNUSED(const char *fmt), ...) +#ifdef ENABLE_RTL8139_LOG +int rtl8139_do_log = ENABLE_RTL8139_LOG; + +static void +rtl8139_log(const char *fmt, ...) { - return 0; + va_list ap; + + if (rtl8139_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } +#else +# define rtl8139_log(fmt, ...) #endif struct RTL8139State; @@ -499,7 +504,7 @@ static void RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr); static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) { - DPRINTF("eeprom command 0x%02x\n", command); + rtl8139_log("eeprom command 0x%02x\n", command); switch (command & Chip9346_op_mask) { case Chip9346_op_read: @@ -509,8 +514,8 @@ prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) eeprom->eedo = 0; eeprom->tick = 0; eeprom->mode = Chip9346_data_read; - DPRINTF("eeprom read from address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output); + rtl8139_log("eeprom read from address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); } break; @@ -520,21 +525,21 @@ prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) eeprom->input = 0; eeprom->tick = 0; eeprom->mode = Chip9346_none; /* Chip9346_data_write */ - DPRINTF("eeprom begin write to address 0x%02x\n", - eeprom->address); + rtl8139_log("eeprom begin write to address 0x%02x\n", + eeprom->address); } break; default: eeprom->mode = Chip9346_none; switch (command & Chip9346_op_ext_mask) { case Chip9346_op_write_enable: - DPRINTF("eeprom write enabled\n"); + rtl8139_log("eeprom write enabled\n"); break; case Chip9346_op_write_all: - DPRINTF("eeprom begin write all\n"); + rtl8139_log("eeprom begin write all\n"); break; case Chip9346_op_write_disable: - DPRINTF("eeprom write disabled\n"); + rtl8139_log("eeprom write disabled\n"); break; default: @@ -551,8 +556,8 @@ prom9346_shift_clock(EEprom9346 *eeprom) ++eeprom->tick; - DPRINTF("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, - eeprom->eedo); + rtl8139_log("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, + eeprom->eedo); switch (eeprom->mode) { case Chip9346_enter_command_mode: @@ -560,7 +565,7 @@ prom9346_shift_clock(EEprom9346 *eeprom) eeprom->mode = Chip9346_read_command; eeprom->tick = 0; eeprom->input = 0; - DPRINTF("eeprom: +++ synchronized, begin command read\n"); + rtl8139_log("eeprom: +++ synchronized, begin command read\n"); } break; @@ -583,7 +588,7 @@ prom9346_shift_clock(EEprom9346 *eeprom) eeprom->input = 0; eeprom->tick = 0; - DPRINTF("eeprom: +++ end of read, awaiting next command\n"); + rtl8139_log("eeprom: +++ end of read, awaiting next command\n"); #else // original behaviour ++eeprom->address; @@ -591,8 +596,8 @@ prom9346_shift_clock(EEprom9346 *eeprom) eeprom->output = eeprom->contents[eeprom->address]; eeprom->tick = 0; - DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output); + rtl8139_log("eeprom: +++ read next address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->output); #endif } break; @@ -600,8 +605,8 @@ prom9346_shift_clock(EEprom9346 *eeprom) case Chip9346_data_write: eeprom->input = (eeprom->input << 1) | (bit & 1); if (eeprom->tick == 16) { - DPRINTF("eeprom write to address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->input); + rtl8139_log("eeprom write to address 0x%02x data=0x%04x\n", + eeprom->address, eeprom->input); eeprom->contents[eeprom->address] = eeprom->input; eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ @@ -616,7 +621,7 @@ prom9346_shift_clock(EEprom9346 *eeprom) for (int i = 0; i < EEPROM_9346_SIZE; i++) { eeprom->contents[i] = eeprom->input; } - DPRINTF("eeprom filled with data=0x%04x\n", eeprom->input); + rtl8139_log("eeprom filled with data=0x%04x\n", eeprom->input); eeprom->mode = Chip9346_enter_command_mode; eeprom->tick = 0; @@ -651,8 +656,8 @@ prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) eeprom->eesk = eesk; eeprom->eedi = eedi; - DPRINTF("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, - eeprom->eesk, eeprom->eedi, eeprom->eedo); + rtl8139_log("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, + eeprom->eesk, eeprom->eedi, eeprom->eedo); if (!old_eecs && eecs) { /* Synchronize start */ @@ -661,11 +666,11 @@ prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) eeprom->output = 0; eeprom->mode = Chip9346_enter_command_mode; - DPRINTF("=== eeprom: begin access, enter command mode\n"); + rtl8139_log("=== eeprom: begin access, enter command mode\n"); } if (!eecs) { - DPRINTF("=== eeprom: end access\n"); + rtl8139_log("=== eeprom: end access\n"); return; } @@ -683,8 +688,8 @@ rtl8139_update_irq(RTL8139State *s) isr = (s->IntrStatus & s->IntrMask) & 0xffff; - DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus, - s->IntrMask); + rtl8139_log("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus, + s->IntrMask); if (isr != 0) pci_set_irq(d, PCI_INTA, &s->irq_state); @@ -731,7 +736,7 @@ rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) /* write packet data */ if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s))) { - DPRINTF(">>> rx packet wrapped in buffer at %d\n", size - wrapped); + rtl8139_log(">>> rx packet wrapped in buffer at %d\n", size - wrapped); if (size > wrapped) { dma_bm_write(s->RxBuf + s->RxBufAddr, @@ -856,34 +861,34 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - DPRINTF(">>> received len=%zu\n", size); + rtl8139_log(">>> received len=%u\n", (uint32_t) size); if (!rtl8139_can_receive(s)) return 0; /* test if board clock is stopped */ if (!s->clock_enabled) { - DPRINTF("stopped ==========================\n"); + rtl8139_log("stopped ==========================\n"); return -1; } /* first check if receiver is enabled */ if (!rtl8139_receiver_enabled(s)) { - DPRINTF("receiver disabled ================\n"); + rtl8139_log("receiver disabled ================\n"); return -1; } /* XXX: check this */ if (s->RxConfig & AcceptAllPhys) { /* promiscuous: receive all */ - DPRINTF(">>> packet received in promiscuous mode\n"); + rtl8139_log(">>> packet received in promiscuous mode\n"); } else { if (!memcmp(buf, broadcast_macaddr, 6)) { /* broadcast address */ if (!(s->RxConfig & AcceptBroadcast)) { - DPRINTF(">>> broadcast packet rejected\n"); + rtl8139_log(">>> broadcast packet rejected\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -893,7 +898,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) packet_header |= RxBroadcast; - DPRINTF(">>> broadcast packet received\n"); + rtl8139_log(">>> broadcast packet received\n"); /* update tally counter */ ++s->tally_counters.RxOkBrd; @@ -901,7 +906,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) } else if (buf[0] & 0x01) { /* multicast */ if (!(s->RxConfig & AcceptMulticast)) { - DPRINTF(">>> multicast packet rejected\n"); + rtl8139_log(">>> multicast packet rejected\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -912,7 +917,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) int mcast_idx = net_crc32(buf, ETH_ALEN) >> 26; if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) { - DPRINTF(">>> multicast address mismatch\n"); + rtl8139_log(">>> multicast address mismatch\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -922,7 +927,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) packet_header |= RxMulticast; - DPRINTF(">>> multicast packet received\n"); + rtl8139_log(">>> multicast packet received\n"); /* update tally counter */ ++s->tally_counters.RxOkMul; @@ -930,7 +935,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) } else if (s->phys[0] == buf[0] && s->phys[1] == buf[1] && s->phys[2] == buf[2] && s->phys[3] == buf[3] && s->phys[4] == buf[4] && s->phys[5] == buf[5]) { /* match */ if (!(s->RxConfig & AcceptMyPhys)) { - DPRINTF(">>> rejecting physical address matching packet\n"); + rtl8139_log(">>> rejecting physical address matching packet\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -940,14 +945,14 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) packet_header |= RxPhysical; - DPRINTF(">>> physical address matching packet received\n"); + rtl8139_log(">>> physical address matching packet received\n"); /* update tally counter */ ++s->tally_counters.RxOkPhy; } else { - DPRINTF(">>> unknown packet\n"); + rtl8139_log(">>> unknown packet\n"); /* update tally counter */ ++s->tally_counters.RxERR; @@ -970,7 +975,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) return size; } - DPRINTF("in C+ Rx mode ================\n"); + rtl8139_log("in C+ Rx mode ================\n"); /* begin C+ receiver mode */ @@ -993,7 +998,7 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); cplus_rx_ring_desc += 16 * descriptor; - DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at " + rtl8139_log("+++ C+ mode reading RX descriptor %d from host memory at " "%08x %08x = " "0x%8X" "\n", @@ -1015,12 +1020,12 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) dma_bm_read(cplus_rx_ring_desc + 12, (uint8_t *) &val, 4, 4); rxbufHI = val; - DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", - descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI); + rtl8139_log("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", + descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI); if (!(rxdw0 & CP_RX_OWN)) { - DPRINTF("C+ Rx mode : descriptor %d is owned by host\n", - descriptor); + rtl8139_log("C+ Rx mode : descriptor %d is owned by host\n", + descriptor); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1048,9 +1053,9 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* BE + ~le_to_cpu()~ + cpu_to_le() = BE */ rxdw1 |= CP_RX_TAVA | *((uint16_t *) (&dot1q_buf[ETHER_TYPE_LEN])); - DPRINTF("C+ Rx mode : extracted vlan tag with tci: " - "%u\n", - bswap16(*((uint16_t *) &dot1q_buf[ETHER_TYPE_LEN]))); + rtl8139_log("C+ Rx mode : extracted vlan tag with tci: " + "%u\n", + bswap16(*((uint16_t *) &dot1q_buf[ETHER_TYPE_LEN]))); } else { /* reset VLAN tag flag */ rxdw1 &= ~CP_RX_TAVA; @@ -1059,8 +1064,8 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* TODO: scatter the packet over available receive ring descriptors space */ if (size + 4 > rx_space) { - DPRINTF("C+ Rx mode : descriptor %d size %d received %zu + 4\n", - descriptor, rx_space, size); + rtl8139_log("C+ Rx mode : descriptor %d size %d received %u + 4\n", + descriptor, rx_space, (uint32_t) size); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1151,10 +1156,10 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) ++s->currCPlusRxDesc; } - DPRINTF("done C+ Rx mode ----------------\n"); + rtl8139_log("done C+ Rx mode ----------------\n"); } else { - DPRINTF("in ring Rx mode ================\n"); + rtl8139_log("in ring Rx mode ================\n"); /* begin ring receiver mode */ int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); @@ -1164,9 +1169,9 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) #define RX_ALIGN(x) (((x) + 3) & ~0x3) if (avail != 0 && RX_ALIGN(size + 8) >= avail) { - DPRINTF("rx overflow: rx buffer length %d head 0x%04x " - "read 0x%04x === available 0x%04x need 0x%04zx\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); + rtl8139_log("rx overflow: rx buffer length %d head 0x%04x " + "read 0x%04x === available 0x%04x need 0x%04zx\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); s->IntrStatus |= RxOverflow; ++s->RxMissed; @@ -1194,8 +1199,8 @@ rtl8139_do_receive(void *priv, uint8_t *buf, int size_) /* now we can signal we have received something */ - DPRINTF("received: rx buffer length %d head 0x%04x read 0x%04x\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); + rtl8139_log("received: rx buffer length %d head 0x%04x read 0x%04x\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } s->IntrStatus |= RxOK; @@ -1330,19 +1335,19 @@ rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DPRINTF("ChipCmd write val=0x%08x\n", val); + rtl8139_log("ChipCmd write val=0x%08x\n", val); if (val & CmdReset) { - DPRINTF("ChipCmd reset\n"); + rtl8139_log("ChipCmd reset\n"); rtl8139_reset(s); } if (val & CmdRxEnb) { - DPRINTF("ChipCmd enable receiver\n"); + rtl8139_log("ChipCmd enable receiver\n"); s->currCPlusRxDesc = 0; } if (val & CmdTxEnb) { - DPRINTF("ChipCmd enable transmitter\n"); + rtl8139_log("ChipCmd enable transmitter\n"); s->currCPlusTxDesc = 0; } @@ -1362,11 +1367,11 @@ rtl8139_RxBufferEmpty(RTL8139State *s) int unread = MOD2(s->RxBufferSize + s->RxBufAddr - s->RxBufPtr, s->RxBufferSize); if (unread != 0) { - DPRINTF("receiver buffer data available 0x%04x\n", unread); + rtl8139_log("receiver buffer data available 0x%04x\n", unread); return 0; } - DPRINTF("receiver buffer is empty\n"); + rtl8139_log("receiver buffer is empty\n"); return 1; } @@ -1379,7 +1384,7 @@ rtl8139_ChipCmd_read(RTL8139State *s) if (rtl8139_RxBufferEmpty(s)) ret |= RxBufEmpty; - DPRINTF("ChipCmd read val=0x%04x\n", ret); + rtl8139_log("ChipCmd read val=0x%04x\n", ret); return ret; } @@ -1389,7 +1394,7 @@ rtl8139_CpCmd_write(RTL8139State *s, uint32_t val) { val &= 0xffff; - DPRINTF("C+ command register write(w) val=0x%04x\n", val); + rtl8139_log("C+ command register write(w) val=0x%04x\n", val); s->cplus_enabled = 1; @@ -1404,7 +1409,7 @@ rtl8139_CpCmd_read(RTL8139State *s) { uint32_t ret = s->CpCmd; - DPRINTF("C+ command register read(w) val=0x%04x\n", ret); + rtl8139_log("C+ command register read(w) val=0x%04x\n", ret); return ret; } @@ -1412,7 +1417,7 @@ rtl8139_CpCmd_read(RTL8139State *s) static void rtl8139_IntrMitigate_write(UNUSED(RTL8139State *s), uint32_t val) { - DPRINTF("C+ IntrMitigate register write(w) val=0x%04x\n", val); + rtl8139_log("C+ IntrMitigate register write(w) val=0x%04x\n", val); } static uint32_t @@ -1420,7 +1425,7 @@ rtl8139_IntrMitigate_read(UNUSED(RTL8139State *s)) { uint32_t ret = 0; - DPRINTF("C+ IntrMitigate register read(w) val=0x%04x\n", ret); + rtl8139_log("C+ IntrMitigate register read(w) val=0x%04x\n", ret); return ret; } @@ -1432,7 +1437,7 @@ rtl8139_config_writable(RTL8139State *s) return 1; } - DPRINTF("Configuration registers are write-protected\n"); + rtl8139_log("Configuration registers are write-protected\n"); return 0; } @@ -1442,7 +1447,7 @@ rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val) { val &= 0xffff; - DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val); + rtl8139_log("BasicModeCtrl register write(w) val=0x%04x\n", val); /* mask unwritable bits */ uint32_t mask = 0xccff; @@ -1469,7 +1474,7 @@ rtl8139_BasicModeCtrl_read(RTL8139State *s) { uint32_t ret = s->BasicModeCtrl; - DPRINTF("BasicModeCtrl register read(w) val=0x%04x\n", ret); + rtl8139_log("BasicModeCtrl register read(w) val=0x%04x\n", ret); return ret; } @@ -1479,7 +1484,7 @@ rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val) { val &= 0xffff; - DPRINTF("BasicModeStatus register write(w) val=0x%04x\n", val); + rtl8139_log("BasicModeStatus register write(w) val=0x%04x\n", val); /* mask unwritable bits */ val = SET_MASKED(val, 0xff3f, s->BasicModeStatus); @@ -1492,7 +1497,7 @@ rtl8139_BasicModeStatus_read(RTL8139State *s) { uint32_t ret = s->BasicModeStatus; - DPRINTF("BasicModeStatus register read(w) val=0x%04x\n", ret); + rtl8139_log("BasicModeStatus register read(w) val=0x%04x\n", ret); return ret; } @@ -1502,7 +1507,7 @@ rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DPRINTF("Cfg9346 write val=0x%02x\n", val); + rtl8139_log("Cfg9346 write val=0x%02x\n", val); /* mask unwritable bits */ val = SET_MASKED(val, 0x31, s->Cfg9346); @@ -1542,7 +1547,7 @@ rtl8139_Cfg9346_read(RTL8139State *s) } } - DPRINTF("Cfg9346 read val=0x%02x\n", ret); + rtl8139_log("Cfg9346 read val=0x%02x\n", ret); return ret; } @@ -1552,7 +1557,7 @@ rtl8139_Config0_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DPRINTF("Config0 write val=0x%02x\n", val); + rtl8139_log("Config0 write val=0x%02x\n", val); if (!rtl8139_config_writable(s)) { return; @@ -1569,7 +1574,7 @@ rtl8139_Config0_read(RTL8139State *s) { uint32_t ret = s->Config0; - DPRINTF("Config0 read val=0x%02x\n", ret); + rtl8139_log("Config0 read val=0x%02x\n", ret); return ret; } @@ -1579,7 +1584,7 @@ rtl8139_Config1_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DPRINTF("Config1 write val=0x%02x\n", val); + rtl8139_log("Config1 write val=0x%02x\n", val); if (!rtl8139_config_writable(s)) { return; @@ -1596,7 +1601,7 @@ rtl8139_Config1_read(RTL8139State *s) { uint32_t ret = s->Config1; - DPRINTF("Config1 read val=0x%02x\n", ret); + rtl8139_log("Config1 read val=0x%02x\n", ret); return ret; } @@ -1606,7 +1611,7 @@ rtl8139_Config3_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DPRINTF("Config3 write val=0x%02x\n", val); + rtl8139_log("Config3 write val=0x%02x\n", val); if (!rtl8139_config_writable(s)) { return; @@ -1623,7 +1628,7 @@ rtl8139_Config3_read(RTL8139State *s) { uint32_t ret = s->Config3; - DPRINTF("Config3 read val=0x%02x\n", ret); + rtl8139_log("Config3 read val=0x%02x\n", ret); return ret; } @@ -1633,7 +1638,7 @@ rtl8139_Config4_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DPRINTF("Config4 write val=0x%02x\n", val); + rtl8139_log("Config4 write val=0x%02x\n", val); if (!rtl8139_config_writable(s)) { return; @@ -1650,7 +1655,7 @@ rtl8139_Config4_read(RTL8139State *s) { uint32_t ret = s->Config4; - DPRINTF("Config4 read val=0x%02x\n", ret); + rtl8139_log("Config4 read val=0x%02x\n", ret); return ret; } @@ -1660,7 +1665,7 @@ rtl8139_Config5_write(RTL8139State *s, uint32_t val) { val &= 0xff; - DPRINTF("Config5 write val=0x%02x\n", val); + rtl8139_log("Config5 write val=0x%02x\n", val); /* mask unwritable bits */ val = SET_MASKED(val, 0x80, s->Config5); @@ -1673,7 +1678,7 @@ rtl8139_Config5_read(RTL8139State *s) { uint32_t ret = s->Config5; - DPRINTF("Config5 read val=0x%02x\n", ret); + rtl8139_log("Config5 read val=0x%02x\n", ret); return ret; } @@ -1682,11 +1687,11 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) { if (!rtl8139_transmitter_enabled(s)) { - DPRINTF("transmitter disabled; no TxConfig write val=0x%08x\n", val); + rtl8139_log("transmitter disabled; no TxConfig write val=0x%08x\n", val); return; } - DPRINTF("TxConfig write val=0x%08x\n", val); + rtl8139_log("TxConfig write val=0x%08x\n", val); val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig); @@ -1696,7 +1701,7 @@ rtl8139_TxConfig_write(RTL8139State *s, uint32_t val) static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val) { - DPRINTF("RTL8139C TxConfig via write(b) val=0x%02x\n", val); + rtl8139_log("RTL8139C TxConfig via write(b) val=0x%02x\n", val); uint32_t tc = s->TxConfig; @@ -1710,7 +1715,7 @@ rtl8139_TxConfig_read(RTL8139State *s) { uint32_t ret = s->TxConfig; - DPRINTF("TxConfig read val=0x%04x\n", ret); + rtl8139_log("TxConfig read val=0x%04x\n", ret); return ret; } @@ -1718,7 +1723,7 @@ rtl8139_TxConfig_read(RTL8139State *s) static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) { - DPRINTF("RxConfig write val=0x%08x\n", val); + rtl8139_log("RxConfig write val=0x%08x\n", val); /* mask unwritable bits */ val = SET_MASKED(val, 0xf0fc0040, s->RxConfig); @@ -1728,7 +1733,7 @@ rtl8139_RxConfig_write(RTL8139State *s, uint32_t val) /* reset buffer size and read/write pointers */ rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3)); - DPRINTF("RxConfig write reset buffer size to %d\n", s->RxBufferSize); + rtl8139_log("RxConfig write reset buffer size to %d\n", s->RxBufferSize); } static uint32_t @@ -1736,7 +1741,7 @@ rtl8139_RxConfig_read(RTL8139State *s) { uint32_t ret = s->RxConfig; - DPRINTF("RxConfig read val=0x%08x\n", ret); + rtl8139_log("RxConfig read val=0x%08x\n", ret); return ret; } @@ -1753,7 +1758,7 @@ rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, { void (*network_func)(netcard_t *, uint8_t *, int) = (TxLoopBack == (s->TxConfig & TxLoopBack)) ? rtl8139_network_rx_put : network_tx; if (!size) { - DPRINTF("+++ empty ethernet frame\n"); + rtl8139_log("+++ empty ethernet frame\n"); return; } @@ -1775,23 +1780,21 @@ rtl8139_transmit_one(RTL8139State *s, int descriptor) uint8_t txbuffer[0x2000]; if (!rtl8139_transmitter_enabled(s)) { - DPRINTF("+++ cannot transmit from descriptor %d: transmitter " - "disabled\n", - descriptor); + rtl8139_log("+++ cannot transmit from descriptor %d: transmitter " + "disabled\n", descriptor); return 0; } if (s->TxStatus[descriptor] & TxHostOwns) { - DPRINTF("+++ cannot transmit from descriptor %d: owned by host " - "(%08x)\n", - descriptor, s->TxStatus[descriptor]); + rtl8139_log("+++ cannot transmit from descriptor %d: owned by host " + "(%08x)\n", descriptor, s->TxStatus[descriptor]); return 0; } - DPRINTF("+++ transmitting from descriptor %d\n", descriptor); + rtl8139_log("+++ transmitting from descriptor %d\n", descriptor); - DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n", - txsize, s->TxAddr[descriptor]); + rtl8139_log("+++ transmit reading %d bytes from host memory at 0x%08x\n", + txsize, s->TxAddr[descriptor]); dma_bm_read(s->TxAddr[descriptor], txbuffer, txsize, 1); @@ -1801,8 +1804,8 @@ rtl8139_transmit_one(RTL8139State *s, int descriptor) rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL); - DPRINTF("+++ transmitted %d bytes from descriptor %d\n", txsize, - descriptor); + rtl8139_log("+++ transmitted %d bytes from descriptor %d\n", txsize, + descriptor); /* update interrupt */ s->IntrStatus |= TxOK; @@ -1902,12 +1905,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) { if (!rtl8139_transmitter_enabled(s)) { - DPRINTF("+++ C+ mode: transmitter disabled\n"); + rtl8139_log("+++ C+ mode: transmitter disabled\n"); return 0; } if (!rtl8139_cp_transmitter_enabled(s)) { - DPRINTF("+++ C+ mode: C+ transmitter disabled\n"); + rtl8139_log("+++ C+ mode: C+ transmitter disabled\n"); return 0; } int descriptor = s->currCPlusTxDesc; @@ -1917,10 +1920,9 @@ rtl8139_cplus_transmit_one(RTL8139State *s) /* Normal priority ring */ cplus_tx_ring_desc += 16 * descriptor; - DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at " - "%08x %08x = 0x%08X\n", - descriptor, s->TxAddr[1], - s->TxAddr[0], cplus_tx_ring_desc); + rtl8139_log("+++ C+ mode reading TX descriptor %d from host memory at " + "%08x %08x = 0x%08X\n", descriptor, s->TxAddr[1], + s->TxAddr[0], cplus_tx_ring_desc); uint32_t val; uint32_t txdw0; @@ -1937,8 +1939,8 @@ rtl8139_cplus_transmit_one(RTL8139State *s) dma_bm_read(cplus_tx_ring_desc + 12, (uint8_t *) &val, 4, 4); txbufHI = le32_to_cpu(val); - DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor, - txdw0, txdw1, txbufLO, txbufHI); + rtl8139_log("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor, + txdw0, txdw1, txbufLO, txbufHI); /* w0 ownership flag */ #define CP_TX_OWN (1 << 31) @@ -1984,16 +1986,15 @@ rtl8139_cplus_transmit_one(RTL8139State *s) #define CP_TX_STATUS_EXC (1 << 20) if (!(txdw0 & CP_TX_OWN)) { - DPRINTF("C+ Tx mode : descriptor %d is owned by host\n", descriptor); + rtl8139_log("C+ Tx mode : descriptor %d is owned by host\n", descriptor); return 0; } - DPRINTF("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor); + rtl8139_log("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor); if (txdw0 & CP_TX_FS) { - DPRINTF("+++ C+ Tx mode : descriptor %d is first segment " - "descriptor\n", - descriptor); + rtl8139_log("+++ C+ Tx mode : descriptor %d is first segment " + "descriptor\n", descriptor); /* reset internal buffer offset */ s->cplus_txbuffer_offset = 0; @@ -2008,25 +2009,21 @@ rtl8139_cplus_transmit_one(RTL8139State *s) s->cplus_txbuffer = calloc(s->cplus_txbuffer_len, 1); s->cplus_txbuffer_offset = 0; - DPRINTF("+++ C+ mode transmission buffer allocated space %d\n", - s->cplus_txbuffer_len); + rtl8139_log("+++ C+ mode transmission buffer allocated space %d\n", + s->cplus_txbuffer_len); } if (s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) { /* The spec didn't tell the maximum size, stick to CP_TX_BUFFER_SIZE */ txsize = s->cplus_txbuffer_len - s->cplus_txbuffer_offset; - DPRINTF("+++ C+ mode transmission buffer overrun, truncated descriptor" - "length to %d\n", - txsize); + rtl8139_log("+++ C+ mode transmission buffer overrun, truncated descriptor" + "length to %d\n", txsize); } /* append more data to the packet */ - DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at " - "%08X" - " to offset %d\n", - txsize, tx_addr, - s->cplus_txbuffer_offset); + rtl8139_log("+++ C+ mode transmit reading %d bytes from host memory at " + "%08X to offset %d\n", txsize, tx_addr, s->cplus_txbuffer_offset); dma_bm_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize, 1); @@ -2063,8 +2060,8 @@ rtl8139_cplus_transmit_one(RTL8139State *s) uint8_t dot1q_buffer_space[VLAN_HLEN]; uint16_t *dot1q_buffer; - DPRINTF("+++ C+ Tx mode : descriptor %d is last segment descriptor\n", - descriptor); + rtl8139_log("+++ C+ Tx mode : descriptor %d is last segment descriptor\n", + descriptor); /* can transfer fully assembled packet */ @@ -2076,9 +2073,8 @@ rtl8139_cplus_transmit_one(RTL8139State *s) if (txdw1 & CP_TX_TAGC) { /* the vlan tag is in BE byte order in the descriptor * BE + le_to_cpu() + ~swap()~ = cpu */ - DPRINTF("+++ C+ Tx mode : inserting vlan tag with " - "tci: %u\n", - bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)); + rtl8139_log("+++ C+ Tx mode : inserting vlan tag with " + "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)); dot1q_buffer = (uint16_t *) dot1q_buffer_space; dot1q_buffer[0] = cpu_to_be16(0x8100); @@ -2094,7 +2090,7 @@ rtl8139_cplus_transmit_one(RTL8139State *s) s->cplus_txbuffer_len = 0; if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN)) { - DPRINTF("+++ C+ mode offloaded task checksum\n"); + rtl8139_log("+++ C+ mode offloaded task checksum\n"); /* Large enough for Ethernet and IP headers? */ if (saved_size < ETH_HLEN + sizeof(struct ip_header)) { @@ -2115,7 +2111,7 @@ rtl8139_cplus_transmit_one(RTL8139State *s) goto skip_offload; } - DPRINTF("+++ C+ mode has IP packet\n"); + rtl8139_log("+++ C+ mode has IP packet\n"); /* Note on memory alignment: eth_payload_data is 16-bit aligned * since saved_buffer is allocated with g_malloc() and ETH_HLEN is @@ -2128,10 +2124,9 @@ rtl8139_cplus_transmit_one(RTL8139State *s) ip = (struct ip_header *) eth_payload_data; if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { - DPRINTF("+++ C+ mode packet has bad IP version %d " - "expected %d\n", - IP_HEADER_VERSION(ip), - IP_HEADER_VERSION_4); + rtl8139_log("+++ C+ mode packet has bad IP version %d " + "expected %d\n", IP_HEADER_VERSION(ip), + IP_HEADER_VERSION_4); goto skip_offload; } @@ -2149,12 +2144,12 @@ rtl8139_cplus_transmit_one(RTL8139State *s) ip_data_len -= hlen; if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & CP_TX_IPCS)) { - DPRINTF("+++ C+ mode need IP checksum\n"); + rtl8139_log("+++ C+ mode need IP checksum\n"); ip->ip_sum = 0; ip->ip_sum = ip_checksum(ip, hlen); - DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", - hlen, ip->ip_sum); + rtl8139_log("+++ C+ mode IP header len=%d checksum=%04x\n", + hlen, ip->ip_sum); } if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) { @@ -2168,9 +2163,9 @@ rtl8139_cplus_transmit_one(RTL8139State *s) goto skip_offload; } - DPRINTF("+++ C+ mode offloaded task TSO IP data %d " - "frame data %d specified MSS=%d\n", - ip_data_len, saved_size - ETH_HLEN, large_send_mss); + rtl8139_log("+++ C+ mode offloaded task TSO IP data %d " + "frame data %d specified MSS=%d\n", + ip_data_len, saved_size - ETH_HLEN, large_send_mss); /* maximum IP header length is 60 bytes */ uint8_t saved_ip_header[60]; @@ -2196,9 +2191,8 @@ rtl8139_cplus_transmit_one(RTL8139State *s) int tcp_data_len = ip_data_len - tcp_hlen; - DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " - "data len %d\n", - ip_data_len, tcp_hlen, tcp_data_len); + rtl8139_log("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " + "data len %d\n", ip_data_len, tcp_hlen, tcp_data_len); /* note the cycle below overwrites IP header data, but restores it from saved_ip_header before sending packet */ @@ -2214,16 +2208,17 @@ rtl8139_cplus_transmit_one(RTL8139State *s) chunk_size = tcp_data_len - tcp_send_offset; } - // DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", - // ldl_be_p(&p_tcp_hdr->th_seq)); +#if 0 + rtl8139_log("+++ C+ mode TSO TCP seqno %08x\n", + ldl_be_p(&p_tcp_hdr->th_seq)); +#endif /* add 4 TCP pseudoheader fields */ /* copy IP source and destination fields */ memcpy(data_to_checksum, saved_ip_header + 12, 8); - DPRINTF("+++ C+ mode TSO calculating TCP checksum for " - "packet with %d bytes data\n", - tcp_hlen + chunk_size); + rtl8139_log("+++ C+ mode TSO calculating TCP checksum for " + "packet with %d bytes data\n", tcp_hlen + chunk_size); if (tcp_send_offset) { memcpy((uint8_t *) p_tcp_hdr + tcp_hlen, (uint8_t *) p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); @@ -2245,8 +2240,7 @@ rtl8139_cplus_transmit_one(RTL8139State *s) p_tcp_hdr->th_sum = 0; int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); - DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", - tcp_checksum); + rtl8139_log("+++ C+ mode TSO TCP checksum %04x\n", tcp_checksum); p_tcp_hdr->th_sum = tcp_checksum; @@ -2261,14 +2255,12 @@ rtl8139_cplus_transmit_one(RTL8139State *s) ip->ip_sum = 0; ip->ip_sum = ip_checksum(eth_payload_data, hlen); - DPRINTF("+++ C+ mode TSO IP header len=%d " - "checksum=%04x\n", - hlen, ip->ip_sum); + rtl8139_log("+++ C+ mode TSO IP header len=%d checksum=%04x\n", + hlen, ip->ip_sum); int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; - DPRINTF("+++ C+ mode TSO transferring packet size " - "%d\n", - tso_send_size); + rtl8139_log("+++ C+ mode TSO transferring packet size %d\n", + tso_send_size); rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0, (uint8_t *) dot1q_buffer); @@ -2283,7 +2275,7 @@ rtl8139_cplus_transmit_one(RTL8139State *s) /* Stop sending this frame */ saved_size = 0; } else if (!(txdw0 & CP_TX_LGSEN) && (txdw0 & (CP_TX_TCPCS | CP_TX_UDPCS))) { - DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); + rtl8139_log("+++ C+ mode need TCP or UDP checksum\n"); /* maximum IP header length is 60 bytes */ uint8_t saved_ip_header[60]; @@ -2299,9 +2291,8 @@ rtl8139_cplus_transmit_one(RTL8139State *s) memcpy(data_to_checksum, saved_ip_header + 12, 8); if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) { - DPRINTF("+++ C+ mode calculating TCP checksum for " - "packet with %d bytes data\n", - ip_data_len); + rtl8139_log("+++ C+ mode calculating TCP checksum for " + "packet with %d bytes data\n", ip_data_len); ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *) data_to_checksum; p_tcpip_hdr->zeros = 0; @@ -2313,14 +2304,12 @@ rtl8139_cplus_transmit_one(RTL8139State *s) p_tcp_hdr->th_sum = 0; int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); - DPRINTF("+++ C+ mode TCP checksum %04x\n", - tcp_checksum); + rtl8139_log("+++ C+ mode TCP checksum %04x\n", tcp_checksum); p_tcp_hdr->th_sum = tcp_checksum; } else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) { - DPRINTF("+++ C+ mode calculating UDP checksum for " - "packet with %d bytes data\n", - ip_data_len); + rtl8139_log("+++ C+ mode calculating UDP checksum for " + "packet with %d bytes data\n", ip_data_len); ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *) data_to_checksum; p_udpip_hdr->zeros = 0; @@ -2332,8 +2321,7 @@ rtl8139_cplus_transmit_one(RTL8139State *s) p_udp_hdr->uh_sum = 0; int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); - DPRINTF("+++ C+ mode UDP checksum %04x\n", - udp_checksum); + rtl8139_log("+++ C+ mode UDP checksum %04x\n", udp_checksum); p_udp_hdr->uh_sum = udp_checksum; } @@ -2347,7 +2335,7 @@ skip_offload: /* update tally counter */ ++s->tally_counters.TxOk; - DPRINTF("+++ C+ mode transmitting %d bytes packet\n", saved_size); + rtl8139_log("+++ C+ mode transmitting %d bytes packet\n", saved_size); rtl8139_transfer_frame(s, saved_buffer, saved_size, 1, (uint8_t *) dot1q_buffer); @@ -2357,11 +2345,10 @@ skip_offload: s->cplus_txbuffer = saved_buffer; s->cplus_txbuffer_len = saved_buffer_len; s->cplus_txbuffer_offset = 0; - } else { + } else free(saved_buffer); - } } else { - DPRINTF("+++ C+ mode transmission continue to next descriptor\n"); + rtl8139_log("+++ C+ mode transmission continue to next descriptor\n"); } return 1; @@ -2378,8 +2365,8 @@ rtl8139_cplus_transmit(RTL8139State *s) /* Mark transfer completed */ if (!txcount) { - DPRINTF("C+ mode : transmitter queue stalled, current TxDesc = %d\n", - s->currCPlusTxDesc); + rtl8139_log("C+ mode : transmitter queue stalled, current TxDesc = %d\n", + s->currCPlusTxDesc); } else { /* update interrupt status */ s->IntrStatus |= TxOK; @@ -2402,8 +2389,8 @@ rtl8139_transmit(RTL8139State *s) /* Mark transfer completed */ if (!txcount) { - DPRINTF("transmitter queue stalled, current TxDesc = %d\n", - s->currTxDesc); + rtl8139_log("transmitter queue stalled, current TxDesc = %d\n", + s->currTxDesc); } } @@ -2415,9 +2402,8 @@ rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) /* handle C+ transmit mode register configuration */ if (s->cplus_enabled) { - DPRINTF("RTL8139C+ DTCCR write offset=0x%x val=0x%08x " - "descriptor=%d\n", - txRegOffset, val, descriptor); + rtl8139_log("RTL8139C+ DTCCR write offset=0x%x val=0x%08x " + "descriptor=%d\n", txRegOffset, val, descriptor); /* handle Dump Tally Counters command */ s->TxStatus[descriptor] = val; @@ -2435,8 +2421,8 @@ rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) return; } - DPRINTF("TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", - txRegOffset, val, descriptor); + rtl8139_log("TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", + txRegOffset, val, descriptor); /* mask only reserved bits */ val &= ~0xff00c000; /* these bits are reset on write */ @@ -2458,9 +2444,8 @@ rtl8139_TxStatus_TxAddr_read(UNUSED(RTL8139State *s), uint32_t regs[], uint32_t ret = 0; if (addr & (size - 1)) { - DPRINTF("not implemented read for TxStatus/TxAddr " - "addr=0x%x size=0x%x\n", - addr, size); + rtl8139_log("not implemented read for TxStatus/TxAddr " + "addr=0x%x size=0x%x\n", addr, size); return ret; } @@ -2469,12 +2454,12 @@ rtl8139_TxStatus_TxAddr_read(UNUSED(RTL8139State *s), uint32_t regs[], case 2: /* fall through */ case 4: ret = (regs[reg] >> offset * 8) & (((uint64_t) 1 << (size * 8)) - 1); - DPRINTF("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n", - reg, addr, size, ret); + rtl8139_log("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n", + reg, addr, size, ret); break; default: - DPRINTF("unsupported size 0x%x of TxStatus/TxAddr reading\n", size); + rtl8139_log("unsupported size 0x%x of TxStatus/TxAddr reading\n", size); break; } @@ -2508,7 +2493,7 @@ rtl8139_TSAD_read(RTL8139State *s) | ((s->TxStatus[1] & TxHostOwns) ? TSAD_OWN1 : 0) | ((s->TxStatus[0] & TxHostOwns) ? TSAD_OWN0 : 0); - DPRINTF("TSAD read val=0x%04x\n", ret); + rtl8139_log("TSAD read val=0x%04x\n", ret); return ret; } @@ -2518,7 +2503,7 @@ rtl8139_CSCR_read(RTL8139State *s) { uint16_t ret = s->CSCR; - DPRINTF("CSCR read val=0x%04x\n", ret); + rtl8139_log("CSCR read val=0x%04x\n", ret); return ret; } @@ -2526,7 +2511,7 @@ rtl8139_CSCR_read(RTL8139State *s) static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val) { - DPRINTF("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val); + rtl8139_log("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val); s->TxAddr[txAddrOffset / 4] = val; } @@ -2536,7 +2521,7 @@ rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) { uint32_t ret = s->TxAddr[txAddrOffset / 4]; - DPRINTF("TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret); + rtl8139_log("TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret); return ret; } @@ -2544,13 +2529,13 @@ rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset) static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) { - DPRINTF("RxBufPtr write val=0x%04x\n", val); + rtl8139_log("RxBufPtr write val=0x%04x\n", val); /* this value is off by 16 */ s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize); - DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", - s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); + rtl8139_log(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", + s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } static uint32_t @@ -2559,7 +2544,7 @@ rtl8139_RxBufPtr_read(RTL8139State *s) /* this value is off by 16 */ uint32_t ret = s->RxBufPtr - 0x10; - DPRINTF("RxBufPtr read val=0x%04x\n", ret); + rtl8139_log("RxBufPtr read val=0x%04x\n", ret); return ret; } @@ -2570,7 +2555,7 @@ rtl8139_RxBufAddr_read(RTL8139State *s) /* this value is NOT off by 16 */ uint32_t ret = s->RxBufAddr; - DPRINTF("RxBufAddr read val=0x%04x\n", ret); + rtl8139_log("RxBufAddr read val=0x%04x\n", ret); return ret; } @@ -2578,7 +2563,7 @@ rtl8139_RxBufAddr_read(RTL8139State *s) static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val) { - DPRINTF("RxBuf write val=0x%08x\n", val); + rtl8139_log("RxBuf write val=0x%08x\n", val); s->RxBuf = val; @@ -2590,7 +2575,7 @@ rtl8139_RxBuf_read(RTL8139State *s) { uint32_t ret = s->RxBuf; - DPRINTF("RxBuf read val=0x%08x\n", ret); + rtl8139_log("RxBuf read val=0x%08x\n", ret); return ret; } @@ -2598,7 +2583,7 @@ rtl8139_RxBuf_read(RTL8139State *s) static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) { - DPRINTF("IntrMask write(w) val=0x%04x\n", val); + rtl8139_log("IntrMask write(w) val=0x%04x\n", val); /* mask unwritable bits */ val = SET_MASKED(val, 0x1e00, s->IntrMask); @@ -2613,7 +2598,7 @@ rtl8139_IntrMask_read(RTL8139State *s) { uint32_t ret = s->IntrMask; - DPRINTF("IntrMask read(w) val=0x%04x\n", ret); + rtl8139_log("IntrMask read(w) val=0x%04x\n", ret); return ret; } @@ -2621,7 +2606,7 @@ rtl8139_IntrMask_read(RTL8139State *s) static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) { - DPRINTF("IntrStatus write(w) val=0x%04x\n", val); + rtl8139_log("IntrStatus write(w) val=0x%04x\n", val); #if 0 @@ -2650,7 +2635,7 @@ rtl8139_IntrStatus_read(RTL8139State *s) { uint32_t ret = s->IntrStatus; - DPRINTF("IntrStatus read(w) val=0x%04x\n", ret); + rtl8139_log("IntrStatus read(w) val=0x%04x\n", ret); #if 0 @@ -2667,7 +2652,7 @@ rtl8139_IntrStatus_read(RTL8139State *s) static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val) { - DPRINTF("MultiIntr write(w) val=0x%04x\n", val); + rtl8139_log("MultiIntr write(w) val=0x%04x\n", val); /* mask unwritable bits */ val = SET_MASKED(val, 0xf000, s->MultiIntr); @@ -2680,7 +2665,7 @@ rtl8139_MultiIntr_read(RTL8139State *s) { uint32_t ret = s->MultiIntr; - DPRINTF("MultiIntr read(w) val=0x%04x\n", ret); + rtl8139_log("MultiIntr read(w) val=0x%04x\n", ret); return ret; } @@ -2730,12 +2715,11 @@ rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) break; case MediaStatus: /* ignore */ - DPRINTF("not implemented write(b) to MediaStatus val=0x%02x\n", - val); + rtl8139_log("not implemented write(b) to MediaStatus val=0x%02x\n", val); break; case HltClk: - DPRINTF("HltClk write val=0x%08x\n", val); + rtl8139_log("HltClk write val=0x%08x\n", val); if (val == 'R') { s->clock_enabled = 1; } else if (val == 'H') { @@ -2744,29 +2728,28 @@ rtl8139_io_writeb(uint32_t addr, uint8_t val, void *priv) break; case TxThresh: - DPRINTF("C+ TxThresh write(b) val=0x%02x\n", val); + rtl8139_log("C+ TxThresh write(b) val=0x%02x\n", val); s->TxThresh = val; break; case TxPoll: - DPRINTF("C+ TxPoll write(b) val=0x%02x\n", val); + rtl8139_log("C+ TxPoll write(b) val=0x%02x\n", val); if (val & (1 << 7)) { - DPRINTF("C+ TxPoll high priority transmission (not " - "implemented)\n"); + rtl8139_log("C+ TxPoll high priority transmission (not " + "implemented)\n"); #if 0 - //rtl8139_cplus_transmit(s); + rtl8139_cplus_transmit(s); #endif } if (val & (1 << 6)) { - DPRINTF("C+ TxPoll normal priority transmission\n"); + rtl8139_log("C+ TxPoll normal priority transmission\n"); rtl8139_cplus_transmit(s); } break; default: - DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr, - val); + rtl8139_log("not implemented write(b) addr=0x%x val=0x%02x\n", addr, val); break; } } @@ -2801,14 +2784,14 @@ rtl8139_io_writew(uint32_t addr, uint16_t val, void *priv) rtl8139_BasicModeStatus_write(s, val); break; case NWayAdvert: - DPRINTF("NWayAdvert write(w) val=0x%04x\n", val); + rtl8139_log("NWayAdvert write(w) val=0x%04x\n", val); s->NWayAdvert = val; break; case NWayLPAR: - DPRINTF("forbidden NWayLPAR write(w) val=0x%04x\n", val); + rtl8139_log("forbidden NWayLPAR write(w) val=0x%04x\n", val); break; case NWayExpansion: - DPRINTF("NWayExpansion write(w) val=0x%04x\n", val); + rtl8139_log("NWayExpansion write(w) val=0x%04x\n", val); s->NWayExpansion = val; break; @@ -2821,8 +2804,8 @@ rtl8139_io_writew(uint32_t addr, uint16_t val, void *priv) break; default: - DPRINTF("ioport write(w) addr=0x%x val=0x%04x via write(b)\n", - addr, val); + rtl8139_log("ioport write(w) addr=0x%x val=0x%04x via write(b)\n", + addr, val); rtl8139_io_writeb(addr, val & 0xff, priv); rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, priv); @@ -2840,7 +2823,7 @@ rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) addr &= 0xFF; switch (addr) { case RxMissed: - DPRINTF("RxMissed clearing on write\n"); + rtl8139_log("RxMissed clearing on write\n"); s->RxMissed = 0; break; @@ -2865,17 +2848,17 @@ rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) break; case RxRingAddrLO: - DPRINTF("C+ RxRing low bits write val=0x%08x\n", val); + rtl8139_log("C+ RxRing low bits write val=0x%08x\n", val); s->RxRingAddrLO = val; break; case RxRingAddrHI: - DPRINTF("C+ RxRing high bits write val=0x%08x\n", val); + rtl8139_log("C+ RxRing high bits write val=0x%08x\n", val); s->RxRingAddrHI = val; break; case Timer: - DPRINTF("TCTR Timer reset on write\n"); + rtl8139_log("TCTR Timer reset on write\n"); s->TCTR = 0; #if 0 s->TCTR_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -2884,15 +2867,14 @@ rtl8139_io_writel(uint32_t addr, uint32_t val, void *priv) break; case FlashReg: - DPRINTF("FlashReg TimerInt write val=0x%08x\n", val); - if (s->TimerInt != val) { + rtl8139_log("FlashReg TimerInt write val=0x%08x\n", val); + if (s->TimerInt != val) s->TimerInt = val; - } break; default: - DPRINTF("ioport write(l) addr=0x%x val=0x%08x via write(b)\n", - addr, val); + rtl8139_log("ioport write(l) addr=0x%x val=0x%08x via write(b)\n", + addr, val); rtl8139_io_writeb(addr, val & 0xff, priv); rtl8139_io_writeb(addr + 1, (val >> 8) & 0xff, priv); rtl8139_io_writeb(addr + 2, (val >> 16) & 0xff, priv); @@ -2947,31 +2929,31 @@ rtl8139_io_readb(uint32_t addr, void *priv) case MediaStatus: /* The LinkDown bit of MediaStatus is inverse with link status */ ret = 0xd0 | (~s->BasicModeStatus & 0x04); - DPRINTF("MediaStatus read 0x%x\n", ret); + rtl8139_log("MediaStatus read 0x%x\n", ret); break; case HltClk: ret = s->clock_enabled; - DPRINTF("HltClk read 0x%x\n", ret); + rtl8139_log("HltClk read 0x%x\n", ret); break; case PCIRevisionID: ret = RTL8139_PCI_REVID; - DPRINTF("PCI Revision ID read 0x%x\n", ret); + rtl8139_log("PCI Revision ID read 0x%x\n", ret); break; case TxThresh: ret = s->TxThresh; - DPRINTF("C+ TxThresh read(b) val=0x%02x\n", ret); + rtl8139_log("C+ TxThresh read(b) val=0x%02x\n", ret); break; case 0x43: /* Part of TxConfig register. Windows driver tries to read it */ ret = s->TxConfig >> 24; - DPRINTF("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret); + rtl8139_log("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret); break; default: - DPRINTF("not implemented read(b) addr=0x%x\n", addr); + rtl8139_log("not implemented read(b) addr=0x%x\n", addr); ret = 0; break; } @@ -3018,15 +3000,15 @@ rtl8139_io_readw(uint32_t addr, void *priv) break; case NWayAdvert: ret = s->NWayAdvert; - DPRINTF("NWayAdvert read(w) val=0x%04x\n", ret); + rtl8139_log("NWayAdvert read(w) val=0x%04x\n", ret); break; case NWayLPAR: ret = s->NWayLPAR; - DPRINTF("NWayLPAR read(w) val=0x%04x\n", ret); + rtl8139_log("NWayLPAR read(w) val=0x%04x\n", ret); break; case NWayExpansion: ret = s->NWayExpansion; - DPRINTF("NWayExpansion read(w) val=0x%04x\n", ret); + rtl8139_log("NWayExpansion read(w) val=0x%04x\n", ret); break; case CpCmd: @@ -3046,12 +3028,12 @@ rtl8139_io_readw(uint32_t addr, void *priv) break; default: - DPRINTF("ioport read(w) addr=0x%x via read(b)\n", addr); + rtl8139_log("ioport read(w) addr=0x%x via read(b)\n", addr); ret = rtl8139_io_readb(addr, priv); ret |= rtl8139_io_readb(addr + 1, priv) << 8; - DPRINTF("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret); + rtl8139_log("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret); break; } @@ -3069,7 +3051,7 @@ rtl8139_io_readl(uint32_t addr, void *priv) case RxMissed: ret = s->RxMissed; - DPRINTF("RxMissed read val=0x%08x\n", ret); + rtl8139_log("RxMissed read val=0x%08x\n", ret); break; case TxConfig: @@ -3095,12 +3077,12 @@ rtl8139_io_readl(uint32_t addr, void *priv) case RxRingAddrLO: ret = s->RxRingAddrLO; - DPRINTF("C+ RxRing low bits read val=0x%08x\n", ret); + rtl8139_log("C+ RxRing low bits read val=0x%08x\n", ret); break; case RxRingAddrHI: ret = s->RxRingAddrHI; - DPRINTF("C+ RxRing high bits read val=0x%08x\n", ret); + rtl8139_log("C+ RxRing high bits read val=0x%08x\n", ret); break; case Timer: @@ -3109,23 +3091,23 @@ rtl8139_io_readl(uint32_t addr, void *priv) PCI_PERIOD; #endif ret = s->TCTR; - DPRINTF("TCTR Timer read val=0x%08x\n", ret); + rtl8139_log("TCTR Timer read val=0x%08x\n", ret); break; case FlashReg: ret = s->TimerInt; - DPRINTF("FlashReg TimerInt read val=0x%08x\n", ret); + rtl8139_log("FlashReg TimerInt read val=0x%08x\n", ret); break; default: - DPRINTF("ioport read(l) addr=0x%x via read(b)\n", addr); + rtl8139_log("ioport read(l) addr=0x%x via read(b)\n", addr); ret = rtl8139_io_readb(addr, priv); ret |= rtl8139_io_readb(addr + 1, priv) << 8; ret |= rtl8139_io_readb(addr + 2, priv) << 16; ret |= rtl8139_io_readb(addr + 3, priv) << 24; - DPRINTF("read(l) addr=0x%x val=%08x\n", addr, ret); + rtl8139_log("read(l) addr=0x%x val=%08x\n", addr, ret); break; } @@ -3192,7 +3174,7 @@ rtl8139_timer(void *priv) timer_on_auto(&s->timer, 1000000.0 / ((double) cpu_pci_speed)); if (!s->clock_enabled) { - DPRINTF(">>> timer: clock is not running\n"); + rtl8139_log(">>> timer: clock is not running\n"); return; } diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 0f5724608..20fd34f94 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -514,129 +514,6 @@ tulip_receive(void *priv, uint8_t *buf, int size) return 1; } -static const char * -tulip_reg_name(const uint32_t addr) -{ - switch (addr) { - case CSR(0): - return "CSR0"; - - case CSR(1): - return "CSR1"; - - case CSR(2): - return "CSR2"; - - case CSR(3): - return "CSR3"; - - case CSR(4): - return "CSR4"; - - case CSR(5): - return "CSR5"; - - case CSR(6): - return "CSR6"; - - case CSR(7): - return "CSR7"; - - case CSR(8): - return "CSR8"; - - case CSR(9): - return "CSR9"; - - case CSR(10): - return "CSR10"; - - case CSR(11): - return "CSR11"; - - case CSR(12): - return "CSR12"; - - case CSR(13): - return "CSR13"; - - case CSR(14): - return "CSR14"; - - case CSR(15): - return "CSR15"; - - default: - break; - } - return ""; -} - -static const char * -tulip_rx_state_name(int state) -{ - switch (state) { - case CSR5_RS_STOPPED: - return "STOPPED"; - - case CSR5_RS_RUNNING_FETCH: - return "RUNNING/FETCH"; - - case CSR5_RS_RUNNING_CHECK_EOR: - return "RUNNING/CHECK EOR"; - - case CSR5_RS_RUNNING_WAIT_RECEIVE: - return "WAIT RECEIVE"; - - case CSR5_RS_SUSPENDED: - return "SUSPENDED"; - - case CSR5_RS_RUNNING_CLOSE: - return "RUNNING/CLOSE"; - - case CSR5_RS_RUNNING_FLUSH: - return "RUNNING/FLUSH"; - - case CSR5_RS_RUNNING_QUEUE: - return "RUNNING/QUEUE"; - - default: - break; - } - return ""; -} - -static const char * -tulip_tx_state_name(int state) -{ - switch (state) { - case CSR5_TS_STOPPED: - return "STOPPED"; - - case CSR5_TS_RUNNING_FETCH: - return "RUNNING/FETCH"; - - case CSR5_TS_RUNNING_WAIT_EOT: - return "RUNNING/WAIT EOT"; - - case CSR5_TS_RUNNING_READ_BUF: - return "RUNNING/READ BUF"; - - case CSR5_TS_RUNNING_SETUP: - return "RUNNING/SETUP"; - - case CSR5_TS_SUSPENDED: - return "SUSPENDED"; - - case CSR5_TS_RUNNING_CLOSE: - return "RUNNING/CLOSE"; - - default: - break; - } - return ""; -} - static void tulip_update_rs(TULIPState *s, int state) { @@ -683,44 +560,6 @@ static const uint16_t tulip_mdi_default[] = { }; /* Readonly mask for MDI (PHY) registers */ -static const uint16_t tulip_mdi_mask[] = { - /* MDI Registers 0 - 6, 7 */ - 0x0000, - 0xffff, - 0xffff, - 0xffff, - 0xc01f, - 0xffff, - 0xffff, - 0x0000, - /* MDI Registers 8 - 15 */ - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - /* MDI Registers 16 - 31 */ - 0x0fff, - 0x0000, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, -}; - extern uint16_t l80225_mii_readw(uint16_t* regs, uint16_t addr); extern void l80225_mii_writew(uint16_t* regs, uint16_t addr, uint16_t val); @@ -1461,16 +1300,6 @@ static const uint8_t eeprom_default_24110[128] = { 0x00, }; -static void -tulip_fill_eeprom(TULIPState *s) -{ - uint16_t *eeprom = nmc93cxx_eeprom_data(s->eeprom); - memcpy(eeprom, eeprom_default, 128); - - tulip_idblock_crc(eeprom); - eeprom[63] = (tulip_srom_crc((uint8_t *) eeprom, 126)); -} - static uint8_t tulip_pci_read(UNUSED(int func), int addr, void *priv) { From fda5cee1f35fae18bc9a0df33876c34e85eae09e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Nov 2023 16:58:44 +0100 Subject: [PATCH 120/133] And in sound/midi_opl4.c. --- src/sound/midi_opl4.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sound/midi_opl4.c b/src/sound/midi_opl4.c index ba641701c..9708db150 100644 --- a/src/sound/midi_opl4.c +++ b/src/sound/midi_opl4.c @@ -437,7 +437,6 @@ note_on(uint8_t note, uint8_t velocity, MIDI_CHANNEL_DATA *midi_channel, opl4_mi const YRW801_WAVE_DATA *wave_data[2]; VOICE_DATA *voice[2]; uint8_t i = 0, voices = 0; - uint32_t j = 0; while (opl4_midi->gen_in_progress) { } From e5cfed2c244ecb648c323a3277900d2c631b4703 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Nov 2023 17:01:56 +0100 Subject: [PATCH 121/133] IT86x1F: Move the declaration of effective_ldn outside the case block. --- src/sio/sio_it86x1f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c index 91dcc756b..d53e78050 100644 --- a/src/sio/sio_it86x1f.c +++ b/src/sio/sio_it86x1f.c @@ -394,6 +394,7 @@ static void it86x1f_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) { it86x1f_t *dev = (it86x1f_t *) priv; + uint8_t effective_ldn; it86x1f_log("IT86x1F: write_vendor_reg(%X, %02X, %02X)\n", ld, reg, val); @@ -450,7 +451,6 @@ it86x1f_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) case 0xf0 ... 0xff: /* Translate GPIO LDN to 7 for the switch block. */ - uint8_t effective_ldn; if (ld == dev->gpio_ldn) effective_ldn = 7; else if (ld == 7) From 0b1d3b6e4ea39672455d9257fafbc987b1136883 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 11 Nov 2023 22:14:42 +0100 Subject: [PATCH 122/133] Fixed Hyungai Hyundai 286C initialization. --- src/machine/m_at_286_386sx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 9a2f7d8bf..79a82595f 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -359,14 +359,14 @@ machine_at_super286c_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_init(model); + machine_at_common_init(model); - device_add(&neat_device); + device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); - device_add(&keyboard_at_ami_device); + device_add(&neat_device); return ret; } From 4e05f211defef2777d45c0070c39bab464533ea5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 12 Nov 2023 00:47:22 +0100 Subject: [PATCH 123/133] Fixed saving of the fullscreen icons setting into the config file. --- src/config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 7d6df5074..b1ed7094f 100644 --- a/src/config.c +++ b/src/config.c @@ -139,7 +139,7 @@ load_general(void) rctrl_is_lalt = ini_section_get_int(cat, "rctrl_is_lalt", 0); update_icons = ini_section_get_int(cat, "update_icons", 1); - status_icons_fullscreen = !!config_get_int(cat, "status_icons_fullscreen", 0); + status_icons_fullscreen = !!ini_section_get_int(cat, "status_icons_fullscreen", 0); window_remember = ini_section_get_int(cat, "window_remember", 0); @@ -1785,9 +1785,9 @@ save_general(void) ini_section_delete_var(cat, "open_dir_usr_path"); if (status_icons_fullscreen) - config_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen); + ini_section_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen); else - config_delete_var(cat, "status_icons_fullscreen"); + ini_section_delete_var(cat, "status_icons_fullscreen"); if (video_framerate != -1) ini_section_set_int(cat, "video_gl_framerate", video_framerate); From cf8dea5ed3c0dac1aea6ab169ebc5711af559fde Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 12 Nov 2023 23:55:00 -0500 Subject: [PATCH 124/133] Fix win32 makefile builds --- src/win/Makefile.mingw | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index eea036f7b..022a639f2 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -706,6 +706,8 @@ SNDOBJ := sound.o \ wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ wave8580_PST.o wave.o \ midi.o \ + midi_opl4.o \ + midi_opl4_yrw801.o \ snd_speaker.o \ snd_pssj.o \ snd_ps1.o \ From 5fe104935484a9afd00d9acdf61ed9ba230bb5bb Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sat, 18 Nov 2023 02:25:24 +0500 Subject: [PATCH 125/133] Rename the Gateway 2000 Venus machine to all-lowercase internally --- src/include/86box/machine.h | 2 +- src/machine/m_at_socket8.c | 12 ++++++------ src/machine/machine_table.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f6b6df2a6..8560f0d3b 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -707,7 +707,7 @@ extern int machine_at_aurora_init(const machine_t *); extern int machine_at_686nx_init(const machine_t *); extern int machine_at_acerv60n_init(const machine_t *); extern int machine_at_vs440fx_init(const machine_t *); -extern int machine_at_GW2KVenus_init(const machine_t *); +extern int machine_at_gw2kvenus_init(const machine_t *); extern int machine_at_ap440fx_init(const machine_t *); extern int machine_at_mb600n_init(const machine_t *); extern int machine_at_8600ttc_init(const machine_t *); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 2ec32802c..628206a61 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -196,15 +196,15 @@ machine_at_vs440fx_init(const machine_t *model) } int -machine_at_GW2KVenus_init(const machine_t *model) +machine_at_gw2kvenus_init(const machine_t *model) { int ret; - ret = bios_load_linear_combined2("roms/machines/GW2KVenus/1011CS1T.BIO", - "roms/machines/GW2KVenus/1011CS1T.BI1", - "roms/machines/GW2KVenus/1011CS1T.BI2", - "roms/machines/GW2KVenus/1011CS1T.BI3", - "roms/machines/GW2KVenus/1011CS1T.RCV", + ret = bios_load_linear_combined2("roms/machines/gw2kvenus/1011CS1T.BIO", + "roms/machines/gw2kvenus/1011CS1T.BI1", + "roms/machines/gw2kvenus/1011CS1T.BI2", + "roms/machines/gw2kvenus/1011CS1T.BI3", + "roms/machines/gw2kvenus/1011CS1T.RCV", 0x3a000, 128); if (bios_only || !ret) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 38193a3cb..08d2041cd 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11738,10 +11738,10 @@ const machine_t machines[] = { /* It's a Intel VS440FX with a Gateway 2000 OEM BIOS */ { .name = "[i440FX] Gateway 2000 Venus", - .internal_name = "GW2KVenus", + .internal_name = "gw2kvenus", .type = MACHINE_TYPE_SOCKET8, .chipset = MACHINE_CHIPSET_INTEL_440FX, - .init = machine_at_GW2KVenus_init, + .init = machine_at_gw2kvenus_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, From af4df47282bf68101fb1098a501c08f8401affba Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sat, 18 Nov 2023 02:15:57 +0500 Subject: [PATCH 126/133] Bring some of the the v4.1 machines in line with the latest upstream changes --- src/machine/machine_table.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 08d2041cd..014417426 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8362,8 +8362,9 @@ const machine_t machines[] = { }, .nvrmask = 127, .kbc_device = NULL, - .kbc_p1 = 0, - .gpio = 0, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, .sio_device = NULL, @@ -10737,8 +10738,9 @@ const machine_t machines[] = { }, .nvrmask = 255, .kbc_device = NULL, - .kbc_p1 = 0, - .gpio = 0, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, .sio_device = NULL, @@ -11765,8 +11767,9 @@ const machine_t machines[] = { }, .nvrmask = 127, .kbc_device = NULL, - .kbc_p1 = 0, - .gpio = 0, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, .sio_device = NULL, From d07160aef2cf928f446db43227a7b83c167b158b Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sat, 18 Nov 2023 00:20:50 +0500 Subject: [PATCH 127/133] Fix a deprecation warning in qt_renderercommon.cpp --- src/qt/qt_renderercommon.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index db0612312..983f14d26 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -147,8 +147,10 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) if (label) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const QPixmap pixmap = label->pixmap(); +#elif QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + const QPixmap pixmap = label->pixmap(Qt::ReturnByValue); #else - const QPixmap pixmap = label->pixmap() ? *label->pixmap() : QPixmap(); + const QPixmap pixmap = (label->pixmap() ? *label->pixmap() : QPixmap()); #endif if (!pixmap.isNull()) { painter->setBrush(QColor::fromRgbF(0, 0, 0, 1.)); From f83a63daf2687e0b6d3eee4f9fa859fa86f7cab2 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sat, 18 Nov 2023 00:21:13 +0500 Subject: [PATCH 128/133] Fix a warning in net_eeprom_nmc93cxx.c --- src/network/net_eeprom_nmc93cxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index 8842af997..6e5b9c60c 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -103,7 +103,7 @@ nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void *params) if (params_details->filename) { FILE *fp = nvr_fopen(params_details->filename, "rb"); - strncpy(eeprom->filename, params_details->filename, 1024); + strncpy(eeprom->filename, params_details->filename, sizeof(eeprom->filename) - 1); if (fp) { filldefault = !fread(eeprom->contents, sizeof(uint16_t), nwords, fp); fclose(fp); From ad51c62451112b93221eeaa62a2b4078505108f7 Mon Sep 17 00:00:00 2001 From: Alexander Babikov <2708460+lemondrops@users.noreply.github.com> Date: Sat, 18 Nov 2023 02:16:43 +0500 Subject: [PATCH 129/133] Remove a redundant and pointless #ifdef in midi_fluidsynth.c --- src/sound/midi_fluidsynth.c | 86 ++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 08aefe16c..c1b9956d0 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -1,32 +1,31 @@ /* some code borrowed from scummvm */ -#ifdef USE_FLUIDSYNTH -# include -# include -# include -# include -# include -# ifdef __unix__ -# include -# endif -# define FLUIDSYNTH_NOT_A_DLL -# include +#include +#include +#include +#include +#include +#ifdef __unix__ +# include +#endif +#define FLUIDSYNTH_NOT_A_DLL +#include -# include <86box/86box.h> -# include <86box/config.h> -# include <86box/device.h> -# include <86box/midi.h> -# include <86box/thread.h> -# include <86box/sound.h> -# include <86box/plat_unused.h> +#include <86box/86box.h> +#include <86box/config.h> +#include <86box/device.h> +#include <86box/midi.h> +#include <86box/thread.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> -# define RENDER_RATE 100 -# define BUFFER_SEGMENTS 10 +#define RENDER_RATE 100 +#define BUFFER_SEGMENTS 10 /* Check the FluidSynth version to determine wheteher to use the older reverb/chorus control functions that were deprecated in 2.2.0, or their newer replacements */ -# if (FLUIDSYNTH_VERSION_MAJOR < 2) || ((FLUIDSYNTH_VERSION_MAJOR == 2) && (FLUIDSYNTH_VERSION_MINOR < 2)) -# define USE_OLD_FLUIDSYNTH_API -# endif +#if (FLUIDSYNTH_VERSION_MAJOR < 2) || ((FLUIDSYNTH_VERSION_MAJOR == 2) && (FLUIDSYNTH_VERSION_MINOR < 2)) +# define USE_OLD_FLUIDSYNTH_API +#endif extern void givealbuffer_midi(void *buf, uint32_t size); extern void al_set_midi(int freq, int buf_size); @@ -167,19 +166,19 @@ fluidsynth_init(UNUSED(const device_t *info)) data->synth = new_fluid_synth(data->settings); const char *sound_font = device_get_config_string("sound_font"); -# ifdef __unix__ +#ifdef __unix__ if (!sound_font || sound_font[0] == 0) sound_font = (access("/usr/share/sounds/sf2/FluidR3_GM.sf2", F_OK) == 0 ? "/usr/share/sounds/sf2/FluidR3_GM.sf2" : (access("/usr/share/soundfonts/default.sf2", F_OK) == 0 ? "/usr/share/soundfonts/default.sf2" : "")); -# endif +#endif data->sound_font = fluid_synth_sfload(data->synth, sound_font, 1); if (device_get_config_int("chorus")) { -# ifndef USE_OLD_FLUIDSYNTH_API +#ifndef USE_OLD_FLUIDSYNTH_API fluid_synth_chorus_on(data->synth, -1, 1); -# else +#else fluid_synth_set_chorus_on(data->synth, 1); -# endif +#endif int chorus_voices = device_get_config_int("chorus_voices"); double chorus_level = device_get_config_int("chorus_level") / 100.0; @@ -192,48 +191,48 @@ fluidsynth_init(UNUSED(const device_t *info)) else chorus_waveform = FLUID_CHORUS_MOD_TRIANGLE; -# ifndef USE_OLD_FLUIDSYNTH_API +#ifndef USE_OLD_FLUIDSYNTH_API fluid_synth_set_chorus_group_nr(data->synth, -1, chorus_voices); fluid_synth_set_chorus_group_level(data->synth, -1, chorus_level); fluid_synth_set_chorus_group_speed(data->synth, -1, chorus_speed); fluid_synth_set_chorus_group_depth(data->synth, -1, chorus_depth); fluid_synth_set_chorus_group_type(data->synth, -1, chorus_waveform); -# else +#else fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); -# endif +#endif } else -# ifndef USE_OLD_FLUIDSYNTH_API +#ifndef USE_OLD_FLUIDSYNTH_API fluid_synth_chorus_on(data->synth, -1, 0); -# else +#else fluid_synth_set_chorus_on(data->synth, 0); -# endif +#endif if (device_get_config_int("reverb")) { -# ifndef USE_OLD_FLUIDSYNTH_API +#ifndef USE_OLD_FLUIDSYNTH_API fluid_synth_reverb_on(data->synth, -1, 1); -# else +#else fluid_synth_set_reverb_on(data->synth, 1); -# endif +#endif double reverb_room_size = device_get_config_int("reverb_room_size") / 100.0; double reverb_damping = device_get_config_int("reverb_damping") / 100.0; double reverb_width = device_get_config_int("reverb_width") / 10.0; double reverb_level = device_get_config_int("reverb_level") / 100.0; -# ifndef USE_OLD_FLUIDSYNTH_API +#ifndef USE_OLD_FLUIDSYNTH_API fluid_synth_set_reverb_group_roomsize(data->synth, -1, reverb_room_size); fluid_synth_set_reverb_group_damp(data->synth, -1, reverb_damping); fluid_synth_set_reverb_group_width(data->synth, -1, reverb_width); fluid_synth_set_reverb_group_level(data->synth, -1, reverb_level); -# else +#else fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); -# endif +#endif } else -# ifndef USE_OLD_FLUIDSYNTH_API +#ifndef USE_OLD_FLUIDSYNTH_API fluid_synth_reverb_on(data->synth, -1, 0); -# else +#else fluid_synth_set_reverb_on(data->synth, 0); -# endif +#endif int interpolation = device_get_config_int("interpolation"); int fs_interpolation = FLUID_INTERP_4THORDER; @@ -499,4 +498,3 @@ const device_t fluidsynth_device = { .config = fluidsynth_config }; -#endif /*USE_FLUIDSYNTH*/ From 3c37ef2eef9c38a575c585b69e673ffaf4536fac Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 18 Nov 2023 05:04:02 +0100 Subject: [PATCH 130/133] Do not delay port 61h I/O on 386 and lower, fixes #3831 . --- src/port_6x.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/port_6x.c b/src/port_6x.c index 750b9678c..971b92d28 100644 --- a/src/port_6x.c +++ b/src/port_6x.c @@ -46,6 +46,8 @@ #define PORT_6X_MIRROR 4 #define PORT_6X_SWA 8 +static int cycles_sub = 0; + static void port_6x_write(uint16_t port, uint8_t val, void *priv) { @@ -53,7 +55,7 @@ port_6x_write(uint16_t port, uint8_t val, void *priv) port &= 3; - cycles -= ISA_CYCLES(8); + cycles -= cycles_sub; if ((port == 3) && (dev->flags & PORT_6X_MIRROR)) port = 1; @@ -83,7 +85,7 @@ port_61_read_simple(UNUSED(uint16_t port), UNUSED(void *priv)) { uint8_t ret = ppi.pb & 0x1f; - cycles -= ISA_CYCLES(8); + cycles -= cycles_sub; if (ppispeakon) ret |= 0x20; @@ -97,7 +99,7 @@ port_61_read(UNUSED(uint16_t port), void *priv) const port_6x_t *dev = (port_6x_t *) priv; uint8_t ret = 0xff; - cycles -= ISA_CYCLES(8); + cycles -= cycles_sub; if (dev->flags & PORT_6X_EXT_REF) { ret = ppi.pb & 0x0f; @@ -197,6 +199,8 @@ port_6x_init(const device_t *info) if (dev->flags & PORT_6X_SWA) io_sethandler(0x0062, 1, port_62_read, NULL, NULL, NULL, NULL, NULL, dev); + cycles_sub = is486 ? ISA_CYCLES(8) : 0; + return dev; } From 76bfbb6ec0eb8cd2fd4087f76baf0ad733b63806 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 19 Nov 2023 01:35:25 +0100 Subject: [PATCH 131/133] DEC Tulip PCI fixes and added proper MAC address generation. --- src/network/net_tulip.c | 65 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 20fd34f94..bdf2c5db0 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -23,6 +23,7 @@ #include <86box/86box.h> #include <86box/timer.h> #include <86box/pci.h> +#include <86box/random.h> #include <86box/io.h> #include <86box/mem.h> #include <86box/dma.h> @@ -1169,6 +1170,7 @@ static const uint8_t eeprom_default[128] = { 0x00, }; +/* MAC address at 14h, card-specific at 17h. */ static const uint8_t eeprom_default_24110[128] = { 0x46, 0x26, @@ -1405,12 +1407,40 @@ nic_init(const device_t *info) nmc93cxx_eeprom_params_t params; TULIPState *s = calloc(1, sizeof(TULIPState)); char filename[1024] = { 0 }; + uint32_t mac; if (!s) return NULL; s->device_info = info; - memcpy(eeprom_default_local, s->device_info->local ? eeprom_default_24110 : eeprom_default, sizeof(eeprom_default)); + memcpy(eeprom_default_local, info->local ? eeprom_default_24110 : eeprom_default, + sizeof(eeprom_default)); + if (info->local == 2) { + /* Microsoft VPC DEC Tulip. */ + eeprom_default_local[0x14] = 0x00; + eeprom_default_local[0x15] = 0x03; + eeprom_default_local[0x16] = 0x0f; + } + + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + eeprom_default_local[0x17] = random_generate(); + eeprom_default_local[0x18] = random_generate(); + eeprom_default_local[0x19] = random_generate(); + mac = (((int) eeprom_default_local[0x17]) << 16); + mac |= (((int) eeprom_default_local[0x18]) << 8); + mac |= ((int) eeprom_default_local[0x19]); + device_set_config_mac("mac", mac); + } else { + eeprom_default_local[0x17] = (mac >> 16) & 0xff; + eeprom_default_local[0x18] = (mac >> 8) & 0xff; + eeprom_default_local[0x19] = (mac & 0xff); + } + tulip_idblock_crc((uint16_t *) eeprom_default_local); ((uint16_t *) eeprom_default_local)[63] = (tulip_srom_crc((uint8_t *) eeprom_default_local, 126)); @@ -1425,7 +1455,7 @@ nic_init(const device_t *info) } memcpy(s->mii_regs, tulip_mdi_default, sizeof(tulip_mdi_default)); s->nic = network_attach(s, (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[10], tulip_receive, NULL); - pci_add_card(PCI_ADD_NETWORK, tulip_pci_read, tulip_pci_write, s, &s->pci_slot); + pci_add_card(PCI_ADD_NORMAL, tulip_pci_read, tulip_pci_write, s, &s->pci_slot); mem_mapping_add(&s->memory, 0, 0, NULL, NULL, tulip_read, NULL, NULL, tulip_write, NULL, MEM_MAPPING_EXTERNAL, s); tulip_reset(s); return s; @@ -1437,6 +1467,19 @@ nic_close(void *priv) free(priv); } +// clang-format off +static const device_config_t dec_tulip_pci_config[] = { + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + const device_t dec_tulip_device = { .name = "Compu-Shack FASTLine-II UTP 10/100 (DECchip 21143 \"Tulip\")", .internal_name = "dec_21143_tulip", @@ -1448,7 +1491,7 @@ const device_t dec_tulip_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL + .config = dec_tulip_pci_config }; const device_t dec_tulip_21140_device = { @@ -1462,5 +1505,19 @@ const device_t dec_tulip_21140_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL + .config = dec_tulip_pci_config +}; + +const device_t dec_tulip_21140_vpc_device = { + .name = "Microsoft Virtual PC Network (DECchip 21140 \"Tulip FasterNet\")", + .internal_name = "dec_21140_tulip_vpc", + .flags = DEVICE_PCI, + .local = 2, + .init = nic_init, + .close = nic_close, + .reset = tulip_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = dec_tulip_pci_config }; From 942be26bdcf5344deeea11d43a15f607a42e636c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 19 Nov 2023 02:09:39 +0100 Subject: [PATCH 132/133] And the RTL8139. --- src/network/net_rtl8139.c | 46 +++++++++++++++++++++++++++++++++++++-- src/network/net_tulip.c | 26 +++++++++++++--------- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 1cac242ad..d1e14fb12 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -32,6 +32,7 @@ #include <86box/86box.h> #include <86box/timer.h> #include <86box/pci.h> +#include <86box/random.h> #include <86box/io.h> #include <86box/mem.h> #include <86box/dma.h> @@ -3300,9 +3301,11 @@ nic_init(const device_t *info) RTL8139State *s = calloc(1, sizeof(RTL8139State)); FILE *fp = NULL; char eeprom_filename[1024] = { 0 }; + uint8_t *mac_bytes; + uint32_t mac; mem_mapping_add(&s->bar_mem, 0, 0, rtl8139_io_readb, rtl8139_io_readw, rtl8139_io_readl, rtl8139_io_writeb, rtl8139_io_writew, rtl8139_io_writel, NULL, MEM_MAPPING_EXTERNAL, s); - pci_add_card(PCI_ADD_NETWORK, rtl8139_pci_read, rtl8139_pci_write, s, &s->pci_slot); + pci_add_card(PCI_ADD_NORMAL, rtl8139_pci_read, rtl8139_pci_write, s, &s->pci_slot); s->inst = device_get_instance(); snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); @@ -3321,11 +3324,37 @@ nic_init(const device_t *info) s->eeprom.contents[2] = 0x8139; /* XXX: Get proper MAC addresses from real EEPROM dumps. OID taken from net_ne2000.c */ +#ifdef USE_REALTEK_OID s->eeprom.contents[7] = 0xe000; s->eeprom.contents[8] = 0x124c; +#else + s->eeprom.contents[7] = 0x1400; + s->eeprom.contents[8] = 0x122a; +#endif s->eeprom.contents[9] = 0x1413; } + mac_bytes = (uint8_t *) &(s->eeprom.contents[7]); + + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + mac_bytes[3] = random_generate(); + mac_bytes[4] = random_generate(); + mac_bytes[5] = random_generate(); + mac = (((int) mac_bytes[3]) << 16); + mac |= (((int) mac_bytes[4]) << 8); + mac |= ((int) mac_bytes[5]); + device_set_config_mac("mac", mac); + } else { + mac_bytes[3] = (mac >> 16) & 0xff; + mac_bytes[4] = (mac >> 8) & 0xff; + mac_bytes[5] = (mac & 0xff); + } + s->nic = network_attach(s, (uint8_t *) &s->eeprom.contents[7], rtl8139_do_receive, rtl8139_set_link_status); timer_add(&s->timer, rtl8139_timer, s, 0); timer_on_auto(&s->timer, 1000000.0 / cpu_pci_speed); @@ -3354,6 +3383,19 @@ nic_close(void *priv) free(priv); } +// clang-format off +static const device_config_t rtl8139c_config[] = { + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + const device_t rtl8139c_plus_device = { .name = "Realtek RTL8139C+", .internal_name = "rtl8139c+", @@ -3365,5 +3407,5 @@ const device_t rtl8139c_plus_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL + .config = rtl8139c_config }; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index bdf2c5db0..aaa60b4fc 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -1060,9 +1060,15 @@ static const uint8_t eeprom_default[128] = { 0x08, 0x04, 0x01, +#ifdef USE_DEC_OID 0x00, 0x80, 0x48, +#else + 0x00, + 0x00, + 0xcb, +#endif 0xb3, 0x0e, 0xa7, @@ -1192,12 +1198,12 @@ static const uint8_t eeprom_default_24110[128] = { 0x08, 0x04, 0x01, - 0x00, /* TODO: Change the MAC Address to the correct one. */ - 0x80, - 0x48, - 0xc3, - 0x3e, - 0xa7, + 0x00, /* Obtained from a Linux dump from the real Kingston KNE110TX: 00:C0:F0:16:2A:CB */ + 0xc0, + 0xf0, + 0x16, + 0x2a, + 0xcb, 0x00, 0x1e, 0x00, @@ -1468,7 +1474,7 @@ nic_close(void *priv) } // clang-format off -static const device_config_t dec_tulip_pci_config[] = { +static const device_config_t dec_tulip_config[] = { { .name = "mac", .description = "MAC Address", @@ -1491,7 +1497,7 @@ const device_t dec_tulip_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = dec_tulip_pci_config + .config = dec_tulip_config }; const device_t dec_tulip_21140_device = { @@ -1505,7 +1511,7 @@ const device_t dec_tulip_21140_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = dec_tulip_pci_config + .config = dec_tulip_config }; const device_t dec_tulip_21140_vpc_device = { @@ -1519,5 +1525,5 @@ const device_t dec_tulip_21140_vpc_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = dec_tulip_pci_config + .config = dec_tulip_config }; From f8902572372314fd1489996918b38d8bde9abb48 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 19 Nov 2023 02:12:33 +0100 Subject: [PATCH 133/133] Added the Virtual PC DEC Tulip 21140. --- src/include/86box/net_tulip.h | 1 + src/network/network.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/include/86box/net_tulip.h b/src/include/86box/net_tulip.h index 3e02b66e4..3e14deeea 100644 --- a/src/include/86box/net_tulip.h +++ b/src/include/86box/net_tulip.h @@ -1,2 +1,3 @@ extern const device_t dec_tulip_device; extern const device_t dec_tulip_21140_device; +extern const device_t dec_tulip_21140_vpc_device; diff --git a/src/network/network.c b/src/network/network.c index 8d814c1c4..38af502b2 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -131,11 +131,12 @@ static const device_t *net_cards[] = { &wd8013epa_device, &pcnet_am79c973_device, &pcnet_am79c970a_device, - &rtl8029as_device, - &pcnet_am79c960_vlb_device, &dec_tulip_device, + &rtl8029as_device, &rtl8139c_plus_device, &dec_tulip_21140_device, + &dec_tulip_21140_vpc_device, + &pcnet_am79c960_vlb_device, NULL };