From 4cefc6908e2c3d9c51c7bc7a7a36d996b2228b09 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 27 Nov 2022 16:11:46 +0600 Subject: [PATCH 01/61] 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 02/61] 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 03/61] 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 04/61] 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 05/61] 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 06/61] 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 07/61] 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 08/61] 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 09/61] 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 10/61] 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 11/61] 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 12/61] 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 13/61] 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 14/61] 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 15/61] 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 16/61] 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 17/61] 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 18/61] 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 19/61] 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 20/61] 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 21/61] 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 22/61] 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 23/61] 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 24/61] 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 25/61] 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 26/61] 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 27/61] 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 28/61] 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 29/61] 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 30/61] 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 31/61] 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 32/61] 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 33/61] 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 34/61] 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 35/61] 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 36/61] 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 37/61] 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 38/61] 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 39/61] 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 40/61] 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 41/61] 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 42/61] 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 43/61] 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 44/61] 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 45/61] 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 46/61] 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 47/61] 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 48/61] 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 49/61] 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 50/61] 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 51/61] 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 52/61] 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 53/61] 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 54/61] 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 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 55/61] 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 56/61] 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 1959665149fe50468cb30bef363fc81a556e4c5a Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 4 Nov 2023 03:04:35 -0400 Subject: [PATCH 57/61] 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 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 58/61] 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 59/61] 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 c243af519bc60f5412da67b16b9ea2929ba89e4f Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 7 Nov 2023 22:02:30 -0300 Subject: [PATCH 60/61] 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 61/61] 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);